supra-l1-sdk-core
Version:
Core of the Supra-L1-SDK
1 lines • 199 kB
Source Map (JSON)
{"version":3,"sources":["../src/account/supra_account.ts","../src/utils/hd-key.ts","../src/utils/misc.ts","../src/utils/hex_string.ts","../src/utils/memoize-decorator.ts","../src/supra_types/index.ts","../src/bcs/index.ts","../src/bcs/consts.ts","../src/bcs/serializer.ts","../src/bcs/deserializer.ts","../src/bcs/helper.ts","../src/supra_types/transaction.ts","../src/supra_types/account_address.ts","../src/supra_types/ed25519.ts","../src/supra_types/multi_ed25519.ts","../src/supra_types/authenticator.ts","../src/supra_types/identifier.ts","../src/supra_types/type_tag.ts","../src/supra_types/abi.ts","../src/supra_types/authentication_key.ts","../src/supra_types/rotation_proof_challenge.ts","../src/transaction_builder/builder.ts","../src/transaction_builder/builder_utils.ts","../src/generated/index.ts","../src/generated/models/AptosErrorCode.ts","../src/generated/models/MoveFunctionVisibility.ts","../src/generated/models/RoleType.ts"],"sourcesContent":["// Copyright © Aptos Foundation\n// SPDX-License-Identifier: Apache-2.0\n\nimport nacl from \"tweetnacl\";\nimport * as bip39 from \"@scure/bip39\";\nimport { bytesToHex } from \"@noble/hashes/utils\";\nimport { sha256 } from \"@noble/hashes/sha256\";\nimport { sha3_256 as sha3Hash } from \"@noble/hashes/sha3\";\nimport { derivePath } from \"../utils/hd-key\";\nimport { HexString, MaybeHexString, Memoize } from \"../utils\";\nimport * as Gen from \"../generated/index\";\nimport {\n AccountAddress,\n AuthenticationKey,\n Ed25519PublicKey,\n} from \"../supra_types\";\nimport { bcsToBytes } from \"../bcs\";\n\nexport interface SupraAccountObject {\n address?: Gen.HexEncodedBytes;\n publicKeyHex?: Gen.HexEncodedBytes;\n privateKeyHex: Gen.HexEncodedBytes;\n}\n\n/**\n * Class for creating and managing Supra account\n */\nexport class SupraAccount {\n /**\n * A private key and public key, associated with the given account\n */\n readonly signingKey: nacl.SignKeyPair;\n\n /**\n * Address associated with the given account\n */\n private readonly accountAddress: HexString;\n\n static fromSupraAccountObject(obj: SupraAccountObject): SupraAccount {\n return new SupraAccount(\n HexString.ensure(obj.privateKeyHex).toUint8Array(),\n obj.address,\n );\n }\n\n /**\n * Check's if the derive path is valid\n */\n static isValidPath(path: string): boolean {\n return /^m\\/44'\\/637'\\/[0-9]+'\\/[0-9]+'\\/[0-9]+'+$/.test(path);\n }\n\n /**\n * Creates new account with bip44 path and mnemonics,\n * @param path. (e.g. m/44'/637'/0'/0'/0')\n * Detailed description: {@link https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki}\n * @param mnemonics.\n * @returns SupraAccount\n */\n static fromDerivePath(path: string, mnemonics: string): SupraAccount {\n if (!SupraAccount.isValidPath(path)) {\n throw new Error(\"Invalid derivation path\");\n }\n\n const normalizeMnemonics = mnemonics\n .trim()\n .split(/\\s+/)\n .map((part) => part.toLowerCase())\n .join(\" \");\n\n const { key } = derivePath(\n path,\n bytesToHex(bip39.mnemonicToSeedSync(normalizeMnemonics)),\n );\n\n return new SupraAccount(key);\n }\n\n /**\n * Creates new account instance. Constructor allows passing in an address,\n * to handle account key rotation, where auth_key != public_key\n * @param privateKeyBytes Private key from which account key pair will be generated.\n * If not specified, new key pair is going to be created.\n * @param address Account address (e.g. 0xe8012714cd17606cee7188a2a365eef3fe760be598750678c8c5954eb548a591).\n * If not specified, a new one will be generated from public key\n */\n constructor(\n privateKeyBytes?: Uint8Array | undefined,\n address?: MaybeHexString,\n ) {\n if (privateKeyBytes) {\n this.signingKey = nacl.sign.keyPair.fromSeed(\n privateKeyBytes.slice(0, 32),\n );\n } else {\n this.signingKey = nacl.sign.keyPair();\n }\n this.accountAddress = HexString.ensure(address || this.authKey().hex());\n }\n\n /**\n * This is the key by which Supra account is referenced.\n * It is the 32-byte of the SHA-3 256 cryptographic hash\n * of the public key(s) concatenated with a signature scheme identifier byte\n * @returns Address associated with the given account\n */\n address(): HexString {\n return this.accountAddress;\n }\n\n /**\n * This key enables account owners to rotate their private key(s)\n * associated with the account without changing the address that hosts their account.\n * @returns Authentication key for the associated account\n */\n @Memoize()\n authKey(): HexString {\n const pubKey = new Ed25519PublicKey(this.signingKey.publicKey);\n const authKey = AuthenticationKey.fromEd25519PublicKey(pubKey);\n return authKey.derivedAddress();\n }\n\n /**\n * Takes source address and seeds and returns the resource account address\n * @param sourceAddress Address used to derive the resource account\n * @param seed The seed bytes\n * @returns The resource account address\n */\n static getResourceAccountAddress(\n sourceAddress: MaybeHexString,\n seed: Uint8Array,\n ): HexString {\n const source = bcsToBytes(AccountAddress.fromHex(sourceAddress));\n\n const bytes = new Uint8Array([\n ...source,\n ...seed,\n AuthenticationKey.DERIVE_RESOURCE_ACCOUNT_SCHEME,\n ]);\n\n const hash = sha3Hash.create();\n hash.update(bytes);\n\n return HexString.fromUint8Array(hash.digest());\n }\n\n /**\n * Takes creator address and collection name and returns the collection id hash.\n * Collection id hash are generated as sha256 hash of (`creator_address::collection_name`)\n *\n * @param creatorAddress Collection creator address\n * @param collectionName The collection name\n * @returns The collection id hash\n */\n static getCollectionID(\n creatorAddress: MaybeHexString,\n collectionName: string,\n ): HexString {\n const seed = new TextEncoder().encode(\n `${creatorAddress}::${collectionName}`,\n );\n const hash = sha256.create();\n hash.update(seed);\n return HexString.fromUint8Array(hash.digest());\n }\n\n /**\n * This key is generated with Ed25519 scheme.\n * Public key is used to check a signature of transaction, signed by given account\n * @returns The public key for the associated account\n */\n pubKey(): HexString {\n return HexString.fromUint8Array(this.signingKey.publicKey);\n }\n\n /**\n * Signs specified `buffer` with account's private key\n * @param buffer A buffer to sign\n * @returns A signature HexString\n */\n signBuffer(buffer: Uint8Array): HexString {\n const signature = nacl.sign.detached(buffer, this.signingKey.secretKey);\n return HexString.fromUint8Array(signature);\n }\n\n /**\n * Signs specified `hexString` with account's private key\n * @param hexString A regular string or HexString to sign\n * @returns A signature HexString\n */\n signHexString(hexString: MaybeHexString): HexString {\n const toSign = HexString.ensure(hexString).toUint8Array();\n return this.signBuffer(toSign);\n }\n\n /**\n * Verifies the signature of the message with the public key of the account\n * @param message a signed message\n * @param signature the signature of the message\n */\n verifySignature(message: MaybeHexString, signature: MaybeHexString): boolean {\n const rawMessage = HexString.ensure(message).toUint8Array();\n const rawSignature = HexString.ensure(signature).toUint8Array();\n return nacl.sign.detached.verify(\n rawMessage,\n rawSignature,\n this.signingKey.publicKey,\n );\n }\n\n /**\n * Derives account address, public key and private key\n * @returns SupraAccountObject instance.\n * @example An example of the returned SupraAccountObject object\n * ```\n * {\n * address: \"0xe8012714cd17606cee7188a2a365eef3fe760be598750678c8c5954eb548a591\",\n * publicKeyHex: \"0xf56d8524faf79fbc0f48c13aeed3b0ce5dd376b4db93b8130a107c0a5e04ba04\",\n * privateKeyHex: `0x009c9f7c992a06cfafe916f125d8adb7a395fca243e264a8e56a4b3e6accf940\n * d2b11e9ece3049ce60e3c7b4a1c58aebfa9298e29a30a58a67f1998646135204`\n * }\n * ```\n */\n toPrivateKeyObject(): SupraAccountObject {\n return {\n address: this.address().hex(),\n publicKeyHex: this.pubKey().hex(),\n privateKeyHex: HexString.fromUint8Array(\n this.signingKey.secretKey.slice(0, 32),\n ).hex(),\n };\n }\n}\n\n// Returns an account address as a HexString given either an SupraAccount or a MaybeHexString.\nexport function getAddressFromAccountOrAddress(\n accountOrAddress: SupraAccount | MaybeHexString,\n): HexString {\n return accountOrAddress instanceof SupraAccount\n ? accountOrAddress.address()\n : HexString.ensure(accountOrAddress);\n}\n","import nacl from \"tweetnacl\";\nimport { hmac } from \"@noble/hashes/hmac\";\nimport { sha512 } from \"@noble/hashes/sha512\";\nimport { hexToBytes } from \"@noble/hashes/utils\";\n\nexport type Keys = {\n key: Uint8Array;\n chainCode: Uint8Array;\n};\n\nconst pathRegex = /^m(\\/[0-9]+')+$/;\n\nconst replaceDerive = (val: string): string => val.replace(\"'\", \"\");\n\nconst HMAC_KEY = \"ed25519 seed\";\nconst HARDENED_OFFSET = 0x80000000;\n\nexport const getMasterKeyFromSeed = (seed: string): Keys => {\n const h = hmac.create(sha512, HMAC_KEY);\n const I = h.update(hexToBytes(seed)).digest();\n const IL = I.slice(0, 32);\n const IR = I.slice(32);\n return {\n key: IL,\n chainCode: IR,\n };\n};\n\nexport const CKDPriv = ({ key, chainCode }: Keys, index: number): Keys => {\n const buffer = new ArrayBuffer(4);\n new DataView(buffer).setUint32(0, index);\n const indexBytes = new Uint8Array(buffer);\n const zero = new Uint8Array([0]);\n const data = new Uint8Array([...zero, ...key, ...indexBytes]);\n\n const I = hmac.create(sha512, chainCode).update(data).digest();\n const IL = I.slice(0, 32);\n const IR = I.slice(32);\n return {\n key: IL,\n chainCode: IR,\n };\n};\n\nexport const getPublicKey = (\n privateKey: Uint8Array,\n withZeroByte = true,\n): Uint8Array => {\n const keyPair = nacl.sign.keyPair.fromSeed(privateKey);\n const signPk = keyPair.secretKey.subarray(32);\n const zero = new Uint8Array([0]);\n return withZeroByte ? new Uint8Array([...zero, ...signPk]) : signPk;\n};\n\nexport const isValidPath = (path: string): boolean => {\n if (!pathRegex.test(path)) {\n return false;\n }\n return !path\n .split(\"/\")\n .slice(1)\n .map(replaceDerive)\n .some(Number.isNaN as any);\n};\n\nexport const derivePath = (\n path: string,\n seed: string,\n offset = HARDENED_OFFSET,\n): Keys => {\n if (!isValidPath(path)) {\n throw new Error(\"Invalid derivation path\");\n }\n\n const { key, chainCode } = getMasterKeyFromSeed(seed);\n const segments = path\n .split(\"/\")\n .slice(1)\n .map(replaceDerive)\n .map((el) => parseInt(el, 10));\n\n return segments.reduce(\n (parentKeys, segment) => CKDPriv(parentKeys, segment + offset),\n { key, chainCode },\n );\n};\n","// Copyright © Aptos Foundation\n// SPDX-License-Identifier: Apache-2.0\n\nexport const DEFAULT_MAX_GAS_AMOUNT = 200000;\n// Transaction expire timestamp\nexport const DEFAULT_TXN_EXP_SEC_FROM_NOW = 20;\n","// Copyright © Aptos Foundation\n// SPDX-License-Identifier: Apache-2.0\n\nimport { bytesToHex, hexToBytes } from \"@noble/hashes/utils\";\nimport { HexEncodedBytes } from \"../generated\";\n\n// eslint-disable-next-line no-use-before-define\nexport type MaybeHexString = HexString | string | HexEncodedBytes;\n\n/**\n * A util class for working with hex strings.\n * Hex strings are strings that are prefixed with `0x`\n */\nexport class HexString {\n /// We want to make sure this hexString has the `0x` hex prefix\n private readonly hexString: string;\n\n /**\n * Creates new hex string from Buffer\n * @param buffer A buffer to convert\n * @returns New HexString\n */\n static fromBuffer(buffer: Uint8Array): HexString {\n return HexString.fromUint8Array(buffer);\n }\n\n /**\n * Creates new hex string from Uint8Array\n * @param arr Uint8Array to convert\n * @returns New HexString\n */\n static fromUint8Array(arr: Uint8Array): HexString {\n return new HexString(bytesToHex(arr));\n }\n\n /**\n * Ensures `hexString` is instance of `HexString` class\n * @param hexString String to check\n * @returns New HexString if `hexString` is regular string or `hexString` if it is HexString instance\n * @example\n * ```\n * const regularString = \"string\";\n * const hexString = new HexString(\"string\"); // \"0xstring\"\n * HexString.ensure(regularString); // \"0xstring\"\n * HexString.ensure(hexString); // \"0xstring\"\n * ```\n */\n static ensure(hexString: MaybeHexString): HexString {\n if (typeof hexString === \"string\") {\n return new HexString(hexString);\n }\n return hexString;\n }\n\n /**\n * Creates new HexString instance from regular string. If specified string already starts with \"0x\" prefix,\n * it will not add another one\n * @param hexString String to convert\n * @example\n * ```\n * const string = \"string\";\n * new HexString(string); // \"0xstring\"\n * ```\n */\n constructor(hexString: string | HexEncodedBytes) {\n if (hexString.startsWith(\"0x\")) {\n this.hexString = hexString;\n } else {\n this.hexString = `0x${hexString}`;\n }\n }\n\n /**\n * Getter for inner hexString\n * @returns Inner hex string\n */\n hex(): string {\n return this.hexString;\n }\n\n /**\n * Getter for inner hexString without prefix\n * @returns Inner hex string without prefix\n * @example\n * ```\n * const hexString = new HexString(\"string\"); // \"0xstring\"\n * hexString.noPrefix(); // \"string\"\n * ```\n */\n noPrefix(): string {\n return this.hexString.slice(2);\n }\n\n /**\n * Overrides default `toString` method\n * @returns Inner hex string\n */\n toString(): string {\n return this.hex();\n }\n\n /**\n * Trimmes extra zeroes in the begining of a string\n * @returns Inner hexString without leading zeroes\n * @example\n * ```\n * new HexString(\"0x000000string\").toShortString(); // result = \"0xstring\"\n * ```\n */\n toShortString(): string {\n const trimmed = this.hexString.replace(/^0x0*/, \"\");\n return `0x${trimmed}`;\n }\n\n /**\n * Converts hex string to a Uint8Array\n * @returns Uint8Array from inner hexString without prefix\n */\n toUint8Array(): Uint8Array {\n return Uint8Array.from(hexToBytes(this.noPrefix()));\n }\n}\n","/**\n * Credits to https://github.com/darrylhodgins/typescript-memoize\n */\n\n/* eslint-disable no-param-reassign */\n/* eslint-disable no-restricted-syntax */\n\ninterface MemoizeArgs {\n // ttl in milliseconds for cached items. After `ttlMs`, cached items are evicted automatically. If no `ttlMs`\n // is provided, cached items won't get auto-evicted.\n ttlMs?: number;\n // produces the cache key based on `args`.\n hashFunction?: boolean | ((...args: any[]) => any);\n // cached items can be taged with `tags`. `tags` can be used to evict cached items\n tags?: string[];\n}\n\nexport function Memoize(args?: MemoizeArgs | MemoizeArgs[\"hashFunction\"]) {\n let hashFunction: MemoizeArgs[\"hashFunction\"];\n let ttlMs: MemoizeArgs[\"ttlMs\"];\n let tags: MemoizeArgs[\"tags\"];\n\n if (typeof args === \"object\") {\n hashFunction = args.hashFunction;\n ttlMs = args.ttlMs;\n tags = args.tags;\n } else {\n hashFunction = args;\n }\n\n return (\n target: Object,\n propertyKey: string,\n descriptor: TypedPropertyDescriptor<any>,\n ) => {\n if (descriptor.value != null) {\n descriptor.value = getNewFunction(\n descriptor.value,\n hashFunction,\n ttlMs,\n tags,\n );\n } else if (descriptor.get != null) {\n descriptor.get = getNewFunction(\n descriptor.get,\n hashFunction,\n ttlMs,\n tags,\n );\n } else {\n throw new Error(\n \"Only put a Memoize() decorator on a method or get accessor.\",\n );\n }\n };\n}\n\nexport function MemoizeExpiring(\n ttlMs: number,\n hashFunction?: MemoizeArgs[\"hashFunction\"],\n) {\n return Memoize({\n ttlMs,\n hashFunction,\n });\n}\n\nconst clearCacheTagsMap: Map<string, Map<any, any>[]> = new Map();\n\nexport function clear(tags: string[]): number {\n const cleared: Set<Map<any, any>> = new Set();\n for (const tag of tags) {\n const maps = clearCacheTagsMap.get(tag);\n if (maps) {\n for (const mp of maps) {\n if (!cleared.has(mp)) {\n mp.clear();\n cleared.add(mp);\n }\n }\n }\n }\n return cleared.size;\n}\n\nfunction getNewFunction(\n originalMethod: () => void,\n hashFunction?: MemoizeArgs[\"hashFunction\"],\n ttlMs: number = 0,\n tags?: MemoizeArgs[\"tags\"],\n) {\n const propMapName = Symbol(\"__memoized_map__\");\n\n // The function returned here gets called instead of originalMethod.\n // eslint-disable-next-line func-names\n return function (...args: any[]) {\n let returnedValue: any;\n\n // @ts-ignore\n const that: any = this;\n\n // Get or create map\n // eslint-disable-next-line no-prototype-builtins\n if (!that.hasOwnProperty(propMapName)) {\n Object.defineProperty(that, propMapName, {\n configurable: false,\n enumerable: false,\n writable: false,\n value: new Map<any, any>(),\n });\n }\n const myMap: Map<any, any> = that[propMapName];\n\n if (Array.isArray(tags)) {\n for (const tag of tags) {\n if (clearCacheTagsMap.has(tag)) {\n clearCacheTagsMap.get(tag)!.push(myMap);\n } else {\n clearCacheTagsMap.set(tag, [myMap]);\n }\n }\n }\n\n if (hashFunction || args.length > 0 || ttlMs > 0) {\n let hashKey: any;\n\n // If true is passed as first parameter, will automatically use every argument, passed to string\n if (hashFunction === true) {\n hashKey = args.map((a) => a.toString()).join(\"!\");\n } else if (hashFunction) {\n hashKey = hashFunction.apply(that, args);\n } else {\n // eslint-disable-next-line prefer-destructuring\n hashKey = args[0];\n }\n\n const timestampKey = `${hashKey}__timestamp`;\n let isExpired: boolean = false;\n if (ttlMs > 0) {\n if (!myMap.has(timestampKey)) {\n // \"Expired\" since it was never called before\n isExpired = true;\n } else {\n const timestamp = myMap.get(timestampKey);\n isExpired = Date.now() - timestamp > ttlMs;\n }\n }\n\n if (myMap.has(hashKey) && !isExpired) {\n returnedValue = myMap.get(hashKey);\n } else {\n returnedValue = originalMethod.apply(that, args as any);\n myMap.set(hashKey, returnedValue);\n if (ttlMs > 0) {\n myMap.set(timestampKey, Date.now());\n }\n }\n } else {\n const hashKey = that;\n if (myMap.has(hashKey)) {\n returnedValue = myMap.get(hashKey);\n } else {\n returnedValue = originalMethod.apply(that, args as any);\n myMap.set(hashKey, returnedValue);\n }\n }\n\n return returnedValue;\n };\n}\n","// Copyright © Aptos Foundation\n// SPDX-License-Identifier: Apache-2.0\n\nexport * from \"./abi\";\nexport * from \"./account_address\";\nexport * from \"./authenticator\";\nexport * from \"./transaction\";\nexport * from \"./type_tag\";\nexport * from \"./identifier\";\nexport * from \"./ed25519\";\nexport * from \"./multi_ed25519\";\nexport * from \"./authentication_key\";\nexport * from \"./rotation_proof_challenge\";\n\nexport type SigningMessage = Uint8Array;\n","// Copyright © Aptos Foundation\n// SPDX-License-Identifier: Apache-2.0\n\nexport * from \"./types\";\nexport * from \"./serializer\";\nexport * from \"./deserializer\";\nexport * from \"./helper\";\n","// Copyright © Aptos Foundation\n// SPDX-License-Identifier: Apache-2.0\n\nimport { Uint128, Uint16, Uint32, Uint64, Uint8, Uint256 } from \"./types\";\n\n// Upper bound values for uint8, uint16, uint64 and uint128\nexport const MAX_U8_NUMBER: Uint8 = 255;\nexport const MAX_U16_NUMBER: Uint16 = 65535;\nexport const MAX_U32_NUMBER: Uint32 = 4294967295;\nexport const MAX_U64_BIG_INT: Uint64 = 18446744073709551615n;\nexport const MAX_U128_BIG_INT: Uint128 =\n 340282366920938463463374607431768211455n;\nexport const MAX_U256_BIG_INT: Uint256 =\n 115792089237316195423570985008687907853269984665640564039457584007913129639935n;\n","// Copyright © Aptos Foundation\n// SPDX-License-Identifier: Apache-2.0\n\n/* eslint-disable no-bitwise */\nimport {\n MAX_U128_BIG_INT,\n MAX_U16_NUMBER,\n MAX_U32_NUMBER,\n MAX_U64_BIG_INT,\n MAX_U8_NUMBER,\n MAX_U256_BIG_INT,\n} from \"./consts\";\nimport { AnyNumber, Bytes, Uint16, Uint32, Uint8 } from \"./types\";\n\nexport class Serializer {\n private buffer: ArrayBuffer;\n\n private offset: number;\n\n constructor() {\n this.buffer = new ArrayBuffer(64);\n this.offset = 0;\n }\n\n private ensureBufferWillHandleSize(bytes: number) {\n while (this.buffer.byteLength < this.offset + bytes) {\n const newBuffer = new ArrayBuffer(this.buffer.byteLength * 2);\n new Uint8Array(newBuffer).set(new Uint8Array(this.buffer));\n this.buffer = newBuffer;\n }\n }\n\n protected serialize(values: Bytes) {\n this.ensureBufferWillHandleSize(values.length);\n new Uint8Array(this.buffer, this.offset).set(values);\n this.offset += values.length;\n }\n\n private serializeWithFunction(\n fn: (byteOffset: number, value: number, littleEndian?: boolean) => void,\n bytesLength: number,\n value: number,\n ) {\n this.ensureBufferWillHandleSize(bytesLength);\n const dv = new DataView(this.buffer, this.offset);\n fn.apply(dv, [0, value, true]);\n this.offset += bytesLength;\n }\n\n /**\n * Serializes a string. UTF8 string is supported. Serializes the string's bytes length \"l\" first,\n * and then serializes \"l\" bytes of the string content.\n *\n * BCS layout for \"string\": string_length | string_content. string_length is the bytes length of\n * the string that is uleb128 encoded. string_length is a u32 integer.\n *\n * @example\n * ```ts\n * const serializer = new Serializer();\n * serializer.serializeStr(\"çå∞≠¢õß∂ƒ∫\");\n * assert(serializer.getBytes() === new Uint8Array([24, 0xc3, 0xa7, 0xc3, 0xa5, 0xe2, 0x88, 0x9e,\n * 0xe2, 0x89, 0xa0, 0xc2, 0xa2, 0xc3, 0xb5, 0xc3, 0x9f, 0xe2, 0x88, 0x82, 0xc6, 0x92, 0xe2, 0x88, 0xab]));\n * ```\n */\n serializeStr(value: string): void {\n const textEncoder = new TextEncoder();\n this.serializeBytes(textEncoder.encode(value));\n }\n\n /**\n * Serializes an array of bytes.\n *\n * BCS layout for \"bytes\": bytes_length | bytes. bytes_length is the length of the bytes array that is\n * uleb128 encoded. bytes_length is a u32 integer.\n */\n serializeBytes(value: Bytes): void {\n this.serializeU32AsUleb128(value.length);\n this.serialize(value);\n }\n\n /**\n * Serializes an array of bytes with known length. Therefore length doesn't need to be\n * serialized to help deserialization. When deserializing, the number of\n * bytes to deserialize needs to be passed in.\n */\n serializeFixedBytes(value: Bytes): void {\n this.serialize(value);\n }\n\n /**\n * Serializes a boolean value.\n *\n * BCS layout for \"boolean\": One byte. \"0x01\" for True and \"0x00\" for False.\n */\n serializeBool(value: boolean): void {\n if (typeof value !== \"boolean\") {\n throw new Error(\"Value needs to be a boolean\");\n }\n const byteValue = value ? 1 : 0;\n this.serialize(new Uint8Array([byteValue]));\n }\n\n /**\n * Serializes a uint8 number.\n *\n * BCS layout for \"uint8\": One byte. Binary format in little-endian representation.\n */\n @checkNumberRange(0, MAX_U8_NUMBER)\n serializeU8(value: Uint8): void {\n this.serialize(new Uint8Array([value]));\n }\n\n /**\n * Serializes a uint16 number.\n *\n * BCS layout for \"uint16\": Two bytes. Binary format in little-endian representation.\n * @example\n * ```ts\n * const serializer = new Serializer();\n * serializer.serializeU16(4660);\n * assert(serializer.getBytes() === new Uint8Array([0x34, 0x12]));\n * ```\n */\n @checkNumberRange(0, MAX_U16_NUMBER)\n serializeU16(value: Uint16): void {\n this.serializeWithFunction(DataView.prototype.setUint16, 2, value);\n }\n\n /**\n * Serializes a uint32 number.\n *\n * BCS layout for \"uint32\": Four bytes. Binary format in little-endian representation.\n * @example\n * ```ts\n * const serializer = new Serializer();\n * serializer.serializeU32(305419896);\n * assert(serializer.getBytes() === new Uint8Array([0x78, 0x56, 0x34, 0x12]));\n * ```\n */\n @checkNumberRange(0, MAX_U32_NUMBER)\n serializeU32(value: Uint32): void {\n this.serializeWithFunction(DataView.prototype.setUint32, 4, value);\n }\n\n /**\n * Serializes a uint64 number.\n *\n * BCS layout for \"uint64\": Eight bytes. Binary format in little-endian representation.\n * @example\n * ```ts\n * const serializer = new Serializer();\n * serializer.serializeU64(1311768467750121216);\n * assert(serializer.getBytes() === new Uint8Array([0x00, 0xEF, 0xCD, 0xAB, 0x78, 0x56, 0x34, 0x12]));\n * ```\n */\n @checkNumberRange(BigInt(0), MAX_U64_BIG_INT)\n serializeU64(value: AnyNumber): void {\n const low = BigInt(value.toString()) & BigInt(MAX_U32_NUMBER);\n const high = BigInt(value.toString()) >> BigInt(32);\n\n // write little endian number\n this.serializeU32(Number(low));\n this.serializeU32(Number(high));\n }\n\n /**\n * Serializes a uint128 number.\n *\n * BCS layout for \"uint128\": Sixteen bytes. Binary format in little-endian representation.\n */\n @checkNumberRange(BigInt(0), MAX_U128_BIG_INT)\n serializeU128(value: AnyNumber): void {\n const low = BigInt(value.toString()) & MAX_U64_BIG_INT;\n const high = BigInt(value.toString()) >> BigInt(64);\n\n // write little endian number\n this.serializeU64(low);\n this.serializeU64(high);\n }\n\n /**\n * Serializes a uint256 number.\n *\n * BCS layout for \"uint256\": Sixteen bytes. Binary format in little-endian representation.\n */\n @checkNumberRange(BigInt(0), MAX_U256_BIG_INT)\n serializeU256(value: AnyNumber): void {\n const low = BigInt(value.toString()) & MAX_U128_BIG_INT;\n const high = BigInt(value.toString()) >> BigInt(128);\n\n // write little endian number\n this.serializeU128(low);\n this.serializeU128(high);\n }\n\n /**\n * Serializes a uint32 number with uleb128.\n *\n * BCS use uleb128 encoding in two cases: (1) lengths of variable-length sequences and (2) tags of enum values\n */\n @checkNumberRange(0, MAX_U32_NUMBER)\n serializeU32AsUleb128(val: Uint32): void {\n let value = val;\n const valueArray = [];\n while (value >>> 7 !== 0) {\n valueArray.push((value & 0x7f) | 0x80);\n value >>>= 7;\n }\n valueArray.push(value);\n this.serialize(new Uint8Array(valueArray));\n }\n\n /**\n * Returns the buffered bytes\n */\n getBytes(): Bytes {\n return new Uint8Array(this.buffer).slice(0, this.offset);\n }\n}\n\n/**\n * Creates a decorator to make sure the arg value of the decorated function is within a range.\n * @param minValue The arg value of decorated function must >= minValue\n * @param maxValue The arg value of decorated function must <= maxValue\n * @param message Error message\n */\nfunction checkNumberRange<T extends AnyNumber>(\n minValue: T,\n maxValue: T,\n message?: string,\n) {\n return (\n target: unknown,\n propertyKey: string,\n descriptor: PropertyDescriptor,\n ) => {\n const childFunction = descriptor.value;\n // eslint-disable-next-line no-param-reassign\n descriptor.value = function deco(value: AnyNumber) {\n const valueBigInt = BigInt(value.toString());\n if (\n valueBigInt > BigInt(maxValue.toString()) ||\n valueBigInt < BigInt(minValue.toString())\n ) {\n throw new Error(message || \"Value is out of range\");\n }\n childFunction.apply(this, [value]);\n };\n return descriptor;\n };\n}\n","// Copyright © Aptos Foundation\n// SPDX-License-Identifier: Apache-2.0\n\n/* eslint-disable no-bitwise */\nimport { MAX_U32_NUMBER } from \"./consts\";\nimport {\n Bytes,\n Uint128,\n Uint16,\n Uint256,\n Uint32,\n Uint64,\n Uint8,\n} from \"./types\";\n\nexport class Deserializer {\n private buffer: ArrayBuffer;\n\n private offset: number;\n\n constructor(data: Bytes) {\n // copies data to prevent outside mutation of buffer.\n this.buffer = new ArrayBuffer(data.length);\n new Uint8Array(this.buffer).set(data, 0);\n this.offset = 0;\n }\n\n private read(length: number): ArrayBuffer {\n if (this.offset + length > this.buffer.byteLength) {\n throw new Error(\"Reached to the end of buffer\");\n }\n\n const bytes = this.buffer.slice(this.offset, this.offset + length);\n this.offset += length;\n return bytes;\n }\n\n /**\n * Deserializes a string. UTF8 string is supported. Reads the string's bytes length \"l\" first,\n * and then reads \"l\" bytes of content. Decodes the byte array into a string.\n *\n * BCS layout for \"string\": string_length | string_content. string_length is the bytes length of\n * the string that is uleb128 encoded. string_length is a u32 integer.\n *\n * @example\n * ```ts\n * const deserializer = new Deserializer(new Uint8Array([24, 0xc3, 0xa7, 0xc3, 0xa5, 0xe2, 0x88, 0x9e,\n * 0xe2, 0x89, 0xa0, 0xc2, 0xa2, 0xc3, 0xb5, 0xc3, 0x9f, 0xe2, 0x88, 0x82, 0xc6, 0x92, 0xe2, 0x88, 0xab]));\n * assert(deserializer.deserializeStr() === \"çå∞≠¢õß∂ƒ∫\");\n * ```\n */\n deserializeStr(): string {\n const value = this.deserializeBytes();\n const textDecoder = new TextDecoder();\n return textDecoder.decode(value);\n }\n\n /**\n * Deserializes an array of bytes.\n *\n * BCS layout for \"bytes\": bytes_length | bytes. bytes_length is the length of the bytes array that is\n * uleb128 encoded. bytes_length is a u32 integer.\n */\n deserializeBytes(): Bytes {\n const len = this.deserializeUleb128AsU32();\n return new Uint8Array(this.read(len));\n }\n\n /**\n * Deserializes an array of bytes. The number of bytes to read is already known.\n *\n */\n deserializeFixedBytes(len: number): Bytes {\n return new Uint8Array(this.read(len));\n }\n\n /**\n * Deserializes a boolean value.\n *\n * BCS layout for \"boolean\": One byte. \"0x01\" for True and \"0x00\" for False.\n */\n deserializeBool(): boolean {\n const bool = new Uint8Array(this.read(1))[0];\n if (bool !== 1 && bool !== 0) {\n throw new Error(\"Invalid boolean value\");\n }\n return bool === 1;\n }\n\n /**\n * Deserializes a uint8 number.\n *\n * BCS layout for \"uint8\": One byte. Binary format in little-endian representation.\n */\n deserializeU8(): Uint8 {\n return new DataView(this.read(1)).getUint8(0);\n }\n\n /**\n * Deserializes a uint16 number.\n *\n * BCS layout for \"uint16\": Two bytes. Binary format in little-endian representation.\n * @example\n * ```ts\n * const deserializer = new Deserializer(new Uint8Array([0x34, 0x12]));\n * assert(deserializer.deserializeU16() === 4660);\n * ```\n */\n deserializeU16(): Uint16 {\n return new DataView(this.read(2)).getUint16(0, true);\n }\n\n /**\n * Deserializes a uint32 number.\n *\n * BCS layout for \"uint32\": Four bytes. Binary format in little-endian representation.\n * @example\n * ```ts\n * const deserializer = new Deserializer(new Uint8Array([0x78, 0x56, 0x34, 0x12]));\n * assert(deserializer.deserializeU32() === 305419896);\n * ```\n */\n deserializeU32(): Uint32 {\n return new DataView(this.read(4)).getUint32(0, true);\n }\n\n /**\n * Deserializes a uint64 number.\n *\n * BCS layout for \"uint64\": Eight bytes. Binary format in little-endian representation.\n * @example\n * ```ts\n * const deserializer = new Deserializer(new Uint8Array([0x00, 0xEF, 0xCD, 0xAB, 0x78, 0x56, 0x34, 0x12]));\n * assert(deserializer.deserializeU64() === 1311768467750121216);\n * ```\n */\n deserializeU64(): Uint64 {\n const low = this.deserializeU32();\n const high = this.deserializeU32();\n\n // combine the two 32-bit values and return (little endian)\n return BigInt((BigInt(high) << BigInt(32)) | BigInt(low));\n }\n\n /**\n * Deserializes a uint128 number.\n *\n * BCS layout for \"uint128\": Sixteen bytes. Binary format in little-endian representation.\n */\n deserializeU128(): Uint128 {\n const low = this.deserializeU64();\n const high = this.deserializeU64();\n\n // combine the two 64-bit values and return (little endian)\n return BigInt((high << BigInt(64)) | low);\n }\n\n /**\n * Deserializes a uint256 number.\n *\n * BCS layout for \"uint256\": Thirty-two bytes. Binary format in little-endian representation.\n */\n deserializeU256(): Uint256 {\n const low = this.deserializeU128();\n const high = this.deserializeU128();\n\n // combine the two 128-bit values and return (little endian)\n return BigInt((high << BigInt(128)) | low);\n }\n\n /**\n * Deserializes a uleb128 encoded uint32 number.\n *\n * BCS use uleb128 encoding in two cases: (1) lengths of variable-length sequences and (2) tags of enum values\n */\n deserializeUleb128AsU32(): Uint32 {\n let value: bigint = BigInt(0);\n let shift = 0;\n\n while (value < MAX_U32_NUMBER) {\n const byte = this.deserializeU8();\n value |= BigInt(byte & 0x7f) << BigInt(shift);\n\n if ((byte & 0x80) === 0) {\n break;\n }\n shift += 7;\n }\n\n if (value > MAX_U32_NUMBER) {\n throw new Error(\"Overflow while parsing uleb128-encoded uint32 value\");\n }\n\n return Number(value);\n }\n}\n","// Copyright © Aptos Foundation\n// SPDX-License-Identifier: Apache-2.0\n\nimport { Deserializer } from \"./deserializer\";\nimport { Serializer } from \"./serializer\";\nimport { AnyNumber, Bytes, Seq, Uint16, Uint32, Uint8 } from \"./types\";\n\ninterface Serializable {\n serialize(serializer: Serializer): void;\n}\n\n/**\n * Serializes a vector values that are \"Serializable\".\n */\nexport function serializeVector<T extends Serializable>(\n value: Seq<T>,\n serializer: Serializer,\n): void {\n serializer.serializeU32AsUleb128(value.length);\n value.forEach((item: T) => {\n item.serialize(serializer);\n });\n}\n\n/**\n * Serializes a vector of bytes.\n */\nexport function serializeVectorOfBytes(\n value: Seq<Bytes>,\n serializer: Serializer,\n): void {\n serializer.serializeU32AsUleb128(value.length);\n value.forEach((item: Bytes) => {\n serializer.serializeBytes(item);\n });\n}\n\n/**\n * Serializes a vector with specified item serialization function.\n * Very dynamic function and bypasses static typechecking.\n */\nexport function serializeVectorWithFunc(value: any[], func: string): Bytes {\n const serializer = new Serializer();\n serializer.serializeU32AsUleb128(value.length);\n const f = (serializer as any)[func];\n value.forEach((item) => {\n f.call(serializer, item);\n });\n return serializer.getBytes();\n}\n\n/**\n * Deserializes a vector of values.\n */\nexport function deserializeVector(deserializer: Deserializer, cls: any): any[] {\n const length = deserializer.deserializeUleb128AsU32();\n const list: Seq<typeof cls> = [];\n for (let i = 0; i < length; i += 1) {\n list.push(cls.deserialize(deserializer));\n }\n return list;\n}\n\n/**\n * Deserializes a vector of bytes.\n */\nexport function deserializeVectorOfBytes(deserializer: Deserializer): Bytes[] {\n const length = deserializer.deserializeUleb128AsU32();\n const list: Seq<Bytes> = [];\n for (let i = 0; i < length; i += 1) {\n list.push(deserializer.deserializeBytes());\n }\n return list;\n}\n\nexport function bcsToBytes<T extends Serializable>(value: T): Bytes {\n const serializer = new Serializer();\n value.serialize(serializer);\n return serializer.getBytes();\n}\n\nexport function bcsSerializeUint64(value: AnyNumber): Bytes {\n const serializer = new Serializer();\n serializer.serializeU64(value);\n return serializer.getBytes();\n}\n\nexport function bcsSerializeU8(value: Uint8): Bytes {\n const serializer = new Serializer();\n serializer.serializeU8(value);\n return serializer.getBytes();\n}\n\nexport function bcsSerializeU16(value: Uint16): Bytes {\n const serializer = new Serializer();\n serializer.serializeU16(value);\n return serializer.getBytes();\n}\n\nexport function bcsSerializeU32(value: Uint32): Bytes {\n const serializer = new Serializer();\n serializer.serializeU32(value);\n return serializer.getBytes();\n}\n\nexport function bcsSerializeU128(value: AnyNumber): Bytes {\n const serializer = new Serializer();\n serializer.serializeU128(value);\n return serializer.getBytes();\n}\n\nexport function bcsSerializeU256(value: AnyNumber): Bytes {\n const serializer = new Serializer();\n serializer.serializeU256(value);\n return serializer.getBytes();\n}\n\nexport function bcsSerializeBool(value: boolean): Bytes {\n const serializer = new Serializer();\n serializer.serializeBool(value);\n return serializer.getBytes();\n}\n\nexport function bcsSerializeStr(value: string): Bytes {\n const serializer = new Serializer();\n serializer.serializeStr(value);\n return serializer.getBytes();\n}\n\nexport function bcsSerializeBytes(value: Bytes): Bytes {\n const serializer = new Serializer();\n serializer.serializeBytes(value);\n return serializer.getBytes();\n}\n\nexport function bcsSerializeFixedBytes(value: Bytes): Bytes {\n const serializer = new Serializer();\n serializer.serializeFixedBytes(value);\n return serializer.getBytes();\n}\n","// Copyright © Aptos Foundation\n// SPDX-License-Identifier: Apache-2.0\n\n/* eslint-disable @typescript-eslint/naming-convention */\n/* eslint-disable class-methods-use-this */\n/* eslint-disable @typescript-eslint/no-unused-vars */\n/* eslint-disable max-classes-per-file */\nimport { sha3_256 as sha3Hash } from \"@noble/hashes/sha3\";\nimport { HexString } from \"../utils\";\nimport {\n Deserializer,\n Serializer,\n Uint64,\n Bytes,\n Seq,\n Uint8,\n Uint128,\n deserializeVector,\n serializeVector,\n bcsToBytes,\n Uint16,\n Uint256,\n serializeVectorOfBytes,\n deserializeVectorOfBytes,\n} from \"../bcs\";\nimport {\n AccountAuthenticator,\n TransactionAuthenticator,\n TransactionAuthenticatorMultiAgent,\n} from \"./authenticator\";\nimport { Identifier } from \"./identifier\";\nimport { TypeTag } from \"./type_tag\";\nimport { AccountAddress } from \"./account_address\";\n\nexport class RawTransaction {\n /**\n * RawTransactions contain the metadata and payloads that can be submitted to Supra chain for execution.\n * RawTransactions must be signed before Supra chain can execute them.\n *\n * @param sender Account address of the sender.\n * @param sequence_number Sequence number of this transaction. This must match the sequence number stored in\n * the sender's account at the time the transaction executes.\n * @param payload Instructions for the Supra Blockchain, including publishing a module,\n * execute a entry function or execute a script payload.\n * @param max_gas_amount Maximum total gas to spend for this transaction. The account must have more\n * than this gas or the transaction will be discarded during validation.\n * @param gas_unit_price Price to be paid per gas unit.\n * @param expiration_timestamp_secs The blockchain timestamp at which the blockchain would discard this transaction.\n * @param chain_id The chain ID of the blockchain that this transaction is intended to be run on.\n */\n constructor(\n public readonly sender: AccountAddress,\n public readonly sequence_number: Uint64,\n public readonly payload: TransactionPayload,\n public readonly max_gas_amount: Uint64,\n public readonly gas_unit_price: Uint64,\n public readonly expiration_timestamp_secs: Uint64,\n public readonly chain_id: ChainId,\n ) {}\n\n serialize(serializer: Serializer): void {\n this.sender.serialize(serializer);\n serializer.serializeU64(this.sequence_number);\n this.payload.serialize(serializer);\n serializer.serializeU64(this.max_gas_amount);\n serializer.serializeU64(this.gas_unit_price);\n serializer.serializeU64(this.expiration_timestamp_secs);\n this.chain_id.serialize(serializer);\n }\n\n static deserialize(deserializer: Deserializer): RawTransaction {\n const sender = AccountAddress.deserialize(deserializer);\n const sequence_number = deserializer.deserializeU64();\n const payload = TransactionPayload.deserialize(deserializer);\n const max_gas_amount = deserializer.deserializeU64();\n const gas_unit_price = deserializer.deserializeU64();\n const expiration_timestamp_secs = deserializer.deserializeU64();\n const chain_id = ChainId.deserialize(deserializer);\n return new RawTransaction(\n sender,\n sequence_number,\n payload,\n max_gas_amount,\n gas_unit_price,\n expiration_timestamp_secs,\n chain_id,\n );\n }\n}\n\nexport class Script {\n /**\n * Scripts contain the Move bytecodes payload that can be submitted to Supra chain for execution.\n * @param code Move bytecode\n * @param ty_args Type arguments that bytecode requires.\n *\n * @example\n * A coin transfer function has one type argument \"CoinType\".\n * ```\n * public(script) fun transfer<CoinType>(from: &signer, to: address, amount: u64,)\n * ```\n * @param args Arugments to bytecode function.\n *\n * @example\n * A coin transfer function has three arugments \"from\", \"to\" and \"amount\".\n * ```\n * public(script) fun transfer<CoinType>(from: &signer, to: address, amount: u64,)\n * ```\n */\n constructor(\n public readonly code: Bytes,\n public readonly ty_args: Seq<TypeTag>,\n public readonly args: Seq<TransactionArgument>,\n ) {}\n\n serialize(serializer: Serializer): void {\n serializer.serializeBytes(this.code);\n serializeVector<TypeTag>(this.ty_args, serializer);\n serializeVector<TransactionArgument>(this.args, serializer);\n }\n\n static deserialize(deserializer: Deserializer): Script {\n const code = deserializer.deserializeBytes();\n const ty_args = deserializeVector(deserializer, TypeTag);\n const args = deserializeVector(deserializer, TransactionArgument);\n return new Script(code, ty_args, args);\n }\n}\n\nexport class EntryFunction {\n /**\n * Contains the payload to run a function within a module.\n * @param module_name Fully qualified module name. ModuleId consists of account address and module name.\n * @param function_name The function to run.\n * @param ty_args Type arguments that move function requires.\n *\n * @example\n * A coin transfer function has one type argument \"CoinType\".\n * ```\n * public(script) fun transfer<CoinType>(from: &signer, to: address, amount: u64,)\n * ```\n * @param args Arugments to the move function.\n *\n * @example\n * A coin transfer function has three arugments \"from\", \"to\" and \"amount\".\n * ```\n * public(script) fun transfer<CoinType>(from: &signer, to: address, amount: u64,)\n * ```\n */\n constructor(\n public readonly module_name: ModuleId,\n public readonly function_name: Identifier,\n public readonly ty_args: Seq<TypeTag>,\n public readonly args: Seq<Bytes>,\n ) {}\n\n /**\n *\n * @param module Fully qualified module name in format \"AccountAddress::module_name\" e.g. \"0x1::coin\"\n * @param func Function name\n * @param ty_args Type arguments that move function requires.\n *\n * @example\n * A coin transfer function has one type argument \"CoinType\".\n * ```\n * public(script) fun transfer<CoinType>(from: &signer, to: address, amount: u64,)\n * ```\n * @param args Arugments to the move function.\n *\n * @example\n * A coin transfer function has three arugments \"from\", \"to\" and \"amount\".\n * ```\n * public(script) fun transfer<CoinType>(from: &signer, to: address, amount: u64,)\n * ```\n * @returns\n */\n static natural(\n module: string,\n func: string,\n ty_args: Seq<TypeTag>,\n args: Seq<Bytes>,\n ): EntryFunction {\n return new EntryFunction(\n ModuleId.fromStr(module),\n new Identifier(func),\n ty_args,\n args,\n );\n }\n\n /**\n * `natual` is deprecated, please use `natural`\n *\n * @deprecated.\n */\n static natual(\n module: string,\n func: string,\n ty_args: Seq<TypeTag>,\n args: Seq<Bytes>,\n ): EntryFunction {\n return EntryFunction.natural(module, func, ty_args, args);\n }\n\n serialize(serializer: Serializer): void {\n this.module_name.serialize(serializer);\n this.function_name.serialize(serializer);\n serializeVector<TypeTag>(this.ty_args, serializer);\n\n serializer.serializeU32AsUleb128(this.args.length);\n this.args.forEach((item: Bytes) => {\n serializer.serializeBytes(item);\n });\n }\n\n static deserialize(deserializer: Deserializer): EntryFunction {\n const module_name = ModuleId.deserialize(deserializer);\n const function_name = Identifier.deserialize(deserializer);\n const ty_args = deserializeVector(deserializer, TypeTag);\n\n const length = deserializer.deserializeUleb128AsU32();\n const list: Seq<Bytes> = [];\n for (let i = 0; i < length; i += 1) {\n list.push(deserializer.deserializeBytes());\n }\n\n const args = list;\n return new EntryFunction(module_name, function_name, ty_args, args);\n }\n}\n\nexport class MultiSigTransactionPayload {\n /**\n * Contains the payload to run a multisig account transaction.\n * @param transaction_payload The payload of the multisig transaction. This can only be EntryFunction for now but\n * Script might be supported in the future.\n */\n constructor(public readonly transaction_payload: EntryFunction) {}\n\n serialize(serializer: Serializer): void {\n // We can support multiple types of inner transaction payload in the future.\n // For now it's only EntryFunction but if we support more types, we need to serialize with the right enum values\n // here\n serializer.serializeU32AsUleb128(0);\n this.transaction_payload.serialize(serializer);\n }\n\n static deserialize(deserializer: Deserializer): MultiSigTransactionPayload {\n // TODO: Support other types of payload beside EntryFunction.\n // This is the enum value indicating which type of payload the multisig tx contains.\n deserializer.deserializeUleb128AsU32();\n return new MultiSigTransactionPayload(\n EntryFunction.deserialize(deserializer),\n );\n }\n}\n\nexport class MultiSig {\n /**\n * Contains the payload to run a multisig account transaction.\n * @param multisig_address The multisig account address the transaction will be executed as.\n * @param transaction_payload The payload of the multisig transaction. This is optional when executing a multisig\n * transaction whose payload is already stored on chain.\n */\n constructor(\n public readonly multisig_address: AccountAddress,\n public readonly transaction_payload?: MultiSigTransactionPayload,\n ) {}\n\n serialize(serializer: Serializer): void {\n this.multisig_address.serialize(serializer);\n // Options are encoded with an extra u8 field before the value - 0x0 is none and 0x1 is present.\n // We use serializeBool below to create this prefix value.\n if (this.transaction_payload === undefined) {\n serializer.serializeBool(false);\n } else {\n serializer.serializeBool(true);\n this.transaction_payload.serialize(serializer);\n }\n }\n\n static deserialize(deserializer: Deserializer): MultiSig {\n const multisig_address = AccountAddress.deserialize(deserializer);\n const payloadPresent = deserializer.deserializeBool();\n let transaction_payload;\n if (payloadPresent) {\n transaction_payload =\n MultiSigTransactionPayload.deserialize(deserializer);\n }\n return new MultiSig(multisig_address, transaction_payload);\n }\n}\n\nexport class Module {\n /**\n * Contains the bytecode of a Move module that can be published to the Supra chain.\n * @param code Move bytecode of a module.\n */\n constructor(public readonly code: Bytes) {}\n\n serialize(serializer: Serializer): void {\n serializer.serializeBytes(this.code);\n }\n\n static deserialize(deserializer: Deserializer): Module {\n const code = deserializer.deserializeBytes();\n return new Module(code);\n }\n}\n\nexport class ModuleId {\n /**\n * Full name of a module.\n * @param address The account address.\n * @param name The name of the module under the account at \"address\".\n */\n constructor(\n public readonly address: AccountAddress,\n public readonly name: Identifier,\n ) {}\n\n /**\n * Converts a string literal to a ModuleId\n * @param moduleId String literal in format \"AccountAddress::module_name\", e.g. \"0x1::coin\"\n * @returns\n */\n static fromStr(moduleId: string): ModuleId {\n const parts = moduleId.split(\"::\");\n if (parts.length !== 2) {\n throw new Error(\"Invalid module id.\");\n }\n return new ModuleId(\n AccountAddress.f