thirdweb 5.34.0-nightly-f6ff5a78fc2d65f0f250b154f1405210ca57ce0a-20240707000358 → 5.34.0-nightly-325416ea19905901f30e795cbf93cb8a085be02f-20240708203622
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.
- package/dist/cjs/auth/core/verify-jwt.js +1 -1
- package/dist/cjs/auth/core/verify-jwt.js.map +1 -1
- package/dist/cjs/auth/verify-hash.js +98 -0
- package/dist/cjs/auth/verify-hash.js.map +1 -0
- package/dist/cjs/auth/verify-signature.js +5 -60
- package/dist/cjs/auth/verify-signature.js.map +1 -1
- package/dist/cjs/auth/verify-typed-data.js +80 -0
- package/dist/cjs/auth/verify-typed-data.js.map +1 -0
- package/dist/cjs/chains/chain-definitions/blast.js +17 -0
- package/dist/cjs/chains/chain-definitions/blast.js.map +1 -0
- package/dist/cjs/exports/chains.js +3 -1
- package/dist/cjs/exports/chains.js.map +1 -1
- package/dist/cjs/exports/extensions/erc20.js +3 -1
- package/dist/cjs/exports/extensions/erc20.js.map +1 -1
- package/dist/cjs/exports/utils.js +10 -1
- package/dist/cjs/exports/utils.js.map +1 -1
- package/dist/cjs/extensions/erc1271/checkContractWalletSignature.js +1 -0
- package/dist/cjs/extensions/erc1271/checkContractWalletSignature.js.map +1 -1
- package/dist/cjs/extensions/erc1271/checkContractWalletSignedTypedData.js +1 -0
- package/dist/cjs/extensions/erc1271/checkContractWalletSignedTypedData.js.map +1 -1
- package/dist/cjs/extensions/erc20/write/transferBatch.js +61 -0
- package/dist/cjs/extensions/erc20/write/transferBatch.js.map +1 -0
- package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.js +21 -12
- package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.js.map +1 -1
- package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/PayWIthCreditCard.js +1 -1
- package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatSteps.js +4 -4
- package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatTxDetailsTable.js +1 -1
- package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/main/useBuyTxStates.js +1 -3
- package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/main/useBuyTxStates.js.map +1 -1
- package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/main/useUISelectionStates.js +1 -4
- package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/main/useUISelectionStates.js.map +1 -1
- package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.js +1 -1
- package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/Fees.js +4 -4
- package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/PayWithCrypto.js +1 -1
- package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/tx-history/BuyTxHistoryButton.js +1 -1
- package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/tx-history/TokenInfoRow.js +1 -1
- package/dist/cjs/utils/hashing/hashTypedData.js +122 -0
- package/dist/cjs/utils/hashing/hashTypedData.js.map +1 -0
- package/dist/cjs/utils/jwt/decode-jwt.js +2 -2
- package/dist/cjs/utils/jwt/decode-jwt.js.map +1 -1
- package/dist/cjs/utils/jwt/refresh-jwt.js +1 -1
- package/dist/cjs/utils/jwt/refresh-jwt.js.map +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/auth/core/verify-jwt.js +2 -2
- package/dist/esm/auth/core/verify-jwt.js.map +1 -1
- package/dist/esm/auth/verify-hash.js +95 -0
- package/dist/esm/auth/verify-hash.js.map +1 -0
- package/dist/esm/auth/verify-signature.js +6 -61
- package/dist/esm/auth/verify-signature.js.map +1 -1
- package/dist/esm/auth/verify-typed-data.js +77 -0
- package/dist/esm/auth/verify-typed-data.js.map +1 -0
- package/dist/esm/chains/chain-definitions/blast.js +14 -0
- package/dist/esm/chains/chain-definitions/blast.js.map +1 -0
- package/dist/esm/exports/chains.js +1 -0
- package/dist/esm/exports/chains.js.map +1 -1
- package/dist/esm/exports/extensions/erc20.js +1 -0
- package/dist/esm/exports/extensions/erc20.js.map +1 -1
- package/dist/esm/exports/utils.js +6 -0
- package/dist/esm/exports/utils.js.map +1 -1
- package/dist/esm/extensions/erc1271/checkContractWalletSignature.js +1 -0
- package/dist/esm/extensions/erc1271/checkContractWalletSignature.js.map +1 -1
- package/dist/esm/extensions/erc1271/checkContractWalletSignedTypedData.js +1 -0
- package/dist/esm/extensions/erc1271/checkContractWalletSignedTypedData.js.map +1 -1
- package/dist/esm/extensions/erc20/write/transferBatch.js +58 -0
- package/dist/esm/extensions/erc20/write/transferBatch.js.map +1 -0
- package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.js +21 -12
- package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.js.map +1 -1
- package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/PayWIthCreditCard.js +1 -1
- package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatSteps.js +4 -4
- package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatTxDetailsTable.js +1 -1
- package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/main/useBuyTxStates.js +1 -3
- package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/main/useBuyTxStates.js.map +1 -1
- package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/main/useUISelectionStates.js +1 -4
- package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/main/useUISelectionStates.js.map +1 -1
- package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.js +1 -1
- package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/Fees.js +4 -4
- package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/PayWithCrypto.js +1 -1
- package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/tx-history/BuyTxHistoryButton.js +1 -1
- package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/tx-history/TokenInfoRow.js +1 -1
- package/dist/esm/utils/hashing/hashTypedData.js +118 -0
- package/dist/esm/utils/hashing/hashTypedData.js.map +1 -0
- package/dist/esm/utils/jwt/decode-jwt.js +1 -1
- package/dist/esm/utils/jwt/decode-jwt.js.map +1 -1
- package/dist/esm/utils/jwt/refresh-jwt.js +2 -2
- package/dist/esm/utils/jwt/refresh-jwt.js.map +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/types/auth/verify-hash.d.ts +45 -0
- package/dist/types/auth/verify-hash.d.ts.map +1 -0
- package/dist/types/auth/verify-signature.d.ts.map +1 -1
- package/dist/types/auth/verify-typed-data.d.ts +75 -0
- package/dist/types/auth/verify-typed-data.d.ts.map +1 -0
- package/dist/types/chains/chain-definitions/blast.d.ts +27 -0
- package/dist/types/chains/chain-definitions/blast.d.ts.map +1 -0
- package/dist/types/exports/chains.d.ts +1 -0
- package/dist/types/exports/chains.d.ts.map +1 -1
- package/dist/types/exports/extensions/erc20.d.ts +1 -0
- package/dist/types/exports/extensions/erc20.d.ts.map +1 -1
- package/dist/types/exports/utils.d.ts +4 -0
- package/dist/types/exports/utils.d.ts.map +1 -1
- package/dist/types/extensions/erc1271/checkContractWalletSignature.d.ts +1 -0
- package/dist/types/extensions/erc1271/checkContractWalletSignature.d.ts.map +1 -1
- package/dist/types/extensions/erc1271/checkContractWalletSignedTypedData.d.ts +1 -0
- package/dist/types/extensions/erc1271/checkContractWalletSignedTypedData.d.ts.map +1 -1
- package/dist/types/extensions/erc20/write/transferBatch.d.ts +42 -0
- package/dist/types/extensions/erc20/write/transferBatch.d.ts.map +1 -0
- package/dist/types/react/web/ui/ConnectWallet/screens/Buy/main/useBuyTxStates.d.ts.map +1 -1
- package/dist/types/react/web/ui/ConnectWallet/screens/Buy/main/useUISelectionStates.d.ts.map +1 -1
- package/dist/types/utils/hashing/hashTypedData.d.ts +17 -0
- package/dist/types/utils/hashing/hashTypedData.d.ts.map +1 -0
- package/dist/types/utils/jwt/decode-jwt.d.ts +1 -1
- package/dist/types/utils/jwt/decode-jwt.d.ts.map +1 -1
- package/dist/types/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/auth/core/verify-jwt.ts +2 -2
- package/src/auth/verify-hash.test.ts +66 -0
- package/src/auth/verify-hash.ts +126 -0
- package/src/auth/verify-signature.ts +6 -77
- package/src/auth/verify-typed-data.test.ts +82 -0
- package/src/auth/verify-typed-data.ts +110 -0
- package/src/chains/chain-definitions/blast.ts +14 -0
- package/src/exports/chains.ts +1 -0
- package/src/exports/extensions/erc20.ts +4 -0
- package/src/exports/utils.ts +8 -0
- package/src/extensions/erc1271/checkContractWalletSignature.ts +1 -0
- package/src/extensions/erc1271/checkContractWalletSignedTypedData.ts +1 -0
- package/src/extensions/erc20/write/transferBatch.ts +78 -0
- package/src/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.tsx +42 -12
- package/src/react/web/ui/ConnectWallet/screens/Buy/PayWIthCreditCard.tsx +1 -1
- package/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatSteps.tsx +5 -5
- package/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatTxDetailsTable.tsx +1 -1
- package/src/react/web/ui/ConnectWallet/screens/Buy/main/useBuyTxStates.ts +1 -5
- package/src/react/web/ui/ConnectWallet/screens/Buy/main/useUISelectionStates.ts +1 -6
- package/src/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.tsx +2 -2
- package/src/react/web/ui/ConnectWallet/screens/Buy/swap/Fees.tsx +4 -4
- package/src/react/web/ui/ConnectWallet/screens/Buy/swap/PayWithCrypto.tsx +1 -1
- package/src/react/web/ui/ConnectWallet/screens/Buy/tx-history/BuyTxHistoryButton.tsx +1 -1
- package/src/react/web/ui/ConnectWallet/screens/Buy/tx-history/TokenInfoRow.tsx +1 -1
- package/src/utils/hashing/hashTypedData.test.ts +207 -0
- package/src/utils/hashing/hashTypedData.ts +210 -0
- package/src/utils/jwt/decode-jwt.ts +1 -1
- package/src/utils/jwt/refresh-jwt.ts +2 -2
- package/src/version.ts +1 -1
@@ -1,7 +1,6 @@
|
|
1
1
|
import { useState } from "react";
|
2
2
|
import { polygon } from "../../../../../../../chains/chain-definitions/polygon.js";
|
3
3
|
import type { Chain } from "../../../../../../../chains/types.js";
|
4
|
-
import { formatNumber } from "../../../../../../../utils/formatNumber.js";
|
5
4
|
import { toEther } from "../../../../../../../utils/units.js";
|
6
5
|
import type { PayUIOptions } from "../../../../../../core/hooks/connection/ConnectButtonProps.js";
|
7
6
|
import { useActiveWalletChain } from "../../../../../hooks/wallets/useActiveWalletChain.js";
|
@@ -24,11 +23,7 @@ export function useUISelectionStates(options: {
|
|
24
23
|
// buy token amount ---------------------------------------------------------
|
25
24
|
const initialTokenAmount =
|
26
25
|
payOptions.prefillBuy?.amount ||
|
27
|
-
(buyForTx
|
28
|
-
? String(
|
29
|
-
formatNumber(Number(toEther(buyForTx.cost - buyForTx.balance)), 4),
|
30
|
-
)
|
31
|
-
: "");
|
26
|
+
(buyForTx ? String(toEther(buyForTx.cost - buyForTx.balance)) : "");
|
32
27
|
|
33
28
|
const [tokenAmount, setTokenAmount] = useState<string>(initialTokenAmount);
|
34
29
|
const deferredTokenAmount = useDebouncedValue(tokenAmount, 300);
|
@@ -84,7 +84,7 @@ export function SwapConfirmationScreen(props: {
|
|
84
84
|
<ConfirmItem label="Pay">
|
85
85
|
<RenderTokenInfo
|
86
86
|
chain={props.fromChain}
|
87
|
-
amount={String(formatNumber(Number(props.fromAmount),
|
87
|
+
amount={String(formatNumber(Number(props.fromAmount), 6))}
|
88
88
|
symbol={props.fromTokenSymbol || ""}
|
89
89
|
token={props.fromToken}
|
90
90
|
client={props.client}
|
@@ -95,7 +95,7 @@ export function SwapConfirmationScreen(props: {
|
|
95
95
|
<ConfirmItem label="Receive">
|
96
96
|
<RenderTokenInfo
|
97
97
|
chain={props.toChain}
|
98
|
-
amount={String(formatNumber(Number(props.toAmount),
|
98
|
+
amount={String(formatNumber(Number(props.toAmount), 6))}
|
99
99
|
symbol={props.toTokenSymbol}
|
100
100
|
token={props.toToken}
|
101
101
|
client={props.client}
|
@@ -21,7 +21,7 @@ export function SwapFees(props: {
|
|
21
21
|
}}
|
22
22
|
>
|
23
23
|
{props.quote.processingFees.map((fee) => {
|
24
|
-
const feeAmount = formatNumber(Number(fee.amount),
|
24
|
+
const feeAmount = formatNumber(Number(fee.amount), 6);
|
25
25
|
return (
|
26
26
|
<Container
|
27
27
|
key={`${fee.token.chainId}_${fee.token.tokenAddress}_${feeAmount}`}
|
@@ -61,14 +61,14 @@ export function FiatFees(props: {
|
|
61
61
|
Amount
|
62
62
|
</Text>
|
63
63
|
<Text color="primaryText" inline>
|
64
|
-
{formatNumber(Number(props.quote.fromCurrency.amount),
|
64
|
+
{formatNumber(Number(props.quote.fromCurrency.amount), 2)}{" "}
|
65
65
|
{props.quote.fromCurrency.currencySymbol}
|
66
66
|
</Text>
|
67
67
|
</div>
|
68
68
|
|
69
69
|
{/* Processing Fees */}
|
70
70
|
{props.quote.processingFees.map((fee, i) => {
|
71
|
-
const feeAmount = formatNumber(Number(fee.amount),
|
71
|
+
const feeAmount = formatNumber(Number(fee.amount), 6);
|
72
72
|
|
73
73
|
return (
|
74
74
|
<div
|
@@ -106,7 +106,7 @@ export function FiatFees(props: {
|
|
106
106
|
Total
|
107
107
|
</Text>
|
108
108
|
<Text color="primaryText" inline>
|
109
|
-
{formatNumber(Number(props.quote.fromCurrencyWithFees.amount),
|
109
|
+
{formatNumber(Number(props.quote.fromCurrencyWithFees.amount), 6)}{" "}
|
110
110
|
{props.quote.fromCurrencyWithFees.currencySymbol}
|
111
111
|
</Text>
|
112
112
|
</div>
|
@@ -46,7 +46,7 @@ export function TokenInfoRow(props: {
|
|
46
46
|
client={props.client}
|
47
47
|
/>
|
48
48
|
<Text color="primaryText">
|
49
|
-
{formatNumber(Number(props.tokenAmount),
|
49
|
+
{formatNumber(Number(props.tokenAmount), 6)} {props.tokenSymbol}
|
50
50
|
</Text>
|
51
51
|
</Container>
|
52
52
|
<Text size="sm">{name}</Text>
|
@@ -0,0 +1,207 @@
|
|
1
|
+
import { expect, test } from "vitest";
|
2
|
+
|
3
|
+
import { pad } from "viem";
|
4
|
+
import { typedData } from "../../../test/src/typed-data.js";
|
5
|
+
import { toHex } from "../encoding/hex.js";
|
6
|
+
import { hashTypedData } from "./hashTypedData.js";
|
7
|
+
|
8
|
+
test("default", () => {
|
9
|
+
expect(
|
10
|
+
hashTypedData({
|
11
|
+
...typedData.basic,
|
12
|
+
primaryType: "Mail",
|
13
|
+
}),
|
14
|
+
).toMatchInlineSnapshot(
|
15
|
+
'"0x448f54762ef8ecccdc4d19bb7d467161383cd4b271617a8cee05c790eb745d74"',
|
16
|
+
);
|
17
|
+
});
|
18
|
+
|
19
|
+
test("complex", () => {
|
20
|
+
expect(
|
21
|
+
hashTypedData({
|
22
|
+
...typedData.complex,
|
23
|
+
primaryType: "Mail",
|
24
|
+
}),
|
25
|
+
).toMatchInlineSnapshot(
|
26
|
+
'"0x9a74cb859ad30835ffb2da406423233c212cf6dd78e6c2c98b0c9289568954ae"',
|
27
|
+
);
|
28
|
+
});
|
29
|
+
|
30
|
+
test("no domain", () => {
|
31
|
+
expect(
|
32
|
+
hashTypedData({
|
33
|
+
...typedData.complex,
|
34
|
+
domain: undefined,
|
35
|
+
primaryType: "Mail",
|
36
|
+
}),
|
37
|
+
).toMatchInlineSnapshot(
|
38
|
+
'"0x14ed1dbbfecbe5de3919f7ea47daafdf3a29dfbb60dd88d85509f79773d503a5"',
|
39
|
+
);
|
40
|
+
expect(
|
41
|
+
hashTypedData({
|
42
|
+
...typedData.complex,
|
43
|
+
domain: {},
|
44
|
+
primaryType: "Mail",
|
45
|
+
}),
|
46
|
+
).toMatchInlineSnapshot(
|
47
|
+
'"0x14ed1dbbfecbe5de3919f7ea47daafdf3a29dfbb60dd88d85509f79773d503a5"',
|
48
|
+
);
|
49
|
+
});
|
50
|
+
|
51
|
+
test("domain: empty name", () => {
|
52
|
+
expect(
|
53
|
+
hashTypedData({
|
54
|
+
...typedData.complex,
|
55
|
+
domain: { name: "" },
|
56
|
+
primaryType: "Mail",
|
57
|
+
}),
|
58
|
+
).toMatchInlineSnapshot(
|
59
|
+
'"0xc3f4f9ebd774352940f60aebbc83fcee20d0b17eb42bd1b20c91a748001ecb53"',
|
60
|
+
);
|
61
|
+
});
|
62
|
+
|
63
|
+
test("minimal valid typed message", () => {
|
64
|
+
const hash = hashTypedData({
|
65
|
+
types: {
|
66
|
+
EIP712Domain: [],
|
67
|
+
},
|
68
|
+
primaryType: "EIP712Domain",
|
69
|
+
domain: {},
|
70
|
+
});
|
71
|
+
|
72
|
+
expect(hash).toMatchInlineSnapshot(
|
73
|
+
'"0x8d4a3f4082945b7879e2b55f181c31a77c8c0a464b70669458abbaaf99de4c38"',
|
74
|
+
);
|
75
|
+
});
|
76
|
+
|
77
|
+
test("typed message with a domain separator that uses all fields.", () => {
|
78
|
+
const hash = hashTypedData({
|
79
|
+
types: {
|
80
|
+
EIP712Domain: [
|
81
|
+
{
|
82
|
+
name: "name",
|
83
|
+
type: "string",
|
84
|
+
},
|
85
|
+
{
|
86
|
+
name: "version",
|
87
|
+
type: "string",
|
88
|
+
},
|
89
|
+
{
|
90
|
+
name: "chainId",
|
91
|
+
type: "uint256",
|
92
|
+
},
|
93
|
+
{
|
94
|
+
name: "verifyingContract",
|
95
|
+
type: "address",
|
96
|
+
},
|
97
|
+
{
|
98
|
+
name: "salt",
|
99
|
+
type: "bytes32",
|
100
|
+
},
|
101
|
+
],
|
102
|
+
},
|
103
|
+
primaryType: "EIP712Domain",
|
104
|
+
domain: {
|
105
|
+
name: "example.metamask.io",
|
106
|
+
version: "1",
|
107
|
+
chainId: 1n,
|
108
|
+
verifyingContract: "0x0000000000000000000000000000000000000000",
|
109
|
+
salt: pad(toHex(new Uint8Array([1, 2, 3])), { dir: "right" }),
|
110
|
+
},
|
111
|
+
});
|
112
|
+
|
113
|
+
expect(hash).toMatchInlineSnapshot(
|
114
|
+
'"0x54ffed5209a17ac210ef3823740b3852ee9cd518b84ee39f0a3fa7f2f9b4205b"',
|
115
|
+
);
|
116
|
+
});
|
117
|
+
|
118
|
+
test("typed message with only custom domain separator fields", () => {
|
119
|
+
const hash = hashTypedData({
|
120
|
+
types: {
|
121
|
+
EIP712Domain: [
|
122
|
+
{
|
123
|
+
name: "customName",
|
124
|
+
type: "string",
|
125
|
+
},
|
126
|
+
{
|
127
|
+
name: "customVersion",
|
128
|
+
type: "string",
|
129
|
+
},
|
130
|
+
{
|
131
|
+
name: "customChainId",
|
132
|
+
type: "uint256",
|
133
|
+
},
|
134
|
+
{
|
135
|
+
name: "customVerifyingContract",
|
136
|
+
type: "address",
|
137
|
+
},
|
138
|
+
{
|
139
|
+
name: "customSalt",
|
140
|
+
type: "bytes32",
|
141
|
+
},
|
142
|
+
{
|
143
|
+
name: "extraField",
|
144
|
+
type: "string",
|
145
|
+
},
|
146
|
+
],
|
147
|
+
},
|
148
|
+
primaryType: "EIP712Domain",
|
149
|
+
domain: {
|
150
|
+
customName: "example.metamask.io",
|
151
|
+
customVersion: "1",
|
152
|
+
customChainId: 1n,
|
153
|
+
customVerifyingContract: "0x0000000000000000000000000000000000000000",
|
154
|
+
customSalt: pad(toHex(new Uint8Array([1, 2, 3])), { dir: "right" }),
|
155
|
+
extraField: "stuff",
|
156
|
+
},
|
157
|
+
});
|
158
|
+
|
159
|
+
expect(hash).toMatchInlineSnapshot(
|
160
|
+
'"0x3efa3ef0305f56ba5bba62000500e29fe82c5314bca2f958c64e31b2498560f8"',
|
161
|
+
);
|
162
|
+
});
|
163
|
+
|
164
|
+
test("typed message with data", () => {
|
165
|
+
const hash = hashTypedData({
|
166
|
+
types: {
|
167
|
+
EIP712Domain: [
|
168
|
+
{
|
169
|
+
name: "name",
|
170
|
+
type: "string",
|
171
|
+
},
|
172
|
+
{
|
173
|
+
name: "version",
|
174
|
+
type: "string",
|
175
|
+
},
|
176
|
+
{
|
177
|
+
name: "chainId",
|
178
|
+
type: "uint256",
|
179
|
+
},
|
180
|
+
{
|
181
|
+
name: "verifyingContract",
|
182
|
+
type: "address",
|
183
|
+
},
|
184
|
+
{
|
185
|
+
name: "salt",
|
186
|
+
type: "bytes32",
|
187
|
+
},
|
188
|
+
],
|
189
|
+
Message: [{ name: "data", type: "string" }],
|
190
|
+
},
|
191
|
+
primaryType: "Message",
|
192
|
+
domain: {
|
193
|
+
name: "example.metamask.io",
|
194
|
+
version: "1",
|
195
|
+
chainId: 1n,
|
196
|
+
verifyingContract: "0x0000000000000000000000000000000000000000",
|
197
|
+
salt: pad(toHex(new Uint8Array([1, 2, 3])), { dir: "right" }),
|
198
|
+
},
|
199
|
+
message: {
|
200
|
+
data: "Hello!",
|
201
|
+
},
|
202
|
+
});
|
203
|
+
|
204
|
+
expect(hash).toMatchInlineSnapshot(
|
205
|
+
'"0xd2669f23b7849020ad41bcbff5b51372793f91320e0f901641945568ed7322be"',
|
206
|
+
);
|
207
|
+
});
|
@@ -0,0 +1,210 @@
|
|
1
|
+
import {
|
2
|
+
type AbiParameter,
|
3
|
+
type TypedData,
|
4
|
+
type TypedDataDefinition,
|
5
|
+
concat,
|
6
|
+
getTypesForEIP712Domain,
|
7
|
+
hashDomain,
|
8
|
+
validateTypedData,
|
9
|
+
} from "viem";
|
10
|
+
import { encodeAbiParameters } from "../abi/encodeAbiParameters.js";
|
11
|
+
import { type Hex, toHex } from "../encoding/hex.js";
|
12
|
+
import { keccak256 } from "./keccak256.js";
|
13
|
+
|
14
|
+
type MessageTypeProperty = {
|
15
|
+
name: string;
|
16
|
+
type: string;
|
17
|
+
};
|
18
|
+
|
19
|
+
export type HashTypedDataParams<
|
20
|
+
typedData extends TypedData | Record<string, unknown> = TypedData,
|
21
|
+
primaryType extends keyof typedData | "EIP712Domain" = keyof typedData,
|
22
|
+
> = TypedDataDefinition<typedData, primaryType>;
|
23
|
+
|
24
|
+
/**
|
25
|
+
* @internal
|
26
|
+
*/
|
27
|
+
export function hashTypedData<
|
28
|
+
const typedData extends TypedData | Record<string, unknown>,
|
29
|
+
primaryType extends keyof typedData | "EIP712Domain",
|
30
|
+
>(parameters: HashTypedDataParams<typedData, primaryType>): Hex {
|
31
|
+
const {
|
32
|
+
domain = {},
|
33
|
+
message,
|
34
|
+
primaryType,
|
35
|
+
} = parameters as HashTypedDataParams;
|
36
|
+
const types = {
|
37
|
+
EIP712Domain: getTypesForEIP712Domain({ domain }),
|
38
|
+
...parameters.types,
|
39
|
+
};
|
40
|
+
|
41
|
+
// Need to do a runtime validation check on addresses, byte ranges, integer ranges, etc
|
42
|
+
// as we can't statically check this with TypeScript.
|
43
|
+
validateTypedData({
|
44
|
+
domain,
|
45
|
+
message,
|
46
|
+
primaryType,
|
47
|
+
types,
|
48
|
+
});
|
49
|
+
|
50
|
+
const parts: Hex[] = ["0x1901"];
|
51
|
+
if (domain)
|
52
|
+
parts.push(
|
53
|
+
hashDomain({
|
54
|
+
domain,
|
55
|
+
types: types as Record<string, MessageTypeProperty[]>,
|
56
|
+
}),
|
57
|
+
);
|
58
|
+
|
59
|
+
if (primaryType !== "EIP712Domain") {
|
60
|
+
const hashedStruct = (() => {
|
61
|
+
const encoded = encodeData({
|
62
|
+
data: message,
|
63
|
+
primaryType,
|
64
|
+
types: types as Record<string, MessageTypeProperty[]>,
|
65
|
+
});
|
66
|
+
return keccak256(encoded);
|
67
|
+
})();
|
68
|
+
|
69
|
+
parts.push(hashedStruct);
|
70
|
+
}
|
71
|
+
|
72
|
+
return keccak256(concat(parts));
|
73
|
+
}
|
74
|
+
|
75
|
+
function encodeData({
|
76
|
+
data,
|
77
|
+
primaryType,
|
78
|
+
types,
|
79
|
+
}: {
|
80
|
+
data: Record<string, unknown>;
|
81
|
+
primaryType: string;
|
82
|
+
types: Record<string, MessageTypeProperty[]>;
|
83
|
+
}) {
|
84
|
+
const encodedTypes: AbiParameter[] = [{ type: "bytes32" }];
|
85
|
+
const encodedValues: unknown[] = [hashType({ primaryType, types })];
|
86
|
+
|
87
|
+
if (!types[primaryType]) throw new Error("Invalid types");
|
88
|
+
for (const field of types[primaryType]) {
|
89
|
+
const [type, value] = encodeField({
|
90
|
+
types,
|
91
|
+
name: field.name,
|
92
|
+
type: field.type,
|
93
|
+
value: data[field.name],
|
94
|
+
});
|
95
|
+
encodedTypes.push(type);
|
96
|
+
encodedValues.push(value);
|
97
|
+
}
|
98
|
+
|
99
|
+
return encodeAbiParameters(encodedTypes, encodedValues);
|
100
|
+
}
|
101
|
+
|
102
|
+
function hashType({
|
103
|
+
primaryType,
|
104
|
+
types,
|
105
|
+
}: {
|
106
|
+
primaryType: string;
|
107
|
+
types: Record<string, MessageTypeProperty[]>;
|
108
|
+
}) {
|
109
|
+
const encodedHashType = toHex(encodeType({ primaryType, types }));
|
110
|
+
return keccak256(encodedHashType);
|
111
|
+
}
|
112
|
+
|
113
|
+
export function encodeType({
|
114
|
+
primaryType,
|
115
|
+
types,
|
116
|
+
}: {
|
117
|
+
primaryType: string;
|
118
|
+
types: Record<string, MessageTypeProperty[]>;
|
119
|
+
}) {
|
120
|
+
let result = "";
|
121
|
+
const unsortedDeps = findTypeDependencies({ primaryType, types });
|
122
|
+
unsortedDeps.delete(primaryType);
|
123
|
+
|
124
|
+
const deps = [primaryType, ...Array.from(unsortedDeps).sort()];
|
125
|
+
for (const type of deps) {
|
126
|
+
if (!types[type]) throw new Error("Invalid types");
|
127
|
+
result += `${type}(${types[type]
|
128
|
+
.map(({ name, type: t }) => `${t} ${name}`)
|
129
|
+
.join(",")})`;
|
130
|
+
}
|
131
|
+
|
132
|
+
return result;
|
133
|
+
}
|
134
|
+
|
135
|
+
function findTypeDependencies(
|
136
|
+
{
|
137
|
+
primaryType: primaryType_,
|
138
|
+
types,
|
139
|
+
}: {
|
140
|
+
primaryType: string;
|
141
|
+
types: Record<string, MessageTypeProperty[]>;
|
142
|
+
},
|
143
|
+
results: Set<string> = new Set(),
|
144
|
+
): Set<string> {
|
145
|
+
const match = primaryType_.match(/^\w*/u);
|
146
|
+
const primaryType = match?.[0] as string;
|
147
|
+
if (results.has(primaryType) || types[primaryType] === undefined) {
|
148
|
+
return results;
|
149
|
+
}
|
150
|
+
|
151
|
+
results.add(primaryType);
|
152
|
+
|
153
|
+
for (const field of types[primaryType]) {
|
154
|
+
findTypeDependencies({ primaryType: field.type, types }, results);
|
155
|
+
}
|
156
|
+
return results;
|
157
|
+
}
|
158
|
+
|
159
|
+
function encodeField({
|
160
|
+
types,
|
161
|
+
name,
|
162
|
+
type,
|
163
|
+
value,
|
164
|
+
}: {
|
165
|
+
types: Record<string, MessageTypeProperty[]>;
|
166
|
+
name: string;
|
167
|
+
type: string;
|
168
|
+
// biome-ignore lint/suspicious/noExplicitAny: Can't anticipate types of nested values
|
169
|
+
value: any;
|
170
|
+
// biome-ignore lint/suspicious/noExplicitAny: Can't anticipate types of nested values
|
171
|
+
}): [type: AbiParameter, value: any] {
|
172
|
+
if (types[type] !== undefined) {
|
173
|
+
return [
|
174
|
+
{ type: "bytes32" },
|
175
|
+
keccak256(encodeData({ data: value, primaryType: type, types })),
|
176
|
+
];
|
177
|
+
}
|
178
|
+
|
179
|
+
if (type === "bytes") {
|
180
|
+
const prepend = value.length % 2 ? "0" : "";
|
181
|
+
value = `0x${prepend + value.slice(2)}`;
|
182
|
+
return [{ type: "bytes32" }, keccak256(value)];
|
183
|
+
}
|
184
|
+
|
185
|
+
if (type === "string") return [{ type: "bytes32" }, keccak256(toHex(value))];
|
186
|
+
|
187
|
+
if (type.lastIndexOf("]") === type.length - 1) {
|
188
|
+
const parsedType = type.slice(0, type.lastIndexOf("["));
|
189
|
+
// biome-ignore lint/suspicious/noExplicitAny: Can't anticipate types of nested values
|
190
|
+
const typeValuePairs = (value as [AbiParameter, any][]).map((item) =>
|
191
|
+
encodeField({
|
192
|
+
name,
|
193
|
+
type: parsedType,
|
194
|
+
types,
|
195
|
+
value: item,
|
196
|
+
}),
|
197
|
+
);
|
198
|
+
return [
|
199
|
+
{ type: "bytes32" },
|
200
|
+
keccak256(
|
201
|
+
encodeAbiParameters(
|
202
|
+
typeValuePairs.map(([t]) => t),
|
203
|
+
typeValuePairs.map(([, v]) => v),
|
204
|
+
),
|
205
|
+
),
|
206
|
+
];
|
207
|
+
}
|
208
|
+
|
209
|
+
return [{ type }, value];
|
210
|
+
}
|
@@ -15,7 +15,7 @@ import type { JWTPayload } from "./types.js";
|
|
15
15
|
* const { payload, signature } = decodeJWT(jwt);
|
16
16
|
* ```
|
17
17
|
*/
|
18
|
-
export function
|
18
|
+
export function decodeJWT(jwt: string) {
|
19
19
|
const [encodedHeader, encodedPayload, encodedSignature] = jwt.split(".");
|
20
20
|
|
21
21
|
if (encodedHeader !== PRECOMPILED_B64_ENCODED_JWT_HEADER) {
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import type { Account } from "../../wallets/interfaces/wallet.js";
|
2
|
-
import {
|
2
|
+
import { decodeJWT } from "./decode-jwt.js";
|
3
3
|
import { encodeJWT } from "./encode-jwt.js";
|
4
4
|
|
5
5
|
const DEFAULT_EXPIRATION_TIME = 60 * 60 * 24;
|
@@ -27,7 +27,7 @@ export type RefreshJWTParams = {
|
|
27
27
|
*/
|
28
28
|
export async function refreshJWT(options: RefreshJWTParams): Promise<string> {
|
29
29
|
const { account, jwt, expirationTime = DEFAULT_EXPIRATION_TIME } = options;
|
30
|
-
const payload =
|
30
|
+
const payload = decodeJWT(jwt).payload;
|
31
31
|
return encodeJWT({
|
32
32
|
payload: {
|
33
33
|
iss: payload.iss,
|
package/src/version.ts
CHANGED
@@ -1 +1 @@
|
|
1
|
-
export const version = "5.34.0-nightly-
|
1
|
+
export const version = "5.34.0-nightly-325416ea19905901f30e795cbf93cb8a085be02f-20240708203622";
|