Skip to content

Commit 1240a0c

Browse files
committed
add solana signer interface and implementation for local private key
1 parent 9c4a11c commit 1240a0c

File tree

1 file changed

+58
-20
lines changed

1 file changed

+58
-20
lines changed

solana/ts/scripts/env.ts

+58-20
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,65 @@
11
import fs from "fs";
2-
import { Connection, Commitment } from "@solana/web3.js";
3-
import { ChainId } from "@certusone/wormhole-sdk";
2+
import { Connection, Commitment, Keypair, Transaction } from "@solana/web3.js";
3+
import { ChainId, sign } from "@certusone/wormhole-sdk";
44
import { SolanaLedgerSigner } from "@xlabs-xyz/ledger-signer-solana";
55
import { Chain } from "@wormhole-foundation/sdk-base";
6-
7-
if (!process.env.LEDGER_DERIVATION_PATH) {
8-
throw new Error("LEDGER_DERIVATION_PATH is not set");
9-
}
6+
import { bs58 } from "@coral-xyz/anchor/dist/cjs/utils/bytes";
7+
import nacl from "tweetnacl";
108

119
if (!process.env.ENV) {
1210
throw new Error("ENV not set");
1311
}
1412

1513
const env = process.env.ENV;
1614

17-
const derivationPath = process.env.LEDGER_DERIVATION_PATH! as string;
15+
interface SolanaSigner {
16+
getAddress(): Promise<Buffer>;
17+
signMessage(message: Buffer): Promise<Buffer>;
18+
signTransaction(transaction: Buffer): Promise<Buffer>;
19+
}
20+
21+
export class SolanaLocalSigner implements SolanaSigner {
22+
readonly keypair: Keypair;
23+
constructor(private privateKey: string) {
24+
this.keypair = Keypair.fromSecretKey(bs58.decode(this.privateKey));
25+
}
26+
27+
async getAddress(): Promise<Buffer> {
28+
return this.keypair.publicKey.toBuffer();
29+
}
30+
31+
async signMessage(message: Buffer): Promise<Buffer> {
32+
return Buffer.from(
33+
nacl.sign.detached(new Uint8Array(message), this.keypair.secretKey)
34+
);
35+
}
36+
37+
async signTransaction(transaction: Buffer): Promise<Buffer> {
38+
const tx = Transaction.from(transaction);
39+
tx.sign(this.keypair);
40+
return tx.serialize();
41+
}
42+
}
1843

1944
let signer;
20-
export async function getSigner(): Promise<SolanaLedgerSigner> {
21-
if (!signer) {
22-
signer = await SolanaLedgerSigner.create(derivationPath);
45+
export async function getSigner(): Promise<SolanaSigner> {
46+
if (signer) return signer;
47+
48+
if (process.env.LEDGER_DERIVATION_PATH) {
49+
signer = await SolanaLedgerSigner.create(
50+
process.env.LEDGER_DERIVATION_PATH!
51+
);
52+
}
53+
54+
if (process.env.SOLANA_PRIVATE_KEY) {
55+
signer = new SolanaLocalSigner(process.env.SOLANA_PRIVATE_KEY!);
2356
}
2457

58+
if (!signer)
59+
throw new Error(
60+
"Either LEDGER_DERIVATION_PATH or SOLANA_PRIVATE_KEY must be set"
61+
);
62+
2563
return signer;
2664
}
2765

@@ -50,11 +88,11 @@ export type NttDeployment = {
5088
};
5189

5290
export type QuoterManagerRegistrations = {
53-
programId: string;
54-
tokenAddress: string;
55-
gasCost: number;
56-
wormholeTransceiverIndex: number;
57-
isSupported: boolean;
91+
programId: string;
92+
tokenAddress: string;
93+
gasCost: number;
94+
wormholeTransceiverIndex: number;
95+
isSupported: boolean;
5896
}[];
5997

6098
export type QuoterPeerQuotes = Partial<Record<Chain, QuoterPeerQuote>>;
@@ -75,30 +113,30 @@ export type QuoterConfig = {
75113
solPriceUsd: number;
76114
peerQuotes: QuoterPeerQuotes;
77115
managerRegistrations: QuoterManagerRegistrations;
78-
}
116+
};
79117

80118
export type NttConfig = {
81119
outboundLimit: string;
82120
mode: "locking" | "burning";
83-
}
121+
};
84122

85123
export type Programs = {
86124
mintProgramId: string;
87125
nttProgramId: string;
88126
wormholeProgramId: string;
89127
quoterProgramId: string;
90128
governanceProgramId: string;
91-
}
129+
};
92130

93131
export type GovernanceVaa = {
94132
vaa: string;
95-
}
133+
};
96134

97135
export function getEvmNttDeployments(): NttDeployment[] {
98136
return loadScriptConfig("evm-peers");
99137
}
100138

101-
export function getQuoterConfiguration(): QuoterConfig {
139+
export function getQuoterConfiguration(): QuoterConfig {
102140
return loadScriptConfig("quoter");
103141
}
104142

0 commit comments

Comments
 (0)