import "../_dnt.polyfills.js"; import { blake2_256, hex } from "../crypto/mod.js" import * as $ from "../deps/scale.js" import { concat } from "../deps/std/bytes.js" import { Signer, SignerError } from "../frame_metadata/Extrinsic.js" import { is, Rune, RunicArgs, ValueRune } from "../rune/mod.js" import { Chain, ChainRune } from "./ChainRune.js" import { CodecRune } from "./CodecRune.js" import { PatternRune } from "./PatternRune.js" import { SignedExtrinsicRune } from "./SignedExtrinsicRune.js" export interface ExtrinsicSender { address: Chain.Address sign: Signer } export function ExtrinsicSender( extrinsicSender: RunicArgs>, ): Rune, RunicArgs.U> { return Rune.object(RunicArgs.resolve(extrinsicSender)) } export interface SignatureData { sender: ExtrinsicSender extra: Chain.Extra additional: Chain.Additional } export type SignatureDataFactory = ( chain: ChainRune, ) => Rune, SU> export class ExtrinsicRune extends PatternRune, C, U> { static readonly PROTOCOL_VERSION = 4 static from( chain: ChainRune, ...args: RunicArgs]> ): ExtrinsicRune> { const [call] = RunicArgs.resolve(args) return call.into(ExtrinsicRune, chain) } static fromBytes( chain: ChainRune, ...args: RunicArgs ) { const $call = chain .into(ValueRune) .access("metadata", "extrinsic", "call") .into(CodecRune) const call = $call.decoded(args[0]) return this.from(chain, call.unsafeAs()) } static fromHex( chain: ChainRune, ...[value]: RunicArgs ) { return this.fromBytes(chain, Rune.resolve(value).map(hex.decode)) } $callData = this.chain.into(ValueRune).access("metadata", "extrinsic", "call").into(CodecRune) callData = this.$callData.encoded(this.unsafeAs()) hex = this.callData.map(hex.encode) $callHash = Rune .fn(($inner: $.Codec) => blake2_256.$hash($inner)) .call(this.$callData.unsafeAs()) .into(CodecRune) callHash = this.$callHash.encoded(this) signed(signatureFactory: SignatureDataFactory) { return this.chain.$extrinsic .encoded(Rune.object({ protocolVersion: ExtrinsicRune.PROTOCOL_VERSION, call: this, signature: signatureFactory(this.chain), })) .throws(is(SignerError)) .into(SignedExtrinsicRune, this.chain) } $dispatchInfo = this.chain.metadata .access("paths", "frame_support::dispatch::DispatchInfo") .into(CodecRune) dispatchInfo() { const extrinsic = this.chain.$extrinsic.encoded(Rune.object({ protocolVersion: ExtrinsicRune.PROTOCOL_VERSION, call: this, })) const arg = Rune .fn(concat) .call(extrinsic, extrinsic.access("length").map((n) => $.u32.encode(n))) .map(hex.encodePrefixed) const info = this.chain.connection .call("state_call", "TransactionPaymentApi_query_info", arg) .map(hex.decode) return this.$dispatchInfo.decoded(info) } $weight = this.chain.metadata.access("paths", "sp_weights::weight_v2::Weight").into(CodecRune) weight() { return this.dispatchInfo().unsafeAs().into(ValueRune).access("weight") } weightRaw() { return this.$weight.encoded(this.weight().unsafeAs()).map(hex.encode) } estimate() { const encoded = this.chain.connection .call("state_call", "TransactionPaymentApi_query_weight_to_fee", this.weightRaw()) .map(hex.decode) return Rune .constant($.u128) .into(CodecRune) .decoded(encoded) } }