diff --git a/modules/apps/package.json b/modules/apps/package.json index c08feba395..971f74a786 100644 --- a/modules/apps/package.json +++ b/modules/apps/package.json @@ -1,6 +1,6 @@ { "name": "@connext/apps", - "version": "7.3.5", + "version": "7.3.6", "description": "Connext Counterfactual Apps", "main": "dist/index.js", "module": "dist/index.esm.js", @@ -19,8 +19,8 @@ }, "devDependencies": { "@connext/contracts": "3.5.0", - "@connext/types": "7.3.5", - "@connext/utils": "7.3.5", + "@connext/types": "7.3.6", + "@connext/utils": "7.3.6", "@rollup/plugin-json": "4.1.0", "ethers": "5.0.8", "rollup": "2.23.0", diff --git a/modules/bot/package.json b/modules/bot/package.json index 2eca531590..87a9287075 100644 --- a/modules/bot/package.json +++ b/modules/bot/package.json @@ -11,11 +11,11 @@ "author": "", "license": "ISC", "dependencies": { - "@connext/client": "7.3.5", + "@connext/client": "7.3.6", "@connext/contracts": "3.5.0", - "@connext/store": "7.3.5", - "@connext/types": "7.3.5", - "@connext/utils": "7.3.5", + "@connext/store": "7.3.6", + "@connext/types": "7.3.6", + "@connext/utils": "7.3.6", "axios": "0.19.2", "body-parser": "1.19.0", "ethers": "5.0.8", diff --git a/modules/cf-core/package.json b/modules/cf-core/package.json index 64fe0ce275..7391c6f5ed 100644 --- a/modules/cf-core/package.json +++ b/modules/cf-core/package.json @@ -1,6 +1,6 @@ { "name": "@connext/cf-core", - "version": "7.3.5", + "version": "7.3.6", "main": "dist/index.js", "iife": "dist/index.iife.js", "types": "dist/index.d.ts", @@ -20,8 +20,8 @@ "dependencies": { "@connext/contracts": "3.5.0", "@connext/pure-evm-wasm": "0.1.4", - "@connext/types": "7.3.5", - "@connext/utils": "7.3.5", + "@connext/types": "7.3.6", + "@connext/utils": "7.3.6", "@openzeppelin/contracts": "3.0.2", "async-mutex": "0.2.4", "ethers": "5.0.8", @@ -32,7 +32,7 @@ }, "devDependencies": { "@babel/core": "7.11.1", - "@connext/store": "7.3.5", + "@connext/store": "7.3.6", "@ethereum-waffle/chai": "3.0.2", "@types/chai": "4.2.12", "@types/chai-as-promised": "7.1.3", diff --git a/modules/channel-provider/package.json b/modules/channel-provider/package.json index 1a3fc065cc..f1456338c8 100644 --- a/modules/channel-provider/package.json +++ b/modules/channel-provider/package.json @@ -1,6 +1,6 @@ { "name": "@connext/channel-provider", - "version": "7.3.5", + "version": "7.3.6", "description": "Channel Provider module for Connext client", "main": "dist/index.js", "files": [ @@ -16,7 +16,7 @@ "test": "./node_modules/.bin/ts-mocha --watch" }, "dependencies": { - "@connext/types": "7.3.5", + "@connext/types": "7.3.6", "eventemitter3": "4.0.4" }, "devDependencies": { diff --git a/modules/client/package.json b/modules/client/package.json index 9d411a34ef..52d8c5ae43 100644 --- a/modules/client/package.json +++ b/modules/client/package.json @@ -1,6 +1,6 @@ { "name": "@connext/client", - "version": "7.3.5", + "version": "7.3.6", "description": "Client for Connext Network", "main": "dist/index.js", "files": [ @@ -16,14 +16,14 @@ }, "dependencies": { "axios": "0.19.2", - "@connext/apps": "7.3.5", - "@connext/cf-core": "7.3.5", - "@connext/channel-provider": "7.3.5", - "@connext/utils": "7.3.5", + "@connext/apps": "7.3.6", + "@connext/cf-core": "7.3.6", + "@connext/channel-provider": "7.3.6", + "@connext/utils": "7.3.6", "@connext/contracts": "3.5.0", - "@connext/messaging": "7.3.5", - "@connext/store": "7.3.5", - "@connext/types": "7.3.5", + "@connext/messaging": "7.3.6", + "@connext/store": "7.3.6", + "@connext/types": "7.3.6", "core-js": "3.6.5", "ethers": "5.0.8", "evt": "1.8.4", diff --git a/modules/client/src/controllers/DepositController.ts b/modules/client/src/controllers/DepositController.ts index e6451ba8b7..aac862ad51 100644 --- a/modules/client/src/controllers/DepositController.ts +++ b/modules/client/src/controllers/DepositController.ts @@ -45,10 +45,12 @@ export class DepositController extends AbstractController { this.throwIfAny(notLessThanOrEqualTo(amount, startingBalance), notGreaterThan(amount, Zero)); const { appIdentityHash } = await this.requestDepositRights({ assetId }); + this.log.info(`Sending deposit transaction to chain`); const txHash = await this.connext.channelProvider.walletDeposit({ amount: amount.toString(), assetId, }); + this.log.info(`Sent deposit transaction to chain: ${txHash}`); const transaction = await this.ethProvider.getTransaction(txHash); const completed: Promise = new Promise( async (resolve, reject) => { @@ -60,7 +62,6 @@ export class DepositController extends AbstractController { appIdentityHash, hash: txHash, }); - this.log.info(`Sent deposit transaction to chain: ${txHash}`); await transaction.wait(); const res = await this.rescindDepositRights({ appIdentityHash, assetId }); this.connext.emit(EventNames.DEPOSIT_CONFIRMED_EVENT, { @@ -160,7 +161,7 @@ export class DepositController extends AbstractController { // get the app instance const app = await this.getDepositApp({ assetId }); if (!app) { - this.log.debug(`No deposit app found for assset: ${assetId}`); + this.log.info(`No deposit app found for assset: ${assetId}`); const freeBalance = await this.connext.getFreeBalance(assetId); this.log.info(`Successfully rescinded deposit rights for ${assetId}`); return { freeBalance }; @@ -200,7 +201,6 @@ export class DepositController extends AbstractController { ////// PRIVATE METHODS private proposeDepositInstall = async (assetId: string): Promise => { - // generate initial totalAmountWithdrawn const multisig = new Contract( this.connext.multisigAddress, diff --git a/modules/contracts/package.json b/modules/contracts/package.json index 2e19e47d63..2b705d4bdc 100644 --- a/modules/contracts/package.json +++ b/modules/contracts/package.json @@ -32,8 +32,8 @@ "transpile": "tsc -p tsconfig.json" }, "dependencies": { - "@connext/types": "7.3.5", - "@connext/utils": "7.3.5", + "@connext/types": "7.3.6", + "@connext/utils": "7.3.6", "@nomiclabs/buidler": "1.4.3", "@openzeppelin/contracts": "3.0.2", "ethers": "5.0.8", diff --git a/modules/daicard/package.json b/modules/daicard/package.json index ad3e910b5e..f2b3b7a589 100644 --- a/modules/daicard/package.json +++ b/modules/daicard/package.json @@ -12,11 +12,11 @@ "format": "prettier --write 'src/**/*.js'" }, "dependencies": { - "@connext/client": "7.3.5", + "@connext/client": "7.3.6", "@connext/contracts": "3.5.0", - "@connext/utils": "7.3.5", - "@connext/store": "7.3.5", - "@connext/types": "7.3.5", + "@connext/utils": "7.3.6", + "@connext/store": "7.3.6", + "@connext/types": "7.3.6", "@material-ui/core": "4.11.0", "@material-ui/icons": "4.9.1", "@walletconnect/browser": "1.0.0", diff --git a/modules/dashboard/package.json b/modules/dashboard/package.json index 42ea610ce2..0cc719c078 100644 --- a/modules/dashboard/package.json +++ b/modules/dashboard/package.json @@ -10,9 +10,9 @@ "eject": "./node_modules/.bin/react-scripts eject" }, "dependencies": { - "@connext/cf-core": "7.3.5", - "@connext/messaging": "7.3.5", - "@connext/types": "7.3.5", + "@connext/cf-core": "7.3.6", + "@connext/messaging": "7.3.6", + "@connext/types": "7.3.6", "@material-ui/core": "4.11.0", "@material-ui/icons": "4.9.1", "react": "16.13.1", diff --git a/modules/messaging/package.json b/modules/messaging/package.json index 5a674e7a2c..2a7c49c308 100644 --- a/modules/messaging/package.json +++ b/modules/messaging/package.json @@ -1,7 +1,7 @@ { "name": "@connext/messaging", "description": "Messaging module for Connext client", - "version": "7.3.5", + "version": "7.3.6", "main": "dist/index.js", "iife": "dist/index.iife.js", "types": "dist/index.d.ts", @@ -16,8 +16,8 @@ "lint": "../../node_modules/.bin/eslint -c '../../.eslintrc.js' --fix 'src/**/*'" }, "dependencies": { - "@connext/types": "7.3.5", - "@connext/utils": "7.3.5", + "@connext/types": "7.3.6", + "@connext/utils": "7.3.6", "ts-natsutil": "1.1.1" }, "devDependencies": { diff --git a/modules/node/package.json b/modules/node/package.json index c4f1982a50..ee39f43170 100644 --- a/modules/node/package.json +++ b/modules/node/package.json @@ -1,6 +1,6 @@ { "name": "indra-node", - "version": "7.3.5", + "version": "7.3.6", "description": "", "author": "", "license": "MIT", @@ -15,14 +15,14 @@ "watch": "ts-mocha --bail --check-leaks --watch --timeout 60000 'src/**/*.spec.ts'" }, "dependencies": { - "@connext/apps": "7.3.5", - "@connext/cf-core": "7.3.5", + "@connext/apps": "7.3.6", + "@connext/cf-core": "7.3.6", "@connext/contracts": "3.5.0", - "@connext/messaging": "7.3.5", + "@connext/messaging": "7.3.6", "@connext/pure-evm-wasm": "0.1.4", - "@connext/store": "7.3.5", - "@connext/types": "7.3.5", - "@connext/utils": "7.3.5", + "@connext/store": "7.3.6", + "@connext/types": "7.3.6", + "@connext/utils": "7.3.6", "@nestjs/common": "7.4.2", "@nestjs/core": "7.4.2", "@nestjs/microservices": "7.4.2", @@ -49,7 +49,7 @@ "wasm-loader": "1.3.0" }, "devDependencies": { - "@connext/client": "7.3.5", + "@connext/client": "7.3.6", "@ethereum-waffle/chai": "3.0.2", "@nestjs/testing": "7.4.2", "@openzeppelin/contracts": "3.0.2", diff --git a/modules/node/src/channel/channel.service.ts b/modules/node/src/channel/channel.service.ts index 37231aef28..842df0642f 100644 --- a/modules/node/src/channel/channel.service.ts +++ b/modules/node/src/channel/channel.service.ts @@ -8,7 +8,11 @@ import { DepositAppState, FreeBalanceResponse, } from "@connext/types"; -import { getSignerAddressFromPublicIdentifier, stringify } from "@connext/utils"; +import { + getSignerAddressFromPublicIdentifier, + stringify, + calculateExchangeWad, +} from "@connext/utils"; import { Injectable, HttpService } from "@nestjs/common"; import { AxiosResponse } from "axios"; import { BigNumber, constants, utils, providers } from "ethers"; @@ -25,7 +29,7 @@ import { Channel } from "./channel.entity"; import { ChannelRepository } from "./channel.repository"; const { AddressZero } = constants; -const { getAddress, toUtf8Bytes, sha256, formatUnits } = utils; +const { getAddress, toUtf8Bytes, sha256 } = utils; export enum RebalanceType { COLLATERALIZE = "COLLATERALIZE", @@ -268,12 +272,18 @@ export class ChannelService { const decimals = await this.configService.getTokenDecimals(chainId, assetId); if (decimals !== DEFAULT_DECIMALS) { this.log.info(`Token has ${decimals} decimals, converting rebalance targets`); - targets.collateralizeThreshold = BigNumber.from( - formatUnits(targets.collateralizeThreshold, decimals).split(".")[0], + targets.collateralizeThreshold = calculateExchangeWad( + targets.collateralizeThreshold, + DEFAULT_DECIMALS, + "1", + decimals, ); - targets.target = BigNumber.from(formatUnits(targets.target, decimals).split(".")[0]); - targets.reclaimThreshold = BigNumber.from( - formatUnits(targets.reclaimThreshold, decimals).split(".")[0], + targets.target = calculateExchangeWad(targets.target, DEFAULT_DECIMALS, "1", decimals); + targets.reclaimThreshold = calculateExchangeWad( + targets.reclaimThreshold, + DEFAULT_DECIMALS, + "1", + decimals, ); this.log.warn(`Converted rebalance targets: ${stringify(targets)}`); } diff --git a/modules/node/src/onchainTransactions/onchainTransaction.repository.ts b/modules/node/src/onchainTransactions/onchainTransaction.repository.ts index 2e7405eb73..b7e92607c7 100644 --- a/modules/node/src/onchainTransactions/onchainTransaction.repository.ts +++ b/modules/node/src/onchainTransactions/onchainTransaction.repository.ts @@ -10,6 +10,7 @@ import { TransactionStatus, } from "./onchainTransaction.entity"; import { toBN } from "@connext/utils"; +import { MinimalTransaction } from "@connext/types"; const { Zero } = constants; export const onchainEntityToReceipt = ( @@ -109,6 +110,25 @@ export class OnchainTransactionRepository extends Repository return tx; } + // Use reason here because channels can collide with multisig/nonce, + // but cannot collide with multisig/nonce + reason due to protocol + // level locks. + // TODO: (Med) Generate the transaction hash ahead of time + async findByChannelReasonAndNonce( + multisigAddress: string, + reason: TransactionReason, + nonce: number, + ): Promise { + const tx = await this.createQueryBuilder("onchainTransaction") + .where('"onchainTransaction"."channelMultisigAddress" = :multisigAddress', { + multisigAddress, + }) + .andWhere("onchainTransaction.reason = :reason", { reason }) + .andWhere("onchainTransaction.nonce = :nonce", { nonce }) + .getOne(); + return tx; + } + async addAppUninstallFlag(appUninstalled: boolean, hash: string): Promise { return getManager().transaction(async (transactionalEntityManager) => { await transactionalEntityManager @@ -124,8 +144,60 @@ export class OnchainTransactionRepository extends Repository }); } + async addPending( + tx: MinimalTransaction, + nonce: number, + from: string, + reason: TransactionReason, + channel: Channel, + appIdentityHash?: string, + ): Promise { + const existing = await this.findByChannelReasonAndNonce(channel.multisigAddress, reason, nonce); + return getManager().transaction(async (transactionalEntityManager) => { + if (existing) { + await transactionalEntityManager + .createQueryBuilder() + .update(OnchainTransaction) + .set({ + to: tx.to, + data: tx.data.toString(), + value: toBN(tx.value), + chainId: channel.chainId.toString(), + from, + nonce, + reason, + status: TransactionStatus.PENDING, + channel, + gasUsed: Zero, + appIdentityHash, + }) + .execute(); + } else { + await transactionalEntityManager + .createQueryBuilder() + .insert() + .into(OnchainTransaction) + .values({ + to: tx.to, + data: tx.data.toString(), + value: toBN(tx.value), + chainId: channel.chainId.toString(), + from, + nonce, + reason, + status: TransactionStatus.PENDING, + channel, + gasUsed: Zero, + appIdentityHash, + }) + .execute(); + } + }); + } + async addResponse( tx: providers.TransactionResponse, + nonce: number, reason: TransactionReason, channel: Channel, appIdentityHash?: string, @@ -133,10 +205,10 @@ export class OnchainTransactionRepository extends Repository return getManager().transaction(async (transactionalEntityManager) => { await transactionalEntityManager .createQueryBuilder() - .insert() - .into(OnchainTransaction) - .values({ - ...tx, + .update(OnchainTransaction) + .set({ + from: tx.from, + to: tx.to, data: tx.data.toString(), value: toBN(tx.value), gasPrice: toBN(tx.gasPrice), @@ -153,13 +225,41 @@ export class OnchainTransactionRepository extends Repository gasUsed: Zero, appIdentityHash, }) - .onConflict(`("hash") DO UPDATE SET "nonce" = :nonce`) - .setParameter("nonce", toBN(tx.nonce).toNumber()) + .where('"onchain_transaction"."channelMultisigAddress" = :multisigAddress', { + multisigAddress: channel.multisigAddress, + }) + .andWhere("onchain_transaction.nonce = :nonce", { nonce }) + .andWhere("onchain_transaction.from = :from", { from: tx.from }) + .execute(); + }); + } + + async markFailedByChannelFromAndNonce( + multisigAddress: string, + from: string, + nonce: number, + errors: { [k: number]: string }, + appIdentityHash?: string, + ): Promise { + return getManager().transaction(async (transactionalEntityManager) => { + await transactionalEntityManager + .createQueryBuilder() + .update(OnchainTransaction) + .set({ + appIdentityHash, + status: TransactionStatus.FAILED, + errors, + }) + .where('"onchain_transaction"."channelMultisigAddress" = :multisigAddress', { + multisigAddress, + }) + .andWhere("onchain_transaction.nonce = :nonce", { nonce }) + .andWhere("onchain_transaction.from = :from", { from }) .execute(); }); } - async markFailed( + async markFailedByTxHash( tx: providers.TransactionResponse, errors: { [k: number]: string }, appIdentityHash?: string, diff --git a/modules/node/src/onchainTransactions/onchainTransaction.service.ts b/modules/node/src/onchainTransactions/onchainTransaction.service.ts index 06f7fdcf57..2323c4198f 100644 --- a/modules/node/src/onchainTransactions/onchainTransaction.service.ts +++ b/modules/node/src/onchainTransactions/onchainTransaction.service.ts @@ -51,18 +51,19 @@ export class OnchainTransactionService implements OnModuleInit { transaction: MinimalTransaction, appIdentityHash: string, ): Promise { - return new Promise((resolve, reject) => { - this.queues.get(channel.chainId)!.add(() => { - this.sendTransaction( - transaction, - TransactionReason.USER_WITHDRAWAL, - channel, - appIdentityHash, - ) - .then((result) => resolve(result)) - .catch((error) => reject(error.message)); - }); - }); + return this.queues.get(channel.chainId)!.add( + () => + new Promise((resolve, reject) => + this.sendTransaction( + transaction, + TransactionReason.USER_WITHDRAWAL, + channel, + appIdentityHash, + ) + .then((result) => resolve(result)) + .catch((error) => reject(error.message)), + ), + ); } async sendWithdrawal( @@ -70,18 +71,19 @@ export class OnchainTransactionService implements OnModuleInit { transaction: MinimalTransaction, appIdentityHash: string, ): Promise { - return new Promise((resolve, reject) => { - this.queues.get(channel.chainId)!.add(() => { - this.sendTransaction( - transaction, - TransactionReason.NODE_WITHDRAWAL, - channel, - appIdentityHash, - ) - .then((result) => resolve(result)) - .catch((error) => reject(error.message)); - }); - }); + return this.queues.get(channel.chainId)!.add( + () => + new Promise((resolve, reject) => + this.sendTransaction( + transaction, + TransactionReason.NODE_WITHDRAWAL, + channel, + appIdentityHash, + ) + .then((result) => resolve(result)) + .catch((error) => reject(error.message)), + ), + ); } async sendDeposit( @@ -89,18 +91,19 @@ export class OnchainTransactionService implements OnModuleInit { transaction: MinimalTransaction, appIdentityHash: string, ): Promise { - return new Promise((resolve, reject) => { - this.queues.get(channel.chainId)!.add(() => { - this.sendTransaction( - transaction, - TransactionReason.COLLATERALIZATION, - channel, - appIdentityHash, - ) - .then((result) => resolve(result)) - .catch((error) => reject(error.message)); - }); - }); + return this.queues.get(channel.chainId)!.add( + () => + new Promise((resolve, reject) => + this.sendTransaction( + transaction, + TransactionReason.COLLATERALIZATION, + channel, + appIdentityHash, + ) + .then((result) => resolve(result)) + .catch((error) => reject(error.message)), + ), + ); } findByHash(hash: string): Promise { @@ -116,13 +119,15 @@ export class OnchainTransactionService implements OnModuleInit { json: StateChannelJSON, ): Promise { const channel = await this.channelRepository.findByMultisigAddressOrThrow(json.multisigAddress); - const tx: OnchainTransactionResponse = await new Promise((resolve, reject) => { - this.queues.get(channel.chainId)!.add(() => { - this.sendTransaction(transaction, TransactionReason.MULTISIG_DEPLOY, channel) - .then((result) => resolve(result)) - .catch((error) => reject(error.message)); - }); - }); + const queue = this.queues.get(channel.chainId); + const tx: OnchainTransactionResponse = (await queue?.add( + () => + new Promise((resolve, reject) => + this.sendTransaction(transaction, TransactionReason.MULTISIG_DEPLOY, channel) + .then((res) => resolve(res)) + .catch((e) => reject(e.message)), + ), + )) as any; // make sure to wait for the transaction to be completed here, since // the multisig deployment is followed by a call to `getOwners`. // and since the cf-core transaction service expects the tx to be @@ -157,13 +162,32 @@ export class OnchainTransactionService implements OnModuleInit { ); const errors: { [k: number]: string } = []; let tx: providers.TransactionResponse | undefined; - for (let attempt = 1; attempt < MAX_RETRIES + 1; attempt += 1) { + let nonce: number | undefined; + let attempt: number | undefined; + for (attempt = 1; attempt < MAX_RETRIES + 1; attempt += 1) { try { this.log.info(`Attempt ${attempt}/${MAX_RETRIES} to send transaction to ${transaction.to}`); const chainNonce = await wallet.getTransactionCount(); const memoryNonce = (await this.nonces.get(channel.chainId))!; - const nonce = chainNonce > memoryNonce ? chainNonce : memoryNonce; + nonce = chainNonce > memoryNonce ? chainNonce : memoryNonce; + // add pending so we can mark it failed + this.log.info(`Adding pending tx with nonce ${nonce}`); + // TODO: (Med) Generate the transaction hash before sending + + // TODO: this wont work if the loop happens more than once + // possible fix: add unique index on from+nonce and use onConflict + // actually this wont work, easiest fix is to look it up by channel+reason+nonce first :/ + await this.onchainTransactionRepository.addPending( + transaction, + nonce, + wallet.address, + reason, + channel, + appIdentityHash, + ); + this.log.info(`Populating tx with nonce ${nonce}`); const populatedTx = await wallet.populateTransaction({ ...transaction, nonce }); + this.log.info(`Sending tx with nonce ${nonce}`); tx = await wallet.sendTransaction({ ...populatedTx, gasLimit: BigNumber.from(populatedTx.gasLimit || 0).lt(MIN_GAS_LIMIT) @@ -171,17 +195,25 @@ export class OnchainTransactionService implements OnModuleInit { : populatedTx.gasLimit, gasPrice: getGasPrice(wallet.provider!, channel.chainId), }); + this.log.info(`Tx submitted, hash: ${tx.hash}`); if (!tx.hash) { throw new Error(NO_TX_HASH); } - // add fields from tx response - await this.onchainTransactionRepository.addResponse(tx, reason, channel, appIdentityHash); this.nonces.set(channel.chainId, Promise.resolve(nonce + 1)); + // add fields from tx response + await this.onchainTransactionRepository.addResponse( + tx, + nonce, + reason, + channel, + appIdentityHash, + ); const start = Date.now(); // eslint-disable-next-line no-loop-func const completed: Promise = new Promise(async (resolve, reject) => { try { const receipt = await tx!.wait(); + this.log.info(`Tx mined, hash: ${receipt.transactionHash}`); await this.onchainTransactionRepository.addReceipt(receipt); resolve(); } catch (e) { @@ -204,7 +236,7 @@ export class OnchainTransactionService implements OnModuleInit { const knownErr = KNOWN_ERRORS.find((err) => e.message.includes(err)); if (!knownErr) { this.log.error(`Transaction failed to send with unknown error: ${e.message}`); - throw new Error(e.stack || e.message); + break; } // known error, retry this.log.warn( @@ -213,7 +245,19 @@ export class OnchainTransactionService implements OnModuleInit { } } if (tx) { - await this.onchainTransactionRepository.markFailed(tx, errors, appIdentityHash); + this.log.info(`Marking failed by tx hash`); + await this.onchainTransactionRepository.markFailedByTxHash(tx, errors, appIdentityHash); + } else if (nonce) { + this.log.info(`Marking failed by nonce`); + await this.onchainTransactionRepository.markFailedByChannelFromAndNonce( + channel.multisigAddress, + wallet.address, + nonce, + errors, + appIdentityHash, + ); + } else { + this.log.error(`No nonce or tx hash found to mark failed tx with!`); } throw new Error(`Failed to send transaction (errors indexed by attempt): ${stringify(errors)}`); } diff --git a/modules/node/src/swapRate/swapRate.service.ts b/modules/node/src/swapRate/swapRate.service.ts index 4afc9b7fa8..56a623424f 100644 --- a/modules/node/src/swapRate/swapRate.service.ts +++ b/modules/node/src/swapRate/swapRate.service.ts @@ -105,7 +105,10 @@ export class SwapRateService implements OnModuleInit { throw new Error(`No valid swap exists for ${from} to ${to}`); } } - return rate!; + if (!rate) { + throw new Error(`Could not get rate for ${from}:${fromChainId} to ${to}:${toChainId}`); + } + return rate; } async fetchSwapRate( @@ -174,6 +177,11 @@ export class SwapRateService implements OnModuleInit { } } + if (newRate === "0" || newRate === "Infinity") { + this.log.debug(`Invalid swap rate for ${from} to ${to}: ${newRate}`); + return undefined; + } + const newSwap: SwapRate = { from, to, diff --git a/modules/store/package.json b/modules/store/package.json index 6d9c63167c..b2ca4b751c 100644 --- a/modules/store/package.json +++ b/modules/store/package.json @@ -1,6 +1,6 @@ { "name": "@connext/store", - "version": "7.3.5", + "version": "7.3.6", "description": "Store module for Connext client", "browser": "dist/browser.js", "react-native": "dist/reactNative.js", @@ -17,8 +17,8 @@ }, "dependencies": { "@connext/contracts": "3.5.0", - "@connext/types": "7.3.5", - "@connext/utils": "7.3.5", + "@connext/types": "7.3.6", + "@connext/utils": "7.3.6", "localStorage": "1.0.4", "p-waterfall": "2.1.0", "pg": "8.3.0", diff --git a/modules/test-runner/package.json b/modules/test-runner/package.json index 1477adcd47..ab06951754 100644 --- a/modules/test-runner/package.json +++ b/modules/test-runner/package.json @@ -11,16 +11,16 @@ "author": "", "license": "ISC", "dependencies": { - "@connext/apps": "7.3.5", - "@connext/cf-core": "7.3.5", - "@connext/channel-provider": "7.3.5", - "@connext/client": "7.3.5", + "@connext/apps": "7.3.6", + "@connext/cf-core": "7.3.6", + "@connext/channel-provider": "7.3.6", + "@connext/client": "7.3.6", "@connext/contracts": "3.5.0", - "@connext/messaging": "7.3.5", + "@connext/messaging": "7.3.6", "@connext/pure-evm-wasm": "0.1.4", - "@connext/store": "7.3.5", - "@connext/types": "7.3.5", - "@connext/utils": "7.3.5", + "@connext/store": "7.3.6", + "@connext/types": "7.3.6", + "@connext/utils": "7.3.6", "@ethereum-waffle/chai": "3.0.2", "@openzeppelin/contracts": "3.0.2", "axios": "0.19.2", diff --git a/modules/test-runner/src/collateral/request.test.ts b/modules/test-runner/src/collateral/request.test.ts index 50a3113ec3..7033a9115c 100644 --- a/modules/test-runner/src/collateral/request.test.ts +++ b/modules/test-runner/src/collateral/request.test.ts @@ -1,13 +1,7 @@ import { IConnextClient, EventNames } from "@connext/types"; import { constants } from "ethers"; -import { - createClient, - ETH_AMOUNT_MD, - expect, - getTestLoggers, - TOKEN_AMOUNT, -} from "../util"; +import { createClient, ETH_AMOUNT_MD, expect, getTestLoggers, TOKEN_AMOUNT } from "../util"; const { AddressZero, Zero } = constants; diff --git a/modules/test-runner/src/util/helpers/fundChannel.ts b/modules/test-runner/src/util/helpers/fundChannel.ts index 5b448539d7..d97bba953c 100644 --- a/modules/test-runner/src/util/helpers/fundChannel.ts +++ b/modules/test-runner/src/util/helpers/fundChannel.ts @@ -88,7 +88,7 @@ export const requestCollateral = async ( return; } if (!res) { - throw new Error("Node did not collateralized, and collateral should be enforced"); + throw new Error("Node did not collateralize, and collateral should be enforced"); } log.info(`waiting for collateral tx to be mined and ap to be uninstalled`); const { freeBalance } = await res.completed(); diff --git a/modules/types/package.json b/modules/types/package.json index 2fd8959a5a..e2cee2d269 100644 --- a/modules/types/package.json +++ b/modules/types/package.json @@ -1,6 +1,6 @@ { "name": "@connext/types", - "version": "7.3.5", + "version": "7.3.6", "description": "TypeScript typings for common Connext types", "main": "dist/index.js", "module": "dist/index.esm.js", diff --git a/modules/utils/package.json b/modules/utils/package.json index 698cdf532f..cc30e59012 100644 --- a/modules/utils/package.json +++ b/modules/utils/package.json @@ -1,6 +1,6 @@ { "name": "@connext/utils", - "version": "7.3.5", + "version": "7.3.6", "description": "Crypto module for Connext client", "main": "dist/index.js", "files": [ @@ -15,7 +15,7 @@ "test": "./node_modules/.bin/ts-mocha --bail --check-leaks --exit 'src/**/*.spec.ts'" }, "dependencies": { - "@connext/types": "7.3.5", + "@connext/types": "7.3.6", "axios": "0.19.2", "bs58check": "2.1.2", "eccrypto-js": "4.5.4", diff --git a/modules/watcher/package.json b/modules/watcher/package.json index 2832572733..f11f173301 100644 --- a/modules/watcher/package.json +++ b/modules/watcher/package.json @@ -1,6 +1,6 @@ { "name": "@connext/watcher", - "version": "7.3.5", + "version": "7.3.6", "description": "Responds to disputes on behalf of a channel participant.", "main": "dist/index.js", "types": "dist/src/index.d.ts", @@ -15,11 +15,11 @@ "test": "mocha -r ts-node/register 'test/**/*.spec.{ts,tsx}' --exit --slow 1000 --timeout 150000 --bail" }, "dependencies": { - "@connext/apps": "7.3.5", + "@connext/apps": "7.3.6", "@connext/contracts": "3.5.0", - "@connext/store": "7.3.5", - "@connext/types": "7.3.5", - "@connext/utils": "7.3.5", + "@connext/store": "7.3.6", + "@connext/types": "7.3.6", + "@connext/utils": "7.3.6", "@types/chai-as-promised": "7.1.3", "@types/chai-subset": "1.3.3", "@types/mocha": "8.0.1", diff --git a/package-lock.json b/package-lock.json index 30d98bf0cd..84400e5adc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "indra", - "version": "7.3.4", + "version": "7.3.5", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 3797436c05..df56f97965 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "indra", - "version": "7.3.5", + "version": "7.3.6", "backwardsCompatibleWith": "7.2.0", "registry": "docker.io/connextproject", "description": "",