|
1 | 1 | import {
|
2 | 2 | CAIP_ACCOUNT_ADDRESS_FIXTURES,
|
3 | 3 | CAIP_ACCOUNT_ID_FIXTURES,
|
| 4 | + CAIP_ASSET_ID_FIXTURES, |
| 5 | + CAIP_ASSET_NAMESPACE_FIXTURES, |
| 6 | + CAIP_ASSET_REFERENCE_FIXTURES, |
| 7 | + CAIP_ASSET_TYPE_FIXTURES, |
4 | 8 | CAIP_CHAIN_ID_FIXTURES,
|
5 | 9 | CAIP_NAMESPACE_FIXTURES,
|
6 | 10 | CAIP_REFERENCE_FIXTURES,
|
7 | 11 | } from './__fixtures__';
|
8 | 12 | import {
|
| 13 | + CAIP_ACCOUNT_ADDRESS_REGEX, |
| 14 | + CAIP_ASSET_NAMESPACE_REGEX, |
| 15 | + CAIP_ASSET_REFERENCE_REGEX, |
| 16 | + CAIP_NAMESPACE_REGEX, |
| 17 | + CAIP_REFERENCE_REGEX, |
| 18 | + CAIP_TOKEN_ID_REGEX, |
9 | 19 | isCaipAccountAddress,
|
10 | 20 | isCaipAccountId,
|
| 21 | + isCaipAssetId, |
| 22 | + isCaipAssetNamespace, |
| 23 | + isCaipAssetReference, |
| 24 | + isCaipAssetType, |
11 | 25 | isCaipChainId,
|
12 | 26 | isCaipNamespace,
|
13 | 27 | isCaipReference,
|
14 |
| - isCaipAssetType, |
15 |
| - isCaipAssetId, |
| 28 | + KnownCaipNamespace, |
16 | 29 | parseCaipAccountId,
|
| 30 | + parseCaipAssetId, |
17 | 31 | parseCaipChainId,
|
| 32 | + toCaipAccountId, |
| 33 | + toCaipAssetId, |
18 | 34 | toCaipChainId,
|
19 |
| - KnownCaipNamespace, |
20 |
| - CAIP_NAMESPACE_REGEX, |
21 |
| - CAIP_REFERENCE_REGEX, |
22 | 35 | } from './caip-types';
|
23 | 36 |
|
24 | 37 | describe('isCaipChainId', () => {
|
@@ -151,21 +164,53 @@ describe('isCaipAccountAddress', () => {
|
151 | 164 | });
|
152 | 165 | });
|
153 | 166 |
|
154 |
| -describe('isCaipAssetType', () => { |
155 |
| - // Imported from: https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-19.md#test-cases |
| 167 | +describe('isCaipAssetNamespace', () => { |
| 168 | + it.each([...CAIP_ASSET_NAMESPACE_FIXTURES])( |
| 169 | + 'returns true for a valid asset namespace %s', |
| 170 | + (assetNamespace) => { |
| 171 | + expect(isCaipAssetNamespace(assetNamespace)).toBe(true); |
| 172 | + }, |
| 173 | + ); |
| 174 | + |
| 175 | + it.each([true, false, null, undefined, 1, {}, [], 'abC', '12', '123456789'])( |
| 176 | + 'returns false for an invalid asset namespace %s', |
| 177 | + (assetNamespace) => { |
| 178 | + expect(isCaipAssetNamespace(assetNamespace)).toBe(false); |
| 179 | + }, |
| 180 | + ); |
| 181 | +}); |
| 182 | + |
| 183 | +describe('isCaipAssetReference', () => { |
| 184 | + it.each([...CAIP_ASSET_REFERENCE_FIXTURES])( |
| 185 | + 'returns true for a valid asset reference %s', |
| 186 | + (assetReference) => { |
| 187 | + expect(isCaipAssetReference(assetReference)).toBe(true); |
| 188 | + }, |
| 189 | + ); |
| 190 | + |
156 | 191 | it.each([
|
157 |
| - 'eip155:1/slip44:60', |
158 |
| - 'bip122:000000000019d6689c085ae165831e93/slip44:0', |
159 |
| - 'cosmos:cosmoshub-3/slip44:118', |
160 |
| - 'bip122:12a765e31ffd4059bada1e25190f6e98/slip44:2', |
161 |
| - 'cosmos:Binance-Chain-Tigris/slip44:714', |
162 |
| - 'cosmos:iov-mainnet/slip44:234', |
163 |
| - 'lip9:9ee11e9df416b18b/slip44:134', |
164 |
| - 'eip155:1/erc20:0x6b175474e89094c44da98b954eedeac495271d0f', |
165 |
| - 'eip155:1/erc721:0x06012c8cf97BEaD5deAe237070F9587f8E7A266d', |
166 |
| - ])('returns true for a valid asset type %s', (id) => { |
167 |
| - expect(isCaipAssetType(id)).toBe(true); |
| 192 | + true, |
| 193 | + false, |
| 194 | + null, |
| 195 | + undefined, |
| 196 | + 1, |
| 197 | + {}, |
| 198 | + [], |
| 199 | + '', |
| 200 | + '!@#$%^&*()', |
| 201 | + Array(129).fill('0').join(''), |
| 202 | + ])('returns false for an invalid asset reference %s', (assetReference) => { |
| 203 | + expect(isCaipAssetReference(assetReference)).toBe(false); |
168 | 204 | });
|
| 205 | +}); |
| 206 | + |
| 207 | +describe('isCaipAssetType', () => { |
| 208 | + it.each([...CAIP_ASSET_TYPE_FIXTURES])( |
| 209 | + 'returns true for a valid asset type %s', |
| 210 | + (assetType) => { |
| 211 | + expect(isCaipAssetType(assetType)).toBe(true); |
| 212 | + }, |
| 213 | + ); |
169 | 214 |
|
170 | 215 | it.each([
|
171 | 216 | true,
|
@@ -198,13 +243,12 @@ describe('isCaipAssetType', () => {
|
198 | 243 | });
|
199 | 244 |
|
200 | 245 | describe('isCaipAssetId', () => {
|
201 |
| - // Imported from: https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-19.md#test-cases |
202 |
| - it.each([ |
203 |
| - 'eip155:1/erc721:0x06012c8cf97BEaD5deAe237070F9587f8E7A266d/771769', |
204 |
| - 'hedera:mainnet/nft:0.0.55492/12', |
205 |
| - ])('returns true for a valid asset id %s', (id) => { |
206 |
| - expect(isCaipAssetId(id)).toBe(true); |
207 |
| - }); |
| 246 | + it.each([...CAIP_ASSET_ID_FIXTURES])( |
| 247 | + 'returns true for a valid asset id %s', |
| 248 | + (id) => { |
| 249 | + expect(isCaipAssetId(id)).toBe(true); |
| 250 | + }, |
| 251 | + ); |
208 | 252 |
|
209 | 253 | it.each([
|
210 | 254 | true,
|
@@ -366,6 +410,113 @@ describe('parseCaipAccountId', () => {
|
366 | 410 | });
|
367 | 411 | });
|
368 | 412 |
|
| 413 | +describe('parseCaipAssetId', () => { |
| 414 | + it('parses valid asset ids', () => { |
| 415 | + expect(parseCaipAssetId('eip155:1/slip44:60')).toMatchInlineSnapshot(` |
| 416 | + { |
| 417 | + "assetNamespace": "slip44", |
| 418 | + "assetReference": "60", |
| 419 | + "chain": { |
| 420 | + "namespace": "eip155", |
| 421 | + "reference": "1", |
| 422 | + }, |
| 423 | + "chainId": "eip155:1", |
| 424 | + } |
| 425 | + `); |
| 426 | + |
| 427 | + expect( |
| 428 | + parseCaipAssetId( |
| 429 | + 'eip155:1/erc721:0x06012c8cf97BEaD5deAe237070F9587f8E7A266d/771769', |
| 430 | + ), |
| 431 | + ).toMatchInlineSnapshot(` |
| 432 | + { |
| 433 | + "assetNamespace": "erc721", |
| 434 | + "assetReference": "0x06012c8cf97BEaD5deAe237070F9587f8E7A266d", |
| 435 | + "chain": { |
| 436 | + "namespace": "eip155", |
| 437 | + "reference": "1", |
| 438 | + }, |
| 439 | + "chainId": "eip155:1", |
| 440 | + "tokenId": "771769", |
| 441 | + } |
| 442 | + `); |
| 443 | + |
| 444 | + expect(parseCaipAssetId('bip122:000000000019d6689c085ae165831e93/slip44:0')) |
| 445 | + .toMatchInlineSnapshot(` |
| 446 | + { |
| 447 | + "assetNamespace": "slip44", |
| 448 | + "assetReference": "0", |
| 449 | + "chain": { |
| 450 | + "namespace": "bip122", |
| 451 | + "reference": "000000000019d6689c085ae165831e93", |
| 452 | + }, |
| 453 | + "chainId": "bip122:000000000019d6689c085ae165831e93", |
| 454 | + } |
| 455 | + `); |
| 456 | + |
| 457 | + expect(parseCaipAssetId('cosmos:cosmoshub-3/slip44:118')) |
| 458 | + .toMatchInlineSnapshot(` |
| 459 | + { |
| 460 | + "assetNamespace": "slip44", |
| 461 | + "assetReference": "118", |
| 462 | + "chain": { |
| 463 | + "namespace": "cosmos", |
| 464 | + "reference": "cosmoshub-3", |
| 465 | + }, |
| 466 | + "chainId": "cosmos:cosmoshub-3", |
| 467 | + } |
| 468 | + `); |
| 469 | + |
| 470 | + expect(parseCaipAssetId('hedera:mainnet/nft:0.0.55492/12')) |
| 471 | + .toMatchInlineSnapshot(` |
| 472 | + { |
| 473 | + "assetNamespace": "nft", |
| 474 | + "assetReference": "0.0.55492", |
| 475 | + "chain": { |
| 476 | + "namespace": "hedera", |
| 477 | + "reference": "mainnet", |
| 478 | + }, |
| 479 | + "chainId": "hedera:mainnet", |
| 480 | + "tokenId": "12", |
| 481 | + } |
| 482 | + `); |
| 483 | + |
| 484 | + expect( |
| 485 | + parseCaipAssetId( |
| 486 | + 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/nft:Fz6LxeUg5qjesYX3BdmtTwyyzBtMxk644XiTqU5W3w9w', |
| 487 | + ), |
| 488 | + ).toMatchInlineSnapshot(` |
| 489 | + { |
| 490 | + "assetNamespace": "nft", |
| 491 | + "assetReference": "Fz6LxeUg5qjesYX3BdmtTwyyzBtMxk644XiTqU5W3w9w", |
| 492 | + "chain": { |
| 493 | + "namespace": "solana", |
| 494 | + "reference": "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", |
| 495 | + }, |
| 496 | + "chainId": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", |
| 497 | + } |
| 498 | + `); |
| 499 | + }); |
| 500 | + |
| 501 | + it.each([ |
| 502 | + true, |
| 503 | + false, |
| 504 | + null, |
| 505 | + undefined, |
| 506 | + 1, |
| 507 | + 'foo', |
| 508 | + 'foobarbazquz:1', |
| 509 | + 'foo:', |
| 510 | + 'foo:foobarbazquzfoobarbazquzfoobarbazquzfoobarbazquzfoobarbazquzfoobarbazquz', |
| 511 | + 'eip155:1', |
| 512 | + 'eip155:1:', |
| 513 | + ])('throws for invalid input %s', (input) => { |
| 514 | + expect(() => parseCaipAssetId(input as any)).toThrow( |
| 515 | + 'Invalid CAIP asset ID.', |
| 516 | + ); |
| 517 | + }); |
| 518 | +}); |
| 519 | + |
369 | 520 | describe('toCaipChainId', () => {
|
370 | 521 | // This function relies on @metamask/utils CAIP helpers. Those are being
|
371 | 522 | // tested with a variety of inputs.
|
@@ -415,3 +566,189 @@ describe('toCaipChainId', () => {
|
415 | 566 | );
|
416 | 567 | });
|
417 | 568 | });
|
| 569 | + |
| 570 | +describe('toCaipAccountId', () => { |
| 571 | + it('returns a valid CAIP-10 account ID when given a valid namespace, reference, and accountAddress', () => { |
| 572 | + const namespace = 'eip'; |
| 573 | + const reference = '1'; |
| 574 | + const accountAddress = '0xab16a96D359eC26a11e2C2b3d8f8B8942d5Bfcdb'; |
| 575 | + expect(toCaipAccountId(namespace, reference, accountAddress)).toBe( |
| 576 | + `${namespace}:${reference}:${accountAddress}`, |
| 577 | + ); |
| 578 | + }); |
| 579 | + |
| 580 | + it.each([ |
| 581 | + // Too short, must have 3 chars at least |
| 582 | + '', |
| 583 | + 'xs', |
| 584 | + // Not matching |
| 585 | + '!@#$%^&*()', |
| 586 | + // Too long |
| 587 | + 'namespacetoolong', |
| 588 | + ])('throws for invalid namespaces: %s', (namespace) => { |
| 589 | + const reference = '1'; |
| 590 | + const accountAddress = '0xab16a96D359eC26a11e2C2b3d8f8B8942d5Bfcdb'; |
| 591 | + expect(() => toCaipAccountId(namespace, reference, accountAddress)).toThrow( |
| 592 | + `Invalid "namespace", must match: ${CAIP_NAMESPACE_REGEX.toString()}`, |
| 593 | + ); |
| 594 | + }); |
| 595 | + |
| 596 | + it.each([ |
| 597 | + // Too short, must have 1 char at least |
| 598 | + '', |
| 599 | + // Not matching |
| 600 | + '!@#$%^&*()', |
| 601 | + // Too long |
| 602 | + '012345678901234567890123456789012', // 33 chars |
| 603 | + ])('throws for invalid reference: %s', (reference) => { |
| 604 | + const namespace = 'eip'; |
| 605 | + const accountAddress = '0xab16a96D359eC26a11e2C2b3d8f8B8942d5Bfcdb'; |
| 606 | + expect(() => toCaipAccountId(namespace, reference, accountAddress)).toThrow( |
| 607 | + `Invalid "reference", must match: ${CAIP_REFERENCE_REGEX.toString()}`, |
| 608 | + ); |
| 609 | + }); |
| 610 | + |
| 611 | + it.each([ |
| 612 | + // Too short, must have 1 char at least |
| 613 | + '', |
| 614 | + // Not matching |
| 615 | + '!@#$%^&*()', |
| 616 | + // Too long |
| 617 | + Array(129).fill('0').join(''), |
| 618 | + ])('throws for invalid accountAddress: %s', (accountAddress) => { |
| 619 | + const namespace = 'eip'; |
| 620 | + const reference = '1'; |
| 621 | + expect(() => toCaipAccountId(namespace, reference, accountAddress)).toThrow( |
| 622 | + `Invalid "accountAddress", must match: ${CAIP_ACCOUNT_ADDRESS_REGEX.toString()}`, |
| 623 | + ); |
| 624 | + }); |
| 625 | +}); |
| 626 | + |
| 627 | +describe('toCaipAssetId', () => { |
| 628 | + it('returns a valid CAIP-19 asset ID when given a valid namespace, reference, assetNamespace, and assetReference', () => { |
| 629 | + const namespace = 'eip'; |
| 630 | + const reference = '1'; |
| 631 | + const assetNamespace = 'erc20'; |
| 632 | + const assetReference = '0x6b175474e89094c44da98b954eedeac495271d0f'; |
| 633 | + expect( |
| 634 | + toCaipAssetId(namespace, reference, assetNamespace, assetReference), |
| 635 | + ).toBe(`${namespace}:${reference}/${assetNamespace}:${assetReference}`); |
| 636 | + }); |
| 637 | + |
| 638 | + it('returns a valid CAIP-19 asset ID when given a valid namespace, reference, assetNamespace, assetReference, and tokenId', () => { |
| 639 | + const namespace = 'eip'; |
| 640 | + const reference = '1'; |
| 641 | + const assetNamespace = 'erc721'; |
| 642 | + const assetReference = '0x06012c8cf97BEaD5deAe237070F9587f8E7A266d'; |
| 643 | + const tokenId = '771769'; |
| 644 | + expect( |
| 645 | + toCaipAssetId( |
| 646 | + namespace, |
| 647 | + reference, |
| 648 | + assetNamespace, |
| 649 | + assetReference, |
| 650 | + tokenId, |
| 651 | + ), |
| 652 | + ).toBe( |
| 653 | + `${namespace}:${reference}/${assetNamespace}:${assetReference}/${tokenId}`, |
| 654 | + ); |
| 655 | + }); |
| 656 | + |
| 657 | + it.each([ |
| 658 | + // Too short, must have 3 chars at least |
| 659 | + '', |
| 660 | + 'xs', |
| 661 | + // Not matching |
| 662 | + '!@#$%^&*()', |
| 663 | + // Too long |
| 664 | + 'namespacetoolong', |
| 665 | + ])('throws for invalid namespaces: %s', (namespace) => { |
| 666 | + const reference = '1'; |
| 667 | + const assetNamespace = 'erc20'; |
| 668 | + const assetReference = '0x6b175474e89094c44da98b954eedeac495271d0f'; |
| 669 | + expect(() => |
| 670 | + toCaipAssetId(namespace, reference, assetNamespace, assetReference), |
| 671 | + ).toThrow( |
| 672 | + `Invalid "namespace", must match: ${CAIP_NAMESPACE_REGEX.toString()}`, |
| 673 | + ); |
| 674 | + }); |
| 675 | + |
| 676 | + it.each([ |
| 677 | + // Too short, must have 1 char at least |
| 678 | + '', |
| 679 | + // Not matching |
| 680 | + '!@#$%^&*()', |
| 681 | + // Too long |
| 682 | + '012345678901234567890123456789012', // 33 chars |
| 683 | + ])('throws for invalid reference: %s', (reference) => { |
| 684 | + const namespace = 'eip'; |
| 685 | + const assetNamespace = 'erc20'; |
| 686 | + const assetReference = '0x6b175474e89094c44da98b954eedeac495271d0f'; |
| 687 | + expect(() => |
| 688 | + toCaipAssetId(namespace, reference, assetNamespace, assetReference), |
| 689 | + ).toThrow( |
| 690 | + `Invalid "reference", must match: ${CAIP_REFERENCE_REGEX.toString()}`, |
| 691 | + ); |
| 692 | + }); |
| 693 | + |
| 694 | + it.each([ |
| 695 | + // Too short, must have 1 char at least |
| 696 | + '', |
| 697 | + // Not matching |
| 698 | + '!@#$%^&*', |
| 699 | + // Too long |
| 700 | + '012345789', |
| 701 | + ])('throws for invalid assetNamespace: %s', (assetNamespace) => { |
| 702 | + const namespace = 'eip'; |
| 703 | + const reference = '1'; |
| 704 | + const assetReference = '0x6b175474e89094c44da98b954eedeac495271d0f'; |
| 705 | + expect(() => |
| 706 | + toCaipAssetId(namespace, reference, assetNamespace, assetReference), |
| 707 | + ).toThrow( |
| 708 | + `Invalid "assetNamespace", must match: ${CAIP_ASSET_NAMESPACE_REGEX.toString()}`, |
| 709 | + ); |
| 710 | + }); |
| 711 | + |
| 712 | + it.each([ |
| 713 | + // Too short, must have 1 char at least |
| 714 | + '', |
| 715 | + // Not matching |
| 716 | + '!@#$%^&*()', |
| 717 | + // Too long |
| 718 | + Array(129).fill('0').join(''), |
| 719 | + ])('throws for invalid assetReference: %s', (assetReference) => { |
| 720 | + const namespace = 'eip'; |
| 721 | + const reference = '1'; |
| 722 | + const assetNamespace = 'erc20'; |
| 723 | + expect(() => |
| 724 | + toCaipAssetId(namespace, reference, assetNamespace, assetReference), |
| 725 | + ).toThrow( |
| 726 | + `Invalid "assetReference", must match: ${CAIP_ASSET_REFERENCE_REGEX.toString()}`, |
| 727 | + ); |
| 728 | + }); |
| 729 | + |
| 730 | + it.each([ |
| 731 | + // Too short, must have 1 char at least |
| 732 | + '', |
| 733 | + // Not matching |
| 734 | + '!@#$%^&*()', |
| 735 | + // Too long |
| 736 | + Array(79).fill('0').join(''), |
| 737 | + ])('throws for invalid tokenId: %s', (tokenId) => { |
| 738 | + const namespace = 'eip'; |
| 739 | + const reference = '1'; |
| 740 | + const assetNamespace = 'erc721'; |
| 741 | + const assetReference = '0x06012c8cf97BEaD5deAe237070F9587f8E7A266d'; |
| 742 | + expect(() => |
| 743 | + toCaipAssetId( |
| 744 | + namespace, |
| 745 | + reference, |
| 746 | + assetNamespace, |
| 747 | + assetReference, |
| 748 | + tokenId, |
| 749 | + ), |
| 750 | + ).toThrow( |
| 751 | + `Invalid "tokenId", must match: ${CAIP_TOKEN_ID_REGEX.toString()}`, |
| 752 | + ); |
| 753 | + }); |
| 754 | +}); |
0 commit comments