@axelar-network/axelar-cgp-sui
Version:
Axelar Sui Move contracts
145 lines • 7.01 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());
});
};
import { fromHEX } from '@mysten/bcs';
import { bcs } from '@mysten/sui/bcs';
import { arrayify, hexlify, keccak256 } from 'ethers/lib/utils';
import { bcsStructs } from './bcs';
import { TxBuilderBase as TxBuilder } from './tx-builder-base';
import { GatewayMessageType, MoveCallType, } from './types';
import { hashMessage, signMessage } from './utils';
const { gateway: { WeightedSigners, MessageToSign, Proof, Message, Transaction }, } = bcsStructs;
export function approve(client, keypair, gatewayApprovalInfo, messageInfo, options) {
return __awaiter(this, void 0, void 0, function* () {
const { packageId, gateway, signers, signerKeys, domainSeparator } = gatewayApprovalInfo;
const messageData = bcs.vector(Message).serialize([messageInfo]).toBytes();
const hashed = hashMessage(messageData, GatewayMessageType.ApproveMessages);
const message = MessageToSign.serialize({
domain_separator: fromHEX(domainSeparator),
signers_hash: keccak256(WeightedSigners.serialize(signers).toBytes()),
data_hash: hashed,
}).toBytes();
let minSigners = 0;
let totalWeight = 0;
for (let i = 0; i < signers.signers.length; i++) {
totalWeight += signers.signers[i].weight;
if (totalWeight >= signers.threshold) {
minSigners = i + 1;
break;
}
}
const signatures = signMessage(signerKeys.slice(0, minSigners), message);
const encodedProof = Proof.serialize({
signers,
signatures,
}).toBytes();
const txBuilder = new TxBuilder(client);
yield txBuilder.moveCall({
target: `${packageId}::gateway::approve_messages`,
arguments: [gateway, hexlify(messageData), hexlify(encodedProof)],
});
yield txBuilder.signAndExecute(keypair, options);
});
}
export function execute(client, keypair, discoveryInfo, gatewayInfo, messageInfo, options) {
return __awaiter(this, void 0, void 0, function* () {
let moveCalls = [createInitialMoveCall(discoveryInfo, messageInfo.destination_id)];
let isFinal = false;
while (!isFinal) {
const builder = new TxBuilder(client);
doMoveCalls(builder.tx, moveCalls, messageInfo.payload);
const nextTx = yield inspectTransaction(builder, keypair);
isFinal = nextTx.is_final;
moveCalls = nextTx.move_calls;
}
const txBuilder = new TxBuilder(client);
const ApprovedMessage = yield createApprovedMessageCall(txBuilder, gatewayInfo, messageInfo);
doMoveCalls(txBuilder.tx, moveCalls, messageInfo.payload, ApprovedMessage);
return txBuilder.signAndExecute(keypair, options);
});
}
export function approveAndExecute(client_1, keypair_1, gatewayApprovalInfo_1, discoveryInfo_1, messageInfo_1) {
return __awaiter(this, arguments, void 0, function* (client, keypair, gatewayApprovalInfo, discoveryInfo, messageInfo, options = {
showEvents: true,
}) {
yield approve(client, keypair, gatewayApprovalInfo, messageInfo, options);
return execute(client, keypair, discoveryInfo, gatewayApprovalInfo, messageInfo, options);
});
}
function createInitialMoveCall(discoveryInfo, destinationId) {
const { packageId, discovery } = discoveryInfo;
const discoveryArg = [MoveCallType.Object, ...arrayify(discovery)];
const targetIdArg = [MoveCallType.Pure, ...arrayify(destinationId)];
return {
function: {
package_id: packageId,
module_name: 'discovery',
name: 'get_transaction',
},
arguments: [discoveryArg, targetIdArg],
type_arguments: [],
};
}
function inspectTransaction(builder, keypair) {
return __awaiter(this, void 0, void 0, function* () {
var _a, _b, _c, _d;
const resp = yield builder.devInspect(keypair.toSuiAddress());
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const txData = (_d = (_c = (_b = (_a = resp.results) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.returnValues) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d[0];
return Transaction.parse(new Uint8Array(txData));
});
}
function createApprovedMessageCall(builder, gatewayInfo, messageInfo) {
return builder.moveCall({
target: `${gatewayInfo.packageId}::gateway::take_approved_message`,
arguments: [
gatewayInfo.gateway,
messageInfo.source_chain,
messageInfo.message_id,
messageInfo.source_address,
messageInfo.destination_id,
messageInfo.payload,
],
});
}
/* eslint-disable @typescript-eslint/no-explicit-any */
function doMoveCalls(tx, moveCalls, payload, ApprovedMessage) {
const txResults = [];
for (const call of moveCalls) {
const moveCall = buildMoveCall(tx, call, payload, txResults, ApprovedMessage);
const txResult = tx.moveCall(moveCall);
txResults.push(Array.isArray(txResult) ? txResult : [txResult]);
}
}
/* eslint-disable @typescript-eslint/no-explicit-any */
function buildMoveCall(tx, moveCallInfo, payload, previousReturns, ApprovedMessage) {
const decodeArgs = (args) => args.map(([argType, ...arg]) => {
switch (argType) {
case MoveCallType.Object:
return tx.object(hexlify(arg));
case MoveCallType.Pure:
return tx.pure(arrayify(arg));
case MoveCallType.ApproveMessage:
return ApprovedMessage;
case MoveCallType.Payload:
return tx.pure(bcs.vector(bcs.U8).serialize(arrayify(payload)));
case MoveCallType.HotPotato:
return previousReturns[arg[1]][arg[2]];
default:
throw new Error(`Invalid argument prefix: ${argType}`);
}
});
const { package_id: packageId, module_name: moduleName, name } = moveCallInfo.function;
return {
target: `${packageId}::${moduleName}::${name}`,
arguments: decodeArgs(moveCallInfo.arguments),
typeArguments: moveCallInfo.type_arguments,
};
}
//# sourceMappingURL=execute.js.map