import { bytesToHex, hexToBytes } from '@xrplf/isomorphic/utils' import { classicAddressToXAddress, xAddressToClassicAddress, isValidXAddress, encodeXAddress, } from '../src' interface AddressTestCase { // classicAddress [0]: string // tag [1]: false | number // mainnetAddress [2]: string // testnetAddress [3]: string } const testCases: AddressTestCase[] = [ [ 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59', false, 'X7AcgcsBL6XDcUb289X4mJ8djcdyKaB5hJDWMArnXr61cqZ', 'T719a5UwUCnEs54UsxG9CJYYDhwmFCqkr7wxCcNcfZ6p5GZ', ], [ 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59', 1, 'X7AcgcsBL6XDcUb289X4mJ8djcdyKaGZMhc9YTE92ehJ2Fu', 'T719a5UwUCnEs54UsxG9CJYYDhwmFCvbJNZbi37gBGkRkbE', ], [ 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59', 14, 'X7AcgcsBL6XDcUb289X4mJ8djcdyKaGo2K5VpXpmCqbV2gS', 'T719a5UwUCnEs54UsxG9CJYYDhwmFCvqXVCALUGJGSbNV3x', ], [ 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59', 11747, 'X7AcgcsBL6XDcUb289X4mJ8djcdyKaLFuhLRuNXPrDeJd9A', 'T719a5UwUCnEs54UsxG9CJYYDhwmFCziiNHtUukubF2Mg6t', ], [ 'rLczgQHxPhWtjkaQqn3Q6UM8AbRbbRvs5K', false, 'XVZVpQj8YSVpNyiwXYSqvQoQqgBttTxAZwMcuJd4xteQHyt', 'TVVrSWtmQQssgVcmoMBcFQZKKf56QscyWLKnUyiuZW8ALU4', ], [ 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', false, 'X7YenJqxv3L66CwhBSfd3N8RzGXxYqPopMGMsCcpho79rex', 'T77wVQzA8ntj9wvCTNiQpNYLT5hmhRsFyXDoMLqYC4BzQtV', ], [ 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', 58, 'X7YenJqxv3L66CwhBSfd3N8RzGXxYqV56ZkTCa9UCzgaao1', 'T77wVQzA8ntj9wvCTNiQpNYLT5hmhR9kej6uxm4jGcQD7rZ', ], [ 'rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW', 23480, 'X7d3eHCXzwBeWrZec1yT24iZerQjYL8m8zCJ16ACxu1BrBY', 'T7YChPFWifjCAXLEtg5N74c7fSAYsvSokwcmBPBUZWhxH5P', ], [ 'rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW', 11747, 'X7d3eHCXzwBeWrZec1yT24iZerQjYLo2CJf8oVC5CMWey5m', 'T7YChPFWifjCAXLEtg5N74c7fSAYsvTcc7nEfwuEEvn5Q4w', ], [ 'rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf', false, 'XVLhHMPHU98es4dbozjVtdWzVrDjtV5fdx1mHp98tDMoQXb', 'TVE26TYGhfLC7tQDno7G8dGtxSkYQn49b3qD26PK7FcGSKE', ], [ 'rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf', 0, 'XVLhHMPHU98es4dbozjVtdWzVrDjtV8AqEL4xcZj5whKbmc', 'TVE26TYGhfLC7tQDno7G8dGtxSkYQnSy8RHqGHoGJ59spi2', ], [ 'rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf', 1, 'XVLhHMPHU98es4dbozjVtdWzVrDjtV8xvjGQTYPiAx6gwDC', 'TVE26TYGhfLC7tQDno7G8dGtxSkYQnSz1uDimDdPYXzSpyw', ], [ 'rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf', 2, 'XVLhHMPHU98es4dbozjVtdWzVrDjtV8zpDURx7DzBCkrQE7', 'TVE26TYGhfLC7tQDno7G8dGtxSkYQnTryP9tG9TW8GeMBmd', ], [ 'rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf', 32, 'XVLhHMPHU98es4dbozjVtdWzVrDjtVoYiC9UvKfjKar4LJe', 'TVE26TYGhfLC7tQDno7G8dGtxSkYQnT2oqaCDzMEuCDAj1j', ], [ 'rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf', 276, 'XVLhHMPHU98es4dbozjVtdWzVrDjtVoKj3MnFGMXEFMnvJV', 'TVE26TYGhfLC7tQDno7G8dGtxSkYQnTMgJJYfAbsiPsc6Zg', ], [ 'rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf', 65591, 'XVLhHMPHU98es4dbozjVtdWzVrDjtVozpjdhPQVdt3ghaWw', 'TVE26TYGhfLC7tQDno7G8dGtxSkYQn7ryu2W6njw7mT1jmS', ], [ 'rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf', 16781933, 'XVLhHMPHU98es4dbozjVtdWzVrDjtVqrDUk2vDpkTjPsY73', 'TVE26TYGhfLC7tQDno7G8dGtxSkYQnVsw45sDtGHhLi27Qa', ], [ 'rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf', 4294967294, 'XVLhHMPHU98es4dbozjVtdWzVrDjtV1kAsixQTdMjbWi39u', 'TVE26TYGhfLC7tQDno7G8dGtxSkYQnX8tDFQ53itLNqs6vU', ], [ 'rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf', 4294967295, 'XVLhHMPHU98es4dbozjVtdWzVrDjtV18pX8yuPT7y4xaEHi', 'TVE26TYGhfLC7tQDno7G8dGtxSkYQnXoy6kSDh6rZzApc69', ], [ 'rPEPPER7kfTD9w2To4CQk6UCfuHM9c6GDY', false, 'XV5sbjUmgPpvXv4ixFWZ5ptAYZ6PD2gYsjNFQLKYW33DzBm', 'TVd2rqMkYL2AyS97NdELcpeiprNBjwLZzuUG5rZnaewsahi', ], [ 'rPEPPER7kfTD9w2To4CQk6UCfuHM9c6GDY', 0, 'XV5sbjUmgPpvXv4ixFWZ5ptAYZ6PD2m4Er6SnvjVLpMWPjR', 'TVd2rqMkYL2AyS97NdELcpeiprNBjwRQUBetPbyrvXSTuxU', ], [ 'rPEPPER7kfTD9w2To4CQk6UCfuHM9c6GDY', 13371337, 'XV5sbjUmgPpvXv4ixFWZ5ptAYZ6PD2qwGkhgc48zzcx6Gkr', 'TVd2rqMkYL2AyS97NdELcpeiprNBjwVUDvp3vhpXbNhLwJi', ], ] ;[false, true].forEach((isTestAddress) => { const MAX_32_BIT_UNSIGNED_INT = 4294967295 const network = isTestAddress ? ' (test)' : ' (main)' testCases.forEach((testCase) => { const classicAddress = testCase[0] const tag = testCase[1] === false ? false : testCase[1] const xAddress = isTestAddress ? testCase[3] : testCase[2] it(`Converts ${classicAddress}${ tag ? `:${tag}` : '' } to ${xAddress}${network}`, () => { expect(classicAddressToXAddress(classicAddress, tag, isTestAddress)).toBe( xAddress, ) const myClassicAddress = xAddressToClassicAddress(xAddress) expect(myClassicAddress).toEqual({ classicAddress, tag, test: isTestAddress, }) expect(isValidXAddress(xAddress)).toBe(true) }) }) { const classicAddress = 'rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf' const tag = MAX_32_BIT_UNSIGNED_INT + 1 it(`Converting ${classicAddress}:${tag}${network} throws`, () => { expect(() => { classicAddressToXAddress(classicAddress, tag, isTestAddress) }).toThrow(new Error('Invalid tag')) }) } { const classicAddress = 'r' it(`Invalid classic address: Converting ${classicAddress}${network} throws`, () => { expect(() => { classicAddressToXAddress(classicAddress, false, isTestAddress) }).toThrow( new Error('invalid_input_size: decoded data must have length >= 5'), ) }) } { const highAndLowAccounts = [ hexToBytes('00'.repeat(20)), hexToBytes(`${'00'.repeat(19)}01`), hexToBytes('01'.repeat(20)), hexToBytes('FF'.repeat(20)), ] highAndLowAccounts.forEach((accountId) => { const tagTestCases: Array = [ false, 0, 1, MAX_32_BIT_UNSIGNED_INT, ] tagTestCases.forEach((testCase) => { const tag = testCase || false const xAddress = encodeXAddress(accountId, tag, isTestAddress) it(`Encoding ${bytesToHex(accountId)}${ tag ? `:${tag}` : '' } to ${xAddress} has expected length`, () => { expect(xAddress.length).toBe(47) }) }) }) } }) { const xAddress = 'XVLhHMPHU98es4dbozjVtdWzVrDjtV5fdx1mHp98tDMoQXa' it(`Invalid X-address (bad checksum): Converting ${xAddress} throws`, () => { expect(() => { xAddressToClassicAddress(xAddress) }).toThrow(new Error('checksum_invalid')) }) } { const xAddress = 'dGzKGt8CVpWoa8aWL1k18tAdy9Won3PxynvbbpkAqp3V47g' it(`Invalid X-address (bad prefix): Converting ${xAddress} throws`, () => { expect(() => { xAddressToClassicAddress(xAddress) }).toThrow(new Error('Invalid X-address: bad prefix')) }) } it(`Invalid X-address (64-bit tag) throws`, () => { expect(() => { // Encoded from: // { // classicAddress: 'rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf', // tag: MAX_32_BIT_UNSIGNED_INT + 1 // } xAddressToClassicAddress('XVLhHMPHU98es4dbozjVtdWzVrDjtV18pX8zeUygYrCgrPh') }).toThrow(new Error('Unsupported X-address')) }) it(`Invalid Account ID throws`, () => { expect(() => { encodeXAddress(hexToBytes('00'.repeat(19)), false, false) }).toThrowError('Account ID must be 20 bytes') }) it(`isValidXAddress returns false for invalid X-address`, () => { expect( isValidXAddress('XVLhHMPHU98es4dbozjVtdWzVrDjtV18pX8zeUygYrCgrPh'), ).toBe(false) }) it(`Converts X7AcgcsBL6XDcUb... to r9cZA1mLK5R5A... and tag: false`, () => { const classicAddress = 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59' // eslint-disable-next-line @typescript-eslint/naming-convention -- tag can be false or a number const tag = false const xAddress = 'X7AcgcsBL6XDcUb289X4mJ8djcdyKaB5hJDWMArnXr61cqZ' const isTestAddress = false expect(classicAddressToXAddress(classicAddress, tag, isTestAddress)).toBe( xAddress, ) const myClassicAddress = xAddressToClassicAddress(xAddress) expect(myClassicAddress).toEqual({ classicAddress, tag, test: isTestAddress, }) expect(isValidXAddress(xAddress)).toBe(true) // Notice that converting an X-address to a classic address has `result.tag === false` (not undefined) expect(myClassicAddress.tag).toEqual(false) })