Skip to content

Commit

Permalink
Feat/papi support (#440)
Browse files Browse the repository at this point in the history
* zombienet doesnt require connected parachains

* prescript errors halt runs

* feat: ✨ basic papi support

* fix

* lint

* lint

* ci-fix

* papi dev

* docs: 📝 Add PAPI docs

* cs fix

* chopsticks fix
  • Loading branch information
timbrinded authored Nov 18, 2024
1 parent 0856edd commit 9fed50b
Show file tree
Hide file tree
Showing 31 changed files with 1,103 additions and 49 deletions.
11 changes: 11 additions & 0 deletions .changeset/olive-lions-enjoy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@moonwall/cli": minor
"@moonwall/tests": minor
"@moonwall/types": minor
"@moonwall/util": minor
---

November Update
- [[#435](https://github.com/Moonsong-Labs/moonwall/issues/435)] Zombienets dont require parachains anymore
- [[#408](https://github.com/Moonsong-Labs/moonwall/issues/408)] preScript failures halt test runs
- [[#405](https://github.com/Moonsong-Labs/moonwall/issues/405)] Add PAPI Support
6 changes: 4 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ jobs:
strategy:
fail-fast: false
matrix:
suite: ["dev_test", "dev_multi", "dev_seq", "dev_smoke"]
suite: ["dev_test", "dev_multi", "dev_seq", "dev_smoke", "papi_dev"]
shard: [1, 2, 3, 4]
steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -142,6 +142,7 @@ jobs:
- name: Run ${{matrix.suite}} dev test
run: |
cd test
bun papi generate
bun moonwall test ${{matrix.suite}} --ts ${{ matrix.shard }}/4
test_chopsticks:
Expand Down Expand Up @@ -188,7 +189,7 @@ jobs:
strategy:
fail-fast: false
matrix:
suite: ["eth_test", "viem_test"]
suite: ["eth_test", "viem_test", "papi_readonly"]
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
Expand All @@ -208,6 +209,7 @@ jobs:
- name: Run standard ${{matrix.suite}}
run: |
cd test
bun papi add dot -n polkadot
bun moonwall test ${{matrix.suite}}
# disabled until web3.js fix their stuff
# - name: Run standard web3 run
Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,3 @@ artifacts

.idea
db.sqlite*
polkadot*
3 changes: 3 additions & 0 deletions docs/guide/intro/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ At time of writing, Moonwall supports the following providers:

PolkadotJs is a suite of tools, including a JavaScript library, for interacting with the Polkadot network and other Substrate-based blockchains. To learn more about PolkadotJs, you can check out the [PolkadotJs docs](https://polkadot.js.org/docs/api/){target=_blank}

### Polkadot-API (PAPI)

[Polkadot-API](https://github.com/polkadot-api/polkadot-api){target=_blank} is a modern, lightweight, and fast alternative to the PolkadotJs library for interacting with Substrate-based blockchains. It is designed to be more performant and have a smaller bundle size compared to PolkadotJs, while maintaining compatibility with the Polkadot ecosystem. For more information about Polkadot-API, check out the [Polkadot-API docs](https://papi.how/){target=_blank}.

### Ethers

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"lint": "pnpm -r --filter='./packages/**' run lint",
"lint:fix": "pnpm -r --filter='./packages/**' run lint:fix",
"changeset": "changeset",
"changeset:release": "changeset publish",
"changeset:release": "sleep 1 && pnpm changeset publish",
"changeset:version": "changeset version",
"clean-all": "rm -rf node_modules && pnpm -r --filter='./packages/**' run clean && pnpm store prune",
"pristine-build": "pnpm clean-all && pnpm i && pnpm build && pnpm generate-types",
Expand Down
1 change: 1 addition & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
"inquirer-press-to-continue": "*",
"jsonc-parser": "3.3.1",
"minimatch": "9.0.5",
"polkadot-api": "^1.7.4",
"semver": "*",
"tiny-invariant": "*",
"viem": "*",
Expand Down
64 changes: 60 additions & 4 deletions packages/cli/src/internal/providerFactories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { createWalletClient, http, publicActions } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { Web3 } from "web3";
import { WebSocketProvider } from "web3-providers-ws";
import { createClient, type PolkadotClient } from "polkadot-api";
import { getWsProvider, WsEvent } from "polkadot-api/ws-provider/web";
import Debug from "debug";
const debug = Debug("global:providers");

Expand All @@ -31,6 +33,8 @@ export class ProviderFactory {
return this.createEthers();
case "viem":
return this.createViem();
case "papi":
return this.createPapi();
default:
return this.createDefault();
}
Expand Down Expand Up @@ -105,6 +109,33 @@ export class ProviderFactory {
};
}

private createPapi(): MoonwallProvider {
debug(`🟢 Papi provider ${this.providerConfig.name} details prepared`);
return {
name: this.providerConfig.name,
type: this.providerConfig.type,
connect: () => {
const provider = getWsProvider(this.url, (status) => {
switch (status.type) {
case WsEvent.CONNECTING:
console.log("Connecting... 🔌");
break;
case WsEvent.CONNECTED:
console.log("Connected! ⚡");
break;
case WsEvent.ERROR:
console.log("Errored... 😢");
break;
case WsEvent.CLOSE:
console.log("Closed 🚪");
break;
}
});
return createClient(provider);
},
};
}

private createDefault(): MoonwallProvider {
debug(`🟢 Default provider ${this.providerConfig.name} details prepared`);
return {
Expand Down Expand Up @@ -211,15 +242,21 @@ export interface ProviderInterface {
name: string;
api: any;
type: ProviderType;
greet: () => void | Promise<void> | { rtVersion: number; rtName: string };
greet: () => Promise<void> | Promise<{ rtVersion: number; rtName: string }>;
disconnect: () => void | Promise<void> | any;
}

export class ProviderInterfaceFactory {
constructor(
private name: string,
private type: ProviderType,
private connect: () => Promise<ApiPromise> | Wallet | Web3 | Promise<ViemClient> | null
private connect: () =>
| Promise<ApiPromise>
| Wallet
| Web3
| Promise<ViemClient>
| PolkadotClient
| null
) {}

public async create(): Promise<ProviderInterface> {
Expand All @@ -232,6 +269,8 @@ export class ProviderInterfaceFactory {
return this.createEthers();
case "viem":
return this.createViem();
case "papi":
return this.createPapi();
default:
throw new Error("UNKNOWN TYPE");
}
Expand All @@ -246,7 +285,7 @@ export class ProviderInterfaceFactory {
name: this.name,
api,
type: this.type,
greet: () => {
greet: async () => {
debug(
`👋 Provider ${this.name} is connected to chain` +
` ${(api.consts.system.version as any).specName.toString()} ` +
Expand Down Expand Up @@ -319,10 +358,27 @@ export class ProviderInterfaceFactory {
};
}

private async createPapi(): Promise<ProviderInterface> {
const api = (await this.connect()) as PolkadotClient;
return {
name: this.name,
api,
type: this.type,
greet: async () => {
const unsafeApi = await api.getUnsafeApi();
const { spec_version, spec_name } = await unsafeApi.constants.System.Version();
return { rtVersion: spec_version as number, rtName: spec_name as string };
},
async disconnect() {
api.destroy();
},
};
}

public static async populate(
name: string,
type: ProviderType,
connect: () => Promise<ApiPromise> | Wallet | Web3 | Promise<ViemClient> | null
connect: () => Promise<ApiPromise> | Wallet | Web3 | Promise<ViemClient> | PolkadotClient | null
): Promise<ProviderInterface> {
debug(`🔄 Populating provider: ${name} of type: ${type}`);
try {
Expand Down
2 changes: 2 additions & 0 deletions packages/cli/src/lib/runnerContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { chopsticksHandler } from "./handlers/chopsticksHandler";
import { devHandler } from "./handlers/devHandler";
import { readOnlyHandler } from "./handlers/readOnlyHandler";
import { zombieHandler } from "./handlers/zombieHandler";
import type { PolkadotClient } from "polkadot-api";

const RT_VERSION = Number(process.env.MOON_RTVERSION);
const RT_NAME = process.env.MOON_RTNAME;
Expand Down Expand Up @@ -150,6 +151,7 @@ export function describeSuite<T extends FoundationType>({
polkadotJs: (apiName?: string): ApiPromise => getApi("polkadotJs", apiName),
ethers: (apiName?: string): Wallet => getApi("ethers", apiName),
web3: (apiName?: string): Web3 => getApi("web3", apiName),
papi: (apiName?: string): PolkadotClient => getApi("papi", apiName),
};

const foundationHandlers: Record<FoundationType, FoundationHandler<any>> = {
Expand Down
4 changes: 2 additions & 2 deletions packages/types/config_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -307,8 +307,8 @@
"type": "object"
},
"ProviderType": {
"description": "The type of provider. Can be \"polkadotJs\", \"ethers\", \"web3\", \"viem\"",
"enum": ["ethers", "polkadotJs", "viem", "web3"],
"description": "The type of provider. Can be \"polkadotJs\", \"ethers\", \"web3\", \"viem\", \"papi\"",
"enum": ["ethers", "papi", "polkadotJs", "viem", "web3"],
"type": "string"
},
"ReadOnlyLaunchSpec": {
Expand Down
3 changes: 2 additions & 1 deletion packages/types/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,15 @@
"@polkadot/api": "*",
"@polkadot/api-base": "*",
"@polkadot/keyring": "*",
"@polkadot/util-crypto": "*",
"@polkadot/types": "*",
"@polkadot/util": "*",
"@polkadot/util-crypto": "*",
"@types/node": "*",
"@zombienet/utils": "*",
"bottleneck": "*",
"debug": "*",
"ethers": "*",
"polkadot-api": "^1.7.4",
"viem": "*",
"web3": "*"
},
Expand Down
4 changes: 2 additions & 2 deletions packages/types/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -404,9 +404,9 @@ export interface ProviderConfig {

/**
* @name ProviderType
* @description The type of provider. Can be "polkadotJs", "ethers", "web3", "viem"
* @description The type of provider. Can be "polkadotJs", "ethers", "web3", "viem", "papi"
*/
export type ProviderType = "polkadotJs" | "ethers" | "web3" | "viem";
export type ProviderType = "polkadotJs" | "ethers" | "web3" | "viem" | "papi";

/**
* @name ZombieNodeType
Expand Down
12 changes: 10 additions & 2 deletions packages/types/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type { Web3 } from "web3";
import type { FoundationType, ProviderType } from "./config";
import type { CallType } from "./foundations";
import type { ViemClient } from "./runner";
import type { PolkadotClient } from "polkadot-api";

/**
* @name MoonwallEnvironment
Expand Down Expand Up @@ -38,7 +39,13 @@ export type MoonwallEnvironment = {
export interface MoonwallProvider {
name: string;
type: ProviderType;
connect: () => Promise<ApiPromise> | Wallet | Web3<any> | Promise<ViemClient> | null;
connect: () =>
| Promise<ApiPromise>
| Wallet
| Web3<any>
| Promise<ViemClient>
| PolkadotClient
| null;
ws?: () => WsProvider;
}

Expand All @@ -56,7 +63,7 @@ export interface ConnectedProvider {
type: ProviderType;
api: ProviderApi;
disconnect: () => Promise<void>;
greet: () => Promise<void> | void | { rtName: string; rtVersion: number };
greet: () => Promise<void> | Promise<{ rtName: string; rtVersion: number }>;
}

export type ProviderApi = {
Expand All @@ -69,6 +76,7 @@ export type ProviderMap = {
web3: Web3;
moon: ApiPromise;
viem: ViemClient;
papi: PolkadotClient;
};

/**
Expand Down
3 changes: 3 additions & 0 deletions packages/types/src/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import type { ContractDeploymentOptions } from "./contracts";
import type { TransactionType } from "./eth";
import type { CallType } from "./foundations";
import type { DeepPartial } from "./helpers";
import type { PolkadotClient } from "polkadot-api";

/**
* @name CustomTest
Expand Down Expand Up @@ -189,10 +190,12 @@ export interface GenericContext {
api(type: "ethers", name?: string): Wallet;
api(type: "web3", name?: string): Web3;
api(type: "viem", name?: string): ViemClient;
api(type: "papi", name?: string): PolkadotClient;
viem(name?: string): ViemClient;
polkadotJs(apiName?: string): ApiPromise;
ethers(name?: string): Wallet;
web3(name?: string): Web3;
papi(name?: string): PolkadotClient;
}

/**
Expand Down
Loading

0 comments on commit 9fed50b

Please sign in to comment.