1
0
mirror of https://github.com/oceanprotocol/ocean.js.git synced 2024-11-26 20:39:05 +01:00

add complete multi decimals support in Pool, add test

This commit is contained in:
lacoop6tu 2021-10-29 13:17:59 -05:00
parent 6df2123f91
commit 22746a10e0
5 changed files with 1249 additions and 1267 deletions

View File

@ -1,5 +1,6 @@
import { Contract } from 'web3-eth-contract' import { Contract } from 'web3-eth-contract'
import Web3 from 'web3' import Web3 from 'web3'
import BigNumber from 'bignumber.js'
import { TransactionReceipt } from 'web3-core' import { TransactionReceipt } from 'web3-core'
import { AbiItem } from 'web3-utils' import { AbiItem } from 'web3-utils'
import defaultFactory721ABI from '@oceanprotocol/contracts/artifacts/contracts/ERC721Factory.sol/ERC721Factory.json' import defaultFactory721ABI from '@oceanprotocol/contracts/artifacts/contracts/ERC721Factory.sol/ERC721Factory.json'
@ -37,7 +38,7 @@ interface ErcCreateData {
interface PoolData { interface PoolData {
addresses: string[] addresses: string[]
ssParams: (string | number)[] ssParams: (string | number | BigNumber)[]
swapFees: number[] swapFees: number[]
} }

View File

@ -124,18 +124,17 @@ export class Router {
/** /**
* Estimate gas cost for addOceanToken * Estimate gas cost for addOceanToken
* @param {String} address * @param {String} address
* @param {String} tokenAddress token address we want to add * @param {String} tokenAddress token address we want to add
* @param {Contract} routerContract optional contract instance * @param {Contract} routerContract optional contract instance
* @return {Promise<any>} * @return {Promise<any>}
*/ */
public async estGasAddOceanToken( public async estGasAddOceanToken(
address: string, address: string,
tokenAddress: string, tokenAddress: string,
contractInstance?: Contract contractInstance?: Contract
) { ) {
const routerContract = const routerContract = contractInstance || this.router
contractInstance || this.router
const gasLimitDefault = this.GASLIMIT_DEFAULT const gasLimitDefault = this.GASLIMIT_DEFAULT
let estGas let estGas
@ -148,6 +147,7 @@ export class Router {
} }
return estGas return estGas
} }
/** /**
* Add a new token to oceanTokens list, pools with basetoken in this list have NO opf Fee * Add a new token to oceanTokens list, pools with basetoken in this list have NO opf Fee
* @param {String} address caller address * @param {String} address caller address
@ -162,9 +162,7 @@ export class Router {
throw new Error(`Caller is not Router Owner`) throw new Error(`Caller is not Router Owner`)
} }
const estGas = await this.estGasAddOceanToken(address, tokenAddress)
const estGas = await this.estGasAddOceanToken(address,tokenAddress)
// Invoke createToken function of the contract // Invoke createToken function of the contract
const trxReceipt = await this.router.methods.addOceanToken(tokenAddress).send({ const trxReceipt = await this.router.methods.addOceanToken(tokenAddress).send({
@ -176,32 +174,31 @@ export class Router {
return trxReceipt return trxReceipt
} }
/** /**
* Estimate gas cost for removeOceanToken * Estimate gas cost for removeOceanToken
* @param {String} address caller address * @param {String} address caller address
* @param {String} tokenAddress token address we want to add * @param {String} tokenAddress token address we want to add
* @param {Contract} routerContract optional contract instance * @param {Contract} routerContract optional contract instance
* @return {Promise<any>} * @return {Promise<any>}
*/ */
public async estGasRemoveOceanToken( public async estGasRemoveOceanToken(
address: string, address: string,
tokenAddress: string, tokenAddress: string,
contractInstance?: Contract contractInstance?: Contract
) { ) {
const routerContract = const routerContract = contractInstance || this.router
contractInstance || this.router
const gasLimitDefault = this.GASLIMIT_DEFAULT
const gasLimitDefault = this.GASLIMIT_DEFAULT let estGas
let estGas try {
try { estGas = await routerContract.methods
estGas = await routerContract.methods .removeOceanToken(tokenAddress)
.removeOceanToken(tokenAddress) .estimateGas({ from: address }, (err, estGas) => (err ? gasLimitDefault : estGas))
.estimateGas({ from: address }, (err, estGas) => (err ? gasLimitDefault : estGas)) } catch (e) {
} catch (e) { estGas = gasLimitDefault
estGas = gasLimitDefault
}
return estGas
} }
return estGas
}
/** /**
* Remove a token from oceanTokens list, pools without basetoken in this list have a opf Fee * Remove a token from oceanTokens list, pools without basetoken in this list have a opf Fee
@ -217,8 +214,7 @@ export class Router {
throw new Error(`Caller is not Router Owner`) throw new Error(`Caller is not Router Owner`)
} }
const estGas = await this.estGasRemoveOceanToken(address,tokenAddress) const estGas = await this.estGasRemoveOceanToken(address, tokenAddress)
// Invoke createToken function of the contract // Invoke createToken function of the contract
const trxReceipt = await this.router.methods.removeOceanToken(tokenAddress).send({ const trxReceipt = await this.router.methods.removeOceanToken(tokenAddress).send({

View File

@ -40,11 +40,9 @@ export class Pool {
spender: string spender: string
): Promise<string> { ): Promise<string> {
const tokenAbi = defaultERC20ABI.abi as AbiItem[] const tokenAbi = defaultERC20ABI.abi as AbiItem[]
const datatoken = new this.web3.eth.Contract(tokenAbi, tokenAddress, { const datatoken = new this.web3.eth.Contract(tokenAbi, tokenAddress)
from: spender
})
const trxReceipt = await datatoken.methods.allowance(owner, spender).call() const trxReceipt = await datatoken.methods.allowance(owner, spender).call()
return this.web3.utils.fromWei(trxReceipt) return (await this.unitsToAmount(tokenAddress, trxReceipt)).toString()
} }
/** /**
@ -103,18 +101,20 @@ export class Pool {
let estGas let estGas
try { try {
estGas = await token.methods estGas = await token.methods
.approve(spender, amount) .approve(spender, await this.amountToUnits(tokenAddress, amount))
.estimateGas({ from: account }, (err, estGas) => (err ? gasLimitDefault : estGas)) .estimateGas({ from: account }, (err, estGas) => (err ? gasLimitDefault : estGas))
} catch (e) { } catch (e) {
estGas = gasLimitDefault estGas = gasLimitDefault
} }
try { try {
result = await token.methods.approve(spender, amount).send({ result = await token.methods
from: account, .approve(spender, await this.amountToUnits(tokenAddress, amount))
gas: estGas + 1, .send({
gasPrice: await getFairGasPrice(this.web3) from: account,
}) gas: estGas + 1,
gasPrice: await getFairGasPrice(this.web3)
})
} catch (e) { } catch (e) {
this.logger.error(`ERRPR: Failed to approve spender to spend tokens : ${e.message}`) this.logger.error(`ERRPR: Failed to approve spender to spend tokens : ${e.message}`)
} }
@ -247,62 +247,60 @@ export class Pool {
return result return result
} }
/** /**
* Get basetoken address of this pool * Get basetoken address of this pool
* @param {String} poolAddress * @param {String} poolAddress
* @return {String} * @return {String}
*/ */
async getBasetoken(poolAddress: string): Promise<string> { async getBasetoken(poolAddress: string): Promise<string> {
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress) const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
let result = null let result = null
try { try {
result = await pool.methods.getBaseTokenAddress().call() result = await pool.methods.getBaseTokenAddress().call()
} catch (e) { } catch (e) {
this.logger.error(`ERROR: Failed to get basetoken address: ${e.message}`) this.logger.error(`ERROR: Failed to get basetoken address: ${e.message}`)
}
return result
} }
return result
}
/** /**
* Get datatoken address of this pool * Get datatoken address of this pool
* @param {String} poolAddress * @param {String} poolAddress
* @return {String} * @return {String}
*/ */
async getDatatoken(poolAddress: string): Promise<string> { async getDatatoken(poolAddress: string): Promise<string> {
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress) const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
let result = null let result = null
try { try {
result = await pool.methods.getDataTokenAddress().call() result = await pool.methods.getDataTokenAddress().call()
} catch (e) { } catch (e) {
this.logger.error(`ERROR: Failed to get datatoken address: ${e.message}`) this.logger.error(`ERROR: Failed to get datatoken address: ${e.message}`)
} }
return result return result
} }
/** /**
* Get marketFeeCollector of this pool * Get marketFeeCollector of this pool
* @param {String} poolAddress * @param {String} poolAddress
* @return {String} * @return {String}
*/ */
async getMarketFeeCollector(poolAddress: string): Promise<string> { async getMarketFeeCollector(poolAddress: string): Promise<string> {
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress) const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
let result = null let result = null
try { try {
result = await pool.methods._marketCollector().call() result = await pool.methods._marketCollector().call()
} catch (e) { } catch (e) {
this.logger.error(`ERROR: Failed to get marketFeeCollector address: ${e.message}`) this.logger.error(`ERROR: Failed to get marketFeeCollector address: ${e.message}`)
}
return result
} }
return result
}
/** /**
* Get OPF Collector of this pool * Get OPF Collector of this pool
* @param {String} poolAddress * @param {String} poolAddress
* @return {String} * @return {String}
*/ */
async getOPFCollector(poolAddress: string): Promise<string> { async getOPFCollector(poolAddress: string): Promise<string> {
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress) const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
let result = null let result = null
try { try {
@ -312,6 +310,7 @@ export class Pool {
} }
return result return result
} }
/** /**
* Get if a token is bounded to a pool * Get if a token is bounded to a pool
* @param {String} poolAddress * @param {String} poolAddress
@ -341,7 +340,7 @@ export class Pool {
try { try {
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress) const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
const result = await pool.methods.getBalance(token).call() const result = await pool.methods.getBalance(token).call()
amount = await this.unitsToAmount(token,result) amount = await this.unitsToAmount(token, result)
} catch (e) { } catch (e) {
this.logger.error(`ERROR: Failed to get how many tokens \ this.logger.error(`ERROR: Failed to get how many tokens \
are in the pool: ${e.message}`) are in the pool: ${e.message}`)
@ -435,103 +434,94 @@ export class Pool {
return weight return weight
} }
/** /**
* Get Market Fees available to be collected for a specific token * Get Market Fees available to be collected for a specific token
* @param {String} poolAddress * @param {String} poolAddress
* @param {String} token token we want to check fees * @param {String} token token we want to check fees
* @return {String} * @return {String}
*/ */
async getMarketFees(poolAddress: string, token: string): Promise<string> { async getMarketFees(poolAddress: string, token: string): Promise<string> {
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress) const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
let weight = null let weight = null
try { try {
const result = await pool.methods.marketFees(token).call() const result = await pool.methods.marketFees(token).call()
weight = this.web3.utils.fromWei(result) weight = this.web3.utils.fromWei(result)
} catch (e) { } catch (e) {
this.logger.error(`ERROR: Failed to get market fees for a token: ${e.message}`) this.logger.error(`ERROR: Failed to get market fees for a token: ${e.message}`)
}
return weight
} }
return weight
}
/** /**
* Get Community Fees available to be collected for a specific token * Get Community Fees available to be collected for a specific token
* @param {String} poolAddress * @param {String} poolAddress
* @param {String} token token we want to check fees * @param {String} token token we want to check fees
* @return {String} * @return {String}
*/ */
async getCommunityFees(poolAddress: string, token: string): Promise<string> { async getCommunityFees(poolAddress: string, token: string): Promise<string> {
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress) const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
let weight = null let weight = null
try { try {
const result = await pool.methods.communityFees(token).call() const result = await pool.methods.communityFees(token).call()
weight = this.web3.utils.fromWei(result) weight = this.web3.utils.fromWei(result)
} catch (e) { } catch (e) {
this.logger.error(`ERROR: Failed to get community fees for a token: ${e.message}`) this.logger.error(`ERROR: Failed to get community fees for a token: ${e.message}`)
} }
return weight return weight
} }
/** /**
* Estimate gas cost for collectOPF * Estimate gas cost for collectOPF
* @param {String} address * @param {String} address
* @param {String} poolAddress * @param {String} poolAddress
* @param {Contract} contractInstance optional contract instance * @param {Contract} contractInstance optional contract instance
* @return {Promise<number>} * @return {Promise<number>}
*/ */
public async estCollectOPF( public async estCollectOPF(
address: string, address: string,
poolAddress: string, poolAddress: string,
contractInstance?: Contract contractInstance?: Contract
) :Promise<number>{ ): Promise<number> {
const poolContract = const poolContract =
contractInstance || contractInstance ||
new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress) new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress)
const gasLimitDefault = this.GASLIMIT_DEFAULT const gasLimitDefault = this.GASLIMIT_DEFAULT
let estGas let estGas
try { try {
estGas = await poolContract.methods estGas = await poolContract.methods
.collectOPF() .collectOPF()
.estimateGas({ from: address }, (err, estGas) => (err ? gasLimitDefault : estGas)) .estimateGas({ from: address }, (err, estGas) => (err ? gasLimitDefault : estGas))
} catch (e) { } catch (e) {
estGas = gasLimitDefault estGas = gasLimitDefault
}
return estGas
} }
return estGas
}
/**
/**
* collectOPF - collect opf fee - can be called by anyone * collectOPF - collect opf fee - can be called by anyone
* @param {String} address * @param {String} address
* @param {String} poolAddress * @param {String} poolAddress
* @return {TransactionReceipt} * @return {TransactionReceipt}
*/ */
async collectOPF( async collectOPF(address: string, poolAddress: string): Promise<TransactionReceipt> {
address: string, const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
poolAddress: string let result = null
): Promise<TransactionReceipt> { const estGas = await this.estCollectOPF(address, poolAddress)
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
let result = null
const estGas = await this.estCollectOPF(
address,
poolAddress
)
try {
result = await pool.methods
.collectOPF()
.send({
from: address,
gas: estGas + 1,
gasPrice: await getFairGasPrice(this.web3)
})
} catch (e) {
this.logger.error(`ERROR: Failed to swap exact amount in : ${e.message}`)
}
return result
}
/** try {
result = await pool.methods.collectOPF().send({
from: address,
gas: estGas + 1,
gasPrice: await getFairGasPrice(this.web3)
})
} catch (e) {
this.logger.error(`ERROR: Failed to swap exact amount in : ${e.message}`)
}
return result
}
/**
* Estimate gas cost for collectMarketFee * Estimate gas cost for collectMarketFee
* @param {String} address * @param {String} address
* @param {String} poolAddress * @param {String} poolAddress
@ -539,67 +529,60 @@ export class Pool {
* @param {Contract} contractInstance optional contract instance * @param {Contract} contractInstance optional contract instance
* @return {Promise<number>} * @return {Promise<number>}
*/ */
public async estCollectMarketFee( public async estCollectMarketFee(
address: string, address: string,
poolAddress: string, poolAddress: string,
to:string, to: string,
contractInstance?: Contract contractInstance?: Contract
) :Promise<number>{ ): Promise<number> {
const poolContract = const poolContract =
contractInstance || contractInstance ||
new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress) new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress)
const gasLimitDefault = this.GASLIMIT_DEFAULT const gasLimitDefault = this.GASLIMIT_DEFAULT
let estGas let estGas
try { try {
estGas = await poolContract.methods estGas = await poolContract.methods
.collectMarketFee(to) .collectMarketFee(to)
.estimateGas({ from: address }, (err, estGas) => (err ? gasLimitDefault : estGas)) .estimateGas({ from: address }, (err, estGas) => (err ? gasLimitDefault : estGas))
} catch (e) { } catch (e) {
estGas = gasLimitDefault estGas = gasLimitDefault
}
return estGas
} }
return estGas
}
/**
/**
* collectOPF - collect market fees - can be called by the marketFeeCollector * collectOPF - collect market fees - can be called by the marketFeeCollector
* @param {String} address * @param {String} address
* @param {String} poolAddress * @param {String} poolAddress
* @param {String} to address that will receive fees * @param {String} to address that will receive fees
* @return {TransactionReceipt} * @return {TransactionReceipt}
*/ */
async collectMarketFee( async collectMarketFee(
address: string, address: string,
poolAddress: string, poolAddress: string,
to: string to: string
): Promise<TransactionReceipt> { ): Promise<TransactionReceipt> {
if ((await this.getMarketFeeCollector(poolAddress)) !== address) { if ((await this.getMarketFeeCollector(poolAddress)) !== address) {
throw new Error(`Caller is not MarketFeeCollector`) throw new Error(`Caller is not MarketFeeCollector`)
}
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
let result = null
const estGas = await this.estCollectMarketFee(
address,
poolAddress,
to
)
try {
result = await pool.methods
.collectMarketFee(to)
.send({
from: address,
gas: estGas + 1,
gasPrice: await getFairGasPrice(this.web3)
})
} catch (e) {
this.logger.error(`ERROR: Failed to swap exact amount in : ${e.message}`)
}
return result
} }
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
let result = null
const estGas = await this.estCollectMarketFee(address, poolAddress, to)
/** try {
result = await pool.methods.collectMarketFee(to).send({
from: address,
gas: estGas + 1,
gasPrice: await getFairGasPrice(this.web3)
})
} catch (e) {
this.logger.error(`ERROR: Failed to swap exact amount in : ${e.message}`)
}
return result
}
/**
* Estimate gas cost for collectMarketFee * Estimate gas cost for collectMarketFee
* @param {String} address * @param {String} address
* @param {String} poolAddress * @param {String} poolAddress
@ -607,67 +590,63 @@ export class Pool {
* @param {Contract} contractInstance optional contract instance * @param {Contract} contractInstance optional contract instance
* @return {Promise<number>} * @return {Promise<number>}
*/ */
public async estUpdateMarketFeeCollector( public async estUpdateMarketFeeCollector(
address: string, address: string,
poolAddress: string, poolAddress: string,
newCollector:string, newCollector: string,
contractInstance?: Contract contractInstance?: Contract
) :Promise<number>{ ): Promise<number> {
const poolContract = const poolContract =
contractInstance || contractInstance ||
new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress) new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress)
const gasLimitDefault = this.GASLIMIT_DEFAULT const gasLimitDefault = this.GASLIMIT_DEFAULT
let estGas let estGas
try { try {
estGas = await poolContract.methods estGas = await poolContract.methods
.updateMarketFeeCollector(newCollector) .updateMarketFeeCollector(newCollector)
.estimateGas({ from: address }, (err, estGas) => (err ? gasLimitDefault : estGas)) .estimateGas({ from: address }, (err, estGas) => (err ? gasLimitDefault : estGas))
} catch (e) { } catch (e) {
estGas = gasLimitDefault estGas = gasLimitDefault
} }
return estGas return estGas
} }
/**
/** * updateMarketFeeCollector - updates marketFeeCollector - can be called only by the marketFeeCollector
* updateMarketFeeCollector - updates marketFeeCollector - can be called only by the marketFeeCollector * @param {String} address
* @param {String} address * @param {String} poolAddress
* @param {String} poolAddress * @param {String} newCollector new market fee collector address
* @param {String} newCollector new market fee collector address * @return {TransactionReceipt}
* @return {TransactionReceipt} */
*/ async updateMarketFeeCollector(
async updateMarketFeeCollector( address: string,
address: string, poolAddress: string,
poolAddress: string, newCollector: string
newCollector: string ): Promise<TransactionReceipt> {
): Promise<TransactionReceipt> { if ((await this.getMarketFeeCollector(poolAddress)) !== address) {
if ((await this.getMarketFeeCollector(poolAddress)) !== address) { throw new Error(`Caller is not MarketFeeCollector`)
throw new Error(`Caller is not MarketFeeCollector`) }
} const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress) let result = null
let result = null const estGas = await this.estUpdateMarketFeeCollector(
const estGas = await this.estUpdateMarketFeeCollector( address,
address, poolAddress,
poolAddress, newCollector
newCollector )
)
try {
try { result = await pool.methods.updateMarketFeeCollector(newCollector).send({
result = await pool.methods from: address,
.updateMarketFeeCollector(newCollector) gas: estGas + 1,
.send({ gasPrice: await getFairGasPrice(this.web3)
from: address, })
gas: estGas + 1, } catch (e) {
gasPrice: await getFairGasPrice(this.web3) this.logger.error(`ERROR: Failed to swap exact amount in : ${e.message}`)
}) }
} catch (e) { return result
this.logger.error(`ERROR: Failed to swap exact amount in : ${e.message}`) }
}
return result
}
/** /**
* Estimate gas cost for swapExactAmountIn * Estimate gas cost for swapExactAmountIn
* @param {String} address * @param {String} address
@ -689,7 +668,7 @@ export class Pool {
minAmountOut: string, minAmountOut: string,
maxPrice: string, maxPrice: string,
contractInstance?: Contract contractInstance?: Contract
) :Promise<number>{ ): Promise<number> {
const poolContract = const poolContract =
contractInstance || contractInstance ||
new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress) new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress)
@ -712,7 +691,7 @@ export class Pool {
return estGas return estGas
} }
async amountToUnits(token:string,amount:string):Promise<number>{ async amountToUnits(token: string, amount: string): Promise<number> {
let decimals = 18 let decimals = 18
let amountFormatted let amountFormatted
const tokenContract = new this.web3.eth.Contract( const tokenContract = new this.web3.eth.Contract(
@ -724,15 +703,13 @@ export class Pool {
} catch (e) { } catch (e) {
this.logger.error('ERROR: FAILED TO CALL DECIMALS(), USING 18') this.logger.error('ERROR: FAILED TO CALL DECIMALS(), USING 18')
} }
console.log(decimals,'decimals')
amountFormatted = new BigNumber(parseInt(amount) * 10 ** decimals) amountFormatted = new BigNumber(parseInt(amount) * 10 ** decimals)
return amountFormatted return amountFormatted
} }
async unitsToAmount(token:string,amount:string):Promise<number>{ async unitsToAmount(token: string, amount: string): Promise<number> {
let decimals = 18 let decimals = 18
let amountFormatted let amountFormatted
const tokenContract = new this.web3.eth.Contract( const tokenContract = new this.web3.eth.Contract(
@ -744,12 +721,10 @@ export class Pool {
} catch (e) { } catch (e) {
this.logger.error('ERROR: FAILED TO CALL DECIMALS(), USING 18') this.logger.error('ERROR: FAILED TO CALL DECIMALS(), USING 18')
} }
console.log(decimals,'decimals')
amountFormatted = new BigNumber(parseInt(amount) / 10 ** decimals)
amountFormatted = new BigNumber(parseInt(amount) /(10 ** decimals) )
return amountFormatted return amountFormatted
} }
/** /**
@ -777,43 +752,16 @@ export class Pool {
defaultERC20ABI.abi as AbiItem[], defaultERC20ABI.abi as AbiItem[],
tokenIn tokenIn
) )
let amountInFormatted let amountInFormatted
let minAmountOutFormatted let minAmountOutFormatted
// let tokenInDecimals = 18 amountInFormatted = await this.amountToUnits(tokenIn, tokenAmountIn)
// let tokenOutDecimals = 18
// try { minAmountOutFormatted = await this.amountToUnits(tokenOut, minAmountOut)
// tokenInDecimals = await tokenInContract.methods.decimals().call()
// } catch (e) {
// this.logger.error('ERROR: FAILED TO CALL DECIMALS(), USING 18')
// }
// try {
// tokenOutDecimals = await tokenOutContract.methods.decimals().call()
// } catch (e) {
// this.logger.error('ERROR: FAILED TO CALL DECIMALS(), USING 18')
// }
amountInFormatted = await this.amountToUnits(tokenIn,tokenAmountIn)
console.log(amountInFormatted,'amountinformatted')
//const tokenInDecimals = await tokenInContract.methods.decimals().call()
// if (tokenInDecimals == 18) {
// amountInFormatted = this.web3.utils.toWei(tokenAmountIn)
// } else {
// amountInFormatted = parseInt(tokenAmountIn) * 10 ** tokenInDecimals
// }
minAmountOutFormatted = await this.amountToUnits(tokenOut,minAmountOut)
// console.log(test)
// if (tokenOutDecimals == 18) {
// minAmountOutFormatted = this.web3.utils.toWei(minAmountOut)
// } else {
// minAmountOutFormatted = parseInt(minAmountOut) * 10 ** tokenOutDecimals
// }
// console.log(tokenInDecimals,'tokenin decimals')
// console.log(tokenOutDecimals,'token out decimals')
let result = null let result = null
// TODO: add multiple decimals support
const estGas = await this.estSwapExactAmountIn( const estGas = await this.estSwapExactAmountIn(
address, address,
poolAddress, poolAddress,
@ -823,7 +771,7 @@ export class Pool {
minAmountOutFormatted, minAmountOutFormatted,
maxPrice ? this.web3.utils.toWei(maxPrice) : MaxUint256 maxPrice ? this.web3.utils.toWei(maxPrice) : MaxUint256
) )
console.log(minAmountOutFormatted,'minamoutnoutformatted') console.log(minAmountOutFormatted, 'minamoutnoutformatted')
try { try {
result = await pool.methods result = await pool.methods
.swapExactAmountIn( .swapExactAmountIn(
@ -838,11 +786,10 @@ export class Pool {
gas: estGas + 1, gas: estGas + 1,
gasPrice: await getFairGasPrice(this.web3) gasPrice: await getFairGasPrice(this.web3)
}) })
} catch (e) { } catch (e) {
this.logger.error(`ERROR: Failed to swap exact amount in : ${e.message}`) this.logger.error(`ERROR: Failed to swap exact amount in : ${e.message}`)
} }
return result return result
} }
@ -867,7 +814,7 @@ export class Pool {
amountOut: string, amountOut: string,
maxPrice?: string, maxPrice?: string,
contractInstance?: Contract contractInstance?: Contract
) :Promise<number>{ ): Promise<number> {
const poolContract = const poolContract =
contractInstance || contractInstance ||
new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress) new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress)
@ -912,10 +859,10 @@ export class Pool {
): Promise<TransactionReceipt> { ): Promise<TransactionReceipt> {
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress) const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
let result = null let result = null
let maxAmountInFormatted let maxAmountInFormatted
let amountOutFormatted let amountOutFormatted
maxAmountInFormatted = await this.amountToUnits(tokenIn,maxAmountIn) maxAmountInFormatted = await this.amountToUnits(tokenIn, maxAmountIn)
amountOutFormatted = await this.amountToUnits(tokenOut,amountOut) amountOutFormatted = await this.amountToUnits(tokenOut, amountOut)
const estGas = await this.estSwapExactAmountOut( const estGas = await this.estSwapExactAmountOut(
account, account,
poolAddress, poolAddress,
@ -961,7 +908,7 @@ export class Pool {
poolAmountOut: string, poolAmountOut: string,
maxAmountsIn: string[], maxAmountsIn: string[],
contractInstance?: Contract contractInstance?: Contract
) :Promise<number>{ ): Promise<number> {
const poolContract = const poolContract =
contractInstance || contractInstance ||
new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress) new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress)
@ -995,14 +942,12 @@ export class Pool {
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress) const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
const weiMaxAmountsIn = [] const weiMaxAmountsIn = []
const tokens = await this.getFinalTokens(poolAddress) const tokens = await this.getFinalTokens(poolAddress)
for (let i = 0; i < 2; i++) {
for (let i=0;i<2;i++){ const amount = await this.amountToUnits(tokens[i], maxAmountsIn[i])
const amount = await this.amountToUnits(tokens[i],maxAmountsIn[i])
weiMaxAmountsIn.push(amount) weiMaxAmountsIn.push(amount)
} }
//console.log(weiMaxAmountsIn) // console.log(weiMaxAmountsIn)
let result = null let result = null
@ -1042,7 +987,7 @@ export class Pool {
poolAmountIn: string, poolAmountIn: string,
minAmountsOut: string[], minAmountsOut: string[],
contractInstance?: Contract contractInstance?: Contract
) :Promise<number>{ ): Promise<number> {
const poolContract = const poolContract =
contractInstance || contractInstance ||
new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress) new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress)
@ -1076,10 +1021,9 @@ export class Pool {
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress) const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
const weiMinAmountsOut = [] const weiMinAmountsOut = []
const tokens = await this.getFinalTokens(poolAddress) const tokens = await this.getFinalTokens(poolAddress)
for (let i = 0; i < 2; i++) {
for (let i=0;i<2;i++){ const amount = await this.amountToUnits(tokens[i], minAmountsOut[i])
const amount = await this.amountToUnits(tokens[i],minAmountsOut[i])
weiMinAmountsOut.push(amount) weiMinAmountsOut.push(amount)
} }
let result = null let result = null
@ -1116,7 +1060,7 @@ export class Pool {
tokenAmountIn: string, tokenAmountIn: string,
minPoolAmountOut: string, minPoolAmountOut: string,
contractInstance?: Contract contractInstance?: Contract
) :Promise<number>{ ): Promise<number> {
const poolContract = const poolContract =
contractInstance || contractInstance ||
new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress) new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress)
@ -1152,7 +1096,7 @@ export class Pool {
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress) const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
let result = null let result = null
let amountInFormatted let amountInFormatted
amountInFormatted = await this.amountToUnits(tokenIn,tokenAmountIn) amountInFormatted = await this.amountToUnits(tokenIn, tokenAmountIn)
const estGas = await this.estJoinswapExternAmountIn( const estGas = await this.estJoinswapExternAmountIn(
account, account,
poolAddress, poolAddress,
@ -1197,7 +1141,7 @@ export class Pool {
poolAmountOut: string, poolAmountOut: string,
maxAmountIn: string, maxAmountIn: string,
contractInstance?: Contract contractInstance?: Contract
) :Promise<number>{ ): Promise<number> {
const poolContract = const poolContract =
contractInstance || contractInstance ||
new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress) new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress)
@ -1214,8 +1158,6 @@ export class Pool {
return estGas return estGas
} }
/** /**
* Specify poolAmountOut pool shares that you want to get, and a token tokenIn to pay with. This costs tokenAmountIn tokens (these went into the pool). * Specify poolAmountOut pool shares that you want to get, and a token tokenIn to pay with. This costs tokenAmountIn tokens (these went into the pool).
* @param {String} account * @param {String} account
@ -1235,7 +1177,7 @@ export class Pool {
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress) const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
let result = null let result = null
let maxAmountInFormatted let maxAmountInFormatted
maxAmountInFormatted = await this.amountToUnits(tokenIn,maxAmountIn) maxAmountInFormatted = await this.amountToUnits(tokenIn, maxAmountIn)
const estGas = await this.estJoinswapPoolAmountOut( const estGas = await this.estJoinswapPoolAmountOut(
account, account,
poolAddress, poolAddress,
@ -1278,7 +1220,7 @@ export class Pool {
poolAmountIn: string, poolAmountIn: string,
minTokenAmountOut: string, minTokenAmountOut: string,
contractInstance?: Contract contractInstance?: Contract
) :Promise<number>{ ): Promise<number> {
const poolContract = const poolContract =
contractInstance || contractInstance ||
new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress) new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress)
@ -1313,8 +1255,8 @@ export class Pool {
): Promise<TransactionReceipt> { ): Promise<TransactionReceipt> {
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress) const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
let result = null let result = null
let minTokenOutFormatted let minTokenOutFormatted
minTokenOutFormatted = await this.amountToUnits(tokenOut,minTokenAmountOut) minTokenOutFormatted = await this.amountToUnits(tokenOut, minTokenAmountOut)
const estGas = await this.estExitswapPoolAmountIn( const estGas = await this.estExitswapPoolAmountIn(
account, account,
poolAddress, poolAddress,
@ -1341,15 +1283,15 @@ export class Pool {
} }
/** /**
* Estimate gas cost for joinswapExternAmountIn * Estimate gas cost for joinswapExternAmountIn
* @param {String} address * @param {String} address
* @param {String} poolAddress * @param {String} poolAddress
* @param {String} tokenOut * @param {String} tokenOut
* @param {String} tokenAmountOut will be converted to wei * @param {String} tokenAmountOut will be converted to wei
* @param {String} maxPoolAmountIn will be converted to wei * @param {String} maxPoolAmountIn will be converted to wei
* @param {Contract} contractInstance optional contract instance * @param {Contract} contractInstance optional contract instance
* @return {Promise<number>} * @return {Promise<number>}
*/ */
public async estExitswapExternAmountOut( public async estExitswapExternAmountOut(
address: string, address: string,
poolAddress: string, poolAddress: string,
@ -1357,7 +1299,7 @@ export class Pool {
tokenAmountOut: string, tokenAmountOut: string,
maxPoolAmountIn: string, maxPoolAmountIn: string,
contractInstance?: Contract contractInstance?: Contract
) :Promise<number>{ ): Promise<number> {
const poolContract = const poolContract =
contractInstance || contractInstance ||
new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress) new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress)
@ -1431,42 +1373,52 @@ export class Pool {
tokenOut: string tokenOut: string
): Promise<string> { ): Promise<string> {
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress) const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
let decimalsTokenIn = 18
let decimalsTokenOut = 18
const tokenInContract = new this.web3.eth.Contract(
defaultERC20ABI.abi as AbiItem[],
tokenIn
)
const tokenOutContract = new this.web3.eth.Contract(
defaultERC20ABI.abi as AbiItem[],
tokenOut
)
try {
decimalsTokenIn = await tokenInContract.methods.decimals().call()
} catch (e) {
this.logger.error('ERROR: FAILED TO CALL DECIMALS(), USING 18')
}
try {
decimalsTokenOut = await tokenOutContract.methods.decimals().call()
} catch (e) {
this.logger.error('ERROR: FAILED TO CALL DECIMALS(), USING 18')
}
let price = null let price = null
try { try {
const result = await pool.methods.getSpotPrice(tokenIn, tokenOut).call() price = await pool.methods.getSpotPrice(tokenIn, tokenOut).call()
price = this.web3.utils.fromWei(result) price = new BigNumber(price.toString())
} catch (e) { } catch (e) {
this.logger.error('ERROR: Failed to get spot price of swapping tokenIn to tokenOut') this.logger.error('ERROR: Failed to get spot price of swapping tokenIn to tokenOut')
} }
return price
}
// public async calcSpotPrice( let decimalsDiff
// poolAddress: string, if (decimalsTokenIn > decimalsTokenOut) {
// tokenBalanceIn: string, decimalsDiff = decimalsTokenIn - decimalsTokenOut
// tokenWeightIn: string, price = new BigNumber(price / 10 ** decimalsDiff)
// tokenBalanceOut: string, // console.log(price.toString())
// tokenWeightOut: string, price = price / 10 ** decimalsTokenOut
// swapFee: string // console.log('dtIn')
// ): Promise<string> { } else {
// const pool = new this.web3.eth.Contract(this.poolABI, poolAddress) decimalsDiff = decimalsTokenOut - decimalsTokenIn
// let amount = '0' price = new BigNumber(price * 10 ** (2 * decimalsDiff))
// try { price = price / 10 ** decimalsTokenOut
// const result = await pool.methods // console.log('usdcIn')
// .calcSpotPrice( }
// this.web3.utils.toWei(tokenBalanceIn),
// this.web3.utils.toWei(tokenWeightIn), return price.toString()
// this.web3.utils.toWei(tokenBalanceOut), }
// this.web3.utils.toWei(tokenWeightOut),
// this.web3.utils.toWei(swapFee)
// )
// .call()
// amount = this.web3.utils.fromWei(result)
// } catch (e) {
// this.logger.error('ERROR: Failed to call calcSpotPrice')
// }
// return amount
// }
public async getAmountInExactOut( public async getAmountInExactOut(
poolAddress: string, poolAddress: string,
@ -1476,14 +1428,15 @@ export class Pool {
): Promise<string> { ): Promise<string> {
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress) const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
let amountOutFormatted let amountOutFormatted
amountOutFormatted = await this.amountToUnits(tokenOut,tokenAmountOut) amountOutFormatted = await this.amountToUnits(tokenOut, tokenAmountOut)
let amount = null let amount = null
// if (new Decimal(tokenAmountOut).gte(tokenBalanceOut)) return null
try { try {
const result = await pool.methods const result = await pool.methods
.getAmountInExactOut(tokenIn, tokenOut,amountOutFormatted) .getAmountInExactOut(tokenIn, tokenOut, amountOutFormatted)
.call() .call()
amount = await this.unitsToAmount(tokenIn,result) amount = await this.unitsToAmount(tokenIn, result)
} catch (e) { } catch (e) {
this.logger.error('ERROR: Failed to calcInGivenOut') this.logger.error('ERROR: Failed to calcInGivenOut')
} }
@ -1496,34 +1449,18 @@ export class Pool {
tokenOut: string, tokenOut: string,
tokenAmountIn: string tokenAmountIn: string
): Promise<string> { ): Promise<string> {
// TODO: solve decimals issue FIRST
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress) const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
const tokenInContract = new this.web3.eth.Contract(
defaultERC20ABI.abi as AbiItem[],
tokenIn
)
let amountInFormatted let amountInFormatted
amountInFormatted = await this.amountToUnits(tokenIn,tokenAmountIn) amountInFormatted = await this.amountToUnits(tokenIn, tokenAmountIn)
// let tokenInDecimals = 18
// try {
// tokenInDecimals = await tokenInContract.methods.decimals().call()
// } catch (e) {
// this.logger.error('ERROR: FAILED TO CALL DECIMALS(), USING 18')
// }
// //const tokenInDecimals = await tokenInContract.methods.decimals().call()
// if (tokenInDecimals == 18) {
// amountInFormatted = this.web3.utils.toWei(tokenAmountIn)
// } else {
// amountInFormatted = parseInt(tokenAmountIn) * 10 ** tokenInDecimals
// }
let amount = null let amount = null
console.log(amountInFormatted) // console.log(amountInFormatted)
try { try {
const result = await pool.methods const result = await pool.methods
.getAmountOutExactIn(tokenIn, tokenOut, amountInFormatted) .getAmountOutExactIn(tokenIn, tokenOut, amountInFormatted)
.call() .call()
amount = await this.unitsToAmount(tokenOut,result) amount = await this.unitsToAmount(tokenOut, result)
} catch (e) { } catch (e) {
this.logger.error('ERROR: Failed to calcOutGivenIn') this.logger.error('ERROR: Failed to calcOutGivenIn')
} }

View File

@ -3,7 +3,6 @@ import { Contract } from 'web3-eth-contract'
import { AbiItem } from 'web3-utils/types' import { AbiItem } from 'web3-utils/types'
import MockERC20 from '@oceanprotocol/contracts/artifacts/contracts/utils/mock/MockERC20Decimals.sol/MockERC20Decimals.json' import MockERC20 from '@oceanprotocol/contracts/artifacts/contracts/utils/mock/MockERC20Decimals.sol/MockERC20Decimals.json'
const oceanAddress = '0x967da4048cd07ab37855c090aaf366e4ce1b9f48' const oceanAddress = '0x967da4048cd07ab37855c090aaf366e4ce1b9f48'
export class TestContractHandler { export class TestContractHandler {
public accounts: string[] public accounts: string[]
@ -30,7 +29,6 @@ export class TestContractHandler {
public OPFCollectorBytecode: string public OPFCollectorBytecode: string
public MockERC20Bytecode: string public MockERC20Bytecode: string
public OPFBytecode: string public OPFBytecode: string
public factory721Address: string public factory721Address: string
public template721Address: string public template721Address: string
@ -56,7 +54,7 @@ export class TestContractHandler {
SideStakingABI?: AbiItem | AbiItem[], SideStakingABI?: AbiItem | AbiItem[],
FixedRateABI?: AbiItem | AbiItem[], FixedRateABI?: AbiItem | AbiItem[],
DispenserABI?: AbiItem | AbiItem[], DispenserABI?: AbiItem | AbiItem[],
OPFABI?: AbiItem | AbiItem[], OPFABI?: AbiItem | AbiItem[],
template721Bytecode?: string, template721Bytecode?: string,
template20Bytecode?: string, template20Bytecode?: string,
@ -66,7 +64,7 @@ export class TestContractHandler {
sideStakingBytecode?: string, sideStakingBytecode?: string,
fixedRateBytecode?: string, fixedRateBytecode?: string,
dispenserBytecode?: string, dispenserBytecode?: string,
opfBytecode?:string opfBytecode?: string
) { ) {
this.web3 = web3 this.web3 = web3
this.ERC721Template = new this.web3.eth.Contract(ERC721TemplateABI) this.ERC721Template = new this.web3.eth.Contract(ERC721TemplateABI)
@ -104,7 +102,7 @@ export class TestContractHandler {
// get est gascost // get est gascost
estGas = await this.OPFCollector.deploy({ estGas = await this.OPFCollector.deploy({
data: this.OPFBytecode, data: this.OPFBytecode,
arguments: [owner,owner] arguments: [owner, owner]
}).estimateGas(function (err, estGas) { }).estimateGas(function (err, estGas) {
if (err) console.log('DeployContracts: ' + err) if (err) console.log('DeployContracts: ' + err)
return estGas return estGas
@ -112,7 +110,7 @@ export class TestContractHandler {
// deploy the contract and get it's address // deploy the contract and get it's address
this.opfCollectorAddress = await this.OPFCollector.deploy({ this.opfCollectorAddress = await this.OPFCollector.deploy({
data: this.OPFBytecode, data: this.OPFBytecode,
arguments: [owner,owner] arguments: [owner, owner]
}) })
.send({ .send({
from: owner, from: owner,
@ -123,7 +121,6 @@ export class TestContractHandler {
return contract.options.address return contract.options.address
}) })
// DEPLOY POOL TEMPLATE // DEPLOY POOL TEMPLATE
// get est gascost // get est gascost
estGas = await this.PoolTemplate.deploy({ estGas = await this.PoolTemplate.deploy({

File diff suppressed because it is too large Load Diff