2021-09-29 04:34:09 +00:00
|
|
|
//
|
|
|
|
// Copyright 2021 Vulcanize, Inc.
|
|
|
|
//
|
|
|
|
|
|
|
|
import assert from 'assert';
|
2021-10-12 10:32:56 +00:00
|
|
|
|
2021-10-20 12:25:54 +00:00
|
|
|
import { UNKNOWN_EVENT_NAME, updateStateForMappingType, updateStateForElementaryType } from '@vulcanize/util';
|
2021-09-29 04:34:09 +00:00
|
|
|
|
|
|
|
import { Indexer, ResultEvent } from './indexer';
|
2021-10-12 10:32:56 +00:00
|
|
|
|
|
|
|
const ACCOUNTS = [
|
2021-10-29 11:33:22 +00:00
|
|
|
'0xDC7d7A8920C8Eecc098da5B7522a5F31509b5Bfc',
|
|
|
|
'0xCA6D29232D1435D8198E3E5302495417dD073d61'
|
2021-10-12 10:32:56 +00:00
|
|
|
];
|
|
|
|
|
|
|
|
/**
|
2021-12-22 09:42:14 +00:00
|
|
|
* Hook function to store an initial state.
|
2021-10-12 10:32:56 +00:00
|
|
|
* @param indexer Indexer instance.
|
2021-12-22 09:42:14 +00:00
|
|
|
* @param blockHash Hash of the concerned block.
|
2021-10-12 10:32:56 +00:00
|
|
|
* @param contractAddress Address of the concerned contract.
|
2021-12-22 09:42:14 +00:00
|
|
|
* @returns Data block to be stored.
|
2021-10-12 10:32:56 +00:00
|
|
|
*/
|
2021-12-22 09:42:14 +00:00
|
|
|
export async function createInitialState (indexer: Indexer, contractAddress: string, blockHash: string): Promise<any> { assert(indexer);
|
2021-10-20 12:25:54 +00:00
|
|
|
assert(indexer);
|
2021-10-26 11:40:03 +00:00
|
|
|
assert(blockHash);
|
2021-10-20 12:25:54 +00:00
|
|
|
assert(contractAddress);
|
|
|
|
|
2021-10-18 09:20:41 +00:00
|
|
|
// Store the initial state values in an IPLDBlock.
|
2021-10-20 12:25:54 +00:00
|
|
|
let ipldBlockData: any = {};
|
2021-10-12 10:32:56 +00:00
|
|
|
|
|
|
|
// Setting the initial balances of accounts.
|
|
|
|
for (const account of ACCOUNTS) {
|
2021-10-26 11:40:03 +00:00
|
|
|
const balance = await indexer._balances(blockHash, contractAddress, account);
|
2021-10-20 12:25:54 +00:00
|
|
|
ipldBlockData = updateStateForMappingType(ipldBlockData, '_balances', [account], balance.value.toString());
|
2021-10-12 10:32:56 +00:00
|
|
|
}
|
|
|
|
|
2021-12-22 09:42:14 +00:00
|
|
|
// Return initial state data to be saved.
|
|
|
|
return ipldBlockData;
|
2021-10-12 10:32:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2021-12-22 09:42:14 +00:00
|
|
|
* Hook function to create state diff.
|
2021-10-12 10:32:56 +00:00
|
|
|
* @param indexer Indexer instance that contains methods to fetch the contract varaiable values.
|
|
|
|
* @param blockHash Block hash of the concerned block.
|
|
|
|
*/
|
2021-10-20 12:25:54 +00:00
|
|
|
export async function createStateDiff (indexer: Indexer, blockHash: string): Promise<void> {
|
|
|
|
assert(indexer);
|
|
|
|
assert(blockHash);
|
|
|
|
|
2021-10-12 10:32:56 +00:00
|
|
|
// Get events for current block and make an entry of updated values in IPLDBlock.
|
|
|
|
const events = await indexer.getEventsByFilter(blockHash);
|
|
|
|
|
|
|
|
// No IPLDBlock entry if there are no events.
|
|
|
|
if (!events) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const event of events) {
|
|
|
|
if (event.eventName === UNKNOWN_EVENT_NAME) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
const contractAddress = event.contract;
|
|
|
|
|
|
|
|
const eventData = indexer.getResultEvent(event);
|
|
|
|
|
2021-10-20 12:25:54 +00:00
|
|
|
let ipldBlockData: any = {};
|
2021-10-12 10:32:56 +00:00
|
|
|
|
|
|
|
switch (event.eventName) {
|
|
|
|
case 'Transfer': {
|
|
|
|
const { from, to } = eventData.event;
|
|
|
|
|
|
|
|
const fromBalance = await indexer._balances(blockHash, contractAddress, from);
|
|
|
|
const toBalance = await indexer._balances(blockHash, contractAddress, to);
|
|
|
|
|
|
|
|
// {
|
|
|
|
// "_balances": {
|
|
|
|
// "0xCA6D29232D1435D8198E3E5302495417dD073d61": "100",
|
|
|
|
// "0xDC7d7A8920C8Eecc098da5B7522a5F31509b5Bfc": "999999999999999999900"
|
|
|
|
// }
|
|
|
|
// }
|
2021-10-20 12:25:54 +00:00
|
|
|
ipldBlockData = updateStateForMappingType(ipldBlockData, '_balances', [from], fromBalance.value.toString());
|
|
|
|
ipldBlockData = updateStateForMappingType(ipldBlockData, '_balances', [to], toBalance.value.toString());
|
2021-10-12 10:32:56 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 'Approval': {
|
|
|
|
const { owner, spender } = eventData.event;
|
|
|
|
const allowance = await indexer._allowances(blockHash, contractAddress, owner, spender);
|
|
|
|
|
|
|
|
// {
|
|
|
|
// "_allowances": {
|
|
|
|
// "0xDC7d7A8920C8Eecc098da5B7522a5F31509b5Bfc": {
|
|
|
|
// "0xCA6D29232D1435D8198E3E5302495417dD073d61": "10"
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
2021-10-20 12:25:54 +00:00
|
|
|
ipldBlockData = updateStateForMappingType(ipldBlockData, '_allowances', [owner, spender], allowance.value.toString());
|
2021-10-12 10:32:56 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-22 09:42:14 +00:00
|
|
|
// Use indexer.createStateDiff() method to create a custom state.
|
2021-10-26 11:40:03 +00:00
|
|
|
await indexer.createDiff(contractAddress, blockHash, ipldBlockData);
|
2021-10-12 10:32:56 +00:00
|
|
|
}
|
|
|
|
}
|
2021-09-29 04:34:09 +00:00
|
|
|
|
2021-10-29 11:33:22 +00:00
|
|
|
/**
|
|
|
|
* Hook function to create state checkpoint
|
|
|
|
* @param indexer Indexer instance.
|
|
|
|
* @param contractAddress Address of the concerned contract.
|
|
|
|
* @param blockHash Block hash of the concerned block.
|
|
|
|
* @returns Whether to disable default checkpoint. If false, the state from this hook is updated with that from default checkpoint.
|
|
|
|
*/
|
|
|
|
export async function createStateCheckpoint (indexer: Indexer, contractAddress: string, blockHash: string): Promise<boolean> {
|
|
|
|
assert(indexer);
|
|
|
|
assert(blockHash);
|
|
|
|
assert(contractAddress);
|
|
|
|
|
|
|
|
let ipldBlockData: any = {};
|
|
|
|
|
|
|
|
// Setting the balances of accounts.
|
|
|
|
for (const account of ACCOUNTS) {
|
|
|
|
const balance = await indexer._balances(blockHash, contractAddress, account);
|
|
|
|
ipldBlockData = updateStateForMappingType(ipldBlockData, '_balances', [account], balance.value.toString());
|
|
|
|
}
|
|
|
|
|
2021-12-22 09:42:14 +00:00
|
|
|
// Use indexer.createStateCheckpoint() method to create a custom checkpoint.
|
2021-10-29 11:33:22 +00:00
|
|
|
await indexer.createCheckpoint(contractAddress, blockHash, ipldBlockData);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-09-29 04:34:09 +00:00
|
|
|
/**
|
|
|
|
* Event hook function.
|
|
|
|
* @param indexer Indexer instance that contains methods to fetch and update the contract values in the database.
|
2021-12-22 09:42:14 +00:00
|
|
|
* @param eventData ResultEvent object containing event information.
|
2021-09-29 04:34:09 +00:00
|
|
|
*/
|
|
|
|
export async function handleEvent (indexer: Indexer, eventData: ResultEvent): Promise<void> {
|
|
|
|
assert(indexer);
|
|
|
|
assert(eventData);
|
|
|
|
|
2021-10-12 10:32:56 +00:00
|
|
|
// The following code is for ERC20 contract implementation.
|
|
|
|
|
2021-09-29 04:34:09 +00:00
|
|
|
// Perform indexing based on the type of event.
|
2021-10-12 10:32:56 +00:00
|
|
|
switch (eventData.event.__typename) {
|
|
|
|
// In case of ERC20 'Transfer' event.
|
|
|
|
case 'TransferEvent': {
|
|
|
|
// On a transfer, balances for both parties change.
|
|
|
|
// Therefore, trigger indexing for both sender and receiver.
|
|
|
|
|
|
|
|
// Get event fields from eventData.
|
2021-10-18 09:20:41 +00:00
|
|
|
const { from, to } = eventData.event;
|
2021-10-12 10:32:56 +00:00
|
|
|
|
|
|
|
// Update balance entry for sender in the database.
|
2021-10-20 12:25:54 +00:00
|
|
|
await indexer._balances(eventData.block.hash, eventData.contract, from);
|
2021-10-12 10:32:56 +00:00
|
|
|
|
|
|
|
// Update balance entry for receiver in the database.
|
2021-10-20 12:25:54 +00:00
|
|
|
await indexer._balances(eventData.block.hash, eventData.contract, to);
|
2021-10-12 10:32:56 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// In case of ERC20 'Approval' event.
|
|
|
|
case 'ApprovalEvent': {
|
|
|
|
// On an approval, allowance for (owner, spender) combination changes.
|
|
|
|
|
|
|
|
// Get event fields from eventData.
|
2021-10-18 09:20:41 +00:00
|
|
|
const { owner, spender } = eventData.event;
|
2021-10-12 10:32:56 +00:00
|
|
|
|
|
|
|
// Update allowance entry for (owner, spender) combination in the database.
|
2021-10-20 12:25:54 +00:00
|
|
|
await indexer._allowances(eventData.block.hash, eventData.contract, owner, spender);
|
2021-10-12 10:32:56 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2021-09-29 04:34:09 +00:00
|
|
|
}
|