liquidops
Version:
LiquidOps is an over-collateralised lending and borrowing protocol built on Arweave's L2 AO.
129 lines (113 loc) • 3.38 kB
text/typescript
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,
};
}