@@ -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 ( / I n v a l i d t r a n s a c t i o n t y p e o n t o k e n e n a b l e m e n t / ) ;
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+ / I n v a l i d t r a n s a c t i o n t y p e o n t o k e n e n a b l e m e n t | E r r o r o n t o k e n e n a b l e m e n t s : r e c e i v e r c o n t r a c t m i s m a t c h /
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