import "../_dnt.polyfills.js"; import { hex } from "../crypto/mod.js" import * as $ from "../deps/scale.js" import { $extrinsic, decodeMetadata, FrameMetadata } from "../frame_metadata/mod.js" import { Connection } from "../rpc/mod.js" import { is, Rune, RunicArgs, ValueRune } from "../rune/mod.js" import { BlockHashRune } from "./BlockHashRune.js" import { CodecRune } from "./CodecRune.js" import { ConnectionRune } from "./ConnectionRune.js" import { ExtrinsicRune } from "./ExtrinsicRune.js" import { PalletRune } from "./PalletRune.js" export interface Chain { connection: Connection metadata: M } export namespace Chain { export type Call = $.Output export type Address = $.Output export type Signature = $.Output export type Extra = $.Output export type Additional = $.Output export type Pallets = C["metadata"]["pallets"] export type PalletName = keyof Pallets export type Pallet> = Pallets[P] export type Constants> = Pallet["constants"] export type ConstantName> = keyof Constants export type Constant, K extends ConstantName> = Constants[K] export namespace Constant { export type Value, K extends ConstantName> = $.Output["codec"]> } export type StorageEntries> = Pallet["storage"] export type StorageName> = keyof StorageEntries export type Storage, S extends StorageName> = StorageEntries[S] export namespace Storage { export type Key, S extends StorageName> = $.Output["key"]> export type PartialKey, S extends StorageName> = $.Output["partialKey"]> export type Value, S extends StorageName> = $.Output["value"]> } } // TODO: do we want to represent the discovery value and conn type within the type system? export class ChainRune extends Rune { static from( connect: (signal: AbortSignal) => Connection, staticMetadata?: M, ) { const connection = ConnectionRune.from(connect) const metadata = staticMetadata ?? Rune .fn(hex.decode) .call(connection.call("state_getMetadata")) .map(decodeMetadata) return Rune.object({ connection, metadata }).into(this) } with(connect: (signal: AbortSignal) => Connection) { const connection = ConnectionRune.from(connect) return Rune.object({ connection, metadata: this.metadata }).into(ChainRune) as ChainRune } connection = this.into(ValueRune).access("connection").into(ConnectionRune) metadata = this.into(ValueRune).access("metadata") $extrinsic = Rune.fn($extrinsic).call(this.metadata).into(CodecRune) latestBlockNum = this.connection .subscribe("chain_subscribeNewHeads", "chain_unsubscribeNewHeads") .access("number") latestBlockHash = this.connection .call("chain_getBlockHash", this.latestBlockNum) .unsafeAs() .into(BlockHashRune, this) blockHash(...[blockHash]: RunicArgs) { return Rune .resolve(blockHash) .handle(is(undefined), () => this.connection.call("chain_getFinalizedHead")) .into(BlockHashRune, this) } extrinsic(...args: RunicArgs]>) { const [call] = RunicArgs.resolve(args) return call.into(ExtrinsicRune, this.as(ChainRune)) } pallet

, X>(...[palletName]: RunicArgs) { return this.metadata .access("pallets", palletName) .unsafeAs>() .into(PalletRune, this.as(ChainRune)) } addressPrefix() { return this .pallet("System") .constant("SS58Prefix") .decoded } chainVersion = this.connection.call("system_version") } export interface AddressPrefixChain extends Chain { metadata: FrameMetadata & { pallets: { System: { constants: { SS58Prefix: { codec: $.Codec } } } } } }