Skip to content

Commit dff84a2

Browse files
committed
fix(wasm-solana): return token program for CreateATA programId
Fix the parser to return the token program (from account index 5) instead of the ATA program for CreateAssociatedTokenAccount instructions. BitGoJS uses programId to indicate which token program owns the ATA (Token Program or Token-2022), not the program executing the instruction. Ticket: BTC-2955
1 parent 4d3ab6a commit dff84a2

File tree

5 files changed

+104
-3
lines changed

5 files changed

+104
-3
lines changed
2.03 KB
Binary file not shown.

packages/wasm-solana/js/index.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,20 @@ export { Transaction } from "./transaction.js";
1919
export { parseTransaction } from "./parser.js";
2020
export { buildTransaction } from "./builder.js";
2121

22+
// Program ID constants (from WASM)
23+
export {
24+
system_program_id as systemProgramId,
25+
stake_program_id as stakeProgramId,
26+
compute_budget_program_id as computeBudgetProgramId,
27+
memo_program_id as memoProgramId,
28+
token_program_id as tokenProgramId,
29+
token_2022_program_id as token2022ProgramId,
30+
ata_program_id as ataProgramId,
31+
stake_pool_program_id as stakePoolProgramId,
32+
stake_account_space as stakeAccountSpace,
33+
nonce_account_space as nonceAccountSpace,
34+
} from "./wasm/wasm_solana.js";
35+
2236
// Type exports
2337
export type { AccountMeta, Instruction } from "./transaction.js";
2438
export type {

packages/wasm-solana/src/instructions/decode.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -337,14 +337,25 @@ fn decode_token_instruction(ctx: InstructionContext) -> ParsedInstruction {
337337

338338
fn decode_ata_instruction(ctx: InstructionContext) -> ParsedInstruction {
339339
// ATA program: Create instruction has no data (discriminator 0 or empty)
340-
// Accounts: [0] payer, [1] ata, [2] owner, [3] mint, [4] system, [5] token
341-
if ctx.accounts.len() >= 4 {
340+
// Accounts: [0] payer, [1] ata, [2] owner, [3] mint, [4] system, [5] token program
341+
// Note: We return the token program (index 5) as programId, not the ATA program,
342+
// because BitGoJS uses programId to indicate which token program owns the ATA.
343+
if ctx.accounts.len() >= 6 {
342344
ParsedInstruction::CreateAssociatedTokenAccount(CreateAtaParams {
343345
payer_address: ctx.accounts[0].clone(),
344346
ata_address: ctx.accounts[1].clone(),
345347
owner_address: ctx.accounts[2].clone(),
346348
mint_address: ctx.accounts[3].clone(),
347-
program_id: ctx.program_id.to_string(),
349+
program_id: ctx.accounts[5].clone(), // Token program, not ATA program
350+
})
351+
} else if ctx.accounts.len() >= 4 {
352+
// Fallback for transactions without token program in accounts (older format)
353+
ParsedInstruction::CreateAssociatedTokenAccount(CreateAtaParams {
354+
payer_address: ctx.accounts[0].clone(),
355+
ata_address: ctx.accounts[1].clone(),
356+
owner_address: ctx.accounts[2].clone(),
357+
mint_address: ctx.accounts[3].clone(),
358+
program_id: TOKEN_PROGRAM_ID.to_string(), // Default to standard token program
348359
})
349360
} else {
350361
make_unknown(ctx)
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
//! Program ID constants exported via WASM.
2+
//!
3+
//! These constants allow JavaScript code to reference well-known Solana program IDs
4+
//! without needing to import @solana/web3.js.
5+
6+
use wasm_bindgen::prelude::*;
7+
8+
// Use re-exported constants from instructions module
9+
use crate::instructions::{
10+
ATA_PROGRAM_ID, COMPUTE_BUDGET_PROGRAM_ID, MEMO_PROGRAM_ID, STAKE_POOL_PROGRAM_ID,
11+
STAKE_PROGRAM_ID, SYSTEM_PROGRAM_ID, TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID,
12+
};
13+
14+
/// System Program ID
15+
#[wasm_bindgen]
16+
pub fn system_program_id() -> String {
17+
SYSTEM_PROGRAM_ID.to_string()
18+
}
19+
20+
/// Stake Program ID
21+
#[wasm_bindgen]
22+
pub fn stake_program_id() -> String {
23+
STAKE_PROGRAM_ID.to_string()
24+
}
25+
26+
/// Compute Budget Program ID
27+
#[wasm_bindgen]
28+
pub fn compute_budget_program_id() -> String {
29+
COMPUTE_BUDGET_PROGRAM_ID.to_string()
30+
}
31+
32+
/// Memo Program ID
33+
#[wasm_bindgen]
34+
pub fn memo_program_id() -> String {
35+
MEMO_PROGRAM_ID.to_string()
36+
}
37+
38+
/// Token Program ID (SPL Token)
39+
#[wasm_bindgen]
40+
pub fn token_program_id() -> String {
41+
TOKEN_PROGRAM_ID.to_string()
42+
}
43+
44+
/// Token 2022 Program ID
45+
#[wasm_bindgen]
46+
pub fn token_2022_program_id() -> String {
47+
TOKEN_2022_PROGRAM_ID.to_string()
48+
}
49+
50+
/// Associated Token Account Program ID
51+
#[wasm_bindgen]
52+
pub fn ata_program_id() -> String {
53+
ATA_PROGRAM_ID.to_string()
54+
}
55+
56+
/// Stake Pool Program ID (Jito)
57+
#[wasm_bindgen]
58+
pub fn stake_pool_program_id() -> String {
59+
STAKE_POOL_PROGRAM_ID.to_string()
60+
}
61+
62+
/// Stake account space in bytes (200)
63+
#[wasm_bindgen]
64+
pub fn stake_account_space() -> u64 {
65+
200
66+
}
67+
68+
/// Nonce account space in bytes (80)
69+
#[wasm_bindgen]
70+
pub fn nonce_account_space() -> u64 {
71+
80
72+
}

packages/wasm-solana/src/wasm/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
mod builder;
2+
mod constants;
23
mod keypair;
34
mod parser;
45
mod pubkey;
@@ -10,3 +11,6 @@ pub use keypair::WasmKeypair;
1011
pub use parser::ParserNamespace;
1112
pub use pubkey::WasmPubkey;
1213
pub use transaction::WasmTransaction;
14+
15+
// Re-export constants functions
16+
pub use constants::*;

0 commit comments

Comments
 (0)