11import 'should' ;
22import { TestBitGo , TestBitGoAPI } from '@bitgo/sdk-test' ;
33import { BitGoAPI } from '@bitgo/sdk-api' ;
4+ import { IWallet } from '@bitgo/sdk-core' ;
45
5- import { register } from '../../src' ;
6+ import { register , XdcToken } from '../../src' ;
7+ import { mockTokenTransferData } from '../resources' ;
68
79describe ( 'XDC Token:' , function ( ) {
810 let bitgo : TestBitGoAPI ;
@@ -27,4 +29,244 @@ describe('XDC Token:', function () {
2729 xdcTokenCoin . network . should . equal ( 'Mainnet' ) ;
2830 xdcTokenCoin . decimalPlaces . should . equal ( 6 ) ;
2931 } ) ;
32+
33+ describe ( 'Token Registration and TransactionBuilder' , function ( ) {
34+ const mainnetTokens = [ 'xdc:usdc' , 'xdc:lbt' , 'xdc:gama' , 'xdc:srx' , 'xdc:weth' ] ;
35+ const testnetTokens = [ 'txdc:tmt' ] ;
36+
37+ describe ( 'Mainnet tokens' , function ( ) {
38+ mainnetTokens . forEach ( ( tokenName ) => {
39+ it ( `${ tokenName } should be registered as XdcToken` , function ( ) {
40+ const token = bitgo . coin ( tokenName ) ;
41+ token . should . be . instanceOf ( XdcToken ) ;
42+ } ) ;
43+
44+ it ( `${ tokenName } should create TransactionBuilder without error` , function ( ) {
45+ const token = bitgo . coin ( tokenName ) as XdcToken ;
46+ // @ts -expect-error - accessing protected method for testing
47+ ( ( ) => token . getTransactionBuilder ( ) ) . should . not . throw ( ) ;
48+ } ) ;
49+
50+ it ( `${ tokenName } should use XDC-specific TransactionBuilder` , function ( ) {
51+ const token = bitgo . coin ( tokenName ) as XdcToken ;
52+ // @ts -expect-error - accessing protected method for testing
53+ const builder = token . getTransactionBuilder ( ) ;
54+ builder . should . have . property ( '_common' ) ;
55+ // Verify it's using XDC's getCommon, not EVM's
56+ // XDC's TransactionBuilder should create successfully without SHARED_EVM_SDK feature
57+ builder . constructor . name . should . equal ( 'TransactionBuilder' ) ;
58+ } ) ;
59+ } ) ;
60+ } ) ;
61+
62+ describe ( 'Testnet tokens' , function ( ) {
63+ testnetTokens . forEach ( ( tokenName ) => {
64+ it ( `${ tokenName } should be registered as XdcToken` , function ( ) {
65+ const token = bitgo . coin ( tokenName ) ;
66+ token . should . be . instanceOf ( XdcToken ) ;
67+ } ) ;
68+
69+ it ( `${ tokenName } should create TransactionBuilder without error` , function ( ) {
70+ const token = bitgo . coin ( tokenName ) as XdcToken ;
71+ // @ts -expect-error - accessing protected method for testing
72+ ( ( ) => token . getTransactionBuilder ( ) ) . should . not . throw ( ) ;
73+ } ) ;
74+
75+ it ( `${ tokenName } should use XDC-specific TransactionBuilder` , function ( ) {
76+ const token = bitgo . coin ( tokenName ) as XdcToken ;
77+ // @ts -expect-error - accessing protected method for testing
78+ const builder = token . getTransactionBuilder ( ) ;
79+ builder . should . have . property ( '_common' ) ;
80+ builder . constructor . name . should . equal ( 'TransactionBuilder' ) ;
81+ } ) ;
82+
83+ it ( `${ tokenName } should have correct base chain` , function ( ) {
84+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
85+ const token : any = bitgo . coin ( tokenName ) ;
86+ token . getBaseChain ( ) . should . equal ( 'txdc' ) ;
87+ } ) ;
88+
89+ it ( `${ tokenName } should not throw "Cannot use common sdk module" error` , function ( ) {
90+ const token = bitgo . coin ( tokenName ) as XdcToken ;
91+ let errorThrown = false ;
92+ let errorMessage = '' ;
93+
94+ try {
95+ // @ts -expect-error - accessing protected method for testing
96+ const builder = token . getTransactionBuilder ( ) ;
97+ // Try to use the builder to ensure it's fully functional
98+ // @ts -expect-error - type expects TransactionType enum
99+ builder . type ( 'Send' ) ;
100+ } catch ( e ) {
101+ errorThrown = true ;
102+ errorMessage = ( e as Error ) . message ;
103+ }
104+
105+ errorThrown . should . equal ( false ) ;
106+ errorMessage . should . not . match ( / C a n n o t u s e c o m m o n s d k m o d u l e / ) ;
107+ } ) ;
108+ } ) ;
109+ } ) ;
110+
111+ it ( 'should verify all XDC tokens use XdcToken class, not EthLikeErc20Token' , function ( ) {
112+ const allTokens = [ ...mainnetTokens , ...testnetTokens ] ;
113+
114+ allTokens . forEach ( ( tokenName ) => {
115+ const token = bitgo . coin ( tokenName ) ;
116+ token . should . be . instanceOf ( XdcToken ) ;
117+ token . constructor . name . should . equal ( 'XdcToken' ) ;
118+ token . constructor . name . should . not . equal ( 'EthLikeErc20Token' ) ;
119+ } ) ;
120+ } ) ;
121+ } ) ;
122+
123+ describe ( 'verifyTssTransaction' , function ( ) {
124+ it ( 'should return true for valid token transfer params' , async function ( ) {
125+ const token = bitgo . coin ( 'txdc:tmt' ) as XdcToken ;
126+ const mockWallet = { } as unknown as IWallet ;
127+
128+ const result = await token . verifyTssTransaction ( {
129+ txParams : {
130+ recipients : [
131+ {
132+ address : mockTokenTransferData . recipientAddress ,
133+ amount : mockTokenTransferData . tokenAmount ,
134+ } ,
135+ ] ,
136+ } ,
137+ txPrebuild : mockTokenTransferData . txPrebuild as unknown as Parameters <
138+ typeof token . verifyTssTransaction
139+ > [ 0 ] [ 'txPrebuild' ] ,
140+ wallet : mockWallet ,
141+ } ) ;
142+
143+ result . should . equal ( true ) ;
144+ } ) ;
145+
146+ it ( 'should return true for transferToken type without recipients' , async function ( ) {
147+ const token = bitgo . coin ( 'txdc:tmt' ) as XdcToken ;
148+ const mockWallet = { } as unknown as IWallet ;
149+
150+ const result = await token . verifyTssTransaction ( {
151+ txParams : {
152+ type : 'transferToken' ,
153+ } ,
154+ txPrebuild : mockTokenTransferData . txPrebuild as unknown as Parameters <
155+ typeof token . verifyTssTransaction
156+ > [ 0 ] [ 'txPrebuild' ] ,
157+ wallet : mockWallet ,
158+ } ) ;
159+
160+ result . should . equal ( true ) ;
161+ } ) ;
162+
163+ it ( 'should throw error when txParams.recipients is missing and no valid type' , async function ( ) {
164+ const token = bitgo . coin ( 'txdc:tmt' ) as XdcToken ;
165+ const mockWallet = { } as unknown as IWallet ;
166+
167+ await token
168+ . verifyTssTransaction ( {
169+ txParams : { } ,
170+ txPrebuild : mockTokenTransferData . txPrebuild as unknown as Parameters <
171+ typeof token . verifyTssTransaction
172+ > [ 0 ] [ 'txPrebuild' ] ,
173+ wallet : mockWallet ,
174+ } )
175+ . should . be . rejectedWith ( 'missing txParams' ) ;
176+ } ) ;
177+
178+ it ( 'should throw error when wallet is missing' , async function ( ) {
179+ const token = bitgo . coin ( 'txdc:tmt' ) as XdcToken ;
180+
181+ await token
182+ . verifyTssTransaction ( {
183+ txParams : {
184+ recipients : [
185+ {
186+ address : mockTokenTransferData . recipientAddress ,
187+ amount : mockTokenTransferData . tokenAmount ,
188+ } ,
189+ ] ,
190+ } ,
191+ txPrebuild : mockTokenTransferData . txPrebuild as unknown as Parameters <
192+ typeof token . verifyTssTransaction
193+ > [ 0 ] [ 'txPrebuild' ] ,
194+ wallet : undefined as unknown as IWallet ,
195+ } )
196+ . should . be . rejectedWith ( 'missing params' ) ;
197+ } ) ;
198+
199+ it ( 'should throw error when txPrebuild is missing' , async function ( ) {
200+ const token = bitgo . coin ( 'txdc:tmt' ) as XdcToken ;
201+ const mockWallet = { } as unknown as IWallet ;
202+
203+ await token
204+ . verifyTssTransaction ( {
205+ txParams : {
206+ recipients : [
207+ {
208+ address : mockTokenTransferData . recipientAddress ,
209+ amount : mockTokenTransferData . tokenAmount ,
210+ } ,
211+ ] ,
212+ } ,
213+ txPrebuild : undefined as unknown as Parameters < typeof token . verifyTssTransaction > [ 0 ] [ 'txPrebuild' ] ,
214+ wallet : mockWallet ,
215+ } )
216+ . should . be . rejectedWith ( 'missing params' ) ;
217+ } ) ;
218+
219+ it ( 'should throw error for batch + hop transaction' , async function ( ) {
220+ const token = bitgo . coin ( 'txdc:tmt' ) as XdcToken ;
221+ const mockWallet = { } as unknown as IWallet ;
222+
223+ await token
224+ . verifyTssTransaction ( {
225+ txParams : {
226+ hop : true ,
227+ recipients : [
228+ { address : '0x1111111111111111111111111111111111111111' , amount : '1000' } ,
229+ { address : '0x2222222222222222222222222222222222222222' , amount : '2000' } ,
230+ ] ,
231+ } ,
232+ txPrebuild : mockTokenTransferData . txPrebuild as unknown as Parameters <
233+ typeof token . verifyTssTransaction
234+ > [ 0 ] [ 'txPrebuild' ] ,
235+ wallet : mockWallet ,
236+ } )
237+ . should . be . rejectedWith ( 'tx cannot be both a batch and hop transaction' ) ;
238+ } ) ;
239+
240+ it ( 'should not throw EIP155 error when verifying token transaction' , async function ( ) {
241+ // This test ensures that verifyTssTransaction does NOT parse the txHex
242+ // which would fail with "Incompatible EIP155-based V" error
243+ const token = bitgo . coin ( 'txdc:tmt' ) as XdcToken ;
244+ const mockWallet = { } as unknown as IWallet ;
245+
246+ // Use the signableHex (with v=51) which would fail if parsed
247+ const txPrebuildWithSignableHex = {
248+ ...mockTokenTransferData . txPrebuild ,
249+ txHex : mockTokenTransferData . signableHex ,
250+ } ;
251+
252+ // This should NOT throw EIP155 error because verifyTssTransaction
253+ // does not parse the transaction
254+ const result = await token . verifyTssTransaction ( {
255+ txParams : {
256+ recipients : [
257+ {
258+ address : mockTokenTransferData . recipientAddress ,
259+ amount : mockTokenTransferData . tokenAmount ,
260+ } ,
261+ ] ,
262+ } ,
263+ txPrebuild : txPrebuildWithSignableHex as unknown as Parameters <
264+ typeof token . verifyTssTransaction
265+ > [ 0 ] [ 'txPrebuild' ] ,
266+ wallet : mockWallet ,
267+ } ) ;
268+
269+ result . should . equal ( true ) ;
270+ } ) ;
271+ } ) ;
30272} ) ;
0 commit comments