diff --git a/config/base/chain.ts b/config/base/chain.ts new file mode 100644 index 0000000..7b0a791 --- /dev/null +++ b/config/base/chain.ts @@ -0,0 +1,70 @@ +import { Address, BigDecimal, BigInt } from '@graphprotocol/graph-ts' +export const SKIP_CHART = true +export const SKIP_TAKE_AND_SWAP = true +export const SKIP_TX_ANALYTICS = true +export const SKIP_USER_ANALYTICS = true + +export const OPERATOR = '0x00f7a0c7e66f0e3a10d9e980e0854ebe0e308625' +export const LIQUIDITY_VAULT = '0xca1f6e4ae690d06e3bf943b9019c5ca060c0b834' + +export class TokenDefinition { + address: Address + symbol: string + name: string + decimals: BigInt +} + +export const NATIVE_TOKEN_DEFINITION: TokenDefinition = { + address: Address.fromString('0x0000000000000000000000000000000000000000'), + symbol: 'ETH', + name: 'Ethereum', + decimals: BigInt.fromI32(18), +} + +export const NATIVE_TOKEN_BOOK_ID: BigInt = BigInt.fromString( + '305798090575971420747066887426250327115295993737352425987', // bid book in ETH/USDC +) + +export const BID_BOOK_ID: BigInt = BigInt.fromString( + '305798090575971420747066887426250327115295993737352425987', // bid book in ETH/USDC +) + +export const ASK_BOOK_ID: BigInt = BigInt.fromString( + '195945309878431825165287262143162122266744910429476987829', // ask book in ETH/USDC +) + +export const STABLE_COINS: string[] = [ + '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913', // USDC + '0xd9aaec86b65d86f6a7b5b1b0c42ffa531710b6ca', // USDbC +] + +export const MINIMUM_USD_LOCKED = BigDecimal.fromString('0') + +export const REFERENCE_TOKEN = '0x4200000000000000000000000000000000000006' + +export const STATIC_TOKEN_DEFINITIONS: TokenDefinition[] = [ + { + address: Address.fromString('0x0000000000000000000000000000000000000000'), + symbol: 'ETH', + name: 'Ethereum', + decimals: BigInt.fromI32(18), + }, + { + address: Address.fromString('0x4200000000000000000000000000000000000006'), + symbol: 'WETH', + name: 'Wrapped Ether', + decimals: BigInt.fromI32(18), + }, + { + address: Address.fromString('0x833589fcd6edb6e08f4c7c32d4f71b54bda02913'), + symbol: 'USDC', + name: 'USD Coin', + decimals: BigInt.fromI32(6), + }, + { + address: Address.fromString('0xd9aaec86b65d86f6a7b5b1b0c42ffa531710b6ca'), + symbol: 'USDbC', + name: 'USD Base Coin', + decimals: BigInt.fromI32(6), + }, +] diff --git a/config/base/config.json b/config/base/config.json new file mode 100644 index 0000000..f94c4bc --- /dev/null +++ b/config/base/config.json @@ -0,0 +1,16 @@ +{ + "network": "base", + "BookManager": { + "address": "0x8ca3a6f4a6260661fcb9a25584c796a1fa380112", + "startBlock": 40941003 + }, + "LiquidityVault": { + "address": "0xca1f6e4ae690d06e3bf943b9019c5ca060c0b834", + "startBlock": 41325337 + }, + "SimpleOracleStrategy": { + "address": "0x29e07197ccf70d0ac6cb0a3c307627819f5f2777", + "startBlock": 41325337 + }, + "hasRouterGateway": false +} \ No newline at end of file diff --git a/config/monad/chain.ts b/config/monad/chain.ts index afe95ee..3918ef5 100644 --- a/config/monad/chain.ts +++ b/config/monad/chain.ts @@ -25,6 +25,14 @@ export const NATIVE_TOKEN_BOOK_ID: BigInt = BigInt.fromString( '5954885684956363054050231031211743946744177791604395877538', ) +export const BID_BOOK_ID: BigInt = BigInt.fromString( + '5954885684956363054050231031211743946744177791604395877538', // bid book in ETH/USDC +) + +export const ASK_BOOK_ID: BigInt = BigInt.fromString( + '3875727077379471850923186002296331935053867847116966170720', // bid book in ETH/USDC +) + export const STABLE_COINS: string[] = [ '0x754704bc059f8c67012fed69bc8a327a5aafb603', // USDC '0xe7cd86e13ac4309349f30b3435a9d337750fc82d', // USDT diff --git a/schema.graphql b/schema.graphql index fe3ceaa..de15a24 100644 --- a/schema.graphql +++ b/schema.graphql @@ -1,654 +1,34 @@ -type Token @entity(immutable: false) { - # immutable values - # token address - id: Bytes! - # token symbol - symbol: String! - # token name - name: String! - # token decimals - decimals: BigInt! - - # mutable values - # current price - priceUSD: BigDecimal! - # volume in token units - volume: BigDecimal! - # volume in derived USD - volumeUSD: BigDecimal! - - # liquidity vault protocol fee - liquidityVaultProtocolFee: BigDecimal! - # liquidity vault protocol fee USD - liquidityVaultProtocolFeeUSD: BigDecimal! - - # router gateway protocol fee - routerGatewayProtocolFee: BigDecimal! - # router gateway protocol fee USD - routerGatewayProtocolFeeUSD: BigDecimal! - - # protocolFees in token units (liquidity vault + router gateway) - protocolFees: BigDecimal! - # protocolFees in USD (liquidity vault + router gateway) - protocolFeesUSD: BigDecimal! - - # number of pools containing this token - bookCount: BigInt! - # liquidity across all books in token units - totalValueLocked: BigDecimal! - # liquidity across all books in derived USD - totalValueLockedUSD: BigDecimal! - # derived fields - tokenDayData: [TokenDayData!]! @derivedFrom(field: "token") - books: [Book!]! @derivedFrom(field: "base") -} - -type Book @entity(immutable: false) { - # immutable values - # book id - id: ID! - # creation - createdAtTimestamp: BigInt! - # block book was created at - createdAtBlockNumber: BigInt! - # quote - quote: Token! - # base - base: Token! - # unit size - unitSize: BigInt! - # maker policy - makerPolicy: BigInt! - # maker fee - makerFee: BigDecimal! - isMakerFeeInQuote: Boolean! - # taker policy - takerPolicy: BigInt! - # taker fee - takerFee: BigDecimal! - isTakerFeeInQuote: Boolean! - # hooks - hooks: Bytes! - # bindings pool if exists - pool: Pool - - # mutable values - # current price tracker - priceRaw: BigInt! - # quote per base - price: BigDecimal! - # base per quote - inversePrice: BigDecimal! - # current tick - tick: BigInt! - # all time quote swapped - volumeQuote: BigDecimal! - # all time base swapped - volumeBase: BigDecimal! - # all time USD swapped - volumeUSD: BigDecimal! - # all time protocolFees quote - protocolFeesQuote: BigDecimal! - # all time protocolFees base - protocolFeesBase: BigDecimal! - # all time protocolFees derived USD - protocolFeesUSD: BigDecimal! - # total TVL across all ticks (denominated in quote token units) - totalValueLocked: BigDecimal! - # tvl USD - totalValueLockedUSD: BigDecimal! - # last taken timestamp - lastTakenTimestamp: BigInt! - # last taken block number - lastTakenBlockNumber: BigInt! - # derived fields - depths: [Depth!]! @derivedFrom(field: "book") - openOrders: [OpenOrder!]! @derivedFrom(field: "book") - takes: [Take!]! @derivedFrom(field: "book") -} - -type Depth @entity(immutable: false) { - # immutable values - # `${bookId}-${tick}` - id: ID! - # book - book: Book! - # tick - tick: BigInt! - # current price tracker - priceRaw: BigInt! - # quote per base - price: BigDecimal! - # base per quote - inversePrice: BigDecimal! - - # mutable values - # amount - unitAmount: BigInt! - baseAmount: BigInt! - quoteAmount: BigInt! - # latest tick index - latestTakenOrderIndex: BigInt! -} - -type OpenOrder @entity(immutable: false) { - # immutable values - # orderId - id: ID! - # time of txn - timestamp: BigInt! - # book position is within - book: Book! - # allow indexing by tokens - quote: Token! - # allow indexing by tokens - base: Token! - # txn origin - origin: Bytes! # the EOA that initiated the txn - # current price tracker - priceRaw: BigInt! - # current tick - tick: BigInt! - # current order index - orderIndex: BigInt! - # quote per base - price: BigDecimal! - # base per quote - inversePrice: BigDecimal! - - # mutable values - # owner of position where liquidity made to - owner: Bytes! - - # order size (descending when cancel) - amountUSD: BigDecimal! - unitAmount: BigInt! - baseAmount: BigInt! - quoteAmount: BigInt! - - # filled (ascending when taken) - filledUnitAmount: BigInt! - filledBaseAmount: BigInt! - filledQuoteAmount: BigInt! - - # claimed (descending when claim) - claimedUnitAmount: BigInt! - claimedBaseAmount: BigInt! - claimedQuoteAmount: BigInt! - - # claimable (ascending when taken) - claimableUnitAmount: BigInt! - claimableBaseAmount: BigInt! - claimableQuoteAmount: BigInt! - - # cancelable (descending when fill or cancel) - cancelableUnitAmount: BigInt! - cancelableBaseAmount: BigInt! - cancelableQuoteAmount: BigInt! -} - -type Transaction @entity(immutable: true) { - # txn hash - id: ID! - # block txn was included in - blockNumber: BigInt! - # timestamp txn was confirmed - timestamp: BigInt! - # gas used during txn execution - gasUsed: BigInt! - gasPrice: BigInt! - # address of the txn sender - from: Bytes! - # address of the txn receiver - to: Bytes - # txn value - value: BigInt! - # derived values - takes: [Take!]! @derivedFrom(field: "transaction") -} - -type ChartLog @entity(immutable: false) { - # `${baseToken}-${quoteToken}-${intervalType}-${timestamp}` - id: ID! - # `${baseToken}-${quoteToken}` - base: Token! - quote: Token! - marketCode: String! - # interval type: 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 6h, 1d, 1w - intervalType: String! - # normalized candle timestamp of the block where event occurred (second) - timestamp: BigInt! - open: BigDecimal! - high: BigDecimal! - low: BigDecimal! - close: BigDecimal! - # total traded volume in base token (sum of bid + ask filled) - baseVolume: BigDecimal! - bidBookBaseVolume: BigDecimal! - askBookBaseVolume: BigDecimal! -} - -type Pool @entity(immutable: false) { - # immutable values - # pool key - id: Bytes! - # salt - salt: Bytes! - # strategy contract address - strategy: Bytes! - # creation - createdAtTimestamp: BigInt! - # block pool was created at - createdAtBlockNumber: BigInt! - # transaction pool was created in - createdAtTransaction: Transaction! - # amount of tokenA deposited at pool creation - initialTokenAAmount: BigInt! - # amount of tokenB deposited at pool creation - initialTokenBAmount: BigInt! - # total supply of liquidity tokens minted at pool creation - initialTotalSupply: BigInt! - # initial price of liquidity tokens in USD - initialLPPriceUSD: BigDecimal! - # initial mint transaction - initialMintTransaction: Transaction - # tokenA - tokenA: Token! - # tokenB - tokenB: Token! - # bookA - bookA: Book! - # bookB - bookB: Book! - - # mutable values - # oracle price - oraclePrice: BigInt! - # total supply of liquidity tokens - totalSupply: BigInt! - # total liquidity of tokenA - liquidityA: BigInt! - # total liquidity of tokenB - liquidityB: BigInt! - # current lp tracker - lpPriceUSD: BigDecimal! - # current priceA tracker - priceA: BigDecimal! - priceARaw: BigInt! - tickA: BigInt! - # current priceB tracker - priceB: BigDecimal! - priceBRaw: BigInt! - tickB: BigInt! - # all time tokenA swapped - volumeTokenA: BigDecimal! - # all time tokenB swapped - volumeTokenB: BigDecimal! - # all time USD swapped - volumeUSD: BigDecimal! - # protocolFees in tokenA units - protocolFeesTokenA: BigDecimal! - # protocolFees in tokenB units - protocolFeesTokenB: BigDecimal! - # protocolFees in tokenA USD - protocolFeesAUSD: BigDecimal! - # protocolFees in tokenB USD - protocolFeesBUSD: BigDecimal! - # all time spread profit in USD - spreadProfitUSD: BigDecimal! - # tvl USD - totalValueLockedUSD: BigDecimal! - # hourly snapshots of pool data - poolHourData: [PoolHourData!]! @derivedFrom(field: "pool") - # daily snapshots of pool data - poolDayData: [PoolDayData!]! @derivedFrom(field: "pool") -} - -type User @entity(immutable: false) { - # wallet address (only eoa) - id: Bytes! - # user discovery metadata - firstSeenTimestamp: BigInt! - firstSeenBlockNumber: BigInt! - # volume in native token units - nativeVolume: BigDecimal! - - # derived fields - userDayData: [UserDayData!]! @derivedFrom(field: "user") -} - -type UserPoolBalance @entity(immutable: false) { - # `${user}-${pool}` - id: ID! - - # pointers - user: User! - pool: Pool! - - # current LP token balance of the user - lpBalance: BigInt! - - # current value of LP (in USD) - lpBalanceUSD: BigDecimal! - - # accumulated cost basis in USD (tolal amount of USD spent to acquire current LP balance) - costBasisUSD: BigDecimal! - - # average entry price of LP (average USD price per LP token based on cost basis = costBasisUSD / lpBalance) - averageLPPriceUSD: BigDecimal! - - # accumulate token0 deposited by user - totalTokenADeposited: BigInt! - - # accumulate token1 deposited by user - totalTokenBDeposited: BigInt! -} - -type BookDayData @entity(immutable: false) { - # `${bookId}-{periodStartUnix}` - id: ID! - # timestamp rounded to current day by dividing by 86400 - date: Int! - # pointer to book - book: Book! - # quote per base - price: BigDecimal! - # base per quote - inversePrice: BigDecimal! - # volume in quote units - volumeQuote: BigDecimal! - # volume in base units - volumeBase: BigDecimal! - # volume in USD - volumeUSD: BigDecimal! - # protocolFees in quote units - protocolFeesQuote: BigDecimal! - # protocolFees in base units - protocolFeesBase: BigDecimal! - # protocolFees in USD - protocolFeesUSD: BigDecimal! - # tvl derived in quote token units (denominated in quote token units) - totalValueLocked: BigDecimal! - # tvl derived in USD at end of period - totalValueLockedUSD: BigDecimal! - # opening price (=quote per base) - open: BigDecimal! - # high price (=quote per base) - high: BigDecimal! - # low price (=quote per base) - low: BigDecimal! - # close price (=quote per base) - close: BigDecimal! -} - -type TokenDayData @entity(immutable: false) { - # token address concatendated with date - id: ID! - # timestamp rounded to current day by dividing by 86400 - date: Int! - # pointer to token - token: Token! - # pointer to clober day data - cloberDayData: CloberDayData! - - # volume in token units - volume: BigDecimal! - # volume in derived USD - volumeUSD: BigDecimal! - # tvl derived in token units (denominated in quote token units) - totalValueLocked: BigDecimal! - # tvl derived in USD at end of period - totalValueLockedUSD: BigDecimal! - # price at end of period in USD - priceUSD: BigDecimal! - - # liquidity vault protocol fee - liquidityVaultProtocolFee: BigDecimal! - # liquidity vault protocol fee USD - liquidityVaultProtocolFeeUSD: BigDecimal! - - # router gateway protocol fee - routerGatewayProtocolFee: BigDecimal! - # router gateway protocol fee USD - routerGatewayProtocolFeeUSD: BigDecimal! - - # protocolFees in token units (liquidity vault + router gateway) - protocolFees: BigDecimal! - # protocolFees in USD (liquidity vault + router gateway) - protocolFeesUSD: BigDecimal! - - # opening price USD - open: BigDecimal! - # high price USD - high: BigDecimal! - # low price USD - low: BigDecimal! - # close price USD - close: BigDecimal! -} - # Data accumulated and condensed into day stats for all of Clober type CloberDayData @entity(immutable: false) { # timestamp rounded to current day by dividing by 86400 id: ID! # timestamp rounded to current day by dividing by 86400 date: Int! - # number of daily transactions - txCount: BigInt! - # number of daily wallets - walletCount: BigInt! - # number of daily new wallets - newWalletCount: BigInt! # derived fields - tokenDayData: [TokenDayData!]! @derivedFrom(field: "cloberDayData") - transactionTypes: [TransactionTypeDayData!]! @derivedFrom(field: "cloberDayData") - routerDayData: [RouterDayData!]! @derivedFrom(field: "cloberDayData") + contractInteractionDayData: [ContractInteractionDayData!]! @derivedFrom(field: "cloberDayData") } -type TransactionTypeDayData @entity(immutable: false) { - # ${type}-${timestamp rounded to current day by dividing by 86400} +type ContractInteraction @entity(immutable: false) { + # `${contractAddress}` id: ID! - # timestamp rounded to current day by dividing by 86400 - date: Int! - # pointer to clober day data - cloberDayData: CloberDayData! - # type of transaction - type: String! - - # tx count - txCount: BigInt! + # count of interactions + callCount: BigInt! + # accumulated volume in USD + volumeUSD: BigDecimal! } -type RouterDayData @entity(immutable: false) { - # ${router}-${timestamp rounded to current day by dividing by 86400} +type ContractInteractionDayData @entity(immutable: false) { + # `${contractAddress}-{periodStartUnix}` id: ID! # timestamp rounded to current day by dividing by 86400 date: Int! # pointer to clober day data cloberDayData: CloberDayData! - # router of swap - router: Bytes! - - # tx count - txCount: BigInt! -} - -type UserDayData @entity(immutable: false) { - # ${wallet}-{timestamp rounded to current day by dividing by 86400} - id: ID! - # timestamp rounded to current day by dividing by 86400 - date: Int! - # number of daily transactions - txCount: BigInt! - # wallet address - user: User! - - # derived fields - volumes: [UserDayVolume!]! @derivedFrom(field: "userDayData") -} - -type UserDayVolume @entity(immutable: false) { - # ${wallet}-${token.id}-${timestamp rounded to current day by dividing by 86400} - id: ID! - # timestamp rounded to current day by dividing by 86400 - date: Int! - # wallet address - user: Bytes! - # pointer to user day data - userDayData: UserDayData! - # binding to token - token: Token! - # volume in token units - volume: BigDecimal! - # volume in derived USD + # contract address + contract: Bytes! + # count of interactions + callCount: BigInt! + # accumulated volume in USD volumeUSD: BigDecimal! } - -# Data accumulated and condensed into day stats for each pool -type PoolDayData @entity(immutable: false) { - # `${poolKey}-{periodStartUnix}` - id: ID! - # timestamp rounded to current day by dividing by 86400 - date: Int! - # pointer to pool - pool: Pool! - - # oracle price - oraclePrice: BigInt! - # total supply of liquidity tokens - totalSupply: BigInt! - # total liquidity of tokenA - liquidityA: BigInt! - # total liquidity of tokenB - liquidityB: BigInt! - # current lp tracker - lpPriceUSD: BigDecimal! - # current priceA tracker - priceA: BigDecimal! - priceARaw: BigInt! - tickA: BigInt! - # current priceB tracker - priceB: BigDecimal! - priceBRaw: BigInt! - tickB: BigInt! - # tokenA swapped - volumeTokenA: BigDecimal! - # tokenB swapped - volumeTokenB: BigDecimal! - # USD swapped - volumeUSD: BigDecimal! - # protocolFees in tokenA units - protocolFeesTokenA: BigDecimal! - # protocolFees in tokenB units - protocolFeesTokenB: BigDecimal! - # protocolFees in tokenA USD - protocolFeesAUSD: BigDecimal! - # protocolFees in tokenB USD - protocolFeesBUSD: BigDecimal! - # spread profit in USD - spreadProfitUSD: BigDecimal! - # tvl derived in USD at end of period - totalValueLockedUSD: BigDecimal! -} - -# hourly stats tracker for pool -type PoolHourData @entity(immutable: false) { - # ${poolKey}-{periodStartUnix} - id: ID! - # unix timestamp for start of hour - date: Int! - # pointer to pool - pool: Pool! - - # oracle price - oraclePrice: BigInt! - # total supply of liquidity tokens - totalSupply: BigInt! - # total liquidity of tokenA - liquidityA: BigInt! - # total liquidity of tokenB - liquidityB: BigInt! - # current lp tracker - lpPriceUSD: BigDecimal! - # current priceA tracker - priceA: BigDecimal! - priceARaw: BigInt! - tickA: BigInt! - # current priceB tracker - priceB: BigDecimal! - priceBRaw: BigInt! - tickB: BigInt! - # tokenA swapped - volumeTokenA: BigDecimal! - # tokenB swapped - volumeTokenB: BigDecimal! - # USD swapped - volumeUSD: BigDecimal! - # protocolFees in tokenA units - protocolFeesTokenA: BigDecimal! - # protocolFees in tokenB units - protocolFeesTokenB: BigDecimal! - # protocolFees in tokenA USD - protocolFeesAUSD: BigDecimal! - # protocolFees in tokenB USD - protocolFeesBUSD: BigDecimal! - # spread profit in USD - spreadProfitUSD: BigDecimal! - # tvl derived in USD at end of period - totalValueLockedUSD: BigDecimal! -} - -# entity for take event on clober book -type Take @entity(immutable: true) { - # {txHash}-{logIndex} - id: ID! - # pointer to transaction - transaction: Transaction! - # timestamp of transaction - timestamp: BigInt! - # book - book: Book! - # allow indexing by tokens - inputToken: Token! - # allow indexing by tokens - outputToken: Token! - # txn origin - origin: Bytes! # the EOA that initiated the txn - # amount In - inputAmount: BigInt! - # amount Out - outputAmount: BigInt! - # amount In USD - amountUSD: BigDecimal! - # index within the txn - logIndex: BigInt -} - -# entity for swap event on clober meta aggregator -type Swap @entity(immutable: true) { - # {txHash}-{logIndex} - id: ID! - # pointer to transaction - transaction: Transaction! - # timestamp of transaction - timestamp: BigInt! - # allow indexing by tokens - inputToken: Bytes! - # allow indexing by tokens - outputToken: Bytes! - # txn origin - origin: Bytes! # the EOA that initiated the txn - # amount In - inputAmount: BigInt! - # amount Out - outputAmount: BigInt! - # amount In USD - amountUSD: BigDecimal! - # index within the txn - logIndex: BigInt - # router address - router: Bytes! - # fee in ouputToken wei - fee: BigInt! -} \ No newline at end of file diff --git a/script/utils/deploy-utils.ts b/script/utils/deploy-utils.ts index 9a54eb3..85bc130 100644 --- a/script/utils/deploy-utils.ts +++ b/script/utils/deploy-utils.ts @@ -21,7 +21,7 @@ const buildGoldskyDeployCommand = async ( process.exit(1) } - const subgraphName = `v2-subgraph-${network}/${gitHashString}` + const subgraphName = `interaction-contracts-${network}/${gitHashString}` return `goldsky subgraph deploy ${subgraphName} --path .` } @@ -34,7 +34,7 @@ const buildAlchemyDeployCommand = ( throw new Error('ALCHEMY_DEPLOY_KEY must be set') } const deployKey = process.env.ALCHEMY_DEPLOY_KEY - return `graph deploy v2-subgraph-${network} --version-label ${gitHashString} --node https://subgraphs.alchemy.com/api/subgraphs/deploy --deploy-key ${deployKey} --ipfs https://ipfs.satsuma.xyz` + return `graph deploy interaction-contracts-${network} --version-label ${gitHashString} --node https://subgraphs.alchemy.com/api/subgraphs/deploy --deploy-key ${deployKey} --ipfs https://ipfs.satsuma.xyz` } const buildOrmiDeployCommand = ( @@ -46,7 +46,7 @@ const buildOrmiDeployCommand = ( throw new Error('ORMI_DEPLOY_KEY must be set') } const deployKey = process.env.ORMI_DEPLOY_KEY - return `graph deploy v2-subgraph-${network} --version-label ${gitHashString} --node https://api.subgraph.ormilabs.com/deploy --deploy-key ${deployKey} --ipfs https://api.subgraph.ormilabs.com/ipfs` + return `graph deploy interaction-contracts-${network} --version-label ${gitHashString} --node https://api.subgraph.ormilabs.com/deploy --deploy-key ${deployKey} --ipfs https://api.subgraph.ormilabs.com/ipfs` } const buildSentioDeployCommand = ( @@ -59,7 +59,7 @@ const buildSentioDeployCommand = ( } const deployKey = process.env.SENTIO_DEPLOY_KEY network = network.includes('testnet') ? network : `${network}-mainnet` - return `graph deploy clober-dex/v2-subgraph-${network} --version-label ${gitHashString} --node https://app.sentio.xyz/api/v1/graph-node --deploy-key ${deployKey} --ipfs https://app.sentio.xyz/api/v1/ipfs` + return `graph deploy clober-dex/interaction-contracts-${network} --version-label ${gitHashString} --node https://app.sentio.xyz/api/v1/graph-node --deploy-key ${deployKey} --ipfs https://app.sentio.xyz/api/v1/ipfs` } const codegen = async (): Promise => { diff --git a/script/utils/prepare-network.ts b/script/utils/prepare-network.ts index fbaab0b..de4dde4 100644 --- a/script/utils/prepare-network.ts +++ b/script/utils/prepare-network.ts @@ -9,6 +9,7 @@ export enum NETWORK { MONAD_TESTNET = 'monad-testnet', MONAD_MAINNET = 'monad-mainnet', MONAD = 'monad', // monad-mainnet alias + base = 'base', RISE_SEPOLIA = 'rise-sepolia', ARBITRUM_SEPOLIA = 'arbitrum-sepolia', BERACHAIN_MAINNET = 'berachain-mainnet', diff --git a/src/mappings/book-manager/cancel.ts b/src/mappings/book-manager/cancel.ts deleted file mode 100644 index 62fc503..0000000 --- a/src/mappings/book-manager/cancel.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { Address, store } from '@graphprotocol/graph-ts' - -import { Cancel } from '../../../generated/BookManager/BookManager' -import { - decodeBookIDFromOrderID, - getPendingUnitAmount, -} from '../../common/order' -import { - getBookOrLog, - getDepthOrLog, - getOpenOrderOrLog, - getTokenOrLog, -} from '../../common/entity-getters' -import { tickToPrice } from '../../common/tick' -import { unitToBase, unitToQuote } from '../../common/amount' -import { convertTokenToDecimal } from '../../common/utils' -import { calculateValueUSD, getTokenUSDPriceFlat } from '../../common/pricing' -import { - updateBookDayData, - updateDayData, - updateTokenDayData, -} from '../interval-updates' -import { OPERATOR } from '../../common/chain' - -export function handleCancel(event: Cancel): void { - if ( - event.transaction.to && - !event.transaction.to!.equals(Address.fromString(OPERATOR)) - ) { - updateDayData(event, 'CANCEL') - } - - if (event.params.unit.isZero()) { - return - } - - const bookID = decodeBookIDFromOrderID(event.params.orderId) - const book = getBookOrLog(bookID, 'CANCEL') - if (book === null) { - return - } - - const openOrderID = event.params.orderId.toString() - const openOrder = getOpenOrderOrLog(openOrderID, 'CANCEL') - if (openOrder === null) { - return - } - - const depthID = bookID.concat('-').concat(openOrder.tick.toString()) - const depth = getDepthOrLog(depthID, 'CANCEL') - if (depth === null) { - return - } - - const quote = getTokenOrLog(book.quote, 'CANCEL') - const base = getTokenOrLog(book.base, 'CANCEL') - if (quote && base) { - const priceRaw = tickToPrice(openOrder.tick.toI32()) - - const quoteAmount = unitToQuote(book.unitSize, event.params.unit) - const quoteAmountDecimal = convertTokenToDecimal( - quoteAmount, - quote.decimals, - ) - const quoteInUSD = getTokenUSDPriceFlat(quote) - - const baseAmount = unitToBase(book.unitSize, event.params.unit, priceRaw) - const baseInUSD = getTokenUSDPriceFlat(base) - - // update quote data - quote.totalValueLocked = quote.totalValueLocked.minus(quoteAmountDecimal) - quote.totalValueLockedUSD = quote.totalValueLocked.times(quoteInUSD) - - // book data - book.totalValueLocked = book.totalValueLocked.minus(quoteAmountDecimal) - book.totalValueLockedUSD = book.totalValueLocked.times(quoteInUSD) - - // open order data - openOrder.unitAmount = openOrder.unitAmount.minus(event.params.unit) - openOrder.quoteAmount = openOrder.quoteAmount.minus(quoteAmount) - openOrder.baseAmount = openOrder.baseAmount.minus(baseAmount) - openOrder.amountUSD = calculateValueUSD( - convertTokenToDecimal(openOrder.quoteAmount, quote.decimals), - quoteInUSD, - convertTokenToDecimal(openOrder.baseAmount, base.decimals), - baseInUSD, - ) - - openOrder.cancelableUnitAmount = openOrder.cancelableUnitAmount.minus( - event.params.unit, - ) - openOrder.cancelableQuoteAmount = - openOrder.cancelableQuoteAmount.minus(quoteAmount) - openOrder.cancelableBaseAmount = - openOrder.cancelableBaseAmount.minus(baseAmount) - - // depth data - depth.unitAmount = depth.unitAmount.minus(event.params.unit) - depth.quoteAmount = depth.quoteAmount.minus(quoteAmount) - depth.baseAmount = depth.baseAmount.minus(baseAmount) - - updateBookDayData(book, event) - updateTokenDayData(quote, quoteInUSD, event) - - if (getPendingUnitAmount(openOrder).isZero()) { - store.remove('OpenOrder', openOrderID) - } else { - openOrder.save() - } - depth.save() - book.save() - quote.save() - } -} diff --git a/src/mappings/book-manager/claim.ts b/src/mappings/book-manager/claim.ts deleted file mode 100644 index dc2cfd1..0000000 --- a/src/mappings/book-manager/claim.ts +++ /dev/null @@ -1,221 +0,0 @@ -import { - Address, - BigDecimal, - BigInt, - ethereum, - log, - store, -} from '@graphprotocol/graph-ts' - -import { Claim } from '../../../generated/BookManager/BookManager' -import { - decodeBookIDFromOrderID, - getPendingUnitAmount, -} from '../../common/order' -import { - getBookOrLog, - getOpenOrderOrLog, - getPoolOrLog, - getTokenOrLog, -} from '../../common/entity-getters' -import { unitToBase, unitToQuote } from '../../common/amount' -import { tickToPrice } from '../../common/tick' -import { OpenOrder, Pool } from '../../../generated/schema' -import { TWO_BD, ZERO_BD } from '../../common/constants' -import { convertTokenToDecimal } from '../../common/utils' -import { getTokenUSDPriceFlat } from '../../common/pricing' -import { - updateBookDayData, - updateDayData, - updatePoolDayData, - updatePoolHourData, - updateTokenDayData, -} from '../interval-updates' -import { LIQUIDITY_VAULT, OPERATOR } from '../../common/chain' - -function updatePool( - pool: Pool, - baseClaimedAmountDecimal: BigDecimal, - marketQuoteInUSD: BigDecimal, - openOrder: OpenOrder, - event: ethereum.Event, -): void { - let spreadInUsd = pool.priceB.minus(pool.priceA).times(marketQuoteInUSD) - if (spreadInUsd.lt(BigDecimal.zero())) { - spreadInUsd = ZERO_BD - } - - if ( - BigInt.fromString(pool.bookA).equals(BigInt.fromString(openOrder.book)) || - BigInt.fromString(pool.bookB).equals(BigInt.fromString(openOrder.book)) - ) { - const spreadDeltaInUsd = spreadInUsd - .div(TWO_BD) - .times(baseClaimedAmountDecimal) - pool.spreadProfitUSD = pool.spreadProfitUSD.plus(spreadDeltaInUsd) - - const poolHourData = updatePoolHourData(pool, event) - const poolDayData = updatePoolDayData(pool, event) - - // update intervals - poolHourData.spreadProfitUSD = - poolHourData.spreadProfitUSD.plus(spreadDeltaInUsd) - poolDayData.spreadProfitUSD = - poolDayData.spreadProfitUSD.plus(spreadDeltaInUsd) - - pool.save() - poolHourData.save() - poolDayData.save() - } else { - log.warning('Pool {} does not contain book {}', [ - pool.id.toString(), - openOrder.book.toString(), - ]) - } -} - -export function handleClaim(event: Claim): void { - if ( - event.transaction.to && - !event.transaction.to!.equals(Address.fromString(OPERATOR)) - ) { - updateDayData(event, 'CLAIM') - } - - if (event.params.unit.isZero()) { - return - } - - const bookID = decodeBookIDFromOrderID(event.params.orderId) - const book = getBookOrLog(bookID, 'CLAIM') - if (book === null) { - return - } - - const openOrderID = event.params.orderId.toString() - const openOrder = getOpenOrderOrLog(openOrderID, 'CLAIM') - if (openOrder === null) { - return - } - - const quote = getTokenOrLog(book.quote, 'CLAIM') - const base = getTokenOrLog(book.base, 'CLAIM') - if (quote && base) { - const priceRaw = tickToPrice(openOrder.tick.toI32()) - - const quoteAmount = unitToQuote(book.unitSize, event.params.unit) - const baseAmount = unitToBase(book.unitSize, event.params.unit, priceRaw) - - // claimed data - openOrder.claimedUnitAmount = openOrder.claimedUnitAmount.plus( - event.params.unit, - ) - openOrder.claimedBaseAmount = openOrder.claimedBaseAmount.plus(baseAmount) - openOrder.claimedQuoteAmount = - openOrder.claimedQuoteAmount.plus(quoteAmount) - - // claimable data - openOrder.claimableUnitAmount = openOrder.claimableUnitAmount.minus( - event.params.unit, - ) - openOrder.claimableBaseAmount = - openOrder.claimableBaseAmount.minus(baseAmount) - openOrder.claimableQuoteAmount = - openOrder.claimableQuoteAmount.minus(quoteAmount) - - const baseInUSD = getTokenUSDPriceFlat(base) - const quoteInUSD = getTokenUSDPriceFlat(quote) - - if ( - book.pool !== null && - Address.fromBytes(openOrder.owner).equals( - Address.fromString(LIQUIDITY_VAULT), - ) - ) { - const pool = getPoolOrLog(book.pool!, 'CLAIM') as Pool - const isClaimingBidBook = BigInt.fromString(pool.bookA!).equals( - BigInt.fromString(bookID), - ) - const baseClaimedAmountDecimal = isClaimingBidBook - ? convertTokenToDecimal(baseAmount, base.decimals) - : convertTokenToDecimal(quoteAmount, quote.decimals) - const marketQuoteInUSD = isClaimingBidBook ? quoteInUSD : baseInUSD - if (pool) { - updatePool( - pool, - baseClaimedAmountDecimal, - marketQuoteInUSD, - openOrder, - event, - ) - } - } - - if (book.makerFee.gt(ZERO_BD)) { - // interval data - const bookDayData = updateBookDayData(book, event) - const quoteDayData = updateTokenDayData(quote, quoteInUSD, event) - const baseDayData = updateTokenDayData(base, baseInUSD, event) - - if (book.isMakerFeeInQuote) { - const protocolFeesQuote = convertTokenToDecimal( - quoteAmount, - quote.decimals, - ).times(book.makerFee) - const protocolFeesInUSD = protocolFeesQuote.times(quoteInUSD) - - book.protocolFeesQuote = book.protocolFeesQuote.plus(protocolFeesQuote) - book.protocolFeesUSD = book.protocolFeesUSD.plus(protocolFeesInUSD) - - quote.protocolFees = quote.protocolFees.plus(protocolFeesQuote) - quote.protocolFeesUSD = quote.protocolFeesUSD.plus(protocolFeesInUSD) - - bookDayData.protocolFeesQuote = - bookDayData.protocolFeesQuote.plus(protocolFeesQuote) - bookDayData.protocolFeesUSD = - bookDayData.protocolFeesUSD.plus(protocolFeesInUSD) - - quoteDayData.protocolFees = - quoteDayData.protocolFees.plus(protocolFeesQuote) - quoteDayData.protocolFeesUSD = - quoteDayData.protocolFeesUSD.plus(protocolFeesInUSD) - } else { - const protocolFeesBase = convertTokenToDecimal( - baseAmount, - base.decimals, - ).times(book.makerFee) - const protocolFeesInUSD = protocolFeesBase.times(baseInUSD) - - book.protocolFeesBase = book.protocolFeesBase.plus(protocolFeesBase) - book.protocolFeesUSD = book.protocolFeesUSD.plus(protocolFeesInUSD) - - base.protocolFees = base.protocolFees.plus(protocolFeesBase) - base.protocolFeesUSD = base.protocolFeesUSD.plus(protocolFeesInUSD) - - bookDayData.protocolFeesBase = - bookDayData.protocolFeesBase.plus(protocolFeesBase) - bookDayData.protocolFeesUSD = - bookDayData.protocolFeesUSD.plus(protocolFeesInUSD) - - baseDayData.protocolFees = - baseDayData.protocolFees.plus(protocolFeesBase) - baseDayData.protocolFeesUSD = - baseDayData.protocolFeesUSD.plus(protocolFeesInUSD) - } - - // save - book.save() - quote.save() - base.save() - bookDayData.save() - quoteDayData.save() - baseDayData.save() - } - - if (getPendingUnitAmount(openOrder).isZero()) { - store.remove('OpenOrder', openOrderID) - } else { - openOrder.save() - } - } -} diff --git a/src/mappings/book-manager/make.ts b/src/mappings/book-manager/make.ts deleted file mode 100644 index c09b686..0000000 --- a/src/mappings/book-manager/make.ts +++ /dev/null @@ -1,141 +0,0 @@ -import { Address, BigInt } from '@graphprotocol/graph-ts' - -import { Make } from '../../../generated/BookManager/BookManager' -import { Depth, OpenOrder } from '../../../generated/schema' -import { unitToBase, unitToQuote } from '../../common/amount' -import { - formatInvertedPrice, - formatPrice, - tickToPrice, -} from '../../common/tick' -import { ZERO_BI } from '../../common/constants' -import { convertTokenToDecimal } from '../../common/utils' -import { calculateValueUSD, getTokenUSDPriceFlat } from '../../common/pricing' -import { encodeOrderID } from '../../common/order' -import { - updateBookDayData, - updateDayData, - updateTokenDayData, -} from '../interval-updates' -import { getBookOrLog, getTokenOrLog } from '../../common/entity-getters' -import { OPERATOR } from '../../common/chain' - -export function handleMake(event: Make): void { - if ( - event.transaction.to && - !event.transaction.to!.equals(Address.fromString(OPERATOR)) - ) { - updateDayData(event, 'MAKE') - } - - const book = getBookOrLog(event.params.bookId.toString(), 'MAKE') - if (book === null) { - return - } - - const quote = getTokenOrLog(book.quote, 'MAKE') - const base = getTokenOrLog(book.base, 'MAKE') - if (quote && base) { - const tick = BigInt.fromI32(event.params.tick) - const priceRaw = tickToPrice(tick.toI32()) - const orderID = encodeOrderID(book.id, tick, event.params.orderIndex) - - const quoteAmount = unitToQuote(book.unitSize, event.params.unit) - const quoteAmountDecimal = convertTokenToDecimal( - quoteAmount, - quote.decimals, - ) - const quoteInUSD = getTokenUSDPriceFlat(quote) - - const baseAmount = unitToBase(book.unitSize, event.params.unit, priceRaw) - const baseAmountDecimal = convertTokenToDecimal(baseAmount, base.decimals) - const baseInUSD = getTokenUSDPriceFlat(base) - - const amountUSD = calculateValueUSD( - quoteAmountDecimal, - quoteInUSD, - baseAmountDecimal, - baseInUSD, - ) - - // update quote data - quote.totalValueLocked = quote.totalValueLocked.plus(quoteAmountDecimal) - quote.totalValueLockedUSD = quote.totalValueLocked.times(quoteInUSD) - - // book data - book.totalValueLocked = book.totalValueLocked.plus(quoteAmountDecimal) - book.totalValueLockedUSD = book.totalValueLocked.times(quoteInUSD) - - // open order data - const openOrder = new OpenOrder(orderID.toString()) - openOrder.timestamp = event.block.timestamp - openOrder.book = book.id - openOrder.quote = quote.id - openOrder.base = base.id - openOrder.origin = event.transaction.from - openOrder.owner = event.params.user - openOrder.priceRaw = priceRaw - openOrder.tick = tick - openOrder.orderIndex = event.params.orderIndex - openOrder.price = formatPrice(priceRaw, base.decimals, quote.decimals) // checked - openOrder.inversePrice = formatInvertedPrice( - priceRaw, - base.decimals, - quote.decimals, - ) // checked - // initial - openOrder.amountUSD = amountUSD - openOrder.unitAmount = event.params.unit - openOrder.baseAmount = baseAmount - openOrder.quoteAmount = quoteAmount - // filled - openOrder.filledUnitAmount = ZERO_BI - openOrder.filledBaseAmount = ZERO_BI - openOrder.filledQuoteAmount = ZERO_BI - // claimed - openOrder.claimedUnitAmount = ZERO_BI - openOrder.claimedBaseAmount = ZERO_BI - openOrder.claimedQuoteAmount = ZERO_BI - // claimable - openOrder.claimableUnitAmount = ZERO_BI - openOrder.claimableBaseAmount = ZERO_BI - openOrder.claimableQuoteAmount = ZERO_BI - // open - openOrder.cancelableUnitAmount = event.params.unit - openOrder.cancelableBaseAmount = baseAmount - openOrder.cancelableQuoteAmount = quoteAmount - - // depth data - const depthID = book.id.toString().concat('-').concat(tick.toString()) - let depth = Depth.load(depthID) - if (depth === null) { - depth = new Depth(depthID) - depth.book = book.id - depth.tick = tick - depth.latestTakenOrderIndex = ZERO_BI - depth.unitAmount = event.params.unit - depth.baseAmount = baseAmount - depth.quoteAmount = quoteAmount - depth.priceRaw = priceRaw - depth.price = formatPrice(priceRaw, base.decimals, quote.decimals) // checked - depth.inversePrice = formatInvertedPrice( - priceRaw, - base.decimals, - quote.decimals, - ) // checked - } else { - depth.unitAmount = depth.unitAmount.plus(event.params.unit) - depth.baseAmount = depth.baseAmount.plus(baseAmount) - depth.quoteAmount = depth.quoteAmount.plus(quoteAmount) - } - - updateBookDayData(book, event) - updateTokenDayData(quote, quoteInUSD, event) - - // save all - book.save() - quote.save() - openOrder.save() - depth.save() - } -} diff --git a/src/mappings/book-manager/open.ts b/src/mappings/book-manager/open.ts deleted file mode 100644 index 76cc456..0000000 --- a/src/mappings/book-manager/open.ts +++ /dev/null @@ -1,125 +0,0 @@ -import { BigDecimal, BigInt, log } from '@graphprotocol/graph-ts' - -import { Open } from '../../../generated/BookManager/BookManager' -import { Book, Token } from '../../../generated/schema' -import { - fetchTokenDecimals, - fetchTokenName, - fetchTokenSymbol, -} from '../../common/token' -import { ONE_BI, ZERO_BD, ZERO_BI } from '../../common/constants' - -const FEE_PRECISION = BigDecimal.fromString('1000000') -const RATE_MASK = BigInt.fromI32(8388607) -const MAX_FEE_RATE = BigInt.fromI32(500000) - -// @ts-ignore -export function getFeeRate(feePolicy: i32): BigDecimal { - const feeBigInt = BigInt.fromI32(feePolicy) - .bitAnd(RATE_MASK) - .minus(MAX_FEE_RATE) - return BigDecimal.fromString(feeBigInt.toString()).div(FEE_PRECISION) -} - -export function getUsesFeeInQuote(feePolicy: i32): boolean { - return BigInt.fromI32(feePolicy).rightShift(23).gt(ZERO_BI) -} - -export function handleBookOpen(event: Open): void { - const book = new Book(event.params.id.toString()) as Book - let quote = Token.load(event.params.quote) - let base = Token.load(event.params.base) - - if (quote === null) { - quote = new Token(event.params.quote) - quote.symbol = fetchTokenSymbol(event.params.quote) - quote.name = fetchTokenName(event.params.quote) - // quote.totalSupply = fetchTokenTotalSupply(event.params.quote) - const decimals = fetchTokenDecimals(event.params.quote) - - // bail if we couldn't figure out the decimals - if (decimals === null) { - log.debug('mybug the decimal on token 0 was null', []) - return - } - - quote.decimals = decimals - quote.volume = ZERO_BD - quote.volumeUSD = ZERO_BD - - quote.liquidityVaultProtocolFee = ZERO_BD - quote.liquidityVaultProtocolFeeUSD = ZERO_BD - quote.routerGatewayProtocolFee = ZERO_BD - quote.routerGatewayProtocolFeeUSD = ZERO_BD - quote.protocolFees = ZERO_BD - quote.protocolFeesUSD = ZERO_BD - - quote.bookCount = ZERO_BI - quote.totalValueLocked = ZERO_BD - quote.totalValueLockedUSD = ZERO_BD - quote.priceUSD = ZERO_BD - } - quote.bookCount = quote.bookCount.plus(ONE_BI) - - if (base === null) { - base = new Token(event.params.base) - base.symbol = fetchTokenSymbol(event.params.base) - base.name = fetchTokenName(event.params.base) - // base.totalSupply = fetchTokenTotalSupply(event.params.base) - const decimals = fetchTokenDecimals(event.params.base) - - // bail if we couldn't figure out the decimals - if (decimals === null) { - log.debug('mybug the decimal on token 0 was null', []) - return - } - - base.decimals = decimals - base.volume = ZERO_BD - base.volumeUSD = ZERO_BD - - base.liquidityVaultProtocolFee = ZERO_BD - base.liquidityVaultProtocolFeeUSD = ZERO_BD - base.routerGatewayProtocolFee = ZERO_BD - base.routerGatewayProtocolFeeUSD = ZERO_BD - base.protocolFees = ZERO_BD - base.protocolFeesUSD = ZERO_BD - - base.bookCount = ZERO_BI - base.totalValueLocked = ZERO_BD - base.totalValueLockedUSD = ZERO_BD - base.priceUSD = ZERO_BD - } - base.bookCount = base.bookCount.plus(ONE_BI) - - book.createdAtTimestamp = event.block.timestamp - book.createdAtBlockNumber = event.block.number - book.quote = quote.id - book.base = base.id - book.unitSize = event.params.unitSize - book.makerPolicy = BigInt.fromI32(event.params.makerPolicy) - book.makerFee = getFeeRate(event.params.makerPolicy) - book.isMakerFeeInQuote = getUsesFeeInQuote(event.params.makerPolicy) - book.takerPolicy = BigInt.fromI32(event.params.takerPolicy) - book.takerFee = getFeeRate(event.params.takerPolicy) - book.isTakerFeeInQuote = getUsesFeeInQuote(event.params.takerPolicy) - book.hooks = event.params.hooks - - book.priceRaw = ZERO_BI - book.price = ZERO_BD - book.inversePrice = ZERO_BD - book.tick = ZERO_BI - book.volumeQuote = ZERO_BD - book.volumeBase = ZERO_BD - book.volumeUSD = ZERO_BD - book.protocolFeesQuote = ZERO_BD - book.protocolFeesBase = ZERO_BD - book.protocolFeesUSD = ZERO_BD - book.totalValueLocked = ZERO_BD - book.totalValueLockedUSD = ZERO_BD - book.lastTakenBlockNumber = ZERO_BI - book.lastTakenTimestamp = ZERO_BI - book.save() - quote.save() - base.save() -} diff --git a/src/mappings/book-manager/take.ts b/src/mappings/book-manager/take.ts index 19185a3..4f418a4 100644 --- a/src/mappings/book-manager/take.ts +++ b/src/mappings/book-manager/take.ts @@ -1,589 +1,80 @@ -import { - Address, - BigDecimal, - BigInt, - ethereum, - log, -} from '@graphprotocol/graph-ts' +import { BigInt } from '@graphprotocol/graph-ts' import { Take } from '../../../generated/BookManager/BookManager' import { - Book, - ChartLog, - OpenOrder, - Pool, - Take as TakeEntity, - Token, + CloberDayData, + ContractInteraction, + ContractInteractionDayData, } from '../../../generated/schema' -import { unitToBase, unitToQuote } from '../../common/amount' -import { encodeOrderID } from '../../common/order' import { ONE_BI, ZERO_BD, ZERO_BI } from '../../common/constants' -import { - getBookOrLog, - getDepthOrLog, - getPoolOrLog, - getTokenOrLog, -} from '../../common/entity-getters' +import { tickToPrice } from '../../common/tick' +import { unitToBase } from '../../common/amount' import { convertTokenToDecimal } from '../../common/utils' -import { calculateValueUSD, getTokenUSDPriceFlat } from '../../common/pricing' -import { - formatInvertedPrice, - formatPrice, - tickToPrice, -} from '../../common/tick' -import { - updateBookDayData, - updateDayData, - updatePoolDayData, - updatePoolHourData, - updateTokenDayData, - updateUserDayVolume, - updateUserNativeVolume, -} from '../interval-updates' -import { - CHART_LOG_INTERVALS, - encodeChartLogID, - encodeMarketCode, -} from '../../common/chart' -import { - LIQUIDITY_VAULT, - SKIP_CHART, - SKIP_TAKE_AND_SWAP, -} from '../../common/chain' - -function fillOpenOrder( - openOrder: OpenOrder, - unitSize: BigInt, - filledUnitAmount: BigInt, -): void { - const updatedFilledUnitAmount = - openOrder.filledUnitAmount.plus(filledUnitAmount) - openOrder.filledUnitAmount = updatedFilledUnitAmount - openOrder.filledBaseAmount = unitToBase( - unitSize, - updatedFilledUnitAmount, - openOrder.priceRaw, - ) - openOrder.filledQuoteAmount = unitToQuote(unitSize, updatedFilledUnitAmount) - - const claimableUnitAfterFill = - openOrder.claimableUnitAmount.plus(filledUnitAmount) - openOrder.claimableUnitAmount = claimableUnitAfterFill - openOrder.claimableBaseAmount = unitToBase( - unitSize, - claimableUnitAfterFill, - openOrder.priceRaw, - ) - openOrder.claimableQuoteAmount = unitToQuote(unitSize, claimableUnitAfterFill) - - const remainingCancelableUnitAmount = - openOrder.cancelableUnitAmount.minus(filledUnitAmount) - openOrder.cancelableUnitAmount = remainingCancelableUnitAmount - openOrder.cancelableBaseAmount = unitToBase( - unitSize, - remainingCancelableUnitAmount, - openOrder.priceRaw, - ) - openOrder.cancelableQuoteAmount = unitToQuote( - unitSize, - remainingCancelableUnitAmount, - ) - - if (remainingCancelableUnitAmount.lt(ZERO_BI)) { - log.error('[TAKE] Negative cancelable unit amount: {}', [openOrder.id]) - } - - openOrder.save() -} - -function updateChart( - block: ethereum.Block, - takenBaseAmountDecimal: BigDecimal, - takenQuoteAmountDecimal: BigDecimal, - book: Book, - base: Token, - quote: Token, -): void { - for (let i = 0; i < CHART_LOG_INTERVALS.entries.length; i++) { - const entry = CHART_LOG_INTERVALS.entries[i] - const intervalType = entry.key - const intervalInNumber = entry.value - const timestampForAcc = (Math.floor( - (block.timestamp.toI64() as number) / intervalInNumber, - ) * intervalInNumber) as i64 - - // natural chart log - const chartLogID = encodeChartLogID( - base, - quote, - intervalType, - timestampForAcc, - ) - const marketCode = encodeMarketCode(base, quote) - let chartLog = ChartLog.load(chartLogID) - if (chartLog === null) { - chartLog = new ChartLog(chartLogID) - chartLog.marketCode = marketCode - chartLog.base = base.id - chartLog.quote = quote.id - chartLog.intervalType = intervalType - chartLog.timestamp = BigInt.fromI64(timestampForAcc) - chartLog.open = book.price - chartLog.high = book.price - chartLog.low = book.price - chartLog.close = book.price - chartLog.baseVolume = takenBaseAmountDecimal - chartLog.bidBookBaseVolume = takenBaseAmountDecimal - chartLog.askBookBaseVolume = ZERO_BD - } else { - if (book.price.gt(chartLog.high)) { - chartLog.high = book.price - } - if (book.price.lt(chartLog.low)) { - chartLog.low = book.price - } - chartLog.close = book.price - chartLog.baseVolume = chartLog.baseVolume.plus(takenBaseAmountDecimal) - chartLog.bidBookBaseVolume = chartLog.bidBookBaseVolume.plus( - takenBaseAmountDecimal, - ) - } - chartLog.save() - - // inverted chart log - const invertedChartLogID = encodeChartLogID( - quote, - base, - intervalType, - timestampForAcc, - ) - const invertedMarketCode = encodeMarketCode(quote, base) - let invertedChartLog = ChartLog.load(invertedChartLogID) - if (invertedChartLog === null) { - invertedChartLog = new ChartLog(invertedChartLogID) - invertedChartLog.marketCode = invertedMarketCode - invertedChartLog.base = quote.id - invertedChartLog.quote = base.id - invertedChartLog.intervalType = intervalType - invertedChartLog.timestamp = BigInt.fromI64(timestampForAcc) - invertedChartLog.open = book.inversePrice - invertedChartLog.high = book.inversePrice - invertedChartLog.low = book.inversePrice - invertedChartLog.close = book.inversePrice - invertedChartLog.baseVolume = takenQuoteAmountDecimal - invertedChartLog.bidBookBaseVolume = ZERO_BD - invertedChartLog.askBookBaseVolume = takenQuoteAmountDecimal - } else { - if (book.inversePrice.gt(invertedChartLog.high)) { - invertedChartLog.high = book.inversePrice - } - if (book.inversePrice.lt(invertedChartLog.low)) { - invertedChartLog.low = book.inversePrice - } - invertedChartLog.close = book.inversePrice - invertedChartLog.baseVolume = invertedChartLog.baseVolume.plus( - takenQuoteAmountDecimal, - ) - invertedChartLog.askBookBaseVolume = - invertedChartLog.askBookBaseVolume.plus(takenQuoteAmountDecimal) - } - invertedChartLog.save() - } -} - -function updatePool( - pool: Pool, - book: Book, - base: Token, - quote: Token, - baseInUSD: BigDecimal, - quoteInUSD: BigDecimal, - filledUnitAmount: BigInt, - priceRaw: BigInt, - event: ethereum.Event, -): void { - const filledBaseAmount = unitToBase(book.unitSize, filledUnitAmount, priceRaw) - const filledBaseAmountDecimal = convertTokenToDecimal( - filledBaseAmount, - base.decimals, - ) - const filledQuoteAmount = unitToQuote(book.unitSize, filledUnitAmount) - const filledQuoteAmountDecimal = convertTokenToDecimal( - filledQuoteAmount, - quote.decimals, - ) - const filledUSDAmount = calculateValueUSD( - filledQuoteAmountDecimal, - quoteInUSD, - filledBaseAmountDecimal, - baseInUSD, - ) - - const poolHourData = updatePoolHourData(pool, event) - const poolDayData = updatePoolDayData(pool, event) - - if (Address.fromBytes(pool.tokenA).equals(Address.fromBytes(book.base))) { - // ask book - pool.liquidityA = pool.liquidityA.plus(filledBaseAmount) - pool.liquidityB = pool.liquidityB.minus(filledQuoteAmount) - - pool.volumeTokenA = pool.volumeTokenA.plus(filledBaseAmountDecimal) - pool.volumeTokenB = pool.volumeTokenB.plus(filledQuoteAmountDecimal) - pool.volumeUSD = pool.volumeUSD.plus(filledUSDAmount) - - // update interval data - poolHourData.volumeTokenA = poolHourData.volumeTokenA.plus( - filledBaseAmountDecimal, - ) - poolHourData.volumeTokenB = poolHourData.volumeTokenB.plus( - filledQuoteAmountDecimal, - ) - poolHourData.volumeUSD = poolHourData.volumeUSD.plus(filledUSDAmount) - poolDayData.volumeTokenA = poolDayData.volumeTokenA.plus( - filledBaseAmountDecimal, - ) - poolDayData.volumeTokenB = poolDayData.volumeTokenB.plus( - filledQuoteAmountDecimal, - ) - poolDayData.volumeUSD = poolDayData.volumeUSD.plus(filledUSDAmount) - } else if ( - Address.fromBytes(pool.tokenB).equals(Address.fromBytes(book.base)) - ) { - // bid book - pool.liquidityA = pool.liquidityA.minus(filledQuoteAmount) - pool.liquidityB = pool.liquidityB.plus(filledBaseAmount) - - pool.volumeTokenA = pool.volumeTokenA.plus(filledQuoteAmountDecimal) - pool.volumeTokenB = pool.volumeTokenB.plus(filledBaseAmountDecimal) - pool.volumeUSD = pool.volumeUSD.plus(filledUSDAmount) - - // update interval data - poolHourData.volumeTokenA = poolHourData.volumeTokenA.plus( - filledQuoteAmountDecimal, - ) - poolHourData.volumeTokenB = poolHourData.volumeTokenB.plus( - filledBaseAmountDecimal, - ) - poolHourData.volumeUSD = poolHourData.volumeUSD.plus(filledUSDAmount) - poolDayData.volumeTokenA = poolDayData.volumeTokenA.plus( - filledQuoteAmountDecimal, - ) - poolDayData.volumeTokenB = poolDayData.volumeTokenB.plus( - filledBaseAmountDecimal, - ) - poolDayData.volumeUSD = poolDayData.volumeUSD.plus(filledUSDAmount) - } else { - log.error('[TAKE] Pool token mismatch: {} {} vs {} {}', [ - pool.tokenA.toHexString(), - pool.tokenB.toHexString(), - book.base.toHexString(), - book.quote.toHexString(), - ]) - } - - pool.save() - poolHourData.save() - poolDayData.save() -} +import { BID_BOOK_ID, ASK_BOOK_ID } from '../../common/chain' export function handleTake(event: Take): void { - const functionSignature = event.transaction.input.toHexString().slice(0, 10) - const isInternalOrderCall = - functionSignature == '0xb305b94c' || // make - functionSignature == '0x08b2c1d8' // limit - - if (isInternalOrderCall) { - updateDayData(event, 'TAKE') + const bookId = event.params.bookId + if (!bookId.equals(BID_BOOK_ID) && !bookId.equals(ASK_BOOK_ID)) { + return } - - if (event.params.unit.isZero()) { + if (!event.transaction.to) { return } - const tick = BigInt.fromI32(event.params.tick) + const isTakingBidBook = bookId.equals(BID_BOOK_ID) const priceRaw = tickToPrice(event.params.tick) - const book = getBookOrLog(event.params.bookId.toString(), 'TAKE') - if (book === null) { - return + const volumeUsd = isTakingBidBook + ? event.params.unit + : unitToBase( + BigInt.fromString('1000000000000'), + event.params.unit, + priceRaw, + ) + const volumeUsdBD = convertTokenToDecimal(volumeUsd, BigInt.fromI32(6)) + + const timestamp = event.block.timestamp.toI32() + const dayID = timestamp / 86400 // rounded + const dayStartTimestamp = dayID * 86400 + let cloberDayData = CloberDayData.load(dayID.toString()) + if (cloberDayData === null) { + cloberDayData = new CloberDayData(dayID.toString()) + cloberDayData.date = dayStartTimestamp } - const depthID = event.params.bookId - .toString() + const contract = event.transaction.to! + const contractInteractionDayDataId = contract + .toHexString() .concat('-') - .concat(tick.toString()) - const depth = getDepthOrLog(depthID, 'TAKE') - if (depth === null) { - return - } - - const quote = getTokenOrLog(book.quote, 'TAKE') - const base = getTokenOrLog(book.base, 'TAKE') - if (quote === null || base === null) { - return - } - - const takenUnitAmount = event.params.unit - const takenBaseAmount = unitToBase(book.unitSize, takenUnitAmount, priceRaw) - const takenBaseAmountDecimal = convertTokenToDecimal( - takenBaseAmount, - base.decimals, - ) - const protocolFeesBase = !book.isTakerFeeInQuote - ? takenBaseAmountDecimal.times(book.takerFee) - : ZERO_BD - - const takenQuoteAmount = unitToQuote(book.unitSize, takenUnitAmount) - const takenQuoteAmountDecimal = convertTokenToDecimal( - takenQuoteAmount, - quote.decimals, - ) - const protocolFeesQuote = book.isTakerFeeInQuote - ? takenQuoteAmountDecimal.times(book.takerFee) - : ZERO_BD - - // book data - book.price = formatPrice(priceRaw, base.decimals, quote.decimals) // this should be first, checked - - const quoteInUSD = getTokenUSDPriceFlat(quote) - const baseInUSD = getTokenUSDPriceFlat(base) - const amountTotalUSD = calculateValueUSD( - takenQuoteAmountDecimal, - quoteInUSD, - takenBaseAmountDecimal, - baseInUSD, - ) - const protocolFeesTotalUSD = calculateValueUSD( - protocolFeesQuote, - quoteInUSD, - protocolFeesBase, - baseInUSD, - ) - - book.priceRaw = priceRaw - book.inversePrice = formatInvertedPrice( - priceRaw, - base.decimals, - quote.decimals, - ) - book.tick = tick - book.volumeQuote = book.volumeQuote.plus(takenQuoteAmountDecimal) - book.volumeBase = book.volumeBase.plus(takenBaseAmountDecimal) - book.volumeUSD = book.volumeUSD.plus(amountTotalUSD) - book.protocolFeesQuote = book.protocolFeesQuote.plus(protocolFeesQuote) - book.protocolFeesBase = book.protocolFeesBase.plus(protocolFeesBase) - book.protocolFeesUSD = book.protocolFeesUSD.plus(protocolFeesTotalUSD) - book.totalValueLocked = book.totalValueLocked.minus(takenQuoteAmountDecimal) - book.totalValueLockedUSD = book.totalValueLocked.times(quoteInUSD) - book.lastTakenTimestamp = event.block.timestamp - book.lastTakenBlockNumber = event.block.number - - // depth data - depth.unitAmount = depth.unitAmount.minus(takenUnitAmount) - depth.quoteAmount = depth.quoteAmount.minus(takenQuoteAmount) - depth.baseAmount = depth.baseAmount.minus(takenBaseAmount) - - // quote token data - quote.priceUSD = quoteInUSD - quote.volume = quote.volume.plus(takenQuoteAmountDecimal) - quote.volumeUSD = quote.volumeUSD.plus(amountTotalUSD) - - // update quote protocol fees - quote.liquidityVaultProtocolFee = quote.liquidityVaultProtocolFee.plus( - book.isTakerFeeInQuote ? protocolFeesQuote : ZERO_BD, - ) - quote.liquidityVaultProtocolFeeUSD = quote.liquidityVaultProtocolFeeUSD.plus( - book.isTakerFeeInQuote ? protocolFeesTotalUSD : ZERO_BD, - ) - quote.protocolFees = quote.protocolFees.plus( - book.isTakerFeeInQuote ? protocolFeesQuote : ZERO_BD, - ) - quote.protocolFeesUSD = quote.protocolFeesUSD.plus( - book.isTakerFeeInQuote ? protocolFeesTotalUSD : ZERO_BD, - ) - quote.totalValueLocked = quote.totalValueLocked.minus(takenQuoteAmountDecimal) - quote.totalValueLockedUSD = quote.totalValueLocked.times(quoteInUSD) - - // base token data - base.priceUSD = baseInUSD - base.volume = base.volume.plus(takenBaseAmountDecimal) - base.volumeUSD = base.volumeUSD.plus(amountTotalUSD) - - // update base protocol fees - base.liquidityVaultProtocolFee = base.liquidityVaultProtocolFee.plus( - book.isTakerFeeInQuote ? ZERO_BD : protocolFeesBase, - ) - base.liquidityVaultProtocolFeeUSD = base.liquidityVaultProtocolFeeUSD.plus( - book.isTakerFeeInQuote ? ZERO_BD : protocolFeesTotalUSD, - ) - base.protocolFees = base.protocolFees.plus( - book.isTakerFeeInQuote ? ZERO_BD : protocolFeesBase, - ) - base.protocolFeesUSD = base.protocolFeesUSD.plus( - book.isTakerFeeInQuote ? ZERO_BD : protocolFeesTotalUSD, - ) - // note: do not update base.totalValueLocked - - // interval data - const bookDayData = updateBookDayData(book, event) - const quoteDayData = updateTokenDayData(quote, quoteInUSD, event) - const baseDayData = updateTokenDayData(base, baseInUSD, event) - - // update volume and protocol fees metrics - bookDayData.volumeQuote = bookDayData.volumeQuote.plus( - takenQuoteAmountDecimal, - ) - bookDayData.volumeBase = bookDayData.volumeBase.plus(takenBaseAmountDecimal) - bookDayData.volumeUSD = bookDayData.volumeUSD.plus(amountTotalUSD) - bookDayData.protocolFeesQuote = - bookDayData.protocolFeesQuote.plus(protocolFeesQuote) - bookDayData.protocolFeesBase = - bookDayData.protocolFeesBase.plus(protocolFeesBase) - bookDayData.protocolFeesUSD = - bookDayData.protocolFeesUSD.plus(protocolFeesTotalUSD) - - quoteDayData.volume = quoteDayData.volume.plus(takenQuoteAmountDecimal) - quoteDayData.volumeUSD = quoteDayData.volumeUSD.plus(amountTotalUSD) - - // update quote protocol fees - quoteDayData.liquidityVaultProtocolFee = - quoteDayData.liquidityVaultProtocolFee.plus( - book.isTakerFeeInQuote ? protocolFeesQuote : ZERO_BD, - ) - quoteDayData.liquidityVaultProtocolFeeUSD = - quoteDayData.liquidityVaultProtocolFeeUSD.plus( - book.isTakerFeeInQuote ? protocolFeesTotalUSD : ZERO_BD, - ) - quoteDayData.protocolFees = quoteDayData.protocolFees.plus( - book.isTakerFeeInQuote ? protocolFeesQuote : ZERO_BD, - ) - quoteDayData.protocolFeesUSD = quoteDayData.protocolFeesUSD.plus( - book.isTakerFeeInQuote ? protocolFeesTotalUSD : ZERO_BD, - ) - - baseDayData.volume = baseDayData.volume.plus(takenBaseAmountDecimal) - baseDayData.volumeUSD = baseDayData.volumeUSD.plus(amountTotalUSD) - - // update base protocol fees - baseDayData.liquidityVaultProtocolFee = - baseDayData.liquidityVaultProtocolFee.plus( - book.isTakerFeeInQuote ? ZERO_BD : protocolFeesBase, - ) - baseDayData.liquidityVaultProtocolFeeUSD = - baseDayData.liquidityVaultProtocolFeeUSD.plus( - book.isTakerFeeInQuote ? ZERO_BD : protocolFeesTotalUSD, - ) - baseDayData.protocolFees = baseDayData.protocolFees.plus( - book.isTakerFeeInQuote ? ZERO_BD : protocolFeesBase, - ) - baseDayData.protocolFeesUSD = baseDayData.protocolFeesUSD.plus( - book.isTakerFeeInQuote ? ZERO_BD : protocolFeesTotalUSD, - ) - - if (!SKIP_CHART) { - updateChart( - event.block, - takenBaseAmountDecimal, - takenQuoteAmountDecimal, - book, - base, - quote, - ) + .concat(dayID.toString()) + let contractInteractionDayData = ContractInteractionDayData.load( + contractInteractionDayDataId, + ) + if (contractInteractionDayData === null) { + contractInteractionDayData = new ContractInteractionDayData( + contractInteractionDayDataId, + ) + contractInteractionDayData.date = dayStartTimestamp + contractInteractionDayData.contract = contract + contractInteractionDayData.callCount = ZERO_BI + contractInteractionDayData.volumeUSD = ZERO_BD + contractInteractionDayData.cloberDayData = cloberDayData.id } - - const take = new TakeEntity( - event.transaction.hash - .toHexString() - .concat('-') - .concat(event.logIndex.toString()), - ) - take.transaction = event.transaction.hash.toHexString() - take.timestamp = event.block.timestamp - take.inputToken = book.base - take.outputToken = book.quote - take.book = book.id - take.origin = event.transaction.from - take.inputAmount = takenBaseAmount - take.outputAmount = takenQuoteAmount - take.amountUSD = amountTotalUSD - take.logIndex = event.logIndex - if (!SKIP_TAKE_AND_SWAP) { - take.save() + let contractInteraction = ContractInteraction.load(contract.toHexString()) + if (contractInteraction === null) { + contractInteraction = new ContractInteraction(contract.toHexString()) + contractInteraction.callCount = ZERO_BI + contractInteraction.volumeUSD = ZERO_BD } - let currentOrderIndex = depth.latestTakenOrderIndex - let remainingTakenUnitAmount = takenUnitAmount - while (remainingTakenUnitAmount.gt(ZERO_BI)) { - const orderID = encodeOrderID(book.id, tick, currentOrderIndex) - const openOrder = OpenOrder.load(orderID.toString()) - if (openOrder === null) { - currentOrderIndex = currentOrderIndex.plus(ONE_BI) - // mathematically, continue is correct, - // but due to an issue on a specific testnet where events are duplicated or missing, - // it could cause an infinite loop, so changed to break - continue - } - - const openOrderRemainingUnitAmount = openOrder.unitAmount.minus( - openOrder.filledUnitAmount, - ) - let filledUnitAmount = ZERO_BI - if (remainingTakenUnitAmount.lt(openOrderRemainingUnitAmount)) { - filledUnitAmount = remainingTakenUnitAmount - } else { - filledUnitAmount = openOrderRemainingUnitAmount - } - - remainingTakenUnitAmount = remainingTakenUnitAmount.minus(filledUnitAmount) + contractInteractionDayData.callCount = + contractInteractionDayData.callCount.plus(ONE_BI) + contractInteractionDayData.volumeUSD = + contractInteractionDayData.volumeUSD.plus(volumeUsdBD) - fillOpenOrder(openOrder, book.unitSize, filledUnitAmount) + contractInteraction.callCount = contractInteraction.callCount.plus(ONE_BI) + contractInteraction.volumeUSD = + contractInteraction.volumeUSD.plus(volumeUsdBD) - if ( - book.pool !== null && - Address.fromBytes(openOrder.owner).equals( - Address.fromString(LIQUIDITY_VAULT), - ) - ) { - const pool = getPoolOrLog(book.pool!, 'TAKE') - if (pool) { - updatePool( - pool, - book, - base, - quote, - baseInUSD, - quoteInUSD, - filledUnitAmount, - priceRaw, - event, - ) - } - } - - if (openOrder.unitAmount.equals(openOrder.filledUnitAmount)) { - currentOrderIndex = currentOrderIndex.plus(ONE_BI) - } - } - - if (quoteInUSD.gt(ZERO_BD)) { - updateUserDayVolume(quote, event, takenQuoteAmountDecimal, amountTotalUSD) - } else if (baseInUSD.gt(ZERO_BD)) { - updateUserDayVolume(base, event, takenBaseAmountDecimal, amountTotalUSD) - } - updateUserNativeVolume( - event, - take.inputToken, - take.outputToken, - take.inputAmount, - take.outputAmount, - ) - depth.latestTakenOrderIndex = currentOrderIndex - depth.save() - book.save() - quote.save() - base.save() - bookDayData.save() - quoteDayData.save() - baseDayData.save() - // openOrder.save() // already saved in fillOpenOrder - // chartLog.save() // already saved in updateChart - // invertedChartLog.save() // already saved in updateChart + contractInteractionDayData.save() + contractInteraction.save() + cloberDayData.save() } diff --git a/src/mappings/book-manager/transfer.ts b/src/mappings/book-manager/transfer.ts deleted file mode 100644 index e5237ff..0000000 --- a/src/mappings/book-manager/transfer.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { Address } from '@graphprotocol/graph-ts' - -import { Transfer } from '../../../generated/BookManager/BookManager' -import { ADDRESS_ZERO } from '../../common/constants' -import { getOpenOrderOrLog } from '../../common/entity-getters' -import { updateDayData } from '../interval-updates' -import { OPERATOR } from '../../common/chain' - -export function handleTransfer(event: Transfer): void { - if ( - event.transaction.to && - !event.transaction.to!.equals(Address.fromString(OPERATOR)) - ) { - updateDayData(event, 'TRANSFER') - } - - const from = event.params.from - const to = event.params.to - const orderID = event.params.tokenId - - if (from.toHexString() == ADDRESS_ZERO || to.toHexString() == ADDRESS_ZERO) { - // mint or burn events are handled in the make, cancel, and claim events - return - } - - const openOrder = getOpenOrderOrLog(orderID.toString(), 'TRANSFER') - if (openOrder === null) { - return - } - - openOrder.owner = to - openOrder.save() -} diff --git a/src/mappings/core.ts b/src/mappings/core.ts index 61becf8..a4ead35 100644 --- a/src/mappings/core.ts +++ b/src/mappings/core.ts @@ -1,25 +1,3 @@ -import { handleBookOpen } from './book-manager/open' -import { handleMake } from './book-manager/make' import { handleTake } from './book-manager/take' -import { handleTransfer as handleBookManagerTransfer } from './book-manager/transfer' -import { handleCancel } from './book-manager/cancel' -import { handleClaim } from './book-manager/claim' -import { handlePoolOpen } from './liquidity-vault/open' -import { handleMint } from './liquidity-vault/mint' -import { handleBurn } from './liquidity-vault/burn' -import { handleUpdatePosition } from './liquidity-vault/strategy' -import { handleTransfer as handleLiquidityVaultTransfer } from './liquidity-vault/transfer' -export { - handleBookOpen, - handleMake, - handleTake, - handleBookManagerTransfer, - handleCancel, - handleClaim, - handlePoolOpen, - handleMint, - handleBurn, - handleUpdatePosition, - handleLiquidityVaultTransfer, -} +export { handleTake } diff --git a/src/mappings/interval-updates.ts b/src/mappings/interval-updates.ts deleted file mode 100644 index 97d8426..0000000 --- a/src/mappings/interval-updates.ts +++ /dev/null @@ -1,355 +0,0 @@ -import { - Address, - BigDecimal, - BigInt, - Bytes, - ethereum, -} from '@graphprotocol/graph-ts' - -import { - Book, - BookDayData, - CloberDayData, - Pool, - PoolDayData, - PoolHourData, - Token, - TokenDayData, - Transaction, - TransactionTypeDayData, - User, - UserDayData, - UserDayVolume, -} from '../../generated/schema' -import { - ADDRESS_ZERO, - BI_18, - ONE_BI, - ZERO_BD, - ZERO_BI, -} from '../common/constants' -import { - getOrCreateTransaction, - getOrCreateUserByFrom, -} from '../common/entity-getters' -import { - REFERENCE_TOKEN, - SKIP_TX_ANALYTICS, - SKIP_USER_ANALYTICS, -} from '../common/chain' -import { convertTokenToDecimal } from '../common/utils' - -/** - * Tracks global aggregate data over daily windows - * @param event - * @param eventType - */ -export function updateDayData(event: ethereum.Event, eventType: string): void { - const functionSignature = event.transaction.input.toHexString().slice(0, 10) - - const timestamp = event.block.timestamp.toI32() - const dayID = timestamp / 86400 // rounded - const dayStartTimestamp = dayID * 86400 - let cloberDayData = CloberDayData.load(dayID.toString()) - if (cloberDayData === null) { - cloberDayData = new CloberDayData(dayID.toString()) - cloberDayData.date = dayStartTimestamp - cloberDayData.txCount = ZERO_BI - cloberDayData.walletCount = ZERO_BI - cloberDayData.newWalletCount = ZERO_BI - } - - const user = event.transaction.from.toHexString() - const userDayDataId = user.concat('-').concat(dayID.toString()) - let userDayData = UserDayData.load(userDayDataId) - if (userDayData === null) { - userDayData = new UserDayData(userDayDataId) - userDayData.date = dayStartTimestamp - userDayData.user = Address.fromString(user) - userDayData.txCount = ZERO_BI - - // increment the wallet count on the clober day data - cloberDayData.walletCount = cloberDayData.walletCount.plus(ONE_BI) - } - - const txDayID = functionSignature.concat('-').concat(dayID.toString()) - let txTypeDayData = TransactionTypeDayData.load(txDayID) - if (txTypeDayData === null) { - txTypeDayData = new TransactionTypeDayData(txDayID) - txTypeDayData.date = dayStartTimestamp - txTypeDayData.cloberDayData = cloberDayData.id - txTypeDayData.type = functionSignature - txTypeDayData.txCount = ZERO_BI - } - - if (!SKIP_USER_ANALYTICS && User.load(Address.fromString(user)) === null) { - cloberDayData.newWalletCount = cloberDayData.newWalletCount.plus(ONE_BI) - - getOrCreateUserByFrom(event) - } - - if ( - !SKIP_TX_ANALYTICS && - Transaction.load(event.transaction.hash.toHexString()) === null - ) { - userDayData.txCount = userDayData.txCount.plus(ONE_BI) - cloberDayData.txCount = cloberDayData.txCount.plus(ONE_BI) - txTypeDayData.txCount = txTypeDayData.txCount.plus(ONE_BI) - - getOrCreateTransaction(event) - } - - cloberDayData.save() - if (!SKIP_USER_ANALYTICS) { - userDayData.save() - } - if (!SKIP_TX_ANALYTICS) { - txTypeDayData.save() - } -} - -export function updateUserNativeVolume( - event: ethereum.Event, - inputToken: Bytes, - outputToken: Bytes, - inputAmount: BigInt, - outputAmount: BigInt, -): void { - if (SKIP_USER_ANALYTICS) { - return - } - const isInputNative = inputToken.toHexString() == ADDRESS_ZERO - const isOutputNative = outputToken.toHexString() == ADDRESS_ZERO - const isInputReference = inputToken.toHexString() == REFERENCE_TOKEN - const isOutputReference = outputToken.toHexString() == REFERENCE_TOKEN - const isWrapOrUnwrap = - (isInputNative && isOutputReference) || (isOutputNative && isInputReference) - const isNativeTx = isInputNative || isOutputNative - - if (!isNativeTx || isWrapOrUnwrap) { - return - } - const nativeAmount = isInputNative - ? convertTokenToDecimal(inputAmount, BI_18) - : convertTokenToDecimal(outputAmount, BI_18) - const user = getOrCreateUserByFrom(event) - user.nativeVolume = user.nativeVolume.plus(nativeAmount) - user.save() -} - -export function updateUserDayVolume( - token: Token, - event: ethereum.Event, - volume: BigDecimal, - volumeUSD: BigDecimal, -): void { - if (SKIP_USER_ANALYTICS) { - return - } - const timestamp = event.block.timestamp.toI32() - const dayID = timestamp / 86400 // rounded - const dayStartTimestamp = dayID * 86400 - const user = event.transaction.from.toHexString() - const userDayDataId = user.concat('-').concat(dayID.toString()) - const userDayVolumeID = user - .concat('-') - .concat(token.id.toHexString()) - .concat('-') - .concat(dayID.toString()) - let userDayVolume = UserDayVolume.load(userDayVolumeID) - if (userDayVolume === null) { - userDayVolume = new UserDayVolume(userDayVolumeID) - userDayVolume.date = dayStartTimestamp - userDayVolume.user = Address.fromString(user) - userDayVolume.userDayData = userDayDataId - userDayVolume.token = token.id - userDayVolume.volume = ZERO_BD - userDayVolume.volumeUSD = ZERO_BD - } - userDayVolume.volume = userDayVolume.volume.plus(volume) - userDayVolume.volumeUSD = userDayVolume.volumeUSD.plus(volumeUSD) - userDayVolume.save() -} - -export function updateBookDayData( - book: Book, - event: ethereum.Event, -): BookDayData { - const timestamp = event.block.timestamp.toI32() - const dayID = timestamp / 86400 - const dayStartTimestamp = dayID * 86400 - const dayBookID = book.id.toString().concat('-').concat(dayID.toString()) - let bookDayData = BookDayData.load(dayBookID) - if (bookDayData === null) { - bookDayData = new BookDayData(dayBookID) - bookDayData.date = dayStartTimestamp - bookDayData.book = book.id - // things that dont get initialized always - bookDayData.volumeQuote = ZERO_BD - bookDayData.volumeBase = ZERO_BD - bookDayData.volumeUSD = ZERO_BD - bookDayData.protocolFeesQuote = ZERO_BD - bookDayData.protocolFeesBase = ZERO_BD - bookDayData.protocolFeesUSD = ZERO_BD - bookDayData.open = book.price - bookDayData.high = book.price - bookDayData.low = book.price - bookDayData.close = book.price - } - - if (book.price.gt(bookDayData.high)) { - bookDayData.high = book.price - } - if (book.price.lt(bookDayData.low)) { - bookDayData.low = book.price - } - - bookDayData.price = book.price - bookDayData.close = book.price - bookDayData.inversePrice = book.inversePrice - bookDayData.totalValueLocked = book.totalValueLocked - bookDayData.totalValueLockedUSD = book.totalValueLockedUSD - bookDayData.save() - - return bookDayData as BookDayData -} - -export function updateTokenDayData( - token: Token, - tokenPrice: BigDecimal, - event: ethereum.Event, -): TokenDayData { - const timestamp = event.block.timestamp.toI32() - const dayID = timestamp / 86400 - const dayStartTimestamp = dayID * 86400 - const tokenDayID = Address.fromBytes(token.id) - .toHexString() - .concat('-') - .concat(dayID.toString()) - - let tokenDayData = TokenDayData.load(tokenDayID) - if (tokenDayData === null) { - tokenDayData = new TokenDayData(tokenDayID) - tokenDayData.date = dayStartTimestamp - tokenDayData.token = token.id - tokenDayData.cloberDayData = dayID.toString() - // things that dont get initialized always - tokenDayData.volume = ZERO_BD - tokenDayData.volumeUSD = ZERO_BD - - tokenDayData.liquidityVaultProtocolFee = ZERO_BD - tokenDayData.liquidityVaultProtocolFeeUSD = ZERO_BD - tokenDayData.routerGatewayProtocolFee = ZERO_BD - tokenDayData.routerGatewayProtocolFeeUSD = ZERO_BD - tokenDayData.protocolFees = ZERO_BD - tokenDayData.protocolFeesUSD = ZERO_BD - - tokenDayData.open = tokenPrice - tokenDayData.high = tokenPrice - tokenDayData.low = tokenPrice - tokenDayData.close = tokenPrice - } - - if (tokenPrice.gt(tokenDayData.high)) { - tokenDayData.high = tokenPrice - } - - if (tokenPrice.lt(tokenDayData.low)) { - tokenDayData.low = tokenPrice - } - - tokenDayData.totalValueLocked = token.totalValueLocked - tokenDayData.totalValueLockedUSD = token.totalValueLockedUSD - tokenDayData.priceUSD = tokenPrice - tokenDayData.close = tokenPrice - tokenDayData.save() - - return tokenDayData as TokenDayData -} - -export function updatePoolDayData( - pool: Pool, - event: ethereum.Event, -): PoolDayData { - const timestamp = event.block.timestamp.toI32() - const dayID = timestamp / 86400 - const dayStartTimestamp = dayID * 86400 - const tokenDayID = pool.id.toHexString().concat('-').concat(dayID.toString()) - - let poolDayData = PoolDayData.load(tokenDayID) - if (poolDayData === null) { - poolDayData = new PoolDayData(tokenDayID) - poolDayData.date = dayStartTimestamp - poolDayData.pool = pool.id - // things that dont get initialized always - poolDayData.volumeTokenA = ZERO_BD - poolDayData.volumeTokenB = ZERO_BD - poolDayData.volumeUSD = ZERO_BD - poolDayData.protocolFeesTokenA = ZERO_BD - poolDayData.protocolFeesTokenB = ZERO_BD - poolDayData.protocolFeesAUSD = ZERO_BD - poolDayData.protocolFeesBUSD = ZERO_BD - poolDayData.spreadProfitUSD = ZERO_BD - poolDayData.totalValueLockedUSD = ZERO_BD - } - poolDayData.oraclePrice = pool.oraclePrice - poolDayData.totalSupply = pool.totalSupply - poolDayData.liquidityA = pool.liquidityA - poolDayData.liquidityB = pool.liquidityB - poolDayData.lpPriceUSD = pool.lpPriceUSD - poolDayData.priceA = pool.priceA - poolDayData.priceARaw = pool.priceARaw - poolDayData.tickA = pool.tickA - poolDayData.priceB = pool.priceB - poolDayData.priceBRaw = pool.priceBRaw - poolDayData.tickB = pool.tickB - poolDayData.totalValueLockedUSD = pool.totalValueLockedUSD - poolDayData.save() - - return poolDayData as PoolDayData -} - -export function updatePoolHourData( - pool: Pool, - event: ethereum.Event, -): PoolHourData { - const timestamp = event.block.timestamp.toI32() - const hourIndex = timestamp / 3600 // get unique hour within unix history - const hourStartUnix = hourIndex * 3600 // want the rounded effect - const tokenHourID = pool.id - .toHexString() - .concat('-') - .concat(hourIndex.toString()) - - let poolHourData = PoolHourData.load(tokenHourID) - if (poolHourData === null) { - poolHourData = new PoolHourData(tokenHourID) - poolHourData.date = hourStartUnix - poolHourData.pool = pool.id - // things that dont get initialized always - poolHourData.volumeTokenA = ZERO_BD - poolHourData.volumeTokenB = ZERO_BD - poolHourData.volumeUSD = ZERO_BD - poolHourData.protocolFeesTokenA = ZERO_BD - poolHourData.protocolFeesTokenB = ZERO_BD - poolHourData.protocolFeesAUSD = ZERO_BD - poolHourData.protocolFeesBUSD = ZERO_BD - poolHourData.spreadProfitUSD = ZERO_BD - poolHourData.totalValueLockedUSD = ZERO_BD - } - poolHourData.oraclePrice = pool.oraclePrice - poolHourData.totalSupply = pool.totalSupply - poolHourData.liquidityA = pool.liquidityA - poolHourData.liquidityB = pool.liquidityB - poolHourData.lpPriceUSD = pool.lpPriceUSD - poolHourData.priceA = pool.priceA - poolHourData.priceARaw = pool.priceARaw - poolHourData.tickA = pool.tickA - poolHourData.priceB = pool.priceB - poolHourData.priceBRaw = pool.priceBRaw - poolHourData.tickB = pool.tickB - poolHourData.totalValueLockedUSD = pool.totalValueLockedUSD - poolHourData.save() - - return poolHourData as PoolHourData -} diff --git a/src/mappings/liquidity-vault/burn.ts b/src/mappings/liquidity-vault/burn.ts deleted file mode 100644 index 41d67ca..0000000 --- a/src/mappings/liquidity-vault/burn.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { - getOrCreateUserPoolBalance, - getPoolOrLog, - getTokenOrLog, -} from '../../common/entity-getters' -import { BI_18, ZERO_BD, ZERO_BI } from '../../common/constants' -import { convertTokenToDecimal } from '../../common/utils' -import { - updateDayData, - updatePoolDayData, - updatePoolHourData, - updateTokenDayData, -} from '../interval-updates' -import { getTokenUSDPriceFlat } from '../../common/pricing' -import { Burn } from '../../../generated/LiquidityVault/LiquidityVault' - -export function handleBurn(event: Burn): void { - updateDayData(event, 'BURN') - - const pool = getPoolOrLog(event.params.key, 'BURN') - if (!pool || event.params.lpAmount.equals(ZERO_BI)) { - return - } - - const tokenA = getTokenOrLog(pool.tokenA, 'BURN') - const tokenB = getTokenOrLog(pool.tokenB, 'BURN') - - if (tokenA && tokenB) { - const feeAInDecimals = convertTokenToDecimal( - event.params.feeA, - tokenA.decimals, - ) - const priceAUSD = getTokenUSDPriceFlat(tokenA) - const feeAInUSD = priceAUSD.times(feeAInDecimals) - const feeBInDecimals = convertTokenToDecimal( - event.params.feeB, - tokenB.decimals, - ) - const priceBUSD = getTokenUSDPriceFlat(tokenB) - const feeBInUSD = priceBUSD.times(feeBInDecimals) - - // update pool state - pool.totalSupply = pool.totalSupply.minus(event.params.lpAmount) - pool.liquidityA = pool.liquidityA.minus(event.params.amountA) - pool.liquidityB = pool.liquidityB.minus(event.params.amountB) - pool.protocolFeesTokenA = pool.protocolFeesTokenA.plus(feeAInDecimals) - pool.protocolFeesTokenB = pool.protocolFeesTokenB.plus(feeBInDecimals) - pool.protocolFeesAUSD = pool.protocolFeesAUSD.plus(feeAInUSD) - pool.protocolFeesBUSD = pool.protocolFeesBUSD.plus(feeBInUSD) - - const lpAmountDecimal = convertTokenToDecimal( - pool.totalSupply, - BI_18, // assuming LP token has 18 decimals - ) - if (lpAmountDecimal.gt(ZERO_BD)) { - const liquidityAInUSD = convertTokenToDecimal( - pool.liquidityA, - tokenA.decimals, - ).times(priceAUSD) - const liquidityBInUSD = convertTokenToDecimal( - pool.liquidityB, - tokenB.decimals, - ).times(priceBUSD) - pool.lpPriceUSD = liquidityAInUSD - .plus(liquidityBInUSD) - .div(lpAmountDecimal) - pool.totalValueLockedUSD = lpAmountDecimal.times(pool.lpPriceUSD) - } else { - pool.lpPriceUSD = ZERO_BD - pool.totalValueLockedUSD = ZERO_BD - } - - const userPoolBalance = getOrCreateUserPoolBalance( - event.transaction.from, - pool.id, - event, - ) - - userPoolBalance.totalTokenADeposited = - userPoolBalance.totalTokenADeposited.minus(event.params.amountA) - userPoolBalance.totalTokenBDeposited = - userPoolBalance.totalTokenBDeposited.minus(event.params.amountB) - userPoolBalance.save() - - // @dev: To calculate the protocol's TVL, we need token.totalValueLocked + pool.totalValueLockedUSD - // since, reducing totalValueLocked twice (cancel -> burn) - // tokenA.totalValueLocked = tokenA.totalValueLocked.minus(amountAInDecimals) - // tokenA.totalValueLockedUSD = tokenA.totalValueLocked.times(priceAUSD) - // tokenB.totalValueLocked = tokenB.totalValueLocked.minus(amountBInDecimals) - // tokenB.totalValueLockedUSD = tokenB.totalValueLocked.times(priceBUSD) - - // update interval - const poolHourData = updatePoolHourData(pool, event) - const poolDayData = updatePoolDayData(pool, event) - const tokenADayData = updateTokenDayData(tokenA, priceAUSD, event) - const tokenBDayData = updateTokenDayData(tokenB, priceBUSD, event) - - poolHourData.protocolFeesTokenA = - poolHourData.protocolFeesTokenA.plus(feeAInDecimals) - poolHourData.protocolFeesTokenB = - poolHourData.protocolFeesTokenB.plus(feeBInDecimals) - poolHourData.protocolFeesAUSD = - poolHourData.protocolFeesAUSD.plus(feeAInUSD) - poolHourData.protocolFeesBUSD = - poolHourData.protocolFeesBUSD.plus(feeBInUSD) - - poolDayData.protocolFeesTokenA = - poolDayData.protocolFeesTokenA.plus(feeAInDecimals) - poolDayData.protocolFeesTokenB = - poolDayData.protocolFeesTokenB.plus(feeBInDecimals) - poolDayData.protocolFeesAUSD = poolDayData.protocolFeesAUSD.plus(feeAInUSD) - poolDayData.protocolFeesBUSD = poolDayData.protocolFeesBUSD.plus(feeBInUSD) - - tokenADayData.protocolFees = tokenADayData.protocolFees.plus(feeAInDecimals) - tokenADayData.protocolFeesUSD = - tokenADayData.protocolFeesUSD.plus(feeAInUSD) - - tokenBDayData.protocolFees = tokenBDayData.protocolFees.plus(feeBInDecimals) - tokenBDayData.protocolFeesUSD = - tokenBDayData.protocolFeesUSD.plus(feeBInUSD) - - poolHourData.save() - poolDayData.save() - tokenADayData.save() - tokenBDayData.save() - pool.save() - } -} diff --git a/src/mappings/liquidity-vault/mint.ts b/src/mappings/liquidity-vault/mint.ts deleted file mode 100644 index e46649c..0000000 --- a/src/mappings/liquidity-vault/mint.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { - getOrCreateTransaction, - getOrCreateUserPoolBalance, - getPoolOrLog, - getTokenOrLog, -} from '../../common/entity-getters' -import { BI_18, ZERO_BI } from '../../common/constants' -import { convertTokenToDecimal } from '../../common/utils' -import { - updateDayData, - updatePoolDayData, - updatePoolHourData, -} from '../interval-updates' -import { getTokenUSDPriceFlat } from '../../common/pricing' -import { Mint } from '../../../generated/LiquidityVault/LiquidityVault' - -export function handleMint(event: Mint): void { - updateDayData(event, 'MINT') - - const pool = getPoolOrLog(event.params.key, 'MINT') - if (!pool || event.params.lpAmount.equals(ZERO_BI)) { - return - } - - const tokenA = getTokenOrLog(pool.tokenA, 'MINT') - const tokenB = getTokenOrLog(pool.tokenB, 'MINT') - - if (tokenA && tokenB) { - const priceAUSD = getTokenUSDPriceFlat(tokenA) - const priceBUSD = getTokenUSDPriceFlat(tokenB) - - if (pool.initialTokenAAmount.isZero()) { - pool.initialTokenAAmount = event.params.amountA - } - if (pool.initialTokenBAmount.isZero()) { - pool.initialTokenBAmount = event.params.amountB - } - if (pool.initialTotalSupply.isZero()) { - pool.initialTotalSupply = event.params.lpAmount - pool.initialMintTransaction = getOrCreateTransaction(event).id - } - - // update pool state - pool.totalSupply = pool.totalSupply.plus(event.params.lpAmount) - pool.liquidityA = pool.liquidityA.plus(event.params.amountA) - pool.liquidityB = pool.liquidityB.plus(event.params.amountB) - - const lpAmountDecimal = convertTokenToDecimal( - pool.totalSupply, - BI_18, // assuming LP token has 18 decimals - ) - const liquidityAInUSD = convertTokenToDecimal( - pool.liquidityA, - tokenA.decimals, - ).times(priceAUSD) - const liquidityBInUSD = convertTokenToDecimal( - pool.liquidityB, - tokenB.decimals, - ).times(priceBUSD) - pool.lpPriceUSD = liquidityAInUSD.plus(liquidityBInUSD).div(lpAmountDecimal) - pool.totalValueLockedUSD = lpAmountDecimal.times(pool.lpPriceUSD) - - const userPoolBalance = getOrCreateUserPoolBalance( - event.transaction.from, - pool.id, - event, - ) - - userPoolBalance.totalTokenADeposited = - userPoolBalance.totalTokenADeposited.plus(event.params.amountA) - userPoolBalance.totalTokenBDeposited = - userPoolBalance.totalTokenBDeposited.plus(event.params.amountB) - userPoolBalance.save() - - // @dev: To calculate the protocol's TVL, we need token.totalValueLocked + pool.totalValueLockedUSD - // tokenA.totalValueLocked = tokenA.totalValueLocked.plus(amountAInDecimals) - // tokenA.totalValueLockedUSD = tokenA.totalValueLocked.times(priceAUSD) - // tokenB.totalValueLocked = tokenB.totalValueLocked.plus(amountBInDecimals) - // tokenB.totalValueLockedUSD = tokenB.totalValueLocked.times(priceBUSD) - - // update interval - updatePoolHourData(pool, event) - updatePoolDayData(pool, event) - - pool.save() - } -} diff --git a/src/mappings/liquidity-vault/open.ts b/src/mappings/liquidity-vault/open.ts deleted file mode 100644 index 9ef26f0..0000000 --- a/src/mappings/liquidity-vault/open.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { Open } from '../../../generated/LiquidityVault/LiquidityVault' -import { - getBookOrLog, - getOrCreateTransaction, -} from '../../common/entity-getters' -import { Pool } from '../../../generated/schema' -import { ZERO_BD, ZERO_BI } from '../../common/constants' - -export function handlePoolOpen(event: Open): void { - const bookA = getBookOrLog(event.params.bookIdA.toString(), 'OPEN') - const bookB = getBookOrLog(event.params.bookIdB.toString(), 'OPEN') - if (bookA && bookB) { - const pool = new Pool(event.params.key) - pool.salt = event.params.salt - pool.strategy = event.params.strategy - pool.createdAtTimestamp = event.block.timestamp - pool.createdAtBlockNumber = event.block.number - pool.createdAtTransaction = getOrCreateTransaction(event).id - pool.initialTokenAAmount = ZERO_BI - pool.initialTokenBAmount = ZERO_BI - pool.initialTotalSupply = ZERO_BI - pool.initialLPPriceUSD = ZERO_BD - pool.tokenA = bookA.quote - pool.tokenB = bookB.quote - pool.bookA = bookA.id - pool.bookB = bookB.id - - pool.oraclePrice = ZERO_BI - pool.totalSupply = ZERO_BI - pool.liquidityA = ZERO_BI - pool.liquidityB = ZERO_BI - pool.lpPriceUSD = ZERO_BD - pool.priceA = ZERO_BD - pool.priceARaw = ZERO_BI - pool.tickA = ZERO_BI - pool.priceB = ZERO_BD - pool.priceBRaw = ZERO_BI - pool.tickB = ZERO_BI - pool.volumeTokenA = ZERO_BD - pool.volumeTokenB = ZERO_BD - pool.volumeUSD = ZERO_BD - pool.protocolFeesTokenA = ZERO_BD - pool.protocolFeesTokenB = ZERO_BD - pool.protocolFeesAUSD = ZERO_BD - pool.protocolFeesBUSD = ZERO_BD - pool.spreadProfitUSD = ZERO_BD - pool.totalValueLockedUSD = ZERO_BD - - // bind book to pool - bookA.pool = pool.id - bookB.pool = pool.id - - pool.save() - bookA.save() - bookB.save() - } -} diff --git a/src/mappings/liquidity-vault/strategy.ts b/src/mappings/liquidity-vault/strategy.ts deleted file mode 100644 index 09bbca9..0000000 --- a/src/mappings/liquidity-vault/strategy.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { Address, BigInt } from '@graphprotocol/graph-ts' - -import { getPoolOrLog, getTokenOrLog } from '../../common/entity-getters' -import { - formatInvertedPrice, - formatPrice, - tickToPrice, -} from '../../common/tick' -import { BI_18, BI_8, ONE_BD, ZERO_BD, ZERO_BI } from '../../common/constants' -import { convertTokenToDecimal } from '../../common/utils' -import { UpdatePosition } from '../../../generated/SimpleOracleStrategy/SimpleOracleStrategy' -import { isStableCoin } from '../../common/token' - -export function handleUpdatePosition(event: UpdatePosition): void { - const pool = getPoolOrLog(event.params.key, 'UPDATE_POSITION') - if (!pool) { - return - } - const tokenA = getTokenOrLog(pool.tokenA, 'UPDATE_POSITION') - const tokenB = getTokenOrLog(pool.tokenB, 'UPDATE_POSITION') - - if (tokenA && tokenB) { - pool.oraclePrice = event.params.oraclePrice - - pool.tickA = BigInt.fromI32(event.params.tickA) - pool.priceARaw = tickToPrice(event.params.tickA) - pool.priceA = formatPrice(pool.priceARaw, tokenB.decimals, tokenA.decimals) - - pool.tickB = BigInt.fromI32(event.params.tickB) - pool.priceBRaw = tickToPrice(event.params.tickB) - pool.priceB = formatInvertedPrice( - pool.priceBRaw, - tokenA.decimals, - tokenB.decimals, - ) - - const tokenAUSDPrice = isStableCoin(Address.fromBytes(tokenA.id)) - ? ONE_BD - : convertTokenToDecimal(event.params.oraclePrice, BI_8) - const tokenBUSDPrice = isStableCoin(Address.fromBytes(tokenB.id)) - ? ONE_BD - : convertTokenToDecimal(event.params.oraclePrice, BI_8) - const initialLpAmountDecimal = convertTokenToDecimal( - pool.initialTotalSupply, - BI_18, // assuming LP token has 18 decimals - ) - if ( - pool.initialLPPriceUSD.equals(ZERO_BD) && - initialLpAmountDecimal.gt(ZERO_BD) && - pool.initialTokenAAmount.gt(ZERO_BI) && - pool.initialTokenBAmount.gt(ZERO_BI) - ) { - const amountAInUSD = convertTokenToDecimal( - pool.initialTokenAAmount, - tokenA.decimals, - ).times(tokenAUSDPrice) - const amountBInUSD = convertTokenToDecimal( - pool.initialTokenBAmount, - tokenB.decimals, - ).times(tokenBUSDPrice) - pool.initialLPPriceUSD = amountAInUSD - .plus(amountBInUSD) - .div(initialLpAmountDecimal) - } - - const lpAmountDecimal = convertTokenToDecimal( - pool.totalSupply, - BI_18, // assuming LP token has 18 decimals - ) - if (lpAmountDecimal.gt(ZERO_BD)) { - const amountAInUSD = convertTokenToDecimal( - pool.liquidityA, - tokenA.decimals, - ).times(tokenAUSDPrice) - const amountBInUSD = convertTokenToDecimal( - pool.liquidityB, - tokenB.decimals, - ).times(tokenBUSDPrice) - pool.lpPriceUSD = amountAInUSD.plus(amountBInUSD).div(lpAmountDecimal) - pool.totalValueLockedUSD = pool.lpPriceUSD.times(lpAmountDecimal) - } - - pool.save() - } -} diff --git a/src/mappings/liquidity-vault/transfer.ts b/src/mappings/liquidity-vault/transfer.ts deleted file mode 100644 index 4769853..0000000 --- a/src/mappings/liquidity-vault/transfer.ts +++ /dev/null @@ -1,145 +0,0 @@ -import { - store, - BigDecimal, - Bytes, - BigInt, - Address, -} from '@graphprotocol/graph-ts' - -import { Transfer } from '../../../generated/LiquidityVault/LiquidityVault' -import { updateDayData } from '../interval-updates' -import { - getOrCreateUserPoolBalance, - getPoolOrLog, - getTokenOrLog, -} from '../../common/entity-getters' -import { - ADDRESS_ZERO, - BI_18, - BI_8, - ONE_BD, - ZERO_BD, - ZERO_BI, -} from '../../common/constants' -import { convertTokenToDecimal } from '../../common/utils' -import { UserPoolBalance } from '../../../generated/schema' -import { isStableCoin } from '../../common/token' - -function buyLpToken( - userPoolBalance: UserPoolBalance, - amount: BigInt, - lpPriceUSD: BigDecimal, -): void { - const costToAdd = convertTokenToDecimal(amount, BI_18).times(lpPriceUSD) - userPoolBalance.lpBalance = userPoolBalance.lpBalance.plus(amount) - userPoolBalance.costBasisUSD = userPoolBalance.costBasisUSD.plus(costToAdd) - - const lpBalanceBD = convertTokenToDecimal(userPoolBalance.lpBalance, BI_18) - userPoolBalance.lpBalanceUSD = lpBalanceBD.times(lpPriceUSD) - - userPoolBalance.averageLPPriceUSD = userPoolBalance.lpBalance.gt(ZERO_BI) - ? userPoolBalance.costBasisUSD.div(lpBalanceBD) - : ZERO_BD - - if (userPoolBalance.lpBalance.equals(ZERO_BI)) { - store.remove('UserPoolBalance', userPoolBalance.id) - } else { - userPoolBalance.save() - } -} - -function sellLpToken( - userPoolBalance: UserPoolBalance, - amount: BigInt, - lpPriceUSD: BigDecimal, -): void { - userPoolBalance.lpBalance = userPoolBalance.lpBalance.minus(amount) - userPoolBalance.lpBalanceUSD = convertTokenToDecimal( - userPoolBalance.lpBalance, - BI_18, - ).times(lpPriceUSD) - - if (userPoolBalance.lpBalance.equals(ZERO_BI)) { - store.remove('UserPoolBalance', userPoolBalance.id) - } else { - userPoolBalance.save() - } -} - -export function handleTransfer(event: Transfer): void { - updateDayData(event, 'TRANSFER') - - const key = Bytes.fromHexString( - '0x' + event.params.id.toHexString().slice(2).padStart(64, '0'), - ) - const pool = getPoolOrLog(key, 'TRANSFER') - if ( - !pool || - event.params.amount.equals(ZERO_BI) || - event.params.from.equals(event.params.to) - ) { - return - } - - const tokenA = getTokenOrLog(pool.tokenA, 'TRANSFER') - const tokenB = getTokenOrLog(pool.tokenB, 'TRANSFER') - if (!tokenA || !tokenB) { - return - } - - const oraclePrice = convertTokenToDecimal(pool.oraclePrice, BI_8) - const tokenAUSDPrice = isStableCoin(Address.fromBytes(tokenA.id)) - ? ONE_BD - : oraclePrice - const tokenBUSDPrice = isStableCoin(Address.fromBytes(tokenB.id)) - ? ONE_BD - : oraclePrice - - const isMint = event.params.from.equals(Bytes.fromHexString(ADDRESS_ZERO)) - const isBurn = event.params.to.equals(Bytes.fromHexString(ADDRESS_ZERO)) - const isTransfer = !isMint && !isBurn - - const liquidityAInUSD = convertTokenToDecimal( - pool.liquidityA, - tokenA.decimals, - ).times(tokenAUSDPrice) - const liquidityBInUSD = convertTokenToDecimal( - pool.liquidityB, - tokenB.decimals, - ).times(tokenBUSDPrice) - const totalSupply = convertTokenToDecimal(pool.totalSupply, BI_18) - const lpPriceUSD = - oraclePrice.gt(ZERO_BD) && totalSupply.gt(ZERO_BD) - ? liquidityAInUSD.plus(liquidityBInUSD).div(totalSupply) - : pool.lpPriceUSD - - if (isMint) { - buyLpToken( - getOrCreateUserPoolBalance(event.params.to, key, event), - event.params.amount, - lpPriceUSD, - ) - } else if (isBurn) { - sellLpToken( - getOrCreateUserPoolBalance(event.params.from, key, event), - event.params.amount, - lpPriceUSD, - ) - } else if ( - isTransfer && - !event.params.from.equals(event.params.to) && - !event.params.from.equals(Bytes.fromHexString(ADDRESS_ZERO)) && - !event.params.to.equals(Bytes.fromHexString(ADDRESS_ZERO)) - ) { - sellLpToken( - getOrCreateUserPoolBalance(event.params.from, key, event), - event.params.amount, - lpPriceUSD, - ) - buyLpToken( - getOrCreateUserPoolBalance(event.params.to, key, event), - event.params.amount, - lpPriceUSD, - ) - } -} diff --git a/src/mappings/router-gateway.ts b/src/mappings/router-gateway.ts deleted file mode 100644 index 1343d0e..0000000 --- a/src/mappings/router-gateway.ts +++ /dev/null @@ -1,169 +0,0 @@ -import { log } from '@graphprotocol/graph-ts' - -import { FeeCollected, Swap } from '../../generated/RouterGateway/RouterGateway' -import { - RouterDayData, - Swap as SwapEntity, - Token, -} from '../../generated/schema' -import { ONE_BI, ZERO_BD, ZERO_BI } from '../common/constants' -import { calculateValueUSD, getTokenUSDPriceFlat } from '../common/pricing' -import { convertTokenToDecimal } from '../common/utils' -import { SKIP_TAKE_AND_SWAP } from '../common/chain' - -import { - updateDayData, - updateTokenDayData, - updateUserDayVolume, - updateUserNativeVolume, -} from './interval-updates' - -export function handleSwap(event: Swap): void { - updateDayData(event, 'SWAP') - - const inputToken = Token.load(event.params.inToken) - const outputToken = Token.load(event.params.outToken) - - const swap = new SwapEntity( - event.transaction.hash - .toHexString() - .concat('-') - .concat(event.logIndex.toString()), - ) - swap.transaction = event.transaction.hash.toHexString() - swap.timestamp = event.block.timestamp - swap.inputToken = event.params.inToken - swap.outputToken = event.params.outToken - swap.origin = event.transaction.from - swap.inputAmount = event.params.amountIn - swap.outputAmount = event.params.amountOut - swap.router = event.params.router - swap.fee = ZERO_BI - if ( - inputToken && - outputToken && - swap.inputAmount.ge(ZERO_BI) && - swap.outputAmount.ge(ZERO_BI) - ) { - const inputAmountDecimal = convertTokenToDecimal( - swap.inputAmount, - inputToken.decimals, - ) - const outputAmountDecimal = convertTokenToDecimal( - swap.outputAmount, - outputToken.decimals, - ) - const priceIn = getTokenUSDPriceFlat(inputToken) - const priceOut = getTokenUSDPriceFlat(outputToken) - - swap.amountUSD = calculateValueUSD( - inputAmountDecimal, - priceIn, - outputAmountDecimal, - priceOut, - ) - - if (priceIn.gt(ZERO_BD)) { - updateUserDayVolume(inputToken, event, inputAmountDecimal, swap.amountUSD) - const inputTokenDayData = updateTokenDayData(inputToken, priceIn, event) - inputTokenDayData.volume = - inputTokenDayData.volume.plus(inputAmountDecimal) - inputTokenDayData.volumeUSD = inputTokenDayData.volumeUSD.plus( - swap.amountUSD, - ) - inputTokenDayData.save() - } else if (priceOut.gt(ZERO_BD)) { - updateUserDayVolume( - outputToken, - event, - outputAmountDecimal, - swap.amountUSD, - ) - const outputTokenDayData = updateTokenDayData( - outputToken, - priceOut, - event, - ) - outputTokenDayData.volume = - outputTokenDayData.volume.plus(outputAmountDecimal) - outputTokenDayData.volumeUSD = outputTokenDayData.volumeUSD.plus( - swap.amountUSD, - ) - outputTokenDayData.save() - } - updateUserNativeVolume( - event, - swap.inputToken, - swap.outputToken, - swap.inputAmount, - swap.outputAmount, - ) - } else { - log.warning( - 'Swap USD skipped: inputToken or outputToken missing or invalid amounts. tx: {}', - [event.transaction.hash.toHexString()], - ) - swap.amountUSD = ZERO_BD - } - swap.logIndex = event.logIndex - if (!SKIP_TAKE_AND_SWAP) { - swap.save() - - const dayID = swap.timestamp.toI32() / 86400 // rounded - const routerDayID = swap.router - .toHexString() - .concat('-') - .concat(dayID.toString()) - let routerDayData = RouterDayData.load(routerDayID) - if (routerDayData === null) { - routerDayData = new RouterDayData(routerDayID) - routerDayData.date = dayID - routerDayData.cloberDayData = dayID.toString() - routerDayData.router = swap.router - routerDayData.txCount = ZERO_BI - } - routerDayData.txCount = routerDayData.txCount.plus(ONE_BI) - routerDayData.save() - } -} - -export function handleFeeCollected(event: FeeCollected): void { - const swap = SwapEntity.load( - event.transaction.hash - .toHexString() - .concat('-') - .concat(event.logIndex.minus(ONE_BI).toString()), - ) - const token = Token.load(event.params.token) - if (swap && token) { - const price = getTokenUSDPriceFlat(token) - const feeAmountDecimal = convertTokenToDecimal( - event.params.amount, - token.decimals, - ) - const feeAmountUSD = feeAmountDecimal.times(price) - // update token fees - token.routerGatewayProtocolFee = - token.routerGatewayProtocolFee.plus(feeAmountDecimal) - token.routerGatewayProtocolFeeUSD = - token.routerGatewayProtocolFeeUSD.plus(feeAmountUSD) - token.protocolFees = token.protocolFees.plus(feeAmountDecimal) - token.protocolFeesUSD = token.protocolFeesUSD.plus(feeAmountUSD) - - const tokenDayData = updateTokenDayData(token, price, event) - // update token day data fees - tokenDayData.routerGatewayProtocolFee = - tokenDayData.routerGatewayProtocolFee.plus(feeAmountDecimal) - tokenDayData.routerGatewayProtocolFeeUSD = - tokenDayData.routerGatewayProtocolFeeUSD.plus(feeAmountUSD) - tokenDayData.protocolFees = tokenDayData.protocolFees.plus(feeAmountDecimal) - tokenDayData.protocolFeesUSD = - tokenDayData.protocolFeesUSD.plus(feeAmountUSD) - - swap.fee = event.params.amount - - swap.save() - token.save() - tokenDayData.save() - } -} diff --git a/subgraph.template.yaml b/subgraph.template.yaml index cd0d460..63e1059 100644 --- a/subgraph.template.yaml +++ b/subgraph.template.yaml @@ -16,132 +16,12 @@ dataSources: apiVersion: 0.0.7 language: wasm/assemblyscript entities: - - Token - - Book - - Depth - - OpenOrder - - Transaction - - ChartLog - - Pool - - User - - BookDayData - - TokenDayData - CloberDayData - - TransactionTypeDayData - - UserDayData - - UserDayVolume - - PoolDayData - - PoolHourData - - Take + - ContractInteractionDayData abis: - name: BookManager file: ./abis/BookManager.json - - name: ERC20 - file: ./abis/ERC20.json - - name: ERC20SymbolBytes - file: ./abis/ERC20SymbolBytes.json - - name: ERC20NameBytes - file: ./abis/ERC20NameBytes.json eventHandlers: - - event: Open(indexed uint192,indexed address,indexed - address,uint64,uint24,uint24,address) - handler: handleBookOpen - - event: Make(indexed uint192,indexed address,int24,uint256,uint64,address) - handler: handleMake - event: Take(indexed uint192,indexed address,int24,uint64) handler: handleTake - - event: Cancel(indexed uint256,uint64) - handler: handleCancel - - event: Claim(indexed uint256,uint64) - handler: handleClaim - - event: Transfer(indexed address,indexed address,indexed uint256) - handler: handleBookManagerTransfer file: ./src/mappings/core.ts - - kind: ethereum - name: LiquidityVault - network: {{ network }} - source: - abi: LiquidityVault - address: "{{ LiquidityVault.address }}" - startBlock: {{ LiquidityVault.startBlock }} - mapping: - kind: ethereum/events - apiVersion: 0.0.7 - language: wasm/assemblyscript - entities: - - Pool - - Transaction - - PoolDayData - - PoolHourData - - TokenDayData - - CloberDayData - - UserDayData - - TransactionTypeDayData - - User - - UserPoolBalance - abis: - - name: LiquidityVault - file: ./abis/LiquidityVault.json - eventHandlers: - - event: Open(indexed bytes32,indexed uint192,indexed uint192,bytes32,address) - handler: handlePoolOpen - - event: Mint(indexed address,indexed bytes32,uint256,uint256,uint256) - handler: handleMint - - event: Burn(indexed address,indexed bytes32,uint256,uint256,uint256,uint256,uint256) - handler: handleBurn - - event: Transfer(address,indexed address,indexed address,indexed uint256,uint256) - handler: handleLiquidityVaultTransfer - file: ./src/mappings/core.ts - - kind: ethereum - name: SimpleOracleStrategy - network: {{ network }} - source: - abi: SimpleOracleStrategy - address: "{{ SimpleOracleStrategy.address }}" - startBlock: {{ SimpleOracleStrategy.startBlock }} - mapping: - kind: ethereum/events - apiVersion: 0.0.7 - language: wasm/assemblyscript - entities: - - Pool - abis: - - name: SimpleOracleStrategy - file: ./abis/SimpleOracleStrategy.json - eventHandlers: - - event: UpdatePosition(indexed bytes32,uint256,int24,int24,uint256) - handler: handleUpdatePosition - file: ./src/mappings/core.ts - {{#hasRouterGateway}} - - kind: ethereum - name: RouterGateway - network: {{ network }} - source: - abi: RouterGateway - address: "{{ RouterGateway.address }}" - startBlock: {{ RouterGateway.startBlock }} - mapping: - kind: ethereum/events - apiVersion: 0.0.7 - language: wasm/assemblyscript - entities: - - Swap - - CloberDayData - - TransactionTypeDayData - - RouterDayData - - TokenDayData - - User - - UserDayData - - UserDayVolume - abis: - - name: RouterGateway - file: ./abis/RouterGateway.json - eventHandlers: - - event: Swap(indexed address,indexed address,indexed - address,uint256,uint256,address,bytes4) - handler: handleSwap - receipt: true - - event: FeeCollected(indexed address,indexed address,uint256) - handler: handleFeeCollected - file: ./src/mappings/router-gateway.ts - {{/hasRouterGateway}}