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
+
+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"