diff --git a/package.json b/package.json index b3f917b..06a7159 100644 --- a/package.json +++ b/package.json @@ -36,4 +36,4 @@ "eslint": "^8.28.0", "prettier": "^2.8.0" } -} +} \ No newline at end of file diff --git a/src/abis/ContractFactory.json b/src/abis/ContractFactory.json new file mode 100644 index 0000000..75dd180 --- /dev/null +++ b/src/abis/ContractFactory.json @@ -0,0 +1,90 @@ +[ + { + "type": "impl", + "name": "Factory", + "interface_name": "sx::factory::factory::IFactory" + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "core::result::Result::>", + "variants": [ + { + "name": "Ok", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "Err", + "type": "core::array::Array::" + } + ] + }, + { + "type": "interface", + "name": "sx::factory::factory::IFactory", + "items": [ + { + "type": "function", + "name": "deploy", + "inputs": [ + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash" + }, + { + "name": "initialize_calldata", + "type": "core::array::Span::" + }, + { + "name": "salt_nonce", + "type": "core::felt252" + } + ], + "outputs": [ + { + "type": "core::result::Result::>" + } + ], + "state_mutability": "external" + } + ] + }, + { + "type": "event", + "name": "sx::factory::factory::Factory::NewContractDeployed", + "kind": "struct", + "members": [ + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + }, + { + "name": "contract_address", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "sx::factory::factory::Factory::Event", + "kind": "enum", + "variants": [ + { + "name": "NewContractDeployed", + "type": "sx::factory::factory::Factory::NewContractDeployed", + "kind": "nested" + } + ] + } +] \ No newline at end of file diff --git a/src/abis/GenericERC20Votes.json b/src/abis/GenericERC20Votes.json new file mode 100644 index 0000000..802790b --- /dev/null +++ b/src/abis/GenericERC20Votes.json @@ -0,0 +1,558 @@ +[ + { + "type": "impl", + "name": "InitToken", + "interface_name": "sn_periphery::generic_erc20_votes::IInitializable" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "struct", + "name": "core::integer::u256", + "members": [ + { + "name": "low", + "type": "core::integer::u128" + }, + { + "name": "high", + "type": "core::integer::u128" + } + ] + }, + { + "type": "interface", + "name": "sn_periphery::generic_erc20_votes::IInitializable", + "items": [ + { + "type": "function", + "name": "initialize", + "inputs": [ + { + "name": "name", + "type": "core::byte_array::ByteArray" + }, + { + "name": "symbol", + "type": "core::byte_array::ByteArray" + }, + { + "name": "initial_supply", + "type": "core::integer::u256" + }, + { + "name": "recipient", + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "type": "impl", + "name": "ERC20MixinImpl", + "interface_name": "openzeppelin::token::erc20::interface::ERC20ABI" + }, + { + "type": "enum", + "name": "core::bool", + "variants": [ + { + "name": "False", + "type": "()" + }, + { + "name": "True", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "openzeppelin::token::erc20::interface::ERC20ABI", + "items": [ + { + "type": "function", + "name": "total_supply", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u256" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "balance_of", + "inputs": [ + { + "name": "account", + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "outputs": [ + { + "type": "core::integer::u256" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "allowance", + "inputs": [ + { + "name": "owner", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "spender", + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "outputs": [ + { + "type": "core::integer::u256" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "transfer", + "inputs": [ + { + "name": "recipient", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "amount", + "type": "core::integer::u256" + } + ], + "outputs": [ + { + "type": "core::bool" + } + ], + "state_mutability": "external" + }, + { + "type": "function", + "name": "transfer_from", + "inputs": [ + { + "name": "sender", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "recipient", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "amount", + "type": "core::integer::u256" + } + ], + "outputs": [ + { + "type": "core::bool" + } + ], + "state_mutability": "external" + }, + { + "type": "function", + "name": "approve", + "inputs": [ + { + "name": "spender", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "amount", + "type": "core::integer::u256" + } + ], + "outputs": [ + { + "type": "core::bool" + } + ], + "state_mutability": "external" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "symbol", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "decimals", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "totalSupply", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u256" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "balanceOf", + "inputs": [ + { + "name": "account", + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "outputs": [ + { + "type": "core::integer::u256" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "transferFrom", + "inputs": [ + { + "name": "sender", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "recipient", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "amount", + "type": "core::integer::u256" + } + ], + "outputs": [ + { + "type": "core::bool" + } + ], + "state_mutability": "external" + } + ] + }, + { + "type": "impl", + "name": "ERC20VotesImpl", + "interface_name": "openzeppelin::governance::utils::interfaces::votes::IVotes" + }, + { + "type": "interface", + "name": "openzeppelin::governance::utils::interfaces::votes::IVotes", + "items": [ + { + "type": "function", + "name": "get_votes", + "inputs": [ + { + "name": "account", + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "outputs": [ + { + "type": "core::integer::u256" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "get_past_votes", + "inputs": [ + { + "name": "account", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "timepoint", + "type": "core::integer::u64" + } + ], + "outputs": [ + { + "type": "core::integer::u256" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "get_past_total_supply", + "inputs": [ + { + "name": "timepoint", + "type": "core::integer::u64" + } + ], + "outputs": [ + { + "type": "core::integer::u256" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "delegates", + "inputs": [ + { + "name": "account", + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "outputs": [ + { + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "delegate", + "inputs": [ + { + "name": "delegatee", + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "delegate_by_sig", + "inputs": [ + { + "name": "delegator", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "delegatee", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "nonce", + "type": "core::felt252" + }, + { + "name": "expiry", + "type": "core::integer::u64" + }, + { + "name": "signature", + "type": "core::array::Array::" + } + ], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "type": "event", + "name": "openzeppelin::token::erc20::erc20::ERC20Component::Transfer", + "kind": "struct", + "members": [ + { + "name": "from", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "key" + }, + { + "name": "to", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "key" + }, + { + "name": "value", + "type": "core::integer::u256", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "openzeppelin::token::erc20::erc20::ERC20Component::Approval", + "kind": "struct", + "members": [ + { + "name": "owner", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "key" + }, + { + "name": "spender", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "key" + }, + { + "name": "value", + "type": "core::integer::u256", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "openzeppelin::token::erc20::erc20::ERC20Component::Event", + "kind": "enum", + "variants": [ + { + "name": "Transfer", + "type": "openzeppelin::token::erc20::erc20::ERC20Component::Transfer", + "kind": "nested" + }, + { + "name": "Approval", + "type": "openzeppelin::token::erc20::erc20::ERC20Component::Approval", + "kind": "nested" + } + ] + }, + { + "type": "event", + "name": "openzeppelin::token::erc20::extensions::erc20_votes::ERC20VotesComponent::DelegateChanged", + "kind": "struct", + "members": [ + { + "name": "delegator", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "key" + }, + { + "name": "from_delegate", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "key" + }, + { + "name": "to_delegate", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "key" + } + ] + }, + { + "type": "event", + "name": "openzeppelin::token::erc20::extensions::erc20_votes::ERC20VotesComponent::DelegateVotesChanged", + "kind": "struct", + "members": [ + { + "name": "delegate", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "key" + }, + { + "name": "previous_votes", + "type": "core::integer::u256", + "kind": "data" + }, + { + "name": "new_votes", + "type": "core::integer::u256", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "openzeppelin::token::erc20::extensions::erc20_votes::ERC20VotesComponent::Event", + "kind": "enum", + "variants": [ + { + "name": "DelegateChanged", + "type": "openzeppelin::token::erc20::extensions::erc20_votes::ERC20VotesComponent::DelegateChanged", + "kind": "nested" + }, + { + "name": "DelegateVotesChanged", + "type": "openzeppelin::token::erc20::extensions::erc20_votes::ERC20VotesComponent::DelegateVotesChanged", + "kind": "nested" + } + ] + }, + { + "type": "event", + "name": "openzeppelin::utils::cryptography::nonces::NoncesComponent::Event", + "kind": "enum", + "variants": [] + }, + { + "type": "event", + "name": "sn_periphery::generic_erc20_votes::GenericERC20Votes::Event", + "kind": "enum", + "variants": [ + { + "name": "ERC20Event", + "type": "openzeppelin::token::erc20::erc20::ERC20Component::Event", + "kind": "flat" + }, + { + "name": "ERC20VotesEvent", + "type": "openzeppelin::token::erc20::extensions::erc20_votes::ERC20VotesComponent::Event", + "kind": "flat" + }, + { + "name": "NoncesEvent", + "type": "openzeppelin::utils::cryptography::nonces::NoncesComponent::Event", + "kind": "flat" + } + ] + } +] \ No newline at end of file diff --git a/src/config.json b/src/config.json index 59c9f6d..d09c72e 100644 --- a/src/config.json +++ b/src/config.json @@ -41,6 +41,32 @@ "fn": "handleDelegateVotesChanged" } ] + }, + { + "contract": "0x0250e28c97e729842190c3672f9fcf8db0fc78b8080e87a894831dc69e4f4439", + "start": 765532, + "abi": "ContractFactory", + "events": [ + { + "name": "NewContractDeployed", + "fn": "handleContractDeployed" + } + ] + } + ], + "templates": { + "GenericERC20Votes": { + "abi": "GenericERC20Votes", + "events": [ + { + "name": "DelegateChanged", + "fn": "handleDelegateChanged" + }, + { + "name": "DelegateVotesChanged", + "fn": "handleDelegateVotesChanged" + } + ] } - ] -} + } +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 570b66b..b55a050 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,6 +9,8 @@ import * as writer from './writer'; import config from './config.json'; import Token from './abis/Token.json'; import Token2 from './abis/Token2.json'; +import ContractFactory from './abis/ContractFactory.json'; +import GenericERC20Votes from './abis/GenericERC20Votes.json'; const dir = __dirname.endsWith('dist/src') ? '../' : ''; const schemaFile = path.join(__dirname, `${dir}../src/schema.gql`); @@ -28,7 +30,7 @@ const checkpoint = new Checkpoint(config, indexer, schema, { logLevel: LogLevel.Info, resetOnConfigChange: true, prettifyLogs: process.env.NODE_ENV !== 'production', - abis: { Token, Token2 } + abis: { Token, Token2, ContractFactory, GenericERC20Votes } }); const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); diff --git a/src/writer.ts b/src/writer.ts index d2508bc..f190d9b 100644 --- a/src/writer.ts +++ b/src/writer.ts @@ -4,10 +4,12 @@ import { formatUnits } from '@ethersproject/units'; import { Delegate, Governance } from '../.checkpoint/models'; import { BIGINT_ZERO, DECIMALS, getGovernance, getDelegate } from './utils'; +const ERC20VOTES_CLASS_HASH = '0x0048b5c15aa3d4c5df35fda6d921d6e9bcb122f5f3c96c9c061931469ce6cd83'; // Address on mainnet + export const handleDelegateChanged: starknet.Writer = async ({ event, source }) => { if (!event) return; - console.log('Handle delegate changed', event); + console.log('Handle delegate changed'); const governanceId = source?.contract || ''; const fromDelegate = validateAndParseAddress(event.from_delegate); @@ -25,7 +27,7 @@ export const handleDelegateChanged: starknet.Writer = async ({ event, source }) export const handleDelegateVotesChanged: starknet.Writer = async ({ event, source }) => { if (!event) return; - console.log('Handle delegate votes changed', event); + console.log('Handle delegate votes changed'); const governanceId = source?.contract || ''; const governance: Governance = await getGovernance(governanceId); @@ -49,3 +51,19 @@ export const handleDelegateVotesChanged: starknet.Writer = async ({ event, sourc await governance.save(); }; + +export const handleContractDeployed: starknet.Writer = async ({ blockNumber, event, instance }) => { + console.log("Handle contract deployed"); + + if (!event) return; + const paddedClassHash = validateAndParseAddress(event.class_hash); + + if (paddedClassHash === ERC20VOTES_CLASS_HASH) { + await instance.executeTemplate('GenericERC20Votes', { + contract: event.contract_address, + start: blockNumber + }); + } else { + console.log('Unknown class hash', paddedClassHash); + } +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index b431a80..3999b9c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3596,4 +3596,4 @@ yocto-queue@^0.1.0: zod@^3.21.4: version "3.22.2" resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.2.tgz#3add8c682b7077c05ac6f979fea6998b573e157b" - integrity sha512-wvWkphh5WQsJbVk1tbx1l1Ly4yg+XecD+Mq280uBGt9wa5BKSWf4Mhp6GmrkPixhMxmabYY7RbzlwVP32pbGCg== + integrity sha512-wvWkphh5WQsJbVk1tbx1l1Ly4yg+XecD+Mq280uBGt9wa5BKSWf4Mhp6GmrkPixhMxmabYY7RbzlwVP32pbGCg== \ No newline at end of file