Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added bitgo-wasm-dot-0.0.1.tgz
Binary file not shown.
Binary file added modules/sdk-coin-dot/bitgo-wasm-dot-0.0.1.tgz
Binary file not shown.
1 change: 1 addition & 0 deletions modules/sdk-coin-dot/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"@bitgo/sdk-core": "^36.30.0",
"@bitgo/sdk-lib-mpc": "^10.9.0",
"@bitgo/statics": "^58.24.0",
"@bitgo/wasm-dot": "file:bitgo-wasm-dot-0.0.1.tgz",
"@polkadot/api": "14.1.1",
"@polkadot/api-augment": "14.1.1",
"@polkadot/keyring": "13.3.1",
Expand Down
2 changes: 2 additions & 0 deletions modules/sdk-coin-dot/src/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ export { TransactionBuilderFactory } from './transactionBuilderFactory';
export { SingletonRegistry } from './singletonRegistry';
export { NativeTransferBuilder } from './nativeTransferBuilder';
export { RemoveProxyBuilder } from './proxyBuilder';
export { explainTransactionFromHex } from './wasmParser';
export type { DotWasmExplanation, DotInput } from './wasmParser';
export { Interface, Utils };
80 changes: 80 additions & 0 deletions modules/sdk-coin-dot/src/lib/wasmParser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { TransactionType } from '@bitgo/sdk-core';
import { parseTransaction, type Material, type ParseContext, type ParsedTransaction } from '@bitgo/wasm-dot';
import type { TransactionExplanation } from './iface';

/**
* Input entry for a DOT transaction.
* For account-model chains, there's typically one input (the sender).
*/
export interface DotInput {
address: string;
value: number;
valueString: string;
}

/**
* Extended explanation returned by WASM-based parsing.
* Includes fields needed by wallet-platform that aren't in the base TransactionExplanation.
*/
export interface DotWasmExplanation extends TransactionExplanation {
sender: string;
nonce: number;
isSigned: boolean;
methodName: string;
isTransferAll: boolean;
inputs: DotInput[];
}

/**
* Explain a DOT transaction from raw hex using the WASM parser.
*
* This is the single source of truth for parsing DOT transactions from bytes.
* Both wallet-platform (server) and sdk-coin-dot (client) should use this function.
*
* @param txHex - Hex-encoded extrinsic bytes
* @param material - Chain metadata needed for decoding
* @param senderAddress - Optional sender address fallback (for unsigned txs that don't embed sender)
* @returns Parsed and explained transaction
*/
export function explainTransactionFromHex(
txHex: string,
material: Material,
senderAddress?: string
): DotWasmExplanation {
const context: ParseContext = { material, sender: senderAddress };
const parsed: ParsedTransaction = parseTransaction(txHex, context);

const sender = parsed.sender || senderAddress || '';
const methodName = (parsed.method?.name ?? '').toLowerCase();
const isTransferAll = methodName === 'transferall';
const type = isTransferAll ? TransactionType.FlushCoins : TransactionType.Send;

const outputs = (parsed.outputs || []).map((o) => ({
address: o.address,
amount: o.amount === 'ALL' ? '0' : o.amount,
}));
const outputAmount = outputs.reduce((sum, o) => sum + parseInt(o.amount || '0', 10), 0);

// For account-model chains, the input is the sender with the total output amount.
// For transferAll, the actual amount depends on chain state (balance - fee - minBalance),
// so we set it to 0 here — wallet-platform overrides it for consolidation.
const inputValue = isTransferAll ? 0 : outputAmount;
const inputs: DotInput[] = sender ? [{ address: sender, value: inputValue, valueString: inputValue.toString() }] : [];

return {
displayOrder: ['outputAmount', 'changeAmount', 'outputs', 'changeOutputs', 'fee', 'type', 'sequenceId', 'id'],
id: parsed.id || '',
outputs,
outputAmount,
changeOutputs: [],
changeAmount: '0',
fee: { fee: parsed.tip?.toString() || '0', type: 'tip' },
type,
sender,
nonce: parsed.nonce ?? 0,
isSigned: parsed.isSigned ?? false,
methodName,
isTransferAll,
inputs,
};
}
Loading