diff --git a/substreams/ethereum-curve/README.md b/substreams/ethereum-curve/README.md index fec075b..2bcc243 100644 --- a/substreams/ethereum-curve/README.md +++ b/substreams/ethereum-curve/README.md @@ -1,8 +1,11 @@ # Instructions -The run command for our substream is a little different here due to the inclusion of the dynamic parameters for manually admitted pools. +The run command for our substream is a little different here due to the inclusion of the dynamic parameters for manually +admitted pools. -This command will add extra parameters to the `map_components` module via the `python params.py` script. This embeds directly in the bash/zsh compatible command here. If `python` is not ideal, the script can be easily converted into `bash` but it would require the `jq` executable (I've used AI to convert it just fine in testing). +This command will add extra parameters to the `map_components` module via the `python params.py` script. This embeds +directly in the bash/zsh compatible command here. If `python` is not ideal, the script can be easily converted into +`bash` but it would require the `jq` executable (I've used AI to convert it just fine in testing). ```bash $ substreams run -e mainnet.eth.streamingfast.io:443 substreams.yaml map_protocol_changes --start-block 11507454 --stop-block +100 -p map_components=`python params.py` @@ -10,12 +13,14 @@ $ substreams run -e mainnet.eth.streamingfast.io:443 substreams.yaml map_protoco ## `params.json` -This json file is a top-level array containing objects that describe a specific `ProtocolComponent`. Each object contains the following fields: +This json file is a top-level array containing objects that describe a specific `ProtocolComponent`. Each object +contains the following fields: - `name`: Just for documentation purposes - `address`: The **lowercase** address of the component - `tx_hash`: The hash of the transaction where the component was emitted - `tokens`: A list of token addresses ordered in the exact same way as the Pool -- `attributes`: A nested object of key to value that represents the static attributes of the component. +- `static_attributes`: A nested object of key to value that represents the static attributes of the component. +- `attributes`: A nested object of key to value that represents attributes. Please see the included 3 examples for `3pool`, `steth`, and `tricrypto2`. diff --git a/substreams/ethereum-curve/integration_test.tycho.yaml b/substreams/ethereum-curve/integration_test.tycho.yaml index f0145d0..b579c9a 100644 --- a/substreams/ethereum-curve/integration_test.tycho.yaml +++ b/substreams/ethereum-curve/integration_test.tycho.yaml @@ -50,7 +50,6 @@ tests: - "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" static_attributes: factory: "0x307830303030303030303030303030303030303030303030303030303030303030303030303030303030" # 0x0000000000000000000000000000000000000000 - stateless_contract_addr_0: "0x307838663638663438313063636533313934623663623666336435306661353863326339626464316435" # 0x8f68f4810cce3194b6cb6f3d50fa58c2c9bdd1d5 factory_name: "0x6e61" # na name: "0x74726963727970746f32" # tricrypto2 creation_tx: "0xdafb6385ed988ce8aacecfe1d97b38ea5e60b1ebce74d2423f71ddd621680138" @@ -108,13 +107,12 @@ tests: factory: "0x307836613863626564373536383034623136653035653734316564616264356362353434616532316266" # 0x6a8cbed756804b16e05e741edabd5cb544ae21bf factory_name: "0x63727970746f5f737761705f6e675f666163746f7279" # crypto_swap_ng_factory name: "0x757364652d75736463" # usde-usdc - stateless_contract_addr_0: "0x63616c6c3a3078366138636265643735363830346231366530356537343165646162643563623534346165323162663a76696577735f696d706c656d656e746174696f6e2829" # call:0x6a8cbed756804b16e05e741edabd5cb544ae21bf:views_implementation() pool_type: "0x706c61696e5f706f6f6c" # plain_pool creation_tx: "0x6f4438aa1785589e2170599053a0cdc740d8987746a4b5ad9614b6ab7bb4e550" skip_simulation: false # CryptoSwapNG factory 0x6A8cbed756804B16E05E741eDaBd5cB544AE21bf - MetaPool - - name: test_crypto_swap_ng_factory_meta_pool + - name: test_crypto_swap_ng_factory_metapool start_block: 19216042 stop_block: 19217045 initialized_accounts: @@ -129,8 +127,6 @@ tests: factory_name: "0x63727970746f5f737761705f6e675f666163746f7279" # crypto_swap_ng_factory name: "0x646f6c612f667261787079757364" # dola/fraxpyusd pool_type: "0x6d657461706f6f6c" # metapool - stateless_contract_addr_0: "0x63616c6c3a3078366138636265643735363830346231366530356537343165646162643563623534346165323162663a76696577735f696d706c656d656e746174696f6e2829" # call:0x6a8cbed756804b16e05e741edabd5cb544ae21bf:views_implementation() - stateless_contract_addr_1: "0x63616c6c3a3078366138636265643735363830346231366530356537343165646162643563623534346165323162663a6d6174685f696d706c656d656e746174696f6e2829" # call:0x6a8cbed756804b16e05e741edabd5cb544ae21bf:math_implementation() base_pool: "0x307861353538386637636466353630383131373130613264383264336339633939373639646231646362" # 0xa5588f7cdf560811710a2d82d3c9c99769db1dcb factory: "0x307836613863626564373536383034623136653035653734316564616264356362353434616532316266" # 0x6a8cbed756804b16e05e741edabd5cb544ae21bf creation_tx: "0x3cfeecae1b43086ee5705f89b803e21eb0492d7d5db06c229586db8fc72f5665" @@ -154,7 +150,6 @@ tests: base_pool: "0x307864636566393638643431366134316364616330656438373032666163383132386136343234316132" # 0xdcfe968d416ac0ed8702fac8128a64241a2 factory: "0x307862396663313537333934616638303461333537383133346136353835633064633963633939306434" # 0xb9fc157394af804a3578134a6585c0dcc993099d pool_type: "0x6d657461706f6f6c" # metapool - stateless_contract_addr_0: "0x307833336262306536326435653863363838653634356464343664666234386364363133323530303637" # 0x33bb0e62d5e8c688e645dd46dfb48cd613250067 creation_tx: "0xc9c6b879cbb19f7f26405335c3879c350592d530956878ff172e9efad786c63f" skip_simulation: true # Reason: this pool calls `totalSupply()` on the LP token during simulation. But this token is overridden and doesn't have anything for totalSupply @@ -162,6 +157,8 @@ tests: - name: test_metapool_factory_plainpool start_block: 18808555 stop_block: 18818577 + initialized_accounts: + - "0xc4ad29ba4b3c580e6d59105fff484999997675ff" # Needed by another component that is created within this block range expected_components: - id: "0xf2DCf6336D8250754B4527f57b275b19c8D5CF88" tokens: @@ -172,7 +169,6 @@ tests: factory: "0x307862396663313537333934616638303461333537383133346136353835633064633963633939306434" # 0xb9fc157394af804a3578134a6585c0dcc993099d factory_name: "0x6d6574615f706f6f6c5f666163746f7279" # meta_pool_factory pool_type: "0x706c61696e5f706f6f6c" # plain_pool - stateless_contract_addr_0: "0x307863363239613031656332336162303465313035303530306133373137613261356330373031343937" # 0xc629a01ec23ab04e1050500a3717a2a5c0701497 creation_tx: "0xeb34c90d352f18ffcfe78b7e393e155f0314acf06c54d1ac9996e4ee5a9b4742" skip_simulation: false - id: "0x3f67dc2AdBA4B1beB6A48c30AB3AFb1c1440d35B" @@ -184,7 +180,6 @@ tests: factory: "0x307862396663313537333934616638303461333537383133346136353835633064633963633939306434" # 0xb9fc157394af804a3578134a6585c0dcc993099d factory_name: "0x6d6574615f706f6f6c5f666163746f7279" # meta_pool_factory pool_type: "0x706c61696e5f706f6f6c" # plain_pool - stateless_contract_addr_0: "0x307863363239613031656332336162303465313035303530306133373137613261356330373031343937" # 0xc629a01ec23ab04e1050500a3717a2a5c0701497 creation_tx: "0x455559b43afaf429c15c1d807fd7f5dd47be30f6411a854499f719b944f4c024" skip_simulation: true # Reason: this pool has no liquidity at stop_block @@ -203,8 +198,6 @@ tests: factory: "0x307866313830353662626433323065393661343865336662663862633036313332323533316161633939" # 0xf18056bbd320e96a48e3fb8bc061322531aacc99 factory_name: "0x63727970746f5f706f6f6c5f666163746f7279" # crypto_pool_factory lp_token: "0x6ade6971ca3d90990c30d39c78b0736c7166e07b" # 0x6ade6971ca3d90990c30d39c78b0736c7166e07b - stateless_contract_addr_1: "0x307863303835353061346363353333336634306535393365636334633437323438303830383564333034" # 0xc08550a4cc5333f40e593ecc4c4724808085d304 - stateless_contract_addr_0: "0x307861383534363161666332646565633031626461323362356364323637643531663736356662613130" # 0xa85461afc2deec01bda23b5cd267d51f765fba10 creation_tx: "0xa89c09a7e0dfd84f3a294b8df4f33cc4a623e6d52deee357457afe2591ea596f" skip_simulation: false - id: "0x6c9Fe53cC13b125d6476E5Ce2b76983bd5b7A112" @@ -217,8 +210,6 @@ tests: factory: "0x307866313830353662626433323065393661343865336662663862633036313332323533316161633939" # 0xf18056bbd320e96a48e3fb8bc061322531aacc99 factory_name: "0x63727970746f5f706f6f6c5f666163746f7279" # crypto_pool_factory lp_token: "0x94c4eba4f4b97be8d778f8c27027d676270e87a6" # 0x94c4eba4f4b97be8d778f8c27027d676270e87a6 - stateless_contract_addr_1: "0x307863303835353061346363353333336634306535393365636334633437323438303830383564333034" # 0xc08550a4cc5333f40e593ecc4c4724808085d304 - stateless_contract_addr_0: "0x307861383534363161666332646565633031626461323362356364323637643531663736356662613130" # 0xa85461afc2deec01bda23b5cd267d51f765fba10 creation_tx: "0xa5b13d50c56242f7994b8e1339032bb4c6f9ac3af3054d4eae3ce9e32e3c1a50" skip_simulation: true # Reason: this pool has no liquidity at stop_block @@ -237,8 +228,6 @@ tests: factory: "0x307866313830353662626433323065393661343865336662663862633036313332323533316161633939" # 0xf18056bbd320e96a48e3fb8bc061322531aacc99 factory_name: "0x63727970746f5f706f6f6c5f666163746f7279" # crypto_pool_factory lp_token: "0x393dad6c76d962abba489a77dbf37ae948a4a6ee" # 0x393dad6c76d962abba489a77dbf37ae948a4a6ee - stateless_contract_addr_0: "0x307861383534363161666332646565633031626461323362356364323637643531663736356662613130" # 0xa85461afc2deec01bda23b5cd267d51f765fba10 - stateless_contract_addr_1: "0x307863303835353061346363353333336634306535393365636334633437323438303830383564333034" # 0xc08550a4cc5333f40e593ecc4c4724808085d304 creation_tx: "0x52f0f76d97e77579eebd32876de99f656930a99131dc4c4f1dec005786c8782b" skip_simulation: false @@ -259,8 +248,6 @@ tests: factory: "0x307830633065356632666630666631386133626539623833353633353033393235366463346234393633" # 0x0c0e5f2ff0ff18a3be9b8356335039256dc4b4963 factory_name: "0x74726963727970746f5f666163746f7279" # tricrypto_factory name: "0x74726963727970746f75736463" # tricrypto_usdc - stateless_contract_addr_0: "0x63616c6c3a3078306330653566326666306666313861336265396238333536333530333932353664633462343936333a76696577735f696d706c656d656e746174696f6e2829" # call:0x0c0e5f2ff0ff18a3be9b8356335039256dc4b4963:views_implementation() - stateless_contract_addr_1: "0x63616c6c3a3078306330653566326666306666313861336265396238333536333530333932353664633462343936333a6d6174685f696d706c656d656e746174696f6e2829" # call:0x0c0e5f2ff0ff18a3be9b8356335039256dc4b4963:math_implementation() pool_type: "0x74726963727970746f" # tricrypto creation_tx: "0x2bd59c19f993b83729fb23498f897a58567c6f0b3ee2f00613ba515a7b19fe23" skip_simulation: false @@ -280,8 +267,6 @@ tests: factory: "0x307839386565383531613030616265653064393564303863663463613262646365333261656161663766" # 0x98ee851a00abee0d95d08cf4ca2bdce32aea7f7f pool_type: "0x74776f63727970746f" # twocrypto factory_name: "0x74776f63727970746f5f666163746f7279" # twocrypto_factory - stateless_contract_addr_0: "0x63616c6c3a3078393865653835316130306162656530643935643038636634636132626463653332616561616637663a76696577735f696d706c656d656e746174696f6e2829" # call:0x98ee851a00abee0d95d08cf4ca2bdce32aea7f7f:views_implementation() - stateless_contract_addr_1: "0x63616c6c3a3078393865653835316130306162656530643935643038636634636132626463653332616561616637663a6d6174685f696d706c656d656e746174696f6e2829" # call:0x98ee851a00abee0d95d08cf4ca2bdce32aea7f7f:math_implementation() name: "0x7577752f77657468" # uwu/weth creation_tx: "0x61d563e2627437da172fdd60ab54e5cc955fcb75829fd819486e857bac31cad2" skip_simulation: false @@ -302,7 +287,6 @@ tests: pool_type: "0x706c61696e5f706f6f6c" # plain_pool factory: "0x307834663838343661653933383062393064326537316435653364303432646666336537656262343064" # 0x4f8846ae9380b90d2e71d5e3d042dff3e7ebb40d factory_name: "0x737461626c655f737761705f666163746f7279" # stable_swap_factory - stateless_contract_addr_0: "0x307836376665343161393465373739636366613232636666303263633239353764633963306534323836" # 0x67fe41a94e779ccfa22cff02cc2957dc9c0e4286 creation_tx: "0x40b25773bf8ea673434277d279af40a85b09072072e7004e9048a2ec0f0dd5a0" skip_simulation: false @@ -324,7 +308,6 @@ tests: - "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490" static_attributes: factory_name: "0x6d6574615f706f6f6c5f666163746f7279" # meta_pool_factory - stateless_contract_addr_0: "0x307835663839303834316636353764393065303831626162646235333261303539393661663739666536" # 0x5f890841f657d90e081babdb532a05996af79fe6 base_pool: "0x307862656263343437383263376462306131613630636236666539376430623438333033326666316337" # 0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7 factory: "0x307830393539313538623630343064333264303463333031613732636266643662333965323163396165" # 0x0959158b6040d32d04c301a72cbfd6b39e21c9ae pool_type: "0x6d657461706f6f6c" # metapool diff --git a/substreams/ethereum-curve/params.py b/substreams/ethereum-curve/params.py index de445d1..3085ce3 100644 --- a/substreams/ethereum-curve/params.py +++ b/substreams/ethereum-curve/params.py @@ -14,14 +14,18 @@ def encode_json_to_query_params(params: list[dict[str, Any]]): contracts: str = param.get("contracts", []) tx_hash: str = param["tx_hash"] tokens: list[str] = param["tokens"] + static_attributes: dict[str, str] = param.get("static_attributes", {}) + static_attributes["name"] = param["name"] + static_attributes["factory_name"] = "NA" + static_attributes["factory"] = EMPTY attributes: dict[str, str] = param.get("attributes", {}) - attributes["name"] = param["name"] - attributes["factory_name"] = "NA" - attributes["factory"] = EMPTY encoded_address = f"address={address}" - encoded_contracts = "&" + "&".join( - [f"contracts[]={contract}" for contract in contracts]) if contracts else '' + encoded_contracts = ( + "&" + "&".join([f"contracts[]={contract}" for contract in contracts]) + if contracts + else "" + ) encoded_tx_hash = f"tx_hash={tx_hash}" encoded_tokens = "&".join([f"tokens[]={token}" for token in tokens]) encoded_attributes = "&".join( @@ -30,8 +34,14 @@ def encode_json_to_query_params(params: list[dict[str, Any]]): for key, value in attributes.items() ] ) + encoded_static_attributes = "&".join( + [ + f"static_attribute_keys[]={key}&static_attribute_vals[]={value}" + for key, value in static_attributes.items() + ] + ) - encoded_param = f"{encoded_address}{encoded_contracts}&{encoded_tx_hash}&{encoded_tokens}&{encoded_attributes}" + encoded_param = f"{encoded_address}{encoded_contracts}&{encoded_tx_hash}&{encoded_tokens}&{encoded_attributes}&{encoded_static_attributes}" encoded_param = encoded_param.rstrip("&") encoded_params.append(encoded_param) diff --git a/substreams/ethereum-curve/src/modules.rs b/substreams/ethereum-curve/src/modules.rs index cf7eddb..3aa8551 100644 --- a/substreams/ethereum-curve/src/modules.rs +++ b/substreams/ethereum-curve/src/modules.rs @@ -36,63 +36,69 @@ impl PartialEq for TransactionWrapper { } #[substreams::handlers::map] -pub fn map_components( - params: String, - block: eth::v2::Block, -) -> Result { - // Gather contract changes by indexing `PoolCreated` events and analysing the `Create` call - // We store these as a hashmap by tx hash since we need to agg by tx hash later - Ok(BlockTransactionProtocolComponents { - tx_components: block - .transactions() - .filter_map(|tx| { - let mut components = tx - .logs_with_calls() - .filter(|(_, call)| !call.call.state_reverted) - .filter_map(|(log, call)| { - pool_factories::address_map( - call.call - .address - .as_slice() - .try_into() - .ok()?, // this shouldn't fail - log, - call.call, - tx, - ) - }) - .collect::>(); +// Map all created components and their related entity changes. +pub fn map_components(params: String, block: eth::v2::Block) -> Result { + let changes = block + .transactions() + .filter_map(|tx| { + let mut entity_changes = vec![]; + let mut components = vec![]; - if let Some(component) = emit_specific_pools(¶ms, tx).expect( - "An unexpected error occured when parsing params for emitting specific pools", + for (log, call) in tx + .logs_with_calls() + .filter(|(_, call)| !call.call.state_reverted) + { + if let Some((component, mut state)) = pool_factories::address_map( + call.call + .address + .as_slice() + .try_into() + .ok()?, // this shouldn't fail + log, + call.call, + tx, ) { - components.push(component) + entity_changes.append(&mut state); + components.push(component); } + } - if !components.is_empty() { - Some(TransactionProtocolComponents { - tx: Some(Transaction { - hash: tx.hash.clone(), - from: tx.from.clone(), - to: tx.to.clone(), - index: Into::::into(tx.index), - }), - components, - }) - } else { - None - } - }) - .collect::>(), - }) + if let Some((component, mut state)) = emit_specific_pools(¶ms, tx).expect( + "An unexpected error occured when parsing params for emitting specific pools", + ) { + entity_changes.append(&mut state); + components.push(component); + } + + if components.is_empty() { + None + } else { + Some(TransactionChanges { + tx: Some(Transaction { + hash: tx.hash.clone(), + from: tx.from.clone(), + to: tx.to.clone(), + index: tx.index.into(), + }), + contract_changes: vec![], + entity_changes, + component_changes: components, + balance_changes: vec![], + }) + } + }) + .collect::>(); + + Ok(BlockChanges { block: None, changes }) } -/// Simply stores the `ProtocolComponent`s with the pool id as the key and tokens as the value +/// Get result `map_components` and stores the created `ProtocolComponent`s with the pool id as the +/// key and tokens as the value #[substreams::handlers::store] -pub fn store_component_tokens(map: BlockTransactionProtocolComponents, store: StoreSetString) { - map.tx_components +pub fn store_component_tokens(map: BlockChanges, store: StoreSetString) { + map.changes .iter() - .flat_map(|tx_components| &tx_components.components) + .flat_map(|tx_changes| &tx_changes.component_changes) .for_each(|component| { store.set( 0, @@ -110,10 +116,10 @@ pub fn store_component_tokens(map: BlockTransactionProtocolComponents, store: St /// pool. /// This is later used to index them with `extract_contract_changes` #[substreams::handlers::store] -pub fn store_non_component_accounts(map: BlockTransactionProtocolComponents, store: StoreSetInt64) { - map.tx_components +pub fn store_non_component_accounts(map: BlockChanges, store: StoreSetInt64) { + map.changes .iter() - .flat_map(|tx_components| &tx_components.components) + .flat_map(|tx_changes| &tx_changes.component_changes) .for_each(|component| { // Crypto pool factory creates LP token separated from the pool, we need to index it so // we add it to the store if the new protocol component comes from this factory @@ -194,7 +200,7 @@ pub fn store_balances(deltas: BlockBalanceDeltas, store: StoreAddBigInt) { #[substreams::handlers::map] pub fn map_protocol_changes( block: eth::v2::Block, - grouped_components: BlockTransactionProtocolComponents, + grouped_components: BlockChanges, deltas: BlockBalanceDeltas, components_store: StoreGetString, non_component_accounts_store: StoreGetInt64, @@ -204,14 +210,14 @@ pub fn map_protocol_changes( // sort them at the very end. let mut transaction_changes: HashMap<_, TransactionChanges> = HashMap::new(); - // `ProtocolComponents` are gathered from `map_pools_created` which just need a bit of work to - // convert into `TransactionChanges` + // `ProtocolComponents` are gathered with some entity changes from `map_pools_created` which + // just need a bit of work to convert into `TransactionChanges` grouped_components - .tx_components + .changes .into_iter() - .for_each(|tx_component| { - let tx = tx_component.tx.as_ref().unwrap(); - transaction_changes + .for_each(|tx_changes| { + let tx = tx_changes.tx.as_ref().unwrap(); + let transaction_entry = transaction_changes .entry(tx.index) .or_insert_with(|| TransactionChanges { tx: Some(tx.clone()), @@ -219,18 +225,23 @@ pub fn map_protocol_changes( component_changes: vec![], balance_changes: vec![], entity_changes: vec![], - }) + }); + + let formated_components: Vec<_> = tx_changes //TODO: format directly at creation .component_changes - .extend_from_slice( - &(tx_component - .components - .into_iter() - .map(|mut component| { - component.id = format!("0x{}", component.id); - component - }) - .collect::>()), - ); + .into_iter() + .map(|mut component| { + component.id = format!("0x{}", component.id); + component + }) + .collect(); + + transaction_entry + .component_changes + .extend(formated_components); + transaction_entry + .entity_changes + .extend(tx_changes.entity_changes); }); // Balance changes are gathered by the `StoreDelta` based on `TokenExchange`, etc. creating diff --git a/substreams/ethereum-curve/src/pool_factories.rs b/substreams/ethereum-curve/src/pool_factories.rs index c116015..a52e249 100644 --- a/substreams/ethereum-curve/src/pool_factories.rs +++ b/substreams/ethereum-curve/src/pool_factories.rs @@ -32,9 +32,14 @@ impl SerializableVecBigInt for Vec { } } -/// Converts address bytes into a string containing a leading `0x`. +/// Converts address bytes into a Vec containing a leading `0x`. fn address_to_bytes_with_0x(address: &[u8; 20]) -> Vec { - format!("0x{}", hex::encode(address)).into_bytes() + address_to_string_with_0x(address).into_bytes() +} + +/// Converts address bytes into a string containing a leading `0x`. +fn address_to_string_with_0x(address: &[u8]) -> String { + format!("0x{}", hex::encode(address)) } /// Function that swaps `WETH` addresses for `ETH` address for specific factory types that decide @@ -52,9 +57,9 @@ fn swap_weth_for_eth(tokens: Vec>) -> Vec> { } /// This massive function matches factory address to specific logic to construct -/// `ProtocolComponent`s. While, most of the logic is readily replicable, several factories differ -/// in information density resulting in needing other information sources such as decoding calls -/// or even making RPC calls to provide extra details. +/// `ProtocolComponent`s and their related `EntityChanges` at creation. While, most of the logic is +/// readily replicable, several factories differ in information density resulting in needing other +/// information sources such as decoding calls or even making RPC calls to provide extra details. /// /// Each `ProtocolComponent` contains the following static attributes: /// - `pool_type`: The type of pool, such as `crypto_pool`, `plain_pool`, `metapool`, etc. @@ -73,7 +78,7 @@ pub fn address_map( log: &Log, call: &Call, tx: &TransactionTrace, -) -> Option { +) -> Option<(ProtocolComponent, Vec)> { match *call_address { CRYPTO_POOL_FACTORY => { let pool_added = @@ -86,61 +91,68 @@ pub fn address_map( let token_implementation = extract_proxy_impl(call, tx, 0).unwrap_or([1u8; 20]); let pool_implementation = extract_proxy_impl(call, tx, 1).unwrap_or([1u8; 20]); - Some(ProtocolComponent { - id: hex::encode(component_id), - tx: Some(Transaction { - to: tx.to.clone(), - from: tx.from.clone(), - hash: tx.hash.clone(), - index: tx.index.into(), - }), - tokens, - contracts: vec![component_id.into(), pool_added.token.clone()], - static_att: vec![ - Attribute { - name: "pool_type".into(), - value: "crypto_pool".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "name".into(), - value: pool_added.a.to_string().into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory_name".into(), - value: "crypto_pool_factory".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory".into(), - value: address_to_bytes_with_0x(&CRYPTO_POOL_FACTORY), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "lp_token".into(), - value: pool_added.token, - change: ChangeType::Creation.into(), - }, - Attribute { - name: "stateless_contract_addr_0".into(), - value: address_to_bytes_with_0x(&pool_implementation), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "stateless_contract_addr_1".into(), - value: address_to_bytes_with_0x(&token_implementation), - change: ChangeType::Creation.into(), - }, - ], - change: ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "curve_pool".into(), - financial_type: FinancialType::Swap.into(), - attribute_schema: Vec::new(), - implementation_type: ImplementationType::Vm.into(), - }), - }) + Some(( + ProtocolComponent { + id: hex::encode(component_id), + tx: Some(Transaction { + to: tx.to.clone(), + from: tx.from.clone(), + hash: tx.hash.clone(), + index: tx.index.into(), + }), + tokens, + contracts: vec![component_id.into(), pool_added.token.clone()], + static_att: vec![ + Attribute { + name: "pool_type".into(), + value: "crypto_pool".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "name".into(), + value: pool_added.a.to_string().into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory_name".into(), + value: "crypto_pool_factory".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory".into(), + value: address_to_bytes_with_0x(&CRYPTO_POOL_FACTORY), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "lp_token".into(), + value: pool_added.token, + change: ChangeType::Creation.into(), + }, + ], + change: ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "curve_pool".into(), + financial_type: FinancialType::Swap.into(), + attribute_schema: Vec::new(), + implementation_type: ImplementationType::Vm.into(), + }), + }, + vec![EntityChanges { + component_id: address_to_string_with_0x(component_id), + attributes: vec![ + Attribute { + name: "stateless_contract_addr_0".into(), + value: address_to_bytes_with_0x(&pool_implementation), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "stateless_contract_addr_1".into(), + value: address_to_bytes_with_0x(&token_implementation), + change: ChangeType::Creation.into(), + }, + ], + }], + )) } META_POOL_FACTORY => { if let Some(pool_added) = @@ -188,51 +200,56 @@ pub fn address_map( .collect(); let pool_implementation = extract_proxy_impl(call, tx, 0).unwrap_or([1u8; 20]); - Some(ProtocolComponent { - id: hex::encode(component_id), - tx: Some(Transaction { - to: tx.to.clone(), - from: tx.from.clone(), - hash: tx.hash.clone(), - index: tx.index.into(), - }), - tokens, - contracts: vec![component_id.into()], - static_att: vec![ - Attribute { - name: "pool_type".into(), - value: "plain_pool".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "name".into(), - value: add_pool.name.into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory_name".into(), - value: "meta_pool_factory".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory".into(), - value: address_to_bytes_with_0x(&META_POOL_FACTORY), - change: ChangeType::Creation.into(), - }, - Attribute { + Some(( + ProtocolComponent { + id: hex::encode(component_id), + tx: Some(Transaction { + to: tx.to.clone(), + from: tx.from.clone(), + hash: tx.hash.clone(), + index: tx.index.into(), + }), + tokens, + contracts: vec![component_id.into()], + static_att: vec![ + Attribute { + name: "pool_type".into(), + value: "plain_pool".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "name".into(), + value: add_pool.name.into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory_name".into(), + value: "meta_pool_factory".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory".into(), + value: address_to_bytes_with_0x(&META_POOL_FACTORY), + change: ChangeType::Creation.into(), + }, + ], + change: ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "curve_pool".into(), + financial_type: FinancialType::Swap.into(), + attribute_schema: Vec::new(), + implementation_type: ImplementationType::Vm.into(), + }), + }, + vec![EntityChanges { + component_id: address_to_string_with_0x(component_id), + attributes: vec![Attribute { name: "stateless_contract_addr_0".into(), value: address_to_bytes_with_0x(&pool_implementation), change: ChangeType::Creation.into(), - }, - ], - change: ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "curve_pool".into(), - financial_type: FinancialType::Swap.into(), - attribute_schema: Vec::new(), - implementation_type: ImplementationType::Vm.into(), - }), - }) + }], + }], + )) } else if let Some(pool_added) = abi::meta_pool_factory::events::MetaPoolDeployed::match_and_decode(log) { @@ -264,58 +281,63 @@ pub fn address_map( let pool_implementation = extract_proxy_impl(call, tx, 0).unwrap_or([1u8; 20]); - Some(ProtocolComponent { - id: hex::encode(component_id), - tx: Some(Transaction { - to: tx.to.clone(), - from: tx.from.clone(), - hash: tx.hash.clone(), - index: tx.index.into(), - }), - tokens: vec![pool_added.coin, lp_token], - contracts: vec![component_id.into(), add_pool.base_pool.clone()], - static_att: vec![ - Attribute { - name: "pool_type".into(), - value: "metapool".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "name".into(), - value: add_pool.name.into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory_name".into(), - value: "meta_pool_factory".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory".into(), - value: address_to_bytes_with_0x(&META_POOL_FACTORY), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "base_pool".into(), - value: address_to_bytes_with_0x( - &add_pool.base_pool.try_into().unwrap(), - ), - change: ChangeType::Creation.into(), - }, - Attribute { + Some(( + ProtocolComponent { + id: hex::encode(component_id), + tx: Some(Transaction { + to: tx.to.clone(), + from: tx.from.clone(), + hash: tx.hash.clone(), + index: tx.index.into(), + }), + tokens: vec![pool_added.coin, lp_token], + contracts: vec![component_id.into(), add_pool.base_pool.clone()], + static_att: vec![ + Attribute { + name: "pool_type".into(), + value: "metapool".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "name".into(), + value: add_pool.name.into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory_name".into(), + value: "meta_pool_factory".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory".into(), + value: address_to_bytes_with_0x(&META_POOL_FACTORY), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "base_pool".into(), + value: address_to_bytes_with_0x( + &add_pool.base_pool.try_into().unwrap(), + ), + change: ChangeType::Creation.into(), + }, + ], + change: ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "curve_pool".into(), + financial_type: FinancialType::Swap.into(), + attribute_schema: Vec::new(), + implementation_type: ImplementationType::Vm.into(), + }), + }, + vec![EntityChanges { + component_id: address_to_string_with_0x(component_id), + attributes: vec![Attribute { name: "stateless_contract_addr_0".into(), value: address_to_bytes_with_0x(&pool_implementation), change: ChangeType::Creation.into(), - }, - ], - change: ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "curve_pool".into(), - financial_type: FinancialType::Swap.into(), - attribute_schema: Vec::new(), - implementation_type: ImplementationType::Vm.into(), - }), - }) + }], + }], + )) } else { None } @@ -346,58 +368,63 @@ pub fn address_map( let component_id = &call.return_data[12..]; let lp_token = get_token_from_pool(&pool_added.base_pool); - Some(ProtocolComponent { - id: hex::encode(component_id), - tx: Some(Transaction { - to: tx.to.clone(), - from: tx.from.clone(), - hash: tx.hash.clone(), - index: tx.index.into(), - }), - tokens: vec![pool_added.coin, lp_token], - contracts: vec![component_id.into()], - static_att: vec![ - Attribute { - name: "pool_type".into(), - value: "metapool".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "name".into(), - value: add_pool.name.into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory_name".into(), - value: "meta_pool_factory".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory".into(), - value: address_to_bytes_with_0x(&META_POOL_FACTORY_OLD), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "base_pool".into(), - value: address_to_bytes_with_0x( - &add_pool.base_pool.try_into().unwrap(), - ), - change: ChangeType::Creation.into(), - }, - Attribute { + Some(( + ProtocolComponent { + id: hex::encode(component_id), + tx: Some(Transaction { + to: tx.to.clone(), + from: tx.from.clone(), + hash: tx.hash.clone(), + index: tx.index.into(), + }), + tokens: vec![pool_added.coin, lp_token], + contracts: vec![component_id.into()], + static_att: vec![ + Attribute { + name: "pool_type".into(), + value: "metapool".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "name".into(), + value: add_pool.name.into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory_name".into(), + value: "meta_pool_factory".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory".into(), + value: address_to_bytes_with_0x(&META_POOL_FACTORY_OLD), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "base_pool".into(), + value: address_to_bytes_with_0x( + &add_pool.base_pool.try_into().unwrap(), + ), + change: ChangeType::Creation.into(), + }, + ], + change: ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "curve_pool".into(), + financial_type: FinancialType::Swap.into(), + attribute_schema: Vec::new(), + implementation_type: ImplementationType::Vm.into(), + }), + }, + vec![EntityChanges { + component_id: address_to_string_with_0x(component_id), + attributes: vec![Attribute { name: "stateless_contract_addr_0".into(), value: address_to_bytes_with_0x(&pool_implementation), change: ChangeType::Creation.into(), - }, - ], - change: ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "curve_pool".into(), - financial_type: FinancialType::Swap.into(), - attribute_schema: Vec::new(), - implementation_type: ImplementationType::Vm.into(), - }), - }) + }], + }], + )) } else { None } @@ -411,38 +438,50 @@ pub fn address_map( call, )?; let component_id = &call.return_data[12..]; - Some(ProtocolComponent { - id: hex::encode(component_id), - tx: Some(Transaction { - to: tx.to.clone(), - from: tx.from.clone(), - hash: tx.hash.clone(), - index: tx.index.into(), - }), - tokens: pool_added.coins, - contracts: vec![component_id.into(), CRYPTO_SWAP_NG_FACTORY.into()], - static_att: vec![ - Attribute { - name: "pool_type".into(), - value: "plain_pool".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "name".into(), - value: add_pool.name.into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory_name".into(), - value: "crypto_swap_ng_factory".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory".into(), - value: address_to_bytes_with_0x(&CRYPTO_SWAP_NG_FACTORY), - change: ChangeType::Creation.into(), - }, - Attribute { + Some(( + ProtocolComponent { + id: hex::encode(component_id), + tx: Some(Transaction { + to: tx.to.clone(), + from: tx.from.clone(), + hash: tx.hash.clone(), + index: tx.index.into(), + }), + tokens: pool_added.coins, + contracts: vec![component_id.into(), CRYPTO_SWAP_NG_FACTORY.into()], + static_att: vec![ + Attribute { + name: "pool_type".into(), + value: "plain_pool".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "name".into(), + value: add_pool.name.into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory_name".into(), + value: "crypto_swap_ng_factory".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory".into(), + value: address_to_bytes_with_0x(&CRYPTO_SWAP_NG_FACTORY), + change: ChangeType::Creation.into(), + }, + ], + change: ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "curve_pool".into(), + financial_type: FinancialType::Swap.into(), + attribute_schema: Vec::new(), + implementation_type: ImplementationType::Vm.into(), + }), + }, + vec![EntityChanges { + component_id: address_to_string_with_0x(component_id), + attributes: vec![Attribute { name: "stateless_contract_addr_0".into(), // Call views_implementation() on CRYPTO_SWAP_NG_FACTORY value: format!( @@ -451,16 +490,9 @@ pub fn address_map( ) .into(), change: ChangeType::Creation.into(), - }, - ], - change: ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "curve_pool".into(), - financial_type: FinancialType::Swap.into(), - attribute_schema: Vec::new(), - implementation_type: ImplementationType::Vm.into(), - }), - }) + }], + }], + )) } else if let Some(pool_added) = abi::crypto_swap_ng_factory::events::MetaPoolDeployed::match_and_decode(log) { @@ -469,77 +501,84 @@ pub fn address_map( let component_id = &call.return_data[12..]; let lp_token = get_token_from_pool(&pool_added.base_pool); - Some(ProtocolComponent { - id: hex::encode(component_id), - tx: Some(Transaction { - to: tx.to.clone(), - from: tx.from.clone(), - hash: tx.hash.clone(), - index: tx.index.into(), - }), - tokens: vec![pool_added.coin, lp_token], - contracts: vec![ - component_id.into(), - CRYPTO_SWAP_NG_FACTORY.into(), - pool_added.base_pool.clone(), - ], - static_att: vec![ - Attribute { - name: "pool_type".into(), - value: "metapool".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "name".into(), - value: add_pool.name.into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory_name".into(), - value: "crypto_swap_ng_factory".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory".into(), - value: address_to_bytes_with_0x(&CRYPTO_SWAP_NG_FACTORY), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "base_pool".into(), - value: address_to_bytes_with_0x( - &pool_added.base_pool.try_into().unwrap(), - ), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "stateless_contract_addr_0".into(), - // Call views_implementation() on CRYPTO_SWAP_NG_FACTORY - value: format!( - "call:0x{}:views_implementation()", - hex::encode(CRYPTO_SWAP_NG_FACTORY) - ) - .into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "stateless_contract_addr_1".into(), - // Call math_implementation() on CRYPTO_SWAP_NG_FACTORY - value: format!( - "call:0x{}:math_implementation()", - hex::encode(CRYPTO_SWAP_NG_FACTORY) - ) - .into(), - change: ChangeType::Creation.into(), - }, - ], - change: ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "curve_pool".into(), - financial_type: FinancialType::Swap.into(), - attribute_schema: Vec::new(), - implementation_type: ImplementationType::Vm.into(), - }), - }) + Some(( + ProtocolComponent { + id: hex::encode(component_id), + tx: Some(Transaction { + to: tx.to.clone(), + from: tx.from.clone(), + hash: tx.hash.clone(), + index: tx.index.into(), + }), + tokens: vec![pool_added.coin, lp_token], + contracts: vec![ + component_id.into(), + CRYPTO_SWAP_NG_FACTORY.into(), + pool_added.base_pool.clone(), + ], + static_att: vec![ + Attribute { + name: "pool_type".into(), + value: "metapool".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "name".into(), + value: add_pool.name.into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory_name".into(), + value: "crypto_swap_ng_factory".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory".into(), + value: address_to_bytes_with_0x(&CRYPTO_SWAP_NG_FACTORY), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "base_pool".into(), + value: address_to_bytes_with_0x( + &pool_added.base_pool.try_into().unwrap(), + ), + change: ChangeType::Creation.into(), + }, + ], + change: ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "curve_pool".into(), + financial_type: FinancialType::Swap.into(), + attribute_schema: Vec::new(), + implementation_type: ImplementationType::Vm.into(), + }), + }, + vec![EntityChanges { + component_id: address_to_string_with_0x(component_id), + attributes: vec![ + Attribute { + name: "stateless_contract_addr_0".into(), + // Call views_implementation() on CRYPTO_SWAP_NG_FACTORY + value: format!( + "call:0x{}:views_implementation()", + hex::encode(CRYPTO_SWAP_NG_FACTORY) + ) + .into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "stateless_contract_addr_1".into(), + // Call math_implementation() on CRYPTO_SWAP_NG_FACTORY + value: format!( + "call:0x{}:math_implementation()", + hex::encode(CRYPTO_SWAP_NG_FACTORY) + ) + .into(), + change: ChangeType::Creation.into(), + }, + ], + }], + )) } else { None } @@ -549,67 +588,75 @@ pub fn address_map( abi::tricrypto_factory::events::TricryptoPoolDeployed::match_and_decode(log) { let tokens = swap_weth_for_eth(pool_added.coins.into()); + let id = hex::encode(&pool_added.pool); - Some(ProtocolComponent { - id: hex::encode(&pool_added.pool), - tx: Some(Transaction { - to: tx.to.clone(), - from: tx.from.clone(), - hash: tx.hash.clone(), - index: tx.index.into(), - }), - tokens, - contracts: vec![pool_added.pool, TRICRYPTO_FACTORY.into()], - static_att: vec![ - Attribute { - name: "pool_type".into(), - value: "tricrypto".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "name".into(), - value: pool_added.name.into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory_name".into(), - value: "tricrypto_factory".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory".into(), - value: address_to_bytes_with_0x(&TRICRYPTO_FACTORY), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "stateless_contract_addr_0".into(), - // Call views_implementation() on TRICRYPTO_FACTORY - value: format!( - "call:0x{}:views_implementation()", - hex::encode(TRICRYPTO_FACTORY) - ) - .into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "stateless_contract_addr_1".into(), - // Call math_implementation() on TRICRYPTO_FACTORY - value: format!( - "call:0x{}:math_implementation()", - hex::encode(TRICRYPTO_FACTORY) - ) - .into(), - change: ChangeType::Creation.into(), - }, - ], - change: ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "curve_pool".into(), - financial_type: FinancialType::Swap.into(), - attribute_schema: Vec::new(), - implementation_type: ImplementationType::Vm.into(), - }), - }) + Some(( + ProtocolComponent { + id: id.clone(), + tx: Some(Transaction { + to: tx.to.clone(), + from: tx.from.clone(), + hash: tx.hash.clone(), + index: tx.index.into(), + }), + tokens, + contracts: vec![pool_added.pool, TRICRYPTO_FACTORY.into()], + static_att: vec![ + Attribute { + name: "pool_type".into(), + value: "tricrypto".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "name".into(), + value: pool_added.name.into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory_name".into(), + value: "tricrypto_factory".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory".into(), + value: address_to_bytes_with_0x(&TRICRYPTO_FACTORY), + change: ChangeType::Creation.into(), + }, + ], + change: ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "curve_pool".into(), + financial_type: FinancialType::Swap.into(), + attribute_schema: Vec::new(), + implementation_type: ImplementationType::Vm.into(), + }), + }, + vec![EntityChanges { + component_id: format!("0x{}", id), + attributes: vec![ + Attribute { + name: "stateless_contract_addr_0".into(), + // Call views_implementation() on TRICRYPTO_FACTORY + value: format!( + "call:0x{}:views_implementation()", + hex::encode(TRICRYPTO_FACTORY) + ) + .into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "stateless_contract_addr_1".into(), + // Call math_implementation() on TRICRYPTO_FACTORY + value: format!( + "call:0x{}:math_implementation()", + hex::encode(TRICRYPTO_FACTORY) + ) + .into(), + change: ChangeType::Creation.into(), + }, + ], + }], + )) } else { None } @@ -659,51 +706,56 @@ pub fn address_map( let pool_implementation = extract_proxy_impl(call, tx, 0).unwrap_or([1u8; 20]); - Some(ProtocolComponent { - id: hex::encode(component_id), - tx: Some(Transaction { - to: tx.to.clone(), - from: tx.from.clone(), - hash: tx.hash.clone(), - index: tx.index.into(), - }), - tokens, - contracts: vec![component_id.into()], - static_att: vec![ - Attribute { - name: "pool_type".into(), - value: "plain_pool".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "name".into(), - value: add_pool.name.into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory_name".into(), - value: "stable_swap_factory".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory".into(), - value: address_to_bytes_with_0x(&STABLESWAP_FACTORY), - change: ChangeType::Creation.into(), - }, - Attribute { + Some(( + ProtocolComponent { + id: hex::encode(component_id), + tx: Some(Transaction { + to: tx.to.clone(), + from: tx.from.clone(), + hash: tx.hash.clone(), + index: tx.index.into(), + }), + tokens, + contracts: vec![component_id.into()], + static_att: vec![ + Attribute { + name: "pool_type".into(), + value: "plain_pool".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "name".into(), + value: add_pool.name.into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory_name".into(), + value: "stable_swap_factory".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory".into(), + value: address_to_bytes_with_0x(&STABLESWAP_FACTORY), + change: ChangeType::Creation.into(), + }, + ], + change: ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "curve_pool".into(), + financial_type: FinancialType::Swap.into(), + attribute_schema: Vec::new(), + implementation_type: ImplementationType::Vm.into(), + }), + }, + vec![EntityChanges { + component_id: address_to_string_with_0x(component_id), + attributes: vec![Attribute { name: "stateless_contract_addr_0".into(), value: address_to_bytes_with_0x(&pool_implementation), change: ChangeType::Creation.into(), - }, - ], - change: ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "curve_pool".into(), - financial_type: FinancialType::Swap.into(), - attribute_schema: Vec::new(), - implementation_type: ImplementationType::Vm.into(), - }), - }) + }], + }], + )) } else if let Some(pool_added) = abi::stableswap_factory::events::MetaPoolDeployed::match_and_decode(log) { @@ -732,53 +784,56 @@ pub fn address_map( abi::meta_registry::functions::GetLpToken1 { pool: add_pool.base_pool.clone() }; let lp_token = get_lp_token.call(META_REGISTRY.to_vec())?; - Some(ProtocolComponent { - id: hex::encode(component_id), - tx: Some(Transaction { - to: tx.to.clone(), - from: tx.from.clone(), - hash: tx.hash.clone(), - index: tx.index.into(), - }), - tokens: vec![pool_added.coin, lp_token], - contracts: vec![component_id.into()], - static_att: vec![ - Attribute { - name: "pool_type".into(), - value: "metapool".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "name".into(), - value: add_pool.name.into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory_name".into(), - value: "stable_swap_factory".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory".into(), - value: address_to_bytes_with_0x(&STABLESWAP_FACTORY), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "base_pool".into(), - value: address_to_bytes_with_0x( - &pool_added.base_pool.try_into().unwrap(), - ), - change: ChangeType::Creation.into(), - }, - ], - change: ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "curve_pool".into(), - financial_type: FinancialType::Swap.into(), - attribute_schema: Vec::new(), - implementation_type: ImplementationType::Vm.into(), - }), - }) + Some(( + ProtocolComponent { + id: hex::encode(component_id), + tx: Some(Transaction { + to: tx.to.clone(), + from: tx.from.clone(), + hash: tx.hash.clone(), + index: tx.index.into(), + }), + tokens: vec![pool_added.coin, lp_token], + contracts: vec![component_id.into()], + static_att: vec![ + Attribute { + name: "pool_type".into(), + value: "metapool".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "name".into(), + value: add_pool.name.into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory_name".into(), + value: "stable_swap_factory".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory".into(), + value: address_to_bytes_with_0x(&STABLESWAP_FACTORY), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "base_pool".into(), + value: address_to_bytes_with_0x( + &pool_added.base_pool.try_into().unwrap(), + ), + change: ChangeType::Creation.into(), + }, + ], + change: ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "curve_pool".into(), + financial_type: FinancialType::Swap.into(), + attribute_schema: Vec::new(), + implementation_type: ImplementationType::Vm.into(), + }), + }, + vec![], + )) } else { None } @@ -787,66 +842,74 @@ pub fn address_map( if let Some(pool_added) = abi::twocrypto_factory::events::TwocryptoPoolDeployed::match_and_decode(log) { - Some(ProtocolComponent { - id: hex::encode(&pool_added.pool), - tx: Some(Transaction { - to: tx.to.clone(), - from: tx.from.clone(), - hash: tx.hash.clone(), - index: tx.index.into(), - }), - tokens: pool_added.coins.into(), - contracts: vec![pool_added.pool, TWOCRYPTO_FACTORY.into()], - static_att: vec![ - Attribute { - name: "pool_type".into(), - value: "twocrypto".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "name".into(), - value: pool_added.name.into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory_name".into(), - value: "twocrypto_factory".into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "factory".into(), - value: address_to_bytes_with_0x(&TWOCRYPTO_FACTORY), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "stateless_contract_addr_0".into(), - // Call views_implementation() on TWOCRYPTO_FACTORY - value: format!( - "call:0x{}:views_implementation()", - hex::encode(TWOCRYPTO_FACTORY) - ) - .into(), - change: ChangeType::Creation.into(), - }, - Attribute { - name: "stateless_contract_addr_1".into(), - // Call math_implementation() on TWOCRYPTO_FACTORY - value: format!( - "call:0x{}:math_implementation()", - hex::encode(TWOCRYPTO_FACTORY) - ) - .into(), - change: ChangeType::Creation.into(), - }, - ], - change: ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "curve_pool".into(), - financial_type: FinancialType::Swap.into(), - attribute_schema: Vec::new(), - implementation_type: ImplementationType::Vm.into(), - }), - }) + let id = hex::encode(&pool_added.pool); + Some(( + ProtocolComponent { + id: id.clone(), + tx: Some(Transaction { + to: tx.to.clone(), + from: tx.from.clone(), + hash: tx.hash.clone(), + index: tx.index.into(), + }), + tokens: pool_added.coins.into(), + contracts: vec![pool_added.pool, TWOCRYPTO_FACTORY.into()], + static_att: vec![ + Attribute { + name: "pool_type".into(), + value: "twocrypto".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "name".into(), + value: pool_added.name.into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory_name".into(), + value: "twocrypto_factory".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory".into(), + value: address_to_bytes_with_0x(&TWOCRYPTO_FACTORY), + change: ChangeType::Creation.into(), + }, + ], + change: ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "curve_pool".into(), + financial_type: FinancialType::Swap.into(), + attribute_schema: Vec::new(), + implementation_type: ImplementationType::Vm.into(), + }), + }, + vec![EntityChanges { + component_id: format!("0x{}", id), + attributes: vec![ + Attribute { + name: "stateless_contract_addr_0".into(), + // Call views_implementation() on TWOCRYPTO_FACTORY + value: format!( + "call:0x{}:views_implementation()", + hex::encode(TWOCRYPTO_FACTORY) + ) + .into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "stateless_contract_addr_1".into(), + // Call math_implementation() on TWOCRYPTO_FACTORY + value: format!( + "call:0x{}:math_implementation()", + hex::encode(TWOCRYPTO_FACTORY) + ) + .into(), + change: ChangeType::Creation.into(), + }, + ], + }], + )) } else { None } diff --git a/substreams/ethereum-curve/src/pools.rs b/substreams/ethereum-curve/src/pools.rs index 8aeef87..a8ca576 100644 --- a/substreams/ethereum-curve/src/pools.rs +++ b/substreams/ethereum-curve/src/pools.rs @@ -12,6 +12,8 @@ struct PoolQueryParams { contracts: Option>, tx_hash: String, tokens: Vec, + static_attribute_keys: Option>, + static_attribute_vals: Option>, attribute_keys: Option>, attribute_vals: Option>, } @@ -32,7 +34,7 @@ struct PoolQueryParams { pub fn emit_specific_pools( params: &str, tx: &TransactionTrace, -) -> Result> { +) -> Result)>> { let pools = parse_params(params)?; create_component(tx, pools) } @@ -40,61 +42,81 @@ pub fn emit_specific_pools( fn create_component( tx: &TransactionTrace, pools: HashMap, -) -> Result> { +) -> Result)>> { let encoded_hash = hex::encode(tx.hash.clone()); if let Some(pool) = pools.get(&encoded_hash) { - Ok(Some(ProtocolComponent { - id: pool.address.clone(), - tx: Some(Transaction { - to: tx.to.clone(), - from: tx.from.clone(), - hash: tx.hash.clone(), - index: tx.index.into(), - }), - tokens: pool - .tokens - .clone() - .into_iter() - .map(|token| Result::Ok(hex::decode(token)?)) - .collect::>>() - .with_context(|| "Token addresses were not formatted properly")?, - static_att: zip( - pool.attribute_keys + Ok(Some(( + ProtocolComponent { + id: pool.address.clone(), + tx: Some(Transaction { + to: tx.to.clone(), + from: tx.from.clone(), + hash: tx.hash.clone(), + index: tx.index.into(), + }), + tokens: pool + .tokens .clone() - .unwrap_or(vec![]), - pool.attribute_vals - .clone() - .unwrap_or(vec![]), - ) - .clone() - .map(|(key, value)| Attribute { - name: key, - value: value.into(), - change: ChangeType::Creation.into(), - }) - .collect::>(), - contracts: pool - .contracts + .into_iter() + .map(|token| Result::Ok(hex::decode(token)?)) + .collect::>>() + .with_context(|| "Token addresses were not formatted properly")?, + static_att: zip( + pool.static_attribute_keys + .clone() + .unwrap_or(vec![]), + pool.static_attribute_vals + .clone() + .unwrap_or(vec![]), + ) .clone() - .unwrap_or_default() - .into_iter() - .map(|contract| { - hex::decode(contract) - .with_context(|| "Pool contracts was not formatted properly") + .map(|(key, value)| Attribute { + name: key, + value: value.into(), + change: ChangeType::Creation.into(), }) - .chain(std::iter::once( - hex::decode(&pool.address) - .with_context(|| "Pool address was not formatted properly"), - )) - .collect::>>>()?, - change: ChangeType::Creation.into(), - protocol_type: Some(ProtocolType { - name: "curve_pool".into(), - financial_type: FinancialType::Swap.into(), - attribute_schema: Vec::new(), - implementation_type: ImplementationType::Vm.into(), - }), - })) + .collect::>(), + contracts: pool + .contracts + .clone() + .unwrap_or_default() + .into_iter() + .map(|contract| { + hex::decode(contract) + .with_context(|| "Pool contracts was not formatted properly") + }) + .chain(std::iter::once( + hex::decode(&pool.address) + .with_context(|| "Pool address was not formatted properly"), + )) + .collect::>>>()?, + change: ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "curve_pool".into(), + financial_type: FinancialType::Swap.into(), + attribute_schema: Vec::new(), + implementation_type: ImplementationType::Vm.into(), + }), + }, + vec![EntityChanges { + component_id: format!("0x{}", pool.address.clone()), + attributes: zip( + pool.attribute_keys + .clone() + .unwrap_or(vec![]), + pool.attribute_vals + .clone() + .unwrap_or(vec![]), + ) + .clone() + .map(|(key, value)| Attribute { + name: key, + value: value.into(), + change: ChangeType::Creation.into(), + }) + .collect::>(), + }], + ))) } else { Ok(None) } @@ -134,6 +156,8 @@ mod tests { "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48".to_string(), "0xdac17f958d2ee523a2206206994597c13d831ec7".to_string(), ], + static_attribute_keys: None, + static_attribute_vals: None, attribute_keys: Some(vec!["key1".to_string()]), attribute_vals: Some(vec!["val1".to_string()]), }, diff --git a/substreams/ethereum-curve/substreams.yaml b/substreams/ethereum-curve/substreams.yaml index b25e59e..34ff1b8 100644 --- a/substreams/ethereum-curve/substreams.yaml +++ b/substreams/ethereum-curve/substreams.yaml @@ -20,12 +20,12 @@ binaries: modules: - name: map_components kind: map - initialBlock: 9906598 + initialBlock: 9906598 # Creation of first Curve pool 0xa5407eae9ba41422680e2e00537571bcc53efbfd inputs: - params: string - source: sf.ethereum.type.v2.Block output: - type: proto:tycho.evm.v1.BlockTransactionProtocolComponents + type: proto:tycho.evm.v1.BlockChanges - name: store_component_tokens kind: store @@ -37,7 +37,7 @@ modules: - name: store_non_component_accounts kind: store - initialBlock: 11968730 + initialBlock: 9906598 updatePolicy: set valueType: int64 inputs: @@ -45,7 +45,7 @@ modules: - name: map_relative_balances kind: map - initialBlock: 9906598 # An arbitrary block that should change based on your requirements + initialBlock: 9906598 inputs: - source: sf.ethereum.type.v2.Block - store: store_component_tokens @@ -75,4 +75,4 @@ modules: type: proto:tycho.evm.v1.BlockChanges params: - map_components: "address=bebc44782c7db0a1a60cb6fe97d0b483032ff1c7&tx_hash=20793bbf260912aae189d5d261ff003c9b9166da8191d8f9d63ff1c7722f3ac6&tokens[]=6b175474e89094c44da98b954eedeac495271d0f&tokens[]=a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&tokens[]=dac17f958d2ee523a2206206994597c13d831ec7&attribute_keys[]=name&attribute_vals[]=3pool&attribute_keys[]=factory_name&attribute_vals[]=NA&attribute_keys[]=factory&attribute_vals[]=0x0000000000000000000000000000000000000000,address=dc24316b9ae028f1497c275eb9192a3ea0f67022&tx_hash=fac67ecbd423a5b915deff06045ec9343568edaec34ae95c43d35f2c018afdaa&tokens[]=eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee&tokens[]=ae7ab96520de3a18e5e111b5eaab095312d7fe84&attribute_keys[]=name&attribute_vals[]=steth&attribute_keys[]=factory_name&attribute_vals[]=NA&attribute_keys[]=factory&attribute_vals[]=0x0000000000000000000000000000000000000000,address=d51a44d3fae010294c616388b506acda1bfaae46&contracts[]=c4ad29ba4b3c580e6d59105fff484999997675ff&contracts[]=40745803c2faa8e8402e2ae935933d07ca8f355c&tx_hash=dafb6385ed988ce8aacecfe1d97b38ea5e60b1ebce74d2423f71ddd621680138&tokens[]=dac17f958d2ee523a2206206994597c13d831ec7&tokens[]=2260fac5e5542a773aa44fbcfedf7c193bc2c599&tokens[]=c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&attribute_keys[]=stateless_contract_addr_0&attribute_vals[]=0x8F68f4810CcE3194B6cB6F3d50fa58c2c9bDD1d5&attribute_keys[]=name&attribute_vals[]=tricrypto2&attribute_keys[]=factory_name&attribute_vals[]=NA&attribute_keys[]=factory&attribute_vals[]=0x0000000000000000000000000000000000000000,address=a5407eae9ba41422680e2e00537571bcc53efbfd&tx_hash=51aca4a03a395de8855fa2ca59b7febe520c2a223e69c502066162f7c1a95ec2&tokens[]=6b175474e89094c44da98b954eedeac495271d0f&tokens[]=a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&tokens[]=dac17f958d2ee523a2206206994597c13d831ec7&tokens[]=57ab1ec28d129707052df4df418d58a2d46d5f51&attribute_keys[]=name&attribute_vals[]=susd&attribute_keys[]=factory_name&attribute_vals[]=NA&attribute_keys[]=factory&attribute_vals[]=0x0000000000000000000000000000000000000000,address=dcef968d416a41cdac0ed8702fac8128a64241a2&tx_hash=1f4254004ce9e19d4eb742ee5a69d30f29085902d976f73e97c44150225ef775&tokens[]=853d955acef822db058eb8505911ed77f175b99e&tokens[]=a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&attribute_keys[]=name&attribute_vals[]=fraxusdc&attribute_keys[]=factory_name&attribute_vals[]=NA&attribute_keys[]=factory&attribute_vals[]=0x0000000000000000000000000000000000000000" + map_components: "address=bebc44782c7db0a1a60cb6fe97d0b483032ff1c7&tx_hash=20793bbf260912aae189d5d261ff003c9b9166da8191d8f9d63ff1c7722f3ac6&tokens[]=6b175474e89094c44da98b954eedeac495271d0f&tokens[]=a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&tokens[]=dac17f958d2ee523a2206206994597c13d831ec7&&static_attribute_keys[]=name&static_attribute_vals[]=3pool&static_attribute_keys[]=factory_name&static_attribute_vals[]=NA&static_attribute_keys[]=factory&static_attribute_vals[]=0x0000000000000000000000000000000000000000,address=dc24316b9ae028f1497c275eb9192a3ea0f67022&tx_hash=fac67ecbd423a5b915deff06045ec9343568edaec34ae95c43d35f2c018afdaa&tokens[]=eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee&tokens[]=ae7ab96520de3a18e5e111b5eaab095312d7fe84&&static_attribute_keys[]=name&static_attribute_vals[]=steth&static_attribute_keys[]=factory_name&static_attribute_vals[]=NA&static_attribute_keys[]=factory&static_attribute_vals[]=0x0000000000000000000000000000000000000000,address=d51a44d3fae010294c616388b506acda1bfaae46&contracts[]=c4ad29ba4b3c580e6d59105fff484999997675ff&contracts[]=40745803c2faa8e8402e2ae935933d07ca8f355c&tx_hash=dafb6385ed988ce8aacecfe1d97b38ea5e60b1ebce74d2423f71ddd621680138&tokens[]=dac17f958d2ee523a2206206994597c13d831ec7&tokens[]=2260fac5e5542a773aa44fbcfedf7c193bc2c599&tokens[]=c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&attribute_keys[]=stateless_contract_addr_0&attribute_vals[]=0x8F68f4810CcE3194B6cB6F3d50fa58c2c9bDD1d5&static_attribute_keys[]=name&static_attribute_vals[]=tricrypto2&static_attribute_keys[]=factory_name&static_attribute_vals[]=NA&static_attribute_keys[]=factory&static_attribute_vals[]=0x0000000000000000000000000000000000000000,address=a5407eae9ba41422680e2e00537571bcc53efbfd&tx_hash=51aca4a03a395de8855fa2ca59b7febe520c2a223e69c502066162f7c1a95ec2&tokens[]=6b175474e89094c44da98b954eedeac495271d0f&tokens[]=a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&tokens[]=dac17f958d2ee523a2206206994597c13d831ec7&tokens[]=57ab1ec28d129707052df4df418d58a2d46d5f51&&static_attribute_keys[]=name&static_attribute_vals[]=susd&static_attribute_keys[]=factory_name&static_attribute_vals[]=NA&static_attribute_keys[]=factory&static_attribute_vals[]=0x0000000000000000000000000000000000000000,address=dcef968d416a41cdac0ed8702fac8128a64241a2&tx_hash=1f4254004ce9e19d4eb742ee5a69d30f29085902d976f73e97c44150225ef775&tokens[]=853d955acef822db058eb8505911ed77f175b99e&tokens[]=a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&&static_attribute_keys[]=name&static_attribute_vals[]=fraxusdc&static_attribute_keys[]=factory_name&static_attribute_vals[]=NA&static_attribute_keys[]=factory&static_attribute_vals[]=0x0000000000000000000000000000000000000000"