Skip to content

Commit

Permalink
chore: Add raw tx interface (#267)
Browse files Browse the repository at this point in the history
* Support sending raw txs in solana

* Add changeset
  • Loading branch information
0xaguspunk authored Jan 22, 2025
1 parent 10b4f84 commit 1f361d5
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 0 deletions.
8 changes: 8 additions & 0 deletions typescript/.changeset/soft-ducks-develop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"conversational-agent": patch
"@goat-sdk/wallet-lit": patch
"@goat-sdk/crossmint": patch
"@goat-sdk/wallet-solana": patch
---

Support raw txs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ export function createSolanaWalletFromDynamic(connection: Connection, signer: IS
};
}

async sendRawTransaction(transaction: string): Promise<{ hash: string }> {
throw new Error("Not implemented");
}

async balanceOf(address: string) {
const pubkey = new PublicKey(address);
const balance = await connection.getBalance(pubkey);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,29 @@ export class CustodialSolanaWalletClient extends SolanaWalletClient {
}
}

async sendRawTransaction(transaction: string): Promise<{ hash: string }> {
const { id: transactionId } = await this.#client.createTransactionForCustodialWallet(
this.#locator,
transaction,
);

while (true) {
const latestTransaction = await this.#client.checkTransactionStatus(this.#locator, transactionId);

if (latestTransaction.status === "success") {
return {
hash: latestTransaction.onChain?.txId ?? "",
};
}

if (latestTransaction.status === "failed") {
throw new Error(`Transaction failed: ${latestTransaction.onChain?.txId}`);
}

await new Promise((resolve) => setTimeout(resolve, 3000)); // Wait 3 seconds
}
}

async balanceOf(address: string) {
const pubkey = new PublicKey(address);
const balance = await this.connection.getBalance(pubkey);
Expand Down
20 changes: 20 additions & 0 deletions typescript/packages/wallets/lit-protocol/src/solana.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,26 @@ export class LitSolanaWallet extends SolanaWalletClient {
};
}

async sendRawTransaction(transaction: string): Promise<{ hash: string }> {
const litTransaction = {
serializedTransaction: transaction,
chain: this.chain,
};

const signedTransaction = await signTransactionWithEncryptedKey({
litNodeClient: this.litNodeClient,
pkpSessionSigs: this.pkpSessionSigs,
network: "solana",
id: this.wrappedKeyMetadata.id,
unsignedTransaction: litTransaction,
broadcast: true,
});

return {
hash: signedTransaction,
};
}

async balanceOf(address: string) {
const pubkey = new PublicKey(address);
const balance = await this.connection.getBalance(pubkey);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,33 @@ export class SolanaKeypairWalletClient extends SolanaWalletClient {
hash,
};
}

async sendRawTransaction(transaction: string): Promise<{ hash: string }> {
const tx = VersionedTransaction.deserialize(Buffer.from(transaction, "base64"));

const latestBlockhash = await this.connection.getLatestBlockhash();
tx.message.recentBlockhash = latestBlockhash.blockhash;

tx.sign([this.#keypair]);

const hash = await this.connection.sendTransaction(tx, {
maxRetries: 10,
preflightCommitment: "confirmed",
});

await this.connection.confirmTransaction(
{
blockhash: latestBlockhash.blockhash,
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
signature: hash,
},
"confirmed",
);

return {
hash,
};
}
}

export const solana = (params: SolanaKeypairWalletClientCtorParams) => new SolanaKeypairWalletClient(params);
2 changes: 2 additions & 0 deletions typescript/packages/wallets/solana/src/SolanaWalletClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ export abstract class SolanaWalletClient extends WalletClientBase {

abstract sendTransaction(transaction: SolanaTransaction): Promise<{ hash: string }>;

abstract sendRawTransaction(transaction: string): Promise<{ hash: string }>;

protected async getAddressLookupTableAccounts(keys: string[]): Promise<AddressLookupTableAccount[]> {
const addressLookupTableAccountInfos = await this.connection.getMultipleAccountsInfo(
keys.map((key) => new PublicKey(key)),
Expand Down

0 comments on commit 1f361d5

Please sign in to comment.