From eec1965980b338ebb7b14008ec02422cd5af6240 Mon Sep 17 00:00:00 2001 From: prathamesh0 <42446521+prathamesh0@users.noreply.github.com> Date: Thu, 20 Jul 2023 17:22:48 +0530 Subject: [PATCH] Add a payments plugin to GQL server (#391) * Add a custom payments plugin in server process * Fix voucher channel read in voucher subscription * Use voucher hash and signature for payment authentication * Use a LRU hash map for storing received vouchers * Avoid hoisting level types to resolve build errors * Upgrade ts-nitro packages * Add payments related logs * Upgrade package versions * Always allow latestBlock query * Upgrade ts-nitro packages --- lerna.json | 2 +- package.json | 3 +- packages/cache/package.json | 2 +- packages/cli/package.json | 6 +- packages/cli/src/server.ts | 8 +- packages/codegen/package.json | 4 +- .../src/templates/package-template.handlebars | 10 +- packages/graph-node/package.json | 10 +- packages/ipld-eth-client/package.json | 4 +- packages/peer/package.json | 2 +- packages/solidity-mapper/package.json | 4 +- packages/test/package.json | 2 +- packages/tracing-client/package.json | 2 +- packages/util/package.json | 12 +- packages/util/src/index.ts | 1 + packages/util/src/payments.ts | 210 ++++++++++++++++++ packages/util/src/server.ts | 6 +- yarn.lock | 115 +++++++++- 18 files changed, 369 insertions(+), 34 deletions(-) create mode 100644 packages/util/src/payments.ts diff --git a/lerna.json b/lerna.json index f7c80094d..def10ce0f 100644 --- a/lerna.json +++ b/lerna.json @@ -2,7 +2,7 @@ "packages": [ "packages/*" ], - "version": "0.2.46", + "version": "0.2.47", "npmClient": "yarn", "useWorkspaces": true, "command": { diff --git a/package.json b/package.json index e225c9cf8..b761611e5 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "packages/*" ], "nohoist": [ - "**/@graphprotocol/graph-ts" + "**/@graphprotocol/graph-ts", + "**/@types/level" ] }, "devDependencies": { diff --git a/packages/cache/package.json b/packages/cache/package.json index ffd692048..95a923c3d 100644 --- a/packages/cache/package.json +++ b/packages/cache/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/cache", - "version": "0.2.46", + "version": "0.2.47", "description": "Generic object cache", "main": "dist/index.js", "scripts": { diff --git a/packages/cli/package.json b/packages/cli/package.json index eff8afbad..356b9c3c6 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/cli", - "version": "0.2.46", + "version": "0.2.47", "main": "dist/index.js", "license": "AGPL-3.0", "scripts": { @@ -11,8 +11,8 @@ "chat": "DEBUG='vulcanize:*, laconic:*' node dist/chat.js" }, "dependencies": { - "@cerc-io/peer": "^0.2.46", - "@cerc-io/util": "^0.2.46", + "@cerc-io/peer": "^0.2.47", + "@cerc-io/util": "^0.2.47", "@ethersproject/providers": "^5.4.4", "@graphql-tools/utils": "^9.1.1", "@ipld/dag-cbor": "^8.0.0", diff --git a/packages/cli/src/server.ts b/packages/cli/src/server.ts index f1dbcd7fe..c97c626f6 100644 --- a/packages/cli/src/server.ts +++ b/packages/cli/src/server.ts @@ -25,7 +25,8 @@ import { EventWatcher, GraphWatcherInterface, Config, - P2PConfig + P2PConfig, + PaymentsManager } from '@cerc-io/util'; import { TypeSource } from '@graphql-tools/utils'; import { @@ -111,7 +112,8 @@ export class ServerCmd { async exec ( createResolvers: (indexer: IndexerInterface, eventWatcher: EventWatcher) => Promise, typeDefs: TypeSource, - parseLibp2pMessage?: (peerId: string, data: any) => void + parseLibp2pMessage?: (peerId: string, data: any) => void, + paymentsManager?: PaymentsManager ): Promise<{ app: Application, server: ApolloServer @@ -136,7 +138,7 @@ export class ServerCmd { // Create an Express app const app: Application = express(); - const server = await createAndStartServer(app, typeDefs, resolvers, config.server); + const server = await createAndStartServer(app, typeDefs, resolvers, config.server, paymentsManager); await startGQLMetricsServer(config); diff --git a/packages/codegen/package.json b/packages/codegen/package.json index a96619ce7..aeef3d8f2 100644 --- a/packages/codegen/package.json +++ b/packages/codegen/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/codegen", - "version": "0.2.46", + "version": "0.2.47", "description": "Code generator", "private": true, "main": "index.js", @@ -20,7 +20,7 @@ }, "homepage": "https://github.com/cerc-io/watcher-ts#readme", "dependencies": { - "@cerc-io/util": "^0.2.46", + "@cerc-io/util": "^0.2.47", "@graphql-tools/load-files": "^6.5.2", "@poanet/solidity-flattener": "https://github.com/vulcanize/solidity-flattener.git", "@solidity-parser/parser": "^0.13.2", diff --git a/packages/codegen/src/templates/package-template.handlebars b/packages/codegen/src/templates/package-template.handlebars index c5beab9d0..259bb028a 100644 --- a/packages/codegen/src/templates/package-template.handlebars +++ b/packages/codegen/src/templates/package-template.handlebars @@ -41,12 +41,12 @@ "homepage": "https://github.com/cerc-io/watcher-ts#readme", "dependencies": { "@apollo/client": "^3.3.19", - "@cerc-io/cli": "^0.2.46", - "@cerc-io/ipld-eth-client": "^0.2.46", - "@cerc-io/solidity-mapper": "^0.2.46", - "@cerc-io/util": "^0.2.46", + "@cerc-io/cli": "^0.2.47", + "@cerc-io/ipld-eth-client": "^0.2.47", + "@cerc-io/solidity-mapper": "^0.2.47", + "@cerc-io/util": "^0.2.47", {{#if (subgraphPath)}} - "@cerc-io/graph-node": "^0.2.46", + "@cerc-io/graph-node": "^0.2.47", {{/if}} "@ethersproject/providers": "^5.4.4", "apollo-type-bigint": "^0.1.3", diff --git a/packages/graph-node/package.json b/packages/graph-node/package.json index b256daa04..a5d38d205 100644 --- a/packages/graph-node/package.json +++ b/packages/graph-node/package.json @@ -1,10 +1,10 @@ { "name": "@cerc-io/graph-node", - "version": "0.2.46", + "version": "0.2.47", "main": "dist/index.js", "license": "AGPL-3.0", "devDependencies": { - "@cerc-io/solidity-mapper": "^0.2.46", + "@cerc-io/solidity-mapper": "^0.2.47", "@ethersproject/providers": "^5.4.4", "@graphprotocol/graph-ts": "^0.22.0", "@nomiclabs/hardhat-ethers": "^2.0.2", @@ -51,9 +51,9 @@ "dependencies": { "@apollo/client": "^3.3.19", "@cerc-io/assemblyscript": "0.19.10-watcher-ts-0.1.2", - "@cerc-io/cache": "^0.2.46", - "@cerc-io/ipld-eth-client": "^0.2.46", - "@cerc-io/util": "^0.2.46", + "@cerc-io/cache": "^0.2.47", + "@cerc-io/ipld-eth-client": "^0.2.47", + "@cerc-io/util": "^0.2.47", "@types/json-diff": "^0.5.2", "@types/yargs": "^17.0.0", "bn.js": "^4.11.9", diff --git a/packages/ipld-eth-client/package.json b/packages/ipld-eth-client/package.json index cf86a6080..078d292da 100644 --- a/packages/ipld-eth-client/package.json +++ b/packages/ipld-eth-client/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/ipld-eth-client", - "version": "0.2.46", + "version": "0.2.47", "description": "IPLD ETH Client", "main": "dist/index.js", "scripts": { @@ -20,7 +20,7 @@ "homepage": "https://github.com/cerc-io/watcher-ts#readme", "dependencies": { "@apollo/client": "^3.7.1", - "@cerc-io/cache": "^0.2.46", + "@cerc-io/cache": "^0.2.47", "cross-fetch": "^3.1.4", "debug": "^4.3.1", "ethers": "^5.4.4", diff --git a/packages/peer/package.json b/packages/peer/package.json index 58a6a5770..1d3700508 100644 --- a/packages/peer/package.json +++ b/packages/peer/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/peer", - "version": "0.2.46", + "version": "0.2.47", "description": "libp2p module", "main": "dist/index.js", "exports": "./dist/index.js", diff --git a/packages/solidity-mapper/package.json b/packages/solidity-mapper/package.json index 2c6ab8099..c1211eb6c 100644 --- a/packages/solidity-mapper/package.json +++ b/packages/solidity-mapper/package.json @@ -1,10 +1,10 @@ { "name": "@cerc-io/solidity-mapper", - "version": "0.2.46", + "version": "0.2.47", "main": "dist/index.js", "license": "AGPL-3.0", "devDependencies": { - "@cerc-io/ipld-eth-client": "^0.2.46", + "@cerc-io/ipld-eth-client": "^0.2.47", "@ethersproject/abi": "^5.3.0", "@nomiclabs/hardhat-ethers": "^2.0.2", "@nomiclabs/hardhat-waffle": "^2.0.1", diff --git a/packages/test/package.json b/packages/test/package.json index 1e712d08b..d8c47c60d 100644 --- a/packages/test/package.json +++ b/packages/test/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/test", - "version": "0.2.46", + "version": "0.2.47", "main": "dist/index.js", "license": "AGPL-3.0", "private": true, diff --git a/packages/tracing-client/package.json b/packages/tracing-client/package.json index e84f583c6..b8b476721 100644 --- a/packages/tracing-client/package.json +++ b/packages/tracing-client/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/tracing-client", - "version": "0.2.46", + "version": "0.2.47", "description": "ETH VM tracing client", "main": "dist/index.js", "scripts": { diff --git a/packages/util/package.json b/packages/util/package.json index 0faf11a1d..d5e7b13f4 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,11 +1,14 @@ { "name": "@cerc-io/util", - "version": "0.2.46", + "version": "0.2.47", "main": "dist/index.js", "license": "AGPL-3.0", "dependencies": { "@apollo/utils.keyvaluecache": "^1.0.1", - "@cerc-io/solidity-mapper": "^0.2.46", + "@cerc-io/nitro-client": "^0.1.3", + "@cerc-io/nitro-util": "^0.1.3", + "@cerc-io/solidity-mapper": "^0.2.47", + "@cerc-io/ts-channel": "1.0.3-ts-nitro-0.1.1", "@ethersproject/providers": "^5.4.4", "@graphql-tools/schema": "^9.0.10", "@graphql-tools/utils": "^9.1.1", @@ -26,6 +29,7 @@ "js-yaml": "^4.1.0", "json-bigint": "^1.0.0", "lodash": "^4.17.21", + "lru-cache": "^10.0.0", "multiformats": "^9.4.8", "pg": "^8.5.1", "pg-boss": "^6.1.0", @@ -37,8 +41,8 @@ "yargs": "^17.0.1" }, "devDependencies": { - "@cerc-io/cache": "^0.2.46", - "@cerc-io/ipld-eth-client": "^0.2.46", + "@cerc-io/cache": "^0.2.47", + "@cerc-io/ipld-eth-client": "^0.2.47", "@nomiclabs/hardhat-waffle": "^2.0.1", "@types/express": "^4.17.14", "@types/fs-extra": "^9.0.11", diff --git a/packages/util/src/index.ts b/packages/util/src/index.ts index 7e36591f4..6e37de19f 100644 --- a/packages/util/src/index.ts +++ b/packages/util/src/index.ts @@ -23,3 +23,4 @@ export * from './graph/database'; export * from './graph/utils'; export * from './graph/state-utils'; export * from './graph/types'; +export * from './payments'; diff --git a/packages/util/src/payments.ts b/packages/util/src/payments.ts new file mode 100644 index 000000000..491982cd4 --- /dev/null +++ b/packages/util/src/payments.ts @@ -0,0 +1,210 @@ +import debug from 'debug'; +import { ethers } from 'ethers'; +import { LRUCache } from 'lru-cache'; +import { FieldNode } from 'graphql'; +import { ApolloServerPlugin, GraphQLResponse, GraphQLRequestContext } from 'apollo-server-plugin-base'; +import { Response as HTTPResponse } from 'apollo-server-env'; + +import Channel from '@cerc-io/ts-channel'; +import type { ReadWriteChannel } from '@cerc-io/ts-channel'; +import type { Client, Signature, Voucher } from '@cerc-io/nitro-client'; +import { recoverEthereumMessageSigner, getSignatureFromEthersSignature } from '@cerc-io/nitro-client'; +import { hex2Bytes } from '@cerc-io/nitro-util'; + +const log = debug('laconic:payments'); + +const IntrospectionQuery = 'IntrospectionQuery'; +const HASH_HEADER_KEY = 'hash'; +const SIG_HEADER_KEY = 'sig'; + +const ERR_FREE_QUOTA_EXHUASTED = 'Free quota exhausted'; +const ERR_PAYMENT_NOT_RECEIVED = 'Payment not received'; +const HTTP_CODE_PAYMENT_NOT_RECEIVED = 402; // Payment required + +const ERR_HEADER_MISSING = 'Header for hash or sig not set'; +const HTTP_CODE_HEADER_MISSING = 400; // Bad request + +const EMPTY_VOUCHER_HASH = '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'; // keccak256('0x') + +// TODO: Configure +const LRU_CACHE_MAX_ACCOUNT_COUNT = 1000; +const LRU_CACHE_ACCOUNT_TTL = 30 * 60 * 1000; // 30mins +const LRU_CACHE_MAX_VOUCHER_COUNT = 1000; +const LRU_CACHE_VOUCHER_TTL = 5 * 60 * 1000; // 5mins + +const FREE_QUERY_LIMIT = 10; +const FREE_QUERIES = ['latestBlock']; + +export class PaymentsManager { + // TODO: Persist data + private remainingFreeQueriesMap: Map = new Map(); + + private receivedVouchers: LRUCache>; + private stopSubscriptionLoop: ReadWriteChannel; + + // TODO: Read query rate map from config + // TODO: Add a method to get rate for a query + + constructor () { + this.receivedVouchers = new LRUCache>({ + max: LRU_CACHE_MAX_ACCOUNT_COUNT, + ttl: LRU_CACHE_ACCOUNT_TTL + }); + this.stopSubscriptionLoop = Channel(); + } + + async subscribeToVouchers (client: Client): Promise { + const receivedVouchersChannel = client.receivedVouchers(); + log('Starting voucher subscription...'); + + while (true) { + switch (await Channel.select([ + receivedVouchersChannel.shift(), + this.stopSubscriptionLoop.shift() + ])) { + case receivedVouchersChannel: { + const voucher = receivedVouchersChannel.value(); + if (voucher === undefined) { + log('Voucher channel closed, stopping voucher subscription'); + return; + } + + const associatedPaymentChannel = await client.getPaymentChannel(voucher.channelId); + const payer = associatedPaymentChannel.balance.payer; + log(`Received a payment voucher from ${payer}`); + + let vouchersMap = this.receivedVouchers.get(payer); + if (!vouchersMap) { + vouchersMap = new LRUCache({ + max: LRU_CACHE_MAX_VOUCHER_COUNT, + ttl: LRU_CACHE_VOUCHER_TTL + }); + + this.receivedVouchers.set(payer, vouchersMap); + } + + vouchersMap.set(voucher.hash(), voucher); + break; + } + + case this.stopSubscriptionLoop: + log('Stop signal received, stopping voucher subscription'); + return; + } + } + } + + async unSubscribeVouchers (): Promise { + await this.stopSubscriptionLoop.close(); + } + + async allowRequest (voucherHash: string, voucherSig: string): Promise<[boolean, string]> { + const senderAddress = getSenderAddress(voucherHash, voucherSig); + + if (voucherHash === EMPTY_VOUCHER_HASH) { + let remainingFreeQueries = this.remainingFreeQueriesMap.get(senderAddress); + if (remainingFreeQueries === undefined) { + remainingFreeQueries = FREE_QUERY_LIMIT; + } + + // Check if user has exhausted their free query limit + if (remainingFreeQueries > 0) { + log(`Serving a free query for ${senderAddress}`); + this.remainingFreeQueriesMap.set(senderAddress, remainingFreeQueries - 1); + + return [true, '']; + } + + log(`Rejecting query from ${senderAddress}, user has exhausted their free quota`); + return [false, ERR_FREE_QUOTA_EXHUASTED]; + } + + // Check for payment voucher received from the Nitro account + const paymentVoucherRecived = await this.authenticateVoucherForSender(voucherHash, senderAddress); + + if (paymentVoucherRecived) { + log(`Serving a paid query for ${senderAddress}`); + return [true, '']; + } else { + log(`Rejecting query from ${senderAddress}, payment voucher not received`); + return [false, ERR_PAYMENT_NOT_RECEIVED]; + } + } + + private async authenticateVoucherForSender (voucherHash:string, senderAddress: string): Promise { + const vouchersMap = this.receivedVouchers.get(senderAddress); + if (!vouchersMap) { + return false; + } + + const receivedVoucher = vouchersMap.get(voucherHash); + if (receivedVoucher) { + vouchersMap.delete(voucherHash); + return true; + } + + return false; + } +} + +export const paymentsPlugin = (paymentsManager?: PaymentsManager): ApolloServerPlugin => { + return { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async requestDidStart (requestContext: GraphQLRequestContext) { + return { + async responseForOperation (requestContext: GraphQLRequestContext): Promise { + // Continue if payments is not setup or it's an introspection query + if (!paymentsManager || requestContext.operationName === IntrospectionQuery) { + return null; + } + + const hash = requestContext.request.http?.headers.get(HASH_HEADER_KEY); + const sig = requestContext.request.http?.headers.get(SIG_HEADER_KEY); + + if (hash == null || sig == null) { + return { + errors: [{ message: ERR_HEADER_MISSING }], + http: new HTTPResponse(undefined, { + headers: requestContext.response?.http?.headers, + status: HTTP_CODE_HEADER_MISSING + }) + }; + } + + const querySelections = requestContext.operation?.selectionSet.selections + .map((selection) => (selection as FieldNode).name.value); + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + for await (const querySelection of querySelections ?? []) { + // TODO: Charge according to the querySelection + if (FREE_QUERIES.includes(querySelection)) { + continue; + } + + const [allowRequest, rejectionMessage] = await paymentsManager.allowRequest(hash, sig); + if (!allowRequest) { + const failResponse: GraphQLResponse = { + errors: [{ message: rejectionMessage }], + http: new HTTPResponse(undefined, { + headers: requestContext.response?.http?.headers, + status: HTTP_CODE_PAYMENT_NOT_RECEIVED + }) + }; + + return failResponse; + } + } + + return null; + } + }; + } + }; +}; + +const getSenderAddress = (hash: string, sig: string): string => { + const splitSig = ethers.utils.splitSignature(sig); + const signature: Signature = getSignatureFromEthersSignature(splitSig); + + return recoverEthereumMessageSigner(hex2Bytes(hash), signature); +}; diff --git a/packages/util/src/server.ts b/packages/util/src/server.ts index ed8c832a3..8c5099414 100644 --- a/packages/util/src/server.ts +++ b/packages/util/src/server.ts @@ -14,6 +14,7 @@ import { makeExecutableSchema } from '@graphql-tools/schema'; import { DEFAULT_MAX_GQL_CACHE_SIZE } from './constants'; import { ServerConfig } from './config'; +import { PaymentsManager, paymentsPlugin } from './payments'; const log = debug('vulcanize:server'); @@ -21,7 +22,8 @@ export const createAndStartServer = async ( app: Application, typeDefs: TypeSource, resolvers: any, - serverConfig: ServerConfig + serverConfig: ServerConfig, + paymentsManager?: PaymentsManager ): Promise => { const { host, port, gqlCache: gqlCacheConfig, maxSimultaneousRequests, maxRequestQueueLimit } = serverConfig; @@ -64,6 +66,8 @@ export const createAndStartServer = async ( }; } }, + // Custom payments plugin + paymentsPlugin(paymentsManager), // GQL response cache plugin responseCachePlugin(), ApolloServerPluginLandingPageLocalDefault({ embed: true }) diff --git a/yarn.lock b/yarn.lock index c6c8ed9ac..ed2fede7b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -350,6 +350,42 @@ wherearewe "^2.0.0" xsalsa20 "^1.1.0" +"@cerc-io/nitro-client@^0.1.3": + version "0.1.3" + resolved "https://git.vdb.to/api/packages/cerc-io/npm/%40cerc-io%2Fnitro-client/-/0.1.3/nitro-client-0.1.3.tgz#a536da9f6c1bc0f95cd3c4ecc2358be5f36bc8f1" + integrity sha512-fZ8+Diz5tDrBz7t56X5R9ul54FE7tLmyAB//5NY2OBncjthpTmkF0kmQvO2KVyQGuriVTe7FbqwJMtIRWKxWEQ== + dependencies: + "@cerc-io/libp2p" "0.42.2-laconic-0.1.3" + "@cerc-io/nitro-util" "^0.1.3" + "@cerc-io/peer" "^0.2.46" + "@cerc-io/ts-channel" "1.0.3-ts-nitro-0.1.1" + "@libp2p/crypto" "^1.0.4" + "@libp2p/tcp" "^6.0.0" + "@multiformats/multiaddr" "^11.1.4" + "@statechannels/exit-format" "^0.2.0" + "@statechannels/nitro-protocol" "^2.0.0-alpha.4" + assert "^2.0.0" + debug "^4.3.4" + ethers "^5.7.2" + it-pipe "^2.0.5" + level "^8.0.0" + lodash "^4.17.21" + promjs "^0.4.2" + uint8arrays "^4.0.3" + +"@cerc-io/nitro-util@^0.1.3": + version "0.1.3" + resolved "https://git.vdb.to/api/packages/cerc-io/npm/%40cerc-io%2Fnitro-util/-/0.1.3/nitro-util-0.1.3.tgz#1c640221c3936203e8ccf492e6374b50502d60d3" + integrity sha512-NTg8RO/3bzGLZie3pavcJJzLeL9gI1RLxwEMVBtRzsZfniDfsu7CTasoEX+hKgyBiZstEoMtGbfpwVmM1IEQBA== + dependencies: + assert "^2.0.0" + debug "^4.3.4" + ethers "^5.7.2" + it-pipe "^3.0.1" + json-bigint "^1.0.0" + lodash "^4.17.21" + uint8arrays "^4.0.3" + "@cerc-io/prometheus-metrics@1.1.4": version "1.1.4" resolved "https://git.vdb.to/api/packages/cerc-io/npm/%40cerc-io%2Fprometheus-metrics/-/1.1.4/prometheus-metrics-1.1.4.tgz#51006b0b5bf6168394390c78072a1c0bb2b02f28" @@ -362,6 +398,11 @@ it-stream-types "^1.0.4" promjs "^0.4.2" +"@cerc-io/ts-channel@1.0.3-ts-nitro-0.1.1": + version "1.0.3-ts-nitro-0.1.1" + resolved "https://git.vdb.to/api/packages/cerc-io/npm/%40cerc-io%2Fts-channel/-/1.0.3-ts-nitro-0.1.1/ts-channel-1.0.3-ts-nitro-0.1.1.tgz#0768781313a167295c0bf21307f47e02dc17e936" + integrity sha512-2jFICUSyffuZ+8+qRhXuLSJq4GJ6Y02wxiXoubH0Kzv2lIKkJtWICY1ZQQhtXAvP0ncAQB85WJHqtqwH8l7J3Q== + "@chainsafe/is-ip@^2.0.1": version "2.0.1" resolved "https://registry.yarnpkg.com/@chainsafe/is-ip/-/is-ip-2.0.1.tgz#62cb285669d91f88fd9fa285048dde3882f0993b" @@ -2353,6 +2394,17 @@ it-stream-types "^1.0.4" uint8arraylist "^2.1.2" +"@libp2p/interface-connection@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@libp2p/interface-connection/-/interface-connection-4.0.0.tgz#fcc830ca891820fac89a4c6bd4fcc2df4874f49b" + integrity sha512-6xx/NmEc84HX7QmsjSC3hHredQYjHv4Dkf4G27adAPf+qN+vnPxmQ7gaTnk243a0++DOFTbZ2gKX/15G2B6SRg== + dependencies: + "@libp2p/interface-peer-id" "^2.0.0" + "@libp2p/interfaces" "^3.0.0" + "@multiformats/multiaddr" "^12.0.0" + it-stream-types "^1.0.4" + uint8arraylist "^2.1.2" + "@libp2p/interface-connection@^5.0.0", "@libp2p/interface-connection@^5.1.0": version "5.1.1" resolved "https://registry.yarnpkg.com/@libp2p/interface-connection/-/interface-connection-5.1.1.tgz#da0572c76da43629d52b8bec6cd092143fae421d" @@ -2790,6 +2842,21 @@ uint8arraylist "^2.0.0" uint8arrays "^4.0.2" +"@libp2p/tcp@^6.0.0": + version "6.2.2" + resolved "https://registry.yarnpkg.com/@libp2p/tcp/-/tcp-6.2.2.tgz#9262e284037f0951aca22f0fb3d488e3515ff6fd" + integrity sha512-5pLQDSUI+6qtAvh7pYgjqXFuFqzZ/AGL3BSX4C2oa+vWGIbooTZK3Mizp+iO0yHomVJ1y3V8AXXH8ddWdFqDpQ== + dependencies: + "@libp2p/interface-connection" "^4.0.0" + "@libp2p/interface-metrics" "^4.0.0" + "@libp2p/interface-transport" "^2.0.0" + "@libp2p/interfaces" "^3.2.0" + "@libp2p/logger" "^2.0.0" + "@libp2p/utils" "^3.0.2" + "@multiformats/mafmt" "^12.0.0" + "@multiformats/multiaddr" "^12.0.0" + stream-to-it "^0.2.2" + "@libp2p/topology@^4.0.0": version "4.0.1" resolved "https://registry.yarnpkg.com/@libp2p/topology/-/topology-4.0.1.tgz#8efab229ed32d30cfa6c4a371e8022011c0ff6f9" @@ -3337,11 +3404,21 @@ dependencies: "@octokit/openapi-types" "^7.2.3" +"@openzeppelin/contracts@4.6.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.6.0.tgz#c91cf64bc27f573836dba4122758b4743418c1b3" + integrity sha512-8vi4d50NNya/bQqCmaVzvHNmwHvS0OBKb7HNtuNwEE3scXWrP31fKQoGxNMT+KbzmrNZzatE3QK5p2gFONI/hg== + "@openzeppelin/contracts@^4.3.2": version "4.8.2" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.8.2.tgz#d815ade0027b50beb9bcca67143c6bcc3e3923d6" integrity sha512-kEUOgPQszC0fSYWpbh2kT94ltOJwj1qfT2DWo+zVttmGmf97JZ99LspePNaeeaLhCImaHVeBbjaQFZQn7+Zc5g== +"@openzeppelin/contracts@^4.7.3": + version "4.9.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.2.tgz#1cb2d5e4d3360141a17dbc45094a8cad6aac16c1" + integrity sha512-mO+y6JaqXjWeMh9glYVzVu8HYPGknAAnWyxTRhGeckOruyXQMNnlcW6w/Dx9ftLeIQk6N+ZJFuVmTwF7lEIFrg== + "@poanet/solidity-flattener@https://github.com/vulcanize/solidity-flattener.git": version "3.0.6" resolved "https://github.com/vulcanize/solidity-flattener.git#144ef6cda8823f4a5e48cb4f615be87a32e2dcbc" @@ -3664,6 +3741,24 @@ "@stablelib/random" "^1.0.2" "@stablelib/wipe" "^1.0.1" +"@statechannels/exit-format@^0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@statechannels/exit-format/-/exit-format-0.2.0.tgz#b9362816c2a23d59e429b86b310021de1031a387" + integrity sha512-i+HIPy2P6ddwT/uP0O6AiTmBRTQ9+vLmLnfJtvXmtpTsB8OT1R9Jjj5iVKowGcWk+cg8koEtQuQDMxfrHq7LaQ== + dependencies: + "@openzeppelin/contracts" "4.6.0" + ethers "^5.1.4" + lodash "^4.17.21" + +"@statechannels/nitro-protocol@^2.0.0-alpha.4": + version "2.0.0-alpha.4" + resolved "https://registry.yarnpkg.com/@statechannels/nitro-protocol/-/nitro-protocol-2.0.0-alpha.4.tgz#ff252e5cd7e73740ad25a35b2af7953b499db63d" + integrity sha512-Nmiyu0h7VjzoYPmzUOVWb7KzzdRRTjnF1YYVqsiHiCEVkjZVBtSK/J8RDL4Ozzn2MwyOIiA90Wlrl4KB+tB43g== + dependencies: + "@openzeppelin/contracts" "^4.7.3" + "@statechannels/exit-format" "^0.2.0" + "@typechain/ethers-v5" "^9.0.0" + "@szmarczak/http-timer@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" @@ -3703,6 +3798,14 @@ dependencies: ethers "^5.0.2" +"@typechain/ethers-v5@^9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-9.0.0.tgz#6aa93bea7425c0463bd8a61eea3643540ef851bd" + integrity sha512-bAanuPl1L2itaUdMvor/QvwnIH+TM/CmG00q17Ilv3ZZMeJ2j8HcarhgJUZ9pBY1teBb85P8cC03dz3mSSx+tQ== + dependencies: + lodash "^4.17.15" + ts-essentials "^7.0.1" + "@types/abstract-leveldown@*": version "7.2.1" resolved "https://registry.yarnpkg.com/@types/abstract-leveldown/-/abstract-leveldown-7.2.1.tgz#bb16403c17754b0c4d5772d71d03b924a03d4c80" @@ -8088,7 +8191,7 @@ ethers@^5.0.1, ethers@^5.0.2, ethers@^5.5.2: "@ethersproject/web" "5.6.1" "@ethersproject/wordlists" "5.6.1" -ethers@^5.4.4: +ethers@^5.1.4, ethers@^5.4.4, ethers@^5.7.2: version "5.7.2" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== @@ -11393,6 +11496,11 @@ lru-cache@5.1.1, lru-cache@^5.1.1: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.13.1.tgz#267a81fbd0881327c46a81c5922606a2cfe336c4" integrity sha512-CHqbAq7NFlW3RSnoWXLJBxCWaZVBrfa9UEHId2M3AW8iEBurbqduNexEUCGc3SHc6iCYXNJCDi903LajSVAEPQ== +lru-cache@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.0.0.tgz#b9e2a6a72a129d81ab317202d93c7691df727e61" + integrity sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw== + lru-cache@^3.2.0: version "3.2.0" resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-3.2.0.tgz" @@ -15547,6 +15655,11 @@ ts-essentials@^6.0.3: resolved "https://registry.npmjs.org/ts-essentials/-/ts-essentials-6.0.7.tgz" integrity sha512-2E4HIIj4tQJlIHuATRHayv0EfMGK3ris/GRk1E3CFnsZzeNV+hUmelbaTZHLtXaZppM5oLhHRtO04gINC4Jusw== +ts-essentials@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-7.0.3.tgz#686fd155a02133eedcc5362dc8b5056cde3e5a38" + integrity sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ== + ts-generator@^0.1.1: version "0.1.1" resolved "https://registry.npmjs.org/ts-generator/-/ts-generator-0.1.1.tgz"