quantumcoin 6.14.2 → 6.14.5

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 (317) hide show
  1. package/CHANGELOG.md +442 -442
  2. package/FUNDING.json +10 -10
  3. package/LICENSE.md +21 -21
  4. package/README.md +132 -142
  5. package/SECURITY.md +34 -34
  6. package/dist/README.md +22 -22
  7. package/dist/quantumcoin.js +1127 -1324
  8. package/dist/quantumcoin.js.map +1 -1
  9. package/dist/quantumcoin.min.js +1 -1
  10. package/dist/quantumcoin.umd.js +1128 -1327
  11. package/dist/quantumcoin.umd.js.map +1 -1
  12. package/dist/quantumcoin.umd.min.js +1 -1
  13. package/dist/wordlists-extra.js +1 -1
  14. package/dist/wordlists-extra.js.map +1 -1
  15. package/dist/wordlists-extra.min.js +1 -1
  16. package/lib.commonjs/README.md +16 -16
  17. package/lib.commonjs/_version.js +1 -1
  18. package/lib.commonjs/crypto/signature.d.ts +3 -76
  19. package/lib.commonjs/crypto/signature.d.ts.map +1 -1
  20. package/lib.commonjs/crypto/signature.js +15 -199
  21. package/lib.commonjs/crypto/signature.js.map +1 -1
  22. package/lib.commonjs/crypto/signing-key.d.ts +1 -1
  23. package/lib.commonjs/crypto/signing-key.d.ts.map +1 -1
  24. package/lib.commonjs/crypto/signing-key.js +19 -10
  25. package/lib.commonjs/crypto/signing-key.js.map +1 -1
  26. package/lib.commonjs/package.json +12 -12
  27. package/lib.commonjs/providers/provider-jsonrpc.d.ts +0 -1
  28. package/lib.commonjs/providers/provider-jsonrpc.d.ts.map +1 -1
  29. package/lib.commonjs/providers/provider-jsonrpc.js +0 -1
  30. package/lib.commonjs/providers/provider-jsonrpc.js.map +1 -1
  31. package/lib.commonjs/quantumcoin.d.ts +2 -0
  32. package/lib.commonjs/quantumcoin.d.ts.map +1 -1
  33. package/lib.commonjs/quantumcoin.js +11 -5
  34. package/lib.commonjs/quantumcoin.js.map +1 -1
  35. package/lib.commonjs/transaction/address.d.ts.map +1 -1
  36. package/lib.commonjs/transaction/address.js +8 -3
  37. package/lib.commonjs/transaction/address.js.map +1 -1
  38. package/lib.commonjs/transaction/transaction.d.ts.map +1 -1
  39. package/lib.commonjs/transaction/transaction.js +7 -40
  40. package/lib.commonjs/transaction/transaction.js.map +1 -1
  41. package/lib.commonjs/wallet/json-keystore.d.ts.map +1 -1
  42. package/lib.commonjs/wallet/json-keystore.js +7 -7
  43. package/lib.commonjs/wallet/json-keystore.js.map +1 -1
  44. package/lib.commonjs/wallet/wallet.d.ts.map +1 -1
  45. package/lib.commonjs/wallet/wallet.js +2 -2
  46. package/lib.commonjs/wallet/wallet.js.map +1 -1
  47. package/lib.esm/README.md +16 -16
  48. package/lib.esm/_version.js +1 -1
  49. package/lib.esm/crypto/signature.d.ts +3 -76
  50. package/lib.esm/crypto/signature.d.ts.map +1 -1
  51. package/lib.esm/crypto/signature.js +16 -202
  52. package/lib.esm/crypto/signature.js.map +1 -1
  53. package/lib.esm/crypto/signing-key.d.ts +1 -1
  54. package/lib.esm/crypto/signing-key.d.ts.map +1 -1
  55. package/lib.esm/crypto/signing-key.js +20 -9
  56. package/lib.esm/crypto/signing-key.js.map +1 -1
  57. package/lib.esm/package.json +12 -12
  58. package/lib.esm/providers/provider-jsonrpc.d.ts +0 -1
  59. package/lib.esm/providers/provider-jsonrpc.d.ts.map +1 -1
  60. package/lib.esm/providers/provider-jsonrpc.js +0 -1
  61. package/lib.esm/providers/provider-jsonrpc.js.map +1 -1
  62. package/lib.esm/quantumcoin.d.ts +2 -0
  63. package/lib.esm/quantumcoin.d.ts.map +1 -1
  64. package/lib.esm/quantumcoin.js +6 -0
  65. package/lib.esm/quantumcoin.js.map +1 -1
  66. package/lib.esm/transaction/address.d.ts.map +1 -1
  67. package/lib.esm/transaction/address.js +8 -2
  68. package/lib.esm/transaction/address.js.map +1 -1
  69. package/lib.esm/transaction/transaction.d.ts.map +1 -1
  70. package/lib.esm/transaction/transaction.js +7 -40
  71. package/lib.esm/transaction/transaction.js.map +1 -1
  72. package/lib.esm/wallet/json-keystore.d.ts.map +1 -1
  73. package/lib.esm/wallet/json-keystore.js +11 -5
  74. package/lib.esm/wallet/json-keystore.js.map +1 -1
  75. package/lib.esm/wallet/wallet.d.ts.map +1 -1
  76. package/lib.esm/wallet/wallet.js +3 -1
  77. package/lib.esm/wallet/wallet.js.map +1 -1
  78. package/package.json +6 -5
  79. package/rollup.config.mjs +50 -50
  80. package/src.ts/_version.ts +1 -1
  81. package/src.ts/abi/abi-coder.ts +237 -237
  82. package/src.ts/abi/bytes32.ts +45 -45
  83. package/src.ts/abi/coders/abstract-coder.ts +541 -541
  84. package/src.ts/abi/coders/address.ts +36 -36
  85. package/src.ts/abi/coders/anonymous.ts +29 -29
  86. package/src.ts/abi/coders/array.ts +199 -199
  87. package/src.ts/abi/coders/boolean.ts +27 -27
  88. package/src.ts/abi/coders/bytes.ts +43 -43
  89. package/src.ts/abi/coders/fixed-bytes.ts +37 -37
  90. package/src.ts/abi/coders/null.ts +28 -28
  91. package/src.ts/abi/coders/number.ts +63 -63
  92. package/src.ts/abi/coders/string.ts +29 -29
  93. package/src.ts/abi/coders/tuple.ts +69 -69
  94. package/src.ts/abi/fragments.ts +1617 -1617
  95. package/src.ts/abi/index.ts +41 -41
  96. package/src.ts/abi/interface.ts +1271 -1271
  97. package/src.ts/abi/typed.ts +796 -796
  98. package/src.ts/address/address.ts +148 -148
  99. package/src.ts/address/checks.ts +123 -123
  100. package/src.ts/address/contract-address.ts +80 -80
  101. package/src.ts/address/index.ts +57 -57
  102. package/src.ts/constants/addresses.ts +8 -8
  103. package/src.ts/constants/hashes.ts +7 -7
  104. package/src.ts/constants/index.ts +16 -16
  105. package/src.ts/constants/numbers.ts +35 -35
  106. package/src.ts/constants/strings.ts +16 -16
  107. package/src.ts/contract/contract.ts +1120 -1120
  108. package/src.ts/contract/factory.ts +143 -143
  109. package/src.ts/contract/index.ts +31 -31
  110. package/src.ts/contract/types.ts +236 -236
  111. package/src.ts/contract/wrappers.ts +225 -225
  112. package/src.ts/crypto/crypto-browser.ts +64 -64
  113. package/src.ts/crypto/crypto.ts +4 -4
  114. package/src.ts/crypto/hmac.ts +51 -51
  115. package/src.ts/crypto/index.ts +59 -59
  116. package/src.ts/crypto/keccak.ts +54 -54
  117. package/src.ts/crypto/pbkdf2.ts +55 -55
  118. package/src.ts/crypto/random.ts +36 -36
  119. package/src.ts/crypto/ripemd160.ts +43 -43
  120. package/src.ts/crypto/scrypt.ts +114 -114
  121. package/src.ts/crypto/sha2.ts +78 -78
  122. package/src.ts/crypto/signature.ts +145 -349
  123. package/src.ts/crypto/signing-key.ts +126 -118
  124. package/src.ts/hash/authorization.ts +38 -38
  125. package/src.ts/hash/id.ts +17 -17
  126. package/src.ts/hash/index.ts +18 -18
  127. package/src.ts/hash/message.ts +51 -51
  128. package/src.ts/hash/namehash.ts +101 -101
  129. package/src.ts/hash/solidity.ts +117 -117
  130. package/src.ts/hash/typed-data.ts +658 -658
  131. package/src.ts/index.ts +12 -12
  132. package/src.ts/providers/abstract-provider.ts +1761 -1761
  133. package/src.ts/providers/abstract-signer.ts +314 -314
  134. package/src.ts/providers/community.ts +49 -49
  135. package/src.ts/providers/contracts.ts +42 -42
  136. package/src.ts/providers/default-provider.ts +96 -96
  137. package/src.ts/providers/ens-resolver.ts +606 -606
  138. package/src.ts/providers/format.ts +320 -320
  139. package/src.ts/providers/formatting.ts +418 -418
  140. package/src.ts/providers/index.ts +125 -125
  141. package/src.ts/providers/network.ts +327 -327
  142. package/src.ts/providers/pagination.ts +8 -8
  143. package/src.ts/providers/plugin-fallback.ts +35 -35
  144. package/src.ts/providers/plugins-network.ts +281 -281
  145. package/src.ts/providers/provider-browser.ts +334 -334
  146. package/src.ts/providers/provider-fallback.ts +801 -801
  147. package/src.ts/providers/provider-ipcsocket-browser.ts +3 -3
  148. package/src.ts/providers/provider-ipcsocket.ts +81 -81
  149. package/src.ts/providers/provider-jsonrpc.ts +1334 -1335
  150. package/src.ts/providers/provider-socket.ts +352 -352
  151. package/src.ts/providers/provider-websocket.ts +103 -103
  152. package/src.ts/providers/provider.ts +2136 -2136
  153. package/src.ts/providers/signer-noncemanager.ts +98 -98
  154. package/src.ts/providers/signer.ts +166 -166
  155. package/src.ts/providers/subscriber-connection.ts +74 -74
  156. package/src.ts/providers/subscriber-filterid.ts +199 -199
  157. package/src.ts/providers/subscriber-polling.ts +321 -321
  158. package/src.ts/providers/ws-browser.ts +11 -11
  159. package/src.ts/providers/ws.ts +3 -3
  160. package/src.ts/quantumcoin.ts +219 -211
  161. package/src.ts/thirdparty.d.ts +16 -16
  162. package/src.ts/transaction/accesslist.ts +43 -43
  163. package/src.ts/transaction/address.ts +35 -31
  164. package/src.ts/transaction/authorization.ts +14 -14
  165. package/src.ts/transaction/index.ts +51 -51
  166. package/src.ts/transaction/transaction.ts +1349 -1379
  167. package/src.ts/utils/base58.ts +73 -73
  168. package/src.ts/utils/base64-browser.ts +25 -25
  169. package/src.ts/utils/base64.ts +56 -56
  170. package/src.ts/utils/data.ts +199 -199
  171. package/src.ts/utils/errors.ts +793 -793
  172. package/src.ts/utils/events.ts +105 -105
  173. package/src.ts/utils/fetch.ts +970 -970
  174. package/src.ts/utils/fixednumber.ts +643 -643
  175. package/src.ts/utils/geturl-browser.ts +81 -81
  176. package/src.ts/utils/geturl.ts +134 -134
  177. package/src.ts/utils/index.ts +95 -95
  178. package/src.ts/utils/maths.ts +240 -240
  179. package/src.ts/utils/properties.ts +60 -60
  180. package/src.ts/utils/rlp-decode.ts +104 -104
  181. package/src.ts/utils/rlp-encode.ts +64 -64
  182. package/src.ts/utils/rlp.ts +20 -20
  183. package/src.ts/utils/units.ts +91 -91
  184. package/src.ts/utils/utf8.ts +325 -325
  185. package/src.ts/utils/uuid.ts +36 -36
  186. package/src.ts/wallet/base-wallet.ts +160 -160
  187. package/src.ts/wallet/index.ts +32 -32
  188. package/src.ts/wallet/json-keystore.ts +108 -106
  189. package/src.ts/wallet/utils.ts +147 -147
  190. package/src.ts/wallet/wallet.ts +138 -139
  191. package/src.ts/wordlists/bit-reader.ts +35 -35
  192. package/src.ts/wordlists/decode-owl.ts +58 -58
  193. package/src.ts/wordlists/decode-owla.ts +33 -33
  194. package/src.ts/wordlists/generation/encode-latin.ts +370 -370
  195. package/src.ts/wordlists/index.ts +26 -26
  196. package/src.ts/wordlists/lang-cz.ts +33 -33
  197. package/src.ts/wordlists/lang-en.ts +33 -33
  198. package/src.ts/wordlists/lang-es.ts +35 -35
  199. package/src.ts/wordlists/lang-fr.ts +34 -34
  200. package/src.ts/wordlists/lang-it.ts +33 -33
  201. package/src.ts/wordlists/lang-ja.ts +181 -181
  202. package/src.ts/wordlists/lang-ko.ts +104 -104
  203. package/src.ts/wordlists/lang-pt.ts +34 -34
  204. package/src.ts/wordlists/lang-zh.ts +112 -112
  205. package/src.ts/wordlists/wordlist-owl.ts +77 -77
  206. package/src.ts/wordlists/wordlist-owla.ts +41 -41
  207. package/src.ts/wordlists/wordlist.ts +59 -59
  208. package/src.ts/wordlists/wordlists-browser.ts +8 -8
  209. package/src.ts/wordlists/wordlists-extra.ts +9 -9
  210. package/src.ts/wordlists/wordlists.ts +38 -38
  211. package/dist/quantumcoin.min.js'.gz' +0 -0
  212. package/dist/quantumcoin.umd.min.js'.gz' +0 -0
  213. package/dist/wordlists-extra.min.js'.gz' +0 -0
  214. package/lib.commonjs/providers/provider-alchemy.d.ts +0 -50
  215. package/lib.commonjs/providers/provider-alchemy.d.ts.map +0 -1
  216. package/lib.commonjs/providers/provider-alchemy.js +0 -151
  217. package/lib.commonjs/providers/provider-alchemy.js.map +0 -1
  218. package/lib.commonjs/providers/provider-ankr.d.ts +0 -61
  219. package/lib.commonjs/providers/provider-ankr.d.ts.map +0 -1
  220. package/lib.commonjs/providers/provider-ankr.js +0 -137
  221. package/lib.commonjs/providers/provider-ankr.js.map +0 -1
  222. package/lib.commonjs/providers/provider-blockscout.d.ts +0 -59
  223. package/lib.commonjs/providers/provider-blockscout.d.ts.map +0 -1
  224. package/lib.commonjs/providers/provider-blockscout.js +0 -145
  225. package/lib.commonjs/providers/provider-blockscout.js.map +0 -1
  226. package/lib.commonjs/providers/provider-chainstack.d.ts +0 -46
  227. package/lib.commonjs/providers/provider-chainstack.d.ts.map +0 -1
  228. package/lib.commonjs/providers/provider-chainstack.js +0 -102
  229. package/lib.commonjs/providers/provider-chainstack.js.map +0 -1
  230. package/lib.commonjs/providers/provider-cloudflare.d.ts +0 -14
  231. package/lib.commonjs/providers/provider-cloudflare.d.ts.map +0 -1
  232. package/lib.commonjs/providers/provider-cloudflare.js +0 -26
  233. package/lib.commonjs/providers/provider-cloudflare.js.map +0 -1
  234. package/lib.commonjs/providers/provider-etherscan.d.ts +0 -147
  235. package/lib.commonjs/providers/provider-etherscan.d.ts.map +0 -1
  236. package/lib.commonjs/providers/provider-etherscan.js +0 -587
  237. package/lib.commonjs/providers/provider-etherscan.js.map +0 -1
  238. package/lib.commonjs/providers/provider-infura.d.ts +0 -101
  239. package/lib.commonjs/providers/provider-infura.d.ts.map +0 -1
  240. package/lib.commonjs/providers/provider-infura.js +0 -206
  241. package/lib.commonjs/providers/provider-infura.js.map +0 -1
  242. package/lib.commonjs/providers/provider-pocket.d.ts +0 -54
  243. package/lib.commonjs/providers/provider-pocket.d.ts.map +0 -1
  244. package/lib.commonjs/providers/provider-pocket.js +0 -109
  245. package/lib.commonjs/providers/provider-pocket.js.map +0 -1
  246. package/lib.commonjs/providers/provider-quicknode.d.ts +0 -59
  247. package/lib.commonjs/providers/provider-quicknode.d.ts.map +0 -1
  248. package/lib.commonjs/providers/provider-quicknode.js +0 -163
  249. package/lib.commonjs/providers/provider-quicknode.js.map +0 -1
  250. package/lib.commonjs/wallet/hdwallet.d.ts +0 -248
  251. package/lib.commonjs/wallet/hdwallet.d.ts.map +0 -1
  252. package/lib.commonjs/wallet/hdwallet.js +0 -505
  253. package/lib.commonjs/wallet/hdwallet.js.map +0 -1
  254. package/lib.commonjs/wallet/json-crowdsale.d.ts +0 -27
  255. package/lib.commonjs/wallet/json-crowdsale.d.ts.map +0 -1
  256. package/lib.commonjs/wallet/json-crowdsale.js +0 -60
  257. package/lib.commonjs/wallet/json-crowdsale.js.map +0 -1
  258. package/lib.commonjs/wallet/mnemonic.d.ts +0 -65
  259. package/lib.commonjs/wallet/mnemonic.d.ts.map +0 -1
  260. package/lib.commonjs/wallet/mnemonic.js +0 -169
  261. package/lib.commonjs/wallet/mnemonic.js.map +0 -1
  262. package/lib.commonjs/wallet/seedwallet.d.ts +0 -4
  263. package/lib.commonjs/wallet/seedwallet.d.ts.map +0 -1
  264. package/lib.commonjs/wallet/seedwallet.js +0 -8
  265. package/lib.commonjs/wallet/seedwallet.js.map +0 -1
  266. package/lib.esm/providers/provider-alchemy.d.ts +0 -50
  267. package/lib.esm/providers/provider-alchemy.d.ts.map +0 -1
  268. package/lib.esm/providers/provider-alchemy.js +0 -147
  269. package/lib.esm/providers/provider-alchemy.js.map +0 -1
  270. package/lib.esm/providers/provider-ankr.d.ts +0 -61
  271. package/lib.esm/providers/provider-ankr.d.ts.map +0 -1
  272. package/lib.esm/providers/provider-ankr.js +0 -133
  273. package/lib.esm/providers/provider-ankr.js.map +0 -1
  274. package/lib.esm/providers/provider-blockscout.d.ts +0 -59
  275. package/lib.esm/providers/provider-blockscout.d.ts.map +0 -1
  276. package/lib.esm/providers/provider-blockscout.js +0 -141
  277. package/lib.esm/providers/provider-blockscout.js.map +0 -1
  278. package/lib.esm/providers/provider-chainstack.d.ts +0 -46
  279. package/lib.esm/providers/provider-chainstack.d.ts.map +0 -1
  280. package/lib.esm/providers/provider-chainstack.js +0 -98
  281. package/lib.esm/providers/provider-chainstack.js.map +0 -1
  282. package/lib.esm/providers/provider-cloudflare.d.ts +0 -14
  283. package/lib.esm/providers/provider-cloudflare.d.ts.map +0 -1
  284. package/lib.esm/providers/provider-cloudflare.js +0 -22
  285. package/lib.esm/providers/provider-cloudflare.js.map +0 -1
  286. package/lib.esm/providers/provider-etherscan.d.ts +0 -147
  287. package/lib.esm/providers/provider-etherscan.d.ts.map +0 -1
  288. package/lib.esm/providers/provider-etherscan.js +0 -584
  289. package/lib.esm/providers/provider-etherscan.js.map +0 -1
  290. package/lib.esm/providers/provider-infura.d.ts +0 -101
  291. package/lib.esm/providers/provider-infura.d.ts.map +0 -1
  292. package/lib.esm/providers/provider-infura.js +0 -201
  293. package/lib.esm/providers/provider-infura.js.map +0 -1
  294. package/lib.esm/providers/provider-pocket.d.ts +0 -54
  295. package/lib.esm/providers/provider-pocket.d.ts.map +0 -1
  296. package/lib.esm/providers/provider-pocket.js +0 -105
  297. package/lib.esm/providers/provider-pocket.js.map +0 -1
  298. package/lib.esm/providers/provider-quicknode.d.ts +0 -59
  299. package/lib.esm/providers/provider-quicknode.d.ts.map +0 -1
  300. package/lib.esm/providers/provider-quicknode.js +0 -159
  301. package/lib.esm/providers/provider-quicknode.js.map +0 -1
  302. package/lib.esm/wallet/hdwallet.d.ts +0 -248
  303. package/lib.esm/wallet/hdwallet.d.ts.map +0 -1
  304. package/lib.esm/wallet/hdwallet.js +0 -498
  305. package/lib.esm/wallet/hdwallet.js.map +0 -1
  306. package/lib.esm/wallet/json-crowdsale.d.ts +0 -27
  307. package/lib.esm/wallet/json-crowdsale.d.ts.map +0 -1
  308. package/lib.esm/wallet/json-crowdsale.js +0 -55
  309. package/lib.esm/wallet/json-crowdsale.js.map +0 -1
  310. package/lib.esm/wallet/mnemonic.d.ts +0 -65
  311. package/lib.esm/wallet/mnemonic.d.ts.map +0 -1
  312. package/lib.esm/wallet/mnemonic.js +0 -165
  313. package/lib.esm/wallet/mnemonic.js.map +0 -1
  314. package/lib.esm/wallet/seedwallet.d.ts +0 -4
  315. package/lib.esm/wallet/seedwallet.d.ts.map +0 -1
  316. package/lib.esm/wallet/seedwallet.js +0 -4
  317. package/lib.esm/wallet/seedwallet.js.map +0 -1
@@ -1,658 +1,658 @@
1
- //import { TypedDataDomain, TypedDataField } from "@ethersproject/providerabstract-signer";
2
- import { getAddress } from "../address/index.js";
3
- import { keccak256 } from "../crypto/index.js";
4
- import { recoverAddress } from "../transaction/index.js";
5
- import {
6
- concat, defineProperties, getBigInt, getBytes, hexlify, isHexString, mask, toBeHex, toQuantity, toTwos, zeroPadValue,
7
- assertArgument
8
- } from "../utils/index.js";
9
-
10
- import { id } from "./id.js";
11
-
12
- import type { SignatureLike } from "../crypto/index.js";
13
- import type { BigNumberish, BytesLike } from "../utils/index.js";
14
-
15
-
16
- const padding = new Uint8Array(32);
17
- padding.fill(0);
18
-
19
- const BN__1 = BigInt(-1);
20
- const BN_0 = BigInt(0);
21
- const BN_1 = BigInt(1);
22
- const BN_MAX_UINT256 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
23
-
24
- // @TODO: in v7, verifyingContract should be an AddressLike and use resolveAddress
25
-
26
- /**
27
- * The domain for an [[link-eip-712]] payload.
28
- */
29
- export interface TypedDataDomain {
30
- /**
31
- * The human-readable name of the signing domain.
32
- */
33
- name?: null | string;
34
-
35
- /**
36
- * The major version of the signing domain.
37
- */
38
- version?: null | string;
39
-
40
- /**
41
- * The chain ID of the signing domain.
42
- */
43
- chainId?: null | BigNumberish;
44
-
45
- /**
46
- * The the address of the contract that will verify the signature.
47
- */
48
- verifyingContract?: null | string;
49
-
50
- /**
51
- * A salt used for purposes decided by the specific domain.
52
- */
53
- salt?: null | BytesLike;
54
- };
55
-
56
- /**
57
- * A specific field of a structured [[link-eip-712]] type.
58
- */
59
- export interface TypedDataField {
60
- /**
61
- * The field name.
62
- */
63
- name: string;
64
-
65
- /**
66
- * The type of the field.
67
- */
68
- type: string;
69
- };
70
-
71
- function hexPadRight(value: BytesLike): string {
72
- const bytes = getBytes(value);
73
- const padOffset = bytes.length % 32
74
- if (padOffset) {
75
- return concat([ bytes, padding.slice(padOffset) ]);
76
- }
77
- return hexlify(bytes);
78
- }
79
-
80
- const hexTrue = toBeHex(BN_1, 32);
81
- const hexFalse = toBeHex(BN_0, 32);
82
-
83
- const domainFieldTypes: Record<string, string> = {
84
- name: "string",
85
- version: "string",
86
- chainId: "uint256",
87
- verifyingContract: "address",
88
- salt: "bytes32"
89
- };
90
-
91
- const domainFieldNames: Array<string> = [
92
- "name", "version", "chainId", "verifyingContract", "salt"
93
- ];
94
-
95
- function checkString(key: string): (value: any) => string {
96
- return function (value: any){
97
- assertArgument(typeof(value) === "string", `invalid domain value for ${ JSON.stringify(key) }`, `domain.${ key }`, value);
98
- return value;
99
- }
100
- }
101
-
102
- const domainChecks: Record<string, (value: any) => any> = {
103
- name: checkString("name"),
104
- version: checkString("version"),
105
- chainId: function(_value: any) {
106
- const value = getBigInt(_value, "domain.chainId");
107
- assertArgument(value >= 0, "invalid chain ID", "domain.chainId", _value);
108
- if (Number.isSafeInteger(value)) { return Number(value); }
109
- return toQuantity(value);
110
- },
111
- verifyingContract: function(value: any) {
112
- try {
113
- return getAddress(value).toLowerCase();
114
- } catch (error) { }
115
- assertArgument(false, `invalid domain value "verifyingContract"`, "domain.verifyingContract", value);
116
- },
117
- salt: function(value: any) {
118
- const bytes = getBytes(value, "domain.salt");
119
- assertArgument(bytes.length === 32, `invalid domain value "salt"`, "domain.salt", value);
120
- return hexlify(bytes);
121
- }
122
- }
123
-
124
- function getBaseEncoder(type: string): null | ((value: any) => string) {
125
- // intXX and uintXX
126
- {
127
- const match = type.match(/^(u?)int(\d+)$/);
128
- if (match) {
129
- const signed = (match[1] === "");
130
-
131
- const width = parseInt(match[2]);
132
- assertArgument(width % 8 === 0 && width !== 0 && width <= 256 && match[2] === String(width), "invalid numeric width", "type", type);
133
-
134
- const boundsUpper = mask(BN_MAX_UINT256, signed ? (width - 1): width);
135
- const boundsLower = signed ? ((boundsUpper + BN_1) * BN__1): BN_0;
136
-
137
- return function(_value: BigNumberish) {
138
- const value = getBigInt(_value, "value");
139
-
140
- assertArgument(value >= boundsLower && value <= boundsUpper, `value out-of-bounds for ${ type }`, "value", value);
141
-
142
- return toBeHex(signed ? toTwos(value, 256): value, 32);
143
- };
144
- }
145
- }
146
-
147
- // bytesXX
148
- {
149
- const match = type.match(/^bytes(\d+)$/);
150
- if (match) {
151
- const width = parseInt(match[1]);
152
- assertArgument(width !== 0 && width <= 32 && match[1] === String(width), "invalid bytes width", "type", type);
153
-
154
- return function(value: BytesLike) {
155
- const bytes = getBytes(value);
156
- assertArgument(bytes.length === width, `invalid length for ${ type }`, "value", value);
157
- return hexPadRight(value);
158
- };
159
- }
160
- }
161
-
162
- switch (type) {
163
- case "address": return function(value: string) {
164
- return zeroPadValue(getAddress(value), 32);
165
- };
166
- case "bool": return function(value: boolean) {
167
- return ((!value) ? hexFalse: hexTrue);
168
- };
169
- case "bytes": return function(value: BytesLike) {
170
- return keccak256(value);
171
- };
172
- case "string": return function(value: string) {
173
- return id(value);
174
- };
175
- }
176
-
177
- return null;
178
- }
179
-
180
- function encodeType(name: string, fields: Array<TypedDataField>): string {
181
- return `${ name }(${ fields.map(({ name, type }) => (type + " " + name)).join(",") })`;
182
- }
183
-
184
- type ArrayResult = {
185
- base: string; // The base type
186
- index?: string; // the full Index (if any)
187
- array?: { // The Array... (if index)
188
- base: string; // ...base type (same as above)
189
- prefix: string; // ...sans the final Index
190
- count: number; // ...the final Index (-1 for dynamic)
191
- }
192
- };
193
-
194
- // foo[][3] => { base: "foo", index: "[][3]", array: {
195
- // base: "foo", prefix: "foo[]", count: 3 } }
196
- function splitArray(type: string): ArrayResult {
197
- const match = type.match(/^([^\x5b]*)((\x5b\d*\x5d)*)(\x5b(\d*)\x5d)$/);
198
- if (match) {
199
- return {
200
- base: match[1],
201
- index: (match[2] + match[4]),
202
- array: {
203
- base: match[1],
204
- prefix: (match[1] + match[2]),
205
- count: (match[5] ? parseInt(match[5]): -1),
206
- }
207
- };
208
- }
209
-
210
- return { base: type };
211
- }
212
-
213
- /**
214
- * A **TypedDataEncode** prepares and encodes [[link-eip-712]] payloads
215
- * for signed typed data.
216
- *
217
- * This is useful for those that wish to compute various components of a
218
- * typed data hash, primary types, or sub-components, but generally the
219
- * higher level [[Signer-signTypedData]] is more useful.
220
- */
221
- export class TypedDataEncoder {
222
- /**
223
- * The primary type for the structured [[types]].
224
- *
225
- * This is derived automatically from the [[types]], since no
226
- * recursion is possible, once the DAG for the types is consturcted
227
- * internally, the primary type must be the only remaining type with
228
- * no parent nodes.
229
- */
230
- readonly primaryType!: string;
231
-
232
- readonly #types: string;
233
-
234
- /**
235
- * The types.
236
- */
237
- get types(): Record<string, Array<TypedDataField>> {
238
- return JSON.parse(this.#types);
239
- }
240
-
241
- readonly #fullTypes: Map<string, string>
242
-
243
- readonly #encoderCache: Map<string, (value: any) => string>;
244
-
245
- /**
246
- * Create a new **TypedDataEncoder** for %%types%%.
247
- *
248
- * This performs all necessary checking that types are valid and
249
- * do not violate the [[link-eip-712]] structural constraints as
250
- * well as computes the [[primaryType]].
251
- */
252
- constructor(_types: Record<string, Array<TypedDataField>>) {
253
- this.#fullTypes = new Map();
254
- this.#encoderCache = new Map();
255
-
256
- // Link struct types to their direct child structs
257
- const links: Map<string, Set<string>> = new Map();
258
-
259
- // Link structs to structs which contain them as a child
260
- const parents: Map<string, Array<string>> = new Map();
261
-
262
- // Link all subtypes within a given struct
263
- const subtypes: Map<string, Set<string>> = new Map();
264
-
265
- const types: Record<string, Array<TypedDataField>> = { };
266
- Object.keys(_types).forEach((type) => {
267
- types[type] = _types[type].map(({ name, type }) => {
268
-
269
- // Normalize the base type (unless name conflict)
270
- let { base, index } = splitArray(type);
271
- if (base === "int" && !_types["int"]) { base = "int256"; }
272
- if (base === "uint" && !_types["uint"]) { base = "uint256"; }
273
-
274
- return { name, type: (base + (index || "")) };
275
- });
276
-
277
- links.set(type, new Set());
278
- parents.set(type, [ ]);
279
- subtypes.set(type, new Set());
280
- });
281
- this.#types = JSON.stringify(types);
282
-
283
- for (const name in types) {
284
- const uniqueNames: Set<string> = new Set();
285
-
286
- for (const field of types[name]) {
287
-
288
- // Check each field has a unique name
289
- assertArgument(!uniqueNames.has(field.name), `duplicate variable name ${ JSON.stringify(field.name) } in ${ JSON.stringify(name) }`, "types", _types);
290
- uniqueNames.add(field.name);
291
-
292
- // Get the base type (drop any array specifiers)
293
- const baseType = splitArray(field.type).base;
294
- assertArgument(baseType !== name, `circular type reference to ${ JSON.stringify(baseType) }`, "types", _types);
295
-
296
- // Is this a base encoding type?
297
- const encoder = getBaseEncoder(baseType);
298
- if (encoder) { continue; }
299
-
300
- assertArgument(parents.has(baseType), `unknown type ${ JSON.stringify(baseType) }`, "types", _types);
301
-
302
- // Add linkage
303
- (parents.get(baseType) as Array<string>).push(name);
304
- (links.get(name) as Set<string>).add(baseType);
305
- }
306
- }
307
-
308
- // Deduce the primary type
309
- const primaryTypes = Array.from(parents.keys()).filter((n) => ((parents.get(n) as Array<string>).length === 0));
310
- assertArgument(primaryTypes.length !== 0, "missing primary type", "types", _types);
311
- assertArgument(primaryTypes.length === 1, `ambiguous primary types or unused types: ${ primaryTypes.map((t) => (JSON.stringify(t))).join(", ") }`, "types", _types);
312
-
313
- defineProperties<TypedDataEncoder>(this, { primaryType: primaryTypes[0] });
314
-
315
- // Check for circular type references
316
- function checkCircular(type: string, found: Set<string>) {
317
- assertArgument(!found.has(type), `circular type reference to ${ JSON.stringify(type) }`, "types", _types);
318
-
319
- found.add(type);
320
-
321
- for (const child of (links.get(type) as Set<string>)) {
322
- if (!parents.has(child)) { continue; }
323
-
324
- // Recursively check children
325
- checkCircular(child, found);
326
-
327
- // Mark all ancestors as having this decendant
328
- for (const subtype of found) {
329
- (subtypes.get(subtype) as Set<string>).add(child);
330
- }
331
- }
332
-
333
- found.delete(type);
334
- }
335
- checkCircular(this.primaryType, new Set());
336
-
337
- // Compute each fully describe type
338
- for (const [ name, set ] of subtypes) {
339
- const st = Array.from(set);
340
- st.sort();
341
- this.#fullTypes.set(name, encodeType(name, types[name]) + st.map((t) => encodeType(t, types[t])).join(""));
342
- }
343
- }
344
-
345
- /**
346
- * Returnthe encoder for the specific %%type%%.
347
- */
348
- getEncoder(type: string): (value: any) => string {
349
- let encoder = this.#encoderCache.get(type);
350
- if (!encoder) {
351
- encoder = this.#getEncoder(type);
352
- this.#encoderCache.set(type, encoder);
353
- }
354
- return encoder;
355
- }
356
-
357
- #getEncoder(type: string): (value: any) => string {
358
-
359
- // Basic encoder type (address, bool, uint256, etc)
360
- {
361
- const encoder = getBaseEncoder(type);
362
- if (encoder) { return encoder; }
363
- }
364
-
365
- // Array
366
- const array = splitArray(type).array;
367
- if (array) {
368
- const subtype = array.prefix;
369
- const subEncoder = this.getEncoder(subtype);
370
- return (value: Array<any>) => {
371
- assertArgument(array.count === -1 || array.count === value.length, `array length mismatch; expected length ${ array.count }`, "value", value);
372
-
373
- let result = value.map(subEncoder);
374
- if (this.#fullTypes.has(subtype)) {
375
- result = result.map(keccak256);
376
- }
377
-
378
- return keccak256(concat(result));
379
- };
380
- }
381
-
382
- // Struct
383
- const fields = this.types[type];
384
- if (fields) {
385
- const encodedType = id(this.#fullTypes.get(type) as string);
386
- return (value: Record<string, any>) => {
387
- const values = fields.map(({ name, type }) => {
388
- const result = this.getEncoder(type)(value[name]);
389
- if (this.#fullTypes.has(type)) { return keccak256(result); }
390
- return result;
391
- });
392
- values.unshift(encodedType);
393
- return concat(values);
394
- }
395
- }
396
-
397
- assertArgument(false, `unknown type: ${ type }`, "type", type);
398
- }
399
-
400
- /**
401
- * Return the full type for %%name%%.
402
- */
403
- encodeType(name: string): string {
404
- const result = this.#fullTypes.get(name);
405
- assertArgument(result, `unknown type: ${ JSON.stringify(name) }`, "name", name);
406
- return result;
407
- }
408
-
409
- /**
410
- * Return the encoded %%value%% for the %%type%%.
411
- */
412
- encodeData(type: string, value: any): string {
413
- return this.getEncoder(type)(value);
414
- }
415
-
416
- /**
417
- * Returns the hash of %%value%% for the type of %%name%%.
418
- */
419
- hashStruct(name: string, value: Record<string, any>): string {
420
- return keccak256(this.encodeData(name, value));
421
- }
422
-
423
- /**
424
- * Return the fulled encoded %%value%% for the [[types]].
425
- */
426
- encode(value: Record<string, any>): string {
427
- return this.encodeData(this.primaryType, value);
428
- }
429
-
430
- /**
431
- * Return the hash of the fully encoded %%value%% for the [[types]].
432
- */
433
- hash(value: Record<string, any>): string {
434
- return this.hashStruct(this.primaryType, value);
435
- }
436
-
437
- /**
438
- * @_ignore:
439
- */
440
- _visit(type: string, value: any, callback: (type: string, data: any) => any): any {
441
- // Basic encoder type (address, bool, uint256, etc)
442
- {
443
- const encoder = getBaseEncoder(type);
444
- if (encoder) { return callback(type, value); }
445
- }
446
-
447
- // Array
448
- const array = splitArray(type).array;
449
- if (array) {
450
- assertArgument(array.count === -1 || array.count === value.length, `array length mismatch; expected length ${ array.count }`, "value", value);
451
- return value.map((v: any) => this._visit(array.prefix, v, callback));
452
- }
453
-
454
- // Struct
455
- const fields = this.types[type];
456
- if (fields) {
457
- return fields.reduce((accum, { name, type }) => {
458
- accum[name] = this._visit(type, value[name], callback);
459
- return accum;
460
- }, <Record<string, any>>{});
461
- }
462
-
463
- assertArgument(false, `unknown type: ${ type }`, "type", type);
464
- }
465
-
466
- /**
467
- * Call %%calback%% for each value in %%value%%, passing the type and
468
- * component within %%value%%.
469
- *
470
- * This is useful for replacing addresses or other transformation that
471
- * may be desired on each component, based on its type.
472
- */
473
- visit(value: Record<string, any>, callback: (type: string, data: any) => any): any {
474
- return this._visit(this.primaryType, value, callback);
475
- }
476
-
477
- /**
478
- * Create a new **TypedDataEncoder** for %%types%%.
479
- */
480
- static from(types: Record<string, Array<TypedDataField>>): TypedDataEncoder {
481
- return new TypedDataEncoder(types);
482
- }
483
-
484
- /**
485
- * Return the primary type for %%types%%.
486
- */
487
- static getPrimaryType(types: Record<string, Array<TypedDataField>>): string {
488
- return TypedDataEncoder.from(types).primaryType;
489
- }
490
-
491
- /**
492
- * Return the hashed struct for %%value%% using %%types%% and %%name%%.
493
- */
494
- static hashStruct(name: string, types: Record<string, Array<TypedDataField>>, value: Record<string, any>): string {
495
- return TypedDataEncoder.from(types).hashStruct(name, value);
496
- }
497
-
498
- /**
499
- * Return the domain hash for %%domain%%.
500
- */
501
- static hashDomain(domain: TypedDataDomain): string {
502
- const domainFields: Array<TypedDataField> = [ ];
503
- for (const name in domain) {
504
- if ((<Record<string, any>>domain)[name] == null) { continue; }
505
- const type = domainFieldTypes[name];
506
- assertArgument(type, `invalid typed-data domain key: ${ JSON.stringify(name) }`, "domain", domain);
507
- domainFields.push({ name, type });
508
- }
509
-
510
- domainFields.sort((a, b) => {
511
- return domainFieldNames.indexOf(a.name) - domainFieldNames.indexOf(b.name);
512
- });
513
-
514
- return TypedDataEncoder.hashStruct("EIP712Domain", { EIP712Domain: domainFields }, domain);
515
- }
516
-
517
- /**
518
- * Return the fully encoded [[link-eip-712]] %%value%% for %%types%% with %%domain%%.
519
- */
520
- static encode(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, value: Record<string, any>): string {
521
- return concat([
522
- "0x1901",
523
- TypedDataEncoder.hashDomain(domain),
524
- TypedDataEncoder.from(types).hash(value)
525
- ]);
526
- }
527
-
528
- /**
529
- * Return the hash of the fully encoded [[link-eip-712]] %%value%% for %%types%% with %%domain%%.
530
- */
531
- static hash(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, value: Record<string, any>): string {
532
- return keccak256(TypedDataEncoder.encode(domain, types, value));
533
- }
534
-
535
- // Replaces all address types with ENS names with their looked up address
536
- /**
537
- * Resolves to the value from resolving all addresses in %%value%% for
538
- * %%types%% and the %%domain%%.
539
- */
540
- static async resolveNames(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, value: Record<string, any>, resolveName: (name: string) => Promise<string>): Promise<{ domain: TypedDataDomain, value: any }> {
541
- // Make a copy to isolate it from the object passed in
542
- domain = Object.assign({ }, domain);
543
-
544
- // Allow passing null to ignore value
545
- for (const key in domain) {
546
- if ((<Record<string, any>>domain)[key] == null) {
547
- delete (<Record<string, any>>domain)[key];
548
- }
549
- }
550
-
551
- // Look up all ENS names
552
- const ensCache: Record<string, string> = { };
553
-
554
- // Do we need to look up the domain's verifyingContract?
555
- if (domain.verifyingContract && !isHexString(domain.verifyingContract, 20)) {
556
- ensCache[domain.verifyingContract] = "0x";
557
- }
558
-
559
- // We are going to use the encoder to visit all the base values
560
- const encoder = TypedDataEncoder.from(types);
561
-
562
- // Get a list of all the addresses
563
- encoder.visit(value, (type: string, value: any) => {
564
- if (type === "address" && !isHexString(value, 20)) {
565
- ensCache[value] = "0x";
566
- }
567
- return value;
568
- });
569
-
570
- // Lookup each name
571
- for (const name in ensCache) {
572
- ensCache[name] = await resolveName(name);
573
- }
574
-
575
- // Replace the domain verifyingContract if needed
576
- if (domain.verifyingContract && ensCache[domain.verifyingContract]) {
577
- domain.verifyingContract = ensCache[domain.verifyingContract];
578
- }
579
-
580
- // Replace all ENS names with their address
581
- value = encoder.visit(value, (type: string, value: any) => {
582
- if (type === "address" && ensCache[value]) { return ensCache[value]; }
583
- return value;
584
- });
585
-
586
- return { domain, value };
587
- }
588
-
589
- /**
590
- * Returns the JSON-encoded payload expected by nodes which implement
591
- * the JSON-RPC [[link-eip-712]] method.
592
- */
593
- static getPayload(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, value: Record<string, any>): any {
594
- // Validate the domain fields
595
- TypedDataEncoder.hashDomain(domain);
596
-
597
- // Derive the EIP712Domain Struct reference type
598
- const domainValues: Record<string, any> = { };
599
- const domainTypes: Array<{ name: string, type:string }> = [ ];
600
-
601
- domainFieldNames.forEach((name) => {
602
- const value = (<any>domain)[name];
603
- if (value == null) { return; }
604
- domainValues[name] = domainChecks[name](value);
605
- domainTypes.push({ name, type: domainFieldTypes[name] });
606
- });
607
-
608
- const encoder = TypedDataEncoder.from(types);
609
-
610
- // Get the normalized types
611
- types = encoder.types;
612
-
613
- const typesWithDomain = Object.assign({ }, types);
614
- assertArgument(typesWithDomain.EIP712Domain == null, "types must not contain EIP712Domain type", "types.EIP712Domain", types);
615
-
616
- typesWithDomain.EIP712Domain = domainTypes;
617
-
618
- // Validate the data structures and types
619
- encoder.encode(value);
620
-
621
- return {
622
- types: typesWithDomain,
623
- domain: domainValues,
624
- primaryType: encoder.primaryType,
625
- message: encoder.visit(value, (type: string, value: any) => {
626
-
627
- // bytes
628
- if (type.match(/^bytes(\d*)/)) {
629
- return hexlify(getBytes(value));
630
- }
631
-
632
- // uint or int
633
- if (type.match(/^u?int/)) {
634
- return getBigInt(value).toString();
635
- }
636
-
637
- switch (type) {
638
- case "address":
639
- return value.toLowerCase();
640
- case "bool":
641
- return !!value;
642
- case "string":
643
- assertArgument(typeof(value) === "string", "invalid string", "value", value);
644
- return value;
645
- }
646
-
647
- assertArgument(false, "unsupported type", "type", type);
648
- })
649
- };
650
- }
651
- }
652
-
653
- /**
654
- * Compute the address used to sign the typed data for the %%signature%%.
655
- */
656
- export function verifyTypedData(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, value: Record<string, any>, signature: SignatureLike): string {
657
- return recoverAddress(TypedDataEncoder.hash(domain, types, value), signature);
658
- }
1
+ //import { TypedDataDomain, TypedDataField } from "@ethersproject/providerabstract-signer";
2
+ import { getAddress } from "../address/index.js";
3
+ import { keccak256 } from "../crypto/index.js";
4
+ import { recoverAddress } from "../transaction/index.js";
5
+ import {
6
+ concat, defineProperties, getBigInt, getBytes, hexlify, isHexString, mask, toBeHex, toQuantity, toTwos, zeroPadValue,
7
+ assertArgument
8
+ } from "../utils/index.js";
9
+
10
+ import { id } from "./id.js";
11
+
12
+ import type { SignatureLike } from "../crypto/index.js";
13
+ import type { BigNumberish, BytesLike } from "../utils/index.js";
14
+
15
+
16
+ const padding = new Uint8Array(32);
17
+ padding.fill(0);
18
+
19
+ const BN__1 = BigInt(-1);
20
+ const BN_0 = BigInt(0);
21
+ const BN_1 = BigInt(1);
22
+ const BN_MAX_UINT256 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
23
+
24
+ // @TODO: in v7, verifyingContract should be an AddressLike and use resolveAddress
25
+
26
+ /**
27
+ * The domain for an [[link-eip-712]] payload.
28
+ */
29
+ export interface TypedDataDomain {
30
+ /**
31
+ * The human-readable name of the signing domain.
32
+ */
33
+ name?: null | string;
34
+
35
+ /**
36
+ * The major version of the signing domain.
37
+ */
38
+ version?: null | string;
39
+
40
+ /**
41
+ * The chain ID of the signing domain.
42
+ */
43
+ chainId?: null | BigNumberish;
44
+
45
+ /**
46
+ * The the address of the contract that will verify the signature.
47
+ */
48
+ verifyingContract?: null | string;
49
+
50
+ /**
51
+ * A salt used for purposes decided by the specific domain.
52
+ */
53
+ salt?: null | BytesLike;
54
+ };
55
+
56
+ /**
57
+ * A specific field of a structured [[link-eip-712]] type.
58
+ */
59
+ export interface TypedDataField {
60
+ /**
61
+ * The field name.
62
+ */
63
+ name: string;
64
+
65
+ /**
66
+ * The type of the field.
67
+ */
68
+ type: string;
69
+ };
70
+
71
+ function hexPadRight(value: BytesLike): string {
72
+ const bytes = getBytes(value);
73
+ const padOffset = bytes.length % 32
74
+ if (padOffset) {
75
+ return concat([ bytes, padding.slice(padOffset) ]);
76
+ }
77
+ return hexlify(bytes);
78
+ }
79
+
80
+ const hexTrue = toBeHex(BN_1, 32);
81
+ const hexFalse = toBeHex(BN_0, 32);
82
+
83
+ const domainFieldTypes: Record<string, string> = {
84
+ name: "string",
85
+ version: "string",
86
+ chainId: "uint256",
87
+ verifyingContract: "address",
88
+ salt: "bytes32"
89
+ };
90
+
91
+ const domainFieldNames: Array<string> = [
92
+ "name", "version", "chainId", "verifyingContract", "salt"
93
+ ];
94
+
95
+ function checkString(key: string): (value: any) => string {
96
+ return function (value: any){
97
+ assertArgument(typeof(value) === "string", `invalid domain value for ${ JSON.stringify(key) }`, `domain.${ key }`, value);
98
+ return value;
99
+ }
100
+ }
101
+
102
+ const domainChecks: Record<string, (value: any) => any> = {
103
+ name: checkString("name"),
104
+ version: checkString("version"),
105
+ chainId: function(_value: any) {
106
+ const value = getBigInt(_value, "domain.chainId");
107
+ assertArgument(value >= 0, "invalid chain ID", "domain.chainId", _value);
108
+ if (Number.isSafeInteger(value)) { return Number(value); }
109
+ return toQuantity(value);
110
+ },
111
+ verifyingContract: function(value: any) {
112
+ try {
113
+ return getAddress(value).toLowerCase();
114
+ } catch (error) { }
115
+ assertArgument(false, `invalid domain value "verifyingContract"`, "domain.verifyingContract", value);
116
+ },
117
+ salt: function(value: any) {
118
+ const bytes = getBytes(value, "domain.salt");
119
+ assertArgument(bytes.length === 32, `invalid domain value "salt"`, "domain.salt", value);
120
+ return hexlify(bytes);
121
+ }
122
+ }
123
+
124
+ function getBaseEncoder(type: string): null | ((value: any) => string) {
125
+ // intXX and uintXX
126
+ {
127
+ const match = type.match(/^(u?)int(\d+)$/);
128
+ if (match) {
129
+ const signed = (match[1] === "");
130
+
131
+ const width = parseInt(match[2]);
132
+ assertArgument(width % 8 === 0 && width !== 0 && width <= 256 && match[2] === String(width), "invalid numeric width", "type", type);
133
+
134
+ const boundsUpper = mask(BN_MAX_UINT256, signed ? (width - 1): width);
135
+ const boundsLower = signed ? ((boundsUpper + BN_1) * BN__1): BN_0;
136
+
137
+ return function(_value: BigNumberish) {
138
+ const value = getBigInt(_value, "value");
139
+
140
+ assertArgument(value >= boundsLower && value <= boundsUpper, `value out-of-bounds for ${ type }`, "value", value);
141
+
142
+ return toBeHex(signed ? toTwos(value, 256): value, 32);
143
+ };
144
+ }
145
+ }
146
+
147
+ // bytesXX
148
+ {
149
+ const match = type.match(/^bytes(\d+)$/);
150
+ if (match) {
151
+ const width = parseInt(match[1]);
152
+ assertArgument(width !== 0 && width <= 32 && match[1] === String(width), "invalid bytes width", "type", type);
153
+
154
+ return function(value: BytesLike) {
155
+ const bytes = getBytes(value);
156
+ assertArgument(bytes.length === width, `invalid length for ${ type }`, "value", value);
157
+ return hexPadRight(value);
158
+ };
159
+ }
160
+ }
161
+
162
+ switch (type) {
163
+ case "address": return function(value: string) {
164
+ return zeroPadValue(getAddress(value), 32);
165
+ };
166
+ case "bool": return function(value: boolean) {
167
+ return ((!value) ? hexFalse: hexTrue);
168
+ };
169
+ case "bytes": return function(value: BytesLike) {
170
+ return keccak256(value);
171
+ };
172
+ case "string": return function(value: string) {
173
+ return id(value);
174
+ };
175
+ }
176
+
177
+ return null;
178
+ }
179
+
180
+ function encodeType(name: string, fields: Array<TypedDataField>): string {
181
+ return `${ name }(${ fields.map(({ name, type }) => (type + " " + name)).join(",") })`;
182
+ }
183
+
184
+ type ArrayResult = {
185
+ base: string; // The base type
186
+ index?: string; // the full Index (if any)
187
+ array?: { // The Array... (if index)
188
+ base: string; // ...base type (same as above)
189
+ prefix: string; // ...sans the final Index
190
+ count: number; // ...the final Index (-1 for dynamic)
191
+ }
192
+ };
193
+
194
+ // foo[][3] => { base: "foo", index: "[][3]", array: {
195
+ // base: "foo", prefix: "foo[]", count: 3 } }
196
+ function splitArray(type: string): ArrayResult {
197
+ const match = type.match(/^([^\x5b]*)((\x5b\d*\x5d)*)(\x5b(\d*)\x5d)$/);
198
+ if (match) {
199
+ return {
200
+ base: match[1],
201
+ index: (match[2] + match[4]),
202
+ array: {
203
+ base: match[1],
204
+ prefix: (match[1] + match[2]),
205
+ count: (match[5] ? parseInt(match[5]): -1),
206
+ }
207
+ };
208
+ }
209
+
210
+ return { base: type };
211
+ }
212
+
213
+ /**
214
+ * A **TypedDataEncode** prepares and encodes [[link-eip-712]] payloads
215
+ * for signed typed data.
216
+ *
217
+ * This is useful for those that wish to compute various components of a
218
+ * typed data hash, primary types, or sub-components, but generally the
219
+ * higher level [[Signer-signTypedData]] is more useful.
220
+ */
221
+ export class TypedDataEncoder {
222
+ /**
223
+ * The primary type for the structured [[types]].
224
+ *
225
+ * This is derived automatically from the [[types]], since no
226
+ * recursion is possible, once the DAG for the types is consturcted
227
+ * internally, the primary type must be the only remaining type with
228
+ * no parent nodes.
229
+ */
230
+ readonly primaryType!: string;
231
+
232
+ readonly #types: string;
233
+
234
+ /**
235
+ * The types.
236
+ */
237
+ get types(): Record<string, Array<TypedDataField>> {
238
+ return JSON.parse(this.#types);
239
+ }
240
+
241
+ readonly #fullTypes: Map<string, string>
242
+
243
+ readonly #encoderCache: Map<string, (value: any) => string>;
244
+
245
+ /**
246
+ * Create a new **TypedDataEncoder** for %%types%%.
247
+ *
248
+ * This performs all necessary checking that types are valid and
249
+ * do not violate the [[link-eip-712]] structural constraints as
250
+ * well as computes the [[primaryType]].
251
+ */
252
+ constructor(_types: Record<string, Array<TypedDataField>>) {
253
+ this.#fullTypes = new Map();
254
+ this.#encoderCache = new Map();
255
+
256
+ // Link struct types to their direct child structs
257
+ const links: Map<string, Set<string>> = new Map();
258
+
259
+ // Link structs to structs which contain them as a child
260
+ const parents: Map<string, Array<string>> = new Map();
261
+
262
+ // Link all subtypes within a given struct
263
+ const subtypes: Map<string, Set<string>> = new Map();
264
+
265
+ const types: Record<string, Array<TypedDataField>> = { };
266
+ Object.keys(_types).forEach((type) => {
267
+ types[type] = _types[type].map(({ name, type }) => {
268
+
269
+ // Normalize the base type (unless name conflict)
270
+ let { base, index } = splitArray(type);
271
+ if (base === "int" && !_types["int"]) { base = "int256"; }
272
+ if (base === "uint" && !_types["uint"]) { base = "uint256"; }
273
+
274
+ return { name, type: (base + (index || "")) };
275
+ });
276
+
277
+ links.set(type, new Set());
278
+ parents.set(type, [ ]);
279
+ subtypes.set(type, new Set());
280
+ });
281
+ this.#types = JSON.stringify(types);
282
+
283
+ for (const name in types) {
284
+ const uniqueNames: Set<string> = new Set();
285
+
286
+ for (const field of types[name]) {
287
+
288
+ // Check each field has a unique name
289
+ assertArgument(!uniqueNames.has(field.name), `duplicate variable name ${ JSON.stringify(field.name) } in ${ JSON.stringify(name) }`, "types", _types);
290
+ uniqueNames.add(field.name);
291
+
292
+ // Get the base type (drop any array specifiers)
293
+ const baseType = splitArray(field.type).base;
294
+ assertArgument(baseType !== name, `circular type reference to ${ JSON.stringify(baseType) }`, "types", _types);
295
+
296
+ // Is this a base encoding type?
297
+ const encoder = getBaseEncoder(baseType);
298
+ if (encoder) { continue; }
299
+
300
+ assertArgument(parents.has(baseType), `unknown type ${ JSON.stringify(baseType) }`, "types", _types);
301
+
302
+ // Add linkage
303
+ (parents.get(baseType) as Array<string>).push(name);
304
+ (links.get(name) as Set<string>).add(baseType);
305
+ }
306
+ }
307
+
308
+ // Deduce the primary type
309
+ const primaryTypes = Array.from(parents.keys()).filter((n) => ((parents.get(n) as Array<string>).length === 0));
310
+ assertArgument(primaryTypes.length !== 0, "missing primary type", "types", _types);
311
+ assertArgument(primaryTypes.length === 1, `ambiguous primary types or unused types: ${ primaryTypes.map((t) => (JSON.stringify(t))).join(", ") }`, "types", _types);
312
+
313
+ defineProperties<TypedDataEncoder>(this, { primaryType: primaryTypes[0] });
314
+
315
+ // Check for circular type references
316
+ function checkCircular(type: string, found: Set<string>) {
317
+ assertArgument(!found.has(type), `circular type reference to ${ JSON.stringify(type) }`, "types", _types);
318
+
319
+ found.add(type);
320
+
321
+ for (const child of (links.get(type) as Set<string>)) {
322
+ if (!parents.has(child)) { continue; }
323
+
324
+ // Recursively check children
325
+ checkCircular(child, found);
326
+
327
+ // Mark all ancestors as having this decendant
328
+ for (const subtype of found) {
329
+ (subtypes.get(subtype) as Set<string>).add(child);
330
+ }
331
+ }
332
+
333
+ found.delete(type);
334
+ }
335
+ checkCircular(this.primaryType, new Set());
336
+
337
+ // Compute each fully describe type
338
+ for (const [ name, set ] of subtypes) {
339
+ const st = Array.from(set);
340
+ st.sort();
341
+ this.#fullTypes.set(name, encodeType(name, types[name]) + st.map((t) => encodeType(t, types[t])).join(""));
342
+ }
343
+ }
344
+
345
+ /**
346
+ * Returnthe encoder for the specific %%type%%.
347
+ */
348
+ getEncoder(type: string): (value: any) => string {
349
+ let encoder = this.#encoderCache.get(type);
350
+ if (!encoder) {
351
+ encoder = this.#getEncoder(type);
352
+ this.#encoderCache.set(type, encoder);
353
+ }
354
+ return encoder;
355
+ }
356
+
357
+ #getEncoder(type: string): (value: any) => string {
358
+
359
+ // Basic encoder type (address, bool, uint256, etc)
360
+ {
361
+ const encoder = getBaseEncoder(type);
362
+ if (encoder) { return encoder; }
363
+ }
364
+
365
+ // Array
366
+ const array = splitArray(type).array;
367
+ if (array) {
368
+ const subtype = array.prefix;
369
+ const subEncoder = this.getEncoder(subtype);
370
+ return (value: Array<any>) => {
371
+ assertArgument(array.count === -1 || array.count === value.length, `array length mismatch; expected length ${ array.count }`, "value", value);
372
+
373
+ let result = value.map(subEncoder);
374
+ if (this.#fullTypes.has(subtype)) {
375
+ result = result.map(keccak256);
376
+ }
377
+
378
+ return keccak256(concat(result));
379
+ };
380
+ }
381
+
382
+ // Struct
383
+ const fields = this.types[type];
384
+ if (fields) {
385
+ const encodedType = id(this.#fullTypes.get(type) as string);
386
+ return (value: Record<string, any>) => {
387
+ const values = fields.map(({ name, type }) => {
388
+ const result = this.getEncoder(type)(value[name]);
389
+ if (this.#fullTypes.has(type)) { return keccak256(result); }
390
+ return result;
391
+ });
392
+ values.unshift(encodedType);
393
+ return concat(values);
394
+ }
395
+ }
396
+
397
+ assertArgument(false, `unknown type: ${ type }`, "type", type);
398
+ }
399
+
400
+ /**
401
+ * Return the full type for %%name%%.
402
+ */
403
+ encodeType(name: string): string {
404
+ const result = this.#fullTypes.get(name);
405
+ assertArgument(result, `unknown type: ${ JSON.stringify(name) }`, "name", name);
406
+ return result;
407
+ }
408
+
409
+ /**
410
+ * Return the encoded %%value%% for the %%type%%.
411
+ */
412
+ encodeData(type: string, value: any): string {
413
+ return this.getEncoder(type)(value);
414
+ }
415
+
416
+ /**
417
+ * Returns the hash of %%value%% for the type of %%name%%.
418
+ */
419
+ hashStruct(name: string, value: Record<string, any>): string {
420
+ return keccak256(this.encodeData(name, value));
421
+ }
422
+
423
+ /**
424
+ * Return the fulled encoded %%value%% for the [[types]].
425
+ */
426
+ encode(value: Record<string, any>): string {
427
+ return this.encodeData(this.primaryType, value);
428
+ }
429
+
430
+ /**
431
+ * Return the hash of the fully encoded %%value%% for the [[types]].
432
+ */
433
+ hash(value: Record<string, any>): string {
434
+ return this.hashStruct(this.primaryType, value);
435
+ }
436
+
437
+ /**
438
+ * @_ignore:
439
+ */
440
+ _visit(type: string, value: any, callback: (type: string, data: any) => any): any {
441
+ // Basic encoder type (address, bool, uint256, etc)
442
+ {
443
+ const encoder = getBaseEncoder(type);
444
+ if (encoder) { return callback(type, value); }
445
+ }
446
+
447
+ // Array
448
+ const array = splitArray(type).array;
449
+ if (array) {
450
+ assertArgument(array.count === -1 || array.count === value.length, `array length mismatch; expected length ${ array.count }`, "value", value);
451
+ return value.map((v: any) => this._visit(array.prefix, v, callback));
452
+ }
453
+
454
+ // Struct
455
+ const fields = this.types[type];
456
+ if (fields) {
457
+ return fields.reduce((accum, { name, type }) => {
458
+ accum[name] = this._visit(type, value[name], callback);
459
+ return accum;
460
+ }, <Record<string, any>>{});
461
+ }
462
+
463
+ assertArgument(false, `unknown type: ${ type }`, "type", type);
464
+ }
465
+
466
+ /**
467
+ * Call %%calback%% for each value in %%value%%, passing the type and
468
+ * component within %%value%%.
469
+ *
470
+ * This is useful for replacing addresses or other transformation that
471
+ * may be desired on each component, based on its type.
472
+ */
473
+ visit(value: Record<string, any>, callback: (type: string, data: any) => any): any {
474
+ return this._visit(this.primaryType, value, callback);
475
+ }
476
+
477
+ /**
478
+ * Create a new **TypedDataEncoder** for %%types%%.
479
+ */
480
+ static from(types: Record<string, Array<TypedDataField>>): TypedDataEncoder {
481
+ return new TypedDataEncoder(types);
482
+ }
483
+
484
+ /**
485
+ * Return the primary type for %%types%%.
486
+ */
487
+ static getPrimaryType(types: Record<string, Array<TypedDataField>>): string {
488
+ return TypedDataEncoder.from(types).primaryType;
489
+ }
490
+
491
+ /**
492
+ * Return the hashed struct for %%value%% using %%types%% and %%name%%.
493
+ */
494
+ static hashStruct(name: string, types: Record<string, Array<TypedDataField>>, value: Record<string, any>): string {
495
+ return TypedDataEncoder.from(types).hashStruct(name, value);
496
+ }
497
+
498
+ /**
499
+ * Return the domain hash for %%domain%%.
500
+ */
501
+ static hashDomain(domain: TypedDataDomain): string {
502
+ const domainFields: Array<TypedDataField> = [ ];
503
+ for (const name in domain) {
504
+ if ((<Record<string, any>>domain)[name] == null) { continue; }
505
+ const type = domainFieldTypes[name];
506
+ assertArgument(type, `invalid typed-data domain key: ${ JSON.stringify(name) }`, "domain", domain);
507
+ domainFields.push({ name, type });
508
+ }
509
+
510
+ domainFields.sort((a, b) => {
511
+ return domainFieldNames.indexOf(a.name) - domainFieldNames.indexOf(b.name);
512
+ });
513
+
514
+ return TypedDataEncoder.hashStruct("EIP712Domain", { EIP712Domain: domainFields }, domain);
515
+ }
516
+
517
+ /**
518
+ * Return the fully encoded [[link-eip-712]] %%value%% for %%types%% with %%domain%%.
519
+ */
520
+ static encode(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, value: Record<string, any>): string {
521
+ return concat([
522
+ "0x1901",
523
+ TypedDataEncoder.hashDomain(domain),
524
+ TypedDataEncoder.from(types).hash(value)
525
+ ]);
526
+ }
527
+
528
+ /**
529
+ * Return the hash of the fully encoded [[link-eip-712]] %%value%% for %%types%% with %%domain%%.
530
+ */
531
+ static hash(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, value: Record<string, any>): string {
532
+ return keccak256(TypedDataEncoder.encode(domain, types, value));
533
+ }
534
+
535
+ // Replaces all address types with ENS names with their looked up address
536
+ /**
537
+ * Resolves to the value from resolving all addresses in %%value%% for
538
+ * %%types%% and the %%domain%%.
539
+ */
540
+ static async resolveNames(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, value: Record<string, any>, resolveName: (name: string) => Promise<string>): Promise<{ domain: TypedDataDomain, value: any }> {
541
+ // Make a copy to isolate it from the object passed in
542
+ domain = Object.assign({ }, domain);
543
+
544
+ // Allow passing null to ignore value
545
+ for (const key in domain) {
546
+ if ((<Record<string, any>>domain)[key] == null) {
547
+ delete (<Record<string, any>>domain)[key];
548
+ }
549
+ }
550
+
551
+ // Look up all ENS names
552
+ const ensCache: Record<string, string> = { };
553
+
554
+ // Do we need to look up the domain's verifyingContract?
555
+ if (domain.verifyingContract && !isHexString(domain.verifyingContract, 20)) {
556
+ ensCache[domain.verifyingContract] = "0x";
557
+ }
558
+
559
+ // We are going to use the encoder to visit all the base values
560
+ const encoder = TypedDataEncoder.from(types);
561
+
562
+ // Get a list of all the addresses
563
+ encoder.visit(value, (type: string, value: any) => {
564
+ if (type === "address" && !isHexString(value, 20)) {
565
+ ensCache[value] = "0x";
566
+ }
567
+ return value;
568
+ });
569
+
570
+ // Lookup each name
571
+ for (const name in ensCache) {
572
+ ensCache[name] = await resolveName(name);
573
+ }
574
+
575
+ // Replace the domain verifyingContract if needed
576
+ if (domain.verifyingContract && ensCache[domain.verifyingContract]) {
577
+ domain.verifyingContract = ensCache[domain.verifyingContract];
578
+ }
579
+
580
+ // Replace all ENS names with their address
581
+ value = encoder.visit(value, (type: string, value: any) => {
582
+ if (type === "address" && ensCache[value]) { return ensCache[value]; }
583
+ return value;
584
+ });
585
+
586
+ return { domain, value };
587
+ }
588
+
589
+ /**
590
+ * Returns the JSON-encoded payload expected by nodes which implement
591
+ * the JSON-RPC [[link-eip-712]] method.
592
+ */
593
+ static getPayload(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, value: Record<string, any>): any {
594
+ // Validate the domain fields
595
+ TypedDataEncoder.hashDomain(domain);
596
+
597
+ // Derive the EIP712Domain Struct reference type
598
+ const domainValues: Record<string, any> = { };
599
+ const domainTypes: Array<{ name: string, type:string }> = [ ];
600
+
601
+ domainFieldNames.forEach((name) => {
602
+ const value = (<any>domain)[name];
603
+ if (value == null) { return; }
604
+ domainValues[name] = domainChecks[name](value);
605
+ domainTypes.push({ name, type: domainFieldTypes[name] });
606
+ });
607
+
608
+ const encoder = TypedDataEncoder.from(types);
609
+
610
+ // Get the normalized types
611
+ types = encoder.types;
612
+
613
+ const typesWithDomain = Object.assign({ }, types);
614
+ assertArgument(typesWithDomain.EIP712Domain == null, "types must not contain EIP712Domain type", "types.EIP712Domain", types);
615
+
616
+ typesWithDomain.EIP712Domain = domainTypes;
617
+
618
+ // Validate the data structures and types
619
+ encoder.encode(value);
620
+
621
+ return {
622
+ types: typesWithDomain,
623
+ domain: domainValues,
624
+ primaryType: encoder.primaryType,
625
+ message: encoder.visit(value, (type: string, value: any) => {
626
+
627
+ // bytes
628
+ if (type.match(/^bytes(\d*)/)) {
629
+ return hexlify(getBytes(value));
630
+ }
631
+
632
+ // uint or int
633
+ if (type.match(/^u?int/)) {
634
+ return getBigInt(value).toString();
635
+ }
636
+
637
+ switch (type) {
638
+ case "address":
639
+ return value.toLowerCase();
640
+ case "bool":
641
+ return !!value;
642
+ case "string":
643
+ assertArgument(typeof(value) === "string", "invalid string", "value", value);
644
+ return value;
645
+ }
646
+
647
+ assertArgument(false, "unsupported type", "type", type);
648
+ })
649
+ };
650
+ }
651
+ }
652
+
653
+ /**
654
+ * Compute the address used to sign the typed data for the %%signature%%.
655
+ */
656
+ export function verifyTypedData(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, value: Record<string, any>, signature: SignatureLike): string {
657
+ return recoverAddress(TypedDataEncoder.hash(domain, types, value), signature);
658
+ }