Skip to content

Conversation

@lcovar
Copy link
Contributor

@lcovar lcovar commented Jan 14, 2026

Add comprehensive Solana transaction parsing capabilities via WASM,
providing types and structures compatible with BitGoJS's sdk-coin-sol.

Rust Layer

Transaction Deserialization (src/transaction.rs)

  • Deserialize legacy Solana transactions from wire format
  • Extract fee payer, blockhash, signatures, and account keys
  • Provide signable payload for signing operations

Instruction Decoding (src/instructions/)

  • Decode System Program: Transfer, CreateAccount, NonceAdvance, NonceInitialize
  • Decode Stake Program: Initialize, Delegate, Deactivate, Withdraw, Authorize
  • Decode ComputeBudget: SetComputeUnitLimit, SetComputeUnitPrice
  • Decode SPL Token: TransferChecked via token and token-2022 programs
  • Decode ATA Program: CreateAssociatedTokenAccount, CloseAccount
  • Decode Memo Program
  • Unknown instruction fallback with raw data preservation

High-Level Parser (src/parser.rs)

  • Combine CreateAccount + NonceInitialize into CreateNonceAccount
  • Combine CreateAccount + StakeInitialize + DelegateStake into StakingActivate
  • Detect durable nonce transactions and populate durableNonce field
  • Add stakingType field (NATIVE, JITO, MARINADE) to StakingActivate

WASM Bindings (src/wasm/)

  • ParserNamespace::parse_transaction - returns ParsedTransaction as JsValue
  • TransactionNamespace - transaction inspection methods

TypeScript Layer

Transaction Wrapper (js/transaction.ts)

  • Transaction class wrapping WASM with typed methods
  • Access to fee payer, blockhash, signatures, instructions, account keys

Parser Types (js/parser.ts)

  • Full TypeScript interfaces matching BitGoJS InstructionParams
  • ParsedTransaction interface with feePayer, nonce, durableNonce, instructionsData
  • parseTransaction() function with BigInt conversion for SetPriorityFee.fee

Exports (js/index.ts)

  • Export Transaction class and parseTransaction function
  • Re-export all instruction parameter types

Tests

  • BitGoJS compatibility tests using actual transaction fixtures
  • Transaction deserialization and inspection tests
  • Parser instruction type discrimination tests

TICKET: BTC-2929

@lcovar lcovar requested a review from a team as a code owner January 14, 2026 23:47
@lcovar lcovar marked this pull request as draft January 15, 2026 00:30
@lcovar lcovar force-pushed the BTC-2929 branch 2 times, most recently from 8c77915 to 500aca4 Compare January 15, 2026 00:51
@lcovar lcovar marked this pull request as ready for review January 15, 2026 00:58
Copy link
Contributor

@OttoAllmendinger OttoAllmendinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's reduce the API surface a little bit (unless we really need compatibility)

if we really need these funcs for compatibility, a lot of them can be implemented in the TS layer and we can keep the rust/wasm layer smaller

@lcovar lcovar force-pushed the BTC-2929 branch 2 times, most recently from d0bc9ec to 05b7ad6 Compare January 15, 2026 22:46
@lcovar lcovar changed the title feat(wasm-solana): add transaction deserialization feat(wasm-solana): add transaction parsing with BitGoJS compatibility Jan 15, 2026
@lcovar lcovar force-pushed the BTC-2929 branch 2 times, most recently from e689c41 to b5cafec Compare January 15, 2026 23:08
@lcovar lcovar force-pushed the BTC-2929 branch 14 times, most recently from 93415f9 to 1a49cef Compare January 24, 2026 06:11
…ding

Add comprehensive Solana transaction parsing to wasm-solana package with
BitGoJS-compatible output format.

Core Features:
- Parse serialized transactions into structured ParsedTransaction
- Decode all major instruction types to semantic InstructionParams
- Support for durable nonce transactions with NonceAdvance detection
- Full account metadata preservation for unknown instructions

Supported Programs:
- System Program: Transfer, CreateAccount, NonceAdvance, NonceInitialize
- Stake Program: Initialize, Delegate, Deactivate, Withdraw, Authorize,
  AuthorizeChecked
- SPL Token: Transfer, TransferChecked (with programId and decimalPlaces)
- SPL Associated Token Account: Create, Close
- Compute Budget: SetComputeUnitLimit, SetPriorityFee
- Memo Program: Memo instructions
- SPL Stake Pool (Jito): DepositSol, WithdrawStake

Instruction Combining (TypeScript):
- CreateAccount + NonceInitialize → CreateNonceAccount
- Staking patterns detected for NATIVE, JITO, and MARINADE types

The parser returns raw instructions; combining logic lives in TypeScript
for flexibility and easier maintenance.

Ticket: BTC-2929
Copy link
Contributor

@OttoAllmendinger OttoAllmendinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make sure all the amounts are bigint, the caller can convert them to string where necessary

/** Raw instruction from WASM before post-processing */
interface RawInstruction {
type: string;
fee?: string; // Fee comes as string from WASM
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can make it bigint here anyway

type: "TokenTransfer";
fromAddress: string;
toAddress: string;
amount: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bigint

type: "StakingWithdraw";
fromAddress: string;
stakingAddress: string;
amount: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bigin

type: "StakingActivate";
fromAddress: string;
stakingAddress: string;
amount: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bigint

fromAddress: string;
nonceAddress: string;
authAddress: string;
amount: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bigin

Comment on lines +308 to +309
export function parseTransaction(bytes: Uint8Array): ParsedTransaction {
const raw = ParserNamespace.parse_transaction(bytes) as RawParsedTransaction;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's allow higher level types here as well so we don't always have to go through bytes

Suggested change
export function parseTransaction(bytes: Uint8Array): ParsedTransaction {
const raw = ParserNamespace.parse_transaction(bytes) as RawParsedTransaction;
export function parseTransaction(bytes: Uint8Array | RawParsedTransaction): ParsedTransaction {
const raw = ParserNamespace.parse_transaction(bytes) as RawParsedTransaction;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants