Skip to content

Commit

Permalink
Merge pull request #389 from oceanprotocol/feature/subscribe_features
Browse files Browse the repository at this point in the history
make create methods subscribable
  • Loading branch information
kremalicious authored Oct 21, 2020
2 parents d21c3c6 + 4db0a0d commit 616e67d
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 92 deletions.
106 changes: 62 additions & 44 deletions src/balancer/OceanPool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { TransactionReceipt } from 'web3-core'
import { Pool } from './Pool'
import { EventData, Filter } from 'web3-eth-contract'
import BigNumber from 'bignumber.js'

import { SubscribablePromise } from '../utils'
declare type PoolTransactionType = 'swap' | 'join' | 'exit'

const POOL_MAX_AMOUNT_IN_LIMIT = 0.25 // maximum 1/4 of the pool reserve
Expand Down Expand Up @@ -34,6 +34,13 @@ export interface PoolTransaction {
type: PoolTransactionType
}

export enum PoolCreateProgressStep {
CreatingPool,
ApprovingDatatoken,
ApprovingOcean,
SetupPool
}

/**
* Ocean Pools submodule exposed under ocean.pool
*/
Expand Down Expand Up @@ -64,13 +71,13 @@ export class OceanPool extends Pool {
* @param {String} fee Swap fee. E.g. to get a 0.1% swapFee use `0.001`. The maximum allowed swapFee is `0.1` (10%).
* @return {String}
*/
public async createDTPool(
public create(
account: string,
token: string,
amount: string,
weight: string,
fee: string
): Promise<string> {
): SubscribablePromise<PoolCreateProgressStep, TransactionReceipt> {
if (this.oceanAddress == null) {
console.error('ERROR: oceanAddress is not defined')
return null
Expand All @@ -83,47 +90,58 @@ export class OceanPool extends Pool {
console.error('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
let txid
txid = await this.approve(
account,
token,
address,
this.web3.utils.toWei(String(amount))
)
if (!txid) {
console.error('ERROR: Failed to call approve DT token')
return null
}
txid = await this.approve(
account,
this.oceanAddress,
address,
this.web3.utils.toWei(String(oceanAmount))
)
if (!txid) {
console.error('ERROR: Failed to call approve OCEAN token')
return null
}
txid = 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)
)
if (!txid) {
console.error('ERROR: Failed to create a new pool')
return null
}
return address
return new SubscribablePromise(async (observer) => {
observer.next(PoolCreateProgressStep.CreatingPool)
const createTxid = await super.createPool(account)
if (!createTxid) {
console.error('ERROR: Failed to call approve DT token')
return null
}
const address = createTxid.events.BPoolRegistered.returnValues[0]
const oceanWeight = 10 - parseFloat(weight)
const oceanAmount = (parseFloat(amount) * oceanWeight) / parseFloat(weight)
this.dtAddress = token
observer.next(PoolCreateProgressStep.ApprovingDatatoken)
let txid
txid = await this.approve(
account,
token,
address,
this.web3.utils.toWei(String(amount))
)
if (!txid) {
console.error('ERROR: Failed to call approve DT token')
return null
}
observer.next(PoolCreateProgressStep.ApprovingOcean)
txid = await this.approve(
account,
this.oceanAddress,
address,
this.web3.utils.toWei(String(oceanAmount))
)
if (!txid) {
console.error('ERROR: Failed to call approve OCEAN token')
return null
}
observer.next(PoolCreateProgressStep.SetupPool)
txid = 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)
)
if (!txid) {
console.error('ERROR: Failed to create a new pool')
return null
}
return createTxid
})
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/balancer/Pool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export class Pool extends PoolFactory {
/**
* Creates a new pool
*/
async createPool(account: string): Promise<string> {
async createPool(account: string): Promise<TransactionReceipt> {
return await super.createPool(account)
}

Expand Down
18 changes: 8 additions & 10 deletions src/balancer/PoolFactory.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Web3 from 'web3'
import { AbiItem } from 'web3-utils/types'
import jsonFactoryABI from '@oceanprotocol/contracts/artifacts/BFactory.json'
import { TransactionReceipt } from 'web3-core'

export class PoolFactory {
public GASLIMIT_DEFAULT = 5000000
Expand All @@ -27,7 +28,7 @@ export class PoolFactory {
/**
* Creates a new pool
*/
async createPool(account: string): Promise<string> {
async createPool(account: string): Promise<TransactionReceipt> {
if (this.web3 === null) {
console.error('ERROR: Web3 object is null')
return null
Expand All @@ -41,18 +42,15 @@ export class PoolFactory {
const factory = new this.web3.eth.Contract(this.factoryABI, this.factoryAddress, {
from: account
})

const transactiondata = await factory.methods
.newBPool()
.send({ from: account, gas: this.GASLIMIT_DEFAULT })

let pooladdress: string

let txid = null
try {
pooladdress = transactiondata.events.BPoolRegistered.returnValues[0]
txid = await factory.methods
.newBPool()
.send({ from: account, gas: this.GASLIMIT_DEFAULT })
// pooladdress = transactiondata.events.BPoolRegistered.returnValues[0]
} catch (e) {
console.error(`ERROR: Failed to create new pool: ${e.message}`)
}
return pooladdress
return txid
}
}
90 changes: 57 additions & 33 deletions src/exchange/FixedRateExchange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { TransactionReceipt } from 'web3-core'
import { Contract, EventData } from 'web3-eth-contract'
import { AbiItem } from 'web3-utils/types'
import Web3 from 'web3'
import { SubscribablePromise } from '../utils'
import { DataTokens } from '../datatokens/Datatokens'

export interface FixedPriceExchange {
exchangeID?: string
Expand All @@ -21,6 +23,12 @@ export interface FixedPriceSwap {
baseTokenAmount: string
dataTokenAmount: string
}

export enum FixedRateCreateProgressStep {
CreatingExchange,
ApprovingDatatoken
}

const DEFAULT_GAS_LIMIT = 300000

export class OceanFixedRateExchange {
Expand All @@ -30,6 +38,7 @@ export class OceanFixedRateExchange {
public fixedRateExchangeABI: AbiItem | AbiItem[]
public web3: Web3
public contract: Contract = null
public datatokens: DataTokens

/**
* Instantiate FixedRateExchange
Expand All @@ -42,13 +51,15 @@ export class OceanFixedRateExchange {
web3: Web3,
fixedRateExchangeAddress: string = null,
fixedRateExchangeABI: AbiItem | AbiItem[] = null,
oceanAddress: string = null
oceanAddress: string = null,
datatokens: DataTokens
) {
this.web3 = web3
this.fixedRateExchangeAddress = fixedRateExchangeAddress
this.fixedRateExchangeABI =
fixedRateExchangeABI || (defaultFixedRateExchangeABI.abi as AbiItem[])
this.oceanAddress = oceanAddress
this.datatokens = datatokens
if (web3)
this.contract = new this.web3.eth.Contract(
this.fixedRateExchangeABI,
Expand All @@ -61,39 +72,52 @@ export class OceanFixedRateExchange {
* @param {String} dataToken Data Token Contract Address
* @param {Number} rate exchange rate
* @param {String} address User address
* @return {Promise<string>} exchangeId
* @param {String} amount Optional, amount of datatokens to be approved for the exchange
* @return {Promise<TransactionReceipt>} TransactionReceipt
*/
public async create(dataToken: string, rate: string, address: string): Promise<string> {
let estGas
try {
/* estGas = await this.contract.methods
.create(this.oceanAddress, dataToken, this.web3.utils.toWei(rate))
.estimateGas(function (err, g) {
if (err) {
return DEFAULT_GAS_LIMIT
} else {
return g
}
})
*/
estGas = DEFAULT_GAS_LIMIT
} catch (e) {
estGas = DEFAULT_GAS_LIMIT
}

let exchangeId = null
try {
const trxReceipt = await this.contract.methods
.create(this.oceanAddress, dataToken, this.web3.utils.toWei(rate))
.send({
from: address,
gas: estGas + 1
})
exchangeId = trxReceipt.events.ExchangeCreated.returnValues[0]
} catch (e) {
console.error(`ERROR: Failed to create new exchange: ${e.message}`)
}
return exchangeId
public create(
dataToken: string,
rate: string,
address: string,
amount?: string
): SubscribablePromise<FixedRateCreateProgressStep, TransactionReceipt> {
return new SubscribablePromise(async (observer) => {
observer.next(FixedRateCreateProgressStep.CreatingExchange)
let estGas
try {
/* estGas = await this.contract.methods
.create(this.oceanAddress, dataToken, this.web3.utils.toWei(rate))
.estimateGas(function (err, g) {
if (err) {
return DEFAULT_GAS_LIMIT
} else {
return g
}
})
*/
estGas = DEFAULT_GAS_LIMIT
} catch (e) {
estGas = DEFAULT_GAS_LIMIT
}
let exchangeId = null
let trxReceipt = null
try {
trxReceipt = await this.contract.methods
.create(this.oceanAddress, dataToken, this.web3.utils.toWei(rate))
.send({
from: address,
gas: estGas + 1
})
exchangeId = trxReceipt.events.ExchangeCreated.returnValues[0]
} catch (e) {
console.error(`ERROR: Failed to create new exchange: ${e.message}`)
}
if (amount && exchangeId) {
observer.next(FixedRateCreateProgressStep.ApprovingDatatoken)
this.datatokens.approve(dataToken, this.fixedRateExchangeAddress, amount, address)
}
return trxReceipt
})
}

/**
Expand Down
3 changes: 2 additions & 1 deletion src/ocean/Ocean.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ export class Ocean extends Instantiable {
instanceConfig.config.web3Provider,
instanceConfig.config.fixedRateExchangeAddress,
instanceConfig.config.fixedRateExchangeAddressABI,
instanceConfig.config.oceanTokenAddress
instanceConfig.config.oceanTokenAddress,
instance.datatokens
)
instance.OnChainMetadataCache = new OnChainMetadataCache(
instanceConfig.config.web3Provider,
Expand Down
3 changes: 2 additions & 1 deletion test/unit/balancer/Balancer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ describe('Balancer flow', () => {
})
it('Alice creates a new OceanPool pool', async () => {
/// new pool with total DT = 45 , dt weight=90% with swap fee 2%
alicePoolAddress = await Pool.createDTPool(alice, tokenAddress, '45', '9', '0.02')
const createTx = await Pool.create(alice, tokenAddress, '45', '9', '0.02')
alicePoolAddress = createTx.events.BPoolRegistered.returnValues[0]
const s = await Pool.getPoolSharesTotalSupply(alicePoolAddress)
assert(String(s) === '100', 'totalSupply does not match: ' + s)
const n = await Pool.getNumTokens(alicePoolAddress)
Expand Down
6 changes: 4 additions & 2 deletions test/unit/exchanges/FixedPriceExchange.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@ describe('FixedRateExchange flow', () => {
web3,
FixedRateExchangeAddress,
FixedRateExchangeContract.abi as AbiItem[],
oceanTokenAddress
oceanTokenAddress,
datatoken
)
assert(FixedRateClass !== null)
})
Expand Down Expand Up @@ -167,7 +168,8 @@ describe('FixedRateExchange flow', () => {
if (consoleDebug) console.log('Bob ocean allowance:' + balance)
})
it('Alice creates a new FixedRate Exchange with a rate of 0.5', async () => {
aliceExchangeId = await FixedRateClass.create(tokenAddress, fixedPriceRate, alice)
const trxReceipt = await FixedRateClass.create(tokenAddress, fixedPriceRate, alice)
aliceExchangeId = trxReceipt.events.ExchangeCreated.returnValues[0]
if (consoleDebug) console.log('aliceExchangeId:' + aliceExchangeId)
})
it('Bob should find the exchange', async () => {
Expand Down

0 comments on commit 616e67d

Please sign in to comment.