UNPKG

evm-blockchain-tools

Version:

This is a collection of resuseable tools to support development for EVM-powered blockchains

152 lines 7.12 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()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MultisigService = void 0; const ethers_1 = require("ethers"); const safe_core_sdk_1 = __importDefault(require("@safe-global/safe-core-sdk")); const safe_ethers_lib_1 = __importDefault(require("@safe-global/safe-ethers-lib")); const axios_1 = __importDefault(require("axios")); const safe_service_client_1 = __importDefault(require("@safe-global/safe-service-client")); const constants_1 = require("../common/constants"); const web3_utils_1 = require("../utils/web3-utils"); class MultisigService { constructor(provider) { this.provider = provider; this.isInitialized = false; } init() { return __awaiter(this, void 0, void 0, function* () { const signer = yield this.provider.signer; this.adapter = new safe_ethers_lib_1.default({ ethers: ethers_1.ethers, signerOrProvider: signer, }); this.serviceClient = new safe_service_client_1.default({ txServiceUrl: this.serviceNetworkUrl, ethAdapter: this.adapter, }); this.isInitialized = true; }); } ensureInit() { if (!this.isInitialized) { throw new Error("service not initialized"); } } getSafeByAddress(safeAddress) { this.ensureInit(); return safe_core_sdk_1.default.create({ ethAdapter: this.adapter, safeAddress: safeAddress, }); } get serviceNetworkUrl() { switch (this.provider.network) { case constants_1.APP_NETWORK.ETH: return "https://safe-transaction-mainnet.safe.global"; case constants_1.APP_NETWORK.BINANCE: return "https://safe-transaction-bsc.safe.global"; case constants_1.APP_NETWORK.GOERLI: return "https://safe-transaction-goerli.safe.global"; case constants_1.APP_NETWORK.BINANCE_TESTNET: throw new Error("service for binance testnet is not supported"); } } checkTxStatus(multisigAddress, internalHash) { var _a; return __awaiter(this, void 0, void 0, function* () { const txData = yield this.getTransaction(internalHash); if (txData.isExecuted && txData.isSuccessful && txData.dataDecoded) { return { status: constants_1.MULTISIG_TX_STATUS.EXECUTED, transactionHash: txData.transactionHash, }; } const txByNonce = yield this.getTxByNonce(multisigAddress, txData.nonce); if (((_a = txByNonce.results) === null || _a === void 0 ? void 0 : _a.length) === 1) { return { status: constants_1.MULTISIG_TX_STATUS.PENDING, }; } const executedRejectionTx = txByNonce.results.find((tx) => tx.isExecuted && tx.isSuccessful && !tx.dataDecoded); if (executedRejectionTx) { return { status: constants_1.MULTISIG_TX_STATUS.REJECTED, }; } return { status: constants_1.MULTISIG_TX_STATUS.PENDING, }; }); } getTxByNonce(multisigAddress, nonce) { return __awaiter(this, void 0, void 0, function* () { const response = yield axios_1.default.get(`${this.serviceNetworkUrl}/api/v1/safes/${multisigAddress}/multisig-transactions?nonce=${nonce}`); if (response.status === 200) { return response.data; } throw new Error("failed to get tx by nonce"); }); } getPendingTransactions(multisigAddress, endingNonce) { return this.serviceClient.getPendingTransactions(multisigAddress, endingNonce); } proposeTx(multisigAddress, data) { return __awaiter(this, void 0, void 0, function* () { const url = `${this.serviceNetworkUrl}/api/v1/safes/${multisigAddress}/multisig-transactions/`; const response = yield axios_1.default.post(url, data); if (response.status !== 201) { throw new Error("failed to propose transaction: " + JSON.stringify(response.data)); } return; }); } getTransaction(hash) { return this.serviceClient.getTransaction(hash); } createTransactionData(toAddress, abi, functionName, params, transfersEth = "0") { const fn = abi.getFunction(functionName); if (!fn) { throw new Error("function name not found in abi"); } const functionCall = (0, web3_utils_1.encodeFunctionSignature)(JSON.parse(fn.format("json")), params); return { to: toAddress, value: transfersEth, data: functionCall, }; } sendMultisigTx(multisigAddress, signerAddress, txData) { return __awaiter(this, void 0, void 0, function* () { this.ensureInit(); const safe = yield this.getSafeByAddress(multisigAddress); const nextNonce = yield this.serviceClient.getNextNonce(multisigAddress); const tx = yield safe.createTransaction({ safeTransactionData: Object.assign(Object.assign({}, txData), { operation: 0, baseGas: 0, gasPrice: 0, gasToken: constants_1.EMPTY_ADDRESS, refundReceiver: constants_1.EMPTY_ADDRESS, safeTxGas: 0, nonce: nextNonce }), }); const signedTx = yield safe.signTransaction(tx); const signatures = signedTx.signatures; const value = signatures.values().next(); const signatureValue = value.value; const txHash = yield safe.getTransactionHash(signedTx); yield this.proposeTx(multisigAddress, Object.assign(Object.assign({}, tx.data), { sender: signerAddress, signature: signatureValue.data, contractTransactionHash: txHash, origin: JSON.stringify({ url: "https://apps.gnosis-safe.io/tx-builder", name: "Transaction Builder", }) })); return txHash; }); } } exports.MultisigService = MultisigService; //# sourceMappingURL=multisig-service.js.map