Skip to content

Commit 261f8ef

Browse files
poppyseedDevclaude
andauthored
chore: update relayer-sdk to 0.4.1 and fix browser mock mode (#43)
* chore: update relayer-sdk to 0.4.1, fhevm packages to latest - @zama-fhe/relayer-sdk → 0.4.1 (all packages) - @fhevm/solidity → ^0.11.1 - @fhevm/hardhat-plugin → ^0.4.2 - @fhevm/mock-utils → ^0.4.2 - ethers → ^6.16.0 (peer dep requirement) - @nomicfoundation/hardhat-ethers → ^3.1.3 (peer dep requirement) - Add turbopack resolveAlias for Node.js built-ins (fixes node-tkms fs error) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: include hardhat chain in wagmi config so network switching works The wagmi config only included sepolia, so useSwitchChain had no hardhat chain to switch to. Now both chains and transports are always configured (hardhat transport is harmless in production). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: enable fhevm mock mode in browser for hardhat localhost - Update relayer-sdk CDN URL to 0.4.1 in layout.tsx and constants.ts - Replace empty-module.js with browser-compatible fs shim that loads WASM files via synchronous XHR from public/ - Copy node-tkms kms_lib_bg.wasm to public/ so the fs shim can serve it - This allows @fhevm/mock-utils to run in the browser, enabling local encrypt/decrypt on hardhat without routing through the remote relayer Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: patch node-tkms for browser compatibility and fix WASM loading - Fix synchronous XHR binary loading using overrideMimeType instead of responseType (which is not supported for sync XHR) - Add tfhe_bg.wasm to public/ for browser serving - Patch node-tkms postinstall to use globalThis.TextEncoder/TextDecoder instead of require('util') (avoids breaking Privy's isKeyObject) - Use empty-module.js fs shim in webpack fallback for production builds Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 1d02490 commit 261f8ef

File tree

15 files changed

+314
-154
lines changed

15 files changed

+314
-154
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"next:lint": "pnpm --filter ./packages/erc7984example lint",
4646
"next:serve": "pnpm --filter ./packages/erc7984example serve",
4747
"precommit": "lint-staged",
48+
"postinstall": "sh scripts/patch-node-tkms.sh",
4849
"preinstall": "pnpm sdk:build",
4950
"start": "pnpm --filter ./packages/erc7984example dev",
5051
"test": "pnpm hardhat:test",

packages/erc7984example/app/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const DappWrapper = ({ children }: { children: React.ReactNode }) => {
1414
<html suppressHydrationWarning className={``}>
1515
<head></head>
1616
<body suppressHydrationWarning>
17-
<Script src="https://cdn.zama.org/relayer-sdk-js/0.4.0-4/relayer-sdk-js.umd.cjs" strategy="beforeInteractive" />
17+
<Script src="https://cdn.zama.org/relayer-sdk-js/0.4.1/relayer-sdk-js.umd.cjs" strategy="beforeInteractive" />
1818
<ThemeProvider enableSystem>
1919
<DappWrapperWithProviders>{children}</DappWrapperWithProviders>
2020
</ThemeProvider>

packages/erc7984example/app/providers.tsx

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { type ReactNode } from "react";
44
import { PrivyProvider } from "@privy-io/react-auth";
55
import { WagmiProvider as PrivyWagmiProvider, createConfig } from "@privy-io/wagmi";
66
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
7-
import { sepolia } from "viem/chains";
7+
import { sepolia, hardhat } from "viem/chains";
88
import { createConfig as createWagmiConfig, http } from "wagmi";
99
import { WagmiProvider as StandardWagmiProvider } from "wagmi";
1010
import scaffoldConfig from "~~/scaffold.config";
@@ -30,28 +30,28 @@ if (!PRIVY_APP_ID && typeof window !== "undefined") {
3030

3131
const { alchemyApiKey } = scaffoldConfig;
3232

33-
// Use Sepolia as the primary chain (Privy doesn't work well with local hardhat)
34-
const activeChain = sepolia;
35-
36-
// Build RPC URL
37-
const rpcUrl = alchemyApiKey
33+
// Build RPC URLs
34+
const sepoliaRpcUrl = alchemyApiKey
3835
? `https://eth-sepolia.g.alchemy.com/v2/${alchemyApiKey}`
3936
: "https://ethereum-sepolia-rpc.publicnode.com";
4037

38+
// Include both chains — hardhat transport is harmless in production
39+
const chains = [sepolia, hardhat] as const;
40+
const transports = {
41+
[sepolia.id]: http(sepoliaRpcUrl),
42+
[hardhat.id]: http("http://127.0.0.1:8545"),
43+
};
44+
4145
// Create Wagmi config using Privy's createConfig (for when Privy is configured)
4246
export const wagmiConfig = createConfig({
43-
chains: [activeChain] as const,
44-
transports: {
45-
[activeChain.id]: http(rpcUrl),
46-
} as Record<typeof activeChain.id, ReturnType<typeof http>>,
47+
chains,
48+
transports,
4749
});
4850

4951
// Create standard Wagmi config (for fallback when Privy is not configured)
5052
const standardWagmiConfig = createWagmiConfig({
51-
chains: [activeChain],
52-
transports: {
53-
[activeChain.id]: http(rpcUrl),
54-
},
53+
chains,
54+
transports,
5555
});
5656

5757
export function Providers({ children }: Props) {
@@ -74,8 +74,8 @@ export function Providers({ children }: Props) {
7474
},
7575
},
7676
loginMethods: ["wallet", "email"],
77-
supportedChains: [activeChain],
78-
defaultChain: activeChain,
77+
supportedChains: [...chains],
78+
defaultChain: sepolia,
7979
appearance: {
8080
showWalletLoginFirst: true,
8181
walletChainType: "ethereum-only",

packages/erc7984example/contracts/deployedContracts.ts

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,19 @@ const deployedContracts = {
7575
name: "OwnershipTransferred",
7676
type: "event",
7777
},
78+
{
79+
inputs: [],
80+
name: "AIRDROP_AMOUNT",
81+
outputs: [
82+
{
83+
internalType: "uint64",
84+
name: "",
85+
type: "uint64",
86+
},
87+
],
88+
stateMutability: "view",
89+
type: "function",
90+
},
7891
{
7992
inputs: [
8093
{
@@ -2119,6 +2132,142 @@ const deployedContracts = {
21192132
},
21202133
deployedOnBlock: 10092096,
21212134
},
2135+
PublicDecryptSingleValue: {
2136+
address: "0x1365229D1769232CCbC795c7181dD65B34872348",
2137+
abi: [
2138+
{
2139+
inputs: [],
2140+
stateMutability: "nonpayable",
2141+
type: "constructor",
2142+
},
2143+
{
2144+
inputs: [],
2145+
name: "InvalidKMSSignatures",
2146+
type: "error",
2147+
},
2148+
{
2149+
inputs: [],
2150+
name: "ZamaProtocolUnsupported",
2151+
type: "error",
2152+
},
2153+
{
2154+
anonymous: false,
2155+
inputs: [
2156+
{
2157+
indexed: false,
2158+
internalType: "bytes32[]",
2159+
name: "handlesList",
2160+
type: "bytes32[]",
2161+
},
2162+
{
2163+
indexed: false,
2164+
internalType: "bytes",
2165+
name: "abiEncodedCleartexts",
2166+
type: "bytes",
2167+
},
2168+
],
2169+
name: "PublicDecryptionVerified",
2170+
type: "event",
2171+
},
2172+
{
2173+
inputs: [
2174+
{
2175+
internalType: "bytes32[]",
2176+
name: "handlesList",
2177+
type: "bytes32[]",
2178+
},
2179+
{
2180+
internalType: "bytes",
2181+
name: "cleartexts",
2182+
type: "bytes",
2183+
},
2184+
{
2185+
internalType: "bytes",
2186+
name: "decryptionProof",
2187+
type: "bytes",
2188+
},
2189+
],
2190+
name: "callbackDecryptSingleUint32",
2191+
outputs: [],
2192+
stateMutability: "nonpayable",
2193+
type: "function",
2194+
},
2195+
{
2196+
inputs: [],
2197+
name: "clearUint32",
2198+
outputs: [
2199+
{
2200+
internalType: "uint32",
2201+
name: "",
2202+
type: "uint32",
2203+
},
2204+
],
2205+
stateMutability: "view",
2206+
type: "function",
2207+
},
2208+
{
2209+
inputs: [],
2210+
name: "confidentialProtocolId",
2211+
outputs: [
2212+
{
2213+
internalType: "uint256",
2214+
name: "",
2215+
type: "uint256",
2216+
},
2217+
],
2218+
stateMutability: "view",
2219+
type: "function",
2220+
},
2221+
{
2222+
inputs: [],
2223+
name: "getHandle",
2224+
outputs: [
2225+
{
2226+
internalType: "bytes32",
2227+
name: "",
2228+
type: "bytes32",
2229+
},
2230+
],
2231+
stateMutability: "view",
2232+
type: "function",
2233+
},
2234+
{
2235+
inputs: [
2236+
{
2237+
internalType: "uint32",
2238+
name: "value",
2239+
type: "uint32",
2240+
},
2241+
],
2242+
name: "initializeUint32",
2243+
outputs: [],
2244+
stateMutability: "nonpayable",
2245+
type: "function",
2246+
},
2247+
{
2248+
inputs: [
2249+
{
2250+
internalType: "uint32",
2251+
name: "value",
2252+
type: "uint32",
2253+
},
2254+
],
2255+
name: "initializeUint32Wrong",
2256+
outputs: [],
2257+
stateMutability: "nonpayable",
2258+
type: "function",
2259+
},
2260+
{
2261+
inputs: [],
2262+
name: "requestDecryptSingleUint32",
2263+
outputs: [],
2264+
stateMutability: "nonpayable",
2265+
type: "function",
2266+
},
2267+
],
2268+
inheritedFunctions: {},
2269+
deployedOnBlock: 10106218,
2270+
},
21222271
},
21232272
} as const;
21242273

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Browser-compatible fs shim for node-tkms WASM loading.
2+
// node-tkms calls require('fs').readFileSync(path) to load kms_lib_bg.wasm.
3+
// In the browser, we serve it from public/ and load via synchronous XHR.
4+
module.exports = {
5+
readFileSync: function (filePath) {
6+
var filename = filePath.split("/").pop();
7+
var xhr = new XMLHttpRequest();
8+
xhr.open("GET", "/" + filename, false); // synchronous
9+
// Use binary string override since synchronous XHR doesn't support responseType
10+
xhr.overrideMimeType("text/plain; charset=x-user-defined");
11+
xhr.send();
12+
if (xhr.status >= 200 && xhr.status < 300) {
13+
var text = xhr.responseText;
14+
var bytes = new Uint8Array(text.length);
15+
for (var i = 0; i < text.length; i++) {
16+
bytes[i] = text.charCodeAt(i) & 0xff;
17+
}
18+
return bytes;
19+
}
20+
throw new Error("fs shim: failed to load /" + filename + " (status: " + xhr.status + ")");
21+
},
22+
};

packages/erc7984example/next.config.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,22 @@ const nextConfig: NextConfig = {
44
transpilePackages: ["fhevm-sdk"],
55
// Exclude Node.js packages that are incompatible with Turbopack bundling
66
serverExternalPackages: ["pino", "thread-stream", "pino-pretty"],
7-
// Empty turbopack config - Turbopack handles Node.js fallbacks automatically
8-
turbopack: {},
7+
// Turbopack: resolve Node.js built-ins to empty modules for client bundle
8+
turbopack: {
9+
resolveAlias: {
10+
fs: "./empty-module.js",
11+
net: "./empty-module.js",
12+
tls: "./empty-module.js",
13+
child_process: "./empty-module.js",
14+
worker_threads: "./empty-module.js",
15+
},
16+
},
917
// Configure webpack fallbacks for client-side (these packages shouldn't be bundled for browser)
1018
webpack: (config, { isServer }) => {
1119
if (!isServer) {
1220
config.resolve.fallback = {
1321
...config.resolve.fallback,
14-
fs: false,
22+
fs: require.resolve("./empty-module.js"),
1523
net: false,
1624
tls: false,
1725
child_process: false,

packages/erc7984example/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"@tanstack/react-query": "~5.59.20",
2222
"@uniswap/sdk-core": "~5.8.5",
2323
"@uniswap/v2-sdk": "~4.6.2",
24-
"@zama-fhe/relayer-sdk": "0.4.0-4",
24+
"@zama-fhe/relayer-sdk": "0.4.1",
2525
"blo": "~1.2.0",
2626
"daisyui": "5.0.9",
2727
"ethers": "^6.15.0",
645 KB
Binary file not shown.
4.5 MB
Binary file not shown.

packages/fhevm-sdk/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@
3737
},
3838
"dependencies": {
3939
"idb": "^8.0.3",
40-
"@zama-fhe/relayer-sdk": "^0.4.0-2",
41-
"ethers": "^6.13.4"
40+
"@zama-fhe/relayer-sdk": "^0.4.1",
41+
"ethers": "^6.16.0"
4242
},
4343
"peerDependencies": {
44-
"@fhevm/mock-utils": "^0.3.0-4",
44+
"@fhevm/mock-utils": "^0.4.2",
4545
"react": ">=16.8.0"
4646
},
4747
"peerDependenciesMeta": {
@@ -53,7 +53,7 @@
5353
"@types/node": "~18.19.50",
5454
"@types/react": "~19.0.7",
5555
"@vitest/coverage-v8": "2.1.9",
56-
"ethers": "^6.13.7",
56+
"ethers": "^6.16.0",
5757
"fake-indexeddb": "~6.0.0",
5858
"jsdom": "^27.0.0",
5959
"react": "~19.0.0",

0 commit comments

Comments
 (0)