ox 1.7.2 → 1.7.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.
Files changed (142) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/dist/core/AbiEvent.d.ts.map +1 -1
  3. package/dist/core/AbiEvent.js +10 -9
  4. package/dist/core/AbiEvent.js.map +1 -1
  5. package/dist/core/Blobs.d.ts.map +1 -1
  6. package/dist/core/Blobs.js +6 -2
  7. package/dist/core/Blobs.js.map +1 -1
  8. package/dist/core/Signature.d.ts +6 -5
  9. package/dist/core/Signature.d.ts.map +1 -1
  10. package/dist/core/Signature.js +17 -7
  11. package/dist/core/Signature.js.map +1 -1
  12. package/dist/core/Siwe.d.ts.map +1 -1
  13. package/dist/core/Siwe.js +21 -1
  14. package/dist/core/Siwe.js.map +1 -1
  15. package/dist/tempo/KeyAuthorization.d.ts +43 -39
  16. package/dist/tempo/KeyAuthorization.d.ts.map +1 -1
  17. package/dist/tempo/KeyAuthorization.js +24 -4
  18. package/dist/tempo/KeyAuthorization.js.map +1 -1
  19. package/dist/tempo/MultisigConfig.d.ts +18 -15
  20. package/dist/tempo/MultisigConfig.d.ts.map +1 -1
  21. package/dist/tempo/MultisigConfig.js +49 -20
  22. package/dist/tempo/MultisigConfig.js.map +1 -1
  23. package/dist/tempo/MultisigOperation.d.ts +45 -28
  24. package/dist/tempo/MultisigOperation.d.ts.map +1 -1
  25. package/dist/tempo/MultisigOperation.js +81 -131
  26. package/dist/tempo/MultisigOperation.js.map +1 -1
  27. package/dist/tempo/MultisigSimulation.d.ts +85 -0
  28. package/dist/tempo/MultisigSimulation.d.ts.map +1 -0
  29. package/dist/tempo/MultisigSimulation.js +112 -0
  30. package/dist/tempo/MultisigSimulation.js.map +1 -0
  31. package/dist/tempo/RpcSchemaTempo.d.ts +20 -10
  32. package/dist/tempo/RpcSchemaTempo.d.ts.map +1 -1
  33. package/dist/tempo/SignatureEnvelope.d.ts +74 -153
  34. package/dist/tempo/SignatureEnvelope.d.ts.map +1 -1
  35. package/dist/tempo/SignatureEnvelope.js +130 -187
  36. package/dist/tempo/SignatureEnvelope.js.map +1 -1
  37. package/dist/tempo/TransactionRequest.d.ts +9 -7
  38. package/dist/tempo/TransactionRequest.d.ts.map +1 -1
  39. package/dist/tempo/TransactionRequest.js +12 -7
  40. package/dist/tempo/TransactionRequest.js.map +1 -1
  41. package/dist/tempo/index.d.ts +7 -5
  42. package/dist/tempo/index.d.ts.map +1 -1
  43. package/dist/tempo/index.js +7 -5
  44. package/dist/tempo/index.js.map +1 -1
  45. package/dist/zod/tempo/AuthorizationTempo.d.ts +360 -140
  46. package/dist/zod/tempo/AuthorizationTempo.d.ts.map +1 -1
  47. package/dist/zod/tempo/KeyAuthorization.d.ts +247 -487
  48. package/dist/zod/tempo/KeyAuthorization.d.ts.map +1 -1
  49. package/dist/zod/tempo/KeyAuthorization.js +29 -31
  50. package/dist/zod/tempo/KeyAuthorization.js.map +1 -1
  51. package/dist/zod/tempo/MultisigOperation.d.ts +0 -10
  52. package/dist/zod/tempo/MultisigOperation.d.ts.map +1 -1
  53. package/dist/zod/tempo/MultisigOperation.js +0 -3
  54. package/dist/zod/tempo/MultisigOperation.js.map +1 -1
  55. package/dist/zod/tempo/MultisigSimulation.d.ts +52 -0
  56. package/dist/zod/tempo/MultisigSimulation.d.ts.map +1 -0
  57. package/dist/zod/tempo/MultisigSimulation.js +44 -0
  58. package/dist/zod/tempo/MultisigSimulation.js.map +1 -0
  59. package/dist/zod/tempo/RpcSchemaTempo.d.ts +357 -422
  60. package/dist/zod/tempo/RpcSchemaTempo.d.ts.map +1 -1
  61. package/dist/zod/tempo/RpcSchemaTempo.js +19 -10
  62. package/dist/zod/tempo/RpcSchemaTempo.js.map +1 -1
  63. package/dist/zod/tempo/SignatureEnvelope.d.ts +108 -42
  64. package/dist/zod/tempo/SignatureEnvelope.d.ts.map +1 -1
  65. package/dist/zod/tempo/SignatureEnvelope.js +21 -19
  66. package/dist/zod/tempo/SignatureEnvelope.js.map +1 -1
  67. package/dist/zod/tempo/Transaction.d.ts +678 -666
  68. package/dist/zod/tempo/Transaction.d.ts.map +1 -1
  69. package/dist/zod/tempo/TransactionRequest.d.ts +580 -619
  70. package/dist/zod/tempo/TransactionRequest.d.ts.map +1 -1
  71. package/dist/zod/tempo/TransactionRequest.js +18 -10
  72. package/dist/zod/tempo/TransactionRequest.js.map +1 -1
  73. package/dist/zod/tempo/TxEnvelopeTempo.d.ts +327 -213
  74. package/dist/zod/tempo/TxEnvelopeTempo.d.ts.map +1 -1
  75. package/dist/zod/tempo/ZoneRpcAuthentication.d.ts +105 -3
  76. package/dist/zod/tempo/ZoneRpcAuthentication.d.ts.map +1 -1
  77. package/dist/zod/tempo/z.d.ts +1 -1
  78. package/dist/zod/tempo/z.d.ts.map +1 -1
  79. package/dist/zod/tempo/z.js +1 -1
  80. package/dist/zod/tempo/z.js.map +1 -1
  81. package/package.json +9 -9
  82. package/src/core/AbiEvent.ts +11 -9
  83. package/src/core/Blobs.ts +6 -2
  84. package/src/core/Signature.ts +41 -11
  85. package/src/core/Siwe.ts +20 -1
  86. package/src/core/_test/AbiEvent.test.ts +45 -0
  87. package/src/core/_test/Blobs.test.ts +22 -0
  88. package/src/core/_test/Signature.test.ts +166 -0
  89. package/src/core/_test/Siwe.test.ts +100 -1
  90. package/src/tempo/AuthorizationTempo.test.ts +8 -0
  91. package/src/tempo/KeyAuthorization.test-d.ts +16 -74
  92. package/src/tempo/KeyAuthorization.test.ts +113 -14
  93. package/src/tempo/KeyAuthorization.ts +110 -66
  94. package/src/tempo/MultisigConfig.test.ts +44 -20
  95. package/src/tempo/MultisigConfig.ts +65 -23
  96. package/src/tempo/MultisigOperation.test-d.ts +8 -6
  97. package/src/tempo/MultisigOperation.test.ts +187 -591
  98. package/src/tempo/MultisigOperation.ts +129 -205
  99. package/src/tempo/MultisigSimulation.test-d.ts +33 -0
  100. package/src/tempo/MultisigSimulation.test.ts +194 -0
  101. package/src/tempo/MultisigSimulation.ts +192 -0
  102. package/src/tempo/RpcSchemaTempo.test-d.ts +45 -10
  103. package/src/tempo/RpcSchemaTempo.ts +15 -6
  104. package/src/tempo/SignatureEnvelope.test-d.ts +27 -101
  105. package/src/tempo/SignatureEnvelope.test.ts +330 -533
  106. package/src/tempo/SignatureEnvelope.ts +198 -310
  107. package/src/tempo/Transaction.test.ts +61 -0
  108. package/src/tempo/TransactionRequest.test-d.ts +7 -7
  109. package/src/tempo/TransactionRequest.test.ts +81 -223
  110. package/src/tempo/TransactionRequest.ts +34 -13
  111. package/src/tempo/index.ts +7 -5
  112. package/src/tempo/multisig.e2e.test.ts +329 -818
  113. package/src/version.ts +1 -1
  114. package/src/zod/tempo/KeyAuthorization.ts +50 -39
  115. package/src/zod/tempo/MultisigOperation.ts +0 -3
  116. package/src/zod/tempo/MultisigSimulation.ts +53 -0
  117. package/src/zod/tempo/RpcSchemaTempo.ts +20 -10
  118. package/src/zod/tempo/SignatureEnvelope.ts +46 -59
  119. package/src/zod/tempo/TransactionRequest.ts +28 -14
  120. package/src/zod/tempo/_test/KeyAuthorization.test.ts +66 -30
  121. package/src/zod/tempo/_test/MultisigOperation.test.ts +0 -2
  122. package/src/zod/tempo/_test/MultisigSimulation.test-d.ts +13 -0
  123. package/src/zod/tempo/_test/MultisigSimulation.test.ts +53 -0
  124. package/src/zod/tempo/_test/RpcSchemaTempo.test-d.ts +19 -2
  125. package/src/zod/tempo/_test/RpcSchemaTempo.test.ts +46 -4
  126. package/src/zod/tempo/_test/SignatureEnvelope.test.ts +108 -129
  127. package/src/zod/tempo/_test/TransactionRequest.test.ts +17 -168
  128. package/src/zod/tempo/z.ts +1 -1
  129. package/dist/tempo/MultisigWitness.d.ts +0 -106
  130. package/dist/tempo/MultisigWitness.d.ts.map +0 -1
  131. package/dist/tempo/MultisigWitness.js +0 -118
  132. package/dist/tempo/MultisigWitness.js.map +0 -1
  133. package/dist/zod/tempo/MultisigWitness.d.ts +0 -152
  134. package/dist/zod/tempo/MultisigWitness.d.ts.map +0 -1
  135. package/dist/zod/tempo/MultisigWitness.js +0 -76
  136. package/dist/zod/tempo/MultisigWitness.js.map +0 -1
  137. package/src/tempo/MultisigWitness.test-d.ts +0 -42
  138. package/src/tempo/MultisigWitness.test.ts +0 -288
  139. package/src/tempo/MultisigWitness.ts +0 -210
  140. package/src/zod/tempo/MultisigWitness.ts +0 -101
  141. package/src/zod/tempo/_test/MultisigWitness.test-d.ts +0 -13
  142. package/src/zod/tempo/_test/MultisigWitness.test.ts +0 -149
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  /** @internal */
2
- export const version = '1.7.2'
2
+ export const version = '1.7.5'
@@ -9,16 +9,6 @@ import {
9
9
  import * as z from 'zod/mini'
10
10
  import * as z_SignatureEnvelope from './SignatureEnvelope.js'
11
11
 
12
- const SignatureRpc = z.union([
13
- z_SignatureEnvelope.PrimitiveRpc,
14
- z_SignatureEnvelope.MultisigRpc,
15
- ])
16
-
17
- const Signature = z.union([
18
- z_SignatureEnvelope.Primitive,
19
- z_SignatureEnvelope.Multisig,
20
- ])
21
-
22
12
  /** RPC token spending limit schema. */
23
13
  export const RpcTokenLimit = z.object({
24
14
  limit: z_Hex.Hex,
@@ -39,18 +29,28 @@ export const RpcCallScope = z.object({
39
29
  })
40
30
 
41
31
  /** RPC key authorization schema. */
42
- export const Rpc = z.object({
43
- account: z.optional(z.nullable(z_Address.Address)),
44
- allowedCalls: z.optional(z.nullable(z.readonly(z.array(RpcCallScope)))),
45
- chainId: z_Hex.Hex,
46
- expiry: z.optional(z.nullable(z_Hex.Hex)),
47
- isAdmin: z.optional(z.nullable(z.boolean())),
48
- keyId: z_Address.Address,
49
- keyType: z_SignatureEnvelope.Type,
50
- limits: z.optional(z.nullable(z.readonly(z.array(RpcTokenLimit)))),
51
- signature: SignatureRpc,
52
- witness: z.optional(z.nullable(z_Hex.Hex)),
53
- })
32
+ export const Rpc = z
33
+ .object({
34
+ account: z.optional(z.nullable(z_Address.Address)),
35
+ allowedCalls: z.optional(z.nullable(z.readonly(z.array(RpcCallScope)))),
36
+ chainId: z_Hex.Hex,
37
+ expiry: z.optional(z.nullable(z_Hex.Hex)),
38
+ isAdmin: z.optional(z.nullable(z.boolean())),
39
+ keyId: z_Address.Address,
40
+ keyType: z.union([z_SignatureEnvelope.Type, z.literal('multisig')]),
41
+ limits: z.optional(z.nullable(z.readonly(z.array(RpcTokenLimit)))),
42
+ signature: z.union([
43
+ z_SignatureEnvelope.PrimitiveRpc,
44
+ z_SignatureEnvelope.MultisigRpc,
45
+ ]),
46
+ witness: z.optional(z.nullable(z_Hex.Hex)),
47
+ })
48
+ .check(
49
+ z.refine(
50
+ (value) => value.keyType !== 'multisig' || value.account != null,
51
+ 'multisig key grants require a parent account binding',
52
+ ),
53
+ )
54
54
 
55
55
  /** Token spending limit schema. */
56
56
  export const TokenLimit = z.object({
@@ -79,20 +79,27 @@ const domainShape = {
79
79
  expiry: z.optional(z.number()),
80
80
  limits: z.optional(z.readonly(z.array(TokenLimit))),
81
81
  scopes: z.optional(z.readonly(z.array(Scope))),
82
- signature: Signature,
83
- type: z_SignatureEnvelope.Type,
82
+ signature: z.union([
83
+ z_SignatureEnvelope.Primitive,
84
+ z_SignatureEnvelope.Multisig,
85
+ ]),
86
+ type: z.union([z_SignatureEnvelope.Type, z.literal('multisig')]),
84
87
  witness: z.optional(z_Hex.Hex),
85
88
  }
86
89
 
87
- /** Decoded key authorization schema (TIP-1049 admin fields are paired: both or neither). */
88
- export const Domain = z.union([
89
- z.object({
90
+ /** Decoded key authorization schema. */
91
+ export const Domain = z
92
+ .object({
90
93
  ...domainShape,
91
- account: z_Address.Address,
92
- isAdmin: z.boolean(),
93
- }),
94
- z.object(domainShape),
95
- ])
94
+ account: z.optional(z_Address.Address),
95
+ isAdmin: z.optional(z.boolean()),
96
+ })
97
+ .check(
98
+ z.refine(
99
+ (value) => value.type !== 'multisig' || value.account != null,
100
+ 'multisig key grants require a parent account binding',
101
+ ),
102
+ )
96
103
 
97
104
  const domainToRpcShape = {
98
105
  ...domainShape,
@@ -102,14 +109,18 @@ const domainToRpcShape = {
102
109
  }
103
110
 
104
111
  /** Encode-only decoded key authorization schema accepting numberish `toRpc` inputs. */
105
- export const DomainToRpc = z.union([
106
- z.object({
112
+ export const DomainToRpc = z
113
+ .object({
107
114
  ...domainToRpcShape,
108
- account: z_Address.Address,
109
- isAdmin: z.boolean(),
110
- }),
111
- z.object(domainToRpcShape),
112
- ])
115
+ account: z.optional(z_Address.Address),
116
+ isAdmin: z.optional(z.boolean()),
117
+ })
118
+ .check(
119
+ z.refine(
120
+ (value) => value.type !== 'multisig' || value.account != null,
121
+ 'multisig key grants require a parent account binding',
122
+ ),
123
+ )
113
124
 
114
125
  /** Codec decoding an RPC key authorization into a signed key authorization. */
115
126
  export const KeyAuthorization = z.codec(Rpc, Domain, {
@@ -3,7 +3,6 @@ import * as core_MultisigOperation from '../../tempo/MultisigOperation.js'
3
3
  import * as z_Address from '../Address.js'
4
4
  import * as z_Hash from '../Hash.js'
5
5
  import * as z_Hex from '../Hex.js'
6
- import * as z_Uint from '../Uint.js'
7
6
  import * as z from 'zod/mini'
8
7
  import * as z_MultisigConfig from './MultisigConfig.js'
9
8
 
@@ -12,10 +11,8 @@ function baseFields() {
12
11
  account: z_Address.Address,
13
12
  approvals: z.readonly(z.array(z_Hex.Hex)),
14
13
  config: z_MultisigConfig.MultisigConfig,
15
- configVersion: z_Uint.Uint64,
16
14
  createdAt: z.number(),
17
15
  hash: z_Hash.Hash,
18
- init: z.boolean(),
19
16
  signatureCount: z.number(),
20
17
  threshold: z.number(),
21
18
  updatedAt: z.number(),
@@ -0,0 +1,53 @@
1
+ /* eslint-disable jsdoc-js/require-jsdoc, jsdoc-js/require-description, jsdoc-js/require-example */
2
+ import * as core_MultisigConfig from '../../tempo/MultisigConfig.js'
3
+ import * as core_MultisigSimulation from '../../tempo/MultisigSimulation.js'
4
+ import * as z_Address from '../Address.js'
5
+ import * as z_Hex from '../Hex.js'
6
+ import * as z from 'zod/mini'
7
+ import * as z_MultisigConfig from './MultisigConfig.js'
8
+ import * as z_SignatureEnvelope from './SignatureEnvelope.js'
9
+
10
+ const PrimitiveApproval = z.strictObject({
11
+ keyData: z.optional(z_Hex.Hex),
12
+ keyType: z.optional(z_SignatureEnvelope.Type),
13
+ owner: z_Address.Address,
14
+ })
15
+
16
+ /** Native multisig simulation spec schema. */
17
+ export const Domain = z.object({
18
+ approvals: z.readonly(
19
+ z
20
+ .array(PrimitiveApproval)
21
+ .check(z.maxLength(core_MultisigConfig.maxSignatures)),
22
+ ),
23
+ config: z_MultisigConfig.Config,
24
+ })
25
+
26
+ const Rpc_ = z
27
+ .object({
28
+ approvals: z.readonly(
29
+ z
30
+ .array(PrimitiveApproval)
31
+ .check(z.maxLength(core_MultisigConfig.maxSignatures)),
32
+ ),
33
+ config: z_Hex.Hex,
34
+ })
35
+ .check(
36
+ z.refine((value) => {
37
+ try {
38
+ core_MultisigSimulation.fromRpc(value)
39
+ return true
40
+ } catch {
41
+ return false
42
+ }
43
+ }, 'expected valid native multisig simulation spec'),
44
+ )
45
+
46
+ /** Codec decoding an RPC multisig simulation spec into its domain representation. */
47
+ export const MultisigSimulation = z.codec(Rpc_, Domain, {
48
+ decode: (value) => core_MultisigSimulation.fromRpc(value),
49
+ encode: (value) => core_MultisigSimulation.toRpc(value),
50
+ })
51
+
52
+ /** RPC native multisig simulation spec schema. */
53
+ export const Rpc = Rpc_
@@ -1,4 +1,5 @@
1
1
  /* eslint-disable jsdoc-js/require-jsdoc, jsdoc-js/require-description, jsdoc-js/require-example */
2
+ import * as z_Address from '../Address.js'
2
3
  import * as z_Block from '../Block.js'
3
4
  import * as z_BlockOverrides from '../BlockOverrides.js'
4
5
  import * as z_Hex from '../Hex.js'
@@ -7,6 +8,7 @@ import * as z_StateOverrides from '../StateOverrides.js'
7
8
  import { from } from '../internal/rpcSchemas/from.js'
8
9
  import * as z from 'zod/mini'
9
10
  import * as z_KeyAuthorization from './KeyAuthorization.js'
11
+ import * as z_MultisigConfig from './MultisigConfig.js'
10
12
  import * as z_MultisigOperation from './MultisigOperation.js'
11
13
  import * as z_TransactionRequest from './TransactionRequest.js'
12
14
 
@@ -88,6 +90,18 @@ export const tempo_simulateV1 = from({
88
90
  /** JSON-RPC method schemas for the `tempo_` namespace. */
89
91
  export const Tempo = { tempo_simulateV1 }
90
92
 
93
+ /** Schema for the `multisig_approveKeyAuthorization` JSON-RPC method. */
94
+ export const multisig_approveKeyAuthorization = from({
95
+ method: 'multisig_approveKeyAuthorization',
96
+ params: z.tuple([
97
+ z.union([
98
+ z.object({ keyAuthorization: z_KeyAuthorization.Rpc }),
99
+ z.object({ hash: z_Hex.Hex, signature: z_Hex.Hex }),
100
+ ]),
101
+ ]),
102
+ returns: z_MultisigOperation.KeyAuthorizationOperation,
103
+ })
104
+
91
105
  /** Schema for the `multisig_approveRawTransaction` JSON-RPC method. */
92
106
  export const multisig_approveRawTransaction = from({
93
107
  method: 'multisig_approveRawTransaction',
@@ -102,16 +116,11 @@ export const multisig_approveRawTransactionSync = from({
102
116
  returns: z_MultisigOperation.TransactionOperation,
103
117
  })
104
118
 
105
- /** Schema for the `multisig_approveKeyAuthorization` JSON-RPC method. */
106
- export const multisig_approveKeyAuthorization = from({
107
- method: 'multisig_approveKeyAuthorization',
108
- params: z.tuple([
109
- z.union([
110
- z.object({ keyAuthorization: z_KeyAuthorization.Rpc }),
111
- z.object({ hash: z_Hex.Hex, signature: z_Hex.Hex }),
112
- ]),
113
- ]),
114
- returns: z_MultisigOperation.KeyAuthorizationOperation,
119
+ /** Schema for the `multisig_getConfig` JSON-RPC method. */
120
+ export const multisig_getConfig = from({
121
+ method: 'multisig_getConfig',
122
+ params: z.tuple([z.object({ address: z_Address.Address })]),
123
+ returns: z.nullable(z_MultisigConfig.Rpc),
115
124
  })
116
125
 
117
126
  /** Schema for the `multisig_getOperation` JSON-RPC method. */
@@ -126,5 +135,6 @@ export const Multisig = {
126
135
  multisig_approveKeyAuthorization,
127
136
  multisig_approveRawTransaction,
128
137
  multisig_approveRawTransactionSync,
138
+ multisig_getConfig,
129
139
  multisig_getOperation,
130
140
  }
@@ -72,39 +72,18 @@ export const WebAuthnRpc = z.object({
72
72
  export const PrimitiveRpc = z.union([Secp256k1Rpc, P256Rpc, WebAuthnRpc])
73
73
 
74
74
  /** RPC keychain signature envelope schema. */
75
- export const KeychainRpc = z.object({
76
- keyId: z.optional(z_Address.Address),
77
- // `signature` is recursive; type the getter concretely to break the cycle.
78
- signature: z.lazy(
79
- (): z.ZodMiniType<core_SignatureEnvelope.SignatureEnvelopeRpc> =>
80
- Rpc as never,
81
- ),
82
- type: z.literal('keychain'),
83
- userAddress: z_Address.Address,
84
- version: z.optional(KeychainVersion),
85
- })
86
-
87
- /** RPC native multisig signature envelope schema. */
88
- export const MultisigRpc = z
89
- .strictObject({
90
- account: z_Address.Address,
91
- config: z_MultisigConfig.Rpc,
92
- signatures: z.lazy(
93
- (): z.ZodMiniType<
94
- readonly core_SignatureEnvelope.SignatureEnvelopeRpc[],
95
- readonly core_SignatureEnvelope.SignatureEnvelopeRpc[]
96
- > =>
97
- z.readonly(
98
- z
99
- .array(Rpc)
100
- .check(
101
- z.minLength(1),
102
- z.maxLength(core_MultisigConfig.maxSignatures),
103
- ),
104
- ) as never,
75
+ export const KeychainRpc = z
76
+ .object({
77
+ keyId: z.optional(z_Address.Address),
78
+ // `signature` is recursive; type the getter concretely to break the cycle.
79
+ signature: z.lazy(
80
+ (): z.ZodMiniType<core_SignatureEnvelope.SignatureEnvelopeRpc> =>
81
+ Rpc as never,
105
82
  ),
83
+ type: z.literal('keychain'),
84
+ userAddress: z_Address.Address,
85
+ version: z.optional(KeychainVersion),
106
86
  })
107
- // Keep invalid recursive approvals inside Zod's issue path.
108
87
  .check(
109
88
  z.refine((value) => {
110
89
  try {
@@ -113,9 +92,21 @@ export const MultisigRpc = z
113
92
  } catch {
114
93
  return false
115
94
  }
116
- }, 'expected valid native multisig signature'),
95
+ }, 'multisig access keys require keychain V2'),
117
96
  )
118
97
 
98
+ /** RPC native multisig signature envelope schema. */
99
+ export const MultisigRpc = z_Hex.Hex.check(
100
+ z.refine((value) => {
101
+ try {
102
+ core_SignatureEnvelope.fromRpc(value)
103
+ return true
104
+ } catch {
105
+ return false
106
+ }
107
+ }, 'expected valid native multisig signature'),
108
+ )
109
+
119
110
  /** RPC signature envelope schema. */
120
111
  export const Rpc = z.union([
121
112
  Secp256k1Rpc,
@@ -154,34 +145,34 @@ export const WebAuthn = z.object({
154
145
  export const Primitive = z.union([Secp256k1, P256, WebAuthn])
155
146
 
156
147
  /** Keychain signature envelope schema. */
157
- export const Keychain = z.object({
158
- // `inner` is recursive; type the getter concretely to break the cycle.
159
- inner: z.lazy(
160
- (): z.ZodMiniType<core_SignatureEnvelope.SignatureEnvelope> =>
161
- Domain as never,
162
- ),
163
- keyId: z.optional(z_Address.Address),
164
- type: z.literal('keychain'),
165
- userAddress: z_Address.Address,
166
- version: z.optional(KeychainVersion),
167
- })
148
+ export const Keychain = z
149
+ .object({
150
+ // `inner` is recursive; type the getter concretely to break the cycle.
151
+ inner: z.lazy(
152
+ (): z.ZodMiniType<core_SignatureEnvelope.SignatureEnvelope> =>
153
+ Domain as never,
154
+ ),
155
+ keyId: z.optional(z_Address.Address),
156
+ type: z.literal('keychain'),
157
+ userAddress: z_Address.Address,
158
+ version: z.optional(KeychainVersion),
159
+ })
160
+ .check(
161
+ z.refine(
162
+ (value) => core_SignatureEnvelope.validate(value),
163
+ 'multisig access keys require keychain V2',
164
+ ),
165
+ )
168
166
 
169
167
  /** Native multisig signature envelope schema. */
170
168
  export const Multisig = z
171
169
  .object({
172
170
  account: z_Address.Address,
173
171
  config: z_MultisigConfig.Config,
174
- // `signatures` is recursive; type the getter concretely to break the cycle.
175
- signatures: z.lazy(
176
- (): z.ZodMiniType<readonly core_SignatureEnvelope.SignatureEnvelope[]> =>
177
- z.readonly(
178
- z
179
- .array(Domain)
180
- .check(
181
- z.minLength(1),
182
- z.maxLength(core_MultisigConfig.maxSignatures),
183
- ),
184
- ) as never,
172
+ signatures: z.readonly(
173
+ z
174
+ .array(Primitive)
175
+ .check(z.minLength(1), z.maxLength(core_MultisigConfig.maxSignatures)),
185
176
  ),
186
177
  type: z.literal('multisig'),
187
178
  })
@@ -209,6 +200,7 @@ export const Serialized = z_Hex.Hex
209
200
  function fromRpc(
210
201
  value: core_SignatureEnvelope.SignatureEnvelopeRpc,
211
202
  ): core_SignatureEnvelope.SignatureEnvelope {
203
+ if (typeof value === 'string') return core_SignatureEnvelope.fromRpc(value)
212
204
  if (value.type === 'secp256k1') {
213
205
  const secp256k1 = value as core_SignatureEnvelope.Secp256k1Rpc
214
206
  return {
@@ -255,11 +247,6 @@ function fromRpc(
255
247
  }
256
248
  }
257
249
 
258
- if ('config' in value && 'signatures' in value)
259
- return core_SignatureEnvelope.fromRpc(
260
- value as core_SignatureEnvelope.MultisigRpc,
261
- )
262
-
263
250
  const keychain = value as core_SignatureEnvelope.KeychainRpc
264
251
  return {
265
252
  inner: fromRpc(keychain.signature),
@@ -13,7 +13,7 @@ import {
13
13
  import * as z from 'zod/mini'
14
14
  import * as z_AuthorizationTempo from './AuthorizationTempo.js'
15
15
  import * as z_KeyAuthorization from './KeyAuthorization.js'
16
- import * as z_MultisigWitness from './MultisigWitness.js'
16
+ import * as z_MultisigSimulation from './MultisigSimulation.js'
17
17
  import * as z_SignatureEnvelope from './SignatureEnvelope.js'
18
18
 
19
19
  const fromRpcType = { '0x76': 'tempo' } as const
@@ -23,6 +23,7 @@ const KeyType = z.union([
23
23
  z.literal('secp256k1'),
24
24
  z.literal('p256'),
25
25
  z.literal('webAuthn'),
26
+ z.literal('multisig'),
26
27
  ])
27
28
 
28
29
  const SignatureRpc = z.object({
@@ -83,7 +84,8 @@ export const Rpc = z.object({
83
84
  maxFeePerBlobGas: z.optional(z_Hex.Hex),
84
85
  maxFeePerGas: z.optional(z_Hex.Hex),
85
86
  maxPriorityFeePerGas: z.optional(z_Hex.Hex),
86
- multisigWitness: z.optional(z_MultisigWitness.Rpc),
87
+ keyAuthorizationSimulation: z.optional(z_MultisigSimulation.Rpc),
88
+ multisigSimulation: z.optional(z_MultisigSimulation.Rpc),
87
89
  nonce: z.optional(z_Hex.Hex),
88
90
  nonceKey: z.optional(z_Hex.Hex),
89
91
  r: z.optional(z_Hex.Hex),
@@ -136,7 +138,8 @@ export const Domain = z.object({
136
138
  maxFeePerBlobGas: z.optional(z.bigint()),
137
139
  maxFeePerGas: z.optional(z.bigint()),
138
140
  maxPriorityFeePerGas: z.optional(z.bigint()),
139
- multisigWitness: z.optional(z_MultisigWitness.Domain),
141
+ keyAuthorizationSimulation: z.optional(z_MultisigSimulation.Domain),
142
+ multisigSimulation: z.optional(z_MultisigSimulation.Domain),
140
143
  nonce: z.optional(z.bigint()),
141
144
  nonceKey: z.optional(z.union([z.bigint(), z.literal('random')])),
142
145
  r: z.optional(z_Hex.Hex),
@@ -175,7 +178,8 @@ export const DomainToRpc = z.object({
175
178
  maxFeePerBlobGas: z.optional(uintBigintNumberish()),
176
179
  maxFeePerGas: z.optional(uintBigintNumberish()),
177
180
  maxPriorityFeePerGas: z.optional(uintBigintNumberish()),
178
- multisigWitness: z.optional(z_MultisigWitness.Domain),
181
+ keyAuthorizationSimulation: z.optional(z_MultisigSimulation.Domain),
182
+ multisigSimulation: z.optional(z_MultisigSimulation.Domain),
179
183
  nonce: z.optional(uintBigintNumberish()),
180
184
  nonceKey: z.optional(z.union([uintBigintNumberish(), z.literal('random')])),
181
185
  r: z.optional(z_Hex.Hex),
@@ -206,7 +210,7 @@ export const TransactionRequestToRpc = z.codec(Rpc, DomainToRpc, {
206
210
  function fromRpc(
207
211
  request: core_TransactionRequest.Rpc,
208
212
  ): core_TransactionRequest.TransactionRequest {
209
- const { authorizationList: _, multisigWitness: __, ...rest } = request
213
+ const { authorizationList: _, multisigSimulation: __, ...rest } = request
210
214
  const request_ = z.decode(
211
215
  z_TransactionRequest.TransactionRequest,
212
216
  rest as never,
@@ -250,10 +254,15 @@ function fromRpc(
250
254
  if (typeof request.keyData !== 'undefined') request_.keyData = request.keyData
251
255
  if (typeof request.keyId !== 'undefined') request_.keyId = request.keyId
252
256
  if (typeof request.keyType !== 'undefined') request_.keyType = request.keyType
253
- if (typeof request.multisigWitness !== 'undefined')
254
- request_.multisigWitness = z.decode(
255
- z_MultisigWitness.MultisigWitness,
256
- request.multisigWitness,
257
+ if (typeof request.keyAuthorizationSimulation !== 'undefined')
258
+ request_.keyAuthorizationSimulation = z.decode(
259
+ z_MultisigSimulation.MultisigSimulation,
260
+ request.keyAuthorizationSimulation,
261
+ )
262
+ if (typeof request.multisigSimulation !== 'undefined')
263
+ request_.multisigSimulation = z.decode(
264
+ z_MultisigSimulation.MultisigSimulation,
265
+ request.multisigSimulation,
257
266
  )
258
267
  if (typeof request.validBefore !== 'undefined')
259
268
  request_.validBefore = core_Hex.toNumber(request.validBefore)
@@ -283,7 +292,7 @@ function toRpc(
283
292
  typeof request.keyData !== 'undefined' ||
284
293
  typeof request.keyId !== 'undefined' ||
285
294
  typeof request.keyType !== 'undefined' ||
286
- typeof request.multisigWitness !== 'undefined' ||
295
+ typeof request.multisigSimulation !== 'undefined' ||
287
296
  typeof request.nonceKey !== 'undefined' ||
288
297
  typeof request.validBefore !== 'undefined' ||
289
298
  typeof request.validAfter !== 'undefined' ||
@@ -338,10 +347,15 @@ function toRpc(
338
347
  if (typeof request.keyId !== 'undefined') request_rpc.keyId = request.keyId
339
348
  if (typeof request.keyType !== 'undefined')
340
349
  request_rpc.keyType = request.keyType
341
- if (typeof request.multisigWitness !== 'undefined')
342
- request_rpc.multisigWitness = z.encode(
343
- z_MultisigWitness.MultisigWitness,
344
- request.multisigWitness,
350
+ if (typeof request.keyAuthorizationSimulation !== 'undefined')
351
+ request_rpc.keyAuthorizationSimulation = z.encode(
352
+ z_MultisigSimulation.MultisigSimulation,
353
+ request.keyAuthorizationSimulation,
354
+ )
355
+ if (typeof request.multisigSimulation !== 'undefined')
356
+ request_rpc.multisigSimulation = z.encode(
357
+ z_MultisigSimulation.MultisigSimulation,
358
+ request.multisigSimulation,
345
359
  )
346
360
  if (typeof request.validBefore !== 'undefined')
347
361
  request_rpc.validBefore = encodeNumberish(request.validBefore)
@@ -1,4 +1,5 @@
1
1
  import { describe, expect, test } from 'vp/test'
2
+ import * as core_SignatureEnvelope from '../../../tempo/SignatureEnvelope.js'
2
3
  import * as core_KeyAuthorization from '../../../tempo/KeyAuthorization.js'
3
4
  import * as z_KeyAuthorization from '../KeyAuthorization.js'
4
5
  import * as z from 'zod/mini'
@@ -20,6 +21,35 @@ const rpc = {
20
21
  } as const
21
22
 
22
23
  describe('KeyAuthorization', () => {
24
+ test('rejects unbound multisig grants through every schema', () => {
25
+ const domain = {
26
+ ...z.decode(z_KeyAuthorization.KeyAuthorization, rpc),
27
+ type: 'multisig',
28
+ } as const
29
+ for (const account of [undefined, null])
30
+ expect(
31
+ z.safeDecode(z_KeyAuthorization.KeyAuthorization, {
32
+ ...rpc,
33
+ keyType: 'multisig',
34
+ account,
35
+ }).success,
36
+ ).toMatchInlineSnapshot(`false`)
37
+ for (const schema of [
38
+ z_KeyAuthorization.Domain,
39
+ z_KeyAuthorization.DomainToRpc,
40
+ ]) {
41
+ expect(z.safeParse(schema, domain).success).toMatchInlineSnapshot(`false`)
42
+ expect(
43
+ z.safeParse(schema, { ...domain, account: rpc.keyId }).success,
44
+ ).toMatchInlineSnapshot(`true`)
45
+ }
46
+ for (const codec of [
47
+ z_KeyAuthorization.KeyAuthorization,
48
+ z_KeyAuthorization.KeyAuthorizationToRpc,
49
+ ])
50
+ expect(z.safeEncode(codec, domain).success).toMatchInlineSnapshot(`false`)
51
+ })
52
+
23
53
  test('decodes an RPC key authorization', () => {
24
54
  expect(z.decode(z_KeyAuthorization.KeyAuthorization, rpc)).toEqual(
25
55
  core_KeyAuthorization.fromRpc(rpc),
@@ -141,40 +171,15 @@ describe('KeyAuthorization', () => {
141
171
  ).toBe(false)
142
172
  })
143
173
 
144
- test('round-trips multisig signatures', () => {
174
+ test('rejects legacy multisig signatures', () => {
145
175
  const multisigRpc = {
146
176
  account: '0x1111111111111111111111111111111111111111',
147
- config: {
148
- owners: [
149
- {
150
- owner: '0x2222222222222222222222222222222222222222',
151
- weight: 1,
152
- },
153
- ],
154
- salt: '0x0000000000000000000000000000000000000000000000000000000000000000',
155
- threshold: 1,
156
- version: '0x1',
157
- },
158
177
  signatures: [rpc.signature],
159
178
  } as const
160
- const withMultisig = { ...rpc, signature: multisigRpc }
161
- const decoded = z.decode(z_KeyAuthorization.KeyAuthorization, withMultisig)
162
- expect(decoded).toEqual(core_KeyAuthorization.fromRpc(withMultisig))
163
- expect(z.encode(z_KeyAuthorization.KeyAuthorization, decoded)).toEqual(
164
- core_KeyAuthorization.toRpc(decoded),
165
- )
166
- })
167
-
168
- test('rejects keychain signatures', () => {
169
- const keychainRpc = {
170
- signature: rpc.signature,
171
- type: 'keychain',
172
- userAddress: '0x1111111111111111111111111111111111111111',
173
- } as const
174
179
  expect(
175
180
  z.safeDecode(z_KeyAuthorization.KeyAuthorization, {
176
181
  ...rpc,
177
- signature: keychainRpc,
182
+ signature: multisigRpc,
178
183
  } as never).success,
179
184
  ).toBe(false)
180
185
 
@@ -183,11 +188,42 @@ describe('KeyAuthorization', () => {
183
188
  z.safeEncode(z_KeyAuthorization.KeyAuthorization, {
184
189
  ...authorization,
185
190
  signature: {
186
- inner: authorization.signature,
187
- type: 'keychain',
188
- userAddress: keychainRpc.userAddress,
191
+ account: multisigRpc.account,
192
+ signatures: [authorization.signature],
193
+ type: 'multisig',
189
194
  },
190
195
  } as never).success,
191
196
  ).toBe(false)
192
197
  })
198
+ test('round-trips account-bound multisig grants', () => {
199
+ const signature = core_SignatureEnvelope.from({
200
+ account: '0x2222222222222222222222222222222222222222',
201
+ config: {
202
+ threshold: 1,
203
+ owners: [
204
+ { owner: '0x1111111111111111111111111111111111111111', weight: 1 },
205
+ ],
206
+ },
207
+ signatures: [
208
+ core_SignatureEnvelope.fromRpc(
209
+ rpc.signature,
210
+ ) as core_SignatureEnvelope.Primitive,
211
+ ],
212
+ })
213
+ const signed = core_KeyAuthorization.from(
214
+ {
215
+ account: signature.account,
216
+ address: '0x3333333333333333333333333333333333333333',
217
+ chainId: 1n,
218
+ type: 'multisig',
219
+ },
220
+ { signature },
221
+ )
222
+ const encoded = z.encode(z_KeyAuthorization.KeyAuthorization, signed)
223
+ const decoded = z.decode(z_KeyAuthorization.KeyAuthorization, encoded)
224
+ expect(decoded).toEqual(
225
+ core_KeyAuthorization.fromRpc(core_KeyAuthorization.toRpc(signed)),
226
+ )
227
+ expect(decoded.account).toBe(signature.account)
228
+ })
193
229
  })
@@ -23,10 +23,8 @@ const rpc = {
23
23
  threshold: 2,
24
24
  version: '0x1',
25
25
  },
26
- configVersion: '0x1',
27
26
  createdAt: 1,
28
27
  hash: '0xcdbc24a8fb192f799c5d166b13a99fb29cbb15e71a5e730988d6f8b3c5959d02',
29
- init: false,
30
28
  signatureCount: 1,
31
29
  status: 'pending',
32
30
  threshold: 2,
@@ -0,0 +1,13 @@
1
+ import type * as core_MultisigSimulation from '../../../tempo/MultisigSimulation.js'
2
+ import type * as z from 'zod/mini'
3
+ import { expectTypeOf, test } from 'vp/test'
4
+ import * as z_MultisigSimulation from '../MultisigSimulation.js'
5
+
6
+ test('MultisigSimulation decodes RPC specs', () => {
7
+ expectTypeOf<core_MultisigSimulation.Rpc>().toMatchTypeOf<
8
+ z.input<typeof z_MultisigSimulation.MultisigSimulation>
9
+ >()
10
+ expectTypeOf<
11
+ z.output<typeof z_MultisigSimulation.MultisigSimulation>
12
+ >().toMatchTypeOf<core_MultisigSimulation.Spec>()
13
+ })