From 198d3e65db8d106526c1b2678a7a1b159c22a51d Mon Sep 17 00:00:00 2001 From: prathamesh0 <42446521+prathamesh0@users.noreply.github.com> Date: Thu, 27 Jul 2023 15:52:36 +0530 Subject: [PATCH] Add payments config and charge according to configured rates (#395) * Track amount paid on payment channels and charge as per query cost * Add payments manager config * Fix received payment checks * Separate out payment not received and amount insufficient errors * Serve a query for free if its rate is not configured * Load open payment channels from the stored state * Take list of free queries from config * Take mutation rates from config * Rename query rates config fields * Take cache settings and request timeout from config * Upgrade ts-nitro packages * Upgrade package versions --- lerna.json | 2 +- packages/cache/package.json | 2 +- packages/cli/package.json | 6 +- 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 | 10 +- packages/util/src/config.ts | 36 +++- packages/util/src/payments.ts | 204 ++++++++++++------ yarn.lock | 21 +- 15 files changed, 208 insertions(+), 111 deletions(-) diff --git a/lerna.json b/lerna.json index 07f2162a..4c4f64fd 100644 --- a/lerna.json +++ b/lerna.json @@ -2,7 +2,7 @@ "packages": [ "packages/*" ], - "version": "0.2.49", + "version": "0.2.50", "npmClient": "yarn", "useWorkspaces": true, "command": { diff --git a/packages/cache/package.json b/packages/cache/package.json index 940d0e4c..d0db535e 100644 --- a/packages/cache/package.json +++ b/packages/cache/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/cache", - "version": "0.2.49", + "version": "0.2.50", "description": "Generic object cache", "main": "dist/index.js", "scripts": { diff --git a/packages/cli/package.json b/packages/cli/package.json index 99dd6205..225c79af 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/cli", - "version": "0.2.49", + "version": "0.2.50", "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.49", - "@cerc-io/util": "^0.2.49", + "@cerc-io/peer": "^0.2.50", + "@cerc-io/util": "^0.2.50", "@ethersproject/providers": "^5.4.4", "@graphql-tools/utils": "^9.1.1", "@ipld/dag-cbor": "^8.0.0", diff --git a/packages/codegen/package.json b/packages/codegen/package.json index 113d0fbb..283d30a8 100644 --- a/packages/codegen/package.json +++ b/packages/codegen/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/codegen", - "version": "0.2.49", + "version": "0.2.50", "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.49", + "@cerc-io/util": "^0.2.50", "@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 352c292b..87a6303d 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.49", - "@cerc-io/ipld-eth-client": "^0.2.49", - "@cerc-io/solidity-mapper": "^0.2.49", - "@cerc-io/util": "^0.2.49", + "@cerc-io/cli": "^0.2.50", + "@cerc-io/ipld-eth-client": "^0.2.50", + "@cerc-io/solidity-mapper": "^0.2.50", + "@cerc-io/util": "^0.2.50", {{#if (subgraphPath)}} - "@cerc-io/graph-node": "^0.2.49", + "@cerc-io/graph-node": "^0.2.50", {{/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 18e4eaa6..7351498f 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.49", + "version": "0.2.50", "main": "dist/index.js", "license": "AGPL-3.0", "devDependencies": { - "@cerc-io/solidity-mapper": "^0.2.49", + "@cerc-io/solidity-mapper": "^0.2.50", "@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.49", - "@cerc-io/ipld-eth-client": "^0.2.49", - "@cerc-io/util": "^0.2.49", + "@cerc-io/cache": "^0.2.50", + "@cerc-io/ipld-eth-client": "^0.2.50", + "@cerc-io/util": "^0.2.50", "@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 04141be9..437a399c 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.49", + "version": "0.2.50", "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.49", + "@cerc-io/cache": "^0.2.50", "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 dd896b9c..cb8b87ea 100644 --- a/packages/peer/package.json +++ b/packages/peer/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/peer", - "version": "0.2.49", + "version": "0.2.50", "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 3b67fb06..9ac63e4d 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.49", + "version": "0.2.50", "main": "dist/index.js", "license": "AGPL-3.0", "devDependencies": { - "@cerc-io/ipld-eth-client": "^0.2.49", + "@cerc-io/ipld-eth-client": "^0.2.50", "@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 74d8116d..1b07a567 100644 --- a/packages/test/package.json +++ b/packages/test/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/test", - "version": "0.2.49", + "version": "0.2.50", "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 794879d8..a841f83d 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.49", + "version": "0.2.50", "description": "ETH VM tracing client", "main": "dist/index.js", "scripts": { diff --git a/packages/util/package.json b/packages/util/package.json index c215f321..7bb021b4 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,12 +1,12 @@ { "name": "@cerc-io/util", - "version": "0.2.49", + "version": "0.2.50", "main": "dist/index.js", "license": "AGPL-3.0", "dependencies": { "@apollo/utils.keyvaluecache": "^1.0.1", - "@cerc-io/nitro-client": "^0.1.4", - "@cerc-io/solidity-mapper": "^0.2.49", + "@cerc-io/nitro-client": "^0.1.5", + "@cerc-io/solidity-mapper": "^0.2.50", "@cerc-io/ts-channel": "1.0.3-ts-nitro-0.1.1", "@ethersproject/providers": "^5.4.4", "@graphql-tools/schema": "^9.0.10", @@ -40,8 +40,8 @@ "yargs": "^17.0.1" }, "devDependencies": { - "@cerc-io/cache": "^0.2.49", - "@cerc-io/ipld-eth-client": "^0.2.49", + "@cerc-io/cache": "^0.2.50", + "@cerc-io/ipld-eth-client": "^0.2.50", "@nomiclabs/hardhat-waffle": "^2.0.1", "@types/express": "^4.17.14", "@types/fs-extra": "^9.0.11", diff --git a/packages/util/src/config.ts b/packages/util/src/config.ts index de1ddcfe..d49435c9 100644 --- a/packages/util/src/config.ts +++ b/packages/util/src/config.ts @@ -81,7 +81,7 @@ interface L2TxsConfig { privateKey: string; // Gas limit for tx - gasLimit?: number + gasLimit?: number; } // Peer config @@ -126,11 +126,37 @@ export interface PeerConfig { l2TxsConfig?: L2TxsConfig; } +export interface BaseRatesConfig { + freeQueriesLimit: number; + freeQueriesList: string[]; + queries: { [key: string]: string }; + mutations: { [key: string]: string }; +} + +export interface PaymentsCacheConfig { + maxAccounts: number; + accountTTLInSecs: number; + maxVouchersPerAccount: number; + voucherTTLInSecs: number; + maxPaymentChannels: number; + paymentChannelTTLInSecs: number; +} + +// Payments manager config +export interface PaymentsConfig { + ratesFile: string; + requestTimeoutInSecs: number; + cache: PaymentsCacheConfig; +} + // ts-nitro config export interface NitroConfig { - store: string - privateKey: string - chainPrivateKey: string + store: string; + + privateKey: string; + chainPrivateKey: string; + + payments: PaymentsConfig; } // P2P config @@ -179,7 +205,7 @@ export interface ServerConfig { // Flag to specify whether RPC endpoint supports block hash as block tag parameter // https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block - rpcSupportsBlockHashParam: boolean + rpcSupportsBlockHashParam: boolean; } export interface UpstreamConfig { diff --git a/packages/util/src/payments.ts b/packages/util/src/payments.ts index 806c87b7..73b1951e 100644 --- a/packages/util/src/payments.ts +++ b/packages/util/src/payments.ts @@ -7,7 +7,9 @@ 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, Voucher } from '@cerc-io/nitro-client'; -import { utils as nitroUtils } from '@cerc-io/nitro-client'; +import { utils as nitroUtils, ChannelStatus } from '@cerc-io/nitro-client'; + +import { BaseRatesConfig, PaymentsConfig } from './config'; const log = debug('laconic:payments'); @@ -17,7 +19,8 @@ const PAYMENT_HEADER_REGEX = /vhash:(.*),vsig:(.*)/; 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_AMOUNT_INSUFFICIENT = 'Payment amount insufficient'; +const HTTP_CODE_PAYMENT_REQUIRED = 402; // Payment required const ERR_HEADER_MISSING = 'Payment header x-payment not set'; const ERR_INVALID_PAYMENT_HEADER = 'Invalid payment header format'; @@ -25,41 +28,72 @@ const HTTP_CODE_BAD_REQUEST = 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 +// Config Defaults +const DEFAULT_REQUEST_TIMEOUT = 10; // 10 seconds -const FREE_QUERY_LIMIT = 10; -const FREE_QUERIES = ['latestBlock']; +const DEFAULT_FREE_QUERIES_LIMIT = 10; -const REQUEST_TIMEOUT = 10 * 1000; // 10 seconds +const DEFAULT_FREE_QUERIES_LIST = ['latestBlock']; + +const DEFAULT_LRU_CACHE_MAX_ACCOUNTS = 1000; +const DEFAULT_LRU_CACHE_ACCOUNT_TTL = 30 * 60; // 30mins +const DEFAULT_LRU_CACHE_MAX_VOUCHERS_PER_ACCOUNT = 1000; +const DEFAULT_LRU_CACHE_VOUCHER_TTL = 5 * 60; // 5mins +const DEFAULT_LRU_CACHE_MAX_PAYMENT_CHANNELS = 10000; +const DEFAULT_LRU_CACHE_PAYMENT_CHANNEL_TTL = DEFAULT_LRU_CACHE_ACCOUNT_TTL; + +interface Payment { + voucher: Voucher; + amount: bigint; +} export class PaymentsManager { clientAddress?: string; + private config: PaymentsConfig; + private ratesConfig: BaseRatesConfig; + // TODO: Persist data private remainingFreeQueriesMap: Map = new Map(); - private receivedVouchers: LRUCache>; + // TODO: Persist data + private receivedPayments: LRUCache>; + private paidSoFarOnChannel: LRUCache; + private stopSubscriptionLoop: ReadWriteChannel; private paymentListeners: ReadWriteChannel[] = []; - // TODO: Read query rate map from config - // TODO: Add a method to get rate for a query + constructor (config: PaymentsConfig, baseRatesConfig: BaseRatesConfig) { + this.config = config; + this.ratesConfig = baseRatesConfig; - constructor () { - this.receivedVouchers = new LRUCache>({ - max: LRU_CACHE_MAX_ACCOUNT_COUNT, - ttl: LRU_CACHE_ACCOUNT_TTL + this.receivedPayments = new LRUCache>({ + max: this.config.cache.maxAccounts ?? DEFAULT_LRU_CACHE_MAX_ACCOUNTS, + ttl: (this.config.cache.accountTTLInSecs ?? DEFAULT_LRU_CACHE_ACCOUNT_TTL) * 1000 }); + + this.paidSoFarOnChannel = new LRUCache({ + max: this.config.cache.maxPaymentChannels ?? DEFAULT_LRU_CACHE_MAX_PAYMENT_CHANNELS, + ttl: (this.config.cache.paymentChannelTTLInSecs ?? DEFAULT_LRU_CACHE_PAYMENT_CHANNEL_TTL) * 1000 + }); + this.stopSubscriptionLoop = Channel(); } + get freeQueriesList (): string[] { + return this.ratesConfig.freeQueriesList ?? DEFAULT_FREE_QUERIES_LIST; + } + + get mutationRates (): { [key: string]: string } { + return this.ratesConfig.mutations; + } + async subscribeToVouchers (client: Client): Promise { this.clientAddress = client.address; + // Load existing open payment channels with amount paid so far from the stored state + await this.loadPaymentChannels(client); + const receivedVouchersChannel = client.receivedVouchers(); log('Starting voucher subscription...'); @@ -77,19 +111,27 @@ export class PaymentsManager { 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); + if (!voucher.amount) { + log(`Amount not set in received voucher on payment channel ${voucher.channelId.string()}`); + continue; } - vouchersMap.set(voucher.hash(), voucher); + const paymentAmount = voucher.amount - (this.paidSoFarOnChannel.get(voucher.channelId.string()) ?? BigInt(0)); + this.paidSoFarOnChannel.set(voucher.channelId.string(), voucher.amount); + log(`Received a payment voucher of ${paymentAmount} from ${payer}`); + + let paymentsMap = this.receivedPayments.get(payer); + if (!paymentsMap) { + paymentsMap = new LRUCache({ + max: this.config.cache.maxVouchersPerAccount ?? DEFAULT_LRU_CACHE_MAX_VOUCHERS_PER_ACCOUNT, + ttl: (this.config.cache.voucherTTLInSecs ?? DEFAULT_LRU_CACHE_VOUCHER_TTL) * 1000 + }); + + this.receivedPayments.set(payer, paymentsMap); + } + + paymentsMap.set(voucher.hash(), { voucher, amount: paymentAmount }); for await (const [, listener] of this.paymentListeners.entries()) { await listener.push(payer); @@ -109,42 +151,51 @@ export class PaymentsManager { await this.stopSubscriptionLoop.close(); } - async allowRequest (voucherHash: string, voucherSig: string): Promise<[boolean, string]> { - const senderAddress = nitroUtils.getSignerAddress(voucherHash, voucherSig); + async allowRequest (voucherHash: string, voucherSig: string, querySelection: string): Promise<[false, string] | [true, null]> { + const signerAddress = nitroUtils.getSignerAddress(voucherHash, voucherSig); + // Use free quota if EMPTY_VOUCHER_HASH passed if (voucherHash === EMPTY_VOUCHER_HASH) { - let remainingFreeQueries = this.remainingFreeQueriesMap.get(senderAddress); + let remainingFreeQueries = this.remainingFreeQueriesMap.get(signerAddress); if (remainingFreeQueries === undefined) { - remainingFreeQueries = FREE_QUERY_LIMIT; + remainingFreeQueries = this.ratesConfig.freeQueriesLimit ?? DEFAULT_FREE_QUERIES_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); + log(`Serving a free query to ${signerAddress}`); + this.remainingFreeQueriesMap.set(signerAddress, remainingFreeQueries - 1); - return [true, '']; + return [true, null]; } - log(`Rejecting query from ${senderAddress}, user has exhausted their free quota`); + log(`Rejecting query from ${signerAddress}: ${ERR_FREE_QUOTA_EXHUASTED}`); return [false, ERR_FREE_QUOTA_EXHUASTED]; } - // Check for payment voucher received from the Nitro account - const paymentVoucherRecived = await this.authenticateVoucher(voucherHash, senderAddress); + // Serve a query for free if rate is not configured + const configuredQueryCost = this.ratesConfig.queries[querySelection]; + if (configuredQueryCost === undefined) { + log(`Query rate not configured for "${querySelection}", serving a free query to ${signerAddress}`); + return [true, null]; + } - if (paymentVoucherRecived) { - log(`Serving a paid query for ${senderAddress}`); - return [true, '']; + // Check if required payment received from the Nitro account + const [paymentReceived, paymentError] = await this.authenticatePayment(voucherHash, signerAddress, BigInt(configuredQueryCost)); + + if (paymentReceived) { + log(`Serving a paid query for ${signerAddress}`); + return [true, null]; } else { - log(`Rejecting query from ${senderAddress}, payment voucher not received`); - return [false, ERR_PAYMENT_NOT_RECEIVED]; + log(`Rejecting query from ${signerAddress}: ${paymentError}`); + return [false, paymentError]; } } - async authenticateVoucher (voucherHash:string, senderAddress: string): Promise { - if (this.acceptReceivedVouchers(voucherHash, senderAddress)) { - return true; + async authenticatePayment (voucherHash:string, signerAddress: string, value: bigint): Promise<[false, string] | [true, null]> { + const [isPaymentReceived, isOfSufficientValue] = this.acceptReceivedPayment(voucherHash, signerAddress, value); + if (isPaymentReceived) { + return isOfSufficientValue ? [true, null] : [false, ERR_AMOUNT_INSUFFICIENT]; } // Wait for payment voucher from sender @@ -153,7 +204,7 @@ export class PaymentsManager { let requestTimeout; const timeoutPromise = new Promise(resolve => { - requestTimeout = setTimeout(resolve, REQUEST_TIMEOUT); + requestTimeout = setTimeout(resolve, (this.config.requestTimeoutInSecs ?? DEFAULT_REQUEST_TIMEOUT) * 1000); }); try { @@ -165,12 +216,13 @@ export class PaymentsManager { // payer is undefined if timeout completes or channel is closed externally if (!payer) { - return false; + return [false, ERR_PAYMENT_NOT_RECEIVED]; } - if (payer === senderAddress) { - if (this.acceptReceivedVouchers(voucherHash, senderAddress)) { - return true; + if (payer === signerAddress) { + const [isPaymentReceived, isOfSufficientValue] = this.acceptReceivedPayment(voucherHash, signerAddress, value); + if (isPaymentReceived) { + return isOfSufficientValue ? [true, null] : [false, ERR_AMOUNT_INSUFFICIENT]; } } } @@ -184,24 +236,43 @@ export class PaymentsManager { } } - // Check vouchers in LRU cache map and remove them - // Returns false if not found - // Returns true after being found and removed - private acceptReceivedVouchers (voucherHash:string, senderAddress: string): boolean { - const vouchersMap = this.receivedVouchers.get(senderAddress); + // Check for a given payment voucher in LRU cache map + // Returns whether the voucher was found, whether it was of sufficient value + private acceptReceivedPayment (voucherHash:string, signerAddress: string, minRequiredValue: bigint): [boolean, boolean] { + const paymentsMap = this.receivedPayments.get(signerAddress); - if (!vouchersMap) { - return false; + if (!paymentsMap) { + return [false, false]; } - const receivedVoucher = vouchersMap.get(voucherHash); + const receivedPayment = paymentsMap.get(voucherHash); - if (!receivedVoucher) { - return false; + if (!receivedPayment) { + return [false, false]; } - vouchersMap.delete(voucherHash); - return true; + if (receivedPayment.amount < minRequiredValue) { + return [true, false]; + } + + paymentsMap.delete(voucherHash); + return [true, true]; + } + + private async loadPaymentChannels (client: Client): Promise { + const ledgerChannels = await client.getAllLedgerChannels(); + + for await (const ledgerChannel of ledgerChannels) { + if (ledgerChannel.status === ChannelStatus.Open) { + const paymentChannels = await client.getPaymentChannelsByLedger(ledgerChannel.iD); + + for (const paymentChannel of paymentChannels) { + if (paymentChannel.status === ChannelStatus.Open) { + this.paidSoFarOnChannel.set(paymentChannel.iD.string(), paymentChannel.balance.paidSoFar); + } + } + } + } } } @@ -243,22 +314,21 @@ export const paymentsPlugin = (paymentsManager?: PaymentsManager): ApolloServerP } const querySelections = requestContext.operation?.selectionSet.selections - .map((selection) => (selection as FieldNode).name.value); + .map((selection: any) => (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)) { + if (paymentsManager.freeQueriesList.includes(querySelection)) { continue; } - const [allowRequest, rejectionMessage] = await paymentsManager.allowRequest(vhash, vsig); + const [allowRequest, rejectionMessage] = await paymentsManager.allowRequest(vhash, vsig, querySelection); if (!allowRequest) { const failResponse: GraphQLResponse = { errors: [{ message: rejectionMessage }], http: new HTTPResponse(undefined, { headers: requestContext.response?.http?.headers, - status: HTTP_CODE_PAYMENT_NOT_RECEIVED + status: HTTP_CODE_PAYMENT_REQUIRED }) }; diff --git a/yarn.lock b/yarn.lock index 838e427e..a28efbd3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -350,14 +350,14 @@ wherearewe "^2.0.0" xsalsa20 "^1.1.0" -"@cerc-io/nitro-client@^0.1.4": - version "0.1.4" - resolved "https://git.vdb.to/api/packages/cerc-io/npm/%40cerc-io%2Fnitro-client/-/0.1.4/nitro-client-0.1.4.tgz#7f69fa5fa66beb7eedd6dddc81a29d2589e6d60d" - integrity sha512-2onCl2wygbXXhtjdMotRdeOXovFeiCegenE/y4uFKxOX83LpslTx/iK+d6HqcQHW4Kkc2pExu6PBntaPoKVpLA== +"@cerc-io/nitro-client@^0.1.5": + version "0.1.5" + resolved "https://git.vdb.to/api/packages/cerc-io/npm/%40cerc-io%2Fnitro-client/-/0.1.5/nitro-client-0.1.5.tgz#43152a8482b53431c35018064cc70031b759895b" + integrity sha512-px/7IgOv1m+DWskJPQ4DUyX84MZHOYMEPN3iNK9uPf+TjyQQm0w2eTPcdQEQN20xzfFFx3k+Dzys3Ko06pXPDQ== dependencies: "@cerc-io/libp2p" "0.42.2-laconic-0.1.3" - "@cerc-io/nitro-util" "^0.1.4" - "@cerc-io/peer" "^0.2.46" + "@cerc-io/nitro-util" "^0.1.5" + "@cerc-io/peer" "^0.2.49" "@cerc-io/ts-channel" "1.0.3-ts-nitro-0.1.1" "@libp2p/crypto" "^1.0.4" "@libp2p/tcp" "^6.0.0" @@ -373,11 +373,12 @@ promjs "^0.4.2" uint8arrays "^4.0.3" -"@cerc-io/nitro-util@^0.1.4": - version "0.1.4" - resolved "https://git.vdb.to/api/packages/cerc-io/npm/%40cerc-io%2Fnitro-util/-/0.1.4/nitro-util-0.1.4.tgz#101f61692050f0ae850b0a0a12e56252f3ddc5a8" - integrity sha512-dqzFA5czCxo/yyAhHMplzRzTyzf52WpU8U+ntZ9zFIfrWPHvHHyDY4YyjA2yVQEWfcyyIZ0GTzf6wDb/kP8dKg== +"@cerc-io/nitro-util@^0.1.5": + version "0.1.5" + resolved "https://git.vdb.to/api/packages/cerc-io/npm/%40cerc-io%2Fnitro-util/-/0.1.5/nitro-util-0.1.5.tgz#829d7cb56c436fcf29184d1d87ed47ac57a2a32f" + integrity sha512-1nNXfoHVOV2QSnnQSiW/dgTuMGJYEcN2M12e5rMXAb4KrJIScT1lWTp+P5dja/F6jN8ZuNlu5REQTdOjdhMNwQ== dependencies: + "@statechannels/nitro-protocol" "^2.0.0-alpha.4" assert "^2.0.0" debug "^4.3.4" ethers "^5.7.2"