@filoz/synapse-react 0.0.1

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 (68) hide show
  1. package/LICENSE.md +228 -0
  2. package/README.md +32 -0
  3. package/dist/src/calibration.d.ts +9 -0
  4. package/dist/src/calibration.d.ts.map +1 -0
  5. package/dist/src/calibration.js +45 -0
  6. package/dist/src/calibration.js.map +1 -0
  7. package/dist/src/erc20.d.ts +17 -0
  8. package/dist/src/erc20.d.ts.map +1 -0
  9. package/dist/src/erc20.js +57 -0
  10. package/dist/src/erc20.js.map +1 -0
  11. package/dist/src/filsnap.d.ts +5 -0
  12. package/dist/src/filsnap.d.ts.map +1 -0
  13. package/dist/src/filsnap.js +14 -0
  14. package/dist/src/filsnap.js.map +1 -0
  15. package/dist/src/index.d.ts +7 -0
  16. package/dist/src/index.d.ts.map +1 -0
  17. package/dist/src/index.js +7 -0
  18. package/dist/src/index.js.map +1 -0
  19. package/dist/src/payments/index.d.ts +42 -0
  20. package/dist/src/payments/index.d.ts.map +1 -0
  21. package/dist/src/payments/index.js +192 -0
  22. package/dist/src/payments/index.js.map +1 -0
  23. package/dist/src/payments/use-deposit-and-approve.d.ts +11 -0
  24. package/dist/src/payments/use-deposit-and-approve.d.ts.map +1 -0
  25. package/dist/src/payments/use-deposit-and-approve.js +42 -0
  26. package/dist/src/payments/use-deposit-and-approve.js.map +1 -0
  27. package/dist/src/usdfc.d.ts +6 -0
  28. package/dist/src/usdfc.d.ts.map +1 -0
  29. package/dist/src/usdfc.js +15 -0
  30. package/dist/src/usdfc.js.map +1 -0
  31. package/dist/src/warm-storage/index.d.ts +6 -0
  32. package/dist/src/warm-storage/index.d.ts.map +1 -0
  33. package/dist/src/warm-storage/index.js +6 -0
  34. package/dist/src/warm-storage/index.js.map +1 -0
  35. package/dist/src/warm-storage/use-create-data-set.d.ts +14 -0
  36. package/dist/src/warm-storage/use-create-data-set.d.ts.map +1 -0
  37. package/dist/src/warm-storage/use-create-data-set.js +35 -0
  38. package/dist/src/warm-storage/use-create-data-set.js.map +1 -0
  39. package/dist/src/warm-storage/use-data-sets.d.ts +42 -0
  40. package/dist/src/warm-storage/use-data-sets.d.ts.map +1 -0
  41. package/dist/src/warm-storage/use-data-sets.js +51 -0
  42. package/dist/src/warm-storage/use-data-sets.js.map +1 -0
  43. package/dist/src/warm-storage/use-providers.d.ts +8 -0
  44. package/dist/src/warm-storage/use-providers.d.ts.map +1 -0
  45. package/dist/src/warm-storage/use-providers.js +14 -0
  46. package/dist/src/warm-storage/use-providers.js.map +1 -0
  47. package/dist/src/warm-storage/use-service-price.d.ts +8 -0
  48. package/dist/src/warm-storage/use-service-price.d.ts.map +1 -0
  49. package/dist/src/warm-storage/use-service-price.js +15 -0
  50. package/dist/src/warm-storage/use-service-price.js.map +1 -0
  51. package/dist/src/warm-storage/use-upload.d.ts +14 -0
  52. package/dist/src/warm-storage/use-upload.d.ts.map +1 -0
  53. package/dist/src/warm-storage/use-upload.js +39 -0
  54. package/dist/src/warm-storage/use-upload.js.map +1 -0
  55. package/package.json +91 -0
  56. package/src/calibration.ts +76 -0
  57. package/src/erc20.ts +103 -0
  58. package/src/filsnap.ts +16 -0
  59. package/src/index.ts +17 -0
  60. package/src/payments/index.ts +357 -0
  61. package/src/payments/use-deposit-and-approve.ts +71 -0
  62. package/src/usdfc.ts +26 -0
  63. package/src/warm-storage/index.ts +5 -0
  64. package/src/warm-storage/use-create-data-set.ts +62 -0
  65. package/src/warm-storage/use-data-sets.ts +74 -0
  66. package/src/warm-storage/use-providers.ts +21 -0
  67. package/src/warm-storage/use-service-price.ts +34 -0
  68. package/src/warm-storage/use-upload.ts +58 -0
package/package.json ADDED
@@ -0,0 +1,91 @@
1
+ {
2
+ "name": "@filoz/synapse-react",
3
+ "version": "0.0.1",
4
+ "description": "React hooks for interacting with Filecoin Onchain Cloud smart contracts",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/FilOzone/synapse-sdk.git"
8
+ },
9
+ "keywords": [
10
+ "filecoin",
11
+ "synapse",
12
+ "filecoin pay",
13
+ "filecoin onchain cloud",
14
+ "web3",
15
+ "react",
16
+ "hooks"
17
+ ],
18
+ "author": "Hugo Dias <hugomrdias@gmail.com>",
19
+ "license": "Apache-2.0 OR MIT",
20
+ "bugs": {
21
+ "url": "https://github.com/FilOzone/synapse-sdk/issues"
22
+ },
23
+ "homepage": "https://github.com/FilOzone/synapse-sdk/tree/main/packages/synapse-react",
24
+ "type": "module",
25
+ "main": "dist/src/index.js",
26
+ "module": "dist/src/index.js",
27
+ "types": "dist/src/index.d.ts",
28
+ "exports": {
29
+ ".": {
30
+ "types": "./dist/src/index.d.ts",
31
+ "default": "./dist/src/index.js"
32
+ }
33
+ },
34
+ "files": [
35
+ "src",
36
+ "dist/src",
37
+ "dist/src/**/*.d.ts",
38
+ "dist/src/**/*.d.ts.map"
39
+ ],
40
+ "wireit": {
41
+ "build": {
42
+ "command": "tsc --build --pretty",
43
+ "clean": "if-file-deleted",
44
+ "files": [
45
+ "src/**/*.ts",
46
+ "tsconfig.json"
47
+ ],
48
+ "output": [
49
+ "dist/**"
50
+ ]
51
+ },
52
+ "lint": {
53
+ "command": "biome check --no-errors-on-unmatched --files-ignore-unknown=true .",
54
+ "files": [
55
+ "src/**/*.ts",
56
+ "../../biome.json"
57
+ ],
58
+ "output": [],
59
+ "dependencies": [
60
+ "build"
61
+ ]
62
+ }
63
+ },
64
+ "dependencies": {
65
+ "filsnap-adapter": "^3.3.8",
66
+ "@filoz/synapse-core": "^0.0.1"
67
+ },
68
+ "devDependencies": {
69
+ "@biomejs/biome": "~2.2.6",
70
+ "@types/node": "^24.9.1",
71
+ "type-fest": "^5.1.0",
72
+ "typescript": "5.9.3"
73
+ },
74
+ "publishConfig": {
75
+ "access": "public"
76
+ },
77
+ "msw": {
78
+ "workerDirectory": [
79
+ "src/test/mocks"
80
+ ]
81
+ },
82
+ "peerDependencies": {
83
+ "@tanstack/react-query": "5.x",
84
+ "viem": "2.x",
85
+ "wagmi": "2.x"
86
+ },
87
+ "scripts": {
88
+ "build": "wireit",
89
+ "lint": "wireit"
90
+ }
91
+ }
@@ -0,0 +1,76 @@
1
+ import { getChain } from '@filoz/synapse-core/chains'
2
+ import { type MutateOptions, useMutation, useQueryClient } from '@tanstack/react-query'
3
+ import type { TransactionReceipt } from 'viem'
4
+ import { waitForTransactionReceipt } from 'viem/actions'
5
+ import { useChainId, useConfig } from 'wagmi'
6
+ import { getConnectorClient } from 'wagmi/actions'
7
+
8
+ interface UseFundWalletProps {
9
+ /**
10
+ * The mutation options.
11
+ */
12
+ mutation?: Omit<MutateOptions<TransactionReceipt, Error>, 'mutationFn'>
13
+ /**
14
+ * The callback to call when the hash is available.
15
+ */
16
+ onHash?: (hash: string) => void
17
+ }
18
+
19
+ /**
20
+ * Fund the wallet with USDFC and FIL.
21
+ *
22
+ * @param props - The props for the fund wallet.
23
+ * @param props.mutation - The mutation options.
24
+ * @param props.onHash - The callback to call when the hash is available.
25
+ * @returns
26
+ */
27
+ export function useFundWallet(props?: UseFundWalletProps) {
28
+ const config = useConfig()
29
+ const chainId = useChainId({ config })
30
+ const chain = getChain(chainId)
31
+ const publicClient = config.getClient()
32
+ const queryClient = useQueryClient()
33
+ const result = useMutation({
34
+ ...props?.mutation,
35
+ mutationFn: async () => {
36
+ const client = await getConnectorClient(config)
37
+
38
+ if (!chain.testnet) {
39
+ throw new Error('Wallet funding is only available on testnet')
40
+ }
41
+
42
+ const responses = await Promise.all([
43
+ fetch(
44
+ `https://forest-explorer.chainsafe.dev/api/claim_token?faucet_info=CalibnetUSDFC&address=${client.account.address}`
45
+ ),
46
+ fetch(
47
+ `https://forest-explorer.chainsafe.dev/api/claim_token?faucet_info=CalibnetFIL&address=${client.account.address}`
48
+ ),
49
+ ])
50
+
51
+ const hashes = await Promise.all(responses.filter((response) => response.ok).map((response) => response.json()))
52
+
53
+ props?.onHash?.(hashes[0] as `0x${string}`)
54
+
55
+ const wait = await waitForTransactionReceipt(publicClient, {
56
+ hash: hashes[0] as `0x${string}`,
57
+ })
58
+
59
+ queryClient.invalidateQueries({
60
+ queryKey: ['synapse-erc20-balance', client.account.address, chain.contracts.usdfc.address],
61
+ })
62
+
63
+ queryClient.invalidateQueries({
64
+ queryKey: [
65
+ 'balance',
66
+ {
67
+ address: client.account.address,
68
+ chainId,
69
+ },
70
+ ],
71
+ })
72
+ return wait
73
+ },
74
+ })
75
+ return result
76
+ }
package/src/erc20.ts ADDED
@@ -0,0 +1,103 @@
1
+ import { getChain } from '@filoz/synapse-core/chains'
2
+ import type { ERC20BalanceOptions, ERC20BalanceResult } from '@filoz/synapse-core/erc20'
3
+ import * as erc20 from '@filoz/synapse-core/erc20'
4
+ import {
5
+ type MutateOptions,
6
+ skipToken,
7
+ type UseQueryOptions,
8
+ useMutation,
9
+ useQuery,
10
+ useQueryClient,
11
+ } from '@tanstack/react-query'
12
+ import type { SetOptional } from 'type-fest'
13
+ import type { TransactionReceipt } from 'viem'
14
+ import { waitForTransactionReceipt } from 'viem/actions'
15
+ import { useAccount, useChainId, useConfig } from 'wagmi'
16
+ import { getConnectorClient } from 'wagmi/actions'
17
+
18
+ interface UseERC20BalanceProps extends SetOptional<ERC20BalanceOptions, 'address'> {
19
+ query?: Omit<UseQueryOptions<ERC20BalanceResult>, 'queryKey' | 'queryFn'>
20
+ }
21
+
22
+ /**
23
+ * Get the balance and allowance of the ERC20 token.
24
+ *
25
+ * @param props - The props to use.
26
+ * @returns The balance and allowance of the ERC20 token.
27
+ */
28
+ export function useERC20Balance(props: UseERC20BalanceProps) {
29
+ const config = useConfig()
30
+ const chain = getChain(config.state.chainId)
31
+ const token = props.token ?? chain.contracts.usdfc.address
32
+ const address = props.address
33
+
34
+ const result = useQuery({
35
+ ...props.query,
36
+ queryKey: ['synapse-erc20-balance', address, token],
37
+ queryFn: address
38
+ ? async () => {
39
+ const result = await erc20.balance(config.getClient(), {
40
+ address,
41
+ token,
42
+ })
43
+
44
+ return result
45
+ }
46
+ : skipToken,
47
+ })
48
+ return result
49
+ }
50
+
51
+ type UseApproveAllowanceVariables = Pick<erc20.ERC20ApproveAllowanceOptions, 'amount'>
52
+
53
+ interface UseApproveAllowanceProps extends Omit<erc20.ERC20ApproveAllowanceOptions, 'amount'> {
54
+ /**
55
+ * The mutation options.
56
+ */
57
+ mutation?: Omit<MutateOptions<TransactionReceipt, Error, UseApproveAllowanceVariables>, 'mutationFn'>
58
+ /**
59
+ * The callback to call when the hash is available.
60
+ */
61
+ onHash?: (hash: string) => void
62
+ }
63
+
64
+ /**
65
+ * Approve the allowance of the ERC20 token to the payments contract.
66
+ *
67
+ * @param props - The props to use.
68
+ * @returns The mutation to approve the allowance of the ERC20 token to the payments contract.
69
+ */
70
+ export function useApproveAllowance(props?: UseApproveAllowanceProps) {
71
+ const config = useConfig()
72
+ const chainId = useChainId({ config })
73
+ const account = useAccount({ config })
74
+ const queryClient = useQueryClient()
75
+ const chain = getChain(config.state.chainId)
76
+ const token = props?.token ?? chain.contracts.usdfc.address
77
+
78
+ return useMutation({
79
+ ...props?.mutation,
80
+ mutationFn: async ({ amount }: UseApproveAllowanceVariables) => {
81
+ const client = await getConnectorClient(config, {
82
+ account: account.address,
83
+ chainId,
84
+ connector: account.connector,
85
+ })
86
+
87
+ const approve = await erc20.approveAllowance(client, {
88
+ token: props?.token,
89
+ amount,
90
+ })
91
+
92
+ props?.onHash?.(approve)
93
+ const transactionReceipt = await waitForTransactionReceipt(config.getClient(), {
94
+ hash: approve,
95
+ })
96
+
97
+ queryClient.invalidateQueries({
98
+ queryKey: ['synapse-erc20-balance', account.address, token],
99
+ })
100
+ return transactionReceipt
101
+ },
102
+ })
103
+ }
package/src/filsnap.ts ADDED
@@ -0,0 +1,16 @@
1
+ import { type EIP1193Provider, getOrInstallSnap } from 'filsnap-adapter'
2
+ import { useAccountEffect } from 'wagmi'
3
+
4
+ const SNAP_ID = 'npm:filsnap' //'local:http://localhost:8080'
5
+ // const SNAP_ID = 'local:http://localhost:8080'
6
+
7
+ export const useFilsnap = ({ version, force }: { version?: string; force?: boolean } = {}) => {
8
+ useAccountEffect({
9
+ onConnect: async (data) => {
10
+ const provider = (await data.connector.getProvider()) as EIP1193Provider
11
+ if (provider.isMetaMask) {
12
+ await getOrInstallSnap(provider, SNAP_ID, version ?? '*', force)
13
+ }
14
+ },
15
+ })
16
+ }
package/src/index.ts ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Synapse React - Main Entry Point
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import * as react from '@filoz/synapse-react'
7
+ * ```
8
+ *
9
+ * @packageDocumentation
10
+ */
11
+
12
+ export * from './calibration.ts'
13
+ export * from './erc20.ts'
14
+ export * from './filsnap.ts'
15
+ export * from './payments/index.ts'
16
+ export * from './usdfc.ts'
17
+ export * from './warm-storage/index.ts'
@@ -0,0 +1,357 @@
1
+ import { getChain } from '@filoz/synapse-core/chains'
2
+ import {
3
+ type AccountInfoOptions,
4
+ type AccountInfoResult,
5
+ accountInfo,
6
+ type DepositOptions,
7
+ deposit,
8
+ type OperatorApprovalsOptions,
9
+ type OperatorApprovalsResult,
10
+ operatorApprovals,
11
+ setOperatorApproval,
12
+ type WithdrawOptions,
13
+ withdraw,
14
+ } from '@filoz/synapse-core/pay'
15
+ import {
16
+ type MutateOptions,
17
+ skipToken,
18
+ type UseQueryOptions,
19
+ useMutation,
20
+ useQuery,
21
+ useQueryClient,
22
+ } from '@tanstack/react-query'
23
+ import type { SetOptional } from 'type-fest'
24
+ import type { Address, TransactionReceipt } from 'viem'
25
+ import { waitForTransactionReceipt } from 'viem/actions'
26
+ import { useAccount, useBlock, useChainId, useConfig } from 'wagmi'
27
+ import { getConnectorClient } from 'wagmi/actions'
28
+
29
+ interface UseAccountInfoProps extends SetOptional<AccountInfoOptions, 'address'> {
30
+ /**
31
+ * Whether to watch blocks.
32
+ * @default false
33
+ */
34
+ watch?: boolean
35
+ query?: Omit<UseQueryOptions<AccountInfoResult>, 'queryKey' | 'queryFn'>
36
+ }
37
+
38
+ /**
39
+ * Get the account info from the payments contract.
40
+ *
41
+ * @param props - The props for the balance.
42
+ * @param props.address - The address of the account to get the balance for.
43
+ * @param props.token - The address of the ERC20 token to query.
44
+ * @param props.watch - Whether to watch blocks.
45
+ * @param props.query - The query options.
46
+ * @returns The account info including funds, lockup details, and available balance.
47
+ */
48
+ export function useAccountInfo(props?: UseAccountInfoProps) {
49
+ const config = useConfig()
50
+ const chainId = useChainId({ config })
51
+ const chain = getChain(chainId)
52
+ const token = props?.token ?? chain.contracts.usdfc.address
53
+ const address = props?.address
54
+ const { data } = useBlock({
55
+ blockTag: 'latest',
56
+ chainId,
57
+ watch: props?.watch ?? false,
58
+ })
59
+
60
+ const result = useQuery({
61
+ ...props?.query,
62
+ queryKey: ['synapse-payments-account-info', address, token, data?.number?.toString()],
63
+ queryFn: address
64
+ ? async () => {
65
+ return await accountInfo(config.getClient(), {
66
+ token,
67
+ address,
68
+ blockNumber: data?.number,
69
+ })
70
+ }
71
+ : skipToken,
72
+ })
73
+ return result
74
+ }
75
+
76
+ export interface UseOperatorApprovalsProps extends SetOptional<OperatorApprovalsOptions, 'address'> {
77
+ query?: Omit<UseQueryOptions<OperatorApprovalsResult>, 'queryKey' | 'queryFn'>
78
+ }
79
+
80
+ export type { OperatorApprovalsResult } from '@filoz/synapse-core/pay'
81
+
82
+ /**
83
+ * Get the operator approvals from the payments contract.
84
+ *
85
+ * @param props - The props for the balance.
86
+ * @returns The operator approvals.
87
+ */
88
+ export function useOperatorApprovals(props?: UseOperatorApprovalsProps) {
89
+ const config = useConfig()
90
+ const chainId = useChainId({ config })
91
+ const chain = getChain(chainId)
92
+ const token = props?.token ?? chain.contracts.usdfc.address
93
+ const operator = props?.operator ?? chain.contracts.storage.address
94
+ const address = props?.address
95
+
96
+ const result = useQuery({
97
+ ...props?.query,
98
+ queryKey: ['synapse-payments-operator-approvals', address, token, operator],
99
+ queryFn: address
100
+ ? async () => {
101
+ return await operatorApprovals(config.getClient(), {
102
+ token,
103
+ address,
104
+ operator,
105
+ })
106
+ }
107
+ : skipToken,
108
+ })
109
+ return result
110
+ }
111
+
112
+ type UseDepositVariables = Pick<DepositOptions, 'amount'>
113
+ interface UseDepositProps extends Omit<DepositOptions, 'amount'> {
114
+ /**
115
+ * The mutation options.
116
+ */
117
+ mutation?: Omit<MutateOptions<TransactionReceipt, Error, UseDepositVariables>, 'mutationFn'>
118
+ /**
119
+ * The callback to call when the hash is available.
120
+ */
121
+ onHash?: (hash: string) => void
122
+ }
123
+
124
+ /**
125
+ * Deposit ERC20 tokens into the payments contract.
126
+ *
127
+ * @param props - The props for the deposit.
128
+ * @param props.address - The address of the account to deposit from.
129
+ * @param props.token - The address of the ERC20 token to deposit.
130
+ * @param props.mutation - The mutation options.
131
+ * @param props.onHash - The callback to call when the hash is available.
132
+ * @returns The deposit mutation.
133
+ */
134
+ export function useDeposit(props?: UseDepositProps) {
135
+ const config = useConfig()
136
+ const chainId = useChainId({ config })
137
+ const chain = getChain(chainId)
138
+ const account = useAccount({ config })
139
+ const queryClient = useQueryClient()
140
+ const token = props?.token ?? chain.contracts.usdfc.address
141
+ const from = props?.address ?? account.address
142
+
143
+ return useMutation({
144
+ mutationFn: async ({ amount }: UseDepositVariables) => {
145
+ const client = await getConnectorClient(config, {
146
+ account: account.address,
147
+ chainId,
148
+ })
149
+
150
+ const hash = await deposit(client, {
151
+ amount,
152
+ address: account.address,
153
+ token,
154
+ })
155
+
156
+ props?.onHash?.(hash)
157
+ const transactionReceipt = await waitForTransactionReceipt(config.getClient(), {
158
+ hash: hash,
159
+ })
160
+
161
+ queryClient.invalidateQueries({
162
+ queryKey: ['synapse-payments-account-info', from, token],
163
+ })
164
+ queryClient.invalidateQueries({
165
+ queryKey: ['synapse-erc20-balance', from, token],
166
+ })
167
+ return transactionReceipt
168
+ },
169
+ ...props?.mutation,
170
+ })
171
+ }
172
+
173
+ type UseWithdrawVariables = Pick<WithdrawOptions, 'amount'>
174
+ type UseWithdrawProps = Omit<WithdrawOptions, 'amount'> & {
175
+ mutation?: Omit<MutateOptions<TransactionReceipt, Error, UseWithdrawVariables>, 'mutationFn'>
176
+ onHash?: (hash: string) => void
177
+ }
178
+ /**
179
+ * Withdraw ERC20 tokens from the payments contract.
180
+ *
181
+ * @param props - The props for the withdraw.
182
+ * @returns The withdraw mutation.
183
+ */
184
+ export function useWithdraw(props?: UseWithdrawProps) {
185
+ const config = useConfig()
186
+ const chainId = useChainId({ config })
187
+ const chain = getChain(chainId)
188
+ const account = useAccount({ config })
189
+ const queryClient = useQueryClient()
190
+ const token = props?.token ?? chain.contracts.usdfc.address
191
+ const from = props?.address ?? account.address
192
+
193
+ return useMutation({
194
+ mutationFn: async ({ amount }: UseWithdrawVariables) => {
195
+ const client = await getConnectorClient(config, {
196
+ account: account.address,
197
+ chainId,
198
+ })
199
+
200
+ const hash = await withdraw(client, {
201
+ amount,
202
+ address: account.address,
203
+ token,
204
+ })
205
+ props?.onHash?.(hash)
206
+ const transactionReceipt = await waitForTransactionReceipt(config.getClient(), {
207
+ hash,
208
+ })
209
+
210
+ queryClient.invalidateQueries({
211
+ queryKey: ['synapse-payments-account-info', from, token],
212
+ })
213
+ queryClient.invalidateQueries({
214
+ queryKey: ['synapse-erc20-balance', from, token],
215
+ })
216
+ return transactionReceipt
217
+ },
218
+ ...props?.mutation,
219
+ })
220
+ }
221
+
222
+ type ApproveOperatorProps =
223
+ | {
224
+ /**
225
+ * The address of the operator to approve.
226
+ * If not provided, the operator will be the Warm Storage contract.
227
+ */
228
+ operator?: Address
229
+ /**
230
+ * The address of the ERC20 token to query.
231
+ * If not provided, the USDFC token address will be used.
232
+ */
233
+ token?: Address
234
+ /**
235
+ * The mutation options.
236
+ */
237
+ mutation?: Omit<MutateOptions<TransactionReceipt, Error>, 'mutationFn'>
238
+ onHash?: (hash: string) => void
239
+ }
240
+ | undefined
241
+
242
+ /**
243
+ * Approve a service contract to act as an operator for payment rails.
244
+ *
245
+ * @param props - The props for the deposit.
246
+ * @param props.operator - The address of the operator to approve.
247
+ * @param props.token - The address of the ERC20 token to deposit.
248
+ * @param props.mutation - The mutation options.
249
+ * @param props.onHash - The callback to call when the hash is available.
250
+ * @returns The deposit mutation.
251
+ */
252
+ export function useApproveOperator(props?: ApproveOperatorProps) {
253
+ const config = useConfig()
254
+ const chainId = useChainId({ config })
255
+ const chain = getChain(chainId)
256
+ const account = useAccount({ config })
257
+ const queryClient = useQueryClient()
258
+ const token = props?.token ?? chain.contracts.usdfc.address
259
+ const operator = props?.operator ?? chain.contracts.storage.address
260
+
261
+ return useMutation({
262
+ ...props?.mutation,
263
+ mutationFn: async () => {
264
+ const client = await getConnectorClient(config, {
265
+ account: account.address,
266
+ chainId,
267
+ })
268
+ const hash = await setOperatorApproval(client, {
269
+ token: props?.token,
270
+ operator: props?.operator,
271
+ approve: true,
272
+ })
273
+
274
+ props?.onHash?.(hash)
275
+ const transactionReceipt = await waitForTransactionReceipt(config.getClient(), {
276
+ hash,
277
+ })
278
+
279
+ queryClient.invalidateQueries({
280
+ queryKey: ['synapse-payments-operator-approvals', account.address, token, operator],
281
+ })
282
+ queryClient.invalidateQueries({
283
+ queryKey: ['synapse-payments-account-info', account.address, token],
284
+ })
285
+
286
+ return transactionReceipt
287
+ },
288
+ })
289
+ }
290
+
291
+ type RevokeOperatorProps =
292
+ | {
293
+ /**
294
+ * The address of the operator to revoke.
295
+ * If not provided, the operator will be the Warm Storage contract.
296
+ */
297
+ operator?: Address
298
+ /**
299
+ * The address of the ERC20 token to query.
300
+ * If not provided, the USDFC token address will be used.
301
+ */
302
+ token?: Address
303
+ /**
304
+ * The mutation options.
305
+ */
306
+ mutation?: Omit<MutateOptions<TransactionReceipt, Error>, 'mutationFn'>
307
+ onHash?: (hash: string) => void
308
+ }
309
+ | undefined
310
+
311
+ /**
312
+ * Revoke the operator to deposit and withdraw ERC20 tokens from the payments contract.
313
+ *
314
+ * @param props - The props for the deposit.
315
+ * @param props.operator - The address of the operator to approve.
316
+ * @param props.token - The address of the ERC20 token to deposit.
317
+ * @param props.mutation - The mutation options.
318
+ * @param props.onHash - The callback to call when the hash is available.
319
+ * @returns The deposit mutation.
320
+ */
321
+ export function useRevokeOperator(props?: RevokeOperatorProps) {
322
+ const config = useConfig()
323
+ const configChainId = useChainId({ config })
324
+ const chain = getChain(configChainId)
325
+ const account = useAccount({ config })
326
+ const queryClient = useQueryClient()
327
+ const token = props?.token ?? chain.contracts.usdfc.address
328
+ const operator = props?.operator ?? chain.contracts.storage.address
329
+
330
+ return useMutation({
331
+ ...props?.mutation,
332
+ mutationFn: async () => {
333
+ const client = await getConnectorClient(config, {
334
+ account: account.address,
335
+ chainId: chain.id,
336
+ })
337
+ const hash = await setOperatorApproval(client, {
338
+ token: props?.token,
339
+ operator: props?.operator,
340
+ approve: false,
341
+ })
342
+ props?.onHash?.(hash)
343
+ const transactionReceipt = await waitForTransactionReceipt(config.getClient(), {
344
+ hash,
345
+ })
346
+ queryClient.invalidateQueries({
347
+ queryKey: ['synapse-payments-operator-approvals', account.address, token, operator],
348
+ })
349
+ queryClient.invalidateQueries({
350
+ queryKey: ['synapse-payments-account-info', account.address, token],
351
+ })
352
+ return transactionReceipt
353
+ },
354
+ })
355
+ }
356
+
357
+ export * from './use-deposit-and-approve.ts'