diff --git a/pom.xml b/pom.xml
index 23c3d14d..2ee91ad7 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
diff --git a/src/main/java/org/p2p/solanaj/core/Message.java b/src/main/java/org/p2p/solanaj/core/Message.java
index 1c5bbda0..12b655a2 100644
--- a/src/main/java/org/p2p/solanaj/core/Message.java
+++ b/src/main/java/org/p2p/solanaj/core/Message.java
@@ -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/Transaction.java b/src/main/java/org/p2p/solanaj/core/Transaction.java
index bab10710..4f03dce1 100644
--- a/src/main/java/org/p2p/solanaj/core/Transaction.java
+++ b/src/main/java/org/p2p/solanaj/core/Transaction.java
@@ -5,6 +5,7 @@
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
+import java.util.function.Function;
import org.bitcoinj.core.Base58;
import org.p2p.solanaj.utils.ShortvecEncoding;
@@ -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/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