Skip to content

Commit 27e79ce

Browse files
committed
feat: add transaction building core infrastructure
Implements the core transaction building functionality using Solana SDK: - types.rs: TransactionIntent, Nonce (blockhash/durable), Instruction variants - build.rs: Transaction builder using solana-sdk 3.x types - Uses SDK instruction builders: system_ix::transfer(), advance_nonce_account(), etc. - Uses ComputeBudgetInstruction for priority fees Supported instructions: - Transfer, CreateAccount, NonceAdvance, NonceInitialize - Allocate, Assign, Memo, ComputeBudget Ticket: BTC-2955
1 parent d659f9b commit 27e79ce

11 files changed

Lines changed: 1739 additions & 51 deletions

File tree

packages/wasm-solana/Cargo.lock

Lines changed: 703 additions & 44 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/wasm-solana/Cargo.toml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,22 @@ wasm-bindgen = "0.2"
1414
js-sys = "0.3"
1515
serde = { version = "1.0", features = ["derive"] }
1616
serde_json = "1.0"
17-
# Solana SDK crates
17+
# Solana 3.x crates (for transaction building)
18+
solana-sdk = { version = "3.0", default-features = false, features = ["full"] }
19+
solana-transaction = { version = "3.0", features = ["serde", "bincode"] }
20+
solana-system-interface = { version = "3.0", features = ["bincode"] }
21+
solana-compute-budget-interface = { version = "3.0", features = ["borsh"] }
22+
# Solana 2.x crates (no 3.x available yet for these)
23+
solana-stake-interface = { version = "2.0", features = ["bincode"] }
1824
solana-pubkey = { version = "2.0", features = ["curve25519"] }
1925
solana-keypair = "2.0"
2026
solana-signer = "2.0"
21-
solana-transaction = { version = "3.0", features = ["serde", "bincode"] }
22-
# Instruction decoder interfaces (official Solana crates)
23-
solana-system-interface = { version = "2.0", features = ["bincode"] }
24-
solana-stake-interface = { version = "2.0", features = ["bincode"] }
25-
solana-compute-budget-interface = { version = "2.0", features = ["borsh"] }
2627
# Serialization
2728
bincode = "1.3"
2829
borsh = "1.5"
2930
base64 = "0.22"
3031
serde-wasm-bindgen = "0.6"
32+
# SPL Stake Pool for Jito decoding
3133
spl-stake-pool = { version = "2.0.3", features = ["no-entrypoint"] }
3234

3335
[dev-dependencies]

packages/wasm-solana/js/builder.ts

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
/**
2+
* Transaction building from high-level intents.
3+
*
4+
* Provides types and functions for building Solana transactions from a
5+
* declarative intent structure, without requiring the full @solana/web3.js dependency.
6+
*/
7+
8+
import { BuilderNamespace } from "./wasm/wasm_solana.js";
9+
10+
// =============================================================================
11+
// Nonce Types
12+
// =============================================================================
13+
14+
/** Use a recent blockhash for the transaction */
15+
export interface BlockhashNonceSource {
16+
type: "blockhash";
17+
/** The recent blockhash value (base58) */
18+
value: string;
19+
}
20+
21+
/** Use a durable nonce account for the transaction */
22+
export interface DurableNonceSource {
23+
type: "durable";
24+
/** The nonce account address (base58) */
25+
address: string;
26+
/** The nonce authority address (base58) */
27+
authority: string;
28+
/** The nonce value stored in the account (base58) - this becomes the blockhash */
29+
value: string;
30+
}
31+
32+
/** Nonce source for the transaction */
33+
export type NonceSource = BlockhashNonceSource | DurableNonceSource;
34+
35+
// =============================================================================
36+
// Instruction Types
37+
// =============================================================================
38+
39+
/** SOL transfer instruction */
40+
export interface TransferInstruction {
41+
type: "transfer";
42+
/** Source account (base58) */
43+
from: string;
44+
/** Destination account (base58) */
45+
to: string;
46+
/** Amount in lamports (as string for BigInt compatibility) */
47+
lamports: string;
48+
}
49+
50+
/** Create new account instruction */
51+
export interface CreateAccountInstruction {
52+
type: "createAccount";
53+
/** Funding account (base58) */
54+
from: string;
55+
/** New account address (base58) */
56+
newAccount: string;
57+
/** Lamports to transfer (as string) */
58+
lamports: string;
59+
/** Space to allocate in bytes */
60+
space: number;
61+
/** Owner program (base58) */
62+
owner: string;
63+
}
64+
65+
/** Advance durable nonce instruction */
66+
export interface NonceAdvanceInstruction {
67+
type: "nonceAdvance";
68+
/** Nonce account address (base58) */
69+
nonce: string;
70+
/** Nonce authority (base58) */
71+
authority: string;
72+
}
73+
74+
/** Initialize nonce account instruction */
75+
export interface NonceInitializeInstruction {
76+
type: "nonceInitialize";
77+
/** Nonce account address (base58) */
78+
nonce: string;
79+
/** Nonce authority (base58) */
80+
authority: string;
81+
}
82+
83+
/** Allocate space instruction */
84+
export interface AllocateInstruction {
85+
type: "allocate";
86+
/** Account to allocate (base58) */
87+
account: string;
88+
/** Space to allocate in bytes */
89+
space: number;
90+
}
91+
92+
/** Assign account to program instruction */
93+
export interface AssignInstruction {
94+
type: "assign";
95+
/** Account to assign (base58) */
96+
account: string;
97+
/** New owner program (base58) */
98+
owner: string;
99+
}
100+
101+
/** Memo instruction */
102+
export interface MemoInstruction {
103+
type: "memo";
104+
/** The memo message */
105+
message: string;
106+
}
107+
108+
/** Compute budget instruction */
109+
export interface ComputeBudgetInstruction {
110+
type: "computeBudget";
111+
/** Compute unit limit (optional) */
112+
unitLimit?: number;
113+
/** Compute unit price in micro-lamports (optional) */
114+
unitPrice?: number;
115+
}
116+
117+
/** Union of all instruction types */
118+
export type Instruction =
119+
| TransferInstruction
120+
| CreateAccountInstruction
121+
| NonceAdvanceInstruction
122+
| NonceInitializeInstruction
123+
| AllocateInstruction
124+
| AssignInstruction
125+
| MemoInstruction
126+
| ComputeBudgetInstruction;
127+
128+
// =============================================================================
129+
// TransactionIntent
130+
// =============================================================================
131+
132+
/**
133+
* A declarative intent to build a Solana transaction.
134+
*
135+
* @example
136+
* ```typescript
137+
* const intent: TransactionIntent = {
138+
* feePayer: 'DgT9qyYwYKBRDyDw3EfR12LHQCQjtNrKu2qMsXHuosmB',
139+
* nonce: {
140+
* type: 'blockhash',
141+
* value: 'GWaQEymC3Z9SHM2gkh8u12xL1zJPMHPCSVR3pSDpEXE4'
142+
* },
143+
* instructions: [
144+
* { type: 'transfer', from: '...', to: '...', lamports: '1000000' }
145+
* ]
146+
* };
147+
* ```
148+
*/
149+
export interface TransactionIntent {
150+
/** The fee payer's public key (base58) */
151+
feePayer: string;
152+
/** The nonce source (blockhash or durable nonce) */
153+
nonce: NonceSource;
154+
/** List of instructions to include */
155+
instructions: Instruction[];
156+
}
157+
158+
// =============================================================================
159+
// buildTransaction function
160+
// =============================================================================
161+
162+
/**
163+
* Build a Solana transaction from a high-level intent.
164+
*
165+
* This function takes a declarative TransactionIntent and produces serialized
166+
* transaction bytes that can be signed and submitted to the network.
167+
*
168+
* The returned transaction is unsigned - signatures should be added before
169+
* broadcasting.
170+
*
171+
* @param intent - The transaction intent describing what to build
172+
* @returns Serialized unsigned transaction bytes (Uint8Array)
173+
* @throws Error if the intent cannot be built (e.g., invalid addresses)
174+
*
175+
* @example
176+
* ```typescript
177+
* import { buildTransaction } from '@bitgo/wasm-solana';
178+
*
179+
* // Build a simple SOL transfer
180+
* const txBytes = buildTransaction({
181+
* feePayer: sender,
182+
* nonce: { type: 'blockhash', value: blockhash },
183+
* instructions: [
184+
* { type: 'transfer', from: sender, to: recipient, lamports: '1000000' }
185+
* ]
186+
* });
187+
*
188+
* // The returned bytes can be signed and broadcast
189+
* ```
190+
*
191+
* @example
192+
* ```typescript
193+
* // Build with durable nonce and priority fee
194+
* const txBytes = buildTransaction({
195+
* feePayer: sender,
196+
* nonce: { type: 'durable', address: nonceAccount, authority: sender, value: nonceValue },
197+
* instructions: [
198+
* { type: 'computeBudget', unitLimit: 200000, unitPrice: 5000 },
199+
* { type: 'transfer', from: sender, to: recipient, lamports: '1000000' },
200+
* { type: 'memo', message: 'BitGo transfer' }
201+
* ]
202+
* });
203+
* ```
204+
*/
205+
export function buildTransaction(intent: TransactionIntent): Uint8Array {
206+
return BuilderNamespace.build_transaction(intent);
207+
}

packages/wasm-solana/js/index.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export * as keypair from "./keypair.js";
88
export * as pubkey from "./pubkey.js";
99
export * as transaction from "./transaction.js";
1010
export * as parser from "./parser.js";
11+
export * as builder from "./builder.js";
1112

1213
// Top-level class exports for convenience
1314
export { Keypair } from "./keypair.js";
@@ -16,6 +17,7 @@ export { Transaction } from "./transaction.js";
1617

1718
// Top-level function exports
1819
export { parseTransaction } from "./parser.js";
20+
export { buildTransaction } from "./builder.js";
1921

2022
// Type exports
2123
export type { AccountMeta, Instruction } from "./transaction.js";
@@ -40,3 +42,20 @@ export type {
4042
MemoParams,
4143
UnknownInstructionParams,
4244
} from "./parser.js";
45+
46+
// Builder type exports (prefixed to avoid conflict with parser/transaction types)
47+
export type {
48+
TransactionIntent,
49+
NonceSource,
50+
BlockhashNonceSource,
51+
DurableNonceSource,
52+
Instruction as BuilderInstruction,
53+
TransferInstruction,
54+
CreateAccountInstruction,
55+
NonceAdvanceInstruction,
56+
NonceInitializeInstruction,
57+
AllocateInstruction,
58+
AssignInstruction,
59+
MemoInstruction,
60+
ComputeBudgetInstruction,
61+
} from "./builder.js";

0 commit comments

Comments
 (0)