ox 0.14.28 → 0.14.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/_cjs/tempo/MultisigConfig.js +19 -21
- package/_cjs/tempo/MultisigConfig.js.map +1 -1
- package/_cjs/tempo/SignatureEnvelope.js +62 -28
- package/_cjs/tempo/SignatureEnvelope.js.map +1 -1
- package/_cjs/version.js +1 -1
- package/_esm/tempo/MultisigConfig.js +60 -49
- package/_esm/tempo/MultisigConfig.js.map +1 -1
- package/_esm/tempo/SignatureEnvelope.js +118 -41
- package/_esm/tempo/SignatureEnvelope.js.map +1 -1
- package/_esm/tempo/index.js +4 -4
- package/_esm/version.js +1 -1
- package/_types/tempo/MultisigConfig.d.ts +68 -56
- package/_types/tempo/MultisigConfig.d.ts.map +1 -1
- package/_types/tempo/SignatureEnvelope.d.ts +90 -26
- package/_types/tempo/SignatureEnvelope.d.ts.map +1 -1
- package/_types/tempo/index.d.ts +4 -4
- package/_types/version.d.ts +1 -1
- package/package.json +1 -1
- package/tempo/MultisigConfig.test.ts +62 -36
- package/tempo/MultisigConfig.ts +102 -95
- package/tempo/SignatureEnvelope.test.ts +226 -27
- package/tempo/SignatureEnvelope.ts +174 -69
- package/tempo/e2e.test.ts +263 -48
- package/tempo/index.ts +4 -4
- package/version.ts +1 -1
|
@@ -30,31 +30,51 @@ describe('from', () => {
|
|
|
30
30
|
})
|
|
31
31
|
})
|
|
32
32
|
|
|
33
|
-
describe('
|
|
33
|
+
describe('getAddress', () => {
|
|
34
34
|
test('matches independent ground truth', () => {
|
|
35
|
-
expect(MultisigConfig.
|
|
36
|
-
`"
|
|
35
|
+
expect(MultisigConfig.getAddress(singleOwnerConfig)).toMatchInlineSnapshot(
|
|
36
|
+
`"0x8820d1497eeaf4f68e00b2cfc00a2f3b1dbb00da"`,
|
|
37
37
|
)
|
|
38
38
|
})
|
|
39
39
|
|
|
40
|
+
test('matches independent ground truth (salt + weights)', () => {
|
|
41
|
+
expect(
|
|
42
|
+
MultisigConfig.getAddress({
|
|
43
|
+
salt: `0x${'42'.repeat(32)}`,
|
|
44
|
+
threshold: 2,
|
|
45
|
+
owners: [
|
|
46
|
+
{ owner: owner1, weight: 1 },
|
|
47
|
+
{ owner: owner2, weight: 2 },
|
|
48
|
+
],
|
|
49
|
+
}),
|
|
50
|
+
).toMatchInlineSnapshot(`"0x0773e28146400643e42cb28f6659b74e7c0b451d"`)
|
|
51
|
+
})
|
|
52
|
+
|
|
40
53
|
test('is stable across calls', () => {
|
|
41
|
-
expect(MultisigConfig.
|
|
42
|
-
MultisigConfig.
|
|
54
|
+
expect(MultisigConfig.getAddress(singleOwnerConfig)).toBe(
|
|
55
|
+
MultisigConfig.getAddress(singleOwnerConfig),
|
|
43
56
|
)
|
|
44
57
|
})
|
|
45
58
|
|
|
46
59
|
test('differs for a different salt', () => {
|
|
47
|
-
expect(MultisigConfig.
|
|
48
|
-
MultisigConfig.
|
|
60
|
+
expect(MultisigConfig.getAddress(singleOwnerConfig)).not.toBe(
|
|
61
|
+
MultisigConfig.getAddress({
|
|
49
62
|
...singleOwnerConfig,
|
|
50
63
|
salt: `0x${'42'.repeat(32)}`,
|
|
51
64
|
}),
|
|
52
65
|
)
|
|
53
66
|
})
|
|
54
67
|
|
|
68
|
+
test('address is chain-independent', () => {
|
|
69
|
+
// Derivation does not include chain ID; identical config → identical address.
|
|
70
|
+
const a = MultisigConfig.getAddress(singleOwnerConfig)
|
|
71
|
+
const b = MultisigConfig.getAddress(MultisigConfig.from(singleOwnerConfig))
|
|
72
|
+
expect(a).toBe(b)
|
|
73
|
+
})
|
|
74
|
+
|
|
55
75
|
test('throws on invalid config', () => {
|
|
56
76
|
expect(() =>
|
|
57
|
-
MultisigConfig.
|
|
77
|
+
MultisigConfig.getAddress({
|
|
58
78
|
threshold: 5,
|
|
59
79
|
owners: singleOwnerConfig.owners,
|
|
60
80
|
}),
|
|
@@ -62,41 +82,27 @@ describe('configId', () => {
|
|
|
62
82
|
})
|
|
63
83
|
})
|
|
64
84
|
|
|
65
|
-
describe('
|
|
85
|
+
describe('getSignPayload', () => {
|
|
66
86
|
test('matches independent ground truth', () => {
|
|
67
87
|
expect(
|
|
68
|
-
MultisigConfig.
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
expect(MultisigConfig.getAddress({ configId })).toBe(
|
|
75
|
-
MultisigConfig.getAddress({ config: singleOwnerConfig }),
|
|
88
|
+
MultisigConfig.getSignPayload({
|
|
89
|
+
payload: `0x${'de'.repeat(32)}`,
|
|
90
|
+
genesisConfig: singleOwnerConfig,
|
|
91
|
+
}),
|
|
92
|
+
).toMatchInlineSnapshot(
|
|
93
|
+
`"0x7df8cb9fef4fc2aeb271b617d1a4c6178b720ae1d7564f48a363069b7d77a079"`,
|
|
76
94
|
)
|
|
77
95
|
})
|
|
78
96
|
|
|
79
|
-
test('
|
|
80
|
-
|
|
81
|
-
const
|
|
82
|
-
const b = MultisigConfig.toId(MultisigConfig.from(singleOwnerConfig))
|
|
83
|
-
expect(a).toBe(b)
|
|
84
|
-
})
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
describe('getSignPayload', () => {
|
|
88
|
-
test('matches independent ground truth', () => {
|
|
89
|
-
const configId = MultisigConfig.toId(singleOwnerConfig)
|
|
90
|
-
const account = MultisigConfig.getAddress({ configId })
|
|
97
|
+
test('behavior: `genesisConfig` and `{ account }` produce identical digests', () => {
|
|
98
|
+
const account = MultisigConfig.getAddress(singleOwnerConfig)
|
|
99
|
+
const payload = `0x${'42'.repeat(32)}` as const
|
|
91
100
|
expect(
|
|
92
101
|
MultisigConfig.getSignPayload({
|
|
93
|
-
payload
|
|
94
|
-
|
|
95
|
-
configId,
|
|
102
|
+
payload,
|
|
103
|
+
genesisConfig: singleOwnerConfig,
|
|
96
104
|
}),
|
|
97
|
-
).
|
|
98
|
-
`"0xe3d66f6118b89a67c71c8137c46abf0c829056a46ee6a038a1b42c84529fc17e"`,
|
|
99
|
-
)
|
|
105
|
+
).toBe(MultisigConfig.getSignPayload({ payload, account }))
|
|
100
106
|
})
|
|
101
107
|
})
|
|
102
108
|
|
|
@@ -143,8 +149,16 @@ describe('assert / validate', () => {
|
|
|
143
149
|
expect(MultisigConfig.validate({ threshold: 1, owners: [] })).toBe(false)
|
|
144
150
|
})
|
|
145
151
|
|
|
152
|
+
test('accepts 255 owners', () => {
|
|
153
|
+
const owners = Array.from({ length: 255 }, (_, i) => ({
|
|
154
|
+
owner: `0x${(i + 1).toString(16).padStart(40, '0')}` as `0x${string}`,
|
|
155
|
+
weight: 1,
|
|
156
|
+
}))
|
|
157
|
+
expect(MultisigConfig.validate({ threshold: 255, owners })).toBe(true)
|
|
158
|
+
})
|
|
159
|
+
|
|
146
160
|
test('too many owners', () => {
|
|
147
|
-
const owners = Array.from({ length:
|
|
161
|
+
const owners = Array.from({ length: 256 }, (_, i) => ({
|
|
148
162
|
owner: `0x${(i + 1).toString(16).padStart(40, '0')}` as `0x${string}`,
|
|
149
163
|
weight: 1,
|
|
150
164
|
}))
|
|
@@ -169,6 +183,18 @@ describe('assert / validate', () => {
|
|
|
169
183
|
).toBe(false)
|
|
170
184
|
})
|
|
171
185
|
|
|
186
|
+
test('total weight exceeds u8 max', () => {
|
|
187
|
+
expect(
|
|
188
|
+
MultisigConfig.validate({
|
|
189
|
+
threshold: 255,
|
|
190
|
+
owners: [
|
|
191
|
+
{ owner: owner1, weight: 128 },
|
|
192
|
+
{ owner: owner2, weight: 128 },
|
|
193
|
+
],
|
|
194
|
+
}),
|
|
195
|
+
).toBe(false)
|
|
196
|
+
})
|
|
197
|
+
|
|
172
198
|
test('zero owner weight', () => {
|
|
173
199
|
expect(
|
|
174
200
|
MultisigConfig.validate({
|
package/tempo/MultisigConfig.ts
CHANGED
|
@@ -3,10 +3,16 @@ import type * as Bytes from '../core/Bytes.js'
|
|
|
3
3
|
import * as Errors from '../core/Errors.js'
|
|
4
4
|
import * as Hash from '../core/Hash.js'
|
|
5
5
|
import * as Hex from '../core/Hex.js'
|
|
6
|
-
import type { Compute } from '../core/internal/types.js'
|
|
6
|
+
import type { Compute, OneOf } from '../core/internal/types.js'
|
|
7
7
|
|
|
8
8
|
/** Maximum number of owners allowed in a native multisig config. */
|
|
9
|
-
export const maxOwners =
|
|
9
|
+
export const maxOwners = 255
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Maximum number of native multisig signatures in one nested authorization
|
|
13
|
+
* path, including the top-level transaction signature.
|
|
14
|
+
*/
|
|
15
|
+
export const maxNestingDepth = 3
|
|
10
16
|
|
|
11
17
|
/** Maximum encoded byte length for one primitive owner approval. */
|
|
12
18
|
export const maxOwnerSignatureBytes = 2049
|
|
@@ -20,20 +26,17 @@ export const zeroSalt = `0x${'00'.repeat(32)}` as const
|
|
|
20
26
|
/** Domain prefix for the native multisig account address derivation. */
|
|
21
27
|
const accountDomain = 'tempo:multisig:account'
|
|
22
28
|
|
|
23
|
-
/** Domain prefix for the native multisig config ID derivation. */
|
|
24
|
-
const configDomain = 'tempo:multisig:config'
|
|
25
|
-
|
|
26
29
|
/** Domain prefix for native multisig owner approvals. */
|
|
27
30
|
const signatureDomain = 'tempo:multisig:signature'
|
|
28
31
|
|
|
29
32
|
/**
|
|
30
|
-
* Native multisig configuration. Determines the
|
|
31
|
-
*
|
|
33
|
+
* Native multisig configuration. Determines the stable multisig account
|
|
34
|
+
* address.
|
|
32
35
|
*/
|
|
33
36
|
export type Config<numberType = number> = Compute<{
|
|
34
37
|
/**
|
|
35
|
-
* Caller-chosen 32-byte salt mixed into the
|
|
36
|
-
* the zero salt (`MultisigConfig.zeroSalt`) when omitted.
|
|
38
|
+
* Caller-chosen 32-byte salt mixed into the derived account address.
|
|
39
|
+
* Defaults to the zero salt (`MultisigConfig.zeroSalt`) when omitted.
|
|
37
40
|
*/
|
|
38
41
|
salt?: Hex.Hex | undefined
|
|
39
42
|
/** Minimum total owner weight required to authorize a transaction. */
|
|
@@ -44,7 +47,7 @@ export type Config<numberType = number> = Compute<{
|
|
|
44
47
|
|
|
45
48
|
/** Native multisig owner entry. */
|
|
46
49
|
export type Owner<numberType = number> = {
|
|
47
|
-
/** Owner address (recovered from the owner's
|
|
50
|
+
/** Owner address (recovered from the owner's approval). */
|
|
48
51
|
owner: Address.Address
|
|
49
52
|
/** Nonzero owner weight. */
|
|
50
53
|
weight: numberType
|
|
@@ -60,9 +63,9 @@ export type Tuple = readonly [
|
|
|
60
63
|
/**
|
|
61
64
|
* Asserts that a native multisig {@link ox#MultisigConfig.Config} is valid.
|
|
62
65
|
*
|
|
63
|
-
* Mirrors the Tempo `
|
|
66
|
+
* Mirrors the Tempo `InitMultisig::validate` rules: owners non-empty and
|
|
64
67
|
* `<= maxOwners`, strictly ascending unique nonzero owner addresses, nonzero
|
|
65
|
-
* owner weights, `threshold >= 1`, total weight `<=
|
|
68
|
+
* owner weights, `threshold >= 1`, total weight `<= 255` (u8 max), and
|
|
66
69
|
* `threshold <= total weight`.
|
|
67
70
|
*
|
|
68
71
|
* @example
|
|
@@ -109,9 +112,9 @@ export function assert<numberType = number>(config: Config<numberType>): void {
|
|
|
109
112
|
totalWeight += Number(owner.weight)
|
|
110
113
|
}
|
|
111
114
|
|
|
112
|
-
if (totalWeight >
|
|
115
|
+
if (totalWeight > 0xff)
|
|
113
116
|
throw new InvalidConfigError({
|
|
114
|
-
reason: 'total owner weight exceeds
|
|
117
|
+
reason: 'total owner weight exceeds u8 max',
|
|
115
118
|
})
|
|
116
119
|
if (Number(threshold) > totalWeight)
|
|
117
120
|
throw new InvalidConfigError({
|
|
@@ -127,7 +130,7 @@ export declare namespace assert {
|
|
|
127
130
|
* Normalizes a native multisig {@link ox#MultisigConfig.Config}.
|
|
128
131
|
*
|
|
129
132
|
* Sorts owners into strictly ascending `owner` address order (the canonical
|
|
130
|
-
* form required for
|
|
133
|
+
* form required for account derivation) and asserts the config is valid.
|
|
131
134
|
*
|
|
132
135
|
* @example
|
|
133
136
|
* ```ts twoslash
|
|
@@ -197,39 +200,57 @@ export function fromTuple(tuple: Tuple): Config {
|
|
|
197
200
|
/**
|
|
198
201
|
* Derives the stable native multisig account address.
|
|
199
202
|
*
|
|
200
|
-
*
|
|
203
|
+
* Preimage (fixed-width big-endian, **not** RLP):
|
|
204
|
+
* `keccak256("tempo:multisig:account" || salt || u8(threshold) || u8(owners.length) || (owner || u8(weight)) for each owner)[12:32]`.
|
|
205
|
+
*
|
|
206
|
+
* The address is derived once from the initial (bootstrap) config and never
|
|
207
|
+
* changes — config updates do not affect it.
|
|
201
208
|
*
|
|
202
209
|
* @example
|
|
203
210
|
* ```ts twoslash
|
|
204
211
|
* import { MultisigConfig } from 'ox/tempo'
|
|
205
212
|
*
|
|
206
|
-
* const
|
|
213
|
+
* const genesisConfig = MultisigConfig.from({
|
|
207
214
|
* threshold: 1,
|
|
208
215
|
* owners: [
|
|
209
216
|
* { owner: '0x1111111111111111111111111111111111111111', weight: 1 },
|
|
210
217
|
* ],
|
|
211
218
|
* })
|
|
212
219
|
*
|
|
213
|
-
* const address = MultisigConfig.getAddress(
|
|
220
|
+
* const address = MultisigConfig.getAddress(genesisConfig)
|
|
214
221
|
* ```
|
|
215
222
|
*
|
|
216
|
-
* @param
|
|
223
|
+
* @param config - The initial (bootstrap) multisig config.
|
|
217
224
|
* @returns The multisig account address.
|
|
218
225
|
*/
|
|
219
|
-
export function getAddress(
|
|
220
|
-
|
|
221
|
-
const hash = Hash.keccak256(
|
|
222
|
-
|
|
226
|
+
export function getAddress(config: Config): Address.Address {
|
|
227
|
+
assert(config)
|
|
228
|
+
const hash = Hash.keccak256(
|
|
229
|
+
Hex.concat(
|
|
230
|
+
Hex.fromString(accountDomain),
|
|
231
|
+
Hex.padLeft(config.salt ?? zeroSalt, 32),
|
|
232
|
+
Hex.fromNumber(config.threshold, { size: 1 }),
|
|
233
|
+
Hex.fromNumber(config.owners.length, { size: 1 }),
|
|
234
|
+
...config.owners.flatMap((owner) => [
|
|
235
|
+
owner.owner,
|
|
236
|
+
Hex.fromNumber(owner.weight, { size: 1 }),
|
|
237
|
+
]),
|
|
238
|
+
),
|
|
239
|
+
)
|
|
240
|
+
const account = Address.from(Hex.slice(hash, 12, 32))
|
|
241
|
+
if (Hex.toBigInt(account) === 0n)
|
|
242
|
+
throw new InvalidConfigError({ reason: 'derived account cannot be zero' })
|
|
243
|
+
return account
|
|
223
244
|
}
|
|
224
245
|
|
|
225
246
|
export declare namespace getAddress {
|
|
226
|
-
type Value = { config: Config } | { configId: Hex.Hex }
|
|
227
|
-
|
|
228
247
|
type ErrorType =
|
|
229
|
-
|
|
|
248
|
+
| assert.ErrorType
|
|
230
249
|
| Address.from.ErrorType
|
|
231
250
|
| Hash.keccak256.ErrorType
|
|
232
251
|
| Hex.concat.ErrorType
|
|
252
|
+
| Hex.fromNumber.ErrorType
|
|
253
|
+
| Hex.fromString.ErrorType
|
|
233
254
|
| Hex.slice.ErrorType
|
|
234
255
|
| Errors.GlobalErrorType
|
|
235
256
|
}
|
|
@@ -237,22 +258,27 @@ export declare namespace getAddress {
|
|
|
237
258
|
/**
|
|
238
259
|
* Computes the digest a native multisig owner approves (signs).
|
|
239
260
|
*
|
|
240
|
-
* `keccak256("tempo:multisig:signature" || inner_digest || account
|
|
261
|
+
* `keccak256("tempo:multisig:signature" || inner_digest || account)`,
|
|
241
262
|
* where `inner_digest` is the transaction sign payload
|
|
242
263
|
* ({@link ox#TxEnvelopeTempo.(getSignPayload:function)}).
|
|
243
264
|
*
|
|
265
|
+
* The digest is keyed on the permanent `account` derived from the genesis
|
|
266
|
+
* (bootstrap) config — config updates never change it, so the genesis config
|
|
267
|
+
* is the correct input even for post-update transactions.
|
|
268
|
+
*
|
|
269
|
+
* For a nested multisig owner approval, the parent digest becomes the nested
|
|
270
|
+
* approval's `payload`, with the nested multisig `account`.
|
|
271
|
+
*
|
|
244
272
|
* @example
|
|
245
273
|
* ```ts twoslash
|
|
246
274
|
* import { MultisigConfig, TxEnvelopeTempo } from 'ox/tempo'
|
|
247
275
|
*
|
|
248
|
-
* const
|
|
276
|
+
* const genesisConfig = MultisigConfig.from({
|
|
249
277
|
* threshold: 1,
|
|
250
278
|
* owners: [
|
|
251
279
|
* { owner: '0x1111111111111111111111111111111111111111', weight: 1 },
|
|
252
280
|
* ],
|
|
253
281
|
* })
|
|
254
|
-
* const configId = MultisigConfig.toId(config)
|
|
255
|
-
* const account = MultisigConfig.getAddress({ configId })
|
|
256
282
|
*
|
|
257
283
|
* const envelope = TxEnvelopeTempo.from({
|
|
258
284
|
* chainId: 1,
|
|
@@ -261,93 +287,74 @@ export declare namespace getAddress {
|
|
|
261
287
|
*
|
|
262
288
|
* const digest = MultisigConfig.getSignPayload({
|
|
263
289
|
* payload: TxEnvelopeTempo.getSignPayload(envelope),
|
|
264
|
-
*
|
|
265
|
-
* configId,
|
|
290
|
+
* genesisConfig,
|
|
266
291
|
* })
|
|
267
292
|
* ```
|
|
268
293
|
*
|
|
269
|
-
* @
|
|
270
|
-
*
|
|
271
|
-
*/
|
|
272
|
-
export function getSignPayload(value: getSignPayload.Value): Hex.Hex {
|
|
273
|
-
const { payload, account, configId } = value
|
|
274
|
-
return Hash.keccak256(
|
|
275
|
-
Hex.concat(
|
|
276
|
-
Hex.fromString(signatureDomain),
|
|
277
|
-
Hex.from(payload),
|
|
278
|
-
account,
|
|
279
|
-
configId,
|
|
280
|
-
),
|
|
281
|
-
)
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
export declare namespace getSignPayload {
|
|
285
|
-
type Value = {
|
|
286
|
-
/** The inner transaction sign payload (`tx.signature_hash()`). */
|
|
287
|
-
payload: Hex.Hex | Bytes.Bytes
|
|
288
|
-
/** The native multisig account address. */
|
|
289
|
-
account: Address.Address
|
|
290
|
-
/** The permanent config ID. */
|
|
291
|
-
configId: Hex.Hex
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
type ErrorType =
|
|
295
|
-
| Hash.keccak256.ErrorType
|
|
296
|
-
| Hex.concat.ErrorType
|
|
297
|
-
| Hex.from.ErrorType
|
|
298
|
-
| Errors.GlobalErrorType
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
/**
|
|
302
|
-
* Derives the permanent config ID for a native multisig
|
|
303
|
-
* {@link ox#MultisigConfig.Config}.
|
|
294
|
+
* @example
|
|
295
|
+
* ### From `account`
|
|
304
296
|
*
|
|
305
|
-
*
|
|
306
|
-
*
|
|
297
|
+
* If you already have the permanent `account` (for example, recovered from a
|
|
298
|
+
* stored envelope), pass it directly:
|
|
307
299
|
*
|
|
308
|
-
* @example
|
|
309
300
|
* ```ts twoslash
|
|
310
|
-
* import { MultisigConfig } from 'ox/tempo'
|
|
301
|
+
* import { MultisigConfig, TxEnvelopeTempo } from 'ox/tempo'
|
|
311
302
|
*
|
|
312
|
-
* const
|
|
303
|
+
* const genesisConfig = MultisigConfig.from({
|
|
313
304
|
* threshold: 1,
|
|
314
305
|
* owners: [
|
|
315
306
|
* { owner: '0x1111111111111111111111111111111111111111', weight: 1 },
|
|
316
307
|
* ],
|
|
317
308
|
* })
|
|
309
|
+
* const account = MultisigConfig.getAddress(genesisConfig)
|
|
318
310
|
*
|
|
319
|
-
* const
|
|
311
|
+
* const envelope = TxEnvelopeTempo.from({ chainId: 1, calls: [] })
|
|
312
|
+
*
|
|
313
|
+
* const digest = MultisigConfig.getSignPayload({
|
|
314
|
+
* payload: TxEnvelopeTempo.getSignPayload(envelope),
|
|
315
|
+
* account
|
|
316
|
+
* })
|
|
320
317
|
* ```
|
|
321
318
|
*
|
|
322
|
-
* @param
|
|
323
|
-
* @returns The
|
|
319
|
+
* @param value - The digest derivation parameters.
|
|
320
|
+
* @returns The owner approval digest.
|
|
324
321
|
*/
|
|
325
|
-
export function
|
|
326
|
-
|
|
327
|
-
const
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
...config.owners.flatMap((owner) => [
|
|
334
|
-
owner.owner,
|
|
335
|
-
Hex.fromNumber(owner.weight, { size: 4 }),
|
|
336
|
-
]),
|
|
337
|
-
),
|
|
322
|
+
export function getSignPayload(value: getSignPayload.Value): Hex.Hex {
|
|
323
|
+
const { payload } = value
|
|
324
|
+
const account =
|
|
325
|
+
'account' in value && value.account
|
|
326
|
+
? value.account
|
|
327
|
+
: getAddress((value as { genesisConfig: Config }).genesisConfig)
|
|
328
|
+
return Hash.keccak256(
|
|
329
|
+
Hex.concat(Hex.fromString(signatureDomain), Hex.from(payload), account),
|
|
338
330
|
)
|
|
339
|
-
if (Hex.toBigInt(id) === 0n)
|
|
340
|
-
throw new InvalidConfigError({ reason: 'config ID cannot be zero' })
|
|
341
|
-
return id
|
|
342
331
|
}
|
|
343
332
|
|
|
344
|
-
export declare namespace
|
|
333
|
+
export declare namespace getSignPayload {
|
|
334
|
+
type Value = {
|
|
335
|
+
/** The inner transaction sign payload (`tx.signature_hash()`). */
|
|
336
|
+
payload: Hex.Hex | Bytes.Bytes
|
|
337
|
+
} & OneOf<
|
|
338
|
+
| {
|
|
339
|
+
/** The native multisig account address. */
|
|
340
|
+
account: Address.Address
|
|
341
|
+
}
|
|
342
|
+
| {
|
|
343
|
+
/**
|
|
344
|
+
* The initial multisig config (the bootstrap config that derived the
|
|
345
|
+
* permanent `account`). Used to derive the account automatically.
|
|
346
|
+
* Config updates never change `account`, so the genesis config is
|
|
347
|
+
* also the correct input for post-update transactions.
|
|
348
|
+
*/
|
|
349
|
+
genesisConfig: Config
|
|
350
|
+
}
|
|
351
|
+
>
|
|
352
|
+
|
|
345
353
|
type ErrorType =
|
|
346
|
-
|
|
|
354
|
+
| getAddress.ErrorType
|
|
347
355
|
| Hash.keccak256.ErrorType
|
|
348
356
|
| Hex.concat.ErrorType
|
|
349
|
-
| Hex.
|
|
350
|
-
| Hex.fromString.ErrorType
|
|
357
|
+
| Hex.from.ErrorType
|
|
351
358
|
| Errors.GlobalErrorType
|
|
352
359
|
}
|
|
353
360
|
|