mirror of
https://github.com/oceanprotocol/ocean-subgraph.git
synced 2024-12-02 05:57:29 +01:00
Add mappings for BFactory and BPool events with handlers
This commit is contained in:
parent
3f79ce7918
commit
49461245d4
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
*.sol linguist-language=Solidity
|
61
.gitignore
vendored
Normal file
61
.gitignore
vendored
Normal file
@ -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
|
||||
|
||||
```
|
||||
|
3034
abis/BFactory.json
Normal file
3034
abis/BFactory.json
Normal file
File diff suppressed because one or more lines are too long
66949
abis/BPool.json
Normal file
66949
abis/BPool.json
Normal file
File diff suppressed because one or more lines are too long
14010
abis/BToken.json
Normal file
14010
abis/BToken.json
Normal file
File diff suppressed because one or more lines are too long
6919
package-lock.json
generated
Normal file
6919
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
25
package.json
Normal file
25
package.json
Normal file
@ -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"
|
||||
}
|
||||
}
|
117
schema.graphql
Normal file
117
schema.graphql
Normal file
@ -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
|
||||
}
|
52
src/mappings/factory.ts
Normal file
52
src/mappings/factory.ts
Normal file
@ -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)
|
||||
}
|
230
src/mappings/helpers.ts
Normal file
230
src/mappings/helpers.ts
Normal file
@ -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()
|
||||
}
|
||||
}
|
397
src/mappings/pool.ts
Normal file
397
src/mappings/pool.ts
Normal file
@ -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()
|
||||
}
|
76
subgraph.yaml
Normal file
76
subgraph.yaml
Normal file
@ -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
|
6
tsconfig.json
Normal file
6
tsconfig.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": "./node_modules/@graphprotocol/graph-ts/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"types": ["@graphprotocol/graph-ts"]
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user