ox 0.14.30 → 0.14.32
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 +25 -0
- package/_cjs/core/AbiParameters.js +2 -1
- package/_cjs/core/AbiParameters.js.map +1 -1
- package/_cjs/core/internal/abiParameters.js +10 -2
- package/_cjs/core/internal/abiParameters.js.map +1 -1
- package/_cjs/tempo/EarnShares.js +66 -0
- package/_cjs/tempo/EarnShares.js.map +1 -0
- package/_cjs/tempo/KeyAuthorization.js +39 -10
- package/_cjs/tempo/KeyAuthorization.js.map +1 -1
- package/_cjs/tempo/MultisigConfig.js +12 -2
- package/_cjs/tempo/MultisigConfig.js.map +1 -1
- package/_cjs/tempo/SignatureEnvelope.js +167 -46
- package/_cjs/tempo/SignatureEnvelope.js.map +1 -1
- package/_cjs/tempo/index.js +2 -1
- package/_cjs/tempo/index.js.map +1 -1
- package/_cjs/version.js +1 -1
- package/_esm/core/AbiParameters.js +4 -1
- package/_esm/core/AbiParameters.js.map +1 -1
- package/_esm/core/internal/abiParameters.js +17 -2
- package/_esm/core/internal/abiParameters.js.map +1 -1
- package/_esm/tempo/EarnShares.js +167 -0
- package/_esm/tempo/EarnShares.js.map +1 -0
- package/_esm/tempo/KeyAuthorization.js +41 -9
- package/_esm/tempo/KeyAuthorization.js.map +1 -1
- package/_esm/tempo/MultisigConfig.js +16 -4
- package/_esm/tempo/MultisigConfig.js.map +1 -1
- package/_esm/tempo/SignatureEnvelope.js +172 -55
- package/_esm/tempo/SignatureEnvelope.js.map +1 -1
- package/_esm/tempo/index.js +22 -0
- package/_esm/tempo/index.js.map +1 -1
- package/_esm/version.js +1 -1
- package/_types/core/AbiParameters.d.ts.map +1 -1
- package/_types/core/internal/abiParameters.d.ts.map +1 -1
- package/_types/core/internal/rpcSchemas/eth.d.ts +16 -0
- package/_types/core/internal/rpcSchemas/eth.d.ts.map +1 -1
- package/_types/tempo/EarnShares.d.ts +176 -0
- package/_types/tempo/EarnShares.d.ts.map +1 -0
- package/_types/tempo/KeyAuthorization.d.ts +22 -16
- package/_types/tempo/KeyAuthorization.d.ts.map +1 -1
- package/_types/tempo/MultisigConfig.d.ts +8 -4
- package/_types/tempo/MultisigConfig.d.ts.map +1 -1
- package/_types/tempo/SignatureEnvelope.d.ts +33 -13
- package/_types/tempo/SignatureEnvelope.d.ts.map +1 -1
- package/_types/tempo/index.d.ts +22 -0
- package/_types/tempo/index.d.ts.map +1 -1
- package/_types/version.d.ts +1 -1
- package/core/AbiParameters.ts +3 -1
- package/core/internal/abiParameters.ts +17 -2
- package/core/internal/rpcSchemas/eth.ts +16 -0
- package/package.json +16 -1
- package/tempo/EarnShares/package.json +6 -0
- package/tempo/EarnShares.test.ts +122 -0
- package/tempo/EarnShares.ts +232 -0
- package/tempo/KeyAuthorization.test-d/package.json +6 -0
- package/tempo/KeyAuthorization.test-d.ts +62 -0
- package/tempo/KeyAuthorization.test.ts +132 -0
- package/tempo/KeyAuthorization.ts +76 -29
- package/tempo/MultisigConfig.test.ts +34 -2
- package/tempo/MultisigConfig.ts +18 -4
- package/tempo/SignatureEnvelope.test-d/package.json +6 -0
- package/tempo/SignatureEnvelope.test-d.ts +97 -0
- package/tempo/SignatureEnvelope.test.ts +227 -36
- package/tempo/SignatureEnvelope.ts +276 -85
- package/tempo/e2e.test.ts +0 -416
- package/tempo/index.ts +22 -0
- package/tempo/multisig.e2e.test.ts +582 -0
- package/version.ts +1 -1
|
@@ -72,10 +72,15 @@ export type GetType<
|
|
|
72
72
|
userAddress: Address.Address
|
|
73
73
|
}
|
|
74
74
|
? 'keychain'
|
|
75
|
-
: envelope extends
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
: envelope extends
|
|
76
|
+
| {
|
|
77
|
+
account: Address.Address
|
|
78
|
+
signatures: any
|
|
79
|
+
}
|
|
80
|
+
| {
|
|
81
|
+
init: MultisigConfig.Config
|
|
82
|
+
signatures: any
|
|
83
|
+
}
|
|
79
84
|
? 'multisig'
|
|
80
85
|
: never
|
|
81
86
|
|
|
@@ -117,6 +122,16 @@ export type SignatureEnvelopeRpc = OneOf<
|
|
|
117
122
|
Secp256k1Rpc | P256Rpc | WebAuthnRpc | KeychainRpc | MultisigRpc
|
|
118
123
|
>
|
|
119
124
|
|
|
125
|
+
/** Primitive signature envelope accepted by protocol sidecars. */
|
|
126
|
+
export type Primitive<bigintType = bigint, numberType = number> = OneOf<
|
|
127
|
+
| Secp256k1<bigintType, numberType>
|
|
128
|
+
| P256<bigintType, numberType>
|
|
129
|
+
| WebAuthn<bigintType, numberType>
|
|
130
|
+
>
|
|
131
|
+
|
|
132
|
+
/** RPC-formatted primitive signature envelope. */
|
|
133
|
+
export type PrimitiveRpc = OneOf<Secp256k1Rpc | P256Rpc | WebAuthnRpc>
|
|
134
|
+
|
|
120
135
|
/**
|
|
121
136
|
* Keychain signature version.
|
|
122
137
|
*
|
|
@@ -174,16 +189,25 @@ export type Multisig<bigintType = bigint, numberType = number> = {
|
|
|
174
189
|
init?: MultisigConfig.Config<numberType> | undefined
|
|
175
190
|
}
|
|
176
191
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
}
|
|
192
|
+
/** RPC-formatted native multisig signature. */
|
|
193
|
+
export type MultisigRpc = OneOf<
|
|
194
|
+
| {
|
|
195
|
+
/** Existing native multisig account. */
|
|
196
|
+
account: Address.Address
|
|
197
|
+
/** Structured owner approvals. */
|
|
198
|
+
signatures: readonly SignatureEnvelopeRpc[]
|
|
199
|
+
/** Multisig RPC signatures are untagged. */
|
|
200
|
+
type?: undefined
|
|
201
|
+
}
|
|
202
|
+
| {
|
|
203
|
+
/** Initial config for bootstrapping a native multisig account. */
|
|
204
|
+
init: MultisigConfig.Config
|
|
205
|
+
/** Structured owner approvals. */
|
|
206
|
+
signatures: readonly SignatureEnvelopeRpc[]
|
|
207
|
+
/** Multisig RPC signatures are untagged. */
|
|
208
|
+
type?: undefined
|
|
209
|
+
}
|
|
210
|
+
>
|
|
187
211
|
|
|
188
212
|
export type P256<bigintType = bigint, numberType = number> = {
|
|
189
213
|
prehash: boolean
|
|
@@ -327,27 +351,7 @@ export function assert(envelope: PartialBy<SignatureEnvelope, 'type'>): void {
|
|
|
327
351
|
|
|
328
352
|
if (type === 'multisig') {
|
|
329
353
|
const multisig = envelope as Multisig
|
|
330
|
-
|
|
331
|
-
if (!multisig.account) missing.push('account')
|
|
332
|
-
if (!Array.isArray(multisig.signatures)) missing.push('signatures')
|
|
333
|
-
if (missing.length > 0)
|
|
334
|
-
throw new MissingPropertiesError({ envelope, missing, type: 'multisig' })
|
|
335
|
-
if (getNestingDepth(multisig) > MultisigConfig.maxNestingDepth)
|
|
336
|
-
throw new InvalidMultisigApprovalError({
|
|
337
|
-
reason: `multisig nesting depth exceeds ${MultisigConfig.maxNestingDepth}`,
|
|
338
|
-
})
|
|
339
|
-
for (const inner of multisig.signatures) {
|
|
340
|
-
if (inner.type === 'keychain')
|
|
341
|
-
throw new InvalidMultisigApprovalError({
|
|
342
|
-
reason: 'keychain owner approvals are not allowed',
|
|
343
|
-
})
|
|
344
|
-
if (inner.type === 'multisig' && inner.init)
|
|
345
|
-
throw new InvalidMultisigApprovalError({
|
|
346
|
-
reason: 'nested multisig owner approvals cannot carry `init`',
|
|
347
|
-
})
|
|
348
|
-
assert(inner)
|
|
349
|
-
}
|
|
350
|
-
if (multisig.init) MultisigConfig.assert(multisig.init)
|
|
354
|
+
assertMultisig(multisig, 1)
|
|
351
355
|
return
|
|
352
356
|
}
|
|
353
357
|
}
|
|
@@ -358,17 +362,75 @@ export declare namespace assert {
|
|
|
358
362
|
| InvalidMultisigApprovalError
|
|
359
363
|
| MissingPropertiesError
|
|
360
364
|
| MultisigConfig.assert.ErrorType
|
|
365
|
+
| MultisigConfig.getAddress.ErrorType
|
|
361
366
|
| Signature.assert.ErrorType
|
|
362
367
|
| Errors.GlobalErrorType
|
|
363
368
|
}
|
|
364
369
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
370
|
+
function assertMultisig(envelope: Multisig, depth: number): void {
|
|
371
|
+
const missing: string[] = []
|
|
372
|
+
if (!envelope.account) missing.push('account')
|
|
373
|
+
if (!Array.isArray(envelope.signatures)) missing.push('signatures')
|
|
374
|
+
if (missing.length > 0)
|
|
375
|
+
throw new MissingPropertiesError({
|
|
376
|
+
envelope,
|
|
377
|
+
missing,
|
|
378
|
+
type: 'multisig',
|
|
379
|
+
})
|
|
380
|
+
if (depth > MultisigConfig.maxNestingDepth)
|
|
381
|
+
throw new InvalidMultisigApprovalError({
|
|
382
|
+
reason: `multisig nesting depth exceeds ${MultisigConfig.maxNestingDepth}`,
|
|
383
|
+
})
|
|
384
|
+
if (!Address.validate(envelope.account))
|
|
385
|
+
throw new InvalidMultisigApprovalError({
|
|
386
|
+
reason: 'multisig account is invalid',
|
|
387
|
+
})
|
|
388
|
+
if (Hex.toBigInt(envelope.account) === 0n)
|
|
389
|
+
throw new InvalidMultisigApprovalError({
|
|
390
|
+
reason: 'multisig account cannot be zero',
|
|
391
|
+
})
|
|
392
|
+
if (envelope.signatures.length === 0)
|
|
393
|
+
throw new InvalidMultisigApprovalError({
|
|
394
|
+
reason: 'multisig signatures cannot be empty',
|
|
395
|
+
})
|
|
396
|
+
if (envelope.signatures.length > MultisigConfig.maxSignatures)
|
|
397
|
+
throw new InvalidMultisigApprovalError({
|
|
398
|
+
reason: `multisig signatures exceed ${MultisigConfig.maxSignatures}`,
|
|
399
|
+
})
|
|
400
|
+
|
|
401
|
+
if (envelope.init) {
|
|
402
|
+
MultisigConfig.assert(envelope.init)
|
|
403
|
+
if (
|
|
404
|
+
!Address.isEqual(
|
|
405
|
+
MultisigConfig.getAddress(envelope.init),
|
|
406
|
+
envelope.account,
|
|
407
|
+
)
|
|
408
|
+
)
|
|
409
|
+
throw new InvalidMultisigApprovalError({
|
|
410
|
+
reason: 'multisig init does not derive account',
|
|
411
|
+
})
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
for (const inner of envelope.signatures) {
|
|
415
|
+
const type = getType(inner)
|
|
416
|
+
if (type === 'keychain')
|
|
417
|
+
throw new InvalidMultisigApprovalError({
|
|
418
|
+
reason: 'keychain owner approvals are not allowed',
|
|
419
|
+
})
|
|
420
|
+
if (type === 'multisig') {
|
|
421
|
+
const multisig = inner as Multisig
|
|
422
|
+
if (multisig.init)
|
|
423
|
+
throw new InvalidMultisigApprovalError({
|
|
424
|
+
reason: 'nested multisig owner approvals cannot carry `init`',
|
|
425
|
+
})
|
|
426
|
+
assertMultisig(multisig, depth + 1)
|
|
427
|
+
} else assert(inner)
|
|
428
|
+
|
|
429
|
+
if (Hex.size(serialize(inner)) > MultisigConfig.maxOwnerSignatureBytes)
|
|
430
|
+
throw new InvalidMultisigApprovalError({
|
|
431
|
+
reason: `multisig owner signature exceeds ${MultisigConfig.maxOwnerSignatureBytes} bytes`,
|
|
432
|
+
})
|
|
433
|
+
}
|
|
372
434
|
}
|
|
373
435
|
|
|
374
436
|
/**
|
|
@@ -516,6 +578,13 @@ export declare namespace extractPublicKey {
|
|
|
516
578
|
* @throws `CoercionError` if the serialized value cannot be coerced to a valid signature envelope.
|
|
517
579
|
*/
|
|
518
580
|
export function deserialize(value: Serialized): SignatureEnvelope {
|
|
581
|
+
return deserialize_(value, 0)
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
function deserialize_(
|
|
585
|
+
value: Serialized,
|
|
586
|
+
multisigDepth: number,
|
|
587
|
+
): SignatureEnvelope {
|
|
519
588
|
const serialized = value.endsWith(magicBytes.slice(2))
|
|
520
589
|
? Hex.slice(value, 0, -Hex.size(magicBytes))
|
|
521
590
|
: value
|
|
@@ -626,7 +695,7 @@ export function deserialize(value: Serialized): SignatureEnvelope {
|
|
|
626
695
|
typeId === serializedKeychainV2Type
|
|
627
696
|
) {
|
|
628
697
|
const userAddress = Hex.slice(data, 0, 20)
|
|
629
|
-
const inner =
|
|
698
|
+
const inner = deserialize_(Hex.slice(data, 20), multisigDepth)
|
|
630
699
|
|
|
631
700
|
return {
|
|
632
701
|
userAddress,
|
|
@@ -637,28 +706,91 @@ export function deserialize(value: Serialized): SignatureEnvelope {
|
|
|
637
706
|
}
|
|
638
707
|
|
|
639
708
|
if (typeId === serializedMultisigType) {
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
// omitted entirely (the empty `0x80` placeholder is rejected).
|
|
643
|
-
const [account, signatures, init] = Rlp.toHex(data) as [
|
|
644
|
-
Hex.Hex,
|
|
645
|
-
readonly Hex.Hex[],
|
|
646
|
-
(Hex.Hex | MultisigConfig.Tuple)?,
|
|
647
|
-
]
|
|
648
|
-
if (typeof init !== 'undefined' && !Array.isArray(init))
|
|
709
|
+
const depth = multisigDepth + 1
|
|
710
|
+
if (depth > MultisigConfig.maxNestingDepth)
|
|
649
711
|
throw new InvalidSerializedError({
|
|
650
|
-
reason:
|
|
651
|
-
'Invalid multisig `init`: expected the bootstrap config list or an omitted trailing element',
|
|
712
|
+
reason: `multisig nesting depth exceeds ${MultisigConfig.maxNestingDepth}`,
|
|
652
713
|
serialized,
|
|
653
714
|
})
|
|
654
|
-
|
|
715
|
+
|
|
716
|
+
// The first field distinguishes the static wire shapes: a bootstrap init
|
|
717
|
+
// config is an RLP list, while an initialized account is a 20-byte string.
|
|
718
|
+
const decoded = Rlp.toHex(data)
|
|
719
|
+
if (!Array.isArray(decoded) || decoded.length !== 2)
|
|
720
|
+
throw new InvalidSerializedError({
|
|
721
|
+
reason: 'invalid multisig wire shape: expected exactly two fields',
|
|
722
|
+
serialized,
|
|
723
|
+
})
|
|
724
|
+
|
|
725
|
+
const [address, signatures] = decoded
|
|
726
|
+
if (!Array.isArray(signatures) || signatures.some(Array.isArray))
|
|
727
|
+
throw new InvalidSerializedError({
|
|
728
|
+
reason: 'invalid multisig signatures list',
|
|
729
|
+
serialized,
|
|
730
|
+
})
|
|
731
|
+
if (signatures.length === 0)
|
|
732
|
+
throw new InvalidSerializedError({
|
|
733
|
+
reason: 'multisig signatures cannot be empty',
|
|
734
|
+
serialized,
|
|
735
|
+
})
|
|
736
|
+
if (signatures.length > MultisigConfig.maxSignatures)
|
|
737
|
+
throw new InvalidSerializedError({
|
|
738
|
+
reason: `multisig signatures exceed ${MultisigConfig.maxSignatures}`,
|
|
739
|
+
serialized,
|
|
740
|
+
})
|
|
741
|
+
for (const signature of signatures)
|
|
742
|
+
if (
|
|
743
|
+
Hex.size(signature as Hex.Hex) > MultisigConfig.maxOwnerSignatureBytes
|
|
744
|
+
)
|
|
745
|
+
throw new InvalidSerializedError({
|
|
746
|
+
reason: `multisig owner signature exceeds ${MultisigConfig.maxOwnerSignatureBytes} bytes`,
|
|
747
|
+
serialized,
|
|
748
|
+
})
|
|
749
|
+
|
|
750
|
+
if (!Array.isArray(address) && !Address.validate(address))
|
|
751
|
+
throw new InvalidSerializedError({
|
|
752
|
+
reason: 'invalid multisig account',
|
|
753
|
+
serialized,
|
|
754
|
+
})
|
|
755
|
+
if (Array.isArray(address)) {
|
|
756
|
+
const [salt, threshold, owners] = address
|
|
757
|
+
if (
|
|
758
|
+
address.length !== 3 ||
|
|
759
|
+
Array.isArray(salt) ||
|
|
760
|
+
Hex.size(salt) !== 32 ||
|
|
761
|
+
Array.isArray(threshold) ||
|
|
762
|
+
Hex.size(threshold) > 1 ||
|
|
763
|
+
!Array.isArray(owners) ||
|
|
764
|
+
owners.some(
|
|
765
|
+
(owner) =>
|
|
766
|
+
!Array.isArray(owner) ||
|
|
767
|
+
owner.length !== 2 ||
|
|
768
|
+
owner.some(Array.isArray) ||
|
|
769
|
+
Hex.size(owner[1] as Hex.Hex) > 1,
|
|
770
|
+
)
|
|
771
|
+
)
|
|
772
|
+
throw new InvalidSerializedError({
|
|
773
|
+
reason: 'invalid multisig init config',
|
|
774
|
+
serialized,
|
|
775
|
+
})
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
const init = Array.isArray(address)
|
|
779
|
+
? MultisigConfig.fromTuple(address as unknown as MultisigConfig.Tuple)
|
|
780
|
+
: undefined
|
|
781
|
+
const account = init
|
|
782
|
+
? MultisigConfig.getAddress(init)
|
|
783
|
+
: (address as Address.Address)
|
|
784
|
+
const envelope = {
|
|
655
785
|
type: 'multisig',
|
|
656
786
|
account,
|
|
657
|
-
signatures: signatures.map((signature) =>
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
787
|
+
signatures: signatures.map((signature) =>
|
|
788
|
+
deserialize_(signature as Hex.Hex, depth),
|
|
789
|
+
),
|
|
790
|
+
...(init ? { init } : {}),
|
|
661
791
|
} satisfies Multisig
|
|
792
|
+
assertMultisig(envelope, depth)
|
|
793
|
+
return envelope
|
|
662
794
|
}
|
|
663
795
|
|
|
664
796
|
throw new InvalidSerializedError({
|
|
@@ -1048,19 +1180,28 @@ export function fromRpc(envelope: SignatureEnvelopeRpc): SignatureEnvelope {
|
|
|
1048
1180
|
}
|
|
1049
1181
|
|
|
1050
1182
|
if (
|
|
1051
|
-
envelope.type === 'multisig' ||
|
|
1052
|
-
('
|
|
1183
|
+
(envelope as { type?: string | undefined }).type === 'multisig' ||
|
|
1184
|
+
('signatures' in envelope && ('account' in envelope || 'init' in envelope))
|
|
1053
1185
|
) {
|
|
1054
1186
|
const multisig = envelope as MultisigRpc
|
|
1055
|
-
|
|
1187
|
+
const hasAccount = typeof multisig.account !== 'undefined'
|
|
1188
|
+
const hasInit = typeof multisig.init !== 'undefined'
|
|
1189
|
+
if (hasAccount === hasInit)
|
|
1190
|
+
throw new InvalidMultisigApprovalError({
|
|
1191
|
+
reason: 'RPC multisig must contain exactly one of `account` or `init`',
|
|
1192
|
+
})
|
|
1193
|
+
const init = hasInit
|
|
1194
|
+
? MultisigConfig.from(multisig.init as MultisigConfig.Config)
|
|
1195
|
+
: undefined
|
|
1196
|
+
const account = init ? MultisigConfig.getAddress(init) : multisig.account
|
|
1197
|
+
const result = {
|
|
1056
1198
|
type: 'multisig',
|
|
1057
|
-
account:
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
}
|
|
1199
|
+
account: account as Address.Address,
|
|
1200
|
+
signatures: multisig.signatures.map((signature) => fromRpc(signature)),
|
|
1201
|
+
...(init ? { init } : {}),
|
|
1202
|
+
} satisfies Multisig
|
|
1203
|
+
assert(result)
|
|
1204
|
+
return result
|
|
1064
1205
|
}
|
|
1065
1206
|
|
|
1066
1207
|
throw new CoercionError({ envelope })
|
|
@@ -1068,8 +1209,10 @@ export function fromRpc(envelope: SignatureEnvelopeRpc): SignatureEnvelope {
|
|
|
1068
1209
|
|
|
1069
1210
|
export declare namespace fromRpc {
|
|
1070
1211
|
type ErrorType =
|
|
1212
|
+
| assert.ErrorType
|
|
1071
1213
|
| CoercionError
|
|
1072
1214
|
| InvalidSerializedError
|
|
1215
|
+
| MultisigConfig.getAddress.ErrorType
|
|
1073
1216
|
| Signature.fromRpc.ErrorType
|
|
1074
1217
|
| Errors.GlobalErrorType
|
|
1075
1218
|
}
|
|
@@ -1141,7 +1284,9 @@ export function getType<
|
|
|
1141
1284
|
|
|
1142
1285
|
// Detect Multisig signature
|
|
1143
1286
|
if (
|
|
1144
|
-
('account' in envelope ||
|
|
1287
|
+
('account' in envelope ||
|
|
1288
|
+
'genesisConfig' in envelope ||
|
|
1289
|
+
'init' in envelope) &&
|
|
1145
1290
|
'signatures' in envelope
|
|
1146
1291
|
)
|
|
1147
1292
|
return 'multisig' as never
|
|
@@ -1160,6 +1305,7 @@ export function getType<
|
|
|
1160
1305
|
* - WebAuthn: `0x02` + webauthnData (variable) + r (32) + s (32) + pubKeyX (32) + pubKeyY (32)
|
|
1161
1306
|
* - Keychain V1: `0x03` + userAddress (20) + inner signature (recursive)
|
|
1162
1307
|
* - Keychain V2: `0x04` + userAddress (20) + inner signature (recursive)
|
|
1308
|
+
* - Multisig: `0x05` + RLP `[account | init, signatures]`
|
|
1163
1309
|
*
|
|
1164
1310
|
* [Signature Types](https://docs.tempo.xyz/protocol/transactions/spec-tempo-transaction#signature-types)
|
|
1165
1311
|
*
|
|
@@ -1241,15 +1387,16 @@ export function serialize(
|
|
|
1241
1387
|
|
|
1242
1388
|
if (type === 'multisig') {
|
|
1243
1389
|
const multisig = envelope as Multisig
|
|
1244
|
-
|
|
1245
|
-
//
|
|
1246
|
-
//
|
|
1390
|
+
assert(multisig)
|
|
1391
|
+
// The first field is either the initialized account or the bootstrap init
|
|
1392
|
+
// config. Each owner approval is an encoded signature.
|
|
1247
1393
|
return Hex.concat(
|
|
1248
1394
|
serializedMultisigType,
|
|
1249
1395
|
Rlp.fromHex([
|
|
1250
|
-
multisig.
|
|
1396
|
+
multisig.init
|
|
1397
|
+
? MultisigConfig.toTuple(multisig.init)
|
|
1398
|
+
: multisig.account,
|
|
1251
1399
|
multisig.signatures.map((signature) => serialize(signature)),
|
|
1252
|
-
...(multisig.init ? [MultisigConfig.toTuple(multisig.init)] : []),
|
|
1253
1400
|
]),
|
|
1254
1401
|
options.magic ? magicBytes : '0x',
|
|
1255
1402
|
)
|
|
@@ -1266,6 +1413,16 @@ export declare namespace serialize {
|
|
|
1266
1413
|
*/
|
|
1267
1414
|
magic?: boolean | undefined
|
|
1268
1415
|
}
|
|
1416
|
+
|
|
1417
|
+
type ErrorType =
|
|
1418
|
+
| assert.ErrorType
|
|
1419
|
+
| CoercionError
|
|
1420
|
+
| Hex.concat.ErrorType
|
|
1421
|
+
| Hex.fromNumber.ErrorType
|
|
1422
|
+
| Hex.fromString.ErrorType
|
|
1423
|
+
| Rlp.fromHex.ErrorType
|
|
1424
|
+
| Signature.toHex.ErrorType
|
|
1425
|
+
| Errors.GlobalErrorType
|
|
1269
1426
|
}
|
|
1270
1427
|
|
|
1271
1428
|
/**
|
|
@@ -1376,7 +1533,9 @@ export declare namespace sortMultisigApprovals {
|
|
|
1376
1533
|
* @param envelope - The signature envelope to convert.
|
|
1377
1534
|
* @returns The RPC signature envelope with hex values.
|
|
1378
1535
|
*/
|
|
1379
|
-
export function toRpc
|
|
1536
|
+
export function toRpc<const envelope extends toRpc.Input>(
|
|
1537
|
+
envelope: envelope,
|
|
1538
|
+
): toRpc.ReturnType<envelope> {
|
|
1380
1539
|
const type = getType(envelope)
|
|
1381
1540
|
|
|
1382
1541
|
if (type === 'secp256k1') {
|
|
@@ -1384,7 +1543,7 @@ export function toRpc(envelope: SignatureEnvelope): SignatureEnvelopeRpc {
|
|
|
1384
1543
|
return {
|
|
1385
1544
|
...Signature.toRpc(secp256k1.signature),
|
|
1386
1545
|
type: 'secp256k1',
|
|
1387
|
-
}
|
|
1546
|
+
} as never
|
|
1388
1547
|
}
|
|
1389
1548
|
|
|
1390
1549
|
if (type === 'p256') {
|
|
@@ -1396,7 +1555,7 @@ export function toRpc(envelope: SignatureEnvelope): SignatureEnvelopeRpc {
|
|
|
1396
1555
|
r: Hex.fromNumber(p256.signature.r, { size: 32 }),
|
|
1397
1556
|
s: Hex.fromNumber(p256.signature.s, { size: 32 }),
|
|
1398
1557
|
type: 'p256',
|
|
1399
|
-
}
|
|
1558
|
+
} as never
|
|
1400
1559
|
}
|
|
1401
1560
|
|
|
1402
1561
|
if (type === 'webAuthn') {
|
|
@@ -1413,7 +1572,7 @@ export function toRpc(envelope: SignatureEnvelope): SignatureEnvelopeRpc {
|
|
|
1413
1572
|
s: Hex.fromNumber(webauthn.signature.s, { size: 32 }),
|
|
1414
1573
|
type: 'webAuthn',
|
|
1415
1574
|
webauthnData,
|
|
1416
|
-
}
|
|
1575
|
+
} as never
|
|
1417
1576
|
}
|
|
1418
1577
|
|
|
1419
1578
|
if (type === 'keychain') {
|
|
@@ -1424,25 +1583,57 @@ export function toRpc(envelope: SignatureEnvelope): SignatureEnvelopeRpc {
|
|
|
1424
1583
|
signature: toRpc(keychain.inner),
|
|
1425
1584
|
...(keychain.keyId ? { keyId: keychain.keyId } : {}),
|
|
1426
1585
|
...(keychain.version ? { version: keychain.version } : {}),
|
|
1427
|
-
}
|
|
1586
|
+
} as never
|
|
1428
1587
|
}
|
|
1429
1588
|
|
|
1430
1589
|
if (type === 'multisig') {
|
|
1431
1590
|
const multisig = envelope as Multisig
|
|
1591
|
+
assert(multisig)
|
|
1592
|
+
const signatures = multisig.signatures.map((signature) => toRpc(signature))
|
|
1593
|
+
if (multisig.init) {
|
|
1594
|
+
const init = {
|
|
1595
|
+
...multisig.init,
|
|
1596
|
+
salt: multisig.init.salt ?? MultisigConfig.zeroSalt,
|
|
1597
|
+
threshold: Number(multisig.init.threshold),
|
|
1598
|
+
owners: multisig.init.owners.map((owner) => ({
|
|
1599
|
+
...owner,
|
|
1600
|
+
weight: Number(owner.weight),
|
|
1601
|
+
})),
|
|
1602
|
+
}
|
|
1603
|
+
return {
|
|
1604
|
+
init,
|
|
1605
|
+
signatures,
|
|
1606
|
+
} as never
|
|
1607
|
+
}
|
|
1432
1608
|
return {
|
|
1433
|
-
type: 'multisig',
|
|
1434
1609
|
account: multisig.account,
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
...(multisig.init ? { init: multisig.init } : {}),
|
|
1438
|
-
}
|
|
1610
|
+
signatures,
|
|
1611
|
+
} as never
|
|
1439
1612
|
}
|
|
1440
1613
|
|
|
1441
1614
|
throw new CoercionError({ envelope })
|
|
1442
1615
|
}
|
|
1443
1616
|
|
|
1444
1617
|
export declare namespace toRpc {
|
|
1618
|
+
/** Input accepted by {@link ox#SignatureEnvelope.(toRpc:function)}. */
|
|
1619
|
+
type Input = SignatureEnvelope
|
|
1620
|
+
|
|
1621
|
+
/** RPC signature envelope inferred from the input type. */
|
|
1622
|
+
type ReturnType<envelope extends Input = Input> =
|
|
1623
|
+
GetType<envelope> extends 'secp256k1'
|
|
1624
|
+
? Secp256k1Rpc
|
|
1625
|
+
: GetType<envelope> extends 'p256'
|
|
1626
|
+
? P256Rpc
|
|
1627
|
+
: GetType<envelope> extends 'webAuthn'
|
|
1628
|
+
? WebAuthnRpc
|
|
1629
|
+
: GetType<envelope> extends 'keychain'
|
|
1630
|
+
? KeychainRpc
|
|
1631
|
+
: GetType<envelope> extends 'multisig'
|
|
1632
|
+
? MultisigRpc
|
|
1633
|
+
: SignatureEnvelopeRpc
|
|
1634
|
+
|
|
1445
1635
|
type ErrorType =
|
|
1636
|
+
| assert.ErrorType
|
|
1446
1637
|
| CoercionError
|
|
1447
1638
|
| Signature.toRpc.ErrorType
|
|
1448
1639
|
| Errors.GlobalErrorType
|