Skip to content

Commit

Permalink
add signall script
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewkmin committed Nov 23, 2024
1 parent b55aa0d commit aaf9f9e
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 0 deletions.
1 change: 1 addition & 0 deletions examples/with-solana/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"start": "pnpm tsx src/index.ts",
"advanced": "pnpm tsx src/advanced.ts",
"token-transfer": "pnpm tsx src/tokenTransfer.ts",
"sign-all": "pnpm tsx src/signAll.ts",
"faucet": "pnpm tsx src/faucet.ts",
"jupiter-swap": "pnpm tsx src/jupiterSwap.ts",
"with-fee-payer": "pnpm tsx src/withFeePayer.ts",
Expand Down
141 changes: 141 additions & 0 deletions examples/with-solana/src/signAll.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import * as dotenv from "dotenv";
import * as path from "path";
import nacl from "tweetnacl";
import bs58 from "bs58";
import prompts from "prompts";

// Load environment variables from `.env.local`
dotenv.config({ path: path.resolve(process.cwd(), ".env.local") });

import {
PublicKey,
SystemProgram,
VersionedTransaction,
Transaction,
TransactionMessage,
} from "@solana/web3.js";

import { Turnkey } from "@turnkey/sdk-server";
import { TurnkeySigner } from "@turnkey/solana";

import { solanaNetwork } from "./utils";

const TURNKEY_WAR_CHEST = "tkhqC9QX2gkqJtUFk2QKhBmQfFyyqZXSpr73VFRi35C";

async function main() {
const organizationId = process.env.ORGANIZATION_ID!;

const connection = solanaNetwork.connect();
const blockhash = await solanaNetwork.recentBlockhash();

const turnkeyClient = new Turnkey({
apiBaseUrl: process.env.BASE_URL!,
apiPublicKey: process.env.API_PUBLIC_KEY!,
apiPrivateKey: process.env.API_PRIVATE_KEY!,
defaultOrganizationId: organizationId,
});

const turnkeySigner = new TurnkeySigner({
organizationId,
client: turnkeyClient.apiClient(),
});

// Arbitrary number of transactions
const numTxs = 3;

// Each transaction will come from one address
// Populate each of these values and fund them with sufficient SOL
const addresses = [
process.env.SOLANA_ADDRESS_1!,
process.env.SOLANA_ADDRESS_2!,
process.env.SOLANA_ADDRESS_3!,
];

const requests = Array.from({ length: numTxs }, async (_, index) => {
const solAddress = addresses[index]!;

const { destination } = await prompts([
{
type: "text",
name: "destination",
message: `${index + 1} Destination address:`,
initial: TURNKEY_WAR_CHEST,
},
]);

// Amount defaults to 100.
// Any other amount is possible, so long as a sufficient balance remains for fees.
const { amount } = await prompts([
{
type: "text",
name: "amount",
message: `${
index + 1
}. Amount (in Lamports) to send to ${TURNKEY_WAR_CHEST}:`,
initial: "100",
validate: function () {
// Not checking balances; just assume valid
return true;
},
},
]);

const fromKey = new PublicKey(solAddress);
const toKey = new PublicKey(destination);

const txMessage = new TransactionMessage({
payerKey: fromKey,
recentBlockhash: blockhash,
instructions: [
SystemProgram.transfer({
fromPubkey: fromKey,
toPubkey: toKey,
lamports: Number(amount),
}),
],
});

const versionedTxMessage = txMessage.compileToV0Message();

// Use VersionedTransaction
const transferTransaction = new VersionedTransaction(versionedTxMessage);

return turnkeySigner.signAllTransactions([transferTransaction], solAddress);
});

const promiseResults = await Promise.allSettled(requests);

const successfulRequests = promiseResults
.filter(
(result): result is PromiseFulfilledResult<(Transaction | VersionedTransaction)[]> =>
result.status === "fulfilled"
)
.map((result) => result.value);

const signedTransactions = successfulRequests;

// Iterate through all signed transactions, verify, and broadcast them
for (let i = 0; i < signedTransactions.length; i++) {
const signedTransaction = signedTransactions[i]![0]! as VersionedTransaction;
const solAddress = addresses[i]!;

const isValidSignature = nacl.sign.detached.verify(
signedTransaction.message.serialize(),
signedTransaction.signatures[0]!,
bs58.decode(solAddress)
);

if (!isValidSignature) {
throw new Error("unable to verify transaction signatures");
}

await solanaNetwork.broadcast(connection, signedTransaction);
}

process.exit(0);
}

main().catch((error) => {
console.error(error);
process.exit(1);
});

0 comments on commit aaf9f9e

Please sign in to comment.