-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Refactor processing and fix caching and fix tests * Clean up processor and add tests and mocks * Clean up types * Add cashflow report and tests * Remove defer and use querywith poolid * Refactor tests and add comments * Add query for metadata and utils around it * Add data for pool fee snapshots and use in cashflow statments * Group tranche data by id to prevent double processing * fix zero case in fromFloat wrapper * Prevent fees and endCashBalance from being aggregated * Add fee snapshot mocks and improve fee testing * Add a few more fee test * Differentiate public and private credit for cashflows * Remove identifying info * Fix data aggregation and improve test coverage with real data * Add code coverage support * Add coverage summary * Exclude types from coverage * And P&L report and processor tests * Add tests for applyGrouping * Add readme for reports * Add test to applyGrouping * Fix test * Fix BigInt tests * Clean up metadata fetching * Remove cache time * Remove filtering in keys * Fix import so that decimal.js-light works in browser and test env * Update README.md Co-authored-by: Jeroen <1748621+hieronx@users.noreply.github.com> * Update README.md Co-authored-by: Jeroen <1748621+hieronx@users.noreply.github.com> * Use purchases and financings instead of acquisistions * Remove coverage in favor of nyc in ci PR * Remove c8 config * Restore sinon stub to fix error * Add fix to P&L report * Add investor tx data and report * Provide access to P&L * Add tests * Add filters and tests to investor transaction report * Add more test cases * Test investor report generation * Optimize processing * Add asset transaction report * Fix typo * Rename so it doesn't appear as main README in repo * Fix asset transaction filtering * Add fee transactions report * Make filtering more efficient * Add token price report * Move types for reports so they're excluded from coverage * Convert date to UTC to prevent timezone bugs in grouping * Fix filtering by type for fee transactions * Improve test coverage and fix some filtering bugs * Remove log and comment * More test coverage improvements * Move indexer querying into separate class * Add asset list report * Add tests for asset list * Add investor list report * ci: fix issue with pr_number check * ci: fix release script logic * ci: debugging pr-check script * ci: final fix for PR checks on release events * [bot] New pkg version: 0.0.0-alpha.3 * ci: final cleanup --------- Co-authored-by: Jeroen <1748621+hieronx@users.noreply.github.com> Co-authored-by: Guillermo Perez <gpmayorga@users.noreply.github.com> Co-authored-by: GitHub Actions <actions@github.com>
- Loading branch information
1 parent
a9f0527
commit 7d2f6c0
Showing
26 changed files
with
2,354 additions
and
168 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
import { Currency, Rate } from '../utils/BigInt.js' | ||
|
||
export type AssetSnapshotFilter = Partial<Record<keyof SubqueryAssetSnapshots['assetSnapshots']['nodes'][0], any>> | ||
|
||
export type AssetSnapshot = { | ||
actualMaturityDate: string | undefined | ||
actualOriginationDate: number | undefined | ||
advanceRate: Rate | undefined | ||
assetId: string | ||
collateralValue: Currency | undefined | ||
currentPrice: Currency | undefined | ||
discountRate: Rate | undefined | ||
faceValue: Currency | undefined | ||
lossGivenDefault: Rate | undefined | ||
name: string | ||
outstandingDebt: Currency | undefined | ||
outstandingInterest: Currency | undefined | ||
outstandingPrincipal: Currency | undefined | ||
outstandingQuantity: Currency | undefined | ||
presentValue: Currency | undefined | ||
probabilityOfDefault: Rate | undefined | ||
status: string | ||
sumRealizedProfitFifo: Currency | undefined | ||
timestamp: string | ||
totalRepaidInterest: Currency | undefined | ||
totalRepaidPrincipal: Currency | undefined | ||
totalRepaidUnscheduled: Currency | undefined | ||
unrealizedProfitAtMarketPrice: Currency | undefined | ||
valuationMethod: string | undefined | ||
} | ||
|
||
export type SubqueryAssetSnapshots = { | ||
assetSnapshots: { | ||
nodes: { | ||
asset: { | ||
pool: { | ||
currency: { | ||
decimals: number | ||
} | ||
} | ||
actualOriginationDate: number | ||
advanceRate: string | undefined | ||
collateralValue: string | undefined | ||
discountRate: string | undefined | ||
id: string | ||
lossGivenDefault: string | undefined | ||
actualMaturityDate: string | undefined | ||
name: string | ||
probabilityOfDefault: string | undefined | ||
status: string | ||
sumRealizedProfitFifo: string | undefined | ||
unrealizedProfitAtMarketPrice: string | undefined | ||
valuationMethod: string | ||
notional: string | undefined | ||
} | ||
timestamp: string | ||
assetId: string | ||
presentValue: string | undefined | ||
currentPrice: string | undefined | ||
outstandingPrincipal: string | undefined | ||
outstandingInterest: string | undefined | ||
outstandingDebt: string | undefined | ||
outstandingQuantity: string | undefined | ||
totalRepaidPrincipal: string | undefined | ||
totalRepaidInterest: string | undefined | ||
totalRepaidUnscheduled: string | undefined | ||
}[] | ||
} | ||
} | ||
|
||
export const assetSnapshotsPostProcess = (data: SubqueryAssetSnapshots): AssetSnapshot[] => { | ||
return data!.assetSnapshots.nodes.map((tx) => { | ||
const currencyDecimals = tx.asset.pool.currency.decimals | ||
return { | ||
...tx, | ||
timestamp: tx.timestamp, | ||
assetId: tx.assetId, | ||
actualMaturityDate: tx.asset.actualMaturityDate || undefined, | ||
actualOriginationDate: tx.asset.actualOriginationDate || undefined, | ||
advanceRate: new Rate(tx.asset.advanceRate || '0'), | ||
collateralValue: tx.asset?.collateralValue | ||
? new Currency(tx.asset?.collateralValue, currencyDecimals) | ||
: undefined, | ||
currentPrice: tx.currentPrice ? new Currency(tx.currentPrice, currencyDecimals).mul(10n ** 18n) : undefined, | ||
discountRate: tx.asset.discountRate ? new Rate(tx.asset.discountRate) : undefined, | ||
faceValue: | ||
tx.asset.notional && tx.outstandingQuantity | ||
? new Currency(tx.asset.notional, currencyDecimals).mul(BigInt(tx.outstandingQuantity)) | ||
: undefined, | ||
lossGivenDefault: tx.asset.lossGivenDefault ? new Rate(tx.asset.lossGivenDefault) : undefined, | ||
name: tx.asset.name, | ||
outstandingDebt: tx.outstandingDebt ? new Currency(tx.outstandingDebt, currencyDecimals) : undefined, | ||
outstandingInterest: tx.outstandingInterest ? new Currency(tx.outstandingInterest, currencyDecimals) : undefined, | ||
outstandingPrincipal: tx.outstandingPrincipal | ||
? new Currency(tx.outstandingPrincipal, currencyDecimals) | ||
: undefined, | ||
outstandingQuantity: tx.outstandingQuantity ? new Currency(tx.outstandingQuantity, 18) : undefined, | ||
presentValue: tx.presentValue ? new Currency(tx.presentValue, currencyDecimals) : undefined, | ||
probabilityOfDefault: tx.asset.probabilityOfDefault ? new Rate(tx.asset.probabilityOfDefault) : undefined, | ||
status: tx.asset.status, | ||
sumRealizedProfitFifo: tx.asset.sumRealizedProfitFifo | ||
? new Currency(tx.asset.sumRealizedProfitFifo, currencyDecimals) | ||
: undefined, | ||
totalRepaidInterest: tx.totalRepaidInterest ? new Currency(tx.totalRepaidInterest, currencyDecimals) : undefined, | ||
totalRepaidPrincipal: tx.totalRepaidPrincipal | ||
? new Currency(tx.totalRepaidPrincipal, currencyDecimals) | ||
: undefined, | ||
totalRepaidUnscheduled: tx.totalRepaidUnscheduled | ||
? new Currency(tx.totalRepaidUnscheduled, currencyDecimals) | ||
: undefined, | ||
unrealizedProfitAtMarketPrice: tx.asset.unrealizedProfitAtMarketPrice | ||
? new Currency(tx.asset.unrealizedProfitAtMarketPrice, currencyDecimals) | ||
: undefined, | ||
valuationMethod: tx.asset.valuationMethod, | ||
} | ||
}) satisfies AssetSnapshot[] | ||
} | ||
|
||
export const assetSnapshotsQuery = ` | ||
query($filter: AssetSnapshotFilter) { | ||
assetSnapshots( | ||
first: 1000, | ||
orderBy: TIMESTAMP_ASC, | ||
filter: $filter | ||
) { | ||
nodes { | ||
assetId | ||
timestamp | ||
totalRepaidUnscheduled | ||
outstandingInterest | ||
totalRepaidInterest | ||
currentPrice | ||
outstandingPrincipal | ||
totalRepaidPrincipal | ||
outstandingQuantity | ||
presentValue | ||
outstandingDebt | ||
asset { | ||
pool { | ||
currency { | ||
decimals | ||
} | ||
} | ||
actualMaturityDate | ||
actualOriginationDate | ||
advanceRate | ||
collateralValue | ||
discountRate | ||
lossGivenDefault | ||
name | ||
notional | ||
probabilityOfDefault | ||
status | ||
sumRealizedProfitFifo | ||
unrealizedProfitAtMarketPrice | ||
valuationMethod | ||
} | ||
} | ||
} | ||
} | ||
` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
import { Currency, Price } from '../utils/BigInt.js' | ||
|
||
export type AssetTransactionFilter = Partial< | ||
Record<keyof SubqueryAssetTransactions['assetTransactions']['nodes'][0], any> | ||
> | ||
|
||
export type AssetTransaction = { | ||
id: string | ||
timestamp: Date | ||
poolId: string | ||
accountId: string | ||
epochId: string | ||
type: AssetTransactionType | ||
amount: Currency | ||
settlementPrice: Price | null | ||
quantity: string | null | ||
principalAmount: Currency | undefined | ||
interestAmount: Currency | undefined | ||
hash: string | ||
realizedProfitFifo: Currency | undefined | ||
unrealizedProfitAtMarketPrice: Currency | undefined | ||
asset: { | ||
id: string | ||
metadata: string | ||
type: AssetType | ||
currentPrice: string | null | ||
} | ||
fromAsset?: { | ||
id: string | ||
metadata: string | ||
type: AssetType | ||
} | ||
toAsset?: { | ||
id: string | ||
metadata: string | ||
type: AssetType | ||
} | ||
} | ||
|
||
export enum AssetType { | ||
OnchainCash = 'OnchainCash', | ||
OffchainCash = 'OffchainCash', | ||
Other = 'Other', | ||
} | ||
|
||
export type AssetTransactionType = | ||
| 'CREATED' | ||
| 'PRICED' | ||
| 'BORROWED' | ||
| 'REPAID' | ||
| 'CLOSED' | ||
| 'CASH_TRANSFER' | ||
| 'DEPOSIT_FROM_INVESTMENTS' | ||
| 'WITHDRAWAL_FOR_REDEMPTIONS' | ||
| 'WITHDRAWAL_FOR_FEES' | ||
| 'INCREASE_DEBT' | ||
| 'DECREASE_DEBT' | ||
|
||
type SubqueryAssetTransactions = { | ||
assetTransactions: { | ||
nodes: { | ||
__typename?: 'AssetTransaction' | ||
id: string | ||
timestamp: string | ||
poolId: string | ||
accountId: string | ||
hash: string | ||
epochId: string | ||
type: AssetTransactionType | ||
amount: string | undefined | ||
principalAmount: string | undefined | ||
interestAmount: string | undefined | ||
settlementPrice: string | null | ||
quantity: string | null | ||
realizedProfitFifo: string | undefined | ||
pool: { | ||
currency: { | ||
decimals: number | ||
} | ||
} | ||
asset: { | ||
id: string | ||
metadata: string | ||
name: string | ||
type: AssetType | ||
sumRealizedProfitFifo: string | ||
unrealizedProfitAtMarketPrice: string | ||
currentPrice: string | ||
} | ||
fromAsset?: { | ||
id: string | ||
metadata: string | ||
name: string | ||
type: AssetType | ||
} | ||
toAsset?: { | ||
id: string | ||
metadata: string | ||
name: string | ||
type: AssetType | ||
} | ||
}[] | ||
} | ||
} | ||
|
||
export const assetTransactionsPostProcess = (data: SubqueryAssetTransactions): AssetTransaction[] => { | ||
return ( | ||
data.assetTransactions.nodes.map((tx) => { | ||
const decimals = tx.pool.currency.decimals | ||
return { | ||
...tx, | ||
settlementPrice: tx.settlementPrice ? new Price(tx.settlementPrice) : null, | ||
amount: new Currency(tx?.amount ?? 0n, decimals), | ||
principalAmount: tx.principalAmount ? new Currency(tx.principalAmount, decimals) : undefined, | ||
interestAmount: tx.interestAmount ? new Currency(tx.interestAmount, decimals) : undefined, | ||
realizedProfitFifo: tx.realizedProfitFifo ? new Currency(tx.realizedProfitFifo, decimals) : undefined, | ||
sumRealizedProfitFifo: tx.asset.sumRealizedProfitFifo | ||
? new Currency(tx.asset.sumRealizedProfitFifo, decimals) | ||
: undefined, | ||
unrealizedProfitAtMarketPrice: tx.asset.unrealizedProfitAtMarketPrice | ||
? new Currency(tx.asset.unrealizedProfitAtMarketPrice, decimals) | ||
: undefined, | ||
timestamp: new Date(`${tx.timestamp}+00:00`), | ||
} | ||
}) || ([] satisfies AssetTransaction[]) | ||
) | ||
} | ||
|
||
export const assetTransactionsQuery = ` | ||
query($filter: AssetTransactionFilter) { | ||
assetTransactions( | ||
orderBy: TIMESTAMP_ASC, | ||
filter: $filter | ||
) { | ||
nodes { | ||
principalAmount | ||
interestAmount | ||
epochId | ||
type | ||
timestamp | ||
amount | ||
settlementPrice | ||
quantity | ||
hash | ||
realizedProfitFifo | ||
pool { | ||
currency { | ||
decimals | ||
} | ||
} | ||
asset { | ||
id | ||
metadata | ||
name | ||
type | ||
sumRealizedProfitFifo | ||
unrealizedProfitAtMarketPrice | ||
} | ||
fromAsset { | ||
id | ||
metadata | ||
name | ||
type | ||
} | ||
toAsset { | ||
id | ||
metadata | ||
name | ||
type | ||
} | ||
} | ||
} | ||
} | ||
` |
Oops, something went wrong.