UNPKG

@axelar-network/axelar-cgp-sui

Version:
226 lines 8.74 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TxBuilderBase = void 0; const bcs_1 = require("@mysten/bcs"); const transactions_1 = require("@mysten/sui/transactions"); const ethers_1 = require("ethers"); const types_1 = require("./types"); const utils_1 = require("./utils"); const { arrayify, hexlify } = ethers_1.utils; const objectCache = {}; function updateCache(objectChanges) { for (const change of objectChanges) { if (change.type === 'published') { continue; } objectCache[change.objectId] = change; } } function getObject(tx, object) { if (Array.isArray(object)) { object = hexlify(object); } if (typeof object === 'string') { const cached = objectCache[object]; if (cached) { // TODO: figure out how to load the object version/digest into the TransactionBlock because it seems impossible for non gas payment objects const txObject = tx.object(object); return txObject; } return tx.object(object); } return object; } function getTypeName(type) { function get(type) { let name = `${type.address}::${type.module}::${type.name}`; if (type.typeArguments.length > 0) { name += `<${type.typeArguments.join(',')}>`; } return name; } if ('Struct' in type) { return get(type.Struct); } else if ('Reference' in type) { return getTypeName(type.Reference); } else if ('MutableReference' in type) { return getTypeName(type.MutableReference); } else if ('Vector' in type) { return `vector<${getTypeName(type.Vector)}>`; } return type.toLowerCase(); } function getNestedStruct(tx, type, arg) { // eslint-disable-next-line @typescript-eslint/no-explicit-any let inside = type; while (inside.Vector) { inside = inside.Vector; } if (!inside.Struct && !inside.Reference && !inside.MutableReference && inside.TypeParameter === undefined) { return null; } if ((0, utils_1.isString)(inside)) { return null; } if (inside.Struct || inside.Reference || inside.MutableReference || inside.TypeParameter !== undefined) { return getObject(tx, arg); } if (!type.Vector) return null; // eslint-disable-next-line @typescript-eslint/no-explicit-any const nested = arg.map((arg) => getNestedStruct(tx, type.Vector, arg)); const typeName = getTypeName(type.Vector); return tx.makeMoveVec({ type: typeName, elements: nested, }); } function serialize(tx, type, arg) { const struct = getNestedStruct(tx, type, arg); if (struct) { return struct; } const vectorU8 = () => bcs_1.bcs.vector(bcs_1.bcs.u8()).transform({ input(val) { if (typeof val === 'string') val = arrayify(val); return val; }, output(value) { return hexlify(value); }, }); const serializer = (type) => { if ((0, utils_1.isString)(type)) { return bcs_1.bcs.string(); } if (typeof type === 'string') { if (type === 'Address') { return bcs_1.bcs.fixedArray(32, bcs_1.bcs.u8()).transform({ input: (id) => arrayify(id), output: (id) => hexlify(id), }); } // eslint-disable-next-line @typescript-eslint/no-explicit-any return bcs_1.bcs[type.toLowerCase()](); } else if (type.Vector) { if (type.Vector === 'U8') { return vectorU8(); } return bcs_1.bcs.vector(serializer(type.Vector)); } throw new Error(`Type ${JSON.stringify(type)} cannot be serialized`); }; return tx.pure(serializer(type).serialize(arg).toBytes()); } function isTxContext(parameter) { // eslint-disable-next-line @typescript-eslint/no-explicit-any let inside = parameter; if (inside.MutableReference) { inside = inside.MutableReference.Struct; if (!inside) return false; } else if (inside.Reference) { inside = inside.Reference.Struct; if (!inside) return false; } else { return false; } return inside.address === types_1.SUI_PACKAGE_ID && inside.module === 'tx_context' && inside.name === 'TxContext'; } class TxBuilderBase { constructor(client) { this.tx = new transactions_1.Transaction(); this.client = client; } moveCall(moveCallInfo) { return __awaiter(this, void 0, void 0, function* () { let target = moveCallInfo.target; // If target is string, convert to object that `getNormalizedMoveFunction` accepts. if (typeof target === 'string') { const first = target.indexOf(':'); const last = target.indexOf(':', first + 2); const packageId = target.slice(0, first); const module = target.slice(first + 2, last); const functionName = target.slice(last + 2); target = { package: packageId, module, function: functionName, }; } const moveFn = yield this.client.getNormalizedMoveFunction(target); let length = moveFn.parameters.length; if (length && isTxContext(moveFn.parameters[length - 1])) length = length - 1; if (!moveCallInfo.arguments) moveCallInfo.arguments = []; if (length !== moveCallInfo.arguments.length) throw new Error(`Function ${target.package}::${target.module}::${target.function} takes ${moveFn.parameters.length} arguments but given ${moveCallInfo.arguments.length}`); const convertedArgs = moveCallInfo.arguments.map((arg, index) => serialize(this.tx, moveFn.parameters[index], arg)); return this.tx.moveCall({ target: `${target.package}::${target.module}::${target.function}`, // eslint-disable-next-line @typescript-eslint/no-explicit-any arguments: convertedArgs, typeArguments: moveCallInfo.typeArguments, }); }); } signAndExecute(keypair, options) { return __awaiter(this, void 0, void 0, function* () { let result = yield this.client.signAndExecuteTransaction({ transaction: this.tx, signer: keypair, options: Object.assign({ showEffects: true, showObjectChanges: true }, options), }); yield this.client.waitForTransaction({ digest: result.digest, options: Object.assign({ showEffects: true, showObjectChanges: true }, options), }); if (!result.confirmedLocalExecution) { while (true) { try { result = yield this.client.getTransactionBlock({ digest: result.digest, options: Object.assign({ showEffects: true, showObjectChanges: true }, options), }); break; } catch (e) { console.log(e); yield new Promise((resolve) => setTimeout(resolve, 1000)); } } } updateCache(result.objectChanges); return result; }); } devInspect(sender) { return __awaiter(this, void 0, void 0, function* () { const result = yield this.client.devInspectTransactionBlock({ transactionBlock: this.tx, sender, }); return result; }); } } exports.TxBuilderBase = TxBuilderBase; //# sourceMappingURL=tx-builder-base.js.map