@moonwell-fi/moonwell-sdk
Version:
TypeScript Interface for Moonwell
156 lines (136 loc) • 4.42 kB
text/typescript
import { type Address, zeroAddress } from "viem";
import { Amount } from "../../../common/index.js";
import {
type Environment,
publicEnvironments,
} from "../../../environments/index.js";
import {
findMarketByAddress,
findTokenByAddress,
} from "../../../environments/utils/index.js";
import type { UserReward } from "../../../types/userReward.js";
export const getUserRewardsData = async (params: {
environment: Environment;
account: Address;
markets?: string[] | undefined;
}) => {
const homeEnvironment =
(Object.values(publicEnvironments) as Environment[]).find((e) =>
e.custom?.governance?.chainIds?.includes(params.environment.chainId),
) || params.environment;
const viewsContract = params.environment.contracts.views;
const homeViewsContract = homeEnvironment.contracts.views;
const userData = await Promise.all([
viewsContract?.read.getAllMarketsInfo(),
viewsContract?.read.getUserRewards([params.account]),
homeViewsContract?.read.getNativeTokenPrice(),
homeViewsContract?.read.getGovernanceTokenPrice(),
]);
const [
allMarkets,
userRewards,
nativeTokenPriceRaw,
governanceTokenPriceRaw,
] = userData;
const governanceTokenPrice = new Amount(governanceTokenPriceRaw || 0n, 18);
const nativeTokenPrice = new Amount(nativeTokenPriceRaw || 0n, 18);
let tokenPrices =
allMarkets
?.map((marketInfo) => {
const marketFound = findMarketByAddress(
params.environment,
marketInfo.market,
);
if (marketFound) {
return {
token: marketFound.underlyingToken,
tokenPrice: new Amount(
marketInfo.underlyingPrice,
36 - marketFound.underlyingToken.decimals,
),
};
} else {
return;
}
})
.filter((token) => !!token) || [];
// Add governance token to token prices
if (params.environment.custom?.governance?.token) {
tokenPrices = [
...tokenPrices,
{
token:
params.environment.config.tokens[
params.environment.custom.governance.token
]!,
tokenPrice: governanceTokenPrice,
},
];
}
// Add native token to token prices
tokenPrices = [
...tokenPrices,
{
token: findTokenByAddress(params.environment, zeroAddress)!,
tokenPrice: nativeTokenPrice,
},
];
const markets = (allMarkets || []).filter((r) =>
params.markets ? params.markets.includes(r.market) : true,
);
const rewards = markets.flatMap((marketInfo) => {
const market = findMarketByAddress(params.environment, marketInfo.market);
if (market) {
const marketRewards =
userRewards?.filter((r) => r.market === marketInfo.market) || [];
return marketRewards
.filter((reward) => {
const token = findTokenByAddress(
params.environment,
reward.rewardToken,
);
return token !== undefined;
})
.map((reward) => {
const token = findTokenByAddress(
params.environment,
reward.rewardToken,
)!;
const isGovernanceToken =
token.symbol === params.environment.custom?.governance?.token;
const isNativeToken = token.address === zeroAddress;
const tokenPrice = tokenPrices?.find(
(r) => r?.token.address === reward.rewardToken,
)?.tokenPrice.value;
const price =
(isNativeToken
? nativeTokenPrice.value
: isGovernanceToken
? governanceTokenPrice.value
: tokenPrice) || 0;
const supplyRewards = new Amount(
reward.supplyRewardsAmount,
token.decimals,
);
const borrowRewards = new Amount(
reward.borrowRewardsAmount,
token.decimals,
);
const result: UserReward = {
chainId: params.environment.chainId,
account: params.account,
market: market.marketToken,
rewardToken: token,
supplyRewards,
supplyRewardsUsd: supplyRewards.value * price,
borrowRewards,
borrowRewardsUsd: borrowRewards.value * price,
};
return result;
});
} else {
return [];
}
});
return rewards;
};