From 9e8738e0355c8e752195351fde059ce02cdcf898 Mon Sep 17 00:00:00 2001 From: Miguel Nieto <39246879+miguelnietoa@users.noreply.github.com> Date: Mon, 4 Mar 2024 08:37:03 -0500 Subject: [PATCH 1/5] [Horizon] Dynamic network configuration: Create `Stellar.Horizon.Server` struct (#353) * Update Transactions, Accounts & Assets modules * Update Assets, ClaimableBalances, Effects, FeeStats, Ledgers & LiquidityPools, Offers & Operations * Update OrderBooks, PaymentPaths, TradeAggregations & Trades modules * Fix Client, Request & Network tests * Format code * Add tests for new Server struct * Update README documentation * Update docs/examples documentation --- README.md | 358 +++++++++++++----- docs/examples/operations/create_account.md | 4 +- docs/examples/operations/payments.md | 10 +- .../signatures/ed25519_signed_payload.md | 10 +- docs/examples/signatures/hash_x.md | 10 +- docs/examples/signatures/pre_auth_tx.md | 7 +- docs/examples/soroban/create_contract.md | 4 +- docs/examples/soroban/extend_footprint_ttl.md | 3 +- .../soroban/invoke_contract_functions.md | 9 +- docs/examples/soroban/restore_footprint.md | 3 +- docs/examples/soroban/upload_contract_code.md | 4 +- lib/horizon/accounts.ex | 158 ++++---- lib/horizon/assets.ex | 46 ++- lib/horizon/claimable_balances.ex | 113 ++++-- lib/horizon/client.ex | 4 +- lib/horizon/client/default.ex | 6 +- lib/horizon/client/spec.ex | 2 + lib/horizon/effects.ex | 18 +- lib/horizon/fee_stats.ex | 16 +- lib/horizon/ledgers.ex | 89 +++-- lib/horizon/liquidity_pools.ex | 104 +++-- lib/horizon/offers.ex | 49 ++- lib/horizon/operations.ex | 63 +-- lib/horizon/order_books.ex | 31 +- lib/horizon/payment_paths.ex | 155 ++++---- lib/horizon/request.ex | 13 +- lib/horizon/server.ex | 28 ++ lib/horizon/trade_aggregations.ex | 41 +- lib/horizon/trades.ex | 20 +- lib/horizon/transactions.ex | 70 ++-- lib/util/network.ex | 36 +- mix.lock | 2 +- test/horizon/accounts_test.exs | 32 +- test/horizon/assets_test.exs | 14 +- test/horizon/claimable_balances_test.exs | 28 +- test/horizon/client/default_test.exs | 39 +- test/horizon/client_test.exs | 6 +- test/horizon/effects_test.exs | 10 +- test/horizon/fee_stats_test.exs | 4 +- test/horizon/ledgers_test.exs | 19 +- test/horizon/liquidity_pools_test.exs | 21 +- test/horizon/offers_test.exs | 14 +- test/horizon/operations_test.exs | 17 +- test/horizon/order_books_test.exs | 5 +- test/horizon/payment_paths_test.exs | 9 +- test/horizon/request_test.exs | 67 ++-- test/horizon/server_test.exs | 25 ++ test/horizon/trade_aggregations_test.exs | 7 +- test/horizon/trades_test.exs | 10 +- test/horizon/transactions_test.exs | 19 +- test/util/network_test.exs | 53 +-- 51 files changed, 1189 insertions(+), 696 deletions(-) create mode 100644 lib/horizon/server.ex create mode 100644 test/horizon/server_test.exs diff --git a/README.md b/README.md index 847c1882..58e600e6 100644 --- a/README.md +++ b/README.md @@ -41,10 +41,6 @@ end ``` ## Configuration -```elixir -config :stellar_sdk, network: :test # Default is `:test`. To use the public network, set it to `:public` - -``` The default HTTP Client is `:hackney`. Options to `:hackney` can be passed through configuration params. ```elixir @@ -154,7 +150,11 @@ Each transaction has a [sequence number][stellar-docs-sequence-number] associate source_account = Stellar.TxBuild.Account.new("GDC3W2X5KUTZRTQIKXM5D2I5WG5JYSEJQWEELVPQ5YMWZR6CA2JJ35RW") # fetch next account's sequence number from Horizon -{:ok, seq_num} = Stellar.Horizon.Accounts.fetch_next_sequence_number("GDC3W2X5KUTZRTQIKXM5D2I5WG5JYSEJQWEELVPQ5YMWZR6CA2JJ35RW") +{:ok, seq_num} = + Stellar.Horizon.Accounts.fetch_next_sequence_number( + Stellar.Horizon.Server.testnet(), + "GDC3W2X5KUTZRTQIKXM5D2I5WG5JYSEJQWEELVPQ5YMWZR6CA2JJ35RW" + ) # set the sequence number sequence_number = Stellar.TxBuild.SequenceNumber.new(seq_num) @@ -436,6 +436,28 @@ More examples can be found in the [**tests**][sdk-tests]. ## Querying Horizon Horizon is an API for interacting with the Stellar network. +To query Horizon, you need to specify the Horizon server to use. + +```elixir +# public horizon server +Stellar.Horizon.Server.public() + +# testnet horizon server +Stellar.Horizon.Server.testnet() + +# futurenet horizon server +Stellar.Horizon.Server.futurenet() + +# local horizon server +Stellar.Horizon.Server.local() + +# custom horizon server +Stellar.Horizon.Server.new("https://horizon-standalone.com") +``` + +See [**Stellar.Horizon.Server**](https://hexdocs.pm/stellar_sdk/Stellar.Horizon.Server.html) for more details. + + To make it possible to explore the millions of records for resources like transactions and operations, this library paginates the data it returns for collection-based resources. Each individual transaction, operation, ledger, etc. is returned as a record. ```elixir @@ -446,7 +468,7 @@ To make it possible to explore the millions of records for resources like transa failed_transaction_count: 0, fee_pool: 3.0e-5, ... - }} = Ledgers.retrieve(1234) + }} = Ledgers.retrieve(Stellar.Horizon.Server.testnet(), 1234) ``` A group of records is called a **collection**, records are returned as a list in the [**Stellar.Horizon.Collection**](https://hexdocs.pm/stellar_sdk/Stellar.Horizon.Collection.html#content) structure. To move between pages of a collection of records, use the `next` and `prev` attributes. @@ -462,7 +484,7 @@ A group of records is called a **collection**, records are returned as a list in %Stellar.Horizon.Ledger{...}, %Stellar.Horizon.Ledger{...} ] - }} = Stellar.Horizon.Ledgers.all() + }} = Stellar.Horizon.Ledgers.all(Stellar.Horizon.Server.testnet()) ``` ### Pagination @@ -474,7 +496,7 @@ The [HAL format links](https://developers.stellar.org/api/introduction/response- next: paginate_next_fn, prev: paginate_prev_fn, records: [...] - }} = Stellar.Horizon.Transactions.all() + }} = Stellar.Horizon.Transactions.all(Stellar.Horizon.Server.testnet()) # next page records for the collection paginate_next_fn.() @@ -500,28 +522,57 @@ paginate_prev_fn.() ### Accounts ```elixir # retrieve an account -Stellar.Horizon.Accounts.retrieve("GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") +Stellar.Horizon.Accounts.retrieve( + Stellar.Horizon.Server.testnet(), + "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD" +) # fetch the ledger's sequence number for the account -Stellar.Horizon.Accounts.fetch_next_sequence_number("GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") +Stellar.Horizon.Accounts.fetch_next_sequence_number( + Stellar.Horizon.Server.testnet(), + "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD" +) # list accounts -Stellar.Horizon.Accounts.all(limit: 10, order: :asc) +Stellar.Horizon.Accounts.all( + Stellar.Horizon.Server.testnet(), + limit: 10, + order: :asc +) # list accounts by sponsor -Stellar.Horizon.Accounts.all(sponsor: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") +Stellar.Horizon.Accounts.all( + Stellar.Horizon.Server.testnet(), + sponsor: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD" +) # list accounts by signer -Stellar.Horizon.Accounts.all(signer: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", order: :desc) +Stellar.Horizon.Accounts.all( + Stellar.Horizon.Server.testnet(), + signer: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", + order: :desc +) # list accounts by canonical asset address -Stellar.Horizon.Accounts.all(asset: "TEST:GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", limit: 20) +Stellar.Horizon.Accounts.all( + Stellar.Horizon.Server.testnet(), + asset: "TEST:GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", + limit: 20 +) # list account's transactions -Stellar.Horizon.Accounts.list_transactions("GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", limit: 20) +Stellar.Horizon.Accounts.list_transactions( + Stellar.Horizon.Server.testnet(), + "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", + limit: 20 +) # list account's payments -Stellar.Horizon.Accounts.list_payments("GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", limit: 20) +Stellar.Horizon.Accounts.list_payments( + Stellar.Horizon.Server.testnet(), + "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", + limit: 20 +) ``` See [**Stellar.Horizon.Accounts**](https://hexdocs.pm/stellar_sdk/Stellar.Horizon.Accounts.html#content) for more details. @@ -529,25 +580,37 @@ See [**Stellar.Horizon.Accounts**](https://hexdocs.pm/stellar_sdk/Stellar.Horizo ### Transactions ```elixir # submit a transaction -Stellar.Horizon.Transactions.create(base64_tx_envelope) +Stellar.Horizon.Transactions.create(Stellar.Horizon.Server.testnet(), base64_tx_envelope) # retrieve a transaction -Stellar.Horizon.Transactions.retrieve("5ebd5c0af4385500b53dd63b0ef5f6e8feef1a7e1c86989be3cdcce825f3c0cc") +Stellar.Horizon.Transactions.retrieve(Stellar.Horizon.Server.testnet(), "5ebd5c0af4385500b53dd63b0ef5f6e8feef1a7e1c86989be3cdcce825f3c0cc") # list transactions -Stellar.Horizon.Transactions.all(limit: 10, order: :asc) +Stellar.Horizon.Transactions.all(Stellar.Horizon.Server.testnet(), limit: 10, order: :asc) # include failed transactions -Stellar.Horizon.Transactions.all(limit: 10, include_failed: true) +Stellar.Horizon.Transactions.all(Stellar.Horizon.Server.testnet(), limit: 10, include_failed: true) # list transaction's effects -Stellar.Horizon.Transactions.list_effects("6b983a4e0dc3c04f4bd6b9037c55f70a09c434dfd01492be1077cf7ea68c2e4a", limit: 20) +Stellar.Horizon.Transactions.list_effects( + Stellar.Horizon.Server.testnet(), + "6b983a4e0dc3c04f4bd6b9037c55f70a09c434dfd01492be1077cf7ea68c2e4a", + limit: 20 +) # list transaction's operations -Stellar.Horizon.Transactions.list_operations("6b983a4e0dc3c04f4bd6b9037c55f70a09c434dfd01492be1077cf7ea68c2e4a", limit: 20) +Stellar.Horizon.Transactions.list_operations( + Stellar.Horizon.Server.testnet(), + "6b983a4e0dc3c04f4bd6b9037c55f70a09c434dfd01492be1077cf7ea68c2e4a", + limit: 20 +) # join transactions in the operations response -Stellar.Horizon.Transactions.list_operations("6b983a4e0dc3c04f4bd6b9037c55f70a09c434dfd01492be1077cf7ea68c2e4a", join: "transactions") +Stellar.Horizon.Transactions.list_operations( + Stellar.Horizon.Server.testnet(), + "6b983a4e0dc3c04f4bd6b9037c55f70a09c434dfd01492be1077cf7ea68c2e4a", + join: "transactions" +) ``` See [**Stellar.Horizon.Transactions**](https://hexdocs.pm/stellar_sdk/Stellar.Horizon.Transactions.html#content) for more details. @@ -556,22 +619,22 @@ See [**Stellar.Horizon.Transactions**](https://hexdocs.pm/stellar_sdk/Stellar.Ho ### Operations ```elixir # retrieve an operation -Stellar.Horizon.Operations.retrieve(121693057904021505) +Stellar.Horizon.Operations.retrieve(Stellar.Horizon.Server.testnet(), 121693057904021505) # list operations -Stellar.Horizon.Operations.all(limit: 10, order: :asc) +Stellar.Horizon.Operations.all(Stellar.Horizon.Server.testnet(), limit: 10, order: :asc) # include failed operations -Stellar.Horizon.Operations.all(limit: 10, include_failed: true) +Stellar.Horizon.Operations.all(Stellar.Horizon.Server.testnet(), limit: 10, include_failed: true) # include operation's transactions -Stellar.Horizon.Operations.all(limit: 10, join: "transactions") +Stellar.Horizon.Operations.all(Stellar.Horizon.Server.testnet(), limit: 10, join: "transactions") # list operation's payments -Stellar.Horizon.Operations.list_payments(limit: 20) +Stellar.Horizon.Operations.list_payments(Stellar.Horizon.Server.testnet(), limit: 20) # list operation's effects -Stellar.Horizon.Operations.list_effects(121693057904021505, limit: 20) +Stellar.Horizon.Operations.list_effects(Stellar.Horizon.Server.testnet(), 121693057904021505, limit: 20) ``` See [**Stellar.Horizon.Operations**](https://hexdocs.pm/stellar_sdk/Stellar.Horizon.Operations.html#content) for more details. @@ -580,18 +643,24 @@ See [**Stellar.Horizon.Operations**](https://hexdocs.pm/stellar_sdk/Stellar.Hori ### Assets ```elixir # list ledger's assets -Stellar.Horizon.Assets.all(limit: 20, order: :desc) +Stellar.Horizon.Assets.all(Stellar.Horizon.Server.testnet(), limit: 20, order: :desc) # list assets by asset issuer -Stellar.Horizon.Assets.all(asset_issuer: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") +Stellar.Horizon.Assets.all(Stellar.Horizon.Server.testnet(), asset_issuer: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") # list assets by asset code -Stellar.Horizon.Assets.list_by_asset_code("TEST") -Stellar.Horizon.Assets.all(asset_code: "TEST") +Stellar.Horizon.Assets.list_by_asset_code(Stellar.Horizon.Server.testnet(), "TEST") +Stellar.Horizon.Assets.all(Stellar.Horizon.Server.testnet(), asset_code: "TEST") # list assets by asset issuer -Stellar.Horizon.Assets.all(asset_issuer: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") -Stellar.Horizon.Assets.list_by_asset_issuer("GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") +Stellar.Horizon.Assets.all( + Stellar.Horizon.Server.testnet(), + asset_issuer: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD" +) +Stellar.Horizon.Assets.list_by_asset_issuer( + Stellar.Horizon.Server.testnet(), + "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD" +) ``` See [**Stellar.Horizon.Assets**](https://hexdocs.pm/stellar_sdk/Stellar.Horizon.Assets.html#content) for more details. @@ -600,22 +669,22 @@ See [**Stellar.Horizon.Assets**](https://hexdocs.pm/stellar_sdk/Stellar.Horizon. ### Ledgers ```elixir # retrieve a ledger -Stellar.Horizon.Ledgers.retrieve(27147222) +Stellar.Horizon.Ledgers.retrieve(Stellar.Horizon.Server.testnet(), 27147222) # list ledgers -Stellar.Horizon.Ledgers.all(limit: 10, order: :asc) +Stellar.Horizon.Ledgers.all(Stellar.Horizon.Server.testnet(), limit: 10, order: :asc) # list ledger's transactions -Stellar.Horizon.Ledgers.list_transactions(27147222, limit: 20) +Stellar.Horizon.Ledgers.list_transactions(Stellar.Horizon.Server.testnet(), 27147222, limit: 20) # list ledger's operations -Stellar.Horizon.Ledgers.list_operations(27147222, join: "transactions") +Stellar.Horizon.Ledgers.list_operations(Stellar.Horizon.Server.testnet(), 27147222, join: "transactions") # list ledger's payments including failed transactions -Stellar.Horizon.Ledgers.list_payments(27147222, include_failed: true) +Stellar.Horizon.Ledgers.list_payments(Stellar.Horizon.Server.testnet(), 27147222, include_failed: true) # list ledger's effects -Stellar.Horizon.Ledgers.list_effects(27147222, limit: 20) +Stellar.Horizon.Ledgers.list_effects(Stellar.Horizon.Server.testnet(), 27147222, limit: 20) ``` See [**Stellar.Horizon.Ledgers**](https://hexdocs.pm/stellar_sdk/Stellar.Horizon.Ledgers.html#content) for more details. @@ -624,16 +693,24 @@ See [**Stellar.Horizon.Ledgers**](https://hexdocs.pm/stellar_sdk/Stellar.Horizon ### Offers ```elixir # list offers -Stellar.Horizon.Offers.all(limit: 20, order: :asc) +Stellar.Horizon.Offers.all(Stellar.Horizon.Server.testnet(), limit: 20, order: :asc) # list offers by sponsor -Stellar.Horizon.Offers.all(sponsor: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") +Stellar.Horizon.Offers.all( + Stellar.Horizon.Server.testnet(), + sponsor: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD" +) # list offers by seller -Stellar.Horizon.Offers.all(seller: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", order: :desc) +Stellar.Horizon.Offers.all( + Stellar.Horizon.Server.testnet(), + seller: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", + order: :desc +) # list offers by selling_asset Stellar.Horizon.Offers.all( + Stellar.Horizon.Server.testnet(), selling_asset: [ code: "TEST", issuer: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD" @@ -642,6 +719,7 @@ Stellar.Horizon.Offers.all( # list offers by buying_asset Stellar.Horizon.Offers.all( + Stellar.Horizon.Server.testnet(), buying_asset: [ code: "TEST", issuer: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD" @@ -650,6 +728,7 @@ Stellar.Horizon.Offers.all( # list offers by selling_asset and buying_asset Stellar.Horizon.Trades.all( + Stellar.Horizon.Server.testnet(), selling_asset: [ code: "TEST", issuer: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD" @@ -661,6 +740,7 @@ Stellar.Horizon.Trades.all( ) Stellar.Horizon.Offers.all( + Stellar.Horizon.Server.testnet(), selling_asset: [ code: "TEST", issuer: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD" @@ -669,7 +749,7 @@ Stellar.Horizon.Offers.all( ) # list offer's trades -Stellar.Horizon.Offers.list_trades(165563085, limit: 20) +Stellar.Horizon.Offers.list_trades(Stellar.Horizon.Server.testnet(), 165563085, limit: 20) ``` See [**Stellar.Horizon.Offers**](https://hexdocs.pm/stellar_sdk/Stellar.Horizon.Offers.html#content) for more details. @@ -678,13 +758,14 @@ See [**Stellar.Horizon.Offers**](https://hexdocs.pm/stellar_sdk/Stellar.Horizon. ### Trades ```elixir # list tardes -Stellar.Horizon.Trades.all(limit: 20, order: :asc) +Stellar.Horizon.Trades.all(Stellar.Horizon.Server.testnet(), limit: 20, order: :asc) # list trades by offer_id -Stellar.Horizon.Trades.all(offer_id: 165563085) +Stellar.Horizon.Trades.all(Stellar.Horizon.Server.testnet(), offer_id: 165563085) # list trades by specific orderbook Stellar.Horizon.Trades.all( + Stellar.Horizon.Server.testnet(), base_asset: [ code: "TEST", issuer: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD" @@ -696,7 +777,8 @@ Stellar.Horizon.Trades.all( ) Stellar.Horizon.Trades.all( - base_asset: [ + Stellar.Horizon.Server.testnet(), + base_asset: [ code: "TEST", issuer: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD" ], @@ -704,7 +786,7 @@ Stellar.Horizon.Trades.all( ) # list trades by trade_type -Stellar.Horizon.Trades.all(trade_type: "liquidity_pools", limit: 20) +Stellar.Horizon.Trades.all(Stellar.Horizon.Server.testnet(), trade_type: "liquidity_pools", limit: 20) ``` See [**Stellar.Horizon.Trades**](https://hexdocs.pm/stellar_sdk/Stellar.Horizon.Trades.html#content) for more details. @@ -713,31 +795,66 @@ See [**Stellar.Horizon.Trades**](https://hexdocs.pm/stellar_sdk/Stellar.Horizon. ### ClaimableBalances ```elixir # retrieve a claimable balance -Stellar.Horizon.ClaimableBalances.retrieve("00000000ca6aba5fb0993844e0076f75bee53f2b8014be29cd8f2e6ae19fb0a17fc68695") +Stellar.Horizon.ClaimableBalances.retrieve( + Stellar.Horizon.Server.testnet(), + "00000000ca6aba5fb0993844e0076f75bee53f2b8014be29cd8f2e6ae19fb0a17fc68695" +) # list claimable balances -Stellar.Horizon.ClaimableBalances.all(limit: 2, order: :asc) +Stellar.Horizon.ClaimableBalances.all(Stellar.Horizon.Server.testnet(), limit: 2, order: :asc) # list claimable balances by sponsor -Stellar.Horizon.ClaimableBalances.list_by_sponsor("GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") -Stellar.Horizon.ClaimableBalances.all(sponsor: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") +Stellar.Horizon.ClaimableBalances.list_by_sponsor( + Stellar.Horizon.Server.testnet(), + "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD" +) +Stellar.Horizon.ClaimableBalances.all( + Stellar.Horizon.Server.testnet(), + sponsor: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD" +) # list claimable balances by claimant -Stellar.Horizon.ClaimableBalances.list_by_claimant("GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") -Stellar.Horizon.ClaimableBalances.all(claimant: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", order: :desc) +Stellar.Horizon.ClaimableBalances.list_by_claimant( + Stellar.Horizon.Server.testnet(), + "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD" +) +Stellar.Horizon.ClaimableBalances.all( + Stellar.Horizon.Server.testnet(), + claimant: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", + order: :desc +) # list claimable balances by canonical asset address -Stellar.Horizon.ClaimableBalances.list_by_asset("TEST:GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") -Stellar.Horizon.ClaimableBalances.all(asset: "TEST:GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", limit: 20) +Stellar.Horizon.ClaimableBalances.list_by_asset( + Stellar.Horizon.Server.testnet(), + "TEST:GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD" +) +Stellar.Horizon.ClaimableBalances.all( + Stellar.Horizon.Server.testnet(), + asset: "TEST:GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", + limit: 20 +) # list claimable balance's transactions -Stellar.Horizon.ClaimableBalances.list_transactions("00000000ca6aba5fb0993844e0076f75bee53f2b8014be29cd8f2e6ae19fb0a17fc68695", limit: 20) +Stellar.Horizon.ClaimableBalances.list_transactions( + Stellar.Horizon.Server.testnet(), + "00000000ca6aba5fb0993844e0076f75bee53f2b8014be29cd8f2e6ae19fb0a17fc68695", + limit: 20 +) # list claimable balance's operations -Stellar.Horizon.ClaimableBalances.list_operations("00000000ca6aba5fb0993844e0076f75bee53f2b8014be29cd8f2e6ae19fb0a17fc68695", limit: 20) +Stellar.Horizon.ClaimableBalances.list_operations( + Stellar.Horizon.Server.testnet(), + "00000000ca6aba5fb0993844e0076f75bee53f2b8014be29cd8f2e6ae19fb0a17fc68695", + limit: 20 +) # join transactions in the operations response -Stellar.Horizon.ClaimableBalances.list_operations("00000000ca6aba5fb0993844e0076f75bee53f2b8014be29cd8f2e6ae19fb0a17fc68695", join: "transactions") +Stellar.Horizon.ClaimableBalances.list_operations( + Stellar.Horizon.Server.testnet(), + "00000000ca6aba5fb0993844e0076f75bee53f2b8014be29cd8f2e6ae19fb0a17fc68695", + join: "transactions" +) ``` See [**Stellar.Horizon.Balances**](https://hexdocs.pm/stellar_sdk/Stellar.Horizon.ClaimableBalances.html#content) for more details. @@ -746,28 +863,54 @@ See [**Stellar.Horizon.Balances**](https://hexdocs.pm/stellar_sdk/Stellar.Horizo ### LiquidityPools ```elixir # retrieve a liquidity pool -Stellar.Horizon.LiquidityPools.retrieve("001365fc79ca661f31ba3ee0849ae4ba36f5c377243242d37fad5b1bb8912dbc") +Stellar.Horizon.LiquidityPools.retrieve( + Stellar.Horizon.Server.testnet(), + "001365fc79ca661f31ba3ee0849ae4ba36f5c377243242d37fad5b1bb8912dbc" +) # list liquidity pools -Stellar.Horizon.LiquidityPools.all(limit: 2, order: :asc) +Stellar.Horizon.LiquidityPools.all(Stellar.Horizon.Server.testnet(), limit: 2, order: :asc) # list liquidity pools by reserves -Stellar.Horizon.LiquidityPools.all(reserves: "TEST:GCXMW..., TEST2:GCXMW...") +Stellar.Horizon.LiquidityPools.all( + Stellar.Horizon.Server.testnet(), + reserves: "TEST:GCXMW..., TEST2:GCXMW..." +) # list liquidity pools by account -Stellar.Horizon.LiquidityPools.all(account: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", order: :desc) +Stellar.Horizon.LiquidityPools.all( + Stellar.Horizon.Server.testnet(), + account: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", + order: :desc +) # list liquidity pool's effects -Stellar.Horizon.LiquidityPools.list_effects("001365fc79ca661f31ba3ee0849ae4ba36f5c377243242d37fad5b1bb8912dbc", limit: 20) +Stellar.Horizon.LiquidityPools.list_effects( + Stellar.Horizon.Server.testnet(), + "001365fc79ca661f31ba3ee0849ae4ba36f5c377243242d37fad5b1bb8912dbc", + limit: 20 +) # list liquidity pool's trades -Stellar.Horizon.LiquidityPools.list_trades("001365fc79ca661f31ba3ee0849ae4ba36f5c377243242d37fad5b1bb8912dbc", limit: 20) +Stellar.Horizon.LiquidityPools.list_trades( + Stellar.Horizon.Server.testnet(), + "001365fc79ca661f31ba3ee0849ae4ba36f5c377243242d37fad5b1bb8912dbc", + limit: 20 +) # list liquidity pool's transactions -Stellar.Horizon.LiquidityPools.list_transactions("001365fc79ca661f31ba3ee0849ae4ba36f5c377243242d37fad5b1bb8912dbc", limit: 20) +Stellar.Horizon.LiquidityPools.list_transactions( + Stellar.Horizon.Server.testnet(), + "001365fc79ca661f31ba3ee0849ae4ba36f5c377243242d37fad5b1bb8912dbc", + limit: 20 +) # list liquidity pool's operations -Stellar.Horizon.LiquidityPools.list_operations("001365fc79ca661f31ba3ee0849ae4ba36f5c377243242d37fad5b1bb8912dbc", limit: 20) +Stellar.Horizon.LiquidityPools.list_operations( + Stellar.Horizon.Server.testnet(), + "001365fc79ca661f31ba3ee0849ae4ba36f5c377243242d37fad5b1bb8912dbc", + limit: 20 +) ``` See [**Stellar.Horizon.Pools**](https://hexdocs.pm/stellar_sdk/Stellar.Horizon.LiquidityPools.html#content) for more details. @@ -776,7 +919,11 @@ See [**Stellar.Horizon.Pools**](https://hexdocs.pm/stellar_sdk/Stellar.Horizon.L ### Effects ```elixir # list effects -Stellar.Horizon.Effects.all(limit: 10, order: :asc) +Stellar.Horizon.Effects.all( + Stellar.Horizon.Server.testnet(), + limit: 10, + order: :asc +) ``` See [**Stellar.Horizon.Effects**](https://hexdocs.pm/stellar_sdk/Stellar.Horizon.Effects.html#content) for more details. @@ -784,7 +931,7 @@ See [**Stellar.Horizon.Effects**](https://hexdocs.pm/stellar_sdk/Stellar.Horizon ### FeeStats ```elixir # retrieve fee stats -Stellar.Horizon.FeeStats.retrieve() +Stellar.Horizon.FeeStats.retrieve(Stellar.Horizon.Server.testnet()) ``` See [**Stellar.Horizon.FeeStats**](https://developers.stellar.org/api/aggregations/fee-stats/single/) for more details. @@ -799,7 +946,12 @@ This will return information about potential path payments: - [Optional] destination_account. The Stellar address of the reciever. ```elixir -Stellar.Horizon.PaymentPaths.list_paths(source_account: "GBRSLTT74SKP62KJ7ENTMP5V4R7UGB6E5UQESNIIRWUNRCCUO4ZMFM4C", destination_asset: :native, destination_amount: 5) +Stellar.Horizon.PaymentPaths.list_paths( + Stellar.Horizon.Server.testnet(), + source_account: "GBRSLTT74SKP62KJ7ENTMP5V4R7UGB6E5UQESNIIRWUNRCCUO4ZMFM4C", + destination_asset: :native, + destination_amount: 5 +) ``` #### List strict receive payment paths @@ -809,7 +961,12 @@ Stellar.Horizon.PaymentPaths.list_paths(source_account: "GBRSLTT74SKP62KJ7ENTMP5 - [Optional] source_assets. A comma-separated list of assets available to the sender. ```elixir -Stellar.Horizon.PaymentPaths.list_receive_paths(destination_asset: :native, destination_amount: 5, source_account: "GBTKSXOTFMC5HR25SNL76MOVQW7GA3F6CQEY622ASLUV4VMLITI6TCOO") +Stellar.Horizon.PaymentPaths.list_receive_paths( + Stellar.Horizon.Server.testnet(), + destination_asset: :native, + destination_amount: 5, + source_account: "GBTKSXOTFMC5HR25SNL76MOVQW7GA3F6CQEY622ASLUV4VMLITI6TCOO" +) ``` #### List strict send payment paths @@ -819,7 +976,12 @@ Stellar.Horizon.PaymentPaths.list_receive_paths(destination_asset: :native, dest - [Optional] destination_assets. A comma-separated list of assets that the recipient can receive. ```elixir -Stellar.Horizon.PaymentPaths.list_send_paths(source_asset: :native, source_amount: 5, destination_assets: "TEST:GA654JC6QLA3ZH4O5V7X5NPM7KEWHKRG5GJA4PETK4SOFBUJLCCN74KQ") +Stellar.Horizon.PaymentPaths.list_send_paths( + Stellar.Horizon.Server.testnet(), + source_asset: :native, + source_amount: 5, + destination_assets: "TEST:GA654JC6QLA3ZH4O5V7X5NPM7KEWHKRG5GJA4PETK4SOFBUJLCCN74KQ" +) ``` See [**Stellar.Horizon.Paths**](https://developers.stellar.org/api/aggregations/paths/) for more details. @@ -833,14 +995,21 @@ Provides an order book’s bids and asks: - [Optional] limit. The maximum number of records returned ```elixir -Stellar.Horizon.OrderBooks.retrieve(selling_asset: :native, buying_asset: :native) -Stellar.Horizon.OrderBooks.retrieve(selling_asset: :native, - buying_asset: [ - code: "BB1", - issuer: "GD5J6HLF5666X4AZLTFTXLY46J5SW7EXRKBLEYPJP33S33MXZGV6CWFN" - ], - limit: 2 - ) +Stellar.Horizon.OrderBooks.retrieve( + Stellar.Horizon.Server.testnet(), + selling_asset: :native, + buying_asset: :native +) + +Stellar.Horizon.OrderBooks.retrieve( + Stellar.Horizon.Server.testnet(), + selling_asset: :native, + buying_asset: [ + code: "BB1", + issuer: "GD5J6HLF5666X4AZLTFTXLY46J5SW7EXRKBLEYPJP33S33MXZGV6CWFN" + ], + limit: 2 +) ``` See [**Stellar.Horizon.OrderBooks**](https://developers.stellar.org/api/aggregations/order-books/) for more details. @@ -859,17 +1028,24 @@ Displays trade data based on filters set in the arguments: - [Optional] limit. The maximum number of records returned. ```elixir -Stellar.Horizon.TradeAggregations.list_trade_aggregations(base_asset: :native, counter_asset: :native, resolution: "60000") -Stellar.Horizon.TradeAggregations.list_trade_aggregations(base_asset: :native, - counter_asset: [ - code: "EURT", - issuer: "GAP5LETOV6YIE62YAM56STDANPRDO7ZFDBGSNHJQIYGGKSMOZAHOOS2S" - ], - resolution: "3600000", - start_time: "1582156800000", - end_time: "1582178400000" - ) +Stellar.Horizon.TradeAggregations.list_trade_aggregations( + Stellar.Horizon.Server.testnet(), + base_asset: :native, + counter_asset: :native, + resolution: "60000" +) +Stellar.Horizon.TradeAggregations.list_trade_aggregations( + Stellar.Horizon.Server.testnet(), + base_asset: :native, + counter_asset: [ + code: "EURT", + issuer: "GAP5LETOV6YIE62YAM56STDANPRDO7ZFDBGSNHJQIYGGKSMOZAHOOS2S" + ], + resolution: "3600000", + start_time: "1582156800000", + end_time: "1582178400000" +) ``` See [**Stellar.Horizon.TradeAggregations**](https://developers.stellar.org/api/aggregations/trade-aggregations/) for more details. diff --git a/docs/examples/operations/create_account.md b/docs/examples/operations/create_account.md index 6acbc3ac..cce4a0ef 100644 --- a/docs/examples/operations/create_account.md +++ b/docs/examples/operations/create_account.md @@ -5,7 +5,7 @@ source_account = Stellar.TxBuild.Account.new("GDC3W2X5KUTZRTQIKXM5D2I5WG5JYSEJQWEELVPQ5YMWZR6CA2JJ35RW") # 2. set the next sequence number for the founder account -{:ok, seq_num} = Stellar.Horizon.Accounts.fetch_next_sequence_number("GDC3W2X5KUTZRTQIKXM5D2I5WG5JYSEJQWEELVPQ5YMWZR6CA2JJ35RW") +{:ok, seq_num} = Stellar.Horizon.Accounts.fetch_next_sequence_number(Stellar.Horizon.Server.testnet(), "GDC3W2X5KUTZRTQIKXM5D2I5WG5JYSEJQWEELVPQ5YMWZR6CA2JJ35RW") sequence_number = Stellar.TxBuild.SequenceNumber.new(seq_num) # 3. build the create_account operation @@ -26,5 +26,5 @@ signature = Stellar.TxBuild.Signature.new(signer_key_pair) |> Stellar.TxBuild.sign(signature) |> Stellar.TxBuild.envelope() -{:ok, submitted_tx} = Stellar.Horizon.Transactions.create(base64_envelope) +{:ok, submitted_tx} = Stellar.Horizon.Transactions.create(Stellar.Horizon.Server.testnet(), base64_envelope) ``` diff --git a/docs/examples/operations/payments.md b/docs/examples/operations/payments.md index 44f04a28..e86842fa 100644 --- a/docs/examples/operations/payments.md +++ b/docs/examples/operations/payments.md @@ -7,7 +7,8 @@ source_account = Stellar.TxBuild.Account.new("GDC3W2X5KUTZRTQIKXM5D2I5WG5JYSEJQWEELVPQ5YMWZR6CA2JJ35RW") # 2. set the next sequence number for the payer account -{:ok, seq_num} = Stellar.Horizon.Accounts.fetch_next_sequence_number("GDC3W2X5KUTZRTQIKXM5D2I5WG5JYSEJQWEELVPQ5YMWZR6CA2JJ35RW") +server = Stellar.Horizon.Server.testnet() +{:ok, seq_num} = Stellar.Horizon.Accounts.fetch_next_sequence_number(server, "GDC3W2X5KUTZRTQIKXM5D2I5WG5JYSEJQWEELVPQ5YMWZR6CA2JJ35RW") sequence_number = Stellar.TxBuild.SequenceNumber.new(seq_num) # 3. build the payment operation @@ -29,7 +30,7 @@ signature = Stellar.TxBuild.Signature.new(signer_key_pair) |> Stellar.TxBuild.sign(signature) |> Stellar.TxBuild.envelope() -{:ok, submitted_tx} = Stellar.Horizon.Transactions.create(base64_envelope) +{:ok, submitted_tx} = Stellar.Horizon.Transactions.create(server, base64_envelope) ``` ## Alphanum asset payment @@ -39,7 +40,8 @@ signature = Stellar.TxBuild.Signature.new(signer_key_pair) source_account = Stellar.TxBuild.Account.new("GDC3W2X5KUTZRTQIKXM5D2I5WG5JYSEJQWEELVPQ5YMWZR6CA2JJ35RW") # 2. set the next sequence number for the payer account -{:ok, seq_num} = Stellar.Horizon.Accounts.fetch_next_sequence_number("GDC3W2X5KUTZRTQIKXM5D2I5WG5JYSEJQWEELVPQ5YMWZR6CA2JJ35RW") +server = Stellar.Horizon.Server.testnet() +{:ok, seq_num} = Stellar.Horizon.Accounts.fetch_next_sequence_number(server, "GDC3W2X5KUTZRTQIKXM5D2I5WG5JYSEJQWEELVPQ5YMWZR6CA2JJ35RW") sequence_number = Stellar.TxBuild.SequenceNumber.new(seq_num) # 3. build the payment operation @@ -61,5 +63,5 @@ signature = Stellar.TxBuild.Signature.new(signer_key_pair) |> Stellar.TxBuild.sign(signature) |> Stellar.TxBuild.envelope() -{:ok, submitted_tx} = Stellar.Horizon.Transactions.create(base64_envelope) +{:ok, submitted_tx} = Stellar.Horizon.Transactions.create(server, base64_envelope) ``` diff --git a/docs/examples/signatures/ed25519_signed_payload.md b/docs/examples/signatures/ed25519_signed_payload.md index e6766d9a..84c8f6e4 100644 --- a/docs/examples/signatures/ed25519_signed_payload.md +++ b/docs/examples/signatures/ed25519_signed_payload.md @@ -69,7 +69,8 @@ So here, you use the `Stellar.TxBuild.SetOptions` operation to set the signer an source_account = Stellar.TxBuild.Account.new(payer_pk) # 2. set the next sequence number for the source account -{:ok, seq_num} = Stellar.Horizon.Accounts.fetch_next_sequence_number(payer_pk) +server = Stellar.Horizon.Server.testnet() +{:ok, seq_num} = Stellar.Horizon.Accounts.fetch_next_sequence_number(server, payer_pk) sequence_number = Stellar.TxBuild.SequenceNumber.new(seq_num) # 3. build the set_options operation setting the ed25519 signed payload as a signer with weight 1 @@ -92,7 +93,7 @@ signature = Stellar.TxBuild.Signature.new(ed25519: payer_sk) |> Stellar.TxBuild.sign(signature) |> Stellar.TxBuild.envelope() -{:ok, submitted_tx} = Stellar.Horizon.Transactions.create(envelope) +{:ok, submitted_tx} = Stellar.Horizon.Transactions.create(server, envelope) ``` ### 4. Send a payment using the Ed25519 Signed Payload signature @@ -104,7 +105,8 @@ Once you have established the signer, you can use the `payload` and the secret k source_account = Stellar.TxBuild.Account.new(payer_pk) # 2. set the next sequence number for the founder account -{:ok, seq_num} = Stellar.Horizon.Accounts.fetch_next_sequence_number(payer_pk) +server = Stellar.Horizon.Server.testnet() +{:ok, seq_num} = Stellar.Horizon.Accounts.fetch_next_sequence_number(server, payer_pk) sequence_number = Stellar.TxBuild.SequenceNumber.new(seq_num) # 3. build the payment operation @@ -127,7 +129,7 @@ signature = Stellar.TxBuild.Signature.new(signed_payload: [payload: payload, ed2 |> Stellar.TxBuild.sign(signature) |> Stellar.TxBuild.envelope() -{:ok, submitted_tx} = Stellar.Horizon.Transactions.create(envelope) +{:ok, submitted_tx} = Stellar.Horizon.Transactions.create(server, envelope) ``` > 👍 That's it! diff --git a/docs/examples/signatures/hash_x.md b/docs/examples/signatures/hash_x.md index dfdf1e37..c1371522 100644 --- a/docs/examples/signatures/hash_x.md +++ b/docs/examples/signatures/hash_x.md @@ -63,7 +63,8 @@ Setting the signer is done via the `Stellar.TxBuild.SetOptions` operation, see t source_account = Stellar.TxBuild.Account.new(payer_pk) # 2. set the next sequence number for the source account -{:ok, seq_num} = Stellar.Horizon.Accounts.fetch_next_sequence_number(payer_pk) +server = Stellar.Horizon.Server.testnet() +{:ok, seq_num} = Stellar.Horizon.Accounts.fetch_next_sequence_number(server, payer_pk) sequence_number = Stellar.TxBuild.SequenceNumber.new(seq_num) # 3. build the set_options operation setting the hash(x) as a signer with weight 1 @@ -80,7 +81,7 @@ signature = Stellar.TxBuild.Signature.new(ed25519: payer_sk) |> Stellar.TxBuild.sign(signature) |> Stellar.TxBuild.envelope() -{:ok, submitted_tx} = Stellar.Horizon.Transactions.create(envelope) +{:ok, submitted_tx} = Stellar.Horizon.Transactions.create(server, envelope) ``` The transaction is submitted! Now, the `hash(x)` is a signer of the account. @@ -96,7 +97,8 @@ Let's send a payment to the destination account! source_account = Stellar.TxBuild.Account.new(payer_pk) # 2. set the next sequence number for the founder account -{:ok, seq_num} = Stellar.Horizon.Accounts.fetch_next_sequence_number(payer_pk) +server = Stellar.Horizon.Server.testnet() +{:ok, seq_num} = Stellar.Horizon.Accounts.fetch_next_sequence_number(server, payer_pk) sequence_number = Stellar.TxBuild.SequenceNumber.new(seq_num) # 3. build the payment operation @@ -118,7 +120,7 @@ signature = Stellar.TxBuild.Signature.new(hash_x: preimage) |> Stellar.TxBuild.sign(signature) |> Stellar.TxBuild.envelope() -{:ok, submitted_tx} = Stellar.Horizon.Transactions.create(envelope) +{:ok, submitted_tx} = Stellar.Horizon.Transactions.create(server, envelope) ``` > 👍 That's it! diff --git a/docs/examples/signatures/pre_auth_tx.md b/docs/examples/signatures/pre_auth_tx.md index 398d1f26..726ea7b8 100644 --- a/docs/examples/signatures/pre_auth_tx.md +++ b/docs/examples/signatures/pre_auth_tx.md @@ -37,7 +37,8 @@ In order to create a pre-authorized transaction, you need to create a future tra source_account = Stellar.TxBuild.Account.new(public_key) # 2. set the next sequence number + 1 for the source account -{:ok, seq_num} = Stellar.Horizon.Accounts.fetch_next_sequence_number(pk1) +server = Stellar.Horizon.Server.testnet() +{:ok, seq_num} = Stellar.Horizon.Accounts.fetch_next_sequence_number(server, pk1) sequence_number = Stellar.TxBuild.SequenceNumber.new(seq_num + 1) # 3. build the payment operation @@ -97,7 +98,7 @@ signature = Stellar.TxBuild.Signature.new(ed25519: secret_key) |> Stellar.TxBuild.sign(signature) |> Stellar.TxBuild.envelope() -{:ok, submitted_set_options_tx} = Stellar.Horizon.Transactions.create(set_options_tx_envelope) +{:ok, submitted_set_options_tx} = Stellar.Horizon.Transactions.create(server, set_options_tx_envelope) ``` ### 4. Submit the payment transaction @@ -109,7 +110,7 @@ Since it was added as a signer, it is already pre-authorized and don't need to b You only need to submit the transaction envelope to the network. ✅ ```elixir -{:ok, submitted_payment_tx} = Stellar.Horizon.Transactions.create(payment_tx_envelope) +{:ok, submitted_payment_tx} = Stellar.Horizon.Transactions.create(server, payment_tx_envelope) ``` Once this is submitted, the transaction will be removed from the account as a signer. diff --git a/docs/examples/soroban/create_contract.md b/docs/examples/soroban/create_contract.md index 15ea7bf7..1e3f0cdd 100644 --- a/docs/examples/soroban/create_contract.md +++ b/docs/examples/soroban/create_contract.md @@ -52,7 +52,7 @@ keypair = source_account = Account.new(public_key) -{:ok, seq_num} = Stellar.Horizon.Accounts.fetch_next_sequence_number(public_key) +{:ok, seq_num} = Stellar.Horizon.Accounts.fetch_next_sequence_number(Stellar.Horizon.Server.testnet(), public_key) sequence_number = SequenceNumber.new(seq_num) signature = @@ -126,7 +126,7 @@ invoke_host_function_op = InvokeHostFunction.new(host_function: host_function) source_account = Account.new(public_key) -{:ok, seq_num} = Accounts.fetch_next_sequence_number(public_key) +{:ok, seq_num} = Accounts.fetch_next_sequence_number(Stellar.Horizon.Server.testnet(), public_key) sequence_number = SequenceNumber.new(seq_num) signature = Signature.new(keypair) diff --git a/docs/examples/soroban/extend_footprint_ttl.md b/docs/examples/soroban/extend_footprint_ttl.md index 7706ca57..7903e1dd 100644 --- a/docs/examples/soroban/extend_footprint_ttl.md +++ b/docs/examples/soroban/extend_footprint_ttl.md @@ -34,6 +34,7 @@ alias Stellar.TxBuild.{ alias Stellar.Horizon.Accounts alias Stellar.KeyPair +server = Stellar.Horizon.Server.testnet() contract_address = "CCNVHP2UAOJAICTQUDSRVZDCB5OJKGQNOJFPOXINELWQHGX33EG34NV2" contract_sc_address = SCAddress.new(contract_address) key = SCVal.new(ledger_key_contract_instance: nil) @@ -67,7 +68,7 @@ soroban_data = |> SorobanTransactionData.to_xdr() source_account = Account.new(public_key) -{:ok, seq_num} = Accounts.fetch_next_sequence_number(public_key) +{:ok, seq_num} = Accounts.fetch_next_sequence_number(server, public_key) sequence_number = SequenceNumber.new(seq_num) signature = Signature.new(keypair) extend_footprint_ttl_op = ExtendFootprintTTL.new(extend_to: 1000) diff --git a/docs/examples/soroban/invoke_contract_functions.md b/docs/examples/soroban/invoke_contract_functions.md index 5836393c..976d1a83 100644 --- a/docs/examples/soroban/invoke_contract_functions.md +++ b/docs/examples/soroban/invoke_contract_functions.md @@ -29,6 +29,7 @@ alias Stellar.TxBuild.{ alias Stellar.Horizon.Accounts alias Stellar.KeyPair +server = Stellar.Horizon.Server.new() contract_address = SCAddress.new("CAMGSYINVVL6WP3Q5WPNL7FS4GZP37TWV7MKIRQF5QMYLK3N2SW4P3RC") function_name = "hello" @@ -43,7 +44,7 @@ host_function = HostFunction.new(invoke_contract: args) invoke_host_function_op = InvokeHostFunction.new(host_function: host_function) keypair = {public_key, _secret} = KeyPair.from_secret_seed("SDR...Q24") source_account = Account.new(public_key) -{:ok, seq_num} = Accounts.fetch_next_sequence_number(public_key) +{:ok, seq_num} = Accounts.fetch_next_sequence_number(server, public_key) sequence_number = SequenceNumber.new(seq_num) signature = Signature.new(keypair) @@ -93,6 +94,7 @@ alias Stellar.TxBuild.{ alias Stellar.Horizon.Accounts alias Stellar.KeyPair +server = Stellar.Horizon.Server.new() contract_address = SCAddress.new("CAMGSYINVVL6WP3Q5WPNL7FS4GZP37TWV7MKIRQF5QMYLK3N2SW4P3RC") function_name = "inc" @@ -110,7 +112,7 @@ args = host_function = HostFunction.new(invoke_contract: args) invoke_host_function_op = InvokeHostFunction.new(host_function: host_function) source_account = Account.new(public_key) -{:ok, seq_num} = Accounts.fetch_next_sequence_number(public_key) +{:ok, seq_num} = Accounts.fetch_next_sequence_number(server, public_key) sequence_number = SequenceNumber.new(seq_num) signature = Signature.new(keypair) @@ -166,6 +168,7 @@ alias Stellar.TxBuild.{ alias Stellar.Horizon.Accounts alias Stellar.KeyPair +server = Stellar.Horizon.Server.new() contract_address = SCAddress.new("CAMGSYINVVL6WP3Q5WPNL7FS4GZP37TWV7MKIRQF5QMYLK3N2SW4P3RC") function_name = "inc" @@ -193,7 +196,7 @@ host_function = HostFunction.new(invoke_contract: args) invoke_host_function_op = InvokeHostFunction.new(host_function: host_function) source_account = Account.new(submitter_public_key) -{:ok, seq_num} = Accounts.fetch_next_sequence_number(submitter_public_key) +{:ok, seq_num} = Accounts.fetch_next_sequence_number(server, submitter_public_key) sequence_number = SequenceNumber.new(seq_num) signature = Signature.new(submitter_keypair) diff --git a/docs/examples/soroban/restore_footprint.md b/docs/examples/soroban/restore_footprint.md index 0b2d2041..fc7873cf 100644 --- a/docs/examples/soroban/restore_footprint.md +++ b/docs/examples/soroban/restore_footprint.md @@ -34,6 +34,7 @@ alias Stellar.TxBuild.{ alias Stellar.Horizon.Accounts alias Stellar.KeyPair +server = Stellar.Horizon.Server.testnet() contract_sc_address = SCAddress.new("CAMGSYINVVL6WP3Q5WPNL7FS4GZP37TWV7MKIRQF5QMYLK3N2SW4P3RC") key = SCVal.new(ledger_key_contract_instance: nil) @@ -63,7 +64,7 @@ soroban_data = |> SorobanTransactionData.to_xdr() source_account = Account.new(public_key) -{:ok, seq_num} = Accounts.fetch_next_sequence_number(public_key) +{:ok, seq_num} = Accounts.fetch_next_sequence_number(server, public_key) sequence_number = SequenceNumber.new(seq_num) signature = Signature.new(keypair) restore_footprint_op = RestoreFootprint.new() diff --git a/docs/examples/soroban/upload_contract_code.md b/docs/examples/soroban/upload_contract_code.md index 07018260..d7ce4627 100644 --- a/docs/examples/soroban/upload_contract_code.md +++ b/docs/examples/soroban/upload_contract_code.md @@ -19,6 +19,8 @@ alias Stellar.TxBuild.{ alias Stellar.Horizon.Accounts alias Stellar.KeyPair +server = Stellar.Horizon.Server.testnet() + # read file {:ok, code} = File.read("file_path/file.wasm") @@ -30,7 +32,7 @@ keypair = {public_key, _secret} = KeyPair.from_secret_seed("SDR...Q24") source_account = Account.new(public_key) -{:ok, seq_num} = Accounts.fetch_next_sequence_number(public_key) +{:ok, seq_num} = Accounts.fetch_next_sequence_number(server, public_key) sequence_number = SequenceNumber.new(seq_num) signature = Signature.new(keypair) diff --git a/lib/horizon/accounts.ex b/lib/horizon/accounts.ex index feab46bd..16ff1953 100644 --- a/lib/horizon/accounts.ex +++ b/lib/horizon/accounts.ex @@ -27,9 +27,11 @@ defmodule Stellar.Horizon.Accounts do Operation, Request, Trade, - Transaction + Transaction, + Server } + @type server :: Server.t() @type account_id :: String.t() @type options :: Keyword.t() @type resource :: Account.t() | Collection.t() @@ -41,17 +43,18 @@ defmodule Stellar.Horizon.Accounts do Retrieves information of a specific account. ## Parameters: + * `server`: The Horizon server to query. * `account_id`: The account’s public key encoded in a base32 string representation. ## Examples - iex> Accounts.retrieve("GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") + iex> Accounts.retrieve(Stellar.Horizon.Server.testnet(), "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") {:ok, %Account{}} """ - @spec retrieve(account_id :: account_id()) :: response() - def retrieve(account_id) do - :get - |> Request.new(@endpoint, path: account_id) + @spec retrieve(server :: server(), account_id :: account_id()) :: response() + def retrieve(server, account_id) do + server + |> Request.new(:get, @endpoint, path: account_id) |> Request.perform() |> Request.results(as: Account) end @@ -61,16 +64,17 @@ defmodule Stellar.Horizon.Accounts do ## Parameters: + * `server`: The Horizon server to query. * `account_id`: The account’s public key encoded in a base32 string representation. ## Examples - iex> Accounts.fetch_next_sequence_number("GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") + iex> Accounts.fetch_next_sequence_number(Stellar.Horizon.Server.testnet(), "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") {:ok, 17218523889687} """ - @spec fetch_next_sequence_number(account_id :: account_id()) :: response() - def fetch_next_sequence_number(account_id) do - case retrieve(account_id) do + @spec fetch_next_sequence_number(server :: server(), account_id :: account_id()) :: response() + def fetch_next_sequence_number(server, account_id) do + case retrieve(server, account_id) do {:ok, %Account{sequence: sequence}} -> {:ok, sequence + 1} error -> error end @@ -79,6 +83,9 @@ defmodule Stellar.Horizon.Accounts do @doc """ Lists all accounts or by one of these three filters: `signer`, `asset`, or `sponsor`. + ## Parameters: + * `server`: The Horizon server to query. + ## Options * `signer`: Account ID of the signer. @@ -90,34 +97,35 @@ defmodule Stellar.Horizon.Accounts do ## Examples - iex> Accounts.all(limit: 2, order: :asc) + iex> Accounts.all(Stellar.Horizon.Server.testnet(), limit: 2, order: :asc) {:ok, %Collection{records: [%Account{}, ...]}} # list by sponsor - iex> Accounts.all(sponsor: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") + iex> Accounts.all(Stellar.Horizon.Server.testnet(), sponsor: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") {:ok, %Collection{records: [%Account{}, ...]}} # list by signer - iex> Accounts.all(signer: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", order: :desc) + iex> Accounts.all(Stellar.Horizon.Server.testnet(), signer: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", order: :desc) {:ok, %Collection{records: [%Account{}, ...]}} # list by canonical asset address - iex> Accounts.all(asset: "TEST:GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", limit: 20) + iex> Accounts.all(Stellar.Horizon.Server.testnet(), asset: "TEST:GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", limit: 20) {:ok, %Collection{records: [%Account{}, ...]}} """ - @spec all(options :: options()) :: response() - def all(options \\ []) do - :get - |> Request.new(@endpoint) + @spec all(server :: server(), options :: options()) :: response() + def all(server, options \\ []) do + server + |> Request.new(:get, @endpoint) |> Request.add_query(options, extra_params: [:sponsor, :asset, :signer, :liquidity_pool]) |> Request.perform() - |> Request.results(collection: {Account, &all/1}) + |> Request.results(collection: {Account, &all(server, &1)}) end @doc """ Lists successful transactions for a given account. - ## Parameters + ## Parameters: + * `server`: The Horizon server to query. * `account_id`: The account’s public key encoded in a base32 string representation. ## Options @@ -128,22 +136,24 @@ defmodule Stellar.Horizon.Accounts do ## Examples - iex> Accounts.list_transactions("GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", limit: 20) + iex> Accounts.list_transactions(Stellar.Horizon.Server.testnet(), "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", limit: 20) {:ok, %Collection{records: [%Transaction{}, ...]}} """ - @spec list_transactions(account_id :: account_id(), options :: options()) :: response() - def list_transactions(account_id, options \\ []) do - :get - |> Request.new(@endpoint, path: account_id, segment: "transactions") + @spec list_transactions(server :: server(), account_id :: account_id(), options :: options()) :: + response() + def list_transactions(server, account_id, options \\ []) do + server + |> Request.new(:get, @endpoint, path: account_id, segment: "transactions") |> Request.add_query(options, extra_params: [:include_failed]) |> Request.perform() - |> Request.results(collection: {Transaction, &list_transactions(account_id, &1)}) + |> Request.results(collection: {Transaction, &list_transactions(server, account_id, &1)}) end @doc """ Lists successful operations for a given account. - ## Parameters + ## Parameters: + * `server`: The Horizon server to query. * `account_id`: The account’s public key encoded in a base32 string representation. ## Options @@ -155,26 +165,28 @@ defmodule Stellar.Horizon.Accounts do ## Examples - iex> Accounts.list_transactions("GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", limit: 20) + iex> Accounts.list_transactions(Stellar.Horizon.Server.testnet(), "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", limit: 20) {:ok, %Collection{records: [%Operation{}, ...]}} # join transactions - iex> Accounts.list_transactions("GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", join: "transactions") + iex> Accounts.list_transactions(Stellar.Horizon.Server.testnet(), "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", join: "transactions") {:ok, %Collection{records: [%Operation{transaction: %Transaction{}}, ...]}} """ - @spec list_operations(account_id :: account_id(), options :: options()) :: response() - def list_operations(account_id, options \\ []) do - :get - |> Request.new(@endpoint, path: account_id, segment: "operations") + @spec list_operations(server :: server(), account_id :: account_id(), options :: options()) :: + response() + def list_operations(server, account_id, options \\ []) do + server + |> Request.new(:get, @endpoint, path: account_id, segment: "operations") |> Request.add_query(options, extra_params: [:include_failed, :join]) |> Request.perform() - |> Request.results(collection: {Operation, &list_operations(account_id, &1)}) + |> Request.results(collection: {Operation, &list_operations(server, account_id, &1)}) end @doc """ Lists successful payments for a given account. - ## Parameters + ## Parameters: + * `server`: The Horizon server to query. * `account_id`: The account’s public key encoded in a base32 string representation. ## Options @@ -186,26 +198,28 @@ defmodule Stellar.Horizon.Accounts do ## Examples - iex> Accounts.list_payments("GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", limit: 20) + iex> Accounts.list_payments(Stellar.Horizon.Server.testnet(), "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", limit: 20) {:ok, %Collection{records: [%Operation{body: %Payment{}}, ...]}} # include failed - iex> Accounts.list_payments("GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", include_failed: true) + iex> Accounts.list_payments(Stellar.Horizon.Server.testnet(), "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", include_failed: true) {:ok, %Collection{records: [%Operation{body: %Payment{}}, ...]}} """ - @spec list_payments(account_id :: account_id(), options :: options()) :: response() - def list_payments(account_id, options \\ []) do - :get - |> Request.new(@endpoint, path: account_id, segment: "payments") + @spec list_payments(server :: server(), account_id :: account_id(), options :: options()) :: + response() + def list_payments(server, account_id, options \\ []) do + server + |> Request.new(:get, @endpoint, path: account_id, segment: "payments") |> Request.add_query(options, extra_params: [:include_failed, :join]) |> Request.perform() - |> Request.results(collection: {Operation, &list_payments(account_id, &1)}) + |> Request.results(collection: {Operation, &list_payments(server, account_id, &1)}) end @doc """ Lists the effects of a specific account. - ## Parameters + ## Parameters: + * `server`: The Horizon server to query. * `account_id`: The account’s public key encoded in a base32 string representation. ## Options @@ -215,22 +229,24 @@ defmodule Stellar.Horizon.Accounts do ## Examples - iex> Accounts.list_effects("GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", limit: 20) + iex> Accounts.list_effects(Stellar.Horizon.Server.testnet(), "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", limit: 20) {:ok, %Collection{records: [%Effect{}, ...]}} """ - @spec list_effects(account_id :: account_id(), options :: options()) :: response() - def list_effects(account_id, options \\ []) do - :get - |> Request.new(@endpoint, path: account_id, segment: "effects") + @spec list_effects(server :: server(), account_id :: account_id(), options :: options()) :: + response() + def list_effects(server, account_id, options \\ []) do + server + |> Request.new(:get, @endpoint, path: account_id, segment: "effects") |> Request.add_query(options) |> Request.perform() - |> Request.results(collection: {Effect, &list_effects(account_id, &1)}) + |> Request.results(collection: {Effect, &list_effects(server, account_id, &1)}) end @doc """ Lists all offers a given account has currently open. - ## Parameters + ## Parameters: + * `server`: The Horizon server to query. * `account_id`: The account’s public key encoded in a base32 string representation. ## Options @@ -240,22 +256,24 @@ defmodule Stellar.Horizon.Accounts do ## Examples - iex> Accounts.list_offers("GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", limit: 20) + iex> Accounts.list_offers(Stellar.Horizon.Server.testnet(), "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", limit: 20) {:ok, %Collection{records: [%Offer{}, ...]}} """ - @spec list_offers(account_id :: account_id(), options :: options()) :: response() - def list_offers(account_id, options \\ []) do - :get - |> Request.new(@endpoint, path: account_id, segment: "offers") + @spec list_offers(server :: server(), account_id :: account_id(), options :: options()) :: + response() + def list_offers(server, account_id, options \\ []) do + server + |> Request.new(:get, @endpoint, path: account_id, segment: "offers") |> Request.add_query(options) |> Request.perform() - |> Request.results(collection: {Offer, &list_offers(account_id, &1)}) + |> Request.results(collection: {Offer, &list_offers(server, account_id, &1)}) end @doc """ Lists all trades for a given account. - ## Parameters + ## Parameters: + * `server`: The Horizon server to query. * `account_id`: The account’s public key encoded in a base32 string representation. ## Options @@ -265,34 +283,36 @@ defmodule Stellar.Horizon.Accounts do ## Examples - iex> Accounts.list_trades("GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", limit: 20) + iex> Accounts.list_trades(Stellar.Horizon.Server.testnet(), "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", limit: 20) {:ok, %Collection{records: [%Trade{}, ...]}} """ - @spec list_trades(account_id :: account_id(), options :: options()) :: response() - def list_trades(account_id, options \\ []) do - :get - |> Request.new(@endpoint, path: account_id, segment: "trades") + @spec list_trades(server :: server(), account_id :: account_id(), options :: options()) :: + response() + def list_trades(server, account_id, options \\ []) do + server + |> Request.new(:get, @endpoint, path: account_id, segment: "trades") |> Request.add_query(options) |> Request.perform() - |> Request.results(collection: {Trade, &list_trades(account_id, &1)}) + |> Request.results(collection: {Trade, &list_trades(server, account_id, &1)}) end @doc """ Retrieves a single data for a given account. - ## Parameters + ## Parameters: + * `server`: The Horizon server to query. * `account_id`: The account’s public key encoded in a base32 string representation. * `key`: The key name for this data. ## Examples - iex> Accounts.data("GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", "config.memo_required") + iex> Accounts.data(Stellar.Horizon.Server.testnet(), "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", "config.memo_required") {:ok, %Account.Data{}} """ - @spec data(account_id :: account_id(), key :: String.t()) :: response() - def data(account_id, key) do - :get - |> Request.new(@endpoint, path: account_id, segment: "data", segment_path: key) + @spec data(server :: server(), account_id :: account_id(), key :: String.t()) :: response() + def data(server, account_id, key) do + server + |> Request.new(:get, @endpoint, path: account_id, segment: "data", segment_path: key) |> Request.perform() |> Request.results(as: Data) end diff --git a/lib/horizon/assets.ex b/lib/horizon/assets.ex index 7fd5082a..323f9186 100644 --- a/lib/horizon/assets.ex +++ b/lib/horizon/assets.ex @@ -10,8 +10,9 @@ defmodule Stellar.Horizon.Assets do Horizon API reference: https://developers.stellar.org/api/resources/assets/ """ - alias Stellar.Horizon.{Asset, Collection, Error, Request} + alias Stellar.Horizon.{Asset, Collection, Error, Request, Server} + @type server :: Server.t() @type asset_code :: String.t() @type asset_issuer :: String.t() @type options :: Keyword.t() @@ -23,6 +24,9 @@ defmodule Stellar.Horizon.Assets do @doc """ Lists all assets or by one of these filters: `asset_code` or `asset_issuer`. + ## Parameters + * `server`: The Horizon server to query. + ## Options * `asset_code`: The code of the asset you would like to filter by. @@ -33,31 +37,31 @@ defmodule Stellar.Horizon.Assets do ## Examples - iex> Assets.all(limit: 20, order: :desc) + iex> Assets.all(Stellar.Horizon.Server.testnet(), limit: 20, order: :desc) {:ok, %Collection{records: [%Asset{}, ...]}} # list by asset_code - iex> Assets.all(asset_code: "TEST") + iex> Assets.all(Stellar.Horizon.Server.testnet(), asset_code: "TEST") {:ok, %Collection{records: [%Asset{}, ...]}} # list by asset_issuer - iex> Assets.all(asset_issuer: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") + iex> Assets.all(Stellar.Horizon.Server.testnet(), asset_issuer: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") {:ok, %Collection{records: [%Asset{}, ...]}} """ - @spec all(options :: options()) :: response() - def all(options \\ []) do - :get - |> Request.new(@endpoint) + @spec all(server :: server(), options :: options()) :: response() + def all(server, options \\ []) do + server + |> Request.new(:get, @endpoint) |> Request.add_query(options, extra_params: [:asset_code, :asset_issuer]) |> Request.perform() - |> Request.results(collection: {Asset, &all/1}) + |> Request.results(collection: {Asset, &all(server, &1)}) end @doc """ Lists assets matching the given asset code. ## Parameters: - + * `server`: The Horizon server to query. * `asset_code`: The code of the asset you would like to filter by. ## Options @@ -68,14 +72,15 @@ defmodule Stellar.Horizon.Assets do ## Examples - iex> Assets.list_by_asset_code("TEST") + iex> Assets.list_by_asset_code(Stellar.Horizon.Server.testnet(), "TEST") {:ok, %Collection{records: [%Asset{asset_code: "TEST"}, ...]}} """ - @spec list_by_asset_code(asset_code :: asset_code(), options :: options()) :: response() - def list_by_asset_code(asset_code, options \\ []) do + @spec list_by_asset_code(server :: server(), asset_code :: asset_code(), options :: options()) :: + response() + def list_by_asset_code(server, asset_code, options \\ []) do options |> Keyword.put(:asset_code, asset_code) - |> all() + |> (&all(server, &1)).() end @doc """ @@ -83,6 +88,7 @@ defmodule Stellar.Horizon.Assets do ## Parameters: + * `server`: The Horizon server to query. * `asset_issuer`: The issuer's Account ID for the asset you would like to filter by. ## Options @@ -93,13 +99,17 @@ defmodule Stellar.Horizon.Assets do ## Examples - iex> Assets.list_by_asset_issuer("GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") + iex> Assets.list_by_asset_issuer(Stellar.Horizon.Server.testnet(), "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") {:ok, %Collection{records: [%Asset{asset_issuer: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD"}, ...]}} """ - @spec list_by_asset_issuer(asset_issuer :: asset_issuer(), options :: options()) :: response() - def list_by_asset_issuer(asset_issuer, options \\ []) do + @spec list_by_asset_issuer( + server :: server(), + asset_issuer :: asset_issuer(), + options :: options() + ) :: response() + def list_by_asset_issuer(server, asset_issuer, options \\ []) do options |> Keyword.put(:asset_issuer, asset_issuer) - |> all() + |> (&all(server, &1)).() end end diff --git a/lib/horizon/claimable_balances.ex b/lib/horizon/claimable_balances.ex index fea169cc..bd1d4f36 100644 --- a/lib/horizon/claimable_balances.ex +++ b/lib/horizon/claimable_balances.ex @@ -11,8 +11,17 @@ defmodule Stellar.Horizon.ClaimableBalances do Horizon API reference: https://developers.stellar.org/api/resources/claimablebalances/ """ - alias Stellar.Horizon.{ClaimableBalance, Collection, Error, Operation, Request, Transaction} - + alias Stellar.Horizon.{ + ClaimableBalance, + Collection, + Error, + Operation, + Request, + Transaction, + Server + } + + @type server :: Server.t() @type claimable_balance_id :: String.t() @type account_id :: String.t() @type asset :: String.t() @@ -26,17 +35,18 @@ defmodule Stellar.Horizon.ClaimableBalances do Retrieves information of a specific claimable balance. ## Parameters: + * `server`: The Horizon server to query. * `claimable_balance_id`: A unique identifier for the claimable balance. ## Examples - iex> ClaimableBalances.retrieve("00000000ca6aba5fb0993844e0076f75bee53f2b8014be29cd8f2e6ae19fb0a17fc68695") + iex> ClaimableBalances.retrieve(Stellar.Horizon.Server.testnet(), "00000000ca6aba5fb0993844e0076f75bee53f2b8014be29cd8f2e6ae19fb0a17fc68695") {:ok, %ClaimableBalance{}} """ - @spec retrieve(claimable_balance_id :: claimable_balance_id()) :: response() - def retrieve(claimable_balance_id) do - :get - |> Request.new(@endpoint, path: claimable_balance_id) + @spec retrieve(server :: server(), claimable_balance_id :: claimable_balance_id()) :: response() + def retrieve(server, claimable_balance_id) do + server + |> Request.new(:get, @endpoint, path: claimable_balance_id) |> Request.perform() |> Request.results(as: ClaimableBalance) end @@ -44,6 +54,9 @@ defmodule Stellar.Horizon.ClaimableBalances do @doc """ Lists all available claimable balances. + ## Parameters: + * `server`: The Horizon server to query. + ## Options * `sponsor`: Account ID of the sponsors. @@ -55,34 +68,35 @@ defmodule Stellar.Horizon.ClaimableBalances do ## Examples - iex> ClaimableBalances.all(limit: 2, order: :asc) + iex> ClaimableBalances.all(Stellar.Horizon.Server.testnet(), limit: 2, order: :asc) {:ok, %Collection{records: [%ClaimableBalance{}, ...]}} # list by sponsor - iex> ClaimableBalances.all(sponsor: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") + iex> ClaimableBalances.all(Stellar.Horizon.Server.testnet(), sponsor: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") {:ok, %Collection{records: [%ClaimableBalance{}, ...]}} # list by claimant - iex> ClaimableBalances.all(claimant: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", order: :desc) + iex> ClaimableBalances.all(Stellar.Horizon.Server.testnet(), claimant: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", order: :desc) {:ok, %Collection{records: [%ClaimableBalance{}, ...]}} # list by canonical asset address - iex> ClaimableBalances.all(asset: "TEST:GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", limit: 20) + iex> ClaimableBalances.all(Stellar.Horizon.Server.testnet(), asset: "TEST:GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", limit: 20) {:ok, %Collection{records: [%ClaimableBalance{}, ...]}} """ - @spec all(options :: options()) :: response() - def all(options \\ []) do - :get - |> Request.new(@endpoint) + @spec all(server :: server(), options :: options()) :: response() + def all(server, options \\ []) do + server + |> Request.new(:get, @endpoint) |> Request.add_query(options, extra_params: [:sponsor, :asset, :claimant]) |> Request.perform() - |> Request.results(collection: {ClaimableBalance, &all/1}) + |> Request.results(collection: {ClaimableBalance, &all(server, &1)}) end @doc """ Lists successful transactions referencing a given claimable balance. ## Parameters + * `server`: The Horizon server to query. * `claimable_balance_id`: A unique identifier for the claimable balance. ## Options @@ -93,23 +107,30 @@ defmodule Stellar.Horizon.ClaimableBalances do ## Examples - iex> ClaimableBalances.list_transactions("00000000ca6aba5fb0993844e0076f75bee53f2b8014be29cd8f2e6ae19fb0a17fc68695", limit: 20) + iex> ClaimableBalances.list_transactions(Stellar.Horizon.Server.testnet(), "00000000ca6aba5fb0993844e0076f75bee53f2b8014be29cd8f2e6ae19fb0a17fc68695", limit: 20) {:ok, %Collection{records: [%Transaction{}, ...]}} """ - @spec list_transactions(claimable_balance_id :: claimable_balance_id(), options :: options()) :: + @spec list_transactions( + server :: server(), + claimable_balance_id :: claimable_balance_id(), + options :: options() + ) :: response() - def list_transactions(claimable_balance_id, options \\ []) do - :get - |> Request.new(@endpoint, path: claimable_balance_id, segment: "transactions") + def list_transactions(server, claimable_balance_id, options \\ []) do + server + |> Request.new(:get, @endpoint, path: claimable_balance_id, segment: "transactions") |> Request.add_query(options, extra_params: [:include_failed]) |> Request.perform() - |> Request.results(collection: {Transaction, &list_transactions(claimable_balance_id, &1)}) + |> Request.results( + collection: {Transaction, &list_transactions(server, claimable_balance_id, &1)} + ) end @doc """ Lists successful operations referencing a given claimable balance. ## Parameters + * `server`: The Horizon server to query. * `claimable_balance_id`: A unique identifier for the claimable balance. ## Options @@ -121,28 +142,34 @@ defmodule Stellar.Horizon.ClaimableBalances do ## Examples - iex> ClaimableBalances.list_operations("00000000ca6aba5fb0993844e0076f75bee53f2b8014be29cd8f2e6ae19fb0a17fc68695", limit: 20) + iex> ClaimableBalances.list_operations(Stellar.Horizon.Server.testnet(), "00000000ca6aba5fb0993844e0076f75bee53f2b8014be29cd8f2e6ae19fb0a17fc68695", limit: 20) {:ok, %Collection{records: [%Operation{}, ...]}} # join transactions - iex> ClaimableBalances.list_operations("00000000ca6aba5fb0993844e0076f75bee53f2b8014be29cd8f2e6ae19fb0a17fc68695", join: "transactions") + iex> ClaimableBalances.list_operations(Stellar.Horizon.Server.testnet(), "00000000ca6aba5fb0993844e0076f75bee53f2b8014be29cd8f2e6ae19fb0a17fc68695", join: "transactions") {:ok, %Collection{records: [%Operation{transaction: %Transaction{}}, ...]}} """ - @spec list_operations(claimable_balance_id :: claimable_balance_id(), options :: options()) :: + @spec list_operations( + server :: server(), + claimable_balance_id :: claimable_balance_id(), + options :: options() + ) :: response() - def list_operations(claimable_balance_id, options \\ []) do - :get - |> Request.new(@endpoint, path: claimable_balance_id, segment: "operations") + def list_operations(server, claimable_balance_id, options \\ []) do + server + |> Request.new(:get, @endpoint, path: claimable_balance_id, segment: "operations") |> Request.add_query(options, extra_params: [:include_failed, :join]) |> Request.perform() - |> Request.results(collection: {Operation, &list_operations(claimable_balance_id, &1)}) + |> Request.results( + collection: {Operation, &list_operations(server, claimable_balance_id, &1)} + ) end @doc """ Lists claimable balances matching the given sponsor. ## Parameters: - + * `server`: The Horizon server to query. * `sponsor`: Account ID of the sponsor. ## Options @@ -153,21 +180,22 @@ defmodule Stellar.Horizon.ClaimableBalances do ## Examples - iex> ClaimableBalances.list_by_sponsor("GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") + iex> ClaimableBalances.list_by_sponsor(Stellar.Horizon.Server.testnet(), "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") {:ok, %Collection{records: [%ClaimableBalance{sponsor: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD"}, ...]}} """ - @spec list_by_sponsor(sponsor :: account_id(), options :: options()) :: response() - def list_by_sponsor(sponsor, options \\ []) do + @spec list_by_sponsor(server :: server(), sponsor :: account_id(), options :: options()) :: + response() + def list_by_sponsor(server, sponsor, options \\ []) do options |> Keyword.put(:sponsor, sponsor) - |> all() + |> (&all(server, &1)).() end @doc """ Lists claimable balances matching the given claimant. ## Parameters: - + * `server`: The Horizon server to query. * `claimant`: Account ID of the destination address. ## Options @@ -181,11 +209,12 @@ defmodule Stellar.Horizon.ClaimableBalances do iex> ClaimableBalances.list_by_claimant("GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") {:ok, %Collection{records: [%ClaimableBalance{claimant: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD"}, ...]}} """ - @spec list_by_claimant(claimant :: account_id(), options :: options()) :: response() - def list_by_claimant(claimant, options \\ []) do + @spec list_by_claimant(server :: server(), claimant :: account_id(), options :: options()) :: + response() + def list_by_claimant(server, claimant, options \\ []) do options |> Keyword.put(:claimant, claimant) - |> all() + |> (&all(server, &1)).() end @doc """ @@ -203,13 +232,13 @@ defmodule Stellar.Horizon.ClaimableBalances do ## Examples - iex> ClaimableBalances.list_by_asset("TEST:GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") + iex> ClaimableBalances.list_by_asset(Stellar.Horizon.Server.testnet(), "TEST:GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") {:ok, %Collection{records: [%ClaimableBalance{asset: "TEST:GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD"}, ...]}} """ - @spec list_by_asset(asset :: asset(), options :: options()) :: response() - def list_by_asset(asset, options \\ []) do + @spec list_by_asset(server :: server(), asset :: asset(), options :: options()) :: response() + def list_by_asset(server, asset, options \\ []) do options |> Keyword.put(:asset, asset) - |> all() + |> (&all(server, &1)).() end end diff --git a/lib/horizon/client.ex b/lib/horizon/client.ex index d954999c..22778295 100644 --- a/lib/horizon/client.ex +++ b/lib/horizon/client.ex @@ -7,8 +7,8 @@ defmodule Stellar.Horizon.Client do @behaviour Client.Spec @impl true - def request(method, path, headers \\ [], body \\ "", opts \\ []), - do: impl().request(method, path, headers, body, opts) + def request(server, method, path, headers \\ [], body \\ "", opts \\ []), + do: impl().request(server, method, path, headers, body, opts) @spec impl() :: atom() defp impl do diff --git a/lib/horizon/client/default.ex b/lib/horizon/client/default.ex index 9184c8b8..52d7456b 100644 --- a/lib/horizon/client/default.ex +++ b/lib/horizon/client/default.ex @@ -7,8 +7,7 @@ defmodule Stellar.Horizon.Client.Default do @behaviour Stellar.Horizon.Client.Spec - alias Stellar.Network - alias Stellar.Horizon.Error + alias Stellar.Horizon.{Error, Server} @type status :: pos_integer() @type headers :: [{binary(), binary()}, ...] @@ -19,8 +18,7 @@ defmodule Stellar.Horizon.Client.Default do @type parsed_response :: {:ok, map()} | {:error, Error.t()} @impl true - def request(method, path, headers \\ [], body \\ "", opts \\ []) do - base_url = Network.base_url() + def request(%Server{url: base_url}, method, path, headers \\ [], body \\ "", opts \\ []) do options = http_options(opts) method diff --git a/lib/horizon/client/spec.ex b/lib/horizon/client/spec.ex index 74f7eafc..a62ac20b 100644 --- a/lib/horizon/client/spec.ex +++ b/lib/horizon/client/spec.ex @@ -6,6 +6,7 @@ defmodule Stellar.Horizon.Client.Spec do The default is :hackney. """ + @type server :: Stellar.Horizon.Server.t() @type method :: :get | :post | :put | :delete @type headers :: [{binary(), binary()}, ...] @type body :: binary() @@ -16,6 +17,7 @@ defmodule Stellar.Horizon.Client.Spec do @type response_error :: {:error, any()} @callback request( + server :: server(), method :: method(), url :: binary(), body :: binary(), diff --git a/lib/horizon/effects.ex b/lib/horizon/effects.ex index a672cce9..71b942e0 100644 --- a/lib/horizon/effects.ex +++ b/lib/horizon/effects.ex @@ -8,8 +8,9 @@ defmodule Stellar.Horizon.Effects do Horizon API reference: https://developers.stellar.org/api/resources/effects/ """ - alias Stellar.Horizon.{Collection, Effect, Error, Request} + alias Stellar.Horizon.{Collection, Effect, Error, Request, Server} + @type server :: Server.t() @type options :: Keyword.t() @type resource :: Effect.t() | Collection.t() @type response :: {:ok, resource()} | {:error, Error.t()} @@ -19,6 +20,9 @@ defmodule Stellar.Horizon.Effects do @doc """ Lists all effects. + ## Parameters + * `server`: The Horizon server to query. + ## Options * `cursor`: A number that points to a specific location in a collection of responses and is pulled from the `paging_token` value of a record. @@ -27,15 +31,15 @@ defmodule Stellar.Horizon.Effects do ## Examples - iex> Effects.all(limit: 10, order: :asc) + iex> Effects.all(Stellar.Horizon.Server.testnet(), limit: 10, order: :asc) {:ok, %Collection{records: [%Effect{}, ...]}} """ - @spec all(options :: options()) :: response() - def all(options \\ []) do - :get - |> Request.new(@endpoint) + @spec all(server :: server(), options :: options()) :: response() + def all(server, options \\ []) do + server + |> Request.new(:get, @endpoint) |> Request.add_query(options) |> Request.perform() - |> Request.results(collection: {Effect, &all/1}) + |> Request.results(collection: {Effect, &all(server, &1)}) end end diff --git a/lib/horizon/fee_stats.ex b/lib/horizon/fee_stats.ex index 80bebdf0..2a9ae665 100644 --- a/lib/horizon/fee_stats.ex +++ b/lib/horizon/fee_stats.ex @@ -8,8 +8,9 @@ defmodule Stellar.Horizon.FeeStats do Horizon API reference: https://developers.stellar.org/api/aggregations/fee-stats/ """ - alias Stellar.Horizon.{Error, FeeStat, Request} + alias Stellar.Horizon.{Error, FeeStat, Request, Server} + @type server :: Server.t() @type resource :: FeeStat.t() @type response :: {:ok, resource()} | {:error, Error.t()} @@ -18,16 +19,19 @@ defmodule Stellar.Horizon.FeeStats do @doc """ Retrieves information of the fee stats. + ## Parameters + * `server`: The Horizon server to query. + ## Examples - iex> FeeStats.retrieve() + iex> FeeStats.retrieve(Stellar.Horizon.Server.testnet()) {:ok, %FeeStat{}} """ - @spec retrieve :: response() - def retrieve do - :get - |> Request.new(@endpoint) + @spec retrieve(server :: server()) :: response() + def retrieve(server) do + server + |> Request.new(:get, @endpoint) |> Request.perform() |> Request.results(as: FeeStat) end diff --git a/lib/horizon/ledgers.ex b/lib/horizon/ledgers.ex index a2ed882f..cb8c1eda 100644 --- a/lib/horizon/ledgers.ex +++ b/lib/horizon/ledgers.ex @@ -19,13 +19,15 @@ defmodule Stellar.Horizon.Ledgers do Ledger, Operation, Request, - Transaction + Transaction, + Server } @type sequence :: non_neg_integer() @type params :: Keyword.t() @type resource :: Ledger.t() | Collection.t() @type response :: {:ok, resource()} | {:error, Error.t()} + @type server :: Server.t() @endpoint "ledgers" @@ -33,17 +35,18 @@ defmodule Stellar.Horizon.Ledgers do Retrieves information of a specific ledger. ## Parameters: + * `server`: The Horizon server to query. * `sequence`: The sequence number of a specific ledger. ## Examples - iex> Ledgers.retrieve(27147222) + iex> Ledgers.retrieve(Stellar.Horizon.Server.testnet(), 27147222) {:ok, %Ledger{}} """ - @spec retrieve(sequence :: sequence()) :: response() - def retrieve(sequence) do - :get - |> Request.new(@endpoint, path: sequence) + @spec retrieve(server :: server(), sequence :: sequence()) :: response() + def retrieve(server, sequence) do + server + |> Request.new(:get, @endpoint, path: sequence) |> Request.perform() |> Request.results(as: Ledger) end @@ -51,6 +54,9 @@ defmodule Stellar.Horizon.Ledgers do @doc """ Lists all ledgers. + ## Parameters: + * `server`: The Horizon server to query. + ## Options * `cursor`: A number that points to a specific location in a collection of responses and is pulled from the `paging_token` value of a record. @@ -59,22 +65,23 @@ defmodule Stellar.Horizon.Ledgers do ## Examples - iex> Ledgers.all(limit: 10, order: :asc) + iex> Ledgers.all(Stellar.Horizon.Server.testnet(), limit: 10, order: :asc) {:ok, %Collection{records: [%Ledger{}, ...]}} """ - @spec all(params :: params()) :: response() - def all(params \\ []) do - :get - |> Request.new(@endpoint) + @spec all(server :: server(), params :: params()) :: response() + def all(server, params \\ []) do + server + |> Request.new(:get, @endpoint) |> Request.add_query(params) |> Request.perform() - |> Request.results(collection: {Ledger, &all/1}) + |> Request.results(collection: {Ledger, &all(server, &1)}) end @doc """ Lists successful transactions in a specific ledger. ## Parameters + * `server`: The Horizon server to query. * `sequence`: The sequence number of a specific ledger. ## Options @@ -85,22 +92,24 @@ defmodule Stellar.Horizon.Ledgers do ## Examples - iex> Ledgers.list_transactions(27147222, limit: 20) + iex> Ledgers.list_transactions(Stellar.Horizon.Server.testnet(), 27147222, limit: 20) {:ok, %Collection{records: [%Transaction{}, ...]}} """ - @spec list_transactions(sequence :: sequence(), params :: params()) :: response() - def list_transactions(sequence, params \\ []) do - :get - |> Request.new(@endpoint, path: sequence, segment: "transactions") + @spec list_transactions(server :: server(), sequence :: sequence(), params :: params()) :: + response() + def list_transactions(server, sequence, params \\ []) do + server + |> Request.new(:get, @endpoint, path: sequence, segment: "transactions") |> Request.add_query(params, extra_params: [:include_failed]) |> Request.perform() - |> Request.results(collection: {Transaction, &list_transactions(sequence, &1)}) + |> Request.results(collection: {Transaction, &list_transactions(server, sequence, &1)}) end @doc """ Lists successful operations in a specific ledger. ## Parameters + * `server`: The Horizon server to query. * `sequence`: The sequence number of a specific ledger. ## Options @@ -112,26 +121,28 @@ defmodule Stellar.Horizon.Ledgers do ## Examples - iex> Ledgers.list_operations(27147222, limit: 20) + iex> Ledgers.list_operations(Stellar.Horizon.Server.testnet(), 27147222, limit: 20) {:ok, %Collection{records: [%Operation{}, ...]}} # join transactions - iex> Ledgers.list_operations(27147222, join: "transactions") + iex> Ledgers.list_operations(Stellar.Horizon.Server.testnet(), 27147222, join: "transactions") {:ok, %Collection{records: [%Operation{transaction: %Transaction{}}, ...]}} """ - @spec list_operations(sequence :: sequence(), params :: params()) :: response() - def list_operations(sequence, params \\ []) do - :get - |> Request.new(@endpoint, path: sequence, segment: "operations") + @spec list_operations(server :: server(), sequence :: sequence(), params :: params()) :: + response() + def list_operations(server, sequence, params \\ []) do + server + |> Request.new(:get, @endpoint, path: sequence, segment: "operations") |> Request.add_query(params, extra_params: [:include_failed, :join]) |> Request.perform() - |> Request.results(collection: {Operation, &list_operations(sequence, &1)}) + |> Request.results(collection: {Operation, &list_operations(server, sequence, &1)}) end @doc """ Lists successful payments in a specific ledger. ## Parameters + * `server`: The Horizon server to query. * `sequence`: The sequence number of a specific ledger. ## Options @@ -143,26 +154,28 @@ defmodule Stellar.Horizon.Ledgers do ## Examples - iex> Ledgers.list_payments(27147222, limit: 20) + iex> Ledgers.list_payments(Stellar.Horizon.Server.testnet(), 27147222, limit: 20) {:ok, %Collection{records: [%Operation{body: %Payment{}}, ...]}} # include failed - iex> Ledgers.list_payments(27147222, include_failed: true) + iex> Ledgers.list_payments(Stellar.Horizon.Server.testnet(), 27147222, include_failed: true) {:ok, %Collection{records: [%Operation{body: %Payment{}}, ...]}} """ - @spec list_payments(sequence :: sequence(), params :: params()) :: response() - def list_payments(sequence, params \\ []) do - :get - |> Request.new(@endpoint, path: sequence, segment: "payments") + @spec list_payments(server :: server(), sequence :: sequence(), params :: params()) :: + response() + def list_payments(server, sequence, params \\ []) do + server + |> Request.new(:get, @endpoint, path: sequence, segment: "payments") |> Request.add_query(params, extra_params: [:include_failed, :join]) |> Request.perform() - |> Request.results(collection: {Operation, &list_payments(sequence, &1)}) + |> Request.results(collection: {Operation, &list_payments(server, sequence, &1)}) end @doc """ Lists the effects of a specific ledger. ## Parameters + * `server`: The Horizon server to query. * `sequence`: The sequence number of a specific ledger. ## Options @@ -172,15 +185,15 @@ defmodule Stellar.Horizon.Ledgers do ## Examples - iex> Ledgers.list_effects(27147222, limit: 20) + iex> Ledgers.list_effects(Stellar.Horizon.Server.testnet(), 27147222, limit: 20) {:ok, %Collection{records: [%Effect{}, ...]}} """ - @spec list_effects(sequence :: sequence(), params :: params()) :: response() - def list_effects(sequence, params \\ []) do - :get - |> Request.new(@endpoint, path: sequence, segment: "effects") + @spec list_effects(server :: server(), sequence :: sequence(), params :: params()) :: response() + def list_effects(server, sequence, params \\ []) do + server + |> Request.new(:get, @endpoint, path: sequence, segment: "effects") |> Request.add_query(params) |> Request.perform() - |> Request.results(collection: {Effect, &list_effects(sequence, &1)}) + |> Request.results(collection: {Effect, &list_effects(server, sequence, &1)}) end end diff --git a/lib/horizon/liquidity_pools.ex b/lib/horizon/liquidity_pools.ex index d6f32b9f..fff89115 100644 --- a/lib/horizon/liquidity_pools.ex +++ b/lib/horizon/liquidity_pools.ex @@ -20,10 +20,12 @@ defmodule Stellar.Horizon.LiquidityPools do LiquidityPool, Operation, Request, + Server, Trade, Transaction } + @type server :: Server.t() @type liquidity_pool_id :: String.t() @type options :: Keyword.t() @type resource :: LiquidityPool.t() | Collection.t() @@ -35,17 +37,18 @@ defmodule Stellar.Horizon.LiquidityPools do Retrieves information of a specific liquidity pool. ## Parameters: + * `server`: The Horizon server to query. * `liquidity_pool_id`: A liquidity pool’s id encoded in a hex string representation. ## Examples - iex> LiquidityPools.retrieve("001365fc79ca661f31ba3ee0849ae4ba36f5c377243242d37fad5b1bb8912dbc") + iex> LiquidityPools.retrieve(Stellar.Horizon.Server.testnet(), "001365fc79ca661f31ba3ee0849ae4ba36f5c377243242d37fad5b1bb8912dbc") {:ok, %LiquidityPool{}} """ - @spec retrieve(liquidity_pool_id :: liquidity_pool_id()) :: response() - def retrieve(liquidity_pool_id) do - :get - |> Request.new(@endpoint, path: liquidity_pool_id) + @spec retrieve(server :: server(), liquidity_pool_id :: liquidity_pool_id()) :: response() + def retrieve(server, liquidity_pool_id) do + server + |> Request.new(:get, @endpoint, path: liquidity_pool_id) |> Request.perform() |> Request.results(as: LiquidityPool) end @@ -53,6 +56,9 @@ defmodule Stellar.Horizon.LiquidityPools do @doc """ Lists all available claimable balances. + ## Parameters: + * `server`: The Horizon server to query. + ## Options * `reserves`: Comma-separated list of assets in canonical form “Code:IssuerAccountID”. @@ -63,30 +69,31 @@ defmodule Stellar.Horizon.LiquidityPools do ## Examples - iex> LiquidityPools.all(limit: 2, order: :asc) + iex> LiquidityPools.all(Stellar.Horizon.Server.testnet(), limit: 2, order: :asc) {:ok, %Collection{records: [%LiquidityPool{}, ...]}} # list by reserves - iex> LiquidityPools.all(reserves: "TEST:GCXMW..., TEST2:GCXMW...") + iex> LiquidityPools.all(Stellar.Horizon.Server.testnet(), reserves: "TEST:GCXMW..., TEST2:GCXMW...") {:ok, %Collection{records: [%LiquidityPool{}, ...]}} # list by account - iex> LiquidityPools.all(account: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", order: :desc) + iex> LiquidityPools.all(Stellar.Horizon.Server.testnet(), account: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", order: :desc) {:ok, %Collection{records: [%LiquidityPool{}, ...]}} """ - @spec all(options :: options()) :: response() - def all(options \\ []) do - :get - |> Request.new(@endpoint) + @spec all(server :: server(), options :: options()) :: response() + def all(server, options \\ []) do + server + |> Request.new(:get, @endpoint) |> Request.add_query(options, extra_options: [:reserves, :account]) |> Request.perform() - |> Request.results(collection: {LiquidityPool, &all/1}) + |> Request.results(collection: {LiquidityPool, &all(server, &1)}) end @doc """ Lists the effects of a specific liquidity pool. ## Parameters + * `server`: The Horizon server to query. * `liquidity_pool_id`: A liquidity pool’s id encoded in a hex string representation. ## Options @@ -96,22 +103,27 @@ defmodule Stellar.Horizon.LiquidityPools do ## Examples - iex> LiquidityPools.list_effects("001365fc79ca661f31ba3ee0849ae4ba36f5c377243242d37fad5b1bb8912dbc", limit: 20) + iex> LiquidityPools.list_effects(Stellar.Horizon.Server.testnet(), "001365fc79ca661f31ba3ee0849ae4ba36f5c377243242d37fad5b1bb8912dbc", limit: 20) {:ok, %Collection{records: [%Effect{}, ...]}} """ - @spec list_effects(liquidity_pool_id :: liquidity_pool_id(), options :: options()) :: response() - def list_effects(liquidity_pool_id, options \\ []) do - :get - |> Request.new(@endpoint, path: liquidity_pool_id, segment: "effects") + @spec list_effects( + server :: server(), + liquidity_pool_id :: liquidity_pool_id(), + options :: options() + ) :: response() + def list_effects(server, liquidity_pool_id, options \\ []) do + server + |> Request.new(:get, @endpoint, path: liquidity_pool_id, segment: "effects") |> Request.add_query(options) |> Request.perform() - |> Request.results(collection: {Effect, &list_effects(liquidity_pool_id, &1)}) + |> Request.results(collection: {Effect, &list_effects(server, liquidity_pool_id, &1)}) end @doc """ Lists the successful trades fulfilled by the given liquidity pool. ## Parameters + * `server`: The Horizon server to query. * `liquidity_pool_id`: A liquidity pool’s id encoded in a hex string representation. ## Options @@ -121,22 +133,27 @@ defmodule Stellar.Horizon.LiquidityPools do ## Examples - iex> LiquidityPools.list_trades("001365fc79ca661f31ba3ee0849ae4ba36f5c377243242d37fad5b1bb8912dbc", limit: 20) + iex> LiquidityPools.list_trades(Stellar.Horizon.Server.testnet(), "001365fc79ca661f31ba3ee0849ae4ba36f5c377243242d37fad5b1bb8912dbc", limit: 20) {:ok, %Collection{records: [%Trade{}, ...]}} """ - @spec list_trades(liquidity_pool_id :: liquidity_pool_id(), options :: options()) :: response() - def list_trades(liquidity_pool_id, options \\ []) do - :get - |> Request.new(@endpoint, path: liquidity_pool_id, segment: "trades") + @spec list_trades( + server :: server(), + liquidity_pool_id :: liquidity_pool_id(), + options :: options() + ) :: response() + def list_trades(server, liquidity_pool_id, options \\ []) do + server + |> Request.new(:get, @endpoint, path: liquidity_pool_id, segment: "trades") |> Request.add_query(options) |> Request.perform() - |> Request.results(collection: {Trade, &list_trades(liquidity_pool_id, &1)}) + |> Request.results(collection: {Trade, &list_trades(server, liquidity_pool_id, &1)}) end @doc """ Lists successful transactions referencing a given liquidity pool. ## Parameters + * `server`: The Horizon server to query. * `liquidity_pool_id`: A liquidity pool’s id encoded in a hex string representation. ## Options @@ -147,23 +164,30 @@ defmodule Stellar.Horizon.LiquidityPools do ## Examples - iex> LiquidityPools.list_transactions("001365fc79ca661f31ba3ee0849ae4ba36f5c377243242d37fad5b1bb8912dbc", limit: 20) + iex> LiquidityPools.list_transactions(Stellar.Horizon.Server.testnet(), "001365fc79ca661f31ba3ee0849ae4ba36f5c377243242d37fad5b1bb8912dbc", limit: 20) {:ok, %Collection{records: [%Transaction{}, ...]}} """ - @spec list_transactions(liquidity_pool_id :: liquidity_pool_id(), options :: options()) :: + @spec list_transactions( + server :: server(), + liquidity_pool_id :: liquidity_pool_id(), + options :: options() + ) :: response() - def list_transactions(liquidity_pool_id, options \\ []) do - :get - |> Request.new(@endpoint, path: liquidity_pool_id, segment: "transactions") + def list_transactions(server, liquidity_pool_id, options \\ []) do + server + |> Request.new(:get, @endpoint, path: liquidity_pool_id, segment: "transactions") |> Request.add_query(options, extra_options: [:include_failed]) |> Request.perform() - |> Request.results(collection: {Transaction, &list_transactions(liquidity_pool_id, &1)}) + |> Request.results( + collection: {Transaction, &list_transactions(server, liquidity_pool_id, &1)} + ) end @doc """ Lists successful operations referencing a given liquidity pool. ## Parameters + * `server`: The Horizon server to query. * `liquidity_pool_id`: A liquidity pool’s id encoded in a hex string representation. ## Options @@ -175,20 +199,24 @@ defmodule Stellar.Horizon.LiquidityPools do ## Examples - iex> LiquidityPools.list_operations("001365fc79ca661f31ba3ee0849ae4ba36f5c377243242d37fad5b1bb8912dbc", limit: 20) + iex> LiquidityPools.list_operations(Stellar.Horizon.Server.testnet(), "001365fc79ca661f31ba3ee0849ae4ba36f5c377243242d37fad5b1bb8912dbc", limit: 20) {:ok, %Collection{records: [%Operation{}, ...]}} # join transactions - iex> LiquidityPools.list_operations("001365fc79ca661f31ba3ee0849ae4ba36f5c377243242d37fad5b1bb8912dbc", join: "transactions") + iex> LiquidityPools.list_operations(Stellar.Horizon.Server.testnet(), "001365fc79ca661f31ba3ee0849ae4ba36f5c377243242d37fad5b1bb8912dbc", join: "transactions") {:ok, %Collection{records: [%Operation{transaction: %Transaction{}}, ...]}} """ - @spec list_operations(liquidity_pool_id :: liquidity_pool_id(), options :: options()) :: + @spec list_operations( + server :: server(), + liquidity_pool_id :: liquidity_pool_id(), + options :: options() + ) :: response() - def list_operations(liquidity_pool_id, options \\ []) do - :get - |> Request.new(@endpoint, path: liquidity_pool_id, segment: "operations") + def list_operations(server, liquidity_pool_id, options \\ []) do + server + |> Request.new(:get, @endpoint, path: liquidity_pool_id, segment: "operations") |> Request.add_query(options, extra_options: [:include_failed, :join]) |> Request.perform() - |> Request.results(collection: {Operation, &list_operations(liquidity_pool_id, &1)}) + |> Request.results(collection: {Operation, &list_operations(server, liquidity_pool_id, &1)}) end end diff --git a/lib/horizon/offers.ex b/lib/horizon/offers.ex index b6c42cd7..0edbd548 100644 --- a/lib/horizon/offers.ex +++ b/lib/horizon/offers.ex @@ -10,8 +10,9 @@ defmodule Stellar.Horizon.Offers do Horizon API reference: https://developers.stellar.org/api/resources/offers/ """ - alias Stellar.Horizon.{Collection, Error, Offer, Request, Trade, RequestParams} + alias Stellar.Horizon.{Collection, Error, Offer, Request, Trade, RequestParams, Server} + @type server :: Server.t() @type offer_id :: String.t() @type options :: Keyword.t() @type resource :: Offer.t() | Collection.t() @@ -23,17 +24,18 @@ defmodule Stellar.Horizon.Offers do Retrieves information of a specific offer. ## Parameters: + * `server`: The Horizon server to query. * `offer_id`: The unique identifier for the offer. ## Examples - iex> Offers.retrieve(165563085) + iex> Offers.retrieve(Stellar.Horizon.Server.testnet(), 165563085) {:ok, %Offer{}} """ - @spec retrieve(offer_id :: offer_id()) :: response() - def retrieve(offer_id) do - :get - |> Request.new(@endpoint, path: offer_id) + @spec retrieve(server :: server(), offer_id :: offer_id()) :: response() + def retrieve(server, offer_id) do + server + |> Request.new(:get, @endpoint, path: offer_id) |> Request.perform() |> Request.results(as: Offer) end @@ -41,6 +43,9 @@ defmodule Stellar.Horizon.Offers do @doc """ Lists all currently open offers. + ## Parameters: + * `server`: The Horizon server to query. + ## Options * `sponsor`: The account ID of the sponsor who is paying the reserves for all the offers included in the response. @@ -53,19 +58,20 @@ defmodule Stellar.Horizon.Offers do ## Examples - iex> Offers.all(limit: 20, order: :asc) + iex> Offers.all(Stellar.Horizon.Server.testnet(), limit: 20, order: :asc) {:ok, %Collection{records: [%Offer{}, ...]}} # list by sponsor - iex> Offers.all(sponsor: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") + iex> Offers.all(Stellar.Horizon.Server.testnet(), sponsor: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD") {:ok, %Collection{records: [%Offer{}, ...]}} # list by seller - iex> Offers.all(seller: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", order: :desc) + iex> Offers.all(Stellar.Horizon.Server.testnet(), seller: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD", order: :desc) {:ok, %Collection{records: [%Offer{}, ...]}} # list by selling_asset iex> Offers.all( + Stellar.Horizon.Server.testnet(), selling_asset: [ code: "TEST", issuer: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD" @@ -76,6 +82,7 @@ defmodule Stellar.Horizon.Offers do # list by buying_asset iex> Offers.all( + Stellar.Horizon.Server.testnet(), buying_asset: [ code: "TEST", issuer: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD" @@ -84,8 +91,8 @@ defmodule Stellar.Horizon.Offers do ) {:ok, %Collection{records: [%Offer{}, ...]}} """ - @spec all(options :: options()) :: response() - def all(options \\ []) do + @spec all(server :: server(), options :: options()) :: response() + def all(server, options \\ []) do selling_asset = RequestParams.build_assets_params(options, :selling_asset) buying_asset = RequestParams.build_assets_params(options, :buying_asset) @@ -94,17 +101,18 @@ defmodule Stellar.Horizon.Offers do |> Keyword.merge(selling_asset) |> Keyword.merge(buying_asset) - :get - |> Request.new(@endpoint) + server + |> Request.new(:get, @endpoint) |> Request.add_query(params, extra_params: allowed_query_options()) |> Request.perform() - |> Request.results(collection: {Offer, &all/1}) + |> Request.results(collection: {Offer, &all(server, &1)}) end @doc """ Lists all trades for a given offer. ## Parameters + * `server`: The Horizon server to query. * `offer_id`: The unique identifier for the offer. ## Options @@ -114,16 +122,17 @@ defmodule Stellar.Horizon.Offers do ## Examples - iex> Offers.list_trades(165563085, limit: 20) + iex> Offers.list_trades(Stellar.Horizon.Server.testnet(), 165563085, limit: 20) {:ok, %Collection{records: [%Trade{}, ...]}} """ - @spec list_trades(offer_id :: offer_id(), options :: options()) :: response() - def list_trades(offer_id, options \\ []) do - :get - |> Request.new(@endpoint, path: offer_id, segment: "trades") + @spec list_trades(server :: server(), offer_id :: offer_id(), options :: options()) :: + response() + def list_trades(server, offer_id, options \\ []) do + server + |> Request.new(:get, @endpoint, path: offer_id, segment: "trades") |> Request.add_query(options) |> Request.perform() - |> Request.results(collection: {Trade, &list_trades(offer_id, &1)}) + |> Request.results(collection: {Trade, &list_trades(server, offer_id, &1)}) end @spec allowed_query_options() :: list() diff --git a/lib/horizon/operations.ex b/lib/horizon/operations.ex index 40e0444e..a2d95466 100644 --- a/lib/horizon/operations.ex +++ b/lib/horizon/operations.ex @@ -11,12 +11,13 @@ defmodule Stellar.Horizon.Operations do Horizon API reference: https://developers.stellar.org/api/resources/operations/ """ - alias Stellar.Horizon.{Collection, Effect, Error, Operation, Request} + alias Stellar.Horizon.{Collection, Effect, Error, Operation, Request, Server} @type operation_id :: String.t() @type options :: Keyword.t() @type resource :: Operation.t() | Collection.t() @type response :: {:ok, resource()} | {:error, Error.t()} + @type server :: Server.t() @endpoint "operations" @payments_endpoint "payments" @@ -25,17 +26,19 @@ defmodule Stellar.Horizon.Operations do Retrieves information of a specific operation. ## Parameters: + * `server`: The Horizon server to query. * `operation_id`: The ID number for the operation. ## Examples - iex> Operations.retrieve(121693057904021505) + iex> Operations.retrieve(Stellar.Horizon.Server.testnet(), 121693057904021505) {:ok, %Operation{}} """ - @spec retrieve(operation_id :: operation_id(), options :: options()) :: response() - def retrieve(operation_id, options \\ []) do - :get - |> Request.new(@endpoint, path: operation_id) + @spec retrieve(server :: server(), operation_id :: operation_id(), options :: options()) :: + response() + def retrieve(server, operation_id, options \\ []) do + server + |> Request.new(:get, @endpoint, path: operation_id) |> Request.add_query(options, extra_params: [:join]) |> Request.perform() |> Request.results(as: Operation) @@ -44,6 +47,9 @@ defmodule Stellar.Horizon.Operations do @doc """ Lists all successful operations. + ## Parameters: + * `server`: The Horizon server to query. + ## Options * `cursor`: A number that points to a specific location in a collection of responses and is pulled from the `paging_token` value of a record. @@ -54,29 +60,32 @@ defmodule Stellar.Horizon.Operations do ## Examples - iex> Operations.all(limit: 10, order: :asc) + iex> Operations.all(Stellar.Horizon.Server.testnet(), limit: 10, order: :asc) {:ok, %Collection{records: [%Operation{}, ...]}} # include failed - iex> Operations.all(limit: 10, include_failed: true) + iex> Operations.all(Stellar.Horizon.Server.testnet(), limit: 10, include_failed: true) {:ok, %Collection{records: [%Operation{}, ...]}} # join transactions - iex> Operations.all(limit: 10, join: "transactions") + iex> Operations.all(Stellar.Horizon.Server.testnet(), limit: 10, join: "transactions") {:ok, %Collection{records: [%Operation{transaction: %Transaction{}}, ...]}} """ - @spec all(options :: options()) :: response() - def all(options \\ []) do - :get - |> Request.new(@endpoint) + @spec all(server :: server(), options :: options()) :: response() + def all(server, options \\ []) do + server + |> Request.new(:get, @endpoint) |> Request.add_query(options, extra_params: [:include_failed, :join]) |> Request.perform() - |> Request.results(collection: {Operation, &all/1}) + |> Request.results(collection: {Operation, &all(server, &1)}) end @doc """ Lists successful payment-related operations. + ## Parameters + * `server`: The Horizon server to query. + ## Options * `cursor`: A number that points to a specific location in a collection of responses and is pulled from the `paging_token` value of a record. * `order`: A designation of the order in which records should appear. Options include `asc` (ascending) or `desc` (descending). @@ -86,22 +95,23 @@ defmodule Stellar.Horizon.Operations do ## Examples - iex> Operations.list_payments(limit: 20) + iex> Operations.list_payments(Stellar.Horizon.Server.testnet(), limit: 20) {:ok, %Collection{records: [%Operation{body: %Payment{}}, ...]}} """ - @spec list_payments(options :: options()) :: response() - def list_payments(options \\ []) do - :get - |> Request.new(@payments_endpoint) + @spec list_payments(server :: server(), options :: options()) :: response() + def list_payments(server, options \\ []) do + server + |> Request.new(:get, @payments_endpoint) |> Request.add_query(options, extra_params: [:include_failed, :join]) |> Request.perform() - |> Request.results(collection: {Operation, &list_payments/1}) + |> Request.results(collection: {Operation, &list_payments(server, &1)}) end @doc """ Lists the effects of a specific operation. ## Parameters + * `server`: The Horizon server to query. * `operation_id`: The ID number for the operation. ## Options @@ -111,15 +121,16 @@ defmodule Stellar.Horizon.Operations do ## Examples - iex> Operations.list_effects(121693057904021505, limit: 20) + iex> Operations.list_effects(Stellar.Horizon.Server.testnet(), 121693057904021505, limit: 20) {:ok, %Collection{records: [%Effect{}, ...]}} """ - @spec list_effects(operation_id :: operation_id(), options :: options()) :: response() - def list_effects(operation_id, options \\ []) do - :get - |> Request.new(@endpoint, path: operation_id, segment: "effects") + @spec list_effects(server :: server(), operation_id :: operation_id(), options :: options()) :: + response() + def list_effects(server, operation_id, options \\ []) do + server + |> Request.new(:get, @endpoint, path: operation_id, segment: "effects") |> Request.add_query(options) |> Request.perform() - |> Request.results(collection: {Effect, &list_effects(operation_id, &1)}) + |> Request.results(collection: {Effect, &list_effects(server, operation_id, &1)}) end end diff --git a/lib/horizon/order_books.ex b/lib/horizon/order_books.ex index d2ccdb35..36441b4d 100644 --- a/lib/horizon/order_books.ex +++ b/lib/horizon/order_books.ex @@ -8,8 +8,9 @@ defmodule Stellar.Horizon.OrderBooks do Horizon API reference: https://developers.stellar.org/api/aggregations/order-books/object/ """ - alias Stellar.Horizon.{Error, OrderBook, Request, RequestParams} + alias Stellar.Horizon.{Error, OrderBook, Request, RequestParams, Server} + @type server :: Server.t() @type args :: Keyword.t() @type resource :: OrderBook.t() @type response :: {:ok, resource()} | {:error, Error.t()} @@ -20,6 +21,7 @@ defmodule Stellar.Horizon.OrderBooks do Retrieve order books ## Parameters + * `server`: The Horizon server to query. * `selling_asset`: `:native` or `[code: "selling_asset_code", issuer: "selling_asset_issuer"]` * `buying_asset`: `:native` or `[code: "buying_asset_code", issuer: "buying_asset_issuer"]` @@ -29,22 +31,25 @@ defmodule Stellar.Horizon.OrderBooks do ## Examples # Retrieve order books - iex> OrderBooks.retrieve(selling_asset: :native, buying_asset: :native) + iex> OrderBooks.retrieve(Stellar.Horizon.Server.testnet(), selling_asset: :native, buying_asset: :native) {:ok, %OrderBook{bids: [%Price{}...], asks: [%Price{}...], ...} # Retrieve with more options - iex> OrderBooks.retrieve(selling_asset: :native, - buying_asset: [ - code: "BB1", - issuer: "GD5J6HLF5666X4AZLTFTXLY46J5SW7EXRKBLEYPJP33S33MXZGV6CWFN" - ], - limit: 2 - ) + iex> OrderBooks.retrieve( + Stellar.Horizon.Server.testnet(), + selling_asset: :native, + buying_asset: [ + code: "BB1", + issuer: "GD5J6HLF5666X4AZLTFTXLY46J5SW7EXRKBLEYPJP33S33MXZGV6CWFN" + ], + limit: 2 + ) + ) {:ok, %OrderBook{bids: [%Price{}...], asks: [%Price{}...], ...} """ - @spec retrieve(args :: args()) :: response() - def retrieve(args \\ []) do + @spec retrieve(server :: server(), args :: args()) :: response() + def retrieve(server, args \\ []) do selling_asset = RequestParams.build_assets_params(args, :selling_asset) buying_asset = RequestParams.build_assets_params(args, :buying_asset) @@ -54,8 +59,8 @@ defmodule Stellar.Horizon.OrderBooks do |> Keyword.merge(selling_asset) |> Keyword.merge(buying_asset) - :get - |> Request.new(@endpoint) + server + |> Request.new(:get, @endpoint) |> Request.add_query(params, extra_params: allowed_query_options()) |> Request.perform() |> Request.results(as: OrderBook) diff --git a/lib/horizon/payment_paths.ex b/lib/horizon/payment_paths.ex index 0f16b4a2..4c87c3ca 100644 --- a/lib/horizon/payment_paths.ex +++ b/lib/horizon/payment_paths.ex @@ -9,8 +9,9 @@ defmodule Stellar.Horizon.PaymentPaths do Horizon API reference: https://developers.stellar.org/api/aggregations/paths/ """ - alias Stellar.Horizon.{Error, Paths, Request, RequestParams} + alias Stellar.Horizon.{Error, Paths, Request, RequestParams, Server} + @type server :: Server.t() @type args :: Keyword.t() @type opt :: atom() @type path :: String.t() @@ -24,6 +25,7 @@ defmodule Stellar.Horizon.PaymentPaths do ## Parameters + * `server`: The Horizon server to query. * `source_account`: The Stellar address of the sender. * `destination_asset`: `:native` or `[code: "destination_asset_code", issuer: "destination_asset_issuer"]` * `destination_amount`: The amount of the destination asset that should be received. @@ -34,34 +36,39 @@ defmodule Stellar.Horizon.PaymentPaths do ## Examples - iex> PaymentPaths.list_paths(source_account: "GBRSLTT74SKP62KJ7ENTMP5V4R7UGB6E5UQESNIIRWUNRCCUO4ZMFM4C", - destination_asset: :native, - destination_amount: 5 - ) + iex> PaymentPaths.list_paths( + Stellar.Horizon.Server.testnet(), + source_account: "GBRSLTT74SKP62KJ7ENTMP5V4R7UGB6E5UQESNIIRWUNRCCUO4ZMFM4C", + destination_asset: :native, + destination_amount: 5 + ) {:ok, %Paths{records: [%Path{}, ...]}} # list with `destination_account` - iex> PaymentPaths.list_paths(source_account: "GBRSLTT74SKP62KJ7ENTMP5V4R7UGB6E5UQESNIIRWUNRCCUO4ZMFM4C", - destination_asset: :native, - destination_amount: 5, - destination_account: "GBRSLTT74SKP62KJ7ENTMP5V4R7UGB6E5UQESNIIRWUNRCCUO4ZMFM4C" - ) + iex> PaymentPaths.list_paths(Stellar.Horizon.Server.testnet(), + source_account: "GBRSLTT74SKP62KJ7ENTMP5V4R7UGB6E5UQESNIIRWUNRCCUO4ZMFM4C", + destination_asset: :native, + destination_amount: 5, + destination_account: "GBRSLTT74SKP62KJ7ENTMP5V4R7UGB6E5UQESNIIRWUNRCCUO4ZMFM4C" + ) {:ok, %Paths{records: [%Path{}, ...]}} # list with more options - iex> PaymentPaths.list_paths(source_account: "GBRSLTT74SKP62KJ7ENTMP5V4R7UGB6E5UQESNIIRWUNRCCUO4ZMFM4C", - destination_asset: [ - code: "TEST", - issuer: "GA654JC6QLA3ZH4O5V7X5NPM7KEWHKRG5GJA4PETK4SOFBUJLCCN74KQ" - ], - destination_amount: 5, - destination_account: "GBRSLTT74SKP62KJ7ENTMP5V4R7UGB6E5UQESNIIRWUNRCCUO4ZMFM4C" - ) + iex> PaymentPaths.list_paths( + Stellar.Horizon.Server.testnet(), + source_account: "GBRSLTT74SKP62KJ7ENTMP5V4R7UGB6E5UQESNIIRWUNRCCUO4ZMFM4C", + destination_asset: [ + code: "TEST", + issuer: "GA654JC6QLA3ZH4O5V7X5NPM7KEWHKRG5GJA4PETK4SOFBUJLCCN74KQ" + ], + destination_amount: 5, + destination_account: "GBRSLTT74SKP62KJ7ENTMP5V4R7UGB6E5UQESNIIRWUNRCCUO4ZMFM4C" + ) {:ok, %Paths{records: [%Path{}, ...]}} """ - @spec list_paths(args :: args()) :: response() - def list_paths(args \\ []) do + @spec list_paths(server :: server(), args :: args()) :: response() + def list_paths(server, args \\ []) do destination_asset = RequestParams.build_assets_params(args, :destination_asset) params = @@ -69,8 +76,8 @@ defmodule Stellar.Horizon.PaymentPaths do |> Keyword.delete(:destination_asset) |> Keyword.merge(destination_asset) - :get - |> Request.new(@endpoint) + server + |> Request.new(:get, @endpoint) |> Request.add_query(params, extra_params: allowed_query_options(:list_paths)) |> Request.perform() |> Request.results(as: Paths) @@ -81,6 +88,8 @@ defmodule Stellar.Horizon.PaymentPaths do ## Parameters + * `server`: The Horizon server to query. + Using either `source_account` or `source_assets` as an argument is required for strict receive path payments. * `destination_asset`: `:native` or `[code: "destination_asset_code", issuer: "destination_asset_issuer"]` * `destination_amount`: The amount of the destination asset that should be received. @@ -93,33 +102,39 @@ defmodule Stellar.Horizon.PaymentPaths do ## Examples # list with `source_account` - iex> PaymentPaths.list_receive_paths(destination_asset: :native, - destination_amount: 5, - source_account: "GBTKSXOTFMC5HR25SNL76MOVQW7GA3F6CQEY622ASLUV4VMLITI6TCOO" - ) + iex> PaymentPaths.list_receive_paths( + Stellar.Horizon.Server.testnet(), + destination_asset: :native, + destination_amount: 5, + source_account: "GBTKSXOTFMC5HR25SNL76MOVQW7GA3F6CQEY622ASLUV4VMLITI6TCOO" + ) {:ok, %Paths{records: [%Path{}, ...]}} # list with `source_assets` - iex> PaymentPaths.list_receive_paths(destination_asset: :native, - destination_amount: 5, - source_assets: :native - ) + iex> PaymentPaths.list_receive_paths( + Stellar.Horizon.Server.testnet(), + destination_asset: :native, + destination_amount: 5, + source_assets: :native + ) {:ok, %Paths{records: [%Path{}, ...]}} # list with more options - iex> PaymentPaths.list_receive_paths(source_assets: "CNY:GAREELUB43IRHWEASCFBLKHURCGMHE5IF6XSE7EXDLACYHGRHM43RFOX", - destination_asset: [ - code: "BB1", - issuer: "GD5J6HLF5666X4AZLTFTXLY46J5SW7EXRKBLEYPJP33S33MXZGV6CWFN" - ], - destination_amount: 5 - ) + iex> PaymentPaths.list_receive_paths( + Stellar.Horizon.Server.testnet(), + source_assets: "CNY:GAREELUB43IRHWEASCFBLKHURCGMHE5IF6XSE7EXDLACYHGRHM43RFOX", + destination_asset: [ + code: "BB1", + issuer: "GD5J6HLF5666X4AZLTFTXLY46J5SW7EXRKBLEYPJP33S33MXZGV6CWFN" + ], + destination_amount: 5 + ) {:ok, %Paths{records: [%Path{}, ...]}} """ - @spec list_receive_paths(args :: args()) :: response() - def list_receive_paths(args \\ []) do + @spec list_receive_paths(server :: server(), args :: args()) :: response() + def list_receive_paths(server, args \\ []) do destination_asset = RequestParams.build_assets_params(args, :destination_asset) params = @@ -127,8 +142,8 @@ defmodule Stellar.Horizon.PaymentPaths do |> Keyword.delete(:destination_asset) |> Keyword.merge(destination_asset) - :get - |> Request.new(@endpoint, path: "strict-receive") + server + |> Request.new(:get, @endpoint, path: "strict-receive") |> Request.add_query(params, extra_params: allowed_query_options(:list_receive)) |> Request.perform() |> Request.results(as: Paths) @@ -138,43 +153,53 @@ defmodule Stellar.Horizon.PaymentPaths do List Strict Send Payment Paths ## Parameters - Using either `destination_account` or `destination_assets` as an argument is required for strict send path payments. - * `source_asset`: `:native` or `[code: "source_asset_code", issuer: "source_asset_issuer"]` - * `source_amount`: The amount of the source asset that should be sent. + + * `server`: The Horizon server to query. + + Using either `destination_account` or `destination_assets` as an argument is required for strict send path payments. + * `source_asset`: `:native` or `[code: "source_asset_code", issuer: "source_asset_issuer"]` + * `source_amount`: The amount of the source asset that should be sent. ## Options - * `destination_account`: The Stellar address of the reciever. - * `destination_assets`: A comma-separated list of assets that the recipient can receive. + + * `destination_account`: The Stellar address of the reciever. + * `destination_assets`: A comma-separated list of assets that the recipient can receive. ## Examples * list with `destination_account` - iex> PaymentPaths.list_send_paths(source_asset: :native, - source_amount: 5, - destination_account: "GBTKSXOTFMC5HR25SNL76MOVQW7GA3F6CQEY622ASLUV4VMLITI6TCOO" - ) + iex> PaymentPaths.list_send_paths( + Stellar.Horizon.Server.testnet(), + source_asset: :native, + source_amount: 5, + destination_account: "GBTKSXOTFMC5HR25SNL76MOVQW7GA3F6CQEY622ASLUV4VMLITI6TCOO" + ) {:ok, %Paths{records: [%Path{}, ...]}} * list with `destination_assets` - iex> PaymentPaths.list_send_paths(source_asset: :native, - source_amount: 5, - destination_assets: "TEST:GA654JC6QLA3ZH4O5V7X5NPM7KEWHKRG5GJA4PETK4SOFBUJLCCN74KQ" - ) + iex> PaymentPaths.list_send_paths( + Stellar.Horizon.Server.testnet(), + source_asset: :native, + source_amount: 5, + destination_assets: "TEST:GA654JC6QLA3ZH4O5V7X5NPM7KEWHKRG5GJA4PETK4SOFBUJLCCN74KQ" + ) {:ok, %Paths{records: [%Path{}, ...]}} # list with more options - iex> PaymentPaths.list_send_paths(destination_account: "GAYOLLLUIZE4DZMBB2ZBKGBUBZLIOYU6XFLW37GBP2VZD3ABNXCW4BVA", - source_asset: [ - code: "BRL", - issuer: "GDVKY2GU2DRXWTBEYJJWSFXIGBZV6AZNBVVSUHEPZI54LIS6BA7DVVSP" - ], - source_amount: 400 - ) + iex> PaymentPaths.list_send_paths( + Stellar.Horizon.Server.testnet(), + destination_account: "GAYOLLLUIZE4DZMBB2ZBKGBUBZLIOYU6XFLW37GBP2VZD3ABNXCW4BVA", + source_asset: [ + code: "BRL", + issuer: "GDVKY2GU2DRXWTBEYJJWSFXIGBZV6AZNBVVSUHEPZI54LIS6BA7DVVSP" + ], + source_amount: 400 + ) {:ok, %Paths{records: [%Path{}, ...]}} """ - @spec list_send_paths(args :: args()) :: response() - def list_send_paths(args \\ []) do + @spec list_send_paths(server :: server(), args :: args()) :: response() + def list_send_paths(server, args \\ []) do source_asset = RequestParams.build_assets_params(args, :source_asset) params = @@ -182,8 +207,8 @@ defmodule Stellar.Horizon.PaymentPaths do |> Keyword.delete(:source_asset) |> Keyword.merge(source_asset) - :get - |> Request.new(@endpoint, path: "strict-send") + server + |> Request.new(:get, @endpoint, path: "strict-send") |> Request.add_query(params, extra_params: allowed_query_options(:list_send)) |> Request.perform() |> Request.results(as: Paths) diff --git a/lib/horizon/request.ex b/lib/horizon/request.ex index ac87d56a..715af0ac 100644 --- a/lib/horizon/request.ex +++ b/lib/horizon/request.ex @@ -11,9 +11,10 @@ defmodule Stellar.Horizon.Request do At a minimum, a request must have the endpoint and method specified to be valid. """ - alias Stellar.Horizon.{Collection, Error} + alias Stellar.Horizon.{Collection, Error, Server} alias Stellar.Horizon.Client, as: Horizon + @type server :: Server.t() @type method :: :get | :post @type headers :: [{binary(), binary()}, ...] | [] @type body :: Keyword.t() @@ -41,6 +42,7 @@ defmodule Stellar.Horizon.Request do } defstruct [ + :server, :method, :headers, :body, @@ -54,13 +56,14 @@ defmodule Stellar.Horizon.Request do @default_query_params ~w(cursor order limit)a - @spec new(method :: method(), endpoint :: endpoint(), opts :: opts()) :: t() - def new(method, endpoint, opts \\ []) when method in [:get, :post] do + @spec new(server :: server(), method :: method(), endpoint :: endpoint(), opts :: opts()) :: t() + def new(%Server{} = server, method, endpoint, opts \\ []) when method in [:get, :post] do path = Keyword.get(opts, :path) segment = Keyword.get(opts, :segment) segment_path = Keyword.get(opts, :segment_path) %__MODULE__{ + server: server, method: method, endpoint: endpoint, path: path, @@ -95,12 +98,12 @@ defmodule Stellar.Horizon.Request do end @spec perform(request :: t()) :: response() - def perform(%__MODULE__{method: method, headers: headers, body: body} = request) do + def perform(%__MODULE__{server: server, method: method, headers: headers, body: body} = request) do encoded_body = URI.encode_query(body) request |> build_request_url() - |> (&Horizon.request(method, &1, headers, encoded_body)).() + |> (&Horizon.request(server, method, &1, headers, encoded_body)).() end @spec results(response :: response(), resource :: Keyword.t()) :: parsed_response() diff --git a/lib/horizon/server.ex b/lib/horizon/server.ex new file mode 100644 index 00000000..a9982393 --- /dev/null +++ b/lib/horizon/server.ex @@ -0,0 +1,28 @@ +defmodule Stellar.Horizon.Server do + @moduledoc """ + Horizon Server URL configuration. + """ + + alias Stellar.Network + + @type t :: %__MODULE__{url: String.t()} + + defstruct [:url] + + @spec new(url :: String.t()) :: t() + def new(url) when is_binary(url) do + %__MODULE__{url: url} + end + + @spec public() :: t() + def public, do: new(Network.public_horizon_url()) + + @spec testnet() :: t() + def testnet, do: new(Network.testnet_horizon_url()) + + @spec futurenet() :: t() + def futurenet, do: new(Network.futurenet_horizon_url()) + + @spec local() :: t() + def local, do: new(Network.local_horizon_url()) +end diff --git a/lib/horizon/trade_aggregations.ex b/lib/horizon/trade_aggregations.ex index 070b96cc..afa7591a 100644 --- a/lib/horizon/trade_aggregations.ex +++ b/lib/horizon/trade_aggregations.ex @@ -8,8 +8,9 @@ defmodule Stellar.Horizon.TradeAggregations do Horizon API reference: https://developers.stellar.org/api/aggregations/trade-aggregations/ """ - alias Stellar.Horizon.{Error, Request, RequestParams, TradeAggregation} + alias Stellar.Horizon.{Error, Request, RequestParams, TradeAggregation, Server} + @type server :: Server.t() @type args :: Keyword.t() @type resource :: TradeAggregation.t() @type response :: {:ok, resource()} | {:error, Error.t()} @@ -21,6 +22,7 @@ defmodule Stellar.Horizon.TradeAggregations do ## Parameters + * `server`: The Horizon server to query. * `base_asset`: `:native` or `[code: "base_asset_code", issuer: "base_asset_issuer"]` * `counter_asset`: `:native` or `[code: "counter_asset_code", issuer: "counter_asset_issuer"]` * `resolution`: The segment duration represented as milliseconds. @@ -35,30 +37,37 @@ defmodule Stellar.Horizon.TradeAggregations do ## Examples - iex> TradeAggregations.list_trade_aggregations(base_asset: :native, counter_asset: :native, resolution: "60000") + iex> TradeAggregations.list_trade_aggregations( + Stellar.Horizon.Server.testnet(), + base_asset: :native, + counter_asset: :native, + resolution: "60000" + ) {:ok, %Collection{records: [%TradeAggregation{}, ...]}} - iex> TradeAggregations.list_trade_aggregations(base_asset: :native, - counter_asset: [ - code: "EURT", - issuer: "GAP5LETOV6YIE62YAM56STDANPRDO7ZFDBGSNHJQIYGGKSMOZAHOOS2S" - ], - resolution: "3600000", - start_time: "1582156800000", - end_time: "1582178400000" - ) + iex> TradeAggregations.list_trade_aggregations( + Stellar.Horizon.Server.testnet(), + base_asset: :native, + counter_asset: [ + code: "EURT", + issuer: "GAP5LETOV6YIE62YAM56STDANPRDO7ZFDBGSNHJQIYGGKSMOZAHOOS2S" + ], + resolution: "3600000", + start_time: "1582156800000", + end_time: "1582178400000" + ) {:ok, %Collection{records: [%TradeAggregation{}, ...]}} """ - @spec list_trade_aggregations(args :: args()) :: response() - def list_trade_aggregations(args \\ []) do + @spec list_trade_aggregations(server :: server(), args :: args()) :: response() + def list_trade_aggregations(server, args \\ []) do params = resolve_params(args) - :get - |> Request.new(@endpoint) + server + |> Request.new(:get, @endpoint) |> Request.add_query(params, extra_params: allowed_query_options()) |> Request.perform() - |> Request.results(collection: {TradeAggregation, &list_trade_aggregations/1}) + |> Request.results(collection: {TradeAggregation, &list_trade_aggregations(server, &1)}) end @spec resolve_params(args :: args()) :: Keyword.t() diff --git a/lib/horizon/trades.ex b/lib/horizon/trades.ex index 9f8e857e..4fd5c414 100644 --- a/lib/horizon/trades.ex +++ b/lib/horizon/trades.ex @@ -8,8 +8,9 @@ defmodule Stellar.Horizon.Trades do Horizon API reference: https://developers.stellar.org/api/resources/trades/ """ - alias Stellar.Horizon.{Collection, Error, Request, Trade, RequestParams} + alias Stellar.Horizon.{Collection, Error, Request, Trade, RequestParams, Server} + @type server :: Server.t() @type options :: Keyword.t() @type resource :: Trade.t() | Collection.t() @type response :: {:ok, resource()} | {:error, Error.t()} @@ -31,15 +32,16 @@ defmodule Stellar.Horizon.Trades do ## Examples - iex> Trades.all(limit: 20, order: :asc) + iex> Trades.all(Stellar.Horizon.Server.testnet(), limit: 20, order: :asc) {:ok, %Collection{records: [%Trade{}, ...]}} # list by offer_id - iex> Trades.all(offer_id: 165563085) + iex> Trades.all(Stellar.Horizon.Server.testnet(), offer_id: 165563085) {:ok, %Collection{records: [%Trade{}, ...]}} # list by specific orderbook iex> Trades.all( + Stellar.Horizon.Server.testnet(), base_asset: [ code: "TEST", issuer: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD" @@ -50,11 +52,11 @@ defmodule Stellar.Horizon.Trades do {:ok, %Collection{records: [%Trade{}, ...]}} # list by trade_type - iex> Trades.all(trade_type: "liquidity_pools", limit: 20) + iex> Trades.all(Stellar.Horizon.Server.testnet(), trade_type: "liquidity_pools", limit: 20) {:ok, %Collection{records: [%Trade{}, ...]}} """ - @spec all(options :: options()) :: response() - def all(options \\ []) do + @spec all(server :: server(), options :: options()) :: response() + def all(server, options \\ []) do base_asset = RequestParams.build_assets_params(options, :base_asset) counter_asset = RequestParams.build_assets_params(options, :counter_asset) @@ -63,11 +65,11 @@ defmodule Stellar.Horizon.Trades do |> Keyword.merge(base_asset) |> Keyword.merge(counter_asset) - :get - |> Request.new(@endpoint) + server + |> Request.new(:get, @endpoint) |> Request.add_query(params, extra_params: allowed_query_options()) |> Request.perform() - |> Request.results(collection: {Trade, &all/1}) + |> Request.results(collection: {Trade, &all(server, &1)}) end @spec allowed_query_options() :: list() diff --git a/lib/horizon/transactions.ex b/lib/horizon/transactions.ex index d87e62d5..8a11ec55 100644 --- a/lib/horizon/transactions.ex +++ b/lib/horizon/transactions.ex @@ -12,8 +12,9 @@ defmodule Stellar.Horizon.Transactions do Horizon API reference: https://developers.stellar.org/api/resources/transactions/ """ - alias Stellar.Horizon.{Collection, Effect, Error, Operation, Transaction, Request} + alias Stellar.Horizon.{Collection, Effect, Error, Operation, Transaction, Request, Server} + @type server :: Server.t() @type hash :: String.t() @type options :: Keyword.t() @type resource :: Transaction.t() | Collection.t() @@ -25,17 +26,18 @@ defmodule Stellar.Horizon.Transactions do Creates a transaction to the Stellar network. ## Parameters: + * `server`: The Horizon server to query. * `tx`: The base64-encoded XDR of the transaction. ## Examples - iex> Transactions.create("AAAAAgAAAACQcEK2yfQA9CHrX+2UMkRIb/1wzltKqHpbdIcJbp+b/QAAAGQAAiEYAAAAAQAAAAEAAAAAAAAAAAAAAABgXP3QAAAAAQAAABBUZXN0IFRyYW5zYWN0aW9uAAAAAQAAAAAAAAABAAAAAJBwQrbJ9AD0Ietf7ZQyREhv/XDOW0qoelt0hwlun5v9AAAAAAAAAAAF9eEAAAAAAAAAAAFun5v9AAAAQKdJnG8QRiv9xGp1Oq7ACv/xR2BnNqjfUHrGNua7m4tWbrun3+GmAj6ca3xz+4ZppWRTbvTUcCxvpbHERZ85QgY=") + iex> Transactions.create(Stellar.Horizon.Server.testnet(), "AAAAAgAAAACQcEK2yfQA9CHrX+2UMkRIb/1wzltKqHpbdIcJbp+b/QAAAGQAAiEYAAAAAQAAAAEAAAAAAAAAAAAAAABgXP3QAAAAAQAAABBUZXN0IFRyYW5zYWN0aW9uAAAAAQAAAAAAAAABAAAAAJBwQrbJ9AD0Ietf7ZQyREhv/XDOW0qoelt0hwlun5v9AAAAAAAAAAAF9eEAAAAAAAAAAAFun5v9AAAAQKdJnG8QRiv9xGp1Oq7ACv/xR2BnNqjfUHrGNua7m4tWbrun3+GmAj6ca3xz+4ZppWRTbvTUcCxvpbHERZ85QgY=") {:ok, %Transaction{}} """ - @spec create(base64_envelope :: String.t()) :: response() - def create(base64_envelope) do - :post - |> Request.new(@endpoint) + @spec create(server :: server(), base64_envelope :: String.t()) :: response() + def create(server, base64_envelope) do + server + |> Request.new(:post, @endpoint) |> Request.add_headers([{"Content-Type", "application/x-www-form-urlencoded"}]) |> Request.add_body(tx: base64_envelope) |> Request.perform() @@ -46,17 +48,18 @@ defmodule Stellar.Horizon.Transactions do Retrieves information of a specific transaction. ## Parameters: + * `server`: The Horizon server to query. * `hash`: A hex-encoded SHA-256 hash of this transaction’s XDR-encoded form. ## Examples - iex> Transactions.retrieve("5ebd5c0af4385500b53dd63b0ef5f6e8feef1a7e1c86989be3cdcce825f3c0cc") + iex> Transactions.retrieve(Stellar.Horizon.Server.testnet(), "5ebd5c0af4385500b53dd63b0ef5f6e8feef1a7e1c86989be3cdcce825f3c0cc") {:ok, %Transaction{}} """ - @spec retrieve(hash :: hash()) :: response() - def retrieve(hash) do - :get - |> Request.new(@endpoint, path: hash) + @spec retrieve(server :: server(), hash :: hash()) :: response() + def retrieve(server, hash) do + server + |> Request.new(:get, @endpoint, path: hash) |> Request.perform() |> Request.results(as: Transaction) end @@ -64,6 +67,9 @@ defmodule Stellar.Horizon.Transactions do @doc """ Lists all successful transactions. + ## Parameters: + * `server`: The Horizon server to query. + ## Options * `cursor`: A number that points to a specific location in a collection of responses and is pulled from the `paging_token` value of a record. @@ -73,26 +79,27 @@ defmodule Stellar.Horizon.Transactions do ## Examples - iex> Transactions.all(limit: 10, order: :asc) + iex> Transactions.all(Stellar.Horizon.Server.testnet(), limit: 10, order: :asc) {:ok, %Collection{records: [%Transaction{}, ...]}} # include failed - iex> Transactions.all(limit: 10, include_failed: true) + iex> Transactions.all(Stellar.Horizon.Server.testnet(), limit: 10, include_failed: true) {:ok, %Collection{records: [%Transaction{}, ...]}} """ - @spec all(options :: options()) :: response() - def all(options \\ []) do - :get - |> Request.new(@endpoint) + @spec all(server :: server(), options :: options()) :: response() + def all(server, options \\ []) do + server + |> Request.new(:get, @endpoint) |> Request.add_query(options, extra_params: [:include_failed]) |> Request.perform() - |> Request.results(collection: {Transaction, &all/1}) + |> Request.results(collection: {Transaction, &all(server, &1)}) end @doc """ Lists the effects of a specific transaction. ## Parameters + * `server`: The Horizon server to query. * `hash`: A hex-encoded SHA-256 hash of this transaction’s XDR-encoded form. ## Options @@ -102,22 +109,23 @@ defmodule Stellar.Horizon.Transactions do ## Examples - iex> Transactions.list_effects("6b983a4e0dc3c04f4bd6b9037c55f70a09c434dfd01492be1077cf7ea68c2e4a", limit: 20) + iex> Transactions.list_effects(Stellar.Horizon.Server.testnet(), "6b983a4e0dc3c04f4bd6b9037c55f70a09c434dfd01492be1077cf7ea68c2e4a", limit: 20) {:ok, %Collection{records: [%Effect{}, ...]}} """ - @spec list_effects(hash :: hash(), options :: options()) :: response() - def list_effects(hash, options \\ []) do - :get - |> Request.new(@endpoint, path: hash, segment: "effects") + @spec list_effects(server :: server(), hash :: hash(), options :: options()) :: response() + def list_effects(server, hash, options \\ []) do + server + |> Request.new(:get, @endpoint, path: hash, segment: "effects") |> Request.add_query(options) |> Request.perform() - |> Request.results(collection: {Effect, &list_effects(hash, &1)}) + |> Request.results(collection: {Effect, &list_effects(server, hash, &1)}) end @doc """ Lists successful operations for a specific transaction. ## Parameters + * `server`: The Horizon server to query. * `hash`: A hex-encoded SHA-256 hash of this transaction’s XDR-encoded form. ## Options @@ -129,19 +137,19 @@ defmodule Stellar.Horizon.Transactions do ## Examples - iex> Transactions.list_operations("6b983a4e0dc3c04f4bd6b9037c55f70a09c434dfd01492be1077cf7ea68c2e4a", limit: 20) + iex> Transactions.list_operations(Stellar.Horizon.Server.testnet(), "6b983a4e0dc3c04f4bd6b9037c55f70a09c434dfd01492be1077cf7ea68c2e4a", limit: 20) {:ok, %Collection{records: [%Operation{}, ...]}} # join transactions - iex> Transactions.list_operations("6b983a4e0dc3c04f4bd6b9037c55f70a09c434dfd01492be1077cf7ea68c2e4a", join: "transactions") + iex> Transactions.list_operations(Stellar.Horizon.Server.testnet(), "6b983a4e0dc3c04f4bd6b9037c55f70a09c434dfd01492be1077cf7ea68c2e4a", join: "transactions") {:ok, %Collection{records: [%Operation{transaction: %Transaction{}}, ...]}} """ - @spec list_operations(hash :: hash(), options :: options()) :: response() - def list_operations(hash, options \\ []) do - :get - |> Request.new(@endpoint, path: hash, segment: "operations") + @spec list_operations(server :: server(), hash :: hash(), options :: options()) :: response() + def list_operations(server, hash, options \\ []) do + server + |> Request.new(:get, @endpoint, path: hash, segment: "operations") |> Request.add_query(options, extra_params: [:include_failed, :join]) |> Request.perform() - |> Request.results(collection: {Operation, &list_operations(hash, &1)}) + |> Request.results(collection: {Operation, &list_operations(server, hash, &1)}) end end diff --git a/lib/util/network.ex b/lib/util/network.ex index 01f515d6..f043fadc 100644 --- a/lib/util/network.ex +++ b/lib/util/network.ex @@ -4,24 +4,42 @@ defmodule Stellar.Network do """ @passphrases [ + public: "Public Global Stellar Network ; September 2015", test: "Test SDF Network ; September 2015", future: "Test SDF Future Network ; October 2022", - public: "Public Global Stellar Network ; September 2015", - local: "Standalone Network ; February 2017" + standalone: "Standalone Network ; February 2017" ] - @base_urls [ + @horizon_urls [ + public: "https://horizon.stellar.org", test: "https://horizon-testnet.stellar.org", future: "https://horizon-futurenet.stellar.org", - public: "https://horizon.stellar.org", local: "http://localhost:8000" ] - @spec base_url() :: String.t() - def base_url do - default = @base_urls[:test] - Keyword.get(@base_urls, current(), default) - end + @spec public_passphrase() :: String.t() + def public_passphrase, do: @passphrases[:public] + + @spec testnet_passphrase() :: String.t() + def testnet_passphrase, do: @passphrases[:test] + + @spec futurenet_passphrase() :: String.t() + def futurenet_passphrase, do: @passphrases[:future] + + @spec standalone_passphrase() :: String.t() + def standalone_passphrase, do: @passphrases[:standalone] + + @spec public_horizon_url() :: String.t() + def public_horizon_url, do: @horizon_urls[:public] + + @spec testnet_horizon_url() :: String.t() + def testnet_horizon_url, do: @horizon_urls[:test] + + @spec futurenet_horizon_url() :: String.t() + def futurenet_horizon_url, do: @horizon_urls[:future] + + @spec local_horizon_url() :: String.t() + def local_horizon_url, do: @horizon_urls[:local] @spec passphrase() :: String.t() def passphrase do diff --git a/mix.lock b/mix.lock index f96d5607..ec439964 100644 --- a/mix.lock +++ b/mix.lock @@ -24,6 +24,6 @@ "nimble_parsec": {:hex, :nimble_parsec, "1.3.1", "2c54013ecf170e249e9291ed0a62e5832f70a476c61da16f6aac6dca0189f2af", [:mix], [], "hexpm", "2682e3c0b2eb58d90c6375fc0cc30bc7be06f365bf72608804fb9cffa5e1b167"}, "parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"}, - "stellar_base": {:git, "https://github.com/kommitters/stellar_base.git", "849841e65575201643d587014752326374494d76", [branch: "v0.15"]}, + "stellar_base": {:hex, :stellar_base, "0.15.0", "893b7ee194aa0c732fbc16be431418d8269dc0221b70ecdb6320705540ba395f", [:mix], [{:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:crc, "~> 0.10.0", [hex: :crc, repo: "hexpm", optional: false]}, {:elixir_xdr, "~> 0.3", [hex: :elixir_xdr, repo: "hexpm", optional: false]}], "hexpm", "411aba27c89c03ac237457c171740428aef6f958aeebb4811723436e9105dc60"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, } diff --git a/test/horizon/accounts_test.exs b/test/horizon/accounts_test.exs index 56675812..835bcb15 100644 --- a/test/horizon/accounts_test.exs +++ b/test/horizon/accounts_test.exs @@ -166,7 +166,8 @@ defmodule Stellar.Horizon.AccountsTest do Offer, Operation, Trade, - Transaction + Transaction, + Server } alias Stellar.Horizon.Operation.{CreateAccount, Payment, SetOptions} @@ -225,11 +226,11 @@ defmodule Stellar.Horizon.AccountsTest do low_threshold: 1, med_threshold: 2 } - }} = Accounts.retrieve(account_id) + }} = Accounts.retrieve(Server.testnet(), account_id) end test "fetch_next_sequence_number/1", %{account_id: account_id} do - {:ok, 17_218_523_889_681} = Accounts.fetch_next_sequence_number(account_id) + {:ok, 17_218_523_889_681} = Accounts.fetch_next_sequence_number(Server.testnet(), account_id) end test "all/1" do @@ -240,7 +241,7 @@ defmodule Stellar.Horizon.AccountsTest do %Account{id: "GAP2KHWUMOHY7IO37UJY7SEBIITJIDZS5DRIIQRPEUT4VUKHZQGIRWS4"}, %Account{id: "GALPCCZN4YXA3YMJHKL6CVIECKPLJJCTVMSNYWBTKJW4K5HQLYLDMZTB"} ] - }} = Accounts.all() + }} = Accounts.all(Server.testnet()) end test "list_effects/1", %{account_id: account_id} do @@ -253,7 +254,7 @@ defmodule Stellar.Horizon.AccountsTest do %Effect{type: "contract_debited", created_at: ~U[2023-10-10 15:53:13Z]}, %Effect{type: "contract_credited", created_at: ~U[2023-10-10 15:52:40Z]} ] - }} = Accounts.list_effects(account_id, limit: 5) + }} = Accounts.list_effects(Server.testnet(), account_id, limit: 5) end test "list_offers/1", %{account_id: account_id} do @@ -279,7 +280,7 @@ defmodule Stellar.Horizon.AccountsTest do amount: "24.9999990" } ] - }} = Accounts.list_offers(account_id) + }} = Accounts.list_offers(Server.testnet(), account_id) end test "list_trades/1", %{account_id: account_id} do @@ -302,7 +303,7 @@ defmodule Stellar.Horizon.AccountsTest do base_amount: "748.5338945" } ] - }} = Accounts.list_trades(account_id) + }} = Accounts.list_trades(Server.testnet(), account_id) end test "list_transactions/1", %{account_id: account_id} do @@ -325,7 +326,7 @@ defmodule Stellar.Horizon.AccountsTest do ledger: 7855 } ] - }} = Accounts.list_transactions(account_id, limit: 3, order: :asc) + }} = Accounts.list_transactions(Server.testnet(), account_id, limit: 3, order: :asc) end test "list_operations/1", %{account_id: account_id} do @@ -351,7 +352,7 @@ defmodule Stellar.Horizon.AccountsTest do type_i: 0 } ] - }} = Accounts.list_operations(account_id, limit: 3, order: :desc) + }} = Accounts.list_operations(Server.testnet(), account_id, limit: 3, order: :desc) end test "list_payments/1", %{account_id: account_id} do @@ -374,22 +375,23 @@ defmodule Stellar.Horizon.AccountsTest do type_i: 1 } ] - }} = Accounts.list_payments(account_id, limit: 3) + }} = Accounts.list_payments(Server.testnet(), account_id, limit: 3) end test "data/1", %{account_id: account_id} do - {:ok, %Account.Data{value: "QkdFR0ZFVEVHRUhIRUVI"}} = Accounts.data(account_id, "NFT") + {:ok, %Account.Data{value: "QkdFR0ZFVEVHRUhIRUVI"}} = + Accounts.data(Server.testnet(), account_id, "NFT") end test "paginate_collection prev" do - {:ok, %Collection{prev: paginate_prev_fn}} = Accounts.all(limit: 3) + {:ok, %Collection{prev: paginate_prev_fn}} = Accounts.all(Server.testnet(), limit: 3) paginate_prev_fn.() assert_receive({:paginated, :prev}) end test "paginate_collection next" do - {:ok, %Collection{next: paginate_next_fn}} = Accounts.all(limit: 3) + {:ok, %Collection{next: paginate_next_fn}} = Accounts.all(Server.testnet(), limit: 3) paginate_next_fn.() assert_receive({:paginated, :next}) @@ -402,7 +404,7 @@ defmodule Stellar.Horizon.AccountsTest do status_code: 404, title: "Resource Missing", type: "https://stellar.org/horizon-errors/not_found" - }} = Accounts.retrieve("not_found") + }} = Accounts.retrieve(Server.testnet(), "not_found") end test "fetch_next_sequence_number error" do @@ -412,6 +414,6 @@ defmodule Stellar.Horizon.AccountsTest do status_code: 404, title: "Resource Missing", type: "https://stellar.org/horizon-errors/not_found" - }} = Accounts.fetch_next_sequence_number("not_found") + }} = Accounts.fetch_next_sequence_number(Server.testnet(), "not_found") end end diff --git a/test/horizon/assets_test.exs b/test/horizon/assets_test.exs index ae657f8d..015e7568 100644 --- a/test/horizon/assets_test.exs +++ b/test/horizon/assets_test.exs @@ -69,7 +69,7 @@ defmodule Stellar.Horizon.AssetsTest do use ExUnit.Case alias Stellar.Horizon.Client.CannedAssetRequests - alias Stellar.Horizon.{Asset, Assets, Collection, Error} + alias Stellar.Horizon.{Asset, Assets, Collection, Error, Server} setup do Application.put_env(:stellar_sdk, :http_client, CannedAssetRequests) @@ -104,7 +104,7 @@ defmodule Stellar.Horizon.AssetsTest do asset_issuer: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD" } ] - }} = Assets.all(limit: 3) + }} = Assets.all(Server.testnet(), limit: 3) end test "list_by_asset_code/2", %{asset_code: asset_code} do @@ -118,7 +118,7 @@ defmodule Stellar.Horizon.AssetsTest do }, _asset2 ] - }} = Assets.list_by_asset_code(asset_code, limit: 3) + }} = Assets.list_by_asset_code(Server.testnet(), asset_code, limit: 3) end test "list_by_asset_issuer/2", %{asset_issuer: asset_issuer} do @@ -135,18 +135,18 @@ defmodule Stellar.Horizon.AssetsTest do asset_issuer: "GCXMWUAUF37IWOOV2FRDKWEX3O2IHLM2FYH4WPI4PYUKAIFQEUU5X3TD" } ] - }} = Assets.list_by_asset_issuer(asset_issuer, limit: 3) + }} = Assets.list_by_asset_issuer(Server.testnet(), asset_issuer, limit: 3) end test "paginate_collection prev" do - {:ok, %Collection{prev: paginate_prev_fn}} = Assets.all(limit: 3) + {:ok, %Collection{prev: paginate_prev_fn}} = Assets.all(Server.testnet(), limit: 3) paginate_prev_fn.() assert_receive({:paginated, :prev}) end test "paginate_collection next" do - {:ok, %Collection{next: paginate_next_fn}} = Assets.all(limit: 3) + {:ok, %Collection{next: paginate_next_fn}} = Assets.all(Server.testnet(), limit: 3) paginate_next_fn.() assert_receive({:paginated, :next}) @@ -160,6 +160,6 @@ defmodule Stellar.Horizon.AssetsTest do status_code: 400, title: "Bad Request", type: "https://stellar.org/horizon-errors/bad_request" - }} = Assets.all(cursor: "error") + }} = Assets.all(Server.testnet(), cursor: "error") end end diff --git a/test/horizon/claimable_balances_test.exs b/test/horizon/claimable_balances_test.exs index 65470f56..0339eeed 100644 --- a/test/horizon/claimable_balances_test.exs +++ b/test/horizon/claimable_balances_test.exs @@ -131,7 +131,8 @@ defmodule Stellar.Horizon.ClaimableBalancesTest do Collection, Error, Operation, - Transaction + Transaction, + Server } alias Stellar.Horizon.Operation.{CreateAccount, Payment, SetOptions} @@ -178,7 +179,7 @@ defmodule Stellar.Horizon.ClaimableBalancesTest do last_modified_time: ~U[2020-02-26 19:29:16Z], paging_token: "00000000929b20b72e5890ab51c24f1cc46fa01c4f318d8d33367d24dd614cfdf5491072", sponsor: nil - }} = ClaimableBalances.retrieve(claimable_balance_id) + }} = ClaimableBalances.retrieve(Server.testnet(), claimable_balance_id) end test "all/1" do @@ -235,7 +236,7 @@ defmodule Stellar.Horizon.ClaimableBalancesTest do sponsor: "GB3A3CK64CZDZ63FZTVI3OKK7ZCD75YQCPA2EKHPDFD6ABKEQ3ESTWVV" } ] - }} = ClaimableBalances.all() + }} = ClaimableBalances.all(Server.testnet()) end test "list_by_sponsor/2" do @@ -247,6 +248,7 @@ defmodule Stellar.Horizon.ClaimableBalancesTest do ] }} = ClaimableBalances.list_by_sponsor( + Server.testnet(), "GBXISGJYYKE6RUO6L6KXBUJ7FJU4CWF647FLQAT3TZ2Q47IZHXFNYKYH" ) end @@ -262,6 +264,7 @@ defmodule Stellar.Horizon.ClaimableBalancesTest do ] }} = ClaimableBalances.list_by_claimant( + Server.testnet(), "GATBAGTTQLQ4VKZMXLINLS6M4F2PEXMAZCK5ZE5ES4B6A2DXNGCFRX54" ) end @@ -275,6 +278,7 @@ defmodule Stellar.Horizon.ClaimableBalancesTest do ] }} = ClaimableBalances.list_by_asset( + Server.testnet(), "BTCN:GDGHQTCJ3SGFBWBHJGVRUFBRLZGS5VS52HEDH4GVPX5GZRJQAOW7ZM37" ) end @@ -296,7 +300,11 @@ defmodule Stellar.Horizon.ClaimableBalancesTest do ledger: 7855 } ] - }} = ClaimableBalances.list_transactions(claimable_balance_id, limit: 3, order: :asc) + }} = + ClaimableBalances.list_transactions(Server.testnet(), claimable_balance_id, + limit: 3, + order: :asc + ) end test "list_operations/1", %{claimable_balance_id: claimable_balance_id} do @@ -319,18 +327,22 @@ defmodule Stellar.Horizon.ClaimableBalancesTest do type_i: 0 } ] - }} = ClaimableBalances.list_operations(claimable_balance_id, limit: 3, order: :desc) + }} = + ClaimableBalances.list_operations(Server.testnet(), claimable_balance_id, + limit: 3, + order: :desc + ) end test "paginate_collection prev" do - {:ok, %Collection{prev: paginate_prev_fn}} = ClaimableBalances.all(limit: 3) + {:ok, %Collection{prev: paginate_prev_fn}} = ClaimableBalances.all(Server.testnet(), limit: 3) paginate_prev_fn.() assert_receive({:paginated, :prev}) end test "paginate_collection next" do - {:ok, %Collection{next: paginate_next_fn}} = ClaimableBalances.all(limit: 3) + {:ok, %Collection{next: paginate_next_fn}} = ClaimableBalances.all(Server.testnet(), limit: 3) paginate_next_fn.() assert_receive({:paginated, :next}) @@ -343,6 +355,6 @@ defmodule Stellar.Horizon.ClaimableBalancesTest do status_code: 404, title: "Resource Missing", type: "https://stellar.org/horizon-errors/not_found" - }} = ClaimableBalances.retrieve("not_found") + }} = ClaimableBalances.retrieve(Server.testnet(), "not_found") end end diff --git a/test/horizon/client/default_test.exs b/test/horizon/client/default_test.exs index 8b691013..dfad9778 100644 --- a/test/horizon/client/default_test.exs +++ b/test/horizon/client/default_test.exs @@ -22,7 +22,7 @@ defmodule Stellar.Horizon.Client.CannedHTTPClient do {:ok, 400, [], json_error} end - def request(:get, @base_url <> "/accounts/unknow_id", _headers, _body, _opts) do + def request(:get, @base_url <> "/accounts/unknown_id", _headers, _body, _opts) do json_error = Horizon.fixture("404") {:ok, 404, [], json_error} end @@ -55,7 +55,7 @@ end defmodule Stellar.Horizon.Client.DefaultTest do use ExUnit.Case - alias Stellar.Horizon.Error + alias Stellar.Horizon.{Error, Server} alias Stellar.Horizon.Client.{Default, CannedHTTPClient} setup do @@ -67,49 +67,50 @@ defmodule Stellar.Horizon.Client.DefaultTest do %{ source_account: "GCO2IP3MJNUOKS4PUDI4C7LGGMQDJGXG3COYX3WSB4HHNAHKYV5YL3VC", - tx_hash: "132c440e984ab97d895f3477015080aafd6c4375f6a70a87327f7f95e13c4e31" + tx_hash: "132c440e984ab97d895f3477015080aafd6c4375f6a70a87327f7f95e13c4e31", + server: Server.testnet() } end describe "request/5" do - test "success", %{source_account: source_account, tx_hash: tx_hash} do + test "success", %{source_account: source_account, tx_hash: tx_hash, server: server} do {:ok, %{source_account: ^source_account, hash: ^tx_hash}} = - Default.request(:get, "/transactions/#{tx_hash}") + Default.request(server, :get, "/transactions/#{tx_hash}") end - test "bad_request" do + test "bad_request", %{server: server} do {:error, %Error{title: "Transaction Failed", status_code: 400}} = - Default.request(:post, "/transactions?tx=bad") + Default.request(server, :post, "/transactions?tx=bad") end - test "not_found" do + test "not_found", %{server: server} do {:error, %Error{title: "Resource Missing", status_code: 404}} = - Default.request(:get, "/accounts/unknow_id") + Default.request(server, :get, "/accounts/unknown_id") end - test "not_acceptable" do + test "not_acceptable", %{server: server} do {:error, %Error{title: "Not Acceptable", status_code: 406}} = - Default.request(:get, "/accounts/id.html") + Default.request(server, :get, "/accounts/id.html") end - test "before_history" do + test "before_history", %{server: server} do {:error, %Error{title: "Data Requested Is Before Recorded History", status_code: 410}} = - Default.request(:get, "/accounts?cursor=old") + Default.request(server, :get, "/accounts?cursor=old") end - test "stale_history" do + test "stale_history", %{server: server} do {:error, %Error{title: "Historical DB Is Too Stale", status_code: 503}} = - Default.request(:post, "/transactions?tx=stale") + Default.request(server, :post, "/transactions?tx=stale") end - test "timeout" do + test "timeout", %{server: server} do {:error, %Error{title: "Timeout", status_code: 504}} = - Default.request(:post, "/transactions?tx=timeout") + Default.request(server, :post, "/transactions?tx=timeout") end - test "network_error" do + test "network_error", %{server: server} do {:error, %Error{title: "Network error", status_code: :network_error}} = - Default.request(:post, "/network_error") + Default.request(server, :post, "/network_error") end end end diff --git a/test/horizon/client_test.exs b/test/horizon/client_test.exs index 6a59d6bd..ea4a00be 100644 --- a/test/horizon/client_test.exs +++ b/test/horizon/client_test.exs @@ -4,7 +4,7 @@ defmodule Stellar.Horizon.Client.CannedClientImpl do @behaviour Stellar.Horizon.Client.Spec @impl true - def request(_method, _path, _headers, _body, _opts) do + def request(_server, _method, _path, _headers, _body, _opts) do send(self(), {:requested, 200}) {:ok, 200, [], nil} end @@ -13,7 +13,7 @@ end defmodule Stellar.Horizon.ClientTest do use ExUnit.Case - alias Stellar.Horizon.Client + alias Stellar.Horizon.{Client, Server} alias Stellar.Horizon.Client.CannedClientImpl setup do @@ -25,7 +25,7 @@ defmodule Stellar.Horizon.ClientTest do end test "request/5" do - Client.request(:get, "/accounts/GAYOLLLUIZE4DZMBB2ZBKGBUBZLIOYU6XBNXCW4BVA") + Client.request(Server.testnet(), :get, "/accounts/GAYOLLLUIZE4DZMBB2ZBKGBUBZLIOYU6XBNXCW4BVA") assert_receive({:requested, 200}) end end diff --git a/test/horizon/effects_test.exs b/test/horizon/effects_test.exs index 80c63632..484e7c10 100644 --- a/test/horizon/effects_test.exs +++ b/test/horizon/effects_test.exs @@ -55,7 +55,7 @@ defmodule Stellar.Horizon.EffectsTest do use ExUnit.Case alias Stellar.Horizon.Client.CannedEffectRequests - alias Stellar.Horizon.{Collection, Error, Effect, Effects} + alias Stellar.Horizon.{Collection, Error, Effect, Effects, Server} setup do Application.put_env(:stellar_sdk, :http_client, CannedEffectRequests) @@ -127,18 +127,18 @@ defmodule Stellar.Horizon.EffectsTest do created_at: ~U[2023-10-10 15:52:40Z] } ] - }} = Effects.all(limit: 3) + }} = Effects.all(Server.testnet(), limit: 3) end test "paginate_collection prev" do - {:ok, %Collection{prev: paginate_prev_fn}} = Effects.all(limit: 3) + {:ok, %Collection{prev: paginate_prev_fn}} = Effects.all(Server.testnet(), limit: 3) paginate_prev_fn.() assert_receive({:paginated, :prev}) end test "paginate_collection next" do - {:ok, %Collection{next: paginate_next_fn}} = Effects.all(limit: 3) + {:ok, %Collection{next: paginate_next_fn}} = Effects.all(Server.testnet(), limit: 3) paginate_next_fn.() assert_receive({:paginated, :next}) @@ -152,6 +152,6 @@ defmodule Stellar.Horizon.EffectsTest do status_code: 400, title: "Bad Request", type: "https://stellar.org/horizon-errors/bad_request" - }} = Effects.all(cursor: "error") + }} = Effects.all(Server.testnet(), cursor: "error") end end diff --git a/test/horizon/fee_stats_test.exs b/test/horizon/fee_stats_test.exs index 41954f25..0522330f 100644 --- a/test/horizon/fee_stats_test.exs +++ b/test/horizon/fee_stats_test.exs @@ -21,7 +21,7 @@ defmodule Stellar.Horizon.FeeStatsTest do use ExUnit.Case alias Stellar.Horizon.Client.CannedFeeStatRequests - alias Stellar.Horizon.{FeeStat, FeeStats} + alias Stellar.Horizon.{FeeStat, FeeStats, Server} setup do Application.put_env(:stellar_sdk, :http_client, CannedFeeStatRequests) @@ -69,6 +69,6 @@ defmodule Stellar.Horizon.FeeStatsTest do p95: "100", p99: "100" } - }} = FeeStats.retrieve() + }} = FeeStats.retrieve(Server.testnet()) end end diff --git a/test/horizon/ledgers_test.exs b/test/horizon/ledgers_test.exs index a51bea13..53cdec55 100644 --- a/test/horizon/ledgers_test.exs +++ b/test/horizon/ledgers_test.exs @@ -88,6 +88,7 @@ defmodule Stellar.Horizon.LedgersTest do Ledger, Ledgers, Operation, + Server, Transaction } @@ -123,7 +124,7 @@ defmodule Stellar.Horizon.LedgersTest do successful_transaction_count: 0, total_coins: "100000000000.0000000", tx_set_operation_count: 0 - }} = Ledgers.retrieve(ledger_sequence) + }} = Ledgers.retrieve(Server.testnet(), ledger_sequence) end test "all/1" do @@ -146,7 +147,7 @@ defmodule Stellar.Horizon.LedgersTest do protocol_version: 18 } ] - }} = Ledgers.all() + }} = Ledgers.all(Server.testnet()) end test "list_transactions/1", %{ledger_sequence: ledger_sequence} do @@ -166,7 +167,7 @@ defmodule Stellar.Horizon.LedgersTest do ledger: 7855 } ] - }} = Ledgers.list_transactions(ledger_sequence, limit: 3, order: :asc) + }} = Ledgers.list_transactions(Server.testnet(), ledger_sequence, limit: 3, order: :asc) end test "list_operations/1", %{ledger_sequence: ledger_sequence} do @@ -189,7 +190,7 @@ defmodule Stellar.Horizon.LedgersTest do type_i: 0 } ] - }} = Ledgers.list_operations(ledger_sequence, limit: 3, order: :desc) + }} = Ledgers.list_operations(Server.testnet(), ledger_sequence, limit: 3, order: :desc) end test "list_payments/1", %{ledger_sequence: ledger_sequence} do @@ -211,7 +212,7 @@ defmodule Stellar.Horizon.LedgersTest do type_i: 1 } ] - }} = Ledgers.list_payments(ledger_sequence, limit: 3) + }} = Ledgers.list_payments(Server.testnet(), ledger_sequence, limit: 3) end test "list_effects/1", %{ledger_sequence: ledger_sequence} do @@ -224,18 +225,18 @@ defmodule Stellar.Horizon.LedgersTest do %Effect{type: "contract_debited", created_at: ~U[2023-10-10 15:53:13Z]}, %Effect{type: "contract_credited", created_at: ~U[2023-10-10 15:52:40Z]} ] - }} = Ledgers.list_effects(ledger_sequence, limit: 5) + }} = Ledgers.list_effects(Server.testnet(), ledger_sequence, limit: 5) end test "paginate_collection prev" do - {:ok, %Collection{prev: paginate_prev_fn}} = Ledgers.all(limit: 3) + {:ok, %Collection{prev: paginate_prev_fn}} = Ledgers.all(Server.testnet(), limit: 3) paginate_prev_fn.() assert_receive({:paginated, :prev}) end test "paginate_collection next" do - {:ok, %Collection{next: paginate_next_fn}} = Ledgers.all(limit: 3) + {:ok, %Collection{next: paginate_next_fn}} = Ledgers.all(Server.testnet(), limit: 3) paginate_next_fn.() assert_receive({:paginated, :next}) @@ -248,6 +249,6 @@ defmodule Stellar.Horizon.LedgersTest do status_code: 404, title: "Resource Missing", type: "https://stellar.org/horizon-errors/not_found" - }} = Ledgers.retrieve("not_found") + }} = Ledgers.retrieve(Server.testnet(), "not_found") end end diff --git a/test/horizon/liquidity_pools_test.exs b/test/horizon/liquidity_pools_test.exs index 1e239314..465abea1 100644 --- a/test/horizon/liquidity_pools_test.exs +++ b/test/horizon/liquidity_pools_test.exs @@ -131,6 +131,7 @@ defmodule Stellar.Horizon.LiquidityPoolsTest do LiquidityPool, LiquidityPools, Operation, + Server, Trade, Transaction } @@ -168,7 +169,7 @@ defmodule Stellar.Horizon.LiquidityPoolsTest do total_shares: "500000000.0000000", total_trustlines: 1, type: "constant_product" - }} = LiquidityPools.retrieve(liquidity_pool_id) + }} = LiquidityPools.retrieve(Server.testnet(), liquidity_pool_id) end test "all/1" do @@ -221,7 +222,7 @@ defmodule Stellar.Horizon.LiquidityPoolsTest do type: "constant_product" } ] - }} = LiquidityPools.all() + }} = LiquidityPools.all(Server.testnet()) end test "list_transactions/1", %{liquidity_pool_id: liquidity_pool_id} do @@ -241,7 +242,8 @@ defmodule Stellar.Horizon.LiquidityPoolsTest do ledger: 7855 } ] - }} = LiquidityPools.list_transactions(liquidity_pool_id, limit: 3, order: :asc) + }} = + LiquidityPools.list_transactions(Server.testnet(), liquidity_pool_id, limit: 3, order: :asc) end test "list_operations/1", %{liquidity_pool_id: liquidity_pool_id} do @@ -264,7 +266,8 @@ defmodule Stellar.Horizon.LiquidityPoolsTest do type_i: 0 } ] - }} = LiquidityPools.list_operations(liquidity_pool_id, limit: 3, order: :desc) + }} = + LiquidityPools.list_operations(Server.testnet(), liquidity_pool_id, limit: 3, order: :desc) end test "list_effects/1", %{liquidity_pool_id: liquidity_pool_id} do @@ -277,7 +280,7 @@ defmodule Stellar.Horizon.LiquidityPoolsTest do %Effect{type: "contract_debited", created_at: ~U[2023-10-10 15:53:13Z]}, %Effect{type: "contract_credited", created_at: ~U[2023-10-10 15:52:40Z]} ] - }} = LiquidityPools.list_effects(liquidity_pool_id, limit: 5) + }} = LiquidityPools.list_effects(Server.testnet(), liquidity_pool_id, limit: 5) end test "list_trades/2", %{liquidity_pool_id: liquidity_pool_id} do @@ -288,18 +291,18 @@ defmodule Stellar.Horizon.LiquidityPoolsTest do %Trade{base_amount: "10.0000000"}, %Trade{base_amount: "748.5338945"} ] - }} = LiquidityPools.list_trades(liquidity_pool_id) + }} = LiquidityPools.list_trades(Server.testnet(), liquidity_pool_id) end test "paginate_collection prev" do - {:ok, %Collection{prev: paginate_prev_fn}} = LiquidityPools.all(limit: 3) + {:ok, %Collection{prev: paginate_prev_fn}} = LiquidityPools.all(Server.testnet(), limit: 3) paginate_prev_fn.() assert_receive({:paginated, :prev}) end test "paginate_collection next" do - {:ok, %Collection{next: paginate_next_fn}} = LiquidityPools.all(limit: 3) + {:ok, %Collection{next: paginate_next_fn}} = LiquidityPools.all(Server.testnet(), limit: 3) paginate_next_fn.() assert_receive({:paginated, :next}) @@ -312,6 +315,6 @@ defmodule Stellar.Horizon.LiquidityPoolsTest do status_code: 404, title: "Resource Missing", type: "https://stellar.org/horizon-errors/not_found" - }} = LiquidityPools.retrieve("not_found") + }} = LiquidityPools.retrieve(Server.testnet(), "not_found") end end diff --git a/test/horizon/offers_test.exs b/test/horizon/offers_test.exs index 60d5ee3b..1ccbfcc9 100644 --- a/test/horizon/offers_test.exs +++ b/test/horizon/offers_test.exs @@ -53,7 +53,7 @@ defmodule Stellar.Horizon.OffersTest do use ExUnit.Case alias Stellar.Horizon.Client.CannedOfferRequests - alias Stellar.Horizon.{Collection, Error, Offer, Offers, Trade} + alias Stellar.Horizon.{Collection, Error, Offer, Offers, Trade, Server} setup do Application.put_env(:stellar_sdk, :http_client, CannedOfferRequests) @@ -83,7 +83,7 @@ defmodule Stellar.Horizon.OffersTest do asset_type: "credit_alphanum4" }, sponsor: nil - }} = Offers.retrieve(offer_id) + }} = Offers.retrieve(Server.testnet(), offer_id) end test "all/1" do @@ -109,7 +109,7 @@ defmodule Stellar.Horizon.OffersTest do price: "12.8899964" } ] - }} = Offers.all() + }} = Offers.all(Server.testnet()) end test "list_trades/2", %{offer_id: offer_id} do @@ -120,18 +120,18 @@ defmodule Stellar.Horizon.OffersTest do %Trade{base_offer_id: ^offer_id, base_amount: "10.0000000"}, %Trade{base_offer_id: ^offer_id, base_amount: "748.5338945"} ] - }} = Offers.list_trades(offer_id) + }} = Offers.list_trades(Server.testnet(), offer_id) end test "paginate_collection prev" do - {:ok, %Collection{prev: paginate_prev_fn}} = Offers.all(limit: 3) + {:ok, %Collection{prev: paginate_prev_fn}} = Offers.all(Server.testnet(), limit: 3) paginate_prev_fn.() assert_receive({:paginated, :prev}) end test "paginate_collection next" do - {:ok, %Collection{next: paginate_next_fn}} = Offers.all(limit: 3) + {:ok, %Collection{next: paginate_next_fn}} = Offers.all(Server.testnet(), limit: 3) paginate_next_fn.() assert_receive({:paginated, :next}) @@ -144,6 +144,6 @@ defmodule Stellar.Horizon.OffersTest do status_code: 404, title: "Resource Missing", type: "https://stellar.org/horizon-errors/not_found" - }} = Offers.retrieve("not_found") + }} = Offers.retrieve(Server.testnet(), "not_found") end end diff --git a/test/horizon/operations_test.exs b/test/horizon/operations_test.exs index 05d34222..902f8825 100644 --- a/test/horizon/operations_test.exs +++ b/test/horizon/operations_test.exs @@ -82,7 +82,8 @@ defmodule Stellar.Horizon.OperationsTest do Effect, Error, Operation, - Operations + Operations, + Server } alias Stellar.Horizon.Operation.{CreateAccount, Payment, SetOptions, PathPaymentStrictSend} @@ -120,7 +121,7 @@ defmodule Stellar.Horizon.OperationsTest do transaction_successful: true, type: "path_payment_strict_send", type_i: 13 - }} = Operations.retrieve(operation_id) + }} = Operations.retrieve(Server.testnet(), operation_id) end test "all/1" do @@ -177,7 +178,7 @@ defmodule Stellar.Horizon.OperationsTest do type_i: 0 } ] - }} = Operations.all() + }} = Operations.all(Server.testnet()) end test "list_effects/2", %{operation_id: operation_id} do @@ -190,7 +191,7 @@ defmodule Stellar.Horizon.OperationsTest do %Effect{type: "contract_debited", created_at: ~U[2023-10-10 15:53:13Z]}, %Effect{type: "contract_credited", created_at: ~U[2023-10-10 15:52:40Z]} ] - }} = Operations.list_effects(operation_id, limit: 5) + }} = Operations.list_effects(Server.testnet(), operation_id, limit: 5) end test "list_payments/1" do @@ -215,18 +216,18 @@ defmodule Stellar.Horizon.OperationsTest do type_i: 1 } ] - }} = Operations.list_payments(limit: 3) + }} = Operations.list_payments(Server.testnet(), limit: 3) end test "paginate_collection prev" do - {:ok, %Collection{prev: paginate_prev_fn}} = Operations.all(limit: 3) + {:ok, %Collection{prev: paginate_prev_fn}} = Operations.all(Server.testnet(), limit: 3) paginate_prev_fn.() assert_receive({:paginated, :prev}) end test "paginate_collection next" do - {:ok, %Collection{next: paginate_next_fn}} = Operations.all(limit: 3) + {:ok, %Collection{next: paginate_next_fn}} = Operations.all(Server.testnet(), limit: 3) paginate_next_fn.() assert_receive({:paginated, :next}) @@ -239,6 +240,6 @@ defmodule Stellar.Horizon.OperationsTest do status_code: 404, title: "Resource Missing", type: "https://stellar.org/horizon-errors/not_found" - }} = Operations.retrieve("error") + }} = Operations.retrieve(Server.testnet(), "error") end end diff --git a/test/horizon/order_books_test.exs b/test/horizon/order_books_test.exs index 182b8351..e5a0f3bf 100644 --- a/test/horizon/order_books_test.exs +++ b/test/horizon/order_books_test.exs @@ -33,7 +33,7 @@ defmodule Stellar.Horizon.OrderBooksTest do use ExUnit.Case alias Stellar.Horizon.Client.CannedOrderBooksRequests - alias Stellar.Horizon.{OrderBooks, OrderBook, Error} + alias Stellar.Horizon.{OrderBooks, OrderBook, Error, Server} alias Stellar.Horizon.OrderBook.Price setup do @@ -92,6 +92,7 @@ defmodule Stellar.Horizon.OrderBooksTest do } }} = OrderBooks.retrieve( + Server.testnet(), selling_asset: selling_asset, buying_asset: buying_asset, limit: limit @@ -104,6 +105,6 @@ defmodule Stellar.Horizon.OrderBooksTest do status_code: 400, title: "Invalid Order Book Parameters", type: "https://stellar.org/horizon-errors/invalid_order_book" - }} = OrderBooks.retrieve(buying_asset: :error) + }} = OrderBooks.retrieve(Server.testnet(), buying_asset: :error) end end diff --git a/test/horizon/payment_paths_test.exs b/test/horizon/payment_paths_test.exs index 1fdf833c..504dad4c 100644 --- a/test/horizon/payment_paths_test.exs +++ b/test/horizon/payment_paths_test.exs @@ -68,7 +68,7 @@ defmodule Stellar.Horizon.PaymentPathsTest do use ExUnit.Case alias Stellar.Horizon.Client.CannedPathRequests - alias Stellar.Horizon.{Path, Paths, PaymentPaths, Error} + alias Stellar.Horizon.{Path, Paths, PaymentPaths, Error, Server} setup do Application.put_env(:stellar_sdk, :http_client, CannedPathRequests) @@ -111,6 +111,7 @@ defmodule Stellar.Horizon.PaymentPathsTest do ] }} = PaymentPaths.list_paths( + Server.testnet(), source_account: source_account, destination_asset: destination_asset, destination_amount: destination_amount @@ -138,6 +139,7 @@ defmodule Stellar.Horizon.PaymentPathsTest do ] }} = PaymentPaths.list_receive_paths( + Server.testnet(), destination_asset: destination_asset, destination_amount: destination_amount, source_account: source_account @@ -177,6 +179,7 @@ defmodule Stellar.Horizon.PaymentPathsTest do ] }} = PaymentPaths.list_send_paths( + Server.testnet(), source_asset: source_asset, source_amount: source_amount, destination_assets: destination_assets @@ -190,7 +193,7 @@ defmodule Stellar.Horizon.PaymentPathsTest do extras: %{invalid_field: "destination_asset_type", reason: "Missing required field"}, status_code: 400, title: "Bad Request" - }} = PaymentPaths.list_receive_paths(destination_amount: "error") + }} = PaymentPaths.list_receive_paths(Server.testnet(), destination_amount: "error") end test "list strict send error" do @@ -200,6 +203,6 @@ defmodule Stellar.Horizon.PaymentPathsTest do extras: %{invalid_field: "source_asset_type", reason: "Missing required field"}, status_code: 400, title: "Bad Request" - }} = PaymentPaths.list_send_paths(source_amount: "error") + }} = PaymentPaths.list_send_paths(Server.testnet(), source_amount: "error") end end diff --git a/test/horizon/request_test.exs b/test/horizon/request_test.exs index ec4a0765..935b4092 100644 --- a/test/horizon/request_test.exs +++ b/test/horizon/request_test.exs @@ -4,7 +4,7 @@ defmodule Stellar.Horizon.Client.CannedRequestImpl do @behaviour Stellar.Horizon.Client.Spec @impl true - def request(_method, "/transactions/f08b8/effects" <> _query, _headers, _body, _opts) do + def request(_server, _method, "/transactions/f08b8/effects" <> _query, _headers, _body, _opts) do send(self(), {:horizon_requested, 200}) {:ok, 200, [], nil} end @@ -15,7 +15,7 @@ defmodule Stellar.Horizon.RequestTest do alias Stellar.Test.Fixtures.Horizon alias Stellar.Horizon.Client.CannedRequestImpl - alias Stellar.Horizon.{Collection, Error, Request, Transaction, Paths, Path} + alias Stellar.Horizon.{Collection, Error, Request, Transaction, Paths, Path, Server} setup do Application.put_env(:stellar_sdk, :http_client_impl, CannedRequestImpl) @@ -24,6 +24,7 @@ defmodule Stellar.Horizon.RequestTest do Application.delete_env(:stellar_sdk, :http_client_impl) end) + server = Server.testnet() endpoint = "transactions" hash = "f08b83906eaebfbf359182cc1e47a0e5c4bbdbad1a897785d5677a2bfc54b5b1" body = [tx: "AAAAAgAAABAAAAAAAAAA==="] @@ -33,6 +34,7 @@ defmodule Stellar.Horizon.RequestTest do segment_path = "0052d44a6c260660115f07c5a78631770e62aae3ffde96731c44b1509e9c8434" %{ + server: server, endpoint: endpoint, hash: hash, segment: segment, @@ -43,18 +45,27 @@ defmodule Stellar.Horizon.RequestTest do } end - test "new/1", %{endpoint: endpoint, hash: hash} do - %Request{method: :get, endpoint: ^endpoint, path: ^hash, body: [], headers: [], query: []} = - Request.new(:get, endpoint, path: hash) + test "new/1", %{server: server, endpoint: endpoint, hash: hash} do + %Request{ + server: ^server, + method: :get, + endpoint: ^endpoint, + path: ^hash, + body: [], + headers: [], + query: [] + } = Request.new(server, :get, endpoint, path: hash) end test "new/1 with_segment", %{ + server: server, endpoint: endpoint, hash: hash, segment: segment, segment_path: segment_path } do %Request{ + server: ^server, method: :get, endpoint: ^endpoint, path: ^hash, @@ -63,65 +74,69 @@ defmodule Stellar.Horizon.RequestTest do body: [], headers: [], query: [] - } = Request.new(:get, endpoint, path: hash, segment: segment, segment_path: segment_path) + } = + Request.new(server, :get, endpoint, path: hash, segment: segment, segment_path: segment_path) end - test "add_body/2", %{endpoint: endpoint, body: body} do - %Request{method: :post, endpoint: ^endpoint, body: ^body} = - :post - |> Request.new(endpoint) + test "add_body/2", %{server: server, endpoint: endpoint, body: body} do + %Request{server: ^server, method: :post, endpoint: ^endpoint, body: ^body} = + server + |> Request.new(:post, endpoint) |> Request.add_body(body) end - test "add_headers/2", %{endpoint: endpoint, headers: headers} do - %Request{method: :post, endpoint: ^endpoint, headers: ^headers} = - :post - |> Request.new(endpoint) + test "add_headers/2", %{server: server, endpoint: endpoint, headers: headers} do + %Request{server: ^server, method: :post, endpoint: ^endpoint, headers: ^headers} = + server + |> Request.new(:post, endpoint) |> Request.add_headers(headers) end - test "add_query/3", %{endpoint: endpoint, query: query} do + test "add_query/3", %{server: server, endpoint: endpoint, query: query} do %Request{ + server: ^server, method: :get, endpoint: ^endpoint, query: ^query, encoded_query: "cursor=549755817992-1&order=desc&limit=25" } = - :get - |> Request.new(endpoint) + server + |> Request.new(:get, endpoint) |> Request.add_query(query) end - test "add_query/3 extra_params", %{endpoint: endpoint, query: query} do + test "add_query/3 extra_params", %{server: server, endpoint: endpoint, query: query} do query = query ++ [include_failed: true] %Request{ + server: ^server, method: :get, endpoint: ^endpoint, query: ^query, encoded_query: "cursor=549755817992-1&order=desc&limit=25&include_failed=true" } = - :get - |> Request.new(endpoint) + server + |> Request.new(:get, endpoint) |> Request.add_query(query, extra_params: [:include_failed]) end - test "add_query/3 invalid_params", %{endpoint: endpoint} do + test "add_query/3 invalid_params", %{server: server, endpoint: endpoint} do %Request{ + server: ^server, method: :get, endpoint: ^endpoint, encoded_query: "cursor=549755817992-1" } = - :get - |> Request.new(endpoint) + server + |> Request.new(:get, endpoint) |> Request.add_query([cursor: "549755817992-1", test: "test"], extra_params: [:include_failed] ) end - test "perform/2" do - :get - |> Request.new("transactions", path: "f08b8", segment: "effects", segment_path: "123") + test "perform/2", %{server: server} do + server + |> Request.new(:get, "transactions", path: "f08b8", segment: "effects", segment_path: "123") |> Request.add_query(limit: 10) |> Request.perform() diff --git a/test/horizon/server_test.exs b/test/horizon/server_test.exs new file mode 100644 index 00000000..894fc389 --- /dev/null +++ b/test/horizon/server_test.exs @@ -0,0 +1,25 @@ +defmodule Stellar.Horizon.ServerTest do + use ExUnit.Case + + alias Stellar.Horizon.Server + + test "new/1" do + %Server{url: "https://horizon-standalone.com"} = Server.new("https://horizon-standalone.com") + end + + test "public/0" do + %Server{url: "https://horizon.stellar.org"} = Server.public() + end + + test "testnet/0" do + %Server{url: "https://horizon-testnet.stellar.org"} = Server.testnet() + end + + test "futurenet/0" do + %Server{url: "https://horizon-futurenet.stellar.org"} = Server.futurenet() + end + + test "local/0" do + %Server{url: "http://localhost:8000"} = Server.local() + end +end diff --git a/test/horizon/trade_aggregations_test.exs b/test/horizon/trade_aggregations_test.exs index 7dbd2738..eaf71d64 100644 --- a/test/horizon/trade_aggregations_test.exs +++ b/test/horizon/trade_aggregations_test.exs @@ -68,7 +68,7 @@ defmodule Stellar.Horizon.TradeAggregationsTest do use ExUnit.Case alias Stellar.Horizon.Client.CannedTradeAggregationRequests - alias Stellar.Horizon.{Collection, TradeAggregation, TradeAggregations, Error} + alias Stellar.Horizon.{Collection, TradeAggregation, TradeAggregations, Error, Server} setup do Application.put_env(:stellar_sdk, :http_client, CannedTradeAggregationRequests) @@ -134,6 +134,7 @@ defmodule Stellar.Horizon.TradeAggregationsTest do ] }} = TradeAggregations.list_trade_aggregations( + Server.testnet(), base_asset: base_asset, counter_asset: counter_asset, resolution: resolution, @@ -153,6 +154,7 @@ defmodule Stellar.Horizon.TradeAggregationsTest do } do {:ok, %Collection{prev: paginate_prev_fn}} = TradeAggregations.list_trade_aggregations( + Server.testnet(), base_asset: base_asset, counter_asset: counter_asset, resolution: resolution, @@ -176,6 +178,7 @@ defmodule Stellar.Horizon.TradeAggregationsTest do } do {:ok, %Collection{next: paginate_next_fn}} = TradeAggregations.list_trade_aggregations( + Server.testnet(), base_asset: base_asset, counter_asset: counter_asset, resolution: resolution, @@ -197,6 +200,6 @@ defmodule Stellar.Horizon.TradeAggregationsTest do status_code: 400, title: "Bad Request", type: "https://stellar.org/horizon-errors/bad_request" - }} = TradeAggregations.list_trade_aggregations(base_asset: :error) + }} = TradeAggregations.list_trade_aggregations(Server.testnet(), base_asset: :error) end end diff --git a/test/horizon/trades_test.exs b/test/horizon/trades_test.exs index bb2e2821..abc4a049 100644 --- a/test/horizon/trades_test.exs +++ b/test/horizon/trades_test.exs @@ -55,7 +55,7 @@ defmodule Stellar.Horizon.TradesTest do use ExUnit.Case alias Stellar.Horizon.Client.CannedTradeRequests - alias Stellar.Horizon.{Collection, Error, Trade, Trades} + alias Stellar.Horizon.{Collection, Error, Trade, Trades, Server} setup do Application.put_env(:stellar_sdk, :http_client, CannedTradeRequests) @@ -136,18 +136,18 @@ defmodule Stellar.Horizon.TradesTest do trade_type: nil } ] - }} = Trades.all(limit: 3) + }} = Trades.all(Server.testnet(), limit: 3) end test "paginate_collection prev" do - {:ok, %Collection{prev: paginate_prev_fn}} = Trades.all(limit: 3) + {:ok, %Collection{prev: paginate_prev_fn}} = Trades.all(Server.testnet(), limit: 3) paginate_prev_fn.() assert_receive({:paginated, :prev}) end test "paginate_collection next" do - {:ok, %Collection{next: paginate_next_fn}} = Trades.all(limit: 3) + {:ok, %Collection{next: paginate_next_fn}} = Trades.all(Server.testnet(), limit: 3) paginate_next_fn.() assert_receive({:paginated, :next}) @@ -161,6 +161,6 @@ defmodule Stellar.Horizon.TradesTest do status_code: 400, title: "Bad Request", type: "https://stellar.org/horizon-errors/bad_request" - }} = Trades.all(cursor: "error") + }} = Trades.all(Server.testnet(), cursor: "error") end end diff --git a/test/horizon/transactions_test.exs b/test/horizon/transactions_test.exs index 9319e3da..b748a9e7 100644 --- a/test/horizon/transactions_test.exs +++ b/test/horizon/transactions_test.exs @@ -107,7 +107,8 @@ defmodule Stellar.Horizon.TransactionsTest do Transactions, Transaction.Preconditions, Transaction.TimeBounds, - Transaction.LedgerBounds + Transaction.LedgerBounds, + Server } alias Stellar.Horizon.Operation.{CreateAccount, Payment, SetOptions} @@ -129,7 +130,7 @@ defmodule Stellar.Horizon.TransactionsTest do test "create/1", %{base64_envelope: base64_envelope, hash: hash} do {:ok, %Transaction{successful: true, envelope_xdr: ^base64_envelope, hash: ^hash}} = - Transactions.create(base64_envelope) + Transactions.create(Server.testnet(), base64_envelope) end test "retrieve/1", %{ @@ -175,7 +176,7 @@ defmodule Stellar.Horizon.TransactionsTest do "GCO2IP3MJNUOKS4PUDI4C7LGGMQDJGXG3COYX3WSB4HHNAHKYV5YL3VC" ] } - }} = Transactions.retrieve(hash) + }} = Transactions.retrieve(Server.testnet(), hash) end test "all/1" do @@ -192,7 +193,7 @@ defmodule Stellar.Horizon.TransactionsTest do hash: "3ce2aca2fed36da2faea31352c76c5e412348887a4c119b1e90de8d1b937396a" } ] - }} = Transactions.all(limit: 3) + }} = Transactions.all(Server.testnet(), limit: 3) end test "list_effects/2", %{hash: hash} do @@ -205,7 +206,7 @@ defmodule Stellar.Horizon.TransactionsTest do %Effect{type: "contract_debited", created_at: ~U[2023-10-10 15:53:13Z]}, %Effect{type: "contract_credited", created_at: ~U[2023-10-10 15:52:40Z]} ] - }} = Transactions.list_effects(hash, limit: 5) + }} = Transactions.list_effects(Server.testnet(), hash, limit: 5) end test "list_operations/2", %{hash: hash, source_account: source_account} do @@ -231,18 +232,18 @@ defmodule Stellar.Horizon.TransactionsTest do type_i: 0 } ] - }} = Transactions.list_operations(hash, limit: 3, order: :desc) + }} = Transactions.list_operations(Server.testnet(), hash, limit: 3, order: :desc) end test "paginate_collection prev" do - {:ok, %Collection{prev: paginate_prev_fn}} = Transactions.all(limit: 3) + {:ok, %Collection{prev: paginate_prev_fn}} = Transactions.all(Server.testnet(), limit: 3) paginate_prev_fn.() assert_receive({:paginated, :prev}) end test "paginate_collection next" do - {:ok, %Collection{next: paginate_next_fn}} = Transactions.all(limit: 3) + {:ok, %Collection{next: paginate_next_fn}} = Transactions.all(Server.testnet(), limit: 3) paginate_next_fn.() assert_receive({:paginated, :next}) @@ -254,6 +255,6 @@ defmodule Stellar.Horizon.TransactionsTest do status_code: 400, title: "Transaction Failed", extras: %{result_codes: %{transaction: "tx_insufficient_fee"}} - }} = Transactions.create("bad") + }} = Transactions.create(Server.testnet(), "bad") end end diff --git a/test/util/network_test.exs b/test/util/network_test.exs index f046d36d..50a55b71 100644 --- a/test/util/network_test.exs +++ b/test/util/network_test.exs @@ -3,40 +3,49 @@ defmodule Stellar.NetworkTest do alias Stellar.Network - @test_network_url "https://horizon-testnet.stellar.org" - @test_passphrase "Test SDF Network ; September 2015" - - @public_network_url "https://horizon.stellar.org" @public_passphrase "Public Global Stellar Network ; September 2015" + @testnet_passphrase "Test SDF Network ; September 2015" + @futurenet_passphrase "Test SDF Future Network ; October 2022" + @standalone_passphrase "Standalone Network ; February 2017" + + @public_horizon_url "https://horizon.stellar.org" + @testnet_horizon_url "https://horizon-testnet.stellar.org" + @futurenet_horizon_url "https://horizon-futurenet.stellar.org" + @local_horizon_url "http://localhost:8000" + + describe "network passphrases" do + test "public_passphrase/0" do + @public_passphrase = Network.public_passphrase() + end - test "base_url/0" do - @test_network_url = Network.base_url() - end + test "testnet_passphrase/0" do + @testnet_passphrase = Network.testnet_passphrase() + end - test "passphrase/0" do - @test_passphrase = Network.passphrase() - end + test "futurenet_passphrase/0" do + @futurenet_passphrase = Network.futurenet_passphrase() + end - test "current/0" do - :test = Network.current() + test "standalone_passphrase/0" do + @standalone_passphrase = Network.standalone_passphrase() + end end - describe "config/0" do - setup do - on_exit(fn -> Application.put_env(:stellar_sdk, :network, :test) end) - Application.put_env(:stellar_sdk, :network, :public) + describe "network horizon urls" do + test "public_horizon_url/0" do + @public_horizon_url = Network.public_horizon_url() end - test "base_url/0" do - @public_network_url = Network.base_url() + test "testnet_horizon_url/0" do + @testnet_horizon_url = Network.testnet_horizon_url() end - test "passphrase/0" do - @public_passphrase = Network.passphrase() + test "futurenet_horizon_url/0" do + @futurenet_horizon_url = Network.futurenet_horizon_url() end - test "current/0" do - :public = Network.current() + test "local_horizon_url/0" do + @local_horizon_url = Network.local_horizon_url() end end end From 66361314f5f18399b1bc6d0e03ccc39d049d2e3a Mon Sep 17 00:00:00 2001 From: Miguel Nieto <39246879+miguelnietoa@users.noreply.github.com> Date: Mon, 4 Mar 2024 09:36:23 -0500 Subject: [PATCH 2/5] [TxBuild] Dynamic network configuration: Receive `network_passphrase` in TxBuild and SorobanAuhorizationEntry (#354) * Receive `network_passphrase` in TxBuild and related modules * Fix tests * Receive `network_passphrase` in SorobanAuthorizationEntry + tests * Fix format and dialyzer * Update README documentation * Remove config * Fix format * Add `Network.network_id_xdr` fn * Add suggested change --- README.md | 26 ++++---- config/config.exs | 3 - config/dev.exs | 3 - config/prod.exs | 3 - config/test.exs | 3 - lib/tx_build.ex | 14 +++-- lib/tx_build/default.ex | 60 +++++++++++++------ lib/tx_build/soroban_authorization_entry.ex | 43 +++++++------ lib/tx_build/spec.ex | 4 +- lib/tx_build/transaction_envelope.ex | 26 +++++--- lib/tx_build/transaction_signature.ex | 46 +++++++------- lib/util/network.ex | 37 +++++++----- test/support/xdr_fixtures.ex | 10 +++- test/tx_build/default_test.exs | 51 ++++++++++++---- .../soroban_authorization_entry_test.exs | 38 +++++++++--- test/tx_build/transaction_envelope_test.exs | 29 +++++++-- test/tx_build/transaction_signature_test.exs | 37 +++++++++--- test/tx_build/tx_build_test.exs | 10 +++- test/util/network_test.exs | 30 ++++++++++ 19 files changed, 327 insertions(+), 146 deletions(-) delete mode 100644 config/config.exs delete mode 100644 config/dev.exs delete mode 100644 config/prod.exs delete mode 100644 config/test.exs diff --git a/README.md b/README.md index 58e600e6..f27354c1 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ The **Stellar SDK** enables the construction, signing and encoding of Stellar [t This library is aimed at developers building Elixir applications that interact with the [**Stellar network**][stellar]. -> **Note** +> [!NOTE] > If you are a smart contract developer building on Soroban, we recommend using [Soroban.ex][soroban.ex], a library built on top of Stellar SDK which offers a developer-friendly interface for interacting with Soroban smart contracts and Soroban-RPC server. #### Protocol Version Support @@ -105,15 +105,15 @@ Stellar relies on public key cryptography to ensure that transactions are secure [Transactions][stellar-docs-tx] are commands that modify the ledger state. They consist of a list of operations (up to 100) used to send payments, enter orders into the decentralized exchange, change settings on accounts, and authorize accounts to hold assets. ```elixir -# set the source account (this accound should exist in the ledger) +# set the source account (this account should exist in the ledger) source_account = Stellar.TxBuild.Account.new("GDC3W2X5KUTZRTQIKXM5D2I5WG5JYSEJQWEELVPQ5YMWZR6CA2JJ35RW") # initialize a transaction -Stellar.TxBuild.new(source_account) +Stellar.TxBuild.new(source_account) # network_passphrase defaults to Stellar.Network.testnet_passphrase() # initialize a transaction with options -# allowed options: memo, sequence_number, base_fee, preconditions -Stellar.TxBuild.new(source_account, memo: memo, sequence_number: sequence_number) +# allowed options: network_passphrase, memo, sequence_number, base_fee, preconditions +Stellar.TxBuild.new(source_account, network_passphrase: Stellar.Network.public_passphrase(), memo: memo, sequence_number: sequence_number) ``` #### Memos @@ -125,7 +125,7 @@ A [memo][stellar-docs-memo] contains optional extra information for the transact * **`MEMO_RETURN`** : A 32 byte hash intended to be interpreted as the hash of the transaction the sender is refunding. ```elixir -# set the source account (this accound should exist in the ledger) +# set the source account (this account should exist in the ledger) source_account = Stellar.TxBuild.Account.new("GDC3W2X5KUTZRTQIKXM5D2I5WG5JYSEJQWEELVPQ5YMWZR6CA2JJ35RW") # build a memo @@ -146,7 +146,7 @@ memo = Stellar.TxBuild.Memo.new(return: "d83f67dc041e66085100859239b58d3f3292455 Each transaction has a [sequence number][stellar-docs-sequence-number] associated with the source account. Transactions follow a strict ordering rule when it comes to processing transactions per account in order to prevent double-spending. ```elixir -# set the source account (this accound should exist in the ledger) +# set the source account (this account should exist in the ledger) source_account = Stellar.TxBuild.Account.new("GDC3W2X5KUTZRTQIKXM5D2I5WG5JYSEJQWEELVPQ5YMWZR6CA2JJ35RW") # fetch next account's sequence number from Horizon @@ -170,7 +170,7 @@ sequence_number = Stellar.TxBuild.SequenceNumber.new(seq_num) Each transaction incurs a [fee][stellar-docs-fee], which is paid by the source account. When you submit a transaction, you set the maximum that you are willing to pay per operation, but you’re charged the minimum fee possible based on network activity. ```elixir -# set the source account (this accound should exist in the ledger) +# set the source account (this account should exist in the ledger) source_account = Stellar.TxBuild.Account.new("GDC3W2X5KUTZRTQIKXM5D2I5WG5JYSEJQWEELVPQ5YMWZR6CA2JJ35RW") # build a fee @@ -199,7 +199,7 @@ Proposed on the [Stellar protocol-19][stellar-protocol-19] implementation, [Prec - **Extra Signers**: A transaction can specify up to two [Extra signers][stellar-docs-extra-signers] (of any type) even if those signatures would not otherwise be required to authorize the transaction. ```elixir -# set the source account (this accound should exist in the ledger) +# set the source account (this account should exist in the ledger) source_account = Stellar.TxBuild.Account.new("GDC3W2X5KUTZRTQIKXM5D2I5WG5JYSEJQWEELVPQ5YMWZR6CA2JJ35RW") # TimeBounds --------------------------------------------------------------------------- @@ -265,7 +265,7 @@ preconditions = [Operations][stellar-docs-list-operations] represent a desired change to the ledger: payments, offers to exchange currency, changes made to account options, etc. Operations are submitted to the Stellar network grouped in a Transaction. Single transactions may have up to 100 operations. ```elixir -# set the source account (this accound should exist in the ledger) +# set the source account (this account should exist in the ledger) source_account = Stellar.TxBuild.Account.new("GDC3W2X5KUTZRTQIKXM5D2I5WG5JYSEJQWEELVPQ5YMWZR6CA2JJ35RW") # build a create_account operation @@ -330,7 +330,7 @@ signature = In some cases, a transaction may need more than one signature. If the transaction has operations with multiple source accounts, it requires the source account signature for each operation. Additional signatures are required if the account associated with the transaction has multiple public keys. ```elixir -# set the source account (this accound should exist in the ledger) +# set the source account (this account should exist in the ledger) source_account = Stellar.TxBuild.Account.new("GDC3W2X5KUTZRTQIKXM5D2I5WG5JYSEJQWEELVPQ5YMWZR6CA2JJ35RW") # build an operation @@ -366,7 +366,7 @@ signature2 = Stellar.TxBuild.Signature.new(ed25519: "SA2NWVOPQMQYAU5RATOE7HJLMPL Once a transaction has been filled out, it is wrapped in a [Transaction envelope][stellar-docs-tx-envelope] containing the transaction as well as a set of signatures. ```elixir -# set the source account (this accound should exist in the ledger) +# set the source account (this account should exist in the ledger) source_account = Stellar.TxBuild.Account.new("GDC3W2X5KUTZRTQIKXM5D2I5WG5JYSEJQWEELVPQ5YMWZR6CA2JJ35RW") # build an operation @@ -395,7 +395,7 @@ source_account The transaction can now be submitted to the Stellar network. ```elixir -# set the source account (this accound should exist in the ledger) +# set the source account (this account should exist in the ledger) source_account = Stellar.TxBuild.Account.new("GDC3W2X5KUTZRTQIKXM5D2I5WG5JYSEJQWEELVPQ5YMWZR6CA2JJ35RW") # fetch next account's sequence number from Horizon diff --git a/config/config.exs b/config/config.exs deleted file mode 100644 index 8233fe92..00000000 --- a/config/config.exs +++ /dev/null @@ -1,3 +0,0 @@ -use Mix.Config - -import_config "#{Mix.env()}.exs" diff --git a/config/dev.exs b/config/dev.exs deleted file mode 100644 index 3c579f70..00000000 --- a/config/dev.exs +++ /dev/null @@ -1,3 +0,0 @@ -use Mix.Config - -config :stellar_sdk, network: :test diff --git a/config/prod.exs b/config/prod.exs deleted file mode 100644 index 9ea33750..00000000 --- a/config/prod.exs +++ /dev/null @@ -1,3 +0,0 @@ -use Mix.Config - -config :stellar_sdk, network: :public diff --git a/config/test.exs b/config/test.exs deleted file mode 100644 index 3c579f70..00000000 --- a/config/test.exs +++ /dev/null @@ -1,3 +0,0 @@ -use Mix.Config - -config :stellar_sdk, network: :test diff --git a/lib/tx_build.ex b/lib/tx_build.ex index adeffcf5..3e0a3028 100644 --- a/lib/tx_build.ex +++ b/lib/tx_build.ex @@ -10,18 +10,24 @@ defmodule Stellar.TxBuild do @type tx :: Transaction.t() @type signatures :: Signature.t() | list(Signature.t()) @type tx_envelope :: TransactionEnvelope.t() | nil + @type network_passphrase :: String.t() @type t :: %__MODULE__{ tx: tx(), signatures: signatures(), - tx_envelope: tx_envelope() + tx_envelope: tx_envelope(), + network_passphrase: network_passphrase() } - defstruct [:tx, :signatures, :tx_envelope] + defstruct [:tx, :signatures, :tx_envelope, :network_passphrase] @impl true def new(account, opts \\ []), do: impl().new(account, opts) + @impl true + def set_network_passphrase(tx, network_passphrase), + do: impl().set_network_passphrase(tx, network_passphrase) + @impl true def add_memo(tx, memo), do: impl().add_memo(tx, memo) @@ -57,8 +63,8 @@ defmodule Stellar.TxBuild do def envelope(tx), do: impl().envelope(tx) @impl true - def sign_envelope(base64_envelope, signatures), - do: impl().sign_envelope(base64_envelope, signatures) + def sign_envelope(base64_envelope, signatures, network_passphrase), + do: impl().sign_envelope(base64_envelope, signatures, network_passphrase) @impl true def hash(tx), do: impl().hash(tx) diff --git a/lib/tx_build/default.ex b/lib/tx_build/default.ex index fbd416bf..f236631f 100644 --- a/lib/tx_build/default.ex +++ b/lib/tx_build/default.ex @@ -3,7 +3,7 @@ defmodule Stellar.TxBuild.Default do Default TxBuild implementation. """ alias StellarBase.XDR.{TransactionExt, SorobanTransactionData} - alias Stellar.TxBuild + alias Stellar.{TxBuild, Network} alias Stellar.TxBuild.{ Account, @@ -33,6 +33,7 @@ defmodule Stellar.TxBuild.Default do @impl true def new(%Account{} = source_account, opts) do + network_passphrase = Keyword.get(opts, :network_passphrase, Network.testnet_passphrase()) sequence_number = Keyword.get(opts, :sequence_number, SequenceNumber.new()) base_fee = Keyword.get(opts, :base_fee, BaseFee.new()) memo = Keyword.get(opts, :memo, Memo.new()) @@ -52,7 +53,13 @@ defmodule Stellar.TxBuild.Default do operations: operations ) do %Transaction{} = transaction -> - {:ok, %TxBuild{tx: transaction, signatures: [], tx_envelope: nil}} + {:ok, + %TxBuild{ + tx: transaction, + signatures: [], + tx_envelope: nil, + network_passphrase: network_passphrase + }} error -> error @@ -61,6 +68,10 @@ defmodule Stellar.TxBuild.Default do def new(_source_account, _opts), do: {:error, :invalid_source_account} + @impl true + def set_network_passphrase({:ok, %TxBuild{} = tx_build}, network_passphrase), + do: {:ok, %{tx_build | network_passphrase: network_passphrase}} + @impl true def add_memo({:ok, %TxBuild{tx: tx} = tx_build}, %Memo{} = memo) do transaction = %{tx | memo: memo} @@ -205,16 +216,29 @@ defmodule Stellar.TxBuild.Default do def sign(error, _signature), do: error @impl true - def build({:ok, %TxBuild{tx: tx, signatures: signatures} = tx_build}) do - {:ok, %{tx_build | tx_envelope: TransactionEnvelope.new(tx, signatures)}} + def build( + {:ok, + %TxBuild{tx: tx, signatures: signatures, network_passphrase: network_passphrase} = + tx_build} + ) do + tx_envelope = + TransactionEnvelope.new( + tx: tx, + signatures: signatures, + network_passphrase: network_passphrase + ) + + {:ok, %{tx_build | tx_envelope: tx_envelope}} end def build(error), do: error @impl true - def envelope({:ok, %TxBuild{tx: tx, signatures: signatures}}) do - tx - |> TransactionEnvelope.new(signatures) + def envelope( + {:ok, %TxBuild{tx: tx, signatures: signatures, network_passphrase: network_passphrase}} + ) do + [tx: tx, signatures: signatures, network_passphrase: network_passphrase] + |> TransactionEnvelope.new() |> TransactionEnvelope.to_xdr() |> TransactionEnvelope.to_base64() |> (&{:ok, &1}).() @@ -223,29 +247,31 @@ defmodule Stellar.TxBuild.Default do def envelope(error), do: error @impl true - def sign_envelope(tx_base64, []), do: tx_base64 - def sign_envelope({:ok, tx_base64}, signatures), do: sign_envelope(tx_base64, signatures) + def sign_envelope(tx_base64, [], _network_passphrase), do: tx_base64 + + def sign_envelope({:ok, tx_base64}, signatures, network_passphrase), + do: sign_envelope(tx_base64, signatures, network_passphrase) - def sign_envelope(tx_base64, [%Signature{} = signature | signatures]) do + def sign_envelope(tx_base64, [%Signature{} = signature | signatures], network_passphrase) do tx_base64 - |> sign_envelope(signature) - |> sign_envelope(signatures) + |> sign_envelope(signature, network_passphrase) + |> sign_envelope(signatures, network_passphrase) end - def sign_envelope(tx_base64, %Signature{} = signature) do + def sign_envelope(tx_base64, %Signature{} = signature, network_passphrase) do tx_base64 - |> TransactionEnvelope.add_signature(signature) + |> TransactionEnvelope.add_signature(signature, network_passphrase) |> TransactionEnvelope.to_base64() |> (&{:ok, &1}).() end - def sign_envelope(_tx_base64, _signature), do: {:error, :invalid_signature} + def sign_envelope(_tx_base64, _signature, _network_passphrase), do: {:error, :invalid_signature} @impl true - def hash({:ok, %TxBuild{tx: tx}}) do + def hash({:ok, %TxBuild{tx: tx, network_passphrase: network_passphrase}}) do tx |> Transaction.to_xdr() - |> TransactionSignature.base_signature() + |> TransactionSignature.base_signature(network_passphrase) |> Base.encode16(case: :lower) |> (&{:ok, &1}).() end diff --git a/lib/tx_build/soroban_authorization_entry.ex b/lib/tx_build/soroban_authorization_entry.ex index c7c4c40a..ef1841b2 100644 --- a/lib/tx_build/soroban_authorization_entry.ex +++ b/lib/tx_build/soroban_authorization_entry.ex @@ -10,7 +10,7 @@ defmodule Stellar.TxBuild.SorobanAuthorizationEntry do alias StellarBase.XDR.SorobanAddressCredentials, as: SorobanAddressCredentialsXDR alias StellarBase.XDR.SorobanAuthorizedInvocation, as: SorobanAuthorizedInvocationXDR - alias StellarBase.XDR.{EnvelopeType, Hash, Int64, SorobanAuthorizationEntry, UInt32} + alias StellarBase.XDR.{EnvelopeType, Int64, SorobanAuthorizationEntry, UInt32} alias Stellar.{KeyPair, Network} alias Stellar.TxBuild.{ @@ -31,6 +31,7 @@ defmodule Stellar.TxBuild.SorobanAuthorizationEntry do @type secret_key :: String.t() @type sign_authorization :: String.t() @type latest_ledger :: non_neg_integer() + @type network_passphrase :: String.t() @type credentials :: SorobanCredentials.t() @type root_invocation :: SorobanAuthorizedInvocation.t() @@ -73,7 +74,11 @@ defmodule Stellar.TxBuild.SorobanAuthorizationEntry do def to_xdr(_struct), do: {:error, :invalid_struct} - @spec sign(credentials :: t(), secret_key :: secret_key()) :: t() | error() + @spec sign( + credentials :: t(), + secret_key :: secret_key(), + network_passphrase :: network_passphrase() + ) :: t() | error() def sign( %__MODULE__{ credentials: %SorobanCredentials{ @@ -86,12 +91,13 @@ defmodule Stellar.TxBuild.SorobanAuthorizationEntry do }, root_invocation: root_invocation } = credentials, - secret_key + secret_key, + network_passphrase ) when is_binary(secret_key) do {public_key, _secret_key} = KeyPair.from_secret_seed(secret_key) raw_public_key = KeyPair.raw_public_key(public_key) - network_id = network_id_xdr() + network_id = Network.network_id(network_passphrase) signature = [ @@ -129,15 +135,17 @@ defmodule Stellar.TxBuild.SorobanAuthorizationEntry do %{credentials | credentials: soroban_address_credentials} end - def sign(_args, _secret_key), do: {:error, :invalid_sign_args} + def sign(_args, _secret_key, _network_passphrase), do: {:error, :invalid_sign_args} @spec sign_xdr( base_64 :: base_64(), secret_key :: secret_key(), - latest_ledger :: latest_ledger() + latest_ledger :: latest_ledger(), + network_passphrase :: network_passphrase() ) :: sign_authorization() | error() - def sign_xdr(base_64, secret_key, latest_ledger) - when is_binary(base_64) and is_binary(secret_key) and is_integer(latest_ledger) do + def sign_xdr(base_64, secret_key, latest_ledger, network_passphrase) + when is_binary(base_64) and is_binary(secret_key) and is_integer(latest_ledger) and + is_binary(network_passphrase) do {%SorobanAuthorizationEntry{ credentials: %{ @@ -160,7 +168,8 @@ defmodule Stellar.TxBuild.SorobanAuthorizationEntry do |> build_signature_from_xdr( signature_expiration_ledger, root_invocation, - secret_key + secret_key, + network_passphrase ) |> (&SCVal.new(vec: [&1])).() |> SCVal.to_xdr() @@ -178,10 +187,8 @@ defmodule Stellar.TxBuild.SorobanAuthorizationEntry do |> Base.encode64() end - def sign_xdr(_base_64, _secret_key, _latest_ledger), do: {:error, :invalid_sign_args} - - @spec network_id_xdr :: binary() - defp network_id_xdr, do: hash(Network.passphrase()) + def sign_xdr(_base_64, _secret_key, _latest_ledger, _network_passphrase), + do: {:error, :invalid_sign_args} @spec hash(data :: binary()) :: binary() defp hash(data), do: :crypto.hash(:sha256, data) @@ -200,21 +207,23 @@ defmodule Stellar.TxBuild.SorobanAuthorizationEntry do nonce :: Int64.t(), signature_expiration_ledger :: UInt32.t(), root_invocation :: SorobanAuthorizedInvocationXDR.t(), - secret_key :: secret_key() + secret_key :: secret_key(), + network_passphrase :: network_passphrase() ) :: SCVal.t() | error() defp build_signature_from_xdr( nonce, signature_expiration_ledger, root_invocation, - secret_key + secret_key, + network_passphrase ) do {public_key, _secret_key} = KeyPair.from_secret_seed(secret_key) raw_public_key = KeyPair.raw_public_key(public_key) envelope_type = EnvelopeType.new(:ENVELOPE_TYPE_SOROBAN_AUTHORIZATION) signature = - network_id_xdr() - |> Hash.new() + network_passphrase + |> Network.network_id_xdr() |> HashIDPreimageSorobanAuthorizationXDR.new( nonce, signature_expiration_ledger, diff --git a/lib/tx_build/spec.ex b/lib/tx_build/spec.ex index 38bdd980..adac0d44 100644 --- a/lib/tx_build/spec.ex +++ b/lib/tx_build/spec.ex @@ -34,6 +34,7 @@ defmodule Stellar.TxBuild.Spec do @type opts :: Keyword.t() @type account :: Account.t() + @type network_passphrase :: String.t() @type sequence_number :: SequenceNumber.t() @type memo :: Memo.t() @type base_fee :: BaseFee.t() @@ -66,6 +67,7 @@ defmodule Stellar.TxBuild.Spec do @type tx_hash :: {:ok, hash()} | {:error, atom()} @callback new(account(), opts()) :: tx_build() + @callback set_network_passphrase(tx_build(), network_passphrase()) :: tx_build() @callback add_memo(tx_build(), memo()) :: tx_build() @callback set_time_bounds(tx_build(), time_bounds()) :: tx_build() @callback set_preconditions(tx_build(), preconditions()) :: tx_build() @@ -77,7 +79,7 @@ defmodule Stellar.TxBuild.Spec do @callback sign(tx_build(), signatures()) :: tx_build() @callback build(tx_build()) :: tx_build() @callback envelope(tx_build()) :: tx_envelope() - @callback sign_envelope(envelope(), signatures()) :: tx_envelope() + @callback sign_envelope(envelope(), signatures(), network_passphrase()) :: tx_envelope() @callback hash(tx_build()) :: tx_hash() @optional_callbacks add_memo: 2, diff --git a/lib/tx_build/transaction_envelope.ex b/lib/tx_build/transaction_envelope.ex index 2b2a0e40..ce41e5bc 100644 --- a/lib/tx_build/transaction_envelope.ex +++ b/lib/tx_build/transaction_envelope.ex @@ -14,20 +14,25 @@ defmodule Stellar.TxBuild.TransactionEnvelope do @type tx_base64 :: String.t() @type signatures :: list(Signature.t()) + @type network_passphrase :: String.t() @type t :: %__MODULE__{tx: Transaction.t(), signatures: signatures()} - defstruct [:tx, :signatures] + defstruct [:tx, :signatures, :network_passphrase] @impl true - def new(%Transaction{} = tx, signatures) when is_list(signatures) do - %__MODULE__{tx: tx, signatures: signatures} + def new(args, _opts \\ []) do + tx = Keyword.get(args, :tx) + signatures = Keyword.get(args, :signatures) + network_passphrase = Keyword.get(args, :network_passphrase) + + %__MODULE__{tx: tx, signatures: signatures, network_passphrase: network_passphrase} end @impl true - def to_xdr(%__MODULE__{tx: tx, signatures: signatures}) do + def to_xdr(%__MODULE__{tx: tx, signatures: signatures, network_passphrase: network_passphrase}) do envelope_type = EnvelopeType.new(:ENVELOPE_TYPE_TX) - decorated_signatures = TransactionSignature.sign(tx, signatures) + decorated_signatures = TransactionSignature.sign(tx, signatures, network_passphrase) tx |> Transaction.to_xdr() @@ -35,11 +40,16 @@ defmodule Stellar.TxBuild.TransactionEnvelope do |> TransactionEnvelope.new(envelope_type) end - @spec add_signature(tx_base64 :: tx_base64, signature :: Signature.t()) :: + @spec add_signature( + tx_base64 :: tx_base64(), + signature :: Signature.t(), + network_passphrase :: network_passphrase() + ) :: TransactionEnvelope.t() - def add_signature(tx_base64, %Signature{} = signature) do + def add_signature(tx_base64, %Signature{} = signature, network_passphrase) do with %TransactionEnvelope{envelope: envelope} = tx_envelope_xdr <- from_base64(tx_base64), - signatures <- TransactionSignature.sign_xdr(tx_envelope_xdr, signature) do + signatures <- + TransactionSignature.sign_xdr(tx_envelope_xdr, signature, network_passphrase) do %{tx_envelope_xdr | envelope: %{envelope | signatures: signatures}} end end diff --git a/lib/tx_build/transaction_signature.ex b/lib/tx_build/transaction_signature.ex index 4f29209e..6986bf98 100644 --- a/lib/tx_build/transaction_signature.ex +++ b/lib/tx_build/transaction_signature.ex @@ -8,7 +8,6 @@ defmodule Stellar.TxBuild.TransactionSignature do alias StellarBase.XDR.{ DecoratedSignatures, EnvelopeType, - Hash, TransactionEnvelope, TransactionSignaturePayload } @@ -17,21 +16,29 @@ defmodule Stellar.TxBuild.TransactionSignature do alias StellarBase.XDR.TransactionSignaturePayloadTaggedTransaction, as: TaggedTransaction @type signatures :: list(Signature.t()) + @type network_passphrase :: String.t() - @spec sign(tx :: Transaction.t(), signatures :: signatures()) :: DecoratedSignatures.t() - def sign(%Transaction{} = tx, signatures) do + @spec sign( + tx :: Transaction.t(), + signatures :: signatures(), + network_passphrase :: network_passphrase() + ) :: DecoratedSignatures.t() + def sign(%Transaction{} = tx, signatures, network_passphrase) do base_signature = tx |> Transaction.to_xdr() - |> base_signature() + |> base_signature(network_passphrase) signatures |> Enum.map(&Signature.to_xdr(&1, base_signature)) |> DecoratedSignatures.new() end - @spec sign_xdr(tx_envelope :: TransactionEnvelope.t(), signature :: Signature.t()) :: - DecoratedSignatures.t() + @spec sign_xdr( + tx_envelope :: TransactionEnvelope.t(), + signature :: Signature.t(), + network_passphrase :: network_passphrase() + ) :: DecoratedSignatures.t() def sign_xdr( %TransactionEnvelope{ envelope: %{ @@ -39,39 +46,36 @@ defmodule Stellar.TxBuild.TransactionSignature do signatures: %DecoratedSignatures{signatures: current_signatures} } }, - %Signature{} = signature + %Signature{} = signature, + network_passphrase ) do - base_signature = base_signature(tx_xdr) + base_signature = base_signature(tx_xdr, network_passphrase) signature |> Signature.to_xdr(base_signature) |> (&DecoratedSignatures.new(current_signatures ++ [&1])).() end - @spec base_signature(tx_xdr :: TransactionXDR.t()) :: binary() - def base_signature(%TransactionXDR{} = tx_xdr) do + @spec base_signature(tx_xdr :: TransactionXDR.t(), network_passphrase :: network_passphrase()) :: + binary() + def base_signature(%TransactionXDR{} = tx_xdr, network_passphrase) do envelope_type = EnvelopeType.new(:ENVELOPE_TYPE_TX) tx_xdr |> TaggedTransaction.new(envelope_type) - |> signature_payload() + |> signature_payload(network_passphrase) end - @spec signature_payload(tagged_tx :: struct()) :: binary() - defp signature_payload(tagged_tx) do - network_id_xdr() + @spec signature_payload(tagged_tx :: struct(), network_passphrase :: network_passphrase()) :: + binary() + defp signature_payload(tagged_tx, network_passphrase) do + network_passphrase + |> Network.network_id_xdr() |> TransactionSignaturePayload.new(tagged_tx) |> TransactionSignaturePayload.encode_xdr!() |> hash() end - @spec network_id_xdr :: Hash.t() - defp network_id_xdr do - Network.passphrase() - |> hash() - |> Hash.new() - end - @spec hash(data :: binary()) :: binary() defp hash(data), do: :crypto.hash(:sha256, data) end diff --git a/lib/util/network.ex b/lib/util/network.ex index f043fadc..70dd560d 100644 --- a/lib/util/network.ex +++ b/lib/util/network.ex @@ -3,6 +3,8 @@ defmodule Stellar.Network do Utility that handles Stellar's network configuration. """ + alias StellarBase.XDR.Hash + @passphrases [ public: "Public Global Stellar Network ; September 2015", test: "Test SDF Network ; September 2015", @@ -17,36 +19,41 @@ defmodule Stellar.Network do local: "http://localhost:8000" ] - @spec public_passphrase() :: String.t() + @type passphrase :: String.t() + @type url :: String.t() + @type hash :: String.t() + + @spec public_passphrase() :: passphrase() def public_passphrase, do: @passphrases[:public] - @spec testnet_passphrase() :: String.t() + @spec testnet_passphrase() :: passphrase() def testnet_passphrase, do: @passphrases[:test] - @spec futurenet_passphrase() :: String.t() + @spec futurenet_passphrase() :: passphrase() def futurenet_passphrase, do: @passphrases[:future] - @spec standalone_passphrase() :: String.t() + @spec standalone_passphrase() :: passphrase() def standalone_passphrase, do: @passphrases[:standalone] - @spec public_horizon_url() :: String.t() + @spec public_horizon_url() :: url() def public_horizon_url, do: @horizon_urls[:public] - @spec testnet_horizon_url() :: String.t() + @spec testnet_horizon_url() :: url() def testnet_horizon_url, do: @horizon_urls[:test] - @spec futurenet_horizon_url() :: String.t() + @spec futurenet_horizon_url() :: url() def futurenet_horizon_url, do: @horizon_urls[:future] - @spec local_horizon_url() :: String.t() + @spec local_horizon_url() :: url() def local_horizon_url, do: @horizon_urls[:local] - @spec passphrase() :: String.t() - def passphrase do - default = @passphrases[:test] - Keyword.get(@passphrases, current(), default) - end + @spec network_id(passphrase :: passphrase()) :: hash() + def network_id(passphrase), do: :crypto.hash(:sha256, passphrase) - @spec current() :: atom() - def current, do: Application.get_env(:stellar_sdk, :network, :test) + @spec network_id_xdr(passphrase :: passphrase()) :: Hash.t() + def network_id_xdr(passphrase) do + passphrase + |> network_id() + |> Hash.new() + end end diff --git a/test/support/xdr_fixtures.ex b/test/support/xdr_fixtures.ex index 649c6901..5503e859 100644 --- a/test/support/xdr_fixtures.ex +++ b/test/support/xdr_fixtures.ex @@ -257,11 +257,15 @@ defmodule Stellar.Test.XDRFixtures do ) end - @spec transaction_envelope_xdr(tx :: Tx.t(), signatures :: list(Signature.t())) :: + @spec transaction_envelope_xdr( + tx :: Tx.t(), + signatures :: list(Signature.t()), + network_passphrase :: String.t() + ) :: TransactionEnvelope.t() - def transaction_envelope_xdr(tx, signatures) do + def transaction_envelope_xdr(tx, signatures, network_passphrase) do envelope_type = EnvelopeType.new(:ENVELOPE_TYPE_TX) - decorated_signatures = TransactionSignature.sign(tx, signatures) + decorated_signatures = TransactionSignature.sign(tx, signatures, network_passphrase) tx |> Tx.to_xdr() diff --git a/test/tx_build/default_test.exs b/test/tx_build/default_test.exs index 18ad5087..58a34bdb 100644 --- a/test/tx_build/default_test.exs +++ b/test/tx_build/default_test.exs @@ -2,7 +2,7 @@ defmodule Stellar.TxBuild.DefaultTest do use ExUnit.Case alias StellarBase.XDR.{SorobanTransactionData, TransactionExt} - alias Stellar.{KeyPair, TxBuild} + alias Stellar.{KeyPair, Network, TxBuild} alias Stellar.TxBuild.{ Account, @@ -35,7 +35,10 @@ defmodule Stellar.TxBuild.DefaultTest do extra_signers = ["GD726E62G6G4ANHWHIQTH5LNMFVF2EQSEXITB6DZCCTKVU6EQRRE2SJS"] # tx_build with empty preconditions - {:ok, %TxBuild{tx: tx}} = tx_build = TxBuild.new(source_account) + network_passphrase = Network.testnet_passphrase() + + {:ok, %TxBuild{tx: tx}} = + tx_build = TxBuild.new(source_account, network_passphrase: network_passphrase) # tx_build with only time_bounds as preconditions tx_build_precond_time = TxBuild.set_time_bounds(tx_build, time_bounds) @@ -54,13 +57,15 @@ defmodule Stellar.TxBuild.DefaultTest do %{ source_account: source_account, + network_passphrase: network_passphrase, keypair: keypair, signature: signature, tx: tx, tx_build: tx_build, tx_build_precond_time: tx_build_precond_time, tx_build_precond_v2: tx_build_precond_v2, - tx_envelope: TransactionEnvelope.new(tx, []), + tx_envelope: + TransactionEnvelope.new(tx: tx, signatures: [], network_passphrase: network_passphrase), tx_envelope_base64: "AAAAAgAAAAD/rxPaN43ANPY6ITP1bWFqXRISJdEw+HkQpqrTxIRiTQAAAGQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABxIRiTQAAAEDGQ1zlNXPps1aYpgCyHFzNgApPhKWhZqXlzPDMYXrZKilBt2SlWDkyki5pkiwKZ5Uc0bLNS1uqu31CJ5GFSWYO", tx_hash: "02eef2a9f2941077b5aa76fb7023494291f9c4e97e65c0e3c705475a69272484" @@ -71,7 +76,11 @@ defmodule Stellar.TxBuild.DefaultTest do {:ok, %TxBuild{tx: ^tx, signatures: [], tx_envelope: nil}} = TxBuild.new(source_account) end - test "new/2 with_options", %{source_account: source_account, keypair: {public_key, _secret}} do + test "new/2 with_options", %{ + source_account: source_account, + keypair: {public_key, _secret}, + network_passphrase: network_passphrase + } do sequence_number = SequenceNumber.new(123_456) base_fee = BaseFee.new(500) memo = Memo.new(text: "TEST") @@ -85,6 +94,7 @@ defmodule Stellar.TxBuild.DefaultTest do {:ok, %TxBuild{ + network_passphrase: ^network_passphrase, tx: %Transaction{ sequence_number: ^sequence_number, base_fee: ^base_fee, @@ -94,6 +104,7 @@ defmodule Stellar.TxBuild.DefaultTest do }} = TxBuild.new( source_account, + network_passphrase: network_passphrase, sequence_number: sequence_number, base_fee: base_fee, memo: memo, @@ -146,6 +157,13 @@ defmodule Stellar.TxBuild.DefaultTest do {:error, :invalid_source_account} = TxBuild.new("ABCD") end + test "set_network_passphrase/2", %{tx_build: tx_build} do + network_passphrase = Network.public_passphrase() + + {:ok, %TxBuild{network_passphrase: ^network_passphrase}} = + TxBuild.set_network_passphrase(tx_build, network_passphrase) + end + test "add_memo/2", %{tx_build: tx_build} do memo = Memo.new(text: "hello") {:ok, %TxBuild{tx: %Transaction{memo: ^memo}}} = TxBuild.add_memo(tx_build, memo) @@ -382,15 +400,23 @@ defmodule Stellar.TxBuild.DefaultTest do {:ok, %TxBuild{signatures: ^signatures}} = TxBuild.sign(tx_build, signatures) end - test "sign_envelope/2", %{keypair: keypair, tx_envelope_base64: tx_envelope_base64} do + test "sign_envelope/3", %{ + keypair: keypair, + tx_envelope_base64: tx_envelope_base64, + network_passphrase: network_passphrase + } do signature = Signature.new(keypair) {:ok, "AAAAAgAAAAD/rxPaN43ANPY6ITP1bWFqXRISJdEw+HkQpqrTxIRiTQAAAGQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACxIRiTQAAAEDGQ1zlNXPps1aYpgCyHFzNgApPhKWhZqXlzPDMYXrZKilBt2SlWDkyki5pkiwKZ5Uc0bLNS1uqu31CJ5GFSWYOxIRiTQAAAEDGQ1zlNXPps1aYpgCyHFzNgApPhKWhZqXlzPDMYXrZKilBt2SlWDkyki5pkiwKZ5Uc0bLNS1uqu31CJ5GFSWYO"} = - TxBuild.sign_envelope(tx_envelope_base64, signature) + TxBuild.sign_envelope(tx_envelope_base64, signature, network_passphrase) end - test "sign_envelope/2 multiple", %{signature: signature, tx_envelope_base64: tx_envelope_base64} do + test "sign_envelope/3 multiple", %{ + signature: signature, + tx_envelope_base64: tx_envelope_base64, + network_passphrase: network_passphrase + } do {pk, sk} = KeyPair.from_secret_seed("SAALZGBDHMY5NQGU2L6G4GHQ65ESCDQD5TNYPWM5AZDVB3HICLKF4KI3") @@ -398,12 +424,17 @@ defmodule Stellar.TxBuild.DefaultTest do {:ok, "AAAAAgAAAAD/rxPaN43ANPY6ITP1bWFqXRISJdEw+HkQpqrTxIRiTQAAAGQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADxIRiTQAAAEDGQ1zlNXPps1aYpgCyHFzNgApPhKWhZqXlzPDMYXrZKilBt2SlWDkyki5pkiwKZ5Uc0bLNS1uqu31CJ5GFSWYOxIRiTQAAAEDGQ1zlNXPps1aYpgCyHFzNgApPhKWhZqXlzPDMYXrZKilBt2SlWDkyki5pkiwKZ5Uc0bLNS1uqu31CJ5GFSWYO8057hgAAAEC70Ava49XnFEQ6d9ed+IvfiMWL6do55bekG9LctPFnjTrRITSFs9cuHTfvbkSTCcFxw5IrZxqgeupuYb+ubU8H"} = - TxBuild.sign_envelope(tx_envelope_base64, signatures) + TxBuild.sign_envelope(tx_envelope_base64, signatures, network_passphrase) end - test "sign_envelope/2 invalid_signature", %{tx_envelope_base64: tx_envelope_base64} do + test "sign_envelope/3 invalid_signature", %{ + tx_envelope_base64: tx_envelope_base64, + network_passphrase: network_passphrase + } do signature = Signature.new({"PUBLIC", "SECRET"}) - {:error, :invalid_signature} = TxBuild.sign_envelope(tx_envelope_base64, signature) + + {:error, :invalid_signature} = + TxBuild.sign_envelope(tx_envelope_base64, signature, network_passphrase) end test "build/1", %{tx_build: tx_build, tx_envelope: tx_envelope} do diff --git a/test/tx_build/soroban_authorization_entry_test.exs b/test/tx_build/soroban_authorization_entry_test.exs index 23cd783e..54210335 100644 --- a/test/tx_build/soroban_authorization_entry_test.exs +++ b/test/tx_build/soroban_authorization_entry_test.exs @@ -13,6 +13,8 @@ defmodule Stellar.TxBuild.SorobanAuthorizationEntryTest do SorobanCredentials } + alias Stellar.Network + setup do fn_args = [SCVal.new(symbol: "dev")] @@ -102,6 +104,7 @@ defmodule Stellar.TxBuild.SorobanAuthorizationEntryTest do "AAAAAQAAAAAAAAAAyU545WHCcUig2re/I2xMg5FaqNroaTV+AXQbahq8ftYOvJBkmBOF7wAAAAAAAAABAAAAAAAAAAEJjPko7iuhBRtsY0aDQ2Einilpmj/rDyGds/qx5seSNAAAAANpbmMAAAAAAgAAABIAAAAAAAAAAMlOeOVhwnFIoNq3vyNsTIORWqja6Gk1fgF0G2oavH7WAAAACQAAAAAAAAAAAAAAAAAAAAIAAAAA", secret_key: "SCAVFA3PI3MJLTQNMXOUNBSEUOSY66YMG3T2KCQKLQBENNVLVKNPV3EK", latest_ledger: 164_256, + network_passphrase: Network.testnet_passphrase(), sign_xdr: "AAAAAQAAAAAAAAAAyU545WHCcUig2re/I2xMg5FaqNroaTV+AXQbahq8ftYOvJBkmBOF7wACgaMAAAAQAAAAAQAAAAEAAAARAAAAAQAAAAIAAAAPAAAACnB1YmxpY19rZXkAAAAAAA0AAAAgyU545WHCcUig2re/I2xMg5FaqNroaTV+AXQbahq8ftYAAAAPAAAACXNpZ25hdHVyZQAAAAAAAA0AAABAIVZ/t4FbgBOE7+B6u41RkQhUrePyoyxrNwGh8oN2HtGtmyuxBwlU49nBUgUwBHmHiQMIMBEW7IbyPNGSuK4YCAAAAAAAAAABCYz5KO4roQUbbGNGg0NhIp4paZo/6w8hnbP6sebHkjQAAAADaW5jAAAAAAIAAAASAAAAAAAAAADJTnjlYcJxSKDat78jbEyDkVqo2uhpNX4BdBtqGrx+1gAAAAkAAAAAAAAAAAAAAAAAAAACAAAAAA==", soroban_auth_entry_with_address_credentials: soroban_auth_entry_with_address_credentials, @@ -133,7 +136,8 @@ defmodule Stellar.TxBuild.SorobanAuthorizationEntryTest do test "sign/2", %{ soroban_auth_entry_with_address_credentials: soroban_auth_entry_with_address_credentials, root_invocation: root_invocation, - secret_key: secret_key + secret_key: secret_key, + network_passphrase: network_passphrase } do %SorobanAuthorizationEntry{ credentials: %SorobanAddressCredentials{ @@ -176,28 +180,44 @@ defmodule Stellar.TxBuild.SorobanAuthorizationEntryTest do } }, root_invocation: ^root_invocation - } = SorobanAuthorizationEntry.sign(soroban_auth_entry_with_address_credentials, secret_key) + } = + SorobanAuthorizationEntry.sign( + soroban_auth_entry_with_address_credentials, + secret_key, + network_passphrase + ) end - test "sign/2 invalid secret_key", %{ - soroban_auth_entry_with_address_credentials: soroban_auth_entry_with_address_credentials + test "sign/4 invalid secret_key", %{ + soroban_auth_entry_with_address_credentials: soroban_auth_entry_with_address_credentials, + network_passphrase: network_passphrase } do {:error, :invalid_sign_args} = - SorobanAuthorizationEntry.sign(soroban_auth_entry_with_address_credentials, :secret_key) + SorobanAuthorizationEntry.sign( + soroban_auth_entry_with_address_credentials, + :secret_key, + network_passphrase + ) end - test "sign_xdr/3", %{ + test "sign_xdr/4", %{ base_64: base_64, secret_key: secret_key, latest_ledger: latest_ledger, + network_passphrase: network_passphrase, sign_xdr: sign_xdr } do - ^sign_xdr = SorobanAuthorizationEntry.sign_xdr(base_64, secret_key, latest_ledger) + ^sign_xdr = + SorobanAuthorizationEntry.sign_xdr(base_64, secret_key, latest_ledger, network_passphrase) end - test "sign_xdr/3 invalid secret_key", %{base_64: base_64, latest_ledger: latest_ledger} do + test "sign_xdr/4 invalid secret_key", %{ + base_64: base_64, + latest_ledger: latest_ledger, + network_passphrase: network_passphrase + } do {:error, :invalid_sign_args} = - SorobanAuthorizationEntry.sign_xdr(base_64, :secret_key, latest_ledger) + SorobanAuthorizationEntry.sign_xdr(base_64, :secret_key, latest_ledger, network_passphrase) end test "to_xdr/1", %{soroban_auth_entry: soroban_auth_entry, xdr: xdr} do diff --git a/test/tx_build/transaction_envelope_test.exs b/test/tx_build/transaction_envelope_test.exs index dcf4eaa7..86e164b3 100644 --- a/test/tx_build/transaction_envelope_test.exs +++ b/test/tx_build/transaction_envelope_test.exs @@ -3,7 +3,7 @@ defmodule Stellar.TxBuild.TransactionEnvelopeTest do alias Stellar.Test.Fixtures.XDR, as: XDRFixtures - alias Stellar.KeyPair + alias Stellar.{Network, KeyPair} alias Stellar.TxBuild.{ Account, @@ -41,20 +41,33 @@ defmodule Stellar.TxBuild.TransactionEnvelopeTest do signature = Signature.new({public_key, secret}) signatures = [signature] + network_passphrase = Network.testnet_passphrase() + + tx_envelope = + TransactionEnvelope.new( + tx: tx, + signatures: signatures, + network_passphrase: network_passphrase + ) %{ tx: tx, signatures: signatures, - tx_envelope: TransactionEnvelope.new(tx, signatures), + network_passphrase: network_passphrase, + tx_envelope: tx_envelope, tx_envelope_xdr: XDRFixtures.transaction_envelope(), tx_envelope_base64: "AAAAAgAAAAD/rxPaN43ANPY6ITP1bWFqXRISJdEw+HkQpqrTxIRiTQAAAfQAAAAAAAHiQAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAP+vE9o3jcA09johM/VtYWpdEhIl0TD4eRCmqtPEhGJNAAAAAADk4cAAAAAAAAAAAcSEYk0AAABA4XBteCIyqJn86GK0xMYA6h2lweeWfo0DNRY+rwiVGlAQyZkV+tYUbR0KmJMzScPRqMX7eEyDdOIMd7IkuEpNAQ==" } end - test "new/2", %{tx: tx, signatures: signatures} do + test "new/2", %{tx: tx, signatures: signatures, network_passphrase: network_passphrase} do %TransactionEnvelope{tx: ^tx, signatures: ^signatures} = - TransactionEnvelope.new(tx, signatures) + TransactionEnvelope.new( + tx: tx, + signatures: signatures, + network_passphrase: network_passphrase + ) end test "to_xdr/1", %{tx_envelope: tx_envelope, tx_envelope_xdr: tx_envelope_xdr} do @@ -76,7 +89,10 @@ defmodule Stellar.TxBuild.TransactionEnvelopeTest do assert_raise ArgumentError, fn -> TransactionEnvelope.from_base64("AAAAA==") end end - test "add_signature/2", %{tx_envelope_base64: tx_envelope_base64} do + test "add_signature/2", %{ + tx_envelope_base64: tx_envelope_base64, + network_passphrase: network_passphrase + } do secret_seed = "SAALZGBDHMY5NQGU2L6G4GHQ65ESCDQD5TNYPWM5AZDVB3HICLKF4KI3" extra_signature = @@ -86,6 +102,7 @@ defmodule Stellar.TxBuild.TransactionEnvelopeTest do xdr = XDRFixtures.transaction_envelope(extra_signatures: [secret_seed]) - ^xdr = TransactionEnvelope.add_signature(tx_envelope_base64, extra_signature) + ^xdr = + TransactionEnvelope.add_signature(tx_envelope_base64, extra_signature, network_passphrase) end end diff --git a/test/tx_build/transaction_signature_test.exs b/test/tx_build/transaction_signature_test.exs index bdf7935c..6d935a12 100644 --- a/test/tx_build/transaction_signature_test.exs +++ b/test/tx_build/transaction_signature_test.exs @@ -1,7 +1,7 @@ defmodule Stellar.TxBuild.TransactionSignatureTest do use ExUnit.Case - alias Stellar.KeyPair + alias Stellar.{KeyPair, Network} alias Stellar.TxBuild.{ Account, @@ -54,24 +54,41 @@ defmodule Stellar.TxBuild.TransactionSignatureTest do signature = Signature.new(keypair1) signature2 = Signature.new(keypair2) - tx_envelope = TransactionEnvelope.new(tx, [signature]) + network_passphrase = Network.testnet_passphrase() + + tx_envelope = + TransactionEnvelope.new( + tx: tx, + signatures: [signature], + network_passphrase: network_passphrase + ) %{ tx: tx, tx_xdr: tx_xdr, tx_envelope: tx_envelope, base_signature: base_signature, + network_passphrase: network_passphrase, decorated_signature: Signature.to_xdr(signature, base_signature), signatures: [signature, signature2] } end - test "sign/2", %{tx: tx, signatures: signatures, decorated_signature: decorated_signature} do + test "sign/3", %{ + tx: tx, + signatures: signatures, + decorated_signature: decorated_signature, + network_passphrase: network_passphrase + } do %DecoratedSignatures{signatures: [^decorated_signature | _signatures]} = - TransactionSignature.sign(tx, signatures) + TransactionSignature.sign(tx, signatures, network_passphrase) end - test "sign_xdr/2", %{tx_envelope: tx_envelope, signatures: [_signature, extra_signature]} do + test "sign_xdr/3", %{ + tx_envelope: tx_envelope, + signatures: [_signature, extra_signature], + network_passphrase: network_passphrase + } do %DecoratedSignatures{ signatures: [ _signature, @@ -80,10 +97,14 @@ defmodule Stellar.TxBuild.TransactionSignatureTest do } = tx_envelope |> TransactionEnvelope.to_xdr() - |> TransactionSignature.sign_xdr(extra_signature) + |> TransactionSignature.sign_xdr(extra_signature, network_passphrase) end - test "base_signature/1", %{tx_xdr: tx_xdr, base_signature: base_signature} do - ^base_signature = TransactionSignature.base_signature(tx_xdr) + test "base_signature/2", %{ + tx_xdr: tx_xdr, + network_passphrase: network_passphrase, + base_signature: base_signature + } do + ^base_signature = TransactionSignature.base_signature(tx_xdr, network_passphrase) end end diff --git a/test/tx_build/tx_build_test.exs b/test/tx_build/tx_build_test.exs index 9ef89257..9f6c2f35 100644 --- a/test/tx_build/tx_build_test.exs +++ b/test/tx_build/tx_build_test.exs @@ -9,6 +9,12 @@ defmodule Stellar.TxBuild.CannedTxBuildImpl do :ok end + @impl true + def set_network_passphrase(_tx, _network_passphrase) do + send(self(), {:set_network_passphrase, "NETWORK_PASSPHRASE_SET"}) + :ok + end + @impl true def add_memo(_tx, _memo) do send(self(), {:add_memo, "MEMO_ADDED"}) @@ -64,7 +70,7 @@ defmodule Stellar.TxBuild.CannedTxBuildImpl do end @impl true - def sign_envelope(_base64, _signatures) do + def sign_envelope(_base64, _signatures, _network_passphrase) do send(self(), {:sign_envelope, "ENVELOPE_SIGNED"}) :ok end @@ -153,7 +159,7 @@ defmodule Stellar.TxBuildTest do end test "sign_envelope/2" do - Stellar.TxBuild.sign_envelope("AAAAA==", :signature) + Stellar.TxBuild.sign_envelope("AAAAA==", :signature, "NETWORK_PASSPHRASE") assert_receive({:sign_envelope, "ENVELOPE_SIGNED"}) end diff --git a/test/util/network_test.exs b/test/util/network_test.exs index 50a55b71..6c692428 100644 --- a/test/util/network_test.exs +++ b/test/util/network_test.exs @@ -2,6 +2,7 @@ defmodule Stellar.NetworkTest do use ExUnit.Case alias Stellar.Network + alias StellarBase.XDR.Hash @public_passphrase "Public Global Stellar Network ; September 2015" @testnet_passphrase "Test SDF Network ; September 2015" @@ -48,4 +49,33 @@ defmodule Stellar.NetworkTest do @local_horizon_url = Network.local_horizon_url() end end + + describe "network ids" do + setup do + %{ + public_network_id: + <<122, 195, 57, 151, 84, 78, 49, 117, 210, 102, 189, 2, 36, 57, 178, 44, 219, 22, 80, + 140, 1, 22, 63, 38, 229, 203, 42, 62, 16, 69, 169, 121>>, + test_network_id: + <<206, 224, 48, 45, 89, 132, 77, 50, 189, 202, 145, 92, 130, 3, 221, 68, 179, 63, 187, + 126, 220, 25, 5, 30, 163, 122, 190, 223, 40, 236, 212, 114>> + } + end + + test "network_id/1 for public network", %{public_network_id: public_network_id} do + ^public_network_id = Network.network_id(@public_passphrase) + end + + test "network_id_xdr/1 for public network", %{public_network_id: public_network_id} do + %Hash{value: ^public_network_id} = Network.network_id_xdr(@public_passphrase) + end + + test "network_id/1 for test network", %{test_network_id: test_network_id} do + ^test_network_id = Network.network_id(@testnet_passphrase) + end + + test "network_id_xdr/1 for test network", %{test_network_id: test_network_id} do + %Hash{value: ^test_network_id} = Network.network_id_xdr(@testnet_passphrase) + end + end end From 29514b1b4db7a6e72478296d2be567f5a004266d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 10:56:07 -0500 Subject: [PATCH 3/5] Update all dependencies (#332) * Update all dependencies * Ignore `ubuntu` update due to OTP version used in CI/CD --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Miguel Nieto <39246879+miguelnietoa@users.noreply.github.com> --- .github/workflows/cd.yml | 8 ++++---- .github/workflows/ci.yml | 10 +++++----- .github/workflows/scorecards.yml | 10 +++++----- mix.exs | 4 ++-- mix.lock | 18 +++++++++--------- renovate.json | 3 +++ 6 files changed, 28 insertions(+), 25 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index fbf7c7f6..f42ada98 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -20,7 +20,7 @@ jobs: HEX_API_KEY: ${{ secrets.HEX_API_KEY }} steps: - name: Harden Runner - uses: step-security/harden-runner@cba0d00b1fc9a034e1e642ea0f1103c282990604 # v2.5.0 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: disable-sudo: true egress-policy: block @@ -28,12 +28,12 @@ jobs: github.com:443 *.hex.pm:443 - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - uses: erlef/setup-elixir@61e01a43a562a89bfc54c7f9a378ff67b03e4a21 # v1.16.0 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: erlef/setup-elixir@904c511e63061a8f501ae4b081ce2c0e9cfc70ab # v1.17.4 with: otp-version: ${{ matrix.otp }} elixir-version: ${{ matrix.elixir }} - - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 + - uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 # v4.0.1 with: path: deps key: ${{ runner.os }}-mix-${{ hashFiles(format('{0}{1}', github.workspace, '/mix.lock')) }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0a9d7ba5..c9f8dced 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: MIX_ENV: test steps: - name: Harden Runner - uses: step-security/harden-runner@cba0d00b1fc9a034e1e642ea0f1103c282990604 # v2.5.0 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: disable-sudo: true egress-policy: block @@ -31,12 +31,12 @@ jobs: github.com:443 *.hex.pm:443 - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - uses: erlef/setup-beam@61e01a43a562a89bfc54c7f9a378ff67b03e4a21 # v1.16.0 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: erlef/setup-beam@904c511e63061a8f501ae4b081ce2c0e9cfc70ab # v1.17.4 with: otp-version: ${{ matrix.otp }} elixir-version: ${{ matrix.elixir }} - - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 + - uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 # v4.0.1 with: path: deps key: ${{ runner.os }}-mix-${{ hashFiles(format('{0}{1}', github.workspace, '/mix.lock')) }} @@ -62,7 +62,7 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Harden Runner - uses: step-security/harden-runner@cba0d00b1fc9a034e1e642ea0f1103c282990604 # v2.5.0 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: disable-sudo: true egress-policy: block diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index e3fecfa5..0803e61a 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -22,7 +22,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@cba0d00b1fc9a034e1e642ea0f1103c282990604 # v2.5.0 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: disable-sudo: true egress-policy: block @@ -38,12 +38,12 @@ jobs: www.bestpractices.dev:443 - name: "Checkout code" - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@08b4669551908b1024bb425080c797723083c031 # v2.2.0 + uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 with: results_file: results.sarif results_format: sarif @@ -62,7 +62,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: SARIF file path: results.sarif @@ -70,6 +70,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@1813ca74c3faaa3a2da2070b9b8a0b3e7373a0d8 # v2.21.0 + uses: github/codeql-action/upload-sarif@8a470fddafa5cbb6266ee11b37ef4d8aae19c571 # v3.24.6 with: sarif_file: results.sarif diff --git a/mix.exs b/mix.exs index 929a8259..3dfed744 100644 --- a/mix.exs +++ b/mix.exs @@ -42,9 +42,9 @@ defmodule Stellar.MixProject do {:hackney, "~> 1.17"}, {:jason, "~> 1.0"}, {:dialyxir, "~> 1.0", only: [:dev], runtime: false}, - {:excoveralls, "~> 0.16", only: :test}, + {:excoveralls, "~> 0.18", only: :test}, {:credo, "~> 1.5", only: [:dev, :test], runtime: false}, - {:ex_doc, "~> 0.30", only: :dev, runtime: false} + {:ex_doc, "~> 0.31", only: :dev, runtime: false} ] end diff --git a/mix.lock b/mix.lock index ec439964..21e2d072 100644 --- a/mix.lock +++ b/mix.lock @@ -1,28 +1,28 @@ %{ "bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"}, "castore": {:hex, :castore, "1.0.4", "ff4d0fb2e6411c0479b1d965a814ea6d00e51eb2f58697446e9c41a97d940b28", [:mix], [], "hexpm", "9418c1b8144e11656f0be99943db4caf04612e3eaecefb5dae9a2a87565584f8"}, - "certifi": {:hex, :certifi, "2.9.0", "6f2a475689dd47f19fb74334859d460a2dc4e3252a3324bd2111b8f0429e7e21", [:rebar3], [], "hexpm", "266da46bdb06d6c6d35fde799bcb28d36d985d424ad7c08b5bb48f5b5cdd4641"}, + "certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"}, "crc": {:hex, :crc, "0.10.5", "ee12a7c056ac498ef2ea985ecdc9fa53c1bfb4e53a484d9f17ff94803707dfd8", [:mix, :rebar3], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "3e673b6495a9525c5c641585af1accba59a1eb33de697bedf341e247012c2c7f"}, "credo": {:hex, :credo, "1.7.0", "6119bee47272e85995598ee04f2ebbed3e947678dee048d10b5feca139435f75", [:mix], [{:bunt, "~> 0.2.1", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "6839fcf63d1f0d1c0f450abc8564a57c43d644077ab96f2934563e68b8a769d7"}, "dialyxir": {:hex, :dialyxir, "1.3.0", "fd1672f0922b7648ff9ce7b1b26fcf0ef56dda964a459892ad15f6b4410b5284", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "00b2a4bcd6aa8db9dcb0b38c1225b7277dca9bc370b6438715667071a304696f"}, - "earmark_parser": {:hex, :earmark_parser, "1.4.33", "3c3fd9673bb5dcc9edc28dd90f50c87ce506d1f71b70e3de69aa8154bc695d44", [:mix], [], "hexpm", "2d526833729b59b9fdb85785078697c72ac5e5066350663e5be6a1182da61b8f"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"}, "ed25519": {:hex, :ed25519, "1.4.1", "479fb83c3e31987c9cad780e6aeb8f2015fb5a482618cdf2a825c9aff809afc4", [:mix], [], "hexpm", "0dacb84f3faa3d8148e81019ca35f9d8dcee13232c32c9db5c2fb8ff48c80ec7"}, "elixir_make": {:hex, :elixir_make, "0.7.7", "7128c60c2476019ed978210c245badf08b03dbec4f24d05790ef791da11aa17c", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "5bc19fff950fad52bbe5f211b12db9ec82c6b34a9647da0c2224b8b8464c7e6c"}, "elixir_xdr": {:hex, :elixir_xdr, "0.3.10", "6443c48f29494b67bf48ef04d2abef2fccfb08d484c688bc3cbd0db390719b24", [:mix], [], "hexpm", "4041f284f802750c9c0b8c0fa5c69cd24911f73668a1d8eb42cbc4c8b8aa5b50"}, "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, - "ex_doc": {:hex, :ex_doc, "0.30.3", "bfca4d340e3b95f2eb26e72e4890da83e2b3a5c5b0e52607333bf5017284b063", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "fbc8702046c1d25edf79de376297e608ac78cdc3a29f075484773ad1718918b6"}, - "excoveralls": {:hex, :excoveralls, "0.16.1", "0bd42ed05c7d2f4d180331a20113ec537be509da31fed5c8f7047ce59ee5a7c5", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "dae763468e2008cf7075a64cb1249c97cb4bc71e236c5c2b5e5cdf1cfa2bf138"}, + "ex_doc": {:hex, :ex_doc, "0.31.1", "8a2355ac42b1cc7b2379da9e40243f2670143721dd50748bf6c3b1184dae2089", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.1", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "3178c3a407c557d8343479e1ff117a96fd31bafe52a039079593fb0524ef61b0"}, + "excoveralls": {:hex, :excoveralls, "0.18.0", "b92497e69465dc51bc37a6422226ee690ab437e4c06877e836f1c18daeb35da9", [:mix], [{:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "1109bb911f3cb583401760be49c02cbbd16aed66ea9509fc5479335d284da60b"}, "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, - "hackney": {:hex, :hackney, "1.18.1", "f48bf88f521f2a229fc7bae88cf4f85adc9cd9bcf23b5dc8eb6a1788c662c4f6", [:rebar3], [{:certifi, "~> 2.9.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a4ecdaff44297e9b5894ae499e9a070ea1888c84afdd1fd9b7b2bc384950128e"}, + "hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~> 2.12.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"}, "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, - "makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"}, + "makeup": {:hex, :makeup, "1.1.1", "fa0bc768698053b2b3869fa8a62616501ff9d11a562f3ce39580d60860c3a55e", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5dc62fbdd0de44de194898b6710692490be74baa02d9d108bc29f007783b0b48"}, "makeup_elixir": {:hex, :makeup_elixir, "0.16.1", "cc9e3ca312f1cfeccc572b37a09980287e243648108384b97ff2b76e505c3555", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e127a341ad1b209bd80f7bd1620a15693a9908ed780c3b763bccf7d200c767c6"}, - "makeup_erlang": {:hex, :makeup_erlang, "0.1.2", "ad87296a092a46e03b7e9b0be7631ddcf64c790fa68a9ef5323b6cbb36affc72", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f3f5a1ca93ce6e092d92b6d9c049bcda58a3b617a8d888f8e7231c85630e8108"}, + "makeup_erlang": {:hex, :makeup_erlang, "0.1.5", "e0ff5a7c708dda34311f7522a8758e23bfcd7d8d8068dc312b5eb41c6fd76eba", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "94d2e986428585a21516d7d7149781480013c56e30c6a233534bedf38867a59a"}, "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"}, - "nimble_parsec": {:hex, :nimble_parsec, "1.3.1", "2c54013ecf170e249e9291ed0a62e5832f70a476c61da16f6aac6dca0189f2af", [:mix], [], "hexpm", "2682e3c0b2eb58d90c6375fc0cc30bc7be06f365bf72608804fb9cffa5e1b167"}, - "parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"}, + "nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"}, + "parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"}, "stellar_base": {:hex, :stellar_base, "0.15.0", "893b7ee194aa0c732fbc16be431418d8269dc0221b70ecdb6320705540ba395f", [:mix], [{:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:crc, "~> 0.10.0", [hex: :crc, repo: "hexpm", optional: false]}, {:elixir_xdr, "~> 0.3", [hex: :elixir_xdr, repo: "hexpm", optional: false]}], "hexpm", "411aba27c89c03ac237457c171740428aef6f958aeebb4811723436e9105dc60"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, diff --git a/renovate.json b/renovate.json index 986bd3dd..0e743dc2 100644 --- a/renovate.json +++ b/renovate.json @@ -2,5 +2,8 @@ "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ "config:semverAllMonthly" + ], + "ignoreDeps": [ + "ubuntu" ] } From 2e843dbc65f0221bb915d8d96550c8d41e73da2f Mon Sep 17 00:00:00 2001 From: Miguel Nieto <39246879+miguelnietoa@users.noreply.github.com> Date: Mon, 4 Mar 2024 11:38:11 -0500 Subject: [PATCH 4/5] Update scorecards allowed-endpoints and Security policy (#355) --- .github/workflows/scorecards.yml | 7 +++---- SECURITY.md | 12 ++++++++++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 0803e61a..022d1a82 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -31,11 +31,10 @@ jobs: api.osv.dev:443 api.securityscorecards.dev:443 bestpractices.coreinfrastructure.org:443 - *.sigstore.dev:443 github.com:443 - sigstore-tuf-root.storage.googleapis.com:443 - oss-fuzz-build-logs.storage.googleapis.com:443 - www.bestpractices.dev:443 + *.sigstore.dev:443 + *.bestpractices.dev:443 + *.storage.googleapis.com:443 - name: "Checkout code" uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 diff --git a/SECURITY.md b/SECURITY.md index 9afd9af7..3a2a1ea3 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,5 +1,13 @@ -# Reporting Security Issues +# Security Policy -To report a security issue, please email [oss@kommit.co](mailto:oss@kommit.co) with a description of the issue, the steps you took to create the issue, affected versions, and, if known, mitigations for the issue. +## Reporting Security Issues + +To report a security issue, you can either: +- Privately report a vulnerability through repository's Security tab by clicking "Report a vulnerability". +- Email us at [oss@kommit.co](mailto:oss@kommit.co). + +Please, make sure to provide a description of the issue, the steps you took to create the issue, affected versions, and, if known, mitigations for the issue. + +## Responsible Disclosure If the issue is confirmed as a vulnerability, we will open a Security Advisory and acknowledge your contributions as part of it. From 87e0000943cb7aec36f192a7e473c7aa097e9bdf Mon Sep 17 00:00:00 2001 From: Miguel Nieto <39246879+miguelnietoa@users.noreply.github.com> Date: Mon, 4 Mar 2024 11:44:12 -0500 Subject: [PATCH 5/5] Prepare release v0.21.0 (#356) --- CHANGELOG.md | 6 ++++++ mix.exs | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 828778f9..7c8c45e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 0.21.0 (04.03.2024) + +* Add Dynamic network configuration: Now you should provide Horizon URL and Network Passphrase. See [Issue #352](https://github.com/kommitters/stellar_sdk/issues/352). +* Update all dependencies. See [PR #332](https://github.com/kommitters/stellar_sdk/pull/332). +* Update scorecards allowed endpoints and Security Policy. See [PR #355](https://github.com/kommitters/stellar_sdk/pull/355). + ## 0.20.0 (20.12.2023) * Add Soroban stable Protocol 20 Support. diff --git a/mix.exs b/mix.exs index 3dfed744..a8630898 100644 --- a/mix.exs +++ b/mix.exs @@ -2,7 +2,7 @@ defmodule Stellar.MixProject do use Mix.Project @github_url "https://github.com/kommitters/stellar_sdk" - @version "0.20.0" + @version "0.21.0" def project do [