Skip to content

Commit

Permalink
feat: index claimed yield (#137)
Browse files Browse the repository at this point in the history
* feat: index claimed yield

* fix: format

* fix: claimed yied asset

* fix: format
  • Loading branch information
matstyler authored Apr 3, 2024
1 parent 0340240 commit 48a2fea
Show file tree
Hide file tree
Showing 9 changed files with 176 additions and 28 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/deploy-subgraph.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ jobs:
- name: Install modules
run: yarn
- name: Generate config
run: yarn generate-config:goerli
run: yarn generate-config:sepolia
- name: Codegen
run: yarn codegen:goerli
run: yarn codegen:sepolia
- name: Authorize TheGraph
run: yarn authorize ${{secrets.THE_GRAPH_ACCESS_TOKEN}}
- name: Deploy
run: yarn deploy:goerli
run: yarn deploy:sepolia
5 changes: 1 addition & 4 deletions .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@
}
}
],
"importOrder": [
"^@*/(.*)$",
"^[./]"
],
"importOrder": ["^@*/(.*)$", "^[./]"],
"importOrderSeparation": true
}
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
This subgraph can be found on The Graph Hosted Service for the following networks:

- [Mainnet](https://thegraph.com/hosted-service/subgraph/perspectivefi/spectra-mainnet)
- [Goerli](https://thegraph.com/hosted-service/subgraph/perspectivefi/spectra-goerli)
- [Sepolia](https://api.studio.thegraph.com/query/58996/spectra-subgraph-sepolia/version/latest)

You can also run this subgraph locally, if you wish. Instructions for that can be found in [The Graph Documentation](https://thegraph.com/docs/en/cookbook/quick-start/).

Expand Down Expand Up @@ -161,7 +161,7 @@ graph auth https://api.thegraph.com/deploy/ <ACCESS_TOKEN>

### 5. Create deployment script in `package.json` (if not exists for your network)

### 6. Add network id (if missing) to the `ChainId` class in `src/utils/ChainId.ts` file
### 6. Add network id (if missing) to the `ChainId` class in `src/utils/ChainId.ts` file

### 7. Deploy the subgraph

Expand All @@ -180,7 +180,8 @@ yarn deploy:<NETWORK>
#### IMPORTANT: If your network is not supported you have to go to `src/configs` and add new config file.

## Schema
Graph definition written in PlantUML framework - [schema.puml](schema.puml)

Graph definition written in PlantUML framework - [schema.puml](schema.puml)

## Example queries

Expand Down
3 changes: 3 additions & 0 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ enum AssetType {
LP
LP_VAULT_SHARES
YIELD
CLAIMED_YIELD
UNKNOWN
}

Expand Down Expand Up @@ -138,6 +139,8 @@ type Asset @entity {

"in the case the asset is an IBT we create relation between this IBT and its underlying asset"
underlying: Asset
"in case the asset is a CLAIMED_YIELD we create relation between this CLAIMED_YIELD and its native IBT"
ibt: Asset
fytTokenDetails: FYTTokenDetails
lpTokenDetails: LPTokenDetails
}
Expand Down
117 changes: 103 additions & 14 deletions src/entities/Yield.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import { Address, BigInt, log } from "@graphprotocol/graph-ts"
import { Address, BigInt } from "@graphprotocol/graph-ts"

import { AccountAsset, Asset, Future } from "../../generated/schema"
import { ZERO_BI } from "../constants"
import { AssetType, generateAccountAssetId } from "../utils"
import { generateYieldAssetId } from "../utils/idGenerators"
import {
generateClaimedYieldAssetId,
generateYieldAssetId,
} from "../utils/idGenerators"
import { getAccount } from "./Account"
import { getAsset } from "./Asset"
import { getERC20Decimals } from "./ERC20"
import {
getName,
getSymbol,
getUnderlying,
getCurrentYieldOfUserInIBT,
getIBT,
} from "./FutureVault"
import { getNetwork } from "./Network"

Expand Down Expand Up @@ -88,10 +91,87 @@ export function getAccountYieldAsset(
return accountAsset
}

export function updateAccountAssetBalance(
function createClaimedYieldAsset(
principalToken: Address,
ibtAddress: Address,
timestamp: BigInt
): Asset {
let asset = new Asset(generateClaimedYieldAssetId(principalToken.toHex()))
asset.chainId = getNetwork().chainId
asset.address = ibtAddress
asset.createdAtTimestamp = timestamp
asset.type = AssetType.CLAIMED_YIELD

asset.name = getName(principalToken) + " Claimed Yield"
asset.symbol = getSymbol(principalToken) + " Claimed Yield"
asset.decimals = getERC20Decimals(ibtAddress)

let ibtAsset = getAsset(ibtAddress.toHex(), timestamp, AssetType.IBT)
asset.ibt = ibtAsset.id
asset.futureVault = principalToken.toHex()

asset.save()
return asset
}

function getClaimedYieldAsset(
principalToken: Address,
ibtAddress: Address,
timestamp: BigInt
): Asset {
let asset = Asset.load(generateClaimedYieldAssetId(principalToken.toHex()))
if (asset) {
return asset
}

asset = createClaimedYieldAsset(principalToken, ibtAddress, timestamp)

return asset as Asset
}

export function getAccountClaimedYieldAsset(
accountAddress: Address,
principalToken: Address,
timestamp: BigInt
): AccountAsset {
const ibtAddress = getIBT(principalToken)
let claimedYieldAsset = getClaimedYieldAsset(
principalToken,
ibtAddress,
timestamp
)
let ibtAsset = getAsset(ibtAddress.toHex(), timestamp, AssetType.IBT)

claimedYieldAsset.ibt = ibtAsset.id
claimedYieldAsset.save()

let account = getAccount(accountAddress.toHex(), timestamp)
let accountAssetId = generateAccountAssetId(
account.address.toHex(),
claimedYieldAsset.id,
"claimed-"
)

let accountAsset = AccountAsset.load(accountAssetId)
if (accountAsset) {
return accountAsset
}

accountAsset = new AccountAsset(accountAssetId)

accountAsset.createdAtTimestamp = timestamp
accountAsset.balance = ZERO_BI

accountAsset.asset = claimedYieldAsset.id
accountAsset.account = accountAddress.toHex()

accountAsset.save()
return accountAsset
}

export function updateYieldAccountAssetBalance(
principalToken: Address,
accountAddress: Address,
assetId: string,
timestamp: BigInt
): AccountAsset {
let yieldAsset = getYieldAsset(principalToken, accountAddress, timestamp)
Expand All @@ -103,7 +183,6 @@ export function updateAccountAssetBalance(
timestamp
)

// TODO: Change IBT to Underlying
accountAsset.balance = getCurrentYieldOfUserInIBT(
principalToken,
accountAddress
Expand All @@ -113,20 +192,30 @@ export function updateAccountAssetBalance(
return accountAsset
}

export function updateYield(
export function updateClaimedYieldAccountAssetBalance(
principalToken: Address,
accountAddress: Address,
claimBalance: BigInt,
timestamp: BigInt
): void {
let underlyingAddress = getUnderlying(principalToken)
let yieldAsset = getYieldAsset(principalToken, underlyingAddress, timestamp)

updateAccountAssetBalance(
principalToken,
): AccountAsset {
let accountAsset = getAccountClaimedYieldAsset(
accountAddress,
yieldAsset.id,
principalToken,
timestamp
)

accountAsset.balance = accountAsset.balance.plus(claimBalance)

accountAsset.save()
return accountAsset
}

export function updateYield(
principalToken: Address,
accountAddress: Address,
timestamp: BigInt
): void {
updateYieldAccountAssetBalance(principalToken, accountAddress, timestamp)
}

export function updateYieldForAll(
Expand Down
12 changes: 10 additions & 2 deletions src/mappings/futures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ import {
import { getNetwork } from "../entities/Network"
import { createPool } from "../entities/Pool"
import { createTransaction } from "../entities/Transaction"
import { updateYieldForAll } from "../entities/Yield"
import {
updateClaimedYieldAccountAssetBalance,
updateYieldForAll,
} from "../entities/Yield"
import { AssetType, generateFeeClaimId } from "../utils"
// import FutureState from "../utils/FutureState"
import transactionType from "../utils/TransactionType"
Expand Down Expand Up @@ -420,7 +423,12 @@ export function handleYieldClaimed(event: YieldClaimed): void {
let future = Future.load(event.address.toHex())

if (future) {
updateYieldForAll(event.address, event.block.timestamp)
updateClaimedYieldAccountAssetBalance(
event.address,
event.params.receiver,
event.params.yieldInIBT,
event.block.timestamp
)
} else {
log.warning("YieldClaimed event call for not existing Future {}", [
event.address.toHex(),
Expand Down
45 changes: 45 additions & 0 deletions src/tests/futures.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
Redeem,
Unpaused,
YieldUpdated,
YieldClaimed,
} from "../../generated/templates/PrincipalToken/PrincipalToken"
import { DAY_ID_0, ZERO_BI } from "../constants"
import {
Expand All @@ -23,6 +24,7 @@ import {
handleRedeem,
handleUnpaused,
handleYieldUpdated,
handleYieldClaimed,
} from "../mappings/futures"
import {
generateAssetAmountId,
Expand Down Expand Up @@ -853,3 +855,46 @@ describe("handleCurvePoolDeployed()", () => {
)
})
})

describe("handleYieldClaimed()", () => {
beforeAll(() => {
let yieldClaimedEvent = changetype<YieldClaimed>(newMockEvent())
yieldClaimedEvent.address = FIRST_FUTURE_VAULT_ADDRESS_MOCK

let ownerParam = new ethereum.EventParam(
"owner",
ethereum.Value.fromAddress(FIRST_USER_MOCK)
)

let receiverParam = new ethereum.EventParam(
"receiver",
ethereum.Value.fromAddress(FIRST_USER_MOCK)
)

let yieldInIBTParam = new ethereum.EventParam(
"yieldInIBT",
ethereum.Value.fromUnsignedBigInt(YIELD_USER_YIELD_IN_IBT_MOCK)
)

yieldClaimedEvent.parameters = [
ownerParam,
receiverParam,
yieldInIBTParam,
]

handleYieldClaimed(yieldClaimedEvent)
})

test("Should update claim yield in user portfolio", () => {
assert.fieldEquals(
ACCOUNT_ASSET_ENTITY,
generateAccountAssetId(
FIRST_USER_MOCK.toHex(),
`${FIRST_FUTURE_VAULT_ADDRESS_MOCK.toHex()}-claimed-yield`,
"claimed-"
),
"balance",
YIELD_USER_YIELD_IN_IBT_MOCK.toString()
)
})
})
1 change: 1 addition & 0 deletions src/utils/AssetType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class AssetType {
LP: string = "LP"
LP_VAULT_SHARES: string = "LP_VAULT_SHARES"
YIELD: string = "YIELD"
CLAIMED_YIELD: string = "CLAIMED_YIELD"
UNKNOWN: string = "UNKNOWN"
}

Expand Down
8 changes: 6 additions & 2 deletions src/utils/idGenerators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ export const generateAssetPriceId = (
// AccountAsset
export const generateAccountAssetId = (
accountAddress: string,
assetAddress: string
): string => `${accountAddress}-${assetAddress}`
assetAddress: string,
prefix: string = ""
): string => `${prefix}${accountAddress}-${assetAddress}`

// Fees
export const generateFeeClaimId = (
Expand All @@ -51,3 +52,6 @@ export const generateTransactionId = (

export const generateYieldAssetId = (principalToken: string): string =>
`${principalToken}-yield`

export const generateClaimedYieldAssetId = (principalToken: string): string =>
`${principalToken}-claimed-yield`

0 comments on commit 48a2fea

Please sign in to comment.