UNPKG

dp-contract-proxy-kit

Version:

Enable batched transactions and contract account interactions using a unique deterministic Gnosis Safe.

476 lines 23 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 __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; var _CPK_safeAppsSdkConnector, _CPK_ethLibAdapter, _CPK_transactionManager, _CPK_contractManager, _CPK_networks, _CPK_ownerAccount, _CPK_saltNonce, _CPK_isConnectedToSafe; Object.defineProperty(exports, "__esModule", { value: true }); const MultiSendAbi_json_1 = __importDefault(require("./abis/MultiSendAbi.json")); const networks_1 = require("./config/networks"); const contractManager_1 = __importDefault(require("./contractManager")); const safeAppsSdkConnector_1 = __importDefault(require("./safeAppsSdkConnector")); const CpkTransactionManager_1 = __importDefault(require("./transactionManagers/CpkTransactionManager")); const checkConnectedToSafe_1 = require("./utils/checkConnectedToSafe"); const constants_1 = require("./utils/constants"); const hexData_1 = require("./utils/hexData"); const networks_2 = require("./utils/networks"); const transactions_1 = require("./utils/transactions"); class CPK { /** * Creates a non-initialized instance of the CPK with the selected configuration parameters. * * @param opts - CPK configuration * @returns The CPK instance */ constructor(opts) { _CPK_safeAppsSdkConnector.set(this, void 0); _CPK_ethLibAdapter.set(this, void 0); _CPK_transactionManager.set(this, void 0); _CPK_contractManager.set(this, void 0); _CPK_networks.set(this, void 0); _CPK_ownerAccount.set(this, void 0); _CPK_saltNonce.set(this, constants_1.predeterminedSaltNonce); _CPK_isConnectedToSafe.set(this, false /** * Creates and initializes an instance of the CPK with the selected configuration parameters. * * @param opts - CPK configuration * @returns The CPK instance */ ); __classPrivateFieldSet(this, _CPK_networks, Object.assign({}, networks_1.defaultNetworks), "f"); if (!opts) { return; } const { ethLibAdapter, transactionManager, ownerAccount, networks, saltNonce, isSafeApp = true } = opts; if (isSafeApp) { __classPrivateFieldSet(this, _CPK_safeAppsSdkConnector, new safeAppsSdkConnector_1.default(), "f"); } if (!ethLibAdapter) { throw new Error('ethLibAdapter property missing from options'); } __classPrivateFieldSet(this, _CPK_ethLibAdapter, ethLibAdapter, "f"); __classPrivateFieldSet(this, _CPK_transactionManager, transactionManager !== null && transactionManager !== void 0 ? transactionManager : new CpkTransactionManager_1.default(), "f"); __classPrivateFieldSet(this, _CPK_ownerAccount, ownerAccount, "f"); __classPrivateFieldSet(this, _CPK_networks, networks_1.normalizeNetworksConfig(networks_1.defaultNetworks, networks), "f"); if (saltNonce) { __classPrivateFieldSet(this, _CPK_saltNonce, saltNonce, "f"); } } /** * Creates and initializes an instance of the CPK with the selected configuration parameters. * * @param opts - CPK configuration * @returns The CPK instance */ static create(opts) { return __awaiter(this, void 0, void 0, function* () { const cpk = new CPK(opts); if (opts) { yield cpk.init(); } return cpk; }); } /** * Initializes the CPK instance. */ init() { var _a, _b; return __awaiter(this, void 0, void 0, function* () { if (!__classPrivateFieldGet(this, _CPK_ethLibAdapter, "f")) { throw new Error('CPK uninitialized ethLibAdapter'); } const networkId = yield __classPrivateFieldGet(this, _CPK_ethLibAdapter, "f").getNetworkId(); const network = __classPrivateFieldGet(this, _CPK_networks, "f")[networkId]; if (!network) { throw new Error(`Unrecognized network ID ${networkId}`); } const ownerAccount = yield this.getOwnerAccount(); __classPrivateFieldSet(this, _CPK_isConnectedToSafe, (yield checkConnectedToSafe_1.checkConnectedToSafe(__classPrivateFieldGet(this, _CPK_ethLibAdapter, "f").getProvider())) || ((_a = __classPrivateFieldGet(this, _CPK_safeAppsSdkConnector, "f")) === null || _a === void 0 ? void 0 : _a.isSafeApp) === true, "f"); __classPrivateFieldSet(this, _CPK_contractManager, yield contractManager_1.default.create({ ethLibAdapter: __classPrivateFieldGet(this, _CPK_ethLibAdapter, "f"), network, ownerAccount, saltNonce: __classPrivateFieldGet(this, _CPK_saltNonce, "f"), isSafeApp: ((_b = __classPrivateFieldGet(this, _CPK_safeAppsSdkConnector, "f")) === null || _b === void 0 ? void 0 : _b.isSafeApp) === true, isConnectedToSafe: __classPrivateFieldGet(this, _CPK_isConnectedToSafe, "f") }), "f"); }); } /** * Checks if the Proxy contract is deployed or not. The deployment of the Proxy contract happens automatically when the first transaction is submitted. * * @returns TRUE when the Proxy contract is deployed */ isProxyDeployed() { return __awaiter(this, void 0, void 0, function* () { const address = yield this.address; if (!address) { throw new Error('CPK address uninitialized'); } if (!this.ethLibAdapter) { throw new Error('CPK ethLibAdapter uninitialized'); } const codeAtAddress = yield this.ethLibAdapter.getCode(address); const isDeployed = codeAtAddress !== '0x'; return isDeployed; }); } /** * Returns the address of the account connected to the CPK (Proxy contract owner). However, if the CPK is running as a Safe App or connected to a Safe, the Safe address will be returned. * * @returns The address of the account connected to the CPK */ getOwnerAccount() { var _a, _b; return __awaiter(this, void 0, void 0, function* () { if ((_a = __classPrivateFieldGet(this, _CPK_safeAppsSdkConnector, "f")) === null || _a === void 0 ? void 0 : _a.isSafeApp) { return (yield __classPrivateFieldGet(this, _CPK_safeAppsSdkConnector, "f").getSafeInfo()).safeAddress; } if (__classPrivateFieldGet(this, _CPK_ownerAccount, "f")) { return __classPrivateFieldGet(this, _CPK_ownerAccount, "f"); } if (!__classPrivateFieldGet(this, _CPK_ethLibAdapter, "f")) { throw new Error('CPK uninitialized ethLibAdapter'); } return (_b = __classPrivateFieldGet(this, _CPK_ethLibAdapter, "f")) === null || _b === void 0 ? void 0 : _b.getAccount(); }); } /** * Returns the ETH balance of the Proxy contract. * * @returns The ETH balance of the Proxy contract */ getBalance() { var _a; return __awaiter(this, void 0, void 0, function* () { const address = yield this.address; if (!address) { throw new Error('CPK address uninitialized'); } if (!__classPrivateFieldGet(this, _CPK_ethLibAdapter, "f")) { throw new Error('CPK ethLibAdapter uninitialized'); } return (_a = __classPrivateFieldGet(this, _CPK_ethLibAdapter, "f")) === null || _a === void 0 ? void 0 : _a.getBalance(address); }); } /** * Returns the ID of the connected network. * * @returns The ID of the connected network */ getNetworkId() { var _a; return __awaiter(this, void 0, void 0, function* () { if ((_a = __classPrivateFieldGet(this, _CPK_safeAppsSdkConnector, "f")) === null || _a === void 0 ? void 0 : _a.isSafeApp) { const networkName = (yield __classPrivateFieldGet(this, _CPK_safeAppsSdkConnector, "f").getSafeInfo()).network; return networks_2.getNetworkIdFromName(networkName); } if (!__classPrivateFieldGet(this, _CPK_ethLibAdapter, "f")) { throw new Error('CPK ethLibAdapter uninitialized'); } return __classPrivateFieldGet(this, _CPK_ethLibAdapter, "f").getNetworkId(); }); } /** * Returns the safeAppsSdkConnector used by the CPK. * * @returns The safeAppsSdkConnector used by the CPK */ get safeAppsSdkConnector() { return __classPrivateFieldGet(this, _CPK_safeAppsSdkConnector, "f"); } /** * Returns the contractManager used by the CPK. * * @returns The contractManager used by the CPK */ get contractManager() { return __classPrivateFieldGet(this, _CPK_contractManager, "f"); } /** * Returns the ethLibAdapter used by the CPK. * * @returns The ethLibAdapter used by the CPK */ get ethLibAdapter() { return __classPrivateFieldGet(this, _CPK_ethLibAdapter, "f"); } /** * Returns a list of the contract addresses which drive the CPK per network by network ID. * * @returns The list of the contract addresses which drive the CPK per network by network ID */ get networks() { return __classPrivateFieldGet(this, _CPK_networks, "f"); } /** * Checks if the CPK is connected to a Safe account or not. * * @returns TRUE if the CPK is connected to a Safe account */ get isConnectedToSafe() { return __classPrivateFieldGet(this, _CPK_isConnectedToSafe, "f"); } /** * Returns the salt nonce used to deploy the Proxy Contract. * * @returns The salt nonce used to deploy the Proxy Contract */ get saltNonce() { return __classPrivateFieldGet(this, _CPK_saltNonce, "f"); } /** * Returns the address of the Proxy contract. * * @returns The address of the Proxy contract */ get address() { var _a, _b, _c, _d; if ((_a = __classPrivateFieldGet(this, _CPK_safeAppsSdkConnector, "f")) === null || _a === void 0 ? void 0 : _a.safeAddress) { return (_b = __classPrivateFieldGet(this, _CPK_safeAppsSdkConnector, "f")) === null || _b === void 0 ? void 0 : _b.safeAddress; } return (_d = (_c = __classPrivateFieldGet(this, _CPK_contractManager, "f")) === null || _c === void 0 ? void 0 : _c.contract) === null || _d === void 0 ? void 0 : _d.address; } /** * Sets the ethLibAdapter used by the CPK. */ setEthLibAdapter(ethLibAdapter) { __classPrivateFieldSet(this, _CPK_ethLibAdapter, ethLibAdapter, "f"); } /** * Sets the transactionManager used by the CPK. */ setTransactionManager(transactionManager) { var _a; if ((_a = __classPrivateFieldGet(this, _CPK_safeAppsSdkConnector, "f")) === null || _a === void 0 ? void 0 : _a.isSafeApp) { throw new Error('TransactionManagers are not allowed when the app is running as a Safe App'); } __classPrivateFieldSet(this, _CPK_transactionManager, transactionManager, "f"); } /** * Sets the network configuration used by the CPK. */ setNetworks(networks) { __classPrivateFieldSet(this, _CPK_networks, networks_1.normalizeNetworksConfig(networks_1.defaultNetworks, networks), "f"); } /** * Returns the encoding of a list of transactions. * * @param transactions - The transaction list * @returns The encoding of a list of transactions */ encodeMultiSendCallData(transactions) { var _a; if (!__classPrivateFieldGet(this, _CPK_ethLibAdapter, "f")) { throw new Error('CPK ethLibAdapter uninitialized'); } const multiSend = ((_a = __classPrivateFieldGet(this, _CPK_contractManager, "f")) === null || _a === void 0 ? void 0 : _a.multiSend) || __classPrivateFieldGet(this, _CPK_ethLibAdapter, "f").getContract(MultiSendAbi_json_1.default); const standardizedTxs = transactions.map(transactions_1.standardizeTransaction); const ethLibAdapter = __classPrivateFieldGet(this, _CPK_ethLibAdapter, "f"); return multiSend.encode('multiSend', [ hexData_1.joinHexData(standardizedTxs.map((tx) => ethLibAdapter.abiEncodePacked({ type: 'uint8', value: tx.operation }, { type: 'address', value: tx.to }, { type: 'uint256', value: tx.value }, { type: 'uint256', value: hexData_1.getHexDataLength(tx.data) }, { type: 'bytes', value: tx.data }))) ]); } /** * Executes a list of transactions. * * @param transactions - The transaction list to execute * @param options - Execution configuration options * @returns The transaction response */ execTransactions(transactions, options) { var _a; return __awaiter(this, void 0, void 0, function* () { const standardizedTxs = transactions.map(transactions_1.standardizeTransaction); if (((_a = __classPrivateFieldGet(this, _CPK_safeAppsSdkConnector, "f")) === null || _a === void 0 ? void 0 : _a.isSafeApp) && transactions.length >= 1) { return __classPrivateFieldGet(this, _CPK_safeAppsSdkConnector, "f").sendTransactions(standardizedTxs, { safeTxGas: options === null || options === void 0 ? void 0 : options.safeTxGas }); } const address = yield this.address; if (!address) { throw new Error('CPK address uninitialized'); } if (!__classPrivateFieldGet(this, _CPK_contractManager, "f")) { throw new Error('CPK contractManager uninitialized'); } if (!__classPrivateFieldGet(this, _CPK_ethLibAdapter, "f")) { throw new Error('CPK ethLibAdapter uninitialized'); } if (!__classPrivateFieldGet(this, _CPK_transactionManager, "f")) { throw new Error('CPK transactionManager uninitialized'); } const ownerAccount = yield this.getOwnerAccount(); if (!ownerAccount) { throw new Error('CPK ownerAccount uninitialized'); } const safeExecTxParams = this.getSafeExecTxParams(transactions); const sendOptions = transactions_1.normalizeGasLimit(Object.assign(Object.assign({}, options), { from: ownerAccount })); const codeAtAddress = yield __classPrivateFieldGet(this, _CPK_ethLibAdapter, "f").getCode(address); const isDeployed = codeAtAddress !== '0x'; const txManager = !isDeployed ? new CpkTransactionManager_1.default() : __classPrivateFieldGet(this, _CPK_transactionManager, "f"); return txManager.execTransactions({ ownerAccount, safeExecTxParams, transactions: standardizedTxs, ethLibAdapter: __classPrivateFieldGet(this, _CPK_ethLibAdapter, "f"), contractManager: __classPrivateFieldGet(this, _CPK_contractManager, "f"), saltNonce: __classPrivateFieldGet(this, _CPK_saltNonce, "f"), isDeployed, isConnectedToSafe: __classPrivateFieldGet(this, _CPK_isConnectedToSafe, "f"), sendOptions }); }); } /** * Returns the Master Copy contract version. * * @returns The Master Copy contract version */ getContractVersion() { var _a; return __awaiter(this, void 0, void 0, function* () { const isProxyDeployed = yield this.isProxyDeployed(); if (!isProxyDeployed) { throw new Error('CPK Proxy contract is not deployed'); } if (!((_a = __classPrivateFieldGet(this, _CPK_contractManager, "f")) === null || _a === void 0 ? void 0 : _a.versionUtils)) { throw new Error('CPK contractManager uninitialized'); } return yield __classPrivateFieldGet(this, _CPK_contractManager, "f").versionUtils.getContractVersion(); }); } /** * Returns the list of addresses of all the enabled Safe modules. * * @returns The list of addresses of all the enabled Safe modules */ getModules() { var _a; return __awaiter(this, void 0, void 0, function* () { const isProxyDeployed = yield this.isProxyDeployed(); if (!isProxyDeployed) { throw new Error('CPK Proxy contract is not deployed'); } if (!((_a = __classPrivateFieldGet(this, _CPK_contractManager, "f")) === null || _a === void 0 ? void 0 : _a.versionUtils)) { throw new Error('CPK contractManager uninitialized'); } return yield __classPrivateFieldGet(this, _CPK_contractManager, "f").versionUtils.getModules(); }); } /** * Checks if a specific Safe module is enabled or not. * * @param moduleAddress - The desired module address * @returns TRUE if the module is enabled */ isModuleEnabled(moduleAddress) { var _a; return __awaiter(this, void 0, void 0, function* () { const isProxyDeployed = yield this.isProxyDeployed(); if (!isProxyDeployed) { throw new Error('CPK Proxy contract is not deployed'); } if (!((_a = __classPrivateFieldGet(this, _CPK_contractManager, "f")) === null || _a === void 0 ? void 0 : _a.versionUtils)) { throw new Error('CPK contractManager uninitialized'); } return yield __classPrivateFieldGet(this, _CPK_contractManager, "f").versionUtils.isModuleEnabled(moduleAddress); }); } /** * Enables a Safe module * * @param moduleAddress - The desired module address * @returns The transaction response */ enableModule(moduleAddress) { var _a; return __awaiter(this, void 0, void 0, function* () { if (!((_a = __classPrivateFieldGet(this, _CPK_contractManager, "f")) === null || _a === void 0 ? void 0 : _a.versionUtils)) { throw new Error('CPK contractManager uninitialized'); } const address = yield this.address; if (!address) { throw new Error('CPK address uninitialized'); } return yield this.execTransactions([ { to: address, data: yield __classPrivateFieldGet(this, _CPK_contractManager, "f").versionUtils.encodeEnableModule(moduleAddress), operation: CPK.Call } ]); }); } /** * Disables a Safe module * * @param moduleAddress - The desired module address * @returns The transaction response */ disableModule(moduleAddress) { var _a; return __awaiter(this, void 0, void 0, function* () { const isProxyDeployed = yield this.isProxyDeployed(); if (!isProxyDeployed) { throw new Error('CPK Proxy contract is not deployed'); } if (!((_a = __classPrivateFieldGet(this, _CPK_contractManager, "f")) === null || _a === void 0 ? void 0 : _a.versionUtils)) { throw new Error('CPK contractManager uninitialized'); } const address = yield this.address; if (!address) { throw new Error('CPK address uninitialized'); } return yield this.execTransactions([ { to: address, data: yield __classPrivateFieldGet(this, _CPK_contractManager, "f").versionUtils.encodeDisableModule(moduleAddress), operation: CPK.Call } ]); }); } getSafeExecTxParams(transactions) { var _a, _b; if (transactions.length === 1) { return transactions_1.standardizeTransaction(transactions[0]); } if (!((_a = __classPrivateFieldGet(this, _CPK_contractManager, "f")) === null || _a === void 0 ? void 0 : _a.multiSend)) { throw new Error('CPK MultiSend uninitialized'); } return { to: (_b = __classPrivateFieldGet(this, _CPK_contractManager, "f")) === null || _b === void 0 ? void 0 : _b.multiSend.address, value: '0', data: this.encodeMultiSendCallData(transactions), operation: CPK.DelegateCall }; } } _CPK_safeAppsSdkConnector = new WeakMap(), _CPK_ethLibAdapter = new WeakMap(), _CPK_transactionManager = new WeakMap(), _CPK_contractManager = new WeakMap(), _CPK_networks = new WeakMap(), _CPK_ownerAccount = new WeakMap(), _CPK_saltNonce = new WeakMap(), _CPK_isConnectedToSafe = new WeakMap(); CPK.Call = transactions_1.OperationType.Call; CPK.DelegateCall = transactions_1.OperationType.DelegateCall; exports.default = CPK; //# sourceMappingURL=CPK.js.map