mirror of
https://github.com/oceanprotocol/ocean.js.git
synced 2024-11-26 20:39:05 +01:00
380 lines
9.7 KiB
TypeScript
380 lines
9.7 KiB
TypeScript
import Web3 from 'web3'
|
|
import { AbiItem } from 'web3-utils/types'
|
|
import { TransactionReceipt } from 'web3-core'
|
|
import { Pool } from './Pool'
|
|
|
|
/**
|
|
* Ocean Pools submodule exposed under ocean.pool
|
|
*/
|
|
export class OceanPool extends Pool {
|
|
public oceanAddress: string = null
|
|
public dtAddress: string = null
|
|
|
|
constructor(
|
|
web3: Web3,
|
|
factoryABI: AbiItem | AbiItem[] = null,
|
|
poolABI: AbiItem | AbiItem[] = null,
|
|
factoryAddress: string = null,
|
|
oceanAddress: string = null,
|
|
gaslimit?: number
|
|
) {
|
|
super(web3, factoryABI, poolABI, factoryAddress, gaslimit)
|
|
if (oceanAddress) {
|
|
this.oceanAddress = oceanAddress
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create DataToken pool
|
|
@param {String} account
|
|
* @param {String} token DataToken address
|
|
* @param {String} amount DataToken amount
|
|
* @param {String} weight DataToken weight
|
|
* @param {String} fee Swap fee (as float)
|
|
* @return {String}
|
|
*/
|
|
public async createDTPool(
|
|
account: string,
|
|
token: string,
|
|
amount: string,
|
|
weight: string,
|
|
fee: string
|
|
): Promise<string> {
|
|
if (this.oceanAddress == null) {
|
|
console.error('oceanAddress is not defined')
|
|
return null
|
|
}
|
|
if (parseFloat(weight) > 9 || parseFloat(weight) < 1) {
|
|
console.error('Weight out of bounds (min 1, max9)')
|
|
return null
|
|
}
|
|
const address = await super.createPool(account)
|
|
const oceanWeight = 10 - parseFloat(weight)
|
|
const oceanAmount = (parseFloat(amount) * oceanWeight) / parseFloat(weight)
|
|
this.dtAddress = token
|
|
|
|
await this.approve(
|
|
account,
|
|
token,
|
|
address,
|
|
this.web3.utils.toWei(String(amount)) as any
|
|
)
|
|
await this.approve(
|
|
account,
|
|
this.oceanAddress,
|
|
address,
|
|
this.web3.utils.toWei(String(oceanAmount)) as any
|
|
)
|
|
|
|
await super.setup(
|
|
account,
|
|
address,
|
|
token,
|
|
this.web3.utils.toWei(String(amount)),
|
|
this.web3.utils.toWei(String(weight)),
|
|
this.oceanAddress,
|
|
this.web3.utils.toWei(String(oceanAmount)),
|
|
this.web3.utils.toWei(String(oceanWeight)),
|
|
this.web3.utils.toWei(fee)
|
|
)
|
|
|
|
return address
|
|
}
|
|
|
|
/**
|
|
* Get DataToken address of token in this pool
|
|
* @param {String} account
|
|
* @param {String} poolAddress
|
|
* @return {string}
|
|
*/
|
|
public async getDTAddress(account: string, poolAddress: string): Promise<string> {
|
|
this.dtAddress = null
|
|
const tokens = await this.getCurrentTokens(account, poolAddress)
|
|
let token
|
|
for (token of tokens) {
|
|
// TODO: Potential timing attack, left side: true
|
|
if (token !== this.oceanAddress) this.dtAddress = token
|
|
}
|
|
return this.dtAddress
|
|
}
|
|
|
|
/**
|
|
* Get Ocean Token balance of a pool
|
|
* @param {String} account
|
|
* @param {String} poolAddress
|
|
* @return {String}
|
|
*/
|
|
public async getOceanReserve(account: string, poolAddress: string): Promise<string> {
|
|
if (this.oceanAddress == null) {
|
|
console.error('oceanAddress is not defined')
|
|
return null
|
|
}
|
|
return super.getReserve(account, poolAddress, this.oceanAddress)
|
|
}
|
|
|
|
/**
|
|
* Get Data Token balance of a pool
|
|
* @param {String} account
|
|
* @param {String} poolAddress
|
|
* @return {String}
|
|
*/
|
|
public async getDTReserve(account: string, poolAddress: string): Promise<string> {
|
|
await this.getDTAddress(account, poolAddress)
|
|
return super.getReserve(account, poolAddress, this.dtAddress)
|
|
}
|
|
|
|
/**
|
|
* Buy Data Token from a pool
|
|
* @param {String} account
|
|
* @param {String} poolAddress
|
|
* @param {String} amount Data Token amount
|
|
* @param {String} oceanAmount Ocean Token amount payed
|
|
* @param {String} maxPrice Maximum price to pay
|
|
* @return {any}
|
|
*/
|
|
public async buyDT(
|
|
account: string,
|
|
poolAddress: string,
|
|
amount: string,
|
|
oceanAmount: string,
|
|
maxPrice: string
|
|
): Promise<any> {
|
|
if (this.oceanAddress == null) {
|
|
console.error('oceanAddress is not defined')
|
|
return null
|
|
}
|
|
await this.getDTAddress(account, poolAddress)
|
|
|
|
// TODO - check balances first
|
|
await super.approve(
|
|
account,
|
|
this.oceanAddress,
|
|
poolAddress,
|
|
this.web3.utils.toWei(oceanAmount)
|
|
)
|
|
|
|
return this.swapExactAmountOut(
|
|
account,
|
|
poolAddress,
|
|
this.oceanAddress,
|
|
oceanAmount,
|
|
this.dtAddress,
|
|
amount,
|
|
maxPrice
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Sell Data Token
|
|
* @param {String} account
|
|
* @param {String} poolAddress
|
|
* @param {String} amount Data Token amount
|
|
* @param {String} oceanAmount Ocean Token amount expected
|
|
* @param {String} maxPrice Minimum price to sell
|
|
* @return {TransactionReceipt}
|
|
*/
|
|
public async sellDT(
|
|
account: string,
|
|
poolAddress: string,
|
|
amount: string,
|
|
oceanAmount: string,
|
|
minPrice: string
|
|
): Promise<TransactionReceipt> {
|
|
if (this.oceanAddress == null) {
|
|
console.error('oceanAddress is not defined')
|
|
return null
|
|
}
|
|
await this.getDTAddress(account, poolAddress)
|
|
return this.swapExactAmountOut(
|
|
account,
|
|
poolAddress,
|
|
this.dtAddress,
|
|
amount,
|
|
this.oceanAddress,
|
|
oceanAmount,
|
|
minPrice
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Add Data Token amount to pool liquidity
|
|
* @param {String} account
|
|
* @param {String} poolAddress
|
|
* @param {String} amount Data Token amount
|
|
* @return {TransactionReceipt}
|
|
*/
|
|
public async addDTLiquidity(
|
|
account: string,
|
|
poolAddress: string,
|
|
amount: string
|
|
): Promise<TransactionReceipt> {
|
|
await this.getDTAddress(account, poolAddress)
|
|
await super.approve(
|
|
account,
|
|
this.dtAddress,
|
|
poolAddress,
|
|
this.web3.utils.toWei(amount)
|
|
)
|
|
const result = await super.joinswapExternAmountIn(
|
|
account,
|
|
poolAddress,
|
|
this.dtAddress,
|
|
amount,
|
|
'0'
|
|
)
|
|
return result
|
|
}
|
|
|
|
/**
|
|
* Remove Data Token amount from pool liquidity
|
|
* @param {String} account
|
|
* @param {String} poolAddress
|
|
* @param {String} amount Data Token amount
|
|
* @return {TransactionReceipt}
|
|
*/
|
|
public async removeDTLiquidity(
|
|
account: string,
|
|
poolAddress: string,
|
|
amount: string,
|
|
maximumPoolShares: string
|
|
): Promise<TransactionReceipt> {
|
|
await this.getDTAddress(account, poolAddress)
|
|
// TODO Check balance of PoolShares before doing exit
|
|
return this.exitswapExternAmountOut(
|
|
account,
|
|
poolAddress,
|
|
this.dtAddress,
|
|
amount,
|
|
maximumPoolShares
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Add Ocean Token amount to pool liquidity
|
|
* @param {String} account
|
|
* @param {String} poolAddress
|
|
* @param {String} amount Ocean Token amount in OCEAN
|
|
* @return {TransactionReceipt}
|
|
*/
|
|
public async addOceanLiquidity(
|
|
account: string,
|
|
poolAddress: string,
|
|
amount: string
|
|
): Promise<TransactionReceipt> {
|
|
if (this.oceanAddress == null) {
|
|
console.error('oceanAddress is not defined')
|
|
return null
|
|
}
|
|
await super.approve(
|
|
account,
|
|
this.oceanAddress,
|
|
poolAddress,
|
|
this.web3.utils.toWei(amount)
|
|
)
|
|
const result = await super.joinswapExternAmountIn(
|
|
account,
|
|
poolAddress,
|
|
this.oceanAddress,
|
|
amount,
|
|
'0'
|
|
)
|
|
return result
|
|
}
|
|
|
|
/**
|
|
* Remove Ocean Token amount from pool liquidity
|
|
* @param {String} account
|
|
* @param {String} poolAddress
|
|
* @param {String} amount Ocean Token amount in OCEAN
|
|
* @return {TransactionReceipt}
|
|
*/
|
|
public removeOceanLiquidity(
|
|
account: string,
|
|
poolAddress: string,
|
|
amount: string,
|
|
maximumPoolShares: string
|
|
): Promise<TransactionReceipt> {
|
|
if (this.oceanAddress == null) {
|
|
console.error('oceanAddress is not defined')
|
|
return null
|
|
}
|
|
// TODO Check balance of PoolShares before doing exit
|
|
return super.exitswapExternAmountOut(
|
|
account,
|
|
poolAddress,
|
|
this.oceanAddress,
|
|
amount,
|
|
maximumPoolShares
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Get Data Token price from pool
|
|
* @param {String} account
|
|
* @param {String} poolAddress
|
|
* @return {String}
|
|
*/
|
|
public async getDTPrice(account: string, poolAddress: string): Promise<string> {
|
|
if (this.oceanAddress == null) {
|
|
console.error('oceanAddress is not defined')
|
|
return null
|
|
}
|
|
return this.getOceanNeeded(account, poolAddress, '1')
|
|
}
|
|
|
|
/**
|
|
* Search all pools that have Data Token in their composition
|
|
* @param {String} account
|
|
* @param {String} dtAddress
|
|
* @return {String[]}
|
|
*/
|
|
public async searchPoolforDT(account: string, dtAddress: string): Promise<string[]> {
|
|
const result: string[] = []
|
|
const factory = new this.web3.eth.Contract(this.factoryABI, this.factoryAddress, {
|
|
from: account
|
|
})
|
|
const events = await factory.getPastEvents('BPoolRegistered', {
|
|
filter: {},
|
|
fromBlock: 0,
|
|
toBlock: 'latest'
|
|
})
|
|
for (let i = 0; i < events.length; i++) {
|
|
const constituents = await super.getCurrentTokens(
|
|
account,
|
|
events[i].returnValues[0]
|
|
)
|
|
if (constituents.includes(dtAddress)) result.push(events[i].returnValues[0])
|
|
}
|
|
return result
|
|
}
|
|
|
|
public async getOceanNeeded(
|
|
account: string,
|
|
poolAddress: string,
|
|
dtRequired: string
|
|
): Promise<string> {
|
|
await this.getDTAddress(account, poolAddress)
|
|
const tokenBalanceIn = await this.getReserve(account, poolAddress, this.oceanAddress)
|
|
const tokenWeightIn = await this.getDenormalizedWeight(
|
|
account,
|
|
poolAddress,
|
|
this.oceanAddress
|
|
)
|
|
const tokenBalanceOut = await this.getReserve(account, poolAddress, this.dtAddress)
|
|
const tokenWeightOut = await this.getDenormalizedWeight(
|
|
account,
|
|
poolAddress,
|
|
this.dtAddress
|
|
)
|
|
const swapFee = await this.getSwapFee(account, poolAddress)
|
|
return super.calcInGivenOut(
|
|
tokenBalanceIn,
|
|
tokenWeightIn,
|
|
tokenBalanceOut,
|
|
tokenWeightOut,
|
|
dtRequired,
|
|
swapFee
|
|
)
|
|
}
|
|
}
|