-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathuseHybridPermitSign.ts
100 lines (89 loc) · 2.72 KB
/
useHybridPermitSign.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
"use client"
import { Address, parseAbi } from "viem"
import { base } from "viem/chains"
import { useAccount, usePublicClient, useSignTypedData } from "wagmi"
import { USDC_BASE } from "@/lib/wallet"
import {
useSignTypedData as usePrivySignTypedData,
useWallets,
} from "@privy-io/react-auth"
/**
* Helper function to sign permit for USDC
* from the connected wallet - can be either
* embedded or smart wallet, or EOA.
*/
export default function useHybridPermitSign() {
const { address: connectedWallet } = useAccount()
const client = usePublicClient()
const { wallets } = useWallets()
const { signTypedDataAsync } = useSignTypedData()
const { signTypedData: privySignTypedData } = usePrivySignTypedData()
async function signPermitUSDC({
owner,
spender,
value,
}: {
owner: Address
spender: Address
value: bigint
}) {
try {
const isEmbeddedWallet = Boolean(
wallets.find(
(wallet) =>
wallet.connectorType === "embedded" &&
wallet.address === connectedWallet
)
)
const ONE_HOUR_IN_BLOCK_TIME = Math.floor(Date.now() / 1000) + 3600
const NONCE = await client?.readContract({
abi: parseAbi([
"function nonces(address) public view returns (uint256)",
]),
address: USDC_BASE,
functionName: "nonces",
args: [owner],
})
if (NONCE === undefined) return null
// Early return if nonce errored
const PAYLOAD = {
message: {
owner,
spender,
value: isEmbeddedWallet ? `0x${value.toString(16)}` : value,
nonce: isEmbeddedWallet ? Number(NONCE) : NONCE,
deadline: isEmbeddedWallet
? // Hex since bigint is not json serializable
// for embedded wallets methods (privy)
`0x${ONE_HOUR_IN_BLOCK_TIME.toString(16)}`
: BigInt(ONE_HOUR_IN_BLOCK_TIME),
},
primaryType: "Permit",
types: {
Permit: [
{ name: "owner", type: "address" },
{ name: "spender", type: "address" },
{ name: "value", type: "uint256" },
{ name: "nonce", type: "uint256" },
{ name: "deadline", type: "uint256" },
],
},
domain: {
name: "USD Coin",
version: "2", // EIP712 version
chainId: base.id,
verifyingContract: USDC_BASE,
},
}
const result: any = await (isEmbeddedWallet
? privySignTypedData
: signTypedDataAsync)(PAYLOAD as any)
return {
signature: result?.signature || result,
expireTime: ONE_HOUR_IN_BLOCK_TIME,
}
} catch (_) {}
return null
}
return { signPermitUSDC }
}