Files
xahau.js/packages/ripple-address-codec/test/index.test.ts
Caleb Kniffen 38b385969b feat: remove Buffer support and bundle polyfill (#2526)
- Removes need for bundlers to polyfill the `Buffer` class. `UInt8Array` are used instead which are native to the browser and node.
- Reduces bundle size 7.1kb gzipped and eliminates 4 runtime dependencies: `base-x`, `base64-js`, `buffer`, and `ieee754`.

BREAKING CHANGE: All methods that previously took a `Buffer` now accept a `UInt8Array`.

---------

Co-authored-by: Jackson Mills <jmills@ripple.com>
2024-02-01 13:53:41 -06:00

291 lines
8.2 KiB
TypeScript

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 | number> = [
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)
})