@d9-network/ink 1.2.1 → 1.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +11 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.mjs +11 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["HexSink","Src","u128","buildPrimitiveCodec","buildSpecialTypeCodec","buildTupleCodec","findPrimitiveTypeId","codec","buildCompositeCodec","buildVariantCodec","u8","u16","u32","u64","u128","i8","i16","i32","i64","i128","bool","str","D9_SS58_PREFIX","_void","structDef: Record<string, AnyCodec>","isLangError","variantDef: Record<string, any>","indices: number[]","fieldCodec: AnyCodec","cache: CodecCache","eventLabel: string | null","rawEvent: RawContractEvent","results: TypedContractEvent<E>[]","contract: Uint8Array","data: Uint8Array","topics: Uint8Array[]","extrinsicIndex: number | undefined","error: unknown","from","Binary","DecodeError","timeoutId: ReturnType<typeof setTimeout>","TimeoutError","AbortedError","MetadataError","codecRegistry: Map<string, ResponseDecoder>","message","rawResponse: Uint8Array","ContractError","LangError","decodedResponse: M[K][\"response\"]","TransactionError","Binary","options","contract: Uint8Array","data: Uint8Array","topics: Uint8Array[]","codec","u8","u16","u32","u64","u128","i8","i16","i32","i64","i128","bool","str","D9_SS58_PREFIX","_void","structDef: Record<string, AnyCodec>","isLangError","variantDef: Record<string, any>","indices: number[]","fieldCodec: AnyCodec","cache: CodecCache","raw: RawContractCall","results: TypedContractCall<M>[]","raw: RawContractCall","results: ParsedContractExtrinsic<M>[]","address: SS58String | null"],"sources":["../src/encode.ts","../src/decode.ts","../src/codec-builder.ts","../src/events.ts","../src/subscriptions.ts","../src/message-builder.ts","../src/rpc.ts","../src/contract.ts","../src/sdk.ts","../src/event-types.ts","../src/codec-builder-internal.ts","../src/calls.ts","../src/extrinsic-parser.ts","../src/utils/fees.ts"],"sourcesContent":["/**\n * Encoding utilities for ContractsApi_call state_call\n */\n\nimport type { Bytes } from \"@subsquid/scale-codec\";\nimport { HexSink } from \"@subsquid/scale-codec\";\nimport type { Binary } from \"polkadot-api\";\nimport { fromHex } from \"polkadot-api/utils\";\n\n/**\n * Encode a contract call for ContractsApi_call state_call.\n *\n * The encoded format matches the ContractsApi::call runtime API:\n * - origin: AccountId (32 bytes)\n * - dest: AccountId (32 bytes)\n * - value: Balance (u128)\n * - gas_limit: Option<Weight> (1 byte for None)\n * - storage_deposit_limit: Option<Balance> (1 byte for None)\n * - input_data: Vec<u8> (compact length + bytes)\n *\n * @param origin - The origin account (as Uint8Array or hex string)\n * @param dest - The contract address (as Uint8Array or hex string)\n * @param input - The encoded call data (selector + arguments)\n * @param value - Optional value to transfer (default: 0)\n * @returns Hex-encoded bytes for state_call\n */\nexport function encodeContractCall(\n origin: Uint8Array | string,\n dest: Uint8Array | string,\n input: Binary | Uint8Array,\n value: bigint = 0n,\n): Bytes {\n const sink = new HexSink();\n\n const originBytes = typeof origin === \"string\" ? fromHex(origin) : origin;\n const destBytes = typeof dest === \"string\" ? fromHex(dest) : dest;\n const inputBytes = \"asBytes\" in input ? input.asBytes() : input;\n\n // origin: AccountId\n sink.bytes(originBytes);\n // dest: AccountId\n sink.bytes(destBytes);\n // value: Balance (u128)\n sink.u128(value);\n // gas_limit: Option<Weight> - None\n sink.u8(0);\n // storage_deposit_limit: Option<Balance> - None\n sink.u8(0);\n // input_data: Vec<u8>\n sink.compact(inputBytes.length);\n sink.bytes(inputBytes);\n\n return sink.toHex();\n}\n\n/**\n * Encode a contract call using the same address for origin and dest.\n * This is a simplified version for query operations where the origin\n * doesn't matter much.\n *\n * @param address - The contract address\n * @param input - The encoded call data\n * @param value - Optional value to transfer\n * @returns Hex-encoded bytes for state_call\n */\nexport function encodeCall(\n address: Uint8Array | string,\n input: Binary | Uint8Array,\n value: bigint = 0n,\n): Bytes {\n return encodeContractCall(address, address, input, value);\n}\n\n/**\n * Encode a contract call with specific gas limit and storage deposit limit.\n *\n * @param origin - The origin account\n * @param dest - The contract address\n * @param input - The encoded call data\n * @param options - Call options including value, gas limit, storage deposit limit\n * @returns Hex-encoded bytes for state_call\n */\nexport function encodeContractCallWithLimits(\n origin: Uint8Array | string,\n dest: Uint8Array | string,\n input: Binary | Uint8Array,\n options: {\n value?: bigint;\n gasLimit?: { refTime: bigint; proofSize: bigint };\n storageDepositLimit?: bigint;\n } = {},\n): Bytes {\n const sink = new HexSink();\n\n const originBytes = typeof origin === \"string\" ? fromHex(origin) : origin;\n const destBytes = typeof dest === \"string\" ? fromHex(dest) : dest;\n const inputBytes = \"asBytes\" in input ? input.asBytes() : input;\n\n // origin: AccountId\n sink.bytes(originBytes);\n // dest: AccountId\n sink.bytes(destBytes);\n // value: Balance (u128)\n sink.u128(options.value ?? 0n);\n\n // gas_limit: Option<Weight>\n if (options.gasLimit) {\n sink.u8(1); // Some\n sink.compact(options.gasLimit.refTime);\n sink.compact(options.gasLimit.proofSize);\n } else {\n sink.u8(0); // None\n }\n\n // storage_deposit_limit: Option<Balance>\n if (options.storageDepositLimit !== undefined) {\n sink.u8(1); // Some\n sink.u128(options.storageDepositLimit);\n } else {\n sink.u8(0); // None\n }\n\n // input_data: Vec<u8>\n sink.compact(inputBytes.length);\n sink.bytes(inputBytes);\n\n return sink.toHex();\n}\n","/**\n * Decoding utilities for ContractsApi_call response\n */\n\nimport { Src } from \"@subsquid/scale-codec\";\nimport { type Codec, u128, Tuple } from \"@polkadot-api/substrate-bindings\";\n\n/**\n * Gas information from contract execution\n */\nexport interface GasInfo {\n /** Gas consumed during execution */\n gasConsumed: { refTime: bigint; proofSize: bigint };\n /** Gas required for execution */\n gasRequired: { refTime: bigint; proofSize: bigint };\n}\n\n/**\n * Storage deposit information\n */\nexport interface StorageDepositInfo {\n /** Storage deposit type: 0 = Refund, 1 = Charge */\n type: \"Refund\" | \"Charge\";\n /** Amount of storage deposit */\n amount: bigint;\n}\n\n/**\n * Full decoded result from ContractsApi_call\n */\nexport interface ContractCallResult {\n /** Gas information */\n gas: GasInfo;\n /** Storage deposit information */\n storageDeposit: StorageDepositInfo;\n /** Debug message (if any) */\n debugMessage: string;\n /** Whether the execution was successful */\n success: boolean;\n /** Execution flags */\n flags: number;\n /** The raw execution result bytes (still wrapped in Result<T, LangError>) */\n data: Uint8Array;\n}\n\n/**\n * Decode the raw ContractsApi_call response.\n *\n * The response format is:\n * - gasConsumed: Weight { ref_time: Compact<u64>, proof_size: Compact<u64> }\n * - gasRequired: Weight\n * - storageDeposit: StorageDeposit { variant: u8, amount: u128 }\n * - debugMessage: String\n * - result: Result<ExecReturnValue, DispatchError>\n * - ExecReturnValue: { flags: u32, data: Vec<u8> }\n *\n * @param result - The raw response bytes from state_call ContractsApi_call\n * @returns Decoded contract call result\n */\nexport function decodeContractCallResult(result: Uint8Array): ContractCallResult {\n const src = new Src(result);\n\n // gasConsumed: Weight\n const gasConsumedRefTime = BigInt(src.compact());\n const gasConsumedProofSize = BigInt(src.compact());\n\n // gasRequired: Weight\n const gasRequiredRefTime = BigInt(src.compact());\n const gasRequiredProofSize = BigInt(src.compact());\n\n // storageDeposit: StorageDeposit\n const storageDepositVariant = src.u8();\n const storageDepositAmount = src.u128();\n\n // debugMessage: String\n const debugMessage = src.str();\n\n // result: Result<ExecReturnValue, DispatchError>\n const resultVariant = src.u8(); // 0 = Ok, 1 = Err\n const success = resultVariant === 0;\n\n // ExecReturnValue: { flags: u32, data: Vec<u8> }\n const flags = src.u32();\n const data = src.bytes(src.compactLength());\n\n return {\n gas: {\n gasConsumed: {\n refTime: gasConsumedRefTime,\n proofSize: gasConsumedProofSize,\n },\n gasRequired: {\n refTime: gasRequiredRefTime,\n proofSize: gasRequiredProofSize,\n },\n },\n storageDeposit: {\n type: storageDepositVariant === 0 ? \"Refund\" : \"Charge\",\n amount: storageDepositAmount,\n },\n debugMessage,\n success,\n flags,\n data,\n };\n}\n\n/**\n * Unwrap the inner value from Result<T, LangError> by checking the variant byte.\n *\n * Ink contracts wrap their return values in Result<T, LangError>.\n * This function handles the unwrapping and throws an error for LangError.\n *\n * @param data - The exec result bytes (Result<T, LangError> encoded)\n * @returns The inner value bytes (T encoded)\n * @throws Error if the result is Err variant (LangError)\n */\nexport function unwrapInkResult(data: Uint8Array): Uint8Array {\n if (data.length === 0) {\n throw new Error(\"Empty result data\");\n }\n\n const variant = data[0];\n\n if (variant === 0) {\n // Ok variant - return the inner data (skip the variant byte)\n return data.slice(1);\n } else if (variant === 1) {\n // Err variant - LangError\n throw new Error(\"Contract call returned LangError\");\n } else {\n throw new Error(`Unknown result variant: ${variant}`);\n }\n}\n\n/**\n * Check if the result indicates a LangError\n *\n * @param data - The exec result bytes\n * @returns True if it's a LangError (Err variant)\n */\nexport function isLangError(data: Uint8Array): boolean {\n return data.length > 0 && data[0] === 1;\n}\n\n/**\n * Decode ink contract message result using a custom SCALE codec.\n * This bypasses polkadot-api's ink decoder which has issues with LangError type.\n *\n * @param data - The exec result bytes (Result<T, LangError> encoded)\n * @param codec - The SCALE codec for the inner value type T\n * @returns The decoded value\n */\nexport function decodeInkValue<T>(data: Uint8Array, codec: Codec<T>): T {\n const innerData = unwrapInkResult(data);\n return codec.dec(innerData);\n}\n\n/**\n * Pre-defined codecs for common types\n */\nexport const InkCodecs = {\n /** u128 codec for Balance type */\n u128,\n /** Tuple of two u128 values, commonly used for (Balance, Balance) */\n balancePair: Tuple(u128, u128),\n};\n","/**\n * Auto-build SCALE decoders from ink metadata type definitions.\n *\n * This module provides a way to automatically construct decoders for ink contract\n * message return types without manually specifying codecs for each message.\n */\n\nimport {\n u8,\n u16,\n u32,\n u64,\n u128,\n i8,\n i16,\n i32,\n i64,\n i128,\n bool,\n str,\n Bytes,\n Vector,\n Tuple,\n Struct,\n Variant,\n _void,\n Option,\n AccountId,\n type Codec,\n} from \"@polkadot-api/substrate-bindings\";\nimport type { InkMetadata } from \"@polkadot-api/ink-contracts\";\nimport { blake2b } from \"@noble/hashes/blake2.js\";\nimport { D9_SS58_PREFIX } from \"@d9-network/spec\";\n\n// Use 'any' for dynamic codec building to avoid TypeScript strict type issues\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyCodec = Codec<any>;\n\n/**\n * Type definition from ink metadata\n */\ninterface TypeDef {\n primitive?: string;\n composite?: {\n fields: Array<{\n name?: string;\n type: number;\n typeName?: string;\n }>;\n };\n variant?: {\n variants: Array<{\n name: string;\n index: number;\n fields: Array<{\n name?: string;\n type: number;\n typeName?: string;\n }>;\n }>;\n };\n sequence?: {\n type: number;\n };\n array?: {\n len: number;\n type: number;\n };\n tuple?: number[];\n}\n\ninterface TypeEntry {\n id: number;\n type: {\n def: TypeDef;\n path?: string[];\n params?: Array<{\n name: string;\n type?: number;\n }>;\n };\n}\n\n/**\n * Cache for built codecs to avoid rebuilding the same type\n */\ntype CodecCache = Map<number, AnyCodec>;\n\n/**\n * Build a SCALE codec from ink metadata type definition\n */\nfunction buildCodecFromType(typeId: number, types: TypeEntry[], cache: CodecCache): AnyCodec {\n // Check cache first\n const cached = cache.get(typeId);\n if (cached) {\n return cached;\n }\n\n const typeEntry = types.find((t) => t.id === typeId);\n if (!typeEntry) {\n throw new Error(`Type ${typeId} not found in metadata`);\n }\n\n const def = typeEntry.type.def;\n const path = typeEntry.type.path;\n\n // Handle primitive types\n if (def.primitive) {\n const codec = buildPrimitiveCodec(def.primitive);\n cache.set(typeId, codec);\n return codec;\n }\n\n // Handle special path types (AccountId, Hash, etc.)\n if (path && path.length > 0) {\n const specialCodec = buildSpecialTypeCodec(path, typeEntry, types, cache);\n if (specialCodec) {\n cache.set(typeId, specialCodec);\n return specialCodec;\n }\n }\n\n // Handle tuple\n if (def.tuple) {\n const codec = buildTupleCodec(def.tuple, types, cache);\n cache.set(typeId, codec);\n return codec;\n }\n\n // Handle sequence (Vec<T>)\n if (def.sequence) {\n const innerCodec = buildCodecFromType(def.sequence.type, types, cache);\n const codec = Vector(innerCodec);\n cache.set(typeId, codec);\n return codec;\n }\n\n // Handle array [T; N]\n if (def.array) {\n const innerCodec = buildCodecFromType(def.array.type, types, cache);\n // For fixed-size byte arrays, use Bytes\n if (def.array.type === findPrimitiveTypeId(types, \"u8\")) {\n const codec = Bytes(def.array.len);\n cache.set(typeId, codec);\n return codec;\n }\n // For other arrays, use Vector with fixed length validation\n const codec = Vector(innerCodec, def.array.len);\n cache.set(typeId, codec);\n return codec;\n }\n\n // Handle composite (struct)\n if (def.composite) {\n const codec = buildCompositeCodec(def.composite, types, cache);\n cache.set(typeId, codec);\n return codec;\n }\n\n // Handle variant (enum)\n if (def.variant) {\n const codec = buildVariantCodec(def.variant, path, types, cache);\n cache.set(typeId, codec);\n return codec;\n }\n\n throw new Error(`Unknown type definition for type ${typeId}: ${JSON.stringify(def)}`);\n}\n\n/**\n * Build codec for primitive types\n */\nfunction buildPrimitiveCodec(primitive: string): AnyCodec {\n switch (primitive) {\n case \"u8\":\n return u8;\n case \"u16\":\n return u16;\n case \"u32\":\n return u32;\n case \"u64\":\n return u64;\n case \"u128\":\n return u128;\n case \"i8\":\n return i8;\n case \"i16\":\n return i16;\n case \"i32\":\n return i32;\n case \"i64\":\n return i64;\n case \"i128\":\n return i128;\n case \"bool\":\n return bool;\n case \"str\":\n return str;\n default:\n throw new Error(`Unknown primitive type: ${primitive}`);\n }\n}\n\n/**\n * Build codec for special types based on path\n */\nfunction buildSpecialTypeCodec(\n path: string[],\n typeEntry: TypeEntry,\n types: TypeEntry[],\n cache: CodecCache,\n): AnyCodec | null {\n const fullPath = path.join(\"::\");\n\n // AccountId type\n if (fullPath.includes(\"AccountId\")) {\n return AccountId(D9_SS58_PREFIX);\n }\n\n // Option type\n if (path[0] === \"Option\") {\n const params = typeEntry.type.params;\n if (params && params.length > 0 && params[0]?.type !== undefined) {\n const innerCodec = buildCodecFromType(params[0].type, types, cache);\n return Option(innerCodec);\n }\n }\n\n // Result type - we need special handling\n if (path[0] === \"Result\") {\n const params = typeEntry.type.params;\n if (params && params.length >= 2) {\n const okTypeId = params[0]?.type;\n const errTypeId = params[1]?.type;\n if (okTypeId !== undefined && errTypeId !== undefined) {\n const okCodec = buildCodecFromType(okTypeId, types, cache);\n const errCodec = buildCodecFromType(errTypeId, types, cache);\n // Build a proper Result variant\n return Variant(\n {\n Ok: okCodec,\n Err: errCodec,\n },\n [0, 1],\n );\n }\n }\n }\n\n return null;\n}\n\n/**\n * Build codec for tuple types\n */\nfunction buildTupleCodec(tupleTypes: number[], types: TypeEntry[], cache: CodecCache): AnyCodec {\n if (tupleTypes.length === 0) {\n return _void;\n }\n\n const innerCodecs = tupleTypes.map((t) => buildCodecFromType(t, types, cache));\n\n // Handle different tuple sizes\n switch (innerCodecs.length) {\n case 1:\n return Tuple(innerCodecs[0]!);\n case 2:\n return Tuple(innerCodecs[0]!, innerCodecs[1]!);\n case 3:\n return Tuple(innerCodecs[0]!, innerCodecs[1]!, innerCodecs[2]!);\n case 4:\n return Tuple(innerCodecs[0]!, innerCodecs[1]!, innerCodecs[2]!, innerCodecs[3]!);\n default:\n // For larger tuples, use dynamic tuple (cast to any)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (Tuple as any)(...innerCodecs);\n }\n}\n\n/**\n * Build codec for composite (struct) types\n */\nfunction buildCompositeCodec(\n composite: NonNullable<TypeDef[\"composite\"]>,\n types: TypeEntry[],\n cache: CodecCache,\n): AnyCodec {\n const fields = composite.fields;\n\n // Single unnamed field - unwrap it\n if (fields.length === 1 && !fields[0]?.name) {\n return buildCodecFromType(fields[0]!.type, types, cache);\n }\n\n // Multiple fields - build a struct\n const structDef: Record<string, AnyCodec> = {};\n for (const field of fields) {\n const fieldName = field.name || `field${fields.indexOf(field)}`;\n structDef[fieldName] = buildCodecFromType(field.type, types, cache);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return Struct(structDef as any);\n}\n\n/**\n * Build codec for variant (enum) types\n */\nfunction buildVariantCodec(\n variant: NonNullable<TypeDef[\"variant\"]>,\n path: string[] | undefined,\n types: TypeEntry[],\n cache: CodecCache,\n): AnyCodec {\n const variants = variant.variants;\n\n // Check if this is a LangError type (ink specific)\n const isLangError = path?.includes(\"LangError\");\n\n // Build variant definition\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const variantDef: Record<string, any> = {};\n const indices: number[] = [];\n\n // For LangError, add a placeholder for index 0 if missing\n if (isLangError && !variants.some((v) => v.index === 0)) {\n variantDef[\"_Placeholder\"] = _void;\n indices.push(0);\n }\n\n for (const v of variants) {\n let fieldCodec: AnyCodec;\n\n // Handle variants with no fields or undefined fields\n const fields = v.fields ?? [];\n\n if (fields.length === 0) {\n fieldCodec = _void;\n } else if (fields.length === 1 && !fields[0]?.name) {\n // Single unnamed field\n fieldCodec = buildCodecFromType(fields[0]!.type, types, cache);\n } else {\n // Multiple or named fields - build struct\n const structDef: Record<string, AnyCodec> = {};\n for (const field of fields) {\n const fieldName = field.name || `field${fields.indexOf(field)}`;\n structDef[fieldName] = buildCodecFromType(field.type, types, cache);\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n fieldCodec = Struct(structDef as any);\n }\n\n variantDef[v.name] = fieldCodec;\n indices.push(v.index);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return Variant(variantDef as any, indices as any);\n}\n\n/**\n * Find the type ID for a primitive type\n */\nfunction findPrimitiveTypeId(types: TypeEntry[], primitive: string): number {\n const entry = types.find((t) => t.type.def.primitive === primitive);\n return entry?.id ?? -1;\n}\n\n/**\n * Extract the inner type from Result<T, LangError>\n * Returns the type ID of T\n */\nfunction extractResultInnerType(typeEntry: TypeEntry): number | null {\n const path = typeEntry.type.path;\n if (!path || path[0] !== \"Result\") {\n return null;\n }\n\n const params = typeEntry.type.params;\n if (!params || params.length < 1) {\n return null;\n }\n\n return params[0]?.type ?? null;\n}\n\n/**\n * Build a decoder for a message's return type from ink metadata.\n * This handles the Result<T, LangError> wrapper and returns a decoder for T.\n *\n * @param metadata - The ink contract metadata\n * @param messageLabel - The message label (e.g., \"PSP22::balance_of\")\n * @returns A decoder function that decodes the inner value bytes\n */\nexport function buildMessageDecoder(\n metadata: InkMetadata,\n messageLabel: string,\n): (data: Uint8Array) => unknown {\n const types = metadata.types as TypeEntry[];\n const message = metadata.spec.messages.find((m) => m.label === messageLabel);\n\n if (!message) {\n throw new Error(`Message \"${messageLabel}\" not found in metadata`);\n }\n\n const returnTypeId = message.returnType.type;\n const returnTypeEntry = types.find((t) => t.id === returnTypeId);\n\n if (!returnTypeEntry) {\n throw new Error(`Return type ${returnTypeId} not found for message \"${messageLabel}\"`);\n }\n\n const cache: CodecCache = new Map();\n\n // Check if it's a Result type and extract inner type\n const innerTypeId = extractResultInnerType(returnTypeEntry);\n\n if (innerTypeId !== null) {\n // Build decoder for the inner type (T in Result<T, LangError>)\n const innerCodec = buildCodecFromType(innerTypeId, types, cache);\n return (data: Uint8Array) => innerCodec.dec(data);\n }\n\n // Not a Result type, build decoder for the full return type\n const codec = buildCodecFromType(returnTypeId, types, cache);\n return (data: Uint8Array) => codec.dec(data);\n}\n\n/**\n * Build decoders for all messages in the metadata.\n * Returns a Map of message label -> decoder function.\n */\nexport function buildAllMessageDecoders(\n metadata: InkMetadata,\n): Map<string, (data: Uint8Array) => unknown> {\n const decoders = new Map<string, (data: Uint8Array) => unknown>();\n\n for (const message of metadata.spec.messages as Array<{ label: string }>) {\n try {\n const decoder = buildMessageDecoder(metadata, message.label);\n decoders.set(message.label, decoder);\n } catch (error) {\n console.warn(`Failed to build decoder for message \"${message.label}\":`, error);\n }\n }\n\n return decoders;\n}\n\n/**\n * Create a codec registry compatible with ResponseDecoder type\n */\nexport function createCodecRegistry(\n metadata: InkMetadata,\n): Map<string, { dec: (data: Uint8Array) => unknown }> {\n const decoders = buildAllMessageDecoders(metadata);\n const registry = new Map<string, { dec: (data: Uint8Array) => unknown }>();\n\n for (const [label, decoder] of decoders) {\n registry.set(label, { dec: decoder });\n }\n\n return registry;\n}\n\n/**\n * Build a SCALE decoder for a contract event from ink metadata\n *\n * @param metadata - The ink contract metadata\n * @param eventLabel - The event label (e.g., \"Transfer\", \"Approval\")\n * @returns A decoder function that decodes the event data bytes\n */\nexport function buildEventDecoder(\n metadata: InkMetadata,\n eventLabel: string,\n): (data: Uint8Array) => unknown {\n const types = metadata.types as TypeEntry[];\n const events = metadata.spec.events as Array<{\n label: string;\n args: Array<{\n label: string;\n type: { type: number };\n }>;\n }>;\n\n const event = events.find((e) => e.label === eventLabel);\n\n if (!event) {\n throw new Error(`Event \"${eventLabel}\" not found in metadata`);\n }\n\n const cache: CodecCache = new Map();\n\n // Build struct codec from event args\n const structDef: Record<string, AnyCodec> = {};\n\n for (const arg of event.args) {\n const fieldName = arg.label;\n const fieldCodec = buildCodecFromType(arg.type.type, types, cache);\n structDef[fieldName] = fieldCodec;\n }\n\n // If event has no args, return void decoder\n if (event.args.length === 0) {\n return () => undefined;\n }\n\n // If event has single unnamed arg, unwrap it\n if (event.args.length === 1) {\n const argCodec = structDef[event.args[0]!.label];\n return (data: Uint8Array) => argCodec!.dec(data);\n }\n\n // Multiple args - return struct\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const codec = Struct(structDef as any);\n return (data: Uint8Array) => codec.dec(data);\n}\n\n/**\n * Build decoders for all events in the metadata\n *\n * @param metadata - The ink contract metadata\n * @returns Map of event label -> decoder function\n */\nexport function buildAllEventDecoders(\n metadata: InkMetadata,\n): Map<string, (data: Uint8Array) => unknown> {\n const decoders = new Map<string, (data: Uint8Array) => unknown>();\n\n const events = metadata.spec.events as Array<{ label: string }>;\n\n for (const event of events) {\n try {\n const decoder = buildEventDecoder(metadata, event.label);\n decoders.set(event.label, decoder);\n } catch (error) {\n console.warn(`Failed to build decoder for event \"${event.label}\":`, error);\n }\n }\n\n return decoders;\n}\n\n/**\n * Get event signature (topic[0]) for filtering\n * Events in ink! use blake2_256 hash of event label as topic[0]\n *\n * @param eventLabel - The event label (e.g., \"Transfer\")\n * @returns Event signature as Uint8Array (32 bytes)\n */\nexport function getEventSignature(eventLabel: string): Uint8Array {\n return blake2b(new TextEncoder().encode(eventLabel), { dkLen: 32 });\n}\n\n/**\n * Create ASCII-encoded event topic (D9 chain format)\n *\n * D9 chain uses a format where:\n * - First byte is 0x00 (null)\n * - Remaining 31 bytes are ASCII characters of `ContractName::EventLabel`\n * - Total is exactly 32 bytes (truncated/padded as needed)\n *\n * @param contractName - Contract name (e.g., \"MarketMaker\", \"Usdt\")\n * @param eventLabel - Event label (e.g., \"Transfer\", \"USDTToD9Conversion\")\n * @returns 32-byte topic with null prefix and ASCII-encoded path\n */\nexport function createAsciiEventTopic(contractName: string, eventLabel: string): Uint8Array {\n const topic = new Uint8Array(32);\n topic[0] = 0; // Null prefix\n const encoder = new TextEncoder();\n const fullPath = `${contractName}::${eventLabel}`;\n const encoded = encoder.encode(fullPath);\n // Copy up to 31 bytes (leaving room for null prefix)\n topic.set(encoded.slice(0, 31), 1);\n return topic;\n}\n","/**\n * Event parsing and filtering for ink! contracts\n */\nimport type {\n InkMetadata,\n InkDescriptors,\n InkStorageDescriptor,\n InkCallableDescriptor,\n Event as InkEvent,\n} from \"@polkadot-api/ink-contracts\";\nimport type { Enum, SS58String } from \"polkadot-api\";\nimport { ss58Decode } from \"@polkadot-labs/hdkd-helpers\";\nimport { toD9Address } from \"@d9-network/spec\";\nimport { buildAllEventDecoders, buildEventDecoder, getEventSignature } from \"./codec-builder\";\nimport type {\n TypedContractEvent,\n EventFilterOptions,\n RawContractEvent,\n ExtractEnumDef,\n ExtractEventLabels,\n ChainEventRecord,\n} from \"./event-types\";\n\n/**\n * Type-safe event parser for a specific contract\n *\n * @typeParam S - The storage descriptor type\n * @typeParam M - The messages descriptor type\n * @typeParam C - The constructors descriptor type\n * @typeParam E - The event type representing all possible events for this contract\n */\nexport class ContractEventParser<\n S extends InkStorageDescriptor = InkStorageDescriptor,\n M extends InkCallableDescriptor = InkCallableDescriptor,\n C extends InkCallableDescriptor = InkCallableDescriptor,\n E extends InkEvent = InkEvent,\n> {\n private eventDecoders: Map<string, (data: Uint8Array) => unknown>;\n private eventSignatures: Map<string, Uint8Array>;\n private contractAddressBytes: Uint8Array;\n private contractAddress: SS58String;\n private metadata: InkMetadata;\n\n constructor(descriptor: InkDescriptors<S, M, C, E>, contractAddress: SS58String) {\n if (!descriptor.metadata) {\n throw new Error(\"Contract descriptor must include metadata\");\n }\n this.metadata = descriptor.metadata;\n // Always store address in D9 format for consistency\n this.contractAddress = toD9Address(contractAddress);\n this.eventDecoders = buildAllEventDecoders(this.metadata);\n // Use original address for bytes decoding (result is the same regardless of prefix)\n this.contractAddressBytes = ss58Decode(contractAddress)[0];\n\n // Build signature map for topic filtering\n this.eventSignatures = new Map();\n const events = this.metadata.spec.events as Array<{ label: string }>;\n\n for (const event of events) {\n const sig = getEventSignature(event.label);\n this.eventSignatures.set(event.label, sig);\n }\n }\n\n /**\n * Parse a raw chain event into a type-safe contract event (if it matches)\n * Returns null if the event is not from this contract or cannot be parsed\n *\n * @example\n * ```ts\n * const event = parser.parseEvent(chainEvent);\n * if (event?.type === \"Transfer\") {\n * // event.value is now typed as { from: SS58String; to: SS58String; value: bigint }\n * console.log(event.value.from);\n * }\n * ```\n */\n parseEvent(chainEvent: unknown): TypedContractEvent<E> | null {\n // Extract Contracts.ContractEmitted event from chain event\n const extracted = this.extractContractEmittedEvent(chainEvent);\n if (!extracted) return null;\n\n const { contract, data, topics, blockNumber, blockHash, eventIndex, extrinsicIndex } = extracted;\n\n // Filter by contract address\n if (!this.bytesEqual(contract, this.contractAddressBytes)) {\n return null;\n }\n\n // Decode event based on topic[0] signature\n if (topics.length === 0) return null;\n\n const signature = topics[0];\n let eventLabel: string | null = null;\n\n // Method 1: Try ASCII extraction (D9 chain format)\n // D9 chain uses format: \\0ContractName::EventLabel (32 bytes, null-prefixed)\n eventLabel = this.extractEventLabelFromAsciiTopic(signature!);\n\n // Verify the extracted label has a decoder\n if (eventLabel && !this.eventDecoders.has(eventLabel)) {\n eventLabel = null;\n }\n\n // Method 2: Fall back to blake2 signature matching (standard ink! format)\n if (!eventLabel) {\n for (const [label, sig] of this.eventSignatures) {\n if (this.bytesEqual(signature!, sig)) {\n eventLabel = label;\n break;\n }\n }\n }\n\n if (!eventLabel) {\n console.warn(\"Unknown event signature:\", signature);\n return null;\n }\n\n const decoder = this.eventDecoders.get(eventLabel);\n if (!decoder) {\n console.warn(`No decoder for event ${eventLabel}`);\n return null;\n }\n\n try {\n // ink! events include a variant discriminant as first byte, skip it\n const decodedData = decoder(data.slice(1));\n const rawEvent: RawContractEvent = {\n blockNumber,\n blockHash,\n eventIndex,\n contractAddress: this.getContractAddress(),\n data,\n topics,\n };\n // Only include extrinsicIndex if it was extracted\n if (extrinsicIndex !== undefined) {\n rawEvent.extrinsicIndex = extrinsicIndex;\n }\n return {\n type: eventLabel,\n value: decodedData,\n raw: rawEvent,\n } as TypedContractEvent<E>;\n } catch (error) {\n console.warn(`Failed to decode event ${eventLabel}:`, error);\n return null;\n }\n }\n\n /**\n * Extract event label from ASCII-encoded topic (D9 chain format)\n *\n * D9 chain uses a format where:\n * - First byte is 0x00 (null)\n * - Remaining 31 bytes are ASCII characters of `ContractName::EventLabel`\n * - Total is exactly 32 bytes (truncated/padded as needed)\n *\n * @param topic - The 32-byte topic from the event\n * @returns The extracted event label, or null if not in ASCII format\n */\n private extractEventLabelFromAsciiTopic(topic: Uint8Array): string | null {\n if (topic.length !== 32) return null;\n\n // D9 format: first byte is null (0x00)\n if (topic[0] !== 0) return null;\n\n // Decode ASCII (skip null prefix, trim trailing nulls)\n const ascii = new TextDecoder().decode(topic.slice(1)).replace(/\\0+$/, \"\");\n\n // Extract label after \"::\"\n const colonIndex = ascii.lastIndexOf(\"::\");\n if (colonIndex !== -1) {\n return ascii.slice(colonIndex + 2);\n }\n\n // No \"::\" found, use entire string as label\n return ascii || null;\n }\n\n /**\n * Filter a batch of events and return type-safe results\n *\n * @param chainEvents - Array of chain events to filter\n * @param options - Optional filter criteria\n * @returns Array of type-safe contract events\n */\n filterEvents(chainEvents: unknown[], options?: EventFilterOptions): TypedContractEvent<E>[] {\n const results: TypedContractEvent<E>[] = [];\n\n for (const chainEvent of chainEvents) {\n const parsed = this.parseEvent(chainEvent);\n if (!parsed) continue;\n\n // Apply label filter\n if (options?.eventLabels && !options.eventLabels.includes(parsed.type)) {\n continue;\n }\n\n // Apply block range filter\n if (options?.fromBlock && parsed.raw.blockNumber < options.fromBlock) {\n continue;\n }\n if (options?.toBlock && parsed.raw.blockNumber > options.toBlock) {\n continue;\n }\n\n results.push(parsed);\n }\n\n return results;\n }\n\n /**\n * Filter events by specific type with proper type narrowing\n *\n * This method provides better type safety than filterEvents with eventLabels\n * because TypeScript can narrow the return type to only the specified event type.\n *\n * @param chainEvents - Array of chain events to filter\n * @param label - The event label to filter by\n * @returns Array of events narrowed to the specific type\n *\n * @example\n * ```ts\n * const transfers = parser.filterByType(events, \"Transfer\");\n *\n * for (const t of transfers) {\n * // t.value is fully typed as Transfer event data\n * console.log(t.value.from, \"->\", t.value.to, \":\", t.value.value);\n * }\n * ```\n */\n filterByType<L extends string>(\n chainEvents: unknown[],\n label: L,\n ): Array<TypedContractEvent<E> & { type: L }> {\n return this.filterEvents(chainEvents).filter(\n (e): e is TypedContractEvent<E> & { type: L } => (e.type as string) === label,\n );\n }\n\n /**\n * Parse chain event records with proper typing\n *\n * Unlike parseEvent/filterEvents which accept `unknown[]`, this method\n * accepts typed `ChainEventRecord[]` which eliminates the need for\n * `as any` casts in user code.\n *\n * @param events - Array of typed chain event records\n * @param options - Optional filter criteria\n * @returns Array of typed contract events\n *\n * @example\n * ```ts\n * // No more `as any` needed!\n * const events: ChainEventRecord[] = await api.query.System.Events.getValue();\n * const contractEvents = parser.parseChainEvents(events);\n *\n * for (const event of contractEvents) {\n * if (event.type === \"Transfer\") {\n * // Fully typed!\n * console.log(event.value.from, event.value.to, event.value.value);\n * }\n * }\n * ```\n */\n parseChainEvents(\n events: ChainEventRecord[],\n options?: EventFilterOptions\n ): TypedContractEvent<E>[] {\n return this.filterEvents(events, options);\n }\n\n /**\n * Get the contract address as SS58 string\n */\n private getContractAddress(): SS58String {\n return this.contractAddress;\n }\n\n /**\n * Get the contract address as bytes\n */\n getContractAddressBytes(): Uint8Array {\n return this.contractAddressBytes;\n }\n\n /**\n * Extract ContractEmitted event from chain event structure\n * Based on polkadot-api event format\n */\n private extractContractEmittedEvent(chainEvent: unknown): {\n contract: Uint8Array;\n data: Uint8Array;\n topics: Uint8Array[];\n blockNumber: number;\n blockHash: string;\n eventIndex: number;\n extrinsicIndex?: number;\n } | null {\n // Type guard and extract event structure\n if (!chainEvent || typeof chainEvent !== \"object\") {\n return null;\n }\n\n const record = chainEvent as any;\n\n // Extract event data\n const event = record.event;\n if (!event || typeof event !== \"object\") {\n return null;\n }\n\n // Check if this is a Contracts pallet event\n if (event.type !== \"Contracts\") {\n return null;\n }\n\n // Check if this is a ContractEmitted event\n const eventValue = event.value;\n if (!eventValue || typeof eventValue !== \"object\") {\n return null;\n }\n\n if (eventValue.type !== \"ContractEmitted\") {\n return null;\n }\n\n // Extract contract address and data\n const contractEmittedData = eventValue.value;\n if (!contractEmittedData || typeof contractEmittedData !== \"object\") {\n return null;\n }\n\n const contractRaw = contractEmittedData.contract;\n const dataRaw = contractEmittedData.data;\n\n // Handle contract address: can be SS58 string or Uint8Array\n let contract: Uint8Array;\n if (contractRaw instanceof Uint8Array) {\n contract = contractRaw;\n } else if (typeof contractRaw === \"string\") {\n // SS58 string format\n contract = ss58Decode(contractRaw)[0];\n } else {\n return null;\n }\n\n // Handle data: can be Binary object (with asBytes()) or Uint8Array\n let data: Uint8Array;\n if (dataRaw instanceof Uint8Array) {\n data = dataRaw;\n } else if (\n dataRaw &&\n typeof dataRaw === \"object\" &&\n \"asBytes\" in dataRaw &&\n typeof dataRaw.asBytes === \"function\"\n ) {\n // Binary object format\n data = dataRaw.asBytes();\n } else {\n return null;\n }\n\n // Extract topics from the event record\n // Topics are typically stored in the event record, not in the event value\n const topics: Uint8Array[] = [];\n\n // Polkadot-API typically stores topics at the record level\n // Topics can be Uint8Array or Binary objects (with asBytes())\n if (record.topics && Array.isArray(record.topics)) {\n for (const topic of record.topics) {\n if (topic instanceof Uint8Array) {\n topics.push(topic);\n } else if (\n topic &&\n typeof topic === \"object\" &&\n \"asBytes\" in topic &&\n typeof topic.asBytes === \"function\"\n ) {\n // Binary object format\n topics.push(topic.asBytes());\n }\n }\n }\n\n // Extract block metadata\n const blockNumber = typeof record.blockNumber === \"number\" ? record.blockNumber : 0;\n const blockHash = typeof record.blockHash === \"string\" ? record.blockHash : \"\";\n const eventIndex = typeof record.eventIndex === \"number\" ? record.eventIndex : 0;\n\n // Extract extrinsic index from phase (if ApplyExtrinsic)\n let extrinsicIndex: number | undefined;\n if (\n record.phase &&\n typeof record.phase === \"object\" &&\n record.phase.type === \"ApplyExtrinsic\" &&\n typeof record.phase.value === \"number\"\n ) {\n extrinsicIndex = record.phase.value;\n }\n\n return {\n contract,\n data,\n topics,\n blockNumber,\n blockHash,\n eventIndex,\n extrinsicIndex,\n };\n }\n\n /**\n * Compare two Uint8Arrays for equality\n */\n private bytesEqual(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n }\n}\n\n/**\n * Type guard for narrowing event types\n *\n * Use this function when you have a `TypedContractEvent` and need to\n * narrow it to a specific event type. This is useful when the type\n * information is lost (e.g., after serialization or in generic functions).\n *\n * @typeParam E - The Enum type representing all possible events\n * @typeParam L - The specific event label to check\n * @param event - The event to check\n * @param label - The event label to match\n * @returns True if the event type matches the label\n *\n * @example\n * ```ts\n * const event = parser.parseEvent(chainEvent);\n *\n * if (event && isEventType(event, \"Transfer\")) {\n * // TypeScript knows event.value is Transfer event data\n * console.log(event.value.from);\n * console.log(event.value.to);\n * console.log(event.value.value);\n * }\n * ```\n */\nexport function isEventType<E extends InkEvent, L extends ExtractEventLabels<E>>(\n event: TypedContractEvent<E>,\n label: L,\n): event is Extract<TypedContractEvent<E>, { type: L }> {\n return event.type === label;\n}\n","/**\n * Event subscriptions using RxJS\n */\nimport { Observable, filter, map, mergeMap, share, from, of, catchError } from \"rxjs\";\nimport type { PolkadotClient, SS58String } from \"polkadot-api\";\nimport type {\n InkMetadata,\n InkDescriptors,\n InkStorageDescriptor,\n InkCallableDescriptor,\n Event as InkEvent,\n} from \"@polkadot-api/ink-contracts\";\nimport { ContractEventParser } from \"./events\";\nimport type { TypedContractEvent, EventSubscriptionOptions } from \"./event-types\";\n\n/**\n * Block info type for type safety\n */\ninterface BlockInfo {\n number: number;\n hash: string;\n}\n\n/**\n * Create an observable stream of contract events\n *\n * @param client - Polkadot API client\n * @param descriptor - Contract descriptor\n * @param options - Subscription options\n * @returns Observable stream of type-safe contract events\n */\nexport function createContractEventStream<\n S extends InkStorageDescriptor = InkStorageDescriptor,\n M extends InkCallableDescriptor = InkCallableDescriptor,\n C extends InkCallableDescriptor = InkCallableDescriptor,\n E extends InkEvent = InkEvent,\n>(\n client: PolkadotClient,\n descriptor: InkDescriptors<S, M, C, E>,\n options: EventSubscriptionOptions,\n): Observable<TypedContractEvent<E>> {\n const parser = new ContractEventParser<S, M, C, E>(descriptor, options.contractAddress);\n\n // Subscribe to finalized blocks\n return client.finalizedBlock$.pipe(\n // For each finalized block, fetch its events\n mergeMap(async (block: BlockInfo) => {\n try {\n // Fetch System.Events at this block using the provided callback\n const events = await options.getEvents(block.hash);\n return { block, events };\n } catch (error: unknown) {\n console.error(\n \"Error fetching events at block\",\n block.number,\n \":\",\n error instanceof Error ? error.message : String(error),\n );\n // Return empty events on error to keep stream alive\n return { block, events: [] as unknown[] };\n }\n }),\n\n // Parse and filter events for this contract\n map(({ block, events }) => {\n const parsedEvents = events\n .map((event, index) => {\n // Attach block metadata to each event before parsing\n const eventWithMeta = {\n ...(event as object),\n blockNumber: block.number,\n blockHash: block.hash,\n eventIndex: index,\n };\n return parser.parseEvent(eventWithMeta);\n })\n .filter((e): e is TypedContractEvent<E> => e !== null);\n\n return parsedEvents;\n }),\n\n // Flatten array of events to individual emissions\n mergeMap((events) => from(events)),\n\n // Filter by event labels if specified\n filter((event) => {\n if (!options.eventLabels) return true;\n return options.eventLabels.includes(event.type);\n }),\n\n // Handle errors gracefully\n catchError((error: unknown) => {\n console.error(\"Error in contract event stream:\", error);\n return of(); // Return empty observable on error\n }),\n\n // Share subscription among multiple subscribers\n share(),\n );\n}\n\n/**\n * PSP22 Transfer event type\n */\nexport interface PSP22TransferEvent {\n type: \"Transfer\";\n value: {\n from?: SS58String | null;\n to?: SS58String | null;\n value: bigint;\n };\n raw: {\n blockNumber: number;\n blockHash: string;\n eventIndex: number;\n contractAddress: SS58String;\n data: Uint8Array;\n topics: Uint8Array[];\n };\n}\n\n/**\n * Convenience helper to create a Transfer event stream for PSP22 tokens\n *\n * @param client - Polkadot API client\n * @param descriptor - PSP22 contract descriptor\n * @param contractAddress - PSP22 contract address\n * @param getEvents - Function to fetch System.Events at a block hash\n * @param watchAddress - Optional address to filter transfers (only events involving this address)\n * @returns Observable stream of Transfer events\n */\nexport function createPSP22TransferStream<\n S extends InkStorageDescriptor = InkStorageDescriptor,\n M extends InkCallableDescriptor = InkCallableDescriptor,\n C extends InkCallableDescriptor = InkCallableDescriptor,\n E extends InkEvent = InkEvent,\n>(\n client: PolkadotClient,\n descriptor: InkDescriptors<S, M, C, E>,\n contractAddress: SS58String,\n getEvents: (blockHash: string) => Promise<unknown[]>,\n watchAddress?: SS58String,\n): Observable<PSP22TransferEvent> {\n return createContractEventStream<S, M, C, E>(client, descriptor, {\n contractAddress,\n eventLabels: [\"Transfer\"],\n getEvents,\n }).pipe(\n filter((event) => {\n if (!watchAddress) return true;\n\n // Filter transfers where from=watchAddress or to=watchAddress\n const value = event.value as {\n from?: SS58String | null;\n to?: SS58String | null;\n value: bigint;\n };\n\n return value.from === watchAddress || value.to === watchAddress;\n }),\n ) as Observable<PSP22TransferEvent>;\n}\n\n/**\n * Create a native token (D9) transfer event stream\n *\n * This monitors System.Transfer events instead of contract events\n *\n * @param client - Polkadot API client\n * @param getEvents - Function to fetch System.Events at a block hash\n * @param watchAddress - Address to monitor for transfers\n * @returns Observable stream of native transfer events\n */\nexport function createNativeTransferStream(\n client: PolkadotClient,\n getEvents: (blockHash: string) => Promise<unknown[]>,\n watchAddress: SS58String,\n): Observable<{\n from: SS58String;\n to: SS58String;\n amount: bigint;\n blockNumber: number;\n blockHash: string;\n}> {\n return client.finalizedBlock$.pipe(\n // For each block, query system events\n mergeMap(async (block: any) => {\n try {\n const events = await getEvents(block.hash);\n return { block, events };\n } catch (error: unknown) {\n console.error(\n \"Error fetching events for native transfers:\",\n error instanceof Error ? error.message : String(error),\n );\n return { block, events: [] };\n }\n }),\n\n // Filter for Balances.Transfer events\n map(({ block, events }) => {\n const transfers = events\n .map((record: any) => {\n // Check if this is a Balances.Transfer event\n if (record.event?.type !== \"Balances\") return null;\n if (record.event?.value?.type !== \"Transfer\") return null;\n\n const { from, to, amount } = record.event.value.value;\n\n // Filter by watchAddress\n if (from !== watchAddress && to !== watchAddress) return null;\n\n return {\n from: from as SS58String,\n to: to as SS58String,\n amount: amount as bigint,\n blockNumber: block.number,\n blockHash: block.hash,\n };\n })\n .filter((t: any): t is NonNullable<typeof t> => t !== null);\n\n return transfers;\n }),\n\n // Flatten array to individual emissions\n mergeMap((transfers: any[]) => from(transfers)),\n\n // Handle errors\n catchError((error: unknown) => {\n console.error(\"Error in native transfer stream:\", error);\n return of();\n }),\n\n // Share subscription\n share(),\n );\n}\n","/**\n * Type-safe message builder for ink! contracts\n *\n * Provides a polkadot-api compatible API for encoding and decoding\n * contract messages with full TypeScript type inference.\n */\nimport type {\n InkMetadata,\n InkDescriptors,\n InkStorageDescriptor,\n InkCallableDescriptor,\n} from \"@polkadot-api/ink-contracts\";\nimport { getInkLookup, getInkDynamicBuilder } from \"@polkadot-api/ink-contracts\";\nimport type { Enum } from \"polkadot-api\";\nimport { Binary } from \"polkadot-api\";\nimport type { ExtractMessageLabels } from \"./call-types\";\n\n/**\n * Message attributes from metadata\n */\nexport interface MessageAttributes {\n /** Whether the message mutates state */\n mutates: boolean;\n /** Whether the message is payable */\n payable: boolean;\n /** Whether this is the default message */\n default: boolean;\n}\n\n/**\n * Type-safe message interface with encode/decode methods\n *\n * @typeParam M - The InkCallableDescriptor type (message definitions)\n * @typeParam L - The specific message label\n */\nexport interface TypedMessage<M extends InkCallableDescriptor, L extends keyof M & string> {\n /**\n * Encode message arguments to Binary\n *\n * @param args - The message arguments (fully typed)\n * @returns Encoded call data as Binary\n *\n * @example\n * ```ts\n * const transfer = builder.message(\"PSP22::transfer\");\n * const encoded = transfer.encode({\n * to: recipientAddress,\n * value: 1000n,\n * data: new Uint8Array(),\n * });\n * ```\n */\n encode: {} extends M[L][\"message\"]\n ? (args?: M[L][\"message\"]) => Binary\n : (args: M[L][\"message\"]) => Binary;\n\n /**\n * Decode response to typed value\n *\n * @param response - The response data\n * @returns Decoded response value\n */\n decode: (response: Binary | Uint8Array) => M[L][\"response\"];\n\n /** Message attributes (mutates, payable, default) */\n attributes: MessageAttributes;\n\n /** 4-byte selector */\n selector: Uint8Array;\n\n /** Message label */\n label: L;\n}\n\n/**\n * Contract message builder interface\n *\n * @typeParam M - The InkCallableDescriptor type (message definitions)\n */\nexport interface ContractMessageBuilder<M extends InkCallableDescriptor> {\n /**\n * Get a type-safe message interface for a specific message\n *\n * @param label - The message label (e.g., \"PSP22::transfer\")\n * @returns Typed message interface with encode/decode methods\n *\n * @example\n * ```ts\n * const transfer = builder.message(\"PSP22::transfer\");\n * const encoded = transfer.encode({ to, value, data });\n * const decoded = transfer.decode(response);\n * ```\n */\n message<L extends ExtractMessageLabels<M>>(label: L): TypedMessage<M, L>;\n\n /**\n * Get all available message labels\n *\n * @returns Array of message labels\n */\n getMessageLabels(): Array<ExtractMessageLabels<M>>;\n}\n\n/**\n * Internal message metadata from ink! spec\n */\ninterface MessageMetadata {\n label: string;\n selector: string;\n mutates: boolean;\n payable: boolean;\n default: boolean;\n args: Array<{ label: string; type: { type: number } }>;\n returnType: { type: number };\n}\n\n/**\n * Create a type-safe message builder from a contract descriptor\n *\n * @typeParam S - Storage descriptor type\n * @typeParam M - Messages descriptor type\n * @typeParam C - Constructors descriptor type\n * @typeParam E - Events Enum type\n * @param descriptor - The ink! contract descriptor containing metadata\n * @returns A ContractMessageBuilder instance\n *\n * @example\n * ```ts\n * import { createMessageBuilder } from '@d9-network/ink';\n * import { contracts } from '@d9-network/spec';\n *\n * const builder = createMessageBuilder(contracts.usdt);\n *\n * // Get a typed message interface\n * const transfer = builder.message(\"PSP22::transfer\");\n *\n * // Encode with full type checking on args\n * const encoded = transfer.encode({\n * to: recipientAddress, // Must be SS58String\n * value: 1000000n, // Must be bigint\n * data: new Uint8Array(), // Must be Uint8Array\n * });\n *\n * // Decode response with full type inference\n * const response = transfer.decode(resultBytes);\n * ```\n */\nexport function createMessageBuilder<\n S extends InkStorageDescriptor,\n M extends InkCallableDescriptor,\n C extends InkCallableDescriptor,\n E extends Enum<any>,\n>(descriptor: InkDescriptors<S, M, C, E>): ContractMessageBuilder<M> {\n if (!descriptor.metadata) {\n throw new Error(\"Contract descriptor must include metadata\");\n }\n\n const metadata = descriptor.metadata;\n const lookup = getInkLookup(metadata);\n const builder = getInkDynamicBuilder(lookup);\n\n // Cache for built message codecs\n type MessageCodec = ReturnType<typeof builder.buildMessage>;\n const codecCache = new Map<string, MessageCodec>();\n\n // Parse message metadata\n const messagesMetadata = new Map<string, MessageMetadata>();\n for (const msg of metadata.spec.messages as MessageMetadata[]) {\n messagesMetadata.set(msg.label, msg);\n }\n\n function getMessageCodec(label: string): MessageCodec {\n const cached = codecCache.get(label);\n if (cached) {\n return cached;\n }\n const codec = builder.buildMessage(label);\n codecCache.set(label, codec);\n return codec;\n }\n\n function parseSelector(selectorHex: string): Uint8Array {\n const hex = selectorHex.startsWith(\"0x\") ? selectorHex.slice(2) : selectorHex;\n return new Uint8Array(hex.match(/.{1,2}/g)!.map((byte) => parseInt(byte, 16)));\n }\n\n function message<L extends ExtractMessageLabels<M>>(label: L): TypedMessage<M, L> {\n const msgMeta = messagesMetadata.get(label);\n if (!msgMeta) {\n throw new Error(`Message \"${label}\" not found in metadata`);\n }\n\n const codec = getMessageCodec(label);\n const selector = parseSelector(msgMeta.selector);\n\n const encode = (args?: M[L][\"message\"]): Binary => {\n const encoded = codec.call.enc((args ?? {}) as Parameters<typeof codec.call.enc>[0]);\n return Binary.fromBytes(encoded);\n };\n\n const decode = (response: Binary | Uint8Array): M[L][\"response\"] => {\n const bytes = response instanceof Uint8Array ? response : response.asBytes();\n return codec.value.dec(bytes) as M[L][\"response\"];\n };\n\n return {\n encode: encode as TypedMessage<M, L>[\"encode\"],\n decode,\n attributes: {\n mutates: msgMeta.mutates,\n payable: msgMeta.payable,\n default: msgMeta.default,\n },\n selector,\n label,\n };\n }\n\n function getMessageLabels(): Array<ExtractMessageLabels<M>> {\n return Array.from(messagesMetadata.keys()) as Array<ExtractMessageLabels<M>>;\n }\n\n return {\n message,\n getMessageLabels,\n };\n}\n","/**\n * Type-safe RPC wrapper for PolkadotClient\n */\nimport type { PolkadotClient } from \"polkadot-api\";\nimport type { TypedRpc } from \"./rpc-types\";\n\n/**\n * Create a type-safe RPC proxy from a PolkadotClient\n *\n * This wraps the client's `_request` method with a Proxy that provides\n * a dot-syntax interface with proper TypeScript types.\n *\n * @param client - The PolkadotClient instance\n * @returns A type-safe RPC proxy object\n *\n * @example\n * ```ts\n * const rpc = createTypedRpc(client);\n *\n * // Dot syntax with full type inference\n * const hash = await rpc.chain_getBlockHash(12345);\n * // hash: HexString | null\n *\n * const header = await rpc.chain_getHeader(hash);\n * // header: BlockHeader | null\n *\n * const result = await rpc.state_call(\"ContractsApi_call\", message, blockHash);\n * // result: HexString\n * ```\n */\nexport function createTypedRpc(client: PolkadotClient): TypedRpc {\n return new Proxy({} as TypedRpc, {\n get(_target, prop: string) {\n return (...args: unknown[]) => client._request(prop, args);\n },\n });\n}\n","/**\n * D9 Ink Contract implementation\n *\n * Provides a type-safe interface for interacting with ink! smart contracts\n * using state_call + ContractsApi_call instead of ReviveApi.\n */\n\nimport type { PolkadotSigner, SS58String } from \"polkadot-api\";\nimport { Binary } from \"polkadot-api\";\nimport { fromHex } from \"polkadot-api/utils\";\nimport {\n getInkLookup,\n getInkDynamicBuilder,\n type InkDescriptors,\n type InkCallableDescriptor,\n type InkStorageDescriptor,\n type InkMetadata,\n type Event as InkEvent,\n} from \"@polkadot-api/ink-contracts\";\nimport { ss58Decode } from \"@polkadot-labs/hdkd-helpers\";\n\nimport type {\n D9InkContract,\n QueryOptions,\n QueryResult,\n SendOptions,\n SendableTransaction,\n TxResult,\n ContractStorage,\n CreateContractOptions,\n ResponseDecoder,\n} from \"./types\";\nimport { encodeContractCall } from \"./encode\";\nimport { decodeContractCallResult, unwrapInkResult, isLangError } from \"./decode\";\nimport { createCodecRegistry } from \"./codec-builder\";\nimport { ContractEventParser } from \"./events\";\nimport { createContractEventStream } from \"./subscriptions\";\nimport type { TypedContractEvent, EventSubscriptionOptions } from \"./event-types\";\nimport type { ExtractMessageLabels } from \"./call-types\";\nimport { createMessageBuilder, type TypedMessage } from \"./message-builder\";\nimport {\n ContractError,\n MetadataError,\n DecodeError,\n LangError,\n TimeoutError,\n AbortedError,\n TransactionError,\n} from \"@d9-network/spec\";\nimport { createTypedRpc } from \"./rpc\";\n\n/**\n * Result type for decodeWithPapiFallback helper\n */\ntype FallbackDecodeResult<T> = { success: true; value: T } | { success: false; error: DecodeError };\n\n/**\n * Decode response data using papi's value codec with proper result unwrapping.\n * This helper handles the common pattern of wrapping inner data in an Ok variant\n * and extracting the actual value from papi's decoded result.\n *\n * @param innerData - The raw response bytes to decode\n * @param codec - The papi codec with value.dec method\n * @param method - Method name for error context\n * @returns Decoded value or error\n */\nfunction decodeWithPapiFallback<T>(\n innerData: Uint8Array,\n codec: { value: { dec: (data: Uint8Array) => unknown } },\n method: string,\n): FallbackDecodeResult<T> {\n try {\n // Wrap inner data in Ok variant for papi's codec\n const fullResult = new Uint8Array(1 + innerData.length);\n fullResult[0] = 0; // Ok variant\n fullResult.set(innerData, 1);\n\n const papiResult = codec.value.dec(fullResult);\n\n // Handle papi's Result wrapper format\n if (\n papiResult !== null &&\n typeof papiResult === \"object\" &&\n \"success\" in papiResult &&\n \"value\" in papiResult\n ) {\n if ((papiResult as { success: boolean }).success) {\n return {\n success: true,\n value: (papiResult as { value: T }).value,\n };\n }\n return {\n success: false,\n error: new DecodeError(\n method,\n `Contract returned error: ${JSON.stringify((papiResult as { value: unknown }).value)}`,\n (papiResult as { value: unknown }).value,\n ),\n };\n }\n\n // Direct value without Result wrapper\n return { success: true, value: papiResult as T };\n } catch (error) {\n return {\n success: false,\n error: new DecodeError(\n method,\n `Failed to decode response: ${error instanceof Error ? error.message : String(error)}`,\n { error },\n ),\n };\n }\n}\n\n/**\n * Patch LangError type in ink metadata to fix the missing index 0 variant issue.\n * Uses structuredClone for efficient deep cloning.\n */\nfunction patchLangErrorInMetadata(metadata: InkMetadata): InkMetadata {\n const patched = structuredClone(metadata);\n\n for (const typeEntry of patched.types) {\n const path = typeEntry.type?.path;\n const def = typeEntry.type?.def as {\n variant?: {\n variants: Array<{\n index: number;\n name: string;\n fields: unknown[];\n docs: string[];\n }>;\n };\n };\n if (path && Array.isArray(path) && path.includes(\"LangError\") && def?.variant) {\n const variants = def.variant.variants;\n if (Array.isArray(variants)) {\n const hasIndex0 = variants.some((v) => v.index === 0);\n if (!hasIndex0) {\n variants.unshift({\n index: 0,\n name: \"_Placeholder\",\n fields: [],\n docs: [],\n });\n }\n }\n }\n }\n\n return patched;\n}\n\n/**\n * Convert SS58 address to bytes\n */\nfunction ss58ToBytes(address: SS58String): Uint8Array {\n const [publicKey] = ss58Decode(address);\n return publicKey;\n}\n\n/**\n * Create a promise that rejects after a timeout\n */\nfunction createTimeout<T>(ms: number, label: string): { promise: Promise<T>; clear: () => void } {\n let timeoutId: ReturnType<typeof setTimeout>;\n const promise = new Promise<T>((_, reject) => {\n timeoutId = setTimeout(() => {\n reject(new TimeoutError(label, ms));\n }, ms);\n });\n return {\n promise,\n clear: () => clearTimeout(timeoutId),\n };\n}\n\n/**\n * Check if AbortSignal is aborted and throw if so\n */\nfunction checkAborted(signal: AbortSignal | undefined, label: string): void {\n if (signal?.aborted) {\n throw new AbortedError(label, signal.reason);\n }\n}\n\n/**\n * Create a D9 Ink Contract instance\n */\nexport function createD9InkContract<\n S extends InkStorageDescriptor,\n M extends InkCallableDescriptor,\n C extends InkCallableDescriptor,\n E extends InkEvent,\n>(\n descriptor: InkDescriptors<S, M, C, E>,\n address: SS58String,\n options: CreateContractOptions,\n): D9InkContract<M, E> {\n const { client, typedApi, defaultQueryOptions = {}, defaultSendOptions = {} } = options;\n\n if (!descriptor.metadata) {\n throw new MetadataError(\"Contract descriptor must include metadata\");\n }\n\n // Patch and prepare metadata\n const patchedMetadata = patchLangErrorInMetadata(descriptor.metadata);\n const lookup = getInkLookup(patchedMetadata);\n const builder = getInkDynamicBuilder(lookup);\n\n // Create a patched descriptor with the patched metadata for internal use\n const patchedDescriptor = {\n ...descriptor,\n metadata: patchedMetadata,\n } as InkDescriptors<S, M, C, E>;\n\n // Build auto-generated codecs\n let codecRegistry: Map<string, ResponseDecoder>;\n try {\n codecRegistry = createCodecRegistry(patchedMetadata);\n } catch (error) {\n console.warn(\"Failed to auto-generate codecs from metadata:\", error);\n codecRegistry = new Map();\n }\n\n // Convert address to bytes\n const addressBytes = ss58ToBytes(address);\n\n // Create typed RPC for type-safe RPC calls\n const rpc = createTypedRpc(client);\n\n // Cache for message codecs\n type MessageCodec = ReturnType<typeof builder.buildMessage>;\n const messageCodecCache = new Map<string, MessageCodec>();\n\n function getMessageCodec(label: string): MessageCodec {\n const cached = messageCodecCache.get(label);\n if (cached) {\n return cached;\n }\n const codec = builder.buildMessage(label);\n messageCodecCache.set(label, codec);\n return codec;\n }\n\n /**\n * Get the decoder for a message\n */\n function getDecoder(label: string): ResponseDecoder | null {\n return codecRegistry.get(label) ?? null;\n }\n\n /**\n * Execute a query (dry-run)\n */\n async function executeQuery<K extends keyof M & string>(\n method: K,\n queryOptions: QueryOptions<M[K][\"message\"]>,\n ): Promise<QueryResult<M[K][\"response\"]>> {\n const opts = { ...defaultQueryOptions, ...queryOptions };\n const { origin, args, value = 0n, signal, timeout, at } = opts;\n\n try {\n checkAborted(signal, method);\n\n const originBytes = ss58ToBytes(origin);\n const codec = getMessageCodec(method);\n\n // Encode the call\n const callData = codec.call.enc((args ?? {}) as Parameters<typeof codec.call.enc>[0]);\n\n // Create the state_call message\n const message = encodeContractCall(originBytes, addressBytes, callData, value);\n\n // Get block hash\n const blockHash = at ?? (await client.getFinalizedBlock()).hash;\n\n checkAborted(signal, method);\n\n // Execute state_call with optional timeout\n const executeCall = async () => {\n const response = await rpc.state_call(\"ContractsApi_call\", message, blockHash);\n return fromHex(response);\n };\n\n let rawResponse: Uint8Array;\n if (timeout) {\n const { promise: timeoutPromise, clear } = createTimeout<Uint8Array>(timeout, method);\n try {\n rawResponse = await Promise.race([executeCall(), timeoutPromise]);\n } finally {\n clear();\n }\n } else {\n rawResponse = await executeCall();\n }\n\n checkAborted(signal, method);\n\n // Decode the ContractsApi_call response\n const callResult = decodeContractCallResult(rawResponse);\n\n // Check for execution error\n if (!callResult.success) {\n return {\n success: false,\n error: new ContractError(\n `Contract execution failed: ${callResult.debugMessage}`,\n \"CONTRACT_ERROR\",\n method,\n ),\n };\n }\n\n // Check for LangError\n if (isLangError(callResult.data)) {\n return {\n success: false,\n error: new LangError(method, callResult.data[1] ?? 1),\n };\n }\n\n // Unwrap the Result<T, LangError>\n const innerData = unwrapInkResult(callResult.data);\n\n // Decode the response\n let decodedResponse: M[K][\"response\"];\n const decoder = getDecoder(method);\n\n if (decoder) {\n try {\n decodedResponse = decoder.dec(innerData) as M[K][\"response\"];\n } catch (decodeError) {\n // Custom decoder failed, fall back to papi's value codec\n console.warn(\"D9InkContract: Failed to decode response:\", decodeError);\n const fallbackResult = decodeWithPapiFallback<M[K][\"response\"]>(innerData, codec, method);\n if (!fallbackResult.success) {\n return { success: false, error: fallbackResult.error };\n }\n decodedResponse = fallbackResult.value;\n }\n } else {\n // No custom decoder, use papi's codec\n const fallbackResult = decodeWithPapiFallback<M[K][\"response\"]>(innerData, codec, method);\n if (!fallbackResult.success) {\n return { success: false, error: fallbackResult.error };\n }\n decodedResponse = fallbackResult.value;\n }\n\n // Return success with QuerySuccessValue fields spread to same level\n return {\n success: true,\n value: decodedResponse,\n events: [],\n gasConsumed: callResult.gas.gasConsumed,\n gasRequired: callResult.gas.gasRequired,\n storageDeposit: callResult.storageDeposit.amount,\n send: () =>\n createSendableTransaction(method, {\n origin,\n args,\n value,\n gasLimit: callResult.gas.gasRequired,\n }),\n };\n } catch (error) {\n if (error instanceof ContractError) {\n return { success: false, error };\n }\n return {\n success: false,\n error: new ContractError(\n error instanceof Error ? error.message : String(error),\n \"NETWORK_ERROR\",\n method,\n ),\n };\n }\n }\n\n /**\n * Create a sendable transaction\n */\n function createSendableTransaction<K extends keyof M & string>(\n method: K,\n sendOptions: SendOptions<M[K][\"message\"]>,\n ): SendableTransaction<M[K][\"response\"]> {\n const opts = { ...defaultSendOptions, ...sendOptions };\n const { origin, args, value = 0n, gasLimit, storageDepositLimit } = opts;\n\n const originBytes = ss58ToBytes(origin);\n const codec = getMessageCodec(method);\n\n // Encode the call\n const callData = codec.call.enc((args ?? {}) as Parameters<typeof codec.call.enc>[0]);\n\n return {\n getEncodedData: () => callData,\n\n async signAndSubmit(signer: PolkadotSigner): Promise<TxResult<M[K][\"response\"]>> {\n if (!typedApi) {\n throw new TransactionError(\n method,\n \"typedApi is required for transaction submission. Pass typedApi in SDK options.\",\n );\n }\n\n try {\n // First do a dry-run to get gas estimate if not provided\n let gas = gasLimit;\n if (!gas) {\n const message = encodeContractCall(originBytes, addressBytes, callData, value);\n const blockHash = (await client.getFinalizedBlock()).hash;\n const response = await rpc.state_call(\"ContractsApi_call\", message, blockHash);\n const callResult = decodeContractCallResult(fromHex(response));\n gas = callResult.gas.gasRequired;\n }\n\n // Build the transaction using typedApi\n const api = typedApi as {\n tx: {\n Contracts: {\n call: (params: {\n dest: { type: \"Id\"; value: SS58String };\n value: bigint;\n gas_limit: { ref_time: bigint; proof_size: bigint };\n storage_deposit_limit: bigint | undefined;\n data: Binary;\n }) => {\n signAndSubmit: (\n signer: PolkadotSigner,\n options?: { at?: \"best\" | \"finalized\" },\n ) => Promise<{\n txHash: string;\n block: { hash: string; number: number };\n events: unknown[];\n }>;\n };\n };\n };\n };\n\n const tx = api.tx.Contracts.call({\n dest: { type: \"Id\", value: address },\n value,\n gas_limit: {\n ref_time: gas.refTime,\n proof_size: gas.proofSize,\n },\n storage_deposit_limit: storageDepositLimit,\n data: Binary.fromBytes(callData),\n });\n\n const txResult = await tx.signAndSubmit(signer, { at: \"finalized\" });\n\n return {\n ok: true,\n txHash: txResult.txHash,\n block: txResult.block,\n events: txResult.events ?? [],\n };\n } catch (error) {\n return {\n ok: false,\n txHash: \"\",\n block: { hash: \"\", number: 0 },\n events: [],\n dispatchError: error,\n };\n }\n },\n };\n }\n\n /**\n * Create send method that returns a sendable transaction\n */\n function send<K extends keyof M & string>(\n method: K,\n sendOptions: SendOptions<M[K][\"message\"]>,\n ): SendableTransaction<M[K][\"response\"]> {\n return createSendableTransaction(method, sendOptions);\n }\n\n /**\n * Create storage query interface.\n *\n * @deprecated Storage queries are not yet implemented. This API is exposed for\n * future compatibility but will throw errors if used. Use contract messages\n * (query/send) to read contract state instead.\n *\n * @returns ContractStorage interface with unimplemented methods\n */\n function getStorage(): ContractStorage {\n const notImplementedWarning = (method: string) => {\n console.warn(\n `[D9InkContract] ${method}() is not implemented. ` +\n `Storage queries are planned for a future release. ` +\n `Use contract messages to read state instead.`,\n );\n };\n\n return {\n async getRoot() {\n notImplementedWarning(\"getRoot\");\n return {\n success: false,\n value: new ContractError(\n \"Storage queries not yet implemented. Use contract messages to read state.\",\n \"METADATA_ERROR\",\n ),\n };\n },\n\n async getNested(path: string, ..._keys: unknown[]) {\n notImplementedWarning(\"getNested\");\n return {\n success: false,\n value: new ContractError(\n `Storage query for \"${path}\" not yet implemented. Use contract messages to read state.`,\n \"METADATA_ERROR\",\n ),\n };\n },\n };\n }\n\n /**\n * Filter events for this contract\n */\n function filterEvents(events: unknown[]): TypedContractEvent<E>[] {\n const parser = new ContractEventParser<S, M, C, E>(patchedDescriptor, address);\n return parser.filterEvents(events);\n }\n\n /**\n * Filter events by specific type with proper type narrowing\n */\n function filterEventsByType<L extends string>(\n events: unknown[],\n label: L,\n ): Array<TypedContractEvent<E> & { type: L }> {\n const parser = new ContractEventParser<S, M, C, E>(patchedDescriptor, address);\n return parser.filterByType(events, label);\n }\n\n // Create message builder for type-safe message encoding/decoding\n const messageBuilder = createMessageBuilder(descriptor);\n\n /**\n * Get a type-safe message interface\n */\n function message<L extends ExtractMessageLabels<M>>(label: L): TypedMessage<M, L> {\n return messageBuilder.message(label);\n }\n\n /**\n * Subscribe to contract events as an RxJS Observable\n *\n * @param options - Subscription options (contractAddress is automatically set)\n * @param options.getEvents - Function to fetch System.Events at a block hash\n * @param options.eventLabels - Optional filter for specific event names\n * @param options.fromBlock - Optional starting block number\n */\n function subscribeToEvents(options: Omit<EventSubscriptionOptions, \"contractAddress\">) {\n return createContractEventStream<S, M, C, E>(client, patchedDescriptor, {\n ...options,\n contractAddress: address,\n });\n }\n\n // Type assertion needed because the runtime correctly unwraps MessageResult\n // but TypeScript doesn't know that. The UnwrapMessageResult type in D9InkContract\n // matches what we actually return at runtime.\n return {\n address,\n metadata: patchedMetadata,\n query: executeQuery,\n send,\n getStorage,\n filterEvents,\n filterEventsByType,\n message,\n subscribeToEvents,\n } as D9InkContract<M, E>;\n}\n","/**\n * D9 Ink SDK entry point\n *\n * Creates an ink SDK that uses state_call + ContractsApi_call\n * instead of ReviveApi for chains that don't support it.\n */\n\nimport type { Enum, PolkadotClient, SS58String } from \"polkadot-api\";\nimport {\n type InkDescriptors,\n type InkCallableDescriptor,\n type InkStorageDescriptor,\n} from \"@polkadot-api/ink-contracts\";\n\nimport type { D9InkSdk, D9InkSdkOptions, D9InkContract, QueryOptions, SendOptions } from \"./types\";\nimport type { TypedRpc } from \"./rpc-types\";\nimport { createD9InkContract } from \"./contract\";\nimport { createTypedRpc } from \"./rpc\";\n\n/**\n * Options for creating D9 Ink SDK\n */\nexport interface CreateD9InkSdkOptions extends D9InkSdkOptions {\n /**\n * Typed API for transaction submission.\n * Required for submitting real transactions.\n */\n typedApi?: unknown;\n}\n\n/**\n * Extended D9 Ink SDK interface with typed RPC access\n */\nexport interface D9InkSdkWithRpc extends D9InkSdk {\n /**\n * Type-safe RPC interface with dot syntax\n *\n * Provides autocomplete for known Substrate RPC methods and type inference\n * for parameters and return values.\n *\n * @example\n * ```ts\n * // Dot syntax with full type inference\n * const hash = await sdk.rpc.chain_getBlockHash(12345);\n * // hash: HexString | null\n *\n * const result = await sdk.rpc.state_call(\"ContractsApi_call\", message, blockHash);\n * // result: HexString\n * ```\n */\n rpc: TypedRpc;\n}\n\n/**\n * Create a D9 Ink SDK instance.\n *\n * This SDK provides a similar API to the official @polkadot-api/sdk-ink,\n * but uses state_call + ContractsApi_call instead of ReviveApi.\n *\n * @example\n * ```ts\n * import { createD9InkSdk } from \"@d9-network/ink\";\n * import { contracts } from \"@d9-network/spec\";\n *\n * const sdk = createD9InkSdk(client);\n * const usdtContract = sdk.getContract(\n * contracts.d9_usdt,\n * \"uLj9DRUujbpCyK7USZY5ebGbxdtKoWvdRvGyyUsoLWDsNng\"\n * );\n *\n * // Query balance\n * const result = await usdtContract.query(\"PSP22::balance_of\", {\n * origin: aliceAddress,\n * args: { owner: aliceAddress }\n * });\n *\n * if (result.success) {\n * console.log(\"Balance:\", result.value.response);\n *\n * // Send transaction from the query result\n * const txResult = await result.value.send().signAndSubmit(aliceSigner);\n * }\n *\n * // Or send directly\n * const txResult = await usdtContract\n * .send(\"PSP22::transfer\", {\n * origin: aliceAddress,\n * args: { to: bobAddress, value: 1000n, data: [] }\n * })\n * .signAndSubmit(aliceSigner);\n * ```\n *\n * @param client - The PolkadotClient instance\n * @param options - Optional SDK configuration\n * @returns D9 Ink SDK instance with typed RPC access\n */\nexport function createD9InkSdk(\n client: PolkadotClient,\n options: CreateD9InkSdkOptions = {},\n): D9InkSdkWithRpc {\n const { typedApi, defaultQueryOptions, defaultSendOptions } = options;\n\n return {\n getContract<\n S extends InkStorageDescriptor,\n M extends InkCallableDescriptor,\n C extends InkCallableDescriptor,\n E extends Enum<any>,\n >(descriptor: InkDescriptors<S, M, C, E>, address: SS58String): D9InkContract<M, E> {\n return createD9InkContract(descriptor, address, {\n client,\n typedApi,\n defaultQueryOptions,\n defaultSendOptions,\n });\n },\n rpc: createTypedRpc(client),\n };\n}\n\n// Re-export types for convenience\nexport type {\n D9InkSdk,\n D9InkSdkOptions,\n D9InkContract,\n QueryOptions,\n SendOptions,\n QueryResult,\n SendableTransaction,\n TxResult,\n ContractStorage,\n} from \"./types\";\n\nexport type { TypedRpc } from \"./rpc-types\";\n","/**\n * Event type definitions for ink! contracts\n */\nimport type { Enum, SS58String } from \"polkadot-api\";\nimport type { Event as InkEvent } from \"@polkadot-api/ink-contracts\";\n\n/**\n * Raw event data from chain\n */\nexport interface RawContractEvent {\n /** Block number where event was emitted */\n blockNumber: number;\n /** Block hash */\n blockHash: string;\n /** Event index in block */\n eventIndex: number;\n /**\n * Extrinsic index that caused this event (if in ApplyExtrinsic phase)\n *\n * This is extracted from the event's `phase.value` when `phase.type === \"ApplyExtrinsic\"`.\n * Useful for indexers to correlate events with their originating transactions.\n */\n extrinsicIndex?: number;\n /** Contract address that emitted the event (always in D9 format) */\n contractAddress: SS58String;\n /** Event data (SCALE encoded) */\n data: Uint8Array;\n /** Event topics (indexed fields) */\n topics: Uint8Array[];\n}\n\n/**\n * Extract the definition object from an Enum type or InkEvent type\n * e.g. ExtractEnumDef<Enum<{A: X, B: Y}>> = {A: X, B: Y}\n *\n * For non-Enum types (e.g., InkEvent { type: string; value: unknown }),\n * returns a generic event definition.\n */\nexport type ExtractEnumDef<E> =\n E extends Enum<infer T> ? T : E extends InkEvent ? Record<string, unknown> : never;\n\n/**\n * Extract event labels as a union type from an Enum type\n * e.g. ExtractEventLabels<Enum<{Transfer: X, Approval: Y}>> = \"Transfer\" | \"Approval\"\n */\nexport type ExtractEventLabels<E extends InkEvent> = keyof ExtractEnumDef<E> & string;\n\n/**\n * Type-safe contract event with discriminated union\n * Enables type narrowing: `if (event.type === \"Transfer\") { event.value.from }`\n */\nexport type TypedContractEvent<E extends InkEvent> =\n E extends Enum<infer T>\n ? {\n [K in keyof T & string]: {\n /** Event type (discriminant for type narrowing) */\n type: K;\n /** Decoded event data (type-safe based on event type) */\n value: T[K];\n /** Original raw event */\n raw: RawContractEvent;\n };\n }[keyof T & string]\n : {\n type: string;\n value: unknown;\n raw: RawContractEvent;\n };\n\n/**\n * Decoded contract event with generic data type.\n * For full type safety with discriminated unions, use TypedContractEvent instead.\n */\nexport interface DecodedContractEvent<T = unknown> {\n /** Event label from metadata (e.g., \"Transfer\", \"Approval\") */\n label: string;\n /** Decoded event data */\n data: T;\n /** Original raw event */\n raw: RawContractEvent;\n}\n\n/**\n * Event filter options\n */\nexport interface EventFilterOptions {\n /** Contract address to filter by */\n contractAddress?: SS58String;\n /** Event labels to include (e.g., [\"Transfer\", \"Approval\"]) */\n eventLabels?: string[];\n /** From block number (inclusive) */\n fromBlock?: number;\n /** To block number (inclusive) */\n toBlock?: number;\n}\n\n/**\n * Type-safe event filter options with literal event labels\n * Provides compile-time validation of event label names\n *\n * @typeParam E - The event type representing all possible events\n *\n * @example\n * ```ts\n * const options: TypedEventFilterOptions<typeof contracts.usdt.__types.event> = {\n * eventLabels: [\"Transfer\", \"Approval\"], // Must be valid event names\n * };\n * ```\n */\nexport interface TypedEventFilterOptions<E extends InkEvent> {\n /** Contract address to filter by */\n contractAddress?: SS58String;\n /** Event labels to include (type-safe) */\n eventLabels?: Array<ExtractEventLabels<E>>;\n /** From block number (inclusive) */\n fromBlock?: number;\n /** To block number (inclusive) */\n toBlock?: number;\n}\n\n/**\n * Event subscription options\n */\nexport interface EventSubscriptionOptions {\n /** Contract address to subscribe to */\n contractAddress: SS58String;\n /** Event labels to subscribe to (undefined = all events) */\n eventLabels?: string[];\n /** Include historical events from this block */\n fromBlock?: number;\n /**\n * Function to fetch System.Events at a given block hash\n * This is required because PolkadotClient doesn't expose typed API directly\n *\n * @example\n * ```ts\n * const options = {\n * contractAddress: usdtAddress,\n * getEvents: async (blockHash) => {\n * return await api.query.System.Events.getValue({ at: blockHash });\n * }\n * };\n * ```\n */\n getEvents: (blockHash: string) => Promise<unknown[]>;\n}\n\n// =============================================================================\n// Chain Event Types (for eliminating `as any` casts)\n// =============================================================================\n\n/**\n * Chain event record structure (matches polkadot-api format)\n *\n * Use this type when processing raw chain events to avoid `as any` casts.\n *\n * @example\n * ```ts\n * // Instead of: const events = await api.query.System.Events.getValue() as any[];\n * // Use: const events: ChainEventRecord[] = await api.query.System.Events.getValue();\n *\n * for (const event of events) {\n * if (isContractEmittedEvent(event)) {\n * // event is now properly typed!\n * }\n * }\n * ```\n */\nexport interface ChainEventRecord {\n /** The event phase */\n phase?: {\n type: string;\n value?: number;\n };\n /** The event pallet and variant */\n event: {\n type: string;\n value: {\n type: string;\n value: unknown;\n };\n };\n /** Event topics (for indexed fields) */\n topics?: Array<Uint8Array | { asBytes?: () => Uint8Array }>;\n /** Block number (if available) */\n blockNumber?: number;\n /** Block hash (if available) */\n blockHash?: string;\n /** Event index in block (if available) */\n eventIndex?: number;\n}\n\n/**\n * Contracts.ContractEmitted event value\n */\nexport interface ContractEmittedValue {\n /** Contract address (SS58 or Uint8Array) */\n contract: SS58String | Uint8Array;\n /** Event data (Binary or Uint8Array) */\n data: Uint8Array | { asBytes: () => Uint8Array };\n}\n\n/**\n * Contracts.Called event value\n */\nexport interface ContractCalledValue {\n /** Caller address */\n caller: SS58String;\n /** Contract address being called */\n contract: SS58String;\n}\n\n/**\n * Typed chain event for Contracts.ContractEmitted\n */\nexport interface ContractEmittedChainEvent extends ChainEventRecord {\n event: {\n type: \"Contracts\";\n value: {\n type: \"ContractEmitted\";\n value: ContractEmittedValue;\n };\n };\n}\n\n/**\n * Typed chain event for Contracts.Called\n */\nexport interface ContractCalledChainEvent extends ChainEventRecord {\n event: {\n type: \"Contracts\";\n value: {\n type: \"Called\";\n value: ContractCalledValue;\n };\n };\n}\n\n/**\n * Typed chain event for Balances.Transfer\n */\nexport interface BalancesTransferChainEvent extends ChainEventRecord {\n event: {\n type: \"Balances\";\n value: {\n type: \"Transfer\";\n value: {\n from: SS58String;\n to: SS58String;\n amount: bigint;\n };\n };\n };\n}\n\n/**\n * Type guard for Contracts.ContractEmitted events\n *\n * @example\n * ```ts\n * for (const event of events) {\n * if (isContractEmittedEvent(event)) {\n * // event.event.value.value is ContractEmittedValue\n * const { contract, data } = event.event.value.value;\n * }\n * }\n * ```\n */\nexport function isContractEmittedEvent(\n event: ChainEventRecord\n): event is ContractEmittedChainEvent {\n return (\n event.event?.type === \"Contracts\" &&\n event.event?.value?.type === \"ContractEmitted\"\n );\n}\n\n/**\n * Type guard for Contracts.Called events\n *\n * @example\n * ```ts\n * for (const event of events) {\n * if (isContractCalledEvent(event)) {\n * // event.event.value.value is ContractCalledValue\n * const { caller, contract } = event.event.value.value;\n * }\n * }\n * ```\n */\nexport function isContractCalledEvent(\n event: ChainEventRecord\n): event is ContractCalledChainEvent {\n return (\n event.event?.type === \"Contracts\" &&\n event.event?.value?.type === \"Called\"\n );\n}\n\n/**\n * Type guard for Balances.Transfer events\n *\n * @example\n * ```ts\n * for (const event of events) {\n * if (isBalancesTransferEvent(event)) {\n * const { from, to, amount } = event.event.value.value;\n * }\n * }\n * ```\n */\nexport function isBalancesTransferEvent(\n event: ChainEventRecord\n): event is BalancesTransferChainEvent {\n return (\n event.event?.type === \"Balances\" &&\n event.event?.value?.type === \"Transfer\"\n );\n}\n\n/**\n * Check if event is in ApplyExtrinsic phase\n *\n * @example\n * ```ts\n * for (const event of events) {\n * if (isApplyExtrinsicPhase(event)) {\n * const extrinsicIndex = event.phase.value;\n * }\n * }\n * ```\n */\nexport function isApplyExtrinsicPhase(\n event: ChainEventRecord\n): event is ChainEventRecord & { phase: { type: \"ApplyExtrinsic\"; value: number } } {\n return event.phase?.type === \"ApplyExtrinsic\" && typeof event.phase.value === \"number\";\n}\n\n/**\n * Extract contract emitted data with proper typing\n *\n * Handles both Uint8Array and Binary object formats.\n *\n * @param event - Chain event record\n * @returns Extracted data or null if not a ContractEmitted event\n */\nexport function extractContractEmittedData(\n event: ChainEventRecord\n): {\n contract: Uint8Array;\n data: Uint8Array;\n topics: Uint8Array[];\n} | null {\n if (!isContractEmittedEvent(event)) {\n return null;\n }\n\n const { contract: contractRaw, data: dataRaw } = event.event.value.value;\n\n // Handle contract address\n let contract: Uint8Array;\n if (contractRaw instanceof Uint8Array) {\n contract = contractRaw;\n } else if (typeof contractRaw === \"string\") {\n // SS58 string - caller should decode if needed\n // Return empty for now, let caller handle SS58 decoding\n contract = new Uint8Array(0);\n } else {\n return null;\n }\n\n // Handle data (Binary or Uint8Array)\n let data: Uint8Array;\n if (dataRaw instanceof Uint8Array) {\n data = dataRaw;\n } else if (\n dataRaw &&\n typeof dataRaw === \"object\" &&\n \"asBytes\" in dataRaw &&\n typeof dataRaw.asBytes === \"function\"\n ) {\n data = dataRaw.asBytes();\n } else {\n return null;\n }\n\n // Extract topics\n const topics: Uint8Array[] = [];\n if (event.topics && Array.isArray(event.topics)) {\n for (const topic of event.topics) {\n if (topic instanceof Uint8Array) {\n topics.push(topic);\n } else if (\n topic &&\n typeof topic === \"object\" &&\n \"asBytes\" in topic &&\n typeof topic.asBytes === \"function\"\n ) {\n topics.push(topic.asBytes());\n }\n }\n }\n\n return { contract, data, topics };\n}\n","/**\n * Internal codec building utilities\n *\n * This module provides lower-level codec building from metadata type IDs.\n */\nimport {\n u8,\n u16,\n u32,\n u64,\n u128,\n i8,\n i16,\n i32,\n i64,\n i128,\n bool,\n str,\n Bytes,\n Vector,\n Tuple,\n Struct,\n Variant,\n _void,\n Option,\n AccountId,\n type Codec,\n} from \"@polkadot-api/substrate-bindings\";\nimport type { InkMetadata } from \"@polkadot-api/ink-contracts\";\nimport { D9_SS58_PREFIX } from \"@d9-network/spec\";\n\n// Use 'any' for dynamic codec building\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyCodec = Codec<any>;\ntype CodecCache = Map<number, AnyCodec>;\n\ninterface TypeDef {\n primitive?: string;\n composite?: {\n fields: Array<{\n name?: string;\n type: number;\n typeName?: string;\n }>;\n };\n variant?: {\n variants: Array<{\n name: string;\n index: number;\n fields: Array<{\n name?: string;\n type: number;\n typeName?: string;\n }>;\n }>;\n };\n sequence?: {\n type: number;\n };\n array?: {\n len: number;\n type: number;\n };\n tuple?: number[];\n}\n\ninterface TypeEntry {\n id: number;\n type: {\n def: TypeDef;\n path?: string[];\n params?: Array<{\n name: string;\n type?: number;\n }>;\n };\n}\n\n/**\n * Build a SCALE codec from ink metadata type definition\n */\nfunction buildCodecFromTypeInternal(\n typeId: number,\n types: TypeEntry[],\n cache: CodecCache,\n): AnyCodec {\n const cached = cache.get(typeId);\n if (cached) return cached;\n\n const typeEntry = types.find((t) => t.id === typeId);\n if (!typeEntry) {\n throw new Error(`Type ${typeId} not found in metadata`);\n }\n\n const def = typeEntry.type.def;\n const path = typeEntry.type.path;\n\n // Handle primitive types\n if (def.primitive) {\n const codec = buildPrimitiveCodec(def.primitive);\n cache.set(typeId, codec);\n return codec;\n }\n\n // Handle special path types\n if (path && path.length > 0) {\n const specialCodec = buildSpecialTypeCodec(path, typeEntry, types, cache);\n if (specialCodec) {\n cache.set(typeId, specialCodec);\n return specialCodec;\n }\n }\n\n // Handle tuple\n if (def.tuple) {\n const codec = buildTupleCodec(def.tuple, types, cache);\n cache.set(typeId, codec);\n return codec;\n }\n\n // Handle sequence\n if (def.sequence) {\n const innerCodec = buildCodecFromTypeInternal(def.sequence.type, types, cache);\n const codec = Vector(innerCodec);\n cache.set(typeId, codec);\n return codec;\n }\n\n // Handle array\n if (def.array) {\n const innerCodec = buildCodecFromTypeInternal(def.array.type, types, cache);\n if (def.array.type === findPrimitiveTypeId(types, \"u8\")) {\n const codec = Bytes(def.array.len);\n cache.set(typeId, codec);\n return codec;\n }\n const codec = Vector(innerCodec, def.array.len);\n cache.set(typeId, codec);\n return codec;\n }\n\n // Handle composite\n if (def.composite) {\n const codec = buildCompositeCodec(def.composite, types, cache);\n cache.set(typeId, codec);\n return codec;\n }\n\n // Handle variant\n if (def.variant) {\n const codec = buildVariantCodec(def.variant, path, types, cache);\n cache.set(typeId, codec);\n return codec;\n }\n\n throw new Error(`Unknown type definition for type ${typeId}`);\n}\n\nfunction buildPrimitiveCodec(primitive: string): AnyCodec {\n switch (primitive) {\n case \"u8\":\n return u8;\n case \"u16\":\n return u16;\n case \"u32\":\n return u32;\n case \"u64\":\n return u64;\n case \"u128\":\n return u128;\n case \"i8\":\n return i8;\n case \"i16\":\n return i16;\n case \"i32\":\n return i32;\n case \"i64\":\n return i64;\n case \"i128\":\n return i128;\n case \"bool\":\n return bool;\n case \"str\":\n return str;\n default:\n throw new Error(`Unknown primitive type: ${primitive}`);\n }\n}\n\nfunction buildSpecialTypeCodec(\n path: string[],\n typeEntry: TypeEntry,\n types: TypeEntry[],\n cache: CodecCache,\n): AnyCodec | null {\n const fullPath = path.join(\"::\");\n\n if (fullPath.includes(\"AccountId\")) {\n return AccountId(D9_SS58_PREFIX);\n }\n\n if (path[0] === \"Option\") {\n const params = typeEntry.type.params;\n if (params && params.length > 0 && params[0]?.type !== undefined) {\n const innerCodec = buildCodecFromTypeInternal(params[0].type, types, cache);\n return Option(innerCodec);\n }\n }\n\n if (path[0] === \"Result\") {\n const params = typeEntry.type.params;\n if (params && params.length >= 2) {\n const okTypeId = params[0]?.type;\n const errTypeId = params[1]?.type;\n if (okTypeId !== undefined && errTypeId !== undefined) {\n const okCodec = buildCodecFromTypeInternal(okTypeId, types, cache);\n const errCodec = buildCodecFromTypeInternal(errTypeId, types, cache);\n return Variant({ Ok: okCodec, Err: errCodec }, [0, 1]);\n }\n }\n }\n\n return null;\n}\n\nfunction buildTupleCodec(tupleTypes: number[], types: TypeEntry[], cache: CodecCache): AnyCodec {\n if (tupleTypes.length === 0) return _void;\n\n const innerCodecs = tupleTypes.map((t) => buildCodecFromTypeInternal(t, types, cache));\n\n switch (innerCodecs.length) {\n case 1:\n return Tuple(innerCodecs[0]!);\n case 2:\n return Tuple(innerCodecs[0]!, innerCodecs[1]!);\n case 3:\n return Tuple(innerCodecs[0]!, innerCodecs[1]!, innerCodecs[2]!);\n case 4:\n return Tuple(innerCodecs[0]!, innerCodecs[1]!, innerCodecs[2]!, innerCodecs[3]!);\n default:\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (Tuple as any)(...innerCodecs);\n }\n}\n\nfunction buildCompositeCodec(\n composite: NonNullable<TypeDef[\"composite\"]>,\n types: TypeEntry[],\n cache: CodecCache,\n): AnyCodec {\n const fields = composite.fields;\n\n if (fields.length === 1 && !fields[0]?.name) {\n return buildCodecFromTypeInternal(fields[0]!.type, types, cache);\n }\n\n const structDef: Record<string, AnyCodec> = {};\n for (const field of fields) {\n const fieldName = field.name || `field${fields.indexOf(field)}`;\n structDef[fieldName] = buildCodecFromTypeInternal(field.type, types, cache);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return Struct(structDef as any);\n}\n\nfunction buildVariantCodec(\n variant: NonNullable<TypeDef[\"variant\"]>,\n path: string[] | undefined,\n types: TypeEntry[],\n cache: CodecCache,\n): AnyCodec {\n const variants = variant.variants;\n const isLangError = path?.includes(\"LangError\");\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const variantDef: Record<string, any> = {};\n const indices: number[] = [];\n\n if (isLangError && !variants.some((v) => v.index === 0)) {\n variantDef[\"_Placeholder\"] = _void;\n indices.push(0);\n }\n\n for (const v of variants) {\n let fieldCodec: AnyCodec;\n const fields = v.fields ?? [];\n\n if (fields.length === 0) {\n fieldCodec = _void;\n } else if (fields.length === 1 && !fields[0]?.name) {\n fieldCodec = buildCodecFromTypeInternal(fields[0]!.type, types, cache);\n } else {\n const structDef: Record<string, AnyCodec> = {};\n for (const field of fields) {\n const fieldName = field.name || `field${fields.indexOf(field)}`;\n structDef[fieldName] = buildCodecFromTypeInternal(field.type, types, cache);\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n fieldCodec = Struct(structDef as any);\n }\n\n variantDef[v.name] = fieldCodec;\n indices.push(v.index);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return Variant(variantDef as any, indices as any);\n}\n\nfunction findPrimitiveTypeId(types: TypeEntry[], primitive: string): number {\n const entry = types.find((t) => t.type.def.primitive === primitive);\n return entry?.id ?? -1;\n}\n\n/**\n * Build a codec for a specific type ID from ink metadata\n *\n * @param metadata - The ink contract metadata\n * @param typeId - The type ID to build codec for\n * @returns A codec with encode/decode methods\n */\nexport function buildCodecFromMetadata(\n metadata: InkMetadata,\n typeId: number,\n): { enc: (value: unknown) => Uint8Array; dec: (data: Uint8Array) => unknown } {\n const types = metadata.types as TypeEntry[];\n const cache: CodecCache = new Map();\n\n const codec = buildCodecFromTypeInternal(typeId, types, cache);\n return codec;\n}\n\n/**\n * Build a struct codec for message arguments\n *\n * @param metadata - The ink contract metadata\n * @param args - The argument definitions\n * @returns A struct codec\n */\nexport function buildArgsCodec(\n metadata: InkMetadata,\n args: Array<{ label: string; type: { type: number } }>,\n): { enc: (value: unknown) => Uint8Array; dec: (data: Uint8Array) => unknown } {\n if (args.length === 0) {\n return {\n enc: () => new Uint8Array(0),\n dec: () => ({}),\n };\n }\n\n const types = metadata.types as TypeEntry[];\n const cache: CodecCache = new Map();\n\n const structDef: Record<string, AnyCodec> = {};\n for (const arg of args) {\n structDef[arg.label] = buildCodecFromTypeInternal(arg.type.type, types, cache);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const codec = Struct(structDef as any) as any;\n return {\n enc: (value: unknown) => codec.enc(value),\n dec: (data: Uint8Array) => codec.dec(data),\n };\n}\n","/**\n * Call parsing for ink! contracts\n *\n * Decodes contract call data (selector + args) into type-safe call objects.\n */\nimport type {\n InkMetadata,\n InkDescriptors,\n InkStorageDescriptor,\n InkCallableDescriptor,\n Event as InkEvent,\n} from \"@polkadot-api/ink-contracts\";\nimport type {\n TypedContractCall,\n RawContractCall,\n CallFilterOptions,\n MessageInfo,\n ExtractMessageLabels,\n} from \"./call-types\";\nimport { buildArgsCodec } from \"./codec-builder-internal\";\n\n/**\n * Build argument decoders for all messages in the metadata\n */\nfunction buildAllMessageDecodersFromMetadata(\n metadata: InkMetadata,\n): Map<string, { selector: Uint8Array; decoder: (data: Uint8Array) => unknown }> {\n const decoders = new Map<\n string,\n { selector: Uint8Array; decoder: (data: Uint8Array) => unknown }\n >();\n\n const messages = metadata.spec.messages as Array<{\n label: string;\n selector: string; // hex string like \"0xdb20f9f5\"\n args: Array<{\n label: string;\n type: { type: number };\n }>;\n }>;\n\n for (const message of messages) {\n try {\n // Parse selector from hex string\n const selectorHex = message.selector.startsWith(\"0x\")\n ? message.selector.slice(2)\n : message.selector;\n const selector = new Uint8Array(\n selectorHex.match(/.{1,2}/g)!.map((byte) => parseInt(byte, 16)),\n );\n\n // Build struct decoder for message arguments\n const argsCodec = buildArgsCodec(metadata, message.args);\n const decoder = (data: Uint8Array) => argsCodec.dec(data);\n\n decoders.set(message.label, { selector, decoder });\n } catch (error) {\n console.warn(`Failed to build decoder for message \"${message.label}\":`, error);\n }\n }\n\n return decoders;\n}\n\n/**\n * Type-safe call parser for a specific contract\n *\n * @typeParam S - The storage descriptor type\n * @typeParam M - The InkCallableDescriptor type (message definitions)\n * @typeParam C - The constructors descriptor type\n * @typeParam E - The events Enum type\n */\nexport class ContractCallParser<\n S extends InkStorageDescriptor = InkStorageDescriptor,\n M extends InkCallableDescriptor = InkCallableDescriptor,\n C extends InkCallableDescriptor = InkCallableDescriptor,\n E extends InkEvent = InkEvent,\n> {\n private messageDecoders: Map<\n string,\n { selector: Uint8Array; decoder: (data: Uint8Array) => unknown }\n >;\n private selectorToLabel: Map<string, string>;\n private metadata: InkMetadata;\n\n constructor(descriptor: InkDescriptors<S, M, C, E>) {\n if (!descriptor.metadata) {\n throw new Error(\"Contract descriptor must include metadata\");\n }\n this.metadata = descriptor.metadata;\n this.messageDecoders = buildAllMessageDecodersFromMetadata(this.metadata);\n\n // Build reverse lookup: selector hex -> label\n this.selectorToLabel = new Map();\n for (const [label, { selector }] of this.messageDecoders) {\n const selectorHex = Array.from(selector)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n this.selectorToLabel.set(selectorHex, label);\n }\n }\n\n /**\n * Parse raw call data into a type-safe contract call\n *\n * @param callData - The raw call data (selector + encoded args) or RawContractCall\n * @returns Parsed call or null if cannot parse\n *\n * @example\n * ```ts\n * const call = parser.parseCall(callData);\n * if (call?.type === \"PSP22::transfer\") {\n * // call.args is typed as { to: SS58String; value: bigint; data: Uint8Array }\n * console.log(call.args.to);\n * }\n * ```\n */\n parseCall(callData: Uint8Array | RawContractCall): TypedContractCall<M> | null {\n const data = callData instanceof Uint8Array ? callData : callData.data;\n const raw: RawContractCall = callData instanceof Uint8Array ? { data: callData } : callData;\n\n if (data.length < 4) {\n return null; // Need at least 4 bytes for selector\n }\n\n // Extract selector (first 4 bytes)\n const selector = data.slice(0, 4);\n const selectorHex = Array.from(selector)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n\n // Find message by selector\n const label = this.selectorToLabel.get(selectorHex);\n if (!label) {\n return null;\n }\n\n const messageInfo = this.messageDecoders.get(label);\n if (!messageInfo) {\n return null;\n }\n\n // Decode arguments (data after selector)\n const argsData = data.slice(4);\n try {\n const args = messageInfo.decoder(argsData);\n\n return {\n type: label,\n args,\n selector,\n raw,\n } as TypedContractCall<M>;\n } catch (error) {\n console.warn(`Failed to decode call \"${label}\":`, error);\n return null;\n }\n }\n\n /**\n * Parse multiple calls and optionally filter by message labels\n *\n * @param calls - Array of raw call data\n * @param options - Filter options\n * @returns Array of parsed calls\n */\n parseCalls(\n calls: Array<Uint8Array | RawContractCall>,\n options?: CallFilterOptions,\n ): TypedContractCall<M>[] {\n const results: TypedContractCall<M>[] = [];\n\n for (const call of calls) {\n const parsed = this.parseCall(call);\n if (!parsed) continue;\n\n // Apply label filter\n if (options?.messageLabels && !options.messageLabels.includes(parsed.type)) {\n continue;\n }\n\n results.push(parsed);\n }\n\n return results;\n }\n\n /**\n * Filter calls by specific type with proper type narrowing\n *\n * This method provides better type safety than parseCalls with messageLabels\n * because TypeScript can narrow the return type to only the specified call type.\n *\n * @param calls - Array of raw call data\n * @param label - The message label to filter by\n * @returns Array of calls narrowed to the specific type\n *\n * @example\n * ```ts\n * const transfers = parser.filterByType(callDataArray, \"PSP22::transfer\");\n *\n * for (const t of transfers) {\n * // t.args is fully typed as PSP22::transfer args\n * console.log(t.args.to, t.args.value);\n * }\n * ```\n */\n filterByType<L extends string>(\n calls: Array<Uint8Array | RawContractCall>,\n label: L,\n ): Array<TypedContractCall<M> & { type: L }> {\n return this.parseCalls(calls).filter(\n (c): c is TypedContractCall<M> & { type: L } => c.type === label,\n );\n }\n\n /**\n * Get information about a message by label\n */\n getMessageInfo(label: string): MessageInfo | null {\n const info = this.messageDecoders.get(label);\n if (!info) return null;\n\n const messages = this.metadata.spec.messages as Array<{\n label: string;\n selector: string;\n mutates: boolean;\n payable: boolean;\n args: Array<{ label: string; type: { type: number } }>;\n }>;\n\n const message = messages.find((m) => m.label === label);\n if (!message) return null;\n\n return {\n label: message.label,\n selector: info.selector,\n mutates: message.mutates,\n payable: message.payable,\n args: message.args,\n };\n }\n\n /**\n * Get all available message labels\n */\n getMessageLabels(): string[] {\n return Array.from(this.messageDecoders.keys());\n }\n\n /**\n * Check if a selector matches a specific message\n */\n matchesMessage(selector: Uint8Array, label: string): boolean {\n const info = this.messageDecoders.get(label);\n if (!info) return false;\n\n if (selector.length !== info.selector.length) return false;\n\n for (let i = 0; i < selector.length; i++) {\n if (selector[i] !== info.selector[i]) return false;\n }\n\n return true;\n }\n\n /**\n * Get selector for a message label\n *\n * @param label - Message label (e.g., \"PSP22::transfer\")\n * @returns Selector as Uint8Array or null if not found\n *\n * @example\n * ```ts\n * const selector = parser.getSelector(\"PSP22::transfer\");\n * // selector is Uint8Array([0xdb, 0x20, 0xf9, 0xf5])\n * ```\n */\n getSelector(label: string): Uint8Array | null {\n const info = this.messageDecoders.get(label);\n return info?.selector ?? null;\n }\n\n /**\n * Get selector as hex string for a message label\n *\n * @param label - Message label (e.g., \"PSP22::transfer\")\n * @returns Selector hex string (without 0x) or null if not found\n *\n * @example\n * ```ts\n * const selectorHex = parser.getSelectorHex(\"PSP22::transfer\");\n * // selectorHex is \"db20f9f5\"\n * ```\n */\n getSelectorHex(label: string): string | null {\n const selector = this.getSelector(label);\n if (!selector) return null;\n return Array.from(selector)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n }\n\n /**\n * Get the label for a selector\n *\n * @param selector - Selector as Uint8Array or hex string (with or without 0x)\n * @returns Message label or null if not found\n *\n * @example\n * ```ts\n * const label = parser.getLabel(\"db20f9f5\");\n * // label is \"PSP22::transfer\"\n *\n * // Also works with Uint8Array\n * const label2 = parser.getLabel(callData.slice(0, 4));\n * ```\n */\n getLabel(selector: Uint8Array | string): string | null {\n const selectorHex = this.normalizeSelector(selector);\n return this.selectorToLabel.get(selectorHex) ?? null;\n }\n\n /**\n * Get all selector-to-label mappings\n *\n * @returns Map of selector hex (without 0x) -> label\n *\n * @example\n * ```ts\n * const map = parser.getSelectorMap();\n * for (const [selectorHex, label] of map) {\n * console.log(`${selectorHex} -> ${label}`);\n * }\n * ```\n */\n getSelectorMap(): Map<string, string> {\n return new Map(this.selectorToLabel);\n }\n\n /**\n * Check if a selector exists in this contract\n *\n * @param selector - Selector to check (Uint8Array or hex string)\n * @returns True if selector is valid for this contract\n *\n * @example\n * ```ts\n * if (parser.hasSelector(\"db20f9f5\")) {\n * // This selector is valid for this contract\n * }\n * ```\n */\n hasSelector(selector: Uint8Array | string): boolean {\n const selectorHex = this.normalizeSelector(selector);\n return this.selectorToLabel.has(selectorHex);\n }\n\n /**\n * Normalize selector to hex string (without 0x prefix)\n */\n private normalizeSelector(selector: Uint8Array | string): string {\n if (selector instanceof Uint8Array) {\n return Array.from(selector)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n }\n // Remove 0x prefix if present and lowercase\n return selector.startsWith(\"0x\")\n ? selector.slice(2).toLowerCase()\n : selector.toLowerCase();\n }\n}\n\n/**\n * Type guard for narrowing call types\n *\n * Use this function when you have a `TypedContractCall` and need to\n * narrow it to a specific call type. This is useful when the type\n * information is lost (e.g., after serialization or in generic functions).\n *\n * @typeParam M - The InkCallableDescriptor type (message definitions)\n * @typeParam L - The specific message label to check\n * @param call - The call to check\n * @param label - The message label to match\n * @returns True if the call type matches the label\n *\n * @example\n * ```ts\n * const call = parser.parseCall(callData);\n *\n * if (call && isCallType(call, \"PSP22::transfer\")) {\n * // TypeScript knows call.args is transfer args\n * console.log(call.args.to);\n * console.log(call.args.value);\n * }\n * ```\n */\nexport function isCallType<M extends InkCallableDescriptor, L extends ExtractMessageLabels<M>>(\n call: TypedContractCall<M>,\n label: L,\n): call is Extract<TypedContractCall<M>, { type: L }> {\n return call.type === label;\n}\n","/**\n * High-level extrinsic parsing for indexers and explorers\n *\n * Provides a simplified API for extracting contract calls from blockchain extrinsics,\n * eliminating the need for manual hex string manipulation and selector matching.\n */\n\nimport type { SS58String } from \"polkadot-api\";\nimport type {\n InkDescriptors,\n InkStorageDescriptor,\n InkCallableDescriptor,\n Event as InkEvent,\n} from \"@polkadot-api/ink-contracts\";\nimport { toD9Address } from \"@d9-network/spec\";\nimport { ContractCallParser } from \"./calls\";\nimport type { TypedContractCall, RawContractCall } from \"./call-types\";\n\n/**\n * Raw extrinsic data that may contain a contract call\n *\n * This interface is designed to work with various extrinsic formats\n * from different data sources (polkadot-api, subsquid, etc.)\n */\nexport interface RawExtrinsic {\n /** Extrinsic hash */\n hash?: string;\n /** Block number */\n blockNumber?: number;\n /** Block hash */\n blockHash?: string;\n /** Extrinsic index in block */\n index?: number;\n /** Signer address */\n signer?: SS58String | string;\n /** The call structure - can be nested */\n call?: ExtrinsicCall;\n}\n\n/**\n * Extrinsic call structure (matches polkadot-api format)\n */\nexport interface ExtrinsicCall {\n type?: string;\n value?: {\n type?: string;\n value?: ContractsCallValue;\n };\n}\n\n/**\n * Contracts.call extrinsic value\n */\nexport interface ContractsCallValue {\n /** Contract address (SS58 or other format) */\n dest?: SS58String | { type: string; value: SS58String } | { Id: SS58String };\n /** Value transferred with the call */\n value?: bigint | string | number;\n /** Call data (Binary or Uint8Array) */\n data?: Uint8Array | { asBytes?: () => Uint8Array };\n /** Gas limit */\n gas_limit?: unknown;\n gasLimit?: unknown;\n /** Storage deposit limit */\n storage_deposit_limit?: unknown;\n storageDepositLimit?: unknown;\n}\n\n/**\n * Parsed contract extrinsic result\n */\nexport interface ParsedContractExtrinsic<M extends InkCallableDescriptor = InkCallableDescriptor> {\n /** The parsed contract call */\n call: TypedContractCall<M>;\n /** Extrinsic metadata */\n extrinsic: {\n /** Extrinsic hash */\n hash: string;\n /** Block number */\n blockNumber: number;\n /** Block hash */\n blockHash: string;\n /** Extrinsic index in block */\n index: number;\n /** Signer address */\n signer: string;\n };\n /** Contract address being called */\n contractAddress: SS58String;\n /** Value transferred with call */\n value: bigint;\n}\n\n/**\n * Extrinsic parser options\n */\nexport interface ExtrinsicParserOptions {\n /** Contract addresses to filter for (if not provided, parses all contract calls) */\n contractAddresses?: SS58String[];\n /** Message labels to filter for */\n messageLabels?: string[];\n}\n\n/**\n * Parser for extracting contract calls from extrinsics\n *\n * This class provides a high-level API for indexers to parse contract\n * interactions from blockchain extrinsics without manual hex manipulation.\n *\n * @typeParam S - The storage descriptor type\n * @typeParam M - The InkCallableDescriptor type (message definitions)\n * @typeParam C - The constructors descriptor type\n * @typeParam E - The events type\n *\n * @example\n * ```ts\n * import { ExtrinsicParser } from \"@d9-network/ink\";\n * import { contracts } from \"@d9-network/spec\";\n *\n * // Create parser for USDT contract\n * const parser = new ExtrinsicParser(contracts.usdt, {\n * contractAddresses: [USDT_ADDRESS],\n * });\n *\n * // Parse extrinsics from a block\n * for (const extrinsic of block.extrinsics) {\n * const parsed = parser.parseExtrinsic(extrinsic);\n * if (parsed?.call.type === \"PSP22::transfer\") {\n * console.log(`Transfer: ${parsed.call.args.value} to ${parsed.call.args.to}`);\n * }\n * }\n * ```\n */\nexport class ExtrinsicParser<\n S extends InkStorageDescriptor = InkStorageDescriptor,\n M extends InkCallableDescriptor = InkCallableDescriptor,\n C extends InkCallableDescriptor = InkCallableDescriptor,\n E extends InkEvent = InkEvent,\n> {\n private callParser: ContractCallParser<S, M, C, E>;\n private options: ExtrinsicParserOptions;\n\n constructor(\n descriptor: InkDescriptors<S, M, C, E>,\n options: ExtrinsicParserOptions = {}\n ) {\n this.callParser = new ContractCallParser(descriptor);\n this.options = options;\n }\n\n /**\n * Parse a single extrinsic for contract calls\n *\n * @param extrinsic - Raw extrinsic data\n * @returns Parsed contract extrinsic or null if not a valid contract call\n */\n parseExtrinsic(extrinsic: RawExtrinsic): ParsedContractExtrinsic<M> | null {\n // Check if this is a contract call\n if (!this.isContractCall(extrinsic)) {\n return null;\n }\n\n // Extract call data\n const extracted = this.extractCallData(extrinsic);\n if (!extracted) {\n return null;\n }\n\n const { data, contractAddress, value } = extracted;\n\n // Filter by contract address if specified\n if (\n this.options.contractAddresses &&\n this.options.contractAddresses.length > 0 &&\n !this.options.contractAddresses.includes(contractAddress)\n ) {\n return null;\n }\n\n // Parse the call\n const raw: RawContractCall = {\n data,\n contractAddress,\n txHash: extrinsic.hash,\n blockNumber: extrinsic.blockNumber,\n blockHash: extrinsic.blockHash,\n };\n\n const call = this.callParser.parseCall(raw);\n if (!call) {\n return null;\n }\n\n // Filter by message label if specified\n if (\n this.options.messageLabels &&\n this.options.messageLabels.length > 0 &&\n !this.options.messageLabels.includes(call.type)\n ) {\n return null;\n }\n\n // Convert signer to D9 format if it looks like an SS58 address\n let signer = String(extrinsic.signer ?? \"\");\n if (signer && signer.length >= 32) {\n try {\n signer = toD9Address(signer as SS58String);\n } catch {\n // Keep original if conversion fails\n }\n }\n\n return {\n call,\n extrinsic: {\n hash: extrinsic.hash ?? \"\",\n blockNumber: extrinsic.blockNumber ?? 0,\n blockHash: extrinsic.blockHash ?? \"\",\n index: extrinsic.index ?? 0,\n signer,\n },\n contractAddress,\n value,\n };\n }\n\n /**\n * Parse multiple extrinsics and filter contract calls\n *\n * @param extrinsics - Array of raw extrinsics\n * @returns Array of parsed contract extrinsics\n */\n parseExtrinsics(extrinsics: RawExtrinsic[]): ParsedContractExtrinsic<M>[] {\n const results: ParsedContractExtrinsic<M>[] = [];\n\n for (const extrinsic of extrinsics) {\n const parsed = this.parseExtrinsic(extrinsic);\n if (parsed) {\n results.push(parsed);\n }\n }\n\n return results;\n }\n\n /**\n * Filter extrinsics by message type with type narrowing\n *\n * @param extrinsics - Array of raw extrinsics\n * @param label - Message label to filter by\n * @returns Filtered and typed extrinsics\n *\n * @example\n * ```ts\n * const transfers = parser.filterByMessageType(extrinsics, \"PSP22::transfer\");\n * for (const tx of transfers) {\n * // tx.call.args is fully typed\n * console.log(tx.call.args.to, tx.call.args.value);\n * }\n * ```\n */\n filterByMessageType<L extends string>(\n extrinsics: RawExtrinsic[],\n label: L\n ): Array<ParsedContractExtrinsic<M> & { call: { type: L } }> {\n return this.parseExtrinsics(extrinsics).filter(\n (tx): tx is ParsedContractExtrinsic<M> & { call: { type: L } } =>\n tx.call.type === label\n );\n }\n\n /**\n * Check if an extrinsic is a contract call\n *\n * @param extrinsic - Raw extrinsic\n * @returns True if this is a Contracts.call extrinsic\n */\n isContractCall(extrinsic: RawExtrinsic): boolean {\n const call = extrinsic.call;\n if (!call) return false;\n\n // Check for Contracts pallet\n if (call.type === \"Contracts\") {\n const innerCall = call.value;\n // Check for call, call_old_weight, etc.\n return (\n innerCall?.type === \"call\" ||\n innerCall?.type === \"call_old_weight\" ||\n innerCall?.type === \"instantiate_with_code\" ||\n innerCall?.type === \"instantiate\"\n );\n }\n\n return false;\n }\n\n /**\n * Extract call data from an extrinsic structure\n *\n * Handles various extrinsic formats (polkadot-api, subsquid, etc.)\n *\n * @param extrinsic - Raw extrinsic\n * @returns Extracted call data or null\n */\n extractCallData(extrinsic: RawExtrinsic): {\n data: Uint8Array;\n contractAddress: SS58String;\n value: bigint;\n } | null {\n const call = extrinsic.call;\n if (!call?.value?.value) return null;\n\n const contractsCall = call.value.value;\n\n // Extract contract address\n const contractAddress = this.extractContractAddress(contractsCall.dest);\n if (!contractAddress) return null;\n\n // Extract call data\n const data = this.extractBytes(contractsCall.data);\n if (!data || data.length < 4) return null;\n\n // Extract value\n const value = this.extractBigInt(contractsCall.value);\n\n return {\n data,\n contractAddress,\n value,\n };\n }\n\n /**\n * Get access to the underlying call parser\n */\n getCallParser(): ContractCallParser<S, M, C, E> {\n return this.callParser;\n }\n\n // Private helpers\n\n private extractContractAddress(\n dest: ContractsCallValue[\"dest\"]\n ): SS58String | null {\n if (!dest) return null;\n\n let address: SS58String | null = null;\n\n // Direct SS58 string\n if (typeof dest === \"string\") {\n address = dest as SS58String;\n }\n // { type: \"Id\", value: address } format\n else if (typeof dest === \"object\" && \"type\" in dest && \"value\" in dest) {\n address = dest.value as SS58String;\n }\n // { Id: address } format (subsquid)\n else if (typeof dest === \"object\" && \"Id\" in dest) {\n address = (dest as { Id: SS58String }).Id;\n }\n\n // Always return D9-formatted address\n return address ? toD9Address(address) : null;\n }\n\n private extractBytes(\n data: ContractsCallValue[\"data\"]\n ): Uint8Array | null {\n if (!data) return null;\n\n // Direct Uint8Array\n if (data instanceof Uint8Array) {\n return data;\n }\n\n // Binary object with asBytes()\n if (\n typeof data === \"object\" &&\n \"asBytes\" in data &&\n typeof data.asBytes === \"function\"\n ) {\n return data.asBytes();\n }\n\n return null;\n }\n\n private extractBigInt(value: ContractsCallValue[\"value\"]): bigint {\n if (value === undefined || value === null) return 0n;\n\n if (typeof value === \"bigint\") return value;\n if (typeof value === \"number\") return BigInt(value);\n if (typeof value === \"string\") {\n try {\n return BigInt(value);\n } catch {\n return 0n;\n }\n }\n\n return 0n;\n }\n}\n\n/**\n * Create an extrinsic parser from a contract descriptor\n *\n * @param descriptor - Contract descriptor\n * @param options - Parser options\n * @returns ExtrinsicParser instance\n *\n * @example\n * ```ts\n * const parser = createExtrinsicParser(contracts.usdt, {\n * contractAddresses: [USDT_ADDRESS],\n * });\n * ```\n */\nexport function createExtrinsicParser<\n S extends InkStorageDescriptor,\n M extends InkCallableDescriptor,\n C extends InkCallableDescriptor,\n E extends InkEvent,\n>(\n descriptor: InkDescriptors<S, M, C, E>,\n options?: ExtrinsicParserOptions\n): ExtrinsicParser<S, M, C, E> {\n return new ExtrinsicParser(descriptor, options);\n}\n","/**\n * Fee estimation utilities for ink! smart contracts\n */\n\nimport type { GasInfo } from \"../decode\";\n\n/**\n * Gas weight representation\n */\nexport interface GasWeight {\n refTime: bigint;\n proofSize: bigint;\n}\n\n/**\n * Estimated transaction cost breakdown\n */\nexport interface EstimatedCost {\n /** Cost from gas consumption */\n gasCost: bigint;\n /** Storage deposit (may be refunded) */\n storageDeposit: bigint;\n /** Total estimated cost (gas + storage) */\n total: bigint;\n}\n\n/**\n * Formatted gas information for display\n */\nexport interface FormattedGasInfo {\n /** Human-readable ref_time */\n refTime: string;\n /** Human-readable proof_size */\n proofSize: string;\n}\n\n// D9 network weight-to-fee constants\n// These should match the chain's WeightToFee implementation\nconst WEIGHT_REF_TIME_PER_SECOND = 1_000_000_000_000n; // 1 trillion\nconst WEIGHT_FEE_COEFFICIENT = 1n; // Adjust based on chain config\n\n/**\n * Estimate the transaction cost from gas info and storage deposit\n *\n * Note: This is an approximation. Actual fees depend on chain configuration\n * and may vary slightly.\n *\n * @param gasInfo - Gas information from contract query\n * @param storageDeposit - Storage deposit amount (positive for charge, negative for refund)\n * @returns Estimated cost breakdown\n *\n * @example\n * ```typescript\n * const result = await contract.query(\"PSP22::transfer\", { origin, args });\n * if (result.success) {\n * const cost = estimateTransactionCost(\n * { gasConsumed: result.gasConsumed, gasRequired: result.gasRequired },\n * result.storageDeposit\n * );\n * console.log(`Estimated cost: ${formatBalance(cost.total, { decimals: 12 })} D9`);\n * }\n * ```\n */\nexport function estimateTransactionCost(gasInfo: GasInfo, storageDeposit: bigint): EstimatedCost {\n // Use gasRequired for estimation as it's the gas that will be charged\n const { gasRequired } = gasInfo;\n\n // Simple weight-to-fee conversion\n // In production, this should match the chain's actual WeightToFee implementation\n const gasCost =\n (gasRequired.refTime * WEIGHT_FEE_COEFFICIENT) / WEIGHT_REF_TIME_PER_SECOND +\n gasRequired.proofSize;\n\n // Storage deposit is additional (may be refunded later)\n const effectiveStorageDeposit = storageDeposit > 0n ? storageDeposit : 0n;\n\n return {\n gasCost,\n storageDeposit: effectiveStorageDeposit,\n total: gasCost + effectiveStorageDeposit,\n };\n}\n\n/**\n * Format gas information for human-readable display\n *\n * @param gasInfo - Gas information from contract query\n * @returns Formatted strings for ref_time and proof_size\n *\n * @example\n * ```typescript\n * const formatted = formatGasInfo(result.gasRequired);\n * console.log(`Gas: refTime=${formatted.refTime}, proofSize=${formatted.proofSize}`);\n * ```\n */\nexport function formatGasInfo(gasInfo: GasInfo[\"gasRequired\"]): FormattedGasInfo {\n return {\n refTime: formatWeight(gasInfo.refTime),\n proofSize: formatWeight(gasInfo.proofSize),\n };\n}\n\n/**\n * Format a single weight value with appropriate units\n */\nfunction formatWeight(weight: bigint): string {\n if (weight >= 1_000_000_000_000n) {\n return `${(Number(weight) / 1_000_000_000_000).toFixed(2)}T`;\n }\n if (weight >= 1_000_000_000n) {\n return `${(Number(weight) / 1_000_000_000).toFixed(2)}G`;\n }\n if (weight >= 1_000_000n) {\n return `${(Number(weight) / 1_000_000).toFixed(2)}M`;\n }\n if (weight >= 1_000n) {\n return `${(Number(weight) / 1_000).toFixed(2)}K`;\n }\n return weight.toString();\n}\n\n/**\n * Apply a safety margin to gas limits\n *\n * It's recommended to add a small margin to gas estimates to account for\n * slight variations in execution. 10% (multiplier = 1.1) is a common choice.\n *\n * @param gas - The gas weight to adjust\n * @param multiplier - The multiplier to apply (default: 1.1 for 10% margin)\n * @returns Adjusted gas weight with margin applied\n *\n * @example\n * ```typescript\n * const result = await contract.query(\"PSP22::transfer\", { origin, args });\n * if (result.success) {\n * // Add 10% safety margin\n * const safeGas = applyGasMargin(result.gasRequired, 1.1);\n * await contract.send(\"PSP22::transfer\", {\n * origin,\n * args,\n * gasLimit: safeGas,\n * });\n * }\n * ```\n */\nexport function applyGasMargin(gas: GasWeight, multiplier = 1.1): GasWeight {\n if (multiplier <= 0) {\n throw new Error(\"Multiplier must be positive\");\n }\n\n // Convert multiplier to basis points for precise bigint math\n // e.g., 1.1 -> 11000, 1.15 -> 11500\n const basisPoints = BigInt(Math.round(multiplier * 10000));\n\n return {\n refTime: (gas.refTime * basisPoints) / 10000n,\n proofSize: (gas.proofSize * basisPoints) / 10000n,\n };\n}\n\n/**\n * Compare two gas weights\n *\n * @param a - First gas weight\n * @param b - Second gas weight\n * @returns -1 if a < b, 0 if equal, 1 if a > b (compares refTime first, then proofSize)\n */\nexport function compareGasWeight(a: GasWeight, b: GasWeight): -1 | 0 | 1 {\n if (a.refTime < b.refTime) return -1;\n if (a.refTime > b.refTime) return 1;\n if (a.proofSize < b.proofSize) return -1;\n if (a.proofSize > b.proofSize) return 1;\n return 0;\n}\n\n/**\n * Check if gas weight exceeds a limit\n *\n * @param gas - The gas to check\n * @param limit - The limit to compare against\n * @returns True if gas exceeds the limit in either dimension\n */\nexport function gasExceedsLimit(gas: GasWeight, limit: GasWeight): boolean {\n return gas.refTime > limit.refTime || gas.proofSize > limit.proofSize;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["HexSink","Src","u128","buildPrimitiveCodec","buildSpecialTypeCodec","buildTupleCodec","findPrimitiveTypeId","codec","buildCompositeCodec","buildVariantCodec","u8","u16","u32","u64","u128","i8","i16","i32","i64","i128","bool","str","D9_SS58_PREFIX","_void","structDef: Record<string, AnyCodec>","isLangError","variantDef: Record<string, any>","indices: number[]","fieldCodec: AnyCodec","cache: CodecCache","eventLabel: string | null","rawEvent: RawContractEvent","results: TypedContractEvent<E>[]","contract: Uint8Array","data: Uint8Array","topics: Uint8Array[]","extrinsicIndex: number | undefined","error: unknown","from","Binary","DecodeError","timeoutId: ReturnType<typeof setTimeout>","TimeoutError","AbortedError","MetadataError","codecRegistry: Map<string, ResponseDecoder>","message","rawResponse: Uint8Array","ContractError","LangError","decodedResponse: M[K][\"response\"]","TransactionError","Binary","options","contract: Uint8Array","data: Uint8Array","topics: Uint8Array[]","codec","u8","u16","u32","u64","u128","i8","i16","i32","i64","i128","bool","str","D9_SS58_PREFIX","_void","structDef: Record<string, AnyCodec>","isLangError","variantDef: Record<string, any>","indices: number[]","fieldCodec: AnyCodec","cache: CodecCache","raw: RawContractCall","results: TypedContractCall<M>[]","raw: RawContractCall","results: ParsedContractExtrinsic<M>[]","address: SS58String | null"],"sources":["../src/encode.ts","../src/decode.ts","../src/codec-builder.ts","../src/events.ts","../src/subscriptions.ts","../src/message-builder.ts","../src/rpc.ts","../src/contract.ts","../src/sdk.ts","../src/event-types.ts","../src/codec-builder-internal.ts","../src/calls.ts","../src/extrinsic-parser.ts","../src/utils/fees.ts"],"sourcesContent":["/**\n * Encoding utilities for ContractsApi_call state_call\n */\n\nimport type { Bytes } from \"@subsquid/scale-codec\";\nimport { HexSink } from \"@subsquid/scale-codec\";\nimport type { Binary } from \"polkadot-api\";\nimport { fromHex } from \"polkadot-api/utils\";\n\n/**\n * Encode a contract call for ContractsApi_call state_call.\n *\n * The encoded format matches the ContractsApi::call runtime API:\n * - origin: AccountId (32 bytes)\n * - dest: AccountId (32 bytes)\n * - value: Balance (u128)\n * - gas_limit: Option<Weight> (1 byte for None)\n * - storage_deposit_limit: Option<Balance> (1 byte for None)\n * - input_data: Vec<u8> (compact length + bytes)\n *\n * @param origin - The origin account (as Uint8Array or hex string)\n * @param dest - The contract address (as Uint8Array or hex string)\n * @param input - The encoded call data (selector + arguments)\n * @param value - Optional value to transfer (default: 0)\n * @returns Hex-encoded bytes for state_call\n */\nexport function encodeContractCall(\n origin: Uint8Array | string,\n dest: Uint8Array | string,\n input: Binary | Uint8Array,\n value: bigint = 0n,\n): Bytes {\n const sink = new HexSink();\n\n const originBytes = typeof origin === \"string\" ? fromHex(origin) : origin;\n const destBytes = typeof dest === \"string\" ? fromHex(dest) : dest;\n const inputBytes = \"asBytes\" in input ? input.asBytes() : input;\n\n // origin: AccountId\n sink.bytes(originBytes);\n // dest: AccountId\n sink.bytes(destBytes);\n // value: Balance (u128)\n sink.u128(value);\n // gas_limit: Option<Weight> - None\n sink.u8(0);\n // storage_deposit_limit: Option<Balance> - None\n sink.u8(0);\n // input_data: Vec<u8>\n sink.compact(inputBytes.length);\n sink.bytes(inputBytes);\n\n return sink.toHex();\n}\n\n/**\n * Encode a contract call using the same address for origin and dest.\n * This is a simplified version for query operations where the origin\n * doesn't matter much.\n *\n * @param address - The contract address\n * @param input - The encoded call data\n * @param value - Optional value to transfer\n * @returns Hex-encoded bytes for state_call\n */\nexport function encodeCall(\n address: Uint8Array | string,\n input: Binary | Uint8Array,\n value: bigint = 0n,\n): Bytes {\n return encodeContractCall(address, address, input, value);\n}\n\n/**\n * Encode a contract call with specific gas limit and storage deposit limit.\n *\n * @param origin - The origin account\n * @param dest - The contract address\n * @param input - The encoded call data\n * @param options - Call options including value, gas limit, storage deposit limit\n * @returns Hex-encoded bytes for state_call\n */\nexport function encodeContractCallWithLimits(\n origin: Uint8Array | string,\n dest: Uint8Array | string,\n input: Binary | Uint8Array,\n options: {\n value?: bigint;\n gasLimit?: { refTime: bigint; proofSize: bigint };\n storageDepositLimit?: bigint;\n } = {},\n): Bytes {\n const sink = new HexSink();\n\n const originBytes = typeof origin === \"string\" ? fromHex(origin) : origin;\n const destBytes = typeof dest === \"string\" ? fromHex(dest) : dest;\n const inputBytes = \"asBytes\" in input ? input.asBytes() : input;\n\n // origin: AccountId\n sink.bytes(originBytes);\n // dest: AccountId\n sink.bytes(destBytes);\n // value: Balance (u128)\n sink.u128(options.value ?? 0n);\n\n // gas_limit: Option<Weight>\n if (options.gasLimit) {\n sink.u8(1); // Some\n sink.compact(options.gasLimit.refTime);\n sink.compact(options.gasLimit.proofSize);\n } else {\n sink.u8(0); // None\n }\n\n // storage_deposit_limit: Option<Balance>\n if (options.storageDepositLimit !== undefined) {\n sink.u8(1); // Some\n sink.u128(options.storageDepositLimit);\n } else {\n sink.u8(0); // None\n }\n\n // input_data: Vec<u8>\n sink.compact(inputBytes.length);\n sink.bytes(inputBytes);\n\n return sink.toHex();\n}\n","/**\n * Decoding utilities for ContractsApi_call response\n */\n\nimport { Src } from \"@subsquid/scale-codec\";\nimport { type Codec, u128, Tuple } from \"@polkadot-api/substrate-bindings\";\n\n/**\n * Gas information from contract execution\n */\nexport interface GasInfo {\n /** Gas consumed during execution */\n gasConsumed: { refTime: bigint; proofSize: bigint };\n /** Gas required for execution */\n gasRequired: { refTime: bigint; proofSize: bigint };\n}\n\n/**\n * Storage deposit information\n */\nexport interface StorageDepositInfo {\n /** Storage deposit type: 0 = Refund, 1 = Charge */\n type: \"Refund\" | \"Charge\";\n /** Amount of storage deposit */\n amount: bigint;\n}\n\n/**\n * Full decoded result from ContractsApi_call\n */\nexport interface ContractCallResult {\n /** Gas information */\n gas: GasInfo;\n /** Storage deposit information */\n storageDeposit: StorageDepositInfo;\n /** Debug message (if any) */\n debugMessage: string;\n /** Whether the execution was successful */\n success: boolean;\n /** Execution flags */\n flags: number;\n /** The raw execution result bytes (still wrapped in Result<T, LangError>) */\n data: Uint8Array;\n}\n\n/**\n * Decode the raw ContractsApi_call response.\n *\n * The response format is:\n * - gasConsumed: Weight { ref_time: Compact<u64>, proof_size: Compact<u64> }\n * - gasRequired: Weight\n * - storageDeposit: StorageDeposit { variant: u8, amount: u128 }\n * - debugMessage: String\n * - result: Result<ExecReturnValue, DispatchError>\n * - ExecReturnValue: { flags: u32, data: Vec<u8> }\n *\n * @param result - The raw response bytes from state_call ContractsApi_call\n * @returns Decoded contract call result\n */\nexport function decodeContractCallResult(result: Uint8Array): ContractCallResult {\n const src = new Src(result);\n\n // gasConsumed: Weight\n const gasConsumedRefTime = BigInt(src.compact());\n const gasConsumedProofSize = BigInt(src.compact());\n\n // gasRequired: Weight\n const gasRequiredRefTime = BigInt(src.compact());\n const gasRequiredProofSize = BigInt(src.compact());\n\n // storageDeposit: StorageDeposit\n const storageDepositVariant = src.u8();\n const storageDepositAmount = src.u128();\n\n // debugMessage: String\n const debugMessage = src.str();\n\n // result: Result<ExecReturnValue, DispatchError>\n const resultVariant = src.u8(); // 0 = Ok, 1 = Err\n const success = resultVariant === 0;\n\n // ExecReturnValue: { flags: u32, data: Vec<u8> }\n const flags = src.u32();\n const data = src.bytes(src.compactLength());\n\n return {\n gas: {\n gasConsumed: {\n refTime: gasConsumedRefTime,\n proofSize: gasConsumedProofSize,\n },\n gasRequired: {\n refTime: gasRequiredRefTime,\n proofSize: gasRequiredProofSize,\n },\n },\n storageDeposit: {\n type: storageDepositVariant === 0 ? \"Refund\" : \"Charge\",\n amount: storageDepositAmount,\n },\n debugMessage,\n success,\n flags,\n data,\n };\n}\n\n/**\n * Unwrap the inner value from Result<T, LangError> by checking the variant byte.\n *\n * Ink contracts wrap their return values in Result<T, LangError>.\n * This function handles the unwrapping and throws an error for LangError.\n *\n * @param data - The exec result bytes (Result<T, LangError> encoded)\n * @returns The inner value bytes (T encoded)\n * @throws Error if the result is Err variant (LangError)\n */\nexport function unwrapInkResult(data: Uint8Array): Uint8Array {\n if (data.length === 0) {\n throw new Error(\"Empty result data\");\n }\n\n const variant = data[0];\n\n if (variant === 0) {\n // Ok variant - return the inner data (skip the variant byte)\n return data.slice(1);\n } else if (variant === 1) {\n // Err variant - LangError\n throw new Error(\"Contract call returned LangError\");\n } else {\n throw new Error(`Unknown result variant: ${variant}`);\n }\n}\n\n/**\n * Check if the result indicates a LangError\n *\n * @param data - The exec result bytes\n * @returns True if it's a LangError (Err variant)\n */\nexport function isLangError(data: Uint8Array): boolean {\n return data.length > 0 && data[0] === 1;\n}\n\n/**\n * Decode ink contract message result using a custom SCALE codec.\n * This bypasses polkadot-api's ink decoder which has issues with LangError type.\n *\n * @param data - The exec result bytes (Result<T, LangError> encoded)\n * @param codec - The SCALE codec for the inner value type T\n * @returns The decoded value\n */\nexport function decodeInkValue<T>(data: Uint8Array, codec: Codec<T>): T {\n const innerData = unwrapInkResult(data);\n return codec.dec(innerData);\n}\n\n/**\n * Pre-defined codecs for common types\n */\nexport const InkCodecs = {\n /** u128 codec for Balance type */\n u128,\n /** Tuple of two u128 values, commonly used for (Balance, Balance) */\n balancePair: Tuple(u128, u128),\n};\n","/**\n * Auto-build SCALE decoders from ink metadata type definitions.\n *\n * This module provides a way to automatically construct decoders for ink contract\n * message return types without manually specifying codecs for each message.\n */\n\nimport {\n u8,\n u16,\n u32,\n u64,\n u128,\n i8,\n i16,\n i32,\n i64,\n i128,\n bool,\n str,\n Bytes,\n Vector,\n Tuple,\n Struct,\n Variant,\n _void,\n Option,\n AccountId,\n type Codec,\n} from \"@polkadot-api/substrate-bindings\";\nimport type { InkMetadata } from \"@polkadot-api/ink-contracts\";\nimport { blake2b } from \"@noble/hashes/blake2.js\";\nimport { D9_SS58_PREFIX } from \"@d9-network/spec\";\n\n// Use 'any' for dynamic codec building to avoid TypeScript strict type issues\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyCodec = Codec<any>;\n\n/**\n * Type definition from ink metadata\n */\ninterface TypeDef {\n primitive?: string;\n composite?: {\n fields: Array<{\n name?: string;\n type: number;\n typeName?: string;\n }>;\n };\n variant?: {\n variants: Array<{\n name: string;\n index: number;\n fields: Array<{\n name?: string;\n type: number;\n typeName?: string;\n }>;\n }>;\n };\n sequence?: {\n type: number;\n };\n array?: {\n len: number;\n type: number;\n };\n tuple?: number[];\n}\n\ninterface TypeEntry {\n id: number;\n type: {\n def: TypeDef;\n path?: string[];\n params?: Array<{\n name: string;\n type?: number;\n }>;\n };\n}\n\n/**\n * Cache for built codecs to avoid rebuilding the same type\n */\ntype CodecCache = Map<number, AnyCodec>;\n\n/**\n * Build a SCALE codec from ink metadata type definition\n */\nfunction buildCodecFromType(typeId: number, types: TypeEntry[], cache: CodecCache): AnyCodec {\n // Check cache first\n const cached = cache.get(typeId);\n if (cached) {\n return cached;\n }\n\n const typeEntry = types.find((t) => t.id === typeId);\n if (!typeEntry) {\n throw new Error(`Type ${typeId} not found in metadata`);\n }\n\n const def = typeEntry.type.def;\n const path = typeEntry.type.path;\n\n // Handle primitive types\n if (def.primitive) {\n const codec = buildPrimitiveCodec(def.primitive);\n cache.set(typeId, codec);\n return codec;\n }\n\n // Handle special path types (AccountId, Hash, etc.)\n if (path && path.length > 0) {\n const specialCodec = buildSpecialTypeCodec(path, typeEntry, types, cache);\n if (specialCodec) {\n cache.set(typeId, specialCodec);\n return specialCodec;\n }\n }\n\n // Handle tuple\n if (def.tuple) {\n const codec = buildTupleCodec(def.tuple, types, cache);\n cache.set(typeId, codec);\n return codec;\n }\n\n // Handle sequence (Vec<T>)\n if (def.sequence) {\n const innerCodec = buildCodecFromType(def.sequence.type, types, cache);\n const codec = Vector(innerCodec);\n cache.set(typeId, codec);\n return codec;\n }\n\n // Handle array [T; N]\n if (def.array) {\n const innerCodec = buildCodecFromType(def.array.type, types, cache);\n // For fixed-size byte arrays, use Bytes\n if (def.array.type === findPrimitiveTypeId(types, \"u8\")) {\n const codec = Bytes(def.array.len);\n cache.set(typeId, codec);\n return codec;\n }\n // For other arrays, use Vector with fixed length validation\n const codec = Vector(innerCodec, def.array.len);\n cache.set(typeId, codec);\n return codec;\n }\n\n // Handle composite (struct)\n if (def.composite) {\n const codec = buildCompositeCodec(def.composite, types, cache);\n cache.set(typeId, codec);\n return codec;\n }\n\n // Handle variant (enum)\n if (def.variant) {\n const codec = buildVariantCodec(def.variant, path, types, cache);\n cache.set(typeId, codec);\n return codec;\n }\n\n throw new Error(`Unknown type definition for type ${typeId}: ${JSON.stringify(def)}`);\n}\n\n/**\n * Build codec for primitive types\n */\nfunction buildPrimitiveCodec(primitive: string): AnyCodec {\n switch (primitive) {\n case \"u8\":\n return u8;\n case \"u16\":\n return u16;\n case \"u32\":\n return u32;\n case \"u64\":\n return u64;\n case \"u128\":\n return u128;\n case \"i8\":\n return i8;\n case \"i16\":\n return i16;\n case \"i32\":\n return i32;\n case \"i64\":\n return i64;\n case \"i128\":\n return i128;\n case \"bool\":\n return bool;\n case \"str\":\n return str;\n default:\n throw new Error(`Unknown primitive type: ${primitive}`);\n }\n}\n\n/**\n * Build codec for special types based on path\n */\nfunction buildSpecialTypeCodec(\n path: string[],\n typeEntry: TypeEntry,\n types: TypeEntry[],\n cache: CodecCache,\n): AnyCodec | null {\n const fullPath = path.join(\"::\");\n\n // AccountId type\n if (fullPath.includes(\"AccountId\")) {\n return AccountId(D9_SS58_PREFIX);\n }\n\n // Option type\n if (path[0] === \"Option\") {\n const params = typeEntry.type.params;\n if (params && params.length > 0 && params[0]?.type !== undefined) {\n const innerCodec = buildCodecFromType(params[0].type, types, cache);\n return Option(innerCodec);\n }\n }\n\n // Result type - we need special handling\n if (path[0] === \"Result\") {\n const params = typeEntry.type.params;\n if (params && params.length >= 2) {\n const okTypeId = params[0]?.type;\n const errTypeId = params[1]?.type;\n if (okTypeId !== undefined && errTypeId !== undefined) {\n const okCodec = buildCodecFromType(okTypeId, types, cache);\n const errCodec = buildCodecFromType(errTypeId, types, cache);\n // Build a proper Result variant\n return Variant(\n {\n Ok: okCodec,\n Err: errCodec,\n },\n [0, 1],\n );\n }\n }\n }\n\n return null;\n}\n\n/**\n * Build codec for tuple types\n */\nfunction buildTupleCodec(tupleTypes: number[], types: TypeEntry[], cache: CodecCache): AnyCodec {\n if (tupleTypes.length === 0) {\n return _void;\n }\n\n const innerCodecs = tupleTypes.map((t) => buildCodecFromType(t, types, cache));\n\n // Handle different tuple sizes\n switch (innerCodecs.length) {\n case 1:\n return Tuple(innerCodecs[0]!);\n case 2:\n return Tuple(innerCodecs[0]!, innerCodecs[1]!);\n case 3:\n return Tuple(innerCodecs[0]!, innerCodecs[1]!, innerCodecs[2]!);\n case 4:\n return Tuple(innerCodecs[0]!, innerCodecs[1]!, innerCodecs[2]!, innerCodecs[3]!);\n default:\n // For larger tuples, use dynamic tuple (cast to any)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (Tuple as any)(...innerCodecs);\n }\n}\n\n/**\n * Build codec for composite (struct) types\n */\nfunction buildCompositeCodec(\n composite: NonNullable<TypeDef[\"composite\"]>,\n types: TypeEntry[],\n cache: CodecCache,\n): AnyCodec {\n const fields = composite.fields;\n\n // Single unnamed field - unwrap it\n if (fields.length === 1 && !fields[0]?.name) {\n return buildCodecFromType(fields[0]!.type, types, cache);\n }\n\n // Multiple fields - build a struct\n const structDef: Record<string, AnyCodec> = {};\n for (const field of fields) {\n const fieldName = field.name || `field${fields.indexOf(field)}`;\n structDef[fieldName] = buildCodecFromType(field.type, types, cache);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return Struct(structDef as any);\n}\n\n/**\n * Build codec for variant (enum) types\n */\nfunction buildVariantCodec(\n variant: NonNullable<TypeDef[\"variant\"]>,\n path: string[] | undefined,\n types: TypeEntry[],\n cache: CodecCache,\n): AnyCodec {\n const variants = variant.variants;\n\n // Check if this is a LangError type (ink specific)\n const isLangError = path?.includes(\"LangError\");\n\n // Build variant definition\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const variantDef: Record<string, any> = {};\n const indices: number[] = [];\n\n // For LangError, add a placeholder for index 0 if missing\n if (isLangError && !variants.some((v) => v.index === 0)) {\n variantDef[\"_Placeholder\"] = _void;\n indices.push(0);\n }\n\n for (const v of variants) {\n let fieldCodec: AnyCodec;\n\n // Handle variants with no fields or undefined fields\n const fields = v.fields ?? [];\n\n if (fields.length === 0) {\n fieldCodec = _void;\n } else if (fields.length === 1 && !fields[0]?.name) {\n // Single unnamed field\n fieldCodec = buildCodecFromType(fields[0]!.type, types, cache);\n } else {\n // Multiple or named fields - build struct\n const structDef: Record<string, AnyCodec> = {};\n for (const field of fields) {\n const fieldName = field.name || `field${fields.indexOf(field)}`;\n structDef[fieldName] = buildCodecFromType(field.type, types, cache);\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n fieldCodec = Struct(structDef as any);\n }\n\n variantDef[v.name] = fieldCodec;\n indices.push(v.index);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return Variant(variantDef as any, indices as any);\n}\n\n/**\n * Find the type ID for a primitive type\n */\nfunction findPrimitiveTypeId(types: TypeEntry[], primitive: string): number {\n const entry = types.find((t) => t.type.def.primitive === primitive);\n return entry?.id ?? -1;\n}\n\n/**\n * Extract the inner type from Result<T, LangError>\n * Returns the type ID of T\n */\nfunction extractResultInnerType(typeEntry: TypeEntry): number | null {\n const path = typeEntry.type.path;\n if (!path || path[0] !== \"Result\") {\n return null;\n }\n\n const params = typeEntry.type.params;\n if (!params || params.length < 1) {\n return null;\n }\n\n return params[0]?.type ?? null;\n}\n\n/**\n * Build a decoder for a message's return type from ink metadata.\n * This handles the Result<T, LangError> wrapper and returns a decoder for T.\n *\n * @param metadata - The ink contract metadata\n * @param messageLabel - The message label (e.g., \"PSP22::balance_of\")\n * @returns A decoder function that decodes the inner value bytes\n */\nexport function buildMessageDecoder(\n metadata: InkMetadata,\n messageLabel: string,\n): (data: Uint8Array) => unknown {\n const types = metadata.types as TypeEntry[];\n const message = metadata.spec.messages.find((m) => m.label === messageLabel);\n\n if (!message) {\n throw new Error(`Message \"${messageLabel}\" not found in metadata`);\n }\n\n const returnTypeId = message.returnType.type;\n const returnTypeEntry = types.find((t) => t.id === returnTypeId);\n\n if (!returnTypeEntry) {\n throw new Error(`Return type ${returnTypeId} not found for message \"${messageLabel}\"`);\n }\n\n const cache: CodecCache = new Map();\n\n // Check if it's a Result type and extract inner type\n const innerTypeId = extractResultInnerType(returnTypeEntry);\n\n if (innerTypeId !== null) {\n // Build decoder for the inner type (T in Result<T, LangError>)\n const innerCodec = buildCodecFromType(innerTypeId, types, cache);\n return (data: Uint8Array) => innerCodec.dec(data);\n }\n\n // Not a Result type, build decoder for the full return type\n const codec = buildCodecFromType(returnTypeId, types, cache);\n return (data: Uint8Array) => codec.dec(data);\n}\n\n/**\n * Build decoders for all messages in the metadata.\n * Returns a Map of message label -> decoder function.\n */\nexport function buildAllMessageDecoders(\n metadata: InkMetadata,\n): Map<string, (data: Uint8Array) => unknown> {\n const decoders = new Map<string, (data: Uint8Array) => unknown>();\n\n for (const message of metadata.spec.messages as Array<{ label: string }>) {\n try {\n const decoder = buildMessageDecoder(metadata, message.label);\n decoders.set(message.label, decoder);\n } catch (error) {\n console.warn(`Failed to build decoder for message \"${message.label}\":`, error);\n }\n }\n\n return decoders;\n}\n\n/**\n * Create a codec registry compatible with ResponseDecoder type\n */\nexport function createCodecRegistry(\n metadata: InkMetadata,\n): Map<string, { dec: (data: Uint8Array) => unknown }> {\n const decoders = buildAllMessageDecoders(metadata);\n const registry = new Map<string, { dec: (data: Uint8Array) => unknown }>();\n\n for (const [label, decoder] of decoders) {\n registry.set(label, { dec: decoder });\n }\n\n return registry;\n}\n\n/**\n * Build a SCALE decoder for a contract event from ink metadata\n *\n * @param metadata - The ink contract metadata\n * @param eventLabel - The event label (e.g., \"Transfer\", \"Approval\")\n * @returns A decoder function that decodes the event data bytes\n */\nexport function buildEventDecoder(\n metadata: InkMetadata,\n eventLabel: string,\n): (data: Uint8Array) => unknown {\n const types = metadata.types as TypeEntry[];\n const events = metadata.spec.events as Array<{\n label: string;\n args: Array<{\n label: string;\n type: { type: number };\n }>;\n }>;\n\n const event = events.find((e) => e.label === eventLabel);\n\n if (!event) {\n throw new Error(`Event \"${eventLabel}\" not found in metadata`);\n }\n\n const cache: CodecCache = new Map();\n\n // Build struct codec from event args\n const structDef: Record<string, AnyCodec> = {};\n\n for (const arg of event.args) {\n const fieldName = arg.label;\n const fieldCodec = buildCodecFromType(arg.type.type, types, cache);\n structDef[fieldName] = fieldCodec;\n }\n\n // If event has no args, return void decoder\n if (event.args.length === 0) {\n return () => undefined;\n }\n\n // If event has single unnamed arg, unwrap it\n if (event.args.length === 1) {\n const argCodec = structDef[event.args[0]!.label];\n return (data: Uint8Array) => argCodec!.dec(data);\n }\n\n // Multiple args - return struct\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const codec = Struct(structDef as any);\n return (data: Uint8Array) => codec.dec(data);\n}\n\n/**\n * Build decoders for all events in the metadata\n *\n * @param metadata - The ink contract metadata\n * @returns Map of event label -> decoder function\n */\nexport function buildAllEventDecoders(\n metadata: InkMetadata,\n): Map<string, (data: Uint8Array) => unknown> {\n const decoders = new Map<string, (data: Uint8Array) => unknown>();\n\n const events = metadata.spec.events as Array<{ label: string }>;\n\n for (const event of events) {\n try {\n const decoder = buildEventDecoder(metadata, event.label);\n decoders.set(event.label, decoder);\n } catch (error) {\n console.warn(`Failed to build decoder for event \"${event.label}\":`, error);\n }\n }\n\n return decoders;\n}\n\n/**\n * Get event signature (topic[0]) for filtering\n * Events in ink! use blake2_256 hash of event label as topic[0]\n *\n * @param eventLabel - The event label (e.g., \"Transfer\")\n * @returns Event signature as Uint8Array (32 bytes)\n */\nexport function getEventSignature(eventLabel: string): Uint8Array {\n return blake2b(new TextEncoder().encode(eventLabel), { dkLen: 32 });\n}\n\n/**\n * Create ASCII-encoded event topic (D9 chain format)\n *\n * D9 chain uses a format where:\n * - First byte is 0x00 (null)\n * - Remaining 31 bytes are ASCII characters of `ContractName::EventLabel`\n * - Total is exactly 32 bytes (truncated/padded as needed)\n *\n * @param contractName - Contract name (e.g., \"MarketMaker\", \"Usdt\")\n * @param eventLabel - Event label (e.g., \"Transfer\", \"USDTToD9Conversion\")\n * @returns 32-byte topic with null prefix and ASCII-encoded path\n */\nexport function createAsciiEventTopic(contractName: string, eventLabel: string): Uint8Array {\n const topic = new Uint8Array(32);\n topic[0] = 0; // Null prefix\n const encoder = new TextEncoder();\n const fullPath = `${contractName}::${eventLabel}`;\n const encoded = encoder.encode(fullPath);\n // Copy up to 31 bytes (leaving room for null prefix)\n topic.set(encoded.slice(0, 31), 1);\n return topic;\n}\n","/**\n * Event parsing and filtering for ink! contracts\n */\nimport type {\n InkMetadata,\n InkDescriptors,\n InkStorageDescriptor,\n InkCallableDescriptor,\n Event as InkEvent,\n} from \"@polkadot-api/ink-contracts\";\nimport type { Enum, SS58String } from \"polkadot-api\";\nimport { ss58Decode } from \"@polkadot-labs/hdkd-helpers\";\nimport { toD9Address } from \"@d9-network/spec\";\nimport { buildAllEventDecoders, buildEventDecoder, getEventSignature } from \"./codec-builder\";\nimport type {\n TypedContractEvent,\n EventFilterOptions,\n RawContractEvent,\n ExtractEnumDef,\n ExtractEventLabels,\n ChainEventRecord,\n} from \"./event-types\";\n\n/**\n * Type-safe event parser for a specific contract\n *\n * @typeParam S - The storage descriptor type\n * @typeParam M - The messages descriptor type\n * @typeParam C - The constructors descriptor type\n * @typeParam E - The event type representing all possible events for this contract\n */\nexport class ContractEventParser<\n S extends InkStorageDescriptor = InkStorageDescriptor,\n M extends InkCallableDescriptor = InkCallableDescriptor,\n C extends InkCallableDescriptor = InkCallableDescriptor,\n E extends InkEvent = InkEvent,\n> {\n private eventDecoders: Map<string, (data: Uint8Array) => unknown>;\n private eventSignatures: Map<string, Uint8Array>;\n /** Maps ink! variant index (first byte of event data) to event label */\n private eventVariantMap: Map<number, string>;\n private contractAddressBytes: Uint8Array;\n private contractAddress: SS58String;\n private metadata: InkMetadata;\n\n constructor(descriptor: InkDescriptors<S, M, C, E>, contractAddress: SS58String) {\n if (!descriptor.metadata) {\n throw new Error(\"Contract descriptor must include metadata\");\n }\n this.metadata = descriptor.metadata;\n // Always store address in D9 format for consistency\n this.contractAddress = toD9Address(contractAddress);\n this.eventDecoders = buildAllEventDecoders(this.metadata);\n // Use original address for bytes decoding (result is the same regardless of prefix)\n this.contractAddressBytes = ss58Decode(contractAddress)[0];\n\n // Build signature map for topic filtering\n this.eventSignatures = new Map();\n // Build variant index map for fallback decoding\n this.eventVariantMap = new Map();\n const events = this.metadata.spec.events as Array<{ label: string }>;\n\n for (let i = 0; i < events.length; i++) {\n const event = events[i];\n const sig = getEventSignature(event.label);\n this.eventSignatures.set(event.label, sig);\n this.eventVariantMap.set(i, event.label);\n }\n }\n\n /**\n * Parse a raw chain event into a type-safe contract event (if it matches)\n * Returns null if the event is not from this contract or cannot be parsed\n *\n * @example\n * ```ts\n * const event = parser.parseEvent(chainEvent);\n * if (event?.type === \"Transfer\") {\n * // event.value is now typed as { from: SS58String; to: SS58String; value: bigint }\n * console.log(event.value.from);\n * }\n * ```\n */\n parseEvent(chainEvent: unknown): TypedContractEvent<E> | null {\n // Extract Contracts.ContractEmitted event from chain event\n const extracted = this.extractContractEmittedEvent(chainEvent);\n if (!extracted) return null;\n\n const { contract, data, topics, blockNumber, blockHash, eventIndex, extrinsicIndex } = extracted;\n\n // Filter by contract address\n if (!this.bytesEqual(contract, this.contractAddressBytes)) {\n return null;\n }\n\n // Decode event based on topic[0] signature\n if (topics.length === 0) return null;\n\n const signature = topics[0];\n let eventLabel: string | null = null;\n\n // Method 1: Try ASCII extraction (D9 chain format)\n // D9 chain uses format: \\0ContractName::EventLabel (32 bytes, null-prefixed)\n eventLabel = this.extractEventLabelFromAsciiTopic(signature!);\n\n // Verify the extracted label has a decoder\n if (eventLabel && !this.eventDecoders.has(eventLabel)) {\n eventLabel = null;\n }\n\n // Method 2: Fall back to blake2 signature matching (standard ink! format)\n if (!eventLabel) {\n for (const [label, sig] of this.eventSignatures) {\n if (this.bytesEqual(signature!, sig)) {\n eventLabel = label;\n break;\n }\n }\n }\n\n // Method 3: Fall back to variant index (first byte of data)\n // This handles cases where the on-chain contract code hash differs from the\n // SDK metadata (e.g., contract was redeployed), causing topic hash mismatches.\n // The data layout is the same, so we can still decode by variant index.\n if (!eventLabel && data.length > 0) {\n const variantIndex = data[0];\n const candidateLabel = this.eventVariantMap.get(variantIndex);\n if (candidateLabel && this.eventDecoders.has(candidateLabel)) {\n eventLabel = candidateLabel;\n }\n }\n\n if (!eventLabel) {\n console.warn(\"Unknown event signature:\", signature);\n return null;\n }\n\n const decoder = this.eventDecoders.get(eventLabel);\n if (!decoder) {\n console.warn(`No decoder for event ${eventLabel}`);\n return null;\n }\n\n try {\n // ink! events include a variant discriminant as first byte, skip it\n const decodedData = decoder(data.slice(1));\n const rawEvent: RawContractEvent = {\n blockNumber,\n blockHash,\n eventIndex,\n contractAddress: this.getContractAddress(),\n data,\n topics,\n };\n // Only include extrinsicIndex if it was extracted\n if (extrinsicIndex !== undefined) {\n rawEvent.extrinsicIndex = extrinsicIndex;\n }\n return {\n type: eventLabel,\n value: decodedData,\n raw: rawEvent,\n } as TypedContractEvent<E>;\n } catch (error) {\n console.warn(`Failed to decode event ${eventLabel}:`, error);\n return null;\n }\n }\n\n /**\n * Extract event label from ASCII-encoded topic (D9 chain format)\n *\n * D9 chain uses a format where:\n * - First byte is 0x00 (null)\n * - Remaining 31 bytes are ASCII characters of `ContractName::EventLabel`\n * - Total is exactly 32 bytes (truncated/padded as needed)\n *\n * @param topic - The 32-byte topic from the event\n * @returns The extracted event label, or null if not in ASCII format\n */\n private extractEventLabelFromAsciiTopic(topic: Uint8Array): string | null {\n if (topic.length !== 32) return null;\n\n // D9 format: first byte is null (0x00)\n if (topic[0] !== 0) return null;\n\n // Decode ASCII (skip null prefix, trim trailing nulls)\n const ascii = new TextDecoder().decode(topic.slice(1)).replace(/\\0+$/, \"\");\n\n // Extract label after \"::\"\n const colonIndex = ascii.lastIndexOf(\"::\");\n if (colonIndex !== -1) {\n return ascii.slice(colonIndex + 2);\n }\n\n // No \"::\" found, use entire string as label\n return ascii || null;\n }\n\n /**\n * Filter a batch of events and return type-safe results\n *\n * @param chainEvents - Array of chain events to filter\n * @param options - Optional filter criteria\n * @returns Array of type-safe contract events\n */\n filterEvents(chainEvents: unknown[], options?: EventFilterOptions): TypedContractEvent<E>[] {\n const results: TypedContractEvent<E>[] = [];\n\n for (const chainEvent of chainEvents) {\n const parsed = this.parseEvent(chainEvent);\n if (!parsed) continue;\n\n // Apply label filter\n if (options?.eventLabels && !options.eventLabels.includes(parsed.type)) {\n continue;\n }\n\n // Apply block range filter\n if (options?.fromBlock && parsed.raw.blockNumber < options.fromBlock) {\n continue;\n }\n if (options?.toBlock && parsed.raw.blockNumber > options.toBlock) {\n continue;\n }\n\n results.push(parsed);\n }\n\n return results;\n }\n\n /**\n * Filter events by specific type with proper type narrowing\n *\n * This method provides better type safety than filterEvents with eventLabels\n * because TypeScript can narrow the return type to only the specified event type.\n *\n * @param chainEvents - Array of chain events to filter\n * @param label - The event label to filter by\n * @returns Array of events narrowed to the specific type\n *\n * @example\n * ```ts\n * const transfers = parser.filterByType(events, \"Transfer\");\n *\n * for (const t of transfers) {\n * // t.value is fully typed as Transfer event data\n * console.log(t.value.from, \"->\", t.value.to, \":\", t.value.value);\n * }\n * ```\n */\n filterByType<L extends string>(\n chainEvents: unknown[],\n label: L,\n ): Array<TypedContractEvent<E> & { type: L }> {\n return this.filterEvents(chainEvents).filter(\n (e): e is TypedContractEvent<E> & { type: L } => (e.type as string) === label,\n );\n }\n\n /**\n * Parse chain event records with proper typing\n *\n * Unlike parseEvent/filterEvents which accept `unknown[]`, this method\n * accepts typed `ChainEventRecord[]` which eliminates the need for\n * `as any` casts in user code.\n *\n * @param events - Array of typed chain event records\n * @param options - Optional filter criteria\n * @returns Array of typed contract events\n *\n * @example\n * ```ts\n * // No more `as any` needed!\n * const events: ChainEventRecord[] = await api.query.System.Events.getValue();\n * const contractEvents = parser.parseChainEvents(events);\n *\n * for (const event of contractEvents) {\n * if (event.type === \"Transfer\") {\n * // Fully typed!\n * console.log(event.value.from, event.value.to, event.value.value);\n * }\n * }\n * ```\n */\n parseChainEvents(\n events: ChainEventRecord[],\n options?: EventFilterOptions\n ): TypedContractEvent<E>[] {\n return this.filterEvents(events, options);\n }\n\n /**\n * Get the contract address as SS58 string\n */\n private getContractAddress(): SS58String {\n return this.contractAddress;\n }\n\n /**\n * Get the contract address as bytes\n */\n getContractAddressBytes(): Uint8Array {\n return this.contractAddressBytes;\n }\n\n /**\n * Extract ContractEmitted event from chain event structure\n * Based on polkadot-api event format\n */\n private extractContractEmittedEvent(chainEvent: unknown): {\n contract: Uint8Array;\n data: Uint8Array;\n topics: Uint8Array[];\n blockNumber: number;\n blockHash: string;\n eventIndex: number;\n extrinsicIndex?: number;\n } | null {\n // Type guard and extract event structure\n if (!chainEvent || typeof chainEvent !== \"object\") {\n return null;\n }\n\n const record = chainEvent as any;\n\n // Extract event data\n const event = record.event;\n if (!event || typeof event !== \"object\") {\n return null;\n }\n\n // Check if this is a Contracts pallet event\n if (event.type !== \"Contracts\") {\n return null;\n }\n\n // Check if this is a ContractEmitted event\n const eventValue = event.value;\n if (!eventValue || typeof eventValue !== \"object\") {\n return null;\n }\n\n if (eventValue.type !== \"ContractEmitted\") {\n return null;\n }\n\n // Extract contract address and data\n const contractEmittedData = eventValue.value;\n if (!contractEmittedData || typeof contractEmittedData !== \"object\") {\n return null;\n }\n\n const contractRaw = contractEmittedData.contract;\n const dataRaw = contractEmittedData.data;\n\n // Handle contract address: can be SS58 string or Uint8Array\n let contract: Uint8Array;\n if (contractRaw instanceof Uint8Array) {\n contract = contractRaw;\n } else if (typeof contractRaw === \"string\") {\n // SS58 string format\n contract = ss58Decode(contractRaw)[0];\n } else {\n return null;\n }\n\n // Handle data: can be Binary object (with asBytes()) or Uint8Array\n let data: Uint8Array;\n if (dataRaw instanceof Uint8Array) {\n data = dataRaw;\n } else if (\n dataRaw &&\n typeof dataRaw === \"object\" &&\n \"asBytes\" in dataRaw &&\n typeof dataRaw.asBytes === \"function\"\n ) {\n // Binary object format\n data = dataRaw.asBytes();\n } else {\n return null;\n }\n\n // Extract topics from the event record\n // Topics are typically stored in the event record, not in the event value\n const topics: Uint8Array[] = [];\n\n // Polkadot-API typically stores topics at the record level\n // Topics can be Uint8Array or Binary objects (with asBytes())\n if (record.topics && Array.isArray(record.topics)) {\n for (const topic of record.topics) {\n if (topic instanceof Uint8Array) {\n topics.push(topic);\n } else if (\n topic &&\n typeof topic === \"object\" &&\n \"asBytes\" in topic &&\n typeof topic.asBytes === \"function\"\n ) {\n // Binary object format\n topics.push(topic.asBytes());\n }\n }\n }\n\n // Extract block metadata\n const blockNumber = typeof record.blockNumber === \"number\" ? record.blockNumber : 0;\n const blockHash = typeof record.blockHash === \"string\" ? record.blockHash : \"\";\n const eventIndex = typeof record.eventIndex === \"number\" ? record.eventIndex : 0;\n\n // Extract extrinsic index from phase (if ApplyExtrinsic)\n let extrinsicIndex: number | undefined;\n if (\n record.phase &&\n typeof record.phase === \"object\" &&\n record.phase.type === \"ApplyExtrinsic\" &&\n typeof record.phase.value === \"number\"\n ) {\n extrinsicIndex = record.phase.value;\n }\n\n return {\n contract,\n data,\n topics,\n blockNumber,\n blockHash,\n eventIndex,\n extrinsicIndex,\n };\n }\n\n /**\n * Compare two Uint8Arrays for equality\n */\n private bytesEqual(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n }\n}\n\n/**\n * Type guard for narrowing event types\n *\n * Use this function when you have a `TypedContractEvent` and need to\n * narrow it to a specific event type. This is useful when the type\n * information is lost (e.g., after serialization or in generic functions).\n *\n * @typeParam E - The Enum type representing all possible events\n * @typeParam L - The specific event label to check\n * @param event - The event to check\n * @param label - The event label to match\n * @returns True if the event type matches the label\n *\n * @example\n * ```ts\n * const event = parser.parseEvent(chainEvent);\n *\n * if (event && isEventType(event, \"Transfer\")) {\n * // TypeScript knows event.value is Transfer event data\n * console.log(event.value.from);\n * console.log(event.value.to);\n * console.log(event.value.value);\n * }\n * ```\n */\nexport function isEventType<E extends InkEvent, L extends ExtractEventLabels<E>>(\n event: TypedContractEvent<E>,\n label: L,\n): event is Extract<TypedContractEvent<E>, { type: L }> {\n return event.type === label;\n}\n","/**\n * Event subscriptions using RxJS\n */\nimport { Observable, filter, map, mergeMap, share, from, of, catchError } from \"rxjs\";\nimport type { PolkadotClient, SS58String } from \"polkadot-api\";\nimport type {\n InkMetadata,\n InkDescriptors,\n InkStorageDescriptor,\n InkCallableDescriptor,\n Event as InkEvent,\n} from \"@polkadot-api/ink-contracts\";\nimport { ContractEventParser } from \"./events\";\nimport type { TypedContractEvent, EventSubscriptionOptions } from \"./event-types\";\n\n/**\n * Block info type for type safety\n */\ninterface BlockInfo {\n number: number;\n hash: string;\n}\n\n/**\n * Create an observable stream of contract events\n *\n * @param client - Polkadot API client\n * @param descriptor - Contract descriptor\n * @param options - Subscription options\n * @returns Observable stream of type-safe contract events\n */\nexport function createContractEventStream<\n S extends InkStorageDescriptor = InkStorageDescriptor,\n M extends InkCallableDescriptor = InkCallableDescriptor,\n C extends InkCallableDescriptor = InkCallableDescriptor,\n E extends InkEvent = InkEvent,\n>(\n client: PolkadotClient,\n descriptor: InkDescriptors<S, M, C, E>,\n options: EventSubscriptionOptions,\n): Observable<TypedContractEvent<E>> {\n const parser = new ContractEventParser<S, M, C, E>(descriptor, options.contractAddress);\n\n // Subscribe to finalized blocks\n return client.finalizedBlock$.pipe(\n // For each finalized block, fetch its events\n mergeMap(async (block: BlockInfo) => {\n try {\n // Fetch System.Events at this block using the provided callback\n const events = await options.getEvents(block.hash);\n return { block, events };\n } catch (error: unknown) {\n console.error(\n \"Error fetching events at block\",\n block.number,\n \":\",\n error instanceof Error ? error.message : String(error),\n );\n // Return empty events on error to keep stream alive\n return { block, events: [] as unknown[] };\n }\n }),\n\n // Parse and filter events for this contract\n map(({ block, events }) => {\n const parsedEvents = events\n .map((event, index) => {\n // Attach block metadata to each event before parsing\n const eventWithMeta = {\n ...(event as object),\n blockNumber: block.number,\n blockHash: block.hash,\n eventIndex: index,\n };\n return parser.parseEvent(eventWithMeta);\n })\n .filter((e): e is TypedContractEvent<E> => e !== null);\n\n return parsedEvents;\n }),\n\n // Flatten array of events to individual emissions\n mergeMap((events) => from(events)),\n\n // Filter by event labels if specified\n filter((event) => {\n if (!options.eventLabels) return true;\n return options.eventLabels.includes(event.type);\n }),\n\n // Handle errors gracefully\n catchError((error: unknown) => {\n console.error(\"Error in contract event stream:\", error);\n return of(); // Return empty observable on error\n }),\n\n // Share subscription among multiple subscribers\n share(),\n );\n}\n\n/**\n * PSP22 Transfer event type\n */\nexport interface PSP22TransferEvent {\n type: \"Transfer\";\n value: {\n from?: SS58String | null;\n to?: SS58String | null;\n value: bigint;\n };\n raw: {\n blockNumber: number;\n blockHash: string;\n eventIndex: number;\n contractAddress: SS58String;\n data: Uint8Array;\n topics: Uint8Array[];\n };\n}\n\n/**\n * Convenience helper to create a Transfer event stream for PSP22 tokens\n *\n * @param client - Polkadot API client\n * @param descriptor - PSP22 contract descriptor\n * @param contractAddress - PSP22 contract address\n * @param getEvents - Function to fetch System.Events at a block hash\n * @param watchAddress - Optional address to filter transfers (only events involving this address)\n * @returns Observable stream of Transfer events\n */\nexport function createPSP22TransferStream<\n S extends InkStorageDescriptor = InkStorageDescriptor,\n M extends InkCallableDescriptor = InkCallableDescriptor,\n C extends InkCallableDescriptor = InkCallableDescriptor,\n E extends InkEvent = InkEvent,\n>(\n client: PolkadotClient,\n descriptor: InkDescriptors<S, M, C, E>,\n contractAddress: SS58String,\n getEvents: (blockHash: string) => Promise<unknown[]>,\n watchAddress?: SS58String,\n): Observable<PSP22TransferEvent> {\n return createContractEventStream<S, M, C, E>(client, descriptor, {\n contractAddress,\n eventLabels: [\"Transfer\"],\n getEvents,\n }).pipe(\n filter((event) => {\n if (!watchAddress) return true;\n\n // Filter transfers where from=watchAddress or to=watchAddress\n const value = event.value as {\n from?: SS58String | null;\n to?: SS58String | null;\n value: bigint;\n };\n\n return value.from === watchAddress || value.to === watchAddress;\n }),\n ) as Observable<PSP22TransferEvent>;\n}\n\n/**\n * Create a native token (D9) transfer event stream\n *\n * This monitors System.Transfer events instead of contract events\n *\n * @param client - Polkadot API client\n * @param getEvents - Function to fetch System.Events at a block hash\n * @param watchAddress - Address to monitor for transfers\n * @returns Observable stream of native transfer events\n */\nexport function createNativeTransferStream(\n client: PolkadotClient,\n getEvents: (blockHash: string) => Promise<unknown[]>,\n watchAddress: SS58String,\n): Observable<{\n from: SS58String;\n to: SS58String;\n amount: bigint;\n blockNumber: number;\n blockHash: string;\n}> {\n return client.finalizedBlock$.pipe(\n // For each block, query system events\n mergeMap(async (block: any) => {\n try {\n const events = await getEvents(block.hash);\n return { block, events };\n } catch (error: unknown) {\n console.error(\n \"Error fetching events for native transfers:\",\n error instanceof Error ? error.message : String(error),\n );\n return { block, events: [] };\n }\n }),\n\n // Filter for Balances.Transfer events\n map(({ block, events }) => {\n const transfers = events\n .map((record: any) => {\n // Check if this is a Balances.Transfer event\n if (record.event?.type !== \"Balances\") return null;\n if (record.event?.value?.type !== \"Transfer\") return null;\n\n const { from, to, amount } = record.event.value.value;\n\n // Filter by watchAddress\n if (from !== watchAddress && to !== watchAddress) return null;\n\n return {\n from: from as SS58String,\n to: to as SS58String,\n amount: amount as bigint,\n blockNumber: block.number,\n blockHash: block.hash,\n };\n })\n .filter((t: any): t is NonNullable<typeof t> => t !== null);\n\n return transfers;\n }),\n\n // Flatten array to individual emissions\n mergeMap((transfers: any[]) => from(transfers)),\n\n // Handle errors\n catchError((error: unknown) => {\n console.error(\"Error in native transfer stream:\", error);\n return of();\n }),\n\n // Share subscription\n share(),\n );\n}\n","/**\n * Type-safe message builder for ink! contracts\n *\n * Provides a polkadot-api compatible API for encoding and decoding\n * contract messages with full TypeScript type inference.\n */\nimport type {\n InkMetadata,\n InkDescriptors,\n InkStorageDescriptor,\n InkCallableDescriptor,\n} from \"@polkadot-api/ink-contracts\";\nimport { getInkLookup, getInkDynamicBuilder } from \"@polkadot-api/ink-contracts\";\nimport type { Enum } from \"polkadot-api\";\nimport { Binary } from \"polkadot-api\";\nimport type { ExtractMessageLabels } from \"./call-types\";\n\n/**\n * Message attributes from metadata\n */\nexport interface MessageAttributes {\n /** Whether the message mutates state */\n mutates: boolean;\n /** Whether the message is payable */\n payable: boolean;\n /** Whether this is the default message */\n default: boolean;\n}\n\n/**\n * Type-safe message interface with encode/decode methods\n *\n * @typeParam M - The InkCallableDescriptor type (message definitions)\n * @typeParam L - The specific message label\n */\nexport interface TypedMessage<M extends InkCallableDescriptor, L extends keyof M & string> {\n /**\n * Encode message arguments to Binary\n *\n * @param args - The message arguments (fully typed)\n * @returns Encoded call data as Binary\n *\n * @example\n * ```ts\n * const transfer = builder.message(\"PSP22::transfer\");\n * const encoded = transfer.encode({\n * to: recipientAddress,\n * value: 1000n,\n * data: new Uint8Array(),\n * });\n * ```\n */\n encode: {} extends M[L][\"message\"]\n ? (args?: M[L][\"message\"]) => Binary\n : (args: M[L][\"message\"]) => Binary;\n\n /**\n * Decode response to typed value\n *\n * @param response - The response data\n * @returns Decoded response value\n */\n decode: (response: Binary | Uint8Array) => M[L][\"response\"];\n\n /** Message attributes (mutates, payable, default) */\n attributes: MessageAttributes;\n\n /** 4-byte selector */\n selector: Uint8Array;\n\n /** Message label */\n label: L;\n}\n\n/**\n * Contract message builder interface\n *\n * @typeParam M - The InkCallableDescriptor type (message definitions)\n */\nexport interface ContractMessageBuilder<M extends InkCallableDescriptor> {\n /**\n * Get a type-safe message interface for a specific message\n *\n * @param label - The message label (e.g., \"PSP22::transfer\")\n * @returns Typed message interface with encode/decode methods\n *\n * @example\n * ```ts\n * const transfer = builder.message(\"PSP22::transfer\");\n * const encoded = transfer.encode({ to, value, data });\n * const decoded = transfer.decode(response);\n * ```\n */\n message<L extends ExtractMessageLabels<M>>(label: L): TypedMessage<M, L>;\n\n /**\n * Get all available message labels\n *\n * @returns Array of message labels\n */\n getMessageLabels(): Array<ExtractMessageLabels<M>>;\n}\n\n/**\n * Internal message metadata from ink! spec\n */\ninterface MessageMetadata {\n label: string;\n selector: string;\n mutates: boolean;\n payable: boolean;\n default: boolean;\n args: Array<{ label: string; type: { type: number } }>;\n returnType: { type: number };\n}\n\n/**\n * Create a type-safe message builder from a contract descriptor\n *\n * @typeParam S - Storage descriptor type\n * @typeParam M - Messages descriptor type\n * @typeParam C - Constructors descriptor type\n * @typeParam E - Events Enum type\n * @param descriptor - The ink! contract descriptor containing metadata\n * @returns A ContractMessageBuilder instance\n *\n * @example\n * ```ts\n * import { createMessageBuilder } from '@d9-network/ink';\n * import { contracts } from '@d9-network/spec';\n *\n * const builder = createMessageBuilder(contracts.usdt);\n *\n * // Get a typed message interface\n * const transfer = builder.message(\"PSP22::transfer\");\n *\n * // Encode with full type checking on args\n * const encoded = transfer.encode({\n * to: recipientAddress, // Must be SS58String\n * value: 1000000n, // Must be bigint\n * data: new Uint8Array(), // Must be Uint8Array\n * });\n *\n * // Decode response with full type inference\n * const response = transfer.decode(resultBytes);\n * ```\n */\nexport function createMessageBuilder<\n S extends InkStorageDescriptor,\n M extends InkCallableDescriptor,\n C extends InkCallableDescriptor,\n E extends Enum<any>,\n>(descriptor: InkDescriptors<S, M, C, E>): ContractMessageBuilder<M> {\n if (!descriptor.metadata) {\n throw new Error(\"Contract descriptor must include metadata\");\n }\n\n const metadata = descriptor.metadata;\n const lookup = getInkLookup(metadata);\n const builder = getInkDynamicBuilder(lookup);\n\n // Cache for built message codecs\n type MessageCodec = ReturnType<typeof builder.buildMessage>;\n const codecCache = new Map<string, MessageCodec>();\n\n // Parse message metadata\n const messagesMetadata = new Map<string, MessageMetadata>();\n for (const msg of metadata.spec.messages as MessageMetadata[]) {\n messagesMetadata.set(msg.label, msg);\n }\n\n function getMessageCodec(label: string): MessageCodec {\n const cached = codecCache.get(label);\n if (cached) {\n return cached;\n }\n const codec = builder.buildMessage(label);\n codecCache.set(label, codec);\n return codec;\n }\n\n function parseSelector(selectorHex: string): Uint8Array {\n const hex = selectorHex.startsWith(\"0x\") ? selectorHex.slice(2) : selectorHex;\n return new Uint8Array(hex.match(/.{1,2}/g)!.map((byte) => parseInt(byte, 16)));\n }\n\n function message<L extends ExtractMessageLabels<M>>(label: L): TypedMessage<M, L> {\n const msgMeta = messagesMetadata.get(label);\n if (!msgMeta) {\n throw new Error(`Message \"${label}\" not found in metadata`);\n }\n\n const codec = getMessageCodec(label);\n const selector = parseSelector(msgMeta.selector);\n\n const encode = (args?: M[L][\"message\"]): Binary => {\n const encoded = codec.call.enc((args ?? {}) as Parameters<typeof codec.call.enc>[0]);\n return Binary.fromBytes(encoded);\n };\n\n const decode = (response: Binary | Uint8Array): M[L][\"response\"] => {\n const bytes = response instanceof Uint8Array ? response : response.asBytes();\n return codec.value.dec(bytes) as M[L][\"response\"];\n };\n\n return {\n encode: encode as TypedMessage<M, L>[\"encode\"],\n decode,\n attributes: {\n mutates: msgMeta.mutates,\n payable: msgMeta.payable,\n default: msgMeta.default,\n },\n selector,\n label,\n };\n }\n\n function getMessageLabels(): Array<ExtractMessageLabels<M>> {\n return Array.from(messagesMetadata.keys()) as Array<ExtractMessageLabels<M>>;\n }\n\n return {\n message,\n getMessageLabels,\n };\n}\n","/**\n * Type-safe RPC wrapper for PolkadotClient\n */\nimport type { PolkadotClient } from \"polkadot-api\";\nimport type { TypedRpc } from \"./rpc-types\";\n\n/**\n * Create a type-safe RPC proxy from a PolkadotClient\n *\n * This wraps the client's `_request` method with a Proxy that provides\n * a dot-syntax interface with proper TypeScript types.\n *\n * @param client - The PolkadotClient instance\n * @returns A type-safe RPC proxy object\n *\n * @example\n * ```ts\n * const rpc = createTypedRpc(client);\n *\n * // Dot syntax with full type inference\n * const hash = await rpc.chain_getBlockHash(12345);\n * // hash: HexString | null\n *\n * const header = await rpc.chain_getHeader(hash);\n * // header: BlockHeader | null\n *\n * const result = await rpc.state_call(\"ContractsApi_call\", message, blockHash);\n * // result: HexString\n * ```\n */\nexport function createTypedRpc(client: PolkadotClient): TypedRpc {\n return new Proxy({} as TypedRpc, {\n get(_target, prop: string) {\n return (...args: unknown[]) => client._request(prop, args);\n },\n });\n}\n","/**\n * D9 Ink Contract implementation\n *\n * Provides a type-safe interface for interacting with ink! smart contracts\n * using state_call + ContractsApi_call instead of ReviveApi.\n */\n\nimport type { PolkadotSigner, SS58String } from \"polkadot-api\";\nimport { Binary } from \"polkadot-api\";\nimport { fromHex } from \"polkadot-api/utils\";\nimport {\n getInkLookup,\n getInkDynamicBuilder,\n type InkDescriptors,\n type InkCallableDescriptor,\n type InkStorageDescriptor,\n type InkMetadata,\n type Event as InkEvent,\n} from \"@polkadot-api/ink-contracts\";\nimport { ss58Decode } from \"@polkadot-labs/hdkd-helpers\";\n\nimport type {\n D9InkContract,\n QueryOptions,\n QueryResult,\n SendOptions,\n SendableTransaction,\n TxResult,\n ContractStorage,\n CreateContractOptions,\n ResponseDecoder,\n} from \"./types\";\nimport { encodeContractCall } from \"./encode\";\nimport { decodeContractCallResult, unwrapInkResult, isLangError } from \"./decode\";\nimport { createCodecRegistry } from \"./codec-builder\";\nimport { ContractEventParser } from \"./events\";\nimport { createContractEventStream } from \"./subscriptions\";\nimport type { TypedContractEvent, EventSubscriptionOptions } from \"./event-types\";\nimport type { ExtractMessageLabels } from \"./call-types\";\nimport { createMessageBuilder, type TypedMessage } from \"./message-builder\";\nimport {\n ContractError,\n MetadataError,\n DecodeError,\n LangError,\n TimeoutError,\n AbortedError,\n TransactionError,\n} from \"@d9-network/spec\";\nimport { createTypedRpc } from \"./rpc\";\n\n/**\n * Result type for decodeWithPapiFallback helper\n */\ntype FallbackDecodeResult<T> = { success: true; value: T } | { success: false; error: DecodeError };\n\n/**\n * Decode response data using papi's value codec with proper result unwrapping.\n * This helper handles the common pattern of wrapping inner data in an Ok variant\n * and extracting the actual value from papi's decoded result.\n *\n * @param innerData - The raw response bytes to decode\n * @param codec - The papi codec with value.dec method\n * @param method - Method name for error context\n * @returns Decoded value or error\n */\nfunction decodeWithPapiFallback<T>(\n innerData: Uint8Array,\n codec: { value: { dec: (data: Uint8Array) => unknown } },\n method: string,\n): FallbackDecodeResult<T> {\n try {\n // Wrap inner data in Ok variant for papi's codec\n const fullResult = new Uint8Array(1 + innerData.length);\n fullResult[0] = 0; // Ok variant\n fullResult.set(innerData, 1);\n\n const papiResult = codec.value.dec(fullResult);\n\n // Handle papi's Result wrapper format\n if (\n papiResult !== null &&\n typeof papiResult === \"object\" &&\n \"success\" in papiResult &&\n \"value\" in papiResult\n ) {\n if ((papiResult as { success: boolean }).success) {\n return {\n success: true,\n value: (papiResult as { value: T }).value,\n };\n }\n return {\n success: false,\n error: new DecodeError(\n method,\n `Contract returned error: ${JSON.stringify((papiResult as { value: unknown }).value)}`,\n (papiResult as { value: unknown }).value,\n ),\n };\n }\n\n // Direct value without Result wrapper\n return { success: true, value: papiResult as T };\n } catch (error) {\n return {\n success: false,\n error: new DecodeError(\n method,\n `Failed to decode response: ${error instanceof Error ? error.message : String(error)}`,\n { error },\n ),\n };\n }\n}\n\n/**\n * Patch LangError type in ink metadata to fix the missing index 0 variant issue.\n * Uses structuredClone for efficient deep cloning.\n */\nfunction patchLangErrorInMetadata(metadata: InkMetadata): InkMetadata {\n const patched = structuredClone(metadata);\n\n for (const typeEntry of patched.types) {\n const path = typeEntry.type?.path;\n const def = typeEntry.type?.def as {\n variant?: {\n variants: Array<{\n index: number;\n name: string;\n fields: unknown[];\n docs: string[];\n }>;\n };\n };\n if (path && Array.isArray(path) && path.includes(\"LangError\") && def?.variant) {\n const variants = def.variant.variants;\n if (Array.isArray(variants)) {\n const hasIndex0 = variants.some((v) => v.index === 0);\n if (!hasIndex0) {\n variants.unshift({\n index: 0,\n name: \"_Placeholder\",\n fields: [],\n docs: [],\n });\n }\n }\n }\n }\n\n return patched;\n}\n\n/**\n * Convert SS58 address to bytes\n */\nfunction ss58ToBytes(address: SS58String): Uint8Array {\n const [publicKey] = ss58Decode(address);\n return publicKey;\n}\n\n/**\n * Create a promise that rejects after a timeout\n */\nfunction createTimeout<T>(ms: number, label: string): { promise: Promise<T>; clear: () => void } {\n let timeoutId: ReturnType<typeof setTimeout>;\n const promise = new Promise<T>((_, reject) => {\n timeoutId = setTimeout(() => {\n reject(new TimeoutError(label, ms));\n }, ms);\n });\n return {\n promise,\n clear: () => clearTimeout(timeoutId),\n };\n}\n\n/**\n * Check if AbortSignal is aborted and throw if so\n */\nfunction checkAborted(signal: AbortSignal | undefined, label: string): void {\n if (signal?.aborted) {\n throw new AbortedError(label, signal.reason);\n }\n}\n\n/**\n * Create a D9 Ink Contract instance\n */\nexport function createD9InkContract<\n S extends InkStorageDescriptor,\n M extends InkCallableDescriptor,\n C extends InkCallableDescriptor,\n E extends InkEvent,\n>(\n descriptor: InkDescriptors<S, M, C, E>,\n address: SS58String,\n options: CreateContractOptions,\n): D9InkContract<M, E> {\n const { client, typedApi, defaultQueryOptions = {}, defaultSendOptions = {} } = options;\n\n if (!descriptor.metadata) {\n throw new MetadataError(\"Contract descriptor must include metadata\");\n }\n\n // Patch and prepare metadata\n const patchedMetadata = patchLangErrorInMetadata(descriptor.metadata);\n const lookup = getInkLookup(patchedMetadata);\n const builder = getInkDynamicBuilder(lookup);\n\n // Create a patched descriptor with the patched metadata for internal use\n const patchedDescriptor = {\n ...descriptor,\n metadata: patchedMetadata,\n } as InkDescriptors<S, M, C, E>;\n\n // Build auto-generated codecs\n let codecRegistry: Map<string, ResponseDecoder>;\n try {\n codecRegistry = createCodecRegistry(patchedMetadata);\n } catch (error) {\n console.warn(\"Failed to auto-generate codecs from metadata:\", error);\n codecRegistry = new Map();\n }\n\n // Convert address to bytes\n const addressBytes = ss58ToBytes(address);\n\n // Create typed RPC for type-safe RPC calls\n const rpc = createTypedRpc(client);\n\n // Cache for message codecs\n type MessageCodec = ReturnType<typeof builder.buildMessage>;\n const messageCodecCache = new Map<string, MessageCodec>();\n\n function getMessageCodec(label: string): MessageCodec {\n const cached = messageCodecCache.get(label);\n if (cached) {\n return cached;\n }\n const codec = builder.buildMessage(label);\n messageCodecCache.set(label, codec);\n return codec;\n }\n\n /**\n * Get the decoder for a message\n */\n function getDecoder(label: string): ResponseDecoder | null {\n return codecRegistry.get(label) ?? null;\n }\n\n /**\n * Execute a query (dry-run)\n */\n async function executeQuery<K extends keyof M & string>(\n method: K,\n queryOptions: QueryOptions<M[K][\"message\"]>,\n ): Promise<QueryResult<M[K][\"response\"]>> {\n const opts = { ...defaultQueryOptions, ...queryOptions };\n const { origin, args, value = 0n, signal, timeout, at } = opts;\n\n try {\n checkAborted(signal, method);\n\n const originBytes = ss58ToBytes(origin);\n const codec = getMessageCodec(method);\n\n // Encode the call\n const callData = codec.call.enc((args ?? {}) as Parameters<typeof codec.call.enc>[0]);\n\n // Create the state_call message\n const message = encodeContractCall(originBytes, addressBytes, callData, value);\n\n // Get block hash\n const blockHash = at ?? (await client.getFinalizedBlock()).hash;\n\n checkAborted(signal, method);\n\n // Execute state_call with optional timeout\n const executeCall = async () => {\n const response = await rpc.state_call(\"ContractsApi_call\", message, blockHash);\n return fromHex(response);\n };\n\n let rawResponse: Uint8Array;\n if (timeout) {\n const { promise: timeoutPromise, clear } = createTimeout<Uint8Array>(timeout, method);\n try {\n rawResponse = await Promise.race([executeCall(), timeoutPromise]);\n } finally {\n clear();\n }\n } else {\n rawResponse = await executeCall();\n }\n\n checkAborted(signal, method);\n\n // Decode the ContractsApi_call response\n const callResult = decodeContractCallResult(rawResponse);\n\n // Check for execution error\n if (!callResult.success) {\n return {\n success: false,\n error: new ContractError(\n `Contract execution failed: ${callResult.debugMessage}`,\n \"CONTRACT_ERROR\",\n method,\n ),\n };\n }\n\n // Check for LangError\n if (isLangError(callResult.data)) {\n return {\n success: false,\n error: new LangError(method, callResult.data[1] ?? 1),\n };\n }\n\n // Unwrap the Result<T, LangError>\n const innerData = unwrapInkResult(callResult.data);\n\n // Decode the response\n let decodedResponse: M[K][\"response\"];\n const decoder = getDecoder(method);\n\n if (decoder) {\n try {\n decodedResponse = decoder.dec(innerData) as M[K][\"response\"];\n } catch (decodeError) {\n // Custom decoder failed, fall back to papi's value codec\n console.warn(\"D9InkContract: Failed to decode response:\", decodeError);\n const fallbackResult = decodeWithPapiFallback<M[K][\"response\"]>(innerData, codec, method);\n if (!fallbackResult.success) {\n return { success: false, error: fallbackResult.error };\n }\n decodedResponse = fallbackResult.value;\n }\n } else {\n // No custom decoder, use papi's codec\n const fallbackResult = decodeWithPapiFallback<M[K][\"response\"]>(innerData, codec, method);\n if (!fallbackResult.success) {\n return { success: false, error: fallbackResult.error };\n }\n decodedResponse = fallbackResult.value;\n }\n\n // Return success with QuerySuccessValue fields spread to same level\n return {\n success: true,\n value: decodedResponse,\n events: [],\n gasConsumed: callResult.gas.gasConsumed,\n gasRequired: callResult.gas.gasRequired,\n storageDeposit: callResult.storageDeposit.amount,\n send: () =>\n createSendableTransaction(method, {\n origin,\n args,\n value,\n gasLimit: callResult.gas.gasRequired,\n }),\n };\n } catch (error) {\n if (error instanceof ContractError) {\n return { success: false, error };\n }\n return {\n success: false,\n error: new ContractError(\n error instanceof Error ? error.message : String(error),\n \"NETWORK_ERROR\",\n method,\n ),\n };\n }\n }\n\n /**\n * Create a sendable transaction\n */\n function createSendableTransaction<K extends keyof M & string>(\n method: K,\n sendOptions: SendOptions<M[K][\"message\"]>,\n ): SendableTransaction<M[K][\"response\"]> {\n const opts = { ...defaultSendOptions, ...sendOptions };\n const { origin, args, value = 0n, gasLimit, storageDepositLimit } = opts;\n\n const originBytes = ss58ToBytes(origin);\n const codec = getMessageCodec(method);\n\n // Encode the call\n const callData = codec.call.enc((args ?? {}) as Parameters<typeof codec.call.enc>[0]);\n\n return {\n getEncodedData: () => callData,\n\n async signAndSubmit(signer: PolkadotSigner): Promise<TxResult<M[K][\"response\"]>> {\n if (!typedApi) {\n throw new TransactionError(\n method,\n \"typedApi is required for transaction submission. Pass typedApi in SDK options.\",\n );\n }\n\n try {\n // First do a dry-run to get gas estimate if not provided\n let gas = gasLimit;\n if (!gas) {\n const message = encodeContractCall(originBytes, addressBytes, callData, value);\n const blockHash = (await client.getFinalizedBlock()).hash;\n const response = await rpc.state_call(\"ContractsApi_call\", message, blockHash);\n const callResult = decodeContractCallResult(fromHex(response));\n gas = callResult.gas.gasRequired;\n }\n\n // Build the transaction using typedApi\n const api = typedApi as {\n tx: {\n Contracts: {\n call: (params: {\n dest: { type: \"Id\"; value: SS58String };\n value: bigint;\n gas_limit: { ref_time: bigint; proof_size: bigint };\n storage_deposit_limit: bigint | undefined;\n data: Binary;\n }) => {\n signAndSubmit: (\n signer: PolkadotSigner,\n options?: { at?: \"best\" | \"finalized\" },\n ) => Promise<{\n txHash: string;\n block: { hash: string; number: number };\n events: unknown[];\n }>;\n };\n };\n };\n };\n\n const tx = api.tx.Contracts.call({\n dest: { type: \"Id\", value: address },\n value,\n gas_limit: {\n ref_time: gas.refTime,\n proof_size: gas.proofSize,\n },\n storage_deposit_limit: storageDepositLimit,\n data: Binary.fromBytes(callData),\n });\n\n const txResult = await tx.signAndSubmit(signer, { at: \"finalized\" });\n\n return {\n ok: true,\n txHash: txResult.txHash,\n block: txResult.block,\n events: txResult.events ?? [],\n };\n } catch (error) {\n return {\n ok: false,\n txHash: \"\",\n block: { hash: \"\", number: 0 },\n events: [],\n dispatchError: error,\n };\n }\n },\n };\n }\n\n /**\n * Create send method that returns a sendable transaction\n */\n function send<K extends keyof M & string>(\n method: K,\n sendOptions: SendOptions<M[K][\"message\"]>,\n ): SendableTransaction<M[K][\"response\"]> {\n return createSendableTransaction(method, sendOptions);\n }\n\n /**\n * Create storage query interface.\n *\n * @deprecated Storage queries are not yet implemented. This API is exposed for\n * future compatibility but will throw errors if used. Use contract messages\n * (query/send) to read contract state instead.\n *\n * @returns ContractStorage interface with unimplemented methods\n */\n function getStorage(): ContractStorage {\n const notImplementedWarning = (method: string) => {\n console.warn(\n `[D9InkContract] ${method}() is not implemented. ` +\n `Storage queries are planned for a future release. ` +\n `Use contract messages to read state instead.`,\n );\n };\n\n return {\n async getRoot() {\n notImplementedWarning(\"getRoot\");\n return {\n success: false,\n value: new ContractError(\n \"Storage queries not yet implemented. Use contract messages to read state.\",\n \"METADATA_ERROR\",\n ),\n };\n },\n\n async getNested(path: string, ..._keys: unknown[]) {\n notImplementedWarning(\"getNested\");\n return {\n success: false,\n value: new ContractError(\n `Storage query for \"${path}\" not yet implemented. Use contract messages to read state.`,\n \"METADATA_ERROR\",\n ),\n };\n },\n };\n }\n\n /**\n * Filter events for this contract\n */\n function filterEvents(events: unknown[]): TypedContractEvent<E>[] {\n const parser = new ContractEventParser<S, M, C, E>(patchedDescriptor, address);\n return parser.filterEvents(events);\n }\n\n /**\n * Filter events by specific type with proper type narrowing\n */\n function filterEventsByType<L extends string>(\n events: unknown[],\n label: L,\n ): Array<TypedContractEvent<E> & { type: L }> {\n const parser = new ContractEventParser<S, M, C, E>(patchedDescriptor, address);\n return parser.filterByType(events, label);\n }\n\n // Create message builder for type-safe message encoding/decoding\n const messageBuilder = createMessageBuilder(descriptor);\n\n /**\n * Get a type-safe message interface\n */\n function message<L extends ExtractMessageLabels<M>>(label: L): TypedMessage<M, L> {\n return messageBuilder.message(label);\n }\n\n /**\n * Subscribe to contract events as an RxJS Observable\n *\n * @param options - Subscription options (contractAddress is automatically set)\n * @param options.getEvents - Function to fetch System.Events at a block hash\n * @param options.eventLabels - Optional filter for specific event names\n * @param options.fromBlock - Optional starting block number\n */\n function subscribeToEvents(options: Omit<EventSubscriptionOptions, \"contractAddress\">) {\n return createContractEventStream<S, M, C, E>(client, patchedDescriptor, {\n ...options,\n contractAddress: address,\n });\n }\n\n // Type assertion needed because the runtime correctly unwraps MessageResult\n // but TypeScript doesn't know that. The UnwrapMessageResult type in D9InkContract\n // matches what we actually return at runtime.\n return {\n address,\n metadata: patchedMetadata,\n query: executeQuery,\n send,\n getStorage,\n filterEvents,\n filterEventsByType,\n message,\n subscribeToEvents,\n } as D9InkContract<M, E>;\n}\n","/**\n * D9 Ink SDK entry point\n *\n * Creates an ink SDK that uses state_call + ContractsApi_call\n * instead of ReviveApi for chains that don't support it.\n */\n\nimport type { Enum, PolkadotClient, SS58String } from \"polkadot-api\";\nimport {\n type InkDescriptors,\n type InkCallableDescriptor,\n type InkStorageDescriptor,\n} from \"@polkadot-api/ink-contracts\";\n\nimport type { D9InkSdk, D9InkSdkOptions, D9InkContract, QueryOptions, SendOptions } from \"./types\";\nimport type { TypedRpc } from \"./rpc-types\";\nimport { createD9InkContract } from \"./contract\";\nimport { createTypedRpc } from \"./rpc\";\n\n/**\n * Options for creating D9 Ink SDK\n */\nexport interface CreateD9InkSdkOptions extends D9InkSdkOptions {\n /**\n * Typed API for transaction submission.\n * Required for submitting real transactions.\n */\n typedApi?: unknown;\n}\n\n/**\n * Extended D9 Ink SDK interface with typed RPC access\n */\nexport interface D9InkSdkWithRpc extends D9InkSdk {\n /**\n * Type-safe RPC interface with dot syntax\n *\n * Provides autocomplete for known Substrate RPC methods and type inference\n * for parameters and return values.\n *\n * @example\n * ```ts\n * // Dot syntax with full type inference\n * const hash = await sdk.rpc.chain_getBlockHash(12345);\n * // hash: HexString | null\n *\n * const result = await sdk.rpc.state_call(\"ContractsApi_call\", message, blockHash);\n * // result: HexString\n * ```\n */\n rpc: TypedRpc;\n}\n\n/**\n * Create a D9 Ink SDK instance.\n *\n * This SDK provides a similar API to the official @polkadot-api/sdk-ink,\n * but uses state_call + ContractsApi_call instead of ReviveApi.\n *\n * @example\n * ```ts\n * import { createD9InkSdk } from \"@d9-network/ink\";\n * import { contracts } from \"@d9-network/spec\";\n *\n * const sdk = createD9InkSdk(client);\n * const usdtContract = sdk.getContract(\n * contracts.d9_usdt,\n * \"uLj9DRUujbpCyK7USZY5ebGbxdtKoWvdRvGyyUsoLWDsNng\"\n * );\n *\n * // Query balance\n * const result = await usdtContract.query(\"PSP22::balance_of\", {\n * origin: aliceAddress,\n * args: { owner: aliceAddress }\n * });\n *\n * if (result.success) {\n * console.log(\"Balance:\", result.value.response);\n *\n * // Send transaction from the query result\n * const txResult = await result.value.send().signAndSubmit(aliceSigner);\n * }\n *\n * // Or send directly\n * const txResult = await usdtContract\n * .send(\"PSP22::transfer\", {\n * origin: aliceAddress,\n * args: { to: bobAddress, value: 1000n, data: [] }\n * })\n * .signAndSubmit(aliceSigner);\n * ```\n *\n * @param client - The PolkadotClient instance\n * @param options - Optional SDK configuration\n * @returns D9 Ink SDK instance with typed RPC access\n */\nexport function createD9InkSdk(\n client: PolkadotClient,\n options: CreateD9InkSdkOptions = {},\n): D9InkSdkWithRpc {\n const { typedApi, defaultQueryOptions, defaultSendOptions } = options;\n\n return {\n getContract<\n S extends InkStorageDescriptor,\n M extends InkCallableDescriptor,\n C extends InkCallableDescriptor,\n E extends Enum<any>,\n >(descriptor: InkDescriptors<S, M, C, E>, address: SS58String): D9InkContract<M, E> {\n return createD9InkContract(descriptor, address, {\n client,\n typedApi,\n defaultQueryOptions,\n defaultSendOptions,\n });\n },\n rpc: createTypedRpc(client),\n };\n}\n\n// Re-export types for convenience\nexport type {\n D9InkSdk,\n D9InkSdkOptions,\n D9InkContract,\n QueryOptions,\n SendOptions,\n QueryResult,\n SendableTransaction,\n TxResult,\n ContractStorage,\n} from \"./types\";\n\nexport type { TypedRpc } from \"./rpc-types\";\n","/**\n * Event type definitions for ink! contracts\n */\nimport type { Enum, SS58String } from \"polkadot-api\";\nimport type { Event as InkEvent } from \"@polkadot-api/ink-contracts\";\n\n/**\n * Raw event data from chain\n */\nexport interface RawContractEvent {\n /** Block number where event was emitted */\n blockNumber: number;\n /** Block hash */\n blockHash: string;\n /** Event index in block */\n eventIndex: number;\n /**\n * Extrinsic index that caused this event (if in ApplyExtrinsic phase)\n *\n * This is extracted from the event's `phase.value` when `phase.type === \"ApplyExtrinsic\"`.\n * Useful for indexers to correlate events with their originating transactions.\n */\n extrinsicIndex?: number;\n /** Contract address that emitted the event (always in D9 format) */\n contractAddress: SS58String;\n /** Event data (SCALE encoded) */\n data: Uint8Array;\n /** Event topics (indexed fields) */\n topics: Uint8Array[];\n}\n\n/**\n * Extract the definition object from an Enum type or InkEvent type\n * e.g. ExtractEnumDef<Enum<{A: X, B: Y}>> = {A: X, B: Y}\n *\n * For non-Enum types (e.g., InkEvent { type: string; value: unknown }),\n * returns a generic event definition.\n */\nexport type ExtractEnumDef<E> =\n E extends Enum<infer T> ? T : E extends InkEvent ? Record<string, unknown> : never;\n\n/**\n * Extract event labels as a union type from an Enum type\n * e.g. ExtractEventLabels<Enum<{Transfer: X, Approval: Y}>> = \"Transfer\" | \"Approval\"\n */\nexport type ExtractEventLabels<E extends InkEvent> = keyof ExtractEnumDef<E> & string;\n\n/**\n * Type-safe contract event with discriminated union\n * Enables type narrowing: `if (event.type === \"Transfer\") { event.value.from }`\n */\nexport type TypedContractEvent<E extends InkEvent> =\n E extends Enum<infer T>\n ? {\n [K in keyof T & string]: {\n /** Event type (discriminant for type narrowing) */\n type: K;\n /** Decoded event data (type-safe based on event type) */\n value: T[K];\n /** Original raw event */\n raw: RawContractEvent;\n };\n }[keyof T & string]\n : {\n type: string;\n value: unknown;\n raw: RawContractEvent;\n };\n\n/**\n * Decoded contract event with generic data type.\n * For full type safety with discriminated unions, use TypedContractEvent instead.\n */\nexport interface DecodedContractEvent<T = unknown> {\n /** Event label from metadata (e.g., \"Transfer\", \"Approval\") */\n label: string;\n /** Decoded event data */\n data: T;\n /** Original raw event */\n raw: RawContractEvent;\n}\n\n/**\n * Event filter options\n */\nexport interface EventFilterOptions {\n /** Contract address to filter by */\n contractAddress?: SS58String;\n /** Event labels to include (e.g., [\"Transfer\", \"Approval\"]) */\n eventLabels?: string[];\n /** From block number (inclusive) */\n fromBlock?: number;\n /** To block number (inclusive) */\n toBlock?: number;\n}\n\n/**\n * Type-safe event filter options with literal event labels\n * Provides compile-time validation of event label names\n *\n * @typeParam E - The event type representing all possible events\n *\n * @example\n * ```ts\n * const options: TypedEventFilterOptions<typeof contracts.usdt.__types.event> = {\n * eventLabels: [\"Transfer\", \"Approval\"], // Must be valid event names\n * };\n * ```\n */\nexport interface TypedEventFilterOptions<E extends InkEvent> {\n /** Contract address to filter by */\n contractAddress?: SS58String;\n /** Event labels to include (type-safe) */\n eventLabels?: Array<ExtractEventLabels<E>>;\n /** From block number (inclusive) */\n fromBlock?: number;\n /** To block number (inclusive) */\n toBlock?: number;\n}\n\n/**\n * Event subscription options\n */\nexport interface EventSubscriptionOptions {\n /** Contract address to subscribe to */\n contractAddress: SS58String;\n /** Event labels to subscribe to (undefined = all events) */\n eventLabels?: string[];\n /** Include historical events from this block */\n fromBlock?: number;\n /**\n * Function to fetch System.Events at a given block hash\n * This is required because PolkadotClient doesn't expose typed API directly\n *\n * @example\n * ```ts\n * const options = {\n * contractAddress: usdtAddress,\n * getEvents: async (blockHash) => {\n * return await api.query.System.Events.getValue({ at: blockHash });\n * }\n * };\n * ```\n */\n getEvents: (blockHash: string) => Promise<unknown[]>;\n}\n\n// =============================================================================\n// Chain Event Types (for eliminating `as any` casts)\n// =============================================================================\n\n/**\n * Chain event record structure (matches polkadot-api format)\n *\n * Use this type when processing raw chain events to avoid `as any` casts.\n *\n * @example\n * ```ts\n * // Instead of: const events = await api.query.System.Events.getValue() as any[];\n * // Use: const events: ChainEventRecord[] = await api.query.System.Events.getValue();\n *\n * for (const event of events) {\n * if (isContractEmittedEvent(event)) {\n * // event is now properly typed!\n * }\n * }\n * ```\n */\nexport interface ChainEventRecord {\n /** The event phase */\n phase?: {\n type: string;\n value?: number;\n };\n /** The event pallet and variant */\n event: {\n type: string;\n value: {\n type: string;\n value: unknown;\n };\n };\n /** Event topics (for indexed fields) */\n topics?: Array<Uint8Array | { asBytes?: () => Uint8Array }>;\n /** Block number (if available) */\n blockNumber?: number;\n /** Block hash (if available) */\n blockHash?: string;\n /** Event index in block (if available) */\n eventIndex?: number;\n}\n\n/**\n * Contracts.ContractEmitted event value\n */\nexport interface ContractEmittedValue {\n /** Contract address (SS58 or Uint8Array) */\n contract: SS58String | Uint8Array;\n /** Event data (Binary or Uint8Array) */\n data: Uint8Array | { asBytes: () => Uint8Array };\n}\n\n/**\n * Contracts.Called event value\n */\nexport interface ContractCalledValue {\n /** Caller address */\n caller: SS58String;\n /** Contract address being called */\n contract: SS58String;\n}\n\n/**\n * Typed chain event for Contracts.ContractEmitted\n */\nexport interface ContractEmittedChainEvent extends ChainEventRecord {\n event: {\n type: \"Contracts\";\n value: {\n type: \"ContractEmitted\";\n value: ContractEmittedValue;\n };\n };\n}\n\n/**\n * Typed chain event for Contracts.Called\n */\nexport interface ContractCalledChainEvent extends ChainEventRecord {\n event: {\n type: \"Contracts\";\n value: {\n type: \"Called\";\n value: ContractCalledValue;\n };\n };\n}\n\n/**\n * Typed chain event for Balances.Transfer\n */\nexport interface BalancesTransferChainEvent extends ChainEventRecord {\n event: {\n type: \"Balances\";\n value: {\n type: \"Transfer\";\n value: {\n from: SS58String;\n to: SS58String;\n amount: bigint;\n };\n };\n };\n}\n\n/**\n * Type guard for Contracts.ContractEmitted events\n *\n * @example\n * ```ts\n * for (const event of events) {\n * if (isContractEmittedEvent(event)) {\n * // event.event.value.value is ContractEmittedValue\n * const { contract, data } = event.event.value.value;\n * }\n * }\n * ```\n */\nexport function isContractEmittedEvent(\n event: ChainEventRecord\n): event is ContractEmittedChainEvent {\n return (\n event.event?.type === \"Contracts\" &&\n event.event?.value?.type === \"ContractEmitted\"\n );\n}\n\n/**\n * Type guard for Contracts.Called events\n *\n * @example\n * ```ts\n * for (const event of events) {\n * if (isContractCalledEvent(event)) {\n * // event.event.value.value is ContractCalledValue\n * const { caller, contract } = event.event.value.value;\n * }\n * }\n * ```\n */\nexport function isContractCalledEvent(\n event: ChainEventRecord\n): event is ContractCalledChainEvent {\n return (\n event.event?.type === \"Contracts\" &&\n event.event?.value?.type === \"Called\"\n );\n}\n\n/**\n * Type guard for Balances.Transfer events\n *\n * @example\n * ```ts\n * for (const event of events) {\n * if (isBalancesTransferEvent(event)) {\n * const { from, to, amount } = event.event.value.value;\n * }\n * }\n * ```\n */\nexport function isBalancesTransferEvent(\n event: ChainEventRecord\n): event is BalancesTransferChainEvent {\n return (\n event.event?.type === \"Balances\" &&\n event.event?.value?.type === \"Transfer\"\n );\n}\n\n/**\n * Check if event is in ApplyExtrinsic phase\n *\n * @example\n * ```ts\n * for (const event of events) {\n * if (isApplyExtrinsicPhase(event)) {\n * const extrinsicIndex = event.phase.value;\n * }\n * }\n * ```\n */\nexport function isApplyExtrinsicPhase(\n event: ChainEventRecord\n): event is ChainEventRecord & { phase: { type: \"ApplyExtrinsic\"; value: number } } {\n return event.phase?.type === \"ApplyExtrinsic\" && typeof event.phase.value === \"number\";\n}\n\n/**\n * Extract contract emitted data with proper typing\n *\n * Handles both Uint8Array and Binary object formats.\n *\n * @param event - Chain event record\n * @returns Extracted data or null if not a ContractEmitted event\n */\nexport function extractContractEmittedData(\n event: ChainEventRecord\n): {\n contract: Uint8Array;\n data: Uint8Array;\n topics: Uint8Array[];\n} | null {\n if (!isContractEmittedEvent(event)) {\n return null;\n }\n\n const { contract: contractRaw, data: dataRaw } = event.event.value.value;\n\n // Handle contract address\n let contract: Uint8Array;\n if (contractRaw instanceof Uint8Array) {\n contract = contractRaw;\n } else if (typeof contractRaw === \"string\") {\n // SS58 string - caller should decode if needed\n // Return empty for now, let caller handle SS58 decoding\n contract = new Uint8Array(0);\n } else {\n return null;\n }\n\n // Handle data (Binary or Uint8Array)\n let data: Uint8Array;\n if (dataRaw instanceof Uint8Array) {\n data = dataRaw;\n } else if (\n dataRaw &&\n typeof dataRaw === \"object\" &&\n \"asBytes\" in dataRaw &&\n typeof dataRaw.asBytes === \"function\"\n ) {\n data = dataRaw.asBytes();\n } else {\n return null;\n }\n\n // Extract topics\n const topics: Uint8Array[] = [];\n if (event.topics && Array.isArray(event.topics)) {\n for (const topic of event.topics) {\n if (topic instanceof Uint8Array) {\n topics.push(topic);\n } else if (\n topic &&\n typeof topic === \"object\" &&\n \"asBytes\" in topic &&\n typeof topic.asBytes === \"function\"\n ) {\n topics.push(topic.asBytes());\n }\n }\n }\n\n return { contract, data, topics };\n}\n","/**\n * Internal codec building utilities\n *\n * This module provides lower-level codec building from metadata type IDs.\n */\nimport {\n u8,\n u16,\n u32,\n u64,\n u128,\n i8,\n i16,\n i32,\n i64,\n i128,\n bool,\n str,\n Bytes,\n Vector,\n Tuple,\n Struct,\n Variant,\n _void,\n Option,\n AccountId,\n type Codec,\n} from \"@polkadot-api/substrate-bindings\";\nimport type { InkMetadata } from \"@polkadot-api/ink-contracts\";\nimport { D9_SS58_PREFIX } from \"@d9-network/spec\";\n\n// Use 'any' for dynamic codec building\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyCodec = Codec<any>;\ntype CodecCache = Map<number, AnyCodec>;\n\ninterface TypeDef {\n primitive?: string;\n composite?: {\n fields: Array<{\n name?: string;\n type: number;\n typeName?: string;\n }>;\n };\n variant?: {\n variants: Array<{\n name: string;\n index: number;\n fields: Array<{\n name?: string;\n type: number;\n typeName?: string;\n }>;\n }>;\n };\n sequence?: {\n type: number;\n };\n array?: {\n len: number;\n type: number;\n };\n tuple?: number[];\n}\n\ninterface TypeEntry {\n id: number;\n type: {\n def: TypeDef;\n path?: string[];\n params?: Array<{\n name: string;\n type?: number;\n }>;\n };\n}\n\n/**\n * Build a SCALE codec from ink metadata type definition\n */\nfunction buildCodecFromTypeInternal(\n typeId: number,\n types: TypeEntry[],\n cache: CodecCache,\n): AnyCodec {\n const cached = cache.get(typeId);\n if (cached) return cached;\n\n const typeEntry = types.find((t) => t.id === typeId);\n if (!typeEntry) {\n throw new Error(`Type ${typeId} not found in metadata`);\n }\n\n const def = typeEntry.type.def;\n const path = typeEntry.type.path;\n\n // Handle primitive types\n if (def.primitive) {\n const codec = buildPrimitiveCodec(def.primitive);\n cache.set(typeId, codec);\n return codec;\n }\n\n // Handle special path types\n if (path && path.length > 0) {\n const specialCodec = buildSpecialTypeCodec(path, typeEntry, types, cache);\n if (specialCodec) {\n cache.set(typeId, specialCodec);\n return specialCodec;\n }\n }\n\n // Handle tuple\n if (def.tuple) {\n const codec = buildTupleCodec(def.tuple, types, cache);\n cache.set(typeId, codec);\n return codec;\n }\n\n // Handle sequence\n if (def.sequence) {\n const innerCodec = buildCodecFromTypeInternal(def.sequence.type, types, cache);\n const codec = Vector(innerCodec);\n cache.set(typeId, codec);\n return codec;\n }\n\n // Handle array\n if (def.array) {\n const innerCodec = buildCodecFromTypeInternal(def.array.type, types, cache);\n if (def.array.type === findPrimitiveTypeId(types, \"u8\")) {\n const codec = Bytes(def.array.len);\n cache.set(typeId, codec);\n return codec;\n }\n const codec = Vector(innerCodec, def.array.len);\n cache.set(typeId, codec);\n return codec;\n }\n\n // Handle composite\n if (def.composite) {\n const codec = buildCompositeCodec(def.composite, types, cache);\n cache.set(typeId, codec);\n return codec;\n }\n\n // Handle variant\n if (def.variant) {\n const codec = buildVariantCodec(def.variant, path, types, cache);\n cache.set(typeId, codec);\n return codec;\n }\n\n throw new Error(`Unknown type definition for type ${typeId}`);\n}\n\nfunction buildPrimitiveCodec(primitive: string): AnyCodec {\n switch (primitive) {\n case \"u8\":\n return u8;\n case \"u16\":\n return u16;\n case \"u32\":\n return u32;\n case \"u64\":\n return u64;\n case \"u128\":\n return u128;\n case \"i8\":\n return i8;\n case \"i16\":\n return i16;\n case \"i32\":\n return i32;\n case \"i64\":\n return i64;\n case \"i128\":\n return i128;\n case \"bool\":\n return bool;\n case \"str\":\n return str;\n default:\n throw new Error(`Unknown primitive type: ${primitive}`);\n }\n}\n\nfunction buildSpecialTypeCodec(\n path: string[],\n typeEntry: TypeEntry,\n types: TypeEntry[],\n cache: CodecCache,\n): AnyCodec | null {\n const fullPath = path.join(\"::\");\n\n if (fullPath.includes(\"AccountId\")) {\n return AccountId(D9_SS58_PREFIX);\n }\n\n if (path[0] === \"Option\") {\n const params = typeEntry.type.params;\n if (params && params.length > 0 && params[0]?.type !== undefined) {\n const innerCodec = buildCodecFromTypeInternal(params[0].type, types, cache);\n return Option(innerCodec);\n }\n }\n\n if (path[0] === \"Result\") {\n const params = typeEntry.type.params;\n if (params && params.length >= 2) {\n const okTypeId = params[0]?.type;\n const errTypeId = params[1]?.type;\n if (okTypeId !== undefined && errTypeId !== undefined) {\n const okCodec = buildCodecFromTypeInternal(okTypeId, types, cache);\n const errCodec = buildCodecFromTypeInternal(errTypeId, types, cache);\n return Variant({ Ok: okCodec, Err: errCodec }, [0, 1]);\n }\n }\n }\n\n return null;\n}\n\nfunction buildTupleCodec(tupleTypes: number[], types: TypeEntry[], cache: CodecCache): AnyCodec {\n if (tupleTypes.length === 0) return _void;\n\n const innerCodecs = tupleTypes.map((t) => buildCodecFromTypeInternal(t, types, cache));\n\n switch (innerCodecs.length) {\n case 1:\n return Tuple(innerCodecs[0]!);\n case 2:\n return Tuple(innerCodecs[0]!, innerCodecs[1]!);\n case 3:\n return Tuple(innerCodecs[0]!, innerCodecs[1]!, innerCodecs[2]!);\n case 4:\n return Tuple(innerCodecs[0]!, innerCodecs[1]!, innerCodecs[2]!, innerCodecs[3]!);\n default:\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (Tuple as any)(...innerCodecs);\n }\n}\n\nfunction buildCompositeCodec(\n composite: NonNullable<TypeDef[\"composite\"]>,\n types: TypeEntry[],\n cache: CodecCache,\n): AnyCodec {\n const fields = composite.fields;\n\n if (fields.length === 1 && !fields[0]?.name) {\n return buildCodecFromTypeInternal(fields[0]!.type, types, cache);\n }\n\n const structDef: Record<string, AnyCodec> = {};\n for (const field of fields) {\n const fieldName = field.name || `field${fields.indexOf(field)}`;\n structDef[fieldName] = buildCodecFromTypeInternal(field.type, types, cache);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return Struct(structDef as any);\n}\n\nfunction buildVariantCodec(\n variant: NonNullable<TypeDef[\"variant\"]>,\n path: string[] | undefined,\n types: TypeEntry[],\n cache: CodecCache,\n): AnyCodec {\n const variants = variant.variants;\n const isLangError = path?.includes(\"LangError\");\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const variantDef: Record<string, any> = {};\n const indices: number[] = [];\n\n if (isLangError && !variants.some((v) => v.index === 0)) {\n variantDef[\"_Placeholder\"] = _void;\n indices.push(0);\n }\n\n for (const v of variants) {\n let fieldCodec: AnyCodec;\n const fields = v.fields ?? [];\n\n if (fields.length === 0) {\n fieldCodec = _void;\n } else if (fields.length === 1 && !fields[0]?.name) {\n fieldCodec = buildCodecFromTypeInternal(fields[0]!.type, types, cache);\n } else {\n const structDef: Record<string, AnyCodec> = {};\n for (const field of fields) {\n const fieldName = field.name || `field${fields.indexOf(field)}`;\n structDef[fieldName] = buildCodecFromTypeInternal(field.type, types, cache);\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n fieldCodec = Struct(structDef as any);\n }\n\n variantDef[v.name] = fieldCodec;\n indices.push(v.index);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return Variant(variantDef as any, indices as any);\n}\n\nfunction findPrimitiveTypeId(types: TypeEntry[], primitive: string): number {\n const entry = types.find((t) => t.type.def.primitive === primitive);\n return entry?.id ?? -1;\n}\n\n/**\n * Build a codec for a specific type ID from ink metadata\n *\n * @param metadata - The ink contract metadata\n * @param typeId - The type ID to build codec for\n * @returns A codec with encode/decode methods\n */\nexport function buildCodecFromMetadata(\n metadata: InkMetadata,\n typeId: number,\n): { enc: (value: unknown) => Uint8Array; dec: (data: Uint8Array) => unknown } {\n const types = metadata.types as TypeEntry[];\n const cache: CodecCache = new Map();\n\n const codec = buildCodecFromTypeInternal(typeId, types, cache);\n return codec;\n}\n\n/**\n * Build a struct codec for message arguments\n *\n * @param metadata - The ink contract metadata\n * @param args - The argument definitions\n * @returns A struct codec\n */\nexport function buildArgsCodec(\n metadata: InkMetadata,\n args: Array<{ label: string; type: { type: number } }>,\n): { enc: (value: unknown) => Uint8Array; dec: (data: Uint8Array) => unknown } {\n if (args.length === 0) {\n return {\n enc: () => new Uint8Array(0),\n dec: () => ({}),\n };\n }\n\n const types = metadata.types as TypeEntry[];\n const cache: CodecCache = new Map();\n\n const structDef: Record<string, AnyCodec> = {};\n for (const arg of args) {\n structDef[arg.label] = buildCodecFromTypeInternal(arg.type.type, types, cache);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const codec = Struct(structDef as any) as any;\n return {\n enc: (value: unknown) => codec.enc(value),\n dec: (data: Uint8Array) => codec.dec(data),\n };\n}\n","/**\n * Call parsing for ink! contracts\n *\n * Decodes contract call data (selector + args) into type-safe call objects.\n */\nimport type {\n InkMetadata,\n InkDescriptors,\n InkStorageDescriptor,\n InkCallableDescriptor,\n Event as InkEvent,\n} from \"@polkadot-api/ink-contracts\";\nimport type {\n TypedContractCall,\n RawContractCall,\n CallFilterOptions,\n MessageInfo,\n ExtractMessageLabels,\n} from \"./call-types\";\nimport { buildArgsCodec } from \"./codec-builder-internal\";\n\n/**\n * Build argument decoders for all messages in the metadata\n */\nfunction buildAllMessageDecodersFromMetadata(\n metadata: InkMetadata,\n): Map<string, { selector: Uint8Array; decoder: (data: Uint8Array) => unknown }> {\n const decoders = new Map<\n string,\n { selector: Uint8Array; decoder: (data: Uint8Array) => unknown }\n >();\n\n const messages = metadata.spec.messages as Array<{\n label: string;\n selector: string; // hex string like \"0xdb20f9f5\"\n args: Array<{\n label: string;\n type: { type: number };\n }>;\n }>;\n\n for (const message of messages) {\n try {\n // Parse selector from hex string\n const selectorHex = message.selector.startsWith(\"0x\")\n ? message.selector.slice(2)\n : message.selector;\n const selector = new Uint8Array(\n selectorHex.match(/.{1,2}/g)!.map((byte) => parseInt(byte, 16)),\n );\n\n // Build struct decoder for message arguments\n const argsCodec = buildArgsCodec(metadata, message.args);\n const decoder = (data: Uint8Array) => argsCodec.dec(data);\n\n decoders.set(message.label, { selector, decoder });\n } catch (error) {\n console.warn(`Failed to build decoder for message \"${message.label}\":`, error);\n }\n }\n\n return decoders;\n}\n\n/**\n * Type-safe call parser for a specific contract\n *\n * @typeParam S - The storage descriptor type\n * @typeParam M - The InkCallableDescriptor type (message definitions)\n * @typeParam C - The constructors descriptor type\n * @typeParam E - The events Enum type\n */\nexport class ContractCallParser<\n S extends InkStorageDescriptor = InkStorageDescriptor,\n M extends InkCallableDescriptor = InkCallableDescriptor,\n C extends InkCallableDescriptor = InkCallableDescriptor,\n E extends InkEvent = InkEvent,\n> {\n private messageDecoders: Map<\n string,\n { selector: Uint8Array; decoder: (data: Uint8Array) => unknown }\n >;\n private selectorToLabel: Map<string, string>;\n private metadata: InkMetadata;\n\n constructor(descriptor: InkDescriptors<S, M, C, E>) {\n if (!descriptor.metadata) {\n throw new Error(\"Contract descriptor must include metadata\");\n }\n this.metadata = descriptor.metadata;\n this.messageDecoders = buildAllMessageDecodersFromMetadata(this.metadata);\n\n // Build reverse lookup: selector hex -> label\n this.selectorToLabel = new Map();\n for (const [label, { selector }] of this.messageDecoders) {\n const selectorHex = Array.from(selector)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n this.selectorToLabel.set(selectorHex, label);\n }\n }\n\n /**\n * Parse raw call data into a type-safe contract call\n *\n * @param callData - The raw call data (selector + encoded args) or RawContractCall\n * @returns Parsed call or null if cannot parse\n *\n * @example\n * ```ts\n * const call = parser.parseCall(callData);\n * if (call?.type === \"PSP22::transfer\") {\n * // call.args is typed as { to: SS58String; value: bigint; data: Uint8Array }\n * console.log(call.args.to);\n * }\n * ```\n */\n parseCall(callData: Uint8Array | RawContractCall): TypedContractCall<M> | null {\n const data = callData instanceof Uint8Array ? callData : callData.data;\n const raw: RawContractCall = callData instanceof Uint8Array ? { data: callData } : callData;\n\n if (data.length < 4) {\n return null; // Need at least 4 bytes for selector\n }\n\n // Extract selector (first 4 bytes)\n const selector = data.slice(0, 4);\n const selectorHex = Array.from(selector)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n\n // Find message by selector\n const label = this.selectorToLabel.get(selectorHex);\n if (!label) {\n return null;\n }\n\n const messageInfo = this.messageDecoders.get(label);\n if (!messageInfo) {\n return null;\n }\n\n // Decode arguments (data after selector)\n const argsData = data.slice(4);\n try {\n const args = messageInfo.decoder(argsData);\n\n return {\n type: label,\n args,\n selector,\n raw,\n } as TypedContractCall<M>;\n } catch (error) {\n console.warn(`Failed to decode call \"${label}\":`, error);\n return null;\n }\n }\n\n /**\n * Parse multiple calls and optionally filter by message labels\n *\n * @param calls - Array of raw call data\n * @param options - Filter options\n * @returns Array of parsed calls\n */\n parseCalls(\n calls: Array<Uint8Array | RawContractCall>,\n options?: CallFilterOptions,\n ): TypedContractCall<M>[] {\n const results: TypedContractCall<M>[] = [];\n\n for (const call of calls) {\n const parsed = this.parseCall(call);\n if (!parsed) continue;\n\n // Apply label filter\n if (options?.messageLabels && !options.messageLabels.includes(parsed.type)) {\n continue;\n }\n\n results.push(parsed);\n }\n\n return results;\n }\n\n /**\n * Filter calls by specific type with proper type narrowing\n *\n * This method provides better type safety than parseCalls with messageLabels\n * because TypeScript can narrow the return type to only the specified call type.\n *\n * @param calls - Array of raw call data\n * @param label - The message label to filter by\n * @returns Array of calls narrowed to the specific type\n *\n * @example\n * ```ts\n * const transfers = parser.filterByType(callDataArray, \"PSP22::transfer\");\n *\n * for (const t of transfers) {\n * // t.args is fully typed as PSP22::transfer args\n * console.log(t.args.to, t.args.value);\n * }\n * ```\n */\n filterByType<L extends string>(\n calls: Array<Uint8Array | RawContractCall>,\n label: L,\n ): Array<TypedContractCall<M> & { type: L }> {\n return this.parseCalls(calls).filter(\n (c): c is TypedContractCall<M> & { type: L } => c.type === label,\n );\n }\n\n /**\n * Get information about a message by label\n */\n getMessageInfo(label: string): MessageInfo | null {\n const info = this.messageDecoders.get(label);\n if (!info) return null;\n\n const messages = this.metadata.spec.messages as Array<{\n label: string;\n selector: string;\n mutates: boolean;\n payable: boolean;\n args: Array<{ label: string; type: { type: number } }>;\n }>;\n\n const message = messages.find((m) => m.label === label);\n if (!message) return null;\n\n return {\n label: message.label,\n selector: info.selector,\n mutates: message.mutates,\n payable: message.payable,\n args: message.args,\n };\n }\n\n /**\n * Get all available message labels\n */\n getMessageLabels(): string[] {\n return Array.from(this.messageDecoders.keys());\n }\n\n /**\n * Check if a selector matches a specific message\n */\n matchesMessage(selector: Uint8Array, label: string): boolean {\n const info = this.messageDecoders.get(label);\n if (!info) return false;\n\n if (selector.length !== info.selector.length) return false;\n\n for (let i = 0; i < selector.length; i++) {\n if (selector[i] !== info.selector[i]) return false;\n }\n\n return true;\n }\n\n /**\n * Get selector for a message label\n *\n * @param label - Message label (e.g., \"PSP22::transfer\")\n * @returns Selector as Uint8Array or null if not found\n *\n * @example\n * ```ts\n * const selector = parser.getSelector(\"PSP22::transfer\");\n * // selector is Uint8Array([0xdb, 0x20, 0xf9, 0xf5])\n * ```\n */\n getSelector(label: string): Uint8Array | null {\n const info = this.messageDecoders.get(label);\n return info?.selector ?? null;\n }\n\n /**\n * Get selector as hex string for a message label\n *\n * @param label - Message label (e.g., \"PSP22::transfer\")\n * @returns Selector hex string (without 0x) or null if not found\n *\n * @example\n * ```ts\n * const selectorHex = parser.getSelectorHex(\"PSP22::transfer\");\n * // selectorHex is \"db20f9f5\"\n * ```\n */\n getSelectorHex(label: string): string | null {\n const selector = this.getSelector(label);\n if (!selector) return null;\n return Array.from(selector)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n }\n\n /**\n * Get the label for a selector\n *\n * @param selector - Selector as Uint8Array or hex string (with or without 0x)\n * @returns Message label or null if not found\n *\n * @example\n * ```ts\n * const label = parser.getLabel(\"db20f9f5\");\n * // label is \"PSP22::transfer\"\n *\n * // Also works with Uint8Array\n * const label2 = parser.getLabel(callData.slice(0, 4));\n * ```\n */\n getLabel(selector: Uint8Array | string): string | null {\n const selectorHex = this.normalizeSelector(selector);\n return this.selectorToLabel.get(selectorHex) ?? null;\n }\n\n /**\n * Get all selector-to-label mappings\n *\n * @returns Map of selector hex (without 0x) -> label\n *\n * @example\n * ```ts\n * const map = parser.getSelectorMap();\n * for (const [selectorHex, label] of map) {\n * console.log(`${selectorHex} -> ${label}`);\n * }\n * ```\n */\n getSelectorMap(): Map<string, string> {\n return new Map(this.selectorToLabel);\n }\n\n /**\n * Check if a selector exists in this contract\n *\n * @param selector - Selector to check (Uint8Array or hex string)\n * @returns True if selector is valid for this contract\n *\n * @example\n * ```ts\n * if (parser.hasSelector(\"db20f9f5\")) {\n * // This selector is valid for this contract\n * }\n * ```\n */\n hasSelector(selector: Uint8Array | string): boolean {\n const selectorHex = this.normalizeSelector(selector);\n return this.selectorToLabel.has(selectorHex);\n }\n\n /**\n * Normalize selector to hex string (without 0x prefix)\n */\n private normalizeSelector(selector: Uint8Array | string): string {\n if (selector instanceof Uint8Array) {\n return Array.from(selector)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n }\n // Remove 0x prefix if present and lowercase\n return selector.startsWith(\"0x\")\n ? selector.slice(2).toLowerCase()\n : selector.toLowerCase();\n }\n}\n\n/**\n * Type guard for narrowing call types\n *\n * Use this function when you have a `TypedContractCall` and need to\n * narrow it to a specific call type. This is useful when the type\n * information is lost (e.g., after serialization or in generic functions).\n *\n * @typeParam M - The InkCallableDescriptor type (message definitions)\n * @typeParam L - The specific message label to check\n * @param call - The call to check\n * @param label - The message label to match\n * @returns True if the call type matches the label\n *\n * @example\n * ```ts\n * const call = parser.parseCall(callData);\n *\n * if (call && isCallType(call, \"PSP22::transfer\")) {\n * // TypeScript knows call.args is transfer args\n * console.log(call.args.to);\n * console.log(call.args.value);\n * }\n * ```\n */\nexport function isCallType<M extends InkCallableDescriptor, L extends ExtractMessageLabels<M>>(\n call: TypedContractCall<M>,\n label: L,\n): call is Extract<TypedContractCall<M>, { type: L }> {\n return call.type === label;\n}\n","/**\n * High-level extrinsic parsing for indexers and explorers\n *\n * Provides a simplified API for extracting contract calls from blockchain extrinsics,\n * eliminating the need for manual hex string manipulation and selector matching.\n */\n\nimport type { SS58String } from \"polkadot-api\";\nimport type {\n InkDescriptors,\n InkStorageDescriptor,\n InkCallableDescriptor,\n Event as InkEvent,\n} from \"@polkadot-api/ink-contracts\";\nimport { toD9Address } from \"@d9-network/spec\";\nimport { ContractCallParser } from \"./calls\";\nimport type { TypedContractCall, RawContractCall } from \"./call-types\";\n\n/**\n * Raw extrinsic data that may contain a contract call\n *\n * This interface is designed to work with various extrinsic formats\n * from different data sources (polkadot-api, subsquid, etc.)\n */\nexport interface RawExtrinsic {\n /** Extrinsic hash */\n hash?: string;\n /** Block number */\n blockNumber?: number;\n /** Block hash */\n blockHash?: string;\n /** Extrinsic index in block */\n index?: number;\n /** Signer address */\n signer?: SS58String | string;\n /** The call structure - can be nested */\n call?: ExtrinsicCall;\n}\n\n/**\n * Extrinsic call structure (matches polkadot-api format)\n */\nexport interface ExtrinsicCall {\n type?: string;\n value?: {\n type?: string;\n value?: ContractsCallValue;\n };\n}\n\n/**\n * Contracts.call extrinsic value\n */\nexport interface ContractsCallValue {\n /** Contract address (SS58 or other format) */\n dest?: SS58String | { type: string; value: SS58String } | { Id: SS58String };\n /** Value transferred with the call */\n value?: bigint | string | number;\n /** Call data (Binary or Uint8Array) */\n data?: Uint8Array | { asBytes?: () => Uint8Array };\n /** Gas limit */\n gas_limit?: unknown;\n gasLimit?: unknown;\n /** Storage deposit limit */\n storage_deposit_limit?: unknown;\n storageDepositLimit?: unknown;\n}\n\n/**\n * Parsed contract extrinsic result\n */\nexport interface ParsedContractExtrinsic<M extends InkCallableDescriptor = InkCallableDescriptor> {\n /** The parsed contract call */\n call: TypedContractCall<M>;\n /** Extrinsic metadata */\n extrinsic: {\n /** Extrinsic hash */\n hash: string;\n /** Block number */\n blockNumber: number;\n /** Block hash */\n blockHash: string;\n /** Extrinsic index in block */\n index: number;\n /** Signer address */\n signer: string;\n };\n /** Contract address being called */\n contractAddress: SS58String;\n /** Value transferred with call */\n value: bigint;\n}\n\n/**\n * Extrinsic parser options\n */\nexport interface ExtrinsicParserOptions {\n /** Contract addresses to filter for (if not provided, parses all contract calls) */\n contractAddresses?: SS58String[];\n /** Message labels to filter for */\n messageLabels?: string[];\n}\n\n/**\n * Parser for extracting contract calls from extrinsics\n *\n * This class provides a high-level API for indexers to parse contract\n * interactions from blockchain extrinsics without manual hex manipulation.\n *\n * @typeParam S - The storage descriptor type\n * @typeParam M - The InkCallableDescriptor type (message definitions)\n * @typeParam C - The constructors descriptor type\n * @typeParam E - The events type\n *\n * @example\n * ```ts\n * import { ExtrinsicParser } from \"@d9-network/ink\";\n * import { contracts } from \"@d9-network/spec\";\n *\n * // Create parser for USDT contract\n * const parser = new ExtrinsicParser(contracts.usdt, {\n * contractAddresses: [USDT_ADDRESS],\n * });\n *\n * // Parse extrinsics from a block\n * for (const extrinsic of block.extrinsics) {\n * const parsed = parser.parseExtrinsic(extrinsic);\n * if (parsed?.call.type === \"PSP22::transfer\") {\n * console.log(`Transfer: ${parsed.call.args.value} to ${parsed.call.args.to}`);\n * }\n * }\n * ```\n */\nexport class ExtrinsicParser<\n S extends InkStorageDescriptor = InkStorageDescriptor,\n M extends InkCallableDescriptor = InkCallableDescriptor,\n C extends InkCallableDescriptor = InkCallableDescriptor,\n E extends InkEvent = InkEvent,\n> {\n private callParser: ContractCallParser<S, M, C, E>;\n private options: ExtrinsicParserOptions;\n\n constructor(\n descriptor: InkDescriptors<S, M, C, E>,\n options: ExtrinsicParserOptions = {}\n ) {\n this.callParser = new ContractCallParser(descriptor);\n this.options = options;\n }\n\n /**\n * Parse a single extrinsic for contract calls\n *\n * @param extrinsic - Raw extrinsic data\n * @returns Parsed contract extrinsic or null if not a valid contract call\n */\n parseExtrinsic(extrinsic: RawExtrinsic): ParsedContractExtrinsic<M> | null {\n // Check if this is a contract call\n if (!this.isContractCall(extrinsic)) {\n return null;\n }\n\n // Extract call data\n const extracted = this.extractCallData(extrinsic);\n if (!extracted) {\n return null;\n }\n\n const { data, contractAddress, value } = extracted;\n\n // Filter by contract address if specified\n if (\n this.options.contractAddresses &&\n this.options.contractAddresses.length > 0 &&\n !this.options.contractAddresses.includes(contractAddress)\n ) {\n return null;\n }\n\n // Parse the call\n const raw: RawContractCall = {\n data,\n contractAddress,\n txHash: extrinsic.hash,\n blockNumber: extrinsic.blockNumber,\n blockHash: extrinsic.blockHash,\n };\n\n const call = this.callParser.parseCall(raw);\n if (!call) {\n return null;\n }\n\n // Filter by message label if specified\n if (\n this.options.messageLabels &&\n this.options.messageLabels.length > 0 &&\n !this.options.messageLabels.includes(call.type)\n ) {\n return null;\n }\n\n // Convert signer to D9 format if it looks like an SS58 address\n let signer = String(extrinsic.signer ?? \"\");\n if (signer && signer.length >= 32) {\n try {\n signer = toD9Address(signer as SS58String);\n } catch {\n // Keep original if conversion fails\n }\n }\n\n return {\n call,\n extrinsic: {\n hash: extrinsic.hash ?? \"\",\n blockNumber: extrinsic.blockNumber ?? 0,\n blockHash: extrinsic.blockHash ?? \"\",\n index: extrinsic.index ?? 0,\n signer,\n },\n contractAddress,\n value,\n };\n }\n\n /**\n * Parse multiple extrinsics and filter contract calls\n *\n * @param extrinsics - Array of raw extrinsics\n * @returns Array of parsed contract extrinsics\n */\n parseExtrinsics(extrinsics: RawExtrinsic[]): ParsedContractExtrinsic<M>[] {\n const results: ParsedContractExtrinsic<M>[] = [];\n\n for (const extrinsic of extrinsics) {\n const parsed = this.parseExtrinsic(extrinsic);\n if (parsed) {\n results.push(parsed);\n }\n }\n\n return results;\n }\n\n /**\n * Filter extrinsics by message type with type narrowing\n *\n * @param extrinsics - Array of raw extrinsics\n * @param label - Message label to filter by\n * @returns Filtered and typed extrinsics\n *\n * @example\n * ```ts\n * const transfers = parser.filterByMessageType(extrinsics, \"PSP22::transfer\");\n * for (const tx of transfers) {\n * // tx.call.args is fully typed\n * console.log(tx.call.args.to, tx.call.args.value);\n * }\n * ```\n */\n filterByMessageType<L extends string>(\n extrinsics: RawExtrinsic[],\n label: L\n ): Array<ParsedContractExtrinsic<M> & { call: { type: L } }> {\n return this.parseExtrinsics(extrinsics).filter(\n (tx): tx is ParsedContractExtrinsic<M> & { call: { type: L } } =>\n tx.call.type === label\n );\n }\n\n /**\n * Check if an extrinsic is a contract call\n *\n * @param extrinsic - Raw extrinsic\n * @returns True if this is a Contracts.call extrinsic\n */\n isContractCall(extrinsic: RawExtrinsic): boolean {\n const call = extrinsic.call;\n if (!call) return false;\n\n // Check for Contracts pallet\n if (call.type === \"Contracts\") {\n const innerCall = call.value;\n // Check for call, call_old_weight, etc.\n return (\n innerCall?.type === \"call\" ||\n innerCall?.type === \"call_old_weight\" ||\n innerCall?.type === \"instantiate_with_code\" ||\n innerCall?.type === \"instantiate\"\n );\n }\n\n return false;\n }\n\n /**\n * Extract call data from an extrinsic structure\n *\n * Handles various extrinsic formats (polkadot-api, subsquid, etc.)\n *\n * @param extrinsic - Raw extrinsic\n * @returns Extracted call data or null\n */\n extractCallData(extrinsic: RawExtrinsic): {\n data: Uint8Array;\n contractAddress: SS58String;\n value: bigint;\n } | null {\n const call = extrinsic.call;\n if (!call?.value?.value) return null;\n\n const contractsCall = call.value.value;\n\n // Extract contract address\n const contractAddress = this.extractContractAddress(contractsCall.dest);\n if (!contractAddress) return null;\n\n // Extract call data\n const data = this.extractBytes(contractsCall.data);\n if (!data || data.length < 4) return null;\n\n // Extract value\n const value = this.extractBigInt(contractsCall.value);\n\n return {\n data,\n contractAddress,\n value,\n };\n }\n\n /**\n * Get access to the underlying call parser\n */\n getCallParser(): ContractCallParser<S, M, C, E> {\n return this.callParser;\n }\n\n // Private helpers\n\n private extractContractAddress(\n dest: ContractsCallValue[\"dest\"]\n ): SS58String | null {\n if (!dest) return null;\n\n let address: SS58String | null = null;\n\n // Direct SS58 string\n if (typeof dest === \"string\") {\n address = dest as SS58String;\n }\n // { type: \"Id\", value: address } format\n else if (typeof dest === \"object\" && \"type\" in dest && \"value\" in dest) {\n address = dest.value as SS58String;\n }\n // { Id: address } format (subsquid)\n else if (typeof dest === \"object\" && \"Id\" in dest) {\n address = (dest as { Id: SS58String }).Id;\n }\n\n // Always return D9-formatted address\n return address ? toD9Address(address) : null;\n }\n\n private extractBytes(\n data: ContractsCallValue[\"data\"]\n ): Uint8Array | null {\n if (!data) return null;\n\n // Direct Uint8Array\n if (data instanceof Uint8Array) {\n return data;\n }\n\n // Binary object with asBytes()\n if (\n typeof data === \"object\" &&\n \"asBytes\" in data &&\n typeof data.asBytes === \"function\"\n ) {\n return data.asBytes();\n }\n\n return null;\n }\n\n private extractBigInt(value: ContractsCallValue[\"value\"]): bigint {\n if (value === undefined || value === null) return 0n;\n\n if (typeof value === \"bigint\") return value;\n if (typeof value === \"number\") return BigInt(value);\n if (typeof value === \"string\") {\n try {\n return BigInt(value);\n } catch {\n return 0n;\n }\n }\n\n return 0n;\n }\n}\n\n/**\n * Create an extrinsic parser from a contract descriptor\n *\n * @param descriptor - Contract descriptor\n * @param options - Parser options\n * @returns ExtrinsicParser instance\n *\n * @example\n * ```ts\n * const parser = createExtrinsicParser(contracts.usdt, {\n * contractAddresses: [USDT_ADDRESS],\n * });\n * ```\n */\nexport function createExtrinsicParser<\n S extends InkStorageDescriptor,\n M extends InkCallableDescriptor,\n C extends InkCallableDescriptor,\n E extends InkEvent,\n>(\n descriptor: InkDescriptors<S, M, C, E>,\n options?: ExtrinsicParserOptions\n): ExtrinsicParser<S, M, C, E> {\n return new ExtrinsicParser(descriptor, options);\n}\n","/**\n * Fee estimation utilities for ink! smart contracts\n */\n\nimport type { GasInfo } from \"../decode\";\n\n/**\n * Gas weight representation\n */\nexport interface GasWeight {\n refTime: bigint;\n proofSize: bigint;\n}\n\n/**\n * Estimated transaction cost breakdown\n */\nexport interface EstimatedCost {\n /** Cost from gas consumption */\n gasCost: bigint;\n /** Storage deposit (may be refunded) */\n storageDeposit: bigint;\n /** Total estimated cost (gas + storage) */\n total: bigint;\n}\n\n/**\n * Formatted gas information for display\n */\nexport interface FormattedGasInfo {\n /** Human-readable ref_time */\n refTime: string;\n /** Human-readable proof_size */\n proofSize: string;\n}\n\n// D9 network weight-to-fee constants\n// These should match the chain's WeightToFee implementation\nconst WEIGHT_REF_TIME_PER_SECOND = 1_000_000_000_000n; // 1 trillion\nconst WEIGHT_FEE_COEFFICIENT = 1n; // Adjust based on chain config\n\n/**\n * Estimate the transaction cost from gas info and storage deposit\n *\n * Note: This is an approximation. Actual fees depend on chain configuration\n * and may vary slightly.\n *\n * @param gasInfo - Gas information from contract query\n * @param storageDeposit - Storage deposit amount (positive for charge, negative for refund)\n * @returns Estimated cost breakdown\n *\n * @example\n * ```typescript\n * const result = await contract.query(\"PSP22::transfer\", { origin, args });\n * if (result.success) {\n * const cost = estimateTransactionCost(\n * { gasConsumed: result.gasConsumed, gasRequired: result.gasRequired },\n * result.storageDeposit\n * );\n * console.log(`Estimated cost: ${formatBalance(cost.total, { decimals: 12 })} D9`);\n * }\n * ```\n */\nexport function estimateTransactionCost(gasInfo: GasInfo, storageDeposit: bigint): EstimatedCost {\n // Use gasRequired for estimation as it's the gas that will be charged\n const { gasRequired } = gasInfo;\n\n // Simple weight-to-fee conversion\n // In production, this should match the chain's actual WeightToFee implementation\n const gasCost =\n (gasRequired.refTime * WEIGHT_FEE_COEFFICIENT) / WEIGHT_REF_TIME_PER_SECOND +\n gasRequired.proofSize;\n\n // Storage deposit is additional (may be refunded later)\n const effectiveStorageDeposit = storageDeposit > 0n ? storageDeposit : 0n;\n\n return {\n gasCost,\n storageDeposit: effectiveStorageDeposit,\n total: gasCost + effectiveStorageDeposit,\n };\n}\n\n/**\n * Format gas information for human-readable display\n *\n * @param gasInfo - Gas information from contract query\n * @returns Formatted strings for ref_time and proof_size\n *\n * @example\n * ```typescript\n * const formatted = formatGasInfo(result.gasRequired);\n * console.log(`Gas: refTime=${formatted.refTime}, proofSize=${formatted.proofSize}`);\n * ```\n */\nexport function formatGasInfo(gasInfo: GasInfo[\"gasRequired\"]): FormattedGasInfo {\n return {\n refTime: formatWeight(gasInfo.refTime),\n proofSize: formatWeight(gasInfo.proofSize),\n };\n}\n\n/**\n * Format a single weight value with appropriate units\n */\nfunction formatWeight(weight: bigint): string {\n if (weight >= 1_000_000_000_000n) {\n return `${(Number(weight) / 1_000_000_000_000).toFixed(2)}T`;\n }\n if (weight >= 1_000_000_000n) {\n return `${(Number(weight) / 1_000_000_000).toFixed(2)}G`;\n }\n if (weight >= 1_000_000n) {\n return `${(Number(weight) / 1_000_000).toFixed(2)}M`;\n }\n if (weight >= 1_000n) {\n return `${(Number(weight) / 1_000).toFixed(2)}K`;\n }\n return weight.toString();\n}\n\n/**\n * Apply a safety margin to gas limits\n *\n * It's recommended to add a small margin to gas estimates to account for\n * slight variations in execution. 10% (multiplier = 1.1) is a common choice.\n *\n * @param gas - The gas weight to adjust\n * @param multiplier - The multiplier to apply (default: 1.1 for 10% margin)\n * @returns Adjusted gas weight with margin applied\n *\n * @example\n * ```typescript\n * const result = await contract.query(\"PSP22::transfer\", { origin, args });\n * if (result.success) {\n * // Add 10% safety margin\n * const safeGas = applyGasMargin(result.gasRequired, 1.1);\n * await contract.send(\"PSP22::transfer\", {\n * origin,\n * args,\n * gasLimit: safeGas,\n * });\n * }\n * ```\n */\nexport function applyGasMargin(gas: GasWeight, multiplier = 1.1): GasWeight {\n if (multiplier <= 0) {\n throw new Error(\"Multiplier must be positive\");\n }\n\n // Convert multiplier to basis points for precise bigint math\n // e.g., 1.1 -> 11000, 1.15 -> 11500\n const basisPoints = BigInt(Math.round(multiplier * 10000));\n\n return {\n refTime: (gas.refTime * basisPoints) / 10000n,\n proofSize: (gas.proofSize * basisPoints) / 10000n,\n };\n}\n\n/**\n * Compare two gas weights\n *\n * @param a - First gas weight\n * @param b - Second gas weight\n * @returns -1 if a < b, 0 if equal, 1 if a > b (compares refTime first, then proofSize)\n */\nexport function compareGasWeight(a: GasWeight, b: GasWeight): -1 | 0 | 1 {\n if (a.refTime < b.refTime) return -1;\n if (a.refTime > b.refTime) return 1;\n if (a.proofSize < b.proofSize) return -1;\n if (a.proofSize > b.proofSize) return 1;\n return 0;\n}\n\n/**\n * Check if gas weight exceeds a limit\n *\n * @param gas - The gas to check\n * @param limit - The limit to compare against\n * @returns True if gas exceeds the limit in either dimension\n */\nexport function gasExceedsLimit(gas: GasWeight, limit: GasWeight): boolean {\n return gas.refTime > limit.refTime || gas.proofSize > limit.proofSize;\n}\n"],"mappings":"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"}
|