Skip to content
Open
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
103 changes: 103 additions & 0 deletions fees/frankencoin/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { FetchOptions, SimpleAdapter } from '../../adapters/types';
import { CHAIN } from '../../helpers/chains';
import { request, gql } from 'graphql-request';

// GraphQL endpoint for Frankencoin
const FRANKENCOIN_GRAPH_URL = 'https://ponder.frankencoin.com';

// ZCHF token address on Ethereum
const ZCHF_ADDRESS = '0xB58E61C3098d85632Df34EecfB899A1Ed80921cB';

// query type
type RevenueQuery = {
chainId: number;
count: number;
created: number;
kind: string;
amount: bigint;
profits: bigint;
losses: bigint;
};

// fetch function
const fetch = async (options: FetchOptions) => {
const dailyFees = options.createBalances();
const dailyRevenue = options.createBalances();
const dailyProtocolRevenue = options.createBalances();
const dailySupplySideRevenue = options.createBalances();

const PROFIT_LOSS_QUERY = gql`
query {
frankencoinProfitLosss(
where: {
created_gt: "${options.startTimestamp}",
created_lte: "${options.endTimestamp}",
}
orderBy: "count",
orderDirection: "desc",
limit: 1000,
) {
items {
created
kind
amount
}
}
}
`;

const { frankencoinProfitLosss } = await request(
FRANKENCOIN_GRAPH_URL,
PROFIT_LOSS_QUERY
);

const entries: RevenueQuery[] = frankencoinProfitLosss.items;

const profits = entries.filter((e) => e.kind == 'Profit');
const losses = entries.filter((e) => e.kind == 'Loss');

// accumulate
const accumProfits = profits.reduce((a, b) => {
return a + BigInt(b.amount);
}, 0n);

const accumLosses = losses.reduce((a, b) => {
return a + BigInt(b.amount);
}, 0n);

// Fees are the total profits in ZCHF
dailyFees.add(ZCHF_ADDRESS, accumProfits);
dailyRevenue.add(ZCHF_ADDRESS, accumProfits);
dailyProtocolRevenue.add(ZCHF_ADDRESS, accumProfits);

// Interest paid by the protocol
dailySupplySideRevenue.add(ZCHF_ADDRESS, accumLosses);

return {
dailyFees,
dailyRevenue,
dailyProtocolRevenue,
dailySupplySideRevenue,
};
};

const adapter: SimpleAdapter = {
version: 2,
adapter: {
[CHAIN.ETHEREUM]: {
fetch,
start: '2023-10-28',
meta: {
methodology: {
Fees: 'Profits generated by the Frankencoin protocol (Frankencoin Pool Shares)',
Revenue: 'Net revenue is retained by the protocol',
ProtocolRevenue: 'Net revenue is retained by the protocol',
SupplySideRevenue:
'Losses absorbed by the protocol, such as interest paid to lenders, auction shortfalls, and similar costs',
},
},
},
},
};

export default adapter;
Loading