From 37de451626a4ec4bf9682139aefb659024259b11 Mon Sep 17 00:00:00 2001 From: jamesm Date: Fri, 1 Nov 2024 09:20:51 -0400 Subject: [PATCH] Add default OptionalParams to existing client - ready for testing non default params as input --- .../jsonrpc/GetAccountInfoContractTest.java | 102 ++++++------ .../GetTokenAccountBalanceContractTest.java | 18 +- .../lmax/solana4j/client/api/SolanaApi.java | 106 +++++++++++- .../api/SolanaClientOptionalParams.java | 27 +++ .../lmax/solana4j/client/api/Transaction.java | 10 +- .../client/api/TransactionResponse.java | 8 +- .../client/jsonrpc/SolanaJsonRpcClient.java | 154 +++++++++++++++--- .../SolanaJsonRpcClientOptionalParams.java | 54 ++++++ .../client/jsonrpc/TransactionDTO.java | 9 +- .../jsonrpc/TransactionResponseDTO.java | 20 ++- .../java/com/lmax/solana4j/SolanaNodeDsl.java | 6 +- .../LegacyTransactionBlobFactory.java | 34 ++-- .../transaction/V0TransactionBlobFactory.java | 34 ++-- 13 files changed, 435 insertions(+), 147 deletions(-) create mode 100644 client/src/main/java/com/lmax/solana4j/client/api/SolanaClientOptionalParams.java create mode 100644 client/src/main/java/com/lmax/solana4j/client/jsonrpc/SolanaJsonRpcClientOptionalParams.java diff --git a/client/src/integration-test/java/com/lmax/solana4j/client/jsonrpc/GetAccountInfoContractTest.java b/client/src/integration-test/java/com/lmax/solana4j/client/jsonrpc/GetAccountInfoContractTest.java index 8af457f9..5f452f14 100644 --- a/client/src/integration-test/java/com/lmax/solana4j/client/jsonrpc/GetAccountInfoContractTest.java +++ b/client/src/integration-test/java/com/lmax/solana4j/client/jsonrpc/GetAccountInfoContractTest.java @@ -1,8 +1,13 @@ package com.lmax.solana4j.client.jsonrpc; +import com.lmax.solana4j.client.api.Commitment; +import com.lmax.solana4j.client.api.SolanaClientOptionalParams; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import java.util.Locale; +import java.util.Map; + import static org.assertj.core.api.Assertions.assertThat; // https://solana.com/docs/rpc/http/getaccountinfo @@ -11,25 +16,6 @@ class GetAccountInfoContractTest extends SolanaClientIntegrationTestBase @Test void shouldGetAccountInfo() throws SolanaJsonRpcClientException { -// { -// "jsonrpc" : "2.0", -// "result" : { -// "context" : { -// "apiVersion" : "1.18.25", -// "slot" : 479 -// }, -// "value" : { -// "data" : [ "", "base64" ], -// "executable" : false, -// "lamports" : 600000, -// "owner" : "11111111111111111111111111111111", -// "rentEpoch" : 18446744073709551615, -// "space" : 0 -// } -// }, -// "id" : 4 -// } - final var accountInfo = api.getAccountInfo(payerAccount).getResponse(); assertThat(accountInfo.getOwner()).isEqualTo("11111111111111111111111111111111"); @@ -42,43 +28,65 @@ void shouldGetAccountInfo() throws SolanaJsonRpcClientException } @Test - @Disabled - void shouldGetTokenAccountInfo() throws SolanaJsonRpcClientException + void shouldGetAccountInfoWithOptionalParams() throws SolanaJsonRpcClientException { -// { -// "jsonrpc" : "2.0", -// "result" : { -// "context" : { -// "apiVersion" : "1.18.25", -// "slot" : 479 -// }, -// "value" : { -// "data" : [ "", "base64" ], -// "executable" : false, -// "lamports" : 600000, -// "owner" : "11111111111111111111111111111111", -// "rentEpoch" : 18446744073709551615, -// "space" : 0 -// } -// }, -// "id" : 4 -// } + final SolanaClientOptionalParams params = new SolanaJsonRpcClientOptionalParams(); + params.addParam("commitment", Commitment.FINALIZED.name().toLowerCase(Locale.UK)); + params.addParam("encoding", "base64"); + params.addParam("dataSlice", Map.of("length", 10, "offset", 0)); + params.addParam("minContextSlot", 1); + + final var accountInfo = api.getAccountInfo(payerAccount, params).getResponse(); + + assertThat(accountInfo.getOwner()).isEqualTo("11111111111111111111111111111111"); + assertThat(accountInfo.getData().get(0)).isEqualTo(""); + assertThat(accountInfo.getData().get(1)).isEqualTo("base64"); + assertThat(accountInfo.getLamports()).isEqualTo(600000L); + assertThat(accountInfo.isExecutable()).isEqualTo(false); + assertThat(accountInfo.getRentEpoch()).isEqualTo("18446744073709551615"); + assertThat(accountInfo.getSpace()).isEqualTo(0); + } + @Test + void shouldGetTokenAccountInfo() throws SolanaJsonRpcClientException + { final var tokenAccountInfo = api.getAccountInfo(tokenAccount).getResponse(); + assertThat(tokenAccountInfo.getOwner()).isEqualTo("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"); + assertThat(tokenAccountInfo.getData().get(0)).isEqualTo( + "DiEMlfEgHelAEAAXQrGw4/3hg4TDygNdPgaE1JMaak97Idi7jw+W6DSraz1ENBeREhm4FdP/BAJ9rBwqRQtkB2Q" + + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); + assertThat(tokenAccountInfo.getData().get(1)).isEqualTo("base64"); + assertThat(tokenAccountInfo.getLamports()).isEqualTo(400000L); + assertThat(tokenAccountInfo.isExecutable()).isEqualTo(false); + assertThat(tokenAccountInfo.getRentEpoch()).isEqualTo("18446744073709551615"); + assertThat(tokenAccountInfo.getSpace()).isEqualTo(165); + } + + @Test + void shouldGetTokenAccountInfoWithOptionalParams() throws SolanaJsonRpcClientException + { + final SolanaClientOptionalParams params = new SolanaJsonRpcClientOptionalParams(); + params.addParam("commitment", Commitment.FINALIZED.name().toLowerCase(Locale.UK)); + params.addParam("encoding", "base64"); + params.addParam("dataSlice", Map.of("length", 10, "offset", 10)); + params.addParam("minContextSlot", 1); + + final var tokenAccountInfo = api.getAccountInfo(tokenAccount, params).getResponse(); -// assertThat(tokenAccountInfo.getOwner()).isEqualTo("11111111111111111111111111111111"); -// assertThat(tokenAccountInfo.getData().get(0)).isEqualTo(""); -// assertThat(tokenAccountInfo.getData().get(1)).isEqualTo("base64"); -// assertThat(tokenAccountInfo.getLamports()).isEqualTo(600000L); -// assertThat(tokenAccountInfo.isExecutable()).isEqualTo(false); -// assertThat(tokenAccountInfo.getRentEpoch()).isEqualTo("18446744073709551615"); -// assertThat(tokenAccountInfo.getSpace()).isEqualTo(0); + assertThat(tokenAccountInfo.getOwner()).isEqualTo("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"); + assertThat(tokenAccountInfo.getData().get(0)).isEqualTo("ABdCsbDj/eGDhA=="); + assertThat(tokenAccountInfo.getData().get(1)).isEqualTo("base64"); + assertThat(tokenAccountInfo.getLamports()).isEqualTo(400000L); + assertThat(tokenAccountInfo.isExecutable()).isEqualTo(false); + assertThat(tokenAccountInfo.getRentEpoch()).isEqualTo("18446744073709551615"); + assertThat(tokenAccountInfo.getSpace()).isEqualTo(165); } @Test @Disabled - void shouldThrowRpcExceptionForAccount() + void shouldThrowRpcExceptionForUnknownAccount() { } diff --git a/client/src/integration-test/java/com/lmax/solana4j/client/jsonrpc/GetTokenAccountBalanceContractTest.java b/client/src/integration-test/java/com/lmax/solana4j/client/jsonrpc/GetTokenAccountBalanceContractTest.java index 97b9295c..c919e569 100644 --- a/client/src/integration-test/java/com/lmax/solana4j/client/jsonrpc/GetTokenAccountBalanceContractTest.java +++ b/client/src/integration-test/java/com/lmax/solana4j/client/jsonrpc/GetTokenAccountBalanceContractTest.java @@ -11,24 +11,8 @@ class GetTokenAccountBalanceContractTest extends SolanaClientIntegrationTestBase @Test void shouldGetTokenAccountBalance() throws SolanaJsonRpcClientException { -// { -// "jsonrpc" : "2.0", -// "result" : { -// "context" : { -// "apiVersion" : "2.0.14", -// "slot" : 258 -// }, -// "value" : { -// "amount" : "100", -// "decimals" : 18, -// "uiAmount" : 1.0E-16, -// "uiAmountString" : "0.0000000000000001" -// } -// }, -// "id" : 4 -// } - final var tokenAccountBalance = api.getTokenAccountBalance(tokenAccount).getResponse(); + assertThat(tokenAccountBalance.getAmount()).isEqualTo("100"); assertThat(tokenAccountBalance.getDecimals()).isEqualTo(18); assertThat(tokenAccountBalance.getUiAmountString()).isEqualTo("0.0000000000000001"); diff --git a/client/src/main/java/com/lmax/solana4j/client/api/SolanaApi.java b/client/src/main/java/com/lmax/solana4j/client/api/SolanaApi.java index b1659ca8..8ab29b51 100644 --- a/client/src/main/java/com/lmax/solana4j/client/api/SolanaApi.java +++ b/client/src/main/java/com/lmax/solana4j/client/api/SolanaApi.java @@ -12,6 +12,18 @@ public interface SolanaApi /** * Sends a transaction to the Solana blockchain. * The transaction is encoded as a base64-encoded string (transaction blob). + * Additional optional parameters can be passed to customize the transaction request. + * + * @param transactionBlob the base64-encoded string representing the transaction + * @param optionalParams a map of optional parameters to customize the transaction request, + * such as `skipPreflight`, `preflightCommitment`, or other Solana JSON-RPC options + * @return the signature of the transaction, which is a base58-encoded string + * @throws SolanaJsonRpcClientException if there is an error with the JSON-RPC request + */ + SolanaClientResponse sendTransaction(String transactionBlob, SolanaClientOptionalParams optionalParams) throws SolanaJsonRpcClientException; + + /** + * Sends a transaction to the Solana blockchain without optional parameters. * * @param transactionBlob the base64-encoded string representing the transaction * @return the signature of the transaction, which is a base58-encoded string @@ -28,17 +40,38 @@ public interface SolanaApi */ SolanaClientResponse getTransaction(String transactionSignature) throws SolanaJsonRpcClientException; + /** + * Retrieves the transaction response for a given transaction signature with optional parameters. + * + * @param transactionSignature the base58-encoded signature of the transaction + * @param optionalParams optional parameters for customizing the request + * @return the {@link TransactionResponse} containing details of the transaction + * @throws SolanaJsonRpcClientException if there is an error with the JSON-RPC request + */ + SolanaClientResponse getTransaction(String transactionSignature, SolanaClientOptionalParams optionalParams) throws SolanaJsonRpcClientException; + /** * Requests an airdrop of lamports to the specified address. * This is used for test purposes to receive lamports (the smallest unit of SOL). * - * @param address the base58-encoded public key of the recipient account + * @param address the base58-encoded public key of the recipient account * @param amountLamports the amount of lamports to be airdropped * @return the transaction signature as a base58-encoded string * @throws SolanaJsonRpcClientException if there is an error with the JSON-RPC request */ SolanaClientResponse requestAirdrop(String address, long amountLamports) throws SolanaJsonRpcClientException; + /** + * Requests an airdrop of lamports to the specified address with optional parameters. + * + * @param address the base58-encoded public key of the recipient account + * @param amountLamports the amount of lamports to be airdropped + * @param optionalParams optional parameters for customizing the request + * @return the transaction signature as a base58-encoded string + * @throws SolanaJsonRpcClientException if there is an error with the JSON-RPC request + */ + SolanaClientResponse requestAirdrop(String address, long amountLamports, SolanaClientOptionalParams optionalParams) throws SolanaJsonRpcClientException; + /** * Retrieves the balance of an account in lamports. * @@ -48,6 +81,16 @@ public interface SolanaApi */ SolanaClientResponse getBalance(String address) throws SolanaJsonRpcClientException; + /** + * Retrieves the balance of an account in lamports with optional parameters. + * + * @param address the base58-encoded public key of the account + * @param optionalParams optional parameters for customizing the request + * @return the balance of the account in lamports + * @throws SolanaJsonRpcClientException if there is an error with the JSON-RPC request + */ + SolanaClientResponse getBalance(String address, SolanaClientOptionalParams optionalParams) throws SolanaJsonRpcClientException; + /** * Retrieves the token account balance of an SPL token account. * @@ -57,6 +100,16 @@ public interface SolanaApi */ SolanaClientResponse getTokenAccountBalance(String address) throws SolanaJsonRpcClientException; + /** + * Retrieves the token account balance of an SPL token account with optional parameters. + * + * @param address the base58-encoded public key of the token account + * @param optionalParams optional parameters for customizing the request + * @return the {@link TokenAmount} representing the token balance of the account + * @throws SolanaJsonRpcClientException if there is an error with the JSON-RPC request + */ + SolanaClientResponse getTokenAccountBalance(String address, SolanaClientOptionalParams optionalParams) throws SolanaJsonRpcClientException; + /** * Retrieves the account information for the specified address. * The account information includes the balance, ownership, and data stored in the account. @@ -67,6 +120,16 @@ public interface SolanaApi */ SolanaClientResponse getAccountInfo(String address) throws SolanaJsonRpcClientException; + /** + * Retrieves the account information for the specified address with optional parameters. + * + * @param address the base58-encoded public key of the account + * @param params optional parameters for customizing the request + * @return the {@link AccountInfo} containing details of the account + * @throws SolanaJsonRpcClientException if there is an error with the JSON-RPC request + */ + SolanaClientResponse getAccountInfo(String address, SolanaClientOptionalParams params) throws SolanaJsonRpcClientException; + /** * Retrieves the current block height of the Solana blockchain. * The block height represents the number of blocks preceding the current block. @@ -76,6 +139,15 @@ public interface SolanaApi */ SolanaClientResponse getBlockHeight() throws SolanaJsonRpcClientException; + /** + * Retrieves the current block height with optional parameters. + * + * @param optionalParams optional parameters for customizing the request + * @return the current block height + * @throws SolanaJsonRpcClientException if there is an error with the JSON-RPC request + */ + SolanaClientResponse getBlockHeight(SolanaClientOptionalParams optionalParams) throws SolanaJsonRpcClientException; + /** * Retrieves the current slot number. * A slot is a specific point in time or block on the Solana blockchain. @@ -85,6 +157,15 @@ public interface SolanaApi */ SolanaClientResponse getSlot() throws SolanaJsonRpcClientException; + /** + * Retrieves the current slot number with optional parameters. + * + * @param optionalParams optional parameters for customizing the request + * @return the current slot number + * @throws SolanaJsonRpcClientException if there is an error with the JSON-RPC request + */ + SolanaClientResponse getSlot(SolanaClientOptionalParams optionalParams) throws SolanaJsonRpcClientException; + /** * Retrieves the most recent blockhash. * The blockhash ensures that a transaction is processed within a specific time window. @@ -94,6 +175,15 @@ public interface SolanaApi */ SolanaClientResponse getLatestBlockhash() throws SolanaJsonRpcClientException; + /** + * Retrieves the most recent blockhash with optional parameters. + * + * @param optionalParams optional parameters for customizing the request + * @return the {@link Blockhash} representing the most recent blockhash + * @throws SolanaJsonRpcClientException if there is an error with the JSON-RPC request + */ + SolanaClientResponse getLatestBlockhash(SolanaClientOptionalParams optionalParams) throws SolanaJsonRpcClientException; + /** * Retrieves the minimum balance required for rent exemption for an account of the given size. * This is the minimum balance needed to ensure the account is rent-exempt. @@ -103,4 +193,16 @@ public interface SolanaApi * @throws SolanaJsonRpcClientException if there is an error with the JSON-RPC request */ SolanaClientResponse getMinimumBalanceForRentExemption(int size) throws SolanaJsonRpcClientException; -} + + /** + * Retrieves the minimum balance required for rent exemption for an account of the given size, + * with additional parameters to customize the request. + * This is the minimum balance needed to ensure the account is rent-exempt. + * + * @param size the size of the account in bytes + * @param optionalParams additional parameters to customize the rent exemption query + * @return the minimum balance in lamports for rent exemption + * @throws SolanaJsonRpcClientException if there is an error with the JSON-RPC request + */ + SolanaClientResponse getMinimumBalanceForRentExemption(int size, SolanaClientOptionalParams optionalParams) throws SolanaJsonRpcClientException; +} \ No newline at end of file diff --git a/client/src/main/java/com/lmax/solana4j/client/api/SolanaClientOptionalParams.java b/client/src/main/java/com/lmax/solana4j/client/api/SolanaClientOptionalParams.java new file mode 100644 index 00000000..9118f41c --- /dev/null +++ b/client/src/main/java/com/lmax/solana4j/client/api/SolanaClientOptionalParams.java @@ -0,0 +1,27 @@ +package com.lmax.solana4j.client.api; + +import java.util.Map; + +/** + * Interface representing optional parameters for customizing Solana JSON-RPC requests. + * Implementations of this interface allow adding parameters that modify request behavior. + */ +public interface SolanaClientOptionalParams +{ + /** + * Adds an optional parameter to the request. + * This can be used to pass additional customization options supported by the Solana JSON-RPC API. + * + * @param key the name of the parameter to add (e.g., "commitment", "encoding") + * @param value the value of the parameter, which can be any supported data type + */ + void addParam(String key, Object value); + + /** + * Retrieves all the optional parameters as a map. + * This map can be used to access the parameters set for a given request. + * + * @return a map containing all the key-value pairs for optional parameters + */ + Map getParams(); +} \ No newline at end of file diff --git a/client/src/main/java/com/lmax/solana4j/client/api/Transaction.java b/client/src/main/java/com/lmax/solana4j/client/api/Transaction.java index a0201822..cce559ca 100644 --- a/client/src/main/java/com/lmax/solana4j/client/api/Transaction.java +++ b/client/src/main/java/com/lmax/solana4j/client/api/Transaction.java @@ -1,5 +1,7 @@ package com.lmax.solana4j.client.api; +import java.util.List; + /** * Represents a transaction on the Solana blockchain. * This interface provides access to the metadata of the transaction and the core transaction data. @@ -15,10 +17,10 @@ public interface Transaction TransactionMetadata getMeta(); /** - * Returns the core transaction data. - * The transaction data contains the instructions, signatures, and other essential components that define the transaction. + * Returns the transaction data and the encoding used. + * The transaction data contains essential components such as instructions, signatures, and account keys involved in the transaction. * - * @return the {@link TransactionData} object representing the core transaction data + * @return a list representing the core transaction data and its encoding */ - TransactionData getTransaction(); + List getTransaction(); } \ No newline at end of file diff --git a/client/src/main/java/com/lmax/solana4j/client/api/TransactionResponse.java b/client/src/main/java/com/lmax/solana4j/client/api/TransactionResponse.java index 236ac2fa..02608c98 100644 --- a/client/src/main/java/com/lmax/solana4j/client/api/TransactionResponse.java +++ b/client/src/main/java/com/lmax/solana4j/client/api/TransactionResponse.java @@ -1,5 +1,7 @@ package com.lmax.solana4j.client.api; +import java.util.List; + /** * Represents the response of a transaction on the Solana blockchain. * This interface provides access to the transaction's metadata, the slot in which the transaction was confirmed, @@ -24,12 +26,12 @@ public interface TransactionResponse long getSlot(); /** - * Returns the core transaction data. + * Returns the transaction data and the encoding used. * The transaction data contains essential components such as instructions, signatures, and account keys involved in the transaction. * - * @return the {@link TransactionData} object representing the core transaction data + * @return a list representing the core transaction data and its encoding */ - TransactionData getTransaction(); + List getTransactionData(); /** * Returns the block time when the transaction was confirmed. diff --git a/client/src/main/java/com/lmax/solana4j/client/jsonrpc/SolanaJsonRpcClient.java b/client/src/main/java/com/lmax/solana4j/client/jsonrpc/SolanaJsonRpcClient.java index 4e34373c..18c8322a 100644 --- a/client/src/main/java/com/lmax/solana4j/client/jsonrpc/SolanaJsonRpcClient.java +++ b/client/src/main/java/com/lmax/solana4j/client/jsonrpc/SolanaJsonRpcClient.java @@ -4,9 +4,9 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.lmax.solana4j.client.api.AccountInfo; import com.lmax.solana4j.client.api.Blockhash; -import com.lmax.solana4j.client.api.Commitment; import com.lmax.solana4j.client.api.SolanaApi; import com.lmax.solana4j.client.api.SolanaClientError; +import com.lmax.solana4j.client.api.SolanaClientOptionalParams; import com.lmax.solana4j.client.api.SolanaClientResponse; import com.lmax.solana4j.client.api.TokenAmount; import com.lmax.solana4j.client.api.TransactionResponse; @@ -18,10 +18,10 @@ import java.net.http.HttpResponse; import java.nio.charset.StandardCharsets; import java.time.Duration; -import java.util.Locale; -import java.util.Map; import java.util.function.Function; +import static com.lmax.solana4j.client.jsonrpc.SolanaJsonRpcClientOptionalParams.defaultOptionalParams; + public class SolanaJsonRpcClient implements SolanaApi { private final String rpcUrl; @@ -55,7 +55,43 @@ public SolanaClientResponse requestAirdrop(final String address, final l new TypeReference>() { }, - dto -> dto, "requestAirdrop", address, amountLamports); + dto -> dto, "requestAirdrop", address, amountLamports, + defaultOptionalParams()); + } + + @Override + public SolanaClientResponse requestAirdrop(final String address, final long amountLamports, final SolanaClientOptionalParams optionalParams) throws SolanaJsonRpcClientException + { + return queryForObject( + new TypeReference>() + { + }, + dto -> dto, "requestAirdrop", address, amountLamports, + optionalParams); + } + + @Override + public SolanaClientResponse sendTransaction(final String transactionBlob) throws SolanaJsonRpcClientException + { + return queryForObject(new TypeReference>() + { + }, + dto -> dto, + "sendTransaction", + transactionBlob, + defaultOptionalParams()); + } + + @Override + public SolanaClientResponse sendTransaction(final String transactionBlob, final SolanaClientOptionalParams optionalParams) throws SolanaJsonRpcClientException + { + return queryForObject(new TypeReference>() + { + }, + dto -> dto, + "sendTransaction", + transactionBlob, + optionalParams.getParams()); } @Override @@ -65,22 +101,17 @@ public SolanaClientResponse getTransaction(final String tra { }, dto -> dto, "getTransaction", transactionSignature, - Map.of( - "econding", "jsonParsed", - "maxSupportedTransactionVersion", 0 - ) - ); + defaultOptionalParams()); } @Override - public SolanaClientResponse sendTransaction(final String transactionBlob) throws SolanaJsonRpcClientException + public SolanaClientResponse getTransaction(final String transactionSignature, final SolanaClientOptionalParams optionalParams) throws SolanaJsonRpcClientException { - return queryForObject(new TypeReference>() + return queryForObject(new TypeReference>() { }, - dto -> dto, "sendTransaction", transactionBlob, - Map.of("preflightCommitment", Commitment.FINALIZED.toString().toLowerCase(Locale.UK)) - ); + dto -> dto, "getTransaction", transactionSignature, + optionalParams); } @Override @@ -89,7 +120,18 @@ public SolanaClientResponse getBalance(final String address) throws Solana return queryForObject(new TypeReference<>() { }, - BalanceDTO::getValue, "getBalance", address); + BalanceDTO::getValue, "getBalance", address, + defaultOptionalParams()); + } + + @Override + public SolanaClientResponse getBalance(final String address, final SolanaClientOptionalParams optionalParams) throws SolanaJsonRpcClientException + { + return queryForObject(new TypeReference<>() + { + }, + BalanceDTO::getValue, "getBalance", address, + optionalParams); } @Override @@ -99,7 +141,19 @@ public SolanaClientResponse getTokenAccountBalance(final String add new TypeReference<>() { }, - TokenAmountDTO::getValue, "getTokenAccountBalance", address); + TokenAmountDTO::getValue, "getTokenAccountBalance", address, + defaultOptionalParams()); + } + + @Override + public SolanaClientResponse getTokenAccountBalance(final String address, final SolanaClientOptionalParams optionalParams) throws SolanaJsonRpcClientException + { + return queryForObject( + new TypeReference<>() + { + }, + TokenAmountDTO::getValue, "getTokenAccountBalance", address, + optionalParams); } @Override @@ -109,7 +163,18 @@ public SolanaClientResponse getAccountInfo(final String address) th { }, AccountInfoDTO::getValue, "getAccountInfo", address, - Map.of("encoding", "base64") + defaultOptionalParams() + ); + } + + @Override + public SolanaClientResponse getAccountInfo(final String address, final SolanaClientOptionalParams solanaClientOptionalParams) throws SolanaJsonRpcClientException + { + return queryForObject(new TypeReference<>() + { + }, + AccountInfoDTO::getValue, "getAccountInfo", address, + solanaClientOptionalParams.getParams() ); } @@ -119,9 +184,18 @@ public SolanaClientResponse getBlockHeight() throws SolanaJsonRpcClientExc return queryForObject(new TypeReference>() { }, - dto -> dto, "getBlockHeight" - ); + dto -> dto, "getBlockHeight", + defaultOptionalParams()); + } + @Override + public SolanaClientResponse getBlockHeight(final SolanaClientOptionalParams optionalParams) throws SolanaJsonRpcClientException + { + return queryForObject(new TypeReference>() + { + }, + dto -> dto, "getBlockHeight", + optionalParams); } @Override @@ -130,8 +204,18 @@ public SolanaClientResponse getSlot() throws SolanaJsonRpcClientException return queryForObject(new TypeReference>() { }, - dto -> dto, "getSlot" - ); + dto -> dto, "getSlot", + defaultOptionalParams()); + } + + @Override + public SolanaClientResponse getSlot(final SolanaClientOptionalParams optionalParams) throws SolanaJsonRpcClientException + { + return queryForObject(new TypeReference>() + { + }, + dto -> dto, "getSlot", + optionalParams); } @Override @@ -140,8 +224,18 @@ public SolanaClientResponse getLatestBlockhash() throws SolanaJsonRpc return queryForObject(new TypeReference<>() { }, - BlockhashDTO::getValue, "getLatestBlockhash" - ); + BlockhashDTO::getValue, "getLatestBlockhash", + defaultOptionalParams()); + } + + @Override + public SolanaClientResponse getLatestBlockhash(final SolanaClientOptionalParams optionalParams) throws SolanaJsonRpcClientException + { + return queryForObject(new TypeReference<>() + { + }, + BlockhashDTO::getValue, "getLatestBlockhash", + optionalParams); } @Override @@ -151,7 +245,19 @@ public SolanaClientResponse getMinimumBalanceForRentExemption(final int si new TypeReference>() { }, - dto -> dto, "getMinimumBalanceForRentExemption", size); + dto -> dto, "getMinimumBalanceForRentExemption", size, + defaultOptionalParams()); + } + + @Override + public SolanaClientResponse getMinimumBalanceForRentExemption(final int size, final SolanaClientOptionalParams optionalParams) throws SolanaJsonRpcClientException + { + return queryForObject( + new TypeReference>() + { + }, + dto -> dto, "getMinimumBalanceForRentExemption", size, + optionalParams); } private SolanaClientResponse queryForObject( diff --git a/client/src/main/java/com/lmax/solana4j/client/jsonrpc/SolanaJsonRpcClientOptionalParams.java b/client/src/main/java/com/lmax/solana4j/client/jsonrpc/SolanaJsonRpcClientOptionalParams.java new file mode 100644 index 00000000..85f8b42a --- /dev/null +++ b/client/src/main/java/com/lmax/solana4j/client/jsonrpc/SolanaJsonRpcClientOptionalParams.java @@ -0,0 +1,54 @@ +package com.lmax.solana4j.client.jsonrpc; + +import com.lmax.solana4j.client.api.Commitment; +import com.lmax.solana4j.client.api.SolanaClientOptionalParams; + +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +class SolanaJsonRpcClientOptionalParams implements SolanaClientOptionalParams +{ + private final Map optionalParams = new HashMap<>(); + + @Override + public void addParam(final String key, final Object value) + { + if (key.equals("encoding") && value.equals("jsonParsed")) + { + throw new UnsupportedOperationException("If you want 'jsonParsed', you must use" + + "the dedicated endpoint. It can not be provided through SolanaClientOptionalParams."); + } + optionalParams.put(key, value); + } + + @Override + public Map getParams() + { + return optionalParams; + } + + /** + * Creates and returns a default instance of {@link SolanaClientOptionalParams} as a {@link Map}. + * This instance contains a set of commonly used default parameters for JSON-RPC requests. + * By default, it includes the following parameters: + *
    + *
  • encoding: "base64" - Specifies that the data should be encoded in base64 format.
  • + *
  • commitment: "finalized" - Sets the commitment level to "finalized" for queries, ensuring the request is processed with finalized data.
  • + *
  • maxSupportedTransactionVersion: 0 - Indicates the maximum supported version of the transaction. + * Setting it to 0 specifies the use of versioned transactions.
  • + *
+ * + * @return a {@link Map} containing default parameters to be used in JSON-RPC requests + */ + public static Map defaultOptionalParams() + { + final SolanaClientOptionalParams params = new SolanaJsonRpcClientOptionalParams(); + + params.addParam("encoding", "base64"); + params.addParam("commitment", Commitment.FINALIZED.name().toLowerCase(Locale.UK)); + params.addParam("maxSupportedTransactionVersion", 0); + + return params.getParams(); + } +} diff --git a/client/src/main/java/com/lmax/solana4j/client/jsonrpc/TransactionDTO.java b/client/src/main/java/com/lmax/solana4j/client/jsonrpc/TransactionDTO.java index f0c344eb..7ec89435 100644 --- a/client/src/main/java/com/lmax/solana4j/client/jsonrpc/TransactionDTO.java +++ b/client/src/main/java/com/lmax/solana4j/client/jsonrpc/TransactionDTO.java @@ -3,18 +3,19 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.lmax.solana4j.client.api.Transaction; -import com.lmax.solana4j.client.api.TransactionData; import com.lmax.solana4j.client.api.TransactionMetadata; +import java.util.List; + final class TransactionDTO implements Transaction { private final MetaDTO metaImpl; - private final TransactionDataDTO transaction; + private final List transaction; @JsonCreator TransactionDTO( final @JsonProperty("meta") MetaDTO metaImpl, - final @JsonProperty("transaction") TransactionDataDTO transaction) + final @JsonProperty("transaction") List transaction) { this.metaImpl = metaImpl; this.transaction = transaction; @@ -27,7 +28,7 @@ public TransactionMetadata getMeta() } @Override - public TransactionData getTransaction() + public List getTransaction() { return transaction; } diff --git a/client/src/main/java/com/lmax/solana4j/client/jsonrpc/TransactionResponseDTO.java b/client/src/main/java/com/lmax/solana4j/client/jsonrpc/TransactionResponseDTO.java index 193cb874..c3a611d7 100644 --- a/client/src/main/java/com/lmax/solana4j/client/jsonrpc/TransactionResponseDTO.java +++ b/client/src/main/java/com/lmax/solana4j/client/jsonrpc/TransactionResponseDTO.java @@ -2,22 +2,23 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import com.lmax.solana4j.client.api.TransactionData; import com.lmax.solana4j.client.api.TransactionMetadata; import com.lmax.solana4j.client.api.TransactionResponse; +import java.util.List; + final class TransactionResponseDTO implements TransactionResponse { private final MetaDTO metaImpl; private final long slot; - private final TransactionDataDTO transaction; + private final List transaction; private final Long blockTime; @JsonCreator TransactionResponseDTO( final @JsonProperty("meta") MetaDTO metaImpl, final @JsonProperty("slot") long slot, - final @JsonProperty("transaction") TransactionDataDTO transaction, + final @JsonProperty("transaction") List transaction, final @JsonProperty("blockTime") Long blockTime) { this.metaImpl = metaImpl; @@ -40,7 +41,7 @@ public long getSlot() } @Override - public TransactionData getTransaction() + public List getTransactionData() { return transaction; } @@ -54,10 +55,11 @@ public Long getBlockTime() @Override public String toString() { - return "TransactionResponse{" + - "meta=" + metaImpl + - ", slot=" + slot + - ", transaction=" + transaction + - '}'; + return "TransactionResponseDTO{" + + "metaImpl=" + metaImpl + + ", slot=" + slot + + ", transaction=" + transaction + + ", blockTime=" + blockTime + + '}'; } } \ No newline at end of file diff --git a/message-encoding/src/test-support/java/com/lmax/solana4j/SolanaNodeDsl.java b/message-encoding/src/test-support/java/com/lmax/solana4j/SolanaNodeDsl.java index 7eef2592..f1c72f11 100644 --- a/message-encoding/src/test-support/java/com/lmax/solana4j/SolanaNodeDsl.java +++ b/message-encoding/src/test-support/java/com/lmax/solana4j/SolanaNodeDsl.java @@ -757,9 +757,9 @@ public void setBpfUpgradeableProgramUpgradeAuthority(final String... args) .collect(Collectors.toList()); final String transactionSignature = solanaDriver.setBpfUpgradeableProgramUpgradeAuthority( - Solana.account(SolanaEncoding.decodeBase58(bpfUpgradeableProgram)), - Solana.account(SolanaEncoding.decodeBase58(oldUpgradeAuthorityPublicKey)), - Solana.account(SolanaEncoding.decodeBase58(newUpgradeAuthority)), + Solana.account(bpfUpgradeableProgram), + Solana.account(oldUpgradeAuthorityPublicKey), + Solana.account(newUpgradeAuthority), payer.getSolana4jPublicKey(), List.of(payer, new TestKeyPair(oldUpgradeAuthorityPublicKey, oldUpgradeAuthorityPrivateKey)), addressLookupTables); diff --git a/message-encoding/src/test-support/java/com/lmax/solana4j/transaction/LegacyTransactionBlobFactory.java b/message-encoding/src/test-support/java/com/lmax/solana4j/transaction/LegacyTransactionBlobFactory.java index 48c1fe83..fe601e60 100644 --- a/message-encoding/src/test-support/java/com/lmax/solana4j/transaction/LegacyTransactionBlobFactory.java +++ b/message-encoding/src/test-support/java/com/lmax/solana4j/transaction/LegacyTransactionBlobFactory.java @@ -10,7 +10,6 @@ import com.lmax.solana4j.api.Slot; import com.lmax.solana4j.domain.TestKeyPair; import com.lmax.solana4j.domain.TokenProgram; -import com.lmax.solana4j.encoding.SolanaEncoding; import com.lmax.solana4j.programs.AddressLookupTableProgram; import com.lmax.solana4j.programs.AssociatedTokenProgram; import com.lmax.solana4j.programs.BpfLoaderUpgradeableProgram; @@ -20,6 +19,7 @@ import com.lmax.solana4j.sign.BouncyCastleSigner; import java.nio.ByteBuffer; +import java.util.Base64; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -61,7 +61,7 @@ public String solTransfer( } signedMessageBuilder.build(); - return base58encode(buffer); + return base64Encode(buffer); } @Override @@ -102,7 +102,7 @@ public String tokenTransfer( signedMessageBuilder.build(); - return base58encode(buffer); + return base64Encode(buffer); } @Override @@ -139,7 +139,7 @@ public String mintTo( signedMessageBuilder.build(); - return base58encode(buffer); + return base64Encode(buffer); } @Override @@ -185,7 +185,7 @@ public String createMintAccount( } signedMessageBuilder.build(); - return base58encode(buffer); + return base64Encode(buffer); } @Override @@ -229,7 +229,7 @@ public String createMultiSigAccount( } signedMessageBuilder.build(); - return base58encode(buffer); + return base64Encode(buffer); } @Override @@ -268,7 +268,7 @@ public String createNonce( } signedMessageBuilder.build(); - return base58encode(buffer); + return base64Encode(buffer); } @Override @@ -312,7 +312,7 @@ public String createTokenAccount( } signedMessageBuilder.build(); - return base58encode(buffer); + return base64Encode(buffer); } @Override @@ -348,7 +348,7 @@ public String createAddressLookupTable( } signedMessageBuilder.build(); - return base58encode(buffer); + return base64Encode(buffer); } @Override @@ -385,7 +385,7 @@ public String extendAddressLookupTable( } signedMessageBuilder.build(); - return base58encode(buffer); + return base64Encode(buffer); } @Override @@ -417,7 +417,7 @@ public String advanceNonce( } signedMessageBuilder.build(); - return base58encode(buffer); + return base64Encode(buffer); } @Override @@ -458,7 +458,7 @@ public String createAssociatedTokenAccount( } signedMessageBuilder.build(); - return base58encode(buffer); + return base64Encode(buffer); } @Override @@ -498,7 +498,7 @@ public String setTokenAccountAuthority( } signedMessageBuilder.build(); - return base58encode(buffer); + return base64Encode(buffer); } @Override @@ -525,7 +525,7 @@ public String setComputeUnits(final int computeUnitLimit, final long computeUnit } signedMessageBuilder.build(); - return base58encode(buffer); + return base64Encode(buffer); } @Override @@ -561,11 +561,11 @@ public String setBpfUpgradeableProgramUpgradeAuthority( } signedMessageBuilder.build(); - return base58encode(buffer); + return base64Encode(buffer); } - private static String base58encode(final ByteBuffer bytes) + private static String base64Encode(final ByteBuffer bytes) { - return SolanaEncoding.encodeBase58(ByteBufferPrimitiveArray.copy(bytes)); + return Base64.getEncoder().encodeToString(ByteBufferPrimitiveArray.copy(bytes)); } } diff --git a/message-encoding/src/test-support/java/com/lmax/solana4j/transaction/V0TransactionBlobFactory.java b/message-encoding/src/test-support/java/com/lmax/solana4j/transaction/V0TransactionBlobFactory.java index c0c509ef..fb70b7e0 100644 --- a/message-encoding/src/test-support/java/com/lmax/solana4j/transaction/V0TransactionBlobFactory.java +++ b/message-encoding/src/test-support/java/com/lmax/solana4j/transaction/V0TransactionBlobFactory.java @@ -10,7 +10,6 @@ import com.lmax.solana4j.api.Slot; import com.lmax.solana4j.domain.TestKeyPair; import com.lmax.solana4j.domain.TokenProgram; -import com.lmax.solana4j.encoding.SolanaEncoding; import com.lmax.solana4j.programs.AddressLookupTableProgram; import com.lmax.solana4j.programs.AssociatedTokenProgram; import com.lmax.solana4j.programs.BpfLoaderUpgradeableProgram; @@ -19,6 +18,7 @@ import com.lmax.solana4j.sign.BouncyCastleSigner; import java.nio.ByteBuffer; +import java.util.Base64; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -58,7 +58,7 @@ public String solTransfer( } signedMessageBuilder.build(); - return base58encode(buffer); + return base64encode(buffer); } @Override @@ -99,7 +99,7 @@ public String tokenTransfer( signedMessageBuilder.build(); - return base58encode(buffer); + return base64encode(buffer); } @Override @@ -136,7 +136,7 @@ public String mintTo( signedMessageBuilder.build(); - return base58encode(buffer); + return base64encode(buffer); } @Override @@ -183,7 +183,7 @@ public String createMintAccount( } signedMessageBuilder.build(); - return base58encode(buffer); + return base64encode(buffer); } @Override @@ -228,7 +228,7 @@ public String createMultiSigAccount( } signedMessageBuilder.build(); - return base58encode(buffer); + return base64encode(buffer); } @Override @@ -267,7 +267,7 @@ public String createNonce( } signedMessageBuilder.build(); - return base58encode(buffer); + return base64encode(buffer); } @Override @@ -312,7 +312,7 @@ public String createTokenAccount( } signedMessageBuilder.build(); - return base58encode(buffer); + return base64encode(buffer); } @Override @@ -348,7 +348,7 @@ public String createAddressLookupTable( } signedMessageBuilder.build(); - return base58encode(buffer); + return base64encode(buffer); } @Override @@ -386,7 +386,7 @@ public String extendAddressLookupTable( } signedMessageBuilder.build(); - return base58encode(buffer); + return base64encode(buffer); } @Override @@ -416,7 +416,7 @@ public String advanceNonce( } signedMessageBuilder.build(); - return base58encode(buffer); + return base64encode(buffer); } @Override @@ -453,7 +453,7 @@ public String createAssociatedTokenAccount( } signedMessageBuilder.build(); - return base58encode(buffer); + return base64encode(buffer); } @Override @@ -492,7 +492,7 @@ public String setTokenAccountAuthority( } signedMessageBuilder.build(); - return base58encode(buffer); + return base64encode(buffer); } @Override @@ -522,7 +522,7 @@ public String setComputeUnits( } signedMessageBuilder.build(); - return base58encode(buffer); + return base64encode(buffer); } @Override @@ -559,11 +559,11 @@ public String setBpfUpgradeableProgramUpgradeAuthority( } signedMessageBuilder.build(); - return base58encode(buffer); + return base64encode(buffer); } - private static String base58encode(final ByteBuffer bytes) + private static String base64encode(final ByteBuffer bytes) { - return SolanaEncoding.encodeBase58(ByteBufferPrimitiveArray.copy(bytes)); + return Base64.getEncoder().encodeToString(ByteBufferPrimitiveArray.copy(bytes)); } }