@axelar-network/axelar-cgp-sui
Version:
Axelar Sui Move contracts
226 lines • 8.74 kB
JavaScript
;
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