@bitgo/wasm-solana 2.4.1 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,100 @@
1
+ /**
2
+ * High-level transaction explanation.
3
+ *
4
+ * Builds on top of `parseTransaction` (WASM) to provide a structured
5
+ * "explain" view of a Solana transaction: type, outputs, inputs, fee, etc.
6
+ *
7
+ * The WASM parser returns raw individual instructions. This module combines
8
+ * related instruction sequences into higher-level operations and derives the
9
+ * overall transaction type.
10
+ */
11
+ export declare enum TransactionType {
12
+ Send = "Send",
13
+ StakingActivate = "StakingActivate",
14
+ StakingDeactivate = "StakingDeactivate",
15
+ StakingWithdraw = "StakingWithdraw",
16
+ StakingAuthorize = "StakingAuthorize",
17
+ StakingDelegate = "StakingDelegate",
18
+ WalletInitialization = "WalletInitialization",
19
+ AssociatedTokenAccountInitialization = "AssociatedTokenAccountInitialization"
20
+ }
21
+ export interface ExplainOptions {
22
+ /** Defaults to 5000 (Solana protocol constant). */
23
+ lamportsPerSignature?: bigint | number | string;
24
+ tokenAccountRentExemptAmount?: bigint | number | string;
25
+ }
26
+ export interface ExplainedOutput {
27
+ address: string;
28
+ amount: bigint;
29
+ tokenName?: string;
30
+ }
31
+ export interface ExplainedInput {
32
+ address: string;
33
+ value: bigint;
34
+ }
35
+ export interface TokenEnablement {
36
+ /** The ATA address being created */
37
+ address: string;
38
+ /** The SPL token mint address */
39
+ mintAddress: string;
40
+ }
41
+ export interface StakingAuthorizeInfo {
42
+ stakingAddress: string;
43
+ oldAuthorizeAddress: string;
44
+ newAuthorizeAddress: string;
45
+ authorizeType: "Staker" | "Withdrawer";
46
+ custodianAddress?: string;
47
+ }
48
+ export interface ExplainedTransaction {
49
+ /** Transaction ID (base58 signature). Undefined if the transaction is unsigned. */
50
+ id: string | undefined;
51
+ type: TransactionType;
52
+ feePayer: string;
53
+ fee: bigint;
54
+ blockhash: string;
55
+ durableNonce?: {
56
+ walletNonceAddress: string;
57
+ authWalletAddress: string;
58
+ };
59
+ outputs: ExplainedOutput[];
60
+ inputs: ExplainedInput[];
61
+ outputAmount: bigint;
62
+ memo?: string;
63
+ /**
64
+ * Maps ATA address → owner address for CreateAssociatedTokenAccount instructions.
65
+ * Allows resolving newly-created token account ownership without an external lookup.
66
+ */
67
+ ataOwnerMap: Record<string, string>;
68
+ /**
69
+ * Token enablements from CreateAssociatedTokenAccount instructions.
70
+ * Contains the ATA address and mint address (consumer resolves token names).
71
+ */
72
+ tokenEnablements: TokenEnablement[];
73
+ /** Staking authorize details, present when the transaction changes stake authority. */
74
+ stakingAuthorize?: StakingAuthorizeInfo;
75
+ numSignatures: number;
76
+ }
77
+ /**
78
+ * Explain a Solana transaction.
79
+ *
80
+ * Takes raw transaction bytes and fee parameters, then returns a structured
81
+ * explanation including transaction type, outputs, inputs, fee, memo, and
82
+ * associated-token-account owner mappings.
83
+ *
84
+ * @param input - Raw transaction bytes (caller is responsible for decoding base64/hex)
85
+ * @param options - Fee parameters for calculating the total fee
86
+ * @returns An ExplainedTransaction with all fields populated
87
+ *
88
+ * @example
89
+ * ```typescript
90
+ * import { explainTransaction } from '@bitgo/wasm-solana';
91
+ *
92
+ * const txBytes = Buffer.from(txBase64, 'base64');
93
+ * const explained = explainTransaction(txBytes, {
94
+ * lamportsPerSignature: 5000n,
95
+ * tokenAccountRentExemptAmount: 2039280n,
96
+ * });
97
+ * console.log(explained.type); // "Send", "StakingActivate", etc.
98
+ * ```
99
+ */
100
+ export declare function explainTransaction(input: Uint8Array, options: ExplainOptions): ExplainedTransaction;
@@ -0,0 +1,311 @@
1
+ "use strict";
2
+ /**
3
+ * High-level transaction explanation.
4
+ *
5
+ * Builds on top of `parseTransaction` (WASM) to provide a structured
6
+ * "explain" view of a Solana transaction: type, outputs, inputs, fee, etc.
7
+ *
8
+ * The WASM parser returns raw individual instructions. This module combines
9
+ * related instruction sequences into higher-level operations and derives the
10
+ * overall transaction type.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.TransactionType = void 0;
14
+ exports.explainTransaction = explainTransaction;
15
+ const parser_js_1 = require("./parser.js");
16
+ // =============================================================================
17
+ // Public types
18
+ // =============================================================================
19
+ var TransactionType;
20
+ (function (TransactionType) {
21
+ TransactionType["Send"] = "Send";
22
+ TransactionType["StakingActivate"] = "StakingActivate";
23
+ TransactionType["StakingDeactivate"] = "StakingDeactivate";
24
+ TransactionType["StakingWithdraw"] = "StakingWithdraw";
25
+ TransactionType["StakingAuthorize"] = "StakingAuthorize";
26
+ TransactionType["StakingDelegate"] = "StakingDelegate";
27
+ TransactionType["WalletInitialization"] = "WalletInitialization";
28
+ TransactionType["AssociatedTokenAccountInitialization"] = "AssociatedTokenAccountInitialization";
29
+ })(TransactionType || (exports.TransactionType = TransactionType = {}));
30
+ /** Solana base fee per signature (protocol constant). */
31
+ const DEFAULT_LAMPORTS_PER_SIGNATURE = 5000n;
32
+ /**
33
+ * Scan for multi-instruction patterns that should be combined:
34
+ *
35
+ * 1. CreateAccount + StakeInitialize [+ StakingDelegate] → StakingActivate
36
+ * - With Delegate following = NATIVE staking
37
+ * - Without Delegate = MARINADE staking (Marinade's program handles delegation)
38
+ * 2. CreateAccount + NonceInitialize → WalletInitialization
39
+ * - BitGo creates a nonce account during wallet initialization
40
+ */
41
+ function detectCombinedPattern(instructions) {
42
+ for (let i = 0; i < instructions.length - 1; i++) {
43
+ const curr = instructions[i];
44
+ const next = instructions[i + 1];
45
+ if (curr.type === "CreateAccount" && next.type === "StakeInitialize") {
46
+ return {
47
+ kind: "StakingActivate",
48
+ fromAddress: curr.fromAddress,
49
+ stakingAddress: curr.newAddress,
50
+ amount: curr.amount,
51
+ };
52
+ }
53
+ if (curr.type === "CreateAccount" && next.type === "NonceInitialize") {
54
+ return {
55
+ kind: "WalletInitialization",
56
+ fromAddress: curr.fromAddress,
57
+ nonceAddress: curr.newAddress,
58
+ amount: curr.amount,
59
+ };
60
+ }
61
+ }
62
+ return null;
63
+ }
64
+ // =============================================================================
65
+ // Transaction type derivation
66
+ // =============================================================================
67
+ const BOILERPLATE_TYPES = new Set([
68
+ "NonceAdvance",
69
+ "Memo",
70
+ "SetComputeUnitLimit",
71
+ "SetPriorityFee",
72
+ ]);
73
+ function deriveTransactionType(instructions, combined, memo) {
74
+ if (combined)
75
+ return TransactionType[combined.kind];
76
+ // Marinade deactivate: Transfer + memo containing "PrepareForRevoke"
77
+ if (memo?.includes("PrepareForRevoke"))
78
+ return TransactionType.StakingDeactivate;
79
+ // Jito pool operations map to staking types
80
+ if (instructions.some((i) => i.type === "StakePoolDepositSol"))
81
+ return TransactionType.StakingActivate;
82
+ if (instructions.some((i) => i.type === "StakePoolWithdrawStake"))
83
+ return TransactionType.StakingDeactivate;
84
+ // ATA-only transactions (ignoring boilerplate like nonce/memo/compute budget)
85
+ const meaningful = instructions.filter((i) => !BOILERPLATE_TYPES.has(i.type));
86
+ if (meaningful.length > 0 && meaningful.every((i) => i.type === "CreateAssociatedTokenAccount")) {
87
+ return TransactionType.AssociatedTokenAccountInitialization;
88
+ }
89
+ // For staking instructions, the instruction type IS the transaction type
90
+ const staking = instructions.find((i) => i.type in TransactionType);
91
+ if (staking)
92
+ return TransactionType[staking.type];
93
+ return TransactionType.Send;
94
+ }
95
+ // =============================================================================
96
+ // Transaction ID extraction
97
+ // =============================================================================
98
+ // Base58 encoding of 64 zero bytes. Unsigned transactions have all-zero
99
+ // signatures which encode to this constant.
100
+ const ALL_ZEROS_BASE58 = "1111111111111111111111111111111111111111111111111111111111111111";
101
+ function extractTransactionId(signatures) {
102
+ const sig = signatures[0];
103
+ if (!sig || sig === ALL_ZEROS_BASE58)
104
+ return undefined;
105
+ return sig;
106
+ }
107
+ // =============================================================================
108
+ // Main export
109
+ // =============================================================================
110
+ /**
111
+ * Explain a Solana transaction.
112
+ *
113
+ * Takes raw transaction bytes and fee parameters, then returns a structured
114
+ * explanation including transaction type, outputs, inputs, fee, memo, and
115
+ * associated-token-account owner mappings.
116
+ *
117
+ * @param input - Raw transaction bytes (caller is responsible for decoding base64/hex)
118
+ * @param options - Fee parameters for calculating the total fee
119
+ * @returns An ExplainedTransaction with all fields populated
120
+ *
121
+ * @example
122
+ * ```typescript
123
+ * import { explainTransaction } from '@bitgo/wasm-solana';
124
+ *
125
+ * const txBytes = Buffer.from(txBase64, 'base64');
126
+ * const explained = explainTransaction(txBytes, {
127
+ * lamportsPerSignature: 5000n,
128
+ * tokenAccountRentExemptAmount: 2039280n,
129
+ * });
130
+ * console.log(explained.type); // "Send", "StakingActivate", etc.
131
+ * ```
132
+ */
133
+ function explainTransaction(input, options) {
134
+ const { lamportsPerSignature, tokenAccountRentExemptAmount } = options;
135
+ const parsed = (0, parser_js_1.parseTransactionData)(input);
136
+ // --- Transaction ID ---
137
+ const id = extractTransactionId(parsed.signatures);
138
+ // --- Fee calculation ---
139
+ // Base fee = numSignatures × lamportsPerSignature
140
+ let fee = BigInt(parsed.numSignatures) *
141
+ (lamportsPerSignature !== undefined
142
+ ? BigInt(lamportsPerSignature)
143
+ : DEFAULT_LAMPORTS_PER_SIGNATURE);
144
+ // Each CreateAssociatedTokenAccount instruction creates a new token account,
145
+ // which requires a rent-exempt deposit. Add that to the fee.
146
+ const ataCount = parsed.instructionsData.filter((i) => i.type === "CreateAssociatedTokenAccount").length;
147
+ if (ataCount > 0 && tokenAccountRentExemptAmount !== undefined) {
148
+ fee += BigInt(ataCount) * BigInt(tokenAccountRentExemptAmount);
149
+ }
150
+ // --- Extract memo (needed before type derivation) ---
151
+ let memo;
152
+ for (const instr of parsed.instructionsData) {
153
+ if (instr.type === "Memo") {
154
+ memo = instr.memo;
155
+ }
156
+ }
157
+ // --- Detect combined instruction patterns ---
158
+ const combined = detectCombinedPattern(parsed.instructionsData);
159
+ const txType = deriveTransactionType(parsed.instructionsData, combined, memo);
160
+ // Marinade deactivate: Transfer + PrepareForRevoke memo.
161
+ // The Transfer is a contract interaction (not a real value transfer),
162
+ // so we skip it from outputs.
163
+ const isMarinadeDeactivate = txType === TransactionType.StakingDeactivate &&
164
+ memo !== undefined &&
165
+ memo.includes("PrepareForRevoke");
166
+ // --- Extract outputs and inputs ---
167
+ const outputs = [];
168
+ const inputs = [];
169
+ if (combined?.kind === "StakingActivate") {
170
+ // Combined native/Marinade staking activate — the staking address receives
171
+ // the full amount from the funding account.
172
+ outputs.push({
173
+ address: combined.stakingAddress,
174
+ amount: combined.amount,
175
+ });
176
+ inputs.push({
177
+ address: combined.fromAddress,
178
+ value: combined.amount,
179
+ });
180
+ }
181
+ else if (combined?.kind === "WalletInitialization") {
182
+ // Wallet initialization — funds the new nonce account.
183
+ outputs.push({
184
+ address: combined.nonceAddress,
185
+ amount: combined.amount,
186
+ });
187
+ inputs.push({
188
+ address: combined.fromAddress,
189
+ value: combined.amount,
190
+ });
191
+ }
192
+ else {
193
+ // Process individual instructions for outputs/inputs
194
+ for (const instr of parsed.instructionsData) {
195
+ switch (instr.type) {
196
+ case "Transfer":
197
+ // Skip Transfer for Marinade deactivate — it's a program interaction,
198
+ // not a real value transfer to an external address.
199
+ if (isMarinadeDeactivate)
200
+ break;
201
+ outputs.push({
202
+ address: instr.toAddress,
203
+ amount: instr.amount,
204
+ });
205
+ inputs.push({
206
+ address: instr.fromAddress,
207
+ value: instr.amount,
208
+ });
209
+ break;
210
+ case "TokenTransfer":
211
+ outputs.push({
212
+ address: instr.toAddress,
213
+ amount: instr.amount,
214
+ tokenName: instr.tokenAddress,
215
+ });
216
+ inputs.push({
217
+ address: instr.fromAddress,
218
+ value: instr.amount,
219
+ });
220
+ break;
221
+ case "StakingActivate":
222
+ outputs.push({
223
+ address: instr.stakingAddress,
224
+ amount: instr.amount,
225
+ });
226
+ inputs.push({
227
+ address: instr.fromAddress,
228
+ value: instr.amount,
229
+ });
230
+ break;
231
+ case "StakingWithdraw":
232
+ // Withdraw: SOL flows FROM the staking address TO the recipient.
233
+ // `fromAddress` is the recipient (where funds go),
234
+ // `stakingAddress` is the source.
235
+ outputs.push({
236
+ address: instr.fromAddress,
237
+ amount: instr.amount,
238
+ });
239
+ inputs.push({
240
+ address: instr.stakingAddress,
241
+ value: instr.amount,
242
+ });
243
+ break;
244
+ case "StakePoolDepositSol":
245
+ // Jito liquid staking: SOL is deposited into the stake pool.
246
+ // The funding account is debited; output goes to the pool address.
247
+ outputs.push({
248
+ address: instr.stakePool,
249
+ amount: instr.lamports,
250
+ });
251
+ inputs.push({
252
+ address: instr.fundingAccount,
253
+ value: instr.lamports,
254
+ });
255
+ break;
256
+ // StakingDeactivate, StakingAuthorize, StakingDelegate,
257
+ // StakePoolWithdrawStake, NonceAdvance, CreateAccount,
258
+ // StakeInitialize, NonceInitialize, SetComputeUnitLimit,
259
+ // SetPriorityFee, CreateAssociatedTokenAccount,
260
+ // CloseAssociatedTokenAccount, Memo, Unknown
261
+ // — no value inputs/outputs.
262
+ }
263
+ }
264
+ }
265
+ // --- Output amount ---
266
+ // Only count native SOL outputs (no tokenName). Token amounts are in different
267
+ // denominations and shouldn't be mixed with SOL lamports.
268
+ const outputAmount = outputs.filter((o) => !o.tokenName).reduce((sum, o) => sum + o.amount, 0n);
269
+ // --- ATA owner mapping and token enablements ---
270
+ const ataOwnerMap = {};
271
+ const tokenEnablements = [];
272
+ for (const instr of parsed.instructionsData) {
273
+ if (instr.type === "CreateAssociatedTokenAccount") {
274
+ ataOwnerMap[instr.ataAddress] = instr.ownerAddress;
275
+ tokenEnablements.push({
276
+ address: instr.ataAddress,
277
+ mintAddress: instr.mintAddress,
278
+ });
279
+ }
280
+ }
281
+ // --- Staking authorize ---
282
+ let stakingAuthorize;
283
+ for (const instr of parsed.instructionsData) {
284
+ if (instr.type === "StakingAuthorize") {
285
+ stakingAuthorize = {
286
+ stakingAddress: instr.stakingAddress,
287
+ oldAuthorizeAddress: instr.oldAuthorizeAddress,
288
+ newAuthorizeAddress: instr.newAuthorizeAddress,
289
+ authorizeType: instr.authorizeType,
290
+ custodianAddress: instr.custodianAddress,
291
+ };
292
+ break;
293
+ }
294
+ }
295
+ return {
296
+ id,
297
+ type: txType,
298
+ feePayer: parsed.feePayer,
299
+ fee,
300
+ blockhash: parsed.nonce,
301
+ durableNonce: parsed.durableNonce,
302
+ outputs,
303
+ inputs,
304
+ outputAmount,
305
+ memo,
306
+ ataOwnerMap,
307
+ tokenEnablements,
308
+ stakingAuthorize,
309
+ numSignatures: parsed.numSignatures,
310
+ };
311
+ }
@@ -3,16 +3,53 @@ export * as pubkey from "./pubkey.js";
3
3
  export * as transaction from "./transaction.js";
4
4
  export * as parser from "./parser.js";
5
5
  export * as builder from "./builder.js";
6
+ export * as explain from "./explain.js";
6
7
  export { Keypair } from "./keypair.js";
7
8
  export { Pubkey } from "./pubkey.js";
8
9
  export { Transaction } from "./transaction.js";
9
10
  export { VersionedTransaction, isVersionedTransaction } from "./versioned.js";
10
11
  export type { AddressLookupTableData } from "./versioned.js";
11
- export { parseTransaction } from "./parser.js";
12
+ export { parseTransactionData } from "./parser.js";
12
13
  export { buildFromVersionedData } from "./builder.js";
13
14
  export { buildFromIntent, buildFromIntent as buildTransactionFromIntent } from "./intentBuilder.js";
14
- export type { BaseIntent, PaymentIntent, StakeIntent, UnstakeIntent, ClaimIntent, DeactivateIntent, DelegateIntent, EnableTokenIntent, CloseAtaIntent, ConsolidateIntent, SolanaIntent, StakePoolConfig, BuildFromIntentParams, BuildFromIntentResult, GeneratedKeypair, NonceSource, BlockhashNonce, DurableNonce, } from "./intentBuilder.js";
15
+ export { explainTransaction, TransactionType } from "./explain.js";
16
+ import { Transaction as _Transaction } from "./transaction.js";
17
+ /**
18
+ * Parse a Solana transaction from raw bytes.
19
+ *
20
+ * Returns a `Transaction` instance that can be both inspected and signed.
21
+ * Use `.parse()` on the returned Transaction to get decoded instruction data.
22
+ *
23
+ * This is the single entry point for working with transactions — like
24
+ * `BitGoPsbt.fromBytes()` in wasm-utxo.
25
+ *
26
+ * @param bytes - Raw transaction bytes
27
+ * @returns A Transaction that can be inspected (`.parse()`) and signed (`.addSignature()`)
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * import { parseTransaction } from '@bitgo/wasm-solana';
32
+ *
33
+ * const tx = parseTransaction(txBytes);
34
+ *
35
+ * // Inspect
36
+ * const parsed = tx.parse();
37
+ * console.log(parsed.feePayer);
38
+ * for (const instr of parsed.instructionsData) {
39
+ * if (instr.type === 'Transfer') {
40
+ * console.log(`${instr.amount} lamports to ${instr.toAddress}`);
41
+ * }
42
+ * }
43
+ *
44
+ * // Sign
45
+ * tx.addSignature(pubkey, signature);
46
+ * const signedBytes = tx.toBytes();
47
+ * ```
48
+ */
49
+ export declare function parseTransaction(bytes: Uint8Array): _Transaction;
50
+ export type { BaseIntent, PaymentIntent, StakeIntent, UnstakeIntent, ClaimIntent, DeactivateIntent, DelegateIntent, EnableTokenIntent, CloseAtaIntent, ConsolidateIntent, AuthorizeIntent, CustomTxIntent, CustomTxInstruction, CustomTxKey, SolanaIntent, StakePoolConfig, BuildFromIntentParams, BuildFromIntentResult, GeneratedKeypair, NonceSource, BlockhashNonce, DurableNonce, } from "./intentBuilder.js";
15
51
  export { system_program_id as systemProgramId, stake_program_id as stakeProgramId, compute_budget_program_id as computeBudgetProgramId, memo_program_id as memoProgramId, token_program_id as tokenProgramId, token_2022_program_id as token2022ProgramId, ata_program_id as ataProgramId, stake_pool_program_id as stakePoolProgramId, stake_account_space as stakeAccountSpace, nonce_account_space as nonceAccountSpace, sysvar_recent_blockhashes as sysvarRecentBlockhashes, get_associated_token_address as getAssociatedTokenAddress, find_withdraw_authority_program_address as findWithdrawAuthorityProgramAddress, } from "./wasm/wasm_solana.js";
16
52
  export type { AccountMeta, Instruction } from "./transaction.js";
17
- export type { TransactionInput, ParsedTransaction, DurableNonce as ParsedDurableNonce, InstructionParams, TransferParams, CreateAccountParams, NonceAdvanceParams, CreateNonceAccountParams, NonceInitializeParams, StakeInitializeParams, StakingActivateParams, StakingDeactivateParams, StakingWithdrawParams, StakingDelegateParams, StakingAuthorizeParams, SetComputeUnitLimitParams, SetPriorityFeeParams, TokenTransferParams, CreateAtaParams, CloseAtaParams, MemoParams, StakePoolDepositSolParams, StakePoolWithdrawStakeParams, UnknownInstructionParams, } from "./parser.js";
53
+ export type { ParsedTransaction, DurableNonce as ParsedDurableNonce, InstructionParams, TransferParams, CreateAccountParams, NonceAdvanceParams, CreateNonceAccountParams, NonceInitializeParams, StakeInitializeParams, StakingActivateParams, StakingDeactivateParams, StakingWithdrawParams, StakingDelegateParams, StakingAuthorizeParams, SetComputeUnitLimitParams, SetPriorityFeeParams, TokenTransferParams, CreateAtaParams, CloseAtaParams, MemoParams, StakePoolDepositSolParams, StakePoolWithdrawStakeParams, UnknownInstructionParams, } from "./parser.js";
54
+ export type { ExplainedTransaction, ExplainedOutput, ExplainedInput, ExplainOptions, TokenEnablement, StakingAuthorizeInfo, } from "./explain.js";
18
55
  export type { AddressLookupTable as BuilderAddressLookupTable, RawVersionedTransactionData, VersionedInstruction as BuilderVersionedInstruction, MessageHeader, } from "./builder.js";
@@ -33,7 +33,8 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.findWithdrawAuthorityProgramAddress = exports.getAssociatedTokenAddress = exports.sysvarRecentBlockhashes = exports.nonceAccountSpace = exports.stakeAccountSpace = exports.stakePoolProgramId = exports.ataProgramId = exports.token2022ProgramId = exports.tokenProgramId = exports.memoProgramId = exports.computeBudgetProgramId = exports.stakeProgramId = exports.systemProgramId = exports.buildTransactionFromIntent = exports.buildFromIntent = exports.buildFromVersionedData = exports.parseTransaction = exports.isVersionedTransaction = exports.VersionedTransaction = exports.Transaction = exports.Pubkey = exports.Keypair = exports.builder = exports.parser = exports.transaction = exports.pubkey = exports.keypair = void 0;
36
+ exports.findWithdrawAuthorityProgramAddress = exports.getAssociatedTokenAddress = exports.sysvarRecentBlockhashes = exports.nonceAccountSpace = exports.stakeAccountSpace = exports.stakePoolProgramId = exports.ataProgramId = exports.token2022ProgramId = exports.tokenProgramId = exports.memoProgramId = exports.computeBudgetProgramId = exports.stakeProgramId = exports.systemProgramId = exports.TransactionType = exports.explainTransaction = exports.buildTransactionFromIntent = exports.buildFromIntent = exports.buildFromVersionedData = exports.parseTransactionData = exports.isVersionedTransaction = exports.VersionedTransaction = exports.Transaction = exports.Pubkey = exports.Keypair = exports.explain = exports.builder = exports.parser = exports.transaction = exports.pubkey = exports.keypair = void 0;
37
+ exports.parseTransaction = parseTransaction;
37
38
  const wasm = __importStar(require("./wasm/wasm_solana.js"));
38
39
  // Force webpack to include the WASM module
39
40
  void wasm;
@@ -43,6 +44,7 @@ exports.pubkey = __importStar(require("./pubkey.js"));
43
44
  exports.transaction = __importStar(require("./transaction.js"));
44
45
  exports.parser = __importStar(require("./parser.js"));
45
46
  exports.builder = __importStar(require("./builder.js"));
47
+ exports.explain = __importStar(require("./explain.js"));
46
48
  // Top-level class exports for convenience
47
49
  var keypair_js_1 = require("./keypair.js");
48
50
  Object.defineProperty(exports, "Keypair", { enumerable: true, get: function () { return keypair_js_1.Keypair; } });
@@ -56,12 +58,52 @@ Object.defineProperty(exports, "VersionedTransaction", { enumerable: true, get:
56
58
  Object.defineProperty(exports, "isVersionedTransaction", { enumerable: true, get: function () { return versioned_js_1.isVersionedTransaction; } });
57
59
  // Top-level function exports
58
60
  var parser_js_1 = require("./parser.js");
59
- Object.defineProperty(exports, "parseTransaction", { enumerable: true, get: function () { return parser_js_1.parseTransaction; } });
61
+ Object.defineProperty(exports, "parseTransactionData", { enumerable: true, get: function () { return parser_js_1.parseTransactionData; } });
60
62
  var builder_js_1 = require("./builder.js");
61
63
  Object.defineProperty(exports, "buildFromVersionedData", { enumerable: true, get: function () { return builder_js_1.buildFromVersionedData; } });
62
64
  var intentBuilder_js_1 = require("./intentBuilder.js");
63
65
  Object.defineProperty(exports, "buildFromIntent", { enumerable: true, get: function () { return intentBuilder_js_1.buildFromIntent; } });
64
66
  Object.defineProperty(exports, "buildTransactionFromIntent", { enumerable: true, get: function () { return intentBuilder_js_1.buildFromIntent; } });
67
+ var explain_js_1 = require("./explain.js");
68
+ Object.defineProperty(exports, "explainTransaction", { enumerable: true, get: function () { return explain_js_1.explainTransaction; } });
69
+ Object.defineProperty(exports, "TransactionType", { enumerable: true, get: function () { return explain_js_1.TransactionType; } });
70
+ // Re-export Transaction import for parseTransaction
71
+ const transaction_js_2 = require("./transaction.js");
72
+ /**
73
+ * Parse a Solana transaction from raw bytes.
74
+ *
75
+ * Returns a `Transaction` instance that can be both inspected and signed.
76
+ * Use `.parse()` on the returned Transaction to get decoded instruction data.
77
+ *
78
+ * This is the single entry point for working with transactions — like
79
+ * `BitGoPsbt.fromBytes()` in wasm-utxo.
80
+ *
81
+ * @param bytes - Raw transaction bytes
82
+ * @returns A Transaction that can be inspected (`.parse()`) and signed (`.addSignature()`)
83
+ *
84
+ * @example
85
+ * ```typescript
86
+ * import { parseTransaction } from '@bitgo/wasm-solana';
87
+ *
88
+ * const tx = parseTransaction(txBytes);
89
+ *
90
+ * // Inspect
91
+ * const parsed = tx.parse();
92
+ * console.log(parsed.feePayer);
93
+ * for (const instr of parsed.instructionsData) {
94
+ * if (instr.type === 'Transfer') {
95
+ * console.log(`${instr.amount} lamports to ${instr.toAddress}`);
96
+ * }
97
+ * }
98
+ *
99
+ * // Sign
100
+ * tx.addSignature(pubkey, signature);
101
+ * const signedBytes = tx.toBytes();
102
+ * ```
103
+ */
104
+ function parseTransaction(bytes) {
105
+ return transaction_js_2.Transaction.fromBytes(bytes);
106
+ }
65
107
  // Program ID constants (from WASM)
66
108
  var wasm_solana_js_1 = require("./wasm/wasm_solana.js");
67
109
  Object.defineProperty(exports, "systemProgramId", { enumerable: true, get: function () { return wasm_solana_js_1.system_program_id; } });
@@ -5,14 +5,7 @@
5
5
  * matching BitGoJS's TxData format.
6
6
  *
7
7
  * All monetary amounts (amount, fee, lamports, poolTokens) are returned as bigint.
8
- * Accepts both raw bytes and Transaction objects for convenience.
9
8
  */
10
- import type { Transaction } from "./transaction.js";
11
- import type { VersionedTransaction } from "./versioned.js";
12
- /**
13
- * Input type for parseTransaction - accepts bytes or Transaction objects.
14
- */
15
- export type TransactionInput = Uint8Array | Transaction | VersionedTransaction;
16
9
  /** SOL transfer parameters */
17
10
  export interface TransferParams {
18
11
  type: "Transfer";
@@ -214,40 +207,13 @@ export interface ParsedTransaction {
214
207
  signatures: string[];
215
208
  }
216
209
  /**
217
- * Parse a Solana transaction into structured data.
218
- *
219
- * This is the main entry point for transaction parsing. It deserializes the
220
- * transaction and decodes all instructions into semantic types.
221
- *
222
- * All monetary amounts (amount, fee, lamports, poolTokens) are returned as bigint
223
- * directly from WASM - no post-processing needed.
210
+ * Parse raw transaction bytes into a plain data object with decoded instructions.
224
211
  *
225
- * Note: This returns the raw parsed data including NonceAdvance instructions.
226
- * Consumers (like BitGoJS) may choose to filter NonceAdvance from instructionsData
227
- * since that info is also available in durableNonce.
212
+ * This is the low-level parsing function. Most callers should use the top-level
213
+ * `parseTransaction(bytes)` which returns a `Transaction` instance with both
214
+ * inspection (`.parse()`) and signing (`.addSignature()`) capabilities.
228
215
  *
229
- * @param input - Raw transaction bytes, Transaction, or VersionedTransaction
216
+ * @param bytes - Raw transaction bytes
230
217
  * @returns A ParsedTransaction with all instructions decoded
231
- * @throws Error if the transaction cannot be parsed
232
- *
233
- * @example
234
- * ```typescript
235
- * import { parseTransaction, buildTransaction, Transaction } from '@bitgo/wasm-solana';
236
- *
237
- * // From bytes
238
- * const txBytes = Buffer.from(base64EncodedTx, 'base64');
239
- * const parsed = parseTransaction(txBytes);
240
- *
241
- * // Directly from a Transaction object (no roundtrip through bytes)
242
- * const tx = buildTransaction(intent);
243
- * const parsed = parseTransaction(tx);
244
- *
245
- * console.log(parsed.feePayer);
246
- * for (const instr of parsed.instructionsData) {
247
- * if (instr.type === 'Transfer') {
248
- * console.log(`Transfer ${instr.amount} from ${instr.fromAddress} to ${instr.toAddress}`);
249
- * }
250
- * }
251
- * ```
252
218
  */
253
- export declare function parseTransaction(input: TransactionInput): ParsedTransaction;
219
+ export declare function parseTransactionData(bytes: Uint8Array): ParsedTransaction;
@@ -6,53 +6,23 @@
6
6
  * matching BitGoJS's TxData format.
7
7
  *
8
8
  * All monetary amounts (amount, fee, lamports, poolTokens) are returned as bigint.
9
- * Accepts both raw bytes and Transaction objects for convenience.
10
9
  */
11
10
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.parseTransaction = parseTransaction;
11
+ exports.parseTransactionData = parseTransactionData;
13
12
  const wasm_solana_js_1 = require("./wasm/wasm_solana.js");
14
13
  // =============================================================================
15
- // parseTransaction function
14
+ // parseTransactionData function
16
15
  // =============================================================================
17
16
  /**
18
- * Parse a Solana transaction into structured data.
17
+ * Parse raw transaction bytes into a plain data object with decoded instructions.
19
18
  *
20
- * This is the main entry point for transaction parsing. It deserializes the
21
- * transaction and decodes all instructions into semantic types.
19
+ * This is the low-level parsing function. Most callers should use the top-level
20
+ * `parseTransaction(bytes)` which returns a `Transaction` instance with both
21
+ * inspection (`.parse()`) and signing (`.addSignature()`) capabilities.
22
22
  *
23
- * All monetary amounts (amount, fee, lamports, poolTokens) are returned as bigint
24
- * directly from WASM - no post-processing needed.
25
- *
26
- * Note: This returns the raw parsed data including NonceAdvance instructions.
27
- * Consumers (like BitGoJS) may choose to filter NonceAdvance from instructionsData
28
- * since that info is also available in durableNonce.
29
- *
30
- * @param input - Raw transaction bytes, Transaction, or VersionedTransaction
23
+ * @param bytes - Raw transaction bytes
31
24
  * @returns A ParsedTransaction with all instructions decoded
32
- * @throws Error if the transaction cannot be parsed
33
- *
34
- * @example
35
- * ```typescript
36
- * import { parseTransaction, buildTransaction, Transaction } from '@bitgo/wasm-solana';
37
- *
38
- * // From bytes
39
- * const txBytes = Buffer.from(base64EncodedTx, 'base64');
40
- * const parsed = parseTransaction(txBytes);
41
- *
42
- * // Directly from a Transaction object (no roundtrip through bytes)
43
- * const tx = buildTransaction(intent);
44
- * const parsed = parseTransaction(tx);
45
- *
46
- * console.log(parsed.feePayer);
47
- * for (const instr of parsed.instructionsData) {
48
- * if (instr.type === 'Transfer') {
49
- * console.log(`Transfer ${instr.amount} from ${instr.fromAddress} to ${instr.toAddress}`);
50
- * }
51
- * }
52
- * ```
53
25
  */
54
- function parseTransaction(input) {
55
- // If input is a Transaction or VersionedTransaction, extract bytes
56
- const bytes = input instanceof Uint8Array ? input : input.toBytes();
26
+ function parseTransactionData(bytes) {
57
27
  return wasm_solana_js_1.ParserNamespace.parse_transaction(bytes);
58
28
  }