Skip to content

Commit

Permalink
chore: Add user position calculation
Browse files Browse the repository at this point in the history
  • Loading branch information
chef-huan committed May 31, 2023
1 parent 4baf5db commit 68ad34e
Show file tree
Hide file tree
Showing 10 changed files with 114 additions and 154 deletions.
48 changes: 23 additions & 25 deletions subgraphs/user-position-v3/template/mappings/pool.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
/* eslint-disable prefer-const */
import { BigInt } from "@graphprotocol/graph-ts";
import { Burn as BurnEvent, Mint as MintEvent, Swap as SwapEvent } from "../generated/templates/Pool/Pool";
import { Burn, Mint, Pool, Swap, Token } from "../generated/schema";
import { convertTokenToDecimal, loadTransaction } from "../utils";
import { Burn, Mint, Pool, Token } from "../generated/schema";
import { convertTokenToDecimal } from "../utils";
import { loadTransaction, updateUserPosition } from "../utils/schema";
import { ONE_BI } from "../utils/constants";

export function handleMint(event: MintEvent): void {
let transaction = loadTransaction(event);
Expand All @@ -29,6 +31,17 @@ export function handleMint(event: MintEvent): void {
mint.tickLower = BigInt.fromI32(event.params.tickLower);
mint.tickUpper = BigInt.fromI32(event.params.tickUpper);
mint.logIndex = event.logIndex;
mint.save();

pool.txCount = pool.txCount.plus(ONE_BI);
pool.save();

transaction.tickLower = BigInt.fromI32(event.params.tickLower);
transaction.tickUpper = BigInt.fromI32(event.params.tickUpper);
transaction.increaseLiquidityAmount = event.params.amount;
transaction.save();

updateUserPosition(transaction, pool.id);
}

export function handleBurn(event: BurnEvent): void {
Expand All @@ -55,30 +68,15 @@ export function handleBurn(event: BurnEvent): void {
burn.tickLower = BigInt.fromI32(event.params.tickLower);
burn.tickUpper = BigInt.fromI32(event.params.tickUpper);
burn.logIndex = event.logIndex;
}
burn.save();

export function handleSwap(event: SwapEvent): void {
let transaction = loadTransaction(event);
let poolAddress = event.address.toHexString();
let pool = Pool.load(poolAddress);
let token0 = Token.load(pool.token0);
let token1 = Token.load(pool.token1);
pool.txCount = pool.txCount.plus(ONE_BI);
pool.save();

let amount0 = convertTokenToDecimal(event.params.amount0, token0.decimals);
let amount1 = convertTokenToDecimal(event.params.amount1, token1.decimals);
transaction.tickLower = BigInt.fromI32(event.params.tickLower);
transaction.tickUpper = BigInt.fromI32(event.params.tickUpper);
transaction.decreaseLiquidityAmount = event.params.amount;
transaction.save();

let swap = new Swap(transaction.id + "#" + pool.txCount.toString());
swap.transaction = transaction.id;
swap.timestamp = transaction.timestamp;
swap.pool = pool.id;
swap.token0 = pool.token0;
swap.token1 = pool.token1;
swap.sender = event.params.sender;
swap.origin = event.transaction.from;
swap.recipient = event.params.recipient;
swap.amount0 = amount0;
swap.amount1 = amount1;
swap.tick = BigInt.fromI32(event.params.tick as i32);
swap.sqrtPriceX96 = event.params.sqrtPriceX96;
swap.logIndex = event.logIndex;
updateUserPosition(transaction, pool.id);
}
17 changes: 16 additions & 1 deletion subgraphs/user-position-v3/template/mappings/position-manager.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,34 @@
/* eslint-disable prefer-const */
import { Address } from "@graphprotocol/graph-ts";
import {
DecreaseLiquidity,
IncreaseLiquidity,
Transfer,
} from "../generated/NonfungiblePositionManager/NonfungiblePositionManager";
import { loadTransaction } from "../utils";
import { loadTransaction } from "../utils/schema";
import { ADDRESS_ZERO } from "../utils/constants";
import { UserPosition } from "../generated/schema";

export function handleIncreaseLiquidity(event: IncreaseLiquidity): void {
let transaction = loadTransaction(event);
transaction.tokenId = event.params.tokenId;
transaction.save();
}

export function handleDecreaseLiquidity(event: DecreaseLiquidity): void {
let transaction = loadTransaction(event);
transaction.tokenId = event.params.tokenId;
transaction.save();
}

export function handleTransfer(event: Transfer): void {
let transaction = loadTransaction(event);
if (event.params.from.equals(Address.fromString(ADDRESS_ZERO))) {
transaction.positionOwner = event.params.to;
} else {
let userPosition = UserPosition.load(event.params.tokenId.toString());
userPosition.owner = event.params.to;
userPosition.save();
}
transaction.save();
}
6 changes: 3 additions & 3 deletions subgraphs/user-position-v3/template/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
"author": "PancakeSwap",
"license": "GPL-3.0-or-later",
"scripts": {
"template": "mustache ../../../config/bsc.js subgraph.template.yaml > subgraph.yaml && mustache ../../../config/bsc.js utils/constants.template.ts > utils/constants.ts",
"auth": "graph auth --product hosted-service SUBGRAPH_KEY",
"template": "mustache ../../../config/bsc.js subgraph.template.yaml > subgraph.yaml",
"auth": "graph auth --product hosted-service f4b727b41dd3465f461ee000115b1102",
"codegen": "graph codegen subgraph.yaml",
"build": "graph build subgraph.yaml",
"deploy:goerli": "graph deploy --product hosted-service --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ pancakeswap/user-position-v3-goerli subgraph.yaml",
"deploy:chapel": "graph deploy --product hosted-service --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ pancakeswap/user-position-v3-chapel subgraph.yaml",
"deploy:eth": "graph deploy --product hosted-service --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ pancakeswap/user-position-v3-eth subgraph.yaml",
"deploy:bsc": "graph deploy --product hosted-service --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ pancakeswap/user-position-v3-bsc subgraph.yaml"
"deploy:bsc": "graph deploy --product hosted-service --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ chef-huan/user-position-v3-bsc subgraph.yaml"
}
}
44 changes: 12 additions & 32 deletions subgraphs/user-position-v3/template/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,10 @@ type Pool @entity {
token0: Token!
# token1
token1: Token!
# fee amount
# current tick
tick: BigInt!

# derived fields
mints: [Mint!]! @derivedFrom(field: "pool")
burns: [Burn!]! @derivedFrom(field: "pool")
swaps: [Swap!]! @derivedFrom(field: "pool")
}

type Transaction @entity {
Expand All @@ -47,11 +43,14 @@ type Transaction @entity {
tokenId: BigInt
increaseLiquidityAmount: BigInt
decreaseLiquidityAmount: BigInt
tickLower: BigInt
tickUpper: BigInt

isPositionUpdated: Boolean!

# derived values
mints: [Mint]! @derivedFrom(field: "transaction")
burns: [Burn]! @derivedFrom(field: "transaction")
swaps: [Swap]! @derivedFrom(field: "transaction")
}

type Mint @entity {
Expand Down Expand Up @@ -118,33 +117,14 @@ type Burn @entity {
logIndex: BigInt
}

type Swap @entity {
# transaction hash + "#" + index in swaps Transaction array
type UserPosition @entity {
# tokenId
id: ID!
# pointer to transaction
transaction: Transaction!
# timestamp of transaction
timestamp: BigInt!
# pool swap occured within
owner: Bytes!
# pool position is within
pool: Pool!
# allow indexing by tokens
token0: Token!
# allow indexing by tokens
token1: Token!
# sender of the swap
sender: Bytes!
# recipient of the swap
recipient: Bytes!
# txn origin
origin: Bytes! # the EOA that initiated the txn
# delta of token0 swapped
amount0: BigDecimal!
# delta of token1 swapped
amount1: BigDecimal!
# The sqrt(price) of the pool after the swap, as a Q64.96
sqrtPriceX96: BigInt!
# the tick after the swap
tick: BigInt!
# index within the txn
logIndex: BigInt

liquidity: BigInt!
tickLower: BigInt!
tickUpper: BigInt!
}
12 changes: 0 additions & 12 deletions subgraphs/user-position-v3/template/subgraph.template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,6 @@ dataSources:
handler: handleIncreaseLiquidity
- event: DecreaseLiquidity(indexed uint256,uint128,uint256,uint256)
handler: handleDecreaseLiquidity
- event: Collect(indexed uint256,address,uint256,uint256)
handler: handleCollect
- event: Transfer(indexed address,indexed address,indexed uint256)
handler: handleTransfer
templates:
Expand All @@ -90,17 +88,7 @@ templates:
- name: ERC20
file: ./abis/ERC20.json
eventHandlers:
- event: Initialize(uint160,int24)
handler: handleInitialize
- event: Swap(indexed address,indexed address,int256,int256,uint160,uint128,int24,uint128,uint128)
handler: handleSwap
- event: Mint(address,indexed address,indexed int24,indexed int24,uint128,uint256,uint256)
handler: handleMint
- event: Burn(indexed address,indexed int24,indexed int24,uint128,uint256,uint256)
handler: handleBurn
- event: Flash(indexed address,indexed address,uint256,uint256,uint256,uint256)
handler: handleFlash
- event: Collect(indexed address,address,indexed int24,indexed int24,uint128,uint128)
handler: handleCollect
- event: CollectProtocol(indexed address,indexed address,uint128,uint128)
handler: handleCollectProtocol
17 changes: 0 additions & 17 deletions subgraphs/user-position-v3/template/utils/constants.template.ts

This file was deleted.

9 changes: 9 additions & 0 deletions subgraphs/user-position-v3/template/utils/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* eslint-disable prefer-const */
import { BigInt, BigDecimal } from "@graphprotocol/graph-ts";

export const ADDRESS_ZERO = "0x0000000000000000000000000000000000000000";

export let ZERO_BI = BigInt.fromI32(0);
export let ONE_BI = BigInt.fromI32(1);
export let ZERO_BD = BigDecimal.fromString("0");
export let ONE_BD = BigDecimal.fromString("1");
43 changes: 2 additions & 41 deletions subgraphs/user-position-v3/template/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/* eslint-disable prefer-const */
import { BigInt, BigDecimal, ethereum } from "@graphprotocol/graph-ts";
import { Transaction } from "../generated/schema";
import { ONE_BI, ZERO_BI, ZERO_BD, ONE_BD } from "./constants";
import { BigInt, BigDecimal } from "@graphprotocol/graph-ts";
import { ONE_BI, ZERO_BI } from "./constants";

export function exponentToBigDecimal(decimals: BigInt): BigDecimal {
let bd = BigDecimal.fromString("1");
Expand All @@ -11,31 +10,6 @@ export function exponentToBigDecimal(decimals: BigInt): BigDecimal {
return bd;
}

// return 0 if denominator is 0 in division
export function safeDiv(amount0: BigDecimal, amount1: BigDecimal): BigDecimal {
if (amount1.equals(ZERO_BD)) {
return ZERO_BD;
} else {
return amount0.div(amount1);
}
}

export function tokenAmountToDecimal(tokenAmount: BigInt, exchangeDecimals: BigInt): BigDecimal {
if (exchangeDecimals == ZERO_BI) {
return tokenAmount.toBigDecimal();
}
return tokenAmount.toBigDecimal().div(exponentToBigDecimal(exchangeDecimals));
}

export function equalToZero(value: BigDecimal): boolean {
const formattedVal = parseFloat(value.toString());
const zero = parseFloat(ZERO_BD.toString());
if (zero == formattedVal) {
return true;
}
return false;
}

export function isNullEthValue(value: string): boolean {
return value == "0x0000000000000000000000000000000000000000000000000000000000000001";
}
Expand All @@ -46,16 +20,3 @@ export function convertTokenToDecimal(tokenAmount: BigInt, exchangeDecimals: Big
}
return tokenAmount.toBigDecimal().div(exponentToBigDecimal(exchangeDecimals));
}

export function loadTransaction(event: ethereum.Event): Transaction {
let transaction = Transaction.load(event.transaction.hash.toHexString());
if (transaction === null) {
transaction = new Transaction(event.transaction.hash.toHexString());
}
transaction.blockNumber = event.block.number;
transaction.timestamp = event.block.timestamp;
transaction.gasUsed = event.transaction.gasUsed;
transaction.gasPrice = event.transaction.gasPrice;
transaction.save();
return transaction as Transaction;
}
48 changes: 48 additions & 0 deletions subgraphs/user-position-v3/template/utils/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { BigInt, Bytes, ethereum } from "@graphprotocol/graph-ts";
import { Transaction, UserPosition } from "../generated/schema";
import { ZERO_BI } from "./constants";

export function loadTransaction(event: ethereum.Event): Transaction {
let transaction = Transaction.load(event.transaction.hash.toHexString());
if (transaction === null) {
transaction = new Transaction(event.transaction.hash.toHexString());
}
transaction.blockNumber = event.block.number;
transaction.timestamp = event.block.timestamp;
transaction.gasUsed = event.transaction.gasUsed;
transaction.gasPrice = event.transaction.gasPrice;
transaction.isPositionUpdated = false;
transaction.save();
return transaction as Transaction;
}

export function updateUserPosition(tx: Transaction, poolId: string): void {
if (
tx.isPositionUpdated === false &&
tx.tickLower !== null &&
tx.tickUpper !== null &&
tx.tokenId !== null &&
tx.positionOwner !== null &&
(tx.increaseLiquidityAmount !== null || tx.decreaseLiquidityAmount !== null)
) {
let userPosition = UserPosition.load(tx.tokenId.toString());
if (userPosition === null) {
userPosition = new UserPosition(tx.tokenId.toString());
userPosition.liquidity = ZERO_BI;
userPosition.pool = poolId;
}
userPosition.tickLower = tx.tickLower as BigInt;
userPosition.tickUpper = tx.tickUpper as BigInt;
userPosition.owner = tx.positionOwner as Bytes;
if (tx.increaseLiquidityAmount !== null) {
userPosition.liquidity = userPosition.liquidity.plus(tx.increaseLiquidityAmount as BigInt);
}
if (tx.decreaseLiquidityAmount !== null) {
userPosition.liquidity = userPosition.liquidity.minus(tx.decreaseLiquidityAmount as BigInt);
}

tx.isPositionUpdated = true;
tx.save();
userPosition.save();
}
}
Loading

0 comments on commit 68ad34e

Please sign in to comment.