ox 1.8.5 → 1.8.7

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 (137) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/dist/tempo/{MultisigConfig.d.ts → AccountConfig.d.ts} +116 -63
  3. package/dist/tempo/AccountConfig.d.ts.map +1 -0
  4. package/dist/tempo/{MultisigConfig.js → AccountConfig.js} +109 -55
  5. package/dist/tempo/AccountConfig.js.map +1 -0
  6. package/dist/tempo/{MultisigOperation.d.ts → AccountOperation.d.ts} +62 -62
  7. package/dist/tempo/AccountOperation.d.ts.map +1 -0
  8. package/dist/tempo/{MultisigOperation.js → AccountOperation.js} +64 -64
  9. package/dist/tempo/AccountOperation.js.map +1 -0
  10. package/dist/tempo/{MultisigSimulation.d.ts → AccountSimulation.d.ts} +21 -21
  11. package/dist/tempo/AccountSimulation.d.ts.map +1 -0
  12. package/dist/tempo/{MultisigSimulation.js → AccountSimulation.js} +20 -20
  13. package/dist/tempo/AccountSimulation.js.map +1 -0
  14. package/dist/tempo/KeyAuthorization.d.ts +37 -27
  15. package/dist/tempo/KeyAuthorization.d.ts.map +1 -1
  16. package/dist/tempo/KeyAuthorization.js +17 -19
  17. package/dist/tempo/KeyAuthorization.js.map +1 -1
  18. package/dist/tempo/RpcSchemaTempo.d.ts +13 -13
  19. package/dist/tempo/RpcSchemaTempo.d.ts.map +1 -1
  20. package/dist/tempo/SignatureEnvelope.d.ts +36 -33
  21. package/dist/tempo/SignatureEnvelope.d.ts.map +1 -1
  22. package/dist/tempo/SignatureEnvelope.js +77 -77
  23. package/dist/tempo/SignatureEnvelope.js.map +1 -1
  24. package/dist/tempo/TokenRole.d.ts +4 -2
  25. package/dist/tempo/TokenRole.d.ts.map +1 -1
  26. package/dist/tempo/TokenRole.js +4 -1
  27. package/dist/tempo/TokenRole.js.map +1 -1
  28. package/dist/tempo/TransactionRequest.d.ts +11 -9
  29. package/dist/tempo/TransactionRequest.d.ts.map +1 -1
  30. package/dist/tempo/TransactionRequest.js +14 -10
  31. package/dist/tempo/TransactionRequest.js.map +1 -1
  32. package/dist/tempo/index.d.ts +56 -54
  33. package/dist/tempo/index.d.ts.map +1 -1
  34. package/dist/tempo/index.js +56 -54
  35. package/dist/tempo/index.js.map +1 -1
  36. package/dist/zod/tempo/{MultisigConfig.d.ts → AccountConfig.d.ts} +6 -6
  37. package/dist/zod/tempo/AccountConfig.d.ts.map +1 -0
  38. package/dist/zod/tempo/{MultisigConfig.js → AccountConfig.js} +12 -12
  39. package/dist/zod/tempo/AccountConfig.js.map +1 -0
  40. package/dist/zod/tempo/{MultisigOperation.d.ts → AccountOperation.d.ts} +5 -5
  41. package/dist/zod/tempo/AccountOperation.d.ts.map +1 -0
  42. package/dist/zod/tempo/{MultisigOperation.js → AccountOperation.js} +10 -10
  43. package/dist/zod/tempo/AccountOperation.js.map +1 -0
  44. package/dist/zod/tempo/{MultisigSimulation.d.ts → AccountSimulation.d.ts} +5 -5
  45. package/dist/zod/tempo/AccountSimulation.d.ts.map +1 -0
  46. package/dist/zod/tempo/AccountSimulation.js +44 -0
  47. package/dist/zod/tempo/AccountSimulation.js.map +1 -0
  48. package/dist/zod/tempo/AuthorizationTempo.d.ts +10 -10
  49. package/dist/zod/tempo/KeyAuthorization.d.ts +12 -12
  50. package/dist/zod/tempo/KeyAuthorization.js +6 -6
  51. package/dist/zod/tempo/KeyAuthorization.js.map +1 -1
  52. package/dist/zod/tempo/RpcSchemaTempo.d.ts +59 -59
  53. package/dist/zod/tempo/RpcSchemaTempo.d.ts.map +1 -1
  54. package/dist/zod/tempo/RpcSchemaTempo.js +28 -28
  55. package/dist/zod/tempo/RpcSchemaTempo.js.map +1 -1
  56. package/dist/zod/tempo/SignatureEnvelope.d.ts +7 -7
  57. package/dist/zod/tempo/SignatureEnvelope.d.ts.map +1 -1
  58. package/dist/zod/tempo/SignatureEnvelope.js +22 -16
  59. package/dist/zod/tempo/SignatureEnvelope.js.map +1 -1
  60. package/dist/zod/tempo/TokenRole.d.ts +1 -1
  61. package/dist/zod/tempo/TokenRole.d.ts.map +1 -1
  62. package/dist/zod/tempo/Transaction.d.ts +24 -24
  63. package/dist/zod/tempo/TransactionRequest.d.ts +84 -84
  64. package/dist/zod/tempo/TransactionRequest.d.ts.map +1 -1
  65. package/dist/zod/tempo/TransactionRequest.js +26 -17
  66. package/dist/zod/tempo/TransactionRequest.js.map +1 -1
  67. package/dist/zod/tempo/TxEnvelopeTempo.d.ts +12 -12
  68. package/dist/zod/tempo/ZoneRpcAuthentication.d.ts +3 -3
  69. package/dist/zod/tempo/z.d.ts +3 -3
  70. package/dist/zod/tempo/z.d.ts.map +1 -1
  71. package/dist/zod/tempo/z.js +3 -3
  72. package/dist/zod/tempo/z.js.map +1 -1
  73. package/package.json +31 -31
  74. package/src/tempo/{MultisigConfig.test-d.ts → AccountConfig.test-d.ts} +22 -12
  75. package/src/tempo/{MultisigConfig.test.ts → AccountConfig.test.ts} +155 -37
  76. package/src/tempo/{MultisigConfig.ts → AccountConfig.ts} +138 -66
  77. package/src/tempo/AccountOperation.test-d.ts +79 -0
  78. package/src/tempo/{MultisigOperation.test.ts → AccountOperation.test.ts} +97 -97
  79. package/src/tempo/{MultisigOperation.ts → AccountOperation.ts} +95 -97
  80. package/src/tempo/{MultisigSimulation.test-d.ts → AccountSimulation.test-d.ts} +7 -9
  81. package/src/tempo/{MultisigSimulation.test.ts → AccountSimulation.test.ts} +28 -28
  82. package/src/tempo/{MultisigSimulation.ts → AccountSimulation.ts} +28 -30
  83. package/src/tempo/KeyAuthorization.test-d.ts +15 -6
  84. package/src/tempo/KeyAuthorization.test.ts +117 -37
  85. package/src/tempo/KeyAuthorization.ts +68 -59
  86. package/src/tempo/RpcSchemaTempo.test-d.ts +19 -19
  87. package/src/tempo/RpcSchemaTempo.ts +13 -13
  88. package/src/tempo/SignatureEnvelope.test-d.ts +7 -7
  89. package/src/tempo/SignatureEnvelope.test.ts +34 -34
  90. package/src/tempo/SignatureEnvelope.ts +112 -108
  91. package/src/tempo/TokenRole.ts +4 -1
  92. package/src/tempo/Transaction.test.ts +4 -4
  93. package/src/tempo/TransactionRequest.test-d.ts +17 -6
  94. package/src/tempo/TransactionRequest.test.ts +32 -17
  95. package/src/tempo/TransactionRequest.ts +27 -19
  96. package/src/tempo/{multisig.e2e.test.ts → configurableAccounts.e2e.test.ts} +16 -16
  97. package/src/tempo/e2e.test.ts +32 -20
  98. package/src/tempo/index.ts +56 -54
  99. package/src/version.ts +1 -1
  100. package/src/zod/tempo/{MultisigConfig.ts → AccountConfig.ts} +12 -12
  101. package/src/zod/tempo/{MultisigOperation.ts → AccountOperation.ts} +9 -9
  102. package/src/zod/tempo/AccountSimulation.ts +53 -0
  103. package/src/zod/tempo/KeyAuthorization.ts +8 -8
  104. package/src/zod/tempo/RpcSchemaTempo.ts +28 -28
  105. package/src/zod/tempo/SignatureEnvelope.ts +23 -17
  106. package/src/zod/tempo/TransactionRequest.ts +29 -18
  107. package/src/zod/tempo/_test/AccountConfig.test-d.ts +13 -0
  108. package/src/zod/tempo/_test/{MultisigConfig.test.ts → AccountConfig.test.ts} +7 -7
  109. package/src/zod/tempo/_test/AccountOperation.test-d.ts +27 -0
  110. package/src/zod/tempo/_test/{MultisigOperation.test.ts → AccountOperation.test.ts} +9 -9
  111. package/src/zod/tempo/_test/AccountSimulation.test-d.ts +13 -0
  112. package/src/zod/tempo/_test/{MultisigSimulation.test.ts → AccountSimulation.test.ts} +13 -13
  113. package/src/zod/tempo/_test/KeyAuthorization.test.ts +9 -9
  114. package/src/zod/tempo/_test/RpcSchemaTempo.test-d.ts +27 -27
  115. package/src/zod/tempo/_test/RpcSchemaTempo.test.ts +16 -18
  116. package/src/zod/tempo/_test/SignatureEnvelope.test-d.ts +5 -5
  117. package/src/zod/tempo/_test/SignatureEnvelope.test.ts +12 -9
  118. package/src/zod/tempo/_test/TransactionRequest.test.ts +28 -8
  119. package/src/zod/tempo/z.ts +3 -3
  120. package/dist/tempo/MultisigConfig.d.ts.map +0 -1
  121. package/dist/tempo/MultisigConfig.js.map +0 -1
  122. package/dist/tempo/MultisigOperation.d.ts.map +0 -1
  123. package/dist/tempo/MultisigOperation.js.map +0 -1
  124. package/dist/tempo/MultisigSimulation.d.ts.map +0 -1
  125. package/dist/tempo/MultisigSimulation.js.map +0 -1
  126. package/dist/zod/tempo/MultisigConfig.d.ts.map +0 -1
  127. package/dist/zod/tempo/MultisigConfig.js.map +0 -1
  128. package/dist/zod/tempo/MultisigOperation.d.ts.map +0 -1
  129. package/dist/zod/tempo/MultisigOperation.js.map +0 -1
  130. package/dist/zod/tempo/MultisigSimulation.d.ts.map +0 -1
  131. package/dist/zod/tempo/MultisigSimulation.js +0 -44
  132. package/dist/zod/tempo/MultisigSimulation.js.map +0 -1
  133. package/src/tempo/MultisigOperation.test-d.ts +0 -79
  134. package/src/zod/tempo/MultisigSimulation.ts +0 -53
  135. package/src/zod/tempo/_test/MultisigConfig.test-d.ts +0 -13
  136. package/src/zod/tempo/_test/MultisigOperation.test-d.ts +0 -27
  137. package/src/zod/tempo/_test/MultisigSimulation.test-d.ts +0 -13
@@ -18,14 +18,14 @@ import * as ox_Secp256k1 from '../core/Secp256k1.js'
18
18
  import * as Signature from '../core/Signature.js'
19
19
  import type * as WebAuthnP256 from '../core/WebAuthnP256.js'
20
20
  import * as ox_WebAuthnP256 from '../core/WebAuthnP256.js'
21
- import * as MultisigConfig from './MultisigConfig.js'
21
+ import * as AccountConfig from './AccountConfig.js'
22
22
 
23
23
  /** Signature type identifiers for encoding/decoding */
24
24
  const serializedP256Type = '0x01'
25
25
  const serializedWebAuthnType = '0x02'
26
26
  const serializedKeychainType = '0x03'
27
27
  const serializedKeychainV2Type = '0x04'
28
- const serializedMultisigType = '0x05'
28
+ const serializedConfigurableType = '0x05'
29
29
 
30
30
  /** Serialized magic identifier for Tempo signature envelopes. */
31
31
  export const magicBytes =
@@ -86,10 +86,10 @@ export type GetType<
86
86
  ? 'keychain'
87
87
  : envelope extends {
88
88
  account: Address.Address
89
- config: MultisigConfig.Input
89
+ config: AccountConfig.Input
90
90
  signatures: any
91
91
  }
92
- ? 'multisig'
92
+ ? 'configurable'
93
93
  : never
94
94
 
95
95
  /**
@@ -113,6 +113,9 @@ export type GetType<
113
113
  * V2 binds the signature to the user account via `keccak256(sigHash || userAddress)`.
114
114
  * The protocol validates the access key authorization via the AccountKeychain precompile.
115
115
  *
116
+ * - **configurable** (type `0x05`): Configurable account signature carrying the account address,
117
+ * its complete current configuration, and primitive owner approvals over the version-bound digest.
118
+ *
116
119
  * [Signature Types Specification](https://docs.tempo.xyz/protocol/transactions/spec-tempo-transaction#signature-types)
117
120
  */
118
121
  export type SignatureEnvelope<numberType = number> = OneOf<
@@ -120,7 +123,7 @@ export type SignatureEnvelope<numberType = number> = OneOf<
120
123
  | P256<numberType>
121
124
  | WebAuthn<numberType>
122
125
  | Keychain<numberType>
123
- | Multisig<numberType>
126
+ | Configurable<numberType>
124
127
  >
125
128
 
126
129
  /**
@@ -128,7 +131,7 @@ export type SignatureEnvelope<numberType = number> = OneOf<
128
131
  */
129
132
  export type SignatureEnvelopeRpc =
130
133
  | OneOf<Secp256k1Rpc | P256Rpc | WebAuthnRpc | KeychainRpc>
131
- | MultisigRpc
134
+ | ConfigurableRpc
132
135
 
133
136
  /** Primitive signature envelope accepted by protocol sidecars. */
134
137
  export type Primitive<numberType = number> = OneOf<
@@ -168,24 +171,24 @@ export type KeychainRpc = {
168
171
  }
169
172
 
170
173
  /**
171
- * Native multisig signature (type `0x05`).
174
+ * Configurable account signature (type `0x05`).
172
175
  *
173
176
  * Carries the account's complete current configuration and primitive owner
174
177
  * approvals over its version-bound digest. The node validates the account
175
178
  * identity or stored commitment and the owner quorum against chain state.
176
179
  */
177
- export type Multisig<numberType = number> = {
178
- /** Permanent native multisig account address. */
180
+ export type Configurable<numberType = number> = {
181
+ /** Permanent account address. */
179
182
  account: Address.Address
180
183
  /** Complete current configuration, included in every signature. */
181
- config: MultisigConfig.Config<bigint, numberType>
184
+ config: AccountConfig.Config<bigint, numberType>
182
185
  /** Primitive owner approvals in ascending recovered-address order. */
183
186
  signatures: readonly Primitive<numberType>[]
184
- type: 'multisig'
187
+ type: 'configurable'
185
188
  }
186
189
 
187
190
  /** RLP-encoded `[account, config, signatures]`, without the `0x05` type byte. */
188
- export type MultisigRpc = Hex.Hex
191
+ export type ConfigurableRpc = Hex.Hex
189
192
 
190
193
  export type P256<numberType = number> = {
191
194
  prehash: boolean
@@ -328,9 +331,9 @@ export function assert(envelope: PartialBy<SignatureEnvelope, 'type'>): void {
328
331
  return
329
332
  }
330
333
 
331
- if (type === 'multisig') {
332
- const multisig = envelope as Multisig
333
- assertMultisig(multisig)
334
+ if (type === 'configurable') {
335
+ const configurable = envelope as Configurable
336
+ assertConfigurable(configurable)
334
337
  return
335
338
  }
336
339
  }
@@ -338,10 +341,10 @@ export function assert(envelope: PartialBy<SignatureEnvelope, 'type'>): void {
338
341
  export declare namespace assert {
339
342
  type ErrorType =
340
343
  | CoercionError
341
- | InvalidMultisigApprovalError
344
+ | InvalidApprovalError
342
345
  | MissingPropertiesError
343
- | MultisigConfig.assert.ErrorType
344
- | MultisigConfig.getAddress.ErrorType
346
+ | AccountConfig.assert.ErrorType
347
+ | AccountConfig.getAddress.ErrorType
345
348
  | Signature.assert.ErrorType
346
349
  | Errors.GlobalErrorType
347
350
  }
@@ -350,13 +353,13 @@ function assertKeychainVersion(keychain: Keychain): void {
350
353
  if (keychain.version !== 'v1') return
351
354
  let inner = keychain.inner
352
355
  while (getType(inner) === 'keychain') inner = (inner as Keychain).inner
353
- if (getType(inner) === 'multisig')
354
- throw new InvalidMultisigApprovalError({
355
- reason: 'multisig access keys require keychain V2',
356
+ if (getType(inner) === 'configurable')
357
+ throw new InvalidApprovalError({
358
+ reason: 'configurable access keys require keychain V2',
356
359
  })
357
360
  }
358
361
 
359
- function assertMultisig(envelope: Multisig): void {
362
+ function assertConfigurable(envelope: Configurable): void {
360
363
  const missing: string[] = []
361
364
  if (!envelope.account) missing.push('account')
362
365
  if (!envelope.config) missing.push('config')
@@ -365,47 +368,47 @@ function assertMultisig(envelope: Multisig): void {
365
368
  throw new MissingPropertiesError({
366
369
  envelope,
367
370
  missing,
368
- type: 'multisig',
371
+ type: 'configurable',
369
372
  })
370
373
  if (!Address.validate(envelope.account))
371
- throw new InvalidMultisigApprovalError({
372
- reason: 'multisig account is invalid',
374
+ throw new InvalidApprovalError({
375
+ reason: 'configurable account is invalid',
373
376
  })
374
377
  if (Hex.toBigInt(envelope.account) === 0n)
375
- throw new InvalidMultisigApprovalError({
376
- reason: 'multisig account cannot be zero',
378
+ throw new InvalidApprovalError({
379
+ reason: 'configurable account cannot be zero',
377
380
  })
378
381
  if (envelope.signatures.length === 0)
379
- throw new InvalidMultisigApprovalError({
380
- reason: 'multisig signatures cannot be empty',
382
+ throw new InvalidApprovalError({
383
+ reason: 'configurable signatures cannot be empty',
381
384
  })
382
- if (envelope.signatures.length > MultisigConfig.maxSignatures)
383
- throw new InvalidMultisigApprovalError({
384
- reason: `multisig signatures exceed ${MultisigConfig.maxSignatures}`,
385
+ if (envelope.signatures.length > AccountConfig.maxSignatures)
386
+ throw new InvalidApprovalError({
387
+ reason: `configurable signatures exceed ${AccountConfig.maxSignatures}`,
385
388
  })
386
389
 
387
- MultisigConfig.assert(envelope.config)
390
+ AccountConfig.assert(envelope.config)
388
391
  if (
389
392
  (envelope.config.version ?? 0n) === 0n &&
390
393
  envelope.config.owners.some((owner) =>
391
394
  Address.isEqual(owner.owner, envelope.account),
392
395
  )
393
396
  )
394
- throw new InvalidMultisigApprovalError({
397
+ throw new InvalidApprovalError({
395
398
  reason: 'initial account cannot be an owner',
396
399
  })
397
400
 
398
401
  for (const inner of envelope.signatures) {
399
402
  const type = getType(inner as SignatureEnvelope)
400
- if (type === 'keychain' || type === 'multisig')
401
- throw new InvalidMultisigApprovalError({
403
+ if (type === 'keychain' || type === 'configurable')
404
+ throw new InvalidApprovalError({
402
405
  reason: 'owner approvals must be primitive signatures',
403
406
  })
404
407
  assert(inner)
405
408
 
406
- if (Hex.size(serialize(inner)) > MultisigConfig.maxOwnerSignatureBytes)
407
- throw new InvalidMultisigApprovalError({
408
- reason: `multisig owner signature exceeds ${MultisigConfig.maxOwnerSignatureBytes} bytes`,
409
+ if (Hex.size(serialize(inner)) > AccountConfig.maxOwnerSignatureBytes)
410
+ throw new InvalidApprovalError({
411
+ reason: `configurable owner signature exceeds ${AccountConfig.maxOwnerSignatureBytes} bytes`,
409
412
  })
410
413
  }
411
414
  }
@@ -447,9 +450,9 @@ export function extractAddress(
447
450
  if (root) return signature.userAddress
448
451
  return extractAddress({ ...options, signature: signature.inner })
449
452
  }
450
- // Native multisig signatures have no single signer; the recovered sender is the
451
- // derived multisig account address.
452
- if (signature.type === 'multisig') return signature.account
453
+ // Configurable signatures have no single signer; the recovered sender is the
454
+ // derived configurable account address.
455
+ if (signature.type === 'configurable') return signature.account
453
456
  return Address.fromPublicKey(extractPublicKey(options))
454
457
  }
455
458
 
@@ -516,9 +519,9 @@ export function extractPublicKey(
516
519
  return signature.publicKey
517
520
  case 'keychain':
518
521
  return extractPublicKey({ payload, signature: signature.inner })
519
- case 'multisig':
520
- // A multisig signature aggregates multiple owner approvals and has no
521
- // single public key; recover the multisig account via `extractAddress`.
522
+ case 'configurable':
523
+ // A configurable signature aggregates multiple owner approvals and has no
524
+ // single public key; recover the configurable account via `extractAddress`.
522
525
  throw new CoercionError({ envelope: signature })
523
526
  }
524
527
  }
@@ -681,46 +684,45 @@ function deserialize_(value: Serialized): SignatureEnvelope {
681
684
  return envelope
682
685
  }
683
686
 
684
- if (typeId === serializedMultisigType) {
687
+ if (typeId === serializedConfigurableType) {
685
688
  const decoded = Rlp.toHex(data)
686
689
  if (!Array.isArray(decoded) || decoded.length !== 3)
687
690
  throw new InvalidSerializedError({
688
- reason: 'invalid multisig wire shape: expected exactly three fields',
691
+ reason:
692
+ 'invalid configurable wire shape: expected exactly three fields',
689
693
  serialized,
690
694
  })
691
695
  const [account, config, signatures] = decoded
692
696
  if (typeof account !== 'string' || !Address.validate(account))
693
697
  throw new InvalidSerializedError({
694
- reason: 'invalid multisig account',
698
+ reason: 'invalid configurable account',
695
699
  serialized,
696
700
  })
697
701
  if (!Array.isArray(config))
698
702
  throw new InvalidSerializedError({
699
- reason: 'invalid multisig config',
703
+ reason: 'invalid account config',
700
704
  serialized,
701
705
  })
702
706
  if (
703
707
  !Array.isArray(signatures) ||
704
708
  signatures.length === 0 ||
705
- signatures.length > MultisigConfig.maxSignatures
709
+ signatures.length > AccountConfig.maxSignatures
706
710
  )
707
711
  throw new InvalidSerializedError({
708
- reason: 'invalid multisig signatures list',
712
+ reason: 'invalid configurable signatures list',
709
713
  serialized,
710
714
  })
711
715
  const envelope = {
712
- type: 'multisig',
716
+ type: 'configurable',
713
717
  account,
714
- config: MultisigConfig.fromTuple(
715
- config as unknown as MultisigConfig.Tuple,
716
- ),
718
+ config: AccountConfig.fromTuple(config as unknown as AccountConfig.Tuple),
717
719
  signatures: signatures.map((signature) => {
718
720
  if (
719
721
  !Hex.validate(signature) ||
720
- Hex.size(signature) > MultisigConfig.maxOwnerSignatureBytes
722
+ Hex.size(signature) > AccountConfig.maxOwnerSignatureBytes
721
723
  )
722
724
  throw new InvalidSerializedError({
723
- reason: 'invalid multisig owner signature',
725
+ reason: 'invalid configurable owner signature',
724
726
  serialized,
725
727
  })
726
728
  // Reject recursive envelopes before decoding their contents.
@@ -734,13 +736,13 @@ function deserialize_(value: Serialized): SignatureEnvelope {
734
736
  })
735
737
  return deserialize(signature) as Primitive
736
738
  }),
737
- } satisfies Multisig
738
- assertMultisig(envelope)
739
+ } satisfies Configurable
740
+ assertConfigurable(envelope)
739
741
  return envelope
740
742
  }
741
743
 
742
744
  throw new InvalidSerializedError({
743
- reason: `Unknown signature type identifier: ${typeId}. Expected ${serializedP256Type} (P256), ${serializedWebAuthnType} (WebAuthn), ${serializedKeychainType} (Keychain V1), ${serializedKeychainV2Type} (Keychain V2), or ${serializedMultisigType} (Multisig)`,
745
+ reason: `Unknown signature type identifier: ${typeId}. Expected ${serializedP256Type} (P256), ${serializedWebAuthnType} (WebAuthn), ${serializedKeychainType} (Keychain V1), ${serializedKeychainV2Type} (Keychain V2), or ${serializedConfigurableType} (Configurable)`,
744
746
  serialized,
745
747
  })
746
748
  }
@@ -871,7 +873,7 @@ function deserialize_(value: Serialized): SignatureEnvelope {
871
873
  * ```
872
874
  *
873
875
  * @example
874
- * ### Multisig
876
+ * ### Configurable
875
877
  *
876
878
  * Include the permanent account and current configuration on every transaction.
877
879
  *
@@ -920,12 +922,12 @@ export function from<const value extends from.Value>(
920
922
 
921
923
  const type = getType(value)
922
924
 
923
- if (type === 'multisig') {
924
- const multisig = value as Multisig
925
+ if (type === 'configurable') {
926
+ const configurable = value as Configurable
925
927
  return {
926
- ...multisig,
927
- config: MultisigConfig.from(multisig.config),
928
- signatures: multisig.signatures.map((signature) => from(signature)),
928
+ ...configurable,
929
+ config: AccountConfig.from(configurable.config),
930
+ signatures: configurable.signatures.map((signature) => from(signature)),
929
931
  type,
930
932
  } as never
931
933
  }
@@ -972,14 +974,14 @@ export declare namespace from {
972
974
  payload?: Hex.Hex | Bytes.Bytes | undefined
973
975
  }
974
976
 
975
- /** Multisig input with an explicit account and a normalizable configuration. */
976
- type MultisigFromConfig = Omit<Multisig, 'config' | 'type'> & {
977
- config: MultisigConfig.Input
978
- type?: 'multisig' | undefined
977
+ /** Configurable input with an explicit account and a normalizable configuration. */
978
+ type ConfigurableFromConfig = Omit<Configurable, 'config' | 'type'> & {
979
+ config: AccountConfig.Input
980
+ type?: 'configurable' | undefined
979
981
  }
980
982
 
981
983
  type Value =
982
- | MultisigFromConfig
984
+ | ConfigurableFromConfig
983
985
  | UnionPartialBy<SignatureEnvelope, 'prehash' | 'type'>
984
986
  | Secp256k1Flat
985
987
  | Serialized
@@ -990,8 +992,8 @@ export declare namespace from {
990
992
  ? SignatureEnvelope
991
993
  : value extends Secp256k1Flat
992
994
  ? Secp256k1
993
- : value extends MultisigFromConfig
994
- ? Extract<SignatureEnvelope, { type: 'multisig' }>
995
+ : value extends ConfigurableFromConfig
996
+ ? Extract<SignatureEnvelope, { type: 'configurable' }>
995
997
  : IsNarrowable<value, SignatureEnvelope> extends true
996
998
  ? SignatureEnvelope
997
999
  : Assign<
@@ -1026,8 +1028,10 @@ export declare namespace from {
1026
1028
  */
1027
1029
  export function fromRpc(envelope: SignatureEnvelopeRpc): SignatureEnvelope {
1028
1030
  if (typeof envelope === 'string') {
1029
- const signature = deserialize(Hex.concat(serializedMultisigType, envelope))
1030
- if (signature.type !== 'multisig') throw new CoercionError({ envelope })
1031
+ const signature = deserialize(
1032
+ Hex.concat(serializedConfigurableType, envelope),
1033
+ )
1034
+ if (signature.type !== 'configurable') throw new CoercionError({ envelope })
1031
1035
  return signature
1032
1036
  }
1033
1037
  if (envelope.type === 'secp256k1')
@@ -1122,7 +1126,7 @@ export declare namespace fromRpc {
1122
1126
  | assert.ErrorType
1123
1127
  | CoercionError
1124
1128
  | InvalidSerializedError
1125
- | MultisigConfig.getAddress.ErrorType
1129
+ | AccountConfig.getAddress.ErrorType
1126
1130
  | Signature.fromRpc.ErrorType
1127
1131
  | Errors.GlobalErrorType
1128
1132
  }
@@ -1196,9 +1200,9 @@ export function getType<
1196
1200
  if ('userAddress' in envelope && 'inner' in envelope)
1197
1201
  return 'keychain' as never
1198
1202
 
1199
- // Detect Multisig signature
1203
+ // Detect Configurable signature
1200
1204
  if ('account' in envelope && 'config' in envelope && 'signatures' in envelope)
1201
- return 'multisig' as never
1205
+ return 'configurable' as never
1202
1206
 
1203
1207
  throw new CoercionError({
1204
1208
  envelope,
@@ -1214,7 +1218,7 @@ export function getType<
1214
1218
  * - WebAuthn: `0x02` + webauthnData (variable) + r (32) + s (32) + pubKeyX (32) + pubKeyY (32)
1215
1219
  * - Keychain V1: `0x03` + userAddress (20) + inner signature (recursive)
1216
1220
  * - Keychain V2: `0x04` + userAddress (20) + inner signature (recursive)
1217
- * - Multisig: `0x05` + RLP `[account, config, signatures]`
1221
+ * - Configurable: `0x05` + RLP `[account, config, signatures]`
1218
1222
  *
1219
1223
  * [Signature Types](https://docs.tempo.xyz/protocol/transactions/spec-tempo-transaction#signature-types)
1220
1224
  *
@@ -1299,15 +1303,15 @@ export function serialize(
1299
1303
  )
1300
1304
  }
1301
1305
 
1302
- if (type === 'multisig') {
1303
- const multisig = envelope as Multisig
1304
- assert(multisig)
1306
+ if (type === 'configurable') {
1307
+ const configurable = envelope as Configurable
1308
+ assert(configurable)
1305
1309
  return Hex.concat(
1306
- serializedMultisigType,
1310
+ serializedConfigurableType,
1307
1311
  Rlp.fromHex([
1308
- multisig.account,
1309
- MultisigConfig.toTuple(multisig.config),
1310
- multisig.signatures.map((signature) => serialize(signature)),
1312
+ configurable.account,
1313
+ AccountConfig.toTuple(configurable.config),
1314
+ configurable.signatures.map((signature) => serialize(signature)),
1311
1315
  ]),
1312
1316
  options.magic ? magicBytes : '0x',
1313
1317
  )
@@ -1339,14 +1343,14 @@ export declare namespace serialize {
1339
1343
  /**
1340
1344
  * Sorts primitive owner approvals by recovered address.
1341
1345
  *
1342
- * Recovery uses the account and current config version's multisig digest.
1346
+ * Recovery uses the account and current config version's owner approval digest.
1343
1347
  * Duplicate or non-owner approvals must still be rejected by the node.
1344
1348
  *
1345
1349
  * @example
1346
1350
  * ```ts twoslash
1347
1351
  * import { SignatureEnvelope } from 'ox/tempo'
1348
1352
  *
1349
- * const ordered = SignatureEnvelope.sortMultisigApprovals({
1353
+ * const ordered = SignatureEnvelope.sortApprovals({
1350
1354
  * account: '0x2222222222222222222222222222222222222222',
1351
1355
  * config: { version: 0n },
1352
1356
  * payload: `0x${'ab'.repeat(32)}`,
@@ -1357,11 +1361,11 @@ export declare namespace serialize {
1357
1361
  * @param value - Account, version, payload, and primitive approvals.
1358
1362
  * @returns The approvals in ascending recovered-address order.
1359
1363
  */
1360
- export function sortMultisigApprovals(
1361
- value: sortMultisigApprovals.Value,
1364
+ export function sortApprovals(
1365
+ value: sortApprovals.Value,
1362
1366
  ): readonly Primitive[] {
1363
1367
  const { signatures } = value
1364
- const digest = MultisigConfig.getSignPayload(value)
1368
+ const digest = AccountConfig.getSignPayload(value)
1365
1369
  // Recover each signer once (decorate–sort–undecorate) rather than inside the
1366
1370
  // comparator.
1367
1371
  return signatures
@@ -1373,14 +1377,14 @@ export function sortMultisigApprovals(
1373
1377
  .map((entry) => entry.signature)
1374
1378
  }
1375
1379
 
1376
- export declare namespace sortMultisigApprovals {
1377
- type Value = MultisigConfig.getSignPayload.Value & {
1380
+ export declare namespace sortApprovals {
1381
+ type Value = AccountConfig.getSignPayload.Value & {
1378
1382
  /** Primitive owner approvals to order. */
1379
1383
  signatures: readonly Primitive[]
1380
1384
  }
1381
1385
 
1382
1386
  type ErrorType =
1383
- | MultisigConfig.getSignPayload.ErrorType
1387
+ | AccountConfig.getSignPayload.ErrorType
1384
1388
  | extractAddress.ErrorType
1385
1389
  | Errors.GlobalErrorType
1386
1390
  }
@@ -1459,20 +1463,20 @@ export function toRpc<const envelope extends toRpc.Input>(
1459
1463
  } as never
1460
1464
  }
1461
1465
 
1462
- if (type === 'multisig') {
1463
- const multisig = envelope as Multisig<Hex.Hex | number>
1466
+ if (type === 'configurable') {
1467
+ const configurable = envelope as Configurable<Hex.Hex | number>
1464
1468
  return Hex.slice(
1465
1469
  serialize({
1466
- ...multisig,
1470
+ ...configurable,
1467
1471
  config: {
1468
- ...multisig.config,
1469
- threshold: Number(multisig.config.threshold),
1470
- owners: multisig.config.owners.map((owner) => ({
1472
+ ...configurable.config,
1473
+ threshold: Number(configurable.config.threshold),
1474
+ owners: configurable.config.owners.map((owner) => ({
1471
1475
  ...owner,
1472
1476
  weight: Number(owner.weight),
1473
1477
  })),
1474
1478
  },
1475
- signatures: multisig.signatures.map((signature) =>
1479
+ signatures: configurable.signatures.map((signature) =>
1476
1480
  signature.type === 'secp256k1'
1477
1481
  ? {
1478
1482
  ...signature,
@@ -1511,8 +1515,8 @@ export declare namespace toRpc {
1511
1515
  ? WebAuthnRpc
1512
1516
  : GetType<envelope> extends 'keychain'
1513
1517
  ? KeychainRpc
1514
- : GetType<envelope> extends 'multisig'
1515
- ? MultisigRpc
1518
+ : GetType<envelope> extends 'configurable'
1519
+ ? ConfigurableRpc
1516
1520
  : SignatureEnvelopeRpc
1517
1521
 
1518
1522
  type ErrorType =
@@ -1769,7 +1773,7 @@ export class MissingPropertiesError extends Errors.BaseError {
1769
1773
  }: {
1770
1774
  envelope: unknown
1771
1775
  missing: string[]
1772
- type: Type | 'keychain' | 'multisig'
1776
+ type: Type | 'keychain' | 'configurable'
1773
1777
  }) {
1774
1778
  super(
1775
1779
  `Signature envelope of type "${type}" is missing required properties: ${missing.map((m) => `\`${m}\``).join(', ')}.\n\nProvided: ${Json.stringify(envelope)}`,
@@ -1790,12 +1794,12 @@ export class InvalidSerializedError extends Errors.BaseError {
1790
1794
  }
1791
1795
 
1792
1796
  /**
1793
- * Error thrown when a native multisig owner approval is invalid.
1797
+ * Error thrown when a configurable account owner approval is invalid.
1794
1798
  */
1795
- export class InvalidMultisigApprovalError extends Errors.BaseError {
1796
- override readonly name = 'SignatureEnvelope.InvalidMultisigApprovalError'
1799
+ export class InvalidApprovalError extends Errors.BaseError {
1800
+ override readonly name = 'SignatureEnvelope.InvalidApprovalError'
1797
1801
  constructor({ reason }: { reason: string }) {
1798
- super(`Invalid native multisig owner approval: ${reason}.`)
1802
+ super(`Invalid owner approval: ${reason}.`)
1799
1803
  }
1800
1804
  }
1801
1805
 
@@ -7,6 +7,7 @@ export const roles = [
7
7
  'unpause',
8
8
  'issuer',
9
9
  'burnBlocked',
10
+ 'burnAt',
10
11
  ] as const
11
12
  export type TokenRole = (typeof roles)[number]
12
13
 
@@ -16,13 +17,15 @@ export const toPreHashed = {
16
17
  unpause: 'UNPAUSE_ROLE',
17
18
  issuer: 'ISSUER_ROLE',
18
19
  burnBlocked: 'BURN_BLOCKED_ROLE',
20
+ burnAt: 'BURN_AT_ROLE',
19
21
  } as const satisfies Record<TokenRole, string>
20
22
 
21
23
  /**
22
24
  * Serializes a token role to its keccak256 hash representation.
23
25
  *
24
26
  * TIP-20 includes a built-in RBAC system with roles like `ISSUER_ROLE` (mint/burn),
25
- * `PAUSE_ROLE`/`UNPAUSE_ROLE` (emergency controls), and `BURN_BLOCKED_ROLE` (compliance).
27
+ * `PAUSE_ROLE`/`UNPAUSE_ROLE` (emergency controls), `BURN_BLOCKED_ROLE` (compliance), and
28
+ * `BURN_AT_ROLE` (burn from any unprotected account, T12+).
26
29
  *
27
30
  * [TIP-20 RBAC](https://docs.tempo.xyz/protocol/tip20/overview#role-based-access-control-rbac)
28
31
  *
@@ -1,7 +1,7 @@
1
1
  import { Transaction } from 'ox/tempo'
2
2
  import { describe, expect, test } from 'vp/test'
3
3
 
4
- const multisigRpcSignature =
4
+ const configurableRpcSignature =
5
5
  '0xf89794c4a590afa7337e5cd5eb3aa60cacf91c5400044bf83ba000000000000000000000000000000000000000000000000000000000000000008001d7d6947e5f4552091a69125d5dfcb7b8c2659029395bdf01f843b841869437e01f64bebeb78a8a6b30bfd3a993819c8cad82c807515d9b9e9b36f98535dfaa5eebc597715d05f6ce4927747f14fa4cd2acc717fdcd3877146437f8f41b' as const
6
6
 
7
7
  describe('fromRpc', () => {
@@ -517,7 +517,7 @@ describe('toRpc', () => {
517
517
  })
518
518
 
519
519
  describe('roundtrip', () => {
520
- test('behavior: multisig RPC signature', () => {
520
+ test('behavior: configurable RPC signature', () => {
521
521
  const rpc = {
522
522
  accessList: [],
523
523
  blockHash:
@@ -532,7 +532,7 @@ describe('roundtrip', () => {
532
532
  maxFeePerGas: '0x2',
533
533
  maxPriorityFeePerGas: '0x1',
534
534
  nonce: '0x357',
535
- signature: multisigRpcSignature,
535
+ signature: configurableRpcSignature,
536
536
  transactionIndex: '0x2',
537
537
  type: '0x76',
538
538
  } as const satisfies Transaction.TempoRpc
@@ -567,7 +567,7 @@ describe('roundtrip', () => {
567
567
  "type": "secp256k1",
568
568
  },
569
569
  ],
570
- "type": "multisig",
570
+ "type": "configurable",
571
571
  },
572
572
  }
573
573
  `)
@@ -1,7 +1,7 @@
1
1
  import type * as ox_TransactionRequest from '../core/TransactionRequest.js'
2
2
  import * as Signature from '../core/Signature.js'
3
3
  import { describe, expectTypeOf, test } from 'vp/test'
4
- import * as MultisigSimulation from './MultisigSimulation.js'
4
+ import * as AccountSimulation from './AccountSimulation.js'
5
5
  import * as SignatureEnvelope from './SignatureEnvelope.js'
6
6
  import * as TransactionRequest from './TransactionRequest.js'
7
7
  import * as TxEnvelopeTempo from './TxEnvelopeTempo.js'
@@ -49,12 +49,23 @@ describe('TransactionRequest type', () => {
49
49
  >()
50
50
  })
51
51
 
52
- test('carries domain and RPC multisig simulations', () => {
52
+ test('carries domain and RPC account simulations', () => {
53
53
  expectTypeOf<
54
- TransactionRequest.TransactionRequest['multisigSimulation']
55
- >().toEqualTypeOf<MultisigSimulation.Spec | undefined>()
54
+ TransactionRequest.TransactionRequest['accountSimulation']
55
+ >().toEqualTypeOf<AccountSimulation.Spec | undefined>()
56
56
  expectTypeOf<TransactionRequest.Rpc['multisigSimulation']>().toEqualTypeOf<
57
- MultisigSimulation.Rpc | undefined
57
+ AccountSimulation.Rpc | undefined
58
+ >()
59
+ })
60
+
61
+ test('maps the configurable key type to the RPC multisig key type', () => {
62
+ expectTypeOf<
63
+ TransactionRequest.TransactionRequest['keyType']
64
+ >().toEqualTypeOf<
65
+ 'configurable' | 'p256' | 'secp256k1' | 'webAuthn' | undefined
66
+ >()
67
+ expectTypeOf<TransactionRequest.Rpc['keyType']>().toEqualTypeOf<
68
+ 'multisig' | 'p256' | 'secp256k1' | 'webAuthn' | undefined
58
69
  >()
59
70
  })
60
71
  })
@@ -73,6 +84,7 @@ describe('toEnvelope', () => {
73
84
  // Forces us to update toEnvelope when fields are added to the request.
74
85
  TransactionRequest.toEnvelope({
75
86
  accessList: [],
87
+ accountSimulation: undefined,
76
88
  authorizationList: undefined,
77
89
  calls: undefined,
78
90
  chainId: 1,
@@ -87,7 +99,6 @@ describe('toEnvelope', () => {
87
99
  keyType: 'secp256k1',
88
100
  maxFeePerGas: 1n,
89
101
  maxPriorityFeePerGas: 1n,
90
- multisigSimulation: undefined,
91
102
  nonce: 0n,
92
103
  nonceKey: 'random',
93
104
  signature: undefined,