diff --git a/README.md b/README.md index ce3fb52a..e124f31c 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,11 @@ As long as there is one honest participant running a working implementation of t ##### ⚖️ [VeaScan explorer](https://veascan.io) +##### 📦 NPM Packages + +- [@kleros/vea-sdk](https://www.npmjs.com/package/@kleros/vea-sdk) +- [@kleros/vea-contracts](https://www.npmjs.com/package/@kleros/vea-contracts) + ##### 🗃️ Subgraph endpoints - [Inbox for VeaScan](veascan-subgraph-inbox/README.md#deployments) @@ -78,10 +83,10 @@ As long as there is one honest participant running a working implementation of t | **[relayer-subgraph-inbox](/relayer-subgraph-inbox)** | Indexing of the bridge inbox for relaying purposes, in particular for the computation of the proof of inclusion of a message in a state root. | | **[services](/services)** | Supporting services such as a graph-node container. | | **[validator-cli](/validator-cli)** | Validator implementation in TypeScript capable of fulfilling the roles of Oracle and Challenger. | +| **[vea-sdk](/vea-sdk)** | SDK for the developers of cross-chain apps on Vea. | | **[veascan-subgraph-inbox](/veascan-subgraph-inbox)** | Indexing of the bridge inbox for retrieval by the Veascan frontend. | | **[veascan-subgraph-outbox](/veascan-subgraph-outbox)** | Indexing of the bridge outbox for retrieval by the Veascan frontend. | | **[veascan-web](/veascan-web)** | Explorer of snapshot and messages crossing the bridge. | -| | | ## Toolchain: diff --git a/contracts/package.json b/contracts/package.json index 8e741d3d..eb03425d 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -1,6 +1,6 @@ { "name": "@kleros/vea-contracts", - "version": "0.1.14", + "version": "0.2.1", "description": "Smart contracts for Vea", "repository": { "type": "git", @@ -75,7 +75,6 @@ "json-schema": "^0.4.0", "mocha": "^10.2.0", "node-fetch": "^3.3.1", - "shelljs": "^0.8.5", "solhint": "^3.4.1", "solidity-coverage": "^0.8.2", "ts-node": "^10.9.1", diff --git a/contracts/scripts/publish.sh b/contracts/scripts/publish.sh index 3fe76910..32a3c894 100755 --- a/contracts/scripts/publish.sh +++ b/contracts/scripts/publish.sh @@ -23,7 +23,7 @@ trap _finally EXIT yarn version $1 mkdir dist -cp -pr README.md deployments src/ dist/ +cp -pr README.md deployments typechain-types src/ dist/ rm -rf dist/test jq 'del(.scripts.prepare)' package.json > dist/package.json diff --git a/package.json b/package.json index 48d950e1..e15022d2 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "relayer-subgraph-inbox", "validator-cli", "relayer-cli", + "vea-sdk", "veascan-web", "veascan-subgraph-inbox", "veascan-subgraph-outbox" diff --git a/relayer-cli/src/utils/relay.ts b/relayer-cli/src/utils/relay.ts index c6f6d76b..0f536017 100644 --- a/relayer-cli/src/utils/relay.ts +++ b/relayer-cli/src/utils/relay.ts @@ -2,7 +2,6 @@ import { getProofAtCount, getMessageDataToRelay, getSubgraph } from "./proof"; import { getVeaOutboxArbToEth } from "./ethers"; import request from "graphql-request"; import { VeaInboxArbToEth, VeaOutboxArbToEth } from "@kleros/vea-contracts/typechain-types"; -const fs = require("fs"); require("dotenv").config(); diff --git a/validator-cli/package.json b/validator-cli/package.json index f6c18f62..54ba8578 100644 --- a/validator-cli/package.json +++ b/validator-cli/package.json @@ -10,18 +10,25 @@ "yarn": "3.3.1" }, "scripts": { - "start": "npx ts-node ./src/ArbToEth/watcher.ts", - "start-chiado-devnet": "npx ts-node ./src/devnet/arbToChiado/happyPath.ts", - "start-goerli-devnet": "npx ts-node ./src/devnet/arbToGoerli/happyPath.ts" + "start": "NODE_NO_WARNINGS=1 NODE_OPTIONS=--experimental-fetch ts-node ./src/ArbToEth/index.ts", + "pm2:start": "pm2 start 'yarn start' --name watcher --cron '*/10 * * * *' --no-autorestart", + "start-chiado-devnet": "NODE_NO_WARNINGS=1 NODE_OPTIONS=--experimental-fetch ts-node ./src/devnet/arbToChiado/happyPath.ts", + "start-goerli-devnet": "NODE_NO_WARNINGS=1 NODE_OPTIONS=--experimental-fetch ts-node ./src/devnet/arbToGoerli/happyPath.ts" }, "dependencies": { "@arbitrum/sdk": "^3.1.2", "@kleros/vea-contracts": "workspace:^", + "@logtail/pino": "^0.4.0", "@typechain/ethers-v5": "^10.2.0", "dotenv": "^16.0.3", + "pino": "^8.14.1", + "pino-pretty": "^10.0.0", "pm2": "^5.2.2", - "typescript": "^4.9.5", "web3": "^1.10.0", "web3-batched-send": "^1.0.3" + }, + "devDependencies": { + "ts-node": "^10.9.1", + "typescript": "^4.9.5" } } diff --git a/validator-cli/src/ArbToEth/index.ts b/validator-cli/src/ArbToEth/index.ts new file mode 100644 index 00000000..c26b2c8d --- /dev/null +++ b/validator-cli/src/ArbToEth/index.ts @@ -0,0 +1,7 @@ +import watch from "./watcher"; + +try { + watch(); +} catch (error) { + console.log("error", error); +} diff --git a/validator-cli/src/ArbToEth/watcher.ts b/validator-cli/src/ArbToEth/watcher.ts index d25c0403..f21022cf 100644 --- a/validator-cli/src/ArbToEth/watcher.ts +++ b/validator-cli/src/ArbToEth/watcher.ts @@ -1,34 +1,44 @@ import { getVeaOutboxArbToEthProvider, getVeaInboxArbToEth } from "../utils/ethers"; import { JsonRpcProvider } from "@ethersproject/providers"; - -require("dotenv").config(); +import { arbToEthDevnet, IBridge } from "../utils/contracts"; +import envVar from "../utils/envVar"; +import baseLogger from "../utils/logger"; const watch = async () => { - const l1provider = new JsonRpcProvider(process.env.RPC_VEAOUTBOX); - - const veaOutbox = getVeaOutboxArbToEthProvider(process.env.VEAOUTBOX_ADDRESS, process.env.PRIVATE_KEY, l1provider); + const bridge: IBridge = arbToEthDevnet; + const logger = baseLogger.child({ + bridge: bridge.label, + inbox: bridge.inboxAddress, + outbox: bridge.outboxAddress, + }); + logger.info("Watching for claims..."); + logger.debug("Inbox RPC: %s", bridge.inboxRpc); + logger.debug("Outbox RPC: %s", bridge.outboxRpc); - const veaInbox = getVeaInboxArbToEth(process.env.VEAINBOX_ADDRESS, process.env.PRIVATE_KEY, process.env.RPC_VEAINBOX); + const privateKey = envVar("PRIVATE_KEY"); + const rpcProviderOutbox = new JsonRpcProvider(bridge.outboxRpc); + const veaOutbox = getVeaOutboxArbToEthProvider(bridge.outboxAddress, privateKey, rpcProviderOutbox); + const veaInbox = getVeaInboxArbToEth(bridge.inboxAddress, privateKey, bridge.inboxRpc); const deposit = await veaOutbox.deposit(); const epochPeriod = (await veaOutbox.epochPeriod()).toNumber(); const claimDelay = (await veaOutbox.claimDelay()).toNumber(); const challengePeriod = (await veaOutbox.challengePeriod()).toNumber(); - const currentBlockNumber = await l1provider.getBlockNumber(); - const challengableTimeStart = Math.floor(Date.now() / 1000) - challengePeriod; - const challengableBlockStart = currentBlockNumber - Math.ceil((challengePeriod * 2) / 12); + const currentBlockNumber = await rpcProviderOutbox.getBlockNumber(); + const challengeableTimeStart = Math.floor(Date.now() / 1000) - challengePeriod; + const challengeableBlockStart = currentBlockNumber - Math.ceil((challengePeriod * 2) / 12); - const logs = await l1provider.getLogs({ - address: process.env.VEAOUTBOX_ADDRESS, + const logs = await rpcProviderOutbox.getLogs({ + address: bridge.outboxAddress, topics: veaOutbox.filters.Claimed(null, null).topics, - fromBlock: challengableBlockStart, + fromBlock: challengeableBlockStart, }); + logger.info("Claim events found: %d", logs.length); - for (let i = 0; i < logs.length; i++) { - const log = logs[i]; - const claimedTimestamp = (await l1provider.getBlock(log.blockNumber)).timestamp; - console.log({ + for (var log of logs) { + const claimedTimestamp = (await rpcProviderOutbox.getBlock(log.blockNumber)).timestamp; + logger.info({ stateRoot: log.data, claimer: "0x" + log.topics[1].substring(26), timestamp: claimedTimestamp, @@ -36,14 +46,14 @@ const watch = async () => { honest: "0", challenger: "0x0000000000000000000000000000000000000000", }); - if (claimedTimestamp < challengableTimeStart) { + if (claimedTimestamp < challengeableTimeStart) { continue; } else { const claimedStateRoot = log.data; const claimedEpoch = Math.floor((claimedTimestamp - claimDelay) / epochPeriod); const inboxStateRoot = await veaInbox.snapshots(claimedEpoch); if (claimedStateRoot !== inboxStateRoot) { - console.log(`Challenging claim ${claimedStateRoot} at epoch ${claimedEpoch}.`); + logger.warn(`Challenging claim ${claimedStateRoot} at epoch ${claimedEpoch}.`); const unchallengedClaim = { stateRoot: claimedStateRoot, claimer: "0x" + log.topics[1].substring(26), @@ -54,17 +64,20 @@ const watch = async () => { }; const unchallengedClaimHash = await veaOutbox.hashClaim(unchallengedClaim); const claimHash = await veaOutbox.claimHashes(claimedEpoch); - console.log(unchallengedClaim); - console.log(unchallengedClaimHash); - console.log(claimHash); - console.log(claimedEpoch); + logger.warn(unchallengedClaim); + logger.warn(unchallengedClaimHash); + logger.warn(claimHash); + logger.warn(claimedEpoch); if (unchallengedClaimHash == claimHash) { const txn = await veaOutbox.challenge(claimedEpoch, unchallengedClaim, { value: deposit }); - console.log(`Challenge Txn: ${txn.hash}`); + logger.warn(`Challenge Txn: ${txn.hash}`); } } } } + + // TODO: make this env var optional, skip fetch if undefined + fetch(envVar("HEARTBEAT_URL")); }; export default watch; diff --git a/validator-cli/src/index.ts b/validator-cli/src/index.ts new file mode 100644 index 00000000..e69de29b diff --git a/validator-cli/src/utils/contracts.ts b/validator-cli/src/utils/contracts.ts new file mode 100644 index 00000000..a894e67b --- /dev/null +++ b/validator-cli/src/utils/contracts.ts @@ -0,0 +1,31 @@ +import VeaInboxArbToGnosisDevnet from "@kleros/vea-contracts/deployments/arbitrumGoerli/VeaInboxArbToGnosisDevnet.json"; +import VeaOutboxArbToGnosisDevnet from "@kleros/vea-contracts/deployments/chiado/VeaOutboxArbToGnosisDevnet.json"; + +import VeaInboxArbToEthDevnet from "@kleros/vea-contracts/deployments/arbitrumGoerli/VeaInboxArbToEthDevnet.json"; +import VeaOutboxArbToEthDevnet from "@kleros/vea-contracts/deployments/goerli/VeaOutboxArbToEthDevnet.json"; + +import envVar from "./envVar"; + +export interface IBridge { + label: string; + inboxAddress: `0x${string}`; + outboxAddress: `0x${string}`; + inboxRpc: string; + outboxRpc: string; +} + +export const arbToGnosisDevnet: IBridge = { + label: "Arbitrum to Chiado Devnet", + inboxAddress: VeaInboxArbToGnosisDevnet.address as `0x${string}`, + outboxAddress: VeaOutboxArbToGnosisDevnet.address as `0x${string}`, + inboxRpc: envVar("RPC_ARB_GOERLI"), + outboxRpc: envVar("RPC_CHIADO"), +}; + +export const arbToEthDevnet: IBridge = { + label: "Arbitrum to Goerli Devnet", + inboxAddress: VeaInboxArbToEthDevnet.address as `0x${string}`, + outboxAddress: VeaOutboxArbToEthDevnet.address as `0x${string}`, + inboxRpc: envVar("RPC_ARB_GOERLI"), + outboxRpc: envVar("RPC_GOERLI"), +}; diff --git a/validator-cli/src/utils/envVar.ts b/validator-cli/src/utils/envVar.ts new file mode 100644 index 00000000..a81b674e --- /dev/null +++ b/validator-cli/src/utils/envVar.ts @@ -0,0 +1,16 @@ +import dotenv from "dotenv"; +import logger from "./logger"; + +dotenv.config(); + +function envVar(key: string): string { + const value = process.env[key]; + if (value === undefined) { + const error = new Error(`Environment variable ${key} is undefined`); + logger.error(error); + throw error; + } + return value; +} + +export default envVar; diff --git a/validator-cli/src/utils/logger.ts b/validator-cli/src/utils/logger.ts new file mode 100644 index 00000000..a3e9a648 --- /dev/null +++ b/validator-cli/src/utils/logger.ts @@ -0,0 +1,28 @@ +import pino from "pino"; +import envVar from "./envVar"; + +// TODO: make this env var optional, skip fetch if undefined +const logtailToken = envVar("LOGTAIL_TOKEN"); +const transport = pino.transport({ + targets: [ + { + target: "@logtail/pino", + options: { sourceToken: logtailToken }, + level: "debug", + }, + { + target: "pino-pretty", + options: {}, + level: "debug", + }, + ], +}); +const logger = pino( + { + level: envVar("LOG_LEVEL"), // TODO: set it to info if not defined + timestamp: pino.stdTimeFunctions.isoTime, + }, + transport +); + +export default logger; diff --git a/validator-cli/tsconfig.json b/validator-cli/tsconfig.json index dbe3a5ab..8395e045 100644 --- a/validator-cli/tsconfig.json +++ b/validator-cli/tsconfig.json @@ -1,4 +1,15 @@ { + "compilerOptions": { + "target": "es2021", + "module": "commonjs", + "strict": true, + "esModuleInterop": true, + "outDir": "dist", + "declaration": true, + "sourceMap": true, + "noImplicitAny": false, + "resolveJsonModule": true + }, "include": [ "src" ] diff --git a/vea-sdk/.env.dist b/vea-sdk/.env.dist new file mode 100644 index 00000000..b009fa7d --- /dev/null +++ b/vea-sdk/.env.dist @@ -0,0 +1,13 @@ +PRIVATE_KEY= + +RPC_CHIADO=https://rpc.chiadochain.net +RPC_ARB_GOERLI=https://goerli-rollup.arbitrum.io/rpc +RPC_GOERLI= + +VEAINBOX_ARBGOERLI_TO_GOERLI_ADDRESS=0x906dE43dBef27639b1688Ac46532a16dc07Ce410 +VEAINBOX_ARBGOERLI_TO_CHIADO_ADDRESS=0xAb53e341121448Ae259Da8fa17f216Cb0e21199C +VEAOUTBOX_ARBGOERLI_TO_GOERLI_ADDRESS=0x906dE43dBef27639b1688Ac46532a16dc07Ce410 +VEAOUTBOX_ARBGOERLI_TO_CHIADO_ADDRESS=0xAb53e341121448Ae259Da8fa17f216Cb0e21199C + +TRANSACTION_BATCHER_CONTRACT_ADDRESS_GOERLI=0xe7953da7751063d0a41ba727c32c762d3523ade8 +TRANSACTION_BATCHER_CONTRACT_ADDRESS_CHIADO=0xcC0a08D4BCC5f91ee9a1587608f7a2975EA75d73 \ No newline at end of file diff --git a/vea-sdk/.npmignore b/vea-sdk/.npmignore new file mode 100644 index 00000000..b8b7024b --- /dev/null +++ b/vea-sdk/.npmignore @@ -0,0 +1,3 @@ +scripts +tsconfig.json +.env* diff --git a/vea-sdk/README.md b/vea-sdk/README.md new file mode 100644 index 00000000..bfb50f10 --- /dev/null +++ b/vea-sdk/README.md @@ -0,0 +1,31 @@ +# Vea SDK npm + +This package facilitates the interactions with the Vea protocol. + +## Getting Started + +```bash +yarn add @kleros/vea-sdk +# or +npm install @kleros/vea-sdk +``` + +## Example + +```typescript +import { Wallet } from "@ethersproject/wallet"; +import VeaSdk from "../src/index"; +import envVar from "../src/utils/envVar"; + +// Create the Vea client +const vea = VeaSdk.ClientFactory.arbitrumGoerliToChiadoDevnet(envVar("RPC_ARB_GOERLI"), envVar("RPC_CHIADO")); + +// Get the message info +const messageId = 42; +const messageInfo = await vea.getMessageInfo(messageId); + +// Relay the message +const privateKey = envVar("PRIVATE_KEY"); +const wallet = new Wallet(privateKey, vea.outboxProvider); +await vea.relay(messageInfo, wallet); +``` diff --git a/vea-sdk/examples/index.ts b/vea-sdk/examples/index.ts new file mode 100644 index 00000000..ab280a4b --- /dev/null +++ b/vea-sdk/examples/index.ts @@ -0,0 +1,15 @@ +import { Wallet } from "@ethersproject/wallet"; +import VeaSdk from "../src/index"; +import envVar from "../src/utils/envVar"; + +// Create the Vea client +const vea = VeaSdk.ClientFactory.arbitrumGoerliToChiadoDevnet(envVar("RPC_ARB_GOERLI"), envVar("RPC_CHIADO")); + +// Get the message info +const messageId = 42; +const messageInfo = await vea.getMessageInfo(messageId); + +// Relay the message +const privateKey = envVar("PRIVATE_KEY"); +const wallet = new Wallet(privateKey, vea.outboxProvider); +await vea.relay(messageInfo, wallet); diff --git a/vea-sdk/package.json b/vea-sdk/package.json new file mode 100644 index 00000000..e77c52b4 --- /dev/null +++ b/vea-sdk/package.json @@ -0,0 +1,58 @@ +{ + "name": "@kleros/vea-sdk", + "version": "0.2.0", + "description": "SDK for the development of cross-chain apps on Vea", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/kleros/vea.git" + }, + "author": "Vea Team (https://vea.ninja)", + "bugs": { + "url": "https://github.com/kleros/vea/issues" + }, + "homepage": "https://vea.ninja", + "license": "MIT", + "packageManager": "yarn@3.3.1", + "engines": { + "node": ">=16.0.0" + }, + "volta": { + "node": "16.20.0", + "yarn": "3.3.1" + }, + "publishConfig": { + "access": "public", + "tag": "latest" + }, + "scripts": { + "start": "NODE_NO_WARNINGS=1 NODE_OPTIONS=--experimental-fetch ts-node ./src/run.ts", + "release:patch": "yarn version patch && yarn npm publish", + "release:minor": "yarn version minor && yarn npm publish", + "release:major": "yarn version major && yarn npm publish", + "clean": "rm -rf dist", + "prepublish": "yarn tsc || echo" + }, + "dependencies": { + "@kleros/vea-contracts": "workspace:^0.2.1", + "@logtail/pino": "^0.4.0", + "@typechain/ethers-v5": "^10.2.0", + "dotenv": "^16.0.3", + "graphql": "^16.6.0", + "graphql-request": "^6.1.0", + "pino": "^8.14.1", + "pino-pretty": "^10.0.0", + "web3": "^1.10.0", + "web3-batched-send": "^1.0.3" + }, + "devDependencies": { + "ts-node": "^10.9.1", + "typescript": "^4.9.5" + }, + "files": [ + "dist", + "src", + "examples" + ] +} diff --git a/vea-sdk/src/bridges.ts b/vea-sdk/src/bridges.ts new file mode 100644 index 00000000..93d3a2bb --- /dev/null +++ b/vea-sdk/src/bridges.ts @@ -0,0 +1,54 @@ +import VeaInboxArbToGnosisDevnetDeployment from "@kleros/vea-contracts/deployments/arbitrumGoerli/VeaInboxArbToGnosisDevnet.json"; +import VeaOutboxArbToGnosisDevnetDeployment from "@kleros/vea-contracts/deployments/chiado/VeaOutboxArbToGnosisDevnet.json"; + +import VeaInboxArbToEthDevnetDeployment from "@kleros/vea-contracts/deployments/arbitrumGoerli/VeaInboxArbToEthDevnet.json"; +import VeaOutboxArbToEthDevnetDeployment from "@kleros/vea-contracts/deployments/goerli/VeaOutboxArbToEthDevnet.json"; + +import { + VeaInboxArbToEth__factory, + VeaOutboxArbToGnosisDevnet__factory, + VeaOutboxArbToEthDevnet__factory, +} from "@kleros/vea-contracts/typechain-types"; + +export type VeaInboxFactory = typeof VeaInboxArbToEth__factory; +export type VeaOutboxFactory = typeof VeaOutboxArbToGnosisDevnet__factory | typeof VeaOutboxArbToEthDevnet__factory; + +export type Bridge = { + label: string; + inboxChainId: number; + outboxChainId: number; + inboxAddress: `0x${string}`; + outboxAddress: `0x${string}`; + inboxFactory: VeaInboxFactory; + outboxFactory: VeaOutboxFactory; + inboxSubgraph: string; + outboxSubgraph: string; +}; + +const getSubgraphUrl = (subgraph: string): string => { + return `https://api.thegraph.com/subgraphs/name/shotaronowhere/${subgraph}`; +}; + +export const arbitrumGoerliToChiadoDevnet: Bridge = { + label: "Arbitrum to Chiado Devnet", + inboxChainId: 421613, + outboxChainId: 10200, + inboxAddress: VeaInboxArbToGnosisDevnetDeployment.address as `0x${string}`, + outboxAddress: VeaOutboxArbToGnosisDevnetDeployment.address as `0x${string}`, + inboxFactory: VeaInboxArbToEth__factory, + outboxFactory: VeaOutboxArbToGnosisDevnet__factory, + inboxSubgraph: getSubgraphUrl("vea-inbox-arbgoerli-to-chiado"), + outboxSubgraph: getSubgraphUrl("FIX ME"), // TODO +}; + +export const arbitrumGoerliToGoerliDevnet: Bridge = { + label: "Arbitrum to Goerli Devnet", + inboxChainId: 5, + outboxChainId: 10200, + inboxAddress: VeaInboxArbToEthDevnetDeployment.address as `0x${string}`, + outboxAddress: VeaOutboxArbToEthDevnetDeployment.address as `0x${string}`, + inboxFactory: VeaInboxArbToEth__factory, + outboxFactory: VeaOutboxArbToEthDevnet__factory, + inboxSubgraph: getSubgraphUrl("vea-inbox-arbgoerli-to-goerli"), + outboxSubgraph: getSubgraphUrl("FIXME"), // TODO, +}; diff --git a/vea-sdk/src/client.ts b/vea-sdk/src/client.ts new file mode 100644 index 00000000..2242c1ef --- /dev/null +++ b/vea-sdk/src/client.ts @@ -0,0 +1,49 @@ +import { JsonRpcProvider } from "@ethersproject/providers"; +import { ContractTransaction } from "@ethersproject/contracts"; +import { Signer } from "@ethersproject/abstract-signer"; +import { + VeaInboxArbToEth, + VeaOutboxArbToGnosisDevnet, + VeaOutboxArbToEthDevnet, +} from "@kleros/vea-contracts/typechain-types"; +import * as Bridges from "./bridges"; +import { MessageInfo, getMessageInfo, relay } from "./message"; + +export type VeaClientConfig = { + readonly bridge: Bridges.Bridge; + readonly inboxRpc: string; + readonly outboxRpc: string; +}; + +export type VeaInbox = VeaInboxArbToEth; +export type VeaOutbox = VeaOutboxArbToEthDevnet | VeaOutboxArbToGnosisDevnet; + +export class VeaClient { + readonly config: VeaClientConfig; + inboxProvider: JsonRpcProvider; + outboxProvider: JsonRpcProvider; + inbox: VeaInbox; + outbox: VeaOutbox; + + constructor( + config: VeaClientConfig, + inboxProvider: JsonRpcProvider, + outboxProvider: JsonRpcProvider, + inbox: VeaInboxArbToEth, + outbox: VeaOutboxArbToEthDevnet | VeaOutboxArbToGnosisDevnet + ) { + this.config = config; + this.inboxProvider = inboxProvider; + this.outboxProvider = outboxProvider; + this.inbox = inbox; + this.outbox = outbox; + } + + public getMessageInfo = async (messageId: number): Promise => { + return getMessageInfo(this, messageId); + }; + + public relay = async (messageInfo: MessageInfo, signer: Signer): Promise => { + return relay(this, messageInfo, signer); + }; +} diff --git a/vea-sdk/src/index.ts b/vea-sdk/src/index.ts new file mode 100644 index 00000000..16da7357 --- /dev/null +++ b/vea-sdk/src/index.ts @@ -0,0 +1,2 @@ +import * as VeaSdk from "./sdk"; +export default VeaSdk; diff --git a/vea-sdk/src/message.ts b/vea-sdk/src/message.ts new file mode 100644 index 00000000..475d6523 --- /dev/null +++ b/vea-sdk/src/message.ts @@ -0,0 +1,109 @@ +import request from "graphql-request"; +import { ContractTransaction } from "@ethersproject/contracts"; +import { Signer } from "@ethersproject/abstract-signer"; +import { VeaClient } from "./client"; + +export type MessageInfo = { + messageId: number; + proof: string[]; + to: `0x${string}`; + data: string; +}; + +export const relay = async ( + client: VeaClient, + messageInfo: MessageInfo, + signer: Signer +): Promise => { + return client.outbox + .connect(signer) + .sendMessage(messageInfo.proof, messageInfo.messageId, messageInfo.to, messageInfo.data); +}; + +export const getMessageInfo = async (client: VeaClient, messageId: number): Promise => { + const count = await getCount(client); + const proof = await getProofAtCount(client, messageId, count); + const [to, data] = (await getMessageDataToRelay(client, messageId)) as [`0x${string}`, string]; + return { + messageId, + proof, + to, + data, + }; +}; + +const getCount = async (client: VeaClient): Promise => { + const subgraph = client.config.bridge.outboxSubgraph; + const stateRoot = await client.outbox.stateRoot(); + const query = `{ + snapshotSaveds(first: 1, where: { stateRoot: "${stateRoot}" }) { + count + } + }`; + const result: any = await request(subgraph, query); + if (result["snapshotSaveds"].length == 0) throw new Error("No snapshot found"); + return Number(result["snapshotSaveds"][0].count); +}; + +const getProofAtCount = async (client: VeaClient, messageId: number, count: number): Promise => { + const proofIndices = getProofIndices(messageId, count); + + let query = "{"; + for (let i = 0; i < proofIndices.length; i++) { + query += `layer${i}: nodes(first: 1, where: {id: "${proofIndices[i]}"}) { + hash + }`; + } + query += "}"; + + const proof: any[] = []; + try { + const subgraph = client.config.bridge.outboxSubgraph; + const result: any = await request(subgraph, query); + for (let i = 0; i < proofIndices.length; i++) { + proof.push(result[`layer${i}`][0].hash); + } + } catch (e) { + console.log(e); + } + return proof; +}; + +const getProofIndices = (messageId: number, count: number) => { + let proof: any[] = []; + if (messageId >= count) { + return proof; + } + const treeDepth = Math.ceil(Math.log2(count)); + for (let i = 0; i < treeDepth; i++) { + if (i == 0 && (messageId ^ 1) < count) proof.push((messageId ^ 1).toString()); // sibling + else { + const low = ((messageId >> i) ^ 1) << i; + const high = Math.min(low + Math.pow(2, i) - 1, count - 1); + if (low < count - 1) proof.push(low.toString() + "," + high.toString()); + else if (low == count - 1) proof.push(low.toString()); + } + } + return proof; +}; + +const getMessageDataToRelay = async (client: VeaClient, messageId: number): Promise<[string, string]> => { + let dataAndTo: [string, string] = ["", ""]; + try { + const subgraph = client.config.bridge.outboxSubgraph; + const query = `{ + messageSents(first: 5, where: {messageId: ${messageId}}) { + messageId + to { + id + } + data + } + }`; + const result: any = await request(subgraph, query); + dataAndTo = [result[`messageSents`][0].to.id, result[`messageSents`][0].data]; + } catch (e) { + console.log(e); + } + return dataAndTo; +}; diff --git a/vea-sdk/src/sdk.ts b/vea-sdk/src/sdk.ts new file mode 100644 index 00000000..06b806d2 --- /dev/null +++ b/vea-sdk/src/sdk.ts @@ -0,0 +1,27 @@ +import { JsonRpcProvider } from "@ethersproject/providers"; +import * as Bridges from "./bridges"; +import { VeaClient, VeaClientConfig } from "./client"; + +export class ClientFactory { + private static configure(bridge: Bridges.Bridge, inboxRpc: string, outboxRpc: string): VeaClient { + const config: VeaClientConfig = { + bridge, + inboxRpc: inboxRpc, + outboxRpc: outboxRpc, + }; + const inboxProvider = new JsonRpcProvider(inboxRpc); + const outboxProvider = new JsonRpcProvider(outboxRpc); + const veaInbox = bridge.inboxFactory.connect(bridge.inboxAddress, inboxProvider); + const veaOutbox = bridge.outboxFactory.connect(bridge.outboxAddress, outboxProvider); + // TODO: Check if the RPCs chainIds match the bridge chainIds + return new VeaClient(config, inboxProvider, outboxProvider, veaInbox, veaOutbox); + } + + static arbitrumGoerliToChiadoDevnet(inboxRpc: string, outboxRpc: string): VeaClient { + return this.configure(Bridges.arbitrumGoerliToChiadoDevnet, inboxRpc, outboxRpc); + } + + static arbitrumGoerliToGoerliDevnet(inboxRpc: string, outboxRpc: string): VeaClient { + return this.configure(Bridges.arbitrumGoerliToGoerliDevnet, inboxRpc, outboxRpc); + } +} diff --git a/vea-sdk/src/utils/envVar.ts b/vea-sdk/src/utils/envVar.ts new file mode 100644 index 00000000..a81b674e --- /dev/null +++ b/vea-sdk/src/utils/envVar.ts @@ -0,0 +1,16 @@ +import dotenv from "dotenv"; +import logger from "./logger"; + +dotenv.config(); + +function envVar(key: string): string { + const value = process.env[key]; + if (value === undefined) { + const error = new Error(`Environment variable ${key} is undefined`); + logger.error(error); + throw error; + } + return value; +} + +export default envVar; diff --git a/vea-sdk/src/utils/logger.ts b/vea-sdk/src/utils/logger.ts new file mode 100644 index 00000000..a3e9a648 --- /dev/null +++ b/vea-sdk/src/utils/logger.ts @@ -0,0 +1,28 @@ +import pino from "pino"; +import envVar from "./envVar"; + +// TODO: make this env var optional, skip fetch if undefined +const logtailToken = envVar("LOGTAIL_TOKEN"); +const transport = pino.transport({ + targets: [ + { + target: "@logtail/pino", + options: { sourceToken: logtailToken }, + level: "debug", + }, + { + target: "pino-pretty", + options: {}, + level: "debug", + }, + ], +}); +const logger = pino( + { + level: envVar("LOG_LEVEL"), // TODO: set it to info if not defined + timestamp: pino.stdTimeFunctions.isoTime, + }, + transport +); + +export default logger; diff --git a/vea-sdk/tsconfig.json b/vea-sdk/tsconfig.json new file mode 100644 index 00000000..cdb804a4 --- /dev/null +++ b/vea-sdk/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "es2021", + "module": "commonjs", + "strict": true, + "esModuleInterop": true, + "outDir": "dist", + "declaration": true, + "sourceMap": true, + "noImplicitAny": false, + "resolveJsonModule": true, + "paths": { + "@kleros/vea-contracts": [ + "../contracts" + ] + } + }, + "include": [ + "src" + ], + "exclude": [ + "node_modules", + "dist" + ] +} diff --git a/yarn.lock b/yarn.lock index cb23dd91..e394dbb2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3357,7 +3357,7 @@ __metadata: languageName: node linkType: hard -"@kleros/vea-contracts@workspace:^, @kleros/vea-contracts@workspace:contracts": +"@kleros/vea-contracts@workspace:^, @kleros/vea-contracts@workspace:^0.2.1, @kleros/vea-contracts@workspace:contracts": version: 0.0.0-use.local resolution: "@kleros/vea-contracts@workspace:contracts" dependencies: @@ -3388,7 +3388,6 @@ __metadata: json-schema: ^0.4.0 mocha: ^10.2.0 node-fetch: ^3.3.1 - shelljs: ^0.8.5 solhint: ^3.4.1 solidity-coverage: ^0.8.2 ts-node: ^10.9.1 @@ -3422,15 +3421,38 @@ __metadata: languageName: unknown linkType: soft +"@kleros/vea-sdk@workspace:vea-sdk": + version: 0.0.0-use.local + resolution: "@kleros/vea-sdk@workspace:vea-sdk" + dependencies: + "@kleros/vea-contracts": "workspace:^0.2.1" + "@logtail/pino": ^0.4.0 + "@typechain/ethers-v5": ^10.2.0 + dotenv: ^16.0.3 + graphql: ^16.6.0 + graphql-request: ^6.1.0 + pino: ^8.14.1 + pino-pretty: ^10.0.0 + ts-node: ^10.9.1 + typescript: ^4.9.5 + web3: ^1.10.0 + web3-batched-send: ^1.0.3 + languageName: unknown + linkType: soft + "@kleros/vea-validator-cli@workspace:validator-cli": version: 0.0.0-use.local resolution: "@kleros/vea-validator-cli@workspace:validator-cli" dependencies: "@arbitrum/sdk": ^3.1.2 "@kleros/vea-contracts": "workspace:^" + "@logtail/pino": ^0.4.0 "@typechain/ethers-v5": ^10.2.0 dotenv: ^16.0.3 + pino: ^8.14.1 + pino-pretty: ^10.0.0 pm2: ^5.2.2 + ts-node: ^10.9.1 typescript: ^4.9.5 web3: ^1.10.0 web3-batched-send: ^1.0.3 @@ -3564,6 +3586,62 @@ __metadata: languageName: node linkType: hard +"@logtail/core@npm:^0.4.0": + version: 0.4.0 + resolution: "@logtail/core@npm:0.4.0" + dependencies: + "@logtail/tools": ^0.4.0 + "@logtail/types": ^0.4.0 + checksum: 866e09decca08ca35640dad6c5e4d307a47bdc14b8a5033daa8f77441c1e46f04256eb401c3477d82c63117818061fe334d8e0242429594e33a4faef833a9a4f + languageName: node + linkType: hard + +"@logtail/node@npm:^0.4.0": + version: 0.4.0 + resolution: "@logtail/node@npm:0.4.0" + dependencies: + "@logtail/core": ^0.4.0 + "@logtail/types": ^0.4.0 + "@msgpack/msgpack": ^2.5.1 + "@types/stack-trace": ^0.0.29 + cross-fetch: ^3.0.4 + minimatch: ^3.0.4 + stack-trace: ^0.0.10 + checksum: b1fa11f757b09baccc7b2fffa36887550a1e36e0318d4306b8b3792923ffa9bd1d4940476cddcb598ee68a7d9ef9dfb6efd9c940ef993003f17657bc5b660620 + languageName: node + linkType: hard + +"@logtail/pino@npm:^0.4.0": + version: 0.4.0 + resolution: "@logtail/pino@npm:0.4.0" + dependencies: + "@logtail/node": ^0.4.0 + "@logtail/types": ^0.4.0 + pino-abstract-transport: ^1.0.0 + peerDependencies: + pino: ^7.0.0 || ^8.0.0 + checksum: 1c4267f871ba46ab36b3ed701de9517bc1680fa043845a10f2b629bb561addaea092c792d3dd2439062506a13b6c9603c814539a781787c982cbebbb2d41884c + languageName: node + linkType: hard + +"@logtail/tools@npm:^0.4.0": + version: 0.4.0 + resolution: "@logtail/tools@npm:0.4.0" + dependencies: + "@logtail/types": ^0.4.0 + checksum: a69e4def9b6ef3a6590717512e18420641429c6242234070980aaaa9e25ccfaacc399199b74c26a1716d4e6b8f31569b9e0cfbd148e1b4d68b9dd9ee881e92bf + languageName: node + linkType: hard + +"@logtail/types@npm:^0.4.0": + version: 0.4.0 + resolution: "@logtail/types@npm:0.4.0" + dependencies: + js: ^0.1.0 + checksum: b21d5a48bd60db0fc8e57f992c6bfcc7191fdb817984a736c13e0fd2afd1b077e631ff455443e1b289782f642c5a27883434347d8b8340bb78e4ff43d84383e0 + languageName: node + linkType: hard + "@metamask/eth-sig-util@npm:^4.0.0": version: 4.0.1 resolution: "@metamask/eth-sig-util@npm:4.0.1" @@ -3607,6 +3685,13 @@ __metadata: languageName: node linkType: hard +"@msgpack/msgpack@npm:^2.5.1": + version: 2.8.0 + resolution: "@msgpack/msgpack@npm:2.8.0" + checksum: bead9393f57239007a2fe455df5277cbc03b125f14f310162a652b81471dcf3ab6780eaa24b36e20aa742998910a6840147d08b7267063b8e2de5d40c624360e + languageName: node + linkType: hard + "@msgpackr-extract/msgpackr-extract-darwin-arm64@npm:3.0.2": version: 3.0.2 resolution: "@msgpackr-extract/msgpackr-extract-darwin-arm64@npm:3.0.2" @@ -5812,6 +5897,13 @@ __metadata: languageName: node linkType: hard +"@types/stack-trace@npm:^0.0.29": + version: 0.0.29 + resolution: "@types/stack-trace@npm:0.0.29" + checksum: 2dcfdf8f10e250a76e43efe6d3e05a463b4e22ca290dbb423ec14fa21f57f94ef0cc8ba19ed3394c448218d9ddd9f7cd9adea131fb6572aa2d484b1cf7f043aa + languageName: node + linkType: hard + "@types/styled-components@npm:^5.1.26": version: 5.1.26 resolution: "@types/styled-components@npm:5.1.26" @@ -6955,6 +7047,13 @@ __metadata: languageName: node linkType: hard +"atomic-sleep@npm:^1.0.0": + version: 1.0.0 + resolution: "atomic-sleep@npm:1.0.0" + checksum: b95275afb2f80732f22f43a60178430c468906a415a7ff18bcd0feeebc8eec3930b51250aeda91a476062a90e07132b43a1794e8d8ffcf9b650e8139be75fa36 + languageName: node + linkType: hard + "auto-bind@npm:~4.0.0": version: 4.0.0 resolution: "auto-bind@npm:4.0.0" @@ -8328,7 +8427,7 @@ __metadata: languageName: node linkType: hard -"colorette@npm:^2.0.16": +"colorette@npm:^2.0.16, colorette@npm:^2.0.7": version: 2.0.20 resolution: "colorette@npm:2.0.20" checksum: 0c016fea2b91b733eb9f4bcdb580018f52c0bc0979443dad930e5037a968237ac53d9beb98e218d2e9235834f8eebce7f8e080422d6194e957454255bde71d3d @@ -8431,6 +8530,15 @@ __metadata: languageName: node linkType: hard +"commander@npm:~1.1.1": + version: 1.1.1 + resolution: "commander@npm:1.1.1" + dependencies: + keypress: 0.1.x + checksum: a27db3772327d1d8a8abaa7d3834c2b4f14067bc9467a113de96834fd6bfcabd0e3a18ca64aa6b4560804d4923c2424b5471409cc85bd929f2a28f8738760d19 + languageName: node + linkType: hard + "common-tags@npm:1.8.2": version: 1.8.2 resolution: "common-tags@npm:1.8.2" @@ -8974,6 +9082,15 @@ __metadata: languageName: node linkType: hard +"cross-fetch@npm:^3.0.4": + version: 3.1.6 + resolution: "cross-fetch@npm:3.1.6" + dependencies: + node-fetch: ^2.6.11 + checksum: 704b3519ab7de488328cc49a52cf1aa14132ec748382be5b9557b22398c33ffa7f8c2530e8a97ed8cb55da52b0a9740a9791d361271c4591910501682d981d9c + languageName: node + linkType: hard + "cross-fetch@npm:^3.1.4, cross-fetch@npm:^3.1.5": version: 3.1.5 resolution: "cross-fetch@npm:3.1.5" @@ -9184,6 +9301,13 @@ __metadata: languageName: node linkType: hard +"dateformat@npm:^4.6.3": + version: 4.6.3 + resolution: "dateformat@npm:4.6.3" + checksum: c3aa0617c0a5b30595122bc8d1bee6276a9221e4d392087b41cbbdf175d9662ae0e50d0d6dcdf45caeac5153c4b5b0844265f8cd2b2245451e3da19e39e3b65d + languageName: node + linkType: hard + "dayjs@npm:1.11.7, dayjs@npm:~1.11.5": version: 1.11.7 resolution: "dayjs@npm:1.11.7" @@ -10746,7 +10870,7 @@ __metadata: languageName: node linkType: hard -"events@npm:^3.2.0": +"events@npm:^3.2.0, events@npm:^3.3.0": version: 3.3.0 resolution: "events@npm:3.3.0" checksum: f6f487ad2198aa41d878fa31452f1a3c00958f46e9019286ff4787c84aac329332ab45c9cdc8c445928fc6d7ded294b9e005a7fce9426488518017831b272780 @@ -10899,6 +11023,13 @@ __metadata: languageName: node linkType: hard +"fast-copy@npm:^3.0.0": + version: 3.0.1 + resolution: "fast-copy@npm:3.0.1" + checksum: 5496b5cf47df29eea479deef03b6b7188626a2cbc356b3015649062846729de6f1a9f555f937e772da8feae0a1231fab13096ed32424b2d61e4d065abc9969fe + languageName: node + linkType: hard + "fast-decode-uri-component@npm:^1.0.1": version: 1.0.1 resolution: "fast-decode-uri-component@npm:1.0.1" @@ -10970,6 +11101,20 @@ __metadata: languageName: node linkType: hard +"fast-redact@npm:^3.1.1": + version: 3.2.0 + resolution: "fast-redact@npm:3.2.0" + checksum: 7305740bbc708b0c5662f46fc30ec910da519275574fea84f6df0bea0cfe6066ddf90c6c4b879642c509e692edf862edd22eaccb2a647db122eebe8259942888 + languageName: node + linkType: hard + +"fast-safe-stringify@npm:^2.1.1": + version: 2.1.1 + resolution: "fast-safe-stringify@npm:2.1.1" + checksum: a851cbddc451745662f8f00ddb622d6766f9bd97642dabfd9a405fb0d646d69fc0b9a1243cbf67f5f18a39f40f6fa821737651ff1bceeba06c9992ca2dc5bd3d + languageName: node + linkType: hard + "fast-shallow-equal@npm:^1.0.0": version: 1.0.0 resolution: "fast-shallow-equal@npm:1.0.0" @@ -11856,7 +12001,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^8.0.1, glob@npm:^8.0.3": +"glob@npm:^8.0.0, glob@npm:^8.0.1, glob@npm:^8.0.3": version: 8.1.0 resolution: "glob@npm:8.1.0" dependencies: @@ -12147,6 +12292,18 @@ __metadata: languageName: node linkType: hard +"graphql-request@npm:^6.1.0": + version: 6.1.0 + resolution: "graphql-request@npm:6.1.0" + dependencies: + "@graphql-typed-document-node/core": ^3.2.0 + cross-fetch: ^3.1.5 + peerDependencies: + graphql: 14 - 16 + checksum: 6d62630a0169574442320651c1f7626c0c602025c3c46b19e09417c9579bb209306ee63de9793a03be2e1701bb7f13971f8545d99bc6573e340f823af0ad35b2 + languageName: node + linkType: hard + "graphql-tag@npm:^2.11.0": version: 2.12.6 resolution: "graphql-tag@npm:2.12.6" @@ -12587,6 +12744,16 @@ __metadata: languageName: node linkType: hard +"help-me@npm:^4.0.1": + version: 4.2.0 + resolution: "help-me@npm:4.2.0" + dependencies: + glob: ^8.0.0 + readable-stream: ^3.6.0 + checksum: 6548acba10dd79ebfc93f0d739c4cb2f32f7932c8d87b091992f3a0f844706263415eab81be015aed4ab874154232beb666920d7e280502c6bba29a40cde343e + languageName: node + linkType: hard + "hi-base32@npm:~0.5.0": version: 0.5.1 resolution: "hi-base32@npm:0.5.1" @@ -13908,6 +14075,13 @@ __metadata: languageName: node linkType: hard +"joycon@npm:^3.1.1": + version: 3.1.1 + resolution: "joycon@npm:3.1.1" + checksum: 8003c9c3fc79c5c7602b1c7e9f7a2df2e9916f046b0dbad862aa589be78c15734d11beb9fe846f5e06138df22cb2ad29961b6a986ba81c4920ce2b15a7f11067 + languageName: node + linkType: hard + "js-cookie@npm:^2.2.1": version: 2.2.1 resolution: "js-cookie@npm:2.2.1" @@ -13990,6 +14164,17 @@ __metadata: languageName: node linkType: hard +"js@npm:^0.1.0": + version: 0.1.0 + resolution: "js@npm:0.1.0" + dependencies: + commander: ~1.1.1 + bin: + js: ./bin/js + checksum: c2967be06de24caace5044d7cd6d9571034cdaae3da5a0a19602a2791d0654e9c87c53fed00283ae861a055c1db82ff0bda26ad9381aa915f3f06205c3f91c7c + languageName: node + linkType: hard + "jsbn@npm:~0.1.0": version: 0.1.1 resolution: "jsbn@npm:0.1.1" @@ -14239,6 +14424,13 @@ __metadata: languageName: node linkType: hard +"keypress@npm:0.1.x": + version: 0.1.0 + resolution: "keypress@npm:0.1.0" + checksum: 3a7e9dc0354dc6e5cfd4a507263dee4d736381d1bf40b59b73ed9972aef9b5e5be3ce6df24ca67d1530c9fe9cf90b913c6d2cc49f610b4077af379933a2968a5 + languageName: node + linkType: hard + "keyv@npm:^4.0.0, keyv@npm:^4.5.2": version: 4.5.2 resolution: "keyv@npm:4.5.2" @@ -16551,6 +16743,13 @@ __metadata: languageName: node linkType: hard +"on-exit-leak-free@npm:^2.1.0": + version: 2.1.0 + resolution: "on-exit-leak-free@npm:2.1.0" + checksum: 7334d98b87b0c89c9b69c747760b21196ff35afdedc4eaf1a0a3a02964463d7f6802481b120e4c8298967c74773ca7b914ab2eb3d9b279010eb7f67ac4960eed + languageName: node + linkType: hard + "on-finished@npm:2.4.1": version: 2.4.1 resolution: "on-finished@npm:2.4.1" @@ -17189,6 +17388,68 @@ __metadata: languageName: node linkType: hard +"pino-abstract-transport@npm:^1.0.0, pino-abstract-transport@npm:v1.0.0": + version: 1.0.0 + resolution: "pino-abstract-transport@npm:1.0.0" + dependencies: + readable-stream: ^4.0.0 + split2: ^4.0.0 + checksum: 05dd0eda52dd99fd204b39fe7b62656744b63e863bc052cdd5105d25f226a236966d0a46e39a1ace4838f6e988c608837ff946d2d0bc92835ca7baa0a3bff8d8 + languageName: node + linkType: hard + +"pino-pretty@npm:^10.0.0": + version: 10.0.0 + resolution: "pino-pretty@npm:10.0.0" + dependencies: + colorette: ^2.0.7 + dateformat: ^4.6.3 + fast-copy: ^3.0.0 + fast-safe-stringify: ^2.1.1 + help-me: ^4.0.1 + joycon: ^3.1.1 + minimist: ^1.2.6 + on-exit-leak-free: ^2.1.0 + pino-abstract-transport: ^1.0.0 + pump: ^3.0.0 + readable-stream: ^4.0.0 + secure-json-parse: ^2.4.0 + sonic-boom: ^3.0.0 + strip-json-comments: ^3.1.1 + bin: + pino-pretty: bin.js + checksum: af45c69fdb50bdd27875d1456b7f2a7227bc1b98ca8b39ff3a4ef0c473ac8bd2ae1cb7de19921dc8cc0217b6d5f800c7af040eae294e5cc26e0fadf0a0a4afd7 + languageName: node + linkType: hard + +"pino-std-serializers@npm:^6.0.0": + version: 6.2.1 + resolution: "pino-std-serializers@npm:6.2.1" + checksum: 9f86579dea7939a5d63c8313b0e2c3ad778a92aa9011a64d170677552b7634025738df890d09679eeed8be334ea90d37ded4b7a8cef4e3fa4d9c4387d339f905 + languageName: node + linkType: hard + +"pino@npm:^8.14.1": + version: 8.14.1 + resolution: "pino@npm:8.14.1" + dependencies: + atomic-sleep: ^1.0.0 + fast-redact: ^3.1.1 + on-exit-leak-free: ^2.1.0 + pino-abstract-transport: v1.0.0 + pino-std-serializers: ^6.0.0 + process-warning: ^2.0.0 + quick-format-unescaped: ^4.0.3 + real-require: ^0.2.0 + safe-stable-stringify: ^2.3.1 + sonic-boom: ^3.1.0 + thread-stream: ^2.0.0 + bin: + pino: bin.js + checksum: 72dcae8f550d375695bb8745f11b30c42aaa20d0bcab8f546ca5af0684d784453850949fe1b244206793e813a46d72cbbf0dda8aed2cee86e9491ba44a643e3e + languageName: node + linkType: hard + "pluralize@npm:^8.0.0": version: 8.0.0 resolution: "pluralize@npm:8.0.0" @@ -17494,6 +17755,13 @@ __metadata: languageName: node linkType: hard +"process-warning@npm:^2.0.0": + version: 2.2.0 + resolution: "process-warning@npm:2.2.0" + checksum: 394ae451c2622ee7d014a7196d36658fc1a5d5cc9f3bfeb54aadd5b77fcfecc89a30a25db259ae76ff49fde3f3f3dd7031dcdfb4da2e5445dac795549352e5d0 + languageName: node + linkType: hard + "process@npm:^0.11.10": version: 0.11.10 resolution: "process@npm:0.11.10" @@ -17791,6 +18059,13 @@ __metadata: languageName: node linkType: hard +"quick-format-unescaped@npm:^4.0.3": + version: 4.0.4 + resolution: "quick-format-unescaped@npm:4.0.4" + checksum: 7bc32b99354a1aa46c089d2a82b63489961002bb1d654cee3e6d2d8778197b68c2d854fd23d8422436ee1fdfd0abaddc4d4da120afe700ade68bd357815b26fd + languageName: node + linkType: hard + "quick-lru@npm:^4.0.1": version: 4.0.1 resolution: "quick-lru@npm:4.0.1" @@ -18191,6 +18466,18 @@ __metadata: languageName: node linkType: hard +"readable-stream@npm:^4.0.0": + version: 4.4.0 + resolution: "readable-stream@npm:4.4.0" + dependencies: + abort-controller: ^3.0.0 + buffer: ^6.0.3 + events: ^3.3.0 + process: ^0.11.10 + checksum: cc1630c2de134aee92646e77b1770019633000c408fd48609babf2caa53f00ca794928023aa9ad3d435a1044cec87d2ce7e2b7389dd1caf948b65c175edb7f52 + languageName: node + linkType: hard + "readable-stream@npm:~1.0.26-4": version: 1.0.34 resolution: "readable-stream@npm:1.0.34" @@ -18237,6 +18524,13 @@ __metadata: languageName: node linkType: hard +"real-require@npm:^0.2.0": + version: 0.2.0 + resolution: "real-require@npm:0.2.0" + checksum: fa060f19f2f447adf678d1376928c76379dce5f72bd334da301685ca6cdcb7b11356813332cc243c88470796bc2e2b1e2917fc10df9143dd93c2ea608694971d + languageName: node + linkType: hard + "rechoir@npm:^0.6.2": version: 0.6.2 resolution: "rechoir@npm:0.6.2" @@ -18828,6 +19122,13 @@ __metadata: languageName: node linkType: hard +"safe-stable-stringify@npm:^2.3.1": + version: 2.4.3 + resolution: "safe-stable-stringify@npm:2.4.3" + checksum: 3aeb64449706ee1f5ad2459fc99648b131d48e7a1fbb608d7c628020177512dc9d94108a5cb61bbc953985d313d0afea6566d243237743e02870490afef04b43 + languageName: node + linkType: hard + "safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0, safer-buffer@npm:^2.0.2, safer-buffer@npm:^2.1.0, safer-buffer@npm:~2.1.0": version: 2.1.2 resolution: "safer-buffer@npm:2.1.2" @@ -18952,6 +19253,13 @@ __metadata: languageName: node linkType: hard +"secure-json-parse@npm:^2.4.0": + version: 2.7.0 + resolution: "secure-json-parse@npm:2.7.0" + checksum: d9d7d5a01fc6db6115744ba23cf9e67ecfe8c524d771537c062ee05ad5c11b64c730bc58c7f33f60bd6877f96b86f0ceb9ea29644e4040cb757f6912d4dd6737 + languageName: node + linkType: hard + "semver-diff@npm:^4.0.0": version: 4.0.0 resolution: "semver-diff@npm:4.0.0" @@ -19195,7 +19503,7 @@ __metadata: languageName: node linkType: hard -"shelljs@npm:^0.8.3, shelljs@npm:^0.8.5": +"shelljs@npm:^0.8.3": version: 0.8.5 resolution: "shelljs@npm:0.8.5" dependencies: @@ -19492,6 +19800,15 @@ __metadata: languageName: node linkType: hard +"sonic-boom@npm:^3.0.0, sonic-boom@npm:^3.1.0": + version: 3.3.0 + resolution: "sonic-boom@npm:3.3.0" + dependencies: + atomic-sleep: ^1.0.0 + checksum: 4a290dd0f3edf49894bb72c631ee304dc3f9be0752c43d516808a365f341821f5cf49997c80ee7c0e67167e0e5131dc71afe7c58812858eb965d6b9746c0cac7 + languageName: node + linkType: hard + "source-map-js@npm:^1.0.2": version: 1.0.2 resolution: "source-map-js@npm:1.0.2" @@ -19589,6 +19906,13 @@ __metadata: languageName: node linkType: hard +"split2@npm:^4.0.0": + version: 4.2.0 + resolution: "split2@npm:4.2.0" + checksum: 05d54102546549fe4d2455900699056580cca006c0275c334611420f854da30ac999230857a85fdd9914dc2109ae50f80fda43d2a445f2aa86eccdc1dfce779d + languageName: node + linkType: hard + "split@npm:^1.0.0": version: 1.0.1 resolution: "split@npm:1.0.1" @@ -19674,6 +19998,13 @@ __metadata: languageName: node linkType: hard +"stack-trace@npm:^0.0.10": + version: 0.0.10 + resolution: "stack-trace@npm:0.0.10" + checksum: 473036ad32f8c00e889613153d6454f9be0536d430eb2358ca51cad6b95cea08a3cc33cc0e34de66b0dad221582b08ed2e61ef8e13f4087ab690f388362d6610 + languageName: node + linkType: hard + "stackframe@npm:^1.3.4": version: 1.3.4 resolution: "stackframe@npm:1.3.4" @@ -20353,6 +20684,15 @@ __metadata: languageName: node linkType: hard +"thread-stream@npm:^2.0.0": + version: 2.3.0 + resolution: "thread-stream@npm:2.3.0" + dependencies: + real-require: ^0.2.0 + checksum: e9ea58f9f36320165b41c2aae5c439bf68bd3575eb533c458483d8b290e31d519979e351408c7d6e248711611434332c2a3aae2165650b028cc3eb9b1052ac16 + languageName: node + linkType: hard + "throttle-debounce@npm:^3.0.1": version: 3.0.1 resolution: "throttle-debounce@npm:3.0.1"