Skip to content

Commit 868d431

Browse files
committed
feat: handling for odd-length hex
1 parent f479c85 commit 868d431

18 files changed

+412
-411
lines changed

.changeset/ten-wombats-prove.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"ox": patch
3+
---
4+
5+
Added handling for odd-length hex values.

src/core/Bytes.ts

+2-4
Original file line numberDiff line numberDiff line change
@@ -230,15 +230,14 @@ fromBoolean.parseError = (error: unknown) =>
230230
export function fromHex(value: Hex.Hex, options: fromHex.Options = {}): Bytes {
231231
const { size } = options
232232

233-
if (value.length % 2) throw new Hex.InvalidLengthError(value)
234-
235233
let hex = value
236234
if (size) {
237235
internal_hex.assertSize(value, size)
238236
hex = Hex.padRight(value, size)
239237
}
240238

241-
const hexString = hex.slice(2) as string
239+
let hexString = hex.slice(2) as string
240+
if (hexString.length % 2) hexString = `0${hexString}`
242241

243242
const length = hexString.length / 2
244243
const bytes = new Uint8Array(length)
@@ -264,7 +263,6 @@ export declare namespace fromHex {
264263
type ErrorType =
265264
| internal_hex.assertSize.ErrorType
266265
| Hex.padRight.ErrorType
267-
| Hex.InvalidLengthError
268266
| Errors.GlobalErrorType
269267
}
270268

src/core/Hex.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ export function fromBoolean(
155155
value: boolean,
156156
options: fromBoolean.Options = {},
157157
): Hex {
158-
const hex: Hex = `0x0${Number(value)}`
158+
const hex: Hex = `0x${Number(value)}`
159159
if (typeof options.size === 'number') {
160160
internal.assertSize(hex, options.size)
161161
return padLeft(hex, options.size)
@@ -275,8 +275,7 @@ export function fromNumber(
275275
signed && value_ < 0 ? (1n << BigInt(size * 8)) + BigInt(value_) : value_
276276
).toString(16)
277277

278-
const hex =
279-
`0x${stringValue.length % 2 === 0 ? stringValue : `0${stringValue}`}` as Hex
278+
const hex = `0x${stringValue}` as Hex
280279
if (size) return padLeft(hex, size) as Hex
281280
return hex
282281
}

src/core/_test/Authorization.test.ts

+65-65
Original file line numberDiff line numberDiff line change
@@ -363,15 +363,15 @@ describe('toRpc', () => {
363363
yParity: 0,
364364
}),
365365
).toMatchInlineSnapshot(`
366-
{
367-
"address": "0x0000000000000000000000000000000000000000",
368-
"chainId": "0x01",
369-
"nonce": "0x01",
370-
"r": "0x635dc2033e60185bb36709c29c75d64ea51dfbd91c32ef4be198e4ceb169fb4d",
371-
"s": "0x50c2667ac4c771072746acfdcf1f1483336dcca8bd2df47cd83175dbe60f0540",
372-
"yParity": "0x0",
373-
}
374-
`)
366+
{
367+
"address": "0x0000000000000000000000000000000000000000",
368+
"chainId": "0x1",
369+
"nonce": "0x1",
370+
"r": "0x635dc2033e60185bb36709c29c75d64ea51dfbd91c32ef4be198e4ceb169fb4d",
371+
"s": "0x50c2667ac4c771072746acfdcf1f1483336dcca8bd2df47cd83175dbe60f0540",
372+
"yParity": "0x0",
373+
}
374+
`)
375375
})
376376
})
377377

@@ -389,17 +389,17 @@ describe('toRpcList', () => {
389389
},
390390
]),
391391
).toMatchInlineSnapshot(`
392-
[
393-
{
394-
"address": "0x0000000000000000000000000000000000000000",
395-
"chainId": "0x01",
396-
"nonce": "0x01",
397-
"r": "0x635dc2033e60185bb36709c29c75d64ea51dfbd91c32ef4be198e4ceb169fb4d",
398-
"s": "0x50c2667ac4c771072746acfdcf1f1483336dcca8bd2df47cd83175dbe60f0540",
399-
"yParity": "0x0",
400-
},
401-
]
402-
`)
392+
[
393+
{
394+
"address": "0x0000000000000000000000000000000000000000",
395+
"chainId": "0x1",
396+
"nonce": "0x1",
397+
"r": "0x635dc2033e60185bb36709c29c75d64ea51dfbd91c32ef4be198e4ceb169fb4d",
398+
"s": "0x50c2667ac4c771072746acfdcf1f1483336dcca8bd2df47cd83175dbe60f0540",
399+
"yParity": "0x0",
400+
},
401+
]
402+
`)
403403
})
404404
})
405405

@@ -413,12 +413,12 @@ describe('toTuple', () => {
413413
})
414414
const tuple = Authorization.toTuple(authorization)
415415
expect(tuple).toMatchInlineSnapshot(`
416-
[
417-
"0x01",
418-
"0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
419-
"0x28",
420-
]
421-
`)
416+
[
417+
"0x1",
418+
"0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
419+
"0x28",
420+
]
421+
`)
422422
}
423423

424424
{
@@ -432,15 +432,15 @@ describe('toTuple', () => {
432432
})
433433
const tuple = Authorization.toTuple(authorization)
434434
expect(tuple).toMatchInlineSnapshot(`
435-
[
436-
"0x01",
437-
"0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
438-
"0x28",
439-
"0x",
440-
"0x01",
441-
"0x02",
442-
]
443-
`)
435+
[
436+
"0x1",
437+
"0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
438+
"0x28",
439+
"0x",
440+
"0x01",
441+
"0x02",
442+
]
443+
`)
444444
}
445445

446446
{
@@ -484,19 +484,19 @@ describe('toTupleList', () => {
484484
authorization_2,
485485
])
486486
expect(tuple).toMatchInlineSnapshot(`
487-
[
488-
[
489-
"0x01",
490-
"0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
491-
"0x28",
492-
],
493487
[
494-
"0x03",
495-
"0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
496-
"0x14",
497-
],
498-
]
499-
`)
488+
[
489+
"0x1",
490+
"0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
491+
"0x28",
492+
],
493+
[
494+
"0x3",
495+
"0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
496+
"0x14",
497+
],
498+
]
499+
`)
500500
}
501501

502502
{
@@ -521,25 +521,25 @@ describe('toTupleList', () => {
521521
authorization_4,
522522
])
523523
expect(tuple).toMatchInlineSnapshot(`
524-
[
525524
[
526-
"0x05",
527-
"0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
528-
"0x2a",
529-
"0x",
530-
"0x01",
531-
"0x02",
532-
],
533-
[
534-
"0x02",
535-
"0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
536-
"0x2b",
537-
"0x",
538-
"0x04",
539-
"0x05",
540-
],
541-
]
542-
`)
525+
[
526+
"0x5",
527+
"0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
528+
"0x2a",
529+
"0x",
530+
"0x01",
531+
"0x02",
532+
],
533+
[
534+
"0x2",
535+
"0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
536+
"0x2b",
537+
"0x",
538+
"0x04",
539+
"0x05",
540+
],
541+
]
542+
`)
543543
}
544544
})
545545
})

src/core/_test/Block.test.ts

+20-20
Original file line numberDiff line numberDiff line change
@@ -521,13 +521,13 @@ describe('toRpc', () => {
521521
)
522522
expect(block).toMatchInlineSnapshot(`
523523
{
524-
"baseFeePerGas": "0x00",
525-
"blobGasUsed": "0x01",
524+
"baseFeePerGas": "0x0",
525+
"blobGasUsed": "0x1",
526526
"difficulty": "0x2d3a678cddba9b",
527-
"excessBlobGas": "0x02",
527+
"excessBlobGas": "0x2",
528528
"extraData": "0x",
529-
"gasLimit": "0x01c9c347",
530-
"gasUsed": "0x00",
529+
"gasLimit": "0x1c9c347",
530+
"gasUsed": "0x0",
531531
"hash": "0xebc3644804e4040c0a74c5a5bbbc6b46a71a5d4010fe0c92ebb2fdf4a43ea5dd",
532532
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
533533
"miner": "0x0000000000000000000000000000000000000000",
@@ -542,27 +542,27 @@ describe('toRpc', () => {
542542
"0x0000000000000000",
543543
],
544544
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
545-
"size": "0x0208",
545+
"size": "0x208",
546546
"stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
547547
"timestamp": "0x63198f6f",
548-
"totalDifficulty": "0x01",
548+
"totalDifficulty": "0x1",
549549
"transactions": [
550550
{
551551
"accessList": [],
552552
"blockHash": "0x0c3e51fc62e1dd7401c8884882755b72e1c5720d0b01c75443cdfa8a129d3fc9",
553-
"blockNumber": "0x012f2974",
554-
"chainId": "0x01",
553+
"blockNumber": "0x12f2974",
554+
"chainId": "0x1",
555555
"from": "0x0ff82acd0cd11bff58729e7dc9cdcdbe1fcf7a74",
556-
"gas": "0x0a87b4",
556+
"gas": "0xa87b4",
557557
"hash": "0x6c4e8a1e9484ad717ef42df12a6cb9655216b6a2f7420f52dc540ed952860fdb",
558558
"input": "0x030102553e9c493678d8606d6a5ba284643db2110df8230040150000000000000000000000daa0e9d3ba85490000006401ae78736cd615f374d3085123a210448e74fc6393c02aaa39b223fe8d0a0e5c4f27ead9083c756cc202e590f497df75e26b99774030e1592a27c3e54a91dffc8d8c7ad7df808906ea64992a25297e17000000000000000000000000cc3d76219d81b15491f32a217206fda8e0f4982a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ae78736cd615f374d3085123a210448e74fc6393000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000c5abae0c91f1ee00000000000000000000000000000000000000000000000000c9c9d12f33719d8a8000000000000000000000e647457cf40066434f0e00000000000000000000469be304682ad55c57aeb258f271eeebd9e81277e3b53955fcf42a134c0b947477322c96c6a6a2d43120b9f8a661ff8cee8b27a146962f39b377d71cff6eb12b00000000000000000000000000000000000000000000000000c5abae0c91f1eea80000e1000015000000000000000000000000000000000000d276d30606c1e400000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000010a553e9c493678d8606d6a5ba284643db2110df823000000c1000000540000005400000054000000540000002a0000000000000000fb2809a5314473e1165f6b58018e20ed8f07b840065e8a0000234c66434e4e0000b40cbbf4065e8a00b4fb2809a5314473e1165f6b58018e20ed8f07b840065e8a0000234c66434e4e0000b40cbbf4065e8a00b4fb2809a5314473e1165f6b58018e20ed8f07b84066434e36b09498030ae3416b66dc00007bf29735c20c566e5a0c00000c989d73cf0bd5f83b660000d18bd45f0b94f54a968f0000d61b892b2ad6249011850000a59ca88d5813e693528f0000299aad897099c9fc85ce000038d42b0ecf8a9f8ba9db7b0c989d73cf0bd5f83b660300000000000000000000000000000000000000000000",
559-
"maxFeePerGas": "0x0270e36628",
560-
"maxPriorityFeePerGas": "0x0270e36628",
559+
"maxFeePerGas": "0x270e36628",
560+
"maxPriorityFeePerGas": "0x270e36628",
561561
"nonce": "0x15e5",
562562
"r": "0x6b55b361fe0329871a1654ba2c6bf4174aa8cffaa69dc912e36f2b5a722ec9a3",
563563
"s": "0x37739460ab0ca1c2007b48d1442601ac1bae40957ceaf7212966f857af6fb8c9",
564564
"to": "0xd42b0ecf8a9f8ba9db7b0c989d73cf0bd5f83b66",
565-
"transactionIndex": "0x0c",
565+
"transactionIndex": "0xc",
566566
"type": "0x2",
567567
"v": "0x1b",
568568
"value": "0x15",
@@ -574,9 +574,9 @@ describe('toRpc', () => {
574574
"withdrawals": [
575575
{
576576
"address": "0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f",
577-
"amount": "0x011bfb57",
578-
"index": "0x02b3aa2e",
579-
"validatorIndex": "0x036318",
577+
"amount": "0x11bfb57",
578+
"index": "0x2b3aa2e",
579+
"validatorIndex": "0x36318",
580580
},
581581
],
582582
"withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
@@ -635,8 +635,8 @@ describe('toRpc', () => {
635635
"difficulty": undefined,
636636
"excessBlobGas": undefined,
637637
"extraData": "0x",
638-
"gasLimit": "0x00",
639-
"gasUsed": "0x00",
638+
"gasLimit": "0x0",
639+
"gasUsed": "0x0",
640640
"hash": null,
641641
"logsBloom": null,
642642
"miner": "0x0000000000000000000000000000000000000000",
@@ -651,9 +651,9 @@ describe('toRpc', () => {
651651
"0x0000000000000000",
652652
],
653653
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
654-
"size": "0x00",
654+
"size": "0x0",
655655
"stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
656-
"timestamp": "0x00",
656+
"timestamp": "0x0",
657657
"totalDifficulty": undefined,
658658
"transactions": [
659659
"0x6c4e8a1e9484ad717ef42df12a6cb9655216b6a2f7420f52dc540ed952860fdb",

src/core/_test/Bytes.test.ts

+9-10
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,15 @@ describe('fromHex', () => {
196196
97,
197197
]
198198
`)
199+
expect(Bytes.fromHex('0xabcde')).toMatchInlineSnapshot(
200+
`
201+
Uint8Array [
202+
10,
203+
188,
204+
222,
205+
]
206+
`,
207+
)
199208
expect(Bytes.fromHex('0x616263')).toMatchInlineSnapshot(
200209
`
201210
Uint8Array [
@@ -303,16 +312,6 @@ describe('fromHex', () => {
303312
`[BaseError: Invalid byte sequence ("gh" in "abcdefgh").]`,
304313
)
305314
})
306-
307-
test('error: invalid length', () => {
308-
expect(() => Bytes.fromHex('0xabcde')).toThrowErrorMatchingInlineSnapshot(
309-
`
310-
[Hex.InvalidLengthError: Hex value \`"0xabcde"\` is an odd length (5 nibbles).
311-
312-
It must be an even length.]
313-
`,
314-
)
315-
})
316315
})
317316

318317
describe('fromNumber', () => {

0 commit comments

Comments
 (0)