@layerzerolabs/chain-utils 0.2.68 → 0.2.70
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/package.json +12 -9
- package/.turbo/turbo-build.log +0 -42
- package/.turbo/turbo-lint.log +0 -8
- package/.turbo/turbo-test.log +0 -23
- package/src/addressParser.test.ts +0 -795
- package/src/addressParser.ts +0 -651
- package/src/index.ts +0 -1
- package/tsconfig.json +0 -20
- package/tsup.config.ts +0 -8
|
@@ -1,795 +0,0 @@
|
|
|
1
|
-
import * as bs58 from 'bs58';
|
|
2
|
-
import { describe, expect, it } from 'vitest';
|
|
3
|
-
|
|
4
|
-
import type { HexString, NormalizedHexString } from '@layerzerolabs/common-chain-model';
|
|
5
|
-
import { NORMALIZED_HEX_ZERO, normalizeHex } from '@layerzerolabs/common-chain-model';
|
|
6
|
-
import { bytesToHexPrefixed, hexToBytes, hexZeroPad } from '@layerzerolabs/common-encoding-utils';
|
|
7
|
-
import { ChainName } from '@layerzerolabs/layerzero-definitions';
|
|
8
|
-
|
|
9
|
-
import { addressParser } from './addressParser';
|
|
10
|
-
|
|
11
|
-
// Test data generators
|
|
12
|
-
const randomBytes = (length: number): Uint8Array => {
|
|
13
|
-
const bytes = new Uint8Array(length);
|
|
14
|
-
for (let i = 0; i < length; i++) {
|
|
15
|
-
bytes[i] = Math.floor(Math.random() * 256);
|
|
16
|
-
}
|
|
17
|
-
return bytes;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
const randomHex = (byteLength: number): NormalizedHexString => {
|
|
21
|
-
return normalizeHex(bytesToHexPrefixed(randomBytes(byteLength)));
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const runPropertyTest = <T>(fn: () => T, iterations = 100): void => {
|
|
25
|
-
for (let i = 0; i < iterations; i++) {
|
|
26
|
-
fn();
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
describe('addressParser - hex/EVM chains', () => {
|
|
31
|
-
const evmChains = [ChainName.ETHEREUM, ChainName.AVALANCHE, ChainName.BSC, ChainName.POLYGON];
|
|
32
|
-
|
|
33
|
-
evmChains.forEach((chain) => {
|
|
34
|
-
describe(chain, () => {
|
|
35
|
-
const parser = addressParser(chain);
|
|
36
|
-
|
|
37
|
-
it('maintains roundtrip invariant: hex -> native -> hex', () => {
|
|
38
|
-
runPropertyTest(() => {
|
|
39
|
-
const input = randomHex(20);
|
|
40
|
-
const native = parser.normalizedToNative(input);
|
|
41
|
-
const back = parser.nativeToNormalized(native);
|
|
42
|
-
expect(back).toBe(input);
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it('maintains byte representation consistency', () => {
|
|
47
|
-
runPropertyTest(() => {
|
|
48
|
-
const input = randomHex(20);
|
|
49
|
-
const nativeStr = parser.normalizedToNativeString(input);
|
|
50
|
-
const bytesFromHex = hexToBytes(nativeStr);
|
|
51
|
-
const nativeBytes = parser.nativeToBytes(nativeStr);
|
|
52
|
-
|
|
53
|
-
expect(nativeBytes).toEqual(bytesFromHex);
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it('correctly pads addresses', () => {
|
|
58
|
-
runPropertyTest(() => {
|
|
59
|
-
const byteLength = Math.floor(Math.random() * 20) + 1; // 1-20 bytes
|
|
60
|
-
const input = randomHex(byteLength);
|
|
61
|
-
const native = parser.normalizedToNative(input);
|
|
62
|
-
expect(native.nativeAddress.length).toBe(42); // Always 20 bytes padded
|
|
63
|
-
expect(native.chainName).toBe(chain);
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
it('normalizedToBytes32Hex pads correctly', () => {
|
|
70
|
-
runPropertyTest(() => {
|
|
71
|
-
const byteLength = Math.floor(Math.random() * 32) + 1; // 1-32 bytes
|
|
72
|
-
const input = randomHex(byteLength);
|
|
73
|
-
const padded = addressParser(ChainName.ETHEREUM).normalizedToBytes32Hex(input);
|
|
74
|
-
expect(padded.length).toBe(66); // 32 bytes -> 64 hex chars + 0x
|
|
75
|
-
expect(padded).toBe(hexZeroPad(input as any, 32));
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('handles edge cases', () => {
|
|
80
|
-
const parser = addressParser(ChainName.ETHEREUM);
|
|
81
|
-
|
|
82
|
-
// Empty address
|
|
83
|
-
const empty = normalizeHex('0x');
|
|
84
|
-
expect(parser.normalizedToNative(empty).nativeAddress.length).toBe(42);
|
|
85
|
-
|
|
86
|
-
// Maximum value
|
|
87
|
-
const max = normalizeHex(('0x' + 'ff'.repeat(20)) as any);
|
|
88
|
-
expect(parser.nativeToNormalized(parser.normalizedToNative(max))).toBe(max);
|
|
89
|
-
|
|
90
|
-
// Single byte
|
|
91
|
-
const single = normalizeHex('0x01');
|
|
92
|
-
expect(parser.normalizedToNative(single).nativeAddress).toBe(hexZeroPad('0x01', 20));
|
|
93
|
-
});
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
describe('addressParser - base58 chains (Solana)', () => {
|
|
97
|
-
const parser = addressParser(ChainName.SOLANA);
|
|
98
|
-
|
|
99
|
-
it('maintains roundtrip invariant: hex -> base58 -> hex', () => {
|
|
100
|
-
runPropertyTest(() => {
|
|
101
|
-
const byteLength = Math.floor(Math.random() * 32) + 1; // 1-32 bytes
|
|
102
|
-
const input = randomHex(byteLength);
|
|
103
|
-
const native = parser.normalizedToNative(input);
|
|
104
|
-
const back = parser.nativeToNormalized(native);
|
|
105
|
-
expect(back).toBe(input);
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it('maintains base58 encoding consistency', () => {
|
|
110
|
-
runPropertyTest(() => {
|
|
111
|
-
const input = randomHex(32);
|
|
112
|
-
const nativeStr = parser.normalizedToNativeString(input);
|
|
113
|
-
const expectedBase58 = bs58.encode(hexToBytes(input as any));
|
|
114
|
-
expect(nativeStr).toBe(expectedBase58);
|
|
115
|
-
|
|
116
|
-
// Verify bytes consistency
|
|
117
|
-
const nativeBytes = parser.nativeToBytes(nativeStr);
|
|
118
|
-
expect(nativeBytes).toEqual(bs58.decode(expectedBase58));
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
it('correctly handles 32-byte padding', () => {
|
|
123
|
-
runPropertyTest(() => {
|
|
124
|
-
const byteLength = Math.floor(Math.random() * 32) + 1;
|
|
125
|
-
const input = randomHex(byteLength);
|
|
126
|
-
const native = parser.normalizedToNativeString(input);
|
|
127
|
-
const padded = parser.nativeToBytes32Hex(native);
|
|
128
|
-
expect(padded.length).toBe(66);
|
|
129
|
-
|
|
130
|
-
// Verify padding preserves original value
|
|
131
|
-
expect(parser.nativeToNormalized(native)).toBe(
|
|
132
|
-
normalizeHex(bytesToHexPrefixed(hexToBytes(input as any))),
|
|
133
|
-
);
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
it('handles edge cases', () => {
|
|
138
|
-
// Single byte
|
|
139
|
-
const single = normalizeHex('0x01');
|
|
140
|
-
const singleNative = parser.normalizedToNative(single);
|
|
141
|
-
expect(parser.nativeToNormalized(singleNative)).toBe(single);
|
|
142
|
-
|
|
143
|
-
// Empty (though typically invalid for Solana)
|
|
144
|
-
const empty = normalizeHex('0x');
|
|
145
|
-
expect(() => parser.normalizedToNative(empty)).not.toThrow();
|
|
146
|
-
|
|
147
|
-
// 32 bytes (typical Solana address length)
|
|
148
|
-
const full32 = randomHex(32);
|
|
149
|
-
const native32 = parser.normalizedToNative(full32);
|
|
150
|
-
expect(parser.nativeToNormalized(native32)).toBe(full32);
|
|
151
|
-
});
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
describe('addressParser - chain validation', () => {
|
|
155
|
-
it('validates chain names for nativeToBytes32Hex', () => {
|
|
156
|
-
const evmParser = addressParser(ChainName.ETHEREUM);
|
|
157
|
-
const solanaParser = addressParser(ChainName.SOLANA);
|
|
158
|
-
|
|
159
|
-
const evmAddress = evmParser.normalizedToNative(randomHex(20));
|
|
160
|
-
const solanaAddress = solanaParser.normalizedToNative(randomHex(32));
|
|
161
|
-
|
|
162
|
-
// nativeTo32BytesHex validates chain names for NativeAddress objects
|
|
163
|
-
expect(() => solanaParser.nativeToBytes32Hex(evmAddress as any)).toThrow(/Cannot convert/);
|
|
164
|
-
expect(() => evmParser.nativeToBytes32Hex(solanaAddress as any)).toThrow(/Cannot convert/);
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
it('accepts string addresses without validation', () => {
|
|
168
|
-
const parser = addressParser(ChainName.ETHEREUM);
|
|
169
|
-
const randomAddress = '0x' + 'ab'.repeat(20);
|
|
170
|
-
|
|
171
|
-
// String addresses bypass chain validation for all methods
|
|
172
|
-
const result = parser.nativeToNormalized(randomAddress as any);
|
|
173
|
-
expect(result).toBe(normalizeHex(randomAddress as any));
|
|
174
|
-
|
|
175
|
-
const padded = parser.nativeToBytes32Hex(randomAddress as any)!;
|
|
176
|
-
expect(padded.length).toBe(66);
|
|
177
|
-
|
|
178
|
-
const bytes = parser.nativeToBytes(randomAddress as any);
|
|
179
|
-
expect(bytes).toEqual(hexToBytes(randomAddress));
|
|
180
|
-
});
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
describe('addressParser - TON', () => {
|
|
184
|
-
const parser = addressParser(ChainName.TON);
|
|
185
|
-
|
|
186
|
-
it('maintains roundtrip invariant: hex -> ton address -> hex', () => {
|
|
187
|
-
runPropertyTest(() => {
|
|
188
|
-
// TON addresses are typically 32 bytes (256 bits)
|
|
189
|
-
const byteLength = Math.floor(Math.random() * 32) + 1;
|
|
190
|
-
const input = randomHex(byteLength);
|
|
191
|
-
const native = parser.normalizedToNative(input);
|
|
192
|
-
const back = parser.nativeToNormalized(native);
|
|
193
|
-
|
|
194
|
-
expect(input).toBe(back);
|
|
195
|
-
});
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
it('correctly handles TON address format', () => {
|
|
199
|
-
runPropertyTest(() => {
|
|
200
|
-
const input = randomHex(32);
|
|
201
|
-
const native = parser.normalizedToNative(input);
|
|
202
|
-
|
|
203
|
-
// TON addresses should have the correct chain name
|
|
204
|
-
expect(native.chainName).toBe(ChainName.TON);
|
|
205
|
-
|
|
206
|
-
// Should be a valid TON address string
|
|
207
|
-
expect(typeof native.nativeAddress).toBe('string');
|
|
208
|
-
expect(native.nativeAddress.length).toBeGreaterThan(0);
|
|
209
|
-
});
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
it('maintains byte representation consistency', () => {
|
|
213
|
-
runPropertyTest(() => {
|
|
214
|
-
const input = randomHex(32);
|
|
215
|
-
const nativeStr = parser.normalizedToNativeString(input);
|
|
216
|
-
const nativeBytes = parser.nativeToBytes(nativeStr);
|
|
217
|
-
|
|
218
|
-
// Both should produce valid byte arrays
|
|
219
|
-
expect(nativeBytes).toBeInstanceOf(Uint8Array);
|
|
220
|
-
|
|
221
|
-
// Converting back should preserve the value
|
|
222
|
-
const backFromBytes = parser.nativeToNormalized(parser.normalizedToNative(input));
|
|
223
|
-
expect(backFromBytes).toBe(input);
|
|
224
|
-
});
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
it('correctly handles 32-byte padding', () => {
|
|
228
|
-
runPropertyTest(() => {
|
|
229
|
-
const byteLength = Math.floor(Math.random() * 32) + 1;
|
|
230
|
-
const input = randomHex(byteLength);
|
|
231
|
-
const native = parser.normalizedToNativeString(input);
|
|
232
|
-
const padded = parser.nativeToBytes32Hex(native)!;
|
|
233
|
-
|
|
234
|
-
expect(padded.length).toBe(66); // 32 bytes -> 64 hex chars + 0x
|
|
235
|
-
|
|
236
|
-
// Verify the numeric value is preserved
|
|
237
|
-
const paddedBigInt = BigInt(padded);
|
|
238
|
-
const inputBigInt = BigInt(input as any);
|
|
239
|
-
expect(paddedBigInt).toBe(inputBigInt);
|
|
240
|
-
});
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
it('handles edge cases', () => {
|
|
244
|
-
// Zero address
|
|
245
|
-
const zero = normalizeHex('0x0');
|
|
246
|
-
const zeroNative = parser.normalizedToNative(zero);
|
|
247
|
-
expect(() => parser.nativeToNormalized(zeroNative)).not.toThrow();
|
|
248
|
-
|
|
249
|
-
// Large values
|
|
250
|
-
const large = normalizeHex(('0x' + 'ff'.repeat(32)) as any);
|
|
251
|
-
const largeNative = parser.normalizedToNative(large);
|
|
252
|
-
const largeBack = parser.nativeToNormalized(largeNative);
|
|
253
|
-
expect(BigInt(largeBack as any)).toBe(BigInt(large as any));
|
|
254
|
-
|
|
255
|
-
// Single byte
|
|
256
|
-
const single = normalizeHex('0x01');
|
|
257
|
-
const singleNative = parser.normalizedToNative(single);
|
|
258
|
-
const singleBack = parser.nativeToNormalized(singleNative);
|
|
259
|
-
expect(BigInt(singleBack as any)).toBe(1n);
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
it('validates native addresses', () => {
|
|
263
|
-
const validAddress = parser.normalizedToNative(randomHex(32));
|
|
264
|
-
expect(parser.validateNative(validAddress.nativeAddress)).toBe(true);
|
|
265
|
-
|
|
266
|
-
// Invalid addresses should return false
|
|
267
|
-
expect(parser.validateNative('invalid-ton-address')).toBe(false);
|
|
268
|
-
});
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
describe('addressParser - Stellar', () => {
|
|
272
|
-
const parser = addressParser(ChainName.STELLAR);
|
|
273
|
-
|
|
274
|
-
// Valid test addresses from SEP-0023 specification
|
|
275
|
-
const validTestAddresses = {
|
|
276
|
-
// Account address (G...)
|
|
277
|
-
account: 'GA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVSGZ',
|
|
278
|
-
// Contract address (C...)
|
|
279
|
-
contract: 'CA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJUWDA',
|
|
280
|
-
// Muxed address (M...)
|
|
281
|
-
muxed: 'MA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJUAAAAAAAAAAAACJUQ',
|
|
282
|
-
// Liquidity pool address (L...)
|
|
283
|
-
liquidityPool: 'LA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJUPJN',
|
|
284
|
-
// Claimable balance address (B...)
|
|
285
|
-
claimableBalance: 'BAAD6DBUX6J22DMZOHIEZTEQ64CVCHEDRKWZONFEUL5Q26QD7R76RGR4TU',
|
|
286
|
-
// Signed payload (P...)
|
|
287
|
-
signedPayload:
|
|
288
|
-
'PA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJUAAAAAQACAQDAQCQMBYIBEFAWDANBYHRAEISCMKBKFQXDAMRUGY4DUPB6IBZGM',
|
|
289
|
-
};
|
|
290
|
-
|
|
291
|
-
describe('roundtrip conversions', () => {
|
|
292
|
-
it('maintains roundtrip invariant for account addresses (G...)', () => {
|
|
293
|
-
const stellarAddress = validTestAddresses.account;
|
|
294
|
-
const normalized = parser.nativeToNormalized(stellarAddress as any);
|
|
295
|
-
const native = parser.normalizedToNative(normalized)!;
|
|
296
|
-
|
|
297
|
-
expect(native.nativeAddress).toBe(stellarAddress);
|
|
298
|
-
expect(native.chainName).toBe(ChainName.STELLAR);
|
|
299
|
-
});
|
|
300
|
-
|
|
301
|
-
it('maintains roundtrip invariant for contract addresses (C...)', () => {
|
|
302
|
-
const stellarAddress = validTestAddresses.contract;
|
|
303
|
-
const normalized = parser.nativeToNormalized(stellarAddress as any);
|
|
304
|
-
const native = parser.normalizedToNative(normalized)!;
|
|
305
|
-
|
|
306
|
-
expect(native.nativeAddress).toBe(stellarAddress);
|
|
307
|
-
});
|
|
308
|
-
|
|
309
|
-
it('maintains roundtrip invariant for muxed addresses (M...)', () => {
|
|
310
|
-
const stellarAddress = validTestAddresses.muxed;
|
|
311
|
-
const normalized = parser.nativeToNormalized(stellarAddress as any);
|
|
312
|
-
const native = parser.normalizedToNative(normalized)!;
|
|
313
|
-
|
|
314
|
-
expect(native.nativeAddress).toBe(stellarAddress);
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
it('maintains roundtrip invariant for liquidity pool addresses (L...)', () => {
|
|
318
|
-
const stellarAddress = validTestAddresses.liquidityPool;
|
|
319
|
-
const normalized = parser.nativeToNormalized(stellarAddress as any);
|
|
320
|
-
const native = parser.normalizedToNative(normalized)!;
|
|
321
|
-
|
|
322
|
-
expect(native.nativeAddress).toBe(stellarAddress);
|
|
323
|
-
});
|
|
324
|
-
|
|
325
|
-
it('maintains roundtrip invariant for claimable balance addresses (B...)', () => {
|
|
326
|
-
const stellarAddress = validTestAddresses.claimableBalance;
|
|
327
|
-
const normalized = parser.nativeToNormalized(stellarAddress as any);
|
|
328
|
-
const native = parser.normalizedToNative(normalized)!;
|
|
329
|
-
|
|
330
|
-
expect(native.nativeAddress).toBe(stellarAddress);
|
|
331
|
-
});
|
|
332
|
-
|
|
333
|
-
it('maintains roundtrip invariant for signed payload (P...)', () => {
|
|
334
|
-
const stellarAddress = validTestAddresses.signedPayload;
|
|
335
|
-
const normalized = parser.nativeToNormalized(stellarAddress as any);
|
|
336
|
-
const native = parser.normalizedToNative(normalized)!;
|
|
337
|
-
|
|
338
|
-
expect(native.nativeAddress).toBe(stellarAddress);
|
|
339
|
-
});
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
describe('validation', () => {
|
|
343
|
-
it('validates all valid Stellar address types', () => {
|
|
344
|
-
expect(parser.validateNative(validTestAddresses.account)).toBe(true);
|
|
345
|
-
expect(parser.validateNative(validTestAddresses.contract)).toBe(true);
|
|
346
|
-
expect(parser.validateNative(validTestAddresses.muxed)).toBe(true);
|
|
347
|
-
expect(parser.validateNative(validTestAddresses.liquidityPool)).toBe(true);
|
|
348
|
-
expect(parser.validateNative(validTestAddresses.claimableBalance)).toBe(true);
|
|
349
|
-
expect(parser.validateNative(validTestAddresses.signedPayload)).toBe(true);
|
|
350
|
-
});
|
|
351
|
-
|
|
352
|
-
it('rejects invalid Stellar addresses', () => {
|
|
353
|
-
// Invalid addresses from SEP-0023 test cases
|
|
354
|
-
const invalidAddresses = [
|
|
355
|
-
'GAAAAAAAACGC6', // Invalid length
|
|
356
|
-
'GA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVSGZA', // Invalid length
|
|
357
|
-
'G47QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVP2I', // Invalid algorithm
|
|
358
|
-
'invalid-stellar-address',
|
|
359
|
-
'',
|
|
360
|
-
'0x1234567890abcdef', // EVM address
|
|
361
|
-
];
|
|
362
|
-
|
|
363
|
-
invalidAddresses.forEach((addr) => {
|
|
364
|
-
expect(parser.validateNative(addr)).toBe(false);
|
|
365
|
-
});
|
|
366
|
-
});
|
|
367
|
-
|
|
368
|
-
it('rejects undefined addresses', () => {
|
|
369
|
-
expect(parser.validateNative(undefined)).toBe(false);
|
|
370
|
-
});
|
|
371
|
-
});
|
|
372
|
-
|
|
373
|
-
describe('ASCII encoding/decoding', () => {
|
|
374
|
-
it('converts Stellar address to UTF-8 bytes correctly', () => {
|
|
375
|
-
const stellarAddress = validTestAddresses.account;
|
|
376
|
-
const bytes = parser.nativeToBytes(stellarAddress as any)!;
|
|
377
|
-
|
|
378
|
-
// Verify it's UTF-8 encoded ASCII
|
|
379
|
-
const decoder = new TextDecoder();
|
|
380
|
-
const decoded = decoder.decode(bytes);
|
|
381
|
-
expect(decoded).toBe(stellarAddress);
|
|
382
|
-
});
|
|
383
|
-
|
|
384
|
-
it('preserves address length in byte representation', () => {
|
|
385
|
-
// Account address (56 chars)
|
|
386
|
-
const accountBytes = parser.nativeToBytes(validTestAddresses.account as any)!;
|
|
387
|
-
expect(accountBytes.length).toBe(56);
|
|
388
|
-
|
|
389
|
-
// Muxed address (69 chars)
|
|
390
|
-
const muxedBytes = parser.nativeToBytes(validTestAddresses.muxed as any)!;
|
|
391
|
-
expect(muxedBytes.length).toBe(69);
|
|
392
|
-
|
|
393
|
-
// Signed payload (variable length)
|
|
394
|
-
const payloadBytes = parser.nativeToBytes(validTestAddresses.signedPayload as any)!;
|
|
395
|
-
expect(payloadBytes.length).toBeGreaterThan(56);
|
|
396
|
-
});
|
|
397
|
-
|
|
398
|
-
it('normalizedToNativeString returns the address string', () => {
|
|
399
|
-
const stellarAddress = validTestAddresses.account;
|
|
400
|
-
const normalized = parser.nativeToNormalized(stellarAddress as any);
|
|
401
|
-
const nativeString = parser.normalizedToNativeString(normalized);
|
|
402
|
-
|
|
403
|
-
expect(nativeString).toBe(stellarAddress);
|
|
404
|
-
});
|
|
405
|
-
});
|
|
406
|
-
|
|
407
|
-
describe('parseNative', () => {
|
|
408
|
-
it('parses valid Stellar addresses', () => {
|
|
409
|
-
const stellarAddress = validTestAddresses.account;
|
|
410
|
-
const normalized = parser.parseNative(stellarAddress as any);
|
|
411
|
-
|
|
412
|
-
// Should return normalized hex representation
|
|
413
|
-
expect(normalized).toMatch(/^0x[0-9a-f]+$/);
|
|
414
|
-
});
|
|
415
|
-
|
|
416
|
-
it('throws on invalid addresses', () => {
|
|
417
|
-
expect(() => parser.parseNative('invalid-stellar-address' as any)).toThrow(
|
|
418
|
-
/Cannot convert/,
|
|
419
|
-
);
|
|
420
|
-
});
|
|
421
|
-
|
|
422
|
-
it('parseNativeToUnpaddedHex returns hex string', () => {
|
|
423
|
-
const stellarAddress = validTestAddresses.account;
|
|
424
|
-
const hex = parser.parseNativeToUnpaddedHex(stellarAddress as any);
|
|
425
|
-
|
|
426
|
-
expect(hex).toMatch(/^0x[0-9a-f]+$/);
|
|
427
|
-
expect(hex).toBe(parser.parseNative(stellarAddress as any));
|
|
428
|
-
});
|
|
429
|
-
});
|
|
430
|
-
|
|
431
|
-
describe('bytes32 operations', () => {
|
|
432
|
-
it('decodes account address (G...) to 32 bytes', () => {
|
|
433
|
-
const stellarAddress = validTestAddresses.account;
|
|
434
|
-
const bytes32Hex = parser.nativeToBytes32Hex(stellarAddress as any)!;
|
|
435
|
-
const bytes32 = parser.nativeToBytes32(stellarAddress as any)!;
|
|
436
|
-
|
|
437
|
-
// Should be 32 bytes (64 hex chars + 0x)
|
|
438
|
-
expect(bytes32Hex.length).toBe(66);
|
|
439
|
-
expect(bytes32Hex).toMatch(/^0x[0-9a-f]{64}$/);
|
|
440
|
-
|
|
441
|
-
// Bytes should be 32 bytes
|
|
442
|
-
expect(bytes32.length).toBe(32);
|
|
443
|
-
|
|
444
|
-
// Both methods should produce consistent results
|
|
445
|
-
expect(bytesToHexPrefixed(bytes32)).toBe(bytes32Hex);
|
|
446
|
-
});
|
|
447
|
-
|
|
448
|
-
it('decodes contract address (C...) to 32 bytes', () => {
|
|
449
|
-
const stellarAddress = validTestAddresses.contract;
|
|
450
|
-
const bytes32Hex = parser.nativeToBytes32Hex(stellarAddress as any)!;
|
|
451
|
-
const bytes32 = parser.nativeToBytes32(stellarAddress as any)!;
|
|
452
|
-
|
|
453
|
-
expect(bytes32Hex.length).toBe(66);
|
|
454
|
-
expect(bytes32.length).toBe(32);
|
|
455
|
-
expect(bytesToHexPrefixed(bytes32)).toBe(bytes32Hex);
|
|
456
|
-
});
|
|
457
|
-
|
|
458
|
-
it('decodes liquidity pool address (L...) to 32 bytes', () => {
|
|
459
|
-
const stellarAddress = validTestAddresses.liquidityPool;
|
|
460
|
-
const bytes32Hex = parser.nativeToBytes32Hex(stellarAddress as any)!;
|
|
461
|
-
const bytes32 = parser.nativeToBytes32(stellarAddress as any)!;
|
|
462
|
-
|
|
463
|
-
expect(bytes32Hex.length).toBe(66);
|
|
464
|
-
expect(bytes32.length).toBe(32);
|
|
465
|
-
expect(bytesToHexPrefixed(bytes32)).toBe(bytes32Hex);
|
|
466
|
-
});
|
|
467
|
-
|
|
468
|
-
it('decodes claimable balance address (B...) to 32 bytes (skipping version byte)', () => {
|
|
469
|
-
const stellarAddress = validTestAddresses.claimableBalance;
|
|
470
|
-
const bytes32Hex = parser.nativeToBytes32Hex(stellarAddress as any)!;
|
|
471
|
-
const bytes32 = parser.nativeToBytes32(stellarAddress as any)!;
|
|
472
|
-
|
|
473
|
-
// Should be 32 bytes (64 hex chars + 0x)
|
|
474
|
-
expect(bytes32Hex.length).toBe(66);
|
|
475
|
-
expect(bytes32Hex).toMatch(/^0x[0-9a-f]{64}$/);
|
|
476
|
-
|
|
477
|
-
// Bytes should be 32 bytes (the hash, without the version byte)
|
|
478
|
-
expect(bytes32.length).toBe(32);
|
|
479
|
-
|
|
480
|
-
// Both methods should produce consistent results
|
|
481
|
-
expect(bytesToHexPrefixed(bytes32)).toBe(bytes32Hex);
|
|
482
|
-
});
|
|
483
|
-
|
|
484
|
-
it('throws error for muxed address (M...) - not 32 bytes', () => {
|
|
485
|
-
const stellarAddress = validTestAddresses.muxed;
|
|
486
|
-
|
|
487
|
-
expect(() => parser.nativeToBytes32Hex(stellarAddress as any)).toThrow(
|
|
488
|
-
/nativeToBytes32 is not supported for Stellar muxed addresses/,
|
|
489
|
-
);
|
|
490
|
-
expect(() => parser.nativeToBytes32(stellarAddress as any)).toThrow(
|
|
491
|
-
/nativeToBytes32 is not supported for Stellar muxed addresses/,
|
|
492
|
-
);
|
|
493
|
-
});
|
|
494
|
-
|
|
495
|
-
it('throws error for signed payload (P...) - variable length', () => {
|
|
496
|
-
const stellarAddress = validTestAddresses.signedPayload;
|
|
497
|
-
|
|
498
|
-
expect(() => parser.nativeToBytes32Hex(stellarAddress as any)).toThrow(
|
|
499
|
-
/nativeToBytes32 is not supported for Stellar signed payload addresses/,
|
|
500
|
-
);
|
|
501
|
-
expect(() => parser.nativeToBytes32(stellarAddress as any)).toThrow(
|
|
502
|
-
/nativeToBytes32 is not supported for Stellar signed payload addresses/,
|
|
503
|
-
);
|
|
504
|
-
});
|
|
505
|
-
|
|
506
|
-
it('returns undefined for undefined input', () => {
|
|
507
|
-
expect(parser.nativeToBytes32Hex(undefined as any)).toBeUndefined();
|
|
508
|
-
expect(parser.nativeToBytes32(undefined as any)).toBeUndefined();
|
|
509
|
-
});
|
|
510
|
-
|
|
511
|
-
it('decodes all supported address types to 32 bytes', () => {
|
|
512
|
-
// Account (G), contract (C), liquidity pool (L), and claimable balance (B) addresses can be converted to 32 bytes
|
|
513
|
-
const accountBytes = parser.nativeToBytes32(validTestAddresses.account as any)!;
|
|
514
|
-
const contractBytes = parser.nativeToBytes32(validTestAddresses.contract as any)!;
|
|
515
|
-
const poolBytes = parser.nativeToBytes32(validTestAddresses.liquidityPool as any)!;
|
|
516
|
-
const balanceBytes = parser.nativeToBytes32(
|
|
517
|
-
validTestAddresses.claimableBalance as any,
|
|
518
|
-
)!;
|
|
519
|
-
|
|
520
|
-
// All should be exactly 32 bytes
|
|
521
|
-
expect(accountBytes.length).toBe(32);
|
|
522
|
-
expect(contractBytes.length).toBe(32);
|
|
523
|
-
expect(poolBytes.length).toBe(32);
|
|
524
|
-
expect(balanceBytes.length).toBe(32);
|
|
525
|
-
|
|
526
|
-
// Should produce consistent hex conversions
|
|
527
|
-
const accountHex = parser.nativeToBytes32Hex(validTestAddresses.account as any)!;
|
|
528
|
-
const contractHex = parser.nativeToBytes32Hex(validTestAddresses.contract as any)!;
|
|
529
|
-
const poolHex = parser.nativeToBytes32Hex(validTestAddresses.liquidityPool as any)!;
|
|
530
|
-
const balanceHex = parser.nativeToBytes32Hex(
|
|
531
|
-
validTestAddresses.claimableBalance as any,
|
|
532
|
-
)!;
|
|
533
|
-
|
|
534
|
-
expect(bytesToHexPrefixed(accountBytes)).toBe(accountHex);
|
|
535
|
-
expect(bytesToHexPrefixed(contractBytes)).toBe(contractHex);
|
|
536
|
-
expect(bytesToHexPrefixed(poolBytes)).toBe(poolHex);
|
|
537
|
-
expect(bytesToHexPrefixed(balanceBytes)).toBe(balanceHex);
|
|
538
|
-
});
|
|
539
|
-
|
|
540
|
-
it('handles ChainNativeAddress objects for bytes32 operations', () => {
|
|
541
|
-
const nativeObj = {
|
|
542
|
-
chainName: ChainName.STELLAR,
|
|
543
|
-
nativeAddress: validTestAddresses.account,
|
|
544
|
-
};
|
|
545
|
-
|
|
546
|
-
const bytes32Hex = parser.nativeToBytes32Hex(nativeObj as any)!;
|
|
547
|
-
const bytes32 = parser.nativeToBytes32(nativeObj as any)!;
|
|
548
|
-
|
|
549
|
-
expect(bytes32Hex.length).toBe(66);
|
|
550
|
-
expect(bytes32.length).toBe(32);
|
|
551
|
-
});
|
|
552
|
-
});
|
|
553
|
-
|
|
554
|
-
describe('normalizedToBytes32 operations', () => {
|
|
555
|
-
it('produces same result as nativeToBytes32Hex for contract address (C...)', () => {
|
|
556
|
-
const stellarAddress = validTestAddresses.contract;
|
|
557
|
-
const normalized = parser.nativeToNormalized(stellarAddress as any);
|
|
558
|
-
|
|
559
|
-
const fromNative = parser.nativeToBytes32Hex(stellarAddress as any)!;
|
|
560
|
-
const fromNormalized = parser.normalizedToBytes32Hex(normalized)!;
|
|
561
|
-
|
|
562
|
-
expect(fromNormalized).toBe(fromNative);
|
|
563
|
-
});
|
|
564
|
-
|
|
565
|
-
it('normalizedToBytes32 returns correct Uint8Array', () => {
|
|
566
|
-
const stellarAddress = validTestAddresses.account;
|
|
567
|
-
const normalized = parser.nativeToNormalized(stellarAddress as any);
|
|
568
|
-
|
|
569
|
-
const bytes32Hex = parser.normalizedToBytes32Hex(normalized)!;
|
|
570
|
-
const bytes32 = parser.normalizedToBytes32(normalized)!;
|
|
571
|
-
|
|
572
|
-
expect(bytes32.length).toBe(32);
|
|
573
|
-
expect(bytesToHexPrefixed(bytes32)).toBe(bytes32Hex);
|
|
574
|
-
});
|
|
575
|
-
});
|
|
576
|
-
|
|
577
|
-
describe('address type preservation', () => {
|
|
578
|
-
it('preserves address type information through conversion', () => {
|
|
579
|
-
const addresses = [
|
|
580
|
-
{ addr: validTestAddresses.account, prefix: 'G' },
|
|
581
|
-
{ addr: validTestAddresses.contract, prefix: 'C' },
|
|
582
|
-
{ addr: validTestAddresses.muxed, prefix: 'M' },
|
|
583
|
-
{ addr: validTestAddresses.liquidityPool, prefix: 'L' },
|
|
584
|
-
{ addr: validTestAddresses.claimableBalance, prefix: 'B' },
|
|
585
|
-
{ addr: validTestAddresses.signedPayload, prefix: 'P' },
|
|
586
|
-
];
|
|
587
|
-
|
|
588
|
-
addresses.forEach(({ addr, prefix }) => {
|
|
589
|
-
const normalized = parser.nativeToNormalized(addr as any);
|
|
590
|
-
const recovered = parser.normalizedToNative(normalized)!;
|
|
591
|
-
|
|
592
|
-
// Should preserve the prefix indicating address type
|
|
593
|
-
expect(recovered.nativeAddress.startsWith(prefix)).toBe(true);
|
|
594
|
-
expect(recovered.nativeAddress).toBe(addr);
|
|
595
|
-
});
|
|
596
|
-
});
|
|
597
|
-
});
|
|
598
|
-
|
|
599
|
-
describe('edge cases', () => {
|
|
600
|
-
it('handles ChainNativeAddress objects', () => {
|
|
601
|
-
const nativeObj = {
|
|
602
|
-
chainName: ChainName.STELLAR,
|
|
603
|
-
nativeAddress: validTestAddresses.account,
|
|
604
|
-
};
|
|
605
|
-
|
|
606
|
-
const normalized = parser.nativeToNormalized(nativeObj as any);
|
|
607
|
-
expect(normalized).toMatch(/^0x[0-9a-f]+$/);
|
|
608
|
-
});
|
|
609
|
-
|
|
610
|
-
it('returns undefined for undefined inputs', () => {
|
|
611
|
-
expect(parser.normalizedToNative(undefined as any)).toBeUndefined();
|
|
612
|
-
expect(parser.normalizedToNativeString(undefined as any)).toBeUndefined();
|
|
613
|
-
expect(parser.nativeToNormalized(undefined as any)).toBeUndefined();
|
|
614
|
-
expect(parser.nativeToBytes(undefined as any)).toBeUndefined();
|
|
615
|
-
});
|
|
616
|
-
|
|
617
|
-
it('handles different address lengths correctly', () => {
|
|
618
|
-
// 56-char addresses
|
|
619
|
-
const short = validTestAddresses.account;
|
|
620
|
-
const shortBytes = parser.nativeToBytes(short as any)!;
|
|
621
|
-
expect(shortBytes.length).toBe(56);
|
|
622
|
-
|
|
623
|
-
// 69-char addresses (muxed)
|
|
624
|
-
const medium = validTestAddresses.muxed;
|
|
625
|
-
const mediumBytes = parser.nativeToBytes(medium as any)!;
|
|
626
|
-
expect(mediumBytes.length).toBe(69);
|
|
627
|
-
|
|
628
|
-
// Variable-length (signed payload)
|
|
629
|
-
const long = validTestAddresses.signedPayload;
|
|
630
|
-
const longBytes = parser.nativeToBytes(long as any)!;
|
|
631
|
-
expect(longBytes.length).toBeGreaterThan(69);
|
|
632
|
-
});
|
|
633
|
-
});
|
|
634
|
-
|
|
635
|
-
describe('encoding type', () => {
|
|
636
|
-
it('has STELLAR encoding type', () => {
|
|
637
|
-
expect(parser.encoding).toBe('stellar');
|
|
638
|
-
});
|
|
639
|
-
});
|
|
640
|
-
});
|
|
641
|
-
|
|
642
|
-
describe('addressParser - normalizedToBytes32Hex (cross-chain)', () => {
|
|
643
|
-
const testCases: { name: string; chainName: ChainName; nativeAddr: string }[] = [
|
|
644
|
-
{
|
|
645
|
-
name: 'EVM (Ethereum)',
|
|
646
|
-
chainName: ChainName.ETHEREUM,
|
|
647
|
-
nativeAddr: '0x1234567890abcdef1234567890abcdef12345678',
|
|
648
|
-
},
|
|
649
|
-
{
|
|
650
|
-
name: 'Solana',
|
|
651
|
-
chainName: ChainName.SOLANA,
|
|
652
|
-
nativeAddr: 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
|
|
653
|
-
},
|
|
654
|
-
{
|
|
655
|
-
name: 'TON',
|
|
656
|
-
chainName: ChainName.TON,
|
|
657
|
-
nativeAddr: 'EQDtFpEwcFAEcRe5mLVh2N6C0x-_hJEM7W61_JLnSF74p4q2',
|
|
658
|
-
},
|
|
659
|
-
{
|
|
660
|
-
name: 'Stellar',
|
|
661
|
-
chainName: ChainName.STELLAR,
|
|
662
|
-
nativeAddr: 'GAAZI4TCR3TY5OJHCTJC2A4QSY6CJWJH5IAJTGKIN2ER7LBNVKOCCWN7',
|
|
663
|
-
},
|
|
664
|
-
{
|
|
665
|
-
name: 'Aptos',
|
|
666
|
-
chainName: ChainName.APTOS,
|
|
667
|
-
nativeAddr: '0x1',
|
|
668
|
-
},
|
|
669
|
-
{
|
|
670
|
-
name: 'Starknet',
|
|
671
|
-
chainName: ChainName.STARKNET,
|
|
672
|
-
nativeAddr: '0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',
|
|
673
|
-
},
|
|
674
|
-
{
|
|
675
|
-
name: 'Initia',
|
|
676
|
-
chainName: ChainName.INITIA,
|
|
677
|
-
nativeAddr: '0x1',
|
|
678
|
-
},
|
|
679
|
-
];
|
|
680
|
-
|
|
681
|
-
testCases.forEach(({ name, chainName, nativeAddr }) => {
|
|
682
|
-
it(`${name}: normalizedToBytes32Hex(normalized) === nativeToBytes32Hex(native)`, () => {
|
|
683
|
-
const p = addressParser(chainName);
|
|
684
|
-
const normalized = p.nativeToNormalized(nativeAddr as any);
|
|
685
|
-
|
|
686
|
-
const fromNormalized = p.normalizedToBytes32Hex(normalized)!;
|
|
687
|
-
const fromNative = p.nativeToBytes32Hex(nativeAddr as any)!;
|
|
688
|
-
|
|
689
|
-
expect(fromNormalized).toBe(fromNative);
|
|
690
|
-
expect(fromNormalized.length).toBe(66);
|
|
691
|
-
expect(fromNormalized).toMatch(/^0x[0-9a-f]{64}$/);
|
|
692
|
-
});
|
|
693
|
-
});
|
|
694
|
-
|
|
695
|
-
it('normalizedToBytes32Hex is consistent across chain parsers for ≤32 byte hex', () => {
|
|
696
|
-
const evmParser = addressParser(ChainName.ETHEREUM);
|
|
697
|
-
const solanaParser = addressParser(ChainName.SOLANA);
|
|
698
|
-
const normalized = normalizeHex('0x1234567890abcdef1234567890abcdef12345678');
|
|
699
|
-
expect(evmParser.normalizedToBytes32Hex(normalized)).toBe(
|
|
700
|
-
solanaParser.normalizedToBytes32Hex(normalized),
|
|
701
|
-
);
|
|
702
|
-
});
|
|
703
|
-
|
|
704
|
-
it('normalizedToBytes32 returns correct Uint8Array', () => {
|
|
705
|
-
const p = addressParser(ChainName.ETHEREUM);
|
|
706
|
-
const normalized = normalizeHex('0x1234567890abcdef1234567890abcdef12345678');
|
|
707
|
-
const bytes32Hex = p.normalizedToBytes32Hex(normalized)!;
|
|
708
|
-
const bytes32 = p.normalizedToBytes32(normalized)!;
|
|
709
|
-
expect(bytes32.length).toBe(32);
|
|
710
|
-
expect(bytesToHexPrefixed(bytes32)).toBe(bytes32Hex);
|
|
711
|
-
});
|
|
712
|
-
|
|
713
|
-
it('returns undefined for undefined input', () => {
|
|
714
|
-
const p = addressParser(ChainName.ETHEREUM);
|
|
715
|
-
expect(p.normalizedToBytes32Hex(undefined as any)).toBeUndefined();
|
|
716
|
-
expect(p.normalizedToBytes32(undefined as any)).toBeUndefined();
|
|
717
|
-
});
|
|
718
|
-
});
|
|
719
|
-
|
|
720
|
-
describe('addressParser - bytes32ToNormalized', () => {
|
|
721
|
-
const ZERO_BYTES32 = ('0x' + '00'.repeat(32)) as HexString;
|
|
722
|
-
|
|
723
|
-
describe('round-trip: bytes32ToNormalized(nativeToBytes32Hex(native)) === nativeToNormalized(native)', () => {
|
|
724
|
-
const cases = [
|
|
725
|
-
{
|
|
726
|
-
name: 'EVM',
|
|
727
|
-
chainName: ChainName.ETHEREUM,
|
|
728
|
-
native: '0x1234567890abcdef1234567890abcdef12345678',
|
|
729
|
-
},
|
|
730
|
-
{
|
|
731
|
-
name: 'Solana',
|
|
732
|
-
chainName: ChainName.SOLANA,
|
|
733
|
-
native: 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
|
|
734
|
-
},
|
|
735
|
-
{
|
|
736
|
-
name: 'TON',
|
|
737
|
-
chainName: ChainName.TON,
|
|
738
|
-
native: 'EQDtFpEwcFAEcRe5mLVh2N6C0x-_hJEM7W61_JLnSF74p4q2',
|
|
739
|
-
},
|
|
740
|
-
{ name: 'Initia', chainName: ChainName.INITIA, native: '0x1' },
|
|
741
|
-
{
|
|
742
|
-
name: 'Starknet',
|
|
743
|
-
chainName: ChainName.STARKNET,
|
|
744
|
-
native: '0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',
|
|
745
|
-
},
|
|
746
|
-
{ name: 'Aptos', chainName: ChainName.APTOS, native: '0x1' },
|
|
747
|
-
];
|
|
748
|
-
|
|
749
|
-
cases.forEach(({ name, chainName, native }) => {
|
|
750
|
-
it(`${name}: round-trip`, () => {
|
|
751
|
-
const p = addressParser(chainName);
|
|
752
|
-
const normalized = p.nativeToNormalized(native as any);
|
|
753
|
-
const bytes32Hex = p.nativeToBytes32Hex(native as any)!;
|
|
754
|
-
expect(p.bytes32ToNormalized(bytes32Hex)).toBe(normalized);
|
|
755
|
-
});
|
|
756
|
-
});
|
|
757
|
-
|
|
758
|
-
it('Stellar contract: round-trip', () => {
|
|
759
|
-
const p = addressParser(ChainName.STELLAR);
|
|
760
|
-
const contractAddr = 'CA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJUWDA';
|
|
761
|
-
const normalized = p.nativeToNormalized(contractAddr as any);
|
|
762
|
-
const bytes32Hex = p.nativeToBytes32Hex(contractAddr as any)!;
|
|
763
|
-
expect(p.bytes32ToNormalized(bytes32Hex)).toBe(normalized);
|
|
764
|
-
});
|
|
765
|
-
});
|
|
766
|
-
|
|
767
|
-
it('undefined input returns undefined', () => {
|
|
768
|
-
const p = addressParser(ChainName.ETHEREUM);
|
|
769
|
-
expect(p.bytes32ToNormalized(undefined as any)).toBeUndefined();
|
|
770
|
-
});
|
|
771
|
-
|
|
772
|
-
it('non-Stellar: bytes32ToNative === normalizeHex for same input', () => {
|
|
773
|
-
const chains = [ChainName.ETHEREUM, ChainName.SOLANA, ChainName.TON, ChainName.STARKNET];
|
|
774
|
-
const bytes32 =
|
|
775
|
-
'0x0000000000000000000000001234567890abcdef1234567890abcdef12345678' as HexString;
|
|
776
|
-
chains.forEach((chainName) => {
|
|
777
|
-
expect(addressParser(chainName).bytes32ToNormalized(bytes32)).toBe(
|
|
778
|
-
normalizeHex(bytes32),
|
|
779
|
-
);
|
|
780
|
-
});
|
|
781
|
-
});
|
|
782
|
-
|
|
783
|
-
it('zero bytes32: EVM returns NORMALIZED_HEX_ZERO', () => {
|
|
784
|
-
const p = addressParser(ChainName.ETHEREUM);
|
|
785
|
-
expect(p.bytes32ToNormalized(ZERO_BYTES32)).toBe(NORMALIZED_HEX_ZERO);
|
|
786
|
-
});
|
|
787
|
-
|
|
788
|
-
it('zero bytes32: Stellar returns C-address for zero contract ID (not undefined)', () => {
|
|
789
|
-
const p = addressParser(ChainName.STELLAR);
|
|
790
|
-
const result = p.bytes32ToNormalized(ZERO_BYTES32);
|
|
791
|
-
// Should be a valid C-address string encoded as UTF-8 normalized hex, not undefined
|
|
792
|
-
expect(result).toBeDefined();
|
|
793
|
-
expect(result).not.toBe(NORMALIZED_HEX_ZERO);
|
|
794
|
-
});
|
|
795
|
-
});
|