mirror of
https://github.com/oceanprotocol/ocean.js.git
synced 2024-11-26 20:39:05 +01:00
Merge pull request #441 from oceanprotocol/feature/pool_logs_history_speed_optimisation
logs/history speed optimizations
This commit is contained in:
commit
9e265912d8
@ -1,6 +1,6 @@
|
||||
import Web3 from 'web3'
|
||||
import { AbiItem } from 'web3-utils/types'
|
||||
import { TransactionReceipt } from 'web3-core'
|
||||
import { TransactionReceipt, Log } from 'web3-core'
|
||||
import { Pool } from './Pool'
|
||||
import { EventData, Filter } from 'web3-eth-contract'
|
||||
import BigNumber from 'bignumber.js'
|
||||
@ -54,6 +54,7 @@ export enum PoolCreateProgressStep {
|
||||
export class OceanPool extends Pool {
|
||||
public oceanAddress: string = null
|
||||
public dtAddress: string = null
|
||||
public startBlock: number
|
||||
|
||||
constructor(
|
||||
web3: Web3,
|
||||
@ -62,12 +63,14 @@ export class OceanPool extends Pool {
|
||||
poolABI: AbiItem | AbiItem[] = null,
|
||||
factoryAddress: string = null,
|
||||
oceanAddress: string = null,
|
||||
gaslimit?: number
|
||||
startBlock?: number
|
||||
) {
|
||||
super(web3, logger, factoryABI, poolABI, factoryAddress, gaslimit)
|
||||
super(web3, logger, factoryABI, poolABI, factoryAddress)
|
||||
if (oceanAddress) {
|
||||
this.oceanAddress = oceanAddress
|
||||
}
|
||||
if (startBlock) this.startBlock = startBlock
|
||||
else this.startBlock = 0
|
||||
}
|
||||
|
||||
/**
|
||||
@ -168,10 +171,11 @@ export class OceanPool extends Pool {
|
||||
const tokens = await this.getCurrentTokens(poolAddress)
|
||||
let token: string
|
||||
|
||||
for (token of tokens) {
|
||||
// TODO: Potential timing attack, left side: true
|
||||
if (token !== this.oceanAddress) this.dtAddress = token
|
||||
}
|
||||
if (tokens != null)
|
||||
for (token of tokens) {
|
||||
// TODO: Potential timing attack, left side: true
|
||||
if (token !== this.oceanAddress) this.dtAddress = token
|
||||
}
|
||||
return this.dtAddress
|
||||
}
|
||||
|
||||
@ -855,7 +859,7 @@ export class OceanPool extends Pool {
|
||||
const factory = new this.web3.eth.Contract(this.factoryABI, this.factoryAddress)
|
||||
const events = await factory.getPastEvents('BPoolRegistered', {
|
||||
filter: {},
|
||||
fromBlock: BPFACTORY_DEPLOY_BLOCK,
|
||||
fromBlock: this.startBlock,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
events.sort((a, b) => (a.blockNumber > b.blockNumber ? 1 : -1))
|
||||
@ -920,7 +924,7 @@ export class OceanPool extends Pool {
|
||||
|
||||
const events = await factory.getPastEvents('BPoolRegistered', {
|
||||
filter: account ? { registeredBy: account } : {},
|
||||
fromBlock: BPFACTORY_DEPLOY_BLOCK,
|
||||
fromBlock: this.startBlock,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
for (let i = 0; i < events.length; i++) {
|
||||
@ -930,6 +934,21 @@ export class OceanPool extends Pool {
|
||||
return result
|
||||
}
|
||||
|
||||
private async getResult(account: string, event: EventData): Promise<PoolShare> {
|
||||
const shares = await super.sharesBalance(account, event.returnValues[0])
|
||||
if (parseFloat(shares) > 0) {
|
||||
const dtAddress = await this.getDTAddress(event.returnValues[0])
|
||||
if (dtAddress) {
|
||||
const onePool: PoolShare = {
|
||||
shares,
|
||||
poolAddress: event.returnValues[0],
|
||||
did: didPrefixed(didNoZeroX(dtAddress))
|
||||
}
|
||||
return onePool
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search all pools in which a user has shares
|
||||
* @param {String} account
|
||||
@ -941,23 +960,20 @@ export class OceanPool extends Pool {
|
||||
|
||||
const events = await factory.getPastEvents('BPoolRegistered', {
|
||||
filter: {},
|
||||
fromBlock: BPFACTORY_DEPLOY_BLOCK,
|
||||
fromBlock: this.startBlock,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
for (let i = 0; i < events.length; i++) {
|
||||
const shares = await super.sharesBalance(account, events[i].returnValues[0])
|
||||
if (parseFloat(shares) > 0) {
|
||||
const dtAddress = await this.getDTAddress(events[i].returnValues[0])
|
||||
if (dtAddress) {
|
||||
const onePool: PoolShare = {
|
||||
shares,
|
||||
poolAddress: events[i].returnValues[0],
|
||||
did: didPrefixed(didNoZeroX(dtAddress))
|
||||
}
|
||||
result.push(onePool)
|
||||
}
|
||||
}
|
||||
}
|
||||
let results = await Promise.all(
|
||||
events.map((event) => {
|
||||
return this.getResult(account, event)
|
||||
})
|
||||
)
|
||||
results = results.filter((share) => {
|
||||
return share !== undefined
|
||||
})
|
||||
|
||||
result.push(...results)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@ -984,43 +1000,55 @@ export class OceanPool extends Pool {
|
||||
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,
|
||||
if (startBlock === 0) startBlock = this.startBlock
|
||||
const swapTopic = super.getSwapEventSignature()
|
||||
const joinTopic = super.getJoinEventSignature()
|
||||
const exitTopic = super.getExitEventSignature()
|
||||
let addressTopic
|
||||
if (account)
|
||||
addressTopic = '0x000000000000000000000000' + account.substring(2).toLowerCase()
|
||||
else addressTopic = null
|
||||
const events = await this.web3.eth.getPastLogs({
|
||||
address: poolAddress,
|
||||
topics: [[swapTopic, joinTopic, exitTopic], addressTopic],
|
||||
fromBlock: startBlock,
|
||||
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: startBlock,
|
||||
toBlock: 'latest'
|
||||
let eventResults = await Promise.all(
|
||||
events.map((event) => {
|
||||
switch (event.topics[0]) {
|
||||
case swapTopic:
|
||||
return this.getEventData('swap', poolAddress, dtAddress, event)
|
||||
break
|
||||
case joinTopic:
|
||||
return this.getEventData('join', poolAddress, dtAddress, event)
|
||||
break
|
||||
case exitTopic:
|
||||
return this.getEventData('exit', poolAddress, dtAddress, event)
|
||||
break
|
||||
}
|
||||
})
|
||||
)
|
||||
eventResults = eventResults.filter((share) => {
|
||||
return share !== undefined
|
||||
})
|
||||
results.push(...eventResults)
|
||||
|
||||
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: startBlock,
|
||||
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]))
|
||||
}
|
||||
|
||||
// for (let i = 0; i < events.length; i++) {
|
||||
// switch (events[i].topics[0]) {
|
||||
// case swapTopic:
|
||||
// results.push(await this.getEventData('swap', poolAddress, dtAddress, events[i]))
|
||||
// break
|
||||
// case joinTopic:
|
||||
// results.push(await this.getEventData('join', poolAddress, dtAddress, events[i]))
|
||||
// break
|
||||
// case exitTopic:
|
||||
// results.push(await this.getEventData('exit', poolAddress, dtAddress, events[i]))
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
return results
|
||||
}
|
||||
|
||||
@ -1034,17 +1062,19 @@ export class OceanPool extends Pool {
|
||||
const factory = new this.web3.eth.Contract(this.factoryABI, this.factoryAddress)
|
||||
const events = await factory.getPastEvents('BPoolRegistered', {
|
||||
filter: {},
|
||||
fromBlock: BPFACTORY_DEPLOY_BLOCK,
|
||||
fromBlock: this.startBlock,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
for (let i = 0; i < events.length; i++) {
|
||||
const logs = await this.getPoolLogs(
|
||||
events[i].returnValues[0],
|
||||
events[i].blockNumber,
|
||||
account
|
||||
)
|
||||
for (let j = 0; j < logs.length; j++) results.push(logs[j])
|
||||
}
|
||||
|
||||
const eventsResults = await Promise.all(
|
||||
events.map((event) => {
|
||||
return this.getPoolLogs(event.returnValues[0], event.blockNumber, account)
|
||||
})
|
||||
)
|
||||
|
||||
const eventResults = eventsResults.reduce((elem1, elem2) => elem1.concat(elem2))
|
||||
results.push(...eventResults)
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
@ -1052,41 +1082,44 @@ export class OceanPool extends Pool {
|
||||
type: PoolTransactionType,
|
||||
poolAddress: string,
|
||||
dtAddress: string,
|
||||
data: EventData
|
||||
data: Log
|
||||
): Promise<PoolTransaction> {
|
||||
const blockDetails = await this.web3.eth.getBlock(data.blockNumber)
|
||||
let result: PoolTransaction = {
|
||||
poolAddress,
|
||||
dtAddress,
|
||||
caller: data.returnValues[0],
|
||||
caller: data.topics[1],
|
||||
transactionHash: data.transactionHash,
|
||||
blockNumber: data.blockNumber,
|
||||
timestamp: parseInt(String(blockDetails.timestamp)),
|
||||
type
|
||||
}
|
||||
|
||||
let params
|
||||
switch (type) {
|
||||
case 'swap':
|
||||
params = this.web3.eth.abi.decodeParameters(['uint256', 'uint256'], data.data)
|
||||
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])
|
||||
tokenIn: '0x' + data.topics[2].substring(data.topics[2].length - 40),
|
||||
tokenOut: '0x' + data.topics[2].substring(data.topics[3].length - 40),
|
||||
tokenAmountIn: this.web3.utils.fromWei(params[0]),
|
||||
tokenAmountOut: this.web3.utils.fromWei(params[1])
|
||||
}
|
||||
break
|
||||
case 'join':
|
||||
params = this.web3.eth.abi.decodeParameters(['uint256'], data.data)
|
||||
result = {
|
||||
...result,
|
||||
tokenIn: data.returnValues[1],
|
||||
tokenAmountIn: this.web3.utils.fromWei(data.returnValues[2])
|
||||
tokenIn: '0x' + data.topics[2].substring(data.topics[2].length - 40),
|
||||
tokenAmountIn: this.web3.utils.fromWei(params[0])
|
||||
}
|
||||
break
|
||||
case 'exit':
|
||||
params = this.web3.eth.abi.decodeParameters(['uint256'], data.data)
|
||||
result = {
|
||||
...result,
|
||||
tokenOut: data.returnValues[1],
|
||||
tokenAmountOut: this.web3.utils.fromWei(data.returnValues[2])
|
||||
tokenOut: '0x' + data.topics[2].substring(data.topics[2].length - 40),
|
||||
tokenAmountOut: this.web3.utils.fromWei(params[0])
|
||||
}
|
||||
break
|
||||
}
|
||||
|
@ -26,10 +26,9 @@ export class Pool extends PoolFactory {
|
||||
logger: Logger,
|
||||
factoryABI: AbiItem | AbiItem[] = null,
|
||||
poolABI: AbiItem | AbiItem[] = null,
|
||||
factoryAddress: string = null,
|
||||
gaslimit?: number
|
||||
factoryAddress: string = null
|
||||
) {
|
||||
super(web3, logger, factoryABI, factoryAddress, gaslimit)
|
||||
super(web3, logger, factoryABI, factoryAddress)
|
||||
if (poolABI) this.poolABI = poolABI
|
||||
else this.poolABI = jsonpoolABI.abi as AbiItem[]
|
||||
}
|
||||
@ -1150,4 +1149,43 @@ export class Pool extends PoolFactory {
|
||||
}
|
||||
return amount
|
||||
}
|
||||
|
||||
/**
|
||||
* Get LOG_SWAP encoded topic
|
||||
* @return {String}
|
||||
*/
|
||||
public getSwapEventSignature(): string {
|
||||
const abi = this.poolABI as AbiItem[]
|
||||
const eventdata = abi.find(function (o) {
|
||||
if (o.name === 'LOG_SWAP' && o.type === 'event') return o
|
||||
})
|
||||
const topic = this.web3.eth.abi.encodeEventSignature(eventdata as any)
|
||||
return topic
|
||||
}
|
||||
|
||||
/**
|
||||
* Get LOG_JOIN encoded topic
|
||||
* @return {String}
|
||||
*/
|
||||
public getJoinEventSignature(): string {
|
||||
const abi = this.poolABI as AbiItem[]
|
||||
const eventdata = abi.find(function (o) {
|
||||
if (o.name === 'LOG_JOIN' && o.type === 'event') return o
|
||||
})
|
||||
const topic = this.web3.eth.abi.encodeEventSignature(eventdata as any)
|
||||
return topic
|
||||
}
|
||||
|
||||
/**
|
||||
* Get LOG_EXIT encoded topic
|
||||
* @return {String}
|
||||
*/
|
||||
public getExitEventSignature(): string {
|
||||
const abi = this.poolABI as AbiItem[]
|
||||
const eventdata = abi.find(function (o) {
|
||||
if (o.name === 'LOG_EXIT' && o.type === 'event') return o
|
||||
})
|
||||
const topic = this.web3.eth.abi.encodeEventSignature(eventdata as any)
|
||||
return topic
|
||||
}
|
||||
}
|
||||
|
@ -15,8 +15,7 @@ export class PoolFactory {
|
||||
web3: Web3,
|
||||
logger: Logger,
|
||||
factoryABI: AbiItem | AbiItem[] = null,
|
||||
factoryAddress: string = null,
|
||||
gaslimit?: number
|
||||
factoryAddress: string = null
|
||||
) {
|
||||
this.web3 = web3
|
||||
|
||||
@ -25,7 +24,6 @@ export class PoolFactory {
|
||||
if (factoryAddress) {
|
||||
this.factoryAddress = factoryAddress
|
||||
}
|
||||
if (gaslimit) this.GASLIMIT_DEFAULT = gaslimit
|
||||
this.logger = logger
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,7 @@ export class OceanFixedRateExchange {
|
||||
public contract: Contract = null
|
||||
private logger: Logger
|
||||
public datatokens: DataTokens
|
||||
public startBlock: number
|
||||
|
||||
/**
|
||||
* Instantiate FixedRateExchange
|
||||
@ -53,10 +54,13 @@ export class OceanFixedRateExchange {
|
||||
fixedRateExchangeAddress: string = null,
|
||||
fixedRateExchangeABI: AbiItem | AbiItem[] = null,
|
||||
oceanAddress: string = null,
|
||||
datatokens: DataTokens
|
||||
datatokens: DataTokens,
|
||||
startBlock?: number
|
||||
) {
|
||||
this.web3 = web3
|
||||
this.fixedRateExchangeAddress = fixedRateExchangeAddress
|
||||
if (startBlock) this.startBlock = startBlock
|
||||
else this.startBlock = 0
|
||||
this.fixedRateExchangeABI =
|
||||
fixedRateExchangeABI || (defaultFixedRateExchangeABI.abi as AbiItem[])
|
||||
this.oceanAddress = oceanAddress
|
||||
@ -359,7 +363,7 @@ export class OceanFixedRateExchange {
|
||||
const result: FixedPriceExchange[] = []
|
||||
const events = await this.contract.getPastEvents('ExchangeCreated', {
|
||||
filter: { datatoken: dataTokenAddress.toLowerCase() },
|
||||
fromBlock: 0,
|
||||
fromBlock: this.startBlock,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
for (let i = 0; i < events.length; i++) {
|
||||
@ -388,7 +392,7 @@ export class OceanFixedRateExchange {
|
||||
const result: FixedPriceExchange[] = []
|
||||
const events = await this.contract.getPastEvents('ExchangeCreated', {
|
||||
filter: {},
|
||||
fromBlock: 0,
|
||||
fromBlock: this.startBlock,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
for (let i = 0; i < events.length; i++) {
|
||||
@ -411,7 +415,7 @@ export class OceanFixedRateExchange {
|
||||
const result: FixedPriceSwap[] = []
|
||||
const events = await this.contract.getPastEvents('Swapped', {
|
||||
filter: { exchangeId: exchangeId },
|
||||
fromBlock: 0,
|
||||
fromBlock: this.startBlock,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
for (let i = 0; i < events.length; i++) {
|
||||
@ -430,7 +434,7 @@ export class OceanFixedRateExchange {
|
||||
const result: FixedPriceSwap[] = []
|
||||
const events = await this.contract.getPastEvents('ExchangeCreated', {
|
||||
filter: {},
|
||||
fromBlock: 0,
|
||||
fromBlock: this.startBlock,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
for (let i = 0; i < events.length; i++) {
|
||||
|
@ -96,6 +96,11 @@ export class Config {
|
||||
* @type {any}
|
||||
*/
|
||||
public metadataContractABI?: AbiItem | AbiItem[]
|
||||
/**
|
||||
* block number of the deployment
|
||||
* @type {number}
|
||||
*/
|
||||
public startBlock?: number
|
||||
/**
|
||||
* Log level.
|
||||
* @type {boolean | LogLevel}
|
||||
|
@ -59,7 +59,8 @@ export class Ocean extends Instantiable {
|
||||
instanceConfig.config.poolFactoryABI,
|
||||
instanceConfig.config.poolABI,
|
||||
instanceConfig.config.poolFactoryAddress,
|
||||
instanceConfig.config.oceanTokenAddress
|
||||
instanceConfig.config.oceanTokenAddress,
|
||||
instanceConfig.config.startBlock
|
||||
)
|
||||
instance.fixedRateExchange = new OceanFixedRateExchange(
|
||||
instanceConfig.config.web3Provider,
|
||||
@ -67,7 +68,8 @@ export class Ocean extends Instantiable {
|
||||
instanceConfig.config.fixedRateExchangeAddress,
|
||||
instanceConfig.config.fixedRateExchangeAddressABI,
|
||||
instanceConfig.config.oceanTokenAddress,
|
||||
instance.datatokens
|
||||
instance.datatokens,
|
||||
instanceConfig.config.startBlock
|
||||
)
|
||||
instance.OnChainMetadataCache = new OnChainMetadataCache(
|
||||
instanceConfig.config.web3Provider,
|
||||
|
@ -27,7 +27,8 @@ const configs: ConfigHelperConfig[] = [
|
||||
factoryAddress: '0x1234',
|
||||
poolFactoryAddress: null,
|
||||
fixedRateExchangeAddress: null,
|
||||
metadataContractAddress: null
|
||||
metadataContractAddress: null,
|
||||
startBlock: 0
|
||||
},
|
||||
{
|
||||
// barge
|
||||
@ -40,7 +41,8 @@ const configs: ConfigHelperConfig[] = [
|
||||
factoryAddress: null,
|
||||
poolFactoryAddress: null,
|
||||
fixedRateExchangeAddress: null,
|
||||
metadataContractAddress: null
|
||||
metadataContractAddress: null,
|
||||
startBlock: 0
|
||||
},
|
||||
{
|
||||
networkId: 4,
|
||||
@ -52,7 +54,8 @@ const configs: ConfigHelperConfig[] = [
|
||||
factoryAddress: null,
|
||||
poolFactoryAddress: null,
|
||||
fixedRateExchangeAddress: null,
|
||||
metadataContractAddress: null
|
||||
metadataContractAddress: null,
|
||||
startBlock: 7294090
|
||||
},
|
||||
{
|
||||
networkId: 1,
|
||||
@ -64,7 +67,8 @@ const configs: ConfigHelperConfig[] = [
|
||||
factoryAddress: null,
|
||||
poolFactoryAddress: null,
|
||||
fixedRateExchangeAddress: null,
|
||||
metadataContractAddress: null
|
||||
metadataContractAddress: null,
|
||||
startBlock: 11105522
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -109,7 +109,8 @@ describe('Balancer flow', () => {
|
||||
OceanPoolFactory.abi as AbiItem[],
|
||||
OceanSPool.abi as AbiItem[],
|
||||
OceanPoolFactoryAddress,
|
||||
oceanTokenAddress
|
||||
oceanTokenAddress,
|
||||
0
|
||||
)
|
||||
assert(Pool !== null)
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user