Skip to content

Commit 97c511d

Browse files
committed
feat(sdk-coin-sol): add WASM-based transaction parsing via @bitgo/wasm-solana
Adds WASM-based transaction parsing using @bitgo/wasm-solana package with no @solana/web3.js dependency in the parsing path. WasmTransaction class for parsing Solana transactions using WASM: - Transaction ID extraction from signatures - Signable payload generation - JSON serialization with parsed instruction data - Transaction explanation for human readability - Token name resolution via BitGo statics Clean instruction combiner without @solana/web3.js dependency: - Combines raw WASM-parsed instructions into BitGoJS InstructionParams - Pattern matching for multi-instruction combinations: - CreateAccount + NonceInitialize → WalletInit - CreateAccount + StakeInitialize + Delegate → StakingActivate (Native) - CreateAccount + StakeInitialize → StakingActivate (Marinade) - StakePoolDepositSol → StakingActivate (Jito) - StakePoolWithdrawStake → StakingDeactivate (Jito) - Derives transaction type from combined instructions - Handles bigint to string conversion for amounts Thin wrapper that orchestrates WASM instruction parsing: 1. Gets transaction bytes from WASM transaction 2. Parses with wasm-solana's parseTransaction() 3. Delegates to wasmParsedInstructionCombiner - Added explainTransactionWithWasm() for WASM-based transaction explanation - Integration with new WASM parsing layer Fixed edge cases in staking instruction parsing: - StakingAuthorize: support 4-key instructions (custodian optional) - StakingAuthorizeRaw: support 2-3 instructions (one or both authorities) - wasmTransaction.ts: Unit tests for WasmTransaction class - jitoWasmVerification.ts: Jito staking WASM verification tests TICKET: BTC-0
1 parent 9b284f3 commit 97c511d

12 files changed

Lines changed: 1538 additions & 114 deletions
388 KB
Binary file not shown.

modules/sdk-coin-sol/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
"@bitgo/sdk-core": "^36.29.0",
4545
"@bitgo/sdk-lib-mpc": "^10.8.1",
4646
"@bitgo/statics": "^58.23.0",
47+
"@bitgo/wasm-solana": "file:bitgo-wasm-solana-0.0.1.tgz",
4748
"@solana/spl-stake-pool": "1.1.8",
4849
"@solana/spl-token": "0.3.1",
4950
"@solana/web3.js": "1.92.1",

modules/sdk-coin-sol/src/lib/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ export { StakingWithdrawBuilder } from './stakingWithdrawBuilder';
1414
export { TokenTransferBuilder } from './tokenTransferBuilder';
1515
export { Transaction } from './transaction';
1616
export { TransactionBuilder } from './transactionBuilder';
17+
export { WasmTransaction } from './wasm';
1718
export { TransactionBuilderFactory } from './transactionBuilderFactory';
1819
export { TransferBuilder } from './transferBuilder';
1920
export { TransferBuilderV2 } from './transferBuilderV2';
2021
export { WalletInitializationBuilder } from './walletInitializationBuilder';
2122
export { Interface, Utils };
2223
export { MessageBuilderFactory } from './messages';
24+
export { InstructionBuilderTypes } from './constants';

modules/sdk-coin-sol/src/lib/instructionParamsFactory.ts

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,7 +1171,10 @@ function parseStakingAuthorizeInstructions(
11711171
*/
11721172
function parseStakingAuthorizeRawInstructions(instructions: TransactionInstruction[]): Array<Nonce | StakingAuthorize> {
11731173
const instructionData: Array<Nonce | StakingAuthorize> = [];
1174-
assert(instructions.length === 2, 'Invalid number of instructions');
1174+
// StakingAuthorizeRaw transactions have:
1175+
// - 2 instructions: NonceAdvance + 1 Authorize (changing either staking OR withdraw authority)
1176+
// - 3 instructions: NonceAdvance + 2 Authorizes (changing BOTH staking AND withdraw authority)
1177+
assert(instructions.length >= 2 && instructions.length <= 3, 'Invalid number of instructions');
11751178
const advanceNonceInstruction = SystemInstruction.decodeNonceAdvance(instructions[0]);
11761179
const nonce: Nonce = {
11771180
type: InstructionBuilderTypes.NonceAdvance,
@@ -1181,17 +1184,24 @@ function parseStakingAuthorizeRawInstructions(instructions: TransactionInstructi
11811184
},
11821185
};
11831186
instructionData.push(nonce);
1184-
const authorize = instructions[1];
1185-
assert(authorize.keys.length === 5, 'Invalid number of keys in authorize instruction');
1186-
instructionData.push({
1187-
type: InstructionBuilderTypes.StakingAuthorize,
1188-
params: {
1189-
stakingAddress: authorize.keys[0].pubkey.toString(),
1190-
oldAuthorizeAddress: authorize.keys[2].pubkey.toString(),
1191-
newAuthorizeAddress: authorize.keys[3].pubkey.toString(),
1192-
custodianAddress: authorize.keys[4].pubkey.toString(),
1193-
},
1194-
});
1187+
1188+
// Process all authorize instructions (1 or 2)
1189+
for (let i = 1; i < instructions.length; i++) {
1190+
const authorize = instructions[i];
1191+
// Authorize instruction keys: [stakePubkey, clockSysvar, oldAuthority, newAuthority, custodian?]
1192+
// - 4 keys: no custodian required
1193+
// - 5 keys: custodian is present (required when stake is locked)
1194+
assert(authorize.keys.length >= 4 && authorize.keys.length <= 5, 'Invalid number of keys in authorize instruction');
1195+
instructionData.push({
1196+
type: InstructionBuilderTypes.StakingAuthorize,
1197+
params: {
1198+
stakingAddress: authorize.keys[0].pubkey.toString(),
1199+
oldAuthorizeAddress: authorize.keys[2].pubkey.toString(),
1200+
newAuthorizeAddress: authorize.keys[3].pubkey.toString(),
1201+
custodianAddress: authorize.keys.length === 5 ? authorize.keys[4].pubkey.toString() : '',
1202+
},
1203+
});
1204+
}
11951205
return instructionData;
11961206
}
11971207

@@ -1239,7 +1249,7 @@ function parseCustomInstructions(
12391249
return instructionData;
12401250
}
12411251

1242-
function findTokenName(
1252+
export function findTokenName(
12431253
mintAddress: string,
12441254
instructionMetadata?: InstructionParams[],
12451255
_useTokenAddressTokenName?: boolean
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/**
2+
* WASM-only implementations for Solana.
3+
*
4+
* These implementations use @bitgo/wasm-solana exclusively,
5+
* with zero @solana/web3.js dependencies.
6+
*/
7+
export { WasmTransaction } from './transaction';

0 commit comments

Comments
 (0)