Add mappings for BFactory and BPool events with handlers
This commit is contained in:
parent
3f79ce7918
commit
49461245d4
|
@ -0,0 +1 @@
|
|||
*.sol linguist-language=Solidity
|
|
@ -0,0 +1,61 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
|
||||
# next.js build output
|
||||
.next
|
32
README.md
32
README.md
|
@ -1 +1,31 @@
|
|||
# ocean.subgraph
|
||||
# Ocean Protocol Subgraph
|
||||
|
||||
## Running locally
|
||||
* Install the Graph: `https://thegraph.com/docs/quick-start`
|
||||
* You can skip running ganache-cli and connect directly to `mainnet` using Infura
|
||||
|
||||
```bash
|
||||
git clone https://github.com/graphprotocol/graph-node/
|
||||
cd graph-node/docker
|
||||
./setup.sh
|
||||
# Update this line in the `docker-compose.yml` file with your Infura ProjectId
|
||||
# ethereum: 'mainnet:https://mainnet.infura.io/v3/INFURA_PROJECT_ID'
|
||||
docker-compose up
|
||||
|
||||
```
|
||||
|
||||
* Install Graph CLI globally with npm
|
||||
```bash
|
||||
npm install -g @graphprotocol/graph-cli
|
||||
```
|
||||
|
||||
* Once the graph node is ready, do the following to deploy the ocean-subgraph to the local graph-node
|
||||
```bash
|
||||
git clone https://github.com/oceanprotocol/ocean-subgraph/
|
||||
cd ocean-subgraph
|
||||
npm i
|
||||
npm run codegen
|
||||
npm run create:local
|
||||
npm run deploy:local
|
||||
|
||||
```
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"name": "oceanpools",
|
||||
"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:local": "graph deploy oceanprotocol/ocean-subgraph subgraph.yaml --debug --ipfs http://localhost:5001 --node http://127.0.0.1:8020"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@graphprotocol/graph-cli": "^0.18.0",
|
||||
"@graphprotocol/graph-ts": "^0.18.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"babel-register": "^6.26.0",
|
||||
"keytar": "^5.0.0",
|
||||
"truffle": "^5.1.0",
|
||||
"truffle-contract": "^4.0.5",
|
||||
"truffle-hdwallet-provider": "^1.0.4"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
type OceanPools @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
|
||||
}
|
||||
|
||||
type Pool @entity {
|
||||
id: ID! # Pool address
|
||||
controller: Bytes! # Controller address
|
||||
publicSwap: Boolean! # isPublicSwap
|
||||
finalized: Boolean! # isFinalized
|
||||
symbol: String # Pool token symbol
|
||||
name: String # Pool token name
|
||||
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
|
||||
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")
|
||||
}
|
||||
|
||||
type PoolToken @entity {
|
||||
id: ID! # poolId + token address
|
||||
poolId: Pool!
|
||||
symbol: String
|
||||
name: String
|
||||
decimals: Int!
|
||||
address: String!
|
||||
balance: BigDecimal!
|
||||
denormWeight: BigDecimal!
|
||||
}
|
||||
|
||||
type PoolShare @entity {
|
||||
id: ID! # poolId + userAddress
|
||||
userAddress: User!
|
||||
poolId: Pool!
|
||||
balance: BigDecimal!
|
||||
}
|
||||
|
||||
type User @entity {
|
||||
id: ID!
|
||||
sharesOwned: [PoolShare!] @derivedFrom(field: "userAddress")
|
||||
txs: [Transaction!] @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
|
||||
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 Transaction @entity {
|
||||
id: ID! # Log ID
|
||||
tx: Bytes!
|
||||
event: String
|
||||
block: Int!
|
||||
timestamp: Int!
|
||||
gasUsed: BigDecimal!
|
||||
gasPrice: BigDecimal!
|
||||
poolAddress: Pool
|
||||
userAddress: User
|
||||
action: SwapType
|
||||
sender: Bytes
|
||||
}
|
||||
|
||||
type TokenPrice @entity {
|
||||
id: ID!
|
||||
symbol: String
|
||||
name: String
|
||||
decimals: Int!
|
||||
price: BigDecimal!
|
||||
poolLiquidity: BigDecimal!
|
||||
poolTokenId: String
|
||||
}
|
||||
|
||||
enum SwapType {
|
||||
swapExactAmountIn,
|
||||
swapExactAmountOut,
|
||||
joinswapExternAmountIn,
|
||||
joinswapPoolAmountOut,
|
||||
exitswapPoolAmountIn,
|
||||
exitswapExternAmountOut
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
import { Address, BigInt, BigDecimal } from '@graphprotocol/graph-ts'
|
||||
import { BPoolRegistered } from '../types/Factory/Factory'
|
||||
import { OceanPools, Pool } from '../types/schema'
|
||||
import { Pool as PoolContract } from '../types/templates'
|
||||
import {
|
||||
ZERO_BD,
|
||||
} from './helpers'
|
||||
import { log } from '@graphprotocol/graph-ts'
|
||||
|
||||
export function handleNewPool(event: BPoolRegistered): void {
|
||||
let factory = OceanPools.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.totalLiquidity = ZERO_BD
|
||||
factory.totalSwapVolume = ZERO_BD
|
||||
factory.totalSwapFee = ZERO_BD
|
||||
}
|
||||
|
||||
let pool = new Pool(event.params.bpoolAddress.toHexString())
|
||||
log.error('************************ handleNewPool: poolId {}', [pool.id.toString()])
|
||||
pool.controller = event.params.registeredBy
|
||||
pool.publicSwap = false
|
||||
pool.finalized = false
|
||||
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.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
|
||||
factory.save()
|
||||
|
||||
PoolContract.create(event.params.bpoolAddress)
|
||||
}
|
|
@ -0,0 +1,230 @@
|
|||
import {
|
||||
BigDecimal,
|
||||
Address,
|
||||
BigInt,
|
||||
Bytes,
|
||||
dataSource,
|
||||
ethereum
|
||||
} from '@graphprotocol/graph-ts'
|
||||
import {
|
||||
Pool,
|
||||
User,
|
||||
PoolToken,
|
||||
PoolShare,
|
||||
TokenPrice,
|
||||
Transaction,
|
||||
OceanPools
|
||||
} from '../types/schema'
|
||||
import { BToken } from '../types/templates/Pool/BToken'
|
||||
import { log } from '@graphprotocol/graph-ts'
|
||||
|
||||
export let ZERO_BD = BigDecimal.fromString('0')
|
||||
|
||||
let network = dataSource.network()
|
||||
|
||||
export let OCEAN: string = (network == 'mainnet')
|
||||
? '0x967da4048cD07aB37855c090aAF366e4ce1b9F48'
|
||||
: '0x8967BCF84170c91B0d24D4302C2376283b0B3a07'
|
||||
|
||||
export function hexToDecimal(hexString: String, decimals: i32): BigDecimal {
|
||||
let bytes = Bytes.fromHexString(hexString).reverse() as Bytes
|
||||
let bi = BigInt.fromUnsignedBytes(bytes)
|
||||
let scale = BigInt.fromI32(10).pow(decimals as u8).toBigDecimal()
|
||||
return bi.divDecimal(scale)
|
||||
}
|
||||
|
||||
export function bigIntToDecimal(amount: BigInt, decimals: i32): BigDecimal {
|
||||
let scale = BigInt.fromI32(10).pow(decimals as u8).toBigDecimal()
|
||||
return amount.toBigDecimal().div(scale)
|
||||
}
|
||||
|
||||
export function tokenToDecimal(amount: BigDecimal, decimals: i32): BigDecimal {
|
||||
let scale = BigInt.fromI32(10).pow(decimals as u8).toBigDecimal()
|
||||
return amount.div(scale)
|
||||
}
|
||||
|
||||
export function createPoolShareEntity(id: string, pool: string, user: string): void {
|
||||
let poolShare = new PoolShare(id)
|
||||
|
||||
createUserEntity(user)
|
||||
|
||||
poolShare.userAddress = user
|
||||
poolShare.poolId = pool
|
||||
poolShare.balance = ZERO_BD
|
||||
poolShare.save()
|
||||
}
|
||||
|
||||
export function createPoolTokenEntity(id: string, pool: string, address: string): void {
|
||||
let token = BToken.bind(Address.fromString(address))
|
||||
let symbol = ''
|
||||
let name = ''
|
||||
let decimals = 18
|
||||
|
||||
// COMMENT THE LINES BELOW OUT FOR LOCAL DEV ON KOVAN
|
||||
let symbolCall = token.try_symbol()
|
||||
let nameCall = token.try_name()
|
||||
|
||||
if (!symbolCall.reverted) {
|
||||
symbol = symbolCall.value
|
||||
}
|
||||
|
||||
if (!nameCall.reverted) {
|
||||
name = nameCall.value
|
||||
}
|
||||
|
||||
// COMMENT THE LINES ABOVE OUT FOR LOCAL DEV ON KOVAN
|
||||
|
||||
// !!! COMMENT THE LINES BELOW OUT FOR NON-LOCAL DEPLOYMENT
|
||||
// This code allows Symbols to be added when testing on local Kovan
|
||||
/*
|
||||
if(address == '0xd0a1e359811322d97991e03f863a0c30c2cf029c')
|
||||
symbol = 'WETH';
|
||||
else if(address == '0x1528f3fcc26d13f7079325fb78d9442607781c8c')
|
||||
symbol = 'DAI'
|
||||
else if(address == '0xef13c0c8abcaf5767160018d268f9697ae4f5375')
|
||||
symbol = 'MKR'
|
||||
else if(address == '0x2f375e94fc336cdec2dc0ccb5277fe59cbf1cae5')
|
||||
symbol = 'USDC'
|
||||
else if(address == '0x1f1f156e0317167c11aa412e3d1435ea29dc3cce')
|
||||
symbol = 'BAT'
|
||||
else if(address == '0x86436bce20258a6dcfe48c9512d4d49a30c4d8c4')
|
||||
symbol = 'SNX'
|
||||
else if(address == '0x8c9e6c40d3402480ace624730524facc5482798c')
|
||||
symbol = 'REP'
|
||||
*/
|
||||
// !!! COMMENT THE LINES ABOVE OUT FOR NON-LOCAL DEPLOYMENT
|
||||
|
||||
let poolToken = new PoolToken(id)
|
||||
poolToken.poolId = pool
|
||||
poolToken.address = address
|
||||
poolToken.name = name
|
||||
poolToken.symbol = symbol
|
||||
poolToken.decimals = decimals
|
||||
poolToken.balance = ZERO_BD
|
||||
poolToken.denormWeight = ZERO_BD
|
||||
poolToken.save()
|
||||
}
|
||||
|
||||
export function updatePoolLiquidity(id: string): void {
|
||||
let pool = Pool.load(id)
|
||||
let tokensList: Array<Bytes> = pool.tokensList
|
||||
|
||||
if (!tokensList || pool.tokensCount.lt(BigInt.fromI32(2)) || !pool.publicSwap) return
|
||||
|
||||
// Find pool liquidity
|
||||
|
||||
let hasPrice = false
|
||||
let hasOceanPrice = false
|
||||
let poolLiquidity = ZERO_BD
|
||||
|
||||
// if (tokensList.includes(Address.fromString(OCEAN))) {
|
||||
// let oceanPoolTokenId = id.concat('-').concat(OCEAN)
|
||||
// let oceanPoolToken = PoolToken.load(oceanPoolTokenId)
|
||||
// poolLiquidity = oceanPoolToken.balance.div(oceanPoolToken.denormWeight).times(pool.totalWeight)
|
||||
// hasPrice = true
|
||||
// hasOceanPrice = true
|
||||
// } else {
|
||||
// let DT = tokensList[1].toHexString()
|
||||
// let dtTokenPrice = TokenPrice.load(DT)
|
||||
// if (dtTokenPrice !== null) {
|
||||
// let poolTokenId = id.concat('-').concat(DT)
|
||||
// let poolToken = PoolToken.load(poolTokenId)
|
||||
// poolLiquidity = wethTokenPrice.price.times(poolToken.balance).div(poolToken.denormWeight).times(pool.totalWeight)
|
||||
// hasPrice = true
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // 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()
|
||||
}
|
||||
|
||||
export function decrPoolCount(finalized: boolean): void {
|
||||
let factory = OceanPools.load('1')
|
||||
factory.poolCount -= 1
|
||||
if (finalized) factory.finalizedPoolCount -= 1
|
||||
factory.save()
|
||||
}
|
||||
|
||||
export function saveTransaction(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 = Transaction.load(tx)
|
||||
if (transaction == null) {
|
||||
transaction = new Transaction(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 createUserEntity(address: string): void {
|
||||
if (User.load(address) == null) {
|
||||
let user = new User(address)
|
||||
user.save()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,397 @@
|
|||
|
||||
import { BigInt, Address, Bytes, store, BigDecimal } from '@graphprotocol/graph-ts'
|
||||
import { LOG_CALL, LOG_JOIN, LOG_EXIT, LOG_SWAP, Transfer, GulpCall } 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
|
||||
} from '../types/schema'
|
||||
import {
|
||||
hexToDecimal,
|
||||
bigIntToDecimal,
|
||||
tokenToDecimal,
|
||||
createPoolShareEntity,
|
||||
createPoolTokenEntity,
|
||||
updatePoolLiquidity,
|
||||
saveTransaction,
|
||||
ZERO_BD,
|
||||
decrPoolCount
|
||||
} from './helpers'
|
||||
|
||||
/************************************
|
||||
********** Pool Controls ***********
|
||||
************************************/
|
||||
|
||||
export function handleSetSwapFee(event: LOG_CALL, swapFeeStr: string=null): void {
|
||||
let poolId = event.address.toHex()
|
||||
let pool = Pool.load(poolId)
|
||||
if (!swapFeeStr) {
|
||||
swapFeeStr = event.params.data.toHexString().slice(-40)
|
||||
}
|
||||
pool.swapFee = hexToDecimal(swapFeeStr, 18)
|
||||
pool.save()
|
||||
|
||||
saveTransaction(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.save()
|
||||
|
||||
saveTransaction(event, 'setController')
|
||||
}
|
||||
|
||||
export function handleSetPublicSwap(event: LOG_CALL): void {
|
||||
let poolId = event.address.toHex()
|
||||
let pool = Pool.load(poolId)
|
||||
let publicSwap = event.params.data.toHexString().slice(-1) == '1'
|
||||
pool.publicSwap = publicSwap
|
||||
pool.save()
|
||||
|
||||
saveTransaction(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')
|
||||
factory.finalizedPoolCount = factory.finalizedPoolCount + 1
|
||||
factory.save()
|
||||
|
||||
saveTransaction(event, 'finalize')
|
||||
}
|
||||
|
||||
export function handleSetup(event: LOG_CALL): void {
|
||||
let poolId = event.address.toHex()
|
||||
|
||||
let data = event.params.data.toHexString()
|
||||
let dataTokenAddress = data.slice(34,74)
|
||||
let dataTokenAmount = data.slice(98,162)
|
||||
let dataTokenWeight = data.slice(162,226)
|
||||
let baseTokenAddress = data.slice(226, 290-24)
|
||||
let baseTokenAmount = data.slice(290,354)
|
||||
let baseTokenWeight = data.slice(354,418)
|
||||
let swapFee = data.slice(418)
|
||||
_handleRebind(event, poolId, dataTokenAddress, dataTokenAmount, dataTokenWeight)
|
||||
_handleRebind(event, poolId, baseTokenAddress, baseTokenAmount, baseTokenWeight)
|
||||
handleSetSwapFee(event, swapFee)
|
||||
handleFinalize(event)
|
||||
|
||||
saveTransaction(event, 'setup')
|
||||
|
||||
}
|
||||
|
||||
export function _handleRebind(event: LOG_CALL, poolId: string, tokenAddress: string, balanceStr: string, denormWeightStr: string): void {
|
||||
let pool = Pool.load(poolId)
|
||||
let tokenBytes = Bytes.fromHexString(tokenAddress) as Bytes
|
||||
let tokensList = pool.tokensList || []
|
||||
if (tokensList.indexOf(tokenBytes) == -1 ) {
|
||||
tokensList.push(tokenBytes)
|
||||
}
|
||||
pool.tokensList = tokensList
|
||||
pool.tokensCount = BigInt.fromI32(tokensList.length)
|
||||
|
||||
let address = Address.fromString(tokenAddress)
|
||||
let denormWeight = hexToDecimal(denormWeightStr, 18)
|
||||
|
||||
let poolTokenId = poolId.concat('-').concat(address.toHexString())
|
||||
let poolToken = PoolToken.load(poolTokenId)
|
||||
if (poolToken == null) {
|
||||
createPoolTokenEntity(poolTokenId, poolId, address.toHexString())
|
||||
poolToken = PoolToken.load(poolTokenId)
|
||||
pool.totalWeight += denormWeight
|
||||
} else {
|
||||
let oldWeight = poolToken.denormWeight
|
||||
if (denormWeight > oldWeight) {
|
||||
pool.totalWeight = pool.totalWeight + (denormWeight - oldWeight)
|
||||
} else {
|
||||
pool.totalWeight = pool.totalWeight - (oldWeight - denormWeight)
|
||||
}
|
||||
}
|
||||
|
||||
let balance = hexToDecimal(balanceStr, poolToken.decimals)
|
||||
|
||||
poolToken.balance = balance
|
||||
poolToken.denormWeight = denormWeight
|
||||
poolToken.save()
|
||||
|
||||
if (balance.equals(ZERO_BD)) {
|
||||
decrPoolCount(pool.finalized)
|
||||
pool.active = false
|
||||
}
|
||||
pool.save()
|
||||
|
||||
updatePoolLiquidity(poolId)
|
||||
}
|
||||
|
||||
export function handleRebind(event: LOG_CALL): void {
|
||||
let poolId = event.address.toHex()
|
||||
_handleRebind(
|
||||
event,
|
||||
poolId,
|
||||
event.params.data.toHexString().slice(34,74),
|
||||
event.params.data.toHexString().slice(74,138),
|
||||
event.params.data.toHexString().slice(138)
|
||||
)
|
||||
|
||||
saveTransaction(event, 'rebind')
|
||||
|
||||
}
|
||||
|
||||
/************************************
|
||||
********** JOINS & EXITS ***********
|
||||
************************************/
|
||||
|
||||
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))
|
||||
pool.save()
|
||||
|
||||
let address = event.params.tokenIn.toHex()
|
||||
let poolTokenId = poolId.concat('-').concat(address.toString())
|
||||
let poolToken = PoolToken.load(poolTokenId)
|
||||
if (!poolToken) {
|
||||
return
|
||||
}
|
||||
poolToken.decimals = BigInt.fromI32(18).toI32()
|
||||
let tokenAmountIn = tokenToDecimal(event.params.tokenAmountIn.toBigDecimal(), poolToken.decimals)
|
||||
poolToken.balance = poolToken.balance.plus(tokenAmountIn)
|
||||
poolToken.save()
|
||||
|
||||
updatePoolLiquidity(poolId)
|
||||
saveTransaction(event, 'join')
|
||||
}
|
||||
|
||||
export function handleExitPool(event: LOG_EXIT): void {
|
||||
let poolId = event.address.toHex()
|
||||
|
||||
let address = event.params.tokenOut.toHex()
|
||||
let poolTokenId = poolId.concat('-').concat(address.toString())
|
||||
let poolToken = PoolToken.load(poolTokenId)
|
||||
if (!poolToken) {
|
||||
return
|
||||
}
|
||||
let tokenAmountOut = tokenToDecimal(event.params.tokenAmountOut.toBigDecimal(), poolToken.decimals)
|
||||
let newAmount = poolToken.balance.minus(tokenAmountOut)
|
||||
poolToken.balance = newAmount
|
||||
poolToken.save()
|
||||
|
||||
let pool = Pool.load(poolId)
|
||||
pool.exitsCount = pool.exitsCount.plus(BigInt.fromI32(1))
|
||||
if (newAmount.equals(ZERO_BD)) {
|
||||
decrPoolCount(pool.finalized)
|
||||
pool.active = false
|
||||
}
|
||||
pool.save()
|
||||
|
||||
updatePoolLiquidity(poolId)
|
||||
saveTransaction(event, 'exit')
|
||||
}
|
||||
|
||||
/************************************
|
||||
************** SWAPS ***************
|
||||
************************************/
|
||||
|
||||
export function handleSwap(event: LOG_SWAP): void {
|
||||
let poolId = event.address.toHex()
|
||||
|
||||
let tokenIn = event.params.tokenIn.toHex()
|
||||
let poolTokenInId = poolId.concat('-').concat(tokenIn.toString())
|
||||
let poolTokenIn = PoolToken.load(poolTokenInId)
|
||||
if (!poolTokenIn) {
|
||||
return
|
||||
}
|
||||
let tokenAmountIn = tokenToDecimal(event.params.tokenAmountIn.toBigDecimal(), poolTokenIn.decimals)
|
||||
let newAmountIn = poolTokenIn.balance.plus(tokenAmountIn)
|
||||
poolTokenIn.balance = newAmountIn
|
||||
poolTokenIn.save()
|
||||
|
||||
let tokenOut = event.params.tokenOut.toHex()
|
||||
let poolTokenOutId = poolId.concat('-').concat(tokenOut.toString())
|
||||
let poolTokenOut = PoolToken.load(poolTokenOutId)
|
||||
let tokenAmountOut = tokenToDecimal(event.params.tokenAmountOut.toBigDecimal(), poolTokenOut.decimals)
|
||||
let newAmountOut = poolTokenOut.balance.minus(tokenAmountOut)
|
||||
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<Bytes> = 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)
|
||||
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 = poolTokenIn.symbol
|
||||
swap.tokenOut = event.params.tokenOut
|
||||
swap.tokenOutSym = poolTokenOut.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()
|
||||
|
||||
saveTransaction(event, 'swap')
|
||||
}
|
||||
|
||||
/************************************
|
||||
*********** POOL SHARES ************
|
||||
************************************/
|
||||
|
||||
export function handleTransfer(event: Transfer): void {
|
||||
let poolId = event.address.toHex()
|
||||
|
||||
let ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
|
||||
|
||||
let isMint = event.params.from.toHex() == ZERO_ADDRESS
|
||||
let isBurn = event.params.to.toHex() == ZERO_ADDRESS
|
||||
|
||||
let poolShareFromId = poolId.concat('-').concat(event.params.from.toHex())
|
||||
let poolShareFrom = PoolShare.load(poolShareFromId)
|
||||
let poolShareFromBalance = poolShareFrom == null ? ZERO_BD : poolShareFrom.balance
|
||||
|
||||
let poolShareToId = poolId.concat('-').concat(event.params.to.toHex())
|
||||
let poolShareTo = PoolShare.load(poolShareToId)
|
||||
let poolShareToBalance = poolShareTo == null ? ZERO_BD : poolShareTo.balance
|
||||
|
||||
let pool = Pool.load(poolId)
|
||||
|
||||
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.save()
|
||||
pool.totalShares += tokenToDecimal(event.params.value.toBigDecimal(), 18)
|
||||
} 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)
|
||||
poolShareFrom.save()
|
||||
pool.totalShares -= tokenToDecimal(event.params.value.toBigDecimal(), 18)
|
||||
} else {
|
||||
if (poolShareTo == null) {
|
||||
createPoolShareEntity(poolShareToId, poolId, event.params.to.toHex())
|
||||
poolShareTo = PoolShare.load(poolShareToId)
|
||||
}
|
||||
poolShareTo.balance += tokenToDecimal(event.params.value.toBigDecimal(), 18)
|
||||
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.save()
|
||||
}
|
||||
|
||||
if (
|
||||
poolShareTo !== null
|
||||
&& poolShareTo.balance.notEqual(ZERO_BD)
|
||||
&& poolShareToBalance.equals(ZERO_BD)
|
||||
) {
|
||||
pool.holdersCount += BigInt.fromI32(1)
|
||||
}
|
||||
|
||||
if (
|
||||
poolShareFrom !== null
|
||||
&& poolShareFrom.balance.equals(ZERO_BD)
|
||||
&& poolShareFromBalance.notEqual(ZERO_BD)
|
||||
) {
|
||||
pool.holdersCount -= BigInt.fromI32(1)
|
||||
}
|
||||
|
||||
pool.save()
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
specVersion: 0.0.2
|
||||
description: Ocean provides data sharing through IDOs
|
||||
repository: https://github.com/oceanprotocol/ocean-subgraph
|
||||
schema:
|
||||
file: ./schema.graphql
|
||||
dataSources:
|
||||
- kind: ethereum/contract
|
||||
name: Factory
|
||||
network: mainnet
|
||||
source:
|
||||
address: "0xbe0083053744ECb871510C88dC0f6b77Da162706"
|
||||
abi: Factory
|
||||
startBlock: 11105585
|
||||
mapping:
|
||||
kind: ethereum/events
|
||||
apiVersion: 0.0.4
|
||||
language: wasm/assemblyscript
|
||||
file: ./src/mappings/factory.ts
|
||||
entities:
|
||||
- OceanPools
|
||||
abis:
|
||||
- name: Factory
|
||||
file: ./abis/BFactory.json
|
||||
eventHandlers:
|
||||
- event: BPoolRegistered(address,indexed address)
|
||||
handler: handleNewPool
|
||||
templates:
|
||||
- kind: ethereum/contract
|
||||
name: Pool
|
||||
network: mainnet
|
||||
source:
|
||||
abi: Pool
|
||||
mapping:
|
||||
kind: ethereum/events
|
||||
apiVersion: 0.0.4
|
||||
language: wasm/assemblyscript
|
||||
file: ./src/mappings/pool.ts
|
||||
entities:
|
||||
- Pool
|
||||
- OceanPools
|
||||
- Swap
|
||||
abis:
|
||||
- name: Pool
|
||||
file: ./abis/BPool.json
|
||||
- name: BToken
|
||||
file: ./abis/BToken.json
|
||||
eventHandlers:
|
||||
- event: LOG_CALL(indexed bytes4,indexed address,bytes)
|
||||
topic0: "0x34e1990700000000000000000000000000000000000000000000000000000000"
|
||||
handler: handleSetSwapFee
|
||||
- event: LOG_CALL(indexed bytes4,indexed address,bytes)
|
||||
topic0: "0x92eefe9b00000000000000000000000000000000000000000000000000000000"
|
||||
handler: handleSetController
|
||||
- event: LOG_CALL(indexed bytes4,indexed address,bytes)
|
||||
topic0: "0x49b5955200000000000000000000000000000000000000000000000000000000"
|
||||
handler: handleSetPublicSwap
|
||||
- event: LOG_CALL(indexed bytes4,indexed address,bytes)
|
||||
topic0: "0x4bb278f300000000000000000000000000000000000000000000000000000000"
|
||||
handler: handleFinalize
|
||||
- event: LOG_CALL(indexed bytes4,indexed address,bytes)
|
||||
topic0: "0xd1d7bc9100000000000000000000000000000000000000000000000000000000"
|
||||
handler: handleSetup
|
||||
- event: LOG_CALL(indexed bytes4,indexed address,bytes)
|
||||
topic0: "0x3fdddaa200000000000000000000000000000000000000000000000000000000"
|
||||
handler: handleRebind
|
||||
- event: LOG_CALL(indexed bytes4,indexed address,bytes)
|
||||
topic0: "0xe4e1e53800000000000000000000000000000000000000000000000000000000"
|
||||
handler: handleRebind
|
||||
- event: LOG_JOIN(indexed address,indexed address,uint256)
|
||||
handler: handleJoinPool
|
||||
- event: LOG_EXIT(indexed address,indexed address,uint256)
|
||||
handler: handleExitPool
|
||||
- event: LOG_SWAP(indexed address,indexed address,indexed address,uint256,uint256)
|
||||
handler: handleSwap
|
||||
- event: Transfer(indexed address,indexed address,uint256)
|
||||
handler: handleTransfer
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"extends": "./node_modules/@graphprotocol/graph-ts/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"types": ["@graphprotocol/graph-ts"]
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue