viem 2.15.0 → 2.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +17 -11
  3. package/_cjs/actions/public/verifyHash.js +21 -3
  4. package/_cjs/actions/public/verifyHash.js.map +1 -1
  5. package/_cjs/actions/public/verifyMessage.js +3 -1
  6. package/_cjs/actions/public/verifyMessage.js.map +1 -1
  7. package/_cjs/actions/public/verifyTypedData.js +3 -1
  8. package/_cjs/actions/public/verifyTypedData.js.map +1 -1
  9. package/_cjs/chains/definitions/zetachain.js +6 -0
  10. package/_cjs/chains/definitions/zetachain.js.map +1 -1
  11. package/_cjs/chains/definitions/zetachainAthensTestnet.js +6 -0
  12. package/_cjs/chains/definitions/zetachainAthensTestnet.js.map +1 -1
  13. package/_cjs/chains/definitions/zircuitTestnet.js +27 -0
  14. package/_cjs/chains/definitions/zircuitTestnet.js.map +1 -0
  15. package/_cjs/chains/index.js +3 -1
  16. package/_cjs/chains/index.js.map +1 -1
  17. package/_cjs/errors/version.js +1 -1
  18. package/_cjs/experimental/index.js +10 -4
  19. package/_cjs/experimental/index.js.map +1 -1
  20. package/_cjs/experimental/solady/actions/signMessage.js +40 -0
  21. package/_cjs/experimental/solady/actions/signMessage.js.map +1 -0
  22. package/_cjs/experimental/solady/actions/signTypedData.js +83 -0
  23. package/_cjs/experimental/solady/actions/signTypedData.js.map +1 -0
  24. package/_cjs/experimental/solady/decorators/solady.js +16 -0
  25. package/_cjs/experimental/solady/decorators/solady.js.map +1 -0
  26. package/_cjs/experimental/solady/types.js +3 -0
  27. package/_cjs/experimental/solady/types.js.map +1 -0
  28. package/_cjs/index.js +11 -3
  29. package/_cjs/index.js.map +1 -1
  30. package/_cjs/utils/index.js +7 -1
  31. package/_cjs/utils/index.js.map +1 -1
  32. package/_cjs/utils/signature/hashMessage.js +2 -12
  33. package/_cjs/utils/signature/hashMessage.js.map +1 -1
  34. package/_cjs/utils/signature/hashTypedData.js +3 -1
  35. package/_cjs/utils/signature/hashTypedData.js.map +1 -1
  36. package/_cjs/{experimental/erc6492 → utils/signature}/isErc6492Signature.js +1 -1
  37. package/_cjs/utils/signature/isErc6492Signature.js.map +1 -0
  38. package/_cjs/{experimental/erc6492 → utils/signature}/parseErc6492Signature.js +1 -1
  39. package/_cjs/utils/signature/parseErc6492Signature.js.map +1 -0
  40. package/_cjs/{experimental/erc6492 → utils/signature}/serializeErc6492Signature.js +2 -2
  41. package/_cjs/utils/signature/serializeErc6492Signature.js.map +1 -0
  42. package/_cjs/utils/signature/toPrefixedMessage.js +20 -0
  43. package/_cjs/utils/signature/toPrefixedMessage.js.map +1 -0
  44. package/_esm/actions/public/getTransactionCount.js +1 -1
  45. package/_esm/actions/public/verifyHash.js +27 -3
  46. package/_esm/actions/public/verifyHash.js.map +1 -1
  47. package/_esm/actions/public/verifyMessage.js +3 -1
  48. package/_esm/actions/public/verifyMessage.js.map +1 -1
  49. package/_esm/actions/public/verifyTypedData.js +3 -1
  50. package/_esm/actions/public/verifyTypedData.js.map +1 -1
  51. package/_esm/chains/definitions/zetachain.js +6 -0
  52. package/_esm/chains/definitions/zetachain.js.map +1 -1
  53. package/_esm/chains/definitions/zetachainAthensTestnet.js +6 -0
  54. package/_esm/chains/definitions/zetachainAthensTestnet.js.map +1 -1
  55. package/_esm/chains/definitions/zircuitTestnet.js +24 -0
  56. package/_esm/chains/definitions/zircuitTestnet.js.map +1 -0
  57. package/_esm/chains/index.js +1 -0
  58. package/_esm/chains/index.js.map +1 -1
  59. package/_esm/errors/version.js +1 -1
  60. package/_esm/experimental/index.js +12 -3
  61. package/_esm/experimental/index.js.map +1 -1
  62. package/_esm/experimental/solady/actions/signMessage.js +84 -0
  63. package/_esm/experimental/solady/actions/signMessage.js.map +1 -0
  64. package/_esm/experimental/solady/actions/signTypedData.js +182 -0
  65. package/_esm/experimental/solady/actions/signTypedData.js.map +1 -0
  66. package/_esm/experimental/solady/decorators/solady.js +27 -0
  67. package/_esm/experimental/solady/decorators/solady.js.map +1 -0
  68. package/_esm/experimental/solady/types.js +2 -0
  69. package/_esm/experimental/solady/types.js.map +1 -0
  70. package/_esm/index.js +4 -0
  71. package/_esm/index.js.map +1 -1
  72. package/_esm/utils/index.js +3 -0
  73. package/_esm/utils/index.js.map +1 -1
  74. package/_esm/utils/signature/hashMessage.js +2 -12
  75. package/_esm/utils/signature/hashMessage.js.map +1 -1
  76. package/_esm/utils/signature/hashTypedData.js +2 -2
  77. package/_esm/utils/signature/hashTypedData.js.map +1 -1
  78. package/_esm/{experimental/erc6492 → utils/signature}/isErc6492Signature.js +1 -1
  79. package/_esm/utils/signature/isErc6492Signature.js.map +1 -0
  80. package/_esm/{experimental/erc6492 → utils/signature}/parseErc6492Signature.js +1 -1
  81. package/_esm/utils/signature/parseErc6492Signature.js.map +1 -0
  82. package/_esm/{experimental/erc6492 → utils/signature}/serializeErc6492Signature.js +2 -2
  83. package/_esm/utils/signature/serializeErc6492Signature.js.map +1 -0
  84. package/_esm/utils/signature/toPrefixedMessage.js +16 -0
  85. package/_esm/utils/signature/toPrefixedMessage.js.map +1 -0
  86. package/_types/actions/public/getTransactionCount.d.ts +1 -1
  87. package/_types/actions/public/verifyHash.d.ts +6 -2
  88. package/_types/actions/public/verifyHash.d.ts.map +1 -1
  89. package/_types/actions/public/verifyMessage.d.ts +1 -1
  90. package/_types/actions/public/verifyMessage.d.ts.map +1 -1
  91. package/_types/actions/public/verifyTypedData.d.ts.map +1 -1
  92. package/_types/chains/definitions/zetachain.d.ts +6 -8
  93. package/_types/chains/definitions/zetachain.d.ts.map +1 -1
  94. package/_types/chains/definitions/zetachainAthensTestnet.d.ts +6 -8
  95. package/_types/chains/definitions/zetachainAthensTestnet.d.ts.map +1 -1
  96. package/_types/chains/definitions/zircuitTestnet.d.ts +33 -0
  97. package/_types/chains/definitions/zircuitTestnet.d.ts.map +1 -0
  98. package/_types/chains/index.d.ts +1 -0
  99. package/_types/chains/index.d.ts.map +1 -1
  100. package/_types/errors/version.d.ts +1 -1
  101. package/_types/experimental/index.d.ts +30 -3
  102. package/_types/experimental/index.d.ts.map +1 -1
  103. package/_types/experimental/solady/actions/signMessage.d.ts +71 -0
  104. package/_types/experimental/solady/actions/signMessage.d.ts.map +1 -0
  105. package/_types/experimental/solady/actions/signTypedData.d.ts +125 -0
  106. package/_types/experimental/solady/actions/signTypedData.d.ts.map +1 -0
  107. package/_types/experimental/solady/decorators/solady.d.ts +183 -0
  108. package/_types/experimental/solady/decorators/solady.d.ts.map +1 -0
  109. package/_types/experimental/solady/types.d.ts +7 -0
  110. package/_types/experimental/solady/types.d.ts.map +1 -0
  111. package/_types/index.d.ts +4 -0
  112. package/_types/index.d.ts.map +1 -1
  113. package/_types/utils/index.d.ts +3 -0
  114. package/_types/utils/index.d.ts.map +1 -1
  115. package/_types/utils/signature/hashMessage.d.ts +1 -3
  116. package/_types/utils/signature/hashMessage.d.ts.map +1 -1
  117. package/_types/utils/signature/hashTypedData.d.ts +9 -0
  118. package/_types/utils/signature/hashTypedData.d.ts.map +1 -1
  119. package/_types/{experimental/erc6492 → utils/signature}/isErc6492Signature.d.ts +1 -1
  120. package/_types/utils/signature/isErc6492Signature.d.ts.map +1 -0
  121. package/_types/{experimental/erc6492 → utils/signature}/parseErc6492Signature.d.ts +1 -1
  122. package/_types/utils/signature/parseErc6492Signature.d.ts.map +1 -0
  123. package/_types/utils/signature/serializeErc6492Signature.d.ts.map +1 -0
  124. package/_types/utils/signature/toPrefixedMessage.d.ts +7 -0
  125. package/_types/utils/signature/toPrefixedMessage.d.ts.map +1 -0
  126. package/actions/public/getTransactionCount.ts +1 -1
  127. package/actions/public/verifyHash.ts +31 -4
  128. package/actions/public/verifyMessage.ts +10 -1
  129. package/actions/public/verifyTypedData.ts +4 -0
  130. package/chains/definitions/zetachain.ts +6 -0
  131. package/chains/definitions/zetachainAthensTestnet.ts +6 -0
  132. package/chains/definitions/zircuitTestnet.ts +24 -0
  133. package/chains/index.ts +1 -0
  134. package/errors/version.ts +1 -1
  135. package/experimental/index.ts +33 -3
  136. package/experimental/solady/actions/signMessage.ts +151 -0
  137. package/experimental/solady/actions/signTypedData.ts +280 -0
  138. package/experimental/solady/decorators/solady.ts +232 -0
  139. package/experimental/solady/types.ts +7 -0
  140. package/index.ts +22 -0
  141. package/package.json +3 -3
  142. package/utils/index.ts +18 -0
  143. package/utils/signature/hashMessage.ts +3 -23
  144. package/utils/signature/hashTypedData.ts +2 -2
  145. package/{experimental/erc6492 → utils/signature}/isErc6492Signature.ts +1 -1
  146. package/{experimental/erc6492 → utils/signature}/parseErc6492Signature.ts +1 -1
  147. package/{experimental/erc6492 → utils/signature}/serializeErc6492Signature.ts +2 -2
  148. package/utils/signature/toPrefixedMessage.ts +27 -0
  149. package/_cjs/experimental/erc6492/isErc6492Signature.js.map +0 -1
  150. package/_cjs/experimental/erc6492/parseErc6492Signature.js.map +0 -1
  151. package/_cjs/experimental/erc6492/serializeErc6492Signature.js.map +0 -1
  152. package/_esm/experimental/erc6492/isErc6492Signature.js.map +0 -1
  153. package/_esm/experimental/erc6492/parseErc6492Signature.js.map +0 -1
  154. package/_esm/experimental/erc6492/serializeErc6492Signature.js.map +0 -1
  155. package/_types/experimental/erc6492/isErc6492Signature.d.ts.map +0 -1
  156. package/_types/experimental/erc6492/parseErc6492Signature.d.ts.map +0 -1
  157. package/_types/experimental/erc6492/serializeErc6492Signature.d.ts.map +0 -1
  158. /package/_types/{experimental/erc6492 → utils/signature}/serializeErc6492Signature.d.ts +0 -0
@@ -53,6 +53,8 @@ export async function verifyTypedData<
53
53
  ): Promise<VerifyTypedDataReturnType> {
54
54
  const {
55
55
  address,
56
+ factory,
57
+ factoryData,
56
58
  signature,
57
59
  message,
58
60
  primaryType,
@@ -63,6 +65,8 @@ export async function verifyTypedData<
63
65
  const hash = hashTypedData({ message, primaryType, types, domain })
64
66
  return verifyHash(client, {
65
67
  address,
68
+ factory: factory!,
69
+ factoryData: factoryData!,
66
70
  hash,
67
71
  signature,
68
72
  ...callRequest,
@@ -13,6 +13,12 @@ export const zetachain = /*#__PURE__*/ defineChain({
13
13
  http: ['https://zetachain-evm.blockpi.network/v1/rpc/public'],
14
14
  },
15
15
  },
16
+ contracts: {
17
+ multicall3: {
18
+ address: '0xcA11bde05977b3631167028862bE2a173976CA11',
19
+ blockCreated: 1632781,
20
+ },
21
+ },
16
22
  blockExplorers: {
17
23
  default: {
18
24
  name: 'ZetaScan',
@@ -13,6 +13,12 @@ export const zetachainAthensTestnet = /*#__PURE__*/ defineChain({
13
13
  http: ['https://zetachain-athens-evm.blockpi.network/v1/rpc/public'],
14
14
  },
15
15
  },
16
+ contracts: {
17
+ multicall3: {
18
+ address: '0xcA11bde05977b3631167028862bE2a173976CA11',
19
+ blockCreated: 2715217,
20
+ },
21
+ },
16
22
  blockExplorers: {
17
23
  default: {
18
24
  name: 'ZetaScan',
@@ -0,0 +1,24 @@
1
+ import { defineChain } from '../../utils/chain/defineChain.js'
2
+
3
+ export const zircuitTestnet = /*#__PURE__*/ defineChain({
4
+ id: 48899,
5
+ name: 'Zircuit Testnet',
6
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
7
+ rpcUrls: {
8
+ default: {
9
+ http: ['https://zircuit1.p2pify.com'],
10
+ },
11
+ },
12
+ blockExplorers: {
13
+ default: {
14
+ name: 'Zircuit Explorer',
15
+ url: 'https://explorer.zircuit.com',
16
+ },
17
+ },
18
+ contracts: {
19
+ multicall3: {
20
+ address: '0xcA11bde05977b3631167028862bE2a173976CA11',
21
+ blockCreated: 6040287,
22
+ },
23
+ },
24
+ })
package/chains/index.ts CHANGED
@@ -293,6 +293,7 @@ export { zkSyncTestnet } from './definitions/zkSyncTestnet.js'
293
293
  export { zora } from './definitions/zora.js'
294
294
  export { zoraSepolia } from './definitions/zoraSepolia.js'
295
295
  export { zoraTestnet } from './definitions/zoraTestnet.js'
296
+ export { zircuitTestnet } from './definitions/zircuitTestnet.js'
296
297
 
297
298
  //////////////////////////////////////////////////////////////////////////////////////
298
299
  // Required type exports to prevent TypeScript error "TS2742".
package/errors/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = '2.15.0'
1
+ export const version = '2.16.0'
@@ -36,23 +36,35 @@ export {
36
36
  } from './eip5792/decorators/eip5792.js'
37
37
 
38
38
  export {
39
+ /** @deprecated This is no longer experimental – use `import type { ParseErc6492SignatureErrorType } from 'viem'` instead. */
39
40
  type ParseErc6492SignatureErrorType,
41
+ /** @deprecated This is no longer experimental – use `import type { ParseErc6492SignatureParameters } from 'viem'` instead. */
40
42
  type ParseErc6492SignatureParameters,
43
+ /** @deprecated This is no longer experimental – use `import type { ParseErc6492SignatureReturnType } from 'viem'` instead. */
41
44
  type ParseErc6492SignatureReturnType,
45
+ /** @deprecated This is no longer experimental – use `import { parseErc6492Signature } from 'viem'` instead. */
42
46
  parseErc6492Signature,
43
- } from './erc6492/parseErc6492Signature.js'
47
+ } from '../utils/signature/parseErc6492Signature.js'
44
48
  export {
49
+ /** @deprecated This is no longer experimental – use `import type { IsErc6492SignatureErrorType } from 'viem'` instead. */
45
50
  type IsErc6492SignatureErrorType,
51
+ /** @deprecated This is no longer experimental – use `import type { IsErc6492SignatureParameters } from 'viem'` instead. */
46
52
  type IsErc6492SignatureParameters,
53
+ /** @deprecated This is no longer experimental – use `import type { IsErc6492SignatureReturnType } from 'viem'` instead. */
47
54
  type IsErc6492SignatureReturnType,
55
+ /** @deprecated This is no longer experimental – use `import { isErc6492Signature } from 'viem'` instead. */
48
56
  isErc6492Signature,
49
- } from './erc6492/isErc6492Signature.js'
57
+ } from '../utils/signature/isErc6492Signature.js'
50
58
  export {
59
+ /** @deprecated This is no longer experimental – use `import type { SerializeErc6492SignatureErrorType } from 'viem'` instead. */
51
60
  type SerializeErc6492SignatureErrorType,
61
+ /** @deprecated This is no longer experimental – use `import type { SerializeErc6492SignatureParameters } from 'viem'` instead. */
52
62
  type SerializeErc6492SignatureParameters,
63
+ /** @deprecated This is no longer experimental – use `import type { SerializeErc6492SignatureReturnType } from 'viem'` instead. */
53
64
  type SerializeErc6492SignatureReturnType,
65
+ /** @deprecated This is no longer experimental – use `import { serializeErc6492Signature } from 'viem'` instead. */
54
66
  serializeErc6492Signature,
55
- } from './erc6492/serializeErc6492Signature.js'
67
+ } from '../utils/signature/serializeErc6492Signature.js'
56
68
 
57
69
  export {
58
70
  type IssuePermissionsParameters,
@@ -63,3 +75,21 @@ export {
63
75
  type WalletActionsErc7715,
64
76
  walletActionsErc7715,
65
77
  } from './erc7715/decorators/erc7715.js'
78
+
79
+ export {
80
+ type SignMessageErrorType,
81
+ type SignMessageParameters,
82
+ type SignMessageReturnType,
83
+ signMessage,
84
+ } from './solady/actions/signMessage.js'
85
+ export {
86
+ type SignTypedDataErrorType,
87
+ type SignTypedDataParameters,
88
+ type SignTypedDataReturnType,
89
+ signTypedData,
90
+ } from './solady/actions/signTypedData.js'
91
+ export {
92
+ type SoladyActions,
93
+ type SoladyActionsParameters,
94
+ soladyActions,
95
+ } from './solady/decorators/solady.js'
@@ -0,0 +1,151 @@
1
+ import type { Address, TypedDataDomain } from 'abitype'
2
+ import type { Account } from '../../../accounts/types.js'
3
+ import { parseAccount } from '../../../accounts/utils/parseAccount.js'
4
+ import {
5
+ type GetEip712DomainParameters,
6
+ getEip712Domain,
7
+ } from '../../../actions/public/getEip712Domain.js'
8
+ import { signTypedData } from '../../../actions/wallet/signTypedData.js'
9
+ import type { Client } from '../../../clients/createClient.js'
10
+ import type { Transport } from '../../../clients/transports/createTransport.js'
11
+ import { AccountNotFoundError } from '../../../errors/account.js'
12
+ import type { ErrorType } from '../../../errors/utils.js'
13
+ import type { GetAccountParameter } from '../../../types/account.js'
14
+ import type { Chain } from '../../../types/chain.js'
15
+ import type { Hex, SignableMessage } from '../../../types/misc.js'
16
+ import type { OneOf, RequiredBy } from '../../../types/utils.js'
17
+ import { getAction } from '../../../utils/getAction.js'
18
+ import { toPrefixedMessage } from '../../../utils/signature/toPrefixedMessage.js'
19
+ import type { GetVerifierParameter } from '../types.js'
20
+
21
+ export type SignMessageParameters<
22
+ account extends Account | undefined = Account | undefined,
23
+ accountOverride extends Account | undefined = Account | undefined,
24
+ verifier extends Address | undefined = Address | undefined,
25
+ > = Pick<GetEip712DomainParameters, 'factory' | 'factoryData'> &
26
+ GetAccountParameter<account, accountOverride> & {
27
+ message: SignableMessage
28
+ } & OneOf<
29
+ | {
30
+ verifierDomain: RequiredBy<
31
+ TypedDataDomain,
32
+ 'chainId' | 'name' | 'verifyingContract' | 'version'
33
+ >
34
+ verifier?: undefined
35
+ }
36
+ | (GetVerifierParameter<verifier> & {
37
+ verifierDomain?:
38
+ | RequiredBy<
39
+ TypedDataDomain,
40
+ 'chainId' | 'name' | 'verifyingContract' | 'version'
41
+ >
42
+ | undefined
43
+ })
44
+ >
45
+
46
+ export type SignMessageReturnType = Hex
47
+
48
+ export type SignMessageErrorType = ErrorType
49
+
50
+ /**
51
+ * Signs a [EIP-191](https://eips.ethereum.org/EIPS/eip-191) personal sign message via Solady's [ERC1271 `PersonalSign` format](https://github.com/Vectorized/solady/blob/678c9163550810b08f0ffb09624c9f7532392303/src/accounts/ERC1271.sol#L154-L166).
52
+ *
53
+ * This Action is suitable to sign messages for Smart Accounts that implement (or conform to) Solady's [ERC1271.sol](https://github.com/Vectorized/solady/blob/main/src/accounts/ERC1271.sol).
54
+ *
55
+ * - Docs: https://viem.sh/experimental/solady/signMessage
56
+ *
57
+ * With the calculated signature, you can:
58
+ * - use [`verifyMessage`](https://viem.sh/docs/utilities/verifyMessage) to verify the signature,
59
+ *
60
+ * @param client - Client to use
61
+ * @param parameters - {@link SignMessageParameters}
62
+ * @returns The signed message. {@link SignMessageReturnType}
63
+ *
64
+ * @example
65
+ * import { createWalletClient, custom } from 'viem'
66
+ * import { mainnet } from 'viem/chains'
67
+ * import { signMessage } from 'viem/experimental/solady'
68
+ *
69
+ * const client = createWalletClient({
70
+ * chain: mainnet,
71
+ * transport: custom(window.ethereum),
72
+ * })
73
+ *
74
+ * const signature = await signMessage(client, {
75
+ * account: '0xE8Df82fA4E10e6A12a9Dab552bceA2acd26De9bb',
76
+ * message: 'hello world',
77
+ * verifier: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
78
+ * })
79
+ *
80
+ * @example
81
+ * // Account Hoisting
82
+ * import { createWalletClient, custom } from 'viem'
83
+ * import { privateKeyToAccount } from 'viem/accounts'
84
+ * import { mainnet } from 'viem/chains'
85
+ * import { signMessage } from 'viem/experimental/solady'
86
+ *
87
+ * const client = createWalletClient({
88
+ * account: '0xE8Df82fA4E10e6A12a9Dab552bceA2acd26De9bb',
89
+ * chain: mainnet,
90
+ * transport: custom(window.ethereum),
91
+ * })
92
+ *
93
+ * const signature = await signMessage(client, {
94
+ * message: 'hello world',
95
+ * verifier: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
96
+ * })
97
+ */
98
+ export async function signMessage<
99
+ chain extends Chain | undefined,
100
+ account extends Account | undefined,
101
+ accountOverride extends Account | undefined = undefined,
102
+ >(
103
+ client: Client<Transport, chain, account>,
104
+ parameters: SignMessageParameters<account, accountOverride>,
105
+ ): Promise<SignMessageReturnType> {
106
+ const {
107
+ account: account_ = client.account,
108
+ factory,
109
+ factoryData,
110
+ message,
111
+ verifier,
112
+ } = parameters
113
+
114
+ if (!account_)
115
+ throw new AccountNotFoundError({
116
+ docsPath: '/experimental/solady/signMessage',
117
+ })
118
+ const account = parseAccount(account_)
119
+
120
+ const domain = await (async () => {
121
+ if (parameters.verifierDomain) return parameters.verifierDomain
122
+ const {
123
+ domain: { salt, ...domain },
124
+ } = await getAction(
125
+ client,
126
+ getEip712Domain,
127
+ 'getEip712Domain',
128
+ )({
129
+ address: verifier!,
130
+ factory,
131
+ factoryData,
132
+ })
133
+ return domain
134
+ })()
135
+
136
+ return getAction(
137
+ client,
138
+ signTypedData,
139
+ 'signTypedData',
140
+ )({
141
+ account,
142
+ domain,
143
+ types: {
144
+ PersonalSign: [{ name: 'prefixed', type: 'bytes' }],
145
+ },
146
+ primaryType: 'PersonalSign',
147
+ message: {
148
+ prefixed: toPrefixedMessage(message),
149
+ },
150
+ })
151
+ }
@@ -0,0 +1,280 @@
1
+ import type { Address, TypedData, TypedDataDomain } from 'abitype'
2
+
3
+ import type { Account } from '../../../accounts/types.js'
4
+ import { parseAccount } from '../../../accounts/utils/parseAccount.js'
5
+ import {
6
+ type GetEip712DomainParameters,
7
+ getEip712Domain,
8
+ } from '../../../actions/public/getEip712Domain.js'
9
+ import { signTypedData as signTypedData_ } from '../../../actions/wallet/signTypedData.js'
10
+ import type { Client } from '../../../clients/createClient.js'
11
+ import type { Transport } from '../../../clients/transports/createTransport.js'
12
+ import { AccountNotFoundError } from '../../../errors/account.js'
13
+ import type { ErrorType } from '../../../errors/utils.js'
14
+ import type { GetAccountParameter } from '../../../types/account.js'
15
+ import type { Chain } from '../../../types/chain.js'
16
+ import type { Hex } from '../../../types/misc.js'
17
+ import type { TypedDataDefinition } from '../../../types/typedData.js'
18
+ import type { OneOf, RequiredBy } from '../../../types/utils.js'
19
+ import { encodePacked } from '../../../utils/abi/encodePacked.js'
20
+ import { size } from '../../../utils/data/size.js'
21
+ import { stringToHex } from '../../../utils/encoding/toHex.js'
22
+ import { getAction } from '../../../utils/getAction.js'
23
+ import {
24
+ encodeType,
25
+ hashStruct,
26
+ } from '../../../utils/signature/hashTypedData.js'
27
+ import { getTypesForEIP712Domain } from '../../../utils/typedData.js'
28
+ import type { GetVerifierParameter } from '../types.js'
29
+
30
+ export type SignTypedDataParameters<
31
+ typedData extends TypedData | Record<string, unknown> = TypedData,
32
+ primaryType extends keyof typedData | 'EIP712Domain' = keyof typedData,
33
+ account extends Account | undefined = undefined,
34
+ accountOverride extends Account | undefined = undefined,
35
+ verifier extends Address | undefined = Address | undefined,
36
+ ///
37
+ primaryTypes = typedData extends TypedData ? keyof typedData : string,
38
+ > = TypedDataDefinition<typedData, primaryType, primaryTypes> &
39
+ Pick<GetEip712DomainParameters, 'factory' | 'factoryData'> &
40
+ GetAccountParameter<account, accountOverride> &
41
+ OneOf<
42
+ | {
43
+ verifierDomain: RequiredBy<
44
+ TypedDataDomain,
45
+ 'chainId' | 'name' | 'verifyingContract' | 'salt' | 'version'
46
+ >
47
+ fields: Hex
48
+ extensions: readonly bigint[]
49
+ verifier?: undefined
50
+ }
51
+ | (GetVerifierParameter<verifier> & {
52
+ verifierDomain?:
53
+ | RequiredBy<
54
+ TypedDataDomain,
55
+ 'chainId' | 'name' | 'verifyingContract' | 'salt' | 'version'
56
+ >
57
+ | undefined
58
+ fields?: Hex | undefined
59
+ extensions?: readonly bigint[] | undefined
60
+ })
61
+ >
62
+
63
+ export type SignTypedDataReturnType = Hex
64
+
65
+ export type SignTypedDataErrorType = ErrorType
66
+
67
+ /**
68
+ * Signs an [EIP-712](https://eips.ethereum.org/EIPS/eip-712) typed data message via Solady's [ERC1271 `TypedDataSign` format](https://github.com/Vectorized/solady/blob/678c9163550810b08f0ffb09624c9f7532392303/src/accounts/ERC1271.sol#L130-L151).
69
+ *
70
+ * This Action is suitable to sign messages for Smart Accounts that implement (or conform to) Solady's [ERC1271.sol](https://github.com/Vectorized/solady/blob/main/src/accounts/ERC1271.sol).
71
+ *
72
+ * - Docs: https://viem.sh/experimental/solady/signTypedData
73
+ *
74
+ * @param client - Client to use
75
+ * @param parameters - {@link SignTypedDataParameters}
76
+ * @returns The signed data. {@link SignTypedDataReturnType}
77
+ *
78
+ * @example
79
+ * import { createWalletClient, custom } from 'viem'
80
+ * import { mainnet } from 'viem/chains'
81
+ * import { signTypedData } from 'viem/experimental/solady'
82
+ *
83
+ * const client = createWalletClient({
84
+ * chain: mainnet,
85
+ * transport: custom(window.ethereum),
86
+ * })
87
+ * const signature = await signTypedData(client, {
88
+ * account: '0xE8Df82fA4E10e6A12a9Dab552bceA2acd26De9bb',
89
+ * domain: {
90
+ * name: 'Ether Mail',
91
+ * version: '1',
92
+ * chainId: 1,
93
+ * verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
94
+ * },
95
+ * types: {
96
+ * Person: [
97
+ * { name: 'name', type: 'string' },
98
+ * { name: 'wallet', type: 'address' },
99
+ * ],
100
+ * Mail: [
101
+ * { name: 'from', type: 'Person' },
102
+ * { name: 'to', type: 'Person' },
103
+ * { name: 'contents', type: 'string' },
104
+ * ],
105
+ * },
106
+ * primaryType: 'Mail',
107
+ * message: {
108
+ * from: {
109
+ * name: 'Cow',
110
+ * wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
111
+ * },
112
+ * to: {
113
+ * name: 'Bob',
114
+ * wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
115
+ * },
116
+ * contents: 'Hello, Bob!',
117
+ * },
118
+ * verifier: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
119
+ * })
120
+ *
121
+ * @example
122
+ * // Account Hoisting
123
+ * import { createWalletClient, http } from 'viem'
124
+ * import { privateKeyToAccount } from 'viem/accounts'
125
+ * import { mainnet } from 'viem/chains'
126
+ * import { signTypedData } from 'viem/experimental/solady'
127
+ *
128
+ * const client = createWalletClient({
129
+ * account: '0xE8Df82fA4E10e6A12a9Dab552bceA2acd26De9bb'
130
+ * chain: mainnet,
131
+ * transport: http(),
132
+ * })
133
+ * const signature = await signTypedData(client, {
134
+ * domain: {
135
+ * name: 'Ether Mail',
136
+ * version: '1',
137
+ * chainId: 1,
138
+ * verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
139
+ * },
140
+ * types: {
141
+ * Person: [
142
+ * { name: 'name', type: 'string' },
143
+ * { name: 'wallet', type: 'address' },
144
+ * ],
145
+ * Mail: [
146
+ * { name: 'from', type: 'Person' },
147
+ * { name: 'to', type: 'Person' },
148
+ * { name: 'contents', type: 'string' },
149
+ * ],
150
+ * },
151
+ * primaryType: 'Mail',
152
+ * message: {
153
+ * from: {
154
+ * name: 'Cow',
155
+ * wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
156
+ * },
157
+ * to: {
158
+ * name: 'Bob',
159
+ * wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
160
+ * },
161
+ * contents: 'Hello, Bob!',
162
+ * },
163
+ * verifier: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
164
+ * })
165
+ */
166
+ export async function signTypedData<
167
+ const typedData extends TypedData | Record<string, unknown>,
168
+ primaryType extends keyof typedData | 'EIP712Domain',
169
+ chain extends Chain | undefined,
170
+ account extends Account | undefined,
171
+ accountOverride extends Account | undefined = undefined,
172
+ >(
173
+ client: Client<Transport, chain, account>,
174
+ parameters: SignTypedDataParameters<
175
+ typedData,
176
+ primaryType,
177
+ account,
178
+ accountOverride
179
+ >,
180
+ ): Promise<SignTypedDataReturnType> {
181
+ const {
182
+ account: account_ = client.account,
183
+ domain,
184
+ factory,
185
+ factoryData,
186
+ message,
187
+ primaryType,
188
+ types,
189
+ verifier,
190
+ } = parameters as unknown as SignTypedDataParameters
191
+
192
+ if (!account_)
193
+ throw new AccountNotFoundError({
194
+ docsPath: '/experimental/solady/signTypedData',
195
+ })
196
+ const account = parseAccount(account_!)
197
+
198
+ // Retrieve account EIP712 domain.
199
+ const {
200
+ domain: verifierDomain,
201
+ fields,
202
+ extensions,
203
+ } = await (async () => {
204
+ if (parameters.verifierDomain && parameters.fields && parameters.extensions)
205
+ return {
206
+ domain: parameters.verifierDomain,
207
+ fields: parameters.fields,
208
+ extensions: parameters.extensions,
209
+ }
210
+ return getAction(
211
+ client,
212
+ getEip712Domain,
213
+ 'getEip712Domain',
214
+ )({
215
+ address: verifier!,
216
+ factory,
217
+ factoryData,
218
+ })
219
+ })()
220
+
221
+ // Sign with typed data wrapper.
222
+ const signature = await getAction(
223
+ client,
224
+ signTypedData_,
225
+ 'signTypedData',
226
+ )({
227
+ account,
228
+ domain,
229
+ types: {
230
+ ...types,
231
+ TypedDataSign: [
232
+ { name: 'contents', type: primaryType },
233
+ { name: 'fields', type: 'bytes1' },
234
+ { name: 'name', type: 'string' },
235
+ { name: 'version', type: 'string' },
236
+ { name: 'chainId', type: 'uint256' },
237
+ { name: 'verifyingContract', type: 'address' },
238
+ { name: 'salt', type: 'bytes32' },
239
+ { name: 'extensions', type: 'uint256[]' },
240
+ ],
241
+ },
242
+ primaryType: 'TypedDataSign',
243
+ message: {
244
+ contents: message as any,
245
+ fields,
246
+ extensions,
247
+ ...(verifierDomain as any),
248
+ },
249
+ })
250
+
251
+ // Compute dependencies for wrapped signature.
252
+ const hashedDomain = hashStruct({
253
+ data: domain ?? {},
254
+ types: {
255
+ EIP712Domain: getTypesForEIP712Domain({ domain }),
256
+ },
257
+ primaryType: 'EIP712Domain',
258
+ })
259
+ const hashedContents = hashStruct({
260
+ data: message,
261
+ types: types as any,
262
+ primaryType,
263
+ })
264
+ const encodedType = encodeType({
265
+ primaryType,
266
+ types: types as any,
267
+ })
268
+
269
+ // Construct wrapped signature.
270
+ return encodePacked(
271
+ ['bytes', 'bytes32', 'bytes32', 'bytes', 'uint16'],
272
+ [
273
+ signature,
274
+ hashedDomain,
275
+ hashedContents,
276
+ stringToHex(encodedType),
277
+ size(stringToHex(encodedType)),
278
+ ],
279
+ )
280
+ }