@pyratzlabs/react-fhevm-utils 1.0.2 → 1.0.4
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/README.md +329 -0
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
## Introduction
|
|
2
|
+
|
|
3
|
+
@pyratzlabs/react-fhevm-utils is a typescript library that enables developers to interact with Zama's [fhevmjs](https://www.npmjs.com/package/fhevmjs?activeTab=readme) API. This library provides a React hooks set that allow frontend developers to easily decrypt/encrypt values or transfer encrypted tokens.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Using npm
|
|
9
|
+
npm install @pyratzlabs/react-fhevm-utils
|
|
10
|
+
|
|
11
|
+
# Using Yarn
|
|
12
|
+
yarn add @pyratzlabs/react-fhevm-utils
|
|
13
|
+
|
|
14
|
+
# Using pnpm
|
|
15
|
+
pnpm add @pyratzlabs/react-fhevm-utils
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
This will download and install the @pyratzlabs/react-fhevm-utils library and its dependencies into your project.
|
|
19
|
+
|
|
20
|
+
## Initialization
|
|
21
|
+
|
|
22
|
+
### Install dependencies
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Using npm
|
|
26
|
+
npm install @tanstack/react-query ethers wagmi
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
You can also use yarn or pnpm depending on your preferences
|
|
30
|
+
|
|
31
|
+
### Providers
|
|
32
|
+
|
|
33
|
+
You can declare these providers at the root of your projet, wherever it makes more sense to you.
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
// src/app/layout.tsx
|
|
37
|
+
|
|
38
|
+
import React from "react";
|
|
39
|
+
import FhevmProvider from "@pyratzlabs/react-fhevm-utils";
|
|
40
|
+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
41
|
+
import { WagmiProvider } from "wagmi";
|
|
42
|
+
|
|
43
|
+
export default function RootLayout({
|
|
44
|
+
children,
|
|
45
|
+
}: Readonly<{
|
|
46
|
+
children: React.ReactNode;
|
|
47
|
+
}>) {
|
|
48
|
+
const queryClient = new QueryClient();
|
|
49
|
+
const config = {
|
|
50
|
+
// ... your wagmi config
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<html lang="en">
|
|
55
|
+
<body>
|
|
56
|
+
<WagmiProvider config={config}>
|
|
57
|
+
<QueryClientProvider client={queryClient}>
|
|
58
|
+
<FhevmProvider>{children}</FhevmProvider>
|
|
59
|
+
</QueryClientProvider>
|
|
60
|
+
</WagmiProvider>
|
|
61
|
+
</body>
|
|
62
|
+
</html>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Retrieve user encrypted balance
|
|
68
|
+
|
|
69
|
+
To retrieve user encrypted balance you can use useGetEncryptedBalance hook.
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
// src/app/page.tsx
|
|
73
|
+
|
|
74
|
+
import React from "react";
|
|
75
|
+
|
|
76
|
+
const TOKEN_ADDRESS = "0xD61a80ec935D210b54FC97F0FBCB8C4793bE80C8";
|
|
77
|
+
|
|
78
|
+
export default function Home() {
|
|
79
|
+
const { encryptedBalance } = useGetEncryptedBalance({
|
|
80
|
+
tokenAddress: TOKEN_ADDRESS,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<div className="space-y-4">
|
|
85
|
+
<p>User encrypted balance : {encryptedBalance}</p>
|
|
86
|
+
</div>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Decrypt user balance
|
|
92
|
+
|
|
93
|
+
You can decrypt the user balance using useDecryptBalance hook.
|
|
94
|
+
|
|
95
|
+
```tsx
|
|
96
|
+
// src/app/page.tsx
|
|
97
|
+
|
|
98
|
+
import React, { useState } from "react";
|
|
99
|
+
|
|
100
|
+
const TOKEN_ADDRESS = "0xD61a80ec935D210b54FC97F0FBCB8C4793bE80C8";
|
|
101
|
+
|
|
102
|
+
export default function Home() {
|
|
103
|
+
const [decryptedBalance, setDecryptedBalance] = useState<number>();
|
|
104
|
+
|
|
105
|
+
const { encryptedBalance } = useGetEncryptedBalance({
|
|
106
|
+
tokenAddress: TOKEN_ADDRESS,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
const { mutate, isPending: isDecrypting } = useDecryptBalance({
|
|
110
|
+
tokenAddress: TOKEN_ADDRESS,
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
const decrypt = async () => {
|
|
114
|
+
if (!encryptedBalance) {
|
|
115
|
+
setDecryptedBalance(0);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
mutate(encryptedBalance, {
|
|
120
|
+
onSuccess: (balance: bigint) => {
|
|
121
|
+
setDecryptedBalance(balance * 10 ** -18);
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
return (
|
|
127
|
+
<div className="space-y-4">
|
|
128
|
+
<p>User encrypted balance : {encryptedBalance}</p>
|
|
129
|
+
|
|
130
|
+
<div className="flex items-center">
|
|
131
|
+
<p>User decrypted balance :</p>
|
|
132
|
+
{decryptedBalance ? (
|
|
133
|
+
<div>{decryptedBalance}</div>
|
|
134
|
+
) : (
|
|
135
|
+
<button>{isDecrypting ? "Decrypting..." : "Decrypt"}</button>
|
|
136
|
+
)}
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Encrypt value
|
|
144
|
+
|
|
145
|
+
In order to encrypt value before a transfer you can use useEncryptValue hook.
|
|
146
|
+
|
|
147
|
+
```tsx
|
|
148
|
+
// src/app/page.tsx
|
|
149
|
+
|
|
150
|
+
import React from "react";
|
|
151
|
+
|
|
152
|
+
const TOKEN_ADDRESS = "0xD61a80ec935D210b54FC97F0FBCB8C4793bE80C8";
|
|
153
|
+
|
|
154
|
+
export default function Home() {
|
|
155
|
+
const [value, setValue] = useState<number>();
|
|
156
|
+
|
|
157
|
+
const {
|
|
158
|
+
mutate: encrypt,
|
|
159
|
+
isPending: isEncrypting,
|
|
160
|
+
isSuccess: isEncryptSuccess,
|
|
161
|
+
isFailed: isEncryptFailed,
|
|
162
|
+
} = useEncryptValue({
|
|
163
|
+
tokenAddress: TOKEN_ADDRESS,
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
const handleEncrypt = () => {
|
|
167
|
+
const valueToEncrypt = BigInt(value * 10 ** 18);
|
|
168
|
+
|
|
169
|
+
encrypt(valueToEncrypt);
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
return (
|
|
173
|
+
<div className="space-y-4">
|
|
174
|
+
<input
|
|
175
|
+
placeholder="Enter value"
|
|
176
|
+
onChange={(e) => setValue(e.target.value)}
|
|
177
|
+
/>
|
|
178
|
+
<button onClick={handleEncrypt}>
|
|
179
|
+
{isEncrypting ? "Encrypting..." : `Encrypt value : ${value}`}
|
|
180
|
+
</button>
|
|
181
|
+
{isEncryptSuccess && <p>Encrypt Success</p>}
|
|
182
|
+
{isEncryptFailed && <p>Encrypt Failed</p>}
|
|
183
|
+
</div>
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Transfer encrypted token
|
|
189
|
+
|
|
190
|
+
If you want to transfer tokens you need to encrypt value before calling the transfer method.
|
|
191
|
+
|
|
192
|
+
```tsx
|
|
193
|
+
// src/app/page.tsx
|
|
194
|
+
|
|
195
|
+
import React from "react";
|
|
196
|
+
import { Address } from "viem";
|
|
197
|
+
|
|
198
|
+
const TOKEN_ADDRESS = "0xD61a80ec935D210b54FC97F0FBCB8C4793bE80C8";
|
|
199
|
+
|
|
200
|
+
export default function Home() {
|
|
201
|
+
const [value, setValue] = useState<number>();
|
|
202
|
+
const [address, setAddress] = useState<Address>();
|
|
203
|
+
|
|
204
|
+
const {
|
|
205
|
+
mutate: encrypt,
|
|
206
|
+
isPending: isEncrypting,
|
|
207
|
+
isSuccess: isEncryptSuccess,
|
|
208
|
+
isFailed: isEncryptFailed,
|
|
209
|
+
} = useEncryptValue({
|
|
210
|
+
tokenAddress: TOKEN_ADDRESS,
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
const {
|
|
214
|
+
transfer,
|
|
215
|
+
isLoading: isTransferring,
|
|
216
|
+
isSuccess: isTransferSuccess,
|
|
217
|
+
isFailed: isTransferFailed,
|
|
218
|
+
} = useEncryptedTransfer({
|
|
219
|
+
tokenAddress: TOKEN_ADDRESS,
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
const transfer = () => {
|
|
223
|
+
if (!address || !value) return;
|
|
224
|
+
|
|
225
|
+
const valueToEncrypt = BigInt(value * 10 ** 18);
|
|
226
|
+
|
|
227
|
+
encrypt(valueToEncrypt, {
|
|
228
|
+
onSuccess: (result) => {
|
|
229
|
+
const { handles, inputProof } = result;
|
|
230
|
+
transfer(address, handles, inputProof);
|
|
231
|
+
},
|
|
232
|
+
});
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
return (
|
|
236
|
+
<div className="space-y-4">
|
|
237
|
+
<input
|
|
238
|
+
placeholder="Enter value"
|
|
239
|
+
onChange={(e) => setValue(e.target.value)}
|
|
240
|
+
/>
|
|
241
|
+
<input
|
|
242
|
+
placeholder="Reciever address"
|
|
243
|
+
onChange={(e) => setAddress(e.target.value)}
|
|
244
|
+
/>
|
|
245
|
+
|
|
246
|
+
<button onClick={transfer}>
|
|
247
|
+
{isEncrypting
|
|
248
|
+
? "Encrypting..."
|
|
249
|
+
: isTransferring
|
|
250
|
+
? "Transferring..."
|
|
251
|
+
: "Transfer"}
|
|
252
|
+
</button>
|
|
253
|
+
|
|
254
|
+
{isEncryptSuccess && <p>Encrypt Success</p>}
|
|
255
|
+
{isEncryptFailed && <p>Encrypt Failed</p>}
|
|
256
|
+
{isTransferSuccess && <p>Transfer Success</p>}
|
|
257
|
+
{isTransferFailed && <p>Transfer Failed</p>}
|
|
258
|
+
</div>
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## Retrieve Fhevm instance
|
|
264
|
+
|
|
265
|
+
To retrieve fhevm instance you can use useFhevmInstance hook.
|
|
266
|
+
|
|
267
|
+
```tsx
|
|
268
|
+
// src/app/page.tsx
|
|
269
|
+
|
|
270
|
+
import React from "react";
|
|
271
|
+
|
|
272
|
+
export default function Home() {
|
|
273
|
+
const { instance } = useFhevmInstance();
|
|
274
|
+
|
|
275
|
+
return (
|
|
276
|
+
<div className="space-y-4">
|
|
277
|
+
<p>Fhevm instance : {instance.toString()}</p>
|
|
278
|
+
</div>
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## Override Fhvem configuration
|
|
284
|
+
|
|
285
|
+
You can override Fhevm configuration depending on the chain you're working with.
|
|
286
|
+
|
|
287
|
+
```tsx
|
|
288
|
+
// src/app/layout.tsx
|
|
289
|
+
|
|
290
|
+
import React from "react";
|
|
291
|
+
import FhevmProvider, { FhevmConfig } from "@pyratzlabs/react-fhevm-utils";
|
|
292
|
+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
293
|
+
import { WagmiProvider } from "wagmi";
|
|
294
|
+
import { polygonAmoy } from "viem/chains";
|
|
295
|
+
|
|
296
|
+
export default function RootLayout({
|
|
297
|
+
children,
|
|
298
|
+
}: Readonly<{
|
|
299
|
+
children: React.ReactNode;
|
|
300
|
+
}>) {
|
|
301
|
+
const queryClient = new QueryClient();
|
|
302
|
+
const config = {
|
|
303
|
+
// ... your wagmi config
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
const customFhevmConfig: FhevmConfig = {
|
|
307
|
+
network: polygonAmoy,
|
|
308
|
+
// other overridable configurations
|
|
309
|
+
// chainId: 11221212,
|
|
310
|
+
// networkUrl: "https://example-polygon-amoy-rpc.com/
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
return (
|
|
314
|
+
<html lang="en">
|
|
315
|
+
<body>
|
|
316
|
+
<WagmiProvider config={config}>
|
|
317
|
+
<QueryClientProvider client={queryClient}>
|
|
318
|
+
<FhevmProvider config={customFhevmConfig}>{children}</FhevmProvider>
|
|
319
|
+
</QueryClientProvider>
|
|
320
|
+
</WagmiProvider>
|
|
321
|
+
</body>
|
|
322
|
+
</html>
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
## License
|
|
328
|
+
|
|
329
|
+
This library is distributed under the MIT license.
|