From 448216ac2113c2fc2c89786ea06d874b51515d58 Mon Sep 17 00:00:00 2001 From: Andrew Min Date: Thu, 2 Jan 2025 10:23:18 -0800 Subject: [PATCH] examples and tests --- examples/with-solana/src/advanced.ts | 40 ++++-- packages/solana/src/__tests__/index-test.ts | 143 +++++++++++--------- 2 files changed, 105 insertions(+), 78 deletions(-) diff --git a/examples/with-solana/src/advanced.ts b/examples/with-solana/src/advanced.ts index cf71b8bbc..d437ca11f 100644 --- a/examples/with-solana/src/advanced.ts +++ b/examples/with-solana/src/advanced.ts @@ -18,6 +18,7 @@ import { Turnkey } from "@turnkey/sdk-server"; import { TurnkeySigner } from "@turnkey/solana"; import { createNewSolanaWallet, solanaNetwork } from "./utils"; +import { assertNonNull } from "@turnkey/http"; const TURNKEY_WAR_CHEST = "tkhqC9QX2gkqJtUFk2QKhBmQfFyyqZXSpr73VFRi35C"; @@ -145,24 +146,33 @@ async function main() { unsignedTxs.push(transferTransaction); } - const signedTransactions = (await turnkeySigner.signAllTransactions( - unsignedTxs, - solAddress - )) as VersionedTransaction[]; + const signedTransactionsResult = await turnkeySigner.signAllTransactions([ + { + signWith: solAddress, + transactions: unsignedTxs as VersionedTransaction[], + }, + ]); - for (let i = 0; i < signedTransactions.length; i++) { - const isValidSignature = nacl.sign.detached.verify( - signedTransactions[i]!.message.serialize(), - signedTransactions[i]!.signatures[0]!, - bs58.decode(solAddress) - ); + const result = assertNonNull(signedTransactionsResult); - if (!isValidSignature) { - throw new Error("unable to verify transaction signatures"); - } + for (let i = 0; i < result.length; i++) { + const txs = result[i]?.transactions!; + + for (const t of txs) { + const signedTx = t as VersionedTransaction; + const isValidSignature = nacl.sign.detached.verify( + signedTx!.message.serialize(), + signedTx!.signatures[0]!, + bs58.decode(solAddress) + ); - // 3. Broadcast the signed payload on devnet - await solanaNetwork.broadcast(connection, signedTransactions[i]!); + if (!isValidSignature) { + throw new Error("unable to verify transaction signatures"); + } + + // 3. Broadcast the signed payload on devnet + await solanaNetwork.broadcast(connection, signedTx); + } } process.exit(0); diff --git a/packages/solana/src/__tests__/index-test.ts b/packages/solana/src/__tests__/index-test.ts index 4ed211555..6fa90f26e 100644 --- a/packages/solana/src/__tests__/index-test.ts +++ b/packages/solana/src/__tests__/index-test.ts @@ -1,6 +1,6 @@ import { test, expect, describe } from "@jest/globals"; import { TurnkeySigner } from "../"; -import { TurnkeyClient } from "@turnkey/http"; +import { TurnkeyClient, assertNonNull } from "@turnkey/http"; import { ApiKeyStamper } from "@turnkey/api-key-stamper"; import { Turnkey } from "@turnkey/sdk-server"; import { @@ -161,38 +161,47 @@ describe("TurnkeySigner", () => { transactions.push(transferTransaction); } - const signedTransactions = - await signerConfig.signer.signAllTransactions( + const rawResult = await signerConfig.signer.signAllTransactions([ + { + signWith: turnkeySolAddress, transactions, - turnkeySolAddress - ); - expect(signedTransactions.length).toBe(numTxs); + }, + ]); - for (let i = 0; i < signedTransactions.length; i++) { - const tx = signedTransactions[i] as Transaction; + const result = assertNonNull(rawResult); + expect(result.length).toBe(1); + expect(result[0]!.signWith).toBe(turnkeySolAddress); + expect(result[0]!.transactions.length).toBe(numTxs); - // Verify the signature itself - const isValidSignature = nacl.sign.detached.verify( - tx.serializeMessage(), - tx.signature as Uint8Array, - bs58.decode(turnkeySolAddress) - ); - expect(isValidSignature).toBeTruthy(); + for (let i = 0; i < result.length; i++) { + const txs = result[i]!.transactions; + + for (const t of txs) { + const tx = t as Transaction; + + // Verify the signature itself + const isValidSignature = nacl.sign.detached.verify( + tx.serializeMessage(), + tx.signature as Uint8Array, + bs58.decode(turnkeySolAddress) + ); + expect(isValidSignature).toBeTruthy(); - // Ensure it's a simple, native transfer - expect(tx.instructions.length).toEqual(1); + // Ensure it's a simple, native transfer + expect(tx.instructions.length).toEqual(1); - const programId = tx.instructions[0]!.programId!; - const data = tx.instructions[0]!.data!; + const programId = tx.instructions[0]!.programId!; + const data = tx.instructions[0]!.data!; - expect(programId).toEqual(SystemProgram.programId); - expect(data[0]).toEqual(2); + expect(programId).toEqual(SystemProgram.programId); + expect(data[0]).toEqual(2); - // Convert raw data to lamports, then to whole SOL units - const amountLamportsBigInt = Buffer.from(data).readBigUInt64LE(4); - const amountLamports = Number(amountLamportsBigInt); + // Convert raw data to lamports, then to whole SOL units + const amountLamportsBigInt = Buffer.from(data).readBigUInt64LE(4); + const amountLamports = Number(amountLamportsBigInt); - expect(amounts[i]).toEqual(amountLamports); + expect(amounts[i]).toEqual(amountLamports); + } } }); @@ -232,45 +241,53 @@ describe("TurnkeySigner", () => { transactions.push(transaction); } - const signedTransactions = - await signerConfig.signer.signAllTransactions( + const rawResult = await signerConfig.signer.signAllTransactions([ + { + signWith: turnkeySolAddress, transactions, - turnkeySolAddress - ); - expect(signedTransactions.length).toBe(numTxs); - - for (let i = 0; i < signedTransactions.length; i++) { - const tx = signedTransactions[i] as VersionedTransaction; - - // After signing the version transaction, the default signature is replaced with the new one - expect(tx.signatures.length).toBe(1); - expect(tx.signatures[0]).not.toEqual(DEFAULT_SIGNATURE); - - // Verify the signature itself - const isValidSignature = nacl.sign.detached.verify( - tx.message.serialize(), - tx.signatures[0] as Uint8Array, - bs58.decode(turnkeySolAddress) - ); - expect(isValidSignature).toBeTruthy(); - - // Ensure it's a simple, native transfer - expect(tx.message.compiledInstructions.length).toEqual(1); - - const programIdIndex = - tx.message.compiledInstructions[0]!.programIdIndex!; - const keys = tx.message.getAccountKeys(); - const programId = keys.staticAccountKeys[programIdIndex]; - const data = tx.message.compiledInstructions[0]!.data!; - - expect(programId).toEqual(SystemProgram.programId); - expect(data[0]).toEqual(2); - - // Convert raw data to lamports, then to whole SOL units - const amountLamportsBigInt = Buffer.from(data).readBigUInt64LE(4); - const amountLamports = Number(amountLamportsBigInt); - - expect(amounts[i]).toEqual(amountLamports); + }, + ]); + const result = assertNonNull(rawResult); + expect(result.length).toBe(1); + expect(result[0]!.signWith).toBe(turnkeySolAddress); + expect(result[0]!.transactions.length).toBe(numTxs); + + for (let i = 0; i < result.length; i++) { + const txs = result[i]!.transactions; + + for (const t of txs) { + const tx = t as VersionedTransaction; + + // Verify the signature itself + const isValidSignature = nacl.sign.detached.verify( + tx.message.serialize(), + tx.signatures[0] as Uint8Array, + bs58.decode(turnkeySolAddress) + ); + expect(isValidSignature).toBeTruthy(); + + // After signing the versioned transaction, the default signature is replaced with the new one + expect(tx.signatures.length).toBe(1); + expect(tx.signatures[0]).not.toEqual(DEFAULT_SIGNATURE); + + // Ensure it's a simple, native transfer + expect(tx.message.compiledInstructions.length).toEqual(1); + + const programIdIndex = + tx.message.compiledInstructions[0]!.programIdIndex!; + const keys = tx.message.getAccountKeys(); + const programId = keys.staticAccountKeys[programIdIndex]; + const data = tx.message.compiledInstructions[0]!.data!; + + expect(programId).toEqual(SystemProgram.programId); + expect(data[0]).toEqual(2); + + // Convert raw data to lamports, then to whole SOL units + const amountLamportsBigInt = Buffer.from(data).readBigUInt64LE(4); + const amountLamports = Number(amountLamportsBigInt); + + expect(amounts[i]).toEqual(amountLamports); + } } });