ox 0.9.3 → 0.9.5

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/core/AbiError.ts CHANGED
@@ -59,6 +59,23 @@ export function decode<
59
59
  * ```
60
60
  *
61
61
  * @example
62
+ * Or define the ABI and error name as parameters to {@link ox#AbiError.(decode:function)}:
63
+ *
64
+ * ```ts twoslash
65
+ * // @noErrors
66
+ * import { Abi, AbiError } from 'ox'
67
+ *
68
+ * const abi = Abi.from([...])
69
+ *
70
+ * const value = AbiError.decode(
71
+ * abi, // [!code hl]
72
+ * 'InvalidSignature', // [!code hl]
73
+ * '0x...'
74
+ * )
75
+ * // @log: [420n, 69n, 1]
76
+ * ```
77
+ *
78
+ * @example
62
79
  * You can pass the error `data` to the `name` property of {@link ox#AbiError.(fromAbi:function)} to extract and infer the error by its 4-byte selector:
63
80
  *
64
81
  * ```ts twoslash
@@ -139,17 +156,58 @@ export function decode<
139
156
  * @param options - Decoding options.
140
157
  * @returns The decoded error.
141
158
  */
142
- export function decode(
143
- abiError: AbiError,
159
+ export function decode<
160
+ const abi extends Abi.Abi | readonly unknown[],
161
+ name extends Name<abi>,
162
+ const args extends
163
+ | AbiItem_internal.ExtractArgs<abi, name>
164
+ | undefined = undefined,
165
+ as extends 'Object' | 'Array' = 'Array',
166
+ //
167
+ abiError extends AbiError = AbiItem.fromAbi.ReturnType<
168
+ abi,
169
+ name,
170
+ args,
171
+ AbiError
172
+ >,
173
+ allNames = Name<abi>,
174
+ >(
175
+ abi: abi | Abi.Abi | readonly unknown[],
176
+ name: Hex.Hex | (name extends allNames ? name : never),
144
177
  data: Hex.Hex,
145
- options?: decode.Options | undefined,
146
- ): unknown | readonly unknown[] | undefined
147
- /** @internal */
148
- export function decode(
149
- abiError: AbiError,
178
+ options?: decode.Options<as> | undefined,
179
+ ): decode.ReturnType<abiError, as>
180
+ export function decode<
181
+ const abiError extends AbiError,
182
+ as extends 'Object' | 'Array' = 'Array',
183
+ >(
184
+ abiError: abiError | AbiError,
150
185
  data: Hex.Hex,
151
- options: decode.Options = {},
186
+ options?: decode.Options<as> | undefined,
187
+ ): decode.ReturnType<abiError, as>
188
+ // eslint-disable-next-line jsdoc/require-jsdoc
189
+ export function decode(
190
+ ...parameters:
191
+ | [
192
+ abi: Abi.Abi | readonly unknown[],
193
+ name: Hex.Hex | string,
194
+ data: Hex.Hex,
195
+ options?: decode.Options | undefined,
196
+ ]
197
+ | [abiError: AbiError, data: Hex.Hex, options?: decode.Options | undefined]
152
198
  ): decode.ReturnType {
199
+ const [abiError, data, options = {}] = (() => {
200
+ if (Array.isArray(parameters[0])) {
201
+ const [abi, name, data, options] = parameters as [
202
+ Abi.Abi | readonly unknown[],
203
+ Hex.Hex | string,
204
+ Hex.Hex,
205
+ decode.Options | undefined,
206
+ ]
207
+ return [fromAbi(abi, name), data, options]
208
+ }
209
+ return parameters as [AbiError, Hex.Hex, decode.Options | undefined]
210
+ })()
153
211
  if (Hex.size(data) < 4) throw new AbiItem.InvalidSelectorSizeError({ data })
154
212
  if (abiError.inputs.length === 0) return undefined
155
213
 
@@ -255,10 +313,55 @@ export declare namespace decode {
255
313
  * @param args - Error arguments
256
314
  * @returns ABI-encoded error name and arguments
257
315
  */
316
+ export function encode<
317
+ const abi extends Abi.Abi | readonly unknown[],
318
+ name extends Name<abi>,
319
+ const args extends
320
+ | AbiItem_internal.ExtractArgs<abi, name>
321
+ | undefined = undefined,
322
+ //
323
+ abiError extends AbiError = AbiItem.fromAbi.ReturnType<
324
+ abi,
325
+ name,
326
+ args,
327
+ AbiError
328
+ >,
329
+ allNames = Name<abi>,
330
+ >(
331
+ abi: abi | Abi.Abi | readonly unknown[],
332
+ name: Hex.Hex | (name extends allNames ? name : never),
333
+ ...args: encode.Args<abiError>
334
+ ): encode.ReturnType
258
335
  export function encode<const abiError extends AbiError>(
259
336
  abiError: abiError,
260
337
  ...args: encode.Args<abiError>
261
- ): encode.ReturnType {
338
+ ): encode.ReturnType
339
+ // eslint-disable-next-line jsdoc/require-jsdoc
340
+ export function encode(
341
+ ...parameters:
342
+ | [
343
+ abi: Abi.Abi | readonly unknown[],
344
+ name: Hex.Hex | string,
345
+ ...args: readonly unknown[],
346
+ ]
347
+ | [abiError: AbiError, ...args: readonly unknown[]]
348
+ ) {
349
+ const [abiError, args] = (() => {
350
+ if (Array.isArray(parameters[0])) {
351
+ const [abi, name, ...args] = parameters as [
352
+ Abi.Abi | readonly unknown[],
353
+ Hex.Hex | string,
354
+ ...(readonly unknown[]),
355
+ ]
356
+ return [fromAbi(abi, name), args]
357
+ }
358
+ const [abiError, ...args] = parameters as [
359
+ AbiError,
360
+ ...(readonly unknown[]),
361
+ ]
362
+ return [abiError, args]
363
+ })()
364
+
262
365
  const selector = getSelector(abiError)
263
366
 
264
367
  const data =
package/core/AbiEvent.ts CHANGED
@@ -286,10 +286,51 @@ export declare namespace assertArgs {
286
286
  * @param log - `topics` & `data` to decode.
287
287
  * @returns The decoded event.
288
288
  */
289
+ export function decode<
290
+ const abi extends Abi.Abi | readonly unknown[],
291
+ name extends Name<abi>,
292
+ const args extends
293
+ | AbiItem_internal.ExtractArgs<abi, name>
294
+ | undefined = undefined,
295
+ //
296
+ abiEvent extends AbiEvent = AbiItem.fromAbi.ReturnType<
297
+ abi,
298
+ name,
299
+ args,
300
+ AbiEvent
301
+ >,
302
+ allNames = Name<abi>,
303
+ >(
304
+ abi: abi | Abi.Abi | readonly unknown[],
305
+ name: Hex.Hex | (name extends allNames ? name : never),
306
+ log: decode.Log,
307
+ ): decode.ReturnType<abiEvent>
289
308
  export function decode<const abiEvent extends AbiEvent>(
290
309
  abiEvent: abiEvent | AbiEvent,
291
310
  log: decode.Log,
292
- ): decode.ReturnType<abiEvent> {
311
+ ): decode.ReturnType<abiEvent>
312
+ // eslint-disable-next-line jsdoc/require-jsdoc
313
+ export function decode(
314
+ ...parameters:
315
+ | [
316
+ abi: Abi.Abi | readonly unknown[],
317
+ name: Hex.Hex | string,
318
+ log: decode.Log,
319
+ ]
320
+ | [abiEvent: AbiEvent, log: decode.Log]
321
+ ): decode.ReturnType {
322
+ const [abiEvent, log] = (() => {
323
+ if (Array.isArray(parameters[0])) {
324
+ const [abi, name, log] = parameters as [
325
+ Abi.Abi | readonly unknown[],
326
+ Hex.Hex | string,
327
+ decode.Log,
328
+ ]
329
+ return [fromAbi(abi, name), log]
330
+ }
331
+ return parameters as [AbiEvent, decode.Log]
332
+ })()
333
+
293
334
  const { data, topics } = log
294
335
 
295
336
  const [selector_, ...argTopics] = topics
@@ -496,10 +537,55 @@ export declare namespace decode {
496
537
  * @param args - The arguments to encode.
497
538
  * @returns The encoded event topics.
498
539
  */
540
+ export function encode<
541
+ const abi extends Abi.Abi | readonly unknown[],
542
+ name extends Name<abi>,
543
+ const args extends
544
+ | AbiItem_internal.ExtractArgs<abi, name>
545
+ | undefined = undefined,
546
+ //
547
+ abiEvent extends AbiEvent = AbiItem.fromAbi.ReturnType<
548
+ abi,
549
+ name,
550
+ args,
551
+ AbiEvent
552
+ >,
553
+ allNames = Name<abi>,
554
+ >(
555
+ abi: abi | Abi.Abi | readonly unknown[],
556
+ name: Hex.Hex | (name extends allNames ? name : never),
557
+ ...[args]: encode.Args<abiEvent>
558
+ ): encode.ReturnType
499
559
  export function encode<const abiEvent extends AbiEvent>(
500
560
  abiEvent: abiEvent | AbiEvent,
501
561
  ...[args]: encode.Args<abiEvent>
562
+ ): encode.ReturnType
563
+ // eslint-disable-next-line jsdoc/require-jsdoc
564
+ export function encode(
565
+ ...parameters:
566
+ | [
567
+ abi: Abi.Abi | readonly unknown[],
568
+ name: Hex.Hex | string,
569
+ args?: readonly unknown[] | Record<string, unknown>,
570
+ ]
571
+ | [abiEvent: AbiEvent, args?: readonly unknown[] | Record<string, unknown>]
502
572
  ): encode.ReturnType {
573
+ const [abiEvent, args] = (() => {
574
+ if (Array.isArray(parameters[0])) {
575
+ const [abi, name, args] = parameters as [
576
+ Abi.Abi | readonly unknown[],
577
+ Hex.Hex | string,
578
+ readonly unknown[] | Record<string, unknown> | undefined,
579
+ ]
580
+ return [fromAbi(abi, name), args]
581
+ }
582
+ const [abiEvent, args] = parameters as [
583
+ AbiEvent,
584
+ readonly unknown[] | Record<string, unknown> | undefined,
585
+ ]
586
+ return [abiEvent, args]
587
+ })()
588
+
503
589
  let topics: (Hex.Hex | Hex.Hex[] | null)[] = []
504
590
  if (args && abiEvent.inputs) {
505
591
  const indexedInputs = abiEvent.inputs.filter(
@@ -93,10 +93,47 @@ export type ExtractNames<
93
93
  * @param abiFunction - The ABI Item to decode.
94
94
  * @param data - The data to decode.
95
95
  */
96
+ export function decodeData<
97
+ const abi extends Abi.Abi | readonly unknown[],
98
+ name extends Name<abi>,
99
+ const args extends
100
+ | AbiItem_internal.ExtractArgs<abi, name>
101
+ | undefined = undefined,
102
+ //
103
+ abiFunction extends AbiFunction = AbiItem.fromAbi.ReturnType<
104
+ abi,
105
+ name,
106
+ args,
107
+ AbiFunction
108
+ >,
109
+ allNames = Name<abi>,
110
+ >(
111
+ abi: abi | Abi.Abi | readonly unknown[],
112
+ name: Hex.Hex | (name extends allNames ? name : never),
113
+ data: Hex.Hex,
114
+ ): decodeData.ReturnType<abiFunction>
96
115
  export function decodeData<const abiItem extends AbiFunction>(
97
116
  abiFunction: abiItem | AbiFunction,
98
117
  data: Hex.Hex,
99
- ): decodeData.ReturnType<abiItem> {
118
+ ): decodeData.ReturnType<abiItem>
119
+ // eslint-disable-next-line jsdoc/require-jsdoc
120
+ export function decodeData(
121
+ ...parameters:
122
+ | [abi: Abi.Abi | readonly unknown[], name: Hex.Hex | string, data: Hex.Hex]
123
+ | [abiFunction: AbiFunction, data: Hex.Hex]
124
+ ) {
125
+ const [abiFunction, data] = (() => {
126
+ if (Array.isArray(parameters[0])) {
127
+ const [abi, name, data] = parameters as [
128
+ Abi.Abi | readonly unknown[],
129
+ Hex.Hex | string,
130
+ Hex.Hex,
131
+ ]
132
+ return [fromAbi(abi, name), data]
133
+ }
134
+ return parameters as [AbiFunction, Hex.Hex]
135
+ })()
136
+
100
137
  const { overloads } = abiFunction
101
138
 
102
139
  if (Hex.size(data) < 4) throw new AbiItem.InvalidSelectorSizeError({ data })
@@ -174,6 +211,25 @@ export declare namespace decodeData {
174
211
  * ```
175
212
  *
176
213
  * @example
214
+ * Or define the ABI and function name as parameters to {@link ox#AbiFunction.(decodeResult:function)}:
215
+ *
216
+ * ```ts twoslash
217
+ * // @noErrors
218
+ * import { Abi, AbiFunction } from 'ox'
219
+ *
220
+ * const data = '0x000000000000000000000000000000000000000000000000000000000000002a'
221
+ *
222
+ * const erc20Abi = Abi.from([...])
223
+ *
224
+ * const output = AbiFunction.decodeResult(
225
+ * erc20Abi, // [!code hl]
226
+ * 'totalSupply', // [!code hl]
227
+ * data
228
+ * )
229
+ * // @log: 42n
230
+ * ```
231
+ *
232
+ * @example
177
233
  * ### End-to-end
178
234
  *
179
235
  * Below is an end-to-end example of using `AbiFunction.decodeResult` to decode the result of a `balanceOf` contract call on the [Wagmi Mint Example contract](https://etherscan.io/address/0xfba3912ca04dd458c843e2ee08967fc04f3579c2).
@@ -230,14 +286,67 @@ export declare namespace decodeData {
230
286
  * @param options - Decoding options
231
287
  * @returns Decoded function output
232
288
  */
289
+ export function decodeResult<
290
+ const abi extends Abi.Abi | readonly unknown[],
291
+ name extends Name<abi>,
292
+ const args extends
293
+ | AbiItem_internal.ExtractArgs<abi, name>
294
+ | undefined = undefined,
295
+ //
296
+ abiFunction extends AbiFunction = AbiItem.fromAbi.ReturnType<
297
+ abi,
298
+ name,
299
+ args,
300
+ AbiFunction
301
+ >,
302
+ allNames = Name<abi>,
303
+ as extends 'Object' | 'Array' = 'Array',
304
+ >(
305
+ abi: abi | Abi.Abi | readonly unknown[],
306
+ name: Hex.Hex | (name extends allNames ? name : never),
307
+ data: Hex.Hex,
308
+ options?: decodeResult.Options<as> | undefined,
309
+ ): decodeResult.ReturnType<abiFunction, as>
233
310
  export function decodeResult<
234
311
  const abiFunction extends AbiFunction,
235
312
  as extends 'Object' | 'Array' = 'Array',
236
313
  >(
237
314
  abiFunction: abiFunction | AbiFunction,
238
315
  data: Hex.Hex,
239
- options: decodeResult.Options<as> = {},
240
- ): decodeResult.ReturnType<abiFunction, as> {
316
+ options?: decodeResult.Options<as> | undefined,
317
+ ): decodeResult.ReturnType<abiFunction, as>
318
+ // eslint-disable-next-line jsdoc/require-jsdoc
319
+ export function decodeResult(
320
+ ...parameters:
321
+ | [
322
+ abi: Abi.Abi | readonly unknown[],
323
+ name: Hex.Hex | string,
324
+ data: Hex.Hex,
325
+ options?: decodeResult.Options | undefined,
326
+ ]
327
+ | [
328
+ abiFunction: AbiFunction,
329
+ data: Hex.Hex,
330
+ options?: decodeResult.Options | undefined,
331
+ ]
332
+ ) {
333
+ const [abiFunction, data, options = {}] = (() => {
334
+ if (Array.isArray(parameters[0])) {
335
+ const [abi, name, data, options] = parameters as [
336
+ Abi.Abi | readonly unknown[],
337
+ Hex.Hex | string,
338
+ Hex.Hex,
339
+ decodeResult.Options | undefined,
340
+ ]
341
+ return [fromAbi(abi, name), data, options]
342
+ }
343
+ return parameters as [
344
+ AbiFunction,
345
+ Hex.Hex,
346
+ decodeResult.Options | undefined,
347
+ ]
348
+ })()
349
+
241
350
  const values = AbiParameters.decode(abiFunction.outputs, data, options)
242
351
  if (values && Object.keys(values).length === 0) return undefined
243
352
  if (values && Object.keys(values).length === 1) {
@@ -248,7 +357,7 @@ export function decodeResult<
248
357
  }
249
358
 
250
359
  export declare namespace decodeResult {
251
- type Options<as extends 'Object' | 'Array'> = {
360
+ type Options<as extends 'Object' | 'Array' = 'Array'> = {
252
361
  /**
253
362
  * Whether the decoded values should be returned as an `Object` or `Array`.
254
363
  *
@@ -324,6 +433,22 @@ export declare namespace decodeResult {
324
433
  * ```
325
434
  *
326
435
  * @example
436
+ * Or define the ABI and function name as parameters to {@link ox#AbiFunction.(encodeData:function)}:
437
+ *
438
+ * ```ts twoslash
439
+ * // @noErrors
440
+ * import { Abi, AbiFunction } from 'ox'
441
+ *
442
+ * const erc20Abi = Abi.from([...])
443
+ *
444
+ * const data = AbiFunction.encodeData(
445
+ * erc20Abi, // [!code hl]
446
+ * 'approve', // [!code hl]
447
+ * ['0xd8da6bf26964af9d7eed9e03e53415d37aa96045', 69420n]
448
+ * )
449
+ * ```
450
+ *
451
+ * @example
327
452
  * ### End-to-end
328
453
  *
329
454
  * Below is an end-to-end example of using `AbiFunction.encodeData` to encode the input of a `balanceOf` contract call on the [Wagmi Mint Example contract](https://etherscan.io/address/0xfba3912ca04dd458c843e2ee08967fc04f3579c2).
@@ -378,24 +503,64 @@ export declare namespace decodeResult {
378
503
  * @param args - Function arguments
379
504
  * @returns ABI-encoded function name and arguments
380
505
  */
506
+ export function encodeData<
507
+ const abi extends Abi.Abi | readonly unknown[],
508
+ name extends Name<abi>,
509
+ const args extends
510
+ | AbiItem_internal.ExtractArgs<abi, name>
511
+ | undefined = undefined,
512
+ //
513
+ abiFunction extends AbiFunction = AbiItem.fromAbi.ReturnType<
514
+ abi,
515
+ name,
516
+ args,
517
+ AbiFunction
518
+ >,
519
+ allNames = Name<abi>,
520
+ >(
521
+ abi: abi | Abi.Abi | readonly unknown[],
522
+ name: Hex.Hex | (name extends allNames ? name : never),
523
+ ...args: encodeData.Args<abiFunction>
524
+ ): Hex.Hex
381
525
  export function encodeData<const abiFunction extends AbiFunction>(
382
526
  abiFunction: abiFunction | AbiFunction,
383
527
  ...args: encodeData.Args<abiFunction>
384
- ): Hex.Hex {
528
+ ): Hex.Hex
529
+ // eslint-disable-next-line jsdoc/require-jsdoc
530
+ export function encodeData(
531
+ ...parameters:
532
+ | [
533
+ abi: Abi.Abi | readonly unknown[],
534
+ name: Hex.Hex | string,
535
+ ...args: readonly unknown[],
536
+ ]
537
+ | [abiFunction: AbiFunction, ...args: readonly unknown[]]
538
+ ) {
539
+ const [abiFunction, args = []] = (() => {
540
+ if (Array.isArray(parameters[0])) {
541
+ const [abi, name, args] = parameters as [
542
+ Abi.Abi | readonly unknown[],
543
+ Hex.Hex | string,
544
+ readonly unknown[],
545
+ ]
546
+ return [fromAbi(abi, name, { args }), args]
547
+ }
548
+ const [abiFunction, args] = parameters as [AbiFunction, readonly unknown[]]
549
+ return [abiFunction, args]
550
+ })()
551
+
385
552
  const { overloads } = abiFunction
386
553
 
387
554
  const item = overloads
388
555
  ? (fromAbi([abiFunction as AbiFunction, ...overloads], abiFunction.name, {
389
- args: (args as any)[0],
556
+ args,
390
557
  }) as AbiFunction)
391
558
  : abiFunction
392
559
 
393
560
  const selector = getSelector(item)
394
561
 
395
562
  const data =
396
- args.length > 0
397
- ? AbiParameters.encode(item.inputs, (args as any)[0])
398
- : undefined
563
+ args.length > 0 ? AbiParameters.encode(item.inputs, args) : undefined
399
564
 
400
565
  return data ? Hex.concat(selector, data) : selector
401
566
  }
@@ -443,14 +608,67 @@ export declare namespace encodeData {
443
608
  * @param options - Encoding options.
444
609
  * @returns The encoded function output.
445
610
  */
611
+ export function encodeResult<
612
+ const abi extends Abi.Abi | readonly unknown[],
613
+ name extends Name<abi>,
614
+ const args extends
615
+ | AbiItem_internal.ExtractArgs<abi, name>
616
+ | undefined = undefined,
617
+ as extends 'Object' | 'Array' = 'Array',
618
+ //
619
+ abiFunction extends AbiFunction = AbiItem.fromAbi.ReturnType<
620
+ abi,
621
+ name,
622
+ args,
623
+ AbiFunction
624
+ >,
625
+ allNames = Name<abi>,
626
+ >(
627
+ abi: abi | Abi.Abi | readonly unknown[],
628
+ name: Hex.Hex | (name extends allNames ? name : never),
629
+ output: encodeResult.Output<abiFunction, as>,
630
+ options?: encodeResult.Options<as>,
631
+ ): Hex.Hex
446
632
  export function encodeResult<
447
633
  const abiFunction extends AbiFunction,
448
634
  as extends 'Object' | 'Array' = 'Array',
449
635
  >(
450
636
  abiFunction: abiFunction | AbiFunction,
451
637
  output: encodeResult.Output<abiFunction, as>,
452
- options: encodeResult.Options<as> = {},
453
- ): Hex.Hex {
638
+ options?: encodeResult.Options<as>,
639
+ ): Hex.Hex
640
+ // eslint-disable-next-line jsdoc/require-jsdoc
641
+ export function encodeResult(
642
+ ...parameters:
643
+ | [
644
+ abi: Abi.Abi | readonly unknown[],
645
+ name: Hex.Hex | string,
646
+ output: any,
647
+ options?: encodeResult.Options<any> | undefined,
648
+ ]
649
+ | [
650
+ abiFunction: AbiFunction,
651
+ output: any,
652
+ options?: encodeResult.Options<any> | undefined,
653
+ ]
654
+ ) {
655
+ const [abiFunction, output, options = {}] = (() => {
656
+ if (Array.isArray(parameters[0])) {
657
+ const [abi, name, output, options] = parameters as [
658
+ Abi.Abi | readonly unknown[],
659
+ Hex.Hex | string,
660
+ any,
661
+ encodeResult.Options<any> | undefined,
662
+ ]
663
+ return [fromAbi(abi, name), output, options]
664
+ }
665
+ return parameters as [
666
+ AbiFunction,
667
+ any,
668
+ encodeResult.Options<any> | undefined,
669
+ ]
670
+ })()
671
+
454
672
  const { as = 'Array' } = options
455
673
 
456
674
  const values = (() => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ox",
3
3
  "description": "Ethereum Standard Library",
4
- "version": "0.9.3",
4
+ "version": "0.9.5",
5
5
  "main": "./_cjs/index.js",
6
6
  "module": "./_esm/index.js",
7
7
  "types": "./_types/index.d.ts",
package/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  /** @internal */
2
- export const version = '0.9.3'
2
+ export const version = '0.9.5'