diff --git a/src/balancer/OceanPool.ts b/src/balancer/OceanPool.ts index 144738b4..f30d0af4 100644 --- a/src/balancer/OceanPool.ts +++ b/src/balancer/OceanPool.ts @@ -220,7 +220,7 @@ export class OceanPool extends Pool { tokenAddress: string ): Promise { const balance = await super.getReserve(poolAddress, tokenAddress) - return String(parseFloat(balance) / 3) + return new Decimal(balance).div(3).toString() } /** @@ -449,14 +449,14 @@ export class OceanPool extends Pool { const totalPoolTokens = await this.getPoolSharesTotalSupply(poolAddress) const dtReserve = await this.getDTReserve(poolAddress) const oceanReserve = await this.getOceanReserve(poolAddress) - - const dtAmount = `${ - (Number(poolShares) / Number(totalPoolTokens)) * Number(dtReserve) - }` - const oceanAmount = `${ - (Number(poolShares) / Number(totalPoolTokens)) * Number(oceanReserve) - }` - + const dtAmount = new Decimal(poolShares) + .div(totalPoolTokens) + .mul(dtReserve) + .toString() + const oceanAmount = new Decimal(poolShares) + .div(totalPoolTokens) + .mul(oceanReserve) + .toString() return { dtAmount, oceanAmount } } catch (e) { this.logger.error(`ERROR: Unable to get token info. ${e.message}`) @@ -491,11 +491,7 @@ export class OceanPool extends Pool { ): Promise { const balance = await super.getReserve(poolAddress, tokenAddress) if (parseFloat(balance) > 0) { - const result = new BigNumber(this.web3.utils.toWei(balance)) - .multipliedBy(POOL_MAX_AMOUNT_IN_LIMIT) - .integerValue(BigNumber.ROUND_DOWN) - .minus(1) - return this.web3.utils.fromWei(result.toString(10)) + return new Decimal(balance).mul(POOL_MAX_AMOUNT_IN_LIMIT).toString() } else return '0' } @@ -510,11 +506,7 @@ export class OceanPool extends Pool { ): Promise { const balance = await super.getReserve(poolAddress, tokenAddress) if (parseFloat(balance) > 0) { - const result = new BigNumber(this.web3.utils.toWei(balance)) - .multipliedBy(POOL_MAX_AMOUNT_OUT_LIMIT) - .integerValue(BigNumber.ROUND_DOWN) - .minus(1) - return this.web3.utils.fromWei(result.toString(10)) + return new Decimal(balance).mul(POOL_MAX_AMOUNT_OUT_LIMIT).toString() } else return '0' } @@ -559,14 +551,13 @@ export class OceanPool extends Pool { } const dtAddress = await this.getDTAddress(poolAddress) if ( - parseFloat(dtAmountWanted) > parseFloat(await this.getDTMaxBuyQuantity(poolAddress)) + new Decimal(dtAmountWanted).greaterThan(await this.getDTMaxBuyQuantity(poolAddress)) ) { this.logger.error('ERROR: Buy quantity exceeds quantity allowed') return null } const calcInGivenOut = await this.getOceanNeeded(poolAddress, dtAmountWanted) - - if (parseFloat(calcInGivenOut) > parseFloat(maxOceanAmount)) { + if (new Decimal(calcInGivenOut).greaterThan(maxOceanAmount)) { this.logger.error('ERROR: Not enough Ocean Tokens') return null } @@ -615,15 +606,15 @@ export class OceanPool extends Pool { } const dtAddress = await this.getDTAddress(poolAddress) if ( - parseFloat(minimumdtAmountWanted) > - parseFloat(await this.getDTMaxBuyQuantity(poolAddress)) + new Decimal(minimumdtAmountWanted).greaterThan( + await this.getDTMaxBuyQuantity(poolAddress) + ) ) { this.logger.error('ERROR: Buy quantity exceeds quantity allowed') return null } const calcInGivenOut = await this.getOceanNeeded(poolAddress, minimumdtAmountWanted) - - if (parseFloat(calcInGivenOut) > parseFloat(OceanAmount)) { + if (new Decimal(calcInGivenOut).greaterThan(OceanAmount)) { this.logger.error('ERROR: Not enough Ocean Tokens') return null } @@ -672,15 +663,15 @@ export class OceanPool extends Pool { } const dtAddress = await this.getDTAddress(poolAddress) if ( - parseFloat(oceanAmountWanted) > - parseFloat(await this.getOceanMaxBuyQuantity(poolAddress)) + new Decimal(oceanAmountWanted).greaterThan( + await this.getOceanMaxBuyQuantity(poolAddress) + ) ) { this.logger.error('ERROR: Buy quantity exceeds quantity allowed') return null } const calcOutGivenIn = await this.getOceanReceived(poolAddress, dtAmount) - - if (parseFloat(calcOutGivenIn) < parseFloat(oceanAmountWanted)) { + if (new Decimal(calcOutGivenIn).lessThan(oceanAmountWanted)) { this.logger.error('ERROR: Not enough datatokens') return null } @@ -720,7 +711,7 @@ export class OceanPool extends Pool { ): Promise { const dtAddress = await this.getDTAddress(poolAddress) const maxAmount = await this.getMaxAddLiquidity(poolAddress, dtAddress) - if (parseFloat(amount) > parseFloat(maxAmount)) { + if (new Decimal(amount).greaterThan(maxAmount)) { this.logger.error('ERROR: Too much reserve to add') return null } @@ -760,23 +751,23 @@ export class OceanPool extends Pool { ): Promise { const dtAddress = await this.getDTAddress(poolAddress) const maxAmount = await this.getDTMaxRemoveLiquidity(poolAddress) - if (parseFloat(amount) > parseFloat(maxAmount)) { + if (new Decimal(amount).greaterThan(maxAmount)) { this.logger.error('ERROR: Too much reserve to remove') return null } const usershares = await this.sharesBalance(account, poolAddress) - if (parseFloat(usershares) < parseFloat(maximumPoolShares)) { + if (new Decimal(usershares).lessThan(maximumPoolShares)) { this.logger.error('ERROR: Not enough poolShares') return null } const sharesRequired = await this.getPoolSharesRequiredToRemoveDT(poolAddress, amount) - if (parseFloat(maximumPoolShares) < parseFloat(sharesRequired)) { + if (new Decimal(maximumPoolShares).lessThan(sharesRequired)) { this.logger.error('ERROR: Not enough poolShares') return null } // Balancer bug fix - if (parseFloat(maximumPoolShares) < parseFloat(sharesRequired)) - maximumPoolShares = String(parseFloat(maximumPoolShares) * 0.9999) + if (new Decimal(maximumPoolShares).lessThan(sharesRequired)) + maximumPoolShares = new Decimal(maximumPoolShares).mul(0.9999).toString() // Balance bug fix return this.exitswapExternAmountOut( account, @@ -804,7 +795,7 @@ export class OceanPool extends Pool { return null } const maxAmount = await this.getOceanMaxAddLiquidity(poolAddress) - if (parseFloat(amount) > parseFloat(maxAmount)) { + if (new Decimal(amount).greaterThan(maxAmount)) { this.logger.error('ERROR: Too much reserve to add') return null } @@ -847,7 +838,7 @@ export class OceanPool extends Pool { return null } const usershares = await this.sharesBalance(account, poolAddress) - if (parseFloat(usershares) < parseFloat(poolShares)) { + if (new Decimal(usershares).lessThan(poolShares)) { this.logger.error('ERROR: Not enough poolShares') return null } @@ -880,12 +871,12 @@ export class OceanPool extends Pool { return null } const maxAmount = await this.getOceanMaxRemoveLiquidity(poolAddress) - if (parseFloat(amount) > parseFloat(maxAmount)) { + if (new Decimal(amount).greaterThan(maxAmount)) { this.logger.error('ERROR: Too much reserve to remove') return null } const usershares = await this.sharesBalance(account, poolAddress) - if (parseFloat(usershares) < parseFloat(maximumPoolShares)) { + if (new Decimal(usershares).lessThan(maximumPoolShares)) { this.logger.error('ERROR: Not enough poolShares') return null } @@ -893,13 +884,13 @@ export class OceanPool extends Pool { poolAddress, amount ) - if (parseFloat(maximumPoolShares) < parseFloat(sharesRequired)) { + if (new Decimal(maximumPoolShares).lessThan(sharesRequired)) { this.logger.error('ERROR: Not enough poolShares') return null } // Balancer bug fix - if (parseFloat(maximumPoolShares) < parseFloat(sharesRequired)) - maximumPoolShares = String(parseFloat(maximumPoolShares) * 0.9999) + if (new Decimal(maximumPoolShares).lessThan(sharesRequired)) + maximumPoolShares = new Decimal(maximumPoolShares).mul(0.9999).toString() // Balance bug fix return super.exitswapExternAmountOut( account, @@ -927,13 +918,13 @@ export class OceanPool extends Pool { minOcean = '0' ): Promise { const usershares = await this.sharesBalance(account, poolAddress) - if (parseFloat(usershares) < parseFloat(poolShares)) { + if (new Decimal(usershares).lessThan(poolShares)) { this.logger.error('ERROR: Not enough poolShares') return null } // Balancer bug fix - if (parseFloat(usershares) === parseFloat(poolShares)) - poolShares = String(parseFloat(poolShares) * 0.9999) + if (new Decimal(usershares).equals(poolShares)) + poolShares = new Decimal(poolShares).mul(0.9999).toString() // Balance bug fix return this.exitPool(account, poolAddress, poolShares, [minDT, minOcean]) } @@ -975,7 +966,7 @@ export class OceanPool extends Pool { public async getOceanNeeded(poolAddress: string, dtRequired: string): Promise { const dtAddress = await this.getDTAddress(poolAddress) if ( - parseFloat(dtRequired) > parseFloat(await this.getDTMaxBuyQuantity(poolAddress)) + new Decimal(dtRequired).greaterThan(await this.getDTMaxBuyQuantity(poolAddress)) ) { return '0' } @@ -1007,8 +998,9 @@ export class OceanPool extends Pool { public async getDTNeeded(poolAddress: string, OceanRequired: string): Promise { const dtAddress = await this.getDTAddress(poolAddress) if ( - parseFloat(OceanRequired) > - parseFloat(await this.getOceanMaxBuyQuantity(poolAddress)) + new Decimal(OceanRequired).greaterThan( + await this.getOceanMaxBuyQuantity(poolAddress) + ) ) { return '0' } @@ -1295,8 +1287,7 @@ export class OceanPool extends Pool { tokenOutWeight, swapfee ) - const slippage = (parseFloat(newPrice) * 100) / parseFloat(initialPrice) - 100 - return String(slippage) + return new Decimal(newPrice).mul(100).div(initialPrice).minus(100).toString() } /* Get slippage for buying some datatokens while spending exactly oceanAmount ocean tokens */ diff --git a/src/balancer/Pool.ts b/src/balancer/Pool.ts index 8b7e193b..83075c89 100644 --- a/src/balancer/Pool.ts +++ b/src/balancer/Pool.ts @@ -134,12 +134,14 @@ export class Pool extends PoolFactory { * @param {String} tokenAddress * @param {String} spender * @param {String} amount (always expressed as wei) + * @param {String} force if true, will overwrite any previous allowence. Else, will check if allowence is enough and will not send a transaction if it's not needed */ async approve( account: string, tokenAddress: string, spender: string, - amount: string + amount: string, + force = false ): Promise { const minABI = [ { @@ -169,6 +171,13 @@ export class Pool extends PoolFactory { const token = new this.web3.eth.Contract(minABI, tokenAddress, { from: account }) + if (!force) { + const currentAllowence = await this.allowance(tokenAddress, account, spender) + if (new Decimal(currentAllowence).greaterThanOrEqualTo(amount)) { + // we have enough + return null + } + } let result = null const gasLimitDefault = this.GASLIMIT_DEFAULT let estGas @@ -890,7 +899,7 @@ export class Pool extends PoolFactory { ) .send({ from: account, - gas: this.GASLIMIT_DEFAULT, + gas: estGas + 1, gasPrice: await getFairGasPrice(this.web3) }) } catch (e) { diff --git a/src/balancer/PoolFactory.ts b/src/balancer/PoolFactory.ts index 953176e4..13bd344f 100644 --- a/src/balancer/PoolFactory.ts +++ b/src/balancer/PoolFactory.ts @@ -45,10 +45,19 @@ export class PoolFactory { from: account }) let txid = null + const gasLimitDefault = this.GASLIMIT_DEFAULT + let estGas try { - txid = await factory.methods + estGas = await factory.methods .newBPool() - .send({ from: account, gas: this.GASLIMIT_DEFAULT }) + .estimateGas({ from: account }, (err, estGas) => (err ? gasLimitDefault : estGas)) + } catch (e) { + this.logger.log('Error estimate gas newBPool') + this.logger.log(e) + estGas = gasLimitDefault + } + try { + txid = await factory.methods.newBPool().send({ from: account, gas: estGas + 1 }) // pooladdress = transactiondata.events.BPoolRegistered.returnValues[0] } catch (e) { this.logger.error(`ERROR: Failed to create new pool: ${e.message}`) diff --git a/src/utils/GasUtils.ts b/src/utils/GasUtils.ts index c94c1489..90b907db 100644 --- a/src/utils/GasUtils.ts +++ b/src/utils/GasUtils.ts @@ -3,5 +3,5 @@ import Web3 from 'web3' export async function getFairGasPrice(web3: Web3): Promise { const x = new BigNumber(await web3.eth.getGasPrice()) - return x.multipliedBy(1.25).integerValue(BigNumber.ROUND_DOWN).toString(10) + return x.multipliedBy(1.05).integerValue(BigNumber.ROUND_DOWN).toString(10) }