Skip to content

Commit

Permalink
examples and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewkmin committed Jan 2, 2025
1 parent 38b9b6c commit 448216a
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 78 deletions.
40 changes: 25 additions & 15 deletions examples/with-solana/src/advanced.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down Expand Up @@ -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);
Expand Down
143 changes: 80 additions & 63 deletions packages/solana/src/__tests__/index-test.ts
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down Expand Up @@ -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);
}
}
});

Expand Down Expand Up @@ -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);
}
}
});

Expand Down

0 comments on commit 448216a

Please sign in to comment.