tempo.ts 0.7.6 → 0.8.0

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 (129) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/chains.d.ts +6 -20
  3. package/dist/chains.d.ts.map +1 -1
  4. package/dist/chains.js +14 -15
  5. package/dist/chains.js.map +1 -1
  6. package/dist/ox/KeyAuthorization.d.ts +356 -0
  7. package/dist/ox/KeyAuthorization.d.ts.map +1 -0
  8. package/dist/ox/KeyAuthorization.js +360 -0
  9. package/dist/ox/KeyAuthorization.js.map +1 -0
  10. package/dist/ox/SignatureEnvelope.d.ts +21 -6
  11. package/dist/ox/SignatureEnvelope.d.ts.map +1 -1
  12. package/dist/ox/SignatureEnvelope.js +43 -3
  13. package/dist/ox/SignatureEnvelope.js.map +1 -1
  14. package/dist/ox/Transaction.d.ts +5 -1
  15. package/dist/ox/Transaction.d.ts.map +1 -1
  16. package/dist/ox/Transaction.js +5 -0
  17. package/dist/ox/Transaction.js.map +1 -1
  18. package/dist/ox/TransactionEnvelopeAA.d.ts +9 -0
  19. package/dist/ox/TransactionEnvelopeAA.d.ts.map +1 -1
  20. package/dist/ox/TransactionEnvelopeAA.js +17 -4
  21. package/dist/ox/TransactionEnvelopeAA.js.map +1 -1
  22. package/dist/ox/TransactionRequest.d.ts +7 -1
  23. package/dist/ox/TransactionRequest.d.ts.map +1 -1
  24. package/dist/ox/TransactionRequest.js +12 -0
  25. package/dist/ox/TransactionRequest.js.map +1 -1
  26. package/dist/ox/index.d.ts +1 -0
  27. package/dist/ox/index.d.ts.map +1 -1
  28. package/dist/ox/index.js +1 -0
  29. package/dist/ox/index.js.map +1 -1
  30. package/dist/prool/Instance.js +1 -1
  31. package/dist/prool/Instance.js.map +1 -1
  32. package/{src/prool/internal → dist/prool}/chain.json +4 -2
  33. package/dist/viem/Abis.d.ts +319 -6
  34. package/dist/viem/Abis.d.ts.map +1 -1
  35. package/dist/viem/Abis.js +199 -7
  36. package/dist/viem/Abis.js.map +1 -1
  37. package/dist/viem/Account.d.ts +103 -14
  38. package/dist/viem/Account.d.ts.map +1 -1
  39. package/dist/viem/Account.js +177 -23
  40. package/dist/viem/Account.js.map +1 -1
  41. package/dist/viem/Actions/account.d.ts.map +1 -1
  42. package/dist/viem/Actions/account.js +4 -5
  43. package/dist/viem/Actions/account.js.map +1 -1
  44. package/dist/viem/Actions/amm.d.ts +72 -0
  45. package/dist/viem/Actions/amm.d.ts.map +1 -1
  46. package/dist/viem/Actions/dex.d.ts +156 -4
  47. package/dist/viem/Actions/dex.d.ts.map +1 -1
  48. package/dist/viem/Actions/fee.d.ts +4 -0
  49. package/dist/viem/Actions/fee.d.ts.map +1 -1
  50. package/dist/viem/Actions/reward.d.ts +78 -0
  51. package/dist/viem/Actions/reward.d.ts.map +1 -1
  52. package/dist/viem/Actions/token.d.ts +585 -0
  53. package/dist/viem/Actions/token.d.ts.map +1 -1
  54. package/dist/viem/Actions/token.js +2 -2
  55. package/dist/viem/Actions/token.js.map +1 -1
  56. package/dist/viem/Addresses.d.ts +1 -1
  57. package/dist/viem/Addresses.d.ts.map +1 -1
  58. package/dist/viem/Addresses.js +1 -1
  59. package/dist/viem/Addresses.js.map +1 -1
  60. package/dist/viem/Chain.d.ts +35 -0
  61. package/dist/viem/Chain.d.ts.map +1 -1
  62. package/dist/viem/Chain.js +37 -0
  63. package/dist/viem/Chain.js.map +1 -1
  64. package/dist/viem/Formatters.d.ts.map +1 -1
  65. package/dist/viem/Formatters.js +8 -7
  66. package/dist/viem/Formatters.js.map +1 -1
  67. package/dist/viem/Storage.d.ts +1 -0
  68. package/dist/viem/Storage.d.ts.map +1 -1
  69. package/dist/viem/Storage.js +21 -0
  70. package/dist/viem/Storage.js.map +1 -1
  71. package/dist/viem/TokenIds.d.ts +1 -1
  72. package/dist/viem/TokenIds.d.ts.map +1 -1
  73. package/dist/viem/TokenIds.js +1 -1
  74. package/dist/viem/TokenIds.js.map +1 -1
  75. package/dist/viem/Transaction.d.ts +9 -1
  76. package/dist/viem/Transaction.d.ts.map +1 -1
  77. package/dist/viem/Transaction.js +2 -1
  78. package/dist/viem/Transaction.js.map +1 -1
  79. package/dist/viem/WebAuthnP256.d.ts +4 -1
  80. package/dist/viem/WebAuthnP256.d.ts.map +1 -1
  81. package/dist/viem/WebAuthnP256.js +3 -1
  82. package/dist/viem/WebAuthnP256.js.map +1 -1
  83. package/dist/wagmi/Connector.d.ts +25 -8
  84. package/dist/wagmi/Connector.d.ts.map +1 -1
  85. package/dist/wagmi/Connector.js +120 -27
  86. package/dist/wagmi/Connector.js.map +1 -1
  87. package/package.json +3 -2
  88. package/src/chains.ts +14 -15
  89. package/src/ox/KeyAuthorization.test.ts +1332 -0
  90. package/src/ox/KeyAuthorization.ts +542 -0
  91. package/src/ox/SignatureEnvelope.test.ts +624 -0
  92. package/src/ox/SignatureEnvelope.ts +89 -9
  93. package/src/ox/Transaction.test.ts +214 -0
  94. package/src/ox/Transaction.ts +13 -1
  95. package/src/ox/TransactionEnvelopeAA.test.ts +164 -4
  96. package/src/ox/TransactionEnvelopeAA.ts +36 -3
  97. package/src/ox/TransactionRequest.ts +22 -1
  98. package/src/ox/e2e.test.ts +612 -5
  99. package/src/ox/index.ts +1 -0
  100. package/src/prool/Instance.ts +1 -1
  101. package/src/prool/chain.json +238 -0
  102. package/src/server/Handler.test.ts +20 -36
  103. package/src/viem/Abis.ts +200 -7
  104. package/src/viem/Account.test.ts +444 -0
  105. package/src/viem/Account.ts +355 -42
  106. package/src/viem/Actions/account.ts +3 -5
  107. package/src/viem/Actions/amm.test.ts +4 -4
  108. package/src/viem/Actions/token.test.ts +8 -8
  109. package/src/viem/Actions/token.ts +2 -2
  110. package/src/viem/Addresses.ts +1 -1
  111. package/src/viem/Chain.test.ts +168 -0
  112. package/src/viem/Chain.ts +37 -1
  113. package/src/viem/Formatters.ts +8 -7
  114. package/src/viem/Storage.ts +22 -0
  115. package/src/viem/TokenIds.ts +1 -1
  116. package/src/viem/Transaction.ts +14 -2
  117. package/src/viem/WebAuthnP256.ts +8 -2
  118. package/src/viem/e2e.test.ts +299 -96
  119. package/src/wagmi/Actions/amm.test.ts +2 -2
  120. package/src/wagmi/Connector.test.ts +1 -1
  121. package/src/wagmi/Connector.ts +184 -54
  122. package/src/wagmi/Hooks/amm.test.ts +4 -4
  123. package/src/wagmi/Hooks/fee.test.ts +10 -4
  124. package/src/wagmi/Hooks/token.test.ts +0 -488
  125. package/dist/viem/internal/account.d.ts +0 -21
  126. package/dist/viem/internal/account.d.ts.map +0 -1
  127. package/dist/viem/internal/account.js +0 -61
  128. package/dist/viem/internal/account.js.map +0 -1
  129. package/src/viem/internal/account.ts +0 -89
@@ -7,10 +7,10 @@ import {
7
7
  WebCryptoP256,
8
8
  } from 'ox'
9
9
  import { getTransactionCount } from 'viem/actions'
10
- import { expect, test } from 'vitest'
10
+ import { beforeEach, describe, expect, test } from 'vitest'
11
11
  import { chainId } from '../../test/config.js'
12
12
  import { client, fundAddress } from '../../test/viem/config.js'
13
- import { SignatureEnvelope } from './index.js'
13
+ import { KeyAuthorization, SignatureEnvelope } from './index.js'
14
14
  import * as Transaction from './Transaction.js'
15
15
  import * as TransactionEnvelopeAA from './TransactionEnvelopeAA.js'
16
16
  import * as TransactionReceipt from './TransactionReceipt.js'
@@ -75,7 +75,6 @@ test('behavior: default (secp256k1)', async () => {
75
75
  hash,
76
76
  feeToken: _,
77
77
  from,
78
- // @ts-expect-error
79
78
  keyAuthorization: __,
80
79
  nonce,
81
80
  maxFeePerGas,
@@ -215,7 +214,6 @@ test('behavior: default (p256)', async () => {
215
214
  chainId,
216
215
  feeToken: _,
217
216
  from,
218
- // @ts-expect-error
219
217
  keyAuthorization: __,
220
218
  hash,
221
219
  nonce,
@@ -501,7 +499,6 @@ test('behavior: default (webauthn)', async () => {
501
499
  chainId,
502
500
  feeToken: _,
503
501
  from,
504
- // @ts-expect-error
505
502
  keyAuthorization: __,
506
503
  hash,
507
504
  nonce,
@@ -703,3 +700,613 @@ test('behavior: feePayerSignature (user → feePayer)', async () => {
703
700
  expect(feeToken).toBe('0x20c0000000000000000000000000000000000001')
704
701
  expect(from).toBe(senderAddress)
705
702
  })
703
+
704
+ describe('behavior: keyAuthorization', () => {
705
+ const privateKey = Secp256k1.randomPrivateKey()
706
+ const address = Address.fromPublicKey(Secp256k1.getPublicKey({ privateKey }))
707
+ const root = {
708
+ address,
709
+ privateKey,
710
+ } as const
711
+
712
+ beforeEach(async () => {
713
+ await fundAddress(client, {
714
+ address,
715
+ })
716
+ })
717
+
718
+ test('behavior: secp256k1 access key', async () => {
719
+ const privateKey =
720
+ '0x06a952d58c24d287245276dd8b4272d82a921d27d90874a6c27a3bc19ff4bfde'
721
+ const publicKey = Secp256k1.getPublicKey({ privateKey })
722
+ const address = Address.fromPublicKey(publicKey)
723
+ const access = {
724
+ address,
725
+ publicKey,
726
+ privateKey,
727
+ } as const
728
+
729
+ const keyAuth = KeyAuthorization.from({
730
+ address: access.address,
731
+ type: 'secp256k1',
732
+ })
733
+
734
+ const keyAuth_signature = Secp256k1.sign({
735
+ payload: KeyAuthorization.getSignPayload(keyAuth),
736
+ privateKey: root.privateKey,
737
+ })
738
+
739
+ const keyAuth_signed = KeyAuthorization.from(keyAuth, {
740
+ signature: SignatureEnvelope.from(keyAuth_signature),
741
+ })
742
+
743
+ const nonce = await getTransactionCount(client, {
744
+ address: root.address,
745
+ blockTag: 'pending',
746
+ })
747
+
748
+ const transaction = TransactionEnvelopeAA.from({
749
+ calls: [
750
+ {
751
+ to: '0x0000000000000000000000000000000000000000',
752
+ },
753
+ ],
754
+ chainId,
755
+ feeToken: '0x20c0000000000000000000000000000000000001',
756
+ keyAuthorization: keyAuth_signed,
757
+ nonce: BigInt(nonce),
758
+ gas: 100_000n,
759
+ maxFeePerGas: Value.fromGwei('20'),
760
+ maxPriorityFeePerGas: Value.fromGwei('10'),
761
+ })
762
+
763
+ const signature = Secp256k1.sign({
764
+ payload: TransactionEnvelopeAA.getSignPayload(transaction),
765
+ privateKey: access.privateKey,
766
+ })
767
+
768
+ const serialized_signed = TransactionEnvelopeAA.serialize(transaction, {
769
+ signature: SignatureEnvelope.from({
770
+ userAddress: root.address,
771
+ inner: SignatureEnvelope.from(signature),
772
+ type: 'keychain',
773
+ }),
774
+ })
775
+
776
+ const receipt = (await client
777
+ .request({
778
+ method: 'eth_sendRawTransactionSync',
779
+ params: [serialized_signed],
780
+ })
781
+ .then((tx) => TransactionReceipt.fromRpc(tx as any)))!
782
+
783
+ {
784
+ const response = await client
785
+ .request({
786
+ method: 'eth_getTransactionByHash',
787
+ params: [receipt.transactionHash],
788
+ })
789
+ .then((tx) => Transaction.fromRpc(tx as any))
790
+ if (!response) throw new Error()
791
+
792
+ const {
793
+ blockNumber,
794
+ blockHash,
795
+ chainId: _,
796
+ gasPrice,
797
+ hash,
798
+ from,
799
+ keyAuthorization,
800
+ maxFeePerGas,
801
+ maxPriorityFeePerGas,
802
+ nonce,
803
+ signature,
804
+ transactionIndex,
805
+ ...rest
806
+ } = response
807
+
808
+ expect(blockNumber).toBeDefined()
809
+ expect(blockHash).toBeDefined()
810
+ expect(gasPrice).toBeDefined()
811
+ expect(maxFeePerGas).toBeDefined()
812
+ expect(maxPriorityFeePerGas).toBeDefined()
813
+ expect(nonce).toBeDefined()
814
+ expect(from).toBe(root.address)
815
+ expect(hash).toBe(receipt.transactionHash)
816
+ expect(keyAuthorization).toBeDefined()
817
+ expect(signature).toBeDefined()
818
+ expect(transactionIndex).toBeDefined()
819
+ expect(rest).toMatchInlineSnapshot(`
820
+ {
821
+ "aaAuthorizationList": [],
822
+ "accessList": [],
823
+ "calls": [
824
+ {
825
+ "data": "0x",
826
+ "to": "0x0000000000000000000000000000000000000000",
827
+ "value": 0n,
828
+ },
829
+ ],
830
+ "data": undefined,
831
+ "feePayerSignature": null,
832
+ "feeToken": "0x20c0000000000000000000000000000000000001",
833
+ "gas": 100000n,
834
+ "nonceKey": 0n,
835
+ "type": "aa",
836
+ "validAfter": null,
837
+ "validBefore": null,
838
+ "value": 0n,
839
+ }
840
+ `)
841
+ }
842
+
843
+ const {
844
+ blockNumber,
845
+ blockHash,
846
+ feePayer,
847
+ feeToken,
848
+ from,
849
+ logs,
850
+ logsBloom,
851
+ transactionHash,
852
+ transactionIndex,
853
+ ...rest
854
+ } = receipt
855
+
856
+ expect(blockNumber).toBeDefined()
857
+ expect(blockHash).toBeDefined()
858
+ expect(feeToken).toBeDefined()
859
+ expect(feePayer).toBeDefined()
860
+ expect(from).toBeDefined()
861
+ expect(logs).toBeDefined()
862
+ expect(logsBloom).toBeDefined()
863
+ expect(transactionHash).toBe(receipt.transactionHash)
864
+ expect(transactionIndex).toBeDefined()
865
+ expect(rest).toMatchInlineSnapshot(`
866
+ {
867
+ "blobGasPrice": undefined,
868
+ "blobGasUsed": undefined,
869
+ "contractAddress": null,
870
+ "cumulativeGasUsed": 23600n,
871
+ "effectiveGasPrice": 20000000000n,
872
+ "gasUsed": 23600n,
873
+ "status": "success",
874
+ "to": "0x0000000000000000000000000000000000000000",
875
+ "type": "0x76",
876
+ }
877
+ `)
878
+
879
+ // Test a subsequent tx signed by access key with no keyAuthorization
880
+ {
881
+ const nonce = await getTransactionCount(client, {
882
+ address: root.address,
883
+ blockTag: 'pending',
884
+ })
885
+
886
+ const transaction = TransactionEnvelopeAA.from({
887
+ calls: [
888
+ {
889
+ to: '0x0000000000000000000000000000000000000000',
890
+ },
891
+ ],
892
+ chainId,
893
+ feeToken: '0x20c0000000000000000000000000000000000001',
894
+ nonce: BigInt(nonce),
895
+ gas: 100_000n,
896
+ maxFeePerGas: Value.fromGwei('20'),
897
+ maxPriorityFeePerGas: Value.fromGwei('10'),
898
+ })
899
+
900
+ const signature = Secp256k1.sign({
901
+ payload: TransactionEnvelopeAA.getSignPayload(transaction),
902
+ privateKey: access.privateKey,
903
+ })
904
+
905
+ const serialized_signed = TransactionEnvelopeAA.serialize(transaction, {
906
+ signature: SignatureEnvelope.from({
907
+ userAddress: root.address,
908
+ inner: SignatureEnvelope.from(signature),
909
+ type: 'keychain',
910
+ }),
911
+ })
912
+
913
+ const receipt = await client.request({
914
+ method: 'eth_sendRawTransactionSync',
915
+ params: [serialized_signed],
916
+ })
917
+
918
+ expect(receipt).toBeDefined()
919
+ }
920
+ })
921
+
922
+ test('behavior: p256 access key', async () => {
923
+ const privateKey =
924
+ '0x06a952d58c24d287245276dd8b4272d82a921d27d90874a6c27a3bc19ff4bfde'
925
+ const publicKey = P256.getPublicKey({ privateKey })
926
+ const address = Address.fromPublicKey(publicKey)
927
+ const access = {
928
+ address,
929
+ publicKey,
930
+ privateKey,
931
+ } as const
932
+
933
+ const keyAuth = KeyAuthorization.from({
934
+ address: access.address,
935
+ type: 'p256',
936
+ })
937
+
938
+ const keyAuth_signature = Secp256k1.sign({
939
+ payload: KeyAuthorization.getSignPayload(keyAuth),
940
+ privateKey: root.privateKey,
941
+ })
942
+
943
+ const keyAuth_signed = KeyAuthorization.from(keyAuth, {
944
+ signature: SignatureEnvelope.from(keyAuth_signature),
945
+ })
946
+
947
+ const nonce = await getTransactionCount(client, {
948
+ address: root.address,
949
+ blockTag: 'pending',
950
+ })
951
+
952
+ const transaction = TransactionEnvelopeAA.from({
953
+ calls: [
954
+ {
955
+ to: '0x0000000000000000000000000000000000000000',
956
+ },
957
+ ],
958
+ chainId,
959
+ feeToken: '0x20c0000000000000000000000000000000000001',
960
+ keyAuthorization: keyAuth_signed,
961
+ nonce: BigInt(nonce),
962
+ gas: 100_000n,
963
+ maxFeePerGas: Value.fromGwei('20'),
964
+ maxPriorityFeePerGas: Value.fromGwei('10'),
965
+ })
966
+
967
+ const signature = P256.sign({
968
+ payload: TransactionEnvelopeAA.getSignPayload(transaction),
969
+ privateKey: access.privateKey,
970
+ })
971
+
972
+ const serialized_signed = TransactionEnvelopeAA.serialize(transaction, {
973
+ signature: SignatureEnvelope.from({
974
+ userAddress: root.address,
975
+ inner: SignatureEnvelope.from({
976
+ prehash: false,
977
+ publicKey: access.publicKey,
978
+ signature,
979
+ type: 'p256',
980
+ }),
981
+ type: 'keychain',
982
+ }),
983
+ })
984
+
985
+ const receipt = (await client
986
+ .request({
987
+ method: 'eth_sendRawTransactionSync',
988
+ params: [serialized_signed],
989
+ })
990
+ .then((tx) => TransactionReceipt.fromRpc(tx as any)))!
991
+ expect(receipt).toBeDefined()
992
+
993
+ {
994
+ const response = await client
995
+ .request({
996
+ method: 'eth_getTransactionByHash',
997
+ params: [receipt.transactionHash],
998
+ })
999
+ .then((tx) => Transaction.fromRpc(tx as any))
1000
+ if (!response) throw new Error()
1001
+
1002
+ const {
1003
+ blockNumber,
1004
+ blockHash,
1005
+ chainId: _,
1006
+ gasPrice,
1007
+ hash,
1008
+ from,
1009
+ keyAuthorization,
1010
+ maxFeePerGas,
1011
+ maxPriorityFeePerGas,
1012
+ nonce,
1013
+ signature,
1014
+ transactionIndex,
1015
+ ...rest
1016
+ } = response
1017
+
1018
+ expect(blockNumber).toBeDefined()
1019
+ expect(blockHash).toBeDefined()
1020
+ expect(gasPrice).toBeDefined()
1021
+ expect(hash).toBe(receipt.transactionHash)
1022
+ expect(from).toBe(root.address)
1023
+ expect(keyAuthorization).toBeDefined()
1024
+ expect(maxFeePerGas).toBeDefined()
1025
+ expect(maxPriorityFeePerGas).toBeDefined()
1026
+ expect(nonce).toBeDefined()
1027
+ expect(signature).toBeDefined()
1028
+ expect(transactionIndex).toBeDefined()
1029
+ expect(rest).toMatchInlineSnapshot(`
1030
+ {
1031
+ "aaAuthorizationList": [],
1032
+ "accessList": [],
1033
+ "calls": [
1034
+ {
1035
+ "data": "0x",
1036
+ "to": "0x0000000000000000000000000000000000000000",
1037
+ "value": 0n,
1038
+ },
1039
+ ],
1040
+ "data": undefined,
1041
+ "feePayerSignature": null,
1042
+ "feeToken": "0x20c0000000000000000000000000000000000001",
1043
+ "gas": 100000n,
1044
+ "nonceKey": 0n,
1045
+ "type": "aa",
1046
+ "validAfter": null,
1047
+ "validBefore": null,
1048
+ "value": 0n,
1049
+ }
1050
+ `)
1051
+ }
1052
+
1053
+ const {
1054
+ blockNumber,
1055
+ blockHash,
1056
+ feePayer,
1057
+ feeToken,
1058
+ from,
1059
+ logs,
1060
+ logsBloom,
1061
+ transactionHash,
1062
+ transactionIndex,
1063
+ ...rest
1064
+ } = receipt
1065
+
1066
+ expect(blockNumber).toBeDefined()
1067
+ expect(blockHash).toBeDefined()
1068
+ expect(feePayer).toBeDefined()
1069
+ expect(feeToken).toBeDefined()
1070
+ expect(from).toBeDefined()
1071
+ expect(logs).toBeDefined()
1072
+ expect(logsBloom).toBeDefined()
1073
+ expect(transactionHash).toBe(receipt.transactionHash)
1074
+ expect(transactionIndex).toBeDefined()
1075
+ expect(rest).toMatchInlineSnapshot(`
1076
+ {
1077
+ "blobGasPrice": undefined,
1078
+ "blobGasUsed": undefined,
1079
+ "contractAddress": null,
1080
+ "cumulativeGasUsed": 28600n,
1081
+ "effectiveGasPrice": 20000000000n,
1082
+ "gasUsed": 28600n,
1083
+ "status": "success",
1084
+ "to": "0x0000000000000000000000000000000000000000",
1085
+ "type": "0x76",
1086
+ }
1087
+ `)
1088
+
1089
+ // Test a subsequent tx signed by access key with no keyAuthorization
1090
+ {
1091
+ const nonce = await getTransactionCount(client, {
1092
+ address: root.address,
1093
+ blockTag: 'pending',
1094
+ })
1095
+
1096
+ const transaction = TransactionEnvelopeAA.from({
1097
+ calls: [
1098
+ {
1099
+ to: '0x0000000000000000000000000000000000000000',
1100
+ },
1101
+ ],
1102
+ chainId,
1103
+ feeToken: '0x20c0000000000000000000000000000000000001',
1104
+ nonce: BigInt(nonce),
1105
+ gas: 100_000n,
1106
+ maxFeePerGas: Value.fromGwei('20'),
1107
+ maxPriorityFeePerGas: Value.fromGwei('10'),
1108
+ })
1109
+
1110
+ const signature = P256.sign({
1111
+ payload: TransactionEnvelopeAA.getSignPayload(transaction),
1112
+ privateKey: access.privateKey,
1113
+ })
1114
+
1115
+ const serialized_signed = TransactionEnvelopeAA.serialize(transaction, {
1116
+ signature: SignatureEnvelope.from({
1117
+ userAddress: root.address,
1118
+ inner: SignatureEnvelope.from({
1119
+ prehash: false,
1120
+ publicKey: access.publicKey,
1121
+ signature,
1122
+ type: 'p256',
1123
+ }),
1124
+ type: 'keychain',
1125
+ }),
1126
+ })
1127
+
1128
+ const receipt = await client.request({
1129
+ method: 'eth_sendRawTransactionSync',
1130
+ params: [serialized_signed],
1131
+ })
1132
+
1133
+ expect(receipt).toBeDefined()
1134
+ }
1135
+ })
1136
+
1137
+ test('behavior: webcrypto access key', async () => {
1138
+ const keyPair = await WebCryptoP256.createKeyPair()
1139
+ const address = Address.fromPublicKey(keyPair.publicKey)
1140
+ const access = {
1141
+ address,
1142
+ publicKey: keyPair.publicKey,
1143
+ privateKey: keyPair.privateKey,
1144
+ } as const
1145
+
1146
+ const keyAuth = KeyAuthorization.from({
1147
+ address: access.address,
1148
+ type: 'p256',
1149
+ })
1150
+
1151
+ const keyAuth_signature = Secp256k1.sign({
1152
+ payload: KeyAuthorization.getSignPayload(keyAuth),
1153
+ privateKey: root.privateKey,
1154
+ })
1155
+
1156
+ const keyAuth_signed = KeyAuthorization.from(keyAuth, {
1157
+ signature: SignatureEnvelope.from(keyAuth_signature),
1158
+ })
1159
+
1160
+ const nonce = await getTransactionCount(client, {
1161
+ address: root.address,
1162
+ blockTag: 'pending',
1163
+ })
1164
+
1165
+ const transaction = TransactionEnvelopeAA.from({
1166
+ calls: [
1167
+ {
1168
+ to: '0x0000000000000000000000000000000000000000',
1169
+ },
1170
+ ],
1171
+ chainId,
1172
+ feeToken: '0x20c0000000000000000000000000000000000001',
1173
+ keyAuthorization: keyAuth_signed,
1174
+ nonce: BigInt(nonce),
1175
+ gas: 100_000n,
1176
+ maxFeePerGas: Value.fromGwei('20'),
1177
+ maxPriorityFeePerGas: Value.fromGwei('10'),
1178
+ })
1179
+
1180
+ const signature = await WebCryptoP256.sign({
1181
+ payload: TransactionEnvelopeAA.getSignPayload(transaction),
1182
+ privateKey: keyPair.privateKey,
1183
+ })
1184
+
1185
+ const serialized_signed = TransactionEnvelopeAA.serialize(transaction, {
1186
+ signature: SignatureEnvelope.from({
1187
+ userAddress: root.address,
1188
+ inner: SignatureEnvelope.from({
1189
+ prehash: true,
1190
+ publicKey: access.publicKey,
1191
+ signature,
1192
+ type: 'p256',
1193
+ }),
1194
+ type: 'keychain',
1195
+ }),
1196
+ })
1197
+
1198
+ const receipt = await client.request({
1199
+ method: 'eth_sendRawTransactionSync',
1200
+ params: [serialized_signed],
1201
+ })
1202
+
1203
+ expect(receipt).toBeDefined()
1204
+
1205
+ {
1206
+ const response = await client
1207
+ .request({
1208
+ method: 'eth_getTransactionByHash',
1209
+ params: [receipt.transactionHash],
1210
+ })
1211
+ .then((tx) => Transaction.fromRpc(tx as any))
1212
+ if (!response) throw new Error()
1213
+
1214
+ const {
1215
+ blockNumber,
1216
+ blockHash,
1217
+ chainId: _,
1218
+ gasPrice,
1219
+ hash,
1220
+ from,
1221
+ keyAuthorization,
1222
+ maxFeePerGas,
1223
+ maxPriorityFeePerGas,
1224
+ nonce,
1225
+ signature,
1226
+ transactionIndex,
1227
+ ...rest
1228
+ } = response
1229
+
1230
+ expect(blockNumber).toBeDefined()
1231
+ expect(blockHash).toBeDefined()
1232
+ expect(gasPrice).toBeDefined()
1233
+ expect(hash).toBe(receipt.transactionHash)
1234
+ expect(from).toBe(root.address)
1235
+ expect(keyAuthorization).toBeDefined()
1236
+ expect(maxFeePerGas).toBeDefined()
1237
+ expect(maxPriorityFeePerGas).toBeDefined()
1238
+ expect(nonce).toBeDefined()
1239
+ expect(signature).toBeDefined()
1240
+ expect(transactionIndex).toBeDefined()
1241
+ expect(rest).toMatchInlineSnapshot(`
1242
+ {
1243
+ "aaAuthorizationList": [],
1244
+ "accessList": [],
1245
+ "calls": [
1246
+ {
1247
+ "data": "0x",
1248
+ "to": "0x0000000000000000000000000000000000000000",
1249
+ "value": 0n,
1250
+ },
1251
+ ],
1252
+ "data": undefined,
1253
+ "feePayerSignature": null,
1254
+ "feeToken": "0x20c0000000000000000000000000000000000001",
1255
+ "gas": 100000n,
1256
+ "nonceKey": 0n,
1257
+ "type": "aa",
1258
+ "validAfter": null,
1259
+ "validBefore": null,
1260
+ "value": 0n,
1261
+ }
1262
+ `)
1263
+ }
1264
+
1265
+ // Test a subsequent tx signed by access key with no keyAuthorization
1266
+ {
1267
+ const nonce = await getTransactionCount(client, {
1268
+ address: root.address,
1269
+ blockTag: 'pending',
1270
+ })
1271
+
1272
+ const transaction = TransactionEnvelopeAA.from({
1273
+ calls: [
1274
+ {
1275
+ to: '0x0000000000000000000000000000000000000000',
1276
+ },
1277
+ ],
1278
+ chainId,
1279
+ feeToken: '0x20c0000000000000000000000000000000000001',
1280
+ nonce: BigInt(nonce),
1281
+ gas: 100_000n,
1282
+ maxFeePerGas: Value.fromGwei('20'),
1283
+ maxPriorityFeePerGas: Value.fromGwei('10'),
1284
+ })
1285
+
1286
+ const signature = await WebCryptoP256.sign({
1287
+ payload: TransactionEnvelopeAA.getSignPayload(transaction),
1288
+ privateKey: keyPair.privateKey,
1289
+ })
1290
+
1291
+ const serialized_signed = TransactionEnvelopeAA.serialize(transaction, {
1292
+ signature: SignatureEnvelope.from({
1293
+ userAddress: root.address,
1294
+ inner: SignatureEnvelope.from({
1295
+ prehash: true,
1296
+ publicKey: access.publicKey,
1297
+ signature,
1298
+ type: 'p256',
1299
+ }),
1300
+ type: 'keychain',
1301
+ }),
1302
+ })
1303
+
1304
+ const receipt = await client.request({
1305
+ method: 'eth_sendRawTransactionSync',
1306
+ params: [serialized_signed],
1307
+ })
1308
+
1309
+ expect(receipt).toBeDefined()
1310
+ }
1311
+ })
1312
+ })
package/src/ox/index.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export * as KeyAuthorization from './KeyAuthorization.js'
1
2
  export * as Order from './Order.js'
2
3
  export * as OrdersFilters from './OrdersFilters.js'
3
4
  export * as Pagination from './Pagination.js'
@@ -22,7 +22,7 @@ export const tempo = defineInstance((parameters: tempo.Parameters = {}) => {
22
22
  const {
23
23
  builder,
24
24
  containerName = `tempo.${crypto.randomUUID()}`,
25
- chain = path.resolve(import.meta.dirname, './internal/chain.json'),
25
+ chain = path.resolve(import.meta.dirname, './chain.json'),
26
26
  image = 'ghcr.io/tempoxyz/tempo',
27
27
  dev,
28
28
  log: log_,