diff --git a/.gitignore b/.gitignore index b3b19025..89c24070 100644 --- a/.gitignore +++ b/.gitignore @@ -204,3 +204,23 @@ veascan-subgraph-inbox/generated/* veascan-subgraph-inbox/build/* validator-subgraph-inbox/generated/* validator-subgraph-inbox/build/* + +# Hardhat files +cache +artifacts +coverage.json + +## Hardhat typechain bindings/types +typechain +typechain/** +typechain-types +typechain-types/** + +# Hardhat deploy files +contracts/deployments/localhost +contracts/deployments/hardhat +contracts/deployments/*/solcInputs/ + +# POA solidity flattener output +out/ + 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/.gitignore b/contracts/.gitignore deleted file mode 100644 index 761c8beb..00000000 --- a/contracts/.gitignore +++ /dev/null @@ -1,181 +0,0 @@ -# Hardhat files -cache -artifacts -coverage.json - -## Hardhat typechain bindings/types -typechain -typechain/** -typechain-types -typechain-types/** - -# Hardhat deploy files -deployments/localhost -deployments/hardhat -deployments/*/solcInputs/ - -# POA solidity flattener output -out/ - -# Created by https://www.toptal.com/developers/gitignore/api/vim,node,visualstudiocode,yarn -# Edit at https://www.toptal.com/developers/gitignore?templates=vim,node,visualstudiocode,yarn - -### Node ### -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* - -# Diagnostic reports (https://nodejs.org/api/report.html) -report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage -*.lcov - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# TypeScript v1 declaration files -typings/ - -# TypeScript cache -*.tsbuildinfo - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Microbundle cache -.rpt2_cache/ -.rts2_cache_cjs/ -.rts2_cache_es/ -.rts2_cache_umd/ - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env -.env.test - -# parcel-bundler cache (https://parceljs.org/) -.cache - -# Next.js build output -.next - -# Nuxt.js build / generate output -.nuxt -dist - -# Gatsby files -.cache/ -# Comment in the public line in if your project uses Gatsby and not Next.js -# https://nextjs.org/blog/next-9-1#public-directory-support -# public - -# vuepress build output -.vuepress/dist - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# TernJS port file -.tern-port - -# Stores VSCode versions used for testing VSCode extensions -.vscode-test - -### Vim ### -# Swap -[._]*.s[a-v][a-z] -!*.svg # comment out if you don't need vector files -[._]*.sw[a-p] -[._]s[a-rt-v][a-z] -[._]ss[a-gi-z] -[._]sw[a-p] - -# Session -Session.vim -Sessionx.vim - -# Temporary -.netrwhist -*~ -# Auto-generated tag files -tags -# Persistent undo -[._]*.un~ - -### VisualStudioCode ### -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json -*.code-workspace - -### VisualStudioCode Patch ### -# Ignore all local history of files -.history - -### yarn ### -# https://yarnpkg.com/advanced/qa#which-files-should-be-gitignored - -# .yarn/unplugged and .yarn/build-state.yml should likely always be ignored since -# they typically hold machine-specific build artifacts. Ignoring them might however -# prevent Zero-Installs from working (to prevent this, set enableScripts to false). -.yarn/unplugged -.yarn/build-state.yml - -# .yarn/cache and .pnp.* may be safely ignored, but you'll need to run yarn install -# to regenerate them between each branch switch. -# Uncomment the following lines if you're not using Zero-Installs: -# .yarn/cache -# .pnp.* - -# End of https://www.toptal.com/developers/gitignore/api/vim,node,visualstudiocode,yarn - diff --git a/contracts/.npmignore b/contracts/.npmignore index 382ffca6..faa64d38 100644 --- a/contracts/.npmignore +++ b/contracts/.npmignore @@ -1,2 +1,6 @@ -# NOP, just force npm to disregard .gitignore -# https://docs.npmjs.com/cli/v9/using-npm/developers#keeping-files-out-of-your-package +.env* +scripts +deploy +tsconfig.json +test +hardhat.config.* \ No newline at end of file diff --git a/contracts/package.json b/contracts/package.json index 8e741d3d..a9b63e2b 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -1,7 +1,10 @@ { "name": "@kleros/vea-contracts", - "version": "0.1.14", + "version": "0.3.2", "description": "Smart contracts for Vea", + "main": "dist/index.js", + "module": "dist/index.js", + "types": "dist/index.d.ts", "repository": { "type": "git", "url": "git+ssh://git@github.com/kleros/vea.git" @@ -32,7 +35,7 @@ }, "scripts": { "build": "hardhat compile", - "clean": "hardhat clean", + "clean": "hardhat clean && rm -rf dist typechain-types", "check": "hardhat check", "test": "TS_NODE_TRANSPILE_ONLY=1 hardhat test", "start": "hardhat node --tags nothing", @@ -44,9 +47,10 @@ "size": "hardhat size-contracts --no-compile", "watch": "hardhat watch", "docgen": "hardhat docgen", - "release:patch": "scripts/publish.sh patch", - "release:minor": "scripts/publish.sh minor", - "release:major": "scripts/publish.sh major" + "release:patch": "yarn version patch && yarn npm publish", + "release:minor": "yarn version minor && yarn npm publish", + "release:major": "yarn version major && yarn npm publish", + "prepublish": "./scripts/prepublish.sh" }, "devDependencies": { "@nomicfoundation/hardhat-chai-matchers": "^1.0.6", @@ -75,7 +79,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", @@ -84,5 +87,19 @@ }, "dependencies": { "@openzeppelin/contracts": "^4.8.3" - } + }, + "files": [ + "src", + "deployments", + "typechain-types", + "!hardhat.config.*", + "!src/test", + "!typechain-types/test", + "!typechain-types/factories/test", + "!test", + "!deploy", + "!deployments/localhost", + "!deployments/hardhat", + "!deployments/**/solcInputs" + ] } diff --git a/contracts/scripts/prepublish.sh b/contracts/scripts/prepublish.sh new file mode 100755 index 00000000..b9d76bc8 --- /dev/null +++ b/contracts/scripts/prepublish.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" + +# Remove the mock contracts from the typechain types +sed -n -i '' '/test/!p' $SCRIPT_DIR/../typechain-types/index.ts +sed -n -i '' '/test/!p' $SCRIPT_DIR/../typechain-types/factories/index.ts +rm -rf \ + $SCRIPT_DIR/../typechain-types/test/ \ + $SCRIPT_DIR/../typechain-types/factories/test/ + +yarn tsc -p $SCRIPT_DIR/../tsconfig.publish.json \ No newline at end of file diff --git a/contracts/scripts/publish.sh b/contracts/scripts/publish.sh deleted file mode 100755 index 3fe76910..00000000 --- a/contracts/scripts/publish.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" - -#-------------------------------------- -# Error handling -#-------------------------------------- - -set -Ee -function _catch { - # Don't propagate to outer shell - exit 0 -} -function _finally { - # TODO: rollback version bump - rm -rf $SCRIPT_DIR/../dist -} -trap _catch ERR -trap _finally EXIT - -#-------------------------------------- - -yarn version $1 - -mkdir dist -cp -pr README.md deployments src/ dist/ -rm -rf dist/test -jq 'del(.scripts.prepare)' package.json > dist/package.json - -cd dist -npm publish -cd - diff --git a/contracts/tsconfig.json b/contracts/tsconfig.json index 0399f604..fa5cbd79 100644 --- a/contracts/tsconfig.json +++ b/contracts/tsconfig.json @@ -8,7 +8,8 @@ "declaration": true, "sourceMap": true, "noImplicitAny": false, - "resolveJsonModule": true + "resolveJsonModule": true, + "skipLibCheck": true }, "include": [ "./src", @@ -17,6 +18,10 @@ "./typechain-types", "./deploy" ], + "exclude": [ + "node_modules", + "dist" + ], "files": [ "./hardhat.config.ts" ] diff --git a/contracts/tsconfig.publish.json b/contracts/tsconfig.publish.json new file mode 100644 index 00000000..14d13562 --- /dev/null +++ b/contracts/tsconfig.publish.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "es2021", + "module": "commonjs", + "strict": true, + "esModuleInterop": true, + "outDir": "typechain-types", + "declaration": true, + "sourceMap": true, + "noImplicitAny": false, + "resolveJsonModule": true, + "skipLibCheck": true + }, + "include": [ + "./typechain-types" + ], + "exclude": [ + "node_modules", + "dist" + ] +} 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/vea-sdk/.env.dist b/vea-sdk/.env.dist new file mode 100644 index 00000000..d6797915 --- /dev/null +++ b/vea-sdk/.env.dist @@ -0,0 +1,9 @@ +PRIVATE_KEY=0x.... + +RPC_CHIADO=https://rpc.chiadochain.net +RPC_ARB_GOERLI=https://goerli-rollup.arbitrum.io/rpc +RPC_GOERLI= + +# Optional +LOG_LEVEL= +LOGTAIL_TOKEN= \ 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..08be6337 --- /dev/null +++ b/vea-sdk/README.md @@ -0,0 +1,33 @@ +# 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"; + +// Create the Vea client +const vea = VeaSdk.ClientFactory.arbitrumGoerliToChiadoDevnet( + "https://rpc.goerli.eth.gateway.fm", + "https://rpc.chiado.gnosis.gateway.fm" +); + +// Get the message info +const messageId = 42; +const messageInfo = await vea.getMessageInfo(messageId); + +// Relay the message +const privateKey = process.env["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..581df141 --- /dev/null +++ b/vea-sdk/examples/index.ts @@ -0,0 +1,39 @@ +import { Wallet } from "@ethersproject/wallet"; +import VeaSdk from "../src/index"; +import env from "../src/utils/env"; + +async function main() { + // Optional logger configuration + const loggerOptions = { + transportTargetOptions: { + target: "@logtail/pino", + options: { sourceToken: env.require("LOGTAIL_TOKEN") }, + level: env.optional("LOG_LEVEL", "info"), + }, + }; + + // Create the Vea client + const vea = VeaSdk.ClientFactory.arbitrumGoerliToChiadoDevnet( + env.require("RPC_ARB_GOERLI"), + env.require("RPC_CHIADO"), + loggerOptions + ); + + // Get the current state root + const logger = vea.logger; + logger.info(`stateRoot=${await vea.outbox.stateRoot()}`); + + // Get a message info + const messageId = 1; + const messageInfo = await vea.getMessageInfo(messageId); + + // Relay the message + const privateKey = env.require("PRIVATE_KEY"); + const wallet = new Wallet(privateKey, vea.outboxProvider); + await vea.relay(messageInfo, wallet); +} + +main().catch((e) => { + VeaSdk.ClientFactory.logger.error(e); + process.exit(1); +}); diff --git a/vea-sdk/package.json b/vea-sdk/package.json new file mode 100644 index 00000000..6fcc9df4 --- /dev/null +++ b/vea-sdk/package.json @@ -0,0 +1,58 @@ +{ + "name": "@kleros/vea-sdk", + "version": "0.4.0", + "description": "SDK for the development of cross-chain apps on Vea", + "main": "dist/index.js", + "module": "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 ./examples/index.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" + }, + "dependencies": { + "@kleros/vea-contracts": "workspace:^0.3.2", + "@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", + "examples" + ] +} diff --git a/vea-sdk/src/bridges.ts b/vea-sdk/src/bridges.ts new file mode 100644 index 00000000..4066bae0 --- /dev/null +++ b/vea-sdk/src/bridges.ts @@ -0,0 +1,54 @@ +import { address as veaInboxArbToGnosisDevnet } from "@kleros/vea-contracts/deployments/arbitrumGoerli/VeaInboxArbToGnosisDevnet.json"; +import { address as veaOutboxArbToGnosisDevnet } from "@kleros/vea-contracts/deployments/chiado/VeaOutboxArbToGnosisDevnet.json"; + +import { address as veaInboxArbToEthDevnet } from "@kleros/vea-contracts/deployments/arbitrumGoerli/VeaInboxArbToEthDevnet.json"; +import { address as veaOutboxArbToEthDevnet } from "@kleros/vea-contracts/deployments/goerli/VeaOutboxArbToEthDevnet.json"; + +import { + VeaInboxArbToEth__factory, + VeaOutboxArbToGnosisDevnet__factory, + VeaOutboxArbToEthDevnet__factory, +} from "@kleros/vea-contracts/typechain-types"; + +export type VeaInboxFactory = VeaInboxArbToEth__factory; +export type VeaOutboxFactory = VeaOutboxArbToGnosisDevnet__factory | 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: veaInboxArbToGnosisDevnet as `0x${string}`, + outboxAddress: veaOutboxArbToGnosisDevnet as `0x${string}`, + inboxFactory: new VeaInboxArbToEth__factory(), + outboxFactory: new VeaOutboxArbToGnosisDevnet__factory(), + inboxSubgraph: getSubgraphUrl("vea-inbox-arbgoerli-to-chiado"), + outboxSubgraph: getSubgraphUrl("FIX ME"), // TODO +}; + +export const arbitrumGoerliToGoerliDevnet: Bridge = { + label: "Arbitrum to Goerli Devnet", + inboxChainId: 421613, + outboxChainId: 5, + inboxAddress: veaInboxArbToEthDevnet as `0x${string}`, + outboxAddress: veaOutboxArbToEthDevnet as `0x${string}`, + inboxFactory: new VeaInboxArbToEth__factory(), + outboxFactory: new 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..cf99cb69 --- /dev/null +++ b/vea-sdk/src/client.ts @@ -0,0 +1,53 @@ +import { JsonRpcProvider } from "@ethersproject/providers"; +import { ContractTransaction } from "@ethersproject/contracts"; +import { Signer } from "@ethersproject/abstract-signer"; +import { Logger } from "pino"; +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; + readonly inboxProvider: JsonRpcProvider; + readonly outboxProvider: JsonRpcProvider; + readonly inbox: VeaInbox; + readonly outbox: VeaOutbox; + readonly logger: Logger; + + constructor( + config: VeaClientConfig, + inboxProvider: JsonRpcProvider, + outboxProvider: JsonRpcProvider, + inbox: VeaInboxArbToEth, + outbox: VeaOutboxArbToEthDevnet | VeaOutboxArbToGnosisDevnet, + logger: Logger + ) { + this.config = config; + this.inboxProvider = inboxProvider; + this.outboxProvider = outboxProvider; + this.inbox = inbox; + this.outbox = outbox; + this.logger = logger; + } + + 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..9c184457 --- /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.inboxSubgraph; + 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.inboxSubgraph; + const result: any = await request(subgraph, query); + for (let i = 0; i < proofIndices.length; i++) { + proof.push(result[`layer${i}`][0].hash); + } + } catch (e) { + client.logger.error(e, "Error getting proof from subgraph"); + } + 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.inboxSubgraph; + const query = `{ + messageSents(first: 5, where: {nonce: ${messageId}}) { + nonce + to { + id + } + data + } + }`; + const result: any = await request(subgraph, query); + dataAndTo = [result[`messageSents`][0].to.id, result[`messageSents`][0].data]; + } catch (e) { + client.logger.error(e, "Error getting message data from subgraph"); + } + return dataAndTo; +}; diff --git a/vea-sdk/src/sdk.ts b/vea-sdk/src/sdk.ts new file mode 100644 index 00000000..72c414ba --- /dev/null +++ b/vea-sdk/src/sdk.ts @@ -0,0 +1,56 @@ +import { JsonRpcProvider } from "@ethersproject/providers"; +import loggerFactory from "./utils/logger"; +import * as Bridges from "./bridges"; +import { VeaClient, VeaClientConfig } from "./client"; + +export class ClientFactory { + static logger = loggerFactory.createLogger(); + + private static configure( + bridge: Bridges.Bridge, + inboxRpc: string, + outboxRpc: string, + loggerOptions?: loggerFactory.LoggerOptions + ): VeaClient { + const config: VeaClientConfig = { + bridge, + inboxRpc: inboxRpc, + outboxRpc: outboxRpc, + }; + const inboxProvider = new JsonRpcProvider(inboxRpc); + const outboxProvider = new JsonRpcProvider(outboxRpc); + const veaInbox = Object.getPrototypeOf(bridge.inboxFactory).constructor.connect(bridge.inboxAddress, inboxProvider); + const veaOutbox = Object.getPrototypeOf(bridge.outboxFactory).constructor.connect( + bridge.outboxAddress, + outboxProvider + ); + this.logger = loggerFactory.createLogger(loggerOptions).child({ + bridge: bridge.label, + inbox: bridge.inboxAddress, + outbox: bridge.outboxAddress, + }); + inboxProvider.getNetwork().then((network) => { + if (network.chainId !== bridge.inboxChainId) throw new Error("Incorrect Inbox RPC"); + }); + outboxProvider.getNetwork().then((network) => { + if (network.chainId !== bridge.outboxChainId) throw new Error("Incorrect Outbox RPC"); + }); + return new VeaClient(config, inboxProvider, outboxProvider, veaInbox, veaOutbox, this.logger); + } + + static arbitrumGoerliToChiadoDevnet( + inboxRpc: string, + outboxRpc: string, + loggerOptions?: loggerFactory.LoggerOptions + ): VeaClient { + return this.configure(Bridges.arbitrumGoerliToChiadoDevnet, inboxRpc, outboxRpc, loggerOptions); + } + + static arbitrumGoerliToGoerliDevnet( + inboxRpc: string, + outboxRpc: string, + loggerOptions?: loggerFactory.LoggerOptions + ): VeaClient { + return this.configure(Bridges.arbitrumGoerliToGoerliDevnet, inboxRpc, outboxRpc, loggerOptions); + } +} diff --git a/vea-sdk/src/utils/env.ts b/vea-sdk/src/utils/env.ts new file mode 100644 index 00000000..ef815ef8 --- /dev/null +++ b/vea-sdk/src/utils/env.ts @@ -0,0 +1,24 @@ +import dotenv from "dotenv"; + +dotenv.config(); + +namespace env { + export const require = (key: string): string => { + const value = process.env[key]; + if (value === undefined) { + throw new Error(`Environment variable ${key} is undefined`); + } + return value; + }; + + export const optional = (key: string, defaultValue: string): string => { + const value = process.env[key]; + return value === undefined ? defaultValue : value; + }; + + export const optionalNoDefault = (key: string): string | undefined => { + return process.env[key]; + }; +} + +export default env; diff --git a/vea-sdk/src/utils/logger.ts b/vea-sdk/src/utils/logger.ts new file mode 100644 index 00000000..d00dc523 --- /dev/null +++ b/vea-sdk/src/utils/logger.ts @@ -0,0 +1,36 @@ +import pino from "pino"; +import { TransportTargetOptions } from "pino"; +import dotenv from "dotenv"; + +dotenv.config(); + +namespace logger { + export type LoggerOptions = { + level?: string; + transportTargetOptions?: TransportTargetOptions; + }; + + export const createLogger = (options?: LoggerOptions): pino.Logger => { + const targets: TransportTargetOptions[] = [ + { + target: "pino-pretty", + options: {}, + level: options?.level ?? "info", + }, + ]; + + if (options?.transportTargetOptions) { + targets.push(options.transportTargetOptions); + } + + return pino( + { + level: options?.level ?? "info", + timestamp: pino.stdTimeFunctions.isoTime, + }, + pino.transport({ targets: targets }) + ); + }; +} + +export default logger; diff --git a/vea-sdk/tsconfig.json b/vea-sdk/tsconfig.json new file mode 100644 index 00000000..e1ae9e5f --- /dev/null +++ b/vea-sdk/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "es2021", + "module": "commonjs", + "strict": true, + "esModuleInterop": true, + "outDir": "dist", + "declaration": true, + "sourceMap": true, + "noImplicitAny": false, + "resolveJsonModule": true, + "skipLibCheck": true, + "paths": { + "@kleros/vea-contracts": [ + "../contracts" + ] + } + }, + "include": [ + "src" + ], + "exclude": [ + "node_modules", + "dist" + ] +} diff --git a/yarn.lock b/yarn.lock index cb23dd91..b3a6ec79 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.3.2, @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,6 +3421,25 @@ __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.3.2" + "@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" @@ -3564,6 +3582,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 +3681,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 +5893,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 +7043,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 +8423,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 +8526,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 +9078,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 +9297,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 +10866,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 +11019,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 +11097,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 +11997,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 +12288,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 +12740,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 +14071,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 +14160,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 +14420,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 +16739,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 +17384,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 +17751,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 +18055,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 +18462,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 +18520,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 +19118,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 +19249,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 +19499,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 +19796,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 +19902,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 +19994,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 +20680,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"