ox 1.8.9 → 1.8.10
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/CHANGELOG.md +18 -0
- package/dist/core/AbiEvent.d.ts.map +1 -1
- package/dist/core/AbiEvent.js +32 -10
- package/dist/core/AbiEvent.js.map +1 -1
- package/dist/core/Hex.d.ts +13 -1
- package/dist/core/Hex.d.ts.map +1 -1
- package/dist/core/Hex.js +5 -3
- package/dist/core/Hex.js.map +1 -1
- package/dist/core/RpcTransport.d.ts.map +1 -1
- package/dist/core/RpcTransport.js +21 -14
- package/dist/core/RpcTransport.js.map +1 -1
- package/dist/core/Signature.d.ts +1 -1
- package/dist/core/Signature.d.ts.map +1 -1
- package/dist/core/Signature.js +3 -2
- package/dist/core/Signature.js.map +1 -1
- package/dist/core/TypedData.js +1 -1
- package/dist/core/TypedData.js.map +1 -1
- package/dist/core/internal/abiItem.d.ts.map +1 -1
- package/dist/core/internal/abiItem.js +45 -19
- package/dist/core/internal/abiItem.js.map +1 -1
- package/package.json +1 -1
- package/src/core/AbiEvent.ts +61 -22
- package/src/core/Hex.ts +17 -3
- package/src/core/RpcTransport.ts +20 -16
- package/src/core/Signature.ts +5 -2
- package/src/core/TypedData.ts +1 -1
- package/src/core/_test/AbiEvent.test.ts +232 -1
- package/src/core/_test/AbiItem.test.ts +342 -0
- package/src/core/_test/Hex.test.ts +31 -0
- package/src/core/_test/RpcTransport.test.ts +48 -0
- package/src/core/_test/Signature.test.ts +42 -1
- package/src/core/_test/TypedData.test.ts +29 -0
- package/src/core/internal/abiItem.ts +59 -25
- package/src/version.ts +1 -1
|
@@ -242,6 +242,54 @@ describe('fromHttp', () => {
|
|
|
242
242
|
|
|
243
243
|
await server.close()
|
|
244
244
|
})
|
|
245
|
+
|
|
246
|
+
test('behavior: caller signal without `AbortSignal.any`', async () => {
|
|
247
|
+
const server = await createHttpServer((_, res) => {
|
|
248
|
+
res.end(JSON.stringify({ id: 0, jsonrpc: '2.0', result: 'wagmi' }))
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
const transport = RpcTransport.fromHttp(server.url, {
|
|
252
|
+
timeout: 50,
|
|
253
|
+
fetchOptions: {
|
|
254
|
+
signal: new AbortController().signal,
|
|
255
|
+
},
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
const descriptor = Object.getOwnPropertyDescriptor(AbortSignal, 'any')!
|
|
259
|
+
Object.defineProperty(AbortSignal, 'any', {
|
|
260
|
+
configurable: true,
|
|
261
|
+
value: undefined,
|
|
262
|
+
})
|
|
263
|
+
try {
|
|
264
|
+
await expect(
|
|
265
|
+
transport.request({ method: 'eth_accounts' }),
|
|
266
|
+
).resolves.toMatchInlineSnapshot(`"wagmi"`)
|
|
267
|
+
} finally {
|
|
268
|
+
Object.defineProperty(AbortSignal, 'any', descriptor)
|
|
269
|
+
await server.close()
|
|
270
|
+
}
|
|
271
|
+
})
|
|
272
|
+
|
|
273
|
+
test('behavior: timeout covers a response body that stalls after its headers', async () => {
|
|
274
|
+
const server = await createHttpServer(async (_, res) => {
|
|
275
|
+
res.writeHead(200, { 'Content-Type': 'application/json' })
|
|
276
|
+
res.write('{"id":0,"jsonrpc":"2.0",')
|
|
277
|
+
await setTimeout(200)
|
|
278
|
+
res.end('"result":"wagmi"}')
|
|
279
|
+
})
|
|
280
|
+
|
|
281
|
+
const transport = RpcTransport.fromHttp(server.url, {
|
|
282
|
+
timeout: 50,
|
|
283
|
+
})
|
|
284
|
+
|
|
285
|
+
await expect(() =>
|
|
286
|
+
transport.request({ method: 'eth_accounts' }),
|
|
287
|
+
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
288
|
+
`[Promise.TimeoutError: Operation timed out.]`,
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
await server.close()
|
|
292
|
+
})
|
|
245
293
|
})
|
|
246
294
|
|
|
247
295
|
test('exports', () => {
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Bytes,
|
|
3
|
+
Hex,
|
|
4
|
+
Secp256k1,
|
|
5
|
+
Signature,
|
|
6
|
+
Solidity,
|
|
7
|
+
TxEnvelopeEip1559,
|
|
8
|
+
} from 'ox'
|
|
2
9
|
import { describe, expect, test } from 'vp/test'
|
|
3
10
|
|
|
4
11
|
describe('assert', () => {
|
|
@@ -488,6 +495,40 @@ describe('serialize', () => {
|
|
|
488
495
|
`"0x6e100a352ec6ad1b70802290e18aeed190704973570f3b8ed42cb9808e2ea6bf4a90a229a244495b41890987806fcbd2d5d23fc0dbe5f5256c2613c039d76db8"`,
|
|
489
496
|
)
|
|
490
497
|
})
|
|
498
|
+
|
|
499
|
+
test('behavior: `r` and `s` shorter than 32 bytes', () => {
|
|
500
|
+
const signature = Signature.toHex({
|
|
501
|
+
r: '0x1cdb3cbf94c7059e0e16d2ba046daef144d77384995a66f379194b638fc07e',
|
|
502
|
+
s: '0xc3d1ccd2c334876b9f8ef0ba3725c30dd5e1def225df36efa406d881ed610b',
|
|
503
|
+
yParity: 1,
|
|
504
|
+
})
|
|
505
|
+
expect(signature).toMatchInlineSnapshot(
|
|
506
|
+
`"0x001cdb3cbf94c7059e0e16d2ba046daef144d77384995a66f379194b638fc07e00c3d1ccd2c334876b9f8ef0ba3725c30dd5e1def225df36efa406d881ed610b1c"`,
|
|
507
|
+
)
|
|
508
|
+
expect(Hex.size(signature)).toMatchInlineSnapshot(`65`)
|
|
509
|
+
})
|
|
510
|
+
|
|
511
|
+
test('behavior: short `s` round-trips through recovery', () => {
|
|
512
|
+
const payload =
|
|
513
|
+
'0x44caf484852acee09d52b2802dba26d3c8ab3d28c7abcc1398b87898115633ec'
|
|
514
|
+
const signature = Signature.fromHex(
|
|
515
|
+
Signature.toHex({
|
|
516
|
+
r: '0xdf1cdb3cbf94c7059e0e16d2ba046daef144d77384995a66f379194b638fc07e',
|
|
517
|
+
s: '0xc3d1ccd2c334876b9f8ef0ba3725c30dd5e1def225df36efa406d881ed610b',
|
|
518
|
+
yParity: 1,
|
|
519
|
+
}),
|
|
520
|
+
)
|
|
521
|
+
expect(signature).toMatchInlineSnapshot(`
|
|
522
|
+
{
|
|
523
|
+
"r": "0xdf1cdb3cbf94c7059e0e16d2ba046daef144d77384995a66f379194b638fc07e",
|
|
524
|
+
"s": "0x00c3d1ccd2c334876b9f8ef0ba3725c30dd5e1def225df36efa406d881ed610b",
|
|
525
|
+
"yParity": 1,
|
|
526
|
+
}
|
|
527
|
+
`)
|
|
528
|
+
expect(
|
|
529
|
+
Secp256k1.recoverAddress({ payload, signature }),
|
|
530
|
+
).toMatchInlineSnapshot(`"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"`)
|
|
531
|
+
})
|
|
491
532
|
})
|
|
492
533
|
|
|
493
534
|
describe('toBytes', () => {
|
|
@@ -791,6 +791,23 @@ describe('extractEip712DomainTypes', () => {
|
|
|
791
791
|
test('empty', () => {
|
|
792
792
|
expect(TypedData.extractEip712DomainTypes({})).toMatchInlineSnapshot('[]')
|
|
793
793
|
})
|
|
794
|
+
|
|
795
|
+
test('empty version', () => {
|
|
796
|
+
expect(
|
|
797
|
+
TypedData.extractEip712DomainTypes({ name: 'Ether Mail', version: '' }),
|
|
798
|
+
).toMatchInlineSnapshot(`
|
|
799
|
+
[
|
|
800
|
+
{
|
|
801
|
+
"name": "name",
|
|
802
|
+
"type": "string",
|
|
803
|
+
},
|
|
804
|
+
{
|
|
805
|
+
"name": "version",
|
|
806
|
+
"type": "string",
|
|
807
|
+
},
|
|
808
|
+
]
|
|
809
|
+
`)
|
|
810
|
+
})
|
|
794
811
|
})
|
|
795
812
|
|
|
796
813
|
describe('getSignPayload', () => {
|
|
@@ -849,6 +866,18 @@ describe('getSignPayload', () => {
|
|
|
849
866
|
)
|
|
850
867
|
})
|
|
851
868
|
|
|
869
|
+
test('domain: empty version', () => {
|
|
870
|
+
expect(
|
|
871
|
+
TypedData.getSignPayload({
|
|
872
|
+
...typedData.complex,
|
|
873
|
+
domain: { name: 'Ether Mail', version: '' },
|
|
874
|
+
primaryType: 'Mail',
|
|
875
|
+
}),
|
|
876
|
+
).toMatchInlineSnapshot(
|
|
877
|
+
`"0xa437e12ee2fd4391429d9714be617951b7e69fb61dc520ad6fb8230d03b7508c"`,
|
|
878
|
+
)
|
|
879
|
+
})
|
|
880
|
+
|
|
852
881
|
test('domain: bigint chainId produces same hash as number chainId', () => {
|
|
853
882
|
const typedDataWithNumberChainId = {
|
|
854
883
|
domain: {
|
|
@@ -4,6 +4,7 @@ import type * as AbiItem from '../AbiItem.js'
|
|
|
4
4
|
import type * as AbiParameters from '../AbiParameters.js'
|
|
5
5
|
import * as Address from '../Address.js'
|
|
6
6
|
import * as Errors from '../Errors.js'
|
|
7
|
+
import { getArrayComponents } from './abiParameters.js'
|
|
7
8
|
import type {
|
|
8
9
|
Compute,
|
|
9
10
|
IsNever,
|
|
@@ -570,20 +571,6 @@ const integerTypeRegex =
|
|
|
570
571
|
*/
|
|
571
572
|
const fixedBytesTypeRegex = /^bytes([1-9]|1[0-9]|2[0-9]|3[0-2])?$/
|
|
572
573
|
|
|
573
|
-
/**
|
|
574
|
-
* Fixed-length (`<type>[M]`) / dynamic (`<type>[]`) array regex.
|
|
575
|
-
*
|
|
576
|
-
* @internal
|
|
577
|
-
*/
|
|
578
|
-
const arrayTypeRegex = /[a-z]+[1-9]{0,3}(\[[0-9]{0,}\])+$/
|
|
579
|
-
|
|
580
|
-
/**
|
|
581
|
-
* Strips a single trailing `[...]` array suffix from a type.
|
|
582
|
-
*
|
|
583
|
-
* @internal
|
|
584
|
-
*/
|
|
585
|
-
const arraySuffixStripRegex = /(\[[0-9]{0,}\])$/
|
|
586
|
-
|
|
587
574
|
/** @internal */
|
|
588
575
|
export function isArgOfType(
|
|
589
576
|
arg: unknown,
|
|
@@ -604,9 +591,12 @@ export function isArgOfType(
|
|
|
604
591
|
if (abiParameterType === 'tuple' && 'components' in abiParameter)
|
|
605
592
|
return Object.values(abiParameter.components).every(
|
|
606
593
|
(component, index) => {
|
|
607
|
-
return
|
|
608
|
-
|
|
609
|
-
|
|
594
|
+
return (
|
|
595
|
+
argType === 'object' &&
|
|
596
|
+
isArgOfType(
|
|
597
|
+
getComponentValue(arg, component, index),
|
|
598
|
+
component as AbiParameters.Parameter,
|
|
599
|
+
)
|
|
610
600
|
)
|
|
611
601
|
},
|
|
612
602
|
)
|
|
@@ -617,14 +607,17 @@ export function isArgOfType(
|
|
|
617
607
|
if (fixedBytesTypeRegex.test(abiParameterType))
|
|
618
608
|
return argType === 'string' || arg instanceof Uint8Array
|
|
619
609
|
|
|
620
|
-
|
|
610
|
+
// Fixed-length (`<type>[M]`) and dynamic (`<type>[]`) arrays.
|
|
611
|
+
const arrayComponents = getArrayComponents(abiParameterType)
|
|
612
|
+
if (arrayComponents) {
|
|
613
|
+
const [length, type] = arrayComponents
|
|
621
614
|
return (
|
|
622
615
|
Array.isArray(arg) &&
|
|
616
|
+
(length === null || arg.length === length) &&
|
|
623
617
|
arg.every((x: unknown) =>
|
|
624
618
|
isArgOfType(x, {
|
|
625
619
|
...abiParameter,
|
|
626
|
-
|
|
627
|
-
type: abiParameterType.replace(arraySuffixStripRegex, ''),
|
|
620
|
+
type,
|
|
628
621
|
} as AbiParameters.Parameter),
|
|
629
622
|
)
|
|
630
623
|
)
|
|
@@ -649,19 +642,49 @@ export function getAmbiguousTypes(
|
|
|
649
642
|
parameterIndex++
|
|
650
643
|
) {
|
|
651
644
|
const sourceParameter = sourceParameters[parameterIndex]!
|
|
652
|
-
const targetParameter = targetParameters[parameterIndex]
|
|
645
|
+
const targetParameter = targetParameters[parameterIndex]
|
|
646
|
+
if (!targetParameter) continue
|
|
653
647
|
|
|
654
648
|
if (
|
|
655
649
|
sourceParameter.type === 'tuple' &&
|
|
656
650
|
targetParameter.type === 'tuple' &&
|
|
657
651
|
'components' in sourceParameter &&
|
|
658
652
|
'components' in targetParameter
|
|
659
|
-
)
|
|
660
|
-
|
|
653
|
+
) {
|
|
654
|
+
const value = args[parameterIndex]
|
|
655
|
+
const types = getAmbiguousTypes(
|
|
661
656
|
sourceParameter.components,
|
|
662
657
|
targetParameter.components,
|
|
663
|
-
(
|
|
658
|
+
sourceParameter.components.map((component, index) =>
|
|
659
|
+
getComponentValue(value, component, index),
|
|
660
|
+
),
|
|
661
|
+
)
|
|
662
|
+
if (types) return types
|
|
663
|
+
continue
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
const sourceArray = getArrayComponents(sourceParameter.type)
|
|
667
|
+
const targetArray = getArrayComponents(targetParameter.type)
|
|
668
|
+
if (sourceArray && targetArray) {
|
|
669
|
+
// Every item matches both element types, so the first item (or `undefined` for an empty array) decides.
|
|
670
|
+
const types = getAmbiguousTypes(
|
|
671
|
+
[
|
|
672
|
+
{
|
|
673
|
+
...sourceParameter,
|
|
674
|
+
type: sourceArray[1],
|
|
675
|
+
} as AbiParameters.Parameter,
|
|
676
|
+
],
|
|
677
|
+
[
|
|
678
|
+
{
|
|
679
|
+
...targetParameter,
|
|
680
|
+
type: targetArray[1],
|
|
681
|
+
} as AbiParameters.Parameter,
|
|
682
|
+
],
|
|
683
|
+
[(args[parameterIndex] as readonly unknown[] | undefined)?.[0]],
|
|
664
684
|
)
|
|
685
|
+
if (types) return types
|
|
686
|
+
continue
|
|
687
|
+
}
|
|
665
688
|
|
|
666
689
|
const sourceType = sourceParameter.type
|
|
667
690
|
const targetType = targetParameter.type
|
|
@@ -679,10 +702,21 @@ export function getAmbiguousTypes(
|
|
|
679
702
|
(sourceType === 'address' && targetType === 'bytes') ||
|
|
680
703
|
(sourceType === 'bytes' && targetType === 'address')
|
|
681
704
|
)
|
|
682
|
-
|
|
705
|
+
// An `undefined` value comes from an empty array, which matches both types.
|
|
706
|
+
ambiguous = arg === undefined || Address.validate(arg, { strict: false })
|
|
683
707
|
|
|
684
708
|
if (ambiguous) return [sourceType, targetType]
|
|
685
709
|
}
|
|
686
710
|
|
|
687
711
|
return
|
|
688
712
|
}
|
|
713
|
+
|
|
714
|
+
// Reads a tuple component's value by index from arrays and by name from objects, like `AbiParameters.encode`.
|
|
715
|
+
function getComponentValue(
|
|
716
|
+
arg: unknown,
|
|
717
|
+
component: AbiParameters.Parameter,
|
|
718
|
+
index: number,
|
|
719
|
+
): unknown {
|
|
720
|
+
if (Array.isArray(arg)) return arg[index]
|
|
721
|
+
return (arg as Record<string, unknown> | undefined)?.[component.name!]
|
|
722
|
+
}
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** @internal */
|
|
2
|
-
export const version = '1.8.
|
|
2
|
+
export const version = '1.8.10'
|