ox 0.14.55 → 0.14.57

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 (97) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/_cjs/tempo/{MultisigConfig.js → AccountConfig.js} +32 -9
  3. package/_cjs/tempo/AccountConfig.js.map +1 -0
  4. package/_cjs/tempo/{MultisigOperation.js → AccountOperation.js} +29 -29
  5. package/_cjs/tempo/AccountOperation.js.map +1 -0
  6. package/_cjs/tempo/{MultisigSimulation.js → AccountSimulation.js} +22 -13
  7. package/_cjs/tempo/AccountSimulation.js.map +1 -0
  8. package/_cjs/tempo/KeyAuthorization.js +10 -18
  9. package/_cjs/tempo/KeyAuthorization.js.map +1 -1
  10. package/_cjs/tempo/SignatureEnvelope.js +64 -64
  11. package/_cjs/tempo/SignatureEnvelope.js.map +1 -1
  12. package/_cjs/tempo/TransactionRequest.js +15 -10
  13. package/_cjs/tempo/TransactionRequest.js.map +1 -1
  14. package/_cjs/tempo/index.js +4 -4
  15. package/_cjs/tempo/index.js.map +1 -1
  16. package/_cjs/version.js +1 -1
  17. package/_esm/tempo/{MultisigConfig.js → AccountConfig.js} +161 -64
  18. package/_esm/tempo/AccountConfig.js.map +1 -0
  19. package/_esm/tempo/{MultisigOperation.js → AccountOperation.js} +64 -64
  20. package/_esm/tempo/AccountOperation.js.map +1 -0
  21. package/_esm/tempo/{MultisigSimulation.js → AccountSimulation.js} +35 -25
  22. package/_esm/tempo/AccountSimulation.js.map +1 -0
  23. package/_esm/tempo/KeyAuthorization.js +16 -19
  24. package/_esm/tempo/KeyAuthorization.js.map +1 -1
  25. package/_esm/tempo/SignatureEnvelope.js +71 -71
  26. package/_esm/tempo/SignatureEnvelope.js.map +1 -1
  27. package/_esm/tempo/TransactionRequest.js +15 -10
  28. package/_esm/tempo/TransactionRequest.js.map +1 -1
  29. package/_esm/tempo/index.js +50 -48
  30. package/_esm/tempo/index.js.map +1 -1
  31. package/_esm/version.js +1 -1
  32. package/_types/tempo/{MultisigConfig.d.ts → AccountConfig.d.ts} +156 -66
  33. package/_types/tempo/AccountConfig.d.ts.map +1 -0
  34. package/_types/tempo/{MultisigOperation.d.ts → AccountOperation.d.ts} +62 -62
  35. package/_types/tempo/AccountOperation.d.ts.map +1 -0
  36. package/_types/tempo/{MultisigSimulation.d.ts → AccountSimulation.d.ts} +25 -21
  37. package/_types/tempo/AccountSimulation.d.ts.map +1 -0
  38. package/_types/tempo/KeyAuthorization.d.ts +28 -23
  39. package/_types/tempo/KeyAuthorization.d.ts.map +1 -1
  40. package/_types/tempo/RpcSchemaTempo.d.ts +13 -13
  41. package/_types/tempo/RpcSchemaTempo.d.ts.map +1 -1
  42. package/_types/tempo/SignatureEnvelope.d.ts +36 -33
  43. package/_types/tempo/SignatureEnvelope.d.ts.map +1 -1
  44. package/_types/tempo/TransactionRequest.d.ts +11 -9
  45. package/_types/tempo/TransactionRequest.d.ts.map +1 -1
  46. package/_types/tempo/index.d.ts +50 -48
  47. package/_types/tempo/index.d.ts.map +1 -1
  48. package/_types/version.d.ts +1 -1
  49. package/package.json +31 -31
  50. package/tempo/AccountConfig/package.json +6 -0
  51. package/tempo/AccountConfig.test-d/package.json +6 -0
  52. package/tempo/AccountConfig.test-d.ts +72 -0
  53. package/tempo/AccountConfig.test.ts +642 -0
  54. package/tempo/{MultisigConfig.ts → AccountConfig.ts} +212 -75
  55. package/tempo/AccountOperation/package.json +6 -0
  56. package/tempo/AccountOperation.test-d/package.json +6 -0
  57. package/tempo/AccountOperation.test-d.ts +71 -0
  58. package/tempo/{MultisigOperation.test.ts → AccountOperation.test.ts} +129 -129
  59. package/tempo/{MultisigOperation.ts → AccountOperation.ts} +95 -97
  60. package/tempo/AccountSimulation/package.json +6 -0
  61. package/tempo/AccountSimulation.test-d/package.json +6 -0
  62. package/tempo/{MultisigSimulation.test-d.ts → AccountSimulation.test-d.ts} +7 -9
  63. package/tempo/{MultisigSimulation.test.ts → AccountSimulation.test.ts} +73 -29
  64. package/tempo/{MultisigSimulation.ts → AccountSimulation.ts} +47 -35
  65. package/tempo/KeyAuthorization.test-d.ts +19 -29
  66. package/tempo/KeyAuthorization.test.ts +151 -74
  67. package/tempo/KeyAuthorization.ts +40 -61
  68. package/tempo/RpcSchemaTempo.test-d.ts +20 -20
  69. package/tempo/RpcSchemaTempo.ts +13 -13
  70. package/tempo/SignatureEnvelope.test-d.ts +7 -7
  71. package/tempo/SignatureEnvelope.test.ts +34 -34
  72. package/tempo/SignatureEnvelope.ts +107 -103
  73. package/tempo/Transaction.test.ts +4 -4
  74. package/tempo/TransactionRequest.test-d.ts +17 -8
  75. package/tempo/TransactionRequest.test.ts +31 -21
  76. package/tempo/TransactionRequest.ts +29 -20
  77. package/tempo/{multisig.e2e.test.ts → configurableAccounts.e2e.test.ts} +16 -16
  78. package/tempo/index.ts +50 -48
  79. package/version.ts +1 -1
  80. package/_cjs/tempo/MultisigConfig.js.map +0 -1
  81. package/_cjs/tempo/MultisigOperation.js.map +0 -1
  82. package/_cjs/tempo/MultisigSimulation.js.map +0 -1
  83. package/_esm/tempo/MultisigConfig.js.map +0 -1
  84. package/_esm/tempo/MultisigOperation.js.map +0 -1
  85. package/_esm/tempo/MultisigSimulation.js.map +0 -1
  86. package/_types/tempo/MultisigConfig.d.ts.map +0 -1
  87. package/_types/tempo/MultisigOperation.d.ts.map +0 -1
  88. package/_types/tempo/MultisigSimulation.d.ts.map +0 -1
  89. package/tempo/MultisigConfig/package.json +0 -6
  90. package/tempo/MultisigConfig.test-d/package.json +0 -6
  91. package/tempo/MultisigConfig.test-d.ts +0 -52
  92. package/tempo/MultisigConfig.test.ts +0 -391
  93. package/tempo/MultisigOperation/package.json +0 -6
  94. package/tempo/MultisigOperation.test-d/package.json +0 -6
  95. package/tempo/MultisigOperation.test-d.ts +0 -71
  96. package/tempo/MultisigSimulation/package.json +0 -6
  97. package/tempo/MultisigSimulation.test-d/package.json +0 -6
@@ -9,39 +9,52 @@ import type { Compute } from '../core/internal/types.js'
9
9
  /** Maximum encoded byte length for one primitive owner approval. */
10
10
  export const maxOwnerSignatureBytes = 2049
11
11
 
12
- /** Maximum number of owners allowed in a native multisig config. */
12
+ /** Maximum number of owners allowed in an account config. */
13
13
  export const maxOwners = 48
14
14
 
15
- /** Maximum number of owner approvals in a native multisig signature. */
15
+ /** Maximum number of owner approvals in a configurable account signature. */
16
16
  export const maxSignatures = 8
17
17
 
18
- /** Maximum threshold accepted by a native multisig config. */
19
- export const maxThreshold = 8
18
+ /**
19
+ * Maximum threshold accepted by an account config.
20
+ *
21
+ * The threshold must also be reachable by at most {@link ox#AccountConfig.maxSignatures}
22
+ * owner approvals.
23
+ */
24
+ export const maxThreshold = 0xff
20
25
 
21
- /** Maximum version accepted by a native multisig config. */
26
+ /** Maximum version accepted by an account config. */
22
27
  export const maxVersion = 2n ** 64n - 1n
23
28
 
24
- /** Tempo signature type byte for native multisig signatures. */
29
+ /** Tempo signature type byte for configurable account signatures. */
25
30
  export const signatureTypeByte = '0x05' as const
26
31
 
27
32
  /** Zero 32-byte salt (the default when no salt is provided). */
28
33
  export const zeroSalt = `0x${'00'.repeat(32)}` as const
29
34
 
30
- /** Domain prefix for the native multisig account address derivation. */
31
- const accountDomain = 'tempo:multisig:account'
35
+ /** Domain prefix for the configurable account address derivation. */
36
+ const accountDomain = 'tempo:configurable-account:account'
32
37
 
33
- /** Domain prefix for native multisig configuration commitments. */
34
- const configDomain = 'tempo:multisig:config'
38
+ /** Domain prefix for account configuration commitments. */
39
+ const configDomain = 'tempo:configurable-account:config'
35
40
 
36
- /** Keccak-256 of the canonical recovery wallet creation code. */
37
- const recoveryWalletInitCodeHash =
41
+ /**
42
+ * Keccak-256 of the account proxy creation code.
43
+ *
44
+ * Placeholder until [TIP-1110](https://tips.sh/1110) fixes the canonical
45
+ * account proxy, which will change every derived address.
46
+ */
47
+ const accountProxyInitCodeHash =
38
48
  '0x583cc63a2e37f645b43eac911b1a6d6de08b83abdc308c61364edda8cfc3bd37'
39
49
 
40
- /** Domain prefix for native multisig owner approvals. */
41
- const signatureDomain = 'tempo:multisig:signature'
50
+ /** Domain prefix for configurable account owner approvals. */
51
+ const signatureDomain = 'tempo:configurable-account:signature'
52
+
53
+ /** Domain prefix for the salt of an account migrated in place. */
54
+ const upgradeDomain = 'tempo:configurable-account:upgrade'
42
55
 
43
56
  /**
44
- * Complete native multisig configuration witness.
57
+ * Complete account configuration witness.
45
58
  */
46
59
  export type Config<bigintType = bigint, numberType = number> = Compute<{
47
60
  /** Weighted owner list, strictly ascending by owner address. */
@@ -54,7 +67,7 @@ export type Config<bigintType = bigint, numberType = number> = Compute<{
54
67
  version: bigintType
55
68
  }>
56
69
 
57
- /** Input accepted when constructing a native multisig configuration. */
70
+ /** Input accepted when constructing an account configuration. */
58
71
  export type Input<
59
72
  versionType extends bigint | number = bigint | number,
60
73
  numberType = number,
@@ -63,7 +76,7 @@ export type Input<
63
76
  owners: readonly Owner<numberType>[]
64
77
  /**
65
78
  * Caller-chosen 32-byte salt mixed into the derived account address.
66
- * Defaults to the zero salt (`MultisigConfig.zeroSalt`) when omitted.
79
+ * Defaults to the zero salt (`AccountConfig.zeroSalt`) when omitted.
67
80
  */
68
81
  salt?: Hex.Hex | undefined
69
82
  /** Minimum total owner weight required to authorize a transaction. */
@@ -72,7 +85,7 @@ export type Input<
72
85
  version?: versionType | undefined
73
86
  }>
74
87
 
75
- /** Native multisig owner entry. */
88
+ /** Account config owner entry. */
76
89
  export type Owner<numberType = number> = {
77
90
  /** Owner address (recovered from the owner's approval). */
78
91
  owner: Address.Address
@@ -80,10 +93,10 @@ export type Owner<numberType = number> = {
80
93
  weight: numberType
81
94
  }
82
95
 
83
- /** JSON-RPC representation of a native multisig configuration. */
96
+ /** JSON-RPC representation of an account configuration. */
84
97
  export type Rpc = Config<Hex.Hex, number>
85
98
 
86
- /** RLP tuple representation of a {@link ox#MultisigConfig.Config}. */
99
+ /** RLP tuple representation of a {@link ox#AccountConfig.Config}. */
87
100
  export type Tuple = readonly [
88
101
  salt: Hex.Hex,
89
102
  version: Hex.Hex,
@@ -92,7 +105,7 @@ export type Tuple = readonly [
92
105
  ]
93
106
 
94
107
  /**
95
- * Asserts that a native multisig {@link ox#MultisigConfig.Config} is valid.
108
+ * Asserts that an {@link ox#AccountConfig.Config} is valid.
96
109
  *
97
110
  * Mirrors the Tempo configuration rules: owners non-empty and
98
111
  * `<= maxOwners`, strictly ascending unique nonzero owner addresses, nonzero
@@ -102,9 +115,9 @@ export type Tuple = readonly [
102
115
  *
103
116
  * @example
104
117
  * ```ts twoslash
105
- * import { MultisigConfig } from 'ox/tempo'
118
+ * import { AccountConfig } from 'ox/tempo'
106
119
  *
107
- * MultisigConfig.assert({
120
+ * AccountConfig.assert({
108
121
  * threshold: 1,
109
122
  * owners: [
110
123
  * { owner: '0x1111111111111111111111111111111111111111', weight: 1 },
@@ -112,7 +125,7 @@ export type Tuple = readonly [
112
125
  * })
113
126
  * ```
114
127
  *
115
- * @param config - The multisig config.
128
+ * @param config - The account config.
116
129
  */
117
130
  export function assert<
118
131
  versionType extends bigint | number = bigint | number,
@@ -183,16 +196,16 @@ export declare namespace assert {
183
196
  }
184
197
 
185
198
  /**
186
- * Normalizes a native multisig {@link ox#MultisigConfig.Config}.
199
+ * Normalizes an {@link ox#AccountConfig.Config}.
187
200
  *
188
201
  * Sorts owners into strictly ascending `owner` address order (the canonical
189
202
  * form required for account derivation) and asserts the config is valid.
190
203
  *
191
204
  * @example
192
205
  * ```ts twoslash
193
- * import { MultisigConfig } from 'ox/tempo'
206
+ * import { AccountConfig } from 'ox/tempo'
194
207
  *
195
- * const config = MultisigConfig.from({
208
+ * const config = AccountConfig.from({
196
209
  * owners: [
197
210
  * { owner: '0x2222222222222222222222222222222222222222', weight: 1 },
198
211
  * { owner: '0x1111111111111111111111111111111111111111', weight: 1 },
@@ -202,8 +215,8 @@ export declare namespace assert {
202
215
  * // owners are now sorted ascending by address
203
216
  * ```
204
217
  *
205
- * @param config - The multisig config.
206
- * @returns The normalized multisig config.
218
+ * @param config - The account config.
219
+ * @returns The normalized account config.
207
220
  */
208
221
  export function from<numberType = number>(
209
222
  config: Input<0 | 0n, numberType> & { version?: 0 | 0n | undefined },
@@ -237,13 +250,13 @@ export function from<numberType = number>(
237
250
  }
238
251
 
239
252
  /**
240
- * Converts a JSON-RPC multisig configuration to its domain representation.
253
+ * Converts a JSON-RPC account configuration to its domain representation.
241
254
  *
242
255
  * @example
243
256
  * ```ts twoslash
244
- * import { MultisigConfig } from 'ox/tempo'
257
+ * import { AccountConfig } from 'ox/tempo'
245
258
  *
246
- * const config = MultisigConfig.fromRpc({
259
+ * const config = AccountConfig.fromRpc({
247
260
  * owners: [
248
261
  * { owner: '0x1111111111111111111111111111111111111111', weight: 1 },
249
262
  * ],
@@ -253,8 +266,8 @@ export function from<numberType = number>(
253
266
  * })
254
267
  * ```
255
268
  *
256
- * @param config - The JSON-RPC multisig configuration.
257
- * @returns The normalized multisig configuration.
269
+ * @param config - The JSON-RPC account configuration.
270
+ * @returns The normalized account configuration.
258
271
  */
259
272
  export function fromRpc(config: Rpc): Config {
260
273
  return from({
@@ -271,14 +284,14 @@ export declare namespace fromRpc {
271
284
  }
272
285
 
273
286
  /**
274
- * Converts an RLP {@link ox#MultisigConfig.Tuple} back to a
275
- * {@link ox#MultisigConfig.Config}.
287
+ * Converts an RLP {@link ox#AccountConfig.Tuple} back to a
288
+ * {@link ox#AccountConfig.Config}.
276
289
  *
277
290
  * @example
278
291
  * ```ts twoslash
279
- * import { MultisigConfig } from 'ox/tempo'
292
+ * import { AccountConfig } from 'ox/tempo'
280
293
  *
281
- * const config = MultisigConfig.fromTuple([
294
+ * const config = AccountConfig.fromTuple([
282
295
  * `0x${'00'.repeat(32)}`,
283
296
  * '0x',
284
297
  * '0x01',
@@ -287,7 +300,7 @@ export declare namespace fromRpc {
287
300
  * ```
288
301
  *
289
302
  * @param tuple - The RLP tuple.
290
- * @returns The multisig config.
303
+ * @returns The account config.
291
304
  */
292
305
  export function fromTuple(tuple: Tuple): Config {
293
306
  const [salt, version, threshold, owners] = tuple
@@ -331,34 +344,97 @@ export function fromTuple(tuple: Tuple): Config {
331
344
  }
332
345
 
333
346
  /**
334
- * Derives the stable native multisig account address.
347
+ * Derives the configuration an existing account installs when it migrates in
348
+ * place with the `upgradeAccount` precompile call
349
+ * ([TIP-1113](https://tips.sh/1113)).
350
+ *
351
+ * The account keeps its address. Its salt is
352
+ * `keccak256("tempo:configurable-account:upgrade" || account)` and its version
353
+ * is `1n`. Owners are sorted into canonical order and the config is validated.
354
+ * The account itself may be listed as an owner.
355
+ *
356
+ * @example
357
+ * ```ts twoslash
358
+ * import { AccountConfig } from 'ox/tempo'
359
+ *
360
+ * const config = AccountConfig.fromUpgrade(
361
+ * '0x3333333333333333333333333333333333333333',
362
+ * {
363
+ * owners: [
364
+ * {
365
+ * owner: '0x1111111111111111111111111111111111111111',
366
+ * weight: 1
367
+ * }
368
+ * ],
369
+ * threshold: 1
370
+ * }
371
+ * )
372
+ * // config.version === 1n
373
+ * ```
374
+ *
375
+ * @param account - The account migrating in place.
376
+ * @param options - The owners and threshold to install.
377
+ * @returns The installed account config.
378
+ */
379
+ export function fromUpgrade<numberType = number>(
380
+ account: Address.Address,
381
+ options: fromUpgrade.Options<numberType>,
382
+ ): Config<1n, numberType> {
383
+ Address.assert(account)
384
+ return from({
385
+ owners: options.owners,
386
+ salt: Hash.keccak256(Hex.concat(Hex.fromString(upgradeDomain), account)),
387
+ threshold: options.threshold,
388
+ version: 1n,
389
+ })
390
+ }
391
+
392
+ export declare namespace fromUpgrade {
393
+ type Options<numberType = number> = {
394
+ /** Weighted owners to install. Sorted into canonical order. */
395
+ owners: readonly Owner<numberType>[]
396
+ /** Minimum total owner weight required for authorization. */
397
+ threshold: numberType
398
+ }
399
+
400
+ type ErrorType =
401
+ | Address.assert.ErrorType
402
+ | assert.ErrorType
403
+ | Hash.keccak256.ErrorType
404
+ | Hex.concat.ErrorType
405
+ | Hex.fromString.ErrorType
406
+ | Errors.GlobalErrorType
407
+ }
408
+
409
+ /**
410
+ * Derives the stable configurable account address.
335
411
  *
336
412
  * The initial config is hashed into a CREATE2 salt using fixed-width
337
413
  * big-endian fields, not RLP. The account uses the chain-configured recovery
338
- * factory and wallet init-code hash.
414
+ * factory and account proxy init-code hash.
339
415
  *
340
416
  * The address is derived once from the initial version-0 config. Config
341
417
  * updates do not change it.
342
418
  *
343
419
  * @example
344
420
  * ```ts twoslash
345
- * import { MultisigConfig } from 'ox/tempo'
421
+ * import { AccountConfig } from 'ox/tempo'
346
422
  *
347
- * const initialConfig = MultisigConfig.from({
423
+ * const initialConfig = AccountConfig.from({
348
424
  * owners: [
349
425
  * { owner: '0x1111111111111111111111111111111111111111', weight: 1 },
350
426
  * ],
351
427
  * threshold: 1,
352
428
  * })
353
429
  *
354
- * const address = MultisigConfig.getAddress(initialConfig, {
430
+ * const address = AccountConfig.getAddress(initialConfig, {
355
431
  * factory: '0x7171717171717171717171717171717171717171'
356
432
  * })
357
433
  * ```
358
434
  *
359
- * @param config - The initial multisig config.
435
+ * @param config - The initial account config.
360
436
  * @param options - The recovery factory configured by the chain.
361
- * @returns The multisig account address.
437
+ * @returns The configurable account address.
362
438
  */
363
439
  export function getAddress(
364
440
  config: Input,
@@ -383,7 +459,7 @@ export function getAddress(
383
459
  ),
384
460
  )
385
461
  const account = ContractAddress.fromCreate2({
386
- bytecodeHash: recoveryWalletInitCodeHash,
462
+ bytecodeHash: accountProxyInitCodeHash,
387
463
  from: options.factory,
388
464
  salt: accountSalt,
389
465
  })
@@ -413,16 +489,16 @@ export declare namespace getAddress {
413
489
  }
414
490
 
415
491
  /**
416
- * Computes the commitment for a native multisig configuration.
492
+ * Computes the commitment for an account configuration.
417
493
  *
418
494
  * The commitment uses raw fixed-width fields, not RLP or ABI encoding:
419
- * `keccak256("tempo:multisig:config" || salt || uint64be(version) || uint8(threshold) || uint8(owners.length) || owners)`.
495
+ * `keccak256("tempo:configurable-account:config" || salt || uint64be(version) || uint8(threshold) || uint8(owners.length) || owners)`.
420
496
  *
421
497
  * @example
422
498
  * ```ts twoslash
423
- * import { MultisigConfig } from 'ox/tempo'
499
+ * import { AccountConfig } from 'ox/tempo'
424
500
  *
425
- * const commitment = MultisigConfig.getCommitment({
501
+ * const commitment = AccountConfig.getCommitment({
426
502
  * owners: [
427
503
  * { owner: '0x1111111111111111111111111111111111111111', weight: 1 },
428
504
  * ],
@@ -431,7 +507,7 @@ export declare namespace getAddress {
431
507
  * })
432
508
  * ```
433
509
  *
434
- * @param config - The complete multisig configuration.
510
+ * @param config - The complete account configuration.
435
511
  * @returns The configuration commitment.
436
512
  */
437
513
  export function getCommitment(config: Input): Hex.Hex {
@@ -462,9 +538,9 @@ export declare namespace getCommitment {
462
538
  }
463
539
 
464
540
  /**
465
- * Computes the digest a native multisig owner approves (signs).
541
+ * Computes the digest a configurable account owner approves (signs).
466
542
  *
467
- * `keccak256("tempo:multisig:signature" || inner_digest || account || uint64be(version))`,
543
+ * `keccak256("tempo:configurable-account:signature" || inner_digest || account || uint64be(version))`,
468
544
  * where `inner_digest` is the transaction sign payload
469
545
  * ({@link ox#TxEnvelopeTempo.(getSignPayload:function)}).
470
546
  *
@@ -474,9 +550,9 @@ export declare namespace getCommitment {
474
550
  *
475
551
  * @example
476
552
  * ```ts twoslash
477
- * import { MultisigConfig, TxEnvelopeTempo } from 'ox/tempo'
553
+ * import { AccountConfig, TxEnvelopeTempo } from 'ox/tempo'
478
554
  *
479
- * const config = MultisigConfig.from({
555
+ * const config = AccountConfig.from({
480
556
  * owners: [
481
557
  * { owner: '0x1111111111111111111111111111111111111111', weight: 1 },
482
558
  * ],
@@ -488,8 +564,8 @@ export declare namespace getCommitment {
488
564
  * calls: [],
489
565
  * })
490
566
  *
491
- * const digest = MultisigConfig.getSignPayload({
492
- * account: MultisigConfig.getAddress(config, {
567
+ * const digest = AccountConfig.getSignPayload({
568
+ * account: AccountConfig.getAddress(config, {
493
569
  * factory: '0x7171717171717171717171717171717171717171'
494
570
  * }),
495
571
  * config,
@@ -518,7 +594,7 @@ export function getSignPayload(value: getSignPayload.Value): Hex.Hex {
518
594
 
519
595
  export declare namespace getSignPayload {
520
596
  type Value = {
521
- /** The native multisig account address. */
597
+ /** The configurable account address. */
522
598
  account: Address.Address
523
599
  /** Configuration whose version applies to the approval. */
524
600
  config: Pick<Config<bigint | number>, 'version'>
@@ -536,13 +612,13 @@ export declare namespace getSignPayload {
536
612
  }
537
613
 
538
614
  /**
539
- * Converts a multisig configuration to its JSON-RPC representation.
615
+ * Converts an account configuration to its JSON-RPC representation.
540
616
  *
541
617
  * @example
542
618
  * ```ts twoslash
543
- * import { MultisigConfig } from 'ox/tempo'
619
+ * import { AccountConfig } from 'ox/tempo'
544
620
  *
545
- * const config = MultisigConfig.toRpc({
621
+ * const config = AccountConfig.toRpc({
546
622
  * owners: [
547
623
  * { owner: '0x1111111111111111111111111111111111111111', weight: 1 },
548
624
  * ],
@@ -550,8 +626,8 @@ export declare namespace getSignPayload {
550
626
  * })
551
627
  * ```
552
628
  *
553
- * @param config - The multisig configuration.
554
- * @returns The JSON-RPC multisig configuration.
629
+ * @param config - The account configuration.
630
+ * @returns The JSON-RPC account configuration.
555
631
  */
556
632
  export function toRpc(config: Input): Rpc {
557
633
  const value = from(config)
@@ -574,7 +650,7 @@ export declare namespace toRpc {
574
650
  }
575
651
 
576
652
  /**
577
- * Converts a {@link ox#MultisigConfig.Config} to its RLP tuple form.
653
+ * Converts a {@link ox#AccountConfig.Config} to its RLP tuple form.
578
654
  *
579
655
  * Tuple shape: `[salt, version, threshold, [[owner, weight], ...]]`. The
580
656
  * 32-byte `salt` encodes as a full fixed-width string; other integers use
@@ -582,9 +658,9 @@ export declare namespace toRpc {
582
658
  *
583
659
  * @example
584
660
  * ```ts twoslash
585
- * import { MultisigConfig } from 'ox/tempo'
661
+ * import { AccountConfig } from 'ox/tempo'
586
662
  *
587
- * const tuple = MultisigConfig.toTuple({
663
+ * const tuple = AccountConfig.toTuple({
588
664
  * owners: [
589
665
  * { owner: '0x1111111111111111111111111111111111111111', weight: 1 },
590
666
  * ],
@@ -592,7 +668,7 @@ export declare namespace toRpc {
592
668
  * })
593
669
  * ```
594
670
  *
595
- * @param config - The multisig config.
671
+ * @param config - The account config.
596
672
  * @returns The RLP tuple.
597
673
  */
598
674
  export function toTuple(config: Input): Tuple {
@@ -613,14 +689,75 @@ export function toTuple(config: Input): Tuple {
613
689
  }
614
690
 
615
691
  /**
616
- * Validates a native multisig {@link ox#MultisigConfig.Config}. Returns `true`
692
+ * Derives the configuration that replaces the current one in an owner update.
693
+ *
694
+ * Mirrors the `updateConfig` precompile ([TIP-1109](https://tips.sh/1109)):
695
+ * keeps the current salt, increments the version by one, and replaces the
696
+ * owners and threshold. Owners are sorted into canonical order and the next
697
+ * configuration is validated. The account address does not change.
698
+ *
699
+ * @example
700
+ * ```ts twoslash
701
+ * import { AccountConfig } from 'ox/tempo'
702
+ *
703
+ * const initialConfig = AccountConfig.from({
704
+ * owners: [
705
+ * { owner: '0x1111111111111111111111111111111111111111', weight: 1 },
706
+ * ],
707
+ * threshold: 1,
708
+ * })
709
+ *
710
+ * const config = AccountConfig.update(initialConfig, {
711
+ * owners: [
712
+ * { owner: '0x2222222222222222222222222222222222222222', weight: 1 },
713
+ * ],
714
+ * threshold: 1,
715
+ * })
716
+ * // config.version === 1n, with the initial salt
717
+ * ```
718
+ *
719
+ * @param config - The current account config.
720
+ * @param options - The replacement owners and threshold.
721
+ * @returns The next account config.
722
+ */
723
+ export function update<numberType = number>(
724
+ config: Input<bigint | number, numberType>,
725
+ options: update.Options<numberType>,
726
+ ): Config<bigint, numberType> {
727
+ const current = from(config)
728
+ if (current.version === maxVersion)
729
+ throw new InvalidConfigError({ reason: 'version overflow' })
730
+ return from({
731
+ owners: options.owners,
732
+ salt: current.salt,
733
+ threshold: options.threshold,
734
+ version: current.version + 1n,
735
+ })
736
+ }
737
+
738
+ export declare namespace update {
739
+ type Options<numberType = number> = {
740
+ /** Replacement weighted owners. Sorted into canonical order. */
741
+ owners: readonly Owner<numberType>[]
742
+ /** Replacement minimum total owner weight required for authorization. */
743
+ threshold: numberType
744
+ }
745
+
746
+ type ErrorType =
747
+ | assert.ErrorType
748
+ | InvalidConfigError
749
+ | Errors.GlobalErrorType
750
+ }
751
+
752
+ /**
753
+ * Validates an {@link ox#AccountConfig.Config}. Returns `true`
617
754
  * if valid, `false` otherwise.
618
755
  *
619
756
  * @example
620
757
  * ```ts twoslash
621
- * import { MultisigConfig } from 'ox/tempo'
758
+ * import { AccountConfig } from 'ox/tempo'
622
759
  *
623
- * const valid = MultisigConfig.validate({
760
+ * const valid = AccountConfig.validate({
624
761
  * owners: [
625
762
  * { owner: '0x1111111111111111111111111111111111111111', weight: 1 },
626
763
  * ],
@@ -629,7 +766,7 @@ export function toTuple(config: Input): Tuple {
629
766
  * // @log: true
630
767
  * ```
631
768
  *
632
- * @param config - The multisig config.
769
+ * @param config - The account config.
633
770
  * @returns Whether the config is valid.
634
771
  */
635
772
  export function validate(config: Input): boolean {
@@ -641,11 +778,11 @@ export function validate(config: Input): boolean {
641
778
  }
642
779
  }
643
780
 
644
- /** Thrown when a native multisig config is invalid. */
781
+ /** Thrown when an account config is invalid. */
645
782
  export class InvalidConfigError extends Errors.BaseError {
646
- override readonly name = 'MultisigConfig.InvalidConfigError'
783
+ override readonly name = 'AccountConfig.InvalidConfigError'
647
784
  constructor({ reason }: { reason: string }) {
648
- super(`Invalid native multisig config: ${reason}.`)
785
+ super(`Invalid account config: ${reason}.`)
649
786
  }
650
787
  }
651
788
 
@@ -0,0 +1,6 @@
1
+ {
2
+ "type": "module",
3
+ "types": "../../_types/tempo/AccountOperation.d.ts",
4
+ "main": "../../_cjs/tempo/AccountOperation.js",
5
+ "module": "../../_esm/tempo/AccountOperation.js"
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "type": "module",
3
+ "types": "../../_types/tempo/AccountOperation.test-d.d.ts",
4
+ "main": "../../_cjs/tempo/AccountOperation.test-d.js",
5
+ "module": "../../_esm/tempo/AccountOperation.test-d.js"
6
+ }
@@ -0,0 +1,71 @@
1
+ import { expectTypeOf, test } from 'vitest'
2
+ import type * as Hex from '../core/Hex.js'
3
+ import * as AccountOperation from './AccountOperation.js'
4
+ import type * as TxEnvelopeTempo from './TxEnvelopeTempo.js'
5
+
6
+ declare const transaction: AccountOperation.TransactionOperation
7
+ declare const transactionRpc: AccountOperation.TransactionRpc
8
+ declare const keyAuthorization: AccountOperation.KeyAuthorizationOperation
9
+ declare const keyAuthorizationRpc: AccountOperation.KeyAuthorizationRpc
10
+ declare const operation: AccountOperation.Operation
11
+ declare const operationRpc: AccountOperation.Rpc
12
+ declare const getHashOptions: AccountOperation.getHash.Options
13
+ declare const selectApprovalsOptions: AccountOperation.selectApprovals.Options
14
+ declare const serializeTransactionOptions: AccountOperation.serializeTransaction.Options
15
+
16
+ test('preserves operation kinds during validation', () => {
17
+ expectTypeOf(
18
+ AccountOperation.from(transaction),
19
+ ).toEqualTypeOf<AccountOperation.TransactionOperation>()
20
+ expectTypeOf(
21
+ AccountOperation.from(keyAuthorization),
22
+ ).toEqualTypeOf<AccountOperation.KeyAuthorizationOperation>()
23
+ expectTypeOf(
24
+ AccountOperation.from(operation),
25
+ ).toEqualTypeOf<AccountOperation.Operation>()
26
+ })
27
+
28
+ test('preserves operation kinds during RPC conversion', () => {
29
+ expectTypeOf(
30
+ AccountOperation.fromRpc(transactionRpc),
31
+ ).toEqualTypeOf<AccountOperation.TransactionOperation>()
32
+ expectTypeOf(
33
+ AccountOperation.fromRpc(keyAuthorizationRpc),
34
+ ).toEqualTypeOf<AccountOperation.KeyAuthorizationOperation>()
35
+ expectTypeOf(
36
+ AccountOperation.toRpc(transaction),
37
+ ).toEqualTypeOf<AccountOperation.TransactionRpc>()
38
+ expectTypeOf(
39
+ AccountOperation.toRpc(keyAuthorization),
40
+ ).toEqualTypeOf<AccountOperation.KeyAuthorizationRpc>()
41
+ expectTypeOf(
42
+ AccountOperation.fromRpc(operationRpc),
43
+ ).toEqualTypeOf<AccountOperation.Operation>()
44
+ expectTypeOf(
45
+ AccountOperation.toRpc(operation),
46
+ ).toEqualTypeOf<AccountOperation.Rpc>()
47
+ })
48
+
49
+ test('uses JSON-RPC quantities only in RPC operations', () => {
50
+ expectTypeOf<
51
+ AccountOperation.Operation['config']['version']
52
+ >().toEqualTypeOf<bigint>()
53
+ expectTypeOf<
54
+ AccountOperation.Rpc['config']['version']
55
+ >().toEqualTypeOf<Hex.Hex>()
56
+ })
57
+
58
+ test('operation helpers return narrow types', async () => {
59
+ expectTypeOf(
60
+ AccountOperation.getHash(getHashOptions),
61
+ ).toEqualTypeOf<Hex.Hex>()
62
+ expectTypeOf(
63
+ await AccountOperation.selectApprovals(selectApprovalsOptions),
64
+ ).toEqualTypeOf<AccountOperation.selectApprovals.ReturnValue>()
65
+ expectTypeOf(
66
+ AccountOperation.serializeTransaction(
67
+ transaction,
68
+ serializeTransactionOptions,
69
+ ),
70
+ ).toEqualTypeOf<TxEnvelopeTempo.Serialized>()
71
+ })