viem 2.11.1 → 2.12.1
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +30 -0
- package/README.md +3 -3
- package/_cjs/actions/public/verifyMessage.js.map +1 -1
- package/_cjs/actions/siwe/verifySiweMessage.js +32 -0
- package/_cjs/actions/siwe/verifySiweMessage.js.map +1 -0
- package/_cjs/chains/definitions/flowPreviewnet.js +6 -0
- package/_cjs/chains/definitions/flowPreviewnet.js.map +1 -1
- package/_cjs/chains/definitions/jbcTestnet.js +0 -4
- package/_cjs/chains/definitions/jbcTestnet.js.map +1 -1
- package/_cjs/chains/definitions/l3x.js +24 -0
- package/_cjs/chains/definitions/l3x.js.map +1 -0
- package/_cjs/chains/definitions/l3xTestnet.js +24 -0
- package/_cjs/chains/definitions/l3xTestnet.js.map +1 -0
- package/_cjs/chains/definitions/metis.js +5 -0
- package/_cjs/chains/definitions/metis.js.map +1 -1
- package/_cjs/chains/definitions/thaiChain.js +29 -0
- package/_cjs/chains/definitions/thaiChain.js.map +1 -0
- package/_cjs/chains/definitions/zkSync.js +4 -0
- package/_cjs/chains/definitions/zkSync.js.map +1 -1
- package/_cjs/chains/definitions/zkSyncSepoliaTestnet.js +5 -1
- package/_cjs/chains/definitions/zkSyncSepoliaTestnet.js.map +1 -1
- package/_cjs/chains/index.js +10 -4
- package/_cjs/chains/index.js.map +1 -1
- package/_cjs/clients/decorators/public.js +2 -0
- package/_cjs/clients/decorators/public.js.map +1 -1
- package/_cjs/errors/siwe.js +22 -0
- package/_cjs/errors/siwe.js.map +1 -0
- package/_cjs/errors/version.js +1 -1
- package/_cjs/siwe/index.js +16 -0
- package/_cjs/siwe/index.js.map +1 -0
- package/_cjs/utils/address/isAddress.js +4 -3
- package/_cjs/utils/address/isAddress.js.map +1 -1
- package/_cjs/utils/siwe/createSiweMessage.js +126 -0
- package/_cjs/utils/siwe/createSiweMessage.js.map +1 -0
- package/_cjs/utils/siwe/generateSiweNonce.js +9 -0
- package/_cjs/utils/siwe/generateSiweNonce.js.map +1 -0
- package/_cjs/utils/siwe/parseSiweMessage.js +25 -0
- package/_cjs/utils/siwe/parseSiweMessage.js.map +1 -0
- package/_cjs/utils/siwe/types.js +3 -0
- package/_cjs/utils/siwe/types.js.map +1 -0
- package/_cjs/utils/siwe/utils.js +44 -0
- package/_cjs/utils/siwe/utils.js.map +1 -0
- package/_cjs/utils/siwe/validateSiweMessage.js +29 -0
- package/_cjs/utils/siwe/validateSiweMessage.js.map +1 -0
- package/_esm/actions/public/verifyMessage.js.map +1 -1
- package/_esm/actions/siwe/verifySiweMessage.js +39 -0
- package/_esm/actions/siwe/verifySiweMessage.js.map +1 -0
- package/_esm/chains/definitions/flowPreviewnet.js +6 -0
- package/_esm/chains/definitions/flowPreviewnet.js.map +1 -1
- package/_esm/chains/definitions/jbcTestnet.js +0 -4
- package/_esm/chains/definitions/jbcTestnet.js.map +1 -1
- package/_esm/chains/definitions/l3x.js +21 -0
- package/_esm/chains/definitions/l3x.js.map +1 -0
- package/_esm/chains/definitions/l3xTestnet.js +21 -0
- package/_esm/chains/definitions/l3xTestnet.js.map +1 -0
- package/_esm/chains/definitions/metis.js +5 -0
- package/_esm/chains/definitions/metis.js.map +1 -1
- package/_esm/chains/definitions/thaiChain.js +26 -0
- package/_esm/chains/definitions/thaiChain.js.map +1 -0
- package/_esm/chains/definitions/zkSync.js +4 -0
- package/_esm/chains/definitions/zkSync.js.map +1 -1
- package/_esm/chains/definitions/zkSyncSepoliaTestnet.js +5 -1
- package/_esm/chains/definitions/zkSyncSepoliaTestnet.js.map +1 -1
- package/_esm/chains/index.js +3 -0
- package/_esm/chains/index.js.map +1 -1
- package/_esm/clients/decorators/public.js +2 -0
- package/_esm/clients/decorators/public.js.map +1 -1
- package/_esm/errors/siwe.js +18 -0
- package/_esm/errors/siwe.js.map +1 -0
- package/_esm/errors/version.js +1 -1
- package/_esm/node/trustedSetups.js +7 -1
- package/_esm/node/trustedSetups.js.map +1 -1
- package/_esm/node/trustedSetups_cjs.js +4 -0
- package/_esm/node/trustedSetups_cjs.js.map +1 -0
- package/_esm/siwe/index.js +7 -0
- package/_esm/siwe/index.js.map +1 -0
- package/_esm/utils/address/isAddress.js +4 -3
- package/_esm/utils/address/isAddress.js.map +1 -1
- package/_esm/utils/siwe/createSiweMessage.js +141 -0
- package/_esm/utils/siwe/createSiweMessage.js.map +1 -0
- package/_esm/utils/siwe/generateSiweNonce.js +15 -0
- package/_esm/utils/siwe/generateSiweNonce.js.map +1 -0
- package/_esm/utils/siwe/parseSiweMessage.js +30 -0
- package/_esm/utils/siwe/parseSiweMessage.js.map +1 -0
- package/_esm/utils/siwe/types.js +2 -0
- package/_esm/utils/siwe/types.js.map +1 -0
- package/_esm/utils/siwe/utils.js +49 -0
- package/_esm/utils/siwe/utils.js.map +1 -0
- package/_esm/utils/siwe/validateSiweMessage.js +30 -0
- package/_esm/utils/siwe/validateSiweMessage.js.map +1 -0
- package/_types/actions/public/verifyMessage.d.ts +3 -2
- package/_types/actions/public/verifyMessage.d.ts.map +1 -1
- package/_types/actions/siwe/verifySiweMessage.d.ts +34 -0
- package/_types/actions/siwe/verifySiweMessage.d.ts.map +1 -0
- package/_types/chains/definitions/flowPreviewnet.d.ts +6 -8
- package/_types/chains/definitions/flowPreviewnet.d.ts.map +1 -1
- package/_types/chains/definitions/jbcTestnet.d.ts +0 -4
- package/_types/chains/definitions/jbcTestnet.d.ts.map +1 -1
- package/_types/chains/definitions/l3x.d.ts +37 -0
- package/_types/chains/definitions/l3x.d.ts.map +1 -0
- package/_types/chains/definitions/l3xTestnet.d.ts +37 -0
- package/_types/chains/definitions/l3xTestnet.d.ts.map +1 -0
- package/_types/chains/definitions/metis.d.ts +5 -0
- package/_types/chains/definitions/metis.d.ts.map +1 -1
- package/_types/chains/definitions/thaiChain.d.ts +34 -0
- package/_types/chains/definitions/thaiChain.d.ts.map +1 -0
- package/_types/chains/definitions/zkSync.d.ts +4 -0
- package/_types/chains/definitions/zkSync.d.ts.map +1 -1
- package/_types/chains/definitions/zkSyncSepoliaTestnet.d.ts +5 -1
- package/_types/chains/definitions/zkSyncSepoliaTestnet.d.ts.map +1 -1
- package/_types/chains/index.d.ts +3 -0
- package/_types/chains/index.d.ts.map +1 -1
- package/_types/clients/decorators/public.d.ts +30 -0
- package/_types/clients/decorators/public.d.ts.map +1 -1
- package/_types/errors/siwe.d.ts +13 -0
- package/_types/errors/siwe.d.ts.map +1 -0
- package/_types/errors/version.d.ts +1 -1
- package/_types/node/trustedSetups.d.ts.map +1 -1
- package/_types/node/trustedSetups_cjs.d.ts +3 -0
- package/_types/node/trustedSetups_cjs.d.ts.map +1 -0
- package/_types/siwe/index.d.ts +8 -0
- package/_types/siwe/index.d.ts.map +1 -0
- package/_types/utils/address/isAddress.d.ts.map +1 -1
- package/_types/utils/siwe/createSiweMessage.d.ts +24 -0
- package/_types/utils/siwe/createSiweMessage.d.ts.map +1 -0
- package/_types/utils/siwe/generateSiweNonce.d.ts +12 -0
- package/_types/utils/siwe/generateSiweNonce.d.ts.map +1 -0
- package/_types/utils/siwe/parseSiweMessage.d.ts +11 -0
- package/_types/utils/siwe/parseSiweMessage.d.ts.map +1 -0
- package/_types/utils/siwe/types.d.ts +61 -0
- package/_types/utils/siwe/types.d.ts.map +1 -0
- package/_types/utils/siwe/utils.d.ts +2 -0
- package/_types/utils/siwe/utils.d.ts.map +1 -0
- package/_types/utils/siwe/validateSiweMessage.d.ts +39 -0
- package/_types/utils/siwe/validateSiweMessage.d.ts.map +1 -0
- package/actions/public/verifyMessage.ts +11 -8
- package/actions/siwe/verifySiweMessage.ts +90 -0
- package/chains/definitions/flowPreviewnet.ts +6 -0
- package/chains/definitions/jbcTestnet.ts +0 -4
- package/chains/definitions/l3x.ts +21 -0
- package/chains/definitions/l3xTestnet.ts +21 -0
- package/chains/definitions/metis.ts +6 -0
- package/chains/definitions/thaiChain.ts +26 -0
- package/chains/definitions/zkSync.ts +4 -0
- package/chains/definitions/zkSyncSepoliaTestnet.ts +5 -1
- package/chains/index.ts +3 -0
- package/clients/decorators/public.ts +37 -0
- package/errors/siwe.ts +20 -0
- package/errors/version.ts +1 -1
- package/node/trustedSetups.ts +9 -1
- package/node/trustedSetups_cjs.ts +11 -0
- package/package.json +9 -1
- package/siwe/index.ts +29 -0
- package/siwe/package.json +6 -0
- package/utils/address/isAddress.ts +3 -2
- package/utils/siwe/createSiweMessage.ts +178 -0
- package/utils/siwe/generateSiweNonce.ts +15 -0
- package/utils/siwe/parseSiweMessage.ts +55 -0
- package/utils/siwe/types.ts +61 -0
- package/utils/siwe/utils.ts +51 -0
- package/utils/siwe/validateSiweMessage.ts +70 -0
@@ -10,6 +10,7 @@ import type {
|
|
10
10
|
SignableMessage,
|
11
11
|
Signature,
|
12
12
|
} from '../../types/misc.js'
|
13
|
+
import type { Prettify } from '../../types/utils.js'
|
13
14
|
import { hashMessage } from '../../utils/signature/hashMessage.js'
|
14
15
|
import type { HashMessageErrorType } from '../../utils/signature/hashMessage.js'
|
15
16
|
import {
|
@@ -18,14 +19,16 @@ import {
|
|
18
19
|
verifyHash,
|
19
20
|
} from './verifyHash.js'
|
20
21
|
|
21
|
-
export type VerifyMessageParameters =
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
22
|
+
export type VerifyMessageParameters = Prettify<
|
23
|
+
Omit<VerifyHashParameters, 'hash'> & {
|
24
|
+
/** The address that signed the original message. */
|
25
|
+
address: Address
|
26
|
+
/** The message to be verified. */
|
27
|
+
message: SignableMessage
|
28
|
+
/** The signature that was generated by signing the message with the address's private key. */
|
29
|
+
signature: Hex | ByteArray | Signature
|
30
|
+
}
|
31
|
+
>
|
29
32
|
|
30
33
|
export type VerifyMessageReturnType = boolean
|
31
34
|
|
@@ -0,0 +1,90 @@
|
|
1
|
+
import type { Client } from '../../clients/createClient.js'
|
2
|
+
import type { Transport } from '../../clients/transports/createTransport.js'
|
3
|
+
import type { ErrorType } from '../../errors/utils.js'
|
4
|
+
import type { Chain } from '../../types/chain.js'
|
5
|
+
import type { Hex } from '../../types/misc.js'
|
6
|
+
import type { Prettify } from '../../types/utils.js'
|
7
|
+
import { hashMessage } from '../../utils/signature/hashMessage.js'
|
8
|
+
import type { HashMessageErrorType } from '../../utils/signature/hashMessage.js'
|
9
|
+
import { parseSiweMessage } from '../../utils/siwe/parseSiweMessage.js'
|
10
|
+
import {
|
11
|
+
type ValidateSiweMessageParameters,
|
12
|
+
validateSiweMessage,
|
13
|
+
} from '../../utils/siwe/validateSiweMessage.js'
|
14
|
+
import {
|
15
|
+
type VerifyHashErrorType,
|
16
|
+
type VerifyHashParameters,
|
17
|
+
verifyHash,
|
18
|
+
} from '../public/verifyHash.js'
|
19
|
+
|
20
|
+
export type VerifySiweMessageParameters = Prettify<
|
21
|
+
Pick<VerifyHashParameters, 'blockNumber' | 'blockTag'> &
|
22
|
+
Pick<
|
23
|
+
ValidateSiweMessageParameters,
|
24
|
+
'address' | 'domain' | 'nonce' | 'scheme' | 'time'
|
25
|
+
> & {
|
26
|
+
/**
|
27
|
+
* EIP-4361 formatted message.
|
28
|
+
*/
|
29
|
+
message: string
|
30
|
+
/**
|
31
|
+
* Signature to check against.
|
32
|
+
*/
|
33
|
+
signature: Hex
|
34
|
+
}
|
35
|
+
>
|
36
|
+
|
37
|
+
export type VerifySiweMessageReturnType = boolean
|
38
|
+
|
39
|
+
export type VerifySiweMessageErrorType =
|
40
|
+
| HashMessageErrorType
|
41
|
+
| VerifyHashErrorType
|
42
|
+
| ErrorType
|
43
|
+
|
44
|
+
/**
|
45
|
+
* Verifies [EIP-4361](https://eips.ethereum.org/EIPS/eip-4361) formatted message was signed.
|
46
|
+
*
|
47
|
+
* Compatible with Smart Contract Accounts & Externally Owned Accounts via [ERC-6492](https://eips.ethereum.org/EIPS/eip-6492).
|
48
|
+
*
|
49
|
+
* - Docs {@link https://viem.sh/docs/siwe/actions/verifySiweMessage}
|
50
|
+
*
|
51
|
+
* @param client - Client to use.
|
52
|
+
* @param parameters - {@link VerifySiweMessageParameters}
|
53
|
+
* @returns Whether or not the signature is valid. {@link VerifySiweMessageReturnType}
|
54
|
+
*/
|
55
|
+
export async function verifySiweMessage<chain extends Chain | undefined>(
|
56
|
+
client: Client<Transport, chain>,
|
57
|
+
parameters: VerifySiweMessageParameters,
|
58
|
+
): Promise<VerifySiweMessageReturnType> {
|
59
|
+
const {
|
60
|
+
address,
|
61
|
+
domain,
|
62
|
+
message,
|
63
|
+
nonce,
|
64
|
+
scheme,
|
65
|
+
signature,
|
66
|
+
time = new Date(),
|
67
|
+
...callRequest
|
68
|
+
} = parameters
|
69
|
+
|
70
|
+
const parsed = parseSiweMessage(message)
|
71
|
+
if (!parsed.address) return false
|
72
|
+
|
73
|
+
const isValid = validateSiweMessage({
|
74
|
+
address,
|
75
|
+
domain,
|
76
|
+
message: parsed,
|
77
|
+
nonce,
|
78
|
+
scheme,
|
79
|
+
time,
|
80
|
+
})
|
81
|
+
if (!isValid) return false
|
82
|
+
|
83
|
+
const hash = hashMessage(message)
|
84
|
+
return verifyHash(client, {
|
85
|
+
address: parsed.address,
|
86
|
+
hash,
|
87
|
+
signature,
|
88
|
+
...callRequest,
|
89
|
+
})
|
90
|
+
}
|
@@ -3,15 +3,11 @@ import { defineChain } from '../../utils/chain/defineChain.js'
|
|
3
3
|
export const jbcTestnet = /*#__PURE__*/ defineChain({
|
4
4
|
id: 88991,
|
5
5
|
name: 'Jibchain Testnet',
|
6
|
-
network: 'jbcTestnet',
|
7
6
|
nativeCurrency: { name: 'tJBC', symbol: 'tJBC', decimals: 18 },
|
8
7
|
rpcUrls: {
|
9
8
|
default: {
|
10
9
|
http: ['https://rpc.testnet.jibchain.net'],
|
11
10
|
},
|
12
|
-
public: {
|
13
|
-
http: ['https://rpc.testnet.jibchain.net'],
|
14
|
-
},
|
15
11
|
},
|
16
12
|
blockExplorers: {
|
17
13
|
default: {
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import { defineChain } from '../../utils/chain/defineChain.js'
|
2
|
+
|
3
|
+
export const l3x = /*#__PURE__*/ defineChain({
|
4
|
+
id: 12324,
|
5
|
+
name: 'L3X Protocol',
|
6
|
+
nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
|
7
|
+
rpcUrls: {
|
8
|
+
default: {
|
9
|
+
http: ['https://rpc-mainnet.l3x.com'],
|
10
|
+
webSocket: ['wss://rpc-mainnet.l3x.com'],
|
11
|
+
},
|
12
|
+
},
|
13
|
+
blockExplorers: {
|
14
|
+
default: {
|
15
|
+
name: 'L3X Mainnet Explorer',
|
16
|
+
url: 'https://explorer.l3x.com',
|
17
|
+
apiUrl: 'https://explorer.l3x.com/api/v2',
|
18
|
+
},
|
19
|
+
},
|
20
|
+
testnet: false,
|
21
|
+
})
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import { defineChain } from '../../utils/chain/defineChain.js'
|
2
|
+
|
3
|
+
export const l3xTestnet = /*#__PURE__*/ defineChain({
|
4
|
+
id: 12325,
|
5
|
+
name: 'L3X Protocol Testnet',
|
6
|
+
nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
|
7
|
+
rpcUrls: {
|
8
|
+
default: {
|
9
|
+
http: ['https://rpc-testnet.l3x.com'],
|
10
|
+
webSocket: ['wss://rpc-testnet.l3x.com'],
|
11
|
+
},
|
12
|
+
},
|
13
|
+
blockExplorers: {
|
14
|
+
default: {
|
15
|
+
name: 'L3X Testnet Explorer',
|
16
|
+
url: 'https://explorer-testnet.l3x.com',
|
17
|
+
apiUrl: 'https://explorer-testnet.l3x.com/api/v2',
|
18
|
+
},
|
19
|
+
},
|
20
|
+
testnet: true,
|
21
|
+
})
|
@@ -13,6 +13,12 @@ export const metis = /*#__PURE__*/ defineChain({
|
|
13
13
|
},
|
14
14
|
blockExplorers: {
|
15
15
|
default: {
|
16
|
+
name: 'Metis Explorer',
|
17
|
+
url: 'https://explorer.metis.io',
|
18
|
+
apiUrl:
|
19
|
+
'https://api.routescan.io/v2/network/mainnet/evm/43114/etherscan/api',
|
20
|
+
},
|
21
|
+
blockscout: {
|
16
22
|
name: 'Andromeda Explorer',
|
17
23
|
url: 'https://andromeda-explorer.metis.io',
|
18
24
|
apiUrl: 'https://andromeda-explorer.metis.io/api',
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import { defineChain } from '../../utils/chain/defineChain.js'
|
2
|
+
|
3
|
+
export const thaiChain = /*#__PURE__*/ defineChain({
|
4
|
+
id: 7,
|
5
|
+
name: 'ThaiChain',
|
6
|
+
nativeCurrency: { name: 'TCH', symbol: 'TCH', decimals: 18 },
|
7
|
+
rpcUrls: {
|
8
|
+
default: {
|
9
|
+
http: ['https://rpc.thaichain.org'],
|
10
|
+
},
|
11
|
+
},
|
12
|
+
blockExplorers: {
|
13
|
+
default: {
|
14
|
+
name: 'Blockscout',
|
15
|
+
url: 'https://exp.thaichain.org',
|
16
|
+
apiUrl: 'https://exp.thaichain.org/api',
|
17
|
+
},
|
18
|
+
},
|
19
|
+
contracts: {
|
20
|
+
multicall3: {
|
21
|
+
address: '0x0DaD6130e832c21719C5CE3bae93454E16A84826',
|
22
|
+
blockCreated: 4806386,
|
23
|
+
},
|
24
|
+
},
|
25
|
+
testnet: false,
|
26
|
+
})
|
@@ -23,6 +23,10 @@ export const zkSync = /*#__PURE__*/ defineChain({
|
|
23
23
|
url: 'https://era.zksync.network/',
|
24
24
|
apiUrl: 'https://api-era.zksync.network/api',
|
25
25
|
},
|
26
|
+
native: {
|
27
|
+
name: 'zkSync Explorer',
|
28
|
+
url: 'https://explorer.zksync.io/',
|
29
|
+
},
|
26
30
|
},
|
27
31
|
contracts: {
|
28
32
|
multicall3: {
|
@@ -15,7 +15,11 @@ export const zkSyncSepoliaTestnet = /*#__PURE__*/ defineChain({
|
|
15
15
|
},
|
16
16
|
blockExplorers: {
|
17
17
|
default: {
|
18
|
-
name: '
|
18
|
+
name: 'Etherscan',
|
19
|
+
url: 'https://sepolia-era.zksync.network/',
|
20
|
+
},
|
21
|
+
native: {
|
22
|
+
name: 'zkSync Explorer',
|
19
23
|
url: 'https://sepolia.explorer.zksync.io/',
|
20
24
|
},
|
21
25
|
},
|
package/chains/index.ts
CHANGED
@@ -124,6 +124,8 @@ export { klaytn } from './definitions/klaytn.js'
|
|
124
124
|
export { klaytnBaobab } from './definitions/klaytnBaobab.js'
|
125
125
|
export { kroma } from './definitions/kroma.js'
|
126
126
|
export { kromaSepolia } from './definitions/kromaSepolia.js'
|
127
|
+
export { l3x } from './definitions/l3x.js'
|
128
|
+
export { l3xTestnet } from './definitions/l3xTestnet.js'
|
127
129
|
export { lightlinkPegasus } from './definitions/lightlinkPegasus.js'
|
128
130
|
export { lightlinkPhoenix } from './definitions/lightlinkPhoenix.js'
|
129
131
|
export { linea } from './definitions/linea.js'
|
@@ -246,6 +248,7 @@ export { telcoinTestnet } from './definitions/telcoinTestnet.js'
|
|
246
248
|
export { telos } from './definitions/telos.js'
|
247
249
|
export { telosTestnet } from './definitions/telosTestnet.js'
|
248
250
|
export { tenet } from './definitions/tenet.js'
|
251
|
+
export { thaiChain } from './definitions/thaiChain.js'
|
249
252
|
export { thunderTestnet } from './definitions/thunderTestnet.js'
|
250
253
|
export { vechain } from './definitions/vechain.js'
|
251
254
|
export { wanchain } from './definitions/wanchain.js'
|
@@ -220,6 +220,11 @@ import {
|
|
220
220
|
type WatchPendingTransactionsReturnType,
|
221
221
|
watchPendingTransactions,
|
222
222
|
} from '../../actions/public/watchPendingTransactions.js'
|
223
|
+
import {
|
224
|
+
type VerifySiweMessageParameters,
|
225
|
+
type VerifySiweMessageReturnType,
|
226
|
+
verifySiweMessage,
|
227
|
+
} from '../../actions/siwe/verifySiweMessage.js'
|
223
228
|
import {
|
224
229
|
type PrepareTransactionRequestParameters,
|
225
230
|
type PrepareTransactionRequestRequest,
|
@@ -1511,9 +1516,40 @@ export type PublicActions<
|
|
1511
1516
|
accountOverride
|
1512
1517
|
>
|
1513
1518
|
>
|
1519
|
+
/**
|
1520
|
+
* Verify that a message was signed by the provided address.
|
1521
|
+
*
|
1522
|
+
* Compatible with Smart Contract Accounts & Externally Owned Accounts via [ERC-6492](https://eips.ethereum.org/EIPS/eip-6492).
|
1523
|
+
*
|
1524
|
+
* - Docs {@link https://viem.sh/docs/actions/public/verifyMessage}
|
1525
|
+
*
|
1526
|
+
* @param parameters - {@link VerifyMessageParameters}
|
1527
|
+
* @returns Whether or not the signature is valid. {@link VerifyMessageReturnType}
|
1528
|
+
*/
|
1514
1529
|
verifyMessage: (
|
1515
1530
|
args: VerifyMessageParameters,
|
1516
1531
|
) => Promise<VerifyMessageReturnType>
|
1532
|
+
/**
|
1533
|
+
* Verifies [EIP-4361](https://eips.ethereum.org/EIPS/eip-4361) formatted message was signed.
|
1534
|
+
*
|
1535
|
+
* Compatible with Smart Contract Accounts & Externally Owned Accounts via [ERC-6492](https://eips.ethereum.org/EIPS/eip-6492).
|
1536
|
+
*
|
1537
|
+
* - Docs {@link https://viem.sh/docs/siwe/actions/verifySiweMessage}
|
1538
|
+
*
|
1539
|
+
* @param parameters - {@link VerifySiweMessageParameters}
|
1540
|
+
* @returns Whether or not the signature is valid. {@link VerifySiweMessageReturnType}
|
1541
|
+
*/
|
1542
|
+
verifySiweMessage: (
|
1543
|
+
args: VerifySiweMessageParameters,
|
1544
|
+
) => Promise<VerifySiweMessageReturnType>
|
1545
|
+
/**
|
1546
|
+
* Verify that typed data was signed by the provided address.
|
1547
|
+
*
|
1548
|
+
* - Docs {@link https://viem.sh/docs/actions/public/verifyTypedData}
|
1549
|
+
*
|
1550
|
+
* @param parameters - {@link VerifyTypedDataParameters}
|
1551
|
+
* @returns Whether or not the signature is valid. {@link VerifyTypedDataReturnType}
|
1552
|
+
*/
|
1517
1553
|
verifyTypedData: (
|
1518
1554
|
args: VerifyTypedDataParameters,
|
1519
1555
|
) => Promise<VerifyTypedDataReturnType>
|
@@ -1807,6 +1843,7 @@ export function publicActions<
|
|
1807
1843
|
sendRawTransaction: (args) => sendRawTransaction(client, args),
|
1808
1844
|
simulateContract: (args) => simulateContract(client, args),
|
1809
1845
|
verifyMessage: (args) => verifyMessage(client, args),
|
1846
|
+
verifySiweMessage: (args) => verifySiweMessage(client, args),
|
1810
1847
|
verifyTypedData: (args) => verifyTypedData(client, args),
|
1811
1848
|
uninstallFilter: (args) => uninstallFilter(client, args),
|
1812
1849
|
waitForTransactionReceipt: (args) =>
|
package/errors/siwe.ts
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
import { BaseError } from './base.js'
|
2
|
+
|
3
|
+
export type SiweInvalidMessageFieldErrorType = SiweInvalidMessageFieldError & {
|
4
|
+
name: 'SiweInvalidMessageFieldError'
|
5
|
+
}
|
6
|
+
export class SiweInvalidMessageFieldError extends BaseError {
|
7
|
+
override name = 'SiweInvalidMessageFieldError'
|
8
|
+
constructor(parameters: {
|
9
|
+
docsPath?: string | undefined
|
10
|
+
field: string
|
11
|
+
metaMessages?: string[] | undefined
|
12
|
+
}) {
|
13
|
+
const { docsPath, field, metaMessages } = parameters
|
14
|
+
super(`Invalid Sign-In with Ethereum message field "${field}".`, {
|
15
|
+
docsPath,
|
16
|
+
docsSlug: 'TODO',
|
17
|
+
metaMessages,
|
18
|
+
})
|
19
|
+
}
|
20
|
+
}
|
package/errors/version.ts
CHANGED
@@ -1 +1 @@
|
|
1
|
-
export const version = '2.
|
1
|
+
export const version = '2.12.1'
|
package/node/trustedSetups.ts
CHANGED
@@ -1,4 +1,12 @@
|
|
1
|
-
import { resolve } from 'node:path'
|
1
|
+
import { dirname, resolve } from 'node:path'
|
2
|
+
import { fileURLToPath } from 'node:url'
|
3
|
+
|
4
|
+
const __filename = fileURLToPath(
|
5
|
+
// import.meta' meta-property is only allowed when the '--module' option is 'es2020', 'es2022', 'esnext', 'system', 'node16', or 'nodenext'
|
6
|
+
// @ts-ignore
|
7
|
+
import.meta.url,
|
8
|
+
)
|
9
|
+
const __dirname = dirname(__filename)
|
2
10
|
|
3
11
|
export const mainnetTrustedSetupPath = resolve(
|
4
12
|
__dirname,
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "viem",
|
3
3
|
"description": "TypeScript Interface for Ethereum",
|
4
|
-
"version": "2.
|
4
|
+
"version": "2.12.1",
|
5
5
|
"main": "./_cjs/index.js",
|
6
6
|
"module": "./_esm/index.js",
|
7
7
|
"types": "./_types/index.d.ts",
|
@@ -68,6 +68,11 @@
|
|
68
68
|
"import": "./_esm/op-stack/index.js",
|
69
69
|
"default": "./_cjs/op-stack/index.js"
|
70
70
|
},
|
71
|
+
"./siwe": {
|
72
|
+
"types": "./_types/siwe/index.d.ts",
|
73
|
+
"import": "./_esm/siwe/index.js",
|
74
|
+
"default": "./_cjs/siwe/index.js"
|
75
|
+
},
|
71
76
|
"./utils": {
|
72
77
|
"types": "./_types/utils/index.d.ts",
|
73
78
|
"import": "./_esm/utils/index.js",
|
@@ -114,6 +119,9 @@
|
|
114
119
|
"op-stack": [
|
115
120
|
"./_types/op-stack/index.d.ts"
|
116
121
|
],
|
122
|
+
"siwe": [
|
123
|
+
"./_types/siwe/index.d.ts"
|
124
|
+
],
|
117
125
|
"utils": [
|
118
126
|
"./_types/utils/index.d.ts"
|
119
127
|
],
|
package/siwe/index.ts
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
export {
|
2
|
+
verifySiweMessage,
|
3
|
+
type VerifySiweMessageParameters,
|
4
|
+
type VerifySiweMessageReturnType,
|
5
|
+
type VerifySiweMessageErrorType,
|
6
|
+
} from '../actions/siwe/verifySiweMessage.js'
|
7
|
+
|
8
|
+
export {
|
9
|
+
createSiweMessage,
|
10
|
+
type CreateSiweMessageParameters,
|
11
|
+
type CreateSiweMessageReturnType,
|
12
|
+
type CreateSiweMessageErrorType,
|
13
|
+
} from '../utils/siwe/createSiweMessage.js'
|
14
|
+
|
15
|
+
export { generateSiweNonce } from '../utils/siwe/generateSiweNonce.js'
|
16
|
+
export { parseSiweMessage } from '../utils/siwe/parseSiweMessage.js'
|
17
|
+
|
18
|
+
export {
|
19
|
+
validateSiweMessage,
|
20
|
+
type ValidateSiweMessageParameters,
|
21
|
+
type ValidateSiweMessageReturnType,
|
22
|
+
} from '../utils/siwe/validateSiweMessage.js'
|
23
|
+
|
24
|
+
export type { SiweMessage } from '../utils/siwe/types.js'
|
25
|
+
|
26
|
+
export {
|
27
|
+
type SiweInvalidMessageFieldErrorType,
|
28
|
+
SiweInvalidMessageFieldError,
|
29
|
+
} from '../errors/siwe.js'
|
@@ -23,8 +23,9 @@ export function isAddress(
|
|
23
23
|
options?: IsAddressOptions | undefined,
|
24
24
|
): address is Address {
|
25
25
|
const { strict = true } = options ?? {}
|
26
|
+
const cacheKey = `${address}.${strict}`
|
26
27
|
|
27
|
-
if (isAddressCache.has(
|
28
|
+
if (isAddressCache.has(cacheKey)) return isAddressCache.get(cacheKey)!
|
28
29
|
|
29
30
|
const result = (() => {
|
30
31
|
if (!addressRegex.test(address)) return false
|
@@ -32,6 +33,6 @@ export function isAddress(
|
|
32
33
|
if (strict) return checksumAddress(address as Address) === address
|
33
34
|
return true
|
34
35
|
})()
|
35
|
-
isAddressCache.set(
|
36
|
+
isAddressCache.set(cacheKey, result)
|
36
37
|
return result
|
37
38
|
}
|
@@ -0,0 +1,178 @@
|
|
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 (
|
65
|
+
!(
|
66
|
+
domainRegex.test(domain) ||
|
67
|
+
ipRegex.test(domain) ||
|
68
|
+
localhostRegex.test(domain)
|
69
|
+
)
|
70
|
+
)
|
71
|
+
throw new SiweInvalidMessageFieldError({
|
72
|
+
field: 'domain',
|
73
|
+
metaMessages: [
|
74
|
+
'- Domain must be an RFC 3986 authority.',
|
75
|
+
'- See https://www.rfc-editor.org/rfc/rfc3986',
|
76
|
+
'',
|
77
|
+
`Provided value: ${domain}`,
|
78
|
+
],
|
79
|
+
})
|
80
|
+
if (!nonceRegex.test(nonce))
|
81
|
+
throw new SiweInvalidMessageFieldError({
|
82
|
+
field: 'nonce',
|
83
|
+
metaMessages: [
|
84
|
+
'- Nonce must be at least 8 characters.',
|
85
|
+
'- Nonce must be alphanumeric.',
|
86
|
+
'',
|
87
|
+
`Provided value: ${nonce}`,
|
88
|
+
],
|
89
|
+
})
|
90
|
+
if (!isUri(uri))
|
91
|
+
throw new SiweInvalidMessageFieldError({
|
92
|
+
field: 'uri',
|
93
|
+
metaMessages: [
|
94
|
+
'- URI must be a RFC 3986 URI referring to the resource that is the subject of the signing.',
|
95
|
+
'- See https://www.rfc-editor.org/rfc/rfc3986',
|
96
|
+
'',
|
97
|
+
`Provided value: ${uri}`,
|
98
|
+
],
|
99
|
+
})
|
100
|
+
if (version !== '1')
|
101
|
+
throw new SiweInvalidMessageFieldError({
|
102
|
+
field: 'version',
|
103
|
+
metaMessages: [
|
104
|
+
"- Version must be '1'.",
|
105
|
+
'',
|
106
|
+
`Provided value: ${version}`,
|
107
|
+
],
|
108
|
+
})
|
109
|
+
|
110
|
+
// Optional fields
|
111
|
+
if (scheme && !schemeRegex.test(scheme))
|
112
|
+
throw new SiweInvalidMessageFieldError({
|
113
|
+
field: 'scheme',
|
114
|
+
metaMessages: [
|
115
|
+
'- Scheme must be an RFC 3986 URI scheme.',
|
116
|
+
'- See https://www.rfc-editor.org/rfc/rfc3986#section-3.1',
|
117
|
+
'',
|
118
|
+
`Provided value: ${scheme}`,
|
119
|
+
],
|
120
|
+
})
|
121
|
+
const statement = parameters.statement
|
122
|
+
if (statement?.includes('\n'))
|
123
|
+
throw new SiweInvalidMessageFieldError({
|
124
|
+
field: 'statement',
|
125
|
+
metaMessages: [
|
126
|
+
"- Statement must not include '\\n'.",
|
127
|
+
'',
|
128
|
+
`Provided value: ${statement}`,
|
129
|
+
],
|
130
|
+
})
|
131
|
+
}
|
132
|
+
|
133
|
+
// Construct message
|
134
|
+
const address = getAddress(parameters.address)
|
135
|
+
const origin = (() => {
|
136
|
+
if (scheme) return `${scheme}://${domain}`
|
137
|
+
return domain
|
138
|
+
})()
|
139
|
+
const statement = (() => {
|
140
|
+
if (!parameters.statement) return ''
|
141
|
+
return `\n${parameters.statement}\n`
|
142
|
+
})()
|
143
|
+
const prefix = `${origin} wants you to sign in with your Ethereum account:\n${address}\n${statement}`
|
144
|
+
|
145
|
+
let suffix = `URI: ${uri}\nVersion: ${version}\nChain ID: ${chainId}\nNonce: ${nonce}\nIssued At: ${issuedAt.toISOString()}`
|
146
|
+
|
147
|
+
if (expirationTime)
|
148
|
+
suffix += `\nExpiration Time: ${expirationTime.toISOString()}`
|
149
|
+
if (notBefore) suffix += `\nNot Before: ${notBefore.toISOString()}`
|
150
|
+
if (requestId) suffix += `\nRequest ID: ${requestId}`
|
151
|
+
if (resources) {
|
152
|
+
let content = '\nResources:'
|
153
|
+
for (const resource of resources) {
|
154
|
+
if (!isUri(resource))
|
155
|
+
throw new SiweInvalidMessageFieldError({
|
156
|
+
field: 'resources',
|
157
|
+
metaMessages: [
|
158
|
+
'- Every resource must be a RFC 3986 URI.',
|
159
|
+
'- See https://www.rfc-editor.org/rfc/rfc3986',
|
160
|
+
'',
|
161
|
+
`Provided value: ${resource}`,
|
162
|
+
],
|
163
|
+
})
|
164
|
+
content += `\n- ${resource}`
|
165
|
+
}
|
166
|
+
suffix += content
|
167
|
+
}
|
168
|
+
|
169
|
+
return `${prefix}\n${suffix}`
|
170
|
+
}
|
171
|
+
|
172
|
+
const domainRegex =
|
173
|
+
/^([a-zA-Z0-9][-a-zA-Z0-9]{0,61}[a-zA-Z0-9])\.[a-zA-Z]{2,}(:[0-9]{1,5})?$/
|
174
|
+
const ipRegex =
|
175
|
+
/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(:[0-9]{1,5})?$/
|
176
|
+
const localhostRegex = /^localhost(:[0-9]{1,5})?$/
|
177
|
+
const nonceRegex = /^[a-zA-Z0-9]{8,}$/
|
178
|
+
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
|
+
}
|