Skip to content
Merged
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
11 changes: 8 additions & 3 deletions modules/sdk-coin-flrp/src/flrp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,11 @@ export class Flrp extends BaseCoin {
// so the TransactionType enum lookup succeeds.
const normalizedType = type === 'stake' ? 'AddPermissionlessDelegator' : type;

if (!normalizedType || (normalizedType !== 'ImportToC' && explainedTx.type !== TransactionType[normalizedType])) {
// When type is provided, verify it matches the parsed transaction.
// When type is not provided (MPC/TSS intent flow where buildParams are unavailable),
// skip the type match check and rely on explainedTx.type from the parsed hex —
// the transaction was built by wallet-platform and the hex is the source of truth.
if (normalizedType && normalizedType !== 'ImportToC' && explainedTx.type !== TransactionType[normalizedType]) {
throw new Error('Tx type does not match with expected txParams type');
}

Expand Down Expand Up @@ -126,8 +130,9 @@ export class Flrp extends BaseCoin {
}
break;
case TransactionType.AddPermissionlessDelegator:
// Validate delegation transaction against both txParams and explainedTx
this.validateDelegationTx(params.txParams, explainedTx);
if (params.txParams.stakingOptions) {
this.validateDelegationTx(params.txParams, explainedTx);
}
break;
default:
throw new Error('Tx type is not supported yet');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,12 @@ export const MULTISIG_ADDRESS_SORTING = {
{ role: 'bitgo', originalIndex: 1, sortedIndex: 1 },
],
};

/**
* MPC/TSS delegation transaction hex (single signer, built by wallet-platform via buildTransactionWithIntent).
* From txRequest b5f89e8b-2273-4e29-80bd-60bd488e172f on Coston2 testnet.
* This is the serializedTxHex that verifyTransaction receives during MPC signing,
* where txParams has no type and no stakingOptions (only { recipients: [] }).
*/
export const MPC_DELEGATION_UNSIGNED_TX_HEX =
'00000000001a0000007200000000000000000000000000000000000000000000000000000000000000000000000158734f94af871c3d131b56131b6fb7a0291eacadd261e69dfb42a9cdf6f7fddd000000070000000253e0efe80000000000000000000000010000000184fa441f981fce7cd63189d5071802376ad6676e000000022ebd7484b5704be67db0344abd9d2223d5c7100795f68c7a6a4a77888dccb9820000000158734f94af871c3d131b56131b6fb7a0291eacadd261e69dfb42a9cdf6f7fddd0000000500002d79883d20000000000100000000933f844e2d35c52963abd7912ec39faa71ed5994a52c584d9bf1f6bd480c976c0000000058734f94af871c3d131b56131b6fb7a0291eacadd261e69dfb42a9cdf6f7fddd0000000500000002540be400000000010000000000000000664b4924a25af8be5f07052b2c2e582f7c10a654000000006a1192a4000000006a2407a400002d79883d200000000000000000000000000000000000000000000000000000000000000000000000000158734f94af871c3d131b56131b6fb7a0291eacadd261e69dfb42a9cdf6f7fddd0000000700002d79883d20000000000000000000000000010000000184fa441f981fce7cd63189d5071802376ad6676e0000000b00000000000000000000000100000001243f65fbcc8458492e09d7693c3966a734c0a30f00000002000000090000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084fa441f981fce7cd63189d5071802376ad6676e000000090000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084fa441f981fce7cd63189d5071802376ad6676ee5e72aa5';
17 changes: 17 additions & 0 deletions modules/sdk-coin-flrp/test/unit/flrp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { IMPORT_IN_C } from '../resources/transactionData/importInC';
import {
MULTISIG_DELEGATION_FULLY_SIGNED_TX_HEX,
MULTISIG_DELEGATION_PARAMS,
MPC_DELEGATION_UNSIGNED_TX_HEX,
} from '../resources/transactionData/multisigDelegationTx';
import { HalfSignedAccountTransaction, TransactionType, MPCAlgorithm } from '@bitgo/sdk-core';
import { secp256k1 } from '@flarenetwork/flarejs';
Expand Down Expand Up @@ -978,6 +979,22 @@ describe('Flrp test cases', function () {
const isVerified = await basecoin.verifyTransaction({ txParams, txPrebuild });
isVerified.should.equal(true);
});

it('should verify delegation transaction when txParams.type is undefined (MPC intent flow)', async () => {
// In the MPC/TSS staking flow, the txRequest is created by staking-service (not the UI).
// The UI only has txRequestId — no buildParams. The SDK falls back to { recipients: [] }
// with no type and no stakingOptions. verifyTransaction must still pass because the
// parsed hex (explainedTx.type) is the source of truth built by wallet-platform.
const txPrebuild = { txHex: MPC_DELEGATION_UNSIGNED_TX_HEX, txInfo: {} };
const txParams = {
recipients: [],
// no type — simulates MPC staking flow where buildParams is unavailable
// no stakingOptions — not passed through in the MPC intent flow
};

const isVerified = await basecoin.verifyTransaction({ txParams, txPrebuild });
isVerified.should.equal(true);
});
});

describe('verifyTransaction with TSS wallet (Avalanche atomic)', () => {
Expand Down
Loading