@notabene/javascript-sdk 2.14.1 → 2.14.2-next.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,638 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { OriginatorV2 } from '../../ivms/v2Types';
3
+ import type { Deposit, TransactionResponse, Withdrawal } from '../../types';
4
+ import { PersonType } from '../../types';
5
+ import { componentResponseToTxRequests, enrichConfig } from '../transformer';
6
+
7
+ // Common test constants
8
+ const TEST_DELEGATE_TOKEN = 'test-delegate-token';
9
+ const TEST_ORIGINATOR_ID = 'did:test:originator-id';
10
+ const TEST_BENEFICIARY_ID = 'did:test:beneficiary-id';
11
+
12
+ const TEST_ADDRESS = '0xd7914021b50a5090d3a13bb4ecae2abf014fafbd';
13
+ const TEST_ADDRESS_DID = `did:pkh:eip155:1:${TEST_ADDRESS}`;
14
+ const TEST_ASSET = 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48';
15
+
16
+ const ORIGINATOR_VASP_DID =
17
+ 'did:ethr:0x7c546f3df830a3e0a63de13d4ae32d64f26e74b2';
18
+ const BENEFICIARY_VASP_DID =
19
+ 'did:ethr:0x54b75d2a0925508682e65194cccb6f1e8eaafb2c';
20
+
21
+ const DEPOSIT_TX_ID = 'b638210e-b99d-4bd3-afaa-6c9b5362f944';
22
+
23
+ // Common proof object for self-declaration
24
+ const selfDeclarationProof = {
25
+ type: 'self-declaration',
26
+ did: TEST_ADDRESS_DID,
27
+ address: `eip155:1:${TEST_ADDRESS}`,
28
+ attestation: `I hereby declare that the beneficiary blockchain address ${TEST_ADDRESS} belongs to the beneficiary.`,
29
+ confirmed: true,
30
+ status: 'verified',
31
+ };
32
+
33
+ // Common geographic address
34
+ const geographicAddress = {
35
+ addressType: 'GEOG',
36
+ townName: 'Test Town',
37
+ addressLine: ['123 Test Street'],
38
+ country: 'AF',
39
+ };
40
+
41
+ // Common national identification
42
+ const nationalIdentification = {
43
+ nationalIdentifier: 'adfsdff',
44
+ nationalIdentifierType: 'IDCD',
45
+ countryOfIssue: 'AQ',
46
+ };
47
+
48
+ // Common account object
49
+ const testAccount = {
50
+ caip10: `eip155:1:${TEST_ADDRESS}`,
51
+ blockchainAddress: TEST_ADDRESS,
52
+ chain: 'eip155:1',
53
+ did: TEST_ADDRESS_DID,
54
+ valid: true,
55
+ };
56
+
57
+ // Common wallet agent
58
+ const walletAgent = {
59
+ type: 'WALLET',
60
+ verified: true,
61
+ did: TEST_ADDRESS_DID,
62
+ };
63
+
64
+ // NOTE: These responses are examples from GoodbyeFiat.
65
+ // We need to cast the type as it is missing requestID which is required by the TransactionResponse type.
66
+ const depositResponse = {
67
+ proof: selfDeclarationProof,
68
+ txUpdate: {
69
+ originatorProof: selfDeclarationProof,
70
+ transactionAsset: { caip19: TEST_ASSET },
71
+ transactionAmount: '10000000000',
72
+ originatorEqualsBeneficiary: false,
73
+ beneficiaryVASPdid: BENEFICIARY_VASP_DID,
74
+ beneficiary: {},
75
+ originator: {
76
+ originatorPersons: [
77
+ {
78
+ naturalPerson: {
79
+ name: {
80
+ nameIdentifier: [
81
+ {
82
+ primaryIdentifier: 'Doe',
83
+ secondaryIdentifier: 'Jane',
84
+ nameIdentifierType: 'LEGL',
85
+ },
86
+ ],
87
+ },
88
+ geographicAddress: [geographicAddress],
89
+ },
90
+ },
91
+ ],
92
+ },
93
+ transactionId: DEPOSIT_TX_ID,
94
+ },
95
+ errors: [],
96
+ status: 'pending',
97
+ valid: true,
98
+ value: {
99
+ source: TEST_ADDRESS,
100
+ amountDecimal: 10000,
101
+ asset: TEST_ASSET,
102
+ transactionId: DEPOSIT_TX_ID,
103
+ customer: { type: 'natural', name: 'Jane Doe' },
104
+ agent: walletAgent,
105
+ account: testAccount,
106
+ counterparty: {
107
+ type: 'natural',
108
+ name: 'Jane Doe',
109
+ verified: false,
110
+ geographicAddress,
111
+ },
112
+ },
113
+ ivms101: {
114
+ originator: {
115
+ originatorPersons: [
116
+ {
117
+ naturalPerson: {
118
+ name: {
119
+ nameIdentifier: [
120
+ {
121
+ primaryIdentifier: 'Doe',
122
+ secondaryIdentifier: 'Jane',
123
+ nameIdentifierType: 'LEGL',
124
+ },
125
+ ],
126
+ },
127
+ geographicAddress: [geographicAddress],
128
+ },
129
+ },
130
+ ],
131
+ },
132
+ },
133
+ } as unknown as TransactionResponse<Deposit>;
134
+
135
+ const withdrawalResponse = {
136
+ proof: selfDeclarationProof,
137
+ txCreate: {
138
+ beneficiaryProof: selfDeclarationProof,
139
+ transactionAsset: { caip19: TEST_ASSET },
140
+ transactionAmount: '100000000000',
141
+ originatorEqualsBeneficiary: false,
142
+ originatorVASPdid: ORIGINATOR_VASP_DID,
143
+ beneficiary: {
144
+ beneficiaryPersons: [
145
+ {
146
+ naturalPerson: {
147
+ name: {
148
+ nameIdentifier: [
149
+ {
150
+ primaryIdentifier: 'Doe',
151
+ secondaryIdentifier: 'Jane',
152
+ nameIdentifierType: 'LEGL',
153
+ },
154
+ ],
155
+ },
156
+ geographicAddress: [geographicAddress],
157
+ nationalIdentification,
158
+ countryOfResidence: 'AF',
159
+ dateAndPlaceOfBirth: {
160
+ dateOfBirth: '2025-12-02',
161
+ placeOfBirth: 'Somewhere',
162
+ },
163
+ },
164
+ },
165
+ ],
166
+ },
167
+ },
168
+ errors: [],
169
+ status: 'pending',
170
+ valid: true,
171
+ value: {
172
+ destination: TEST_ADDRESS,
173
+ asset: TEST_ASSET,
174
+ customer: { type: 'natural', name: 'John', email: 'test@gmail.com' },
175
+ amountDecimal: 100000,
176
+ counterparty: {
177
+ type: 'natural',
178
+ name: 'Jane Doe',
179
+ verified: false,
180
+ website: 'http://www.janedoe.com',
181
+ email: 'jane@doe.com',
182
+ phone: '23423432',
183
+ dateOfBirth: '2025-12-02',
184
+ placeOfBirth: 'Somewhere',
185
+ countryOfResidence: 'AF',
186
+ geographicAddress,
187
+ nationalIdentification,
188
+ },
189
+ account: testAccount,
190
+ agent: walletAgent,
191
+ },
192
+ ivms101: {
193
+ beneficiary: {
194
+ beneficiaryPersons: [
195
+ {
196
+ naturalPerson: {
197
+ name: {
198
+ nameIdentifier: [
199
+ {
200
+ primaryIdentifier: 'Doe',
201
+ secondaryIdentifier: 'Jane',
202
+ nameIdentifierType: 'LEGL',
203
+ },
204
+ ],
205
+ },
206
+ geographicAddress: [geographicAddress],
207
+ nationalIdentification,
208
+ countryOfResidence: 'AF',
209
+ dateAndPlaceOfBirth: {
210
+ dateOfBirth: '2025-12-02',
211
+ placeOfBirth: 'Somewhere',
212
+ },
213
+ },
214
+ },
215
+ ],
216
+ },
217
+ },
218
+ } as unknown as TransactionResponse<Withdrawal>;
219
+
220
+ const withdrawalSelfVaspResponse = {
221
+ txCreate: {
222
+ transactionAsset: { caip19: TEST_ASSET },
223
+ transactionAmount: '10000000000',
224
+ originatorEqualsBeneficiary: true,
225
+ originatorVASPdid: ORIGINATOR_VASP_DID,
226
+ beneficiaryVASPdid: BENEFICIARY_VASP_DID,
227
+ beneficiaryVASPname: 'Beneficiary VASP Inc',
228
+ beneficiary: {
229
+ beneficiaryPersons: [
230
+ {
231
+ naturalPerson: {
232
+ name: {
233
+ nameIdentifier: [
234
+ { primaryIdentifier: 'John', nameIdentifierType: 'LEGL' },
235
+ ],
236
+ },
237
+ },
238
+ },
239
+ ],
240
+ },
241
+ },
242
+ errors: [],
243
+ status: 'pending',
244
+ valid: true,
245
+ value: {
246
+ destination: TEST_ADDRESS,
247
+ asset: TEST_ASSET,
248
+ customer: { type: 'natural', name: 'John', email: 'test@gmail.com' },
249
+ amountDecimal: 10000,
250
+ agent: {
251
+ name: 'Beneficiary VASP Inc',
252
+ did: BENEFICIARY_VASP_DID,
253
+ jurisdictions: null,
254
+ logo: null,
255
+ type: 'VASP',
256
+ },
257
+ counterparty: {
258
+ type: 'self',
259
+ name: 'John',
260
+ email: 'test@gmail.com',
261
+ did: 'did:key:z6Mkimok1nXUmbMeGGQ4cgJMMGPiWn9yYyappc9YenKTLqgf',
262
+ verified: true,
263
+ },
264
+ account: testAccount,
265
+ },
266
+ ivms101: {
267
+ beneficiary: {
268
+ beneficiaryPersons: [
269
+ {
270
+ naturalPerson: {
271
+ name: {
272
+ nameIdentifier: [
273
+ { primaryIdentifier: 'John', nameIdentifierType: 'LEGL' },
274
+ ],
275
+ },
276
+ },
277
+ },
278
+ ],
279
+ },
280
+ },
281
+ } as unknown as TransactionResponse<Withdrawal>;
282
+
283
+ describe('componentResponseToTxRequests', () => {
284
+ it('should transform a deposit response using txUpdate', () => {
285
+ const result = componentResponseToTxRequests(
286
+ depositResponse,
287
+ TEST_DELEGATE_TOKEN,
288
+ {
289
+ originatorId: TEST_ORIGINATOR_ID,
290
+ beneficiaryId: TEST_BENEFICIARY_ID,
291
+ },
292
+ );
293
+
294
+ expect(result).toEqual({
295
+ createTx: {
296
+ originator: { '@id': TEST_ORIGINATOR_ID },
297
+ beneficiary: { '@id': TEST_BENEFICIARY_ID },
298
+ asset: TEST_ASSET,
299
+ amount: '10000',
300
+ agents: [
301
+ {
302
+ '@id': BENEFICIARY_VASP_DID,
303
+ for: TEST_BENEFICIARY_ID,
304
+ role: 'VASP',
305
+ },
306
+ {
307
+ '@id': TEST_ADDRESS_DID,
308
+ for: TEST_ORIGINATOR_ID,
309
+ role: 'SourceAddress',
310
+ },
311
+ ],
312
+ ref: DEPOSIT_TX_ID,
313
+ },
314
+ ivms101: {
315
+ ivms101: {
316
+ originator: {
317
+ originatorPerson: [
318
+ {
319
+ naturalPerson: {
320
+ name: {
321
+ nameIdentifier: [
322
+ {
323
+ primaryIdentifier: 'Doe',
324
+ secondaryIdentifier: 'Jane',
325
+ naturalPersonNameIdentifierType: 'LEGL',
326
+ },
327
+ ],
328
+ },
329
+ geographicAddress: [geographicAddress],
330
+ },
331
+ legalPerson: undefined,
332
+ accountNumber: [TEST_ORIGINATOR_ID],
333
+ },
334
+ ],
335
+ },
336
+ beneficiary: undefined,
337
+ },
338
+ },
339
+ confirmRelationship: { proof: selfDeclarationProof },
340
+ });
341
+ });
342
+
343
+ it('should transform a deposit response with source array and settlementAddress', () => {
344
+ const depositWithSourceArray = {
345
+ ...depositResponse,
346
+ value: {
347
+ ...depositResponse.value,
348
+ source: [TEST_ADDRESS_DID, 'did:pkh:eip155:1:0xsecondaddress'],
349
+ },
350
+ } as unknown as TransactionResponse<Deposit>;
351
+
352
+ const settlementAddress = '0xsettlementaddress123';
353
+
354
+ const result = componentResponseToTxRequests(
355
+ depositWithSourceArray,
356
+ TEST_DELEGATE_TOKEN,
357
+ {
358
+ originatorId: TEST_ORIGINATOR_ID,
359
+ beneficiaryId: TEST_BENEFICIARY_ID,
360
+ settlementAddress,
361
+ },
362
+ );
363
+
364
+ expect(result.createTx.agents).toEqual([
365
+ {
366
+ '@id': BENEFICIARY_VASP_DID,
367
+ for: TEST_BENEFICIARY_ID,
368
+ role: 'VASP',
369
+ },
370
+ {
371
+ '@id': TEST_ADDRESS_DID,
372
+ for: TEST_ORIGINATOR_ID,
373
+ role: 'SourceAddress',
374
+ },
375
+ {
376
+ '@id': `did:pkh:eip155:1:${settlementAddress}`,
377
+ for: BENEFICIARY_VASP_DID,
378
+ role: 'SettlementAddress',
379
+ },
380
+ ]);
381
+ });
382
+
383
+ it('should transform a withdrawal response using txCreate', () => {
384
+ const result = componentResponseToTxRequests(
385
+ withdrawalResponse,
386
+ TEST_DELEGATE_TOKEN,
387
+ {
388
+ originatorId: TEST_ORIGINATOR_ID,
389
+ beneficiaryId: TEST_BENEFICIARY_ID,
390
+ },
391
+ );
392
+
393
+ expect(result).toEqual({
394
+ createTx: {
395
+ originator: { '@id': TEST_ORIGINATOR_ID },
396
+ beneficiary: { '@id': TEST_BENEFICIARY_ID },
397
+ asset: TEST_ASSET,
398
+ amount: '100000',
399
+ agents: [
400
+ { '@id': ORIGINATOR_VASP_DID, for: TEST_ORIGINATOR_ID, role: 'VASP' },
401
+ {
402
+ '@id': TEST_ADDRESS_DID,
403
+ for: TEST_BENEFICIARY_ID,
404
+ role: 'SettlementAddress',
405
+ },
406
+ ],
407
+ ref: expect.any(String),
408
+ },
409
+ ivms101: {
410
+ ivms101: {
411
+ originator: undefined,
412
+ beneficiary: {
413
+ beneficiaryPerson: [
414
+ {
415
+ naturalPerson: {
416
+ name: {
417
+ nameIdentifier: [
418
+ {
419
+ primaryIdentifier: 'Doe',
420
+ secondaryIdentifier: 'Jane',
421
+ naturalPersonNameIdentifierType: 'LEGL',
422
+ },
423
+ ],
424
+ },
425
+ geographicAddress: [geographicAddress],
426
+ nationalIdentification,
427
+ countryOfResidence: 'AF',
428
+ dateAndPlaceOfBirth: {
429
+ dateOfBirth: '2025-12-02',
430
+ placeOfBirth: 'Somewhere',
431
+ },
432
+ },
433
+ legalPerson: undefined,
434
+ accountNumber: [TEST_BENEFICIARY_ID],
435
+ },
436
+ ],
437
+ },
438
+ },
439
+ },
440
+ confirmRelationship: { proof: selfDeclarationProof },
441
+ });
442
+ });
443
+
444
+ it('should transform a self-transfer withdrawal with VASP agent and use originator data for beneficiary', () => {
445
+ const originatorData: OriginatorV2 = {
446
+ originatorPerson: [
447
+ {
448
+ naturalPerson: {
449
+ name: {
450
+ nameIdentifier: [
451
+ {
452
+ primaryIdentifier: 'Smith',
453
+ secondaryIdentifier: 'John',
454
+ naturalPersonNameIdentifierType: 'LEGL',
455
+ },
456
+ ],
457
+ },
458
+ },
459
+ accountNumber: [TEST_ORIGINATOR_ID],
460
+ },
461
+ ],
462
+ };
463
+
464
+ const result = componentResponseToTxRequests(
465
+ withdrawalSelfVaspResponse,
466
+ TEST_DELEGATE_TOKEN,
467
+ {
468
+ originatorId: TEST_ORIGINATOR_ID,
469
+ beneficiaryId: TEST_BENEFICIARY_ID,
470
+ originator: originatorData,
471
+ },
472
+ );
473
+
474
+ // No confirmRelationship since there's no proof (VASP agent, not wallet)
475
+ expect(result.confirmRelationship).toBeUndefined();
476
+
477
+ expect(result).toEqual({
478
+ createTx: {
479
+ originator: { '@id': TEST_ORIGINATOR_ID },
480
+ beneficiary: { '@id': TEST_BENEFICIARY_ID },
481
+ asset: TEST_ASSET,
482
+ amount: '10000',
483
+ agents: [
484
+ { '@id': ORIGINATOR_VASP_DID, for: TEST_ORIGINATOR_ID, role: 'VASP' },
485
+ {
486
+ '@id': BENEFICIARY_VASP_DID,
487
+ for: TEST_BENEFICIARY_ID,
488
+ role: 'VASP',
489
+ },
490
+ {
491
+ '@id': TEST_ADDRESS_DID,
492
+ for: BENEFICIARY_VASP_DID,
493
+ role: 'SettlementAddress',
494
+ },
495
+ ],
496
+ ref: expect.any(String),
497
+ },
498
+ ivms101: {
499
+ ivms101: {
500
+ originator: originatorData,
501
+ // For self-transfers, beneficiary uses the same originator data
502
+ beneficiary: { beneficiaryPerson: originatorData.originatorPerson },
503
+ },
504
+ },
505
+ });
506
+ });
507
+ });
508
+
509
+ describe('enrichConfig', () => {
510
+ const CUSTOMER_DID = 'did:key:customer123';
511
+ const SOURCE_ADDRESS = '0xsource123';
512
+ const DESTINATION_ADDRESS = '0xdest456';
513
+
514
+ // Create a valid JWT token with the given sub claim
515
+ // JWT format: header.payload.signature (signature not verified by decodeJwt)
516
+ function createDelegateToken(sub: string): string {
517
+ const header = btoa(JSON.stringify({ alg: 'HS256', typ: 'JWT' }));
518
+ const payload = btoa(JSON.stringify({ sub, iat: Date.now() }));
519
+ return `${header}.${payload}.fake-signature`;
520
+ }
521
+
522
+ describe('withdrawal transactions', () => {
523
+ it('should extract originatorId from delegate token and generate beneficiaryId from destination', () => {
524
+ const delegateToken = createDelegateToken(CUSTOMER_DID);
525
+ const withdrawal = {
526
+ destination: DESTINATION_ADDRESS,
527
+ asset: TEST_ASSET,
528
+ amountDecimal: 100,
529
+ } as Withdrawal;
530
+
531
+ const result = enrichConfig({}, delegateToken, withdrawal);
532
+
533
+ expect(result.originatorId).toBe(CUSTOMER_DID);
534
+ expect(result.beneficiaryId).toBe(`did:key:${DESTINATION_ADDRESS}`);
535
+ });
536
+
537
+ it('should set beneficiaryId equal to originatorId for self-transfers', () => {
538
+ const delegateToken = createDelegateToken(CUSTOMER_DID);
539
+ const withdrawal = {
540
+ destination: DESTINATION_ADDRESS,
541
+ asset: TEST_ASSET,
542
+ amountDecimal: 100,
543
+ counterparty: { type: PersonType.SELF },
544
+ } as Withdrawal;
545
+
546
+ const result = enrichConfig({}, delegateToken, withdrawal);
547
+
548
+ expect(result.originatorId).toBe(CUSTOMER_DID);
549
+ expect(result.beneficiaryId).toBe(CUSTOMER_DID);
550
+ });
551
+
552
+ it('should not override provided config values', () => {
553
+ const delegateToken = createDelegateToken(CUSTOMER_DID);
554
+ const withdrawal = {
555
+ destination: DESTINATION_ADDRESS,
556
+ asset: TEST_ASSET,
557
+ amountDecimal: 100,
558
+ } as Withdrawal;
559
+
560
+ const result = enrichConfig(
561
+ {
562
+ originatorId: TEST_ORIGINATOR_ID,
563
+ beneficiaryId: TEST_BENEFICIARY_ID,
564
+ },
565
+ delegateToken,
566
+ withdrawal,
567
+ );
568
+
569
+ expect(result.originatorId).toBe(TEST_ORIGINATOR_ID);
570
+ expect(result.beneficiaryId).toBe(TEST_BENEFICIARY_ID);
571
+ });
572
+ });
573
+
574
+ describe('deposit transactions', () => {
575
+ it('should extract beneficiaryId from delegate token and generate originatorId from source', () => {
576
+ const delegateToken = createDelegateToken(CUSTOMER_DID);
577
+ const deposit = {
578
+ source: SOURCE_ADDRESS,
579
+ asset: TEST_ASSET,
580
+ amountDecimal: 100,
581
+ } as Deposit;
582
+
583
+ const result = enrichConfig({}, delegateToken, deposit);
584
+
585
+ expect(result.beneficiaryId).toBe(CUSTOMER_DID);
586
+ expect(result.originatorId).toBe(`did:key:${SOURCE_ADDRESS}`);
587
+ });
588
+
589
+ it('should set originatorId equal to beneficiaryId for self-transfers', () => {
590
+ const delegateToken = createDelegateToken(CUSTOMER_DID);
591
+ const deposit = {
592
+ source: SOURCE_ADDRESS,
593
+ asset: TEST_ASSET,
594
+ amountDecimal: 100,
595
+ counterparty: { type: PersonType.SELF },
596
+ } as Deposit;
597
+
598
+ const result = enrichConfig({}, delegateToken, deposit);
599
+
600
+ expect(result.beneficiaryId).toBe(CUSTOMER_DID);
601
+ expect(result.originatorId).toBe(CUSTOMER_DID);
602
+ });
603
+
604
+ it('should not override provided config values', () => {
605
+ const delegateToken = createDelegateToken(CUSTOMER_DID);
606
+ const deposit = {
607
+ source: SOURCE_ADDRESS,
608
+ asset: TEST_ASSET,
609
+ amountDecimal: 100,
610
+ } as Deposit;
611
+
612
+ const result = enrichConfig(
613
+ {
614
+ originatorId: TEST_ORIGINATOR_ID,
615
+ beneficiaryId: TEST_BENEFICIARY_ID,
616
+ },
617
+ delegateToken,
618
+ deposit,
619
+ );
620
+
621
+ expect(result.originatorId).toBe(TEST_ORIGINATOR_ID);
622
+ expect(result.beneficiaryId).toBe(TEST_BENEFICIARY_ID);
623
+ });
624
+ });
625
+
626
+ it('should handle invalid delegate token gracefully', () => {
627
+ const withdrawal = {
628
+ destination: DESTINATION_ADDRESS,
629
+ asset: TEST_ASSET,
630
+ amountDecimal: 100,
631
+ } as Withdrawal;
632
+
633
+ const result = enrichConfig({}, 'invalid-token', withdrawal);
634
+
635
+ expect(result.originatorId).toBeUndefined();
636
+ expect(result.beneficiaryId).toBe(`did:key:${DESTINATION_ADDRESS}`);
637
+ });
638
+ });
@@ -0,0 +1,35 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { getCaip10ChainPrefix } from '../utils';
3
+
4
+ describe('getCaip10ChainPrefix', () => {
5
+ it('should extract chain prefix from EIP155 CAIP-10 address', () => {
6
+ const caip10 = 'eip155:1:0xd7914021b50a5090d3a13bb4ecae2abf014fafbd';
7
+ const result = getCaip10ChainPrefix(caip10);
8
+ expect(result).toBe('eip155:1');
9
+ });
10
+
11
+ it('should extract chain prefix from Solana CAIP-10 address', () => {
12
+ const caip10 =
13
+ 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:7kfAoE5opxrCN7rHjBNWvZQ1Fxm7vvhqZz9ZQWF8XGTo';
14
+ const result = getCaip10ChainPrefix(caip10);
15
+ expect(result).toBe('solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp');
16
+ });
17
+
18
+ it('should extract chain prefix from Polygon CAIP-10 address', () => {
19
+ const caip10 = 'eip155:137:0xd7914021b50a5090d3a13bb4ecae2abf014fafbd';
20
+ const result = getCaip10ChainPrefix(caip10);
21
+ expect(result).toBe('eip155:137');
22
+ });
23
+
24
+ it('should throw error for invalid CAIP-10 format', () => {
25
+ expect(() => getCaip10ChainPrefix('invalid')).toThrow(
26
+ 'Invalid CAIP-10 format: "invalid". Expected format: {namespace}:{chainId}:{address}',
27
+ );
28
+ });
29
+
30
+ it('should throw error for CAIP-10 with missing address', () => {
31
+ expect(() => getCaip10ChainPrefix('eip155:1')).toThrow(
32
+ 'Invalid CAIP-10 format',
33
+ );
34
+ });
35
+ });