evm-blockchain-tools
Version:
This is a collection of resuseable tools to support development for EVM-powered blockchains
152 lines • 7.12 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());
});
};
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