ox 1.0.0-beta.0 → 1.0.0-beta.2

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.
Files changed (66) hide show
  1. package/dist/core/Provider.d.ts +7 -7
  2. package/dist/core/Provider.d.ts.map +1 -1
  3. package/dist/core/RpcSchema.d.ts +50 -0
  4. package/dist/core/RpcSchema.d.ts.map +1 -1
  5. package/dist/core/RpcSchema.js.map +1 -1
  6. package/dist/core/RpcTransport.d.ts +2 -2
  7. package/dist/core/RpcTransport.d.ts.map +1 -1
  8. package/dist/core/RpcTransport.js.map +1 -1
  9. package/dist/core/internal/rpcTransport.d.ts +1 -1
  10. package/dist/core/internal/rpcTransport.d.ts.map +1 -1
  11. package/dist/index.d.ts +2 -0
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +2 -0
  14. package/dist/index.js.map +1 -1
  15. package/dist/tempo/MultisigConfig.d.ts +79 -16
  16. package/dist/tempo/MultisigConfig.d.ts.map +1 -1
  17. package/dist/tempo/MultisigConfig.js +69 -11
  18. package/dist/tempo/MultisigConfig.js.map +1 -1
  19. package/dist/tempo/SignatureEnvelope.d.ts +83 -19
  20. package/dist/tempo/SignatureEnvelope.d.ts.map +1 -1
  21. package/dist/tempo/SignatureEnvelope.js +99 -30
  22. package/dist/tempo/SignatureEnvelope.js.map +1 -1
  23. package/dist/tempo/index.d.ts +2 -2
  24. package/dist/tempo/index.js +2 -2
  25. package/dist/zod/RpcSchema.d.ts +144 -25
  26. package/dist/zod/RpcSchema.d.ts.map +1 -1
  27. package/dist/zod/RpcSchema.js +85 -13
  28. package/dist/zod/RpcSchema.js.map +1 -1
  29. package/dist/zod/internal/rpcSchemas/Eth.d.ts +12 -12
  30. package/dist/zod/internal/rpcSchemas/Eth.d.ts.map +1 -1
  31. package/dist/zod/internal/rpcSchemas/Eth.js +14 -12
  32. package/dist/zod/internal/rpcSchemas/Eth.js.map +1 -1
  33. package/dist/zod/tempo/AuthorizationTempo.d.ts +6 -6
  34. package/dist/zod/tempo/KeyAuthorization.d.ts +3 -3
  35. package/dist/zod/tempo/RpcSchemaTempo.d.ts +6 -6
  36. package/dist/zod/tempo/SignatureEnvelope.d.ts +3 -3
  37. package/dist/zod/tempo/SignatureEnvelope.js +1 -1
  38. package/dist/zod/tempo/SignatureEnvelope.js.map +1 -1
  39. package/dist/zod/tempo/Transaction.d.ts +6 -6
  40. package/dist/zod/tempo/TransactionRequest.d.ts +6 -6
  41. package/dist/zod/tempo/TxEnvelopeTempo.d.ts +9 -9
  42. package/dist/zod/tempo/ZoneRpcAuthentication.d.ts +3 -3
  43. package/package.json +1 -1
  44. package/src/CHANGELOG.md +6 -0
  45. package/src/core/Provider.ts +7 -7
  46. package/src/core/RpcSchema.ts +60 -0
  47. package/src/core/RpcTransport.ts +7 -4
  48. package/src/core/_test/Provider.test-d.ts +21 -0
  49. package/src/core/_test/RpcSchema.test-d.ts +87 -1
  50. package/src/core/_test/RpcTransport.test-d.ts +43 -0
  51. package/src/core/internal/rpcTransport.ts +1 -1
  52. package/src/index.ts +2 -0
  53. package/src/tempo/MultisigConfig.test.ts +21 -12
  54. package/src/tempo/MultisigConfig.ts +103 -18
  55. package/src/tempo/SignatureEnvelope.test.ts +124 -26
  56. package/src/tempo/SignatureEnvelope.ts +150 -48
  57. package/src/tempo/e2e.test.ts +42 -47
  58. package/src/tempo/index.ts +2 -2
  59. package/src/version.ts +1 -1
  60. package/src/zod/RpcSchema.ts +190 -13
  61. package/src/zod/_test/RpcSchema.test-d.ts +53 -6
  62. package/src/zod/_test/RpcSchema.test.ts +138 -18
  63. package/src/zod/internal/rpcSchemas/Eth.ts +14 -12
  64. package/src/zod/tempo/SignatureEnvelope.ts +1 -1
  65. package/src/zod/tempo/_test/RpcSchemaTempo.test.ts +1 -1
  66. package/src/zod/tempo/_test/SignatureEnvelope.test.ts +23 -0
@@ -87,6 +87,7 @@ test('behavior: default (secp256k1)', async () => {
87
87
  from,
88
88
  keyAuthorization: __,
89
89
  nonce,
90
+ gasPrice,
90
91
  maxFeePerGas,
91
92
  maxPriorityFeePerGas,
92
93
  signature,
@@ -100,6 +101,7 @@ test('behavior: default (secp256k1)', async () => {
100
101
  expect(chainId).toBe(chainId)
101
102
  expect(hash).toBe(receipt.transactionHash)
102
103
  expect(from).toBe(address)
104
+ expect(gasPrice).toBeDefined()
103
105
  expect(maxFeePerGas).toBeDefined()
104
106
  expect(maxPriorityFeePerGas).toBeDefined()
105
107
  expect(nonce).toBeDefined()
@@ -119,7 +121,6 @@ test('behavior: default (secp256k1)', async () => {
119
121
  "data": undefined,
120
122
  "feePayerSignature": null,
121
123
  "gas": 500000n,
122
- "gasPrice": 20000000000n,
123
124
  "nonceKey": 0n,
124
125
  "type": "tempo",
125
126
  "validAfter": null,
@@ -133,6 +134,7 @@ test('behavior: default (secp256k1)', async () => {
133
134
  blockNumber,
134
135
  blockHash,
135
136
  cumulativeGasUsed,
137
+ effectiveGasPrice,
136
138
  feePayer,
137
139
  feeToken: _,
138
140
  from,
@@ -147,6 +149,7 @@ test('behavior: default (secp256k1)', async () => {
147
149
  expect(blockNumber).toBeDefined()
148
150
  expect(blockHash).toBeDefined()
149
151
  expect(cumulativeGasUsed).toBeDefined()
152
+ expect(effectiveGasPrice).toBeDefined()
150
153
  expect(feePayer).toBeDefined()
151
154
  expect(from).toBe(address)
152
155
  expect(gasUsed).toBeDefined()
@@ -159,7 +162,6 @@ test('behavior: default (secp256k1)', async () => {
159
162
  "blobGasPrice": undefined,
160
163
  "blobGasUsed": undefined,
161
164
  "contractAddress": null,
162
- "effectiveGasPrice": 20000000000n,
163
165
  "status": "success",
164
166
  "to": "0x0000000000000000000000000000000000000000",
165
167
  "type": "0x76",
@@ -298,6 +300,7 @@ test('behavior: default (p256)', async () => {
298
300
  keyAuthorization: __,
299
301
  hash,
300
302
  nonce,
303
+ gasPrice,
301
304
  maxFeePerGas,
302
305
  maxPriorityFeePerGas,
303
306
  signature,
@@ -312,6 +315,7 @@ test('behavior: default (p256)', async () => {
312
315
  expect(from).toBe(address)
313
316
  expect(hash).toBe(receipt.transactionHash)
314
317
  expect(nonce).toBeDefined()
318
+ expect(gasPrice).toBeDefined()
315
319
  expect(maxFeePerGas).toBeDefined()
316
320
  expect(maxPriorityFeePerGas).toBeDefined()
317
321
  expect(signature).toBeDefined()
@@ -330,7 +334,6 @@ test('behavior: default (p256)', async () => {
330
334
  "data": undefined,
331
335
  "feePayerSignature": null,
332
336
  "gas": 500000n,
333
- "gasPrice": 20000000000n,
334
337
  "nonceKey": 0n,
335
338
  "type": "tempo",
336
339
  "validAfter": null,
@@ -344,6 +347,7 @@ test('behavior: default (p256)', async () => {
344
347
  blockNumber,
345
348
  blockHash,
346
349
  cumulativeGasUsed,
350
+ effectiveGasPrice,
347
351
  feePayer,
348
352
  feeToken: _,
349
353
  from,
@@ -358,6 +362,7 @@ test('behavior: default (p256)', async () => {
358
362
  expect(blockNumber).toBeDefined()
359
363
  expect(blockHash).toBeDefined()
360
364
  expect(cumulativeGasUsed).toBeDefined()
365
+ expect(effectiveGasPrice).toBeDefined()
361
366
  expect(feePayer).toBeDefined()
362
367
  expect(from).toBe(address)
363
368
  expect(gasUsed).toBeDefined()
@@ -370,7 +375,6 @@ test('behavior: default (p256)', async () => {
370
375
  "blobGasPrice": undefined,
371
376
  "blobGasUsed": undefined,
372
377
  "contractAddress": null,
373
- "effectiveGasPrice": 20000000000n,
374
378
  "status": "success",
375
379
  "to": "0x0000000000000000000000000000000000000000",
376
380
  "type": "0x76",
@@ -441,6 +445,7 @@ test('behavior: default (p256 - webcrypto)', async () => {
441
445
  keyAuthorization: __,
442
446
  hash,
443
447
  nonce,
448
+ gasPrice,
444
449
  maxFeePerGas,
445
450
  maxPriorityFeePerGas,
446
451
  signature,
@@ -455,6 +460,7 @@ test('behavior: default (p256 - webcrypto)', async () => {
455
460
  expect(from).toBeDefined()
456
461
  expect(hash).toBe(receipt.transactionHash)
457
462
  expect(nonce).toBeDefined()
463
+ expect(gasPrice).toBeDefined()
458
464
  expect(maxFeePerGas).toBeDefined()
459
465
  expect(maxPriorityFeePerGas).toBeDefined()
460
466
  expect(signature).toBeDefined()
@@ -473,7 +479,6 @@ test('behavior: default (p256 - webcrypto)', async () => {
473
479
  "data": undefined,
474
480
  "feePayerSignature": null,
475
481
  "gas": 500000n,
476
- "gasPrice": 20000000000n,
477
482
  "nonceKey": 0n,
478
483
  "type": "tempo",
479
484
  "validAfter": null,
@@ -487,6 +492,7 @@ test('behavior: default (p256 - webcrypto)', async () => {
487
492
  blockNumber,
488
493
  blockHash,
489
494
  cumulativeGasUsed,
495
+ effectiveGasPrice,
490
496
  feePayer,
491
497
  feeToken: _,
492
498
  from,
@@ -501,6 +507,7 @@ test('behavior: default (p256 - webcrypto)', async () => {
501
507
  expect(blockNumber).toBeDefined()
502
508
  expect(blockHash).toBeDefined()
503
509
  expect(cumulativeGasUsed).toBeDefined()
510
+ expect(effectiveGasPrice).toBeDefined()
504
511
  expect(feePayer).toBeDefined()
505
512
  expect(from).toBeDefined()
506
513
  expect(gasUsed).toBeDefined()
@@ -513,7 +520,6 @@ test('behavior: default (p256 - webcrypto)', async () => {
513
520
  "blobGasPrice": undefined,
514
521
  "blobGasUsed": undefined,
515
522
  "contractAddress": null,
516
- "effectiveGasPrice": 20000000000n,
517
523
  "status": "success",
518
524
  "to": "0x0000000000000000000000000000000000000000",
519
525
  "type": "0x76",
@@ -591,6 +597,7 @@ test('behavior: default (webauthn)', async () => {
591
597
  keyAuthorization: __,
592
598
  hash,
593
599
  nonce,
600
+ gasPrice,
594
601
  maxFeePerGas,
595
602
  maxPriorityFeePerGas,
596
603
  transactionIndex,
@@ -605,6 +612,7 @@ test('behavior: default (webauthn)', async () => {
605
612
  expect(from).toBeDefined()
606
613
  expect(hash).toBe(receipt.transactionHash)
607
614
  expect(nonce).toBeDefined()
615
+ expect(gasPrice).toBeDefined()
608
616
  expect(maxFeePerGas).toBeDefined()
609
617
  expect(maxPriorityFeePerGas).toBeDefined()
610
618
  expect(signature).toBeDefined()
@@ -623,7 +631,6 @@ test('behavior: default (webauthn)', async () => {
623
631
  "data": undefined,
624
632
  "feePayerSignature": null,
625
633
  "gas": 500000n,
626
- "gasPrice": 20000000000n,
627
634
  "nonceKey": 0n,
628
635
  "type": "tempo",
629
636
  "validAfter": null,
@@ -637,6 +644,7 @@ test('behavior: default (webauthn)', async () => {
637
644
  blockNumber,
638
645
  blockHash,
639
646
  cumulativeGasUsed,
647
+ effectiveGasPrice,
640
648
  feePayer,
641
649
  feeToken: _,
642
650
  from,
@@ -651,6 +659,7 @@ test('behavior: default (webauthn)', async () => {
651
659
  expect(blockNumber).toBeDefined()
652
660
  expect(blockHash).toBeDefined()
653
661
  expect(cumulativeGasUsed).toBeDefined()
662
+ expect(effectiveGasPrice).toBeDefined()
654
663
  expect(feePayer).toBeDefined()
655
664
  expect(from).toBe(address)
656
665
  expect(gasUsed).toBeDefined()
@@ -663,7 +672,6 @@ test('behavior: default (webauthn)', async () => {
663
672
  "blobGasPrice": undefined,
664
673
  "blobGasUsed": undefined,
665
674
  "contractAddress": null,
666
- "effectiveGasPrice": 20000000000n,
667
675
  "status": "success",
668
676
  "to": "0x0000000000000000000000000000000000000000",
669
677
  "type": "0x76",
@@ -745,6 +753,7 @@ test('behavior: feePayerSignature (user → feePayer)', async () => {
745
753
  blockNumber,
746
754
  blockHash,
747
755
  cumulativeGasUsed,
756
+ effectiveGasPrice,
748
757
  feePayer,
749
758
  feeToken: _,
750
759
  from,
@@ -759,6 +768,7 @@ test('behavior: feePayerSignature (user → feePayer)', async () => {
759
768
  expect(blockNumber).toBeDefined()
760
769
  expect(blockHash).toBeDefined()
761
770
  expect(cumulativeGasUsed).toBeDefined()
771
+ expect(effectiveGasPrice).toBeDefined()
762
772
  expect(feePayer).toBe(feePayerAddress)
763
773
  expect(from).toBe(senderAddress)
764
774
  expect(gasUsed).toBeDefined()
@@ -771,7 +781,6 @@ test('behavior: feePayerSignature (user → feePayer)', async () => {
771
781
  "blobGasPrice": undefined,
772
782
  "blobGasUsed": undefined,
773
783
  "contractAddress": null,
774
- "effectiveGasPrice": 20000000000n,
775
784
  "status": "success",
776
785
  "to": "0x0000000000000000000000000000000000000000",
777
786
  "type": "0x76",
@@ -1019,6 +1028,7 @@ describe('behavior: keyAuthorization', () => {
1019
1028
  blockNumber,
1020
1029
  blockHash,
1021
1030
  cumulativeGasUsed,
1031
+ effectiveGasPrice,
1022
1032
  feePayer,
1023
1033
  feeToken,
1024
1034
  from,
@@ -1033,6 +1043,7 @@ describe('behavior: keyAuthorization', () => {
1033
1043
  expect(blockNumber).toBeDefined()
1034
1044
  expect(blockHash).toBeDefined()
1035
1045
  expect(cumulativeGasUsed).toBeDefined()
1046
+ expect(effectiveGasPrice).toBeDefined()
1036
1047
  expect(feeToken).toBeDefined()
1037
1048
  expect(feePayer).toBeDefined()
1038
1049
  expect(gasUsed).toBeDefined()
@@ -1046,7 +1057,6 @@ describe('behavior: keyAuthorization', () => {
1046
1057
  "blobGasPrice": undefined,
1047
1058
  "blobGasUsed": undefined,
1048
1059
  "contractAddress": null,
1049
- "effectiveGasPrice": 20000000000n,
1050
1060
  "status": "success",
1051
1061
  "to": "0x0000000000000000000000000000000000000000",
1052
1062
  "type": "0x76",
@@ -1238,6 +1248,7 @@ describe('behavior: keyAuthorization', () => {
1238
1248
  blockNumber,
1239
1249
  blockHash,
1240
1250
  cumulativeGasUsed,
1251
+ effectiveGasPrice,
1241
1252
  feePayer,
1242
1253
  feeToken,
1243
1254
  from,
@@ -1252,6 +1263,7 @@ describe('behavior: keyAuthorization', () => {
1252
1263
  expect(blockNumber).toBeDefined()
1253
1264
  expect(blockHash).toBeDefined()
1254
1265
  expect(cumulativeGasUsed).toBeDefined()
1266
+ expect(effectiveGasPrice).toBeDefined()
1255
1267
  expect(feePayer).toBeDefined()
1256
1268
  expect(feeToken).toBeDefined()
1257
1269
  expect(from).toBeDefined()
@@ -1265,7 +1277,6 @@ describe('behavior: keyAuthorization', () => {
1265
1277
  "blobGasPrice": undefined,
1266
1278
  "blobGasUsed": undefined,
1267
1279
  "contractAddress": null,
1268
- "effectiveGasPrice": 20000000000n,
1269
1280
  "status": "success",
1270
1281
  "to": "0x0000000000000000000000000000000000000000",
1271
1282
  "type": "0x76",
@@ -3015,7 +3026,7 @@ describe.skip('behavior: multisig (TIP-1061)', () => {
3015
3026
  return { address, privateKey } as const
3016
3027
  })
3017
3028
 
3018
- const config = MultisigConfig.from({
3029
+ const genesisConfig = MultisigConfig.from({
3019
3030
  // A fresh random salt yields a distinct account each run, exercising the
3020
3031
  // salt-inclusive config-ID derivation against the node.
3021
3032
  salt: Hex.random(32),
@@ -3025,10 +3036,9 @@ describe.skip('behavior: multisig (TIP-1061)', () => {
3025
3036
  weight: 1,
3026
3037
  })),
3027
3038
  })
3028
- const configId = MultisigConfig.toId(config)
3029
- const account = MultisigConfig.getAddress({ configId })
3039
+ const account = MultisigConfig.getAddress(genesisConfig)
3030
3040
 
3031
- return { account, config, configId, ownerKeys } as const
3041
+ return { account, genesisConfig, ownerKeys } as const
3032
3042
  }
3033
3043
 
3034
3044
  // Signs the multisig owner digest with the provided owner keys, returning
@@ -3036,32 +3046,26 @@ describe.skip('behavior: multisig (TIP-1061)', () => {
3036
3046
  // address (required by the node: "recovered owners must be strictly
3037
3047
  // ascending").
3038
3048
  function approve(parameters: {
3039
- account: Address.Address
3040
- configId: Hex.Hex
3049
+ genesisConfig: MultisigConfig.Config
3041
3050
  payload: Hex.Hex
3042
3051
  signers: readonly { privateKey: Hex.Hex }[]
3043
3052
  }) {
3044
- const { account, configId, payload, signers } = parameters
3045
- const digest = MultisigConfig.getSignPayload({
3046
- account,
3047
- configId,
3048
- payload,
3049
- })
3053
+ const { genesisConfig, payload, signers } = parameters
3054
+ const digest = MultisigConfig.getSignPayload({ payload, genesisConfig })
3050
3055
  const signatures = signers.map((signer) =>
3051
3056
  SignatureEnvelope.from(
3052
3057
  Secp256k1.sign({ payload: digest, privateKey: signer.privateKey }),
3053
3058
  ),
3054
3059
  )
3055
3060
  return SignatureEnvelope.sortMultisigApprovals({
3056
- account,
3057
- configId,
3061
+ genesisConfig,
3058
3062
  payload,
3059
3063
  signatures,
3060
3064
  })
3061
3065
  }
3062
3066
 
3063
3067
  test('behavior: bootstrap + spend (2-of-3 secp256k1)', async () => {
3064
- const { account, config, configId, ownerKeys } = setup({
3068
+ const { account, genesisConfig, ownerKeys } = setup({
3065
3069
  count: 3,
3066
3070
  threshold: 2,
3067
3071
  })
@@ -3083,15 +3087,12 @@ describe.skip('behavior: multisig (TIP-1061)', () => {
3083
3087
 
3084
3088
  const bootstrap_signed = TxEnvelopeTempo.serialize(bootstrap, {
3085
3089
  signature: SignatureEnvelope.from({
3086
- type: 'multisig',
3087
- account,
3088
- configId,
3089
- // The bootstrap config is carried by the signature `init`.
3090
- init: config,
3090
+ genesisConfig,
3091
+ // Initialize multisig.
3092
+ init: true,
3091
3093
  // Approve with 2 of the 3 owners to satisfy the threshold.
3092
3094
  signatures: approve({
3093
- account,
3094
- configId,
3095
+ genesisConfig,
3095
3096
  payload: TxEnvelopeTempo.getSignPayload(bootstrap),
3096
3097
  signers: [ownerKeys[0]!, ownerKeys[1]!],
3097
3098
  }),
@@ -3121,7 +3122,7 @@ describe.skip('behavior: multisig (TIP-1061)', () => {
3121
3122
  // The bootstrap config is carried by the multisig signature `init`.
3122
3123
  expect(
3123
3124
  (response.signature as SignatureEnvelope.Multisig | undefined)?.init,
3124
- ).toEqual(config)
3125
+ ).toEqual(genesisConfig)
3125
3126
  }
3126
3127
 
3127
3128
  // Spend (subsequent transaction): no signature `init`, nonce 1, uses the
@@ -3143,13 +3144,10 @@ describe.skip('behavior: multisig (TIP-1061)', () => {
3143
3144
 
3144
3145
  const spend_signed = TxEnvelopeTempo.serialize(spend, {
3145
3146
  signature: SignatureEnvelope.from({
3146
- type: 'multisig',
3147
- account,
3148
- configId,
3147
+ genesisConfig,
3149
3148
  // A different 2-of-3 subset still authorizes the transaction.
3150
3149
  signatures: approve({
3151
- account,
3152
- configId,
3150
+ genesisConfig,
3153
3151
  payload: TxEnvelopeTempo.getSignPayload(spend),
3154
3152
  signers: [ownerKeys[1]!, ownerKeys[2]!],
3155
3153
  }),
@@ -3168,7 +3166,7 @@ describe.skip('behavior: multisig (TIP-1061)', () => {
3168
3166
  })
3169
3167
 
3170
3168
  test('behavior: rejects below-threshold approvals', async () => {
3171
- const { account, config, configId, ownerKeys } = setup({
3169
+ const { account, genesisConfig, ownerKeys } = setup({
3172
3170
  count: 3,
3173
3171
  threshold: 2,
3174
3172
  })
@@ -3187,15 +3185,12 @@ describe.skip('behavior: multisig (TIP-1061)', () => {
3187
3185
 
3188
3186
  const serialized_signed = TxEnvelopeTempo.serialize(bootstrap, {
3189
3187
  signature: SignatureEnvelope.from({
3190
- type: 'multisig',
3191
- account,
3192
- configId,
3193
- // The bootstrap config is carried by the signature `init`.
3194
- init: config,
3188
+ genesisConfig,
3189
+ // Opt into bootstrap: writes `genesisConfig` into the signature `init`.
3190
+ init: true,
3195
3191
  // Only one approval — below the threshold of 2.
3196
3192
  signatures: approve({
3197
- account,
3198
- configId,
3193
+ genesisConfig,
3199
3194
  payload: TxEnvelopeTempo.getSignPayload(bootstrap),
3200
3195
  signers: [ownerKeys[0]!],
3201
3196
  }),
@@ -131,7 +131,7 @@ export * as KeyAuthorization from './KeyAuthorization.js'
131
131
  * ```ts twoslash
132
132
  * import { MultisigConfig } from 'ox/tempo'
133
133
  *
134
- * const config = MultisigConfig.from({
134
+ * const genesisConfig = MultisigConfig.from({
135
135
  * threshold: 2,
136
136
  * owners: [
137
137
  * {
@@ -145,7 +145,7 @@ export * as KeyAuthorization from './KeyAuthorization.js'
145
145
  * ]
146
146
  * })
147
147
  *
148
- * const account = MultisigConfig.getAddress({ config })
148
+ * const account = MultisigConfig.getAddress(genesisConfig)
149
149
  * ```
150
150
  *
151
151
  * @category Reference
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  /** @internal */
2
- export const version = '1.0.0-beta.0'
2
+ export const version = '1.0.0-beta.2'
@@ -1,12 +1,103 @@
1
1
  import * as Errors from '../core/Errors.js'
2
2
  import * as eth from './internal/rpcSchemas/Eth.js'
3
+ import { from as fromItem } from './internal/rpcSchemas/from.js'
3
4
  import type { Item } from './internal/rpcSchemas/from.js'
4
5
  import * as wallet from './internal/rpcSchemas/Wallet.js'
5
6
  import * as z from 'zod/mini'
6
7
 
7
- export { from } from './internal/rpcSchemas/from.js'
8
8
  export type { Item } from './internal/rpcSchemas/from.js'
9
9
 
10
+ /**
11
+ * Instantiates JSON-RPC method schema(s) from Zod `params`/`returns` schemas.
12
+ *
13
+ * Two forms are supported:
14
+ *
15
+ * - A single method `{ method, params, returns }`, returning a `RpcSchema.Item`.
16
+ * - A record of `{ params, returns }` keyed by method name, returning a
17
+ * normalized `RpcSchema.Namespace` (each method's name is taken from its key
18
+ * and its `request` schema is derived). The result is usable with the
19
+ * `RpcSchema.decode*`/`RpcSchema.encode*` methods and as a schema for
20
+ * `Provider`/`RpcTransport`.
21
+ *
22
+ * @example
23
+ * ### Single Method
24
+ *
25
+ * ```ts twoslash
26
+ * import { z } from 'ox/zod'
27
+ *
28
+ * const eth_blockNumber = z.RpcSchema.from({
29
+ * method: 'eth_blockNumber',
30
+ * params: z.optional(z.tuple([])),
31
+ * returns: z.Hex.Hex
32
+ * })
33
+ * ```
34
+ *
35
+ * @example
36
+ * ### Namespace
37
+ *
38
+ * ```ts twoslash
39
+ * import { z } from 'ox/zod'
40
+ *
41
+ * const schema = z.RpcSchema.from({
42
+ * ...z.RpcSchema.Eth,
43
+ * abe_foo: {
44
+ * params: z.tuple([z.number()]),
45
+ * returns: z.string()
46
+ * }
47
+ * })
48
+ *
49
+ * const params = z.RpcSchema.decodeParams(
50
+ * schema,
51
+ * 'abe_foo',
52
+ * [123]
53
+ * )
54
+ * ```
55
+ */
56
+ export function from<
57
+ const method extends string,
58
+ params extends z.ZodMiniType,
59
+ returns extends z.ZodMiniType,
60
+ >(parameters: {
61
+ method: method
62
+ params: params
63
+ returns: returns
64
+ }): Item<method, params, returns>
65
+ export function from<const namespace extends from.Namespace>(
66
+ namespace: namespace,
67
+ ): from.ReturnType<namespace>
68
+ // eslint-disable-next-line jsdoc-js/require-jsdoc
69
+ export function from(
70
+ input:
71
+ | { method?: string; params?: z.ZodMiniType; returns?: z.ZodMiniType }
72
+ | from.Namespace,
73
+ ): unknown {
74
+ if (typeof input.method === 'string')
75
+ return fromItem(input as Parameters<typeof fromItem>[0])
76
+ return Object.fromEntries(
77
+ Object.entries(input as from.Namespace).map(([method, item]) => [
78
+ method,
79
+ fromItem({ method, params: item.params, returns: item.returns }),
80
+ ]),
81
+ )
82
+ }
83
+
84
+ export declare namespace from {
85
+ /** A record of `{ params, returns }` Zod schemas keyed by method name. */
86
+ type Namespace = Record<
87
+ string,
88
+ { params: z.ZodMiniType; returns: z.ZodMiniType }
89
+ >
90
+
91
+ /** The normalized `RpcSchema.Namespace` derived from a {@link from.Namespace}. */
92
+ type ReturnType<namespace extends Namespace> = {
93
+ [method in keyof namespace & string]: Item<
94
+ method,
95
+ namespace[method]['params'],
96
+ namespace[method]['returns']
97
+ >
98
+ }
99
+ }
100
+
10
101
  /** A namespace of JSON-RPC method schemas, keyed by method name. */
11
102
  export type Namespace = Record<string, Item>
12
103
 
@@ -61,13 +152,15 @@ export function parseItem<
61
152
  }
62
153
 
63
154
  /**
64
- * Validates and decodes the `params` for a method on a namespace.
155
+ * Decodes (wire native) the `params` for a method on a namespace. Use on the
156
+ * receiving side (e.g. a server) to coerce incoming wire params into their
157
+ * native representation.
65
158
  *
66
159
  * @example
67
160
  * ```ts twoslash
68
161
  * import { z } from 'ox/zod'
69
162
  *
70
- * const params = z.RpcSchema.parseParams(
163
+ * const params = z.RpcSchema.decodeParams(
71
164
  * z.RpcSchema.Eth,
72
165
  * 'eth_getBlockByNumber',
73
166
  * ['0x1', true]
@@ -76,7 +169,7 @@ export function parseItem<
76
169
  *
77
170
  * @throws `RpcSchema.MethodNotFoundError` if the method does not exist.
78
171
  */
79
- export function parseParams<
172
+ export function decodeParams<
80
173
  const namespace extends Namespace,
81
174
  method extends MethodName<namespace>,
82
175
  >(
@@ -88,13 +181,44 @@ export function parseParams<
88
181
  }
89
182
 
90
183
  /**
91
- * Validates and decodes the `returns` value for a method on a namespace.
184
+ * Encodes (native wire) the `params` for a method on a namespace. Use on the
185
+ * sending side (e.g. a client) to serialize native params into the wire shape
186
+ * a JSON-RPC endpoint expects.
187
+ *
188
+ * @example
189
+ * ```ts twoslash
190
+ * import { z } from 'ox/zod'
191
+ *
192
+ * const params = z.RpcSchema.encodeParams(
193
+ * z.RpcSchema.Eth,
194
+ * 'eth_getBlockByNumber',
195
+ * [1n, true]
196
+ * )
197
+ * ```
198
+ *
199
+ * @throws `RpcSchema.MethodNotFoundError` if the method does not exist.
200
+ */
201
+ export function encodeParams<
202
+ const namespace extends Namespace,
203
+ method extends MethodName<namespace>,
204
+ >(
205
+ namespace: namespace,
206
+ method: method,
207
+ params: z.output<namespace[method]['params']>,
208
+ ): z.input<namespace[method]['params']> {
209
+ return z.encode(parseItem(namespace, method).params, params as never) as never
210
+ }
211
+
212
+ /**
213
+ * Decodes (wire → native) the `returns` value for a method on a namespace. Use
214
+ * on the receiving side (e.g. a client) to coerce a wire result into its native
215
+ * representation.
92
216
  *
93
217
  * @example
94
218
  * ```ts twoslash
95
219
  * import { z } from 'ox/zod'
96
220
  *
97
- * const result = z.RpcSchema.parseReturns(
221
+ * const result = z.RpcSchema.decodeReturns(
98
222
  * z.RpcSchema.Eth,
99
223
  * 'eth_blockNumber',
100
224
  * '0x1b4'
@@ -103,7 +227,7 @@ export function parseParams<
103
227
  *
104
228
  * @throws `RpcSchema.MethodNotFoundError` if the method does not exist.
105
229
  */
106
- export function parseReturns<
230
+ export function decodeReturns<
107
231
  const namespace extends Namespace,
108
232
  method extends MethodName<namespace>,
109
233
  >(
@@ -118,20 +242,52 @@ export function parseReturns<
118
242
  }
119
243
 
120
244
  /**
121
- * Validates and decodes a full JSON-RPC request (`{ method, params }`) against
122
- * a namespace, dispatching on `method`.
245
+ * Encodes (native wire) the `returns` value for a method on a namespace. Use
246
+ * on the sending side (e.g. a server) to serialize a native result into the
247
+ * wire shape.
123
248
  *
124
249
  * @example
125
250
  * ```ts twoslash
126
251
  * import { z } from 'ox/zod'
127
252
  *
128
- * const request = z.RpcSchema.parseRequest(z.RpcSchema.Eth, {
253
+ * const result = z.RpcSchema.encodeReturns(
254
+ * z.RpcSchema.Eth,
255
+ * 'eth_blockNumber',
256
+ * 436n
257
+ * )
258
+ * ```
259
+ *
260
+ * @throws `RpcSchema.MethodNotFoundError` if the method does not exist.
261
+ */
262
+ export function encodeReturns<
263
+ const namespace extends Namespace,
264
+ method extends MethodName<namespace>,
265
+ >(
266
+ namespace: namespace,
267
+ method: method,
268
+ returns: z.output<namespace[method]['returns']>,
269
+ ): z.input<namespace[method]['returns']> {
270
+ return z.encode(
271
+ parseItem(namespace, method).returns,
272
+ returns as never,
273
+ ) as never
274
+ }
275
+
276
+ /**
277
+ * Decodes (wire → native) a full JSON-RPC request (`{ method, params }`)
278
+ * against a namespace, dispatching on `method`.
279
+ *
280
+ * @example
281
+ * ```ts twoslash
282
+ * import { z } from 'ox/zod'
283
+ *
284
+ * const request = z.RpcSchema.decodeRequest(z.RpcSchema.Eth, {
129
285
  * method: 'eth_getBlockByNumber',
130
286
  * params: ['0x1', true]
131
287
  * })
132
288
  * ```
133
289
  */
134
- export function parseRequest<const namespace extends Namespace>(
290
+ export function decodeRequest<const namespace extends Namespace>(
135
291
  namespace: namespace,
136
292
  request: RequestInput<namespace>,
137
293
  ): RequestOutput<namespace> {
@@ -139,7 +295,28 @@ export function parseRequest<const namespace extends Namespace>(
139
295
  }
140
296
 
141
297
  /**
142
- * Alias for `RpcSchema.parseRequest`.
298
+ * Encodes (native → wire) a full JSON-RPC request (`{ method, params }`)
299
+ * against a namespace, dispatching on `method`.
300
+ *
301
+ * @example
302
+ * ```ts twoslash
303
+ * import { z } from 'ox/zod'
304
+ *
305
+ * const request = z.RpcSchema.encodeRequest(z.RpcSchema.Eth, {
306
+ * method: 'eth_getBlockByNumber',
307
+ * params: [1n, true]
308
+ * })
309
+ * ```
310
+ */
311
+ export function encodeRequest<const namespace extends Namespace>(
312
+ namespace: namespace,
313
+ request: RequestOutput<namespace>,
314
+ ): RequestInput<namespace> {
315
+ return z.encode(requestSchema(namespace), request as never) as never
316
+ }
317
+
318
+ /**
319
+ * Alias for `RpcSchema.decodeRequest`.
143
320
  *
144
321
  * @example
145
322
  * ```ts twoslash
@@ -154,7 +331,7 @@ export function parseRequest<const namespace extends Namespace>(
154
331
  * })
155
332
  * ```
156
333
  */
157
- export const parse = parseRequest
334
+ export const parse = decodeRequest
158
335
 
159
336
  /** Wire (input) request envelope for a namespace. */
160
337
  export type RequestInput<namespace extends Namespace> = {