Skip to content

Commit

Permalink
feat: mv helper utils
Browse files Browse the repository at this point in the history
  • Loading branch information
ponyjackal committed Jan 25, 2024
1 parent 1da57d9 commit c5b1da1
Show file tree
Hide file tree
Showing 25 changed files with 801 additions and 2,347 deletions.
342 changes: 337 additions & 5 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
"dotenv": "^16.3.1",
"handlebars": "^4.7.8",
"path": "^0.12.7",
"viem": "^1.19.13"
"viem": "^1.19.13",
"web3-utils": "^4.1.1"
}
}
91 changes: 63 additions & 28 deletions src/transformers/helpers/constants.ts → src/helpers/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,9 @@ export const ERC1155_METHOD_SIGNATURES = [
'safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)',
];

export const ERC1155_METHODS = createSignatureMapping(ERC1155_METHOD_SIGNATURES);
export const ERC1155_METHODS = createSignatureMapping(
ERC1155_METHOD_SIGNATURES,
);

//https://eips.ethereum.org/EIPS/eip-165
export const ERC165_METHOD_SIGNATURES = ['supportsInterface(bytes4)'];
Expand All @@ -118,8 +120,11 @@ export const ERC165_METHODS = createSignatureMapping(ERC165_METHOD_SIGNATURES);

// Contract Addresses
export const OPENSEA_REGISTRY_SIGNATURES = ['registerProxy()'];
export const OPENSEA_REGISTRY_METHODS = createSignatureMapping(OPENSEA_REGISTRY_SIGNATURES);
export const OPENSEA_REGISTRY_ADDRESS = '0xa5409ec958c83c3f309868babaca7c86dcb077c1';
export const OPENSEA_REGISTRY_METHODS = createSignatureMapping(
OPENSEA_REGISTRY_SIGNATURES,
);
export const OPENSEA_REGISTRY_ADDRESS =
'0xa5409ec958c83c3f309868babaca7c86dcb077c1';

// Gnosis Safe
export const GNOSIS_SAFE_FACTORY_METHOD_SIGNATURES = [
Expand All @@ -128,13 +133,20 @@ export const GNOSIS_SAFE_FACTORY_METHOD_SIGNATURES = [
'createProxyWithCallback(address,bytes,uint256,address)',
];

export const GNOSIS_SAFE_FACTORY_METHODS = createSignatureMapping(GNOSIS_SAFE_FACTORY_METHOD_SIGNATURES);
export const GNOSIS_SAFE_FACTORY_METHODS = createSignatureMapping(
GNOSIS_SAFE_FACTORY_METHOD_SIGNATURES,
);

export const GNOSIS_SAFE_FACTORY_0_1_0_ADDRESS = '0x88cd603a5dc47857d02865bbc7941b588c533263'; // Not used often
export const GNOSIS_SAFE_FACTORY_1_0_0_ADDRESS = '0x12302fe9c02ff50939baaaaf415fc226c078613c'; // This release appears to have been buggy and didn't deploy contracts often
export const GNOSIS_SAFE_FACTORY_1_0_1_ADDRESS = '0x50e55af101c777ba7a1d560a774a82ef002ced9f'; // Not used often
export const GNOSIS_SAFE_FACTORY_1_1_1_ADDRESS = '0x76e2cfc1f5fa8f6a5b3fc4c8f4788f0116861f9b';
export const GNOSIS_SAFE_FACTORY_1_3_0_ADDRESS = '0xa6b71e26c5e0845f74c812102ca7114b6a896ab2';
export const GNOSIS_SAFE_FACTORY_0_1_0_ADDRESS =
'0x88cd603a5dc47857d02865bbc7941b588c533263'; // Not used often
export const GNOSIS_SAFE_FACTORY_1_0_0_ADDRESS =
'0x12302fe9c02ff50939baaaaf415fc226c078613c'; // This release appears to have been buggy and didn't deploy contracts often
export const GNOSIS_SAFE_FACTORY_1_0_1_ADDRESS =
'0x50e55af101c777ba7a1d560a774a82ef002ced9f'; // Not used often
export const GNOSIS_SAFE_FACTORY_1_1_1_ADDRESS =
'0x76e2cfc1f5fa8f6a5b3fc4c8f4788f0116861f9b';
export const GNOSIS_SAFE_FACTORY_1_3_0_ADDRESS =
'0xa6b71e26c5e0845f74c812102ca7114b6a896ab2';

export const KNOWN_ADDRESSES = {
CryptoKitties: '0x06012c8cf97bead5deae237070f9587f8e7a266d', // Meow
Expand All @@ -155,10 +167,12 @@ const createEventSignatureMapping = (signatures: string[]) => {
};

// https://eips.ethereum.org/EIPS/eip-1967
export const TRANSPARENT_UPGRADEABLE_PROXY_EVENT_SIGNATURES = ['Upgraded(address)'];
export const TRANSPARENT_UPGRADEABLE_PROXY_EVENT_SIGNATURES = [
'Upgraded(address)',
];

export const TRANSPARENT_UPGRADEABLE_PROXY_EVENTS = createEventSignatureMapping(
TRANSPARENT_UPGRADEABLE_PROXY_EVENT_SIGNATURES
TRANSPARENT_UPGRADEABLE_PROXY_EVENT_SIGNATURES,
);

export const ERC20ABI: AbiItem[] = [
Expand Down Expand Up @@ -251,26 +265,38 @@ export const INTERFACE_IDS = {
ERC777TokensRecipient: '0x9a20483d',
};

export const GENERIC_GOVERNANCE_INTERFACES = ['0xbf26d897', '0x79dd796f', '0x3938f78a'];
export const GENERIC_GOVERNANCE_INTERFACES = [
'0xbf26d897',
'0x79dd796f',
'0x3938f78a',
];

export const UNISWAP_V3_FACTORY = '0x1f98431c8ad98523631ae4a59f267346ea31f984';
export const UNISWAP_V2_FACTORY = '0x5c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f';
export const UNISWAP_V1_FACTORY = '0xc0a47dfe034b400b47bdad5fecda2621de6c4d95';
export const PROP_HOUSE_PROXY_CONTRACT = '0xd310a3041dfcf14def5ccbc508668974b5da7174';
export const PROP_HOUSE_IMPLEMENTATION_CONTRACT = '0x138d8aef5cbbbb9ea8da98cc0847fe0f3b573b40';

export const UNISWAP_V3_POOL_CREATED_EVENT_HASH = '0x783cca1c0412dd0d695e784568c96da2e9c22ff989357a2e8b1d9b2b4e6b7118';
export const UNISWAP_V2_PAIR_CREATED_EVENT_HASH = '0x0d3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31afa28d0e9';
export const UNISWAP_V1_NEW_EXCHANGE_EVENT_HASH = '0x9d42cb017eb05bd8944ab536a8b35bc68085931dd5f4356489801453923953f9';

export const UNISWAP_V1_NEW_EXCHANGE_EVENT = 'event NewExchange(address,address)';
export const PROP_HOUSE_PROXY_CONTRACT =
'0xd310a3041dfcf14def5ccbc508668974b5da7174';
export const PROP_HOUSE_IMPLEMENTATION_CONTRACT =
'0x138d8aef5cbbbb9ea8da98cc0847fe0f3b573b40';

export const UNISWAP_V3_POOL_CREATED_EVENT_HASH =
'0x783cca1c0412dd0d695e784568c96da2e9c22ff989357a2e8b1d9b2b4e6b7118';
export const UNISWAP_V2_PAIR_CREATED_EVENT_HASH =
'0x0d3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31afa28d0e9';
export const UNISWAP_V1_NEW_EXCHANGE_EVENT_HASH =
'0x9d42cb017eb05bd8944ab536a8b35bc68085931dd5f4356489801453923953f9';

export const UNISWAP_V1_NEW_EXCHANGE_EVENT =
'event NewExchange(address,address)';
export const UNISWAP_V2_PAIR_CREATED_EVENT =
'event PairCreated(address indexed token0, address indexed token1, address pair, uint)';
export const UNISWAP_V3_POOL_CREATED_EVENT =
'event PoolCreated(address indexed token0, address indexed token1, uint24 indexed fee, int24 tickSpacing, address pool)';

export const PROP_HOUSE_DAO_DEPLOYED_EVENT_HASH = '0x456d2baf5a87d70e586ec06fb91c2d7849778dd41d80fa826a6ea5bf8d28e3a6';
export const PROP_HOUSE_DAO_DEPLOYED_EVENT = 'event DAODeployed(address,address,address,address,address)';
export const PROP_HOUSE_DAO_DEPLOYED_EVENT_HASH =
'0x456d2baf5a87d70e586ec06fb91c2d7849778dd41d80fa826a6ea5bf8d28e3a6';
export const PROP_HOUSE_DAO_DEPLOYED_EVENT =
'event DAODeployed(address,address,address,address,address)';

// https://docs.openzeppelin.com/contracts/4.x/api/governance#IGovernor
export const GOVERNOR_METHOD_SIGNATURES = [
Expand All @@ -292,7 +318,9 @@ export const GOVERNOR_METHOD_SIGNATURES = [
'castVoteWithReason(uint256,uint8,string)',
'castVoteBySig(uint256,uint8,uint8,bytes32,bytes32)',
];
export const GOVERNOR_METHODS = createSignatureMapping(GOVERNOR_METHOD_SIGNATURES);
export const GOVERNOR_METHODS = createSignatureMapping(
GOVERNOR_METHOD_SIGNATURES,
);

export const TOKEN_SWAP_CONTRACTS = [
'0xe592427a0aece92de3edee1f18e0157c05861564', // Uniswap V3 Router
Expand Down Expand Up @@ -388,9 +416,16 @@ export const OLD_NFT_ADDRESSES = [
'0x323a3e1693e7a0959f65972f3bf2dfcb93239dfe', // Digital Art Chain
'0x552d72f86f04098a4eaeda6d7b665ac12f846ad2', // Dark Winds
];
export const ERC721_TRANSFER_EVENT_1 = 'event Transfer(address indexed,address indexed,uint256)';
export const ERC721_TRANSFER_EVENT_2 = 'event Transfer(address,address,uint256)';

export const PROXY_IMPLEMENTATION_METHOD_SIGNATURES = ['implementation()', 'IMPL()'];
export const ERC721_TRANSFER_EVENT_1 =
'event Transfer(address indexed,address indexed,uint256)';
export const ERC721_TRANSFER_EVENT_2 =
'event Transfer(address,address,uint256)';

export const PROXY_IMPLEMENTATION_METHOD_SIGNATURES = [
'implementation()',
'IMPL()',
];

export const PROXY_IMPLEMENTATION_METHODS = createSignatureMapping(PROXY_IMPLEMENTATION_METHOD_SIGNATURES);
export const PROXY_IMPLEMENTATION_METHODS = createSignatureMapping(
PROXY_IMPLEMENTATION_METHOD_SIGNATURES,
);
172 changes: 158 additions & 14 deletions src/helpers/utils.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,162 @@
import {
ERC20_METHODS,
ERC777_METHODS,
ERC721_METHODS,
ERC1155_METHODS,
ERC165_METHODS,
GOVERNOR_METHODS,
SAFE_METHODS,
} from './constants';
import { RawBlock, StdObj } from '../types';

export const makeTransform = (
children: Record<string, (transaction: any) => any>,
) => {
return (transaction: any): any => {
for (const childTransformer of Object.values(children)) {
const result = childTransformer(transaction);
if (result) {
return result;
}
children: Record<string, (transaction: any) => any>,
) => {
return (transaction: any): any => {
for (const childTransformer of Object.values(children)) {
const result = childTransformer(transaction);
if (result) {
return result;
}
return transaction;
};
}
return transaction;
};
};

export function shortenTxHash(hash: string): string {
if (hash.length <= 10) return hash;
return hash.substr(0, 6) + hash.substr(-4);
}

// monkey-patch BigInt to serialize as JSON
// more context here: https://github.com/GoogleChromeLabs/jsbi/issues/30
(BigInt.prototype as any).toJSON = function () {
return this.toString();
};

export const bytecodeIsERC = (
standard: Record<string, string>,
bytecode: string,
): boolean => {
const ercMethodsDetected = Object.keys(standard).filter(
(key: string): boolean => bytecode.includes(standard[key]),
);
return ercMethodsDetected.length == Object.keys(standard).length;
};

export const bytecodeIsERC20 = (bytecode: string): boolean =>
bytecodeIsERC(ERC20_METHODS, bytecode);
export const bytecodeIsERC777 = (bytecode: string): boolean =>
bytecodeIsERC(ERC777_METHODS, bytecode);
export const bytecodeIsERC721 = (bytecode: string): boolean =>
bytecodeIsERC(ERC721_METHODS, bytecode);
export const bytecodeIsERC1155 = (bytecode: string): boolean =>
bytecodeIsERC(ERC1155_METHODS, bytecode);
export const bytecodeIsERC165 = (bytecode: string): boolean =>
bytecodeIsERC(ERC165_METHODS, bytecode);
export const bytecodeIsIGovernor = (bytecode: string): boolean =>
bytecodeIsERC(GOVERNOR_METHODS, bytecode);
export const bytecodeIsGnosisSafe = (bytecode: string): boolean =>
bytecodeIsERC(SAFE_METHODS, bytecode);

export const normalizeBlock = (block: StdObj): RawBlock => {
// console.log('block', block);

let str = JSON.stringify(block);

// replace all EVM addresses with lowercased versions
str = str.replace(/("0x[A-z0-9]{40}")/g, (v) => v.toLowerCase());

return JSON.parse(str) as RawBlock;
};

const VALID_CHARS =
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890.? ';

export const countValidChars = (stringToCount: string) => {
let count = 0;
for (let i = 0; i < stringToCount.length; i++) {
if (VALID_CHARS.indexOf(stringToCount[i]) >= 0) {
count++;
}
}
return count;
};

export const convertToString = (value: any): string => {
// Check if the value is not null or undefined, and it has a toString() method.
if (
value !== null &&
value !== undefined &&
typeof value?.toString === 'function'
) {
return value.toString();
} else {
// Return an empty string if the value is not convertible to a string.
return '';
}
};

export function splitStringIntoChunks(
inputString: string,
chunkSize: number,
): string[] {
const chunks: string[] = [];
for (let i = 0; i < inputString.length; i += chunkSize) {
chunks.push(inputString.slice(i, i + chunkSize));
}
return chunks;
}

export function objectToDotNotation(
obj: Record<string, unknown>,
current?: string,
) {
if (!obj || typeof obj !== 'object') {
return obj;
}

const newObj = {};

for (const key in obj) {
const val = obj[key];
const newKey = current ? `${current}.${key}` : key;
if (val && typeof val === 'object') {
Object.assign(
newObj,
objectToDotNotation(val as Record<string, unknown>, newKey),
);
} else {
newObj[newKey] = val;
}
}

return newObj;
}

export const getTokenName = async (token): Promise<string> => {
try {
return (await token.methods.name().call()) as string;
} catch (error) {
console.log(`Name method not implemented.`);
return '';
}
};

export const getTokenSymbol = async (token): Promise<string> => {
try {
return (await token.methods.symbol().call()) as string;
} catch (error) {
console.log('Symbol method not implemented.');
return '';
}
};

export function shortenTxHash(hash: string): string {
if (hash.length <= 10) return hash;
return hash.substr(0, 6) + hash.substr(-4);
}
export const getTokenDecimals = async (token): Promise<number> => {
try {
return (await token.methods.decimals().call()) as number;
} catch (error) {
console.log('Decimals method not implemented.');
return 18;
}
};
2 changes: 1 addition & 1 deletion src/transformers/_common/transactionAssetTransfers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Web3 from 'web3';

import { decodeEVMAddress, toBigNumber } from '../helpers/utils';
import type { AssetTransfer, RawBlock, RawTransaction } from '../types';
import { KNOWN_ADDRESSES } from '../helpers/constants';
import { KNOWN_ADDRESSES } from '../../helpers/constants';

// 1. pull out token transfers from logs
// 2. pull out ETH transfers from traces (this covers tx.value transfers)
Expand Down
2 changes: 1 addition & 1 deletion src/transformers/_common/transactionProxyUpgrades.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { RawBlock, RawTransaction } from '../types';
import { TRANSPARENT_UPGRADEABLE_PROXY_EVENTS } from '../helpers/constants';
import { TRANSPARENT_UPGRADEABLE_PROXY_EVENTS } from '../../helpers/constants';
import { decodeEVMAddress } from '../helpers/utils';

type ProxyUpgrade = { hash: string; address: string; upgradedAddress: string };
Expand Down
2 changes: 1 addition & 1 deletion src/transformers/ethereum/blockFork.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { RawBlock } from '../types';
import { FORKS } from '../helpers/constants';
import { FORKS } from '../../helpers/constants';

export function transform(block: RawBlock) {
let fork: string;
Expand Down
2 changes: 1 addition & 1 deletion src/transformers/ethereum/contractPropHouseDetection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
PROP_HOUSE_PROXY_CONTRACT,
PROP_HOUSE_DAO_DEPLOYED_EVENT_HASH,
PROP_HOUSE_DAO_DEPLOYED_EVENT,
} from '../helpers/constants';
} from '../../helpers/constants';

export function transform(block: RawBlock): TransactionContract[] {
const result: TransactionContract[] = block.transactions
Expand Down
2 changes: 1 addition & 1 deletion src/transformers/ethereum/contractUniswapDetection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
UNISWAP_V1_NEW_EXCHANGE_EVENT_HASH,
UNISWAP_V2_PAIR_CREATED_EVENT_HASH,
UNISWAP_V3_POOL_CREATED_EVENT_HASH,
} from '../helpers/constants';
} from '../../helpers/constants';

export function transform(block: RawBlock): TransactionContract[] {
const result: TransactionContract[] = block.transactions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
OLD_NFT_ADDRESSES,
ERC721_TRANSFER_EVENT_1,
ERC721_TRANSFER_EVENT_2,
} from '../helpers/constants';
} from '../../helpers/constants';
import { decodeEvent } from '../helpers/sigMapper';

const TRANSFER_SIGNATURES = {
Expand Down
2 changes: 1 addition & 1 deletion src/transformers/ethereum/transactionFees.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { RawBlock, RawTransaction } from '../types';
import { toBigNumber } from '../helpers/utils';
import { FORKS } from '../helpers/constants';
import { FORKS } from '../../helpers/constants';

export function transform(block: RawBlock) {
const newTxs: Partial<RawTransaction>[] = [];
Expand Down
Loading

0 comments on commit c5b1da1

Please sign in to comment.