UNPKG

bitcore-node

Version:

A blockchain indexing node with extended capabilities using bitcore

183 lines 8.34 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Gnosis = exports.GnosisApi = void 0; const stream_1 = require("stream"); const __1 = require("../../"); const config_1 = require("../../../../services/config"); const multisig_1 = require("../abi/multisig"); const multisigTransform_1 = require("../api/multisigTransform"); const populateEffectsTransform_1 = require("../api/populateEffectsTransform"); const populateReceiptTransform_1 = require("../api/populateReceiptTransform"); const transform_1 = require("../api/transform"); const block_1 = require("../models/block"); const transaction_1 = require("../models/transaction"); function getCSP(chain, network) { return __1.ChainStateProvider.get({ chain, network }); } class GnosisApi { constructor() { this.gnosisFactories = { 'ETH': { testnet: '0x2C992817e0152A65937527B774c7A99a84603045', mainnet: '0x6e95C8E8557AbC08b46F3c347bA06F8dC012763f' }, 'MATIC': { mainnet: '0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2' } }; this.MULTISIG_TX_PROPOSAL_EXPIRE_TIME = 48 * 3600 * 1000; } async multisigFor(chain, network, address) { const { web3 } = await getCSP(chain, network).getWeb3(network); const contract = new web3.eth.Contract(multisig_1.MultisigAbi, address); return contract; } async getMultisigContractInstantiationInfo(chain, network, sender, txId) { const { web3 } = await getCSP(chain, network).getWeb3(network); const networkConfig = config_1.Config.chainConfig({ chain: 'ETH', network }); const { gnosisFactory = this.gnosisFactories[chain][network] } = networkConfig; let query = { chain, network, txid: txId }; const found = await transaction_1.EVMTransactionStorage.collection.findOne(query); const blockHeight = found && found.blockHeight ? found.blockHeight : null; if (!blockHeight || blockHeight < 0) return Promise.resolve([]); const contract = await this.multisigFor(chain, network, gnosisFactory); const contractInfo = await contract.getPastEvents('ContractInstantiation', { fromBlock: web3.utils.toHex(blockHeight), toBlock: web3.utils.toHex(blockHeight) }); return this.convertMultisigContractInstantiationInfo(contractInfo.filter(info => info.returnValues.sender.toLowerCase() === sender.toLowerCase())); } convertMultisigContractInstantiationInfo(contractInstantiationInfo) { return contractInstantiationInfo.map(this.convertContractInstantiationInfo); } convertContractInstantiationInfo(transfer) { const { blockHash, blockNumber, transactionHash, returnValues, transactionIndex } = transfer; return { blockHash, blockNumber, transactionHash, transactionIndex, hash: transactionHash, sender: returnValues['sender'], instantiation: returnValues['instantiation'] }; } async getMultisigTxpsInfo(chain, network, multisigContractAddress) { const contract = await this.multisigFor(chain, network, multisigContractAddress); const time = Math.floor(Date.now()) - this.MULTISIG_TX_PROPOSAL_EXPIRE_TIME; const [block] = await block_1.EVMBlockStorage.collection .find({ chain, network, timeNormalized: { $gte: new Date(time) } }) .limit(1) .toArray(); const blockHeight = block.height; const [confirmationInfo, revocationInfo, executionInfo, executionFailure] = await Promise.all([ contract.getPastEvents('Confirmation', { fromBlock: blockHeight, toBlock: 'latest' }), contract.getPastEvents('Revocation', { fromBlock: blockHeight, toBlock: 'latest' }), contract.getPastEvents('Execution', { fromBlock: blockHeight, toBlock: 'latest' }), contract.getPastEvents('ExecutionFailure', { fromBlock: blockHeight, toBlock: 'latest' }) ]); const executionTransactionIdArray = executionInfo.map(i => i.returnValues.transactionId); const contractTransactionsInfo = [...confirmationInfo, ...revocationInfo, ...executionFailure]; const multisigTxpsInfo = contractTransactionsInfo.filter(i => !executionTransactionIdArray.includes(i.returnValues.transactionId)); return this.convertMultisigTxpsInfo(multisigTxpsInfo); } convertMultisigTxpsInfo(multisigTxpsInfo) { return multisigTxpsInfo.map(this.convertTxpsInfo); } convertTxpsInfo(transfer) { const { blockHash, blockNumber, transactionHash, returnValues, transactionIndex, event } = transfer; return { blockHash, blockNumber, transactionHash, transactionIndex, hash: transactionHash, sender: returnValues['sender'], transactionId: returnValues['transactionId'], event }; } async getMultisigInfo(chain, network, multisigContractAddress) { const contract = await this.multisigFor(chain, network, multisigContractAddress); const owners = await contract.methods.getOwners().call(); const required = await contract.methods.required().call(); return { owners, required }; } async streamGnosisWalletTransactions(params) { const { chain, network, multisigContractAddress, res, args } = params; const transactionQuery = getCSP(chain, network).getWalletTransactionQuery(params); delete transactionQuery.wallets; delete transactionQuery['wallets.0']; let query; if (args.tokenAddress) { query = { $or: [ { ...transactionQuery, to: args.tokenAddress, 'abiType.params.0.value': multisigContractAddress.toLowerCase() }, { ...transactionQuery, 'internal.action.to': args.tokenAddress.toLowerCase(), 'internal.action.from': multisigContractAddress.toLowerCase() }, { ...transactionQuery, 'effects.contractAddress': args.tokenAddress, 'effects.from': multisigContractAddress } ] }; } else { query = { $or: [ { ...transactionQuery, to: multisigContractAddress }, { ...transactionQuery, 'internal.action.to': multisigContractAddress.toLowerCase() }, { ...transactionQuery, 'effects.to': multisigContractAddress } ] }; } let transactionStream = new stream_1.Readable({ objectMode: true }); const ethTransactionTransform = new transform_1.EVMListTransactionsStream([multisigContractAddress, args.tokenAddress]); const populateReceipt = new populateReceiptTransform_1.PopulateReceiptTransform(); const populateEffects = new populateEffectsTransform_1.PopulateEffectsTransform(); transactionStream = transaction_1.EVMTransactionStorage.collection .find(query) .sort({ blockTimeNormalized: 1 }) .addCursorFlag('noCursorTimeout', true); transactionStream = transactionStream.pipe(populateEffects); // For old db entires if (multisigContractAddress) { const multisigTransform = new multisigTransform_1.MultisigRelatedFilterTransform(multisigContractAddress, args.tokenAddress); transactionStream = transactionStream.pipe(multisigTransform); } transactionStream .pipe(populateReceipt) .pipe(ethTransactionTransform) .pipe(res); } } exports.GnosisApi = GnosisApi; exports.Gnosis = new GnosisApi(); //# sourceMappingURL=gnosis.js.map