diff --git a/.env.example b/.env.example index 866019c..e196c61 100755 --- a/.env.example +++ b/.env.example @@ -1,5 +1,5 @@ AVAIL_CLIENT_URL= -SUCCINCT_URL= +MERKLE_PROOF_SERVICE_URL= AVAIL_CHAIN_NAME= CONTRACT_CHAIN_ID= VECTORX_CONTRACT_ADDRESS= @@ -23,3 +23,7 @@ POSTGRES_URL= PG_USERNAME= PG_PASSWORD= POSTGRES_DB= + +HELIOS_UPDATE_FREQUENCY= + +VECTOR_UPDATE_FREQUENCY= \ No newline at end of file diff --git a/.sqlx/query-1780f7cc46df7e368f058c4d6604abdd8bac5de0a9ac71c248ac7c841edec225.json b/.sqlx/query-1780f7cc46df7e368f058c4d6604abdd8bac5de0a9ac71c248ac7c841edec225.json new file mode 100644 index 0000000..c5dc080 --- /dev/null +++ b/.sqlx/query-1780f7cc46df7e368f058c4d6604abdd8bac5de0a9ac71c248ac7c841edec225.json @@ -0,0 +1,96 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT be.message_id,\n be.sender,\n be.receiver,\n be.amount,\n be.source_block_hash,\n be.source_transaction_hash,\n be.block_number as source_block_height,\n be.timestamp,\n ai.block_height as \"destination_block_height?: i32\",\n ai.ext_index as \"destination_tx_index?: i32\",\n COALESCE(\n CASE\n WHEN be.status = 'in_progress' AND aet.message_id IS NULL THEN 'in_progress'::status\n WHEN be.status = 'in_progress' AND aet.message_id IS NOT NULL THEN 'bridged'::status\n ELSE be.status\n END,\n 'in_progress'::status\n ) ::status AS \"final_status!: BridgeStatusEnum\"\nFROM bridge_event be\n LEFT JOIN public.avail_execute_table AS aet\n ON be.message_id = aet.message_id\n LEFT JOIN public.avail_indexer AS ai on ai.id = aet.id\nWHERE be.sender = $1\n AND be.event_type = $2\n AND (ai.ext_success = $3\n OR ai.ext_success is null)\nORDER BY be.timestamp DESC\nLIMIT 1000", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "message_id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "sender", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "receiver", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "amount", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "source_block_hash", + "type_info": "Text" + }, + { + "ordinal": 5, + "name": "source_transaction_hash", + "type_info": "Text" + }, + { + "ordinal": 6, + "name": "source_block_height", + "type_info": "Int4" + }, + { + "ordinal": 7, + "name": "timestamp", + "type_info": "Int8" + }, + { + "ordinal": 8, + "name": "destination_block_height?: i32", + "type_info": "Int4" + }, + { + "ordinal": 9, + "name": "destination_tx_index?: i32", + "type_info": "Int4" + }, + { + "ordinal": 10, + "name": "final_status!: BridgeStatusEnum", + "type_info": { + "Custom": { + "name": "status", + "kind": { + "Enum": [ + "initiated", + "in_progress", + "claim_ready", + "bridged" + ] + } + } + } + } + ], + "parameters": { + "Left": [ + "Text", + "Text", + "Bool" + ] + }, + "nullable": [ + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + null + ] + }, + "hash": "1780f7cc46df7e368f058c4d6604abdd8bac5de0a9ac71c248ac7c841edec225" +} diff --git a/.sqlx/query-b4e72b9ba8a6b9d8947e2fdd6b58ecad9ad0c9bd398c13fdd879dced0dc81c43.json b/.sqlx/query-b4e72b9ba8a6b9d8947e2fdd6b58ecad9ad0c9bd398c13fdd879dced0dc81c43.json new file mode 100644 index 0000000..cbc8b56 --- /dev/null +++ b/.sqlx/query-b4e72b9ba8a6b9d8947e2fdd6b58ecad9ad0c9bd398c13fdd879dced0dc81c43.json @@ -0,0 +1,97 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT ai.id AS message_id,\n ai.signature_address AS sender,\n es.to AS \"receiver!\",\n COALESCE(es.amount, '0')::text AS \"amount!\",\n ai.block_hash AS source_block_hash,\n ai.ext_hash AS source_transaction_hash,\n ai.block_height AS source_block_height,\n ai.ext_index AS source_tx_index,\n es.block_timestamp,\n be.source_transaction_hash AS \"destination_tx_hash?: String\",\n COALESCE(\n CASE\n WHEN be.message_id IS NOT NULL THEN 'bridged'::status\n END,\n 'in_progress'::status\n ) ::status AS \"final_status!: BridgeStatusEnum\"\nFROM avail_send_message_table es\n INNER JOIN public.avail_indexer AS ai\n ON ai.id = es.id\n LEFT JOIN public.bridge_event AS be\n ON es.id = be.message_id\nWHERE ai.signature_address = $1\n AND es.type = $2\n AND (be.event_type = $3 or be.event_type is null)\n AND ai.ext_success = $4\nORDER BY es.block_timestamp DESC\nLIMIT 1000;\n", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "message_id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "sender", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "receiver!", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "amount!", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "source_block_hash", + "type_info": "Text" + }, + { + "ordinal": 5, + "name": "source_transaction_hash", + "type_info": "Text" + }, + { + "ordinal": 6, + "name": "source_block_height", + "type_info": "Int4" + }, + { + "ordinal": 7, + "name": "source_tx_index", + "type_info": "Int4" + }, + { + "ordinal": 8, + "name": "block_timestamp", + "type_info": "Int8" + }, + { + "ordinal": 9, + "name": "destination_tx_hash?: String", + "type_info": "Text" + }, + { + "ordinal": 10, + "name": "final_status!: BridgeStatusEnum", + "type_info": { + "Custom": { + "name": "status", + "kind": { + "Enum": [ + "initiated", + "in_progress", + "claim_ready", + "bridged" + ] + } + } + } + } + ], + "parameters": { + "Left": [ + "Text", + "Text", + "Text", + "Bool" + ] + }, + "nullable": [ + false, + true, + false, + null, + false, + false, + false, + false, + false, + false, + null + ] + }, + "hash": "b4e72b9ba8a6b9d8947e2fdd6b58ecad9ad0c9bd398c13fdd879dced0dc81c43" +} diff --git a/Cargo.lock b/Cargo.lock index 766d0d8..5a9ade9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -102,9 +102,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "alloy" -version = "1.0.7" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a6f38130b8716f18c69cede2b8ebe6cf70038a3d97740907bb0637941f759be" +checksum = "f07655fedc35188f3c50ff8fc6ee45703ae14ef1bc7ae7d80e23a747012184e3" dependencies = [ "alloy-consensus", "alloy-contract", @@ -120,6 +120,7 @@ dependencies = [ "alloy-signer-local", "alloy-transport", "alloy-transport-http", + "alloy-trie", ] [[package]] @@ -135,16 +136,18 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "1.0.7" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7329eb72d95576dfb8813175bcf671198fb24266b0b3e520052a513e30c284df" +checksum = "2e318e25fb719e747a7e8db1654170fc185024f3ed5b10f86c08d448a912f6e2" dependencies = [ "alloy-eips", "alloy-primitives", "alloy-rlp", "alloy-serde", "alloy-trie", + "alloy-tx-macros", "auto_impl", + "borsh", "c-kzg", "derive_more 2.0.1", "either", @@ -153,15 +156,16 @@ dependencies = [ "rand 0.8.5", "secp256k1 0.30.0", "serde", + "serde_json", "serde_with", "thiserror 2.0.11", ] [[package]] name = "alloy-consensus-any" -version = "1.0.7" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31b286aeef04a32720c10defd21c3aa6c626154ac442b55f6d472caeb1c6741" +checksum = "364380a845193a317bcb7a5398fc86cdb66c47ebe010771dde05f6869bf9e64a" dependencies = [ "alloy-consensus", "alloy-eips", @@ -173,9 +177,9 @@ dependencies = [ [[package]] name = "alloy-contract" -version = "1.0.7" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1658352ca9425d7b5bbb3ae364bc276ab18d4afae06f5faf00377b6964fdf68" +checksum = "08d39c80ffc806f27a76ed42f3351a455f3dc4f81d6ff92c8aad2cf36b7d3a34" dependencies = [ "alloy-consensus", "alloy-dyn-abi", @@ -189,14 +193,15 @@ dependencies = [ "alloy-transport", "futures", "futures-util", + "serde_json", "thiserror 2.0.11", ] [[package]] name = "alloy-core" -version = "1.1.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3c5a28f166629752f2e7246b813cdea3243cca59aab2d4264b1fd68392c10eb" +checksum = "5ca96214615ec8cf3fa2a54b32f486eb49100ca7fe7eb0b8c1137cd316e7250a" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -207,9 +212,9 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "1.1.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18cc14d832bc3331ca22a1c7819de1ede99f58f61a7d123952af7dde8de124a6" +checksum = "3fdff496dd4e98a81f4861e66f7eaf5f2488971848bb42d9c892f871730245c8" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -236,32 +241,34 @@ dependencies = [ [[package]] name = "alloy-eip2930" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b82752a889170df67bbb36d42ca63c531eb16274f0d7299ae2a680facba17bd" +checksum = "9441120fa82df73e8959ae0e4ab8ade03de2aaae61be313fbf5746277847ce25" dependencies = [ "alloy-primitives", "alloy-rlp", + "borsh", "serde", ] [[package]] name = "alloy-eip7702" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d4769c6ffddca380b0070d71c8b7f30bed375543fe76bb2f74ec0acf4b7cd16" +checksum = "2919c5a56a1007492da313e7a3b6d45ef5edc5d33416fdec63c0d7a2702a0d20" dependencies = [ "alloy-primitives", "alloy-rlp", + "borsh", "serde", "thiserror 2.0.11", ] [[package]] name = "alloy-eips" -version = "1.0.7" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fa190bfa5340aee544ac831114876fa73bc8da487095b49a5ea153a6a4656ea" +checksum = "a4c4d7c5839d9f3a467900c625416b24328450c65702eb3d8caff8813e4d1d33" dependencies = [ "alloy-eip2124", "alloy-eip2930", @@ -270,31 +277,36 @@ dependencies = [ "alloy-rlp", "alloy-serde", "auto_impl", + "borsh", "c-kzg", "derive_more 2.0.1", "either", "serde", + "serde_with", "sha2 0.10.8", + "thiserror 2.0.11", ] [[package]] name = "alloy-genesis" -version = "1.0.7" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b81b2dfd278d58af8bfde8753fa4685407ba8fbad8bc88a2bb0e065eed48478" +checksum = "1ba4b1be0988c11f0095a2380aa596e35533276b8fa6c9e06961bbfe0aebcac5" dependencies = [ "alloy-eips", "alloy-primitives", "alloy-serde", "alloy-trie", + "borsh", "serde", + "serde_with", ] [[package]] name = "alloy-json-abi" -version = "1.1.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ccaa79753d7bf15f06399ea76922afbfaf8d18bebed9e8fc452984b4a90dcc9" +checksum = "5513d5e6bd1cba6bdcf5373470f559f320c05c8c59493b6e98912fbe6733943f" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -304,12 +316,13 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "1.0.7" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ab2dba5dca01ad4281b4d4726a18e2012a20e3950bfc2a90c5376840555366" +checksum = "f72cf87cda808e593381fb9f005ffa4d2475552b7a6c5ac33d087bf77d82abd0" dependencies = [ "alloy-primitives", "alloy-sol-types", + "http", "serde", "serde_json", "thiserror 2.0.11", @@ -318,9 +331,9 @@ dependencies = [ [[package]] name = "alloy-network" -version = "1.0.7" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0ed07e76fbc72790a911ea100cdfbe85b1f12a097c91b948042e854959d140e" +checksum = "12aeb37b6f2e61b93b1c3d34d01ee720207c76fe447e2a2c217e433ac75b17f5" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -344,9 +357,9 @@ dependencies = [ [[package]] name = "alloy-network-primitives" -version = "1.0.7" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f05aa52713c376f797b3c7077708585f22a5c3053a7b1b2b355ea98edeb2052d" +checksum = "abd29ace62872083e30929cd9b282d82723196d196db589f3ceda67edcc05552" dependencies = [ "alloy-consensus", "alloy-eips", @@ -357,17 +370,17 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "1.1.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18c35fc4b03ace65001676358ffbbaefe2a2b27ee50fe777c345082c7c888be8" +checksum = "355bf68a433e0fd7f7d33d5a9fc2583fde70bf5c530f63b80845f8da5505cf28" dependencies = [ "alloy-rlp", "bytes", "cfg-if", "const-hex", "derive_more 2.0.1", - "foldhash", - "hashbrown 0.15.2", + "foldhash 0.2.0", + "hashbrown 0.16.0", "indexmap 2.7.0", "itoa", "k256", @@ -384,9 +397,9 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "1.0.7" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05a3f7a59c276c6e410267e77a166f9297dbe74e4605f1abf625e29d85c53144" +checksum = "9b710636d7126e08003b8217e24c09f0cca0b46d62f650a841736891b1ed1fc1" dependencies = [ "alloy-chains", "alloy-consensus", @@ -445,15 +458,14 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "1.0.7" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f185483536cbcbf55971077140e03548dad4f3a4ddb35044bcdc01b8f02ce1" +checksum = "d0882e72d2c1c0c79dcf4ab60a67472d3f009a949f774d4c17d0bdb669cfde05" dependencies = [ "alloy-json-rpc", "alloy-primitives", "alloy-transport", "alloy-transport-http", - "async-stream", "futures", "pin-project", "reqwest", @@ -463,16 +475,15 @@ dependencies = [ "tokio-stream", "tower", "tracing", - "tracing-futures", "url", "wasmtimer", ] [[package]] name = "alloy-rpc-types" -version = "1.0.7" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "347dfd77ba4d74886dba9e2872ff64fb246001b08868d27baec94e7248503e08" +checksum = "39cf1398cb33aacb139a960fa3d8cf8b1202079f320e77e952a0b95967bf7a9f" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -482,9 +493,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-any" -version = "1.0.7" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67971a228100ac65bd86e90439028853435f21796330ef08f00a70a918a84126" +checksum = "6a63fb40ed24e4c92505f488f9dd256e2afaed17faa1b7a221086ebba74f4122" dependencies = [ "alloy-consensus-any", "alloy-rpc-types-eth", @@ -493,9 +504,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "1.0.7" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d9b4293dfd4721781d33ee40de060376932d4a55d421cf6618ad66ff97cc52" +checksum = "9eae0c7c40da20684548cbc8577b6b7447f7bf4ddbac363df95e3da220e41e72" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -508,14 +519,15 @@ dependencies = [ "itertools 0.13.0", "serde", "serde_json", + "serde_with", "thiserror 2.0.11", ] [[package]] name = "alloy-serde" -version = "1.0.7" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b7d927aa39ca51545ae4c9cf4bdb2cbc1f6b46ab4b54afc3ed9255f93eedbce" +checksum = "c0df1987ed0ff2d0159d76b52e7ddfc4e4fbddacc54d2fbee765e0d14d7c01b5" dependencies = [ "alloy-primitives", "serde", @@ -524,9 +536,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "1.0.7" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c63771b50008d2b079187e9e74a08235ab16ecaf4609b4eb895e2890a3bcd465" +checksum = "6ff69deedee7232d7ce5330259025b868c5e6a52fa8dffda2c861fb3a5889b24" dependencies = [ "alloy-primitives", "async-trait", @@ -539,9 +551,9 @@ dependencies = [ [[package]] name = "alloy-signer-local" -version = "1.0.7" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db906294ee7876bd332cd760f460d30de183554434e07fc19d7d54e16a7aeaf0" +checksum = "72cfe0be3ec5a8c1a46b2e5a7047ed41121d360d97f4405bb7c1c784880c86cb" dependencies = [ "alloy-consensus", "alloy-network", @@ -555,9 +567,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "1.1.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8612e0658964d616344f199ab251a49d48113992d81b92dab93ed855faa66383" +checksum = "f3ce480400051b5217f19d6e9a82d9010cdde20f1ae9c00d53591e4a1afbb312" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", @@ -569,9 +581,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-expander" -version = "1.1.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a384edac7283bc4c010a355fb648082860c04b826bb7a814c45263c8f304c74" +checksum = "6d792e205ed3b72f795a8044c52877d2e6b6e9b1d13f431478121d8d4eaa9028" dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", @@ -588,9 +600,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-input" -version = "1.1.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd588c2d516da7deb421b8c166dc60b7ae31bca5beea29ab6621fcfa53d6ca5" +checksum = "0bd1247a8f90b465ef3f1207627547ec16940c35597875cdc09c49d58b19693c" dependencies = [ "alloy-json-abi", "const-hex", @@ -606,9 +618,9 @@ dependencies = [ [[package]] name = "alloy-sol-type-parser" -version = "1.1.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86ddeb70792c7ceaad23e57d52250107ebbb86733e52f4a25d8dc1abc931837" +checksum = "954d1b2533b9b2c7959652df3076954ecb1122a28cc740aa84e7b0a49f6ac0a9" dependencies = [ "serde", "winnow 0.7.10", @@ -616,9 +628,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "1.1.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "584cb97bfc5746cb9dcc4def77da11694b5d6d7339be91b7480a6a68dc129387" +checksum = "70319350969a3af119da6fb3e9bddb1bce66c9ea933600cb297c8b1850ad2a3c" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -628,12 +640,12 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "1.0.7" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca9b645fe4f4e6582cfbb4a8d20cedcf5aa23548e92eacbdacac6278b425e023" +checksum = "be98b07210d24acf5b793c99b759e9a696e4a2e67593aec0487ae3b3e1a2478c" dependencies = [ "alloy-json-rpc", - "alloy-primitives", + "auto_impl", "base64 0.22.1", "derive_more 2.0.1", "futures", @@ -651,9 +663,9 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "1.0.7" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee18869ecabe658ff6316e7db7c25d958c7d10f0a1723c2f7447d4f402920b66" +checksum = "4198a1ee82e562cab85e7f3d5921aab725d9bd154b6ad5017f82df1695877c97" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -666,9 +678,9 @@ dependencies = [ [[package]] name = "alloy-trie" -version = "0.8.1" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "983d99aa81f586cef9dae38443245e585840fcf0fc58b09aee0b1f27aed1d500" +checksum = "e3412d52bb97c6c6cc27ccc28d4e6e8cf605469101193b50b0bd5813b1f990b5" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -680,6 +692,18 @@ dependencies = [ "tracing", ] +[[package]] +name = "alloy-tx-macros" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "333544408503f42d7d3792bfc0f7218b643d968a03d2c0ed383ae558fb4a76d0" +dependencies = [ + "darling 0.21.3", + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -1264,6 +1288,15 @@ dependencies = [ "syn 2.0.101", ] +[[package]] +name = "atoi" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" +dependencies = [ + "num-traits", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -1383,11 +1416,12 @@ dependencies = [ [[package]] name = "backon" -version = "0.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e5b65cc81d81fbb8488f36458ab4771be35a722967bbc959df28b47397e3ff" +checksum = "cffb0e931875b666fc4fcb20fee52e9bbd1ef836fd9e9e04ec21555f9f85f7ef" dependencies = [ "fastrand", + "gloo-timers", "tokio", ] @@ -1453,6 +1487,20 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bigdecimal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "560f42649de9fa436b73517378a147ec21f6c997a546581df4b4b31677828934" +dependencies = [ + "autocfg", + "libm", + "num-bigint", + "num-integer", + "num-traits", + "serde", +] + [[package]] name = "binary-merkle-tree" version = "13.0.0" @@ -1542,6 +1590,9 @@ name = "bitflags" version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +dependencies = [ + "serde", +] [[package]] name = "bitvec" @@ -1605,6 +1656,29 @@ dependencies = [ "zeroize", ] +[[package]] +name = "borsh" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1da5ab77c1437701eeff7c88d968729e7766172279eab0676857b3d63af7a6f" +dependencies = [ + "borsh-derive", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0686c856aa6aac0c4498f936d7d6a02df690f614c03e4d906d1018062b5c5e2c" +dependencies = [ + "once_cell", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "bounded-collections" version = "0.2.2" @@ -1626,13 +1700,13 @@ dependencies = [ "avail-core", "axum", "backon", + "bigdecimal", "chrono", - "diesel", - "diesel-enum", "dotenvy", "http", "jsonrpsee", "lazy_static", + "log", "reqwest", "serde", "serde_json", @@ -1640,11 +1714,13 @@ dependencies = [ "sha3", "sp-core 34.0.0", "sp-io 34.0.0", + "sqlx", "tikv-jemallocator", "tokio", "tower-http", "tracing", "tracing-subscriber 0.3.19", + "uuid", ] [[package]] @@ -1749,6 +1825,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chrono" version = "0.4.39" @@ -1795,6 +1877,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2382f75942f4b3be3690fe4f86365e9c853c1587d6ee58212cebf6e2a9ccd101" +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "const-hex" version = "1.14.0" @@ -1942,6 +2033,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.21" @@ -2043,8 +2143,18 @@ version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.20.10", + "darling_macro 0.20.10", +] + +[[package]] +name = "darling" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +dependencies = [ + "darling_core 0.21.3", + "darling_macro 0.21.3", ] [[package]] @@ -2061,13 +2171,39 @@ dependencies = [ "syn 2.0.101", ] +[[package]] +name = "darling_core" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "serde", + "strsim", + "syn 2.0.101", +] + [[package]] name = "darling_macro" version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ - "darling_core", + "darling_core 0.20.10", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "darling_macro" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +dependencies = [ + "darling_core 0.21.3", "quote", "syn 2.0.101", ] @@ -2093,6 +2229,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", + "pem-rfc7468", "zeroize", ] @@ -2191,54 +2328,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "diesel" -version = "2.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf1bedf64cdb9643204a36dd15b19a6ce8e7aa7f7b105868e9f1fad5ffa7d12" -dependencies = [ - "bitflags 2.8.0", - "byteorder", - "chrono", - "diesel_derives", - "itoa", - "pq-sys", - "r2d2", -] - -[[package]] -name = "diesel-enum" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4b8470493d7120fd53f7d7db6ad167c2bc06fdf8abb3cef7e7669eb1347b415" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "diesel_derives" -version = "2.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f2c3de51e2ba6bf2a648285696137aaf0f5f487bcbea93972fe8a364e131a4" -dependencies = [ - "diesel_table_macro_syntax", - "dsl_auto_type", - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "diesel_table_macro_syntax" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "209c735641a413bc68c4923a9d6ad4bcb3ca306b794edaa7eb0b3228a99ffb25" -dependencies = [ - "syn 2.0.101", -] - [[package]] name = "digest" version = "0.9.0" @@ -2320,20 +2409,6 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" -[[package]] -name = "dsl_auto_type" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5d9abe6314103864cc2d8901b7ae224e0ab1a103a0a416661b4097b0779b607" -dependencies = [ - "darling", - "either", - "heck", - "proc-macro2", - "quote", - "syn 2.0.101", -] - [[package]] name = "dunce" version = "1.0.5" @@ -2527,6 +2602,17 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "etcetera" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" +dependencies = [ + "cfg-if", + "home", + "windows-sys 0.48.0", +] + [[package]] name = "ethabi-decode" version = "2.0.0" @@ -2559,6 +2645,17 @@ dependencies = [ "uint 0.10.0", ] +[[package]] +name = "event-listener" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + [[package]] name = "expander" version = "2.2.1" @@ -2659,6 +2756,17 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "flume" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" +dependencies = [ + "futures-core", + "futures-sink", + "spin", +] + [[package]] name = "fnv" version = "1.0.7" @@ -2671,6 +2779,12 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "foreign-types" version = "0.3.2" @@ -2847,6 +2961,17 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "futures-intrusive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot", +] + [[package]] name = "futures-io" version = "0.3.31" @@ -2924,8 +3049,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -2935,9 +3062,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi", "wasi 0.14.2+wasi-0.2.4", + "wasm-bindgen", ] [[package]] @@ -2973,6 +3102,18 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" +[[package]] +name = "gloo-timers" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "group" version = "0.13.0" @@ -3054,10 +3195,28 @@ checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ "allocator-api2", "equivalent", - "foldhash", + "foldhash 0.1.4", +] + +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" +dependencies = [ + "foldhash 0.2.0", "serde", ] +[[package]] +name = "hashlink" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +dependencies = [ + "hashbrown 0.15.2", +] + [[package]] name = "heck" version = "0.5.0" @@ -3094,6 +3253,15 @@ dependencies = [ "arrayvec", ] +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac 0.12.1", +] + [[package]] name = "hmac" version = "0.8.1" @@ -3134,6 +3302,15 @@ dependencies = [ "hmac 0.8.1", ] +[[package]] +name = "home" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "http" version = "1.2.0" @@ -3182,13 +3359,14 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "1.5.2" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" +checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" dependencies = [ + "atomic-waker", "bytes", "futures-channel", - "futures-util", + "futures-core", "h2", "http", "http-body", @@ -3196,6 +3374,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", + "pin-utils", "smallvec", "tokio", "want", @@ -3216,6 +3395,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower-service", + "webpki-roots 1.0.3", ] [[package]] @@ -3236,21 +3416,28 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.10" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" dependencies = [ + "base64 0.22.1", "bytes", "futures-channel", + "futures-core", "futures-util", "http", "http-body", "hyper", + "ipnet", + "libc", + "percent-encoding", "pin-project-lite", - "socket2", + "socket2 0.6.1", + "system-configuration", "tokio", "tower-service", "tracing", + "windows-registry", ] [[package]] @@ -3546,6 +3733,16 @@ version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" +[[package]] +name = "iri-string" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "itertools" version = "0.10.5" @@ -3613,9 +3810,9 @@ dependencies = [ [[package]] name = "jsonrpsee" -version = "0.25.1" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fba77a59c4c644fd48732367624d1bcf6f409f9c9a286fbc71d2f1fc0b2ea16" +checksum = "3f3f48dc3e6b8bd21e15436c1ddd0bc22a6a54e8ec46fedd6adf3425f396ec6a" dependencies = [ "jsonrpsee-core", "jsonrpsee-http-client", @@ -3626,9 +3823,9 @@ dependencies = [ [[package]] name = "jsonrpsee-core" -version = "0.25.1" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693c93cbb7db25f4108ed121304b671a36002c2db67dff2ee4391a688c738547" +checksum = "316c96719901f05d1137f19ba598b5fe9c9bc39f4335f67f6be8613921946480" dependencies = [ "async-trait", "bytes", @@ -3651,9 +3848,9 @@ dependencies = [ [[package]] name = "jsonrpsee-http-client" -version = "0.25.1" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6962d2bd295f75e97dd328891e58fce166894b974c1f7ce2e7597f02eeceb791" +checksum = "790bedefcec85321e007ff3af84b4e417540d5c87b3c9779b9e247d1bcc3dab8" dependencies = [ "base64 0.22.1", "http-body", @@ -3674,9 +3871,9 @@ dependencies = [ [[package]] name = "jsonrpsee-proc-macros" -version = "0.25.1" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fa4f5daed39f982a1bb9d15449a28347490ad42b212f8eaa2a2a344a0dce9e9" +checksum = "2da3f8ab5ce1bb124b6d082e62dffe997578ceaf0aeb9f3174a214589dc00f07" dependencies = [ "heck", "proc-macro-crate", @@ -3687,9 +3884,9 @@ dependencies = [ [[package]] name = "jsonrpsee-types" -version = "0.25.1" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66df7256371c45621b3b7d2fb23aea923d577616b9c0e9c0b950a6ea5c2be0ca" +checksum = "bc88ff4688e43cc3fa9883a8a95c6fa27aa2e76c96e610b737b6554d650d7fd5" dependencies = [ "http", "serde", @@ -3735,12 +3932,15 @@ name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] [[package]] name = "libc" -version = "0.2.169" +version = "0.2.178" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" [[package]] name = "libm" @@ -3748,6 +3948,17 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" +[[package]] +name = "libredox" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +dependencies = [ + "bitflags 2.8.0", + "libc", + "redox_syscall", +] + [[package]] name = "libsecp256k1" version = "0.7.1" @@ -3796,6 +4007,16 @@ dependencies = [ "libsecp256k1-core", ] +[[package]] +name = "libsqlite3-sys" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" +dependencies = [ + "pkg-config", + "vcpkg", +] + [[package]] name = "linux-raw-sys" version = "0.1.4" @@ -3842,6 +4063,12 @@ dependencies = [ "hashbrown 0.15.2", ] +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "mach" version = "0.3.2" @@ -3934,6 +4161,16 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest 0.10.7", +] + [[package]] name = "memchr" version = "2.7.4" @@ -4048,6 +4285,23 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-bigint-dig" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand 0.8.5", + "smallvec", + "zeroize", +] + [[package]] name = "num-conv" version = "0.1.0" @@ -4073,6 +4327,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -4115,13 +4380,14 @@ dependencies = [ [[package]] name = "nybbles" -version = "0.3.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8983bb634df7248924ee0c4c3a749609b5abcb082c28fffe3254b3eb3602b307" +checksum = "2c4b5ecbd0beec843101bffe848217f770e8b8da81d8355b7d6e226f2199b3dc" dependencies = [ "alloy-rlp", - "const-hex", + "cfg-if", "proptest", + "ruint", "serde", "smallvec", ] @@ -4255,6 +4521,12 @@ version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1ad0aff30c1da14b1254fcb2af73e1fa9a28670e584a626f53a369d0e157304" +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + [[package]] name = "parking_lot" version = "0.12.3" @@ -4314,6 +4586,15 @@ dependencies = [ "password-hash", ] +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -4363,6 +4644,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + [[package]] name = "pkcs8" version = "0.10.2" @@ -4468,15 +4760,6 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "pq-sys" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6cc05d7ea95200187117196eee9edd0644424911821aeb28a18ce60ea0b8793" -dependencies = [ - "vcpkg", -] - [[package]] name = "prettyplease" version = "0.2.29" @@ -4622,6 +4905,61 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2 0.6.1", + "thiserror 2.0.11", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +dependencies = [ + "bytes", + "getrandom 0.3.3", + "lru-slab", + "rand 0.9.1", + "ring 0.17.8", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.11", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2 0.6.1", + "tracing", + "windows-sys 0.60.2", +] + [[package]] name = "quote" version = "1.0.38" @@ -4637,17 +4975,6 @@ version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" -[[package]] -name = "r2d2" -version = "0.8.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93" -dependencies = [ - "log", - "parking_lot", - "scheduled-thread-pool", -] - [[package]] name = "radium" version = "0.7.0" @@ -4753,9 +5080,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.8" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ "bitflags 2.8.0", ] @@ -4826,16 +5153,14 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.12.15" +version = "0.12.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" +checksum = "3b4c14b2d9afca6a60277086b0cc6a6ae0b568f6f7916c943a8cdc79f8be240f" dependencies = [ - "async-compression", "base64 0.22.1", "bytes", "encoding_rs", "futures-core", - "futures-util", "h2", "http", "http-body", @@ -4844,30 +5169,30 @@ dependencies = [ "hyper-rustls", "hyper-tls", "hyper-util", - "ipnet", "js-sys", "log", "mime", "native-tls", - "once_cell", "percent-encoding", "pin-project-lite", - "rustls-pemfile", + "quinn", + "rustls", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", - "system-configuration", "tokio", "tokio-native-tls", - "tokio-util", + "tokio-rustls", "tower", + "tower-http", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "windows-registry", + "webpki-roots 1.0.3", ] [[package]] @@ -4921,15 +5246,36 @@ dependencies = [ "rustc-hex", ] +[[package]] +name = "rsa" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" +dependencies = [ + "const-oid", + "digest 0.10.7", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core 0.6.4", + "signature", + "spki", + "subtle", + "zeroize", +] + [[package]] name = "ruint" -version = "1.15.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11256b5fe8c68f56ac6f39ef0720e592f33d2367a4782740d9c9142e889c7fb4" +checksum = "a68df0380e5c9d20ce49534f292a36a7514ae21350726efe1865bdb1fa91d278" dependencies = [ "alloy-rlp", "ark-ff 0.3.0", "ark-ff 0.4.2", + "ark-ff 0.5.0", "bytes", "fastrlp 0.3.1", "fastrlp 0.4.0", @@ -4943,7 +5289,7 @@ dependencies = [ "rand 0.9.1", "rlp", "ruint-macro", - "serde", + "serde_core", "valuable", "zeroize", ] @@ -5044,21 +5390,13 @@ dependencies = [ "security-framework 3.2.0", ] -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", -] - [[package]] name = "rustls-pki-types" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" dependencies = [ + "web-time", "zeroize", ] @@ -5168,15 +5506,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "scheduled-thread-pool" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19" -dependencies = [ - "parking_lot", -] - [[package]] name = "schnellru" version = "0.2.4" @@ -5338,10 +5667,11 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.217" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ + "serde_core", "serde_derive", ] @@ -5354,11 +5684,20 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + [[package]] name = "serde_derive" -version = "1.0.217" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -5367,14 +5706,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.135" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", "memchr", "ryu", "serde", + "serde_core", ] [[package]] @@ -5432,7 +5772,7 @@ version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" dependencies = [ - "darling", + "darling 0.20.10", "proc-macro2", "quote", "syn 2.0.101", @@ -5448,6 +5788,17 @@ dependencies = [ "serde", ] +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + [[package]] name = "sha2" version = "0.9.9" @@ -5550,6 +5901,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "socket2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + [[package]] name = "sp-api" version = "26.0.0" @@ -6451,6 +6812,9 @@ name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] [[package]] name = "spki" @@ -6462,6 +6826,204 @@ dependencies = [ "der", ] +[[package]] +name = "sqlx" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fefb893899429669dcdd979aff487bd78f4064e5e7907e4269081e0ef7d97dc" +dependencies = [ + "sqlx-core", + "sqlx-macros", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", +] + +[[package]] +name = "sqlx-core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6" +dependencies = [ + "base64 0.22.1", + "bigdecimal", + "bytes", + "chrono", + "crc", + "crossbeam-queue", + "either", + "event-listener", + "futures-core", + "futures-intrusive", + "futures-io", + "futures-util", + "hashbrown 0.15.2", + "hashlink", + "indexmap 2.7.0", + "log", + "memchr", + "once_cell", + "percent-encoding", + "rustls", + "serde", + "serde_json", + "sha2 0.10.8", + "smallvec", + "thiserror 2.0.11", + "tokio", + "tokio-stream", + "tracing", + "url", + "webpki-roots 0.26.11", +] + +[[package]] +name = "sqlx-macros" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2d452988ccaacfbf5e0bdbc348fb91d7c8af5bee192173ac3636b5fb6e6715d" +dependencies = [ + "proc-macro2", + "quote", + "sqlx-core", + "sqlx-macros-core", + "syn 2.0.101", +] + +[[package]] +name = "sqlx-macros-core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19a9c1841124ac5a61741f96e1d9e2ec77424bf323962dd894bdb93f37d5219b" +dependencies = [ + "dotenvy", + "either", + "heck", + "hex", + "once_cell", + "proc-macro2", + "quote", + "serde", + "serde_json", + "sha2 0.10.8", + "sqlx-core", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", + "syn 2.0.101", + "tokio", + "url", +] + +[[package]] +name = "sqlx-mysql" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" +dependencies = [ + "atoi", + "base64 0.22.1", + "bigdecimal", + "bitflags 2.8.0", + "byteorder", + "bytes", + "chrono", + "crc", + "digest 0.10.7", + "dotenvy", + "either", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "generic-array", + "hex", + "hkdf", + "hmac 0.12.1", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "percent-encoding", + "rand 0.8.5", + "rsa", + "serde", + "sha1", + "sha2 0.10.8", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror 2.0.11", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-postgres" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" +dependencies = [ + "atoi", + "base64 0.22.1", + "bigdecimal", + "bitflags 2.8.0", + "byteorder", + "chrono", + "crc", + "dotenvy", + "etcetera", + "futures-channel", + "futures-core", + "futures-util", + "hex", + "hkdf", + "hmac 0.12.1", + "home", + "itoa", + "log", + "md-5", + "memchr", + "num-bigint", + "once_cell", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.10.8", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror 2.0.11", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-sqlite" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2d12fe70b2c1b4401038055f90f151b78208de1f9f89a7dbfd41587a10c3eea" +dependencies = [ + "atoi", + "chrono", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "libsqlite3-sys", + "log", + "percent-encoding", + "serde", + "serde_urlencoded", + "sqlx-core", + "thiserror 2.0.11", + "tracing", + "url", +] + [[package]] name = "ss58-registry" version = "1.51.0" @@ -6489,6 +7051,17 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "stringprep" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", + "unicode-properties", +] + [[package]] name = "strsim" version = "0.11.1" @@ -6573,9 +7146,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "1.1.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5d879005cc1b5ba4e18665be9e9501d9da3a9b95f625497c4cb7ee082b532e" +checksum = "ff790eb176cc81bb8936aed0f7b9f14fc4670069a2d371b3e3b0ecce908b2cb3" dependencies = [ "paste", "proc-macro2", @@ -6835,7 +7408,7 @@ dependencies = [ "mio", "parking_lot", "pin-project-lite", - "socket2", + "socket2 0.5.8", "tokio-macros", "windows-sys 0.52.0", ] @@ -6948,20 +7521,23 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.5.2" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ "async-compression", "bitflags 2.8.0", "bytes", "futures-core", + "futures-util", "http", "http-body", "http-body-util", + "iri-string", "pin-project-lite", "tokio", "tokio-util", + "tower", "tower-layer", "tower-service", "tracing", @@ -7012,18 +7588,6 @@ dependencies = [ "valuable", ] -[[package]] -name = "tracing-futures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" -dependencies = [ - "futures", - "futures-task", - "pin-project", - "tracing", -] - [[package]] name = "tracing-log" version = "0.1.4" @@ -7198,6 +7762,12 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" +[[package]] +name = "unicode-bidi" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + [[package]] name = "unicode-ident" version = "1.0.14" @@ -7213,6 +7783,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-properties" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" + [[package]] name = "unicode-xid" version = "0.2.6" @@ -7248,6 +7824,17 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +[[package]] +name = "uuid" +version = "1.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" +dependencies = [ + "getrandom 0.3.3", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "valuable" version = "0.1.0" @@ -7333,6 +7920,12 @@ dependencies = [ "wit-bindgen-rt", ] +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + [[package]] name = "wasm-bindgen" version = "0.2.100" @@ -7570,6 +8163,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "webpki-root-certs" version = "0.26.11" @@ -7588,6 +8191,34 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "webpki-roots" +version = "0.26.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" +dependencies = [ + "webpki-roots 1.0.3", +] + +[[package]] +name = "webpki-roots" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b130c0d2d49f8b6889abc456e795e82525204f27c42cf767cf0d7734e089b8" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "whoami" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d" +dependencies = [ + "libredox", + "wasite", +] + [[package]] name = "winapi" version = "0.3.9" @@ -7610,7 +8241,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.48.0", ] [[package]] @@ -7634,6 +8265,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + [[package]] name = "windows-registry" version = "0.4.0" @@ -7642,7 +8279,7 @@ checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" dependencies = [ "windows-result", "windows-strings", - "windows-targets 0.53.0", + "windows-targets 0.53.5", ] [[package]] @@ -7651,7 +8288,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ - "windows-link", + "windows-link 0.1.1", ] [[package]] @@ -7660,7 +8297,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" dependencies = [ - "windows-link", + "windows-link 0.1.1", ] [[package]] @@ -7699,6 +8336,24 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -7747,10 +8402,11 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.0" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ + "windows-link 0.2.1", "windows_aarch64_gnullvm 0.53.0", "windows_aarch64_msvc 0.53.0", "windows_i686_gnu 0.53.0", diff --git a/Cargo.toml b/Cargo.toml index 017aa5b..4700059 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,29 +10,32 @@ publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -alloy = { version = "1", features = ["serde", "json"] } +alloy = { version = "1.1.3", features = ["serde", "json"] } axum = { version = "0.8", features = ["http2", "macros", "tracing"] } dotenvy = "0.15" -jsonrpsee = { version = "0.25", features = ["http-client", "macros", "async-client"] } -reqwest = { version = "0.12", features = ["json", "brotli"] } +jsonrpsee = { version = "0.26.0", features = ["http-client", "macros", "async-client"] } +reqwest = { version = "0.12.26", features = ["json", "brotli"] } serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", features = ["arbitrary_precision"] } sha3 = "0.10" tokio = { version = "1.35", features = ["macros", "rt-multi-thread", "parking_lot"] } -tower-http = { version = "0.5", features = ["trace", "compression-br", "cors"] } +tower-http = { version = "0.6.6", features = ["trace", "compression-br", "cors"] } tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] } sp-io = "34.0" sp-core = "34.0" avail-core = { git = "https://github.com/availproject/avail-core", tag = "core-node-3"} http = "1.1" -backon = { version = "0.5", features = ["tokio-sleep"] } +backon = { version = "1.5.2", features = ["tokio-sleep"] } anyhow = "1" lazy_static = "1.5" -diesel = { version = "2.2", features = ["postgres", "chrono", "r2d2"] } -diesel-enum = "0.2.1" serde_with = "3.11.0" chrono = { version = "0.4", features = ["serde"] } +sqlx = { version = "0.8.6", features = ["postgres", "runtime-tokio-rustls", "macros", "chrono", "bigdecimal"] } +#alloy-rpc-types ="1.0.27" +bigdecimal = { version = "0.4", features = ["serde"] } +uuid = { version = "1.18.0", features = ["v4"] } +log = "0.4.25" [target.'cfg(not(target_env = "msvc"))'.dependencies] tikv-jemallocator = "0.6" diff --git a/README.md b/README.md index 8ab723b..16f6ec6 100755 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Bridge API -The bridge API is a REST API for fetching proofs from Avail's Kate RPC and Succinct API to submit on Ethereum or +The bridge API is a REST API for fetching proofs from Avail's Kate RPC and Merkle proof service API to submit on Ethereum or any off-chain proof verification. ## Deploying the bridge API @@ -309,48 +309,34 @@ RUSTFLAGS="-C target-cpu=native" cargo run --profile maxperf curl localhost:8080/v1/transactions?availAddress=0x1a985fdff5f6eee4afce1dc0f367ab925cdca57e7e8585329830fc3ce6ef4e7aðAddress=0x48e7e157cf873c15a5a6734ea37c000e1cb2383d ``` - * Response + * Response - ```json - { - "availSend": [ + ```json + [ { - "amount": "10000000000000000", - "depositorAddress": "0x1a985fdff5f6eee4afce1dc0f367ab925cdca57e7e8585329830fc3ce6ef4e7a", - "destinationBlockHash": null, - "destinationBlockNumber": null, - "destinationTimestamp": null, - "messageId": 106695577567233, - "receiverAddress": "0x8d31529525f23b14767d4dde78567ca083d3d56f", - "sourceBlockHash": "0x9cd91b1bd5497d96a98cf20e1563df29d85b8444d906a64a40980629e1288d70", - "sourceBlockNumber": 24842, - "sourceTimestamp": "2024-04-23T08:15:40", - "sourceTransactionHash": "0x9cd91b1bd5497d96a98cf20e1563df29d85b8444d906a64a40980629e1288d70", - "sourceTransactionIndex": 1, - "status": "claimPending", - "tokenId": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "ethSend": [ + "amount": "200000000000000000000000", + "claimEstimate": 3284, + "direction": "EthAvail", + "messageId": 1771, + "receiver": "0xc2b6ddd8382bcb813753562adb3d30cda40369750401b195dbabc6ac9bce620c", + "sender": "0xc1b2aff52877b4a23422f554f3d240be50ec80cf", + "sourceBlockHash": "0x1b18ad7d42e941b5df80585c2674aa9cd70cca6312dcca6374237b512e59ad7a", + "sourceTxHash": "0x3d4fa0e38bae95ad0a512def7c8d19174ecb943fe6a49fab55682ec6f89ab60a", + "status": "InProgress" + }, { - "amount": "10000000000000000", - "depositorAddress": "0x48e7e157cf873c15a5a6734ea37c000e1cb2383d", - "destinationBlockHash": "0xb52bdaf649c84fdccdf2e18aac13e18b0a67ceca11e23bfb94e6476cab23eb38", - "destinationBlockNumber": 22650, - "destinationTimestamp": "2024-04-22T20:03:40", - "destinationTransactionIndex": 1, - "messageId": 311, - "receiverAddress": "0x1a985fdff5f6eee4afce1dc0f367ab925cdca57e7e8585329830fc3ce6ef4e7a", - "sourceBlockHash": "0x463b0853f65f7a80c4c8ca188c37eb9589fb42cfe327bc1736ce02245bc045e8", - "sourceBlockNumber": 5755158, - "sourceTimestamp": "2024-04-22T19:40:24", - "sourceTransactionHash": "0xcf7945f68d7544a81eb8c32a794e97e229da3535aebd5488a4404f0a1093f29c", - "status": "bridged", - "tokenId": "0x0000000000000000000000000000000000000000000000000000000000000000" + "amount": "189766320000000000000000", + "claimEstimate": 3284, + "direction": "EthAvail", + "messageId": 1751, + "receiver": "0xc2b6ddd8382bcb813753562adb3d30cda40369750401b195dbabc6ac9bce620c", + "sender": "0xc1b2aff52877b4a23422f554f3d240be50ec80cf", + "sourceBlockHash": "0x207a0be28232e64fb984ac0ad1ea6e79cb32bbbf8217962277a4b2c9bc802997", + "sourceTxHash": "0xd060a6b7f8946bd0c8c8fb1bedf58f81a5745c250ef800e1bc18b00d57c79013", + "status": "InProgress" } - ] - } - ``` + ] + ``` ### Map slot to Ethereum block number (Deprecated) diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..472cf3d --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,17 @@ +version: '3' + +services: + db: + image: postgres:latest + container_name: bridge-api + environment: + POSTGRES_USER: avail + POSTGRES_PASSWORD: avail + POSTGRES_DB: ui-indexer + ports: + - "5432:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + +volumes: + postgres_data: diff --git a/sql/query_avail_tx.sql b/sql/query_avail_tx.sql new file mode 100644 index 0000000..66e9d44 --- /dev/null +++ b/sql/query_avail_tx.sql @@ -0,0 +1,27 @@ +SELECT ai.id AS message_id, + ai.signature_address AS sender, + es.to AS "receiver!", + COALESCE(es.amount, '0')::text AS "amount!", + ai.block_hash AS source_block_hash, + ai.ext_hash AS source_transaction_hash, + ai.block_height AS source_block_height, + ai.ext_index AS source_tx_index, + es.block_timestamp, + be.source_transaction_hash AS "destination_tx_hash?: String", + COALESCE( + CASE + WHEN be.message_id IS NOT NULL THEN 'bridged'::status + END, + 'in_progress'::status + ) ::status AS "final_status!: BridgeStatusEnum" +FROM avail_send_message_table es + INNER JOIN public.avail_indexer AS ai + ON ai.id = es.id + LEFT JOIN public.bridge_event AS be + ON es.id = be.message_id +WHERE ai.signature_address = $1 + AND es.type = $2 + AND (be.event_type = $3 or be.event_type is null) + AND ai.ext_success = $4 +ORDER BY es.block_timestamp DESC +LIMIT 1000; diff --git a/sql/query_eth_tx.sql b/sql/query_eth_tx.sql new file mode 100644 index 0000000..3a1dfed --- /dev/null +++ b/sql/query_eth_tx.sql @@ -0,0 +1,28 @@ +SELECT be.message_id, + be.sender, + be.receiver, + be.amount, + be.source_block_hash, + be.source_transaction_hash, + be.block_number as source_block_height, + be.timestamp, + ai.block_height as "destination_block_height?: i32", + ai.ext_index as "destination_tx_index?: i32", + COALESCE( + CASE + WHEN be.status = 'in_progress' AND aet.message_id IS NULL THEN 'in_progress'::status + WHEN be.status = 'in_progress' AND aet.message_id IS NOT NULL THEN 'bridged'::status + ELSE be.status + END, + 'in_progress'::status + ) ::status AS "final_status!: BridgeStatusEnum" +FROM bridge_event be + LEFT JOIN public.avail_execute_table AS aet + ON be.message_id = aet.message_id + LEFT JOIN public.avail_indexer AS ai on ai.id = aet.id +WHERE be.sender = $1 + AND be.event_type = $2 + AND (ai.ext_success = $3 + OR ai.ext_success is null) +ORDER BY be.timestamp DESC +LIMIT 1000 \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 7ea6c14..6c32428 100755 --- a/src/main.rs +++ b/src/main.rs @@ -1,14 +1,9 @@ mod models; -mod schema; +use crate::models::*; -use crate::models::{AvailSend, EthereumSend, StatusEnum}; -use crate::schema::avail_sends::dsl::avail_sends; -use crate::schema::ethereum_sends::dsl::ethereum_sends; use alloy::primitives::{Address, B256, U256, hex}; use alloy::providers::ProviderBuilder; -use alloy::sol; use anyhow::{Context, Result, anyhow}; -use avail_core::data_proof::AddressedMessage; use axum::body::{Body, to_bytes}; use axum::response::Response; use axum::{ @@ -20,12 +15,11 @@ use axum::{ }; use backon::ExponentialBuilder; use backon::Retryable; -use chrono::{NaiveDateTime, Utc}; -use diesel::{ - ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl, SelectableHelper, r2d2, - r2d2::ConnectionManager, -}; -use http::{HeaderMap, HeaderName, HeaderValue, Method}; +use chrono::Utc; + +use crate::models::TxDirection::{AvailEth, EthAvail}; +use alloy::core::sol; +use http::Method; use jsonrpsee::{ core::ClientError, core::client::ClientT, @@ -34,12 +28,11 @@ use jsonrpsee::{ }; use lazy_static::lazy_static; use reqwest::Client; -use serde::{Deserialize, Deserializer, Serialize}; use serde_json::{Value, json}; -use serde_with::serde_as; use sha3::{Digest, Keccak256}; -use sp_core::{Decode, H160, H256}; +use sp_core::Decode; use sp_io::hashing::twox_128; +use sqlx::PgPool; use std::collections::HashMap; use std::sync::Arc; use std::{env, process, time::Duration}; @@ -52,315 +45,45 @@ use tower_http::{ cors::{Any, CorsLayer}, trace::TraceLayer, }; +use tracing::{info, warn}; use tracing_subscriber::prelude::*; -#[cfg(not(target_env = "msvc"))] -#[global_allocator] -static GLOBAL: Jemalloc = Jemalloc; - -sol!( - #[allow(missing_docs)] - #[sol(rpc)] - SP1Vector, - "src/abi/SP1Vector.json" -); - -#[derive(Debug, Deserialize)] -struct Root { - data: Data, -} - -#[derive(Debug, Deserialize)] -struct Data { - message: Message, -} - -#[derive(Debug, Deserialize)] -struct Message { - slot: String, - body: MessageBody, -} - -#[derive(Debug, Deserialize)] -struct MessageBody { - execution_payload: ExecutionPayload, -} - -#[derive(Debug, Deserialize)] -struct ExecutionPayload { - block_number: String, - block_hash: String, -} - -struct ErrorResponse { - pub error: anyhow::Error, - pub headers_keypairs: Vec<(String, String)>, - pub status_code: Option, -} - -impl ErrorResponse { - pub fn new(error: anyhow::Error) -> Self { - Self { - error, - headers_keypairs: vec![], - status_code: None, - } - } - pub fn with_status(error: anyhow::Error, status_code: StatusCode) -> Self { - Self { - error, - headers_keypairs: vec![], - status_code: Some(status_code), - } - } - - pub fn with_status_and_headers( - error: anyhow::Error, - status_code: StatusCode, - headers: &[(&str, &str)], - ) -> Self { - let h = headers - .iter() - .map(|(k, v)| (k.to_string(), v.to_string())) - .collect::>(); - Self { - error, - headers_keypairs: h, - status_code: Some(status_code), - } +sol! { + #[derive(Debug)] + contract AvailBridge { + function sendAVAIL(bytes32 recipient, uint256 amount) external; + event MessageSent(address indexed from, bytes32 indexed to, uint256 messageId); } } -// Tell axum how to convert `AppError` into a response. -impl IntoResponse for ErrorResponse { - fn into_response(self) -> Response { - let status = self - .status_code - .unwrap_or(StatusCode::INTERNAL_SERVER_ERROR); - let mut headermap = HeaderMap::new(); - for (k, v) in self.headers_keypairs { - headermap.insert( - HeaderName::try_from(k).unwrap(), - HeaderValue::try_from(v).unwrap(), - ); - } - let json_resp = Json(json!({"error" : format!("{:#}", self.error)})); - - (status, headermap, json_resp).into_response() - } -} - -// This enables using `?` on functions that return `Result<_, anyhow::Error>` to turn them into -// `Result<_, AppError>`. That way you don't need to do that manually. -impl From for ErrorResponse -where - E: Into, -{ - fn from(err: E) -> Self { - Self { - error: err.into(), - headers_keypairs: vec![], - status_code: None, - } - } -} - -#[derive(Debug)] -struct AppState { - avail_client: HttpClient, - ethereum_client: HttpClient, - request_client: Client, - succinct_base_url: String, - beaconchain_base_url: String, - avail_chain_name: String, - contract_chain_id: String, - contract_address: String, - bridge_contract_address: String, - eth_head_cache_maxage: u16, - avl_head_cache_maxage: u16, - head_cache_maxage: u16, - avl_proof_cache_maxage: u32, - eth_proof_cache_maxage: u32, - proof_cache_maxage: u32, - eth_proof_failure_cache_maxage: u32, - slot_mapping_cache_maxage: u32, - transactions_cache_maxage: u32, - connection_pool: r2d2::Pool>, - chains: HashMap, -} +#[cfg(not(target_env = "msvc"))] +#[global_allocator] +static GLOBAL: Jemalloc = Jemalloc; #[derive(Debug)] -struct Chain { - rpc_url: String, - contract_address: Address, -} - -#[derive(Deserialize)] -struct IndexStruct { - index: u32, -} - -#[derive(Deserialize)] -struct ProofQueryStruct { - index: u32, - block_hash: B256, -} - -#[derive(Deserialize, Serialize)] -#[serde(rename_all = "camelCase")] -struct KateQueryDataProofResponse { - data_proof: DataProof, - #[serde(skip_serializing_if = "Option::is_none")] - message: Option, -} - -#[derive(Deserialize, Serialize)] -#[serde(rename_all = "camelCase")] -struct DataProof { - roots: Roots, - proof: Vec, - leaf_index: u32, - leaf: B256, -} - -#[derive(Deserialize, Serialize)] -#[serde(rename_all = "camelCase")] -struct Roots { - data_root: B256, - blob_root: B256, - bridge_root: B256, -} - -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -struct AccountStorageProofResponse { - account_proof: Vec, - storage_proof: Vec, -} - -#[derive(Deserialize)] -struct StorageProof { - proof: Vec, -} - -#[derive(Deserialize)] -struct SuccinctAPIResponse { - data: Option, - error: Option, - success: Option, -} - -#[derive(Serialize)] -#[serde(rename_all = "camelCase")] -struct SlotMappingResponse { - block_hash: String, - block_number: String, -} - -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -struct SuccinctAPIData { - range_hash: B256, - data_commitment: B256, - merkle_branch: Vec, - index: u16, -} - -#[derive(Serialize)] -#[serde(rename_all = "camelCase")] -struct AggregatedResponse { - data_root_proof: Vec, - leaf_proof: Vec, - range_hash: B256, - data_root_index: u16, - leaf: B256, - leaf_index: u32, - data_root: B256, - blob_root: B256, - bridge_root: B256, - data_root_commitment: B256, - block_hash: B256, - message: Option, -} - -impl AggregatedResponse { - pub fn new( - range_data: SuccinctAPIData, - data_proof_res: KateQueryDataProofResponse, - hash: B256, - ) -> Self { - AggregatedResponse { - data_root_proof: range_data.merkle_branch, - leaf_proof: data_proof_res.data_proof.proof, - range_hash: range_data.range_hash, - data_root_index: range_data.index, - leaf: data_proof_res.data_proof.leaf, - leaf_index: data_proof_res.data_proof.leaf_index, - data_root: data_proof_res.data_proof.roots.data_root, - blob_root: data_proof_res.data_proof.roots.blob_root, - bridge_root: data_proof_res.data_proof.roots.bridge_root, - data_root_commitment: range_data.data_commitment, - block_hash: hash, - message: data_proof_res.message, - } - } -} - -#[derive(Serialize)] -#[serde(rename_all = "camelCase")] -struct EthProofResponse { - account_proof: Vec, - storage_proof: Vec, -} - -#[derive(Serialize)] -#[serde(rename_all = "camelCase")] -struct HeadResponseV2 { - pub slot: u64, - pub block_number: u64, - pub block_hash: B256, - pub timestamp: u64, - pub timestamp_diff: u64, -} - -#[derive(Serialize)] -#[serde(rename_all = "camelCase")] -struct HeadResponseLegacy { - pub slot: u64, - pub timestamp: u64, - pub timestamp_diff: u64, -} - -#[derive(Serialize, Deserialize)] -struct ChainHeadResponse { - pub head: u32, -} - -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -struct RangeBlocks { - start: u32, - end: u32, -} - -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -struct RangeBlocksAPIResponse { - data: RangeBlocks, -} - -#[derive(Debug, Deserialize)] -pub struct HeaderBlockNumber { - #[serde(deserialize_with = "hex_to_u32")] - pub number: u32, -} - -fn hex_to_u32<'de, D>(deserializer: D) -> Result -where - D: Deserializer<'de>, -{ - let s: &str = Deserialize::deserialize(deserializer)?; - u32::from_str_radix(s.trim_start_matches("0x"), 16).map_err(serde::de::Error::custom) +pub struct AppState { + pub avail_client: HttpClient, + pub ethereum_client: HttpClient, + pub request_client: Client, + pub merkle_proof_service_base_url: String, + pub beaconchain_base_url: String, + pub avail_chain_name: String, + pub contract_chain_id: String, + pub contract_address: String, + pub bridge_contract_address: String, + pub eth_head_cache_maxage: u16, + pub avl_head_cache_maxage: u16, + pub head_cache_maxage: u16, + pub avl_proof_cache_maxage: u32, + pub eth_proof_cache_maxage: u32, + pub proof_cache_maxage: u32, + pub eth_proof_failure_cache_maxage: u32, + pub slot_mapping_cache_maxage: u32, + pub transactions_cache_maxage: u32, + pub db: PgPool, + pub chains: HashMap, + pub helios_update_frequency: u32, + pub vector_update_frequency: u32, } async fn alive() -> Result, StatusCode> { @@ -382,91 +105,14 @@ async fn versions(State(_state): State>) -> Result, St Ok(Json(json!(["v1"]))) } -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -struct TransactionQueryParams { - eth_address: Option, - avail_address: Option, -} - -#[derive(Debug, Serialize, Deserialize)] -#[serde_as] -#[serde(rename_all = "camelCase")] -pub struct TransactionData { - pub message_id: i64, - pub status: StatusEnum, - pub source_transaction_hash: String, - pub source_block_number: i64, - pub source_block_hash: String, - #[serde(skip_serializing_if = "Option::is_none")] - pub source_transaction_index: Option, - #[serde_as(as = "TimestampSeconds")] - pub source_timestamp: NaiveDateTime, - pub token_id: String, - pub destination_block_number: Option, - pub destination_block_hash: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub destination_transaction_index: Option, - #[serde_as(as = "Option")] - pub destination_timestamp: Option, - pub depositor_address: String, - pub receiver_address: String, - pub amount: String, -} - -#[derive(Debug, Default, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct TransactionResult { - pub avail_send: Vec, - pub eth_send: Vec, -} - -fn map_ethereum_send_to_transaction_result(send: EthereumSend) -> TransactionData { - TransactionData { - message_id: send.message_id, - status: send.status, - source_transaction_hash: send.source_transaction_hash, - source_block_number: send.source_block_number, - source_block_hash: send.source_block_hash, - source_transaction_index: None, - source_timestamp: send.source_timestamp, - token_id: send.token_id, - destination_block_number: send.destination_block_number, - destination_block_hash: send.destination_block_hash, - destination_transaction_index: send.destination_transaction_index, - destination_timestamp: send.destination_timestamp, - depositor_address: send.depositor_address, - receiver_address: send.receiver_address, - amount: send.amount, - } -} - -// Function to map AvailSend to TransactionResult -fn map_avail_send_to_transaction_result(send: AvailSend) -> TransactionData { - TransactionData { - message_id: send.message_id, - status: send.status, - source_transaction_hash: send.source_transaction_hash, - source_block_number: send.source_block_number, - source_block_hash: send.source_block_hash, - source_transaction_index: Some(send.source_transaction_index), - source_timestamp: send.source_timestamp, - token_id: send.token_id, - destination_block_number: send.destination_block_number, - destination_block_hash: send.destination_block_hash, - destination_transaction_index: None, - destination_timestamp: send.destination_timestamp, - depositor_address: send.depositor_address, - receiver_address: send.receiver_address, - amount: send.amount, - } -} - #[inline(always)] async fn transactions( Query(address_query): Query, State(state): State>, ) -> Result { + info!("Transaction query: {:?}", address_query); + + // check provided params if address_query.eth_address.is_none() && address_query.avail_address.is_none() { tracing::error!("Query params not provided."); return Err(ErrorResponse::with_status_and_headers( @@ -476,72 +122,165 @@ async fn transactions( )); } - let cloned_state = state.clone(); - let mut conn = cloned_state - .connection_pool - .get_timeout(Duration::from_secs(1)) - .expect("Get connection pool"); - - // Initialize the result variables - let mut transaction_results: TransactionResult = TransactionResult::default(); + let mut transaction_data_results: Vec = vec![]; - // Return the combined results if let Some(eth_address) = address_query.eth_address { - let ethereum_sends_results = ethereum_sends - .select(EthereumSend::as_select()) - .filter(schema::ethereum_sends::depositor_address.eq(format!("{:?}", eth_address))) - .order_by(schema::ethereum_sends::source_timestamp.desc()) - .limit(500) - .load::(&mut conn); - - transaction_results.eth_send = ethereum_sends_results - .map_err(|e| { - tracing::error!("Cannot get ethereum send transactions:: {e:#}"); - ErrorResponse::with_status_and_headers( - e.into(), - StatusCode::INTERNAL_SERVER_ERROR, - &[("Cache-Control", "public, max-age=60, must-revalidate")], - ) - })? - .into_iter() - .map(map_ethereum_send_to_transaction_result) - .collect(); + let transactions: Vec = sqlx::query_file_as!( + EthTransactionRow, + "sql/query_eth_tx.sql", + format!("{:?}", eth_address), + "MessageSent", + true + ) + .fetch_all(&state.db) + .await?; + + let slot_block_head = SLOT_BLOCK_HEAD.read().await; + let (_slot, last_eth_block, _hash, helios_update_timestamp) = + slot_block_head.as_ref().ok_or_else(|| { + ErrorResponse::with_status(anyhow!("Not found"), StatusCode::INTERNAL_SERVER_ERROR) + })?; + + let claim_estimate = + time_until_next_helios_update(*helios_update_timestamp, state.helios_update_frequency); + + for mut tx in transactions { + let mut estimate = None; + if tx.final_status != BridgeStatusEnum::Bridged + && tx.source_block_height <= (*last_eth_block) as i32 + { + // safe cast + tx.final_status = BridgeStatusEnum::ClaimReady + } else if tx.final_status != BridgeStatusEnum::Bridged + && tx.final_status != BridgeStatusEnum::ClaimReady + { + estimate = Some(claim_estimate.as_secs()); + } + + transaction_data_results.push(TransactionData::new( + EthAvail, + tx.message_id, + tx.sender, + tx.receiver, + tx.source_block_hash, + tx.source_transaction_hash, + tx.amount, + tx.final_status, + tx.timestamp, + estimate, + Some(tx.source_block_height), + None, + tx.destination_block_height, + tx.destination_tx_index, + None, + )); + } } if let Some(avail_address) = address_query.avail_address { - let avail_sends_results = avail_sends - .select(AvailSend::as_select()) - .filter(schema::avail_sends::depositor_address.eq(format!("{:?}", avail_address))) - .order_by(schema::avail_sends::source_timestamp.desc()) - .limit(500) - .load::(&mut conn); - - transaction_results.avail_send = avail_sends_results - .map_err(|e| { - tracing::error!("Cannot get avail send transactions: {e:#}"); - ErrorResponse::with_status_and_headers( - e.into(), - StatusCode::INTERNAL_SERVER_ERROR, - &[("Cache-Control", "public, max-age=60, must-revalidate")], - ) - })? - .into_iter() - .map(map_avail_send_to_transaction_result) - .collect(); + let transactions: Vec = sqlx::query_file_as!( + AvailTransactionRow, + "sql/query_avail_tx.sql", + avail_address, + "FungibleToken", + "MessageReceived", + true + ) + .fetch_all(&state.db) + .await?; + + let range_blocks = fetch_range_blocks(&state).await?; + + let avail_finalized_block: u32 = state + .avail_client + .request("chain_getFinalizedHead", rpc_params![]) + .await + .context("finalized head") + .unwrap_or(0); + + let claim_estimate = time_until_next_vector_update( + avail_finalized_block, + range_blocks.data.end, + state.vector_update_frequency, + 20, + ); + + for mut tx in transactions { + let mut estimate = None; + + if tx.final_status == BridgeStatusEnum::InProgress + && tx.source_block_height < range_blocks.data.end as i32 + { + tx.final_status = BridgeStatusEnum::ClaimReady; + } else if tx.final_status == BridgeStatusEnum::Initiated + || tx.final_status == BridgeStatusEnum::InProgress + { + estimate = Some(claim_estimate.as_secs()); + } + + transaction_data_results.push(TransactionData::new( + AvailEth, + tx.message_id, + tx.sender.unwrap_or("".to_string()), // cannot be empty because of where clause + tx.receiver, + tx.source_block_hash, + tx.source_transaction_hash, + tx.amount, + tx.final_status, + tx.block_timestamp, + estimate, + Some(tx.source_block_height), + Some(tx.source_tx_index), + None, + None, + tx.destination_tx_hash, + )); + } } - Ok(( - StatusCode::OK, - [( - "Cache-Control", - format!( - "public, max-age={}, immutable", - state.transactions_cache_maxage - ), - )], - Json(json!(transaction_results)), - ) - .into_response()) + transaction_data_results.sort_unstable_by(|a, b| b.timestamp.cmp(&a.timestamp)); + + Ok(Json(json!(transaction_data_results))) +} + +async fn fetch_range_blocks( + state: &Arc, +) -> Result { + let block_range_url = format!( + "{}/{}?chainName={}&contractChainId={}&contractAddress={}", + state.merkle_proof_service_base_url, + "range", + state.avail_chain_name, + state.contract_chain_id, + state.contract_address + ); + + let response = state + .request_client + .get(block_range_url) + .send() + .await + .map_err(|e| { + tracing::error!("Cannot parse range blocks: {e:#}"); + ErrorResponse::with_status_and_headers( + anyhow!("{e:#}"), + StatusCode::INTERNAL_SERVER_ERROR, + &[("Cache-Control", "public, max-age=60, must-revalidate")], + ) + })?; + + let range_blocks = response + .json::() + .await + .map_err(|e| { + tracing::error!("Cannot parse range blocks: {e:#}"); + ErrorResponse::with_status_and_headers( + anyhow!("{e:#}"), + StatusCode::INTERNAL_SERVER_ERROR, + &[("Cache-Control", "public, max-age=60, must-revalidate")], + ) + })?; + Ok(range_blocks) } #[inline(always)] @@ -565,21 +304,22 @@ async fn get_eth_proof( let eth_proof_failure_cache_maxage = state.eth_proof_failure_cache_maxage; let url = format!( "{}?chainName={}&contractChainId={}&contractAddress={}&blockHash={}", - state.succinct_base_url, + state.merkle_proof_service_base_url, state.avail_chain_name, state.contract_chain_id, state.contract_address, block_hash ); - let succinct_response_fut = tokio::spawn(async move { - let succinct_response = state.request_client.get(url).send().await; - match succinct_response { - Ok(resp) => resp.json::().await, + let mekrle_proof_response_fut = tokio::spawn(async move { + let merkle_proof_response = state.request_client.get(url).send().await; + match merkle_proof_response { + Ok(resp) => resp.json::().await, Err(err) => Err(err), } }); - let (data_proof, succinct_response) = join!(data_proof_response_fut, succinct_response_fut); + let (data_proof, merkle_proof_response) = + join!(data_proof_response_fut, mekrle_proof_response_fut); let data_proof_res: KateQueryDataProofResponse = data_proof .map_err(|e| { tracing::error!("❌ Failed to fetch the kate query data. Error: {e:#}"); @@ -592,17 +332,17 @@ async fn get_eth_proof( .map_err(|e| { tracing::error!("❌ Failed to get the kate query data. Error: {e:#}"); ErrorResponse::with_status_and_headers( - anyhow::anyhow!("Something went wrong."), + anyhow::anyhow!("Failed to get the kate query data."), StatusCode::BAD_REQUEST, &[("Cache-Control", "public, max-age=60, must-revalidate")], ) })?; - let succinct_data = succinct_response + let merkle_proof_data = merkle_proof_response .map_err(|e| { tracing::error!("❌ Failed to get the merkle proof data. Error: {e:#}"); ErrorResponse::with_status_and_headers( - anyhow::anyhow!("Something went wrong."), + anyhow::anyhow!("Failed to get the merkle proof data."), StatusCode::INTERNAL_SERVER_ERROR, &[("Cache-Control", "public, max-age=60, must-revalidate")], ) @@ -615,41 +355,46 @@ async fn get_eth_proof( &[("Cache-Control", "public, max-age=60, must-revalidate")], ) })?; - let succinct_data = match succinct_data { - SuccinctAPIResponse { + let merkle_data = match merkle_proof_data { + MekrleProofAPIResponse { data: Some(data), .. } => data, - SuccinctAPIResponse { + MekrleProofAPIResponse { success: Some(false), error: Some(data), .. } => { if data.contains("not in the range of blocks") { - tracing::warn!( - "⏳ Succinct VectorX contract not updated yet! Response: {}", + warn!( + "⏳ Merkle proof VectorX contract not updated yet! Response: {}", data ); + + return Err(ErrorResponse::with_status_and_headers( + anyhow!("VectorX contract not updated yet!"), + StatusCode::NOT_FOUND, + &[( + "Cache-Control", + &format!( + "public, max-age={eth_proof_failure_cache_maxage}, must-revalidate" + ), + )], + )); } else { - tracing::error!( - "❌ Succinct API returned unsuccessfully. Response: {}", - data - ); - } + tracing::error!("❌ Merkle API returned unsuccessfully. Response: {}", data); - return Err(ErrorResponse::with_status_and_headers( - anyhow!("{data}"), - StatusCode::NOT_FOUND, - &[( - "Cache-Control", - &format!("public, max-age={eth_proof_failure_cache_maxage}, must-revalidate"), - )], - )); + return Err(ErrorResponse::with_status_and_headers( + anyhow::anyhow!("Something went wrong."), + StatusCode::INTERNAL_SERVER_ERROR, + &[("Cache-Control", "public, max-age=60, must-revalidate")], + )); + } } _ => { - tracing::error!("❌ Succinct API returned no data"); + tracing::error!("❌ Merkle proof API returned no data"); return Err(ErrorResponse::with_status_and_headers( - anyhow!("Succinct API returned no data"), + anyhow!("Merkle proof API returned no data"), StatusCode::NOT_FOUND, &[("Cache-Control", "public, max-age=60, must-revalidate")], )); @@ -663,16 +408,16 @@ async fn get_eth_proof( format!("public, max-age={}, immutable", eth_proof_cache_maxage), )], Json(json!(AggregatedResponse { - data_root_proof: succinct_data.merkle_branch, + data_root_proof: merkle_data.merkle_branch, leaf_proof: data_proof_res.data_proof.proof, - range_hash: succinct_data.range_hash, - data_root_index: succinct_data.index, + range_hash: merkle_data.range_hash, + data_root_index: merkle_data.index, leaf: data_proof_res.data_proof.leaf, leaf_index: data_proof_res.data_proof.leaf_index, data_root: data_proof_res.data_proof.roots.data_root, blob_root: data_proof_res.data_proof.roots.blob_root, bridge_root: data_proof_res.data_proof.roots.bridge_root, - data_root_commitment: succinct_data.data_commitment, + data_root_commitment: merkle_data.data_commitment, block_hash, message: data_proof_res.message })), @@ -739,59 +484,6 @@ async fn get_avl_proof( .into_response()) } -/// Creates a request to the beaconcha service for mapping slot to the block number. -#[inline(always)] -async fn get_beacon_slot( - Path(slot): Path, - State(state): State>, -) -> Result { - let resp = state - .request_client - .get(format!( - "{}/eth/v2/beacon/blocks/{}", - state.beaconchain_base_url, slot - )) - .send() - .await - .map_err(|e| { - tracing::error!("❌ Cannot get beacon API data: {e:#}"); - ErrorResponse::with_status_and_headers( - e.into(), - StatusCode::INTERNAL_SERVER_ERROR, - &[("Cache-Control", "public, max-age=60, must-revalidate")], - ) - })?; - - let response_data = resp.json::().await.map_err(|e| { - tracing::error!("❌ Cannot get beacon API response data: {e:#}"); - ErrorResponse::with_status_and_headers( - e.into(), - StatusCode::INTERNAL_SERVER_ERROR, - &[("Cache-Control", "public, max-age=60, must-revalidate")], - ) - })?; - Ok(( - StatusCode::OK, - [( - "Cache-Control", - format!( - "public, max-age={}, immutable", - state.slot_mapping_cache_maxage - ), - )], - Json(json!(SlotMappingResponse { - block_number: response_data - .data - .message - .body - .execution_payload - .block_number, - block_hash: response_data.data.message.body.execution_payload.block_hash - })), - ) - .into_response()) -} - /// get_eth_head returns Ethereum head with the latest slot/block that is stored and a time. #[inline(always)] async fn get_eth_head( @@ -827,39 +519,6 @@ async fn get_eth_head( .into_response()) } -/// get_eth_head returns Ethereum head with the latest slot/block that is stored and a time. -#[inline(always)] -async fn get_eth_head_legacy( - State(state): State>, -) -> Result { - let slot_block_head = SLOT_BLOCK_HEAD.read().await; - let (slot, _block, _hash, timestamp) = slot_block_head.as_ref().ok_or_else(|| { - ErrorResponse::with_status_and_headers( - anyhow!("Not found"), - StatusCode::INTERNAL_SERVER_ERROR, - &[("Cache-Control", "public, max-age=60, must-revalidate")], - ) - })?; - - let now = Utc::now().timestamp() as u64; - Ok(( - StatusCode::OK, - [( - "Cache-Control", - format!( - "public, max-age={}, must-revalidate", - state.eth_head_cache_maxage - ), - )], - Json(json!(HeadResponseLegacy { - slot: *slot, - timestamp: *timestamp, - timestamp_diff: now - *timestamp - })), - ) - .into_response()) -} - /// get_avl_head returns start and end blocks which the contract has commitments #[inline(always)] async fn get_avl_head( @@ -867,7 +526,10 @@ async fn get_avl_head( ) -> Result { let url = format!( "{}/{}/?contractChainId={}&contractAddress={}", - state.succinct_base_url, "range", state.contract_chain_id, state.contract_address + state.merkle_proof_service_base_url, + "range", + state.contract_chain_id, + state.contract_address ); let response = state.request_client.get(url).send().await.map_err(|e| { tracing::error!("❌ Cannot parse range blocks: {e:#}"); @@ -1040,21 +702,21 @@ async fn get_proof( &[("Cache-Control", "max-age=60, must-revalidate")], ) })? { - Ok(SuccinctAPIResponse { + Ok(MekrleProofAPIResponse { data: Some(data), .. }) => data, - Ok(SuccinctAPIResponse { + Ok(MekrleProofAPIResponse { success: Some(false), error: Some(data), .. }) => { if data.contains("not in the range of blocks") { - tracing::warn!( - "Succinct VectorX contract not updated yet! Response: {}", + warn!("VectorX contract not updated yet! Response: {}", data); + } else { + tracing::error!( + "Merkle proof API returned unsuccessfully. Response: {}", data ); - } else { - tracing::error!("Succinct API returned unsuccessfully. Response: {}", data); } return Err(ErrorResponse::with_status_and_headers( anyhow!("error: {data}"), @@ -1063,7 +725,7 @@ async fn get_proof( )); } Err(err) => { - tracing::error!("Cannot get succinct api response {:?}", err); + tracing::error!("Cannot get merkle proof api response {:?}", err); return Err(ErrorResponse::with_status_and_headers( anyhow!("error: {err}"), StatusCode::INTERNAL_SERVER_ERROR, @@ -1071,9 +733,9 @@ async fn get_proof( )); } _ => { - tracing::error!("Succinct API returned no data"); + tracing::error!("Merkle proof API returned no data"); return Err(ErrorResponse::with_status_and_headers( - anyhow!("Succinct API returned no data"), + anyhow!("Merkle proof API returned no data"), StatusCode::INTERNAL_SERVER_ERROR, &[("Cache-Control", "max-age=60, must-revalidate")], )); @@ -1113,10 +775,10 @@ fn spawn_kate_proof( fn spawn_merkle_proof_range_fetch( state: Arc, block_hash: B256, -) -> JoinHandle> { +) -> JoinHandle> { let url = format!( "{}?chainName={}&contractChainId={}&contractAddress={}&blockHash={}", - state.succinct_base_url, + state.merkle_proof_service_base_url, state.avail_chain_name, state.contract_chain_id, state.contract_address, @@ -1125,7 +787,7 @@ fn spawn_merkle_proof_range_fetch( tokio::spawn(async move { let res = state.request_client.get(url).send().await; match res { - Ok(resp) => resp.json::().await, + Ok(resp) => resp.json::().await, Err(e) => Err(e), } }) @@ -1167,14 +829,19 @@ async fn main() { // Connection pool let connections_string = format!( "postgresql://{}:{}@{}/{}", - env::var("PG_USERNAME").unwrap_or("myuser".to_owned()), - env::var("PG_PASSWORD").unwrap_or("mypassword".to_owned()), + env::var("PG_USERNAME").unwrap_or("avail".to_owned()), + env::var("PG_PASSWORD").unwrap_or("avail".to_owned()), env::var("POSTGRES_URL").unwrap_or("localhost:5432".to_owned()), - env::var("POSTGRES_DB").unwrap_or("bridge-ui-indexer".to_owned()), + env::var("POSTGRES_DB").unwrap_or("ui-indexer".to_owned()), ); - let connection_pool = r2d2::Pool::builder() - .build(ConnectionManager::::new(connections_string)) - .expect("Failed to create pool."); + + info!("Connecting to {}", connections_string); + + let db = PgPool::connect(&connections_string) + .await + .context("Cannot get connection pool") + .unwrap(); + const SUPPORTED_CHAIN_IDS: [u64; 7] = [1, 123, 32657, 84532, 11155111, 17000, 421614]; // loop through expected_chain_ids and store the chain information, if value is missing, skip chain_id let chains = SUPPORTED_CHAIN_IDS @@ -1210,7 +877,7 @@ async fn main() { ) .unwrap(), request_client: Client::builder().brotli(true).build().unwrap(), - succinct_base_url: env::var("SUCCINCT_URL") + merkle_proof_service_base_url: env::var("MERKLE_PROOF_SERVICE_URL") .unwrap_or("https://beaconapi.succinct.xyz/api/integrations/vectorx".to_owned()), beaconchain_base_url: env::var("BEACONCHAIN_URL") .unwrap_or("https://sepolia.beaconcha.in/api/v1/slot".to_owned()), @@ -1258,31 +925,33 @@ async fn main() { transactions_mapping_response.parse::().ok() }) .unwrap_or(60), - connection_pool, + db, chains, + helios_update_frequency: env::var("HELIOS_UPDATE_FREQUENCY") + .ok() + .and_then(|helios_update_frequency| helios_update_frequency.parse::().ok()) + .unwrap_or(3600), + vector_update_frequency: env::var("VECTOR_UPDATE_FREQUENCY") + .ok() + .and_then(|vector_update_frequency| vector_update_frequency.parse::().ok()) + .unwrap_or(360), }); let app = Router::new() .route("/", get(alive)) .route("/versions", get(versions)) .route("/v1/info", get(info)) - .route("/info", get(info)) - .route("/v1/eth/proof/{block_hash}", get(get_eth_proof)) - .route("/eth/proof/{block_hash}", get(get_eth_proof)) - .route("/v1/eth/head", get(get_eth_head)) - .route("/eth/head", get(get_eth_head_legacy)) - .route("/v1/avl/head", get(get_avl_head)) - .route("/avl/head", get(get_avl_head)) + .route("/v1/eth/proof/{block_hash}", get(get_eth_proof)) // get proof from avail for ethereum + .route("/v1/eth/head", get(get_eth_head)) // fetch head form eth contract + .route("/v1/avl/head", get(get_avl_head)) // fetch head form avail pallet .route( "/v1/avl/proof/{block_hash}/{message_id}", - get(get_avl_proof), + get(get_avl_proof), // get proof from ethereum for avail ) - .route("/v1/transactions", get(transactions)) + .route("/v1/transactions", get(transactions)) // fetch all transaction .route("/transactions", get(transactions)) - .route("/avl/proof/{block_hash}/{message_id}", get(get_avl_proof)) - .route("/beacon/slot/{slot_number}", get(get_beacon_slot)) - .route("/v1/head/{chain_id}", get(get_head)) - .route("/v1/proof/{chain_id}", get(get_proof)) + .route("/v1/head/{chain_id}", get(get_head)) // get head based on chain + .route("/v1/proof/{chain_id}", get(get_proof)) // get proof for avail based on chain .layer(TraceLayer::new_for_http()) .layer(CompressionLayer::new()) .layer( @@ -1408,6 +1077,8 @@ async fn track_slot_avail_task(state: Arc) -> Result<()> { let mut slot_block_head = SLOT_BLOCK_HEAD.write().await; tracing::info!("Beacon mapping: {slot}:{bl}"); *slot_block_head = Some((slot, bl, hash, timestamp)); + info!("Timestamp form task: {:?}", timestamp); + drop(slot_block_head); tokio::time::sleep(Duration::from_secs(60 * 5)).await; @@ -1426,3 +1097,38 @@ async fn track_slot_avail_task(state: Arc) -> Result<()> { Ok(()) } + +fn time_until_next_vector_update( + current_block: u32, + last_updated_block: u32, + blocks_per_update: u32, + block_time_seconds: u32, +) -> Duration { + let blocks_since_update = current_block.saturating_sub(last_updated_block); + let blocks_remaining = blocks_per_update.saturating_sub(blocks_since_update); + + Duration::from_secs((blocks_remaining * block_time_seconds) as u64) +} + +fn time_until_next_helios_update(timestamp_ms: u64, helios_update_frequency: u32) -> Duration { + let now = Utc::now().timestamp() as u64; + let time_since_update = now - timestamp_ms; + let update_frequency = Duration::from_secs(helios_update_frequency as u64).as_secs(); + let remaining = update_frequency.saturating_sub(time_since_update); + Duration::from_secs(remaining) +} + +#[test] +fn test_remaining_time_for_vector_update() { + let duration = time_until_next_vector_update(350, 50, 360, 20); + assert_eq!(1200, duration.as_secs()); + let duration = time_until_next_vector_update(100, 50, 360, 20); + assert_eq!(6200, duration.as_secs()); +} + +#[test] +fn test_remaining_time_for_helios_update() { + let update = Utc::now().timestamp() - 1200; + let remaining = time_until_next_helios_update(update as u64, 3600); + assert_eq!(2400, remaining.as_secs()); +} diff --git a/src/models.rs b/src/models.rs index 67ebf4d..dccb254 100644 --- a/src/models.rs +++ b/src/models.rs @@ -1,102 +1,404 @@ -use crate::schema::sql_types::Status; -use chrono::NaiveDateTime; -use diesel::pg::{Pg, PgValue}; -use diesel::serialize::{IsNull, Output}; -use diesel::{ - deserialize::{self, FromSql}, - expression::AsExpression, - serialize::ToSql, - *, -}; +use alloy::primitives::{Address, B256}; +use alloy::sol; +use avail_core::data_proof::AddressedMessage; +use axum::Json; +use axum::response::{IntoResponse, Response}; +use bigdecimal::BigDecimal; +use http::{HeaderMap, HeaderName, HeaderValue, StatusCode}; use jsonrpsee::core::Serialize; -use serde::Deserialize; +use serde::{Deserialize, Deserializer}; +use serde_json::json; use serde_with::serde_as; -use std::io::Write; +use sp_core::H160; +use sqlx::FromRow; -#[derive(Debug, Clone, PartialEq, FromSqlRow, AsExpression, Eq)] -#[diesel(sql_type = Status)] -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub enum StatusEnum { - InProgress, - ClaimPending, - Bridged, +sol!( + #[allow(missing_docs)] + #[sol(rpc)] + SP1Vector, + "src/abi/SP1Vector.json" +); + +#[derive(Debug, Deserialize)] +pub struct Root { + pub data: Data, +} + +#[derive(Debug, Deserialize)] +pub struct Data { + pub message: Message, +} + +#[derive(Debug, Deserialize)] +pub struct Message { + pub slot: String, + pub body: MessageBody, +} + +#[derive(Debug, Deserialize)] +pub struct MessageBody { + pub execution_payload: ExecutionPayload, +} + +#[derive(Debug, Deserialize)] +pub struct ExecutionPayload { + pub block_number: String, + pub block_hash: String, } -impl ToSql for StatusEnum { - fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result { - match *self { - StatusEnum::InProgress => out.write_all(b"IN_PROGRESS")?, - StatusEnum::ClaimPending => out.write_all(b"CLAIM_PENDING")?, - StatusEnum::Bridged => out.write_all(b"BRIDGED")?, + +pub struct ErrorResponse { + pub error: anyhow::Error, + pub headers_keypairs: Vec<(String, String)>, + pub status_code: Option, +} + +impl ErrorResponse { + pub fn new(error: anyhow::Error) -> Self { + Self { + error, + headers_keypairs: vec![], + status_code: None, } - Ok(IsNull::No) } + pub fn with_status(error: anyhow::Error, status_code: StatusCode) -> Self { + Self { + error, + headers_keypairs: vec![], + status_code: Some(status_code), + } + } + + pub fn with_status_and_headers( + error: anyhow::Error, + status_code: StatusCode, + headers: &[(&str, &str)], + ) -> Self { + let h = headers + .iter() + .map(|(k, v)| (k.to_string(), v.to_string())) + .collect::>(); + Self { + error, + headers_keypairs: h, + status_code: Some(status_code), + } + } +} + +// Tell axum how to convert `AppError` into a response. +impl IntoResponse for ErrorResponse { + fn into_response(self) -> Response { + let status = self + .status_code + .unwrap_or(StatusCode::INTERNAL_SERVER_ERROR); + let mut headermap = HeaderMap::new(); + for (k, v) in self.headers_keypairs { + headermap.insert( + HeaderName::try_from(k).unwrap(), + HeaderValue::try_from(v).unwrap(), + ); + } + let json_resp = Json(json!({"error" : format!("{:#}", self.error)})); + + (status, headermap, json_resp).into_response() + } +} + +// This enables using `?` on functions that return `Result<_, anyhow::Error>` to turn them into +// `Result<_, AppError>`. That way you don't need to do that manually. +impl From for ErrorResponse +where + E: Into, +{ + fn from(err: E) -> Self { + Self { + error: err.into(), + headers_keypairs: vec![], + status_code: None, + } + } +} + +#[derive(Debug)] +pub struct Chain { + pub rpc_url: String, + pub contract_address: Address, +} + +#[derive(Deserialize)] +pub struct IndexStruct { + pub index: u32, +} + +#[derive(Deserialize)] +pub struct ProofQueryStruct { + pub index: u32, + pub block_hash: B256, +} + +#[derive(Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct KateQueryDataProofResponse { + pub data_proof: DataProof, + #[serde(skip_serializing_if = "Option::is_none")] + pub message: Option, +} + +#[derive(Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct DataProof { + pub roots: Roots, + pub proof: Vec, + pub leaf_index: u32, + pub leaf: B256, +} + +#[derive(Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct Roots { + pub data_root: B256, + pub blob_root: B256, + pub bridge_root: B256, +} + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct AccountStorageProofResponse { + pub account_proof: Vec, + pub storage_proof: Vec, +} + +#[derive(Deserialize)] +pub struct StorageProof { + pub proof: Vec, +} + +#[derive(Deserialize)] +pub struct MekrleProofAPIResponse { + pub data: Option, + pub error: Option, + pub success: Option, +} + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct MerkleProofData { + pub range_hash: B256, + pub data_commitment: B256, + pub merkle_branch: Vec, + pub index: u16, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct AggregatedResponse { + pub data_root_proof: Vec, + pub leaf_proof: Vec, + pub range_hash: B256, + pub data_root_index: u16, + pub leaf: B256, + pub leaf_index: u32, + pub data_root: B256, + pub blob_root: B256, + pub bridge_root: B256, + pub data_root_commitment: B256, + pub block_hash: B256, + pub message: Option, } -impl FromSql for StatusEnum { - fn from_sql(bytes: PgValue<'_>) -> deserialize::Result { - match bytes.as_bytes() { - b"IN_PROGRESS" => Ok(StatusEnum::InProgress), - b"CLAIM_PENDING" => Ok(StatusEnum::ClaimPending), - b"BRIDGED" => Ok(StatusEnum::Bridged), - _ => Err(format!( - "Unrecognized enum variant {}", - std::str::from_utf8(bytes.as_bytes()).unwrap() - ) - .as_str() - .into()), +impl AggregatedResponse { + pub fn new( + range_data: MerkleProofData, + data_proof_res: KateQueryDataProofResponse, + hash: B256, + ) -> Self { + AggregatedResponse { + data_root_proof: range_data.merkle_branch, + leaf_proof: data_proof_res.data_proof.proof, + range_hash: range_data.range_hash, + data_root_index: range_data.index, + leaf: data_proof_res.data_proof.leaf, + leaf_index: data_proof_res.data_proof.leaf_index, + data_root: data_proof_res.data_proof.roots.data_root, + blob_root: data_proof_res.data_proof.roots.blob_root, + bridge_root: data_proof_res.data_proof.roots.bridge_root, + data_root_commitment: range_data.data_commitment, + block_hash: hash, + message: data_proof_res.message, } } } -#[derive(Queryable, Selectable, Insertable, Identifiable, Serialize)] +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct EthProofResponse { + pub account_proof: Vec, + pub storage_proof: Vec, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct HeadResponseV2 { + pub slot: u64, + pub block_number: u64, + pub block_hash: B256, + pub timestamp: u64, + pub timestamp_diff: u64, +} + +#[derive(Serialize, Deserialize)] +pub struct ChainHeadResponse { + pub head: u32, +} + +#[derive(Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -#[diesel(table_name = crate::schema::avail_sends)] -#[diesel(primary_key(message_id))] -#[diesel(check_for_backend(diesel::pg::Pg))] -#[derive(Clone, Debug)] +pub struct RangeBlocks { + pub start: u32, + pub end: u32, +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct RangeBlocksAPIResponse { + pub data: RangeBlocks, +} + +#[derive(Debug, Deserialize)] +pub struct HeaderBlockNumber { + #[serde(deserialize_with = "hex_to_u32")] + pub number: u32, +} + +fn hex_to_u32<'de, D>(deserializer: D) -> anyhow::Result +where + D: Deserializer<'de>, +{ + let s: &str = Deserialize::deserialize(deserializer)?; + u32::from_str_radix(s.trim_start_matches("0x"), 16).map_err(serde::de::Error::custom) +} + +#[derive(Debug, PartialEq, Serialize, Deserialize, sqlx::Type)] +#[sqlx(type_name = "status")] +pub enum BridgeStatusEnum { + #[sqlx(rename = "initiated")] + Initiated, + #[sqlx(rename = "in_progress")] + InProgress, + #[sqlx(rename = "claim_ready")] + ClaimReady, + #[sqlx(rename = "bridged")] + Bridged, +} + +#[derive(Debug, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TransactionQueryParams { + pub eth_address: Option, + pub avail_address: Option, +} + +#[derive(Debug, Serialize, Deserialize, FromRow)] #[serde_as] -pub struct AvailSend { - pub message_id: i64, - pub status: StatusEnum, - pub source_transaction_hash: String, - pub source_block_number: i64, +#[serde(rename_all = "camelCase")] +pub struct EthTransactionRow { + pub message_id: BigDecimal, + pub sender: String, + pub receiver: String, pub source_block_hash: String, - pub source_transaction_index: i64, - #[serde_as(as = "TimestampSeconds")] - pub source_timestamp: NaiveDateTime, - pub token_id: String, - pub destination_block_number: Option, - pub destination_block_hash: Option, - #[serde_as(as = "Option")] - pub destination_timestamp: Option, - pub depositor_address: String, - pub receiver_address: String, + pub source_transaction_hash: String, pub amount: String, + pub timestamp: i64, + pub final_status: BridgeStatusEnum, + pub source_block_height: i32, + pub destination_block_height: Option, + pub destination_tx_index: Option, } -#[derive(Queryable, Selectable, Insertable, Identifiable, Serialize)] -#[serde(rename_all = "camelCase")] -#[diesel(table_name = crate::schema::ethereum_sends)] -#[diesel(primary_key(message_id))] -#[diesel(check_for_backend(diesel::pg::Pg))] -#[derive(Clone, Debug)] +#[derive(Debug, Serialize, Deserialize, FromRow)] #[serde_as] -pub struct EthereumSend { - pub message_id: i64, - pub status: StatusEnum, +#[serde(rename_all = "camelCase")] +pub struct AvailTransactionRow { + pub message_id: BigDecimal, + pub sender: Option, + pub receiver: String, + pub source_block_hash: String, pub source_transaction_hash: String, - pub source_block_number: i64, + pub amount: String, + pub block_timestamp: i64, + pub final_status: BridgeStatusEnum, + pub source_block_height: i32, + pub source_tx_index: i32, + pub destination_tx_hash: Option, +} + +#[derive(Debug, Serialize, Deserialize)] +pub enum TxDirection { + AvailEth, + EthAvail, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde_as] +#[serde(rename_all = "camelCase")] +pub struct TransactionData { + pub direction: TxDirection, + pub message_id: BigDecimal, + pub sender: String, + pub receiver: String, pub source_block_hash: String, - #[serde_as(as = "TimestampSeconds")] - pub source_timestamp: NaiveDateTime, - pub token_id: String, - pub destination_block_number: Option, - pub destination_block_hash: Option, - pub destination_transaction_index: Option, - #[serde_as(as = "Option")] - pub destination_timestamp: Option, - pub depositor_address: String, - pub receiver_address: String, + pub source_tx_hash: String, pub amount: String, + pub status: BridgeStatusEnum, + pub timestamp: i64, + #[serde(skip_serializing_if = "Option::is_none")] + pub claim_estimate: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub source_block_number: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub source_tx_index: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub destination_block_number: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub destination_tx_index: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub destination_tx_hash: Option, +} + +impl TransactionData { + pub fn new( + direction: TxDirection, + message_id: BigDecimal, + sender: String, + receiver: String, + source_block_hash: String, + source_tx_hash: String, + amount: String, + status: BridgeStatusEnum, + timestamp: i64, + claim_estimate: Option, + source_block_number: Option, + source_tx_index: Option, + destination_block_number: Option, + destination_tx_index: Option, + destination_tx_hash: Option, + ) -> Self { + Self { + direction, + message_id, + sender, + receiver, + source_block_hash, + source_tx_hash, + amount, + status, + timestamp, + claim_estimate, + source_block_number, + source_tx_index, + destination_block_number, + destination_tx_index, + destination_tx_hash, + } + } } diff --git a/src/schema.rs b/src/schema.rs deleted file mode 100644 index 54dec35..0000000 --- a/src/schema.rs +++ /dev/null @@ -1,79 +0,0 @@ -// @generated automatically by Diesel CLI. - -pub mod sql_types { - #[derive(diesel::query_builder::QueryId, Clone, diesel::sql_types::SqlType)] - #[diesel(postgres_type(name = "claim_type"))] - pub struct ClaimType; - - #[derive(diesel::query_builder::QueryId, Clone, diesel::sql_types::SqlType)] - #[diesel(postgres_type(name = "status"))] - pub struct Status; -} - -diesel::table! { - use diesel::sql_types::*; - use super::sql_types::Status; - use super::sql_types::ClaimType; - - avail_sends (message_id) { - message_id -> Int8, - status -> Status, - #[max_length = 66] - source_transaction_hash -> Varchar, - source_block_number -> Int8, - #[max_length = 66] - source_block_hash -> Varchar, - source_transaction_index -> Int8, - source_timestamp -> Timestamp, - #[max_length = 66] - token_id -> Varchar, - #[max_length = 66] - destination_transaction_hash -> Nullable, - destination_block_number -> Nullable, - #[max_length = 66] - destination_block_hash -> Nullable, - destination_timestamp -> Nullable, - #[max_length = 66] - depositor_address -> Varchar, - #[max_length = 22] - receiver_address -> Varchar, - #[max_length = 255] - amount -> Varchar, - claim_type -> ClaimType, - } -} - -diesel::table! { - use diesel::sql_types::*; - use super::sql_types::Status; - use super::sql_types::ClaimType; - - ethereum_sends (message_id) { - message_id -> Int8, - status -> Status, - #[max_length = 66] - source_transaction_hash -> Varchar, - source_block_number -> Int8, - #[max_length = 66] - source_block_hash -> Varchar, - source_timestamp -> Timestamp, - #[max_length = 66] - token_id -> Varchar, - #[max_length = 66] - destination_transaction_hash -> Nullable, - destination_block_number -> Nullable, - #[max_length = 66] - destination_block_hash -> Nullable, - destination_transaction_index-> Nullable, - destination_timestamp -> Nullable, - #[max_length = 66] - depositor_address -> Varchar, - #[max_length = 66] - receiver_address -> Varchar, - #[max_length = 255] - amount -> Varchar, - claim_type -> ClaimType, - } -} - -diesel::allow_tables_to_appear_in_same_query!(avail_sends, ethereum_sends,);