Skip to content

Commit c15c32c

Browse files
committed
test(sdk-coin-near): prebuildTransactionTxRequests
TICKET: WP-5782
1 parent 9c41648 commit c15c32c

File tree

1 file changed

+250
-0
lines changed

1 file changed

+250
-0
lines changed

modules/sdk-coin-near/test/unit/tokenEnablementValidation.ts

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ describe('NEAR Token Enablement Validation', function () {
1111
let bitgo: TestBitGoAPI;
1212
let basecoin: Near;
1313
let wallet: Wallet;
14+
let tssWallet: Wallet;
1415

1516
before(function () {
1617
bitgo = TestBitGo.decorate(BitGoAPI, { env: 'test' });
@@ -28,6 +29,18 @@ describe('NEAR Token Enablement Validation', function () {
2829
},
2930
};
3031
wallet = new Wallet(bitgo, basecoin, walletData);
32+
33+
const tssWalletData = {
34+
id: '5b34252f1bf34993006eae97',
35+
coin: 'tnear',
36+
type: 'hot',
37+
multisigType: 'tss',
38+
keys: ['5b3424f91bf34993006eae94', '5b3424f91bf34993006eae95', '5b3424f91bf34993006eae96'],
39+
coinSpecific: {
40+
baseAddress: testData.accounts.account1.address,
41+
},
42+
};
43+
tssWallet = new Wallet(bitgo, basecoin, tssWalletData);
3144
});
3245

3346
const createValidTxParams = () => ({
@@ -421,4 +434,241 @@ describe('NEAR Token Enablement Validation', function () {
421434
result.failure.should.have.length(1);
422435
result.failure[0].message.should.containEql('transaction beneficiary mismatch with user expectation');
423436
});
437+
438+
describe('TSS Wallet Tests (prebuildTransactionTxRequests flow)', function () {
439+
it('should properly validate token enablement through TSS wallet flow', async function () {
440+
const bgUrl = common.Environments['test'].uri;
441+
442+
// Mock the /txrequests endpoint (used by TSS wallets)
443+
const txRequestNock = nock(bgUrl)
444+
.post(`/api/v2/wallet/${tssWallet.id()}/txrequests`)
445+
.reply((uri, requestBody: any) => {
446+
// Validate the request structure
447+
requestBody.intent.should.have.property('intentType');
448+
requestBody.intent.intentType.should.equal('enableToken');
449+
requestBody.intent.should.have.property('enableTokens');
450+
requestBody.intent.enableTokens.should.deepEqual([{ name: 'tnear:tnep24dp' }]);
451+
452+
return [
453+
200,
454+
{
455+
txRequestId: 'test-request-id',
456+
apiVersion: 'full',
457+
transactions: [
458+
{
459+
state: 'pending',
460+
unsignedTx: {
461+
serializedTxHex: testData.rawTx.selfStorageDeposit.unsigned,
462+
signableHex: testData.rawTx.selfStorageDeposit.unsigned,
463+
derivationPath: 'm/0',
464+
feeInfo: {
465+
fee: 1160407,
466+
feeString: '1160407',
467+
},
468+
},
469+
signatureShares: [],
470+
},
471+
],
472+
},
473+
];
474+
});
475+
476+
const result = await tssWallet.buildTokenEnablements({
477+
enableTokens: [
478+
{
479+
name: 'tnear:tnep24dp',
480+
},
481+
],
482+
});
483+
484+
txRequestNock.isDone().should.equal(true);
485+
result.should.have.length(1);
486+
result[0].should.have.property('txRequestId');
487+
result[0].txRequestId!.should.equal('test-request-id');
488+
});
489+
490+
it('should reject spoofed transaction in TSS wallet flow', async function () {
491+
const bgUrl = common.Environments['test'].uri;
492+
493+
// Platform returns a fungible token transfer instead of storage deposit
494+
const txRequestNock = nock(bgUrl)
495+
.post(`/api/v2/wallet/${tssWallet.id()}/txrequests`)
496+
.reply(200, {
497+
txRequestId: 'test-request-id',
498+
apiVersion: 'full',
499+
transactions: [
500+
{
501+
state: 'pending',
502+
unsignedTx: {
503+
serializedTxHex: testData.rawTx.fungibleTokenTransfer.unsigned,
504+
signableHex: testData.rawTx.fungibleTokenTransfer.unsigned,
505+
derivationPath: 'm/0',
506+
feeInfo: {
507+
fee: 1160407,
508+
feeString: '1160407',
509+
},
510+
},
511+
signatureShares: [],
512+
},
513+
],
514+
});
515+
516+
const buildResult = await tssWallet.buildTokenEnablements({
517+
enableTokens: [
518+
{
519+
name: 'tnear:tnep24dp',
520+
},
521+
],
522+
});
523+
524+
txRequestNock.isDone().should.equal(true);
525+
526+
// Now verify the transaction - it should fail validation
527+
const txPrebuild = buildResult[0] as any;
528+
const txParams = {
529+
type: 'enabletoken' as const,
530+
recipients: [
531+
{
532+
address: testData.accounts.account1.address,
533+
amount: '0',
534+
tokenName: 'tnear:tnep24dp',
535+
},
536+
],
537+
};
538+
539+
// For TSS, txHex is at the top level of prebuild result
540+
const verifyOptions: VerifyTransactionOptions = {
541+
txParams,
542+
txPrebuild: txPrebuild,
543+
wallet: tssWallet as any,
544+
verification: { verifyTokenEnablement: true },
545+
walletType: 'tss',
546+
};
547+
548+
await basecoin
549+
.verifyTransaction(verifyOptions)
550+
.should.be.rejectedWith(/Invalid transaction type on token enablement/);
551+
});
552+
553+
it('should detect wrong receiver contract in TSS wallet flow', async function () {
554+
const bgUrl = common.Environments['test'].uri;
555+
556+
// Platform returns a regular transfer (wrong receiver)
557+
const txRequestNock = nock(bgUrl)
558+
.post(`/api/v2/wallet/${tssWallet.id()}/txrequests`)
559+
.reply(200, {
560+
txRequestId: 'test-request-id',
561+
apiVersion: 'full',
562+
transactions: [
563+
{
564+
state: 'pending',
565+
unsignedTx: {
566+
serializedTxHex: testData.rawTx.transfer.unsigned,
567+
signableHex: testData.rawTx.transfer.unsigned,
568+
derivationPath: 'm/0',
569+
feeInfo: {
570+
fee: 1160407,
571+
feeString: '1160407',
572+
},
573+
},
574+
signatureShares: [],
575+
},
576+
],
577+
});
578+
579+
const buildResult = await tssWallet.buildTokenEnablements({
580+
enableTokens: [
581+
{
582+
name: 'tnear:tnep24dp',
583+
},
584+
],
585+
});
586+
587+
txRequestNock.isDone().should.equal(true);
588+
589+
// Verify should detect the wrong transaction
590+
const txPrebuild = buildResult[0] as any;
591+
const verifyOptions: VerifyTransactionOptions = {
592+
txParams: {
593+
type: 'enabletoken' as const,
594+
recipients: [
595+
{
596+
address: testData.accounts.account1.address,
597+
amount: '0',
598+
tokenName: 'tnear:tnep24dp',
599+
},
600+
],
601+
},
602+
txPrebuild: txPrebuild,
603+
wallet: tssWallet as any,
604+
verification: { verifyTokenEnablement: true },
605+
walletType: 'tss',
606+
};
607+
608+
await basecoin
609+
.verifyTransaction(verifyOptions)
610+
.should.be.rejectedWith(
611+
/Invalid transaction type on token enablement|Error on token enablements: receiver contract mismatch/
612+
);
613+
});
614+
615+
it('should validate correct storage deposit in TSS wallet flow', async function () {
616+
const bgUrl = common.Environments['test'].uri;
617+
618+
// Platform returns correct storage deposit transaction
619+
const txRequestNock = nock(bgUrl)
620+
.post(`/api/v2/wallet/${tssWallet.id()}/txrequests`)
621+
.reply(200, {
622+
txRequestId: 'test-request-id',
623+
apiVersion: 'full',
624+
transactions: [
625+
{
626+
state: 'pending',
627+
unsignedTx: {
628+
serializedTxHex: testData.rawTx.selfStorageDeposit.unsigned,
629+
signableHex: testData.rawTx.selfStorageDeposit.unsigned,
630+
derivationPath: 'm/0',
631+
feeInfo: {
632+
fee: 1160407,
633+
feeString: '1160407',
634+
},
635+
},
636+
signatureShares: [],
637+
},
638+
],
639+
});
640+
641+
const buildResult = await tssWallet.buildTokenEnablements({
642+
enableTokens: [
643+
{
644+
name: 'tnear:tnep24dp',
645+
},
646+
],
647+
});
648+
649+
txRequestNock.isDone().should.equal(true);
650+
651+
// Verify should pass for valid transaction
652+
const txPrebuild = buildResult[0] as any;
653+
const verifyOptions: VerifyTransactionOptions = {
654+
txParams: {
655+
type: 'enabletoken' as const,
656+
recipients: [
657+
{
658+
address: testData.accounts.account1.address,
659+
amount: '0',
660+
tokenName: 'tnear:tnep24dp',
661+
},
662+
],
663+
},
664+
txPrebuild: txPrebuild,
665+
wallet: tssWallet as any,
666+
verification: { verifyTokenEnablement: true },
667+
walletType: 'tss',
668+
};
669+
670+
const result = await basecoin.verifyTransaction(verifyOptions);
671+
result.should.equal(true);
672+
});
673+
});
424674
});

0 commit comments

Comments
 (0)