From 2c88bf8eb92b07c6016917ef7595d703a6cdb799 Mon Sep 17 00:00:00 2001 From: CedarMist <134699267+CedarMist@users.noreply.github.com> Date: Fri, 6 Sep 2024 13:54:41 +0100 Subject: [PATCH 1/4] clients/viem: use interval for routine fetching, unref intervalId --- integrations/viem-v2/src/index.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/integrations/viem-v2/src/index.ts b/integrations/viem-v2/src/index.ts index 02874b2b..d051fc57 100644 --- a/integrations/viem-v2/src/index.ts +++ b/integrations/viem-v2/src/index.ts @@ -119,13 +119,20 @@ export async function createSapphireSerializer< return originalSerializer; } - // As the serialized is synchronous, fetching keys while running + // As the serializer is synchronous, fetching keys while running const fetcher = new KeyFetcher(); const provider = client as EthereumProvider; await fetcher.fetch(provider); - setTimeout(async () => { + + // The fetcher runs in the background, routinely fetching the keys + // This means when the serializer requests a calldata public key one will + // have been retrieved pre-emptively. + const intervalId = setInterval(async () => { await fetcher.fetch(provider); }, fetcher.timeoutMilliseconds); + // The interval ID is unreferenced to prevent Node from hanging at exit + // See discussion on https://github.com/oasisprotocol/sapphire-paratime/pull/379 + intervalId.unref(); const wrappedSerializer = ((tx, sig?) => { if (!sig) { From 8d630b04899ac8761966b00da1aa71416d4b420c Mon Sep 17 00:00:00 2001 From: CedarMist <134699267+CedarMist@users.noreply.github.com> Date: Fri, 6 Sep 2024 18:05:28 +0100 Subject: [PATCH 2/4] integrations/viem: detect if unref exists on interval --- integrations/viem-v2/src/index.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/integrations/viem-v2/src/index.ts b/integrations/viem-v2/src/index.ts index d051fc57..a64e6a0a 100644 --- a/integrations/viem-v2/src/index.ts +++ b/integrations/viem-v2/src/index.ts @@ -127,12 +127,15 @@ export async function createSapphireSerializer< // The fetcher runs in the background, routinely fetching the keys // This means when the serializer requests a calldata public key one will // have been retrieved pre-emptively. - const intervalId = setInterval(async () => { + const intervalId: NodeJS.Timeout | number = setInterval(async () => { await fetcher.fetch(provider); }, fetcher.timeoutMilliseconds); // The interval ID is unreferenced to prevent Node from hanging at exit // See discussion on https://github.com/oasisprotocol/sapphire-paratime/pull/379 - intervalId.unref(); + // This is only available in NodeJS, and not in browsers + if (typeof intervalId.unref === "function") { + intervalId.unref(); + } const wrappedSerializer = ((tx, sig?) => { if (!sig) { From a2d117e3fd042652873710da792a50ef48ea287e Mon Sep 17 00:00:00 2001 From: CedarMist <134699267+CedarMist@users.noreply.github.com> Date: Tue, 10 Sep 2024 16:20:42 +0100 Subject: [PATCH 3/4] integrations/viem: add test to verify Node doesn't hang --- integrations/viem-v2/package.json | 2 +- integrations/viem-v2/scripts/test.js | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 integrations/viem-v2/scripts/test.js diff --git a/integrations/viem-v2/package.json b/integrations/viem-v2/package.json index 180c8982..953d596e 100644 --- a/integrations/viem-v2/package.json +++ b/integrations/viem-v2/package.json @@ -29,7 +29,7 @@ "lint": "biome check .", "format": "biome format --write .", "clean": "rm -rf dist", - "test": "vitest --run", + "test": "vitest --run && timeout -k 5s 2s pnpm ts-node ./scripts/test.js", "build": "npm run build:cjs && npm run build:esm && npm run build:types", "build:cjs": "tsc --project ./tsconfig.build.json --module commonjs --outDir ./dist/_cjs --removeComments --verbatimModuleSyntax false && printf '{\"type\":\"commonjs\"}' > ./dist/_cjs/package.json && node scripts/rename-cjs.js", "build:esm": "tsc --project ./tsconfig.build.json --module es2015 --outDir ./dist/_esm && printf '{\"type\": \"module\",\"sideEffects\":false}' > ./dist/_esm/package.json", diff --git a/integrations/viem-v2/scripts/test.js b/integrations/viem-v2/scripts/test.js new file mode 100644 index 00000000..f5da5eaa --- /dev/null +++ b/integrations/viem-v2/scripts/test.js @@ -0,0 +1,28 @@ +/* +This script verifies that when Viem is used using Node via the CLI it won't +prevent Node from exiting cleanly. + +See: https://github.com/oasisprotocol/sapphire-paratime/pull/383 +*/ + +import { createPublicClient, defineChain } from "viem"; +import { sapphireHttpTransport, sapphireLocalnet, createSapphireSerializer } from '@oasisprotocol/sapphire-viem-v2'; + +const transport = sapphireHttpTransport(); +const chain = sapphireLocalnet; +const publicClient = createPublicClient({ chain, transport }); +defineChain({ + id: 0x5afd, + name: "Oasis Sapphire Localnet", + network: "sapphire-localnet", + nativeCurrency: { name: "Sapphire Local Rose", symbol: "TEST", decimals: 18 }, + rpcUrls: { + default: { + http: ["http://localhost:8545"], + }, + }, + serializers: { + transaction: await createSapphireSerializer(publicClient) + }, + testnet: true, +}); From c34b198643f11384c309b998d41f8a349dec3fc1 Mon Sep 17 00:00:00 2001 From: CedarMist <134699267+CedarMist@users.noreply.github.com> Date: Tue, 10 Sep 2024 16:26:52 +0100 Subject: [PATCH 4/4] integrations/viem: formatting --- integrations/viem-v2/scripts/test.js | 32 ++++++++++++++++------------ 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/integrations/viem-v2/scripts/test.js b/integrations/viem-v2/scripts/test.js index f5da5eaa..4092f0d5 100644 --- a/integrations/viem-v2/scripts/test.js +++ b/integrations/viem-v2/scripts/test.js @@ -5,24 +5,28 @@ prevent Node from exiting cleanly. See: https://github.com/oasisprotocol/sapphire-paratime/pull/383 */ +import { + createSapphireSerializer, + sapphireHttpTransport, + sapphireLocalnet, +} from "@oasisprotocol/sapphire-viem-v2"; import { createPublicClient, defineChain } from "viem"; -import { sapphireHttpTransport, sapphireLocalnet, createSapphireSerializer } from '@oasisprotocol/sapphire-viem-v2'; const transport = sapphireHttpTransport(); const chain = sapphireLocalnet; const publicClient = createPublicClient({ chain, transport }); defineChain({ - id: 0x5afd, - name: "Oasis Sapphire Localnet", - network: "sapphire-localnet", - nativeCurrency: { name: "Sapphire Local Rose", symbol: "TEST", decimals: 18 }, - rpcUrls: { - default: { - http: ["http://localhost:8545"], - }, - }, - serializers: { - transaction: await createSapphireSerializer(publicClient) - }, - testnet: true, + id: 0x5afd, + name: "Oasis Sapphire Localnet", + network: "sapphire-localnet", + nativeCurrency: { name: "Sapphire Local Rose", symbol: "TEST", decimals: 18 }, + rpcUrls: { + default: { + http: ["http://localhost:8545"], + }, + }, + serializers: { + transaction: await createSapphireSerializer(publicClient), + }, + testnet: true, });