tempo.ts 0.7.6 → 0.8.1
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 +32 -0
- package/dist/chains.d.ts +6 -20
- package/dist/chains.d.ts.map +1 -1
- package/dist/chains.js +14 -15
- package/dist/chains.js.map +1 -1
- package/dist/ox/KeyAuthorization.d.ts +356 -0
- package/dist/ox/KeyAuthorization.d.ts.map +1 -0
- package/dist/ox/KeyAuthorization.js +360 -0
- package/dist/ox/KeyAuthorization.js.map +1 -0
- package/dist/ox/SignatureEnvelope.d.ts +21 -6
- package/dist/ox/SignatureEnvelope.d.ts.map +1 -1
- package/dist/ox/SignatureEnvelope.js +43 -3
- package/dist/ox/SignatureEnvelope.js.map +1 -1
- package/dist/ox/Transaction.d.ts +5 -1
- package/dist/ox/Transaction.d.ts.map +1 -1
- package/dist/ox/Transaction.js +5 -0
- package/dist/ox/Transaction.js.map +1 -1
- package/dist/ox/TransactionEnvelopeAA.d.ts +9 -0
- package/dist/ox/TransactionEnvelopeAA.d.ts.map +1 -1
- package/dist/ox/TransactionEnvelopeAA.js +17 -4
- package/dist/ox/TransactionEnvelopeAA.js.map +1 -1
- package/dist/ox/TransactionRequest.d.ts +7 -1
- package/dist/ox/TransactionRequest.d.ts.map +1 -1
- package/dist/ox/TransactionRequest.js +12 -0
- package/dist/ox/TransactionRequest.js.map +1 -1
- package/dist/ox/index.d.ts +1 -0
- package/dist/ox/index.d.ts.map +1 -1
- package/dist/ox/index.js +1 -0
- package/dist/ox/index.js.map +1 -1
- package/dist/prool/Instance.js +1 -1
- package/dist/prool/Instance.js.map +1 -1
- package/{src/prool/internal → dist/prool}/chain.json +4 -2
- package/dist/viem/Abis.d.ts +319 -6
- package/dist/viem/Abis.d.ts.map +1 -1
- package/dist/viem/Abis.js +199 -7
- package/dist/viem/Abis.js.map +1 -1
- package/dist/viem/Account.d.ts +103 -14
- package/dist/viem/Account.d.ts.map +1 -1
- package/dist/viem/Account.js +177 -23
- package/dist/viem/Account.js.map +1 -1
- package/dist/viem/Actions/account.d.ts.map +1 -1
- package/dist/viem/Actions/account.js +4 -5
- package/dist/viem/Actions/account.js.map +1 -1
- package/dist/viem/Actions/amm.d.ts +72 -0
- package/dist/viem/Actions/amm.d.ts.map +1 -1
- package/dist/viem/Actions/dex.d.ts +156 -4
- package/dist/viem/Actions/dex.d.ts.map +1 -1
- package/dist/viem/Actions/fee.d.ts +4 -0
- package/dist/viem/Actions/fee.d.ts.map +1 -1
- package/dist/viem/Actions/reward.d.ts +158 -0
- package/dist/viem/Actions/reward.d.ts.map +1 -1
- package/dist/viem/Actions/reward.js +54 -0
- package/dist/viem/Actions/reward.js.map +1 -1
- package/dist/viem/Actions/token.d.ts +585 -0
- package/dist/viem/Actions/token.d.ts.map +1 -1
- package/dist/viem/Actions/token.js +2 -2
- package/dist/viem/Actions/token.js.map +1 -1
- package/dist/viem/Addresses.d.ts +1 -1
- package/dist/viem/Addresses.d.ts.map +1 -1
- package/dist/viem/Addresses.js +1 -1
- package/dist/viem/Addresses.js.map +1 -1
- package/dist/viem/Chain.d.ts +35 -0
- package/dist/viem/Chain.d.ts.map +1 -1
- package/dist/viem/Chain.js +37 -0
- package/dist/viem/Chain.js.map +1 -1
- package/dist/viem/Decorator.d.ts +74 -0
- package/dist/viem/Decorator.d.ts.map +1 -1
- package/dist/viem/Decorator.js +3 -0
- package/dist/viem/Decorator.js.map +1 -1
- package/dist/viem/Formatters.d.ts.map +1 -1
- package/dist/viem/Formatters.js +8 -7
- package/dist/viem/Formatters.js.map +1 -1
- package/dist/viem/Storage.d.ts +1 -0
- package/dist/viem/Storage.d.ts.map +1 -1
- package/dist/viem/Storage.js +21 -0
- package/dist/viem/Storage.js.map +1 -1
- package/dist/viem/TokenIds.d.ts +1 -1
- package/dist/viem/TokenIds.d.ts.map +1 -1
- package/dist/viem/TokenIds.js +1 -1
- package/dist/viem/TokenIds.js.map +1 -1
- package/dist/viem/Transaction.d.ts +9 -1
- package/dist/viem/Transaction.d.ts.map +1 -1
- package/dist/viem/Transaction.js +2 -1
- package/dist/viem/Transaction.js.map +1 -1
- package/dist/viem/WebAuthnP256.d.ts +4 -1
- package/dist/viem/WebAuthnP256.d.ts.map +1 -1
- package/dist/viem/WebAuthnP256.js +3 -1
- package/dist/viem/WebAuthnP256.js.map +1 -1
- package/dist/wagmi/Actions/reward.d.ts +44 -0
- package/dist/wagmi/Actions/reward.d.ts.map +1 -1
- package/dist/wagmi/Actions/reward.js +49 -0
- package/dist/wagmi/Actions/reward.js.map +1 -1
- package/dist/wagmi/Connector.d.ts +25 -8
- package/dist/wagmi/Connector.d.ts.map +1 -1
- package/dist/wagmi/Connector.js +120 -27
- package/dist/wagmi/Connector.js.map +1 -1
- package/dist/wagmi/Hooks/reward.d.ts +32 -0
- package/dist/wagmi/Hooks/reward.d.ts.map +1 -1
- package/dist/wagmi/Hooks/reward.js +39 -0
- package/dist/wagmi/Hooks/reward.js.map +1 -1
- package/package.json +3 -2
- package/src/chains.ts +14 -15
- package/src/ox/KeyAuthorization.test.ts +1332 -0
- package/src/ox/KeyAuthorization.ts +542 -0
- package/src/ox/SignatureEnvelope.test.ts +624 -0
- package/src/ox/SignatureEnvelope.ts +89 -9
- package/src/ox/Transaction.test.ts +214 -0
- package/src/ox/Transaction.ts +13 -1
- package/src/ox/TransactionEnvelopeAA.test.ts +164 -4
- package/src/ox/TransactionEnvelopeAA.ts +36 -3
- package/src/ox/TransactionRequest.ts +22 -1
- package/src/ox/e2e.test.ts +612 -5
- package/src/ox/index.ts +1 -0
- package/src/prool/Instance.ts +1 -1
- package/src/prool/chain.json +238 -0
- package/src/server/Handler.test.ts +20 -36
- package/src/viem/Abis.ts +200 -7
- package/src/viem/Account.test.ts +444 -0
- package/src/viem/Account.ts +355 -42
- package/src/viem/Actions/account.ts +3 -5
- package/src/viem/Actions/amm.test.ts +4 -4
- package/src/viem/Actions/reward.test.ts +84 -0
- package/src/viem/Actions/reward.ts +73 -0
- package/src/viem/Actions/token.test.ts +8 -8
- package/src/viem/Actions/token.ts +2 -2
- package/src/viem/Addresses.ts +1 -1
- package/src/viem/Chain.test.ts +168 -0
- package/src/viem/Chain.ts +37 -1
- package/src/viem/Decorator.ts +84 -0
- package/src/viem/Formatters.ts +8 -7
- package/src/viem/Storage.ts +22 -0
- package/src/viem/TokenIds.ts +1 -1
- package/src/viem/Transaction.ts +14 -2
- package/src/viem/WebAuthnP256.ts +8 -2
- package/src/viem/e2e.test.ts +299 -96
- package/src/wagmi/Actions/amm.test.ts +2 -2
- package/src/wagmi/Actions/reward.test.ts +36 -0
- package/src/wagmi/Actions/reward.ts +91 -0
- package/src/wagmi/Connector.test.ts +1 -1
- package/src/wagmi/Connector.ts +184 -54
- package/src/wagmi/Hooks/amm.test.ts +4 -4
- package/src/wagmi/Hooks/fee.test.ts +10 -4
- package/src/wagmi/Hooks/reward.test.ts +72 -0
- package/src/wagmi/Hooks/reward.ts +68 -0
- package/src/wagmi/Hooks/token.test.ts +0 -488
- package/dist/viem/internal/account.d.ts +0 -21
- package/dist/viem/internal/account.d.ts.map +0 -1
- package/dist/viem/internal/account.js +0 -61
- package/dist/viem/internal/account.js.map +0 -1
- package/src/viem/internal/account.ts +0 -89
|
@@ -37,6 +37,22 @@ const signature_webauthn = SignatureEnvelope.from({
|
|
|
37
37
|
},
|
|
38
38
|
})
|
|
39
39
|
|
|
40
|
+
// Keychain signatures with different inner types
|
|
41
|
+
const signature_keychain_secp256k1 = SignatureEnvelope.from({
|
|
42
|
+
userAddress: '0x1234567890123456789012345678901234567890',
|
|
43
|
+
inner: SignatureEnvelope.from(signature_secp256k1),
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
const signature_keychain_p256 = SignatureEnvelope.from({
|
|
47
|
+
userAddress: '0xabcdefabcdefabcdefabcdefabcdefabcdefabcd',
|
|
48
|
+
inner: signature_p256,
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
const signature_keychain_webauthn = SignatureEnvelope.from({
|
|
52
|
+
userAddress: '0xfedcbafedcbafedcbafedcbafedcbafedcbafedc',
|
|
53
|
+
inner: signature_webauthn,
|
|
54
|
+
})
|
|
55
|
+
|
|
40
56
|
describe('assert', () => {
|
|
41
57
|
describe('secp256k1', () => {
|
|
42
58
|
test('behavior: validates valid signature', () => {
|
|
@@ -383,6 +399,47 @@ describe('assert', () => {
|
|
|
383
399
|
})
|
|
384
400
|
})
|
|
385
401
|
|
|
402
|
+
describe('keychain', () => {
|
|
403
|
+
test('behavior: validates valid keychain with secp256k1 inner', () => {
|
|
404
|
+
expect(() =>
|
|
405
|
+
SignatureEnvelope.assert(signature_keychain_secp256k1),
|
|
406
|
+
).not.toThrow()
|
|
407
|
+
})
|
|
408
|
+
|
|
409
|
+
test('behavior: validates valid keychain with p256 inner', () => {
|
|
410
|
+
expect(() =>
|
|
411
|
+
SignatureEnvelope.assert(signature_keychain_p256),
|
|
412
|
+
).not.toThrow()
|
|
413
|
+
})
|
|
414
|
+
|
|
415
|
+
test('behavior: validates valid keychain with webAuthn inner', () => {
|
|
416
|
+
expect(() =>
|
|
417
|
+
SignatureEnvelope.assert(signature_keychain_webauthn),
|
|
418
|
+
).not.toThrow()
|
|
419
|
+
})
|
|
420
|
+
|
|
421
|
+
test('behavior: validates keychain without explicit type', () => {
|
|
422
|
+
const { type: _, ...signatureWithoutType } = signature_keychain_secp256k1
|
|
423
|
+
expect(() => SignatureEnvelope.assert(signatureWithoutType)).not.toThrow()
|
|
424
|
+
})
|
|
425
|
+
|
|
426
|
+
test('error: throws on invalid inner signature', () => {
|
|
427
|
+
expect(() =>
|
|
428
|
+
SignatureEnvelope.assert({
|
|
429
|
+
userAddress: '0x1234567890123456789012345678901234567890',
|
|
430
|
+
inner: SignatureEnvelope.from({
|
|
431
|
+
r: 0n,
|
|
432
|
+
s: 0n,
|
|
433
|
+
yParity: 2,
|
|
434
|
+
}),
|
|
435
|
+
type: 'keychain',
|
|
436
|
+
} as any),
|
|
437
|
+
).toThrowErrorMatchingInlineSnapshot(
|
|
438
|
+
`[Signature.InvalidYParityError: Value \`2\` is an invalid y-parity value. Y-parity must be 0 or 1.]`,
|
|
439
|
+
)
|
|
440
|
+
})
|
|
441
|
+
})
|
|
442
|
+
|
|
386
443
|
test('error: throws on invalid envelope', () => {
|
|
387
444
|
expect(() =>
|
|
388
445
|
SignatureEnvelope.assert({} as any),
|
|
@@ -549,6 +606,86 @@ describe('deserialize', () => {
|
|
|
549
606
|
)
|
|
550
607
|
})
|
|
551
608
|
})
|
|
609
|
+
|
|
610
|
+
describe('keychain', () => {
|
|
611
|
+
test('behavior: deserializes keychain signature with secp256k1 inner', () => {
|
|
612
|
+
const serialized = SignatureEnvelope.serialize(
|
|
613
|
+
signature_keychain_secp256k1,
|
|
614
|
+
)
|
|
615
|
+
const deserialized = SignatureEnvelope.deserialize(serialized)
|
|
616
|
+
|
|
617
|
+
expect(deserialized).toMatchObject({
|
|
618
|
+
userAddress: signature_keychain_secp256k1.userAddress,
|
|
619
|
+
inner: SignatureEnvelope.from(signature_secp256k1),
|
|
620
|
+
type: 'keychain',
|
|
621
|
+
})
|
|
622
|
+
})
|
|
623
|
+
|
|
624
|
+
test('behavior: deserializes keychain signature with p256 inner', () => {
|
|
625
|
+
const serialized = SignatureEnvelope.serialize(signature_keychain_p256)
|
|
626
|
+
const deserialized = SignatureEnvelope.deserialize(serialized)
|
|
627
|
+
|
|
628
|
+
expect(deserialized).toMatchInlineSnapshot(`
|
|
629
|
+
{
|
|
630
|
+
"inner": {
|
|
631
|
+
"prehash": true,
|
|
632
|
+
"publicKey": {
|
|
633
|
+
"prefix": 4,
|
|
634
|
+
"x": 78495282704852028275327922540131762143565388050940484317945369745559774511861n,
|
|
635
|
+
"y": 8109764566587999957624872393871720746996669263962991155166704261108473113504n,
|
|
636
|
+
},
|
|
637
|
+
"signature": {
|
|
638
|
+
"r": 92602584010956101470289867944347135737570451066466093224269890121909314569518n,
|
|
639
|
+
"s": 54171125190222965779385658110416711469231271457324878825831748147306957269813n,
|
|
640
|
+
},
|
|
641
|
+
"type": "p256",
|
|
642
|
+
},
|
|
643
|
+
"type": "keychain",
|
|
644
|
+
"userAddress": "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd",
|
|
645
|
+
}
|
|
646
|
+
`)
|
|
647
|
+
})
|
|
648
|
+
|
|
649
|
+
test('behavior: deserializes keychain signature with webAuthn inner', () => {
|
|
650
|
+
const serialized = SignatureEnvelope.serialize(
|
|
651
|
+
signature_keychain_webauthn,
|
|
652
|
+
)
|
|
653
|
+
const deserialized = SignatureEnvelope.deserialize(serialized)
|
|
654
|
+
|
|
655
|
+
expect(deserialized).toMatchInlineSnapshot(`
|
|
656
|
+
{
|
|
657
|
+
"inner": {
|
|
658
|
+
"metadata": {
|
|
659
|
+
"authenticatorData": "0x49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97630500000000",
|
|
660
|
+
"clientDataJSON": "{"type":"webauthn.get","challenge":"3q2-7w","origin":"http://localhost","crossOrigin":false}",
|
|
661
|
+
},
|
|
662
|
+
"publicKey": {
|
|
663
|
+
"prefix": 4,
|
|
664
|
+
"x": 78495282704852028275327922540131762143565388050940484317945369745559774511861n,
|
|
665
|
+
"y": 8109764566587999957624872393871720746996669263962991155166704261108473113504n,
|
|
666
|
+
},
|
|
667
|
+
"signature": {
|
|
668
|
+
"r": 92602584010956101470289867944347135737570451066466093224269890121909314569518n,
|
|
669
|
+
"s": 54171125190222965779385658110416711469231271457324878825831748147306957269813n,
|
|
670
|
+
},
|
|
671
|
+
"type": "webAuthn",
|
|
672
|
+
},
|
|
673
|
+
"type": "keychain",
|
|
674
|
+
"userAddress": "0xfedcbafedcbafedcbafedcbafedcbafedcbafedc",
|
|
675
|
+
}
|
|
676
|
+
`)
|
|
677
|
+
})
|
|
678
|
+
|
|
679
|
+
test('error: throws on invalid keychain signature length', () => {
|
|
680
|
+
// Keychain signature too short (must be at least 21 bytes: 1 type + 20 address)
|
|
681
|
+
const invalidSig = `0x03${'00'.repeat(10)}` as const
|
|
682
|
+
expect(() =>
|
|
683
|
+
SignatureEnvelope.deserialize(invalidSig),
|
|
684
|
+
).toThrowErrorMatchingInlineSnapshot(
|
|
685
|
+
`[Hex.SliceOffsetOutOfBoundsError: Slice starting at offset \`20\` is out-of-bounds (size: \`10\`).]`,
|
|
686
|
+
)
|
|
687
|
+
})
|
|
688
|
+
})
|
|
552
689
|
})
|
|
553
690
|
|
|
554
691
|
describe('from', () => {
|
|
@@ -636,6 +773,38 @@ describe('from', () => {
|
|
|
636
773
|
expect(envelope.type).toBe('webAuthn')
|
|
637
774
|
})
|
|
638
775
|
})
|
|
776
|
+
|
|
777
|
+
describe('keychain', () => {
|
|
778
|
+
test('behavior: coerces from hex string with secp256k1 inner', () => {
|
|
779
|
+
const serialized = SignatureEnvelope.serialize(
|
|
780
|
+
signature_keychain_secp256k1,
|
|
781
|
+
)
|
|
782
|
+
const envelope = SignatureEnvelope.from(serialized)
|
|
783
|
+
|
|
784
|
+
expect(envelope).toMatchObject({
|
|
785
|
+
userAddress: signature_keychain_secp256k1.userAddress,
|
|
786
|
+
inner: SignatureEnvelope.from(signature_secp256k1),
|
|
787
|
+
type: 'keychain',
|
|
788
|
+
})
|
|
789
|
+
})
|
|
790
|
+
|
|
791
|
+
test('behavior: coerces from hex string with p256 inner', () => {
|
|
792
|
+
const serialized = SignatureEnvelope.serialize(signature_keychain_p256)
|
|
793
|
+
const envelope = SignatureEnvelope.from(serialized)
|
|
794
|
+
|
|
795
|
+
expect(envelope).toMatchObject({
|
|
796
|
+
userAddress: signature_keychain_p256.userAddress,
|
|
797
|
+
type: 'keychain',
|
|
798
|
+
})
|
|
799
|
+
})
|
|
800
|
+
|
|
801
|
+
test('behavior: adds type to object', () => {
|
|
802
|
+
const { type: _, ...withoutType } = signature_keychain_secp256k1
|
|
803
|
+
const envelope = SignatureEnvelope.from(withoutType)
|
|
804
|
+
|
|
805
|
+
expect(envelope.type).toBe('keychain')
|
|
806
|
+
})
|
|
807
|
+
})
|
|
639
808
|
})
|
|
640
809
|
|
|
641
810
|
describe('getType', () => {
|
|
@@ -683,6 +852,29 @@ describe('getType', () => {
|
|
|
683
852
|
})
|
|
684
853
|
})
|
|
685
854
|
|
|
855
|
+
describe('keychain', () => {
|
|
856
|
+
test('behavior: returns explicit type', () => {
|
|
857
|
+
expect(SignatureEnvelope.getType(signature_keychain_secp256k1)).toBe(
|
|
858
|
+
'keychain',
|
|
859
|
+
)
|
|
860
|
+
})
|
|
861
|
+
|
|
862
|
+
test('behavior: infers type from properties', () => {
|
|
863
|
+
const { type: _, ...signatureWithoutType } = signature_keychain_secp256k1
|
|
864
|
+
expect(SignatureEnvelope.getType(signatureWithoutType)).toBe('keychain')
|
|
865
|
+
})
|
|
866
|
+
|
|
867
|
+
test('behavior: infers type for keychain with p256 inner', () => {
|
|
868
|
+
const { type: _, ...signatureWithoutType } = signature_keychain_p256
|
|
869
|
+
expect(SignatureEnvelope.getType(signatureWithoutType)).toBe('keychain')
|
|
870
|
+
})
|
|
871
|
+
|
|
872
|
+
test('behavior: infers type for keychain with webAuthn inner', () => {
|
|
873
|
+
const { type: _, ...signatureWithoutType } = signature_keychain_webauthn
|
|
874
|
+
expect(SignatureEnvelope.getType(signatureWithoutType)).toBe('keychain')
|
|
875
|
+
})
|
|
876
|
+
})
|
|
877
|
+
|
|
686
878
|
test('error: throws on invalid envelope', () => {
|
|
687
879
|
expect(() =>
|
|
688
880
|
SignatureEnvelope.getType({} as any),
|
|
@@ -776,6 +968,83 @@ describe('serialize', () => {
|
|
|
776
968
|
})
|
|
777
969
|
})
|
|
778
970
|
|
|
971
|
+
describe('keychain', () => {
|
|
972
|
+
test('behavior: serializes keychain signature with secp256k1 inner and type identifier', () => {
|
|
973
|
+
const serialized = SignatureEnvelope.serialize(
|
|
974
|
+
signature_keychain_secp256k1,
|
|
975
|
+
)
|
|
976
|
+
|
|
977
|
+
// Should be: 1 (type) + 20 (address) + 65 (secp256k1 signature)
|
|
978
|
+
expect(Hex.size(serialized)).toBe(1 + 20 + 65)
|
|
979
|
+
|
|
980
|
+
// First byte should be Keychain type identifier (0x03)
|
|
981
|
+
expect(Hex.slice(serialized, 0, 1)).toBe('0x03')
|
|
982
|
+
|
|
983
|
+
// Next 20 bytes should be the user address (without '0x')
|
|
984
|
+
expect(Hex.slice(serialized, 1, 21)).toBe(
|
|
985
|
+
signature_keychain_secp256k1.userAddress,
|
|
986
|
+
)
|
|
987
|
+
})
|
|
988
|
+
|
|
989
|
+
test('behavior: serializes keychain signature with p256 inner', () => {
|
|
990
|
+
const serialized = SignatureEnvelope.serialize(signature_keychain_p256)
|
|
991
|
+
|
|
992
|
+
// Should be: 1 (type) + 20 (address) + 130 (p256 signature with type)
|
|
993
|
+
expect(Hex.size(serialized)).toBe(1 + 20 + 130)
|
|
994
|
+
|
|
995
|
+
// First byte should be Keychain type identifier (0x03)
|
|
996
|
+
expect(Hex.slice(serialized, 0, 1)).toBe('0x03')
|
|
997
|
+
|
|
998
|
+
// Next 20 bytes should be the user address (without '0x')
|
|
999
|
+
expect(Hex.slice(serialized, 1, 21)).toBe(
|
|
1000
|
+
signature_keychain_p256.userAddress,
|
|
1001
|
+
)
|
|
1002
|
+
|
|
1003
|
+
// Next 130 bytes should be the p256 signature
|
|
1004
|
+
expect(Hex.slice(serialized, 21, 151)).toBe(
|
|
1005
|
+
SignatureEnvelope.serialize(signature_p256),
|
|
1006
|
+
)
|
|
1007
|
+
})
|
|
1008
|
+
|
|
1009
|
+
test('behavior: serializes keychain signature with webAuthn inner', () => {
|
|
1010
|
+
const serialized = SignatureEnvelope.serialize(
|
|
1011
|
+
signature_keychain_webauthn,
|
|
1012
|
+
)
|
|
1013
|
+
|
|
1014
|
+
// First byte should be Keychain type identifier (0x03)
|
|
1015
|
+
expect(Hex.slice(serialized, 0, 1)).toBe('0x03')
|
|
1016
|
+
|
|
1017
|
+
// Should contain the user address
|
|
1018
|
+
expect(Hex.slice(serialized, 1, 21)).toBe(
|
|
1019
|
+
signature_keychain_webauthn.userAddress,
|
|
1020
|
+
)
|
|
1021
|
+
|
|
1022
|
+
// Next N bytes should be the webAuthn signature
|
|
1023
|
+
expect(Hex.slice(serialized, 21)).toBe(
|
|
1024
|
+
SignatureEnvelope.serialize(signature_webauthn),
|
|
1025
|
+
)
|
|
1026
|
+
})
|
|
1027
|
+
|
|
1028
|
+
test('behavior: preserves userAddress and inner signature', () => {
|
|
1029
|
+
const serialized = SignatureEnvelope.serialize(
|
|
1030
|
+
signature_keychain_secp256k1,
|
|
1031
|
+
)
|
|
1032
|
+
const deserialized = SignatureEnvelope.deserialize(serialized)
|
|
1033
|
+
|
|
1034
|
+
expect(deserialized.userAddress).toBe(
|
|
1035
|
+
signature_keychain_secp256k1.userAddress,
|
|
1036
|
+
)
|
|
1037
|
+
expect(deserialized.inner).toMatchObject({
|
|
1038
|
+
type: 'secp256k1',
|
|
1039
|
+
signature: {
|
|
1040
|
+
r: signature_secp256k1.r,
|
|
1041
|
+
s: signature_secp256k1.s,
|
|
1042
|
+
yParity: signature_secp256k1.yParity,
|
|
1043
|
+
},
|
|
1044
|
+
})
|
|
1045
|
+
})
|
|
1046
|
+
})
|
|
1047
|
+
|
|
779
1048
|
describe('roundtrip', () => {
|
|
780
1049
|
describe('secp256k1', () => {
|
|
781
1050
|
test('behavior: roundtrips serialize -> deserialize', () => {
|
|
@@ -869,6 +1138,72 @@ describe('serialize', () => {
|
|
|
869
1138
|
expect(deserialized.metadata?.clientDataJSON).toBe(longClientData)
|
|
870
1139
|
})
|
|
871
1140
|
})
|
|
1141
|
+
|
|
1142
|
+
describe('keychain', () => {
|
|
1143
|
+
test('behavior: roundtrips serialize -> deserialize with secp256k1 inner', () => {
|
|
1144
|
+
const serialized = SignatureEnvelope.serialize(
|
|
1145
|
+
signature_keychain_secp256k1,
|
|
1146
|
+
)
|
|
1147
|
+
const deserialized = SignatureEnvelope.deserialize(serialized)
|
|
1148
|
+
|
|
1149
|
+
expect(deserialized).toMatchObject(signature_keychain_secp256k1)
|
|
1150
|
+
})
|
|
1151
|
+
|
|
1152
|
+
test('behavior: roundtrips serialize -> deserialize with p256 inner', () => {
|
|
1153
|
+
const serialized = SignatureEnvelope.serialize(signature_keychain_p256)
|
|
1154
|
+
const deserialized = SignatureEnvelope.deserialize(serialized)
|
|
1155
|
+
|
|
1156
|
+
expect(deserialized).toMatchInlineSnapshot(`
|
|
1157
|
+
{
|
|
1158
|
+
"inner": {
|
|
1159
|
+
"prehash": true,
|
|
1160
|
+
"publicKey": {
|
|
1161
|
+
"prefix": 4,
|
|
1162
|
+
"x": 78495282704852028275327922540131762143565388050940484317945369745559774511861n,
|
|
1163
|
+
"y": 8109764566587999957624872393871720746996669263962991155166704261108473113504n,
|
|
1164
|
+
},
|
|
1165
|
+
"signature": {
|
|
1166
|
+
"r": 92602584010956101470289867944347135737570451066466093224269890121909314569518n,
|
|
1167
|
+
"s": 54171125190222965779385658110416711469231271457324878825831748147306957269813n,
|
|
1168
|
+
},
|
|
1169
|
+
"type": "p256",
|
|
1170
|
+
},
|
|
1171
|
+
"type": "keychain",
|
|
1172
|
+
"userAddress": "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd",
|
|
1173
|
+
}
|
|
1174
|
+
`)
|
|
1175
|
+
})
|
|
1176
|
+
|
|
1177
|
+
test('behavior: roundtrips serialize -> deserialize with webAuthn inner', () => {
|
|
1178
|
+
const serialized = SignatureEnvelope.serialize(
|
|
1179
|
+
signature_keychain_webauthn,
|
|
1180
|
+
)
|
|
1181
|
+
const deserialized = SignatureEnvelope.deserialize(serialized)
|
|
1182
|
+
|
|
1183
|
+
expect(deserialized).toMatchInlineSnapshot(`
|
|
1184
|
+
{
|
|
1185
|
+
"inner": {
|
|
1186
|
+
"metadata": {
|
|
1187
|
+
"authenticatorData": "0x49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97630500000000",
|
|
1188
|
+
"clientDataJSON": "{"type":"webauthn.get","challenge":"3q2-7w","origin":"http://localhost","crossOrigin":false}",
|
|
1189
|
+
},
|
|
1190
|
+
"publicKey": {
|
|
1191
|
+
"prefix": 4,
|
|
1192
|
+
"x": 78495282704852028275327922540131762143565388050940484317945369745559774511861n,
|
|
1193
|
+
"y": 8109764566587999957624872393871720746996669263962991155166704261108473113504n,
|
|
1194
|
+
},
|
|
1195
|
+
"signature": {
|
|
1196
|
+
"r": 92602584010956101470289867944347135737570451066466093224269890121909314569518n,
|
|
1197
|
+
"s": 54171125190222965779385658110416711469231271457324878825831748147306957269813n,
|
|
1198
|
+
},
|
|
1199
|
+
"type": "webAuthn",
|
|
1200
|
+
},
|
|
1201
|
+
"type": "keychain",
|
|
1202
|
+
"userAddress": "0xfedcbafedcbafedcbafedcbafedcbafedcbafedc",
|
|
1203
|
+
}
|
|
1204
|
+
`)
|
|
1205
|
+
})
|
|
1206
|
+
})
|
|
872
1207
|
})
|
|
873
1208
|
|
|
874
1209
|
test('error: throws on invalid envelope', () => {
|
|
@@ -943,6 +1278,39 @@ describe('validate', () => {
|
|
|
943
1278
|
})
|
|
944
1279
|
})
|
|
945
1280
|
|
|
1281
|
+
describe('keychain', () => {
|
|
1282
|
+
test('behavior: returns true for valid keychain with secp256k1 inner', () => {
|
|
1283
|
+
expect(SignatureEnvelope.validate(signature_keychain_secp256k1)).toBe(
|
|
1284
|
+
true,
|
|
1285
|
+
)
|
|
1286
|
+
})
|
|
1287
|
+
|
|
1288
|
+
test('behavior: returns true for valid keychain with p256 inner', () => {
|
|
1289
|
+
expect(SignatureEnvelope.validate(signature_keychain_p256)).toBe(true)
|
|
1290
|
+
})
|
|
1291
|
+
|
|
1292
|
+
test('behavior: returns true for valid keychain with webAuthn inner', () => {
|
|
1293
|
+
expect(SignatureEnvelope.validate(signature_keychain_webauthn)).toBe(true)
|
|
1294
|
+
})
|
|
1295
|
+
|
|
1296
|
+
test('behavior: returns false for invalid keychain signature', () => {
|
|
1297
|
+
expect(
|
|
1298
|
+
SignatureEnvelope.validate({
|
|
1299
|
+
userAddress: '0x1234567890123456789012345678901234567890',
|
|
1300
|
+
inner: {
|
|
1301
|
+
signature: {
|
|
1302
|
+
r: 0n,
|
|
1303
|
+
s: 0n,
|
|
1304
|
+
yParity: 2,
|
|
1305
|
+
},
|
|
1306
|
+
type: 'secp256k1',
|
|
1307
|
+
},
|
|
1308
|
+
type: 'keychain',
|
|
1309
|
+
} as any),
|
|
1310
|
+
).toBe(false)
|
|
1311
|
+
})
|
|
1312
|
+
})
|
|
1313
|
+
|
|
946
1314
|
test('behavior: returns false for invalid envelope', () => {
|
|
947
1315
|
expect(SignatureEnvelope.validate({} as any)).toBe(false)
|
|
948
1316
|
})
|
|
@@ -1046,6 +1414,118 @@ describe('fromRpc', () => {
|
|
|
1046
1414
|
})
|
|
1047
1415
|
})
|
|
1048
1416
|
})
|
|
1417
|
+
|
|
1418
|
+
describe('keychain', () => {
|
|
1419
|
+
test('behavior: converts RPC keychain signature with secp256k1 inner', () => {
|
|
1420
|
+
const rpc: SignatureEnvelope.KeychainRpc = {
|
|
1421
|
+
type: 'keychain',
|
|
1422
|
+
userAddress: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
|
|
1423
|
+
signature: {
|
|
1424
|
+
type: 'secp256k1',
|
|
1425
|
+
r: '0xa2bb71146c20ce932456c043ebb2973ed205e07cd32c35a60bdefca1285fd132',
|
|
1426
|
+
s: '0x7cba10692bccdbfba9a215418443c2903dbee6fe5cb55c91172e47efc607840e',
|
|
1427
|
+
yParity: '0x1',
|
|
1428
|
+
},
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
const envelope = SignatureEnvelope.fromRpc(rpc)
|
|
1432
|
+
|
|
1433
|
+
expect(envelope).toMatchObject({
|
|
1434
|
+
type: 'keychain',
|
|
1435
|
+
userAddress: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
|
|
1436
|
+
inner: {
|
|
1437
|
+
type: 'secp256k1',
|
|
1438
|
+
signature: {
|
|
1439
|
+
r: 0xa2bb71146c20ce932456c043ebb2973ed205e07cd32c35a60bdefca1285fd132n,
|
|
1440
|
+
s: 0x7cba10692bccdbfba9a215418443c2903dbee6fe5cb55c91172e47efc607840en,
|
|
1441
|
+
yParity: 1,
|
|
1442
|
+
},
|
|
1443
|
+
},
|
|
1444
|
+
})
|
|
1445
|
+
})
|
|
1446
|
+
|
|
1447
|
+
test('behavior: converts RPC keychain signature with p256 inner', () => {
|
|
1448
|
+
const rpc: SignatureEnvelope.KeychainRpc = {
|
|
1449
|
+
type: 'keychain',
|
|
1450
|
+
userAddress: '0xabcdefabcdefabcdefabcdefabcdefabcdefabcd',
|
|
1451
|
+
signature: {
|
|
1452
|
+
prehash: true,
|
|
1453
|
+
pubKeyX: Hex.fromNumber(publicKey.x, { size: 32 }),
|
|
1454
|
+
pubKeyY: Hex.fromNumber(publicKey.y, { size: 32 }),
|
|
1455
|
+
r: Hex.fromNumber(p256Signature.r, { size: 32 }),
|
|
1456
|
+
s: Hex.fromNumber(p256Signature.s, { size: 32 }),
|
|
1457
|
+
type: 'p256',
|
|
1458
|
+
},
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
const envelope = SignatureEnvelope.fromRpc(rpc)
|
|
1462
|
+
|
|
1463
|
+
expect(envelope).toMatchObject({
|
|
1464
|
+
type: 'keychain',
|
|
1465
|
+
userAddress: '0xabcdefabcdefabcdefabcdefabcdefabcdefabcd',
|
|
1466
|
+
inner: {
|
|
1467
|
+
type: 'p256',
|
|
1468
|
+
prehash: true,
|
|
1469
|
+
publicKey: {
|
|
1470
|
+
x: publicKey.x,
|
|
1471
|
+
y: publicKey.y,
|
|
1472
|
+
},
|
|
1473
|
+
signature: {
|
|
1474
|
+
r: p256Signature.r,
|
|
1475
|
+
s: p256Signature.s,
|
|
1476
|
+
},
|
|
1477
|
+
},
|
|
1478
|
+
})
|
|
1479
|
+
})
|
|
1480
|
+
|
|
1481
|
+
test('behavior: converts RPC keychain signature with webAuthn inner', () => {
|
|
1482
|
+
const webauthnData = WebAuthnP256.getAuthenticatorData({
|
|
1483
|
+
rpId: 'localhost',
|
|
1484
|
+
})
|
|
1485
|
+
const clientDataJSON = WebAuthnP256.getClientDataJSON({
|
|
1486
|
+
challenge: '0xdeadbeef',
|
|
1487
|
+
origin: 'http://localhost',
|
|
1488
|
+
})
|
|
1489
|
+
|
|
1490
|
+
const rpc: SignatureEnvelope.KeychainRpc = {
|
|
1491
|
+
type: 'keychain',
|
|
1492
|
+
userAddress: '0xfedcbafedcbafedcbafedcbafedcbafedcbafedc',
|
|
1493
|
+
signature: {
|
|
1494
|
+
pubKeyX: Hex.fromNumber(publicKey.x, { size: 32 }),
|
|
1495
|
+
pubKeyY: Hex.fromNumber(publicKey.y, { size: 32 }),
|
|
1496
|
+
r: Hex.fromNumber(p256Signature.r, { size: 32 }),
|
|
1497
|
+
s: Hex.fromNumber(p256Signature.s, { size: 32 }),
|
|
1498
|
+
type: 'webAuthn',
|
|
1499
|
+
webauthnData: Hex.concat(
|
|
1500
|
+
webauthnData,
|
|
1501
|
+
Hex.fromString(clientDataJSON),
|
|
1502
|
+
),
|
|
1503
|
+
},
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
const envelope = SignatureEnvelope.fromRpc(rpc)
|
|
1507
|
+
|
|
1508
|
+
expect(envelope).toMatchObject({
|
|
1509
|
+
type: 'keychain',
|
|
1510
|
+
userAddress: '0xfedcbafedcbafedcbafedcbafedcbafedcbafedc',
|
|
1511
|
+
inner: {
|
|
1512
|
+
type: 'webAuthn',
|
|
1513
|
+
metadata: {
|
|
1514
|
+
authenticatorData: webauthnData,
|
|
1515
|
+
clientDataJSON,
|
|
1516
|
+
},
|
|
1517
|
+
publicKey: {
|
|
1518
|
+
x: publicKey.x,
|
|
1519
|
+
y: publicKey.y,
|
|
1520
|
+
},
|
|
1521
|
+
signature: {
|
|
1522
|
+
r: p256Signature.r,
|
|
1523
|
+
s: p256Signature.s,
|
|
1524
|
+
},
|
|
1525
|
+
},
|
|
1526
|
+
})
|
|
1527
|
+
})
|
|
1528
|
+
})
|
|
1049
1529
|
})
|
|
1050
1530
|
|
|
1051
1531
|
describe('toRpc', () => {
|
|
@@ -1113,6 +1593,56 @@ describe('toRpc', () => {
|
|
|
1113
1593
|
)
|
|
1114
1594
|
})
|
|
1115
1595
|
})
|
|
1596
|
+
|
|
1597
|
+
describe('keychain', () => {
|
|
1598
|
+
test('behavior: converts keychain signature with secp256k1 inner to RPC', () => {
|
|
1599
|
+
const envelope: SignatureEnvelope.Keychain = {
|
|
1600
|
+
type: 'keychain',
|
|
1601
|
+
userAddress: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
|
|
1602
|
+
inner: {
|
|
1603
|
+
signature: signature_secp256k1,
|
|
1604
|
+
type: 'secp256k1',
|
|
1605
|
+
},
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1608
|
+
const rpc = SignatureEnvelope.toRpc(
|
|
1609
|
+
envelope,
|
|
1610
|
+
) as SignatureEnvelope.KeychainRpc
|
|
1611
|
+
|
|
1612
|
+
expect(rpc.type).toBe('keychain')
|
|
1613
|
+
expect(rpc.userAddress).toBe('0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266')
|
|
1614
|
+
expect(rpc.signature).toMatchObject({
|
|
1615
|
+
r: Signature.toRpc(signature_secp256k1).r,
|
|
1616
|
+
s: Signature.toRpc(signature_secp256k1).s,
|
|
1617
|
+
yParity: Signature.toRpc(signature_secp256k1).yParity,
|
|
1618
|
+
type: 'secp256k1',
|
|
1619
|
+
})
|
|
1620
|
+
})
|
|
1621
|
+
|
|
1622
|
+
test('behavior: converts keychain signature with p256 inner to RPC', () => {
|
|
1623
|
+
const rpc = SignatureEnvelope.toRpc(
|
|
1624
|
+
signature_keychain_p256,
|
|
1625
|
+
) as SignatureEnvelope.KeychainRpc
|
|
1626
|
+
|
|
1627
|
+
expect(rpc.type).toBe('keychain')
|
|
1628
|
+
expect(rpc.userAddress).toBe(signature_keychain_p256.userAddress)
|
|
1629
|
+
expect(rpc.signature.type).toBe('p256')
|
|
1630
|
+
expect(typeof rpc.signature.pubKeyX).toBe('string')
|
|
1631
|
+
expect(typeof rpc.signature.pubKeyY).toBe('string')
|
|
1632
|
+
})
|
|
1633
|
+
|
|
1634
|
+
test('behavior: converts keychain signature with webAuthn inner to RPC', () => {
|
|
1635
|
+
const rpc = SignatureEnvelope.toRpc(
|
|
1636
|
+
signature_keychain_webauthn,
|
|
1637
|
+
) as SignatureEnvelope.KeychainRpc
|
|
1638
|
+
|
|
1639
|
+
expect(rpc.type).toBe('keychain')
|
|
1640
|
+
expect(rpc.userAddress).toBe(signature_keychain_webauthn.userAddress)
|
|
1641
|
+
expect(rpc.signature.type).toBe('webAuthn')
|
|
1642
|
+
expect(typeof rpc.signature.pubKeyX).toBe('string')
|
|
1643
|
+
expect(typeof rpc.signature.webauthnData).toBe('string')
|
|
1644
|
+
})
|
|
1645
|
+
})
|
|
1116
1646
|
})
|
|
1117
1647
|
|
|
1118
1648
|
describe('roundtrip: toRpc <-> fromRpc', () => {
|
|
@@ -1223,6 +1753,100 @@ describe('roundtrip: toRpc <-> fromRpc', () => {
|
|
|
1223
1753
|
expect(roundtripped.metadata?.clientDataJSON).toBe(longClientData)
|
|
1224
1754
|
})
|
|
1225
1755
|
})
|
|
1756
|
+
|
|
1757
|
+
describe('keychain', () => {
|
|
1758
|
+
test('behavior: roundtrips toRpc -> fromRpc with secp256k1 inner', () => {
|
|
1759
|
+
const envelope: SignatureEnvelope.Keychain = {
|
|
1760
|
+
type: 'keychain',
|
|
1761
|
+
userAddress: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
|
|
1762
|
+
inner: {
|
|
1763
|
+
signature: signature_secp256k1,
|
|
1764
|
+
type: 'secp256k1',
|
|
1765
|
+
},
|
|
1766
|
+
}
|
|
1767
|
+
|
|
1768
|
+
const rpc = SignatureEnvelope.toRpc(envelope)
|
|
1769
|
+
const roundtripped = SignatureEnvelope.fromRpc(rpc)
|
|
1770
|
+
|
|
1771
|
+
expect(roundtripped).toMatchObject({
|
|
1772
|
+
type: 'keychain',
|
|
1773
|
+
userAddress: envelope.userAddress,
|
|
1774
|
+
inner: {
|
|
1775
|
+
type: 'secp256k1',
|
|
1776
|
+
signature: {
|
|
1777
|
+
r: signature_secp256k1.r,
|
|
1778
|
+
s: signature_secp256k1.s,
|
|
1779
|
+
yParity: signature_secp256k1.yParity,
|
|
1780
|
+
},
|
|
1781
|
+
},
|
|
1782
|
+
})
|
|
1783
|
+
})
|
|
1784
|
+
|
|
1785
|
+
test('behavior: roundtrips toRpc -> fromRpc with p256 inner', () => {
|
|
1786
|
+
const rpc = SignatureEnvelope.toRpc(signature_keychain_p256)
|
|
1787
|
+
const roundtripped = SignatureEnvelope.fromRpc(rpc)
|
|
1788
|
+
|
|
1789
|
+
expect(roundtripped).toMatchObject({
|
|
1790
|
+
type: 'keychain',
|
|
1791
|
+
userAddress: signature_keychain_p256.userAddress,
|
|
1792
|
+
inner: {
|
|
1793
|
+
type: 'p256',
|
|
1794
|
+
prehash: signature_p256.prehash,
|
|
1795
|
+
publicKey: {
|
|
1796
|
+
x: signature_p256.publicKey.x,
|
|
1797
|
+
y: signature_p256.publicKey.y,
|
|
1798
|
+
},
|
|
1799
|
+
signature: {
|
|
1800
|
+
r: signature_p256.signature.r,
|
|
1801
|
+
s: signature_p256.signature.s,
|
|
1802
|
+
},
|
|
1803
|
+
},
|
|
1804
|
+
})
|
|
1805
|
+
})
|
|
1806
|
+
|
|
1807
|
+
test('behavior: roundtrips toRpc -> fromRpc with webAuthn inner', () => {
|
|
1808
|
+
const rpc = SignatureEnvelope.toRpc(signature_keychain_webauthn)
|
|
1809
|
+
const roundtripped = SignatureEnvelope.fromRpc(rpc)
|
|
1810
|
+
|
|
1811
|
+
expect(roundtripped).toMatchObject({
|
|
1812
|
+
type: 'keychain',
|
|
1813
|
+
userAddress: signature_keychain_webauthn.userAddress,
|
|
1814
|
+
inner: {
|
|
1815
|
+
type: 'webAuthn',
|
|
1816
|
+
metadata: {
|
|
1817
|
+
authenticatorData: signature_webauthn.metadata.authenticatorData,
|
|
1818
|
+
clientDataJSON: signature_webauthn.metadata.clientDataJSON,
|
|
1819
|
+
},
|
|
1820
|
+
publicKey: {
|
|
1821
|
+
x: signature_webauthn.publicKey.x,
|
|
1822
|
+
y: signature_webauthn.publicKey.y,
|
|
1823
|
+
},
|
|
1824
|
+
signature: {
|
|
1825
|
+
r: signature_webauthn.signature.r,
|
|
1826
|
+
s: signature_webauthn.signature.s,
|
|
1827
|
+
},
|
|
1828
|
+
},
|
|
1829
|
+
})
|
|
1830
|
+
})
|
|
1831
|
+
|
|
1832
|
+
test('behavior: roundtrips fromRpc -> toRpc with secp256k1 inner', () => {
|
|
1833
|
+
const rpc: SignatureEnvelope.KeychainRpc = {
|
|
1834
|
+
type: 'keychain',
|
|
1835
|
+
userAddress: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
|
|
1836
|
+
signature: {
|
|
1837
|
+
type: 'secp256k1',
|
|
1838
|
+
r: '0xa2bb71146c20ce932456c043ebb2973ed205e07cd32c35a60bdefca1285fd132',
|
|
1839
|
+
s: '0x7cba10692bccdbfba9a215418443c2903dbee6fe5cb55c91172e47efc607840e',
|
|
1840
|
+
yParity: '0x1',
|
|
1841
|
+
},
|
|
1842
|
+
}
|
|
1843
|
+
|
|
1844
|
+
const envelope = SignatureEnvelope.fromRpc(rpc)
|
|
1845
|
+
const roundtripped = SignatureEnvelope.toRpc(envelope)
|
|
1846
|
+
|
|
1847
|
+
expect(roundtripped).toMatchObject(rpc)
|
|
1848
|
+
})
|
|
1849
|
+
})
|
|
1226
1850
|
})
|
|
1227
1851
|
|
|
1228
1852
|
describe('types', () => {
|