bitcore-node
Version:
A blockchain indexing node with extended capabilities using bitcore
183 lines • 8.34 kB
JavaScript
;
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