viem 2.11.1 → 2.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +3 -3
  3. package/_cjs/actions/public/verifyMessage.js.map +1 -1
  4. package/_cjs/actions/siwe/verifySiweMessage.js +32 -0
  5. package/_cjs/actions/siwe/verifySiweMessage.js.map +1 -0
  6. package/_cjs/chains/definitions/flowPreviewnet.js +6 -0
  7. package/_cjs/chains/definitions/flowPreviewnet.js.map +1 -1
  8. package/_cjs/chains/definitions/jbcTestnet.js +0 -4
  9. package/_cjs/chains/definitions/jbcTestnet.js.map +1 -1
  10. package/_cjs/chains/definitions/l3x.js +24 -0
  11. package/_cjs/chains/definitions/l3x.js.map +1 -0
  12. package/_cjs/chains/definitions/l3xTestnet.js +24 -0
  13. package/_cjs/chains/definitions/l3xTestnet.js.map +1 -0
  14. package/_cjs/chains/definitions/metis.js +5 -0
  15. package/_cjs/chains/definitions/metis.js.map +1 -1
  16. package/_cjs/chains/definitions/thaiChain.js +29 -0
  17. package/_cjs/chains/definitions/thaiChain.js.map +1 -0
  18. package/_cjs/chains/index.js +10 -4
  19. package/_cjs/chains/index.js.map +1 -1
  20. package/_cjs/clients/decorators/public.js +2 -0
  21. package/_cjs/clients/decorators/public.js.map +1 -1
  22. package/_cjs/errors/siwe.js +22 -0
  23. package/_cjs/errors/siwe.js.map +1 -0
  24. package/_cjs/errors/version.js +1 -1
  25. package/_cjs/siwe/index.js +16 -0
  26. package/_cjs/siwe/index.js.map +1 -0
  27. package/_cjs/utils/siwe/createSiweMessage.js +122 -0
  28. package/_cjs/utils/siwe/createSiweMessage.js.map +1 -0
  29. package/_cjs/utils/siwe/generateSiweNonce.js +9 -0
  30. package/_cjs/utils/siwe/generateSiweNonce.js.map +1 -0
  31. package/_cjs/utils/siwe/parseSiweMessage.js +25 -0
  32. package/_cjs/utils/siwe/parseSiweMessage.js.map +1 -0
  33. package/_cjs/utils/siwe/types.js +3 -0
  34. package/_cjs/utils/siwe/types.js.map +1 -0
  35. package/_cjs/utils/siwe/utils.js +44 -0
  36. package/_cjs/utils/siwe/utils.js.map +1 -0
  37. package/_cjs/utils/siwe/validateSiweMessage.js +29 -0
  38. package/_cjs/utils/siwe/validateSiweMessage.js.map +1 -0
  39. package/_esm/actions/public/verifyMessage.js.map +1 -1
  40. package/_esm/actions/siwe/verifySiweMessage.js +39 -0
  41. package/_esm/actions/siwe/verifySiweMessage.js.map +1 -0
  42. package/_esm/chains/definitions/flowPreviewnet.js +6 -0
  43. package/_esm/chains/definitions/flowPreviewnet.js.map +1 -1
  44. package/_esm/chains/definitions/jbcTestnet.js +0 -4
  45. package/_esm/chains/definitions/jbcTestnet.js.map +1 -1
  46. package/_esm/chains/definitions/l3x.js +21 -0
  47. package/_esm/chains/definitions/l3x.js.map +1 -0
  48. package/_esm/chains/definitions/l3xTestnet.js +21 -0
  49. package/_esm/chains/definitions/l3xTestnet.js.map +1 -0
  50. package/_esm/chains/definitions/metis.js +5 -0
  51. package/_esm/chains/definitions/metis.js.map +1 -1
  52. package/_esm/chains/definitions/thaiChain.js +26 -0
  53. package/_esm/chains/definitions/thaiChain.js.map +1 -0
  54. package/_esm/chains/index.js +3 -0
  55. package/_esm/chains/index.js.map +1 -1
  56. package/_esm/clients/decorators/public.js +2 -0
  57. package/_esm/clients/decorators/public.js.map +1 -1
  58. package/_esm/errors/siwe.js +18 -0
  59. package/_esm/errors/siwe.js.map +1 -0
  60. package/_esm/errors/version.js +1 -1
  61. package/_esm/siwe/index.js +7 -0
  62. package/_esm/siwe/index.js.map +1 -0
  63. package/_esm/utils/siwe/createSiweMessage.js +137 -0
  64. package/_esm/utils/siwe/createSiweMessage.js.map +1 -0
  65. package/_esm/utils/siwe/generateSiweNonce.js +15 -0
  66. package/_esm/utils/siwe/generateSiweNonce.js.map +1 -0
  67. package/_esm/utils/siwe/parseSiweMessage.js +30 -0
  68. package/_esm/utils/siwe/parseSiweMessage.js.map +1 -0
  69. package/_esm/utils/siwe/types.js +2 -0
  70. package/_esm/utils/siwe/types.js.map +1 -0
  71. package/_esm/utils/siwe/utils.js +49 -0
  72. package/_esm/utils/siwe/utils.js.map +1 -0
  73. package/_esm/utils/siwe/validateSiweMessage.js +30 -0
  74. package/_esm/utils/siwe/validateSiweMessage.js.map +1 -0
  75. package/_types/actions/public/verifyMessage.d.ts +3 -2
  76. package/_types/actions/public/verifyMessage.d.ts.map +1 -1
  77. package/_types/actions/siwe/verifySiweMessage.d.ts +34 -0
  78. package/_types/actions/siwe/verifySiweMessage.d.ts.map +1 -0
  79. package/_types/chains/definitions/flowPreviewnet.d.ts +6 -8
  80. package/_types/chains/definitions/flowPreviewnet.d.ts.map +1 -1
  81. package/_types/chains/definitions/jbcTestnet.d.ts +0 -4
  82. package/_types/chains/definitions/jbcTestnet.d.ts.map +1 -1
  83. package/_types/chains/definitions/l3x.d.ts +37 -0
  84. package/_types/chains/definitions/l3x.d.ts.map +1 -0
  85. package/_types/chains/definitions/l3xTestnet.d.ts +37 -0
  86. package/_types/chains/definitions/l3xTestnet.d.ts.map +1 -0
  87. package/_types/chains/definitions/metis.d.ts +5 -0
  88. package/_types/chains/definitions/metis.d.ts.map +1 -1
  89. package/_types/chains/definitions/thaiChain.d.ts +34 -0
  90. package/_types/chains/definitions/thaiChain.d.ts.map +1 -0
  91. package/_types/chains/index.d.ts +3 -0
  92. package/_types/chains/index.d.ts.map +1 -1
  93. package/_types/clients/decorators/public.d.ts +30 -0
  94. package/_types/clients/decorators/public.d.ts.map +1 -1
  95. package/_types/errors/siwe.d.ts +13 -0
  96. package/_types/errors/siwe.d.ts.map +1 -0
  97. package/_types/errors/version.d.ts +1 -1
  98. package/_types/siwe/index.d.ts +8 -0
  99. package/_types/siwe/index.d.ts.map +1 -0
  100. package/_types/utils/siwe/createSiweMessage.d.ts +24 -0
  101. package/_types/utils/siwe/createSiweMessage.d.ts.map +1 -0
  102. package/_types/utils/siwe/generateSiweNonce.d.ts +12 -0
  103. package/_types/utils/siwe/generateSiweNonce.d.ts.map +1 -0
  104. package/_types/utils/siwe/parseSiweMessage.d.ts +11 -0
  105. package/_types/utils/siwe/parseSiweMessage.d.ts.map +1 -0
  106. package/_types/utils/siwe/types.d.ts +61 -0
  107. package/_types/utils/siwe/types.d.ts.map +1 -0
  108. package/_types/utils/siwe/utils.d.ts +2 -0
  109. package/_types/utils/siwe/utils.d.ts.map +1 -0
  110. package/_types/utils/siwe/validateSiweMessage.d.ts +39 -0
  111. package/_types/utils/siwe/validateSiweMessage.d.ts.map +1 -0
  112. package/actions/public/verifyMessage.ts +11 -8
  113. package/actions/siwe/verifySiweMessage.ts +90 -0
  114. package/chains/definitions/flowPreviewnet.ts +6 -0
  115. package/chains/definitions/jbcTestnet.ts +0 -4
  116. package/chains/definitions/l3x.ts +21 -0
  117. package/chains/definitions/l3xTestnet.ts +21 -0
  118. package/chains/definitions/metis.ts +6 -0
  119. package/chains/definitions/thaiChain.ts +26 -0
  120. package/chains/index.ts +3 -0
  121. package/clients/decorators/public.ts +37 -0
  122. package/errors/siwe.ts +20 -0
  123. package/errors/version.ts +1 -1
  124. package/package.json +9 -1
  125. package/siwe/index.ts +29 -0
  126. package/siwe/package.json +6 -0
  127. package/utils/siwe/createSiweMessage.ts +168 -0
  128. package/utils/siwe/generateSiweNonce.ts +15 -0
  129. package/utils/siwe/parseSiweMessage.ts +55 -0
  130. package/utils/siwe/types.ts +61 -0
  131. package/utils/siwe/utils.ts +51 -0
  132. package/utils/siwe/validateSiweMessage.ts +70 -0
@@ -0,0 +1,168 @@
1
+ import {
2
+ SiweInvalidMessageFieldError,
3
+ type SiweInvalidMessageFieldErrorType,
4
+ } from '../../errors/siwe.js'
5
+ import type { ErrorType } from '../../errors/utils.js'
6
+ import { type GetAddressErrorType, getAddress } from '../address/getAddress.js'
7
+ import type { SiweMessage } from './types.js'
8
+ import { isUri } from './utils.js'
9
+
10
+ export type CreateSiweMessageParameters = SiweMessage
11
+
12
+ export type CreateSiweMessageReturnType = string
13
+
14
+ export type CreateSiweMessageErrorType =
15
+ | GetAddressErrorType
16
+ | SiweInvalidMessageFieldErrorType
17
+ | ErrorType
18
+
19
+ /**
20
+ * @description Creates EIP-4361 formatted message.
21
+ *
22
+ * @example
23
+ * const message = createMessage({
24
+ * address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
25
+ * chainId: 1,
26
+ * domain: 'example.com',
27
+ * nonce: 'foobarbaz',
28
+ * uri: 'https://example.com/path',
29
+ * version: '1',
30
+ * })
31
+ *
32
+ * @see https://eips.ethereum.org/EIPS/eip-4361
33
+ */
34
+ export function createSiweMessage(
35
+ parameters: CreateSiweMessageParameters,
36
+ ): CreateSiweMessageReturnType {
37
+ const {
38
+ chainId,
39
+ domain,
40
+ expirationTime,
41
+ issuedAt = new Date(),
42
+ nonce,
43
+ notBefore,
44
+ requestId,
45
+ resources,
46
+ scheme,
47
+ uri,
48
+ version,
49
+ } = parameters
50
+
51
+ // Validate fields
52
+ {
53
+ // Required fields
54
+ if (chainId !== Math.floor(chainId))
55
+ throw new SiweInvalidMessageFieldError({
56
+ field: 'chainId',
57
+ metaMessages: [
58
+ '- Chain ID must be a EIP-155 chain ID.',
59
+ '- See https://eips.ethereum.org/EIPS/eip-155',
60
+ '',
61
+ `Provided value: ${chainId}`,
62
+ ],
63
+ })
64
+ if (!domainRegex.test(domain))
65
+ throw new SiweInvalidMessageFieldError({
66
+ field: 'domain',
67
+ metaMessages: [
68
+ '- Domain must be an RFC 3986 authority.',
69
+ '- See https://www.rfc-editor.org/rfc/rfc3986',
70
+ '',
71
+ `Provided value: ${domain}`,
72
+ ],
73
+ })
74
+ if (!nonceRegex.test(nonce))
75
+ throw new SiweInvalidMessageFieldError({
76
+ field: 'nonce',
77
+ metaMessages: [
78
+ '- Nonce must be at least 8 characters.',
79
+ '- Nonce must be alphanumeric.',
80
+ '',
81
+ `Provided value: ${nonce}`,
82
+ ],
83
+ })
84
+ if (!isUri(uri))
85
+ throw new SiweInvalidMessageFieldError({
86
+ field: 'uri',
87
+ metaMessages: [
88
+ '- URI must be a RFC 3986 URI referring to the resource that is the subject of the signing.',
89
+ '- See https://www.rfc-editor.org/rfc/rfc3986',
90
+ '',
91
+ `Provided value: ${uri}`,
92
+ ],
93
+ })
94
+ if (version !== '1')
95
+ throw new SiweInvalidMessageFieldError({
96
+ field: 'version',
97
+ metaMessages: [
98
+ "- Version must be '1'.",
99
+ '',
100
+ `Provided value: ${version}`,
101
+ ],
102
+ })
103
+
104
+ // Optional fields
105
+ if (scheme && !schemeRegex.test(scheme))
106
+ throw new SiweInvalidMessageFieldError({
107
+ field: 'scheme',
108
+ metaMessages: [
109
+ '- Scheme must be an RFC 3986 URI scheme.',
110
+ '- See https://www.rfc-editor.org/rfc/rfc3986#section-3.1',
111
+ '',
112
+ `Provided value: ${scheme}`,
113
+ ],
114
+ })
115
+ const statement = parameters.statement
116
+ if (statement?.includes('\n'))
117
+ throw new SiweInvalidMessageFieldError({
118
+ field: 'statement',
119
+ metaMessages: [
120
+ "- Statement must not include '\\n'.",
121
+ '',
122
+ `Provided value: ${statement}`,
123
+ ],
124
+ })
125
+ }
126
+
127
+ // Construct message
128
+ const address = getAddress(parameters.address)
129
+ const origin = (() => {
130
+ if (scheme) return `${scheme}://${domain}`
131
+ return domain
132
+ })()
133
+ const statement = (() => {
134
+ if (!parameters.statement) return ''
135
+ return `\n${parameters.statement}\n`
136
+ })()
137
+ const prefix = `${origin} wants you to sign in with your Ethereum account:\n${address}\n${statement}`
138
+
139
+ let suffix = `URI: ${uri}\nVersion: ${version}\nChain ID: ${chainId}\nNonce: ${nonce}\nIssued At: ${issuedAt.toISOString()}`
140
+
141
+ if (expirationTime)
142
+ suffix += `\nExpiration Time: ${expirationTime.toISOString()}`
143
+ if (notBefore) suffix += `\nNot Before: ${notBefore.toISOString()}`
144
+ if (requestId) suffix += `\nRequest ID: ${requestId}`
145
+ if (resources) {
146
+ let content = '\nResources:'
147
+ for (const resource of resources) {
148
+ if (!isUri(resource))
149
+ throw new SiweInvalidMessageFieldError({
150
+ field: 'resources',
151
+ metaMessages: [
152
+ '- Every resource must be a RFC 3986 URI.',
153
+ '- See https://www.rfc-editor.org/rfc/rfc3986',
154
+ '',
155
+ `Provided value: ${resource}`,
156
+ ],
157
+ })
158
+ content += `\n- ${resource}`
159
+ }
160
+ suffix += content
161
+ }
162
+
163
+ return `${prefix}\n${suffix}`
164
+ }
165
+
166
+ const domainRegex = /^(?:(?:(?!-)[a-zA-Z0-9-]{1,63}(?<!-)\.)+[a-zA-Z]{2,63})$/
167
+ const nonceRegex = /^[a-zA-Z0-9]{8,}$/
168
+ const schemeRegex = /^([a-zA-Z][a-zA-Z0-9+-.]*)$/
@@ -0,0 +1,15 @@
1
+ import { uid } from '../../utils/uid.js'
2
+
3
+ /**
4
+ * @description Generates random EIP-4361 nonce.
5
+ *
6
+ * @example
7
+ * const nonce = generateNonce()
8
+ *
9
+ * @see https://eips.ethereum.org/EIPS/eip-4361
10
+ *
11
+ * @returns A randomly generated EIP-4361 nonce.
12
+ */
13
+ export function generateSiweNonce(): string {
14
+ return uid(96)
15
+ }
@@ -0,0 +1,55 @@
1
+ import type { Address } from 'abitype'
2
+
3
+ import type { ExactPartial, Prettify } from '../../types/utils.js'
4
+ import type { SiweMessage } from './types.js'
5
+
6
+ /**
7
+ * @description Parses EIP-4361 formatted message into message fields object.
8
+ *
9
+ * @see https://eips.ethereum.org/EIPS/eip-4361
10
+ *
11
+ * @returns EIP-4361 fields object
12
+ */
13
+ export function parseSiweMessage(
14
+ message: string,
15
+ ): Prettify<ExactPartial<SiweMessage>> {
16
+ const { scheme, statement, ...prefix } = (message.match(prefixRegex)
17
+ ?.groups ?? {}) as {
18
+ address: Address
19
+ domain: string
20
+ scheme?: string
21
+ statement?: string
22
+ }
23
+ const { chainId, expirationTime, issuedAt, notBefore, requestId, ...suffix } =
24
+ (message.match(suffixRegex)?.groups ?? {}) as {
25
+ chainId: string
26
+ expirationTime?: string
27
+ issuedAt?: string
28
+ nonce: string
29
+ notBefore?: string
30
+ requestId?: string
31
+ uri: string
32
+ version: '1'
33
+ }
34
+ const resources = message.split('Resources:')[1]?.split('\n- ').slice(1)
35
+ return {
36
+ ...prefix,
37
+ ...suffix,
38
+ ...(chainId ? { chainId: Number(chainId) } : {}),
39
+ ...(expirationTime ? { expirationTime: new Date(expirationTime) } : {}),
40
+ ...(issuedAt ? { issuedAt: new Date(issuedAt) } : {}),
41
+ ...(notBefore ? { notBefore: new Date(notBefore) } : {}),
42
+ ...(requestId ? { requestId } : {}),
43
+ ...(resources ? { resources } : {}),
44
+ ...(scheme ? { scheme } : {}),
45
+ ...(statement ? { statement } : {}),
46
+ }
47
+ }
48
+
49
+ // https://regexr.com/80gdj
50
+ const prefixRegex =
51
+ /^(?:(?<scheme>[a-zA-Z][a-zA-Z0-9+-.]*):\/\/)?(?<domain>[a-zA-Z0-9+-.]*) (?:wants you to sign in with your Ethereum account:\n)(?<address>0x[a-fA-F0-9]{40})\n\n(?:(?<statement>.*)\n\n)?/
52
+
53
+ // https://regexr.com/80gf9
54
+ const suffixRegex =
55
+ /(?:URI: (?<uri>.+))\n(?:Version: (?<version>.+))\n(?:Chain ID: (?<chainId>\d+))\n(?:Nonce: (?<nonce>[a-zA-Z0-9]+))\n(?:Issued At: (?<issuedAt>.+))(?:\nExpiration Time: (?<expirationTime>.+))?(?:\nNot Before: (?<notBefore>.+))?(?:\nRequest ID: (?<requestId>.+))?/
@@ -0,0 +1,61 @@
1
+ import type { Address } from 'abitype'
2
+
3
+ /**
4
+ * @description EIP-4361 message fields
5
+ *
6
+ * @see https://eips.ethereum.org/EIPS/eip-4361
7
+ */
8
+ export type SiweMessage = {
9
+ /**
10
+ * The Ethereum address performing the signing.
11
+ */
12
+ address: Address
13
+ /**
14
+ * The [EIP-155](https://eips.ethereum.org/EIPS/eip-155) Chain ID to which the session is bound,
15
+ */
16
+ chainId: number
17
+ /**
18
+ * [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986) authority that is requesting the signing.
19
+ */
20
+ domain: string
21
+ /**
22
+ * Time when the signed authentication message is no longer valid.
23
+ */
24
+ expirationTime?: Date | undefined
25
+ /**
26
+ * Time when the message was generated, typically the current time.
27
+ */
28
+ issuedAt?: Date | undefined
29
+ /**
30
+ * A random string typically chosen by the relying party and used to prevent replay attacks.
31
+ */
32
+ nonce: string
33
+ /**
34
+ * Time when the signed authentication message will become valid.
35
+ */
36
+ notBefore?: Date | undefined
37
+ /**
38
+ * A system-specific identifier that may be used to uniquely refer to the sign-in request.
39
+ */
40
+ requestId?: string | undefined
41
+ /**
42
+ * A list of information or references to information the user wishes to have resolved as part of authentication by the relying party.
43
+ */
44
+ resources?: string[] | undefined
45
+ /**
46
+ * [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) URI scheme of the origin of the request.
47
+ */
48
+ scheme?: string | undefined
49
+ /**
50
+ * A human-readable ASCII assertion that the user will sign.
51
+ */
52
+ statement?: string | undefined
53
+ /**
54
+ * [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986) URI referring to the resource that is the subject of the signing (as in the subject of a claim).
55
+ */
56
+ uri: string
57
+ /**
58
+ * The current version of the SIWE Message.
59
+ */
60
+ version: '1'
61
+ }
@@ -0,0 +1,51 @@
1
+ export function isUri(value: string) {
2
+ // based on https://github.com/ogt/valid-url
3
+
4
+ // check for illegal characters
5
+ if (/[^a-z0-9\:\/\?\#\[\]\@\!\$\&\'\(\)\*\+\,\;\=\.\-\_\~\%]/i.test(value))
6
+ return false
7
+
8
+ // check for hex escapes that aren't complete
9
+ if (/%[^0-9a-f]/i.test(value)) return false
10
+ if (/%[0-9a-f](:?[^0-9a-f]|$)/i.test(value)) return false
11
+
12
+ // from RFC 3986
13
+ const splitted = splitUri(value)
14
+ const scheme = splitted[1]
15
+ const authority = splitted[2]
16
+ const path = splitted[3]
17
+ const query = splitted[4]
18
+ const fragment = splitted[5]
19
+
20
+ // scheme and path are required, though the path can be empty
21
+ if (!(scheme?.length && path.length >= 0)) return false
22
+
23
+ // if authority is present, the path must be empty or begin with a /
24
+ if (authority?.length) {
25
+ if (!(path.length === 0 || /^\//.test(path))) return false
26
+ } else {
27
+ // if authority is not present, the path must not start with //
28
+ if (/^\/\//.test(path)) return false
29
+ }
30
+
31
+ // scheme must begin with a letter, then consist of letters, digits, +, ., or -
32
+ if (!/^[a-z][a-z0-9\+\-\.]*$/.test(scheme.toLowerCase())) return false
33
+
34
+ let out = ''
35
+ // re-assemble the URL per section 5.3 in RFC 3986
36
+ out += `${scheme}:`
37
+ if (authority?.length) out += `//${authority}`
38
+
39
+ out += path
40
+
41
+ if (query?.length) out += `?${query}`
42
+ if (fragment?.length) out += `#${fragment}`
43
+
44
+ return out
45
+ }
46
+
47
+ function splitUri(value: string) {
48
+ return value.match(
49
+ /(?:([^:\/?#]+):)?(?:\/\/([^\/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?/,
50
+ )!
51
+ }
@@ -0,0 +1,70 @@
1
+ import type { Address } from 'abitype'
2
+
3
+ import type { ExactPartial } from '../../types/utils.js'
4
+ import { isAddressEqual } from '../address/isAddressEqual.js'
5
+ import type { SiweMessage } from './types.js'
6
+
7
+ export type ValidateSiweMessageParameters = {
8
+ /**
9
+ * Ethereum address to check against.
10
+ */
11
+ address?: Address | undefined
12
+ /**
13
+ * [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986) authority to check against.
14
+ */
15
+ domain?: string | undefined
16
+ /**
17
+ * EIP-4361 message fields.
18
+ */
19
+ message: ExactPartial<SiweMessage>
20
+ /**
21
+ * Random string to check against.
22
+ */
23
+ nonce?: string | undefined
24
+ /**
25
+ * [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) URI scheme to check against.
26
+ */
27
+ scheme?: string | undefined
28
+ /**
29
+ * Current time to check optional `expirationTime` and `notBefore` fields.
30
+ *
31
+ * @default new Date()
32
+ */
33
+ time?: Date | undefined
34
+ }
35
+
36
+ export type ValidateSiweMessageReturnType = boolean
37
+
38
+ /**
39
+ * @description Validates EIP-4361 message.
40
+ *
41
+ * @see https://eips.ethereum.org/EIPS/eip-4361
42
+ */
43
+ export function validateSiweMessage(
44
+ parameters: ValidateSiweMessageParameters,
45
+ ): ValidateSiweMessageReturnType {
46
+ const {
47
+ address,
48
+ domain,
49
+ message,
50
+ nonce,
51
+ scheme,
52
+ time = new Date(),
53
+ } = parameters
54
+
55
+ if (domain && message.domain !== domain) return false
56
+ if (nonce && message.nonce !== nonce) return false
57
+ if (scheme && message.scheme !== scheme) return false
58
+
59
+ if (message.expirationTime && time >= message.expirationTime) return false
60
+ if (message.notBefore && time < message.notBefore) return false
61
+
62
+ try {
63
+ if (!message.address) return false
64
+ if (address && !isAddressEqual(message.address, address)) return false
65
+ } catch {
66
+ return false
67
+ }
68
+
69
+ return true
70
+ }