diff --git a/.gradle/8.5/checksums/checksums.lock b/.gradle/8.5/checksums/checksums.lock
new file mode 100644
index 00000000..70309d0c
Binary files /dev/null and b/.gradle/8.5/checksums/checksums.lock differ
diff --git a/.gradle/8.5/dependencies-accessors/dependencies-accessors.lock b/.gradle/8.5/dependencies-accessors/dependencies-accessors.lock
new file mode 100644
index 00000000..e352785b
Binary files /dev/null and b/.gradle/8.5/dependencies-accessors/dependencies-accessors.lock differ
diff --git a/.gradle/8.5/fileChanges/last-build.bin b/.gradle/8.5/fileChanges/last-build.bin
new file mode 100644
index 00000000..f76dd238
Binary files /dev/null and b/.gradle/8.5/fileChanges/last-build.bin differ
diff --git a/.gradle/8.5/fileHashes/fileHashes.lock b/.gradle/8.5/fileHashes/fileHashes.lock
new file mode 100644
index 00000000..c31107e2
Binary files /dev/null and b/.gradle/8.5/fileHashes/fileHashes.lock differ
diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock
new file mode 100644
index 00000000..f6798826
Binary files /dev/null and b/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ
diff --git a/pom.xml b/pom.xml
index 23c3d14d..ce6ecd3e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -18,7 +18,7 @@
scm:git:git://github.com/skynetcap/solanaj.git
scm:git:ssh://github.com/skynetcap/solanaj.git
https://github.com/skynetcap/solanaj/tree/main
-
+
Michael Morrell
@@ -42,7 +42,7 @@
org.bitcoinj
bitcoinj-core
- 0.16.3
+ 0.17
com.google.protobuf
diff --git a/src/main/java/org/p2p/solanaj/core/Account.java b/src/main/java/org/p2p/solanaj/core/Account.java
index 7be0df15..4f151ea1 100644
--- a/src/main/java/org/p2p/solanaj/core/Account.java
+++ b/src/main/java/org/p2p/solanaj/core/Account.java
@@ -5,7 +5,7 @@
import java.util.List;
import org.bitcoinj.crypto.*;
-import org.bitcoinj.core.Base58;
+import org.bitcoinj.base.Base58;
import org.p2p.solanaj.utils.TweetNaclFast;
import org.p2p.solanaj.utils.bip32.wallet.SolanaBip44;
import org.p2p.solanaj.utils.bip32.wallet.DerivableType;
@@ -30,7 +30,7 @@ public static Account fromMnemonic(List words, String passphrase) {
byte[] seed = MnemonicCode.toSeed(words, passphrase);
DeterministicKey masterPrivateKey = HDKeyDerivation.createMasterPrivateKey(seed);
DeterministicHierarchy deterministicHierarchy = new DeterministicHierarchy(masterPrivateKey);
- DeterministicKey child = deterministicHierarchy.get(HDUtils.parsePath("M/501H/0H/0/0"), true, true);
+ DeterministicKey child = deterministicHierarchy.get(HDPath.parsePath("M/501H/0H/0/0"), true, true);
TweetNaclFast.Signature.KeyPair keyPair = TweetNaclFast.Signature.keyPair_fromSeed(child.getPrivKeyBytes());
return new Account(keyPair);
}
diff --git a/src/main/java/org/p2p/solanaj/core/Message.java b/src/main/java/org/p2p/solanaj/core/Message.java
index 1c5bbda0..7ad6024d 100644
--- a/src/main/java/org/p2p/solanaj/core/Message.java
+++ b/src/main/java/org/p2p/solanaj/core/Message.java
@@ -1,6 +1,6 @@
package org.p2p.solanaj.core;
-import org.bitcoinj.core.Base58;
+import org.bitcoinj.base.Base58;
import org.p2p.solanaj.utils.ShortvecEncoding;
import java.nio.ByteBuffer;
@@ -41,7 +41,7 @@ int getLength() {
private String recentBlockhash;
private AccountKeysList accountKeys;
private List instructions;
- private Account feePayer;
+ private PublicKey feePayerPublicKey;
public Message() {
this.accountKeys = new AccountKeysList();
@@ -143,8 +143,8 @@ public byte[] serialize() {
return out.array();
}
- protected void setFeePayer(Account feePayer) {
- this.feePayer = feePayer;
+ protected void setFeePayerPublicKey(PublicKey feePayerPublicKey) {
+ this.feePayerPublicKey = feePayerPublicKey;
}
private List getAccountKeys() {
@@ -159,7 +159,7 @@ private List getAccountKeys() {
.collect(Collectors.toList());
}
- int feePayerIndex = findAccountIndex(keysList, feePayer.getPublicKey());
+ int feePayerIndex = findAccountIndex(keysList, feePayerPublicKey);
List newList = new ArrayList();
AccountMeta feePayerMeta = keysList.get(feePayerIndex);
newList.add(new AccountMeta(feePayerMeta.getPublicKey(), true, true));
diff --git a/src/main/java/org/p2p/solanaj/core/PublicKey.java b/src/main/java/org/p2p/solanaj/core/PublicKey.java
index eec1c1b2..160de908 100644
--- a/src/main/java/org/p2p/solanaj/core/PublicKey.java
+++ b/src/main/java/org/p2p/solanaj/core/PublicKey.java
@@ -7,8 +7,8 @@
import java.util.List;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import org.bitcoinj.core.Base58;
-import org.bitcoinj.core.Sha256Hash;
+import org.bitcoinj.base.Base58;
+import org.bitcoinj.base.Sha256Hash;
import org.p2p.solanaj.utils.ByteUtils;
import org.p2p.solanaj.utils.PublicKeySerializer;
import org.p2p.solanaj.utils.TweetNaclFast;
diff --git a/src/main/java/org/p2p/solanaj/core/Transaction.java b/src/main/java/org/p2p/solanaj/core/Transaction.java
index bab10710..554ee4dc 100644
--- a/src/main/java/org/p2p/solanaj/core/Transaction.java
+++ b/src/main/java/org/p2p/solanaj/core/Transaction.java
@@ -5,8 +5,9 @@
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
+import java.util.function.Function;
-import org.bitcoinj.core.Base58;
+import org.bitcoinj.base.Base58;
import org.p2p.solanaj.utils.ShortvecEncoding;
import org.p2p.solanaj.utils.TweetNaclFast;
@@ -76,8 +77,7 @@ public void sign(List signers) {
}
Account feePayer = signers.get(0);
- message.setFeePayer(feePayer);
-
+ message.setFeePayerPublicKey(feePayer.getPublicKey());
serializedMessage = message.serialize();
for (Account signer : signers) {
@@ -91,6 +91,29 @@ public void sign(List signers) {
}
}
+ /**
+ * Signs the transaction with external signer.
+ *
+ * @param feePayerPublicKey - The public key of the signer's account.
+ * @param externalSigner - Function for external sign.
+ * @throws IllegalArgumentException if no signers are provided
+ */
+ public void signByExternalSigner(PublicKey feePayerPublicKey, Function externalSigner) {
+ if (externalSigner == null) {
+ throw new IllegalArgumentException("No external signer provided");
+ }
+
+ message.setFeePayerPublicKey(feePayerPublicKey);
+ serializedMessage = message.serialize();
+
+ try {
+ byte[] signature = externalSigner.apply(message.serialize());
+ signatures.add(Base58.encode(signature));
+ } catch (Exception e) {
+ throw new RuntimeException("Error signing transaction", e); // Improve exception handling
+ }
+ }
+
/**
* Serializes the transaction into a byte array.
*
diff --git a/src/main/java/org/p2p/solanaj/programs/AssociatedTokenProgram.java b/src/main/java/org/p2p/solanaj/programs/AssociatedTokenProgram.java
index 1a26e1e7..50bd088d 100644
--- a/src/main/java/org/p2p/solanaj/programs/AssociatedTokenProgram.java
+++ b/src/main/java/org/p2p/solanaj/programs/AssociatedTokenProgram.java
@@ -30,8 +30,9 @@ public class AssociatedTokenProgram extends Program {
*/
public static TransactionInstruction create(PublicKey fundingAccount,
PublicKey walletAddress,
- PublicKey mint) {
- return createInstruction(CREATE_METHOD_ID, fundingAccount, walletAddress, mint);
+ PublicKey mint,
+ PublicKey tokenProgram) {
+ return createInstruction(CREATE_METHOD_ID, fundingAccount, walletAddress, mint, tokenProgram);
}
/**
@@ -45,8 +46,9 @@ public static TransactionInstruction create(PublicKey fundingAccount,
*/
public static TransactionInstruction createIdempotent(PublicKey fundingAccount,
PublicKey walletAddress,
- PublicKey mint) {
- return createInstruction(CREATE_IDEMPOTENT_METHOD_ID, fundingAccount, walletAddress, mint);
+ PublicKey mint,
+ PublicKey tokenProgram) {
+ return createInstruction(CREATE_IDEMPOTENT_METHOD_ID, fundingAccount, walletAddress, mint, tokenProgram);
}
/**
@@ -66,7 +68,8 @@ public static TransactionInstruction recoverNested(PublicKey nestedAccount,
PublicKey destinationAccount,
PublicKey ownerAccount,
PublicKey ownerMint,
- PublicKey wallet) {
+ PublicKey wallet,
+ PublicKey tokenProgram) {
final List keys = new ArrayList<>();
keys.add(new AccountMeta(nestedAccount, false, true));
@@ -75,7 +78,7 @@ public static TransactionInstruction recoverNested(PublicKey nestedAccount,
keys.add(new AccountMeta(ownerAccount, false, false));
keys.add(new AccountMeta(ownerMint, false, false));
keys.add(new AccountMeta(wallet, true, true));
- keys.add(new AccountMeta(TokenProgram.PROGRAM_ID, false, false));
+ keys.add(new AccountMeta(tokenProgram, false, false));
byte[] transactionData = encodeInstructionData(RECOVER_NESTED_METHOD_ID);
@@ -85,29 +88,30 @@ public static TransactionInstruction recoverNested(PublicKey nestedAccount,
private static TransactionInstruction createInstruction(int methodId,
PublicKey fundingAccount,
PublicKey walletAddress,
- PublicKey mint) {
+ PublicKey mint,
+ PublicKey tokenProgram) {
final List keys = new ArrayList<>();
- PublicKey pda = findAssociatedTokenAddress(walletAddress, mint);
+ PublicKey pda = findAssociatedTokenAddress(walletAddress, mint, tokenProgram);
keys.add(new AccountMeta(fundingAccount, true, true));
keys.add(new AccountMeta(pda, false, true));
keys.add(new AccountMeta(walletAddress, false, false));
keys.add(new AccountMeta(mint, false, false));
keys.add(new AccountMeta(SystemProgram.PROGRAM_ID, false, false));
- keys.add(new AccountMeta(TokenProgram.PROGRAM_ID, false, false));
+ keys.add(new AccountMeta(tokenProgram, false, false));
byte[] transactionData = encodeInstructionData(methodId);
return createTransactionInstruction(PROGRAM_ID, keys, transactionData);
}
- private static PublicKey findAssociatedTokenAddress(PublicKey walletAddress, PublicKey mint) {
+ private static PublicKey findAssociatedTokenAddress(PublicKey walletAddress, PublicKey mint, PublicKey tokenProgram) {
try {
PublicKey pda = PublicKey.findProgramAddress(
List.of(
walletAddress.toByteArray(),
- TokenProgram.PROGRAM_ID.toByteArray(),
+ tokenProgram.toByteArray(),
mint.toByteArray()
),
PROGRAM_ID
diff --git a/src/main/java/org/p2p/solanaj/programs/SystemProgram.java b/src/main/java/org/p2p/solanaj/programs/SystemProgram.java
index 177321a1..ee138292 100644
--- a/src/main/java/org/p2p/solanaj/programs/SystemProgram.java
+++ b/src/main/java/org/p2p/solanaj/programs/SystemProgram.java
@@ -55,6 +55,27 @@ public static TransactionInstruction transfer(PublicKey fromPublicKey, PublicKey
return new TransactionInstruction(PROGRAM_ID, keys, data);
}
+ /** Write 8 bytes to the byte array (starting at the offset) as signed 64-bit integer in little endian format. */
+ public static void int64ToByteArrayLE(long val, byte[] out, int offset) {
+ out[offset] = (byte) (0xFF & val);
+ out[offset + 1] = (byte) (0xFF & (val >> 8));
+ out[offset + 2] = (byte) (0xFF & (val >> 16));
+ out[offset + 3] = (byte) (0xFF & (val >> 24));
+ out[offset + 4] = (byte) (0xFF & (val >> 32));
+ out[offset + 5] = (byte) (0xFF & (val >> 40));
+ out[offset + 6] = (byte) (0xFF & (val >> 48));
+ out[offset + 7] = (byte) (0xFF & (val >> 56));
+ }
+
+
+ /** Write 4 bytes to the byte array (starting at the offset) as unsigned 32-bit integer in little endian format. */
+ public static void uint32ToByteArrayLE(long val, byte[] out, int offset) {
+ out[offset] = (byte) (0xFF & val);
+ out[offset + 1] = (byte) (0xFF & (val >> 8));
+ out[offset + 2] = (byte) (0xFF & (val >> 16));
+ out[offset + 3] = (byte) (0xFF & (val >> 24));
+ }
+
/**
* Creates an instruction to create a new account.
*
diff --git a/src/main/java/org/p2p/solanaj/programs/TokenProgram.java b/src/main/java/org/p2p/solanaj/programs/TokenProgram.java
index a80fca32..0009a230 100644
--- a/src/main/java/org/p2p/solanaj/programs/TokenProgram.java
+++ b/src/main/java/org/p2p/solanaj/programs/TokenProgram.java
@@ -15,6 +15,7 @@
public class TokenProgram extends Program {
public static final PublicKey PROGRAM_ID = new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
+ public static final PublicKey PROGRAM_ID_2022 = new PublicKey("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb");
/**
* The public key of the Solana rent sysvar.
@@ -45,7 +46,13 @@ public class TokenProgram extends Program {
* @param owner account/private key signing this transaction
* @return transaction id for explorer
*/
- public static TransactionInstruction transfer(PublicKey source, PublicKey destination, long amount, PublicKey owner) {
+ public static TransactionInstruction transfer(
+ PublicKey source,
+ PublicKey destination,
+ long amount,
+ PublicKey owner,
+ boolean isToken2022
+ ) {
final List keys = new ArrayList<>();
keys.add(new AccountMeta(source,false, true));
@@ -57,7 +64,7 @@ public static TransactionInstruction transfer(PublicKey source, PublicKey destin
);
return createTransactionInstruction(
- PROGRAM_ID,
+ isToken2022? PROGRAM_ID_2022: PROGRAM_ID,
keys,
transactionData
);
@@ -74,7 +81,15 @@ public static TransactionInstruction transfer(PublicKey source, PublicKey destin
* @param tokenMint The public key of the token's mint
* @return A TransactionInstruction for the transfer
*/
- public static TransactionInstruction transferChecked(PublicKey source, PublicKey destination, long amount, byte decimals, PublicKey owner, PublicKey tokenMint) {
+ public static TransactionInstruction transferChecked(
+ PublicKey source,
+ PublicKey destination,
+ long amount,
+ byte decimals,
+ PublicKey owner,
+ PublicKey tokenMint,
+ boolean isToken2022
+ ) {
final List keys = new ArrayList<>();
keys.add(new AccountMeta(source,false, true));
@@ -89,13 +104,18 @@ public static TransactionInstruction transferChecked(PublicKey source, PublicKey
);
return createTransactionInstruction(
- PROGRAM_ID,
+ isToken2022? PROGRAM_ID_2022: PROGRAM_ID,
keys,
transactionData
);
}
- public static TransactionInstruction initializeAccount(final PublicKey account, final PublicKey mint, final PublicKey owner) {
+ public static TransactionInstruction initializeAccount(
+ final PublicKey account,
+ final PublicKey mint,
+ final PublicKey owner,
+ boolean isToken2022
+ ) {
final List keys = new ArrayList<>();
keys.add(new AccountMeta(account,false, true));
@@ -108,13 +128,18 @@ public static TransactionInstruction initializeAccount(final PublicKey account,
buffer.put((byte) INITIALIZE_ACCOUNT_METHOD_ID);
return createTransactionInstruction(
- PROGRAM_ID,
+ isToken2022? PROGRAM_ID_2022: PROGRAM_ID,
keys,
buffer.array()
);
}
- public static TransactionInstruction closeAccount(final PublicKey accountPubkey, final PublicKey destinationPubkey, final PublicKey ownerPubkey) {
+ public static TransactionInstruction closeAccount(
+ final PublicKey accountPubkey,
+ final PublicKey destinationPubkey,
+ final PublicKey ownerPubkey,
+ boolean isToken2022
+ ) {
final List keys = new ArrayList<>();
keys.add(new AccountMeta(accountPubkey, false, true));
@@ -126,7 +151,7 @@ public static TransactionInstruction closeAccount(final PublicKey accountPubkey,
buffer.put((byte) CLOSE_ACCOUNT_METHOD_ID);
return createTransactionInstruction(
- PROGRAM_ID,
+ isToken2022? PROGRAM_ID_2022: PROGRAM_ID,
keys,
buffer.array()
);
@@ -179,7 +204,8 @@ public static TransactionInstruction initializeMint(
PublicKey mintPubkey,
int decimals,
PublicKey mintAuthority,
- PublicKey freezeAuthority
+ PublicKey freezeAuthority,
+ boolean isToken2022
) {
List keys = new ArrayList<>();
keys.add(new AccountMeta(mintPubkey, false, true));
@@ -195,7 +221,7 @@ public static TransactionInstruction initializeMint(
buffer.put(freezeAuthority.toByteArray());
}
- return createTransactionInstruction(PROGRAM_ID, keys, buffer.array());
+ return createTransactionInstruction(isToken2022? PROGRAM_ID_2022: PROGRAM_ID, keys, buffer.array());
}
/**
@@ -209,7 +235,8 @@ public static TransactionInstruction initializeMint(
public static TransactionInstruction initializeMultisig(
PublicKey multisigPubkey,
List signerPubkeys,
- int m
+ int m,
+ boolean isToken2022
) {
List keys = new ArrayList<>();
keys.add(new AccountMeta(multisigPubkey, false, true));
@@ -223,7 +250,7 @@ public static TransactionInstruction initializeMultisig(
buffer.put((byte) INITIALIZE_MULTISIG_METHOD_ID);
buffer.put((byte) m);
- return createTransactionInstruction(PROGRAM_ID, keys, buffer.array());
+ return createTransactionInstruction(isToken2022? PROGRAM_ID_2022: PROGRAM_ID, keys, buffer.array());
}
/**
@@ -239,7 +266,8 @@ public static TransactionInstruction approve(
PublicKey sourcePubkey,
PublicKey delegatePubkey,
PublicKey ownerPubkey,
- long amount
+ long amount,
+ boolean isToken2022
) {
List keys = new ArrayList<>();
keys.add(new AccountMeta(sourcePubkey, false, true));
@@ -251,7 +279,7 @@ public static TransactionInstruction approve(
buffer.put((byte) APPROVE_METHOD_ID);
buffer.putLong(amount);
- return createTransactionInstruction(PROGRAM_ID, keys, buffer.array());
+ return createTransactionInstruction(isToken2022? PROGRAM_ID_2022: PROGRAM_ID, keys, buffer.array());
}
/**
@@ -263,7 +291,8 @@ public static TransactionInstruction approve(
*/
public static TransactionInstruction revoke(
PublicKey accountPubkey,
- PublicKey ownerPubkey
+ PublicKey ownerPubkey,
+ boolean isToken2022
) {
List keys = new ArrayList<>();
keys.add(new AccountMeta(accountPubkey, false, true));
@@ -272,7 +301,7 @@ public static TransactionInstruction revoke(
ByteBuffer buffer = ByteBuffer.allocate(1);
buffer.put((byte) REVOKE_METHOD_ID);
- return createTransactionInstruction(PROGRAM_ID, keys, buffer.array());
+ return createTransactionInstruction(isToken2022? PROGRAM_ID_2022: PROGRAM_ID, keys, buffer.array());
}
/**
@@ -288,7 +317,8 @@ public static TransactionInstruction setAuthority(
PublicKey accountPubkey,
PublicKey currentAuthorityPubkey,
PublicKey newAuthorityPubkey,
- AuthorityType authorityType
+ AuthorityType authorityType,
+ boolean isToken2022
) {
List keys = new ArrayList<>();
keys.add(new AccountMeta(accountPubkey, false, true));
@@ -303,7 +333,7 @@ public static TransactionInstruction setAuthority(
buffer.put(newAuthorityPubkey.toByteArray());
}
- return createTransactionInstruction(PROGRAM_ID, keys, buffer.array());
+ return createTransactionInstruction(isToken2022? PROGRAM_ID_2022: PROGRAM_ID, keys, buffer.array());
}
/**
@@ -319,7 +349,8 @@ public static TransactionInstruction mintTo(
PublicKey mintPubkey,
PublicKey destinationPubkey,
PublicKey authorityPubkey,
- long amount
+ long amount,
+ boolean isToken2022
) {
List keys = new ArrayList<>();
keys.add(new AccountMeta(mintPubkey, false, true));
@@ -331,7 +362,7 @@ public static TransactionInstruction mintTo(
buffer.put((byte) MINT_TO_METHOD_ID);
buffer.putLong(amount);
- return createTransactionInstruction(PROGRAM_ID, keys, buffer.array());
+ return createTransactionInstruction(isToken2022? PROGRAM_ID_2022: PROGRAM_ID, keys, buffer.array());
}
/**
@@ -347,7 +378,8 @@ public static TransactionInstruction burn(
PublicKey accountPubkey,
PublicKey mintPubkey,
PublicKey ownerPubkey,
- long amount
+ long amount,
+ boolean isToken2022
) {
List keys = new ArrayList<>();
keys.add(new AccountMeta(accountPubkey, false, true));
@@ -359,7 +391,7 @@ public static TransactionInstruction burn(
buffer.put((byte) BURN_METHOD_ID);
buffer.putLong(amount);
- return createTransactionInstruction(PROGRAM_ID, keys, buffer.array());
+ return createTransactionInstruction(isToken2022? PROGRAM_ID_2022: PROGRAM_ID, keys, buffer.array());
}
/**
@@ -373,7 +405,8 @@ public static TransactionInstruction burn(
public static TransactionInstruction freezeAccount(
PublicKey accountPubkey,
PublicKey mintPubkey,
- PublicKey authorityPubkey
+ PublicKey authorityPubkey,
+ boolean isToken2022
) {
List keys = new ArrayList<>();
keys.add(new AccountMeta(accountPubkey, false, true));
@@ -383,7 +416,7 @@ public static TransactionInstruction freezeAccount(
ByteBuffer buffer = ByteBuffer.allocate(1);
buffer.put((byte) FREEZE_ACCOUNT_METHOD_ID);
- return createTransactionInstruction(PROGRAM_ID, keys, buffer.array());
+ return createTransactionInstruction(isToken2022? PROGRAM_ID_2022: PROGRAM_ID, keys, buffer.array());
}
/**
@@ -397,7 +430,8 @@ public static TransactionInstruction freezeAccount(
public static TransactionInstruction thawAccount(
PublicKey accountPubkey,
PublicKey mintPubkey,
- PublicKey authorityPubkey
+ PublicKey authorityPubkey,
+ boolean isToken2022
) {
List keys = new ArrayList<>();
keys.add(new AccountMeta(accountPubkey, false, true));
@@ -407,7 +441,7 @@ public static TransactionInstruction thawAccount(
ByteBuffer buffer = ByteBuffer.allocate(1);
buffer.put((byte) THAW_ACCOUNT_METHOD_ID);
- return createTransactionInstruction(PROGRAM_ID, keys, buffer.array());
+ return createTransactionInstruction(isToken2022? PROGRAM_ID_2022: PROGRAM_ID, keys, buffer.array());
}
/**
diff --git a/src/main/java/org/p2p/solanaj/rpc/RpcApi.java b/src/main/java/org/p2p/solanaj/rpc/RpcApi.java
index 71b06b76..4363f5a3 100644
--- a/src/main/java/org/p2p/solanaj/rpc/RpcApi.java
+++ b/src/main/java/org/p2p/solanaj/rpc/RpcApi.java
@@ -13,6 +13,7 @@
import org.p2p.solanaj.ws.listeners.NotificationEventListener;
import java.util.*;
+import java.util.function.Function;
import java.util.stream.Collectors;
public class RpcApi {
@@ -91,6 +92,37 @@ public String sendTransaction(Transaction transaction, List signers, St
return client.call("sendTransaction", params, String.class);
}
+ /**
+ * Sends a transaction to the RPC server with external signer
+ *
+ * @param transaction - The transaction to send.
+ * @param feePayerPublicKey - The public key of the signer's account.
+ * @param externalSigner - Function for external sign.
+ * @param recentBlockHash - The recent block hash. If null, it will be obtained from the RPC server.
+ * @param rpcSendTransactionConfig - The configuration object for sending transactions via RPC.
+ * @return The transaction ID as a string.
+ * @throws RpcException If an error occurs during the RPC call.
+ */
+ public String sendTransaction(Transaction transaction, PublicKey feePayerPublicKey,
+ Function externalSigner, String recentBlockHash,
+ RpcSendTransactionConfig rpcSendTransactionConfig) throws RpcException {
+ if (recentBlockHash == null) {
+ recentBlockHash = getLatestBlockhash().getValue().getBlockhash();
+ }
+ transaction.setRecentBlockHash(recentBlockHash);
+ transaction.signByExternalSigner(feePayerPublicKey, externalSigner);
+ byte[] serializedTransaction = transaction.serialize();
+
+ String base64Trx = Base64.getEncoder().encodeToString(serializedTransaction);
+
+ List