UNPKG

liquidops

Version:

LiquidOps is an over-collateralised lending and borrowing protocol built on Arweave's L2 AO.

129 lines (113 loc) 3.38 kB
import { AoUtils, connectToAO } from "../../ao/utils/connect"; import { getTags } from "../../arweave/getTags"; import { getTransactions, Transaction, } from "../getTransactions/getTransactions"; import { GQLTransactionsResultInterface } from "ar-gql/dist/faces"; export interface GetEarnings { walletAddress: string; token: string; collateralization?: bigint; } export interface GetEarningsRes { base: bigint; profit: bigint; startDate?: number; } export async function getEarnings( aoUtilsInput: Pick<AoUtils, "signer" | "configs">, { walletAddress, token, collateralization }: GetEarnings, ): Promise<GetEarningsRes> { if (!walletAddress || !token) { throw new Error("Please specify a token and a wallet address"); } const { spawn, message, result } = await connectToAO(aoUtilsInput.configs); const aoUtils: AoUtils = { spawn, message, result, signer: aoUtilsInput.signer, configs: aoUtilsInput.configs, }; if (!collateralization || collateralization === BigInt(0)) { return { base: BigInt(0), profit: BigInt(0), }; } // get lends and unlends const [lends, unlends] = await Promise.all([ getTransactions(aoUtils, { token, action: "lend", walletAddress, }), getTransactions(aoUtils, { token, action: "unLend", walletAddress, }), ]); // get lend and unlend confirmations const [lendConfirmations, unlendConfirmations] = await Promise.all([ getTags({ aoUtils, tags: [ { name: "Action", values: "Mint-Confirmation" }, { name: "Pushed-For", values: lends.transactions.map((t) => t.id) }, ], cursor: "", }), getTags({ aoUtils, tags: [ { name: "Action", values: "Redeem-Confirmation" }, { name: "Pushed-For", values: unlends.transactions.map((t) => t.id) }, ], cursor: "", }), ]); // reducer function for a list of lends/unlends based on a // list of mint/redeem confirmations // it adds together the quantities if they have a confirmation const sumIfSuccessfull = (confirmations: GQLTransactionsResultInterface) => { return (prev: bigint, curr: Transaction) => { // check if it was a successfull interaction (received confirmation) if ( !confirmations.edges.find( (tx) => tx.node.tags.find((t) => t.name === "Pushed-For")?.value === curr.id, ) ) { return prev; } // add together return prev + BigInt(curr.tags.Quantity || 0); }; }; // deposited tokens (sum of successfull lends) const sumDeposited = lends.transactions.reduce( sumIfSuccessfull(lendConfirmations), BigInt(0), ); // withdrawn tokens (sum of successfull burns) const sumWithdrawn = unlends.transactions.reduce( sumIfSuccessfull(unlendConfirmations), BigInt(0), ); // the result of the total deposited and total withdrawn tokens // is the amount of tokens that the user has in the pool, that // they have deposited (without the interest!!) const base = sumDeposited - sumWithdrawn; // the first mint date const startDate = lendConfirmations?.edges?.[lendConfirmations?.edges?.length - 1 || 0]?.node ?.block?.timestamp; return { base, profit: collateralization - base, startDate, }; }