mirror of
https://github.com/oceanprotocol/ocean.js.git
synced 2024-11-26 20:39:05 +01:00
Merge pull request #289 from oceanprotocol/feature/statstics_history
add stats/history
This commit is contained in:
commit
9d33417b7c
@ -2,6 +2,28 @@ import Web3 from 'web3'
|
||||
import { AbiItem } from 'web3-utils/types'
|
||||
import { TransactionReceipt } from 'web3-core'
|
||||
import { Pool } from './Pool'
|
||||
import { EventData, Filter } from 'web3-eth-contract'
|
||||
|
||||
declare type PoolTransactionType = 'swap' | 'join' | 'exit'
|
||||
|
||||
export interface PoolDetails {
|
||||
poolAddress: string
|
||||
tokens: string[]
|
||||
}
|
||||
|
||||
export interface PoolTransaction {
|
||||
poolAddress: string
|
||||
dtAddress: string
|
||||
caller: string
|
||||
transactionHash: string
|
||||
blockNumber: number
|
||||
timestamp: number
|
||||
tokenIn?: string
|
||||
tokenOut?: string
|
||||
tokenAmountIn?: string
|
||||
tokenAmountOut?: string
|
||||
type: PoolTransactionType
|
||||
}
|
||||
|
||||
/**
|
||||
* Ocean Pools submodule exposed under ocean.pool
|
||||
@ -82,9 +104,9 @@ export class OceanPool extends Pool {
|
||||
* @param {String} poolAddress
|
||||
* @return {string}
|
||||
*/
|
||||
public async getDTAddress(account: string, poolAddress: string): Promise<string> {
|
||||
public async getDTAddress(poolAddress: string): Promise<string> {
|
||||
this.dtAddress = null
|
||||
const tokens = await this.getCurrentTokens(account, poolAddress)
|
||||
const tokens = await this.getCurrentTokens(poolAddress)
|
||||
let token: string
|
||||
|
||||
for (token of tokens) {
|
||||
@ -115,7 +137,7 @@ export class OceanPool extends Pool {
|
||||
* @return {String}
|
||||
*/
|
||||
public async getDTReserve(account: string, poolAddress: string): Promise<string> {
|
||||
await this.getDTAddress(account, poolAddress)
|
||||
await this.getDTAddress(poolAddress)
|
||||
return super.getReserve(account, poolAddress, this.dtAddress)
|
||||
}
|
||||
|
||||
@ -139,7 +161,7 @@ export class OceanPool extends Pool {
|
||||
console.error('oceanAddress is not defined')
|
||||
return null
|
||||
}
|
||||
await this.getDTAddress(account, poolAddress)
|
||||
await this.getDTAddress(poolAddress)
|
||||
|
||||
// TODO - check balances first
|
||||
await super.approve(
|
||||
@ -180,7 +202,7 @@ export class OceanPool extends Pool {
|
||||
console.error('oceanAddress is not defined')
|
||||
return null
|
||||
}
|
||||
await this.getDTAddress(account, poolAddress)
|
||||
await this.getDTAddress(poolAddress)
|
||||
return this.swapExactAmountOut(
|
||||
account,
|
||||
poolAddress,
|
||||
@ -204,7 +226,7 @@ export class OceanPool extends Pool {
|
||||
poolAddress: string,
|
||||
amount: string
|
||||
): Promise<TransactionReceipt> {
|
||||
await this.getDTAddress(account, poolAddress)
|
||||
await this.getDTAddress(poolAddress)
|
||||
await super.approve(
|
||||
account,
|
||||
this.dtAddress,
|
||||
@ -234,7 +256,7 @@ export class OceanPool extends Pool {
|
||||
amount: string,
|
||||
maximumPoolShares: string
|
||||
): Promise<TransactionReceipt> {
|
||||
await this.getDTAddress(account, poolAddress)
|
||||
await this.getDTAddress(poolAddress)
|
||||
// TODO Check balance of PoolShares before doing exit
|
||||
return this.exitswapExternAmountOut(
|
||||
account,
|
||||
@ -335,10 +357,7 @@ export class OceanPool extends Pool {
|
||||
toBlock: 'latest'
|
||||
})
|
||||
for (let i = 0; i < events.length; i++) {
|
||||
const constituents = await super.getCurrentTokens(
|
||||
account,
|
||||
events[i].returnValues[0]
|
||||
)
|
||||
const constituents = await super.getCurrentTokens(events[i].returnValues[0])
|
||||
if (constituents.includes(dtAddress)) result.push(events[i].returnValues[0])
|
||||
}
|
||||
return result
|
||||
@ -349,7 +368,7 @@ export class OceanPool extends Pool {
|
||||
poolAddress: string,
|
||||
dtRequired: string
|
||||
): Promise<string> {
|
||||
await this.getDTAddress(account, poolAddress)
|
||||
await this.getDTAddress(poolAddress)
|
||||
const tokenBalanceIn = await this.getReserve(account, poolAddress, this.oceanAddress)
|
||||
const tokenWeightIn = await this.getDenormalizedWeight(
|
||||
account,
|
||||
@ -372,4 +391,154 @@ export class OceanPool extends Pool {
|
||||
swapFee
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Search all pools created by an address
|
||||
* @param {String} account If empty, will return all pools ever created by anybody
|
||||
* @return {PoolDetails[]}
|
||||
*/
|
||||
public async getPoolsbyCreator(account?: string): Promise<PoolDetails[]> {
|
||||
const result: PoolDetails[] = []
|
||||
const factory = new this.web3.eth.Contract(this.factoryABI, this.factoryAddress)
|
||||
|
||||
const events = await factory.getPastEvents('BPoolRegistered', {
|
||||
filter: account ? { registeredBy: account } : {},
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
|
||||
for (let i = 0; i < events.length; i++) {
|
||||
if (!account || events[i].returnValues[1].toLowerCase() === account.toLowerCase())
|
||||
result.push(await this.getPoolDetails(events[i].returnValues[0]))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Get pool details
|
||||
* @param {String} poolAddress Pool address
|
||||
* @return {PoolDetails}
|
||||
*/
|
||||
public async getPoolDetails(poolAddress: string): Promise<PoolDetails> {
|
||||
const tokens = await super.getFinalTokens(poolAddress)
|
||||
const details: PoolDetails = { poolAddress, tokens }
|
||||
return details
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all actions from a pool (join,exit,swap)
|
||||
* @param {String} poolAddress Pool address
|
||||
* @param {String} account
|
||||
* @return {PoolTransaction[]}
|
||||
*/
|
||||
public async getPoolLogs(
|
||||
poolAddress: string,
|
||||
account?: string
|
||||
): Promise<PoolTransaction[]> {
|
||||
const results: PoolTransaction[] = []
|
||||
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
|
||||
const dtAddress = await this.getDTAddress(poolAddress)
|
||||
const filter: Filter = account ? { caller: account } : {}
|
||||
let events: EventData[]
|
||||
|
||||
events = await pool.getPastEvents('LOG_SWAP', {
|
||||
filter,
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
|
||||
for (let i = 0; i < events.length; i++) {
|
||||
if (!account || events[i].returnValues[0].toLowerCase() === account.toLowerCase())
|
||||
results.push(await this.getEventData('swap', poolAddress, dtAddress, events[i]))
|
||||
}
|
||||
|
||||
events = await pool.getPastEvents('LOG_JOIN', {
|
||||
filter,
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
|
||||
for (let i = 0; i < events.length; i++) {
|
||||
if (!account || events[i].returnValues[0].toLowerCase() === account.toLowerCase())
|
||||
results.push(await this.getEventData('join', poolAddress, dtAddress, events[i]))
|
||||
}
|
||||
|
||||
events = await pool.getPastEvents('LOG_EXIT', {
|
||||
filter,
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
for (let i = 0; i < events.length; i++) {
|
||||
if (!account || events[i].returnValues[0].toLowerCase() === account.toLowerCase())
|
||||
results.push(await this.getEventData('exit', poolAddress, dtAddress, events[i]))
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all logs on all pools for a specific address
|
||||
* @param {String} account
|
||||
* @return {PoolTransaction[]}
|
||||
*/
|
||||
public async getAllPoolLogs(account: string): Promise<PoolTransaction[]> {
|
||||
const results: PoolTransaction[] = []
|
||||
const factory = new this.web3.eth.Contract(this.factoryABI, this.factoryAddress)
|
||||
const events = await factory.getPastEvents('BPoolRegistered', {
|
||||
filter: {},
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
|
||||
for (let i = 0; i < events.length; i++) {
|
||||
const logs = await this.getPoolLogs(events[i].returnValues[0], account)
|
||||
for (let j = 0; j < logs.length; j++) results.push(logs[j])
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
private async getEventData(
|
||||
type: PoolTransactionType,
|
||||
poolAddress: string,
|
||||
dtAddress: string,
|
||||
data: EventData
|
||||
): Promise<PoolTransaction> {
|
||||
const blockDetails = await this.web3.eth.getBlock(data.blockNumber)
|
||||
let result: PoolTransaction = {
|
||||
poolAddress,
|
||||
dtAddress,
|
||||
caller: data.returnValues[0],
|
||||
transactionHash: data.transactionHash,
|
||||
blockNumber: data.blockNumber,
|
||||
timestamp: parseInt(String(blockDetails.timestamp)),
|
||||
type
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case 'swap':
|
||||
result = {
|
||||
...result,
|
||||
tokenIn: data.returnValues[1],
|
||||
tokenOut: data.returnValues[2],
|
||||
tokenAmountIn: this.web3.utils.fromWei(data.returnValues[3]),
|
||||
tokenAmountOut: this.web3.utils.fromWei(data.returnValues[4])
|
||||
}
|
||||
break
|
||||
case 'join':
|
||||
result = {
|
||||
...result,
|
||||
tokenIn: data.returnValues[1],
|
||||
tokenAmountIn: this.web3.utils.fromWei(data.returnValues[2])
|
||||
}
|
||||
break
|
||||
case 'exit':
|
||||
result = {
|
||||
...result,
|
||||
tokenOut: data.returnValues[1],
|
||||
tokenAmountOut: this.web3.utils.fromWei(data.returnValues[2])
|
||||
}
|
||||
break
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ export interface TokensToAdd {
|
||||
}
|
||||
|
||||
export class Pool extends PoolFactory {
|
||||
private poolABI: AbiItem | AbiItem[]
|
||||
public poolABI: AbiItem | AbiItem[]
|
||||
|
||||
constructor(
|
||||
web3: Web3,
|
||||
@ -275,14 +275,11 @@ export class Pool extends PoolFactory {
|
||||
|
||||
/**
|
||||
* Get tokens composing this pool
|
||||
* @param {String} account
|
||||
* @param {String} poolAddress
|
||||
* @return {String[]}
|
||||
*/
|
||||
async getCurrentTokens(account: string, poolAddress: string): Promise<string[]> {
|
||||
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress, {
|
||||
from: account
|
||||
})
|
||||
async getCurrentTokens(poolAddress: string): Promise<string[]> {
|
||||
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
|
||||
let result = null
|
||||
try {
|
||||
result = await pool.methods.getCurrentTokens().call()
|
||||
@ -294,14 +291,11 @@ export class Pool extends PoolFactory {
|
||||
|
||||
/**
|
||||
* Get the final tokens composing this pool
|
||||
* @param {String} account
|
||||
* @param {String} poolAddress
|
||||
* @return {String[]}
|
||||
*/
|
||||
async getFinalTokens(account: string, poolAddress: string): Promise<string[]> {
|
||||
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress, {
|
||||
from: account
|
||||
})
|
||||
async getFinalTokens(poolAddress: string): Promise<string[]> {
|
||||
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
|
||||
let result = null
|
||||
try {
|
||||
result = await pool.methods.getFinalTokens().call()
|
||||
|
@ -1,11 +1,11 @@
|
||||
import defaultFixedRateExchangeABI from '@oceanprotocol/contracts/artifacts/FixedRateExchange.json'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import { TransactionReceipt } from 'web3-core'
|
||||
import { Contract } from 'web3-eth-contract'
|
||||
import { Contract, EventData } from 'web3-eth-contract'
|
||||
import { AbiItem } from 'web3-utils/types'
|
||||
import Web3 from 'web3'
|
||||
|
||||
export interface FixedPricedExchange {
|
||||
export interface FixedPriceExchange {
|
||||
exchangeID?: string
|
||||
exchangeOwner: string
|
||||
dataToken: string
|
||||
@ -15,6 +15,12 @@ export interface FixedPricedExchange {
|
||||
supply: string
|
||||
}
|
||||
|
||||
export interface FixedPriceSwap {
|
||||
exchangeID: string
|
||||
caller: string
|
||||
baseTokenAmount: string
|
||||
dataTokenAmount: string
|
||||
}
|
||||
const DEFAULT_GAS_LIMIT = 300000
|
||||
|
||||
export class OceanFixedRateExchange {
|
||||
@ -292,8 +298,8 @@ export class OceanFixedRateExchange {
|
||||
* @param {String} exchangeId ExchangeId
|
||||
* @return {Promise<FixedPricedExchange>} Exchange details
|
||||
*/
|
||||
public async getExchange(exchangeId: string): Promise<FixedPricedExchange> {
|
||||
const result: FixedPricedExchange = await this.contract.methods
|
||||
public async getExchange(exchangeId: string): Promise<FixedPriceExchange> {
|
||||
const result: FixedPriceExchange = await this.contract.methods
|
||||
.getExchange(exchangeId)
|
||||
.call()
|
||||
return result
|
||||
@ -337,8 +343,8 @@ export class OceanFixedRateExchange {
|
||||
public async searchforDT(
|
||||
dataTokenAddress: string,
|
||||
minSupply: string
|
||||
): Promise<FixedPricedExchange[]> {
|
||||
const result: FixedPricedExchange[] = []
|
||||
): Promise<FixedPriceExchange[]> {
|
||||
const result: FixedPriceExchange[] = []
|
||||
const events = await this.contract.getPastEvents('ExchangeCreated', {
|
||||
filter: { datatoken: dataTokenAddress },
|
||||
fromBlock: 0,
|
||||
@ -357,4 +363,80 @@ export class OceanFixedRateExchange {
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all exchanges, filtered by creator(if any)
|
||||
* @param {String} account
|
||||
* @return {Promise<FixedPricedExchange[]>}
|
||||
*/
|
||||
public async getExchangesbyCreator(account?: string): Promise<FixedPriceExchange[]> {
|
||||
const result: FixedPriceExchange[] = []
|
||||
const events = await this.contract.getPastEvents('ExchangeCreated', {
|
||||
filter: {},
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
for (let i = 0; i < events.length; i++) {
|
||||
if (!account || events[i].returnValues[3].toLowerCase() === account.toLowerCase())
|
||||
result.push(await this.getExchange(events[i].returnValues[0]))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all swaps for an exchange, filtered by account(if any)
|
||||
* @param {String} exchangeId
|
||||
* @param {String} account
|
||||
* @return {Promise<FixedPricedSwap[]>}
|
||||
*/
|
||||
public async getExchangeSwaps(
|
||||
exchangeId: string,
|
||||
account?: string
|
||||
): Promise<FixedPriceSwap[]> {
|
||||
const result: FixedPriceSwap[] = []
|
||||
const events = await this.contract.getPastEvents('Swapped', {
|
||||
filter: { exchangeId: exchangeId },
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
for (let i = 0; i < events.length; i++) {
|
||||
if (!account || events[i].returnValues[1].toLowerCase() === account.toLowerCase())
|
||||
result.push(this.getEventData(events[i]))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all swaps for an account
|
||||
* @param {String} account
|
||||
* @return {Promise<FixedPricedSwap[]>}
|
||||
*/
|
||||
public async getAllExchangesSwaps(account: string): Promise<FixedPriceSwap[]> {
|
||||
const result: FixedPriceSwap[] = []
|
||||
const events = await this.contract.getPastEvents('ExchangeCreated', {
|
||||
filter: {},
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
for (let i = 0; i < events.length; i++) {
|
||||
const swaps: FixedPriceSwap[] = await this.getExchangeSwaps(
|
||||
events[i].returnValues[0],
|
||||
account
|
||||
)
|
||||
swaps.forEach((swap) => {
|
||||
result.push(swap)
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private getEventData(data: EventData): FixedPriceSwap {
|
||||
const result: FixedPriceSwap = {
|
||||
exchangeID: data.returnValues[0],
|
||||
caller: data.returnValues[1],
|
||||
baseTokenAmount: data.returnValues[2],
|
||||
dataTokenAmount: data.returnValues[3]
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ describe('Balancer flow', () => {
|
||||
assert(String(n) === '2', 'unexpected num tokens: ' + n)
|
||||
})
|
||||
it('Get pool information', async () => {
|
||||
const currentTokens = await Pool.getCurrentTokens(alice, alicePoolAddress)
|
||||
const currentTokens = await Pool.getCurrentTokens(alicePoolAddress)
|
||||
assert(currentTokens.length === 2)
|
||||
assert(currentTokens.includes(tokenAddress))
|
||||
assert(currentTokens.includes(oceanTokenAddress))
|
||||
@ -270,4 +270,18 @@ describe('Balancer flow', () => {
|
||||
assert(parseFloat(bobDtBalance) < parseFloat(newbobDtBalance))
|
||||
assert(parseFloat(poolShares) > parseFloat(newpoolShares))
|
||||
})
|
||||
|
||||
it('ALice should get all the pools that she created', async () => {
|
||||
const alicePools = await Pool.getPoolsbyCreator(alice)
|
||||
assert(alicePools.length > 0)
|
||||
})
|
||||
|
||||
it('ALice should get the logs for her pool', async () => {
|
||||
const poolLogs = await Pool.getPoolLogs(greatPool, null)
|
||||
assert(poolLogs.length > 0)
|
||||
})
|
||||
it('Bob should get the logs for all his activities', async () => {
|
||||
const poolLogs = await Pool.getAllPoolLogs(bob)
|
||||
assert(poolLogs.length > 0)
|
||||
})
|
||||
})
|
||||
|
@ -226,4 +226,12 @@ describe('FixedRateExchange flow', () => {
|
||||
const exchangeDetails = await FixedRateClass.searchforDT(tokenAddress, tokenAmount)
|
||||
assert(exchangeDetails.length === 0)
|
||||
})
|
||||
it('Bob should find all the exchanges created by Alice', async () => {
|
||||
const exchangeDetails = await FixedRateClass.getExchangesbyCreator(alice)
|
||||
assert(exchangeDetails.length > 0)
|
||||
})
|
||||
it('Bob should find all his swaps', async () => {
|
||||
const exchangeDetails = await FixedRateClass.getAllExchangesSwaps(bob)
|
||||
assert(exchangeDetails.length > 0)
|
||||
})
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user