Skip to content

Commit 1e1253d

Browse files
feat(sdk-api): add isTestTransaction support
for withdrawals Add isTestTransaction parameter support for wallet transactions: - Add isTestTransaction to PrebuildTransactionOptions interface (available for both TSS and multisig wallets) - Pass isTestTransaction through prebuildTransactionTxRequests for TSS transfer transactions - Include isTestTransaction in PopulatedIntent and baseIntent objects for TSS wallet flow - SendManyOptions inherits isTestTransaction via PrebuildAndSignTransactionOptions Add comprehensive test coverage: - Test isTestTransaction is passed through prebuildTransaction for TSS wallets - Test isTestTransaction flows through sendMany to prebuildAndSignTransaction - Add proper TypeScript assertions with existence checks This ensures the isTestTransaction flag is correctly sent to the /api/v2/wallet/:walletId/txrequests endpoint for TSS wallets (e.g., NEAR) and is available for multisig wallets when building transfer transactions via prebuildTransaction() or sendMany(). TICKET: CS-6399
1 parent 4e3cdad commit 1e1253d

File tree

6 files changed

+101
-0
lines changed

6 files changed

+101
-0
lines changed

modules/bitgo/test/v2/unit/wallet.ts

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1786,6 +1786,28 @@ describe('V2 Wallet:', function () {
17861786
txPrebuild.recipients[0].amount.should.equal('1000000000000000');
17871787
});
17881788

1789+
it('should pass isTestTransaction parameter through for multisig wallets', async function () {
1790+
const recipients = [
1791+
{
1792+
address: 'aaa',
1793+
amount: '1000',
1794+
},
1795+
];
1796+
const isTestTransaction = true;
1797+
const path = `/api/v2/${wallet.coin()}/wallet/${wallet.id()}/tx/build`;
1798+
const response = nock(bgUrl)
1799+
.post(path, _.matches({ recipients, isTestTransaction })) // use _.matches to do a partial match on request body object instead of strict matching
1800+
.reply(200);
1801+
try {
1802+
await wallet.prebuildTransaction({ recipients, isTestTransaction });
1803+
} catch (e) {
1804+
// the prebuildTransaction method will probably throw an exception for not having all of the correct nocks
1805+
// we only care about /tx/build and whether isTestTransaction is an allowed parameter
1806+
}
1807+
1808+
response.isDone().should.be.true();
1809+
});
1810+
17891811
it('should pass unspent reservation parameter through when building transactions', async function () {
17901812
const reservation = {
17911813
expireTime: '2029-08-12',
@@ -2362,6 +2384,50 @@ describe('V2 Wallet:', function () {
23622384
});
23632385
});
23642386

2387+
it('should build a transfer transaction with isTestTransaction flag', async function () {
2388+
const recipients = [
2389+
{
2390+
address: '6DadkZcx9JZgeQUDbHh12cmqCpaqehmVxv6sGy49jrah',
2391+
amount: '1000',
2392+
},
2393+
];
2394+
2395+
const prebuildTxWithIntent = sandbox.stub(TssUtils.prototype, 'prebuildTxWithIntent');
2396+
prebuildTxWithIntent.resolves(txRequest);
2397+
2398+
const txPrebuild = await tssSolWallet.prebuildTransaction({
2399+
reqId,
2400+
recipients,
2401+
type: 'transfer',
2402+
isTestTransaction: true,
2403+
});
2404+
2405+
// Verify isTestTransaction is passed to prebuildTxWithIntent
2406+
sinon.assert.calledOnce(prebuildTxWithIntent);
2407+
const callArgs = prebuildTxWithIntent.getCall(0).args[0];
2408+
callArgs.should.have.property('isTestTransaction', true);
2409+
callArgs.should.have.property('intentType', 'payment');
2410+
callArgs.should.have.property('recipients');
2411+
should.exist(callArgs.recipients);
2412+
callArgs.recipients!.should.deepEqual(recipients);
2413+
2414+
txPrebuild.should.deepEqual({
2415+
walletId: tssSolWallet.id(),
2416+
wallet: tssSolWallet,
2417+
txRequestId: 'id',
2418+
txHex: 'ababcdcd',
2419+
buildParams: {
2420+
recipients,
2421+
type: 'transfer',
2422+
isTestTransaction: true,
2423+
},
2424+
feeInfo: {
2425+
fee: 5000,
2426+
feeString: '5000',
2427+
},
2428+
});
2429+
});
2430+
23652431
it('should build an enable token transaction', async function () {
23662432
const recipients = [];
23672433
const tokenName = 'tcoin:tokenName';
@@ -3909,6 +3975,35 @@ describe('V2 Wallet:', function () {
39093975
setRequestTracerSpy.restore();
39103976
});
39113977

3978+
it('should pass isTestTransaction through sendMany to prebuildAndSignTransaction', async function () {
3979+
const signedTransaction = {
3980+
txRequestId: 'txRequestId',
3981+
};
3982+
3983+
const sendManyInputWithTestFlag = {
3984+
...sendManyInput,
3985+
type: 'transfer',
3986+
isTestTransaction: true,
3987+
};
3988+
3989+
const prebuildAndSignTransaction = sandbox.stub(tssSolWallet, 'prebuildAndSignTransaction');
3990+
prebuildAndSignTransaction.resolves(signedTransaction);
3991+
3992+
const sendTxRequest = sandbox.stub(TssUtils.prototype, 'sendTxRequest');
3993+
sendTxRequest.resolves('sendTxResponse');
3994+
3995+
const sendMany = await tssSolWallet.sendMany(sendManyInputWithTestFlag);
3996+
3997+
// Verify prebuildAndSignTransaction was called with isTestTransaction
3998+
sinon.assert.calledOnce(prebuildAndSignTransaction);
3999+
const callArgs = prebuildAndSignTransaction.getCall(0).args[0];
4000+
should.exist(callArgs);
4001+
callArgs!.should.have.property('isTestTransaction', true);
4002+
callArgs!.should.have.property('type', 'transfer');
4003+
4004+
sendMany.should.deepEqual('sendTxResponse');
4005+
});
4006+
39124007
it('should return transfer from sendMany for apiVersion=full', async function () {
39134008
const wallet = new Wallet(bitgo, tsol, {
39144009
...walletData,

modules/sdk-core/src/bitgo/utils/mpcUtils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ export abstract class MpcUtils {
188188
nonce: params.nonce,
189189
recipients: intentRecipients,
190190
tokenName: params.tokenName,
191+
isTestTransaction: params.isTestTransaction,
191192
};
192193

193194
if (baseCoin.getFamily() === 'eth' || baseCoin.getFamily() === 'polygon' || baseCoin.getFamily() === 'bsc') {

modules/sdk-core/src/bitgo/utils/tss/baseTypes.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ export interface PrebuildTransactionWithIntentOptions extends IntentOptionsBase
269269
abi?: any;
270270
};
271271
txRequestId?: string;
272+
isTestTransaction?: boolean;
272273
}
273274
export interface IntentRecipient {
274275
address: {
@@ -338,6 +339,7 @@ export interface PopulatedIntent extends PopulatedIntentBase {
338339
*/
339340
aptosCustomTransactionParams?: aptosCustomTransactionParams;
340341
txRequestId?: string;
342+
isTestTransaction?: boolean;
341343
}
342344

343345
export type TxRequestState =

modules/sdk-core/src/bitgo/wallet/BuildParams.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ export const BuildParams = t.exact(
116116
solVersionedTransactionData: t.unknown,
117117
// Aptos custom transaction parameters for smart contract calls
118118
aptosCustomTransactionParams: t.unknown,
119+
isTestTransaction: t.unknown,
119120
}),
120121
])
121122
);

modules/sdk-core/src/bitgo/wallet/iWallet.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ export interface PrebuildTransactionOptions {
217217
abi?: any;
218218
};
219219
txRequestId?: string;
220+
isTestTransaction?: boolean;
220221
}
221222

222223
export interface PrebuildAndSignTransactionOptions extends PrebuildTransactionOptions, WalletSignTransactionOptions {

modules/sdk-core/src/bitgo/wallet/wallet.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3434,6 +3434,7 @@ export class Wallet implements IWallet {
34343434
custodianTransactionId: params.custodianTransactionId,
34353435
unspents: params.unspents,
34363436
senderAddress: params.senderAddress,
3437+
isTestTransaction: params.isTestTransaction,
34373438
},
34383439
apiVersion,
34393440
params.preview

0 commit comments

Comments
 (0)