@exodus/bytes 1.0.0-rc.10 → 1.0.0-rc.11
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.
- package/README.md +3 -0
- package/base58.js +16 -8
- package/fallback/_utils.js +14 -6
- package/fallback/encoding.js +17 -7
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -150,6 +150,9 @@ Same as `windows1252toString = createSinglebyteDecoder('windows-1252')`.
|
|
|
150
150
|
##### `toBase58(arr)`
|
|
151
151
|
##### `fromBase58(str, format = 'uint8')`
|
|
152
152
|
|
|
153
|
+
##### `toBase58xrp(arr)`
|
|
154
|
+
##### `fromBase58xrp(str, format = 'uint8')`
|
|
155
|
+
|
|
153
156
|
### `@exodus/bytes/base58check.js`
|
|
154
157
|
|
|
155
158
|
##### `async toBase58check(arr)`
|
package/base58.js
CHANGED
|
@@ -3,10 +3,10 @@ import { assertUint8 } from './assert.js'
|
|
|
3
3
|
import { nativeDecoder, nativeEncoder, isHermes } from './fallback/_utils.js'
|
|
4
4
|
import { encodeAscii, decodeAscii } from './fallback/latin1.js'
|
|
5
5
|
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
6
|
+
const alphabet58 = [...'123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz']
|
|
7
|
+
const alphabetXRP = [...'rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz']
|
|
8
|
+
const codes58 = new Uint8Array(alphabet58.map((x) => x.charCodeAt(0)))
|
|
9
|
+
const codesXRP = new Uint8Array(alphabetXRP.map((x) => x.charCodeAt(0)))
|
|
10
10
|
|
|
11
11
|
const _0n = BigInt(0)
|
|
12
12
|
const _1n = BigInt(1)
|
|
@@ -16,17 +16,18 @@ const _58n = BigInt(58)
|
|
|
16
16
|
const _0xffffffffn = BigInt(0xff_ff_ff_ff)
|
|
17
17
|
|
|
18
18
|
let table // 15 * 82, diagonal, <1kb
|
|
19
|
-
|
|
19
|
+
const fromMaps = new Map()
|
|
20
20
|
|
|
21
21
|
const E_CHAR = 'Invalid character in base58 input'
|
|
22
22
|
|
|
23
23
|
const shouldUseBigIntFrom = isHermes // faster only on Hermes, numbers path beats it on normal engines
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
function toBase58core(arr, alphabet, codes) {
|
|
26
26
|
assertUint8(arr)
|
|
27
27
|
const length = arr.length
|
|
28
28
|
if (length === 0) return ''
|
|
29
29
|
|
|
30
|
+
const ZERO = alphabet[0]
|
|
30
31
|
let zeros = 0
|
|
31
32
|
while (zeros < length && arr[zeros] === 0) zeros++
|
|
32
33
|
|
|
@@ -120,18 +121,20 @@ export function toBase58(arr) {
|
|
|
120
121
|
return ZERO.repeat(zeros) + out
|
|
121
122
|
}
|
|
122
123
|
|
|
123
|
-
|
|
124
|
-
export function fromBase58(str, format = 'uint8') {
|
|
124
|
+
function fromBase58core(str, alphabet, codes, format = 'uint8') {
|
|
125
125
|
if (typeof str !== 'string') throw new TypeError('Input is not a string')
|
|
126
126
|
const length = str.length
|
|
127
127
|
if (length === 0) return typedView(new Uint8Array(), format)
|
|
128
128
|
|
|
129
|
+
const zeroC = codes[0]
|
|
129
130
|
let zeros = 0
|
|
130
131
|
while (zeros < length && str.charCodeAt(zeros) === zeroC) zeros++
|
|
131
132
|
|
|
133
|
+
let fromMap = fromMaps.get(alphabet)
|
|
132
134
|
if (!fromMap) {
|
|
133
135
|
fromMap = new Int8Array(256).fill(-1)
|
|
134
136
|
for (let i = 0; i < 58; i++) fromMap[alphabet[i].charCodeAt(0)] = i
|
|
137
|
+
fromMaps.set(alphabet, fromMap)
|
|
135
138
|
}
|
|
136
139
|
|
|
137
140
|
const size = zeros + (((length - zeros + 1) * 3) >> 2) // 3/4 rounded up, larger than ~0.73 coef to fit everything
|
|
@@ -210,3 +213,8 @@ export function fromBase58(str, format = 'uint8') {
|
|
|
210
213
|
|
|
211
214
|
return typedView(res.slice(at - zeros), format) // slice is faster for small sizes than subarray
|
|
212
215
|
}
|
|
216
|
+
|
|
217
|
+
export const toBase58 = (arr) => toBase58core(arr, alphabet58, codes58)
|
|
218
|
+
export const fromBase58 = (str, format) => fromBase58core(str, alphabet58, codes58, format)
|
|
219
|
+
export const toBase58xrp = (arr) => toBase58core(arr, alphabetXRP, codesXRP)
|
|
220
|
+
export const fromBase58xrp = (str, format) => fromBase58core(str, alphabetXRP, codesXRP, format)
|
package/fallback/_utils.js
CHANGED
|
@@ -1,22 +1,30 @@
|
|
|
1
1
|
const { Buffer, TextEncoder, TextDecoder } = globalThis
|
|
2
2
|
const haveNativeBuffer = Buffer && !Buffer.TYPED_ARRAY_SUPPORT
|
|
3
|
-
|
|
3
|
+
export const nativeBuffer = haveNativeBuffer ? Buffer : null
|
|
4
|
+
export const isHermes = Boolean(globalThis.HermesInternal)
|
|
5
|
+
export const isDeno = Boolean(globalThis.Deno)
|
|
6
|
+
export const isLE = new Uint8Array(Uint16Array.of(258).buffer)[0] === 2
|
|
7
|
+
|
|
8
|
+
let isNative = (x) => {
|
|
9
|
+
if (!x) return false
|
|
10
|
+
if (haveNativeBuffer) return true // we consider Node.js TextDecoder/TextEncoder native
|
|
11
|
+
const s = `${x}`
|
|
12
|
+
// See https://github.com/facebook/hermes/pull/1855#issuecomment-3659386410
|
|
13
|
+
return s.includes('[native code]') || s.includes(`[bytecode]`) // Static Hermes has [bytecode] for contrib, which includes TextEncoder/TextDecoder
|
|
14
|
+
}
|
|
15
|
+
|
|
4
16
|
if (!haveNativeBuffer && isNative(() => {})) isNative = () => false // e.g. XS, we don't want false positives
|
|
5
17
|
|
|
6
18
|
export const nativeEncoder = isNative(TextEncoder) ? new TextEncoder() : null
|
|
7
19
|
export const nativeDecoder = isNative(TextDecoder)
|
|
8
20
|
? new TextDecoder('utf-8', { ignoreBOM: true })
|
|
9
21
|
: null
|
|
10
|
-
export const nativeBuffer = haveNativeBuffer ? Buffer : null
|
|
11
|
-
export const isHermes = Boolean(globalThis.HermesInternal)
|
|
12
|
-
export const isDeno = Boolean(globalThis.Deno)
|
|
13
|
-
export const isLE = new Uint8Array(Uint16Array.of(258).buffer)[0] === 2
|
|
14
22
|
|
|
15
23
|
// Actually windows-1252, compatible with ascii and latin1 decoding
|
|
16
24
|
// Beware that on non-latin1, i.e. on windows-1252, this is broken in ~all Node.js versions released
|
|
17
25
|
// in 2025 due to a regression, so we call it Latin1 as it's usable only for that
|
|
18
26
|
let nativeDecoderLatin1impl = null
|
|
19
|
-
if (
|
|
27
|
+
if (nativeDecoder) {
|
|
20
28
|
// Not all barebone engines with TextDecoder support something except utf-8, detect
|
|
21
29
|
try {
|
|
22
30
|
nativeDecoderLatin1impl = new TextDecoder('latin1', { ignoreBOM: true })
|
package/fallback/encoding.js
CHANGED
|
@@ -51,10 +51,7 @@ const fromSource = (x) => {
|
|
|
51
51
|
if (x instanceof Uint8Array) return x
|
|
52
52
|
if (x instanceof ArrayBuffer) return new Uint8Array(x)
|
|
53
53
|
if (ArrayBuffer.isView(x)) return new Uint8Array(x.buffer, x.byteOffset, x.byteLength)
|
|
54
|
-
if (globalThis.SharedArrayBuffer && x instanceof
|
|
55
|
-
return new Uint8Array(x.buffer, x.byteOffset, x.byteLength)
|
|
56
|
-
}
|
|
57
|
-
|
|
54
|
+
if (globalThis.SharedArrayBuffer && x instanceof SharedArrayBuffer) return new Uint8Array(x)
|
|
58
55
|
throw new TypeError('Argument must be a SharedArrayBuffer, ArrayBuffer or ArrayBufferView')
|
|
59
56
|
}
|
|
60
57
|
|
|
@@ -265,15 +262,28 @@ export function legacyHookDecode(input, fallbackEncoding) {
|
|
|
265
262
|
const bomEncoding = getBOMEncoding(u8)
|
|
266
263
|
if (bomEncoding) u8 = u8.subarray(bomEncoding === 'utf-8' ? 3 : 2)
|
|
267
264
|
const enc = bomEncoding ?? fallbackEncoding ?? 'utf-8' // "the byte order mark is more authoritative than anything else"
|
|
265
|
+
|
|
268
266
|
if (enc === 'utf-8') return utf8toStringLoose(u8)
|
|
269
|
-
if (enc === 'utf-16le'
|
|
270
|
-
|
|
271
|
-
|
|
267
|
+
if (enc === 'utf-16le' || enc === 'utf-16be') {
|
|
268
|
+
let suffix = ''
|
|
269
|
+
if (u8.byteLength % 2 !== 0) {
|
|
270
|
+
suffix = replacementChar
|
|
271
|
+
u8 = u8.subarray(0, -1)
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return utf16toStringLoose(u8, enc === 'utf-16le' ? 'uint8-le' : 'uint8-be') + suffix
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (!Object.hasOwn(labels, enc)) throw new RangeError(E_ENCODING)
|
|
272
278
|
|
|
273
279
|
if (multibyteSet.has(enc)) {
|
|
274
280
|
if (!createMultibyteDecoder) throw new Error(E_MULTI)
|
|
275
281
|
return createMultibyteDecoder(enc, true)(u8)
|
|
276
282
|
}
|
|
277
283
|
|
|
284
|
+
// https://encoding.spec.whatwg.org/#replacement-decoder
|
|
285
|
+
// On non-streaming non-fatal case, it just replaces any non-empty input with a single replacement char
|
|
286
|
+
if (enc === 'replacement') return input.byteLength > 0 ? replacementChar : ''
|
|
287
|
+
|
|
278
288
|
return createSinglebyteDecoder(enc, true)(u8)
|
|
279
289
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/bytes",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.11",
|
|
4
4
|
"description": "Various operations on Uint8Array data",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"lint": "eslint .",
|
|
@@ -132,6 +132,7 @@
|
|
|
132
132
|
"@types/node": "^22.13.0",
|
|
133
133
|
"base-x": "^5.0.1",
|
|
134
134
|
"base32.js": "^0.1.0",
|
|
135
|
+
"base58-js": "^3.0.3",
|
|
135
136
|
"base64-js": "^1.5.1",
|
|
136
137
|
"bech32": "^2.0.0",
|
|
137
138
|
"bs58": "^6.0.0",
|