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

first cut, tests are failing

This commit is contained in:
alexcos20 2020-08-27 03:29:00 -07:00
parent 0968638f9c
commit cc6cf435fe
7 changed files with 617 additions and 4 deletions

View File

@ -40,7 +40,7 @@
}, },
"dependencies": { "dependencies": {
"@ethereum-navigator/navigator": "^0.5.0", "@ethereum-navigator/navigator": "^0.5.0",
"@oceanprotocol/contracts": "^0.3.4", "@oceanprotocol/contracts": "^0.3.5",
"decimal.js": "^10.2.0", "decimal.js": "^10.2.0",
"fs": "0.0.1-security", "fs": "0.0.1-security",
"node-fetch": "^2.6.0", "node-fetch": "^2.6.0",

View File

@ -0,0 +1,233 @@
const defaultFixedRateExchangeABI = require('@oceanprotocol/contracts/artifacts/FixedRateExchange.json')
export interface FixedPricedExchange {
exchangeOwner: string
dataToken: string
baseToken: string
fixedRate: number
active: boolean
}
export class OceanFixedRateExchange {
/** Ocean related functions */
public oceanAddress: string = null
public fixedRateExchangeAddress: string
public fixedRateExchangeABI: any
public web3: any
public contract: any = null
/**
* Instantiate FixedRateExchange
* @param {any} web3
* @param {String} fixedRateExchangeAddress
* @param {any} fixedRateExchangeABI
* @param {String} oceanAddress
*/
constructor(
web3: any,
fixedRateExchangeAddress: string = null,
fixedRateExchangeABI: any = null,
oceanAddress: string = null
) {
this.web3 = web3
this.fixedRateExchangeAddress = fixedRateExchangeAddress
this.fixedRateExchangeABI = fixedRateExchangeABI || defaultFixedRateExchangeABI.abi
this.oceanAddress = oceanAddress
if (web3)
this.contract = new this.web3.eth.Contract(
this.fixedRateExchangeABI,
this.fixedRateExchangeAddress
)
}
/**
* Creates new exchange pair between Ocean Token and data token.
* @param {String} dataToken Data Token Contract Address
* @param {Number} rate exchange rate
* @param {String} address User address
* @return {Promise<string>} exchangeId
*/
public async create(dataToken: string, rate: string, address: string): Promise<string> {
const estGas = await this.contract.methods
.create(this.oceanAddress, dataToken, this.web3.utils.toWei(rate))
.estimateGas(function (err, estGas) {
if (err) console.log('FixedPriceExchange: ' + err)
return estGas
})
const trxReceipt = await this.contract.methods
.create(this.oceanAddress, dataToken, this.web3.utils.toWei(rate))
.send({
from: address,
gas: estGas + 1
})
let exchangeId = null
try {
exchangeId = trxReceipt.events.ExchangeCreated.returnValues[0]
} catch (e) {
console.error(e)
}
return exchangeId
}
/**
* Creates unique exchange identifier.
* @param {String} dataToken Data Token Contract Address
* @param {String} owner Owner of the exchange
* @return {Promise<string>} exchangeId
*/
public async generateExchangeId(dataToken: string, owner: string): Promise<string> {
const exchangeId = await this.contract.methods
.generateExchangeId(this.oceanAddress, dataToken, owner)
.call()
return exchangeId
}
/**
* Atomic swap
* @param {String} exchangeId ExchangeId
* @param {Number} dataTokenAmount Amount of Data Tokens
* @param {String} address User address
* @return {Promise<any>} transaction receipt
*/
public async swap(
exchangeId: string,
dataTokenAmount: string,
address: string
): Promise<any> {
const estGas = await this.contract.methods
.swap(exchangeId, this.web3.utils.toWei(String(dataTokenAmount)))
.estimateGas(function (err, estGas) {
if (err) console.log('FixedPriceExchange: ' + err)
return estGas
})
const trxReceipt = await this.contract.methods
.swap(exchangeId, this.web3.utils.toWei(String(dataTokenAmount)))
.send({
from: address,
gas: estGas + 1
})
return trxReceipt
}
/**
* Gets total number of exchanges
* @param {String} exchangeId ExchangeId
* @param {Number} dataTokenAmount Amount of Data Tokens
* @return {Promise<Number>} no of available exchanges
*/
public async getNumberOfExchanges(): Promise<number> {
const numExchanges = await this.contract.methods.getNumberOfExchanges().call()
return numExchanges
}
/**
* Set new rate
* @param {String} exchangeId ExchangeId
* @param {Number} newRate New rate
* @param {String} address User account
* @return {Promise<any>} transaction receipt
*/
public async setRate(
exchangeId: string,
newRate: number,
address: string
): Promise<any> {
const estGas = await this.contract.methods
.setRate(exchangeId, this.web3.utils.toWei(String(newRate)))
.estimateGas(function (err, estGas) {
if (err) console.log('FixedPriceExchange: ' + err)
return estGas
})
const trxReceipt = await this.contract.methods
.setRate(exchangeId, this.web3.utils.toWei(String(newRate)))
.send({
from: address,
gas: estGas + 1
})
return trxReceipt
}
/**
* Activate an exchange
* @param {String} exchangeId ExchangeId
* @param {String} address User address
* @return {Promise<any>} transaction receipt
*/
public async activate(exchangeId: string, address: string): Promise<any> {
const estGas = await this.contract.methods
.activate(exchangeId)
.estimateGas(function (err, estGas) {
if (err) console.log('FixedPriceExchange: ' + err)
return estGas
})
const trxReceipt = await this.contract.methods.activate(exchangeId).send({
from: address,
gas: estGas + 1
})
return trxReceipt
}
/**
* Deactivate an exchange
* @param {String} exchangeId ExchangeId
* @param {String} address User address
* @return {Promise<any>} transaction receipt
*/
public async deactivate(exchangeId: string, address: string): Promise<any> {
const estGas = await this.contract.methods
.deactivate(exchangeId)
.estimateGas(function (err, estGas) {
if (err) console.log('FixedPriceExchange: ' + err)
return estGas
})
const trxReceipt = await this.contract.methods.deactivate(exchangeId).send({
from: address,
gas: estGas + 1
})
return trxReceipt
}
/**
* Get Rate
* @param {String} exchangeId ExchangeId
* @return {Promise<string>} Rate (converted from wei)
*/
public async getRate(exchangeId: string): Promise<string> {
const weiRate = await this.contract.methods.getRate(exchangeId).call()
return this.web3.utils.fromWei(weiRate)
}
/**
* Get exchange details
* @param {String} exchangeId ExchangeId
* @return {Promise<FixedPricedExchange>} Exchange details
*/
public async getExchange(exchangeId: string): Promise<FixedPricedExchange> {
const result: FixedPricedExchange = await this.contract.methods
.getExchange(exchangeId)
.call()
return result
}
/**
* Get all exchanges
* @param {String} exchangeId ExchangeId
* @return {Promise<String[]>} Exchanges list
*/
public async getExchanges(): Promise<string[]> {
const result = await this.contract.methods.getExchanges().call()
return result
}
/**
* Check if an exchange is active
* @param {String} exchangeId ExchangeId
* @return {Promise<Boolean>} Result
*/
public async isActive(exchangeId: string): Promise<boolean> {
const result = await this.contract.methods.isActive(exchangeId).call()
return result
}
}

View File

@ -68,12 +68,24 @@ export class Config {
*/ */
public poolFactoryABI?: any public poolFactoryABI?: any
/** /**
* Pool ABI * Pool ABI
* @type {string} * @type {string}
*/ */
public poolABI?: any public poolABI?: any
/**
* FixedRateExchangeAddress
* @type {string}
*/
public fixedRateExchangeAddress?: string
/**
* FixedRateExchangeAddressABI
* @type {any}
*/
public fixedRateExchangeAddressABI?: any
/** /**
* Log level. * Log level.
* @type {boolean | LogLevel} * @type {boolean | LogLevel}

View File

@ -13,6 +13,7 @@ import {
} from '../Instantiable.abstract' } from '../Instantiable.abstract'
import { Compute } from './Compute' import { Compute } from './Compute'
import { OceanPool } from '../balancer/OceanPool' import { OceanPool } from '../balancer/OceanPool'
import {OceanFixedRateExchange, FixedPricedExchange} from '../exchange/FixRateExchange'
/** /**
* Main interface for Ocean Protocol. * Main interface for Ocean Protocol.
@ -57,6 +58,13 @@ export class Ocean extends Instantiable {
instanceConfig.config.poolFactoryAddress, instanceConfig.config.poolFactoryAddress,
instanceConfig.config.oceanTokenAddress instanceConfig.config.oceanTokenAddress
) )
instance.fixedRateExchange = new OceanFixedRateExchange(
instanceConfig.config.web3Provider,
instanceConfig.config.fixedRateExchangeAddress,
instanceConfig.config.fixedRateExchangeAddressABI,
instanceConfig.config.oceanTokenAddress
)
instance.versions = await Versions.getInstance(instanceConfig) instance.versions = await Versions.getInstance(instanceConfig)
instance.network = new Network() instance.network = new Network()
return instance return instance
@ -123,6 +131,12 @@ export class Ocean extends Instantiable {
*/ */
public pool: OceanPool public pool: OceanPool
/**
* Ocean FixedRateExchange submodule
* @type {OceanFixedRateExchange}
*/
public fixedRateExchange: OceanFixedRateExchange
/** /**
* Ocean tokens submodule * Ocean tokens submodule
* @type {OceanTokens} * @type {OceanTokens}

View File

@ -19,7 +19,8 @@ const configs = [
factoryAddress: null, factoryAddress: null,
metadataStoreUri: 'http://127.0.0.1:5000', metadataStoreUri: 'http://127.0.0.1:5000',
providerUri: 'http://127.0.0.1:8030', providerUri: 'http://127.0.0.1:8030',
poolFactoryAddress: null poolFactoryAddress: null,
fixedRateExchangeAddress: null
}, },
{ {
chainId: 4, chainId: 4,
@ -29,7 +30,8 @@ const configs = [
oceanTokenAddress: '0x8967BCF84170c91B0d24D4302C2376283b0B3a07', oceanTokenAddress: '0x8967BCF84170c91B0d24D4302C2376283b0B3a07',
metadataStoreUri: 'https://aquarius.rinkeby.v3.dev-ocean.com', metadataStoreUri: 'https://aquarius.rinkeby.v3.dev-ocean.com',
providerUri: 'https://provider.rinkeby.v3.dev-ocean.com', providerUri: 'https://provider.rinkeby.v3.dev-ocean.com',
poolFactoryAddress: '0xA4531C624A3D88323a1e178DABe1233AF178701B' poolFactoryAddress: '0xA4531C624A3D88323a1e178DABe1233AF178701B',
fixedRateExchangeAddress: '0x7219AfFc1C2b474830D9d9b0423ecf47073C5488'
}, },
{ {
chainId: 1, chainId: 1,
@ -39,7 +41,8 @@ const configs = [
oceanTokenAddress: '0x985dd3d42de1e256d09e1c10f112bccb8015ad41', oceanTokenAddress: '0x985dd3d42de1e256d09e1c10f112bccb8015ad41',
metadataStoreUri: null, metadataStoreUri: null,
providerUri: null, providerUri: null,
poolFactoryAddress: null poolFactoryAddress: null,
fixedRateExchangeAddress: null
} }
] ]

View File

@ -0,0 +1,58 @@
import Web3 from 'web3'
import { Contract } from 'web3-eth-contract'
import { AbiItem } from 'web3-utils/types'
export class FixedPricedContractHandler {
public contract: Contract
public accounts: string[]
public contractBytecode: string
public contractAddress: string
public web3: Web3
constructor(
contractABI: AbiItem | AbiItem[],
contractBytecode: string,
web3: Web3
) {
this.web3 = web3
this.contract = new this.web3.eth.Contract(contractABI)
this.contractBytecode = contractBytecode
}
public async getAccounts() {
this.accounts = await this.web3.eth.getAccounts()
}
public async deployContracts() {
let estGas
await this.getAccounts()
// get est gascost
estGas = await this.contract
.deploy({
data: this.contractBytecode,
arguments: []
})
.estimateGas(function (err, estGas) {
if (err) console.log('DeployContracts: ' + err)
return estGas
})
// deploy the contract and get it's address
this.contractAddress = await this.contract
.deploy({
data: this.contractBytecode,
arguments: []
})
.send({
from: this.accounts[0],
gas: estGas + 1,
gasPrice: '3000000000'
})
.then(function (contract) {
return contract.options.address
})
}
}

View File

@ -0,0 +1,293 @@
import { assert } from 'chai'
import { AbiItem } from 'web3-utils/types'
import { TestContractHandler } from '../../TestContractHandler'
import { FixedPricedContractHandler } from '../../FixedPriceContractHandler'
import { DataTokens } from '../../../src/datatokens/Datatokens'
import {
OceanFixedRateExchange,
FixedPricedExchange
} from '../../../src/exchange/FixRateExchange'
import Web3 from 'web3'
import factory from '@oceanprotocol/contracts/artifacts/DTFactory.json'
import datatokensTemplate from '@oceanprotocol/contracts/artifacts/DataTokenTemplate.json'
import FixedRateExchangeContract = require('@oceanprotocol/contracts/artifacts/FixedRateExchange.json')
import BigNumber from 'bignumber.js'
const web3 = new Web3('http://127.0.0.1:8545')
describe('FixedRateExchange flow', () => {
let oceanTokenAddress
let FixedRateExchangeAddress
let FixedRateClass
let oceandatatoken
let aliceExchangeId
let bob
let alice
let datatoken
let tokenAddress
let alicePoolAddress
let currentDtPrice
let owner
let contracts
let consoleDebug: false
let greatPool
const tokenAmount = '1000'
const transferAmount = '200'
const blob = 'http://localhost:8030/api/v1/services/consume'
describe('#test', () => {
before(async () => {
// deploy SFactory
const Contracts = new FixedPricedContractHandler(
FixedRateExchangeContract.abi as AbiItem[],
FixedRateExchangeContract.bytecode,
web3
)
await Contracts.getAccounts()
owner = Contracts.accounts[0]
await Contracts.deployContracts()
FixedRateExchangeAddress = Contracts.contractAddress
assert(FixedRateExchangeAddress !== null)
// deploy DT Factory
contracts = new TestContractHandler(
factory.abi as AbiItem[],
datatokensTemplate.abi as AbiItem[],
datatokensTemplate.bytecode,
factory.bytecode,
web3
)
await contracts.getAccounts()
owner = contracts.accounts[0]
alice = contracts.accounts[1]
bob = contracts.accounts[2]
await contracts.deployContracts(owner)
// initialize DataTokens
datatoken = new DataTokens(
contracts.factoryAddress,
factory.abi as AbiItem[],
datatokensTemplate.abi as AbiItem[],
web3
)
assert(datatoken !== null)
})
it('should create datatokens smart contract', async () => {
tokenAddress = await datatoken.create(blob, alice)
assert(tokenAddress !== null)
console.log('data Token address:' + tokenAddress)
})
it('Create a dummy OceanToken', async () => {
// Bob creates a Datatoken
oceandatatoken = new DataTokens(
contracts.factoryAddress,
factory.abi as AbiItem[],
datatokensTemplate.abi as AbiItem[],
web3
)
oceanTokenAddress = await oceandatatoken.create(blob, bob)
console.log('oceanTokenAddress:' + oceanTokenAddress)
})
it('should initialize FixedExchangeRate class', async () => {
FixedRateClass = new OceanFixedRateExchange(
web3,
FixedRateExchangeAddress,
FixedRateExchangeContract.abi,
oceanTokenAddress
)
assert(FixedRateClass !== null)
})
it('Alice mints 1000 tokens', async () => {
await datatoken.mint(tokenAddress, alice, tokenAmount)
})
it('Bob mints 1000 Ocean tokens', async () => {
await oceandatatoken.mint(oceanTokenAddress, bob, tokenAmount)
})
it('Alice should have 1000 tokens', async () => {
const balance = await datatoken.balance(tokenAddress, alice)
console.log(balance)
})
it('Bob should have 1000 ocean tokens', async () => {
const balance = await oceandatatoken.balance(oceanTokenAddress, bob)
console.log(balance)
})
it('Alice creates a new FixedRate Exchange with a rate of 0.5', async () => {
aliceExchangeId = await FixedRateClass.create(tokenAddress, '0.1', alice)
console.log(aliceExchangeId)
})
it('Alice allows Exchange to spend 1000 data tokens', async () => {
await datatoken.approve(tokenAddress, FixedRateExchangeAddress, tokenAmount, alice)
})
it('Bob allows Exchange to spend 1000 ocean tokens', async () => {
await oceandatatoken.approve(
oceanTokenAddress,
FixedRateExchangeAddress,
tokenAmount,
bob
)
})
it('Alice should aproved speding datatokens', async () => {
const balance = await datatoken.allowance(
tokenAddress,
alice,
FixedRateExchangeAddress
)
console.log(balance)
})
it('Bob should aproved speding oceantokens', async () => {
const balance = await oceandatatoken.allowance(
oceanTokenAddress,
bob,
FixedRateExchangeAddress
)
console.log(balance)
})
it('Bob should get the exchange details', async () => {
const exchangeDetails = await FixedRateClass.getExchange(aliceExchangeId)
console.log(exchangeDetails)
})
it('Bob should swap 1 DataToken', async () => {
const swapResult = await FixedRateClass.swap(aliceExchangeId, '1', bob)
console.log(swapResult)
})
/*
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')
})
it('Get pool information', async () => {
const currentTokens = await Pool.getCurrentTokens(alice, alicePoolAddress)
assert(currentTokens.length === 2)
assert(currentTokens.includes(tokenAddress))
assert(currentTokens.includes(oceanTokenAddress))
})
it('Get pool swap fee', async () => {
const currentSwapFee = await Pool.getSwapFee(alice, alicePoolAddress)
assert(currentSwapFee === '0.02')
})
it('Get dtPrice from the pool ', async () => {
currentDtPrice = await Pool.getDTPrice(alice, alicePoolAddress)
assert(currentDtPrice > 0)
})
it('Get dtToken pool reserve ', async () => {
const currentDtReserve = await Pool.getDTReserve(alice, alicePoolAddress)
assert(currentDtReserve > 0)
})
it('Get Ocean pool reserve ', async () => {
const currentOceanReserve = await Pool.getOceanReserve(alice, alicePoolAddress)
assert(currentOceanReserve > 0)
})
it('Get total supply of pool tokens', async () => {
const totalSupply = await Pool.totalSupply(alicePoolAddress)
assert(totalSupply > 0)
})
it('Get amount of Ocean needed to buy 1 dtToken', async () => {
const requiredOcean = await Pool.getOceanNeeded(alice, alicePoolAddress, '1')
assert(requiredOcean > 0)
})
it('Bob should search for pools with this DT', async () => {
const pools = await Pool.searchPoolforDT(bob, tokenAddress)
assert(pools.length > 0)
greatPool = pools[0]
})
it('Bob should buy a DT ', async () => {
const maxPrice = parseFloat(currentDtPrice) * 2
await Pool.buyDT(bob, greatPool, '1', '2', String(maxPrice))
const bobDtBalance = await datatoken.balance(tokenAddress, bob)
const bobOceanBalance = await datatoken.balance(oceanTokenAddress, bob)
assert(bobDtBalance > 0)
assert(bobOceanBalance > 0)
})
it('Bob should add DT liquidity to pool ', async () => {
const currentDtReserve = await Pool.getDTReserve(bob, greatPool)
if (consoleDebug) console.log('currentDtReserve:' + currentDtReserve)
const bobDtBalance = await datatoken.balance(tokenAddress, bob)
if (consoleDebug) console.log('BOB DT Balance:' + bobDtBalance)
await Pool.addDTLiquidity(bob, greatPool, bobDtBalance)
const newbobDtBalance = await datatoken.balance(tokenAddress, bob)
const newDtReserve = await Pool.getDTReserve(bob, greatPool)
const sharesBalance = await Pool.sharesBalance(bob, greatPool)
if (consoleDebug) console.log('newDtReserve:' + newDtReserve)
if (consoleDebug) console.log('newbobDtBalance:' + newbobDtBalance)
if (consoleDebug) console.log('sharesBalance:' + sharesBalance)
assert(parseFloat(newbobDtBalance) < parseFloat(bobDtBalance))
assert(parseFloat(newDtReserve) > parseFloat(currentDtReserve))
assert(parseFloat(sharesBalance) > 0)
})
it('Bob should remove DT liquidity from pool ', async () => {
const currentDtReserve = await Pool.getDTReserve(bob, greatPool)
if (consoleDebug) console.log('currentDtReserve:' + currentDtReserve)
const bobDtBalance = await datatoken.balance(tokenAddress, bob)
if (consoleDebug) console.log('bobDtBalance:' + bobDtBalance)
const poolShares = await Pool.sharesBalance(bob, greatPool)
if (consoleDebug) console.log('poolShares:' + poolShares)
await Pool.removeDTLiquidity(bob, greatPool, '0.75', poolShares)
const newDtReserve = await Pool.getDTReserve(bob, greatPool)
if (consoleDebug) console.log('newDtReserve:' + newDtReserve)
const newbobDtBalance = await datatoken.balance(tokenAddress, bob)
if (consoleDebug) console.log('newbobDtBalance:' + newbobDtBalance)
const newpoolShares = await Pool.sharesBalance(bob, greatPool)
if (consoleDebug) console.log('newpoolShares:' + newpoolShares)
assert(parseFloat(newDtReserve) < parseFloat(currentDtReserve))
assert(parseFloat(bobDtBalance) < parseFloat(newbobDtBalance))
assert(parseFloat(poolShares) > parseFloat(newpoolShares))
})
it('Bob should add Ocean liquidity to pool ', async () => {
const currentDtReserve = await Pool.getOceanReserve(bob, greatPool)
const bobDtBalance = await datatoken.balance(oceanTokenAddress, bob)
if (consoleDebug) console.log('currentDtReserve:' + currentDtReserve)
if (consoleDebug) console.log('bobDtBalance:' + bobDtBalance)
await Pool.addOceanLiquidity(bob, greatPool, '1')
const newbobDtBalance = await datatoken.balance(oceanTokenAddress, bob)
const newDtReserve = await Pool.getOceanReserve(bob, greatPool)
const sharesBalance = await Pool.sharesBalance(bob, greatPool)
if (consoleDebug) console.log('newDtReserve:' + newDtReserve)
if (consoleDebug) console.log('newbobDtBalance:' + newbobDtBalance)
if (consoleDebug) console.log('sharesBalance:' + sharesBalance)
assert(parseFloat(newbobDtBalance) < parseFloat(bobDtBalance))
assert(parseFloat(newDtReserve) > parseFloat(currentDtReserve))
assert(parseFloat(sharesBalance) > 0)
})
it('Bob should remove Ocean liquidity from pool ', async () => {
const currentDtReserve = await Pool.getOceanReserve(bob, greatPool)
const bobDtBalance = await datatoken.balance(oceanTokenAddress, bob)
const poolShares = await Pool.sharesBalance(bob, greatPool)
if (consoleDebug) console.log('currentDtReserve:' + currentDtReserve)
if (consoleDebug) console.log('bobDtBalance:' + bobDtBalance)
if (consoleDebug) console.log('poolShares:' + poolShares)
await Pool.removeOceanLiquidity(bob, greatPool, '0.75', poolShares)
const newDtReserve = await Pool.getOceanReserve(bob, greatPool)
const newbobDtBalance = await datatoken.balance(oceanTokenAddress, bob)
const newpoolShares = await Pool.sharesBalance(bob, greatPool)
if (consoleDebug) console.log('newDtReserve:' + newDtReserve)
if (consoleDebug) console.log('newbobDtBalance:' + newbobDtBalance)
if (consoleDebug) console.log('newpoolShares:' + newpoolShares)
assert(parseFloat(newDtReserve) < parseFloat(currentDtReserve))
assert(parseFloat(bobDtBalance) < parseFloat(newbobDtBalance))
assert(parseFloat(poolShares) > parseFloat(newpoolShares))
})
*/
})
})