diff --git a/Readme.md b/Readme.md index 609955aba..88650b0a7 100644 --- a/Readme.md +++ b/Readme.md @@ -99,9 +99,9 @@ capi sync --import-map import_map.json Retrieve the first 10 entries from a storage map of Polkadot. ```ts -import { chain } from "@capi/polkadot" +import { polkadot } from "@capi/polkadot" -const accounts = await chain.System.Account +const accounts = await polkadot.System.Account .entryPage(10, null) .run() ``` @@ -111,8 +111,13 @@ const accounts = await chain.System.Account Let's modify the usage above to target our configured devnet. ```diff -- import { chain } from "@capi/polkadot" -+ import { chain } from "@capi/polkadot-dev" +- import { polkadot } from "@capi/polkadot" ++ import { polkadotDev } from "@capi/polkadot-dev" + +- const accounts = await polkadot.System.Account ++ const accounts = await polkadotDev.System.Account + .entryPage(10, null) + .run() ``` To run code that depends on a devnet, use the `serve` command, followed by a diff --git a/capi.config.ts b/capi.config.ts index dd0d48a2c..4fd488cf9 100644 --- a/capi.config.ts +++ b/capi.config.ts @@ -1,10 +1,10 @@ -import { binary, CapiConfig } from "./mod.ts" +import { binary, Config } from "./mod.ts" const polkadot = binary("polkadot", "v0.9.38") const polkadotParachain = binary("polkadot-parachain", "v0.9.380") const substrateContractsNode = binary("substrate-contracts-node", "v0.24.0") -export const config: CapiConfig = { +export const config: Config = { server: "http://localhost:4646/", chains: { polkadot: { @@ -74,5 +74,8 @@ export const config: CapiConfig = { }, }, }, + polkadotFromMetadata: { + metadata: await Deno.readFile("examples/raw_rpc/metadata"), + }, }, } diff --git a/cli/resolveConfig.ts b/cli/resolveConfig.ts index 43d668880..10c0d52d5 100644 --- a/cli/resolveConfig.ts +++ b/cli/resolveConfig.ts @@ -1,8 +1,8 @@ import * as flags from "../deps/std/flags.ts" import * as path from "../deps/std/path.ts" -import { CapiConfig } from "../devnets/mod.ts" +import { Config } from "../devnets/mod.ts" -export async function resolveConfig(...args: string[]) { +export async function resolveConfig(...args: string[]): Promise { const { config: rawConfigPath } = flags.parse(args, { string: ["config"], default: { @@ -14,6 +14,5 @@ export async function resolveConfig(...args: string[]) { const configModule = await import(path.toFileUrl(configPath).toString()) const config = configModule.config if (typeof config !== "object") throw new Error("config file must have a config export") - - return config as CapiConfig + return config } diff --git a/cli/serve.ts b/cli/serve.ts index fccd09cd9..4e07022ab 100644 --- a/cli/serve.ts +++ b/cli/serve.ts @@ -1,4 +1,5 @@ import * as flags from "../deps/std/flags.ts" +import { blue, gray, yellow } from "../deps/std/fmt/colors.ts" import { serve } from "../deps/std/http.ts" import { createTempDir } from "../devnets/createTempDir.ts" import { createDevnetsHandler } from "../devnets/mod.ts" @@ -58,12 +59,12 @@ export default async function(...args: string[]) { throw error }, async onListen() { - console.log(`Capi server listening at "${href}"`) + console.log(blue("Created"), "Capi server instance", gray(`at ${href}`)) await onReady() }, }) } else { - console.log(`Reusing existing Capi server at "${href}"`) + console.log(yellow("Reusing"), "Capi server instance", gray(`at ${href}`)) await onReady() } diff --git a/cli/sync.ts b/cli/sync.ts index 182a3f07f..18e679e71 100644 --- a/cli/sync.ts +++ b/cli/sync.ts @@ -1,4 +1,5 @@ import * as flags from "../deps/std/flags.ts" +import { blue, gray } from "../deps/std/fmt/colors.ts" import { assertEquals } from "../deps/std/testing/asserts.ts" import { createTempDir } from "../devnets/createTempDir.ts" import { syncConfig } from "../devnets/mod.ts" @@ -20,38 +21,41 @@ export default async function(...args: string[]) { const tempDir = await createTempDir() const baseUrl = await syncConfig(tempDir, config) - console.log(baseUrl) if (importMapFile) { - const importMapText = await Deno.readTextFile(importMapFile) - const importMap = JSON.parse(importMapText) - importMap.imports["@capi/"] = baseUrl - if (check) { - assertEquals(JSON.parse(importMapText), importMap) - } else { - await Deno.writeTextFile(importMapFile, JSON.stringify(importMap, null, 2) + "\n") - } + syncFile(importMapFile, (importMap) => { + importMap.imports["@capi/"] = baseUrl + }) } if (packageJsonFile) { - const packageJsonText = await Deno.readTextFile(packageJsonFile) - const packageJson = JSON.parse(packageJsonText) - const addedPackages = new Set() - for (const rawName of Object.keys(config.chains ?? {})) { - const name = normalizePackageName(rawName) - const packageName = `@capi/${name}` - addedPackages.add(packageName) - packageJson.dependencies[packageName] = `${baseUrl}${name}.tar` - } - for (const packageName of Object.keys(packageJson.dependencies)) { - if (packageName.startsWith("@capi/") && !addedPackages.has(packageName)) { - delete packageJson.dependencies[packageName] + syncFile(packageJsonFile, (packageJson) => { + const addedPackages = new Set() + for (const rawName of Object.keys(config.chains ?? {})) { + const name = normalizePackageName(rawName) + const packageName = `@capi/${name}` + addedPackages.add(packageName) + packageJson.dependencies[packageName] = `${baseUrl}${name}.tar` } - } - if (check) { - assertEquals(JSON.parse(packageJsonText), packageJson) - } else { - await Deno.writeTextFile(packageJsonFile, JSON.stringify(packageJson, null, 2) + "\n") + for (const packageName of Object.keys(packageJson.dependencies)) { + if (packageName.startsWith("@capi/") && !addedPackages.has(packageName)) { + delete packageJson.dependencies[packageName] + } + } + }) + } + + async function syncFile(filePath: string, modify: (value: any) => void) { + const text = await Deno.readTextFile(filePath) + const newJson = JSON.parse(text) + modify(newJson) + try { + assertEquals(JSON.parse(text), newJson) + console.log(gray("Unchanged"), filePath) + } catch (e) { + if (check) throw e + await Deno.writeTextFile(filePath, JSON.stringify(newJson, null, 2) + "\n") + console.log(blue("Updated"), filePath) } } } diff --git a/codegen/frameCodegen.ts b/codegen/frameCodegen.ts index 0bd471ca4..e298ce4f9 100644 --- a/codegen/frameCodegen.ts +++ b/codegen/frameCodegen.ts @@ -39,10 +39,13 @@ export function frameCodegen( const palletDeclarations: string[] = [] const palletDefinitions: string[] = [] + const chainRuneIdent = `${chainIdent}Rune` + for (const pallet of Object.values(metadata.pallets)) { - chainMemberDeclarations.push(`${pallet.name}: ${pallet.name}PalletRune`) + const palletRuneIdent = `${chainIdent}${pallet.name}Rune` + chainMemberDeclarations.push(`${pallet.name}: ${palletRuneIdent}`) chainMembers.push( - `${pallet.name} = this.pallet("${pallet.name}").into(${pallet.name}PalletRune, this)`, + `${pallet.name} = this.pallet("${pallet.name}").into(${palletRuneIdent}, this)`, ) const palletDeclarationStatements: string[] = [] @@ -109,12 +112,12 @@ export function frameCodegen( } palletDeclarations.push(` - export class ${pallet.name}PalletRune extends C.PalletRune<${chainIdent}, "${pallet.name}", U> { + export class ${palletRuneIdent} extends C.PalletRune<${chainIdent}, "${pallet.name}", U> { ${palletDeclarationStatements.join("\n")} } `) palletDefinitions.push(` - export class ${pallet.name}PalletRune extends C.PalletRune { + export class ${palletRuneIdent} extends C.PalletRune { ${palletStatements.join("\n")} } `) @@ -143,17 +146,15 @@ export function frameCodegen( export interface ${chainIdent} extends C.Chain {} - export class ${chainIdent}ChainRune extends C.ChainRune<${chainIdent}, U> { - static override from(connect: (signal: AbortSignal) => C.Connection): ${chainIdent}ChainRune + export class ${chainRuneIdent} extends C.ChainRune<${chainIdent}, U> { + static override from(connect: (signal: AbortSignal) => C.Connection): ${chainRuneIdent} - override with(connection: (signal: AbortSignal) => C.Connection): ${chainIdent}ChainRune + override with(connection: (signal: AbortSignal) => C.Connection): ${chainRuneIdent} ${chainMemberDeclarations.join("\n")} } ${palletDeclarations.join("\n")} - - export const chain: ${chainIdent}ChainRune `, ) @@ -161,24 +162,21 @@ export function frameCodegen( "chain.js", ` ${importsCommon} - import { connect } from "./connection.js" import { metadata } from "./metadata.js" - export class ${chainIdent}ChainRune extends C.ChainRune { + export class ${chainRuneIdent} extends C.ChainRune { static from(connect) { return super.from(connect, metadata) } with(connect) { - return super.with(connect).into(${chainIdent}ChainRune) + return super.with(connect).into(${chainRuneIdent}) } ${chainMembers.join("\n")} } ${palletDefinitions.join("\n")} - - export const chain = ${chainIdent}ChainRune.from(connect) `, ) } diff --git a/cspell.json b/cspell.json index 502f30ac5..ca9f4c6b3 100644 --- a/cspell.json +++ b/cspell.json @@ -11,14 +11,16 @@ "enableGlobDot": true, "dictionaries": ["project-words"], "ignorePaths": [ - ".git", - "**/*.wasm", - "target", - "**/__snapshots__/*.snap", "**/*.contract", - "examples/ink/erc20.json", "**/*.scale", "**/*.svg", + "**/__snapshots__/*.snap", + ".git", + "examples/ink/erc20.json", + "examples/ink/erc20.wasm", + "examples/raw_rpc/metadata", + "examples/smoldot/chainspec.json", + "target", "util/_artifacts" ] } diff --git a/deps/std/fmt/colors.ts b/deps/std/fmt/colors.ts new file mode 100644 index 000000000..403b22268 --- /dev/null +++ b/deps/std/fmt/colors.ts @@ -0,0 +1 @@ +export * from "https://deno.land/std@0.184.0/fmt/colors.ts" diff --git a/devnets/CapiConfig.ts b/devnets/CapiConfig.ts deleted file mode 100644 index ddee8c353..000000000 --- a/devnets/CapiConfig.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Binary } from "./binary.ts" - -export interface WsChain { - url: string - binary?: never - version: string -} - -export interface NetworkConfig { - url?: never - binary: Binary - chain: string - nodes?: number - parachains?: Record -} - -export interface CapiConfig { - server: string - chains?: Record -} diff --git a/devnets/Config.ts b/devnets/Config.ts new file mode 100644 index 000000000..52b7e3d27 --- /dev/null +++ b/devnets/Config.ts @@ -0,0 +1,40 @@ +import { Binary } from "./binary.ts" + +export interface Config { + server: string + chains?: Record +} + +export type ChainConfig = + | WsChainConfig + | DevChainConfig + | RawMetadataChainConfig + +export interface WsChainConfig { + url: string + binary?: never + metadata?: never + + version: string +} + +export interface DevChainConfig { + url?: never + binary: Binary + metadata?: never + + chain: string + nodes?: number + parachains?: Record +} + +export interface RawMetadataChainConfig { + url?: never + binary?: never + metadata: Uint8Array +} diff --git a/devnets/devnetsHandler.ts b/devnets/devnetsHandler.ts index 881ca9216..efac580b9 100644 --- a/devnets/devnetsHandler.ts +++ b/devnets/devnetsHandler.ts @@ -2,14 +2,14 @@ import * as path from "../deps/std/path.ts" import { $ } from "../mod.ts" import * as f from "../server/factories.ts" import { PermanentMemo } from "../util/memo.ts" -import { CapiConfig } from "./CapiConfig.ts" +import { Config } from "./Config.ts" import { devUserPublicKeys } from "./dev_users.ts" import { proxyWebSocket } from "./proxyWebSocket.ts" import { Network, startNetwork } from "./startNetwork.ts" const rDevnetsApi = /^\/devnets\/([\w-]+)(?:\/([\w-]+))?$/ -export function createDevnetsHandler(tempDir: string, config: CapiConfig, signal: AbortSignal) { +export function createDevnetsHandler(tempDir: string, config: Config, signal: AbortSignal) { const networkMemo = new PermanentMemo() let devUserIndex = 0 return async (request: Request) => { diff --git a/devnets/mod.ts b/devnets/mod.ts index c1212e31f..b3e0c920c 100644 --- a/devnets/mod.ts +++ b/devnets/mod.ts @@ -1,8 +1,8 @@ // moderate export * from "./binary.ts" -export * from "./CapiConfig.ts" export * from "./chainSpec.ts" +export * from "./Config.ts" export * from "./createTempDir.ts" export * from "./dev_users.ts" export * from "./DevnetConnection.ts" diff --git a/devnets/startNetwork.ts b/devnets/startNetwork.ts index e68599281..da01e1383 100644 --- a/devnets/startNetwork.ts +++ b/devnets/startNetwork.ts @@ -6,13 +6,13 @@ import * as path from "../deps/std/path.ts" import { writableStreamFromWriter } from "../deps/std/streams.ts" import { getFreePort, portReady } from "../util/port.ts" import { resolveBinary } from "./binary.ts" -import { NetworkConfig } from "./CapiConfig.ts" import { createCustomChainSpec, createRawChainSpec, GenesisConfig, getGenesisConfig, } from "./chainSpec.ts" +import { DevChainConfig } from "./Config.ts" import { addDevUsers } from "./dev_users.ts" export interface Network { @@ -27,7 +27,7 @@ export interface NetworkChain { export async function startNetworkForMetadata( tempDir: string, - config: NetworkConfig, + config: DevChainConfig, signal: AbortSignal, ): Promise { const relayBinary = await resolveBinary(config.binary, signal) @@ -70,7 +70,7 @@ export async function startNetworkForMetadata( export async function startNetwork( tempDir: string, - config: NetworkConfig, + config: DevChainConfig, signal: AbortSignal, ): Promise { const paras = await Promise.all( diff --git a/devnets/syncConfig.ts b/devnets/syncConfig.ts index 212cc1f57..8c3e4b827 100644 --- a/devnets/syncConfig.ts +++ b/devnets/syncConfig.ts @@ -2,44 +2,55 @@ export * from "./binary.ts" import { blake2_512, blake2_64, Hasher } from "../crypto/hashers.ts" import { hex } from "../crypto/mod.ts" +import { gray, green } from "../deps/std/fmt/colors.ts" import * as path from "../deps/std/path.ts" import { WsConnection } from "../mod.ts" import { $codegenSpec, CodegenEntry, CodegenSpec } from "../server/codegenSpec.ts" import { normalizePackageName, withSignal } from "../util/mod.ts" import { normalizeTypeName } from "../util/normalize.ts" -import { CapiConfig } from "./CapiConfig.ts" +import { Config } from "./Config.ts" import { startNetworkForMetadata } from "./startNetwork.ts" -export async function syncConfig(tempDir: string, config: CapiConfig) { +export async function syncConfig(tempDir: string, config: Config) { return withSignal(async (signal) => { const { server } = config const entries = new Map() + const chainConfigEntries = Object.entries(config.chains ?? {}) + const syncTotal = chainConfigEntries + .map(([_, entry]) => + entry.binary && entry.parachains ? 1 + Object.values(entry.parachains).length : 1 + ) + .reduce((a, b) => a + b, 0) + let synced = 0 await Promise.all( - Object.entries(config.chains ?? {}).map(async ([name, chain]) => { + chainConfigEntries.map(async ([name, chain]) => { + const relayPackageName = normalizePackageName(name) if (chain.url != null) { const metadata = await uploadMetadata(server, chain.url) - entries.set(normalizePackageName(name), { + entries.set(relayPackageName, { type: "frame", metadata, chainName: normalizeTypeName(name), connection: { type: "WsConnection", discovery: chain.url }, }) - return - } - const network = await startNetworkForMetadata(path.join(tempDir, name), chain, signal) - await Promise.all( - [ - [undefined, network.relay] as const, - ...Object.entries(network.paras), - ].map( - async ([paraName, chain]) => { - const metadata = await uploadMetadata( - server, - `ws://127.0.0.1:${chain.ports[0]}`, - ) - entries.set( - normalizePackageName(name) + (paraName ? `/${normalizePackageName(paraName)}` : ""), - { + logSynced(relayPackageName) + } else if (chain.metadata) { + const metadata = await _upload(server, "metadata", chain.metadata, blake2_512) + entries.set(relayPackageName, { + type: "frame", + metadata, + chainName: normalizeTypeName(name), + }) + logSynced(relayPackageName) + } else { + const network = await startNetworkForMetadata(path.join(tempDir, name), chain, signal) + await Promise.all( + [[undefined, network.relay] as const, ...Object.entries(network.paras)].map( + async ([paraName, chain]) => { + const metadata = await uploadMetadata(server, `ws://127.0.0.1:${chain.ports[0]}`) + const packageName = relayPackageName + + (paraName ? `/${normalizePackageName(paraName)}` : "") + entries.set(packageName, { type: "frame", metadata: metadata, chainName: normalizeTypeName(paraName ?? name), @@ -47,11 +58,12 @@ export async function syncConfig(tempDir: string, config: CapiConfig) { type: "DevnetConnection", discovery: name + (paraName ? `/${paraName}` : ""), }, - }, - ) - }, - ), - ) + }) + logSynced(packageName) + }, + ), + ) + } }), ) const sortedEntries = new Map([...entries].sort((a, b) => a[0] < b[0] ? 1 : -1)) @@ -60,6 +72,10 @@ export async function syncConfig(tempDir: string, config: CapiConfig) { codegen: sortedEntries, }) return new URL(codegenHash + "/", server).toString() + + function logSynced(packageName: string) { + console.log(green("Synced"), gray(`(${++synced}/${syncTotal})`), `@capi/${packageName}`) + } }) } diff --git a/dprint.json b/dprint.json index 20ea35fce..78f12a4fc 100644 --- a/dprint.json +++ b/dprint.json @@ -11,13 +11,12 @@ "lineWidth": 80, "textWrap": "always" }, - "includes": [ - "**.{dockerfile,json,md,toml,ts,tsx}" - ], + "includes": ["**.{dockerfile,json,md,toml,ts,tsx}"], "excludes": [ + "examples/ink/erc20.json", + "examples/raw_rpc/metadata", "target", - "util/_artifacts", - "examples/ink/erc20.json" + "util/_artifacts" ], "plugins": [ "https://plugins.dprint.dev/dockerfile-0.3.0.wasm", diff --git a/examples/blocks.eg.ts b/examples/blocks.eg.ts index 48c0b20fd..f6e6481f8 100644 --- a/examples/blocks.eg.ts +++ b/examples/blocks.eg.ts @@ -6,12 +6,12 @@ * various pieces of data pertaining to that block. */ -import { $eventRecord, chain, metadata } from "@capi/polkadot" +import { $eventRecord, metadata, polkadot } from "@capi/polkadot" import { $, $extrinsic, known, Rune } from "capi" import { babeBlockAuthor } from "capi/patterns/consensus/mod.ts" /// Reference the latest block hash. -const blockHash = chain.blockHash() +const blockHash = polkadot.blockHash() /// Reference the associated block. const block = blockHash.block() @@ -26,7 +26,7 @@ const extrinsicsRaw = block.extrinsicsRaw() const events = block.events() /// Reference the author as well. -const author = babeBlockAuthor(chain, blockHash) +const author = babeBlockAuthor(polkadot, blockHash) /// Use `Rune.object` to parallelize these retrievals. const collection = await Rune diff --git a/examples/dev/metadata.eg.ts b/examples/dev/metadata.eg.ts index 0d155f7ba..b26bb2b45 100644 --- a/examples/dev/metadata.eg.ts +++ b/examples/dev/metadata.eg.ts @@ -10,9 +10,9 @@ * chances are that you don't need to work with the metadata directly. */ -import { chain } from "@capi/polkadot-dev" +import { polkadotDev } from "@capi/polkadot-dev" /// Execute the metadata Rune. -const metadata = await chain.metadata.run() +const metadata = await polkadotDev.metadata.run() console.log("Metadata:", metadata) diff --git a/examples/dev/storage_sizes.eg.ts b/examples/dev/storage_sizes.eg.ts index b0e7ec64e..5afff8c0c 100644 --- a/examples/dev/storage_sizes.eg.ts +++ b/examples/dev/storage_sizes.eg.ts @@ -7,12 +7,12 @@ * this can be helpful in the context of chain development. */ -import { chain } from "@capi/polkadot-dev" +import { polkadotDev } from "@capi/polkadot-dev" import { $ } from "capi" import { storageSizes } from "capi/patterns/storage_sizes.ts" /// Use the storageSizes factory to produce a Rune. Then execute it. -const sizes = await storageSizes(chain).run() +const sizes = await storageSizes(polkadotDev).run() /// Ensure `sizes` is of the expected shape. console.log("Sizes:", sizes) diff --git a/examples/ink/deploy.eg.ts b/examples/ink/deploy.eg.ts index c6892f78a..a8fefefc6 100644 --- a/examples/ink/deploy.eg.ts +++ b/examples/ink/deploy.eg.ts @@ -6,7 +6,7 @@ * is much the same as any other extrinsic submission. */ -import { chain } from "@capi/contracts-dev" +import { contractsDev } from "@capi/contracts-dev" import { $, createDevUsers, hex, Sr25519, ss58 } from "capi" import { InkMetadataRune } from "capi/patterns/ink/mod.ts" import { signature } from "capi/patterns/signature/polkadot.ts" @@ -27,7 +27,7 @@ const sender = senderSecret /// Instantiate `code.wasm` with `alice` and––upon block inclusion––return the /// list of system events specific to this instantiation. const events = await metadata - .instantiation(chain, { + .instantiation(contractsDev, { sender: sender.publicKey, code: Deno.readFileSync(new URL("./erc20.wasm", import.meta.url)), args: [1_000_000n], @@ -49,7 +49,7 @@ for (const { event } of events) { const accountId = event.value.contract console.log("Account id:", accountId) $.assert($.sizedUint8Array(32), accountId) - const address = ss58.encode(chain.System.SS58Prefix, accountId) + const address = ss58.encode(contractsDev.System.SS58Prefix, accountId) console.log("Contract ss58 address:", address) Deno.env.set("CONTRACT_SS58_ADDRESS", address) break diff --git a/examples/ink/interact.eg.ts b/examples/ink/interact.eg.ts index 35f43fd52..767f3398c 100644 --- a/examples/ink/interact.eg.ts +++ b/examples/ink/interact.eg.ts @@ -6,7 +6,7 @@ * as well as the submission of transactions. */ -import { chain } from "@capi/contracts-dev" +import { contractsDev } from "@capi/contracts-dev" import { assert } from "asserts" import { $, createDevUsers, hex } from "capi" import { InkMetadataRune } from "capi/patterns/ink/mod.ts" @@ -28,7 +28,7 @@ export const metadata = InkMetadataRune.fromMetadataText( ) /// Initialize an `InkRune` with `metadata`, `chain` and the deployed contract address. -const contract = metadata.instanceFromSs58(chain, address) +const contract = metadata.instanceFromSs58(contractsDev, address) const state = contract.call({ sender: alexa.publicKey, diff --git a/examples/misc/identity.eg.ts b/examples/misc/identity.eg.ts index 4893aec03..3cfb76b6e 100644 --- a/examples/misc/identity.eg.ts +++ b/examples/misc/identity.eg.ts @@ -6,7 +6,7 @@ * @description Set a user's identity, potentially with metadata of arbitrary user-defined shape. */ -import { chain } from "@capi/polkadot-dev" +import { polkadotDev } from "@capi/polkadot-dev" import { $, createDevUsers } from "capi" import { IdentityInfoTranscoders } from "capi/patterns/identity.ts" import { signature } from "capi/patterns/signature/polkadot.ts" @@ -18,7 +18,7 @@ const transcoders = new IdentityInfoTranscoders({ stars: $.u8 }) /// Encode some identity info into the expected shape and use it /// to execute the identity-setting transaction. -await chain.Identity +await polkadotDev.Identity .setIdentity({ info: transcoders.encode({ display: "Chev Chelios", @@ -32,7 +32,7 @@ await chain.Identity .run() /// Retrieve and decode the identity info. -const infoDecoded = await chain.Identity.IdentityOf +const infoDecoded = await polkadotDev.Identity.IdentityOf .value(alexa.publicKey) .unhandle(undefined) .access("info") diff --git a/examples/misc/indices.eg.ts b/examples/misc/indices.eg.ts index 45088e24d..50bae3249 100644 --- a/examples/misc/indices.eg.ts +++ b/examples/misc/indices.eg.ts @@ -5,7 +5,7 @@ * the user's account id using the index. */ -import { chain } from "@capi/polkadot-dev" +import { polkadotDev } from "@capi/polkadot-dev" import { assertEquals } from "asserts" import { createDevUsers } from "capi" import { signature } from "capi/patterns/signature/polkadot.ts" @@ -15,7 +15,7 @@ const { alexa } = await createDevUsers() const index = 254 /// Claim the index. -const hash = await chain.Indices +const hash = await polkadotDev.Indices .claim({ index }) .signed(signature({ sender: alexa })) .sent() @@ -24,7 +24,7 @@ const hash = await chain.Indices .run() /// Use the index to key into the indices accounts map. -const mapped = await chain.Indices.Accounts +const mapped = await polkadotDev.Indices.Accounts .value(index, hash) .unhandle(undefined) .access(0) diff --git a/examples/multisig/basic.eg.ts b/examples/multisig/basic.eg.ts index f83b342bc..ef874c569 100644 --- a/examples/multisig/basic.eg.ts +++ b/examples/multisig/basic.eg.ts @@ -6,7 +6,7 @@ * @test_skip */ -import { chain } from "@capi/polkadot-dev" +import { polkadotDev } from "@capi/polkadot-dev" import { assert } from "asserts" import { $, createDevUsers } from "capi" import { MultisigRune } from "capi/patterns/multisig/mod.ts" @@ -15,13 +15,13 @@ import { signature } from "capi/patterns/signature/polkadot.ts" const { alexa, billy, carol, david } = await createDevUsers() /// Initialize the `MultisigRune` with Alexa, Billy and Carol. Set the passing threshold to 2. -const multisig = MultisigRune.from(chain, { +const multisig = MultisigRune.from(polkadotDev, { signatories: [alexa, billy, carol].map(({ publicKey }) => publicKey), threshold: 2, }) /// Reference David's initial balance. We'll be executing a transfer of some funds to David. -const davidFree = chain.System.Account +const davidFree = polkadotDev.System.Account .value(david.publicKey) .unhandle(undefined) .access("data", "free") @@ -31,7 +31,7 @@ const davidFreeInitial = await davidFree.run() console.log("David free initial:", davidFreeInitial) /// Transfer initial funds to the multisig (existential deposit). -await chain.Balances +await polkadotDev.Balances .transfer({ value: 2_000_000_000_000n, dest: multisig.address, @@ -43,7 +43,7 @@ await chain.Balances .run() /// Describe the call we wish to dispatch from the multisig. -const call = chain.Balances.transferKeepAlive({ +const call = polkadotDev.Balances.transferKeepAlive({ dest: david.address, value: 1_230_000_000_000n, }) diff --git a/examples/multisig/stash.eg.ts b/examples/multisig/stash.eg.ts index a9d49754b..6c9d947d0 100644 --- a/examples/multisig/stash.eg.ts +++ b/examples/multisig/stash.eg.ts @@ -6,7 +6,7 @@ * @test_skip */ -import { chain, MultiAddress } from "@capi/polkadot-dev" +import { MultiAddress, polkadotDev } from "@capi/polkadot-dev" import { assert } from "asserts" import { createDevUsers } from "capi" import { MultisigRune } from "capi/patterns/multisig/mod.ts" @@ -16,13 +16,13 @@ import { signature } from "capi/patterns/signature/polkadot.ts" const { alexa, billy, carol } = await createDevUsers() /// Initialize the `MultisigRune` with Alexa, Billy and Carol. Set the passing threshold to 2. -const multisig = MultisigRune.from(chain, { +const multisig = MultisigRune.from(polkadotDev, { signatories: [alexa, billy, carol].map(({ publicKey }) => publicKey), threshold: 2, }) /// Send funds to the multisig (existential deposit). -await chain.Balances +await polkadotDev.Balances .transfer({ value: 20_000_000_000_000n, dest: multisig.address, @@ -35,7 +35,7 @@ await chain.Balances /// Describe the call which we wish to dispatch from the multisig account: /// the creation of the stash / pure proxy, belonging to the multisig account itself. -const call = chain.Proxy.createPure({ +const call = polkadotDev.Proxy.createPure({ proxyType: "Any", delay: 0, index: 0, @@ -63,7 +63,7 @@ const stashAccountId = await multisig .run() /// Send funds to the stash (existential deposit). -await chain.Balances +await polkadotDev.Balances .transfer({ value: 20_000_000_000_000n, dest: MultiAddress.Id(stashAccountId), @@ -75,7 +75,7 @@ await chain.Balances .run() /// Ensure that the funds arrived successfully. -const stashFree = await chain.System.Account +const stashFree = await polkadotDev.System.Account .value(stashAccountId) .unhandle(undefined) .access("data", "free") diff --git a/examples/multisig/virtual.eg.ts b/examples/multisig/virtual.eg.ts index 04c3b95b6..f13e41516 100644 --- a/examples/multisig/virtual.eg.ts +++ b/examples/multisig/virtual.eg.ts @@ -19,7 +19,7 @@ * @test_skip */ -import { chain, MultiAddress } from "@capi/polkadot-dev" +import { MultiAddress, polkadotDev } from "@capi/polkadot-dev" import { assert } from "asserts" import { $, createDevUsers, Rune, Sr25519 } from "capi" import { VirtualMultisigRune } from "capi/patterns/multisig/mod.ts" @@ -36,7 +36,7 @@ const { alexa, billy, carol, david } = await createDevUsers() let { state } = parse(Deno.args, { string: ["state"] }) if (!state) { state = await VirtualMultisigRune - .deployment(chain, { + .deployment(polkadotDev, { founders: [alexa.publicKey, billy.publicKey, carol.publicKey], threshold: 2, deployer: alexa.address, @@ -49,10 +49,10 @@ console.log("State:", state) $.assert($.str, state) /// Initialize a `VirtualMultisigRune` with the state's scale-encoded hex string. -const vMultisig = VirtualMultisigRune.fromHex(chain, state) +const vMultisig = VirtualMultisigRune.fromHex(polkadotDev, state) /// Transfer funds to the virtual multisig's stash account. -await chain.Balances +await polkadotDev.Balances .transfer({ dest: MultiAddress.Id(vMultisig.stash), value: 20_000_000_000_000n, @@ -64,7 +64,7 @@ await chain.Balances .run() /// Reference David's free balance. -const davidFree = chain.System.Account +const davidFree = polkadotDev.System.Account .value(david.publicKey) .unhandle(undefined) .access("data", "free") @@ -74,7 +74,7 @@ const davidFreeInitial = await davidFree.run() console.log("David free initial:", davidFreeInitial) /// Describe the call we wish to dispatch from the virtual multisig's stash. -const call = chain.Balances.transfer({ +const call = polkadotDev.Balances.transfer({ dest: david.address, value: 1_234_000_000_000n, }) @@ -91,7 +91,7 @@ console.log("David free final:", davidFreeFinal) assert(davidFreeFinal > davidFreeInitial) function fundAndRatify(name: string, sender: Sr25519) { - return chain.Utility + return polkadotDev.Utility .batchAll({ calls: Rune.array([ vMultisig.fundMemberProxy(sender.publicKey, 20_000_000_000_000n), diff --git a/examples/nfts.eg.ts b/examples/nfts.eg.ts index c920febe7..e440dcb40 100644 --- a/examples/nfts.eg.ts +++ b/examples/nfts.eg.ts @@ -7,26 +7,23 @@ */ import { - chain, CollectionConfig, MintSettings, MintType, PalletNftsEvent, RuntimeEvent, + westmint, } from "@capi/rococo-westmint/westmint" import { assertEquals } from "asserts" import { $, createDevUsers, Rune } from "capi" import { DefaultCollectionSetting, DefaultItemSetting } from "capi/patterns/nfts.ts" import { signature } from "capi/patterns/signature/statemint.ts" -/// Destructure the pallet bindings for later use. -const { Nfts } = chain - /// Create two dev users. Alexa will mint and list the NFT. Billy will purchase it. const { alexa, billy } = await createDevUsers() /// Create a collection and get the resulting events. -const createEvents = await Nfts +const createEvents = await westmint.Nfts .create({ config: CollectionConfig({ settings: DefaultCollectionSetting.AllOff, @@ -61,7 +58,7 @@ console.log("Collection id:", collection) const item = 46 /// Mint an item to the collection. -await Nfts +await westmint.Nfts .mint({ collection, item, @@ -73,7 +70,7 @@ await Nfts .finalized() .run() -const owner = Nfts.Item +const owner = westmint.Nfts.Item .value([collection, item]) .unhandle(undefined) .access("owner") @@ -91,12 +88,12 @@ assertEquals(initialOwner, alexa.publicKey) /// 2. Prevent further minting. /// 3. Lock the collection to prevent changes. const price = 1000000n -await chain.Utility +await westmint.Utility .batchAll({ calls: Rune.array([ - Nfts.setPrice({ collection, item, price }), - Nfts.setCollectionMaxSupply({ collection, maxSupply: 1 }), - Nfts.lockCollection({ collection, lockSettings: 8n }), /// TODO: enum helper + westmint.Nfts.setPrice({ collection, item, price }), + westmint.Nfts.setCollectionMaxSupply({ collection, maxSupply: 1 }), + westmint.Nfts.lockCollection({ collection, lockSettings: 8n }), /// TODO: enum helper ]), }) .signed(signature({ sender: alexa })) @@ -106,7 +103,7 @@ await chain.Utility .run() /// Retrieve the price of the NFT. -const bidPrice = await Nfts.ItemPriceOf +const bidPrice = await westmint.Nfts.ItemPriceOf .value([collection, item]) .unhandle(undefined) .access(0) @@ -117,7 +114,7 @@ console.log(bidPrice) assertEquals(price, bidPrice) /// Buy the NFT as Billy. -await Nfts +await westmint.Nfts .buyItem({ collection, item, bidPrice }) .signed(signature({ sender: billy })) .sent() diff --git a/examples/paginate.eg.ts b/examples/paginate.eg.ts index 9c7996633..de6c42ef3 100644 --- a/examples/paginate.eg.ts +++ b/examples/paginate.eg.ts @@ -4,18 +4,18 @@ * @description Read pages (either of keys or entries) from storage maps. */ -import { $accountInfo, chain } from "@capi/polkadot-dev" +import { $accountInfo, polkadotDev } from "@capi/polkadot-dev" import { $ } from "capi" // Reference the first 10 keys of a polkadot dev chain's system account map. -const accountKeys = await chain.System.Account.keyPage(10, null).run() +const accountKeys = await polkadotDev.System.Account.keyPage(10, null).run() /// Each key should be of type `Uint8Array`. console.log("Account keys:", accountKeys) $.assert($.sizedArray($.uint8Array, 10), accountKeys) // Reference the first 10 key-value pairs of a polkadot dev chain's system account map. -const accountEntries = await chain.System.Account.entryPage(10, null).run() +const accountEntries = await polkadotDev.System.Account.entryPage(10, null).run() /// Each entry should be of type `[Uint8Array, AccountInfo]` console.log("Account entries:", accountEntries) diff --git a/examples/raw_rpc/call.eg.ts b/examples/raw_rpc/call.eg.ts index 384fc56d0..62ce8a5c0 100644 --- a/examples/raw_rpc/call.eg.ts +++ b/examples/raw_rpc/call.eg.ts @@ -4,11 +4,11 @@ * @description Interact directly with the RPC node's call methods. */ -import { chain } from "@capi/polkadot-dev" +import { polkadotDev } from "@capi/polkadot-dev" import { $ } from "capi" /// Make a call. -const hash = await chain.connection +const hash = await polkadotDev.connection .call("chain_getFinalizedHead") .run() diff --git a/examples/raw_rpc/connection.ts b/examples/raw_rpc/connection.ts new file mode 100644 index 000000000..4c78f21f6 --- /dev/null +++ b/examples/raw_rpc/connection.ts @@ -0,0 +1,29 @@ +/** + * @title Raw Connection + * @unstable + * @description utilize a raw connection to interact with an RPC node + */ + +import { $, hex, WsConnection } from "capi" + +/// The connection's life will be bound to the following controller. +const controller = new AbortController() +const { signal } = controller + +/// Open the connection. +const connection = WsConnection.connect("wss://rpc.polkadot.io/", signal) + +/// Use the connection to retrieve the raw FRAME metadata. +const { result } = await connection.call("state_getMetadata", []) + +/// Ensure the result is a string. +$.assert($.str, result) + +/// Dispose of the connection. +controller.abort() + +/// Write the metadata to a a file for later use. +await Deno.writeFile( + new URL("./metadata", import.meta.url), + hex.decode(result), +) diff --git a/examples/raw_rpc/metadata b/examples/raw_rpc/metadata new file mode 100644 index 000000000..adb86a5f8 Binary files /dev/null and b/examples/raw_rpc/metadata differ diff --git a/examples/raw_rpc/subscription.eg.ts b/examples/raw_rpc/subscription.eg.ts index f1a1a6a0a..8ab0a7304 100644 --- a/examples/raw_rpc/subscription.eg.ts +++ b/examples/raw_rpc/subscription.eg.ts @@ -4,19 +4,21 @@ * @description Interact directly with the RPC node's subscription methods. */ -import { chain } from "@capi/polkadot-dev" +import { polkadotDev } from "@capi/polkadot-dev" import { $, known } from "capi" /// Get an async iterator, which yields subscription events. -const headerIter = chain.connection +const headerIter = polkadotDev.connection .subscribe("chain_subscribeFinalizedHeads", "chain_unsubscribeAllHeads") .iter() +/// Create a simple counter so that we can break iteration at 3. +let i = 0 + /// Iterate over its items and ensure they conform to the expected shape. -let count = 0 for await (const header of headerIter) { $.assert(known.$header, header) console.log(header) - count += 1 - if (count === 3) break + i += 1 + if (i === 3) break } diff --git a/examples/read/account_info.eg.ts b/examples/read/account_info.eg.ts index 159199bf6..9dbd14b97 100644 --- a/examples/read/account_info.eg.ts +++ b/examples/read/account_info.eg.ts @@ -4,13 +4,13 @@ * @description Read the value (an `AccountInfo`) from the system account map. */ -import { $accountInfo, chain } from "@capi/polkadot-dev" +import { $accountInfo, polkadotDev } from "@capi/polkadot-dev" import { $, createDevUsers } from "capi" const { alexa } = await createDevUsers() /// Retrieve Alexa's account info. -const accountInfo = await chain.System.Account.value(alexa.publicKey).run() +const accountInfo = await polkadotDev.System.Account.value(alexa.publicKey).run() /// Ensure that the account info is of the expected shape. console.log("Account info:", accountInfo) diff --git a/examples/read/era_reward_points.eg.ts b/examples/read/era_reward_points.eg.ts index e54dc6f26..6b5a9132d 100644 --- a/examples/read/era_reward_points.eg.ts +++ b/examples/read/era_reward_points.eg.ts @@ -6,17 +6,17 @@ * reward points). */ -import { $eraRewardPoints, chain } from "@capi/westend" +import { $eraRewardPoints, westend } from "@capi/westend" import { $ } from "capi" /// Reference the active era index. -const idx = chain.Staking.ActiveEra +const idx = westend.Staking.ActiveEra .value() .unhandle(undefined) .access("index") /// Retrieve the reward points corresponding to `idx`. -const points = await chain.Staking.ErasRewardPoints.value(idx).run() +const points = await westend.Staking.ErasRewardPoints.value(idx).run() /// Ensure the era reward points is of the correct shape. console.log("Era reward points:", points) diff --git a/examples/read/now.eg.ts b/examples/read/now.eg.ts index 0ae587262..c3130c9fa 100644 --- a/examples/read/now.eg.ts +++ b/examples/read/now.eg.ts @@ -4,11 +4,11 @@ * @description Read the current timestamp as agreed upon by validators. */ -import { chain } from "@capi/polkadot" +import { polkadot } from "@capi/polkadot" import { $ } from "capi" /// Retrieve the chain's current recorded time. -const now = await chain.Timestamp.Now.value().run() +const now = await polkadot.Timestamp.Now.value().run() /// Ensure `now` is of the correct shape. console.log("Now:", now) diff --git a/examples/read/para_heads.eg.ts b/examples/read/para_heads.eg.ts index 01e6e5704..df0d7153e 100644 --- a/examples/read/para_heads.eg.ts +++ b/examples/read/para_heads.eg.ts @@ -6,15 +6,15 @@ * (the corresponding parachain heads). */ -import { chain } from "@capi/polkadot" +import { polkadot } from "@capi/polkadot" import { $, ArrayRune, ValueRune } from "capi" /// Retrieve the head for each id in the parachains storage. -const heads = await chain.Paras.Parachains +const heads = await polkadot.Paras.Parachains .value() .unhandle(undefined) .into(ArrayRune) - .mapArray((id) => chain.Paras.Heads.value(id).unhandle(undefined)) + .mapArray((id) => polkadot.Paras.Heads.value(id).unhandle(undefined)) .into(ValueRune) .rehandle(undefined) .run() diff --git a/examples/sign/ed25519.eg.ts b/examples/sign/ed25519.eg.ts index ac360456c..8d1be92da 100644 --- a/examples/sign/ed25519.eg.ts +++ b/examples/sign/ed25519.eg.ts @@ -4,7 +4,7 @@ * @description Utilize an Ed25519 library for signing. */ -import { chain, MultiAddress } from "@capi/westend-dev" +import { MultiAddress, westendDev } from "@capi/westend-dev" import { assert } from "asserts" import { createDevUsers, ExtrinsicSender } from "capi" import { signature } from "capi/patterns/signature/polkadot.ts" @@ -13,7 +13,7 @@ import * as ed from "../../deps/ed25519.ts" const { alexa, billy } = await createDevUsers() /// Reference Billy's free balance for later use. -const billyFree = chain.System.Account +const billyFree = westendDev.System.Account .value(billy.publicKey) .unhandle(undefined) .access("data", "free") @@ -36,7 +36,7 @@ async function sign(msg: Uint8Array) { } /// Transfer some funds to the derived address (existential deposit). -await chain.Balances +await westendDev.Balances .transfer({ value: 1_000_000_000_000n, dest: address, @@ -49,7 +49,7 @@ await chain.Balances /// Execute a transfer from the derived user to Billy. We utilize our /// derived ed25519 `sign` function for this. -await chain.Balances +await westendDev.Balances .transfer({ value: 12345n, dest: billy.address, diff --git a/examples/sign/offline.eg.ts b/examples/sign/offline.eg.ts index 9bd120a9e..889a862d1 100644 --- a/examples/sign/offline.eg.ts +++ b/examples/sign/offline.eg.ts @@ -5,14 +5,14 @@ * Finally, rehydrate the extrinsic and submit it. */ -import { chain } from "@capi/westend-dev" +import { westendDev } from "@capi/westend-dev" import { $, createDevUsers, SignedExtrinsicRune } from "capi" import { signature } from "capi/patterns/signature/polkadot.ts" const { alexa, billy } = await createDevUsers() /// Create and sign the extrinsic. Extract the hex. -const hex = await chain.Balances +const hex = await westendDev.Balances .transfer({ value: 12345n, dest: billy.address, @@ -27,7 +27,7 @@ save(hex) /// Hydrate the signed extrinsic, submit it and await finalization. const hash = await SignedExtrinsicRune - .fromHex(chain, hex) + .fromHex(westendDev, hex) .sent() .dbgStatus("Tx status:") .finalized() diff --git a/examples/sign/pjs.eg.ts b/examples/sign/pjs.eg.ts index 7af0318c1..6245404ea 100644 --- a/examples/sign/pjs.eg.ts +++ b/examples/sign/pjs.eg.ts @@ -5,7 +5,7 @@ * extension) to sign a Capi extrinsic. */ -import { chain } from "@capi/polkadot-dev" +import { polkadotDev } from "@capi/polkadot-dev" import { createDevUsers, ss58 } from "capi" import { pjsSender, PjsSigner } from "capi/patterns/compat/pjs_sender.ts" import { signature } from "capi/patterns/signature/polkadot.ts" @@ -36,14 +36,14 @@ const pjsSigner: PjsSigner = { /// extension). In our case––since we manually create the signer––we'll also manually /// create the associated ss58 (by applying the prefix and Alexa's public key to /// Capi's `ss58.encode` util). -const alexaSs58 = ss58.encode(chain.System.SS58Prefix, alexa.publicKey) +const alexaSs58 = ss58.encode(polkadotDev.System.SS58Prefix, alexa.publicKey) /// Use the `chain` and signer to create a `sender` factory, which accepts an Ss58 /// address and returns the `ExtrinsicSender`. -const sender = pjsSender(chain, pjsSigner) +const sender = pjsSender(polkadotDev, pjsSigner) /// Sign and send the transfer with the pjs compat `sender` factory and Alexa's Ss58. -await chain.Balances +await polkadotDev.Balances .transfer({ value: 12345n, dest: billy.address, diff --git a/examples/smoldot/fetch_chainspec.eg.ts b/examples/smoldot/fetch_chainspec.eg.ts index ad219fe23..38d2c682a 100644 --- a/examples/smoldot/fetch_chainspec.eg.ts +++ b/examples/smoldot/fetch_chainspec.eg.ts @@ -6,10 +6,10 @@ * connect to the chain in the future. */ -import { chain } from "@capi/polkadot" +import { polkadot } from "@capi/polkadot" /// We'll connect to the polkadot wss server to get the chainspec. -const chainSpec = await chain.connection.call("sync_state_genSyncSpec", true).run() +const chainSpec = await polkadot.connection.call("sync_state_genSyncSpec", true).run() /// We'll print out the chainspec here. This can be written into a file for later use. console.log(JSON.stringify(chainSpec, null, 2)) diff --git a/examples/smoldot/smoldot.eg.ts b/examples/smoldot/smoldot.eg.ts index 993794f1a..c571a706a 100644 --- a/examples/smoldot/smoldot.eg.ts +++ b/examples/smoldot/smoldot.eg.ts @@ -6,18 +6,20 @@ * a centralized intermediary. This is the future of unstoppable applications. */ -import { chain } from "@capi/polkadot-dev" +import { PolkadotDevRune } from "@capi/polkadot-dev" import { $, known, SmoldotConnection } from "capi" /// Bring the chainspec into scope. Here, we'll import it from a local file. import relayChainSpec from "./chainspec.json" assert { type: "json" } -/// Initialize a `ChainRune` with `SmoldotConnection` and the chainspec. -const { block } = await chain - .with(SmoldotConnection.bind({ relayChainSpec: JSON.stringify(relayChainSpec) })) - .blockHash() - .block() - .run() +/// Use the generate chain rune with `SmoldotConnection` and the chainspec. +const polkadot = PolkadotDevRune + .from(SmoldotConnection.bind({ + relayChainSpec: JSON.stringify(relayChainSpec), + })) + +// Utilize the smoldot-connected `PolkadotRune` instance. +const { block } = await polkadot.blockHash().block().run() /// Ensure the block is of the expected shape. console.log(block) diff --git a/examples/tx/balances_transfer.eg.ts b/examples/tx/balances_transfer.eg.ts index c18656688..eeca5d25b 100644 --- a/examples/tx/balances_transfer.eg.ts +++ b/examples/tx/balances_transfer.eg.ts @@ -4,7 +4,7 @@ * @description Transfer some funds from one user to another. */ -import { chain } from "@capi/westend-dev" +import { westendDev } from "@capi/westend-dev" import { assert } from "asserts" import { createDevUsers } from "capi" import { signature } from "capi/patterns/signature/polkadot.ts" @@ -13,7 +13,7 @@ import { signature } from "capi/patterns/signature/polkadot.ts" const { alexa, billy } = await createDevUsers() /// Reference Billy's free balance. -const billyFree = chain.System.Account +const billyFree = westendDev.System.Account .value(billy.publicKey) .unhandle(undefined) .access("data", "free") @@ -23,7 +23,7 @@ const initialFree = await billyFree.run() console.log("Billy free initial:", initialFree) // Create and submit the transaction. -await chain.Balances +await westendDev.Balances .transfer({ value: 12345n, dest: billy.address, diff --git a/examples/tx/handle_errors.eg.ts b/examples/tx/handle_errors.eg.ts index 4ff5baa21..048ce4031 100644 --- a/examples/tx/handle_errors.eg.ts +++ b/examples/tx/handle_errors.eg.ts @@ -5,7 +5,7 @@ * easy decoding (and handling) of dispatch errors. */ -import { chain } from "@capi/contracts-dev" +import { contractsDev } from "@capi/contracts-dev" import { assertInstanceOf } from "asserts" import { createDevUsers, ExtrinsicError } from "capi" import { signature } from "capi/patterns/signature/polkadot.ts" @@ -13,7 +13,7 @@ import { signature } from "capi/patterns/signature/polkadot.ts" const { alexa, billy } = await createDevUsers() /// The following should reject with an `ExtrinsicError`. -const extrinsicError = await chain.Balances +const extrinsicError = await contractsDev.Balances .transfer({ value: 1_000_000_000_000_000_000_000_000_000_000_000_000n, dest: billy.address, diff --git a/examples/tx/utility_batch.eg.ts b/examples/tx/utility_batch.eg.ts index 1dad379a9..efc9a1744 100644 --- a/examples/tx/utility_batch.eg.ts +++ b/examples/tx/utility_batch.eg.ts @@ -4,7 +4,7 @@ * @description Sign and submit multiple calls within a single extrinsic. */ -import { chain } from "@capi/westend-dev" +import { westendDev } from "@capi/westend-dev" import { assert } from "asserts" import { createDevUsers, Rune } from "capi" import { signature } from "capi/patterns/signature/polkadot.ts" @@ -16,7 +16,7 @@ const [sender, ...recipients] = await createDevUsers(4) /// Reference the three recipient user free balances as a single Rune. const frees = Rune.tuple( recipients.map(({ publicKey }) => - chain.System.Account.value(publicKey).unhandle(undefined).access("data", "free") + westendDev.System.Account.value(publicKey).unhandle(undefined).access("data", "free") ), ) @@ -26,10 +26,10 @@ console.log("Initial frees:", initialFrees) /// Create and submit the batch call. Not how we must utilize `Rune.tuple` in /// order to convert the `Rune[]` into a `Rune`. -await chain.Utility +await westendDev.Utility .batch({ calls: Rune.tuple(recipients.map(({ address }) => - chain.Balances.transfer({ + westendDev.Balances.transfer({ dest: address, value: 3_000_000_123_456_789n, }) diff --git a/examples/watch.eg.ts b/examples/watch.eg.ts index a631eae4a..d7d7523fc 100644 --- a/examples/watch.eg.ts +++ b/examples/watch.eg.ts @@ -6,13 +6,13 @@ * produce promises resolving to subsequent states. */ -import { chain } from "@capi/polkadot" +import { polkadot } from "@capi/polkadot" import { $ } from "capi" /// Specifying `chain.latestBlockHash` indicates that (A) this Rune tree /// can be treated as reactive and (B) is a dependent of a "timeline" associated /// with Polkadot's block production. -const now = chain.Timestamp.Now.value(undefined, chain.latestBlockHash) +const now = polkadot.Timestamp.Now.value(undefined, polkadot.latestBlockHash) /// Create a simple counter so that we can break iteration at 3. let i = 0 diff --git a/examples/xcm/asset_teleportation.eg.ts b/examples/xcm/asset_teleportation.eg.ts index c754d1206..5af83f640 100644 --- a/examples/xcm/asset_teleportation.eg.ts +++ b/examples/xcm/asset_teleportation.eg.ts @@ -8,7 +8,7 @@ */ import { - chain as relayChain, + rococoDev, VersionedMultiAssets, VersionedMultiLocation, XcmV2AssetId, @@ -21,9 +21,9 @@ import { XcmV2WeightLimit, } from "@capi/rococo-dev" import { - chain as parachain, CumulusPalletParachainSystemEvent, RuntimeEvent, + westmint, } from "@capi/rococo-westmint/westmint" import { assert } from "asserts" import { createDevUsers, Rune } from "capi" @@ -32,7 +32,7 @@ import { signature } from "capi/patterns/signature/polkadot.ts" const { alexa } = await createDevUsers() /// Reference Alexa's free balance. -const alexaBalance = parachain.System.Account +const alexaBalance = westmint.System.Account .value(alexa.publicKey) .unhandle(undefined) .access("data", "free") @@ -42,7 +42,7 @@ const alexaFreeInitial = await alexaBalance.run() console.log("Alexa initial free:", alexaFreeInitial) /// Execute the teleportation without blocking. -relayChain.XcmPallet +rococoDev.XcmPallet .limitedTeleportAssets({ dest: VersionedMultiLocation.V2( XcmV2MultiLocation({ @@ -82,7 +82,7 @@ relayChain.XcmPallet /// Iterate over the parachain events until receiving a downward message processed event, /// at which point we can read alexa's free balance, which should be greater than the initial. outer: -for await (const e of parachain.System.Events.value(undefined, parachain.latestBlockHash).iter()) { +for await (const e of westmint.System.Events.value(undefined, westmint.latestBlockHash).iter()) { if (e) { for (const { event } of e) { if ( diff --git a/examples/xcm/reserve_transfer.eg.ts b/examples/xcm/reserve_transfer.eg.ts index f03292c1c..5e2f75e81 100644 --- a/examples/xcm/reserve_transfer.eg.ts +++ b/examples/xcm/reserve_transfer.eg.ts @@ -7,16 +7,16 @@ * @test_skip */ -import { chain as rococo, DoubleEncoded, Instruction } from "@capi/rococo-dev-xcm" +import { DoubleEncoded, Instruction, rococoDevXcm } from "@capi/rococo-dev-xcm" import { $assetDetails, AssetId, - chain as statemine, CumulusPalletXcmpQueueEvent, Fungibility, Junctions, NetworkId, RuntimeEvent, + statemine, VersionedMultiAssets, VersionedMultiLocation, VersionedXcm, @@ -25,7 +25,7 @@ import { XcmV1MultiAsset, XcmV1MultiLocation, } from "@capi/rococo-dev-xcm/statemine" -import { chain as trappist } from "@capi/rococo-dev-xcm/trappist" +import { trappist } from "@capi/rococo-dev-xcm/trappist" import { assert, assertNotEquals } from "asserts" import { $, alice as root, createDevUsers, Rune, ValueRune } from "capi" import { $siblId } from "capi/patterns/para_id.ts" @@ -50,10 +50,10 @@ const retryOptions = { /// Create a sufficient asset with Sudo. When targeting a common good /// parachain, access root instead through the relay chain. -await rococo.Sudo +await rococoDevXcm.Sudo // ae8aa6c (clean up reserve transfer example) .sudo({ - call: rococo.ParasSudoWrapper.sudoQueueDownwardXcm({ + call: rococoDevXcm.ParasSudoWrapper.sudoQueueDownwardXcm({ id: RESERVE_CHAIN_ID, xcm: VersionedXcm.V2( Rune.array([ diff --git a/fluent/SignedExtrinsicRune.ts b/fluent/SignedExtrinsicRune.ts index d3a45c3a6..5a555b911 100644 --- a/fluent/SignedExtrinsicRune.ts +++ b/fluent/SignedExtrinsicRune.ts @@ -8,14 +8,14 @@ export class SignedExtrinsicRune extends PatternRune static from( chain: ChainRune, ...[value]: RunicArgs - ) { + ): SignedExtrinsicRune> { return Rune.resolve(value).into(SignedExtrinsicRune, chain) } static fromHex( chain: ChainRune, ...[value]: RunicArgs - ) { + ): SignedExtrinsicRune> { return this.from(chain, Rune.resolve(value).map(hex.decode)) } diff --git a/import_map.json b/import_map.json index 389f65eba..93b2941ac 100644 --- a/import_map.json +++ b/import_map.json @@ -1,6 +1,6 @@ { "imports": { - "@capi/": "http://localhost:4646/29dcd8564faca56b/" + "@capi/": "http://localhost:4646/2c655e26fc9ba86a/" }, "scopes": { "examples/": { diff --git a/rune/mod.ts b/rune/mod.ts index edbd2d8ba..9d8afcb5c 100644 --- a/rune/mod.ts +++ b/rune/mod.ts @@ -1,6 +1,6 @@ export * from "./Rune.ts" -// moderate --exclude Rune.ts +// moderate --exclude _empty.js Rune.ts export * from "./ArrayRune.ts" export * from "./FnRune.ts" diff --git a/server/codegenHandler.ts b/server/codegenHandler.ts index 53644f60e..d96f77d19 100644 --- a/server/codegenHandler.ts +++ b/server/codegenHandler.ts @@ -10,7 +10,7 @@ import { decodeMetadata } from "../frame_metadata/decodeMetadata.ts" import { $metadata } from "../frame_metadata/raw/v14.ts" import { CacheBase } from "../util/cache/base.ts" import { WeakMemo } from "../util/memo.ts" -import { normalizePackageName } from "../util/normalize.ts" +import { normalizePackageName, normalizeVariableName } from "../util/normalize.ts" import { tsFormatter } from "../util/tsFormatter.ts" import { $codegenSpec, CodegenEntry } from "./codegenSpec.ts" import * as f from "./factories.ts" @@ -137,7 +137,7 @@ export function createCodegenHandler(dataCache: CacheBase, tempCache: CacheBase) const capiCode = `export * from "${relative(`${hash}/${key}/`, "capi/mod.ts")}"` files.set("capi.js", capiCode) files.set("capi.d.ts", capiCode) - writeConnectionCode(files, entry.connection) + writeConnectionCode(entry.chainName, files, entry.connection) return files }) } @@ -208,19 +208,39 @@ export function createCodegenHandler(dataCache: CacheBase, tempCache: CacheBase) } } -function writeConnectionCode(files: Map, connection: CodegenEntry["connection"]) { +function writeConnectionCode( + chainIdent: string, + files: Map, + connection: CodegenEntry["connection"], +) { + const chainRuneTypeName = `${chainIdent}Rune` + const chainRuneInstanceName = normalizeVariableName(chainIdent) files.set( - "connection.js", - `import * as C from "./capi.js" + "connection.d.ts", + connection + ? ` + import * as C from "./capi.js" + import { ${chainRuneTypeName} } from "./chain.js" -export const connect = C.${connection.type}.bind(${JSON.stringify(connection.discovery)}) -`, + export const connect: (signal: AbortSignal) => C.Connection + + export const ${chainRuneInstanceName}: ${chainRuneTypeName} + ` + : emptyMod, ) files.set( - "connection.d.ts", - `import * as C from "./capi.js" + "connection.js", + connection + ? ` + import * as C from "./capi.js" + import { ${chainRuneTypeName} } from "./chain.js" + + export const connect = C.${connection.type}.bind(${JSON.stringify(connection.discovery)}) -export const connect: (signal: AbortSignal) => C.Connection -`, + export const ${chainRuneInstanceName} = ${chainRuneTypeName}.from(connect) + ` + : emptyMod, ) } + +const emptyMod = "export {}" diff --git a/server/codegenSpec.ts b/server/codegenSpec.ts index f68080c56..a2926748c 100644 --- a/server/codegenSpec.ts +++ b/server/codegenSpec.ts @@ -6,7 +6,7 @@ const $codegenEntry = $.taggedUnion("type", [ "frame", $.field("metadata", $.sizedUint8Array(64)), $.field("chainName", $.str), - $.field( + $.optionalField( "connection", $.taggedUnion("type", [ $.variant("WsConnection", $.field("discovery", $.str)), diff --git a/util/normalize.ts b/util/normalize.ts index a9b4f2829..0a3f0d80f 100644 --- a/util/normalize.ts +++ b/util/normalize.ts @@ -14,3 +14,7 @@ export function normalizePackageName(name: string) { export function normalizeTypeName(name: string) { return normalizeIdent(name).replace(/^./, (x) => x.toUpperCase()) } + +export function normalizeVariableName(name: string) { + return normalizeIdent(name).replace(/^./, (x) => x.toLowerCase()) +}