Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions rage/generated/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1958,6 +1958,15 @@ export class RageTradePool extends Entity {
set dayData(value: string) {
this.set("dayData", Value.fromString(value));
}

get fundingObservations(): Array<string> {
let value = this.get("fundingObservations");
return value.toStringArray();
}

set fundingObservations(value: Array<string>) {
this.set("fundingObservations", Value.fromStringArray(value));
}
}

export class VToken extends Entity {
Expand Down Expand Up @@ -2067,6 +2076,64 @@ export class VPoolWrapper extends Entity {
}
}

export class FundingObservation extends Entity {
constructor(id: string) {
super();
this.set("id", Value.fromString(id));
}

save(): void {
let id = this.get("id");
assert(id !== null, "Cannot save FundingObservation entity without an ID");
assert(
id.kind == ValueKind.STRING,
"Cannot save FundingObservation entity with non-string ID. " +
'Considering using .toHex() to convert the "id" to a string.'
);
store.set("FundingObservation", id.toString(), this);
}

static load(id: string): FundingObservation | null {
return store.get("FundingObservation", id) as FundingObservation | null;
}

get id(): string {
let value = this.get("id");
return value.toString();
}

set id(value: string) {
this.set("id", Value.fromString(value));
}

get timestamp(): BigInt {
let value = this.get("timestamp");
return value.toBigInt();
}

set timestamp(value: BigInt) {
this.set("timestamp", Value.fromBigInt(value));
}

get fundingRate(): BigDecimal {
let value = this.get("fundingRate");
return value.toBigDecimal();
}

set fundingRate(value: BigDecimal) {
this.set("fundingRate", Value.fromBigDecimal(value));
}

get pool(): string {
let value = this.get("pool");
return value.toString();
}

set pool(value: string) {
this.set("pool", Value.fromString(value));
}
}

export class Collection extends Entity {
constructor(id: string) {
super();
Expand Down
42 changes: 30 additions & 12 deletions rage/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,20 @@ type Account @entity {
"Total number of swaps made by the account"
tokenPositionChangeEntriesCount: BigInt!
"list all swaps made by the account"
tokenPositionChangeEntries: [TokenPositionChangeEntry!]! @derivedFrom(field: "account")
tokenPositionChangeEntries: [TokenPositionChangeEntry!]!
@derivedFrom(field: "account")
"list of all margin/collateral tokens deposited by the account, currently only USDC"
margin: [Collateral!]! @derivedFrom(field: "account")
"total number time a funding payment realized for an account"
fundingPaymentRealizedEntriesCount: BigInt!
"list of funding payment realized entries for an account"
fundingPaymentRealizedEntries: [FundingPaymentRealizedEntry!]! @derivedFrom(field: "account")
fundingPaymentRealizedEntries: [FundingPaymentRealizedEntry!]!
@derivedFrom(field: "account")
"total number of liquidations that occurred for this account"
tokenPositionLiquidatedEntriesCount: BigInt!
"list of all liquidations that occurred for this account"
tokenPositionLiquidatedEntries: [TokenPositionLiquidatedEntry!]! @derivedFrom(field: "account")
tokenPositionLiquidatedEntries: [TokenPositionLiquidatedEntry!]!
@derivedFrom(field: "account")
"list of all V-Token tokens positions held by the account, currently only ETH"
tokenPositions: [TokenPosition!]! @derivedFrom(field: "account")
"total number of margin changes made by the account ie. withdraws and deposits"
Expand Down Expand Up @@ -148,21 +151,24 @@ type TokenPosition @entity {
"Total number of swaps made by the account, for this pool"
tokenPositionChangeEntriesCount: BigInt!
"list all swaps made by the account, for this pool"
tokenPositionChangeEntries: [TokenPositionChangeEntry!]! @derivedFrom(field: "tokenPosition")
tokenPositionChangeEntries: [TokenPositionChangeEntry!]!
@derivedFrom(field: "tokenPosition")
"total number time a funding payment realized entry was created for this position"
fundingPaymentRealizedEntriesCount: BigInt!
"timestamp of the last funding payment realized entry for this position"
lastFundingPaymentRealizedEntryTimestamp: BigInt!
"list of funding payment realized entries for this position"
fundingPaymentRealizedEntries: [FundingPaymentRealizedEntry!]! @derivedFrom(field: "tokenPosition")
fundingPaymentRealizedEntries: [FundingPaymentRealizedEntry!]!
@derivedFrom(field: "tokenPosition")
"list of id(s) of the token position change entries, that are 'open' positions, used for calculating the pnl"
openPositionEntries: [String!]!
"the latest token position change entry, used in calculation for TokenPositionLiquidated event"
lastTokenPositionChangeEntry: TokenPositionChangeEntry!
"total number of liquidations that occurred for this position"
tokenPositionLiquidatedEntriesCount: BigInt!
"list of all liquidations that occurred for this position"
tokenPositionLiquidatedEntries: [TokenPositionLiquidatedEntry!]! @derivedFrom(field: "tokenPosition")
tokenPositionLiquidatedEntries: [TokenPositionLiquidatedEntry!]!
@derivedFrom(field: "tokenPosition")
"total funding payment amount for this position"
totalRealizedFundingPaymentAmount: BigDecimal!
"latest sum of all the A terms in the pool, at the time of the position change"
Expand All @@ -178,7 +184,7 @@ type TokenPosition @entity {
"sum aff (vTokenQuantity * entryPrice), across all token position change entries"
entryValue: BigDecimal!
"entryPrice = abs(entryValue / netPosition)"
entryPrice: BigDecimal!
entryPrice: BigDecimal!
}

"""
Expand All @@ -194,7 +200,7 @@ token position change
"""
type MarginChangeEntry @entity {
"unique id of the margin change entry"
id: ID!
id: ID!
"block.timestamp of the transaction of the margin change entry"
timestamp: BigInt!
"transaction.hash of the event that triggered this margin change entry"
Expand Down Expand Up @@ -422,6 +428,8 @@ type RageTradePool @entity {
hourData: Collection!
"list of collection of candles, recorded for each day"
dayData: Collection!
"list of funding observations"
fundingObservations: [FundingObservation!]! @derivedFrom(field: "pool")
}

type VToken @entity {
Expand All @@ -444,6 +452,16 @@ type VPoolWrapper @entity {
pool: RageTradePool!
}

type FundingObservation @entity {
id: ID!
"timestamp of the observation"
timestamp: BigInt!
"funding rate over 24hrs - (virtualPrice - realPrice) / (realPrice * 24)"
fundingRate: BigDecimal!
"pool to which the observation belongs to"
pool: RageTradePool!
}

type Collection @entity {
"unique id of the collection"
id: ID!
Expand Down Expand Up @@ -699,7 +717,7 @@ type UniswapV3Transaction @entity {
}

type UniswapV3Mint @entity {
"transaction hash + "#" + index in mints Transaction array"
"transaction hash + " #" + index in mints Transaction array"
id: ID!
"which txn the mint was included in"
transaction: UniswapV3Transaction!
Expand Down Expand Up @@ -734,7 +752,7 @@ type UniswapV3Mint @entity {
}

type UniswapV3Burn @entity {
"transaction hash + "#" + index in mints Transaction array"
"transaction hash + " #" + index in mints Transaction array"
id: ID!
"txn burn was included in"
transaction: UniswapV3Transaction!
Expand Down Expand Up @@ -767,7 +785,7 @@ type UniswapV3Burn @entity {
}

type UniswapV3Swap @entity {
"transaction hash + "#" + index in swaps Transaction array"
"transaction hash + " #" + index in swaps Transaction array"
id: ID!
"pointer to transaction"
transaction: UniswapV3Transaction!
Expand Down Expand Up @@ -800,7 +818,7 @@ type UniswapV3Swap @entity {
}

type UniswapV3Collect @entity {
"transaction hash + "#" + index in collect Transaction array"
"transaction hash + " #" + index in collect Transaction array"
id: ID!
"pointer to txn"
transaction: UniswapV3Transaction!
Expand Down
13 changes: 13 additions & 0 deletions rage/src/mappings/clearinghouse/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
min,
parsePriceX128,
parseSqrtPriceX96,
recordFundingObservation,
safeDiv,
} from '../../utils';
import { UniswapV3Pool } from '../../../generated/templates/UniswapV3Pool/UniswapV3Pool';
Expand Down Expand Up @@ -69,6 +70,12 @@ export function handleTokenPositionChanged(event: TokenPositionChanged): void {
]
);

recordFundingObservation(
event.params.poolId,
event.block.timestamp,
getFundingRate(event.params.poolId)
);

// update token position
let account = getAccount(event.params.accountId);

Expand Down Expand Up @@ -538,6 +545,12 @@ export function handleTokenPositionFundingPaymentRealized(

rageTradePool.fundingRate = getFundingRate(event.params.poolId);

recordFundingObservation(
event.params.poolId,
event.block.timestamp,
rageTradePool.fundingRate
);

entry.side = tokenPosition.netPosition.gt(ZERO_BD) ? 'long' : 'short';

tokenPosition.lastFundingPaymentRealizedEntryTimestamp = entry.timestamp;
Expand Down
21 changes: 20 additions & 1 deletion rage/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
/* eslint-disable prefer-const */
import { BigInt, BigDecimal, ethereum, log } from '@graphprotocol/graph-ts';
import { UniswapV3Transaction } from '../../generated/schema';
import {
FundingObservation,
UniswapV3Transaction,
} from '../../generated/schema';
import {
ONE_BI,
ZERO_BI,
Expand All @@ -14,6 +17,7 @@ import { Address } from '@graphprotocol/graph-ts';
import { ClearingHouse } from '../../generated/ClearingHouse/ClearingHouse';
import { VPoolWrapperLogic } from '../../generated/templates/VPoolWrapperLogic/VPoolWrapperLogic';
import { contracts } from './addresses';
import { getRageTradePoolId } from '../mappings/ragetradeFactory/rageTradePool';

export function exponentToBigDecimal(decimals: BigInt): BigDecimal {
let bd = BigDecimal.fromString('1');
Expand Down Expand Up @@ -289,3 +293,18 @@ export function min(a: BigDecimal, b: BigDecimal): BigDecimal {
export function max(a: BigDecimal, b: BigDecimal): BigDecimal {
return a.gt(b) ? a : b;
}

export function recordFundingObservation(
poolId: BigInt,
timestamp: BigInt,
fundingRate: BigDecimal
): void {
let observationId = generateId([poolId.toHexString(), timestamp.toString()]);
if (!FundingObservation.load(observationId)) {
let observation = new FundingObservation(observationId);
observation.pool = getRageTradePoolId(poolId);
observation.timestamp = timestamp;
observation.fundingRate = fundingRate;
observation.save();
}
}