UNPKG

@mysten/sui

Version:

Sui TypeScript API(Work in Progress)

281 lines (280 loc) 9.01 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var TransactionData_exports = {}; __export(TransactionData_exports, { TransactionDataBuilder: () => TransactionDataBuilder }); module.exports = __toCommonJS(TransactionData_exports); var import_bcs = require("@mysten/bcs"); var import_valibot = require("valibot"); var import_bcs2 = require("../bcs/index.js"); var import_sui_types = require("../utils/sui-types.js"); var import_internal = require("./data/internal.js"); var import_v1 = require("./data/v1.js"); var import_hash = require("./hash.js"); function prepareSuiAddress(address) { return (0, import_sui_types.normalizeSuiAddress)(address).replace("0x", ""); } class TransactionDataBuilder { constructor(clone) { this.version = 2; this.sender = clone?.sender ?? null; this.expiration = clone?.expiration ?? null; this.inputs = clone?.inputs ?? []; this.commands = clone?.commands ?? []; this.gasData = clone?.gasData ?? { budget: null, price: null, owner: null, payment: null }; } static fromKindBytes(bytes) { const kind = import_bcs2.bcs.TransactionKind.parse(bytes); const programmableTx = kind.ProgrammableTransaction; if (!programmableTx) { throw new Error("Unable to deserialize from bytes."); } return TransactionDataBuilder.restore({ version: 2, sender: null, expiration: null, gasData: { budget: null, owner: null, payment: null, price: null }, inputs: programmableTx.inputs, commands: programmableTx.commands }); } static fromBytes(bytes) { const rawData = import_bcs2.bcs.TransactionData.parse(bytes); const data = rawData?.V1; const programmableTx = data.kind.ProgrammableTransaction; if (!data || !programmableTx) { throw new Error("Unable to deserialize from bytes."); } return TransactionDataBuilder.restore({ version: 2, sender: data.sender, expiration: data.expiration, gasData: data.gasData, inputs: programmableTx.inputs, commands: programmableTx.commands }); } static restore(data) { if (data.version === 2) { return new TransactionDataBuilder((0, import_valibot.parse)(import_internal.TransactionData, data)); } else { return new TransactionDataBuilder((0, import_valibot.parse)(import_internal.TransactionData, (0, import_v1.transactionDataFromV1)(data))); } } /** * Generate transaction digest. * * @param bytes BCS serialized transaction data * @returns transaction digest. */ static getDigestFromBytes(bytes) { const hash = (0, import_hash.hashTypedData)("TransactionData", bytes); return (0, import_bcs.toBase58)(hash); } // @deprecated use gasData instead get gasConfig() { return this.gasData; } // @deprecated use gasData instead set gasConfig(value) { this.gasData = value; } build({ maxSizeBytes = Infinity, overrides, onlyTransactionKind } = {}) { const inputs = this.inputs; const commands = this.commands; const kind = { ProgrammableTransaction: { inputs, commands } }; if (onlyTransactionKind) { return import_bcs2.bcs.TransactionKind.serialize(kind, { maxSize: maxSizeBytes }).toBytes(); } const expiration = overrides?.expiration ?? this.expiration; const sender = overrides?.sender ?? this.sender; const gasData = { ...this.gasData, ...overrides?.gasConfig, ...overrides?.gasData }; if (!sender) { throw new Error("Missing transaction sender"); } if (!gasData.budget) { throw new Error("Missing gas budget"); } if (!gasData.payment) { throw new Error("Missing gas payment"); } if (!gasData.price) { throw new Error("Missing gas price"); } const transactionData = { sender: prepareSuiAddress(sender), expiration: expiration ? expiration : { None: true }, gasData: { payment: gasData.payment, owner: prepareSuiAddress(this.gasData.owner ?? sender), price: BigInt(gasData.price), budget: BigInt(gasData.budget) }, kind: { ProgrammableTransaction: { inputs, commands } } }; return import_bcs2.bcs.TransactionData.serialize( { V1: transactionData }, { maxSize: maxSizeBytes } ).toBytes(); } addInput(type, arg) { const index = this.inputs.length; this.inputs.push(arg); return { Input: index, type, $kind: "Input" }; } getInputUses(index, fn) { this.mapArguments((arg, command) => { if (arg.$kind === "Input" && arg.Input === index) { fn(arg, command); } return arg; }); } mapCommandArguments(index, fn) { const command = this.commands[index]; switch (command.$kind) { case "MoveCall": command.MoveCall.arguments = command.MoveCall.arguments.map( (arg) => fn(arg, command, index) ); break; case "TransferObjects": command.TransferObjects.objects = command.TransferObjects.objects.map( (arg) => fn(arg, command, index) ); command.TransferObjects.address = fn(command.TransferObjects.address, command, index); break; case "SplitCoins": command.SplitCoins.coin = fn(command.SplitCoins.coin, command, index); command.SplitCoins.amounts = command.SplitCoins.amounts.map( (arg) => fn(arg, command, index) ); break; case "MergeCoins": command.MergeCoins.destination = fn(command.MergeCoins.destination, command, index); command.MergeCoins.sources = command.MergeCoins.sources.map( (arg) => fn(arg, command, index) ); break; case "MakeMoveVec": command.MakeMoveVec.elements = command.MakeMoveVec.elements.map( (arg) => fn(arg, command, index) ); break; case "Upgrade": command.Upgrade.ticket = fn(command.Upgrade.ticket, command, index); break; case "$Intent": const inputs = command.$Intent.inputs; command.$Intent.inputs = {}; for (const [key, value] of Object.entries(inputs)) { command.$Intent.inputs[key] = Array.isArray(value) ? value.map((arg) => fn(arg, command, index)) : fn(value, command, index); } break; case "Publish": break; default: throw new Error(`Unexpected transaction kind: ${command.$kind}`); } } mapArguments(fn) { for (const commandIndex of this.commands.keys()) { this.mapCommandArguments(commandIndex, fn); } } replaceCommand(index, replacement, resultIndex = index) { if (!Array.isArray(replacement)) { this.commands[index] = replacement; return; } const sizeDiff = replacement.length - 1; this.commands.splice(index, 1, ...replacement); if (sizeDiff !== 0) { this.mapArguments((arg, _command, commandIndex) => { if (commandIndex < index + replacement.length) { return arg; } switch (arg.$kind) { case "Result": if (arg.Result === index) { arg.Result = resultIndex; } if (arg.Result > index) { arg.Result += sizeDiff; } break; case "NestedResult": if (arg.NestedResult[0] === index) { arg.NestedResult[0] = resultIndex; } if (arg.NestedResult[0] > index) { arg.NestedResult[0] += sizeDiff; } break; } return arg; }); } } getDigest() { const bytes = this.build({ onlyTransactionKind: false }); return TransactionDataBuilder.getDigestFromBytes(bytes); } snapshot() { return (0, import_valibot.parse)(import_internal.TransactionData, this); } shallowClone() { return new TransactionDataBuilder({ version: this.version, sender: this.sender, expiration: this.expiration, gasData: { ...this.gasData }, inputs: [...this.inputs], commands: [...this.commands] }); } } //# sourceMappingURL=TransactionData.js.map