From 7184969ece3b339abb9cbbf717a2109ab34fe59b Mon Sep 17 00:00:00 2001 From: ssallam Date: Wed, 2 Dec 2020 11:07:09 +0100 Subject: [PATCH] update schema to support pool reserve/price history and data token transaction history and balance history. --- package-lock.json | 2 +- package.json | 6 +- schema.graphql | 159 +++++++++++++-------------- src/mappings/datatoken.ts | 63 +++++------ src/mappings/dtfactory.ts | 15 ++- src/mappings/factory.ts | 43 +++++--- src/mappings/helpers.ts | 224 ++++++++++++++++++-------------------- src/mappings/pool.ts | 213 ++++++++++++------------------------ subgraph.yaml | 8 +- 9 files changed, 324 insertions(+), 409 deletions(-) diff --git a/package-lock.json b/package-lock.json index e37497b..bbd52b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "oceanpools", + "name": "ocean-subgraph", "version": "0.1.0", "lockfileVersion": 1, "requires": true, diff --git a/package.json b/package.json index a640c11..f4f713a 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,13 @@ { - "name": "oceanpools", + "name": "ocean-subgraph", "version": "0.1.0", "scripts": { "create": "graph create oceanprotocol/ocean-subgraph --node https://api.thegraph.com/deploy/", "create:local": "graph create oceanprotocol/ocean-subgraph --node http://127.0.0.1:8020", "codegen": "graph codegen --output-dir src/types/", "build": "graph build", - "deploy": "graph deploy oceanprotocol/oceanpools --ipfs https://api.thegraph.com/ipfs/ --node https://api.thegraph.com/deploy/", - "deploy:beta": "graph deploy oceanprotocol/oceanpools-beta --ipfs https://api.thegraph.com/ipfs/ --node https://api.thegraph.com/deploy/", + "deploy": "graph deploy oceanprotocol/ocean-subgraph --ipfs https://api.thegraph.com/ipfs/ --node https://api.thegraph.com/deploy/", + "deploy:beta": "graph deploy oceanprotocol/ocean-subgraph-beta --ipfs https://api.thegraph.com/ipfs/ --node https://api.thegraph.com/deploy/", "deploy:local": "graph deploy oceanprotocol/ocean-subgraph subgraph.yaml --debug --ipfs http://localhost:5001 --node http://127.0.0.1:8020" }, "devDependencies": { diff --git a/schema.graphql b/schema.graphql index d97e26d..0b91906 100644 --- a/schema.graphql +++ b/schema.graphql @@ -1,17 +1,20 @@ -type OceanPools @entity { +type PoolFactory @entity { id: ID! - color: String! # Bronze, Silver, Gold - poolCount: Int! # Number of pools - finalizedPoolCount: Int! # Number of finalized pools - pools: [Pool!] @derivedFrom(field: "factoryID") - txCount: BigInt! # Number of txs + totalLiquidity: BigDecimal! # All the pools liquidity value in Ocean totalSwapVolume: BigDecimal! # All the swap volume in Ocean totalSwapFee: BigDecimal! # All the swap fee in Ocean + + poolCount: Int! # Number of pools + finalizedPoolCount: Int! # Number of finalized pools + txCount: BigInt! # Number of txs + + pools: [Pool!] @derivedFrom(field: "factoryID") } type Pool @entity { id: ID! # Pool address + factoryID: PoolFactory! controller: Bytes! # Controller address publicSwap: Boolean! # isPublicSwap finalized: Boolean! # isFinalized @@ -20,30 +23,37 @@ type Pool @entity { cap: BigInt # Maximum supply if any active: Boolean! # isActive swapFee: BigDecimal! # Swap Fees + totalWeight: BigDecimal! totalShares: BigDecimal! # Total pool token shares totalSwapVolume: BigDecimal! # Total swap volume in OCEAN totalSwapFee: BigDecimal! # Total swap fee in OCEAN - liquidity: BigDecimal! # Pool liquidity value in OCEAN - tokensList: [Bytes!]! # Temp workaround until graph supports filtering on derived field + + datatokenReserve: BigDecimal! # Total pool reserve of Datatoken + oceanReserve: BigDecimal! # Total pool reserve of OCEAN + spotPrice: BigDecimal! + consumePrice: BigDecimal! + + tokenCount: BigInt! # Number of tokens in the pool + holderCount: BigInt! # Number of addresses holding a positive balance of pool shares + joinCount: BigInt! # liquidity has been added + exitCount: BigInt! # liquidity has been removed + swapCount: BigInt! + + datatokenAddress: String! + createTime: Int! # Block time pool was created + tx: Bytes # Pool creation transaction id + tokens: [PoolToken!] @derivedFrom(field: "poolId") shares: [PoolShare!] @derivedFrom(field: "poolId") - createTime: Int! # Block time pool was created - tokensCount: BigInt! # Number of tokens in the pool - holdersCount: BigInt! # Number of addresses holding a positive balance of BPT - joinsCount: BigInt! # liquidity has been added - exitsCount: BigInt! # liquidity has been removed - swapsCount: BigInt! - factoryID: OceanPools! - tx: Bytes # Pool creation transaction id - swaps: [Swap!] @derivedFrom(field: "poolAddress") + transactions: [PoolTransaction!] @derivedFrom(field: "poolAddress") } type PoolToken @entity { id: ID! # poolId + token address poolId: Pool! tokenId: Datatoken - address: String + tokenAddress: String balance: BigDecimal! denormWeight: BigDecimal! } @@ -55,70 +65,49 @@ type PoolShare @entity { balance: BigDecimal! } -type User @entity { - id: ID! - sharesOwned: [PoolShare!] @derivedFrom(field: "userAddress") - tokenBalancesOwned: [TokenBalance!] @derivedFrom(field: "userAddress") - tokensOwned: [Datatoken!] @derivedFrom(field: "minter") - poolTxs: [PoolTransaction!] @derivedFrom(field: "userAddress") - tokenTxs: [TokenTransaction!] @derivedFrom(field: "userAddress") - swaps: [Swap!] @derivedFrom(field: "userAddress") - -} - -type Swap @entity { - id: ID! # - caller: Bytes! # - tokenIn: Bytes! # - tokenInSym: String! # - tokenOut: Bytes! # - tokenOutSym: String! # - tokenAmountIn: BigDecimal! # - tokenAmountOut: BigDecimal! # - poolAddress: Pool - userAddress: User # User address that initiates the swap - value: BigDecimal! # Swap value in OCEAN +type PoolTransactionTokenValues @entity { + id: ID! # pool tx + tokenAddress + txId: PoolTransaction! + poolToken: PoolToken! + value: BigDecimal! + tokenReserve: BigDecimal! feeValue: BigDecimal! # Swap fee value in OCEAN - poolTotalSwapVolume: BigDecimal! # Total pool swap volume in OCEAN - poolTotalSwapFee: BigDecimal! # Total pool swap fee in OCEAN - poolLiquidity: BigDecimal! # Pool liquidity value in OCEAN - timestamp: Int! + type: String! } type PoolTransaction @entity { - id: ID! # Log ID + id: ID! # pool tx + poolAddress: Pool + userAddress: User # User address that initiates the swap + + sharesTransferAmount: BigDecimal! # + sharesBalance: BigDecimal! + + spotPrice: BigDecimal! + consumePrice: BigDecimal! tx: Bytes! event: String block: Int! timestamp: Int! gasUsed: BigDecimal! gasPrice: BigDecimal! - poolAddress: Pool - userAddress: User - action: SwapType - sender: Bytes + + tokens: [PoolTransactionTokenValues!] @derivedFrom(field: "txId") } -type TokenPrice @entity { +type DatatokenFactory @entity { id: ID! - symbol: String - name: String - decimals: Int! - price: BigDecimal! - poolLiquidity: BigDecimal! - poolTokenId: String -} -type OceanDatatokens @entity { - id: ID! tokenCount: Int! # Number of datatokens - datatokens: [Datatoken!] @derivedFrom(field: "factoryID") txCount: BigInt! # Number of txs + + datatokens: [Datatoken!] @derivedFrom(field: "factoryID") } type Datatoken @entity { id: ID! # token address - factoryID: OceanDatatokens! + factoryID: DatatokenFactory! + symbol: String name: String decimals: Int! @@ -127,24 +116,30 @@ type Datatoken @entity { supply: BigDecimal! minter: User! publisher: User! + + holderCount: BigInt! # Number of addresses holding a balance of datatoken + orderCount: BigInt! # Number of orders executed for this dataset + + createTime: Int! # Block time datatoken was created + tx: Bytes # Datatoken creation transaction id + balances: [TokenBalance!] @derivedFrom(field: "datatokenId") orders: [TokenOrder!] @derivedFrom(field: "datatokenId") - createTime: Int! # Block time datatoken was created - holdersCount: BigInt! # Number of addresses holding a balance of datatoken - orderCount: BigInt! # Number of orders executed for this dataset - tx: Bytes # Datatoken creation transaction id } type TokenOrder @entity { id: ID! # datatokenId + userAddress + tx + datatokenId: Datatoken! + consumer: User! payer: User! amount: BigDecimal! serviceId: Int! - timestamp: Int! marketFeeCollector: User marketFee: BigDecimal! + + timestamp: Int! tx: Bytes } @@ -157,23 +152,25 @@ type TokenBalance @entity { type TokenTransaction @entity { id: ID! # Log ID - tx: Bytes! + event: String - block: Int! - timestamp: Int! - gasUsed: BigDecimal! - gasPrice: BigDecimal! datatokenAddress: Datatoken userAddress: User - sender: Bytes + block: Int! + gasUsed: BigDecimal! + gasPrice: BigDecimal! + timestamp: Int! + tx: Bytes! } -enum SwapType { - swapExactAmountIn, - swapExactAmountOut, - joinswapExternAmountIn, - joinswapPoolAmountOut, - exitswapPoolAmountIn, - exitswapExternAmountOut -} \ No newline at end of file +type User @entity { + id: ID! + + sharesOwned: [PoolShare!] @derivedFrom(field: "userAddress") + tokenBalancesOwned: [TokenBalance!] @derivedFrom(field: "userAddress") + tokensOwned: [Datatoken!] @derivedFrom(field: "minter") + poolTransactions: [PoolTransaction!] @derivedFrom(field: "userAddress") + tokenTransactions: [TokenTransaction!] @derivedFrom(field: "userAddress") + orders: [TokenOrder!] @derivedFrom(field: "payer") +} diff --git a/src/mappings/datatoken.ts b/src/mappings/datatoken.ts index 5713646..7f45825 100644 --- a/src/mappings/datatoken.ts +++ b/src/mappings/datatoken.ts @@ -1,21 +1,16 @@ -import { BigInt, Address, Bytes, store, BigDecimal } from '@graphprotocol/graph-ts' +import { BigInt, BigDecimal } from '@graphprotocol/graph-ts' import { OrderStarted, Transfer } from '../types/templates/Datatoken/Datatoken' -import { Datatoken as DatatokenTemplate } from '../types/templates/Datatoken/Datatoken' import { log } from '@graphprotocol/graph-ts' import { - OceanDatatokens, - Datatoken, PoolShare, Pool, User, TokenBalance, TokenOrder + Datatoken, TokenBalance, TokenOrder } from '../types/schema' import { - hexToDecimal, - bigIntToDecimal, - tokenToDecimal, - createTokenBalanceEntity, - updateDatatokenBalance, - saveTokenTransaction, - ZERO_BD, createPoolShareEntity, createUserEntity + tokenToDecimal, + updateTokenBalance, + ZERO_BD, + MINUS_1, saveTokenTransaction } from './helpers' /************************************ @@ -43,36 +38,27 @@ export function handleTransfer(event: Transfer): void { let datatoken = Datatoken.load(tokenId) if (isMint) { - createTokenBalanceEntity(tokenBalanceToId, tokenId, tokenShareTo) tokenBalanceTo = TokenBalance.load(tokenBalanceToId) - let user = User.load(tokenShareTo) - oldBalanceTo = tokenBalanceTo.balance - tokenBalanceTo.balance += amount - tokenBalanceTo.save() - datatoken.supply += amount + oldBalanceTo = (tokenBalanceTo == null) ? ZERO_BD : tokenBalanceTo.balance + datatoken.supply = datatoken.supply.plus(amount) + updateTokenBalance(tokenBalanceToId, tokenId, tokenShareTo, amount) + } else if (isBurn) { - createTokenBalanceEntity(tokenBalanceFromId, tokenId, tokenShareFrom) tokenBalanceFrom = TokenBalance.load(tokenBalanceFromId) - let user = User.load(tokenShareFrom) - oldBalanceFrom = tokenBalanceFrom.balance - tokenBalanceFrom.balance -= amount - tokenBalanceFrom.save() - datatoken.supply -= amount + oldBalanceFrom = (tokenBalanceFrom == null) ? ZERO_BD : tokenBalanceFrom.balance + datatoken.supply = datatoken.supply.minus(amount) + updateTokenBalance(tokenBalanceFromId, tokenId, tokenShareFrom, amount.times(MINUS_1)) } else { - createTokenBalanceEntity(tokenBalanceFromId, tokenId, tokenShareFrom) - let userFrom = User.load(tokenShareFrom) tokenBalanceFrom = TokenBalance.load(tokenBalanceFromId) - oldBalanceFrom = tokenBalanceFrom.balance - tokenBalanceFrom.balance -= amount - tokenBalanceFrom.save() + oldBalanceFrom = (tokenBalanceFrom == null) ? ZERO_BD : tokenBalanceFrom.balance + datatoken.supply = datatoken.supply.minus(amount) + updateTokenBalance(tokenBalanceFromId, tokenId, tokenShareFrom, amount.times(MINUS_1)) - createTokenBalanceEntity(tokenBalanceToId, tokenId, tokenShareTo) - let userTo = User.load(tokenShareTo) tokenBalanceTo = TokenBalance.load(tokenBalanceToId) - oldBalanceTo = tokenBalanceTo.balance - tokenBalanceTo.balance += amount - tokenBalanceTo.save() + oldBalanceTo = (tokenBalanceTo == null) ? ZERO_BD : tokenBalanceTo.balance + datatoken.supply = datatoken.supply.plus(amount) + updateTokenBalance(tokenBalanceToId, tokenId, tokenShareTo, amount) } if ( @@ -80,7 +66,7 @@ export function handleTransfer(event: Transfer): void { && tokenBalanceTo.balance.notEqual(ZERO_BD) && oldBalanceTo.equals(ZERO_BD) ) { - datatoken.holdersCount += BigInt.fromI32(1) + datatoken.holderCount = datatoken.holderCount.plus(BigInt.fromI32(1)) } if ( @@ -88,10 +74,11 @@ export function handleTransfer(event: Transfer): void { && tokenBalanceFrom.balance.equals(ZERO_BD) && oldBalanceFrom.notEqual(ZERO_BD) ) { - datatoken.holdersCount -= BigInt.fromI32(1) + datatoken.holderCount = datatoken.holderCount.minus(BigInt.fromI32(1)) } datatoken.save() + saveTokenTransaction(event, 'Transfer') } export function handleOrderStarted(event: OrderStarted): void { @@ -100,7 +87,6 @@ export function handleOrderStarted(event: OrderStarted): void { let datatoken = Datatoken.load(tokenId) if (datatoken == null) return - let payer = event.params.payer.toHex() // let feeCollector = event.params.mrktFeeCollector // let marketFee = event.params.marketFee @@ -123,6 +109,9 @@ export function handleOrderStarted(event: OrderStarted): void { order.tx = tx order.save() - datatoken.orderCount = datatoken.orderCount + BigInt.fromI32(1) + + datatoken.orderCount = datatoken.orderCount.plus(BigInt.fromI32(1)) datatoken.save() + + saveTokenTransaction(event, 'OrderStarted') } diff --git a/src/mappings/dtfactory.ts b/src/mappings/dtfactory.ts index be766a8..d88054c 100644 --- a/src/mappings/dtfactory.ts +++ b/src/mappings/dtfactory.ts @@ -1,6 +1,6 @@ -import { Address, BigInt, BigDecimal } from '@graphprotocol/graph-ts' +import { BigInt } from '@graphprotocol/graph-ts' import { TokenRegistered } from '../types/DTFactory/DTFactory' -import { OceanDatatokens, Datatoken } from '../types/schema' +import { DatatokenFactory, Datatoken } from '../types/schema' import { Datatoken as DatatokenContract } from '../types/templates' import { tokenToDecimal, @@ -9,11 +9,11 @@ import { import { log } from '@graphprotocol/graph-ts' export function handleNewToken(event: TokenRegistered): void { - let factory = OceanDatatokens.load('1') + let factory = DatatokenFactory.load('1') // if no factory yet, set up blank initial if (factory == null) { - factory = new OceanDatatokens('1') + factory = new DatatokenFactory('1') factory.tokenCount = 0 factory.txCount = BigInt.fromI32(0) } @@ -22,6 +22,7 @@ export function handleNewToken(event: TokenRegistered): void { log.error('************************ handleNewToken: datatokenId {}', [datatoken.id.toString()]) datatoken.factoryID = event.address.toHexString() + datatoken.symbol = event.params.tokenSymbol datatoken.name = event.params.tokenName datatoken.decimals = 18 @@ -30,9 +31,11 @@ export function handleNewToken(event: TokenRegistered): void { datatoken.supply = ZERO_BD datatoken.minter = event.params.registeredBy.toHex() datatoken.publisher = event.params.registeredBy.toHex() - datatoken.createTime = event.block.timestamp.toI32() - datatoken.holdersCount = BigInt.fromI32(0) + + datatoken.holderCount = BigInt.fromI32(0) datatoken.orderCount = BigInt.fromI32(0) + + datatoken.createTime = event.block.timestamp.toI32() datatoken.tx = event.transaction.hash datatoken.save() diff --git a/src/mappings/factory.ts b/src/mappings/factory.ts index 07e57a7..23ca33f 100644 --- a/src/mappings/factory.ts +++ b/src/mappings/factory.ts @@ -1,6 +1,6 @@ import { Address, BigInt, BigDecimal } from '@graphprotocol/graph-ts' import { BPoolRegistered } from '../types/Factory/Factory' -import { OceanPools, Pool } from '../types/schema' +import { PoolFactory, Pool } from '../types/schema' import { Pool as PoolContract } from '../types/templates' import { ZERO_BD, @@ -8,41 +8,54 @@ import { import { log } from '@graphprotocol/graph-ts' export function handleNewPool(event: BPoolRegistered): void { - let factory = OceanPools.load('1') + let factory = PoolFactory.load('1') // if no factory yet, set up blank initial if (factory == null) { - factory = new OceanPools('1') - factory.color = 'Bronze' - factory.poolCount = 0 - factory.finalizedPoolCount = 0 - factory.txCount = BigInt.fromI32(0) + factory = new PoolFactory('1') factory.totalLiquidity = ZERO_BD factory.totalSwapVolume = ZERO_BD factory.totalSwapFee = ZERO_BD + + factory.poolCount = 0 + factory.finalizedPoolCount = 0 + factory.txCount = BigInt.fromI32(0) } let pool = new Pool(event.params.bpoolAddress.toHexString()) log.error('************************ handleNewPool: poolId {}', [pool.id.toString()]) + + pool.factoryID = event.address.toHexString() pool.controller = event.params.registeredBy pool.publicSwap = false pool.finalized = false + pool.symbol = '' + pool.name = '' + // pool.cap = pool.active = true pool.swapFee = BigDecimal.fromString('0.000001') + pool.totalWeight = ZERO_BD pool.totalShares = ZERO_BD pool.totalSwapVolume = ZERO_BD pool.totalSwapFee = ZERO_BD - pool.liquidity = ZERO_BD + + pool.datatokenReserve = ZERO_BD + pool.oceanReserve = ZERO_BD + pool.spotPrice = ZERO_BD //: BigDecimal! + pool.consumePrice = ZERO_BD //: BigDecimal! + + pool.tokenCount = BigInt.fromI32(0) + pool.holderCount = BigInt.fromI32(0) + pool.joinCount = BigInt.fromI32(0) + pool.exitCount = BigInt.fromI32(0) + pool.swapCount = BigInt.fromI32(0) + + pool.datatokenAddress = '' + pool.createTime = event.block.timestamp.toI32() - pool.tokensCount = BigInt.fromI32(0) - pool.holdersCount = BigInt.fromI32(0) - pool.joinsCount = BigInt.fromI32(0) - pool.exitsCount = BigInt.fromI32(0) - pool.swapsCount = BigInt.fromI32(0) - pool.factoryID = event.address.toHexString() - pool.tokensList = [] pool.tx = event.transaction.hash + pool.save() factory.poolCount = factory.poolCount + 1 diff --git a/src/mappings/helpers.ts b/src/mappings/helpers.ts index e3d0378..d215bd2 100644 --- a/src/mappings/helpers.ts +++ b/src/mappings/helpers.ts @@ -1,6 +1,5 @@ import { BigDecimal, - Address, BigInt, Bytes, dataSource, @@ -11,14 +10,18 @@ import { User, PoolToken, PoolShare, - TokenPrice, PoolTransaction, - OceanPools, Datatoken, TokenBalance, TokenTransaction + PoolFactory, + Datatoken, + TokenBalance, + TokenTransaction, + PoolTransactionTokenValues } from '../types/schema' -import { BToken } from '../types/templates/Pool/BToken' import { log } from '@graphprotocol/graph-ts' -export let ZERO_BD = BigDecimal.fromString('0') +export let ZERO_BD = BigDecimal.fromString('0.0') +export let MINUS_1 = BigDecimal.fromString('-1.0') +export let ONE = BigDecimal.fromString('1.0') let network = dataSource.network() @@ -60,127 +63,107 @@ export function createPoolTokenEntity(id: string, pool: string, address: string) let poolToken = new PoolToken(id) poolToken.poolId = pool poolToken.tokenId = datatoken ? datatoken.id: '' - poolToken.address = address + poolToken.tokenAddress = address poolToken.balance = ZERO_BD poolToken.denormWeight = ZERO_BD poolToken.save() } -export function updatePoolLiquidity(id: string): void { - let pool = Pool.load(id) - let tokensList: Array = pool.tokensList +export function updatePoolTransactionToken( + poolTx: string, poolTokenId: string, amount: BigDecimal, + balance: BigDecimal, feeValue: BigDecimal +): void { - if (!tokensList || pool.tokensCount.lt(BigInt.fromI32(2)) || !pool.publicSwap) return - if (tokensList[0] != Address.fromString(OCEAN)) return - - // Find pool liquidity - - let hasPrice = false - let hasOceanPrice = false - let poolOcnLiquidity = ZERO_BD - let poolDTLiquidity = ZERO_BD - return - - let oceanPoolTokenId = id.concat('-').concat(OCEAN) - let oceanPoolToken = PoolToken.load(oceanPoolTokenId) - poolOcnLiquidity = oceanPoolToken.balance.div(oceanPoolToken.denormWeight).times(pool.totalWeight) - let DT = tokensList[1].toHexString() - let dtTokenPrice = TokenPrice.load(DT) - if (dtTokenPrice !== null) { - let poolTokenId = id.concat('-').concat(DT) - let poolToken = PoolToken.load(poolTokenId) - poolDTLiquidity = TokenPrice.price.times(poolToken.balance).div(poolToken.denormWeight).times(pool.totalWeight) - hasPrice = true + let poolToken = PoolToken.load(poolTokenId) + let ptxTokenValuesId = poolTx.concat('-').concat(poolToken.tokenAddress) + let ptxTokenValues = PoolTransactionTokenValues.load(ptxTokenValuesId) + if (ptxTokenValues == null) { + ptxTokenValues = new PoolTransactionTokenValues(ptxTokenValuesId) + } + ptxTokenValues.txId = poolTx + ptxTokenValues.poolToken = poolTokenId + ptxTokenValues.value = amount + ptxTokenValues.tokenReserve = balance.plus(amount) + ptxTokenValues.feeValue = feeValue + if (amount.lt(ZERO_BD)) { + ptxTokenValues.type = 'out' + } else { + ptxTokenValues.type = 'in' } - // // Create or update token price - // - // if (hasPrice) { - // for (let i: i32 = 0; i < tokensList.length; i++) { - // let tokenPriceId = tokensList[i].toHexString() - // let tokenPrice = TokenPrice.load(tokenPriceId) - // if (tokenPrice == null) { - // tokenPrice = new TokenPrice(tokenPriceId) - // tokenPrice.poolTokenId = '' - // tokenPrice.poolLiquidity = ZERO_BD - // } - // - // let poolTokenId = id.concat('-').concat(tokenPriceId) - // let poolToken = PoolToken.load(poolTokenId) - // - // if ( - // (tokenPrice.poolTokenId == poolTokenId || poolLiquidity.gt(tokenPrice.poolLiquidity)) && - // (tokenPriceId != WETH.toString() || (pool.tokensCount.equals(BigInt.fromI32(2)) && hasUsdPrice)) - // ) { - // tokenPrice.price = ZERO_BD - // - // if (poolToken.balance.gt(ZERO_BD)) { - // tokenPrice.price = poolLiquidity.div(pool.totalWeight).times(poolToken.denormWeight).div(poolToken.balance) - // } - // - // tokenPrice.symbol = poolToken.symbol - // tokenPrice.name = poolToken.name - // tokenPrice.decimals = poolToken.decimals - // tokenPrice.poolLiquidity = poolLiquidity - // tokenPrice.poolTokenId = poolTokenId - // tokenPrice.save() - // } - // } - // } - - // Update pool liquidity - - let liquidity = ZERO_BD - let denormWeight = ZERO_BD - - for (let i: i32 = 0; i < tokensList.length; i++) { - let tokenPriceId = tokensList[i].toHexString() - let tokenPrice = TokenPrice.load(tokenPriceId) - if (tokenPrice !== null) { - let poolTokenId = id.concat('-').concat(tokenPriceId) - let poolToken = PoolToken.load(poolTokenId) - if (poolToken.denormWeight.gt(denormWeight)) { - denormWeight = poolToken.denormWeight - liquidity = tokenPrice.price.times(poolToken.balance).div(poolToken.denormWeight).times(pool.totalWeight) - } - } - } - - let factory = OceanPools.load('1') - factory.totalLiquidity = factory.totalLiquidity.minus(pool.liquidity).plus(liquidity) - factory.save() - - pool.liquidity = liquidity - pool.save() + ptxTokenValues.save() } +export function createPoolTransaction(event: ethereum.Event, event_type: string, userAddress: string): void { + let poolId = event.address.toHex() + let pool = Pool.load(poolId) + + let ptx = event.transaction.hash.toHexString() + + let ocnToken = PoolToken.load(poolId.concat('-').concat(OCEAN)) + let dtToken = PoolToken.load(poolId.concat('-').concat(pool.datatokenAddress)) + if (ocnToken == null || dtToken == null) return + + let poolTx = PoolTransaction.load(ptx) + if (poolTx == null) { + poolTx = new PoolTransaction(ptx) + } + + poolTx.poolAddress = poolId + poolTx.userAddress = userAddress + poolTx.sharesTransferAmount = ZERO_BD + poolTx.sharesBalance = ZERO_BD +// poolTx.spotPrice = ZERO_BD + poolTx.spotPrice = calcSpotPrice( + ocnToken.denormWeight, dtToken.denormWeight, ocnToken.balance, dtToken.balance, pool.swapFee) + // poolTx.consumePrice = calcInGivenOut( + // ocnToken.denormWeight, dtToken.denormWeight, ocnToken.balance, dtToken.balance, + // ONE, pool.swapFee) + poolTx.consumePrice = ZERO_BD + + poolTx.tx = event.transaction.hash + poolTx.event = event_type + poolTx.block = event.block.number.toI32() + poolTx.timestamp = event.block.timestamp.toI32() + poolTx.gasUsed = event.transaction.gasUsed.toBigDecimal() + poolTx.gasPrice = event.transaction.gasPrice.toBigDecimal() + + poolTx.save() +} + +export function calcSpotPrice( + wIn: BigDecimal, wOut: BigDecimal, + balanceIn: BigDecimal, balanceOut: BigDecimal, + swapFee: BigDecimal +): BigDecimal { + let numer = balanceIn.div(wIn) + let denom = balanceOut.div(wOut) + let ratio = numer.div(denom) + let scale = ONE.div(ONE.minus(swapFee)) + return ratio.times(scale) +} + +// export function calcInGivenOut( +// wIn: BigDecimal, wOut: BigDecimal, balanceIn: BigDecimal, balanceOut: BigDecimal, +// amountOut: BigDecimal, swapFee: BigDecimal): BigDecimal { +// +// let weightRatio = wOut.div(wIn) +// let diff = balanceOut.minus(amountOut) +// let y = balanceOut.div(diff) +// y.toString() +// +// let foo = BigDecimal.fromString(Math.pow(y, weightRatio).toString()) - ONE +// return balanceIn.times(foo / (ONE - swapFee)) +// } + + export function decrPoolCount(finalized: boolean): void { - let factory = OceanPools.load('1') + let factory = PoolFactory.load('1') factory.poolCount -= 1 if (finalized) factory.finalizedPoolCount -= 1 factory.save() } -export function savePoolTransaction(event: ethereum.Event, eventName: string): void { - let tx = event.transaction.hash.toHexString().concat('-').concat(event.logIndex.toString()) - let userAddress = event.transaction.from.toHex() - let transaction = PoolTransaction.load(tx) - if (transaction == null) { - transaction = new PoolTransaction(tx) - } - transaction.event = eventName - transaction.poolAddress = event.address.toHex() - transaction.userAddress = userAddress - transaction.gasUsed = event.transaction.gasUsed.toBigDecimal() - transaction.gasPrice = event.transaction.gasPrice.toBigDecimal() - transaction.tx = event.transaction.hash - transaction.timestamp = event.block.timestamp.toI32() - transaction.block = event.block.number.toI32() - transaction.save() - - createUserEntity(userAddress) -} - export function saveTokenTransaction(event: ethereum.Event, eventName: string): void { let tx = event.transaction.hash.toHexString().concat('-').concat(event.logIndex.toString()) let userAddress = event.transaction.from.toHex() @@ -208,17 +191,16 @@ export function createUserEntity(address: string): void { } } -export function createTokenBalanceEntity(id: string, token: string, user: string): void { - if (TokenBalance.load(id) != null) return +export function updateTokenBalance(id: string, token: string, user: string, amount: BigDecimal): void { + let tokenBalance = TokenBalance.load(id) + if (tokenBalance == null) { + tokenBalance = new TokenBalance(id) + createUserEntity(user) + tokenBalance.userAddress = user + tokenBalance.datatokenId = token + tokenBalance.balance = ZERO_BD + } - let tokenBalance = new TokenBalance(id) - createUserEntity(user) - tokenBalance.userAddress = user - tokenBalance.datatokenId = token - tokenBalance.balance = ZERO_BD + tokenBalance.balance = tokenBalance.balance.plus(amount) tokenBalance.save() } - -export function updateDatatokenBalance(): void { - -} \ No newline at end of file diff --git a/src/mappings/pool.ts b/src/mappings/pool.ts index 6eb55a1..457a980 100644 --- a/src/mappings/pool.ts +++ b/src/mappings/pool.ts @@ -1,27 +1,25 @@ -import { BigInt, Address, Bytes, store, BigDecimal } from '@graphprotocol/graph-ts' +import {BigInt, Address, BigDecimal} from '@graphprotocol/graph-ts' import { LOG_CALL, LOG_JOIN, LOG_EXIT, LOG_SWAP, Transfer } from '../types/templates/Pool/Pool' -import { Pool as BPool } from '../types/templates/Pool/Pool' import { log } from '@graphprotocol/graph-ts' import { - OceanPools, - Pool, - PoolToken, - PoolShare, - Swap, - TokenPrice, Datatoken + PoolFactory, + Pool, + PoolToken, + PoolShare, + Datatoken, PoolTransaction, PoolTransactionTokenValues } from '../types/schema' import { hexToDecimal, - bigIntToDecimal, tokenToDecimal, createPoolShareEntity, createPoolTokenEntity, - updatePoolLiquidity, - savePoolTransaction, ZERO_BD, - decrPoolCount + MINUS_1, + decrPoolCount, + updatePoolTransactionToken, + createPoolTransaction, OCEAN, } from './helpers' /************************************ @@ -36,18 +34,13 @@ export function handleSetSwapFee(event: LOG_CALL, swapFeeStr: string=null): void } pool.swapFee = hexToDecimal(swapFeeStr, 18) pool.save() - - // savePoolTransaction(event, 'setSwapFee') } export function handleSetController(event: LOG_CALL): void { let poolId = event.address.toHex() let pool = Pool.load(poolId) - let controller = Address.fromString(event.params.data.toHexString().slice(-40)) - pool.controller = controller + pool.controller = Address.fromString(event.params.data.toHexString().slice(-40)) pool.save() - - // savePoolTransaction(event, 'setController') } export function handleSetPublicSwap(event: LOG_CALL): void { @@ -55,36 +48,19 @@ export function handleSetPublicSwap(event: LOG_CALL): void { let pool = Pool.load(poolId) pool.publicSwap = event.params.data.toHexString().slice(-1) == '1' pool.save() - - // savePoolTransaction(event, 'setPublicSwap') } export function handleFinalize(event: LOG_CALL): void { let poolId = event.address.toHex() let pool = Pool.load(poolId) - // let balance = BigDecimal.fromString('100') pool.finalized = true pool.symbol = 'BPT' pool.publicSwap = true - // pool.totalShares = balance pool.save() - /* - let poolShareId = poolId.concat('-').concat(event.params.caller.toHex()) - let poolShare = PoolShare.load(poolShareId) - if (poolShare == null) { - createPoolShareEntity(poolShareId, poolId, event.params.caller.toHex()) - poolShare = PoolShare.load(poolShareId) - } - poolShare.balance = balance - poolShare.save() - */ - - let factory = OceanPools.load('1') + let factory = PoolFactory.load('1') factory.finalizedPoolCount = factory.finalizedPoolCount + 1 factory.save() - - // savePoolTransaction(event, 'finalize') } export function handleSetup(event: LOG_CALL): void { @@ -107,30 +83,24 @@ export function handleSetup(event: LOG_CALL): void { let baseTokenAmount = data.slice(266,330) // (74+(3*64),74+(4*64)) let baseTokenWeight = data.slice(330,394) // (74+(4*64),74+(5*64)) let swapFee = data.slice(394) // (74+(5*64), END) - // log.error('handleSetup: ##{}, {}, {}, {}, {}, {}, {}##, \nDATA=##{} ##\n lenData={}', - // [dataTokenAddress, dataTokenAmount, dataTokenWeight, baseTokenAddress, baseTokenAmount, baseTokenWeight, swapFee, data, BigInt.fromI32(data.length).toString()]) _handleRebind(event, poolId, dataTokenAddress, dataTokenAmount, dataTokenWeight) + _handleRebind(event, poolId, baseTokenAddress, baseTokenAmount, baseTokenWeight) handleSetSwapFee(event, swapFee) handleFinalize(event) - savePoolTransaction(event, 'setup') } export function _handleRebind(event: LOG_CALL, poolId: string, tokenAddress: string, balanceStr: string, denormWeightStr: string): void { let pool = Pool.load(poolId) let decimals = BigInt.fromI32(18).toI32() - let tokenBytes = Bytes.fromHexString(tokenAddress) as Bytes - let tokensList = pool.tokensList || [] - if (tokensList.indexOf(tokenBytes) == -1 ) { - tokensList.push(tokenBytes) + if (tokenAddress != OCEAN ) { + pool.datatokenAddress = tokenAddress } - pool.tokensList = tokensList - pool.tokensCount = BigInt.fromI32(tokensList.length) + pool.tokenCount = BigInt.fromI32(2) let address = Address.fromString(tokenAddress) let denormWeight = hexToDecimal(denormWeightStr, decimals) - let poolTokenId = poolId.concat('-').concat(address.toHexString()) let poolToken = PoolToken.load(poolTokenId) if (poolToken == null) { @@ -146,9 +116,9 @@ export function _handleRebind(event: LOG_CALL, poolId: string, tokenAddress: str } } - let balance = hexToDecimal(balanceStr, decimals) poolToken.balance = balance + poolToken.denormWeight = denormWeight poolToken.save() if (balance.equals(ZERO_BD)) { @@ -156,8 +126,6 @@ export function _handleRebind(event: LOG_CALL, poolId: string, tokenAddress: str pool.active = false } pool.save() - - updatePoolLiquidity(poolId) } export function handleRebind(event: LOG_CALL): void { @@ -169,9 +137,6 @@ export function handleRebind(event: LOG_CALL): void { event.params.data.toHexString().slice(74,138), event.params.data.toHexString().slice(138) ) - - savePoolTransaction(event, 'rebind') - } /************************************ @@ -182,13 +147,17 @@ export function handleJoinPool(event: LOG_JOIN): void { let poolId = event.address.toHex() let pool = Pool.load(poolId) - pool.joinsCount = pool.joinsCount.plus(BigInt.fromI32(1)) + if (pool.finalized == false){ + return + } + + pool.joinCount = pool.joinCount.plus(BigInt.fromI32(1)) pool.save() let address = event.params.tokenIn.toHex() - let poolTokenId = poolId.concat('-').concat(address.toString()) + let poolTokenId = poolId.concat('-').concat(address) let poolToken = PoolToken.load(poolTokenId) - if (!poolToken) { + if (poolToken == null) { return } @@ -199,8 +168,12 @@ export function handleJoinPool(event: LOG_JOIN): void { poolToken.balance = poolToken.balance.plus(tokenAmountIn) poolToken.save() - updatePoolLiquidity(poolId) - savePoolTransaction(event, 'join') + createPoolTransaction(event, 'join', event.params.caller.toHexString()) + updatePoolTransactionToken( + event.transaction.hash.toHexString(), poolTokenId, + tokenAmountIn, poolToken.balance, + tokenAmountIn.times(pool.swapFee) + ) } export function handleExitPool(event: LOG_EXIT): void { @@ -222,15 +195,19 @@ export function handleExitPool(event: LOG_EXIT): void { poolToken.save() let pool = Pool.load(poolId) - pool.exitsCount = pool.exitsCount.plus(BigInt.fromI32(1)) + pool.exitCount = pool.exitCount.plus(BigInt.fromI32(1)) if (newAmount.equals(ZERO_BD)) { decrPoolCount(pool.finalized) pool.active = false } pool.save() - updatePoolLiquidity(poolId) - savePoolTransaction(event, 'exit') + createPoolTransaction(event, 'exit', event.params.caller.toHexString()) + updatePoolTransactionToken( + event.transaction.hash.toHexString(), poolTokenId, + tokenAmountOut.times(MINUS_1), poolToken.balance, + tokenAmountOut.times(pool.swapFee) + ) } /************************************ @@ -239,6 +216,7 @@ export function handleExitPool(event: LOG_EXIT): void { export function handleSwap(event: LOG_SWAP): void { let poolId = event.address.toHex() + let ptx = event.transaction.hash.toHexString() let tokenIn = event.params.tokenIn.toHex() let poolTokenInId = poolId.concat('-').concat(tokenIn.toString()) @@ -261,84 +239,22 @@ export function handleSwap(event: LOG_SWAP): void { poolTokenOut.balance = newAmountOut poolTokenOut.save() - updatePoolLiquidity(poolId) - - let swapId = event.transaction.hash.toHexString().concat('-').concat(event.logIndex.toString()) - let swap = Swap.load(swapId) - if (swap == null) { - swap = new Swap(swapId) - } - let pool = Pool.load(poolId) - let tokensList: Array = pool.tokensList - let tokenOutPriceValue = ZERO_BD - let tokenOutPrice = TokenPrice.load(tokenOut) - if (tokenOutPrice != null) { - tokenOutPriceValue = tokenOutPrice.price - } else { - for (let i: i32 = 0; i < tokensList.length; i++) { - let tokenPriceId = tokensList[i].toHexString() - if (!tokenOutPriceValue.gt(ZERO_BD) && tokenPriceId !== tokenOut) { - let tokenPrice = TokenPrice.load(tokenPriceId) - if (tokenPrice !== null && tokenPrice.price.gt(ZERO_BD)) { - let poolTokenId = poolId.concat('-').concat(tokenPriceId) - let poolToken = PoolToken.load(poolTokenId) - tokenOutPriceValue = tokenPrice.price - .times(poolToken.balance) - .div(poolToken.denormWeight) - .times(poolTokenOut.denormWeight) - .div(poolTokenOut.balance) - } - } - } - } - - let totalSwapVolume = pool.totalSwapVolume - let totalSwapFee = pool.totalSwapFee - let liquidity = pool.liquidity - let swapValue = ZERO_BD - let swapFeeValue = ZERO_BD - - if (tokenOutPriceValue.gt(ZERO_BD)) { - swapValue = tokenOutPriceValue.times(tokenAmountOut) - swapFeeValue = swapValue.times(pool.swapFee) - totalSwapVolume = totalSwapVolume.plus(swapValue) - totalSwapFee = totalSwapFee.plus(swapFeeValue) - - let factory = OceanPools.load('1') - factory.totalSwapVolume = factory.totalSwapVolume.plus(swapValue) - factory.totalSwapFee = factory.totalSwapFee.plus(swapFeeValue) - factory.save() - - pool.totalSwapVolume = totalSwapVolume - pool.totalSwapFee = totalSwapFee - } - pool.swapsCount += BigInt.fromI32(1) + pool.swapCount += BigInt.fromI32(1) if (newAmountIn.equals(ZERO_BD) || newAmountOut.equals(ZERO_BD)) { decrPoolCount(pool.finalized) pool.active = false } pool.save() - swap.caller = event.params.caller - swap.tokenIn = event.params.tokenIn - swap.tokenInSym = (dtIn == null) ? 'OCEAN' : dtIn.symbol - swap.tokenOut = event.params.tokenOut - swap.tokenOutSym = (dtOut == null) ? 'OCEAN' : dtOut.symbol - swap.tokenAmountIn = tokenAmountIn - swap.tokenAmountOut = tokenAmountOut - swap.poolAddress = event.address.toHex() - swap.userAddress = event.transaction.from.toHex() - swap.poolTotalSwapVolume = totalSwapVolume - swap.poolTotalSwapFee = totalSwapFee - swap.poolLiquidity = liquidity - swap.value = swapValue - swap.feeValue = swapFeeValue - swap.timestamp = event.block.timestamp.toI32() - swap.save() - - savePoolTransaction(event, 'swap') + createPoolTransaction(event, 'swap', event.params.caller.toHexString()) + updatePoolTransactionToken( + ptx, poolTokenIn.id, tokenAmountIn, poolTokenIn.balance, + tokenAmountIn.times(pool.swapFee)) + updatePoolTransactionToken( + ptx, poolTokenOut.id, tokenAmountOut.times(MINUS_1), poolTokenOut.balance, + BigDecimal.fromString('0.0')) } /************************************ @@ -362,36 +278,47 @@ export function handleSwap(event: LOG_SWAP): void { let poolShareToBalance = poolShareTo == null ? ZERO_BD : poolShareTo.balance let pool = Pool.load(poolId) + let poolTx = PoolTransaction.load(event.transaction.hash.toHexString()) + let value = tokenToDecimal(event.params.value.toBigDecimal(), 18) if (isMint) { if (poolShareTo == null) { createPoolShareEntity(poolShareToId, poolId, event.params.to.toHex()) poolShareTo = PoolShare.load(poolShareToId) } - poolShareTo.balance += tokenToDecimal(event.params.value.toBigDecimal(), 18) + poolShareTo.balance += value poolShareTo.save() - pool.totalShares += tokenToDecimal(event.params.value.toBigDecimal(), 18) + pool.totalShares += value + if (poolTx != null) { + poolTx.sharesTransferAmount = value + poolTx.sharesBalance = poolShareTo.balance + } } else if (isBurn) { if (poolShareFrom == null) { - createPoolShareEntity(poolShareFromId, poolId, event.params.from.toHex()) - poolShareFrom = PoolShare.load(poolShareFromId) - } - poolShareFrom.balance -= tokenToDecimal(event.params.value.toBigDecimal(), 18) + createPoolShareEntity(poolShareFromId, poolId, event.params.from.toHex()) + poolShareFrom = PoolShare.load(poolShareFromId) + } + poolShareFrom.balance -= value poolShareFrom.save() - pool.totalShares -= tokenToDecimal(event.params.value.toBigDecimal(), 18) + pool.totalShares -= value + if (poolTx != null) { + poolTx.sharesTransferAmount = -value + poolTx.sharesBalance = poolShareFrom.balance + } + } else { if (poolShareTo == null) { createPoolShareEntity(poolShareToId, poolId, event.params.to.toHex()) poolShareTo = PoolShare.load(poolShareToId) } - poolShareTo.balance += tokenToDecimal(event.params.value.toBigDecimal(), 18) + poolShareTo.balance += value poolShareTo.save() if (poolShareFrom == null) { createPoolShareEntity(poolShareFromId, poolId, event.params.from.toHex()) poolShareFrom = PoolShare.load(poolShareFromId) } - poolShareFrom.balance -= tokenToDecimal(event.params.value.toBigDecimal(), 18) + poolShareFrom.balance -= value poolShareFrom.save() } @@ -400,7 +327,7 @@ export function handleSwap(event: LOG_SWAP): void { && poolShareTo.balance.notEqual(ZERO_BD) && poolShareToBalance.equals(ZERO_BD) ) { - pool.holdersCount += BigInt.fromI32(1) + pool.holderCount += BigInt.fromI32(1) } if ( @@ -408,7 +335,11 @@ export function handleSwap(event: LOG_SWAP): void { && poolShareFrom.balance.equals(ZERO_BD) && poolShareFromBalance.notEqual(ZERO_BD) ) { - pool.holdersCount -= BigInt.fromI32(1) + pool.holderCount -= BigInt.fromI32(1) + } + + if (poolTx != null) { + poolTx.save() } pool.save() diff --git a/subgraph.yaml b/subgraph.yaml index c6bec21..665be6b 100644 --- a/subgraph.yaml +++ b/subgraph.yaml @@ -17,7 +17,7 @@ dataSources: language: wasm/assemblyscript file: ./src/mappings/factory.ts entities: - - OceanPools + - PoolFactory abis: - name: Factory file: ./abis/BFactory.json @@ -37,7 +37,7 @@ dataSources: language: wasm/assemblyscript file: ./src/mappings/dtfactory.ts entities: - - OceanDatatokens + - DatatokenFactory abis: - name: DTFactory file: ./abis/DTFactory.json @@ -57,7 +57,7 @@ templates: file: ./src/mappings/pool.ts entities: - Pool - - OceanPools + - PoolFactory - Swap abis: - name: Pool @@ -107,7 +107,7 @@ templates: file: ./src/mappings/datatoken.ts entities: - Datatoken - - OceanDatatokens + - DatatokenFactory abis: - name: Datatoken file: ./abis/DataTokenTemplate.json