diff --git a/.env.example b/.env.example index 2097017..c93adda 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,5 @@ +DATABASE_URL=postgres://mina:whatever@localhost:5432/archive # TODO: we only need this one during development + MINAMESH_ARCHIVE_DATABASE_URL=postgres://mina:whatever@localhost:5432/archive MINAMESH_GENESIS_BLOCK_IDENTIFIER_STATE_HASH=3NK4BpDSekaqsG6tx8Nse2zJchRft2JpnbvMiog55WCr5xJZaKeP MINAMESH_GENESIS_BLOCK_IDENTIFIER_HEIGHT=359605 diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml index 4a5dc91..bc62ff8 100644 --- a/.github/workflows/checks.yaml +++ b/.github/workflows/checks.yaml @@ -54,16 +54,12 @@ jobs: ~/.cargo/git target key: ${{ runner.os }}-test-${{ hashFiles('**/Cargo.lock') }} - - name: Setup - run: | - cp .env.example .env - just get-mainnet-archive-db - just pg - just wait-for-pg - name: Test - run: just test - - name: Tear down - run: just pg-down + run: | + sed "s|postgres://mina:whatever@localhost:5432/archive|$MINAMESH_ARCHIVE_DATABASE_URL|g" .env.example > .env + just test + env: + MINAMESH_ARCHIVE_DATABASE_URL: ${{ secrets.MINAMESH_ARCHIVE_DATABASE_URL }} rustfmt: runs-on: ubuntu-latest diff --git a/.sqlx/query-54a347698cebe4f8696a0ba51c9b267ed9289096a665a13eeabd4b0dae1fc59a.json b/.sqlx/query-54a347698cebe4f8696a0ba51c9b267ed9289096a665a13eeabd4b0dae1fc59a.json new file mode 100644 index 0000000..6d50714 --- /dev/null +++ b/.sqlx/query-54a347698cebe4f8696a0ba51c9b267ed9289096a665a13eeabd4b0dae1fc59a.json @@ -0,0 +1,165 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT\n b.block_winner_id,\n b.chain_status AS \"chain_status: ChainStatus\",\n b.creator_id,\n b.global_slot_since_genesis,\n b.global_slot_since_hard_fork,\n b.height,\n b.id,\n b.last_vrf_output,\n b.ledger_hash,\n b.min_window_density,\n b.next_epoch_data_id,\n b.parent_hash,\n b.parent_id,\n b.proposed_protocol_version_id,\n b.protocol_version_id,\n b.snarked_ledger_hash_id,\n b.staking_epoch_data_id,\n b.state_hash,\n b.sub_window_densities,\n b.timestamp,\n b.total_currency,\n pk.value AS creator,\n bw.value AS winner\nFROM\n blocks b\n INNER JOIN public_keys pk ON pk.id=b.creator_id\n INNER JOIN public_keys bw ON bw.id=b.block_winner_id\nWHERE\n b.id=$1\n", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "block_winner_id", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "chain_status: ChainStatus", + "type_info": { + "Custom": { + "name": "chain_status_type", + "kind": { + "Enum": [ + "canonical", + "orphaned", + "pending" + ] + } + } + } + }, + { + "ordinal": 2, + "name": "creator_id", + "type_info": "Int4" + }, + { + "ordinal": 3, + "name": "global_slot_since_genesis", + "type_info": "Int8" + }, + { + "ordinal": 4, + "name": "global_slot_since_hard_fork", + "type_info": "Int8" + }, + { + "ordinal": 5, + "name": "height", + "type_info": "Int8" + }, + { + "ordinal": 6, + "name": "id", + "type_info": "Int4" + }, + { + "ordinal": 7, + "name": "last_vrf_output", + "type_info": "Text" + }, + { + "ordinal": 8, + "name": "ledger_hash", + "type_info": "Text" + }, + { + "ordinal": 9, + "name": "min_window_density", + "type_info": "Int8" + }, + { + "ordinal": 10, + "name": "next_epoch_data_id", + "type_info": "Int4" + }, + { + "ordinal": 11, + "name": "parent_hash", + "type_info": "Text" + }, + { + "ordinal": 12, + "name": "parent_id", + "type_info": "Int4" + }, + { + "ordinal": 13, + "name": "proposed_protocol_version_id", + "type_info": "Int4" + }, + { + "ordinal": 14, + "name": "protocol_version_id", + "type_info": "Int4" + }, + { + "ordinal": 15, + "name": "snarked_ledger_hash_id", + "type_info": "Int4" + }, + { + "ordinal": 16, + "name": "staking_epoch_data_id", + "type_info": "Int4" + }, + { + "ordinal": 17, + "name": "state_hash", + "type_info": "Text" + }, + { + "ordinal": 18, + "name": "sub_window_densities", + "type_info": "Int8Array" + }, + { + "ordinal": 19, + "name": "timestamp", + "type_info": "Text" + }, + { + "ordinal": 20, + "name": "total_currency", + "type_info": "Text" + }, + { + "ordinal": 21, + "name": "creator", + "type_info": "Text" + }, + { + "ordinal": 22, + "name": "winner", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Int4" + ] + }, + "nullable": [ + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + true, + true, + false, + false, + false, + false, + false, + false, + false, + false, + false + ] + }, + "hash": "54a347698cebe4f8696a0ba51c9b267ed9289096a665a13eeabd4b0dae1fc59a" +} diff --git a/.sqlx/query-62d4595387036ec87c261812c744bb1415fb492671cdb2000cfed94131f9ee60.json b/.sqlx/query-62d4595387036ec87c261812c744bb1415fb492671cdb2000cfed94131f9ee60.json new file mode 100644 index 0000000..9ae60c8 --- /dev/null +++ b/.sqlx/query-62d4595387036ec87c261812c744bb1415fb492671cdb2000cfed94131f9ee60.json @@ -0,0 +1,115 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT\n u.command_type AS \"command_type: UserCommandType\",\n u.nonce,\n u.amount,\n u.fee,\n u.valid_until,\n u.memo,\n u.hash,\n pk_payer.value AS fee_payer,\n pk_source.value AS source,\n pk_receiver.value AS receiver,\n buc.status AS \"status: TransactionStatus\",\n buc.failure_reason AS \"failure_reason?\",\n ac.creation_fee AS \"creation_fee?\"\nFROM\n user_commands AS u\n INNER JOIN blocks_user_commands AS buc ON u.id=buc.user_command_id\n INNER JOIN public_keys AS pk_payer ON u.fee_payer_id=pk_payer.id\n INNER JOIN public_keys AS pk_source ON u.source_id=pk_source.id\n INNER JOIN public_keys AS pk_receiver ON u.receiver_id=pk_receiver.id\n LEFT JOIN account_identifiers AS ai_receiver ON pk_receiver.id=ai_receiver.public_key_id\n /* Account creation fees are attributed to the first successful command in the\n block that mentions the account with the following LEFT JOIN */\n LEFT JOIN accounts_created AS ac ON buc.block_id=ac.block_id\n AND ai_receiver.id=ac.account_identifier_id\n AND buc.status='applied'\n AND buc.sequence_no=(\n SELECT\n least(\n (\n SELECT\n min(bic2.sequence_no)\n FROM\n blocks_internal_commands AS bic2\n INNER JOIN internal_commands AS ic2 ON bic2.internal_command_id=ic2.id\n WHERE\n u.receiver_id=ic2.receiver_id\n AND bic2.block_id=buc.block_id\n AND bic2.status='applied'\n ),\n (\n SELECT\n min(buc2.sequence_no)\n FROM\n blocks_user_commands AS buc2\n INNER JOIN user_commands AS uc2 ON buc2.user_command_id=uc2.id\n WHERE\n u.receiver_id=uc2.receiver_id\n AND buc2.block_id=buc.block_id\n AND buc2.status='applied'\n )\n )\n )\n LEFT JOIN tokens AS t ON ai_receiver.token_id=t.id\nWHERE\n buc.block_id=$1\n AND t.value=$2\n", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "command_type: UserCommandType", + "type_info": { + "Custom": { + "name": "user_command_type", + "kind": { + "Enum": [ + "payment", + "delegation" + ] + } + } + } + }, + { + "ordinal": 1, + "name": "nonce", + "type_info": "Int8" + }, + { + "ordinal": 2, + "name": "amount", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "fee", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "valid_until", + "type_info": "Int8" + }, + { + "ordinal": 5, + "name": "memo", + "type_info": "Text" + }, + { + "ordinal": 6, + "name": "hash", + "type_info": "Text" + }, + { + "ordinal": 7, + "name": "fee_payer", + "type_info": "Text" + }, + { + "ordinal": 8, + "name": "source", + "type_info": "Text" + }, + { + "ordinal": 9, + "name": "receiver", + "type_info": "Text" + }, + { + "ordinal": 10, + "name": "status: TransactionStatus", + "type_info": { + "Custom": { + "name": "transaction_status", + "kind": { + "Enum": [ + "applied", + "failed" + ] + } + } + } + }, + { + "ordinal": 11, + "name": "failure_reason?", + "type_info": "Text" + }, + { + "ordinal": 12, + "name": "creation_fee?", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Int4", + "Text" + ] + }, + "nullable": [ + false, + false, + true, + false, + true, + false, + false, + false, + false, + false, + false, + true, + false + ] + }, + "hash": "62d4595387036ec87c261812c744bb1415fb492671cdb2000cfed94131f9ee60" +} diff --git a/.sqlx/query-de3ae438ab25d585ae49ed2bf4b0761b3fbb32f2ff125cfc557e41106bb7debd.json b/.sqlx/query-de3ae438ab25d585ae49ed2bf4b0761b3fbb32f2ff125cfc557e41106bb7debd.json new file mode 100644 index 0000000..cd3e427 --- /dev/null +++ b/.sqlx/query-de3ae438ab25d585ae49ed2bf4b0761b3fbb32f2ff125cfc557e41106bb7debd.json @@ -0,0 +1,87 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT\n zc.id,\n zc.memo,\n zc.hash,\n pk_fee_payer.value AS fee_payer,\n zfpb.fee,\n zfpb.valid_until,\n zfpb.nonce,\n bzc.sequence_no,\n bzc.status AS \"status: TransactionStatus\",\n ARRAY(\n SELECT\n unnest(zauf.failures)\n FROM\n zkapp_account_update_failures AS zauf\n WHERE\n zauf.id=ANY (bzc.failure_reasons_ids)\n ) AS failure_reasons\nFROM\n blocks_zkapp_commands AS bzc\n INNER JOIN zkapp_commands AS zc ON bzc.zkapp_command_id=zc.id\n INNER JOIN zkapp_fee_payer_body AS zfpb ON zc.zkapp_fee_payer_body_id=zfpb.id\n INNER JOIN public_keys AS pk_fee_payer ON zfpb.public_key_id=pk_fee_payer.id\n INNER JOIN blocks AS b ON bzc.block_id=b.id\n LEFT JOIN zkapp_account_update AS zau ON zau.id=ANY (zc.zkapp_account_updates_ids)\n LEFT JOIN zkapp_account_update_body AS zaub ON zau.body_id=zaub.id\n LEFT JOIN account_identifiers AS ai_update_body ON zaub.account_identifier_id=ai_update_body.id\n LEFT JOIN public_keys AS pk_update_body ON ai_update_body.public_key_id=pk_update_body.id\n LEFT JOIN tokens AS token_update_body ON ai_update_body.token_id=token_update_body.id\nWHERE\n bzc.block_id=$1\n AND (\n token_update_body.value=$2\n OR token_update_body.id IS NULL\n )\nORDER BY\n zc.id,\n bzc.sequence_no\n", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "memo", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "hash", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "fee_payer", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "fee", + "type_info": "Text" + }, + { + "ordinal": 5, + "name": "valid_until", + "type_info": "Int8" + }, + { + "ordinal": 6, + "name": "nonce", + "type_info": "Int8" + }, + { + "ordinal": 7, + "name": "sequence_no", + "type_info": "Int4" + }, + { + "ordinal": 8, + "name": "status: TransactionStatus", + "type_info": { + "Custom": { + "name": "transaction_status", + "kind": { + "Enum": [ + "applied", + "failed" + ] + } + } + } + }, + { + "ordinal": 9, + "name": "failure_reasons", + "type_info": "TextArray" + } + ], + "parameters": { + "Left": [ + "Int4", + "Text" + ] + }, + "nullable": [ + false, + false, + false, + false, + false, + true, + false, + false, + false, + null + ] + }, + "hash": "de3ae438ab25d585ae49ed2bf4b0761b3fbb32f2ff125cfc557e41106bb7debd" +} diff --git a/.sqlx/query-e67cd389b7cac6565172a2f837861660557b9c084af85a5f4a24ee06cb0741e8.json b/.sqlx/query-e67cd389b7cac6565172a2f837861660557b9c084af85a5f4a24ee06cb0741e8.json new file mode 100644 index 0000000..c4f5671 --- /dev/null +++ b/.sqlx/query-e67cd389b7cac6565172a2f837861660557b9c084af85a5f4a24ee06cb0741e8.json @@ -0,0 +1,76 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH\n internal_commands_cte AS (\n SELECT DISTINCT\n ON (\n i.hash,\n i.command_type,\n bic.sequence_no,\n bic.secondary_sequence_no\n ) i.*,\n ac.creation_fee,\n pk.value AS receiver,\n bic.sequence_no,\n bic.secondary_sequence_no\n FROM\n internal_commands AS i\n INNER JOIN blocks_internal_commands AS bic ON i.id=bic.internal_command_id\n INNER JOIN public_keys AS pk ON i.receiver_id=pk.id\n INNER JOIN account_identifiers AS ai ON i.receiver_id=ai.public_key_id\n LEFT JOIN accounts_created AS ac ON ai.id=ac.account_identifier_id\n AND bic.block_id=ac.block_id\n AND bic.sequence_no=(\n SELECT\n least(\n (\n SELECT\n min(bic2.sequence_no)\n FROM\n blocks_internal_commands AS bic2\n INNER JOIN internal_commands AS ic2 ON bic2.internal_command_id=ic2.id\n WHERE\n i.receiver_id=ic2.receiver_id\n AND bic2.block_id=bic.block_id\n AND bic2.status='applied'\n ),\n (\n SELECT\n min(buc2.sequence_no)\n FROM\n blocks_user_commands AS buc2\n INNER JOIN user_commands AS uc2 ON buc2.user_command_id=uc2.id\n WHERE\n i.receiver_id=uc2.receiver_id\n AND buc2.block_id=bic.block_id\n AND buc2.status='applied'\n )\n )\n )\n INNER JOIN tokens AS t ON ai.token_id=t.id\n WHERE\n bic.block_id=$1\n AND t.value=$2\n )\nSELECT\n ic.command_type AS \"command_type: InternalCommandType\",\n ic.hash,\n ic.creation_fee AS \"creation_fee?\",\n ic.receiver,\n ic.sequence_no,\n ic.secondary_sequence_no,\n ic.fee,\n coinbase_receiver_pk.value AS coinbase_receiver\nFROM\n internal_commands_cte AS ic\n LEFT JOIN internal_commands_cte AS ic_coinbase_receiver ON ic.command_type='fee_transfer_via_coinbase'\n AND ic_coinbase_receiver.command_type='coinbase'\n LEFT JOIN public_keys AS coinbase_receiver_pk ON ic_coinbase_receiver.receiver_id=coinbase_receiver_pk.id\n", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "command_type: InternalCommandType", + "type_info": { + "Custom": { + "name": "internal_command_type", + "kind": { + "Enum": [ + "fee_transfer_via_coinbase", + "fee_transfer", + "coinbase" + ] + } + } + } + }, + { + "ordinal": 1, + "name": "hash", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "creation_fee?", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "receiver", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "sequence_no", + "type_info": "Int4" + }, + { + "ordinal": 5, + "name": "secondary_sequence_no", + "type_info": "Int4" + }, + { + "ordinal": 6, + "name": "fee", + "type_info": "Text" + }, + { + "ordinal": 7, + "name": "coinbase_receiver", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Int4", + "Text" + ] + }, + "nullable": [ + false, + false, + false, + false, + false, + false, + false, + true + ] + }, + "hash": "e67cd389b7cac6565172a2f837861660557b9c084af85a5f4a24ee06cb0741e8" +} diff --git a/Cargo.lock b/Cargo.lock index 5118ad4..7200a4b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -513,6 +513,15 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -713,6 +722,28 @@ dependencies = [ "serde", ] +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "syn 2.0.72", + "unicode-xid", +] + [[package]] name = "digest" version = "0.10.7" @@ -1497,9 +1528,11 @@ dependencies = [ "anyhow", "axum", "clap", + "convert_case", "cynic", "cynic-codegen", "cynic-querygen", + "derive_more", "dotenv", "envy", "futures", @@ -3129,6 +3162,18 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52ea75f83c0137a9b98608359a5f1af8144876eb67bcb1ce837368e906a9f524" +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + [[package]] name = "unicode_categories" version = "0.1.1" diff --git a/Cargo.toml b/Cargo.toml index 28ef164..6646203 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,9 @@ aide = { version = "0.13.4", features = ["scalar"] } anyhow = "1.0.86" axum = { version = "0.7.5", features = ["macros"] } clap = { version = "4.5.11", features = ["derive", "env"] } +convert_case = "0.6.0" cynic = { version = "3.7.3", features = ["http-reqwest-blocking"] } +derive_more = { version = "1.0.0", features = ["full"] } dotenv = "0.15.0" envy = "0.4.2" futures = "0.3.30" diff --git a/cspell.json b/cspell.json index 2542756..e46a20c 100644 --- a/cspell.json +++ b/cspell.json @@ -17,6 +17,7 @@ "sql/**", "static/scalar.standalone.min.js", "target/**", + "tests/snapshots", "flake.*", "nix/**", ".gitignore" diff --git a/sql/internal_commands.sql b/sql/internal_commands.sql index c766631..51b9e37 100644 --- a/sql/internal_commands.sql +++ b/sql/internal_commands.sql @@ -51,7 +51,13 @@ WITH AND t.value=$2 ) SELECT - ic.*, + ic.command_type AS "command_type: InternalCommandType", + ic.hash, + ic.creation_fee AS "creation_fee?", + ic.receiver, + ic.sequence_no, + ic.secondary_sequence_no, + ic.fee, coinbase_receiver_pk.value AS coinbase_receiver FROM internal_commands_cte AS ic diff --git a/sql/query_id.sql b/sql/query_id.sql index 03ae000..626e891 100644 --- a/sql/query_id.sql +++ b/sql/query_id.sql @@ -1,5 +1,25 @@ SELECT - b.*, + b.block_winner_id, + b.chain_status AS "chain_status: ChainStatus", + b.creator_id, + b.global_slot_since_genesis, + b.global_slot_since_hard_fork, + b.height, + b.id, + b.last_vrf_output, + b.ledger_hash, + b.min_window_density, + b.next_epoch_data_id, + b.parent_hash, + b.parent_id, + b.proposed_protocol_version_id, + b.protocol_version_id, + b.snarked_ledger_hash_id, + b.staking_epoch_data_id, + b.state_hash, + b.sub_window_densities, + b.timestamp, + b.total_currency, pk.value AS creator, bw.value AS winner FROM diff --git a/sql/user_commands.sql b/sql/user_commands.sql index 9ce4571..fb7ea96 100644 --- a/sql/user_commands.sql +++ b/sql/user_commands.sql @@ -1,11 +1,17 @@ SELECT - u.*, + u.command_type AS "command_type: UserCommandType", + u.nonce, + u.amount, + u.fee, + u.valid_until, + u.memo, + u.hash, pk_payer.value AS fee_payer, pk_source.value AS source, pk_receiver.value AS receiver, - buc.status, - buc.failure_reason, - ac.creation_fee + buc.status AS "status: TransactionStatus", + buc.failure_reason AS "failure_reason?", + ac.creation_fee AS "creation_fee?" FROM user_commands AS u INNER JOIN blocks_user_commands AS buc ON u.id=buc.user_command_id @@ -48,7 +54,4 @@ FROM LEFT JOIN tokens AS t ON ai_receiver.token_id=t.id WHERE buc.block_id=$1 - AND ( - t.value=$2 - OR t.id IS NULL - ) + AND t.value=$2 diff --git a/sql/zkapps_commands.sql b/sql/zkapp_commands.sql similarity index 93% rename from sql/zkapps_commands.sql rename to sql/zkapp_commands.sql index c187952..8c6d497 100644 --- a/sql/zkapps_commands.sql +++ b/sql/zkapp_commands.sql @@ -1,11 +1,13 @@ SELECT - zc.*, + zc.id, + zc.memo, + zc.hash, pk_fee_payer.value AS fee_payer, zfpb.fee, zfpb.valid_until, zfpb.nonce, bzc.sequence_no, - bzc.status, + bzc.status AS "status: TransactionStatus", ARRAY( SELECT unnest(zauf.failures) diff --git a/src/api.rs b/src/api.rs index b68b12a..6c50edb 100644 --- a/src/api.rs +++ b/src/api.rs @@ -15,20 +15,3 @@ mod network_health_check; mod network_list; mod network_options; mod network_status; - -pub use account_balance::*; -pub use block::*; -pub use call::*; -pub use construction_combine::*; -pub use construction_derive::*; -pub use construction_hash::*; -pub use construction_metadata::*; -pub use construction_parse::*; -pub use construction_payloads::*; -pub use construction_preprocess::*; -pub use construction_submit::*; -pub use mempool::*; -pub use mempool_transaction::*; -pub use network_list::*; -pub use network_options::*; -pub use network_status::*; diff --git a/src/api/account_balance.rs b/src/api/account_balance.rs index 689d721..9386c80 100644 --- a/src/api/account_balance.rs +++ b/src/api/account_balance.rs @@ -1,7 +1,7 @@ use cynic::QueryBuilder; -use mesh::models::AccountIdentifier; -pub use mesh::models::{ - AccountBalanceRequest, AccountBalanceResponse, Amount, BlockIdentifier, Currency, PartialBlockIdentifier, +use mesh::models::{ + AccountBalanceRequest, AccountBalanceResponse, AccountIdentifier, Amount, BlockIdentifier, Currency, + PartialBlockIdentifier, }; use crate::{ diff --git a/src/api/block.rs b/src/api/block.rs index 8ea8f17..d96e3a0 100644 --- a/src/api/block.rs +++ b/src/api/block.rs @@ -1,21 +1,121 @@ use anyhow::Result; -use cynic::QueryBuilder; -pub use mesh::models::{BlockRequest, BlockResponse, PartialBlockIdentifier}; +use convert_case::{Case, Casing}; +use mesh::models::{ + AccountIdentifier, Amount, Block, BlockIdentifier, BlockRequest, BlockResponse, Currency, Operation, + OperationIdentifier, PartialBlockIdentifier, Transaction, TransactionIdentifier, +}; +use serde::Serialize; +use sqlx::FromRow; use crate::{ - graphql::{QueryBlockTransactions, QueryBlockTransactionsVariables}, - MinaMesh, MinaMeshError, Wrapper, + util::DEFAULT_TOKEN_ID, ChainStatus, InternalCommandType, MinaMesh, MinaMeshError, OperationStatus, OperationType, + TransactionStatus, UserCommandType, }; -#[derive(sqlx::Type, Debug, PartialEq, Eq)] -#[sqlx(type_name = "chain_status_type", rename_all = "lowercase")] -enum ChainStatus { - Canonical, - Pending, - Orphaned, +/// https://github.com/MinaProtocol/mina/blob/985eda49bdfabc046ef9001d3c406e688bc7ec45/src/app/rosetta/lib/block.ml#L7 +impl MinaMesh { + pub async fn block(&self, request: BlockRequest) -> Result { + let partial_block_identifier = *request.block_identifier; + let metadata = match self.block_metadata(&partial_block_identifier).await? { + Some(metadata) => metadata, + None => return Err(MinaMeshError::BlockMissing(serde_json::to_string(&partial_block_identifier)?)), + }; + let parent_block_metadata = match &metadata.parent_id { + Some(parent_id) => { + sqlx::query_file_as!(BlockMetadata, "sql/query_id.sql", parent_id).fetch_optional(&self.pg_pool).await? + } + None => None, + }; + let block_identifier = BlockIdentifier::new(metadata.height, metadata.state_hash.clone()); + let parent_block_identifier = match parent_block_metadata { + Some(block_metadata) => BlockIdentifier::new(block_metadata.height, block_metadata.state_hash), + None => block_identifier.clone(), + }; + let (mut user_commands, internal_commands, zkapp_commands) = tokio::try_join!( + self.user_commands(&metadata), + self.internal_commands(&metadata), + self.zkapp_commands(&metadata) + )?; + user_commands.extend(internal_commands.into_iter()); + user_commands.extend(zkapp_commands.into_iter()); + Ok(BlockResponse { + block: Some(Box::new(Block::new( + block_identifier, + parent_block_identifier, + metadata.timestamp.parse()?, + user_commands, + ))), + other_transactions: None, + }) + } + + // TODO: use default token value, check how to best handle this + pub async fn user_commands(&self, metadata: &BlockMetadata) -> Result, MinaMeshError> { + let metadata = sqlx::query_file_as!(UserCommandMetadata, "sql/user_commands.sql", metadata.id, DEFAULT_TOKEN_ID) + .fetch_all(&self.pg_pool) + .await?; + let transactions = metadata + .into_iter() + .map(|item| { + Transaction::new(TransactionIdentifier::new(item.hash.clone()), user_command_metadata_to_operations(&item)) + }) + .collect(); + Ok(transactions) + } + + pub async fn internal_commands(&self, metadata: &BlockMetadata) -> Result, MinaMeshError> { + let metadata = + sqlx::query_file_as!(InternalCommandMetadata, "sql/internal_commands.sql", metadata.id, DEFAULT_TOKEN_ID) + .fetch_all(&self.pg_pool) + .await?; + let transactions = metadata + .into_iter() + .map(|item| { + internal_command_metadata_to_operation(&item) + .map(|operation| Transaction::new(TransactionIdentifier::new(item.hash.clone()), operation)) + }) + .collect::, MinaMeshError>>()?; + Ok(transactions) + } + + pub async fn zkapp_commands(&self, metadata: &BlockMetadata) -> Result, MinaMeshError> { + let metadata = sqlx::query_file_as!(ZkappCommandMetadata, "sql/zkapp_commands.sql", metadata.id, DEFAULT_TOKEN_ID) + .fetch_all(&self.pg_pool) + .await?; + let transactions = metadata + .into_iter() + .map(|item| { + zkapp_command_metadata_to_operation(&item) + .map(|operation| Transaction::new(TransactionIdentifier::new(item.hash.clone()), operation)) + }) + .collect::, MinaMeshError>>()?; + Ok(transactions) + } + + pub async fn block_metadata( + &self, + PartialBlockIdentifier { index, hash }: &PartialBlockIdentifier, + ) -> Result, sqlx::Error> { + if let (Some(index), Some(hash)) = (&index, &hash) { + sqlx::query_file_as!(BlockMetadata, "sql/query_both.sql", hash.to_string(), index) + .fetch_optional(&self.pg_pool) + .await + } else if let Some(index) = index { + let record = sqlx::query_file!("sql/max_canonical_height.sql").fetch_one(&self.pg_pool).await?; + if index <= &record.max_canonical_height.unwrap() { + sqlx::query_file_as!(BlockMetadata, "sql/query_canonical.sql", index).fetch_optional(&self.pg_pool).await + } else { + sqlx::query_file_as!(BlockMetadata, "sql/query_pending.sql", index).fetch_optional(&self.pg_pool).await + } + } else if let Some(hash) = &hash { + sqlx::query_file_as!(BlockMetadata, "sql/query_hash.sql", hash).fetch_optional(&self.pg_pool).await + } else { + sqlx::query_file_as!(BlockMetadata, "sql/query_best.sql").fetch_optional(&self.pg_pool).await + } + } } -#[derive(Debug, PartialEq, Eq, sqlx::FromRow)] +#[derive(Debug, PartialEq, Eq, FromRow, Serialize)] pub struct BlockMetadata { id: i32, block_winner_id: i32, @@ -42,60 +142,165 @@ pub struct BlockMetadata { winner: String, } -/// https://github.com/MinaProtocol/mina/blob/985eda49bdfabc046ef9001d3c406e688bc7ec45/src/app/rosetta/lib/block.ml#L7 -impl MinaMesh { - pub async fn block(&self, request: BlockRequest) -> Result { - let block_identifier = *request.block_identifier; - let metadata = match self.block_metadata(&block_identifier).await? { - Some(metadata) => metadata, - None => return Err(MinaMeshError::BlockMissing(Wrapper(&block_identifier).to_string())), - }; - let block_transactions = self - .graphql_client - .send(QueryBlockTransactions::build(QueryBlockTransactionsVariables { state_hash: Some(&metadata.state_hash) })) - .await - .map_err(|_| MinaMeshError::ChainInfoMissing)?; - println!("block_transactions: {:?}", block_transactions); - unimplemented!() +#[derive(Debug, PartialEq, Eq, FromRow, Serialize)] +pub struct UserCommandMetadata { + command_type: UserCommandType, + nonce: i64, + amount: Option, + fee: String, + valid_until: Option, + memo: String, + hash: String, + fee_payer: String, + source: String, + receiver: String, + status: TransactionStatus, + failure_reason: Option, + creation_fee: Option, +} - // Fetch transactions from DB - // Internal commands, user commands, and zkapps commands +#[derive(Debug, PartialEq, Eq, FromRow, Serialize)] +pub struct InternalCommandMetadata { + command_type: InternalCommandType, + receiver: String, + fee: String, + hash: String, + creation_fee: Option, + sequence_no: i32, + secondary_sequence_no: i32, + coinbase_receiver: Option, +} - // SQL command -> Rosetta/mesh transaction - // Each command will originate multiple atomic Rosetta/mesh operations +#[derive(Debug, PartialEq, Eq, FromRow, Serialize)] +pub struct ZkappCommandMetadata { + id: i64, + memo: Option, + hash: String, + fee_payer: String, + fee: String, + valid_until: Option, + nonce: i64, + sequence_no: i64, + status: TransactionStatus, + failure_reasons: Option>, +} - // Populate the block response from the fetched metadata, if any. +#[derive(Debug, PartialEq, Eq, FromRow, Serialize)] +pub struct ZkappAccountUpdateMetadata { + account_identifier_id: i32, + update_id: i32, + balance_change: String, + increment_nonce: bool, + events_id: i32, + actions_id: i32, + call_data_id: i32, + call_depth: i32, + zkapp_network_precondition_id: i32, + zkapp_account_precondition_id: i32, + zkapp_valid_while_precondition_id: Option, + use_full_commitment: bool, + implicit_account_creation_fee: bool, + may_use_token: String, + authorization_kind: String, + verification_key_hash_id: Option, + account: String, + token: String, +} - // Ok(BlockResponse { - // block: Some(Box::new(Block::new( - // BlockIdentifier::new(0, "".to_string()), - // BlockIdentifier::new(0, "".to_string()), - // 0, - // vec![], - // ))), - // other_transactions: Some(vec![]), - // }) +fn user_command_metadata_to_operations(metadata: &UserCommandMetadata) -> Vec { + let mut operations = Vec::new(); + if metadata.fee != "0" { + operations.push(operation(0, Some(&metadata.fee), &metadata.fee_payer, OperationType::FeePayment, None)); + } + if metadata.failure_reason.is_none() { + if let Some(creation_fee) = &metadata.creation_fee { + operations.push(operation( + 1, + Some(creation_fee), + &metadata.receiver, + OperationType::AccountCreationFeeViaPayment, + Some(&metadata.status), + )); + } + match metadata.command_type { + UserCommandType::Delegation => { + operations.push(operation(2, None, &metadata.source, OperationType::DelegateChange, Some(&metadata.status))); + } + UserCommandType::Payment => { + operations.extend_from_slice(&[ + operation( + 2, + metadata.amount.as_ref(), + &metadata.source, + OperationType::PaymentSourceDec, + Some(&metadata.status), + ), + operation( + 3, + metadata.amount.as_ref(), + &metadata.receiver, + OperationType::PaymentReceiverInc, + Some(&metadata.status), + ), + ]); + } + }; } + operations +} - pub async fn block_metadata( - &self, - PartialBlockIdentifier { index, hash }: &PartialBlockIdentifier, - ) -> Result, sqlx::Error> { - if let (Some(index), Some(hash)) = (&index, &hash) { - sqlx::query_file_as!(BlockMetadata, "sql/query_both.sql", hash.to_string(), index) - .fetch_optional(&self.pg_pool) - .await - } else if let Some(index) = index { - let record = sqlx::query_file!("sql/max_canonical_height.sql").fetch_one(&self.pg_pool).await?; - if index <= &record.max_canonical_height.unwrap() { - sqlx::query_file_as!(BlockMetadata, "sql/query_canonical.sql", index).fetch_optional(&self.pg_pool).await +fn internal_command_metadata_to_operation(metadata: &InternalCommandMetadata) -> Result, MinaMeshError> { + let mut operations = Vec::new(); + if let Some(creation_fee) = &metadata.creation_fee { + operations.push(operation( + 0, + Some(creation_fee), + &metadata.receiver, + OperationType::AccountCreationFeeViaFeeReceiver, + None, + )); + } + match metadata.command_type { + InternalCommandType::Coinbase => { + operations.push(operation(2, Some(&metadata.fee), &metadata.receiver, OperationType::CoinbaseInc, None)); + } + InternalCommandType::FeeTransfer => { + operations.push(operation(2, Some(&metadata.fee), &metadata.receiver, OperationType::FeeReceiverInc, None)); + } + InternalCommandType::FeeTransferViaCoinbase => { + if let Some(coinbase_receiver) = &metadata.coinbase_receiver { + operations.push(operation(2, Some(&metadata.fee), &metadata.receiver, OperationType::FeeReceiverInc, None)); + operations.push(operation(3, Some(&metadata.fee), coinbase_receiver, OperationType::FeePayerDec, None)); } else { - sqlx::query_file_as!(BlockMetadata, "sql/query_pending.sql", index).fetch_optional(&self.pg_pool).await + return Err(MinaMeshError::InvariantViolation); } - } else if let Some(hash) = &hash { - sqlx::query_file_as!(BlockMetadata, "sql/query_hash.sql", hash).fetch_optional(&self.pg_pool).await - } else { - sqlx::query_file_as!(BlockMetadata, "sql/query_best.sql").fetch_optional(&self.pg_pool).await } } + Ok(operations) +} + +// TODO: implement +fn zkapp_command_metadata_to_operation(_metadata: &ZkappCommandMetadata) -> Result, MinaMeshError> { + Ok(Vec::new()) +} + +fn operation( + ident: i64, + amount: Option<&String>, + account: &String, + operation_type: OperationType, + status: Option<&TransactionStatus>, +) -> Operation { + Operation { + operation_identifier: Box::new(OperationIdentifier::new(ident)), + amount: amount.map(|value| Box::new(Amount::new(value.to_owned(), Currency::new("mina".to_string(), 9)))), + account: Some(Box::new(AccountIdentifier::new(account.to_owned()))), + status: Some( + status.map(|item| OperationStatus::from(item.to_owned())).unwrap_or(OperationStatus::Success).to_string(), + ), + related_operations: None, + coin_change: None, + r#type: operation_type.to_string().to_case(Case::Snake), + metadata: None, // TODO: get the correct metadata + } } diff --git a/src/api/call.rs b/src/api/call.rs index 86ff839..52fed7d 100644 --- a/src/api/call.rs +++ b/src/api/call.rs @@ -1,5 +1,5 @@ use anyhow::Result; -pub use mesh::models::{CallRequest, CallResponse}; +use mesh::models::{CallRequest, CallResponse}; use crate::MinaMesh; diff --git a/src/api/construction_combine.rs b/src/api/construction_combine.rs index ca141dd..318e95c 100644 --- a/src/api/construction_combine.rs +++ b/src/api/construction_combine.rs @@ -1,5 +1,5 @@ use anyhow::Result; -pub use mesh::models::{ConstructionCombineRequest, ConstructionCombineResponse}; +use mesh::models::{ConstructionCombineRequest, ConstructionCombineResponse}; use crate::MinaMesh; diff --git a/src/api/construction_derive.rs b/src/api/construction_derive.rs index d64bb2a..c92ebf5 100644 --- a/src/api/construction_derive.rs +++ b/src/api/construction_derive.rs @@ -1,5 +1,5 @@ use anyhow::Result; -pub use mesh::models::{ConstructionDeriveRequest, ConstructionDeriveResponse}; +use mesh::models::{ConstructionDeriveRequest, ConstructionDeriveResponse}; use crate::MinaMesh; diff --git a/src/api/construction_hash.rs b/src/api/construction_hash.rs index 243a404..d1f4438 100644 --- a/src/api/construction_hash.rs +++ b/src/api/construction_hash.rs @@ -1,5 +1,5 @@ use anyhow::Result; -pub use mesh::models::{ConstructionHashRequest, TransactionIdentifier}; +use mesh::models::{ConstructionHashRequest, TransactionIdentifier}; use crate::MinaMesh; diff --git a/src/api/construction_metadata.rs b/src/api/construction_metadata.rs index 0d260eb..a6e07c0 100644 --- a/src/api/construction_metadata.rs +++ b/src/api/construction_metadata.rs @@ -1,5 +1,5 @@ use anyhow::Result; -pub use mesh::models::{ConstructionMetadataRequest, ConstructionMetadataResponse}; +use mesh::models::{ConstructionMetadataRequest, ConstructionMetadataResponse}; use crate::MinaMesh; diff --git a/src/api/construction_parse.rs b/src/api/construction_parse.rs index 9045031..30e59f3 100644 --- a/src/api/construction_parse.rs +++ b/src/api/construction_parse.rs @@ -1,5 +1,5 @@ use anyhow::Result; -pub use mesh::models::{ConstructionParseRequest, ConstructionParseResponse}; +use mesh::models::{ConstructionParseRequest, ConstructionParseResponse}; use crate::MinaMesh; diff --git a/src/api/construction_payloads.rs b/src/api/construction_payloads.rs index a2ac7ff..ffba914 100644 --- a/src/api/construction_payloads.rs +++ b/src/api/construction_payloads.rs @@ -1,5 +1,5 @@ use anyhow::Result; -pub use mesh::models::{ConstructionPayloadsRequest, ConstructionPayloadsResponse}; +use mesh::models::{ConstructionPayloadsRequest, ConstructionPayloadsResponse}; use crate::MinaMesh; diff --git a/src/api/construction_preprocess.rs b/src/api/construction_preprocess.rs index 35ca076..0f3e443 100644 --- a/src/api/construction_preprocess.rs +++ b/src/api/construction_preprocess.rs @@ -1,5 +1,5 @@ use anyhow::Result; -pub use mesh::models::{ConstructionPreprocessRequest, ConstructionPreprocessResponse}; +use mesh::models::{ConstructionPreprocessRequest, ConstructionPreprocessResponse}; use crate::MinaMesh; diff --git a/src/api/construction_submit.rs b/src/api/construction_submit.rs index 2d96107..e700599 100644 --- a/src/api/construction_submit.rs +++ b/src/api/construction_submit.rs @@ -1,5 +1,5 @@ use anyhow::Result; -pub use mesh::models::{ConstructionSubmitRequest, TransactionIdentifier}; +use mesh::models::{ConstructionSubmitRequest, TransactionIdentifier}; use crate::MinaMesh; diff --git a/src/api/mempool.rs b/src/api/mempool.rs index 6b4570e..519d413 100644 --- a/src/api/mempool.rs +++ b/src/api/mempool.rs @@ -4,7 +4,7 @@ use anyhow::Result; use cynic::QueryBuilder; -pub use mesh::models::{MempoolResponse, TransactionIdentifier}; +use mesh::models::{MempoolResponse, TransactionIdentifier}; use crate::{graphql::QueryMempool, MinaMesh}; diff --git a/src/api/mempool_transaction.rs b/src/api/mempool_transaction.rs index 2f0cbab..f9f4de0 100644 --- a/src/api/mempool_transaction.rs +++ b/src/api/mempool_transaction.rs @@ -1,5 +1,5 @@ use cynic::QueryBuilder; -pub use mesh::models::{MempoolTransactionRequest, MempoolTransactionResponse, Transaction, TransactionIdentifier}; +use mesh::models::{MempoolTransactionRequest, MempoolTransactionResponse, Transaction, TransactionIdentifier}; use crate::{ graphql::{QueryMempoolTransactions, QueryMempoolTransactionsVariables}, diff --git a/src/api/network_list.rs b/src/api/network_list.rs index 6ef4656..1c0f8f1 100644 --- a/src/api/network_list.rs +++ b/src/api/network_list.rs @@ -1,6 +1,6 @@ use anyhow::Result; use cynic::QueryBuilder; -pub use mesh::models::{NetworkIdentifier, NetworkListResponse}; +use mesh::models::{NetworkIdentifier, NetworkListResponse}; use crate::{graphql::QueryNetworkId, MinaMesh}; @@ -8,15 +8,10 @@ use crate::{graphql::QueryNetworkId, MinaMesh}; impl MinaMesh { pub async fn network_list(&self) -> Result { let QueryNetworkId { network_id } = self.graphql_client.send(QueryNetworkId::build(())).await?; - - // Split the network_id into chain_id and network_id by the colon ':' - let parts: Vec<&str> = network_id.split(':').collect(); - - let (chain_id, network_id) = match parts.as_slice() { - [chain, network] => (chain.to_string(), network.to_string()), - _ => ("unknown".to_string(), "unknown".to_string()), - }; - + let (chain_id, network_id) = network_id.split_once(':').map_or_else( + || ("unknown".to_string(), "unknown".to_string()), + |(chain, network)| (chain.to_string(), network.to_string()), + ); Ok(NetworkListResponse::new(vec![NetworkIdentifier::new(chain_id, network_id)])) } } diff --git a/src/api/network_options.rs b/src/api/network_options.rs index a6216c8..18e2a6a 100644 --- a/src/api/network_options.rs +++ b/src/api/network_options.rs @@ -1,7 +1,7 @@ // TODO: double-check the data is correct // TODO: why do long string literals in the error metadata break rustfmt? -pub use mesh::models::{Allow, Case, Error, NetworkOptionsResponse, OperationStatus, Version}; +use mesh::models::{Allow, Case, Error, NetworkOptionsResponse, OperationStatus, Version}; use crate::{MinaMesh, MinaMeshError}; diff --git a/src/api/network_status.rs b/src/api/network_status.rs index 4011353..29bddc6 100644 --- a/src/api/network_status.rs +++ b/src/api/network_status.rs @@ -1,7 +1,7 @@ // TODO: get genesis block identifier from env use cynic::QueryBuilder; -pub use mesh::models::{BlockIdentifier, NetworkStatusResponse, Peer}; +use mesh::models::{BlockIdentifier, NetworkStatusResponse, Peer}; use crate::{ graphql::{Block3, DaemonStatus3, QueryNetworkStatus}, diff --git a/src/commands/serve.rs b/src/commands/serve.rs index e858273..c8a5285 100644 --- a/src/commands/serve.rs +++ b/src/commands/serve.rs @@ -64,7 +64,7 @@ impl ServeCommand { macro_rules! create_handler { ($name:ident, $request_type:ty) => { paste! { - async fn [](mina_mesh: State>, Json(req): Json) -> impl IntoResponse { + async fn [](mina_mesh: State>, Json(req): Json) -> impl IntoResponse { Wrapper(mina_mesh.$name(req).await) } } diff --git a/src/error.rs b/src/error.rs index 2da2857..ffd6047 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,10 +1,11 @@ use std::num::ParseIntError; use cynic::http::CynicReqwestError; +use serde_json::Error as SerdeError; use sqlx::Error as SqlxError; use thiserror::Error; -#[derive(Error, Debug)] +#[derive(Error, Debug, PartialEq)] pub enum MinaMeshError { #[error("SQL failure")] Sql(String), @@ -85,7 +86,7 @@ pub enum MinaMeshError { TransactionSubmitExpired, } -#[derive(Debug)] +#[derive(Debug, PartialEq)] pub enum PartialReason { LengthMismatch, FeePayerAndSourceMismatch, @@ -137,3 +138,11 @@ impl From for MinaMeshError { MinaMeshError::GraphqlMinaQuery(value.to_string()) } } + +// TODO: this isn't necessarily accurate, as we use this for a serialization +// errors as well. +impl From for MinaMeshError { + fn from(value: SerdeError) -> Self { + MinaMeshError::JsonParse(Some(value.to_string())) + } +} diff --git a/src/lib.rs b/src/lib.rs index 772f460..f1e9fc1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,22 +1,24 @@ -pub mod api; +mod api; mod commands; mod config; mod error; mod graphql; mod playground; +mod types; mod util; -pub use api::*; pub use commands::*; pub use config::*; pub use error::*; -pub use mesh::models::{AccountIdentifier, BlockIdentifier, NetworkIdentifier}; +use graphql::GraphQLClient; +pub use mesh::models; +use mesh::models::BlockIdentifier; use sqlx::PgPool; -pub use util::Wrapper; +pub use types::*; #[derive(Debug)] pub struct MinaMesh { - pub graphql_client: graphql::GraphQLClient, + pub graphql_client: GraphQLClient, pub pg_pool: PgPool, pub genesis_block_identifier: BlockIdentifier, } diff --git a/src/types.rs b/src/types.rs new file mode 100644 index 0000000..264df6b --- /dev/null +++ b/src/types.rs @@ -0,0 +1,66 @@ +use derive_more::derive::Display; +use serde::Serialize; +use sqlx::Type; + +#[derive(Type, Debug, PartialEq, Eq, Serialize)] +#[sqlx(type_name = "chain_status_type", rename_all = "lowercase")] +pub enum ChainStatus { + Canonical, + Pending, + Orphaned, +} + +#[derive(Type, Debug, PartialEq, Eq, Serialize)] +#[sqlx(type_name = "command_type", rename_all = "lowercase")] +pub enum UserCommandType { + Payment, + Delegation, +} + +#[derive(Type, Debug, PartialEq, Eq, Serialize)] +#[sqlx(type_name = "internal_command_type", rename_all = "snake_case")] +pub enum InternalCommandType { + FeeTransferViaCoinbase, + FeeTransfer, + Coinbase, +} + +#[derive(Type, Debug, PartialEq, Eq, Serialize, Display, Clone)] +#[sqlx(type_name = "transaction_status", rename_all = "lowercase")] +pub enum TransactionStatus { + Applied, + Failed, +} + +#[derive(Debug, Display)] +pub enum OperationStatus { + Success, + Failed, +} + +impl From for OperationStatus { + fn from(status: TransactionStatus) -> Self { + match status { + TransactionStatus::Applied => OperationStatus::Success, + TransactionStatus::Failed => OperationStatus::Failed, + } + } +} + +#[derive(Debug, Display)] +pub enum OperationType { + FeePayerDec, + FeeReceiverInc, + CoinbaseInc, + AccountCreationFeeViaPayment, + AccountCreationFeeViaFeePayer, + AccountCreationFeeViaFeeReceiver, + PaymentSourceDec, + PaymentReceiverInc, + FeePayment, + DelegateChange, + CreateToken, + MintTokens, + ZkappFeePayerDec, + ZkappBalanceUpdate, +} diff --git a/src/util.rs b/src/util.rs index 3b001cd..d5a949d 100644 --- a/src/util.rs +++ b/src/util.rs @@ -4,7 +4,6 @@ use axum::{ http::StatusCode, response::{IntoResponse, Response}, }; -use mesh::models::PartialBlockIdentifier; use serde::Serialize; use crate::MinaMeshError; @@ -21,8 +20,8 @@ impl IntoResponse for Wrapper> { } impl Wrapper> { - pub fn to_token_id(self) -> Result { - match self.0 { + pub fn to_token_id(&self) -> Result { + match &self.0 { None => Ok(DEFAULT_TOKEN_ID.to_string()), Some(serde_json::Value::Object(map)) => { Ok(map.get("token_id").map(|v| v.to_string()).ok_or(MinaMeshError::JsonParse(None))?) @@ -33,20 +32,7 @@ impl Wrapper> { } // cspell:disable-next-line -const DEFAULT_TOKEN_ID: &str = "wSHV2S4qX9jFsLjQo8r1BsMLH2ZRKsZx6EJd1sbozGPieEC4Jf"; - -#[allow(clippy::to_string_trait_impl)] -impl ToString for Wrapper<&PartialBlockIdentifier> { - fn to_string(&self) -> String { - match &self.0.hash { - Some(hash) => hash.to_owned(), - None => match self.0.index { - Some(index) => index.to_string(), - None => "latest".to_string(), - }, - } - } -} +pub const DEFAULT_TOKEN_ID: &str = "wSHV2S4qX9jFsLjQo8r1BsMLH2ZRKsZx6EJd1sbozGPieEC4Jf"; pub fn default_mina_proxy_url() -> String { "https://mainnet.minaprotocol.network/graphql".to_string() diff --git a/tests/account_balance.rs b/tests/account_balance.rs index f475c23..3dec2d4 100644 --- a/tests/account_balance.rs +++ b/tests/account_balance.rs @@ -2,8 +2,10 @@ use anyhow::Result; use futures::future::try_join_all; use insta::assert_debug_snapshot; use mina_mesh::{ - AccountBalanceRequest, AccountBalanceResponse, AccountIdentifier, MinaMeshConfig, NetworkIdentifier, - PartialBlockIdentifier, + models::{ + AccountBalanceRequest, AccountBalanceResponse, AccountIdentifier, NetworkIdentifier, PartialBlockIdentifier, + }, + MinaMeshConfig, }; #[tokio::test] diff --git a/tests/block.rs b/tests/block.rs index 2d309e4..552d3a6 100644 --- a/tests/block.rs +++ b/tests/block.rs @@ -2,20 +2,27 @@ use std::sync::OnceLock; use anyhow::Result; use futures::{stream::FuturesUnordered, StreamExt}; -use mina_mesh::{BlockMetadata, MinaMeshConfig, PartialBlockIdentifier}; +use insta::assert_debug_snapshot; +use mina_mesh::{ + models::{BlockRequest, BlockResponse, NetworkIdentifier, PartialBlockIdentifier}, + MinaMeshConfig, MinaMeshError, +}; #[tokio::test] async fn specified() -> Result<()> { let mina_mesh = MinaMeshConfig::from_env().to_mina_mesh().await?; - let mut metadata_futures = - specified_identifiers().iter().map(|item| mina_mesh.block_metadata(item)).collect::>(); - let mut maybe_prev: Option> = None; - while let Some(Ok(resolved)) = metadata_futures.next().await { + let mut futures = specified_identifiers() + .iter() + .map(|item| mina_mesh.block(BlockRequest::new(network_identifier().to_owned(), item.to_owned()))) + .collect::>(); + let mut maybe_prev: Option> = None; + while let Some(resolved) = futures.next().await { if let Some(prev) = maybe_prev { assert_eq!(prev, resolved); } maybe_prev = Some(resolved); } + assert_debug_snapshot!(maybe_prev); Ok(()) } @@ -36,12 +43,17 @@ fn specified_identifiers() -> &'static [PartialBlockIdentifier; 3] { }) } +fn network_identifier() -> &'static NetworkIdentifier { + static NETWORK_IDENTIFIER: OnceLock = OnceLock::new(); + NETWORK_IDENTIFIER.get_or_init(|| NetworkIdentifier::new("mina".to_string(), "mainnet".to_string())) +} + #[tokio::test] async fn unspecified() -> Result<()> { let response = MinaMeshConfig::from_env() .to_mina_mesh() .await? - .block_metadata(&PartialBlockIdentifier { hash: None, index: None }) + .block(BlockRequest::new(network_identifier().to_owned(), PartialBlockIdentifier::new())) .await; assert!(response.is_ok()); Ok(()) diff --git a/tests/snapshots/block__specified.snap b/tests/snapshots/block__specified.snap new file mode 100644 index 0000000..49c1aad --- /dev/null +++ b/tests/snapshots/block__specified.snap @@ -0,0 +1,2697 @@ +--- +source: tests/block.rs +expression: maybe_prev +--- +Some( + Ok( + BlockResponse { + block: Some( + Block { + block_identifier: BlockIdentifier { + index: 375991, + hash: "3NKAyx2FuWx3jqtkpigndDRoyydQSUozPYix3hw3FWhZc8iUWwTP", + }, + parent_block_identifier: BlockIdentifier { + index: 375990, + hash: "3NK52dBHg4HELVhqMGuLonyCiHreiD6BXxAZSBmzjNnbNMrdvh5v", + }, + timestamp: 1722725820000, + transactions: [ + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5JuF58kLXaW9cMRAM5AviaRVUNK3aArLN6jxxbY9JyVz7RcnjgZv", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 0, + network_index: None, + }, + related_operations: None, + type: "fee_payment", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qntsJ1p1ECs3jLoBByBHkt74G8VM4Q5Uv82e1xa2NtUBbwdUpJR9", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "250000000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "payment_source_dec", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qntsJ1p1ECs3jLoBByBHkt74G8VM4Q5Uv82e1xa2NtUBbwdUpJR9", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "13149444000000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 3, + network_index: None, + }, + related_operations: None, + type: "payment_receiver_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qrDtZh2prv8NEUgmW376K6U2u7rtpWGar2MaQzroEcL9i69xLfbw", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "13149444000000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5Jtmx39tAzhx4Z6zxFrxGJzEP8U3gkPSukmT3LX9yjCsmN6N4LwU", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 0, + network_index: None, + }, + related_operations: None, + type: "fee_payment", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qpLST3UC1rpVT6SHfB7wqW2iQgiopFAGfrcovPgLjgfpDUN2LLeg", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "95401000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "payment_source_dec", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qpLST3UC1rpVT6SHfB7wqW2iQgiopFAGfrcovPgLjgfpDUN2LLeg", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "85000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 3, + network_index: None, + }, + related_operations: None, + type: "payment_receiver_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qnasrSvfAjsuHNpRgcyYw9coPDyQnUT16UDWqGFuQ5BTst7LFrD7", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "85000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5Ju3dZ9iom6YrQsi1DPC6NzM5gpLe5NC8xURW2LbSnzfsYFXu4KH", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 0, + network_index: None, + }, + related_operations: None, + type: "fee_payment", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qpLST3UC1rpVT6SHfB7wqW2iQgiopFAGfrcovPgLjgfpDUN2LLeg", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "95401000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "payment_source_dec", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qpLST3UC1rpVT6SHfB7wqW2iQgiopFAGfrcovPgLjgfpDUN2LLeg", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "85000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 3, + network_index: None, + }, + related_operations: None, + type: "payment_receiver_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qnasrSvfAjsuHNpRgcyYw9coPDyQnUT16UDWqGFuQ5BTst7LFrD7", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "85000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5Jv7rq6pcts8TQm5R2SziD85aLWwFkRb7S1K3VypQeb42ixvRexH", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 0, + network_index: None, + }, + related_operations: None, + type: "fee_payment", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qoXQhp63oNsLSN9Dy7wcF3PzLmdBnnin2rTnNWLbpgF7diABciU6", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "95401000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "payment_source_dec", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qoXQhp63oNsLSN9Dy7wcF3PzLmdBnnin2rTnNWLbpgF7diABciU6", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "85000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 3, + network_index: None, + }, + related_operations: None, + type: "payment_receiver_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qr6VeKCpYdqg7wZyside9EgzDxGMAPbfnMajPm4gH6TE7zf3Z3Xk", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "85000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5JtwYGkYEawWg9Ww1tVKpUz3EY4SZVBsKZtAqvX6Cf2VmkhkrUF3", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 0, + network_index: None, + }, + related_operations: None, + type: "fee_payment", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qoXQhp63oNsLSN9Dy7wcF3PzLmdBnnin2rTnNWLbpgF7diABciU6", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "95401000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "payment_source_dec", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qoXQhp63oNsLSN9Dy7wcF3PzLmdBnnin2rTnNWLbpgF7diABciU6", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "85000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 3, + network_index: None, + }, + related_operations: None, + type: "payment_receiver_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qr6VeKCpYdqg7wZyside9EgzDxGMAPbfnMajPm4gH6TE7zf3Z3Xk", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "85000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5JuUdWNuk4Qr8LkunKouFJUNrmRznJVNam2ENez1GZP1q5bCCwgG", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 0, + network_index: None, + }, + related_operations: None, + type: "fee_payment", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qrAWZFqvgJbfU95t1owLAMKtsDTAGgSZzsBJYUzeQZ7dQNMmG5vw", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "21001011", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "payment_source_dec", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qrAWZFqvgJbfU95t1owLAMKtsDTAGgSZzsBJYUzeQZ7dQNMmG5vw", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "0", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 3, + network_index: None, + }, + related_operations: None, + type: "payment_receiver_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qnFCUtCu4bHJZGroNZvmq8ya1E9kAJkQGYnETh9E3CMHV98UvrPZ", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "0", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5JuywuAvK9adJvfGwD8sXEPFBgjHvfrpwxzCQbVXbB1wijv1AmHq", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 0, + network_index: None, + }, + related_operations: None, + type: "fee_payment", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qrAWZFqvgJbfU95t1owLAMKtsDTAGgSZzsBJYUzeQZ7dQNMmG5vw", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "21000005", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "payment_source_dec", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qrAWZFqvgJbfU95t1owLAMKtsDTAGgSZzsBJYUzeQZ7dQNMmG5vw", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "0", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 3, + network_index: None, + }, + related_operations: None, + type: "payment_receiver_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qnFCUtCu4bHJZGroNZvmq8ya1E9kAJkQGYnETh9E3CMHV98UvrPZ", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "0", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5Ju6aGg5PRHzw2fwg2QaYfnFmX5WeaBQscrcC7ZCdWPLWDNxBxYL", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 0, + network_index: None, + }, + related_operations: None, + type: "fee_payment", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qrAWZFqvgJbfU95t1owLAMKtsDTAGgSZzsBJYUzeQZ7dQNMmG5vw", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "21001000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "payment_source_dec", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qrAWZFqvgJbfU95t1owLAMKtsDTAGgSZzsBJYUzeQZ7dQNMmG5vw", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "55000000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 3, + network_index: None, + }, + related_operations: None, + type: "payment_receiver_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qnFCUtCu4bHJZGroNZvmq8ya1E9kAJkQGYnETh9E3CMHV98UvrPZ", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "55000000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5Jtah6bTfk16HwFanYS9JUVHSrfq4LSct62b6vnuStvESsRmVTa5", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 0, + network_index: None, + }, + related_operations: None, + type: "fee_payment", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qrAWZFqvgJbfU95t1owLAMKtsDTAGgSZzsBJYUzeQZ7dQNMmG5vw", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "21001000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "payment_source_dec", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qrAWZFqvgJbfU95t1owLAMKtsDTAGgSZzsBJYUzeQZ7dQNMmG5vw", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "55000000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 3, + network_index: None, + }, + related_operations: None, + type: "payment_receiver_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qnFCUtCu4bHJZGroNZvmq8ya1E9kAJkQGYnETh9E3CMHV98UvrPZ", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "55000000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5Jtg1T9mzmfkwGoH97MD5uma5KDLnJg2MAay1AnKU1vsb1xSq34e", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 0, + network_index: None, + }, + related_operations: None, + type: "fee_payment", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qp69bsgUNySCY2wEYDCrRN3gdMB6cDSZGBucTzc9vUUH4jUoDSED", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "17400000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "payment_source_dec", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qp69bsgUNySCY2wEYDCrRN3gdMB6cDSZGBucTzc9vUUH4jUoDSED", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "74000000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 3, + network_index: None, + }, + related_operations: None, + type: "payment_receiver_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qq6PqndihT5uoGAXzndoNgYSUMvUPmVqMQATusaoS1ZmCZRcM1ku", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "74000000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5Ju3Z8WGZTxGbufgvBVVGmUcMdRJmNJZKVnMApGgsDZa4X1Szvvu", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 0, + network_index: None, + }, + related_operations: None, + type: "fee_payment", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qp69bsgUNySCY2wEYDCrRN3gdMB6cDSZGBucTzc9vUUH4jUoDSED", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "17400000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "payment_source_dec", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qp69bsgUNySCY2wEYDCrRN3gdMB6cDSZGBucTzc9vUUH4jUoDSED", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "74000000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 3, + network_index: None, + }, + related_operations: None, + type: "payment_receiver_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qq6PqndihT5uoGAXzndoNgYSUMvUPmVqMQATusaoS1ZmCZRcM1ku", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "74000000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5JvCfZH23MXjrqGVH7EXc5S3ee4MwqTgRaX5akap4JNmp7ep7vek", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 0, + network_index: None, + }, + related_operations: None, + type: "fee_payment", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qp69bsgUNySCY2wEYDCrRN3gdMB6cDSZGBucTzc9vUUH4jUoDSED", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "17400000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "payment_source_dec", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qp69bsgUNySCY2wEYDCrRN3gdMB6cDSZGBucTzc9vUUH4jUoDSED", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "74000000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 3, + network_index: None, + }, + related_operations: None, + type: "payment_receiver_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qq6PqndihT5uoGAXzndoNgYSUMvUPmVqMQATusaoS1ZmCZRcM1ku", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "74000000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5JtWK6Jv3y2iQDq1ikrUNfWf8Nc5PyJQxCtQuiKfE1ABRFwUDLmr", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 0, + network_index: None, + }, + related_operations: None, + type: "fee_payment", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qp69bsgUNySCY2wEYDCrRN3gdMB6cDSZGBucTzc9vUUH4jUoDSED", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "17400000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "payment_source_dec", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qp69bsgUNySCY2wEYDCrRN3gdMB6cDSZGBucTzc9vUUH4jUoDSED", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "74000000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 3, + network_index: None, + }, + related_operations: None, + type: "payment_receiver_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qq6PqndihT5uoGAXzndoNgYSUMvUPmVqMQATusaoS1ZmCZRcM1ku", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "74000000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5JvLtChRftJ1g5ibN3YtLdvU5bK9h9bveoyURM7inEfw4ajwxsbf", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 0, + network_index: None, + }, + related_operations: None, + type: "fee_payment", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qp69bsgUNySCY2wEYDCrRN3gdMB6cDSZGBucTzc9vUUH4jUoDSED", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "17400000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "payment_source_dec", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qp69bsgUNySCY2wEYDCrRN3gdMB6cDSZGBucTzc9vUUH4jUoDSED", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "74000000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 3, + network_index: None, + }, + related_operations: None, + type: "payment_receiver_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qq6PqndihT5uoGAXzndoNgYSUMvUPmVqMQATusaoS1ZmCZRcM1ku", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "74000000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5JuUKT4goESyU49J8JAHvQ58iLvzuoUj4tAMKFZoGxPCxEBXwFGn", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 0, + network_index: None, + }, + related_operations: None, + type: "fee_payment", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qp69bsgUNySCY2wEYDCrRN3gdMB6cDSZGBucTzc9vUUH4jUoDSED", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "17400000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "payment_source_dec", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qp69bsgUNySCY2wEYDCrRN3gdMB6cDSZGBucTzc9vUUH4jUoDSED", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "74000000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 3, + network_index: None, + }, + related_operations: None, + type: "payment_receiver_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qq6PqndihT5uoGAXzndoNgYSUMvUPmVqMQATusaoS1ZmCZRcM1ku", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "74000000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5Jv8hdmz44CssU1LVD4a99S8C28oNkDX4MiXYCrVa3JEHdMQ1iCZ", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 0, + network_index: None, + }, + related_operations: None, + type: "fee_payment", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qp69bsgUNySCY2wEYDCrRN3gdMB6cDSZGBucTzc9vUUH4jUoDSED", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "17400000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "payment_source_dec", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qp69bsgUNySCY2wEYDCrRN3gdMB6cDSZGBucTzc9vUUH4jUoDSED", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "74000000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 3, + network_index: None, + }, + related_operations: None, + type: "payment_receiver_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qq6PqndihT5uoGAXzndoNgYSUMvUPmVqMQATusaoS1ZmCZRcM1ku", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "74000000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5JttmDyScSo77BQvd1yckUyrzr9mkqwhqJV8E6bndHFzg6wJovaZ", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 0, + network_index: None, + }, + related_operations: None, + type: "fee_payment", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qp69bsgUNySCY2wEYDCrRN3gdMB6cDSZGBucTzc9vUUH4jUoDSED", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "17400000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "payment_source_dec", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qp69bsgUNySCY2wEYDCrRN3gdMB6cDSZGBucTzc9vUUH4jUoDSED", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "74000000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 3, + network_index: None, + }, + related_operations: None, + type: "payment_receiver_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qq6PqndihT5uoGAXzndoNgYSUMvUPmVqMQATusaoS1ZmCZRcM1ku", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "74000000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5JuHeXyGFSr87GdMEUobZWCHJC6KsSvgnFjX52Yr7Zh5CjVXwgwW", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 0, + network_index: None, + }, + related_operations: None, + type: "fee_payment", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qp69bsgUNySCY2wEYDCrRN3gdMB6cDSZGBucTzc9vUUH4jUoDSED", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "17400000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "payment_source_dec", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qp69bsgUNySCY2wEYDCrRN3gdMB6cDSZGBucTzc9vUUH4jUoDSED", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "74000000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 3, + network_index: None, + }, + related_operations: None, + type: "payment_receiver_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qq6PqndihT5uoGAXzndoNgYSUMvUPmVqMQATusaoS1ZmCZRcM1ku", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "74000000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5Jv9o4iyshYFWJYjWxykYDgdhTp9f3QmmqeDgmiYj7q73P69cM5h", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 0, + network_index: None, + }, + related_operations: None, + type: "fee_payment", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qnEeb4KAp9WxdMxddHVtJ8gwfyJURG5BZZ6e4LsRjQKHNWqmgSWt", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "15859000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "payment_source_dec", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qnEeb4KAp9WxdMxddHVtJ8gwfyJURG5BZZ6e4LsRjQKHNWqmgSWt", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "73060000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 3, + network_index: None, + }, + related_operations: None, + type: "payment_receiver_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qoVxygiYzqRCj4taZDbRJGY6xLvuzoiLdY5CpGm7L9Tz5cj2Qr6i", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "73060000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5Jv13YKkkF8cnBtDjnZPveZt1srjca9Jpm9P8iPKmAkScUZez1DE", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 0, + network_index: None, + }, + related_operations: None, + type: "fee_payment", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qnEeb4KAp9WxdMxddHVtJ8gwfyJURG5BZZ6e4LsRjQKHNWqmgSWt", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "15683000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "payment_source_dec", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qnEeb4KAp9WxdMxddHVtJ8gwfyJURG5BZZ6e4LsRjQKHNWqmgSWt", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "76420000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 3, + network_index: None, + }, + related_operations: None, + type: "payment_receiver_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qoVxygiYzqRCj4taZDbRJGY6xLvuzoiLdY5CpGm7L9Tz5cj2Qr6i", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "76420000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5Jv4wH5ADecmogG4s7pn8ud8gt1dfwpGyQHjNUjcj7xYBV2Y5CXr", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 0, + network_index: None, + }, + related_operations: None, + type: "fee_payment", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qnXy1f75qq8c6HS2Am88Gk6UyvTHK3iSYh4Hb3nD6DS2eS6wZ4or", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "8710000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "payment_source_dec", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qnXy1f75qq8c6HS2Am88Gk6UyvTHK3iSYh4Hb3nD6DS2eS6wZ4or", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "84990000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 3, + network_index: None, + }, + related_operations: None, + type: "payment_receiver_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qqJ1AqK3YQmEEALdJeMw49438Sh6zuQ5cNWUYfCgRsPkduFE2uLU", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "84990000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5Juj2n1NowUcbmz462sPP3aoDus84HkY8KF7hq28qdx1TZxfMMeF", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 0, + network_index: None, + }, + related_operations: None, + type: "fee_payment", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qnXy1f75qq8c6HS2Am88Gk6UyvTHK3iSYh4Hb3nD6DS2eS6wZ4or", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "5000000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "payment_source_dec", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qnXy1f75qq8c6HS2Am88Gk6UyvTHK3iSYh4Hb3nD6DS2eS6wZ4or", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "90486111", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 3, + network_index: None, + }, + related_operations: None, + type: "payment_receiver_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qqJ1AqK3YQmEEALdJeMw49438Sh6zuQ5cNWUYfCgRsPkduFE2uLU", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "90486111", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5JtiX3kseB6qebRCiyeigmuiTxNhQfWEQBTwdBPCFueFiY9SjV5g", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 0, + network_index: None, + }, + related_operations: None, + type: "fee_payment", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qov9yv8TayLteD6SDXvxyYtmn3KkUoozAbs47fVo9JZSpcynbzTz", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "1401000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "payment_source_dec", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qov9yv8TayLteD6SDXvxyYtmn3KkUoozAbs47fVo9JZSpcynbzTz", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "89999000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 3, + network_index: None, + }, + related_operations: None, + type: "payment_receiver_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qpV4EsWwwaoQo9PaVVxk7RNPopWDEd3u4hZZgd83gXCPcuoDBrEz", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "89999000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5JtpvYebhneMcZ9iTaozUKViELaXNSP5vwAj34Np8ZFEs9HTggp8", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 0, + network_index: None, + }, + related_operations: None, + type: "fee_payment", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qov9yv8TayLteD6SDXvxyYtmn3KkUoozAbs47fVo9JZSpcynbzTz", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "24001000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "payment_source_dec", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qov9yv8TayLteD6SDXvxyYtmn3KkUoozAbs47fVo9JZSpcynbzTz", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "44999000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 3, + network_index: None, + }, + related_operations: None, + type: "payment_receiver_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qpV4EsWwwaoQo9PaVVxk7RNPopWDEd3u4hZZgd83gXCPcuoDBrEz", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "44999000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5JtoEyG9HC1viU8ASjgphG85JC5g7Ycbk5KR61fBT37fT4WHcT1p", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 0, + network_index: None, + }, + related_operations: None, + type: "fee_payment", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qov9yv8TayLteD6SDXvxyYtmn3KkUoozAbs47fVo9JZSpcynbzTz", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "4801000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "payment_source_dec", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qov9yv8TayLteD6SDXvxyYtmn3KkUoozAbs47fVo9JZSpcynbzTz", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "50399000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + Operation { + operation_identifier: OperationIdentifier { + index: 3, + network_index: None, + }, + related_operations: None, + type: "payment_receiver_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qpV4EsWwwaoQo9PaVVxk7RNPopWDEd3u4hZZgd83gXCPcuoDBrEz", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "50399000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5JtyT69gceMuEzmyjbEMZ6E9oTiQwaDjoVyZRM7Ggfm8mbtdGceK", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "fee_receiver_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qktPtDFWG8ciSsd6eEPr7S7HuiGaouqDhfPT7H84DPp9mCgTHjwE", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "232055000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5Ju2teejDK5Q2ea1P21dPTdnnqt5c8QmSL1Tpf8PVr2SmLQzA3KY", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "coinbase_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qktPtDFWG8ciSsd6eEPr7S7HuiGaouqDhfPT7H84DPp9mCgTHjwE", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "720000000000", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + Transaction { + transaction_identifier: TransactionIdentifier { + hash: "5JuMZ2QrMWkpQuCFEw9iPVS8zXQkmR1g3LHg4a33xdmUCHEJRQho", + }, + operations: [ + Operation { + operation_identifier: OperationIdentifier { + index: 2, + network_index: None, + }, + related_operations: None, + type: "fee_receiver_inc", + status: Some( + "Success", + ), + account: Some( + AccountIdentifier { + address: "B62qktPtDFWG8ciSsd6eEPr7S7HuiGaouqDhfPT7H84DPp9mCgTHjwE", + sub_account: None, + metadata: None, + }, + ), + amount: Some( + Amount { + value: "715607016", + currency: Currency { + symbol: "mina", + decimals: 9, + metadata: None, + }, + metadata: None, + }, + ), + coin_change: None, + metadata: None, + }, + ], + related_transactions: None, + metadata: None, + }, + ], + metadata: None, + }, + ), + other_transactions: None, + }, + ), +) diff --git a/words.txt b/words.txt index 3f75934..60db930 100644 --- a/words.txt +++ b/words.txt @@ -24,6 +24,7 @@ keypair lookback microschemas mina +minafoundation navroot nocapture openapi @@ -42,5 +43,6 @@ urlencode utxo walkdir webroot +xlarge zkapp zkapps