rspace-online/modules/rwallet/lib/yield-protocols.ts

177 lines
5.7 KiB
TypeScript

/**
* Yield protocol constants — contract addresses, function selectors, and types
* for Aave V3 and Morpho Blue vault integrations.
*/
// ── Supported chains for yield ──
export type SupportedYieldChain = "1" | "8453";
export type YieldProtocol = "aave-v3" | "morpho-blue";
export type StablecoinSymbol = "USDC" | "USDT" | "DAI";
export interface YieldOpportunity {
protocol: YieldProtocol;
chainId: SupportedYieldChain;
asset: StablecoinSymbol;
assetAddress: string;
vaultAddress: string; // aToken for Aave, vault for Morpho
apy: number;
apy7d?: number;
apy30d?: number;
apyBase?: number;
tvl?: number;
poolId?: string; // DeFi Llama pool ID
vaultName?: string;
}
export interface YieldPosition {
protocol: YieldProtocol;
chainId: SupportedYieldChain;
asset: StablecoinSymbol;
assetAddress: string;
vaultAddress: string;
shares: string; // raw shares/aToken balance
underlying: string; // underlying asset value
decimals: number;
apy: number;
dailyEarnings: number;
annualEarnings: number;
}
export interface YieldSuggestion {
type: "deposit" | "rebalance";
priority: "high" | "medium" | "low";
from?: { protocol: YieldProtocol; chainId: SupportedYieldChain; vaultAddress: string; apy: number };
to: YieldOpportunity;
amount: string;
amountUSD: number;
reason: string;
estimatedGasCostUSD: number;
}
// ── Stablecoin addresses per chain ──
export const STABLECOIN_ADDRESSES: Record<SupportedYieldChain, Record<StablecoinSymbol, string>> = {
"1": {
USDC: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
USDT: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
DAI: "0x6B175474E89094C44Da98b954EedeAC495271d0F",
},
"8453": {
USDC: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
USDT: "0x0000000000000000000000000000000000000000", // not on Base
DAI: "0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb",
},
};
export const STABLECOIN_DECIMALS: Record<StablecoinSymbol, number> = {
USDC: 6,
USDT: 6,
DAI: 18,
};
// ── Aave V3 ──
export const AAVE_V3_POOL: Record<SupportedYieldChain, string> = {
"1": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2",
"8453": "0xA238Dd80C259a72e81d7e4664a9801593F98d1c5",
};
// aToken addresses (receipt tokens for deposits)
export const AAVE_ATOKENS: Record<SupportedYieldChain, Partial<Record<StablecoinSymbol, string>>> = {
"1": {
USDC: "0x98C23E9d8f34FEFb1B7BD6a91B7FF122F4e16F5c",
USDT: "0x23878914EFE38d27C4D67Ab83ed1b93A74D4086a",
DAI: "0x018008bfb33d285247A21d44E50697654f754e63",
},
"8453": {
USDC: "0x4e65fE4DbA92790696d040ac24Aa414708F5c0AB",
DAI: "0x0a1d576f3eFeF75b330424287a95A366e8281D54",
},
};
// ── Morpho Blue Vaults ──
export interface MorphoVaultInfo {
address: string;
name: string;
asset: StablecoinSymbol;
}
export const MORPHO_VAULTS: Record<SupportedYieldChain, MorphoVaultInfo[]> = {
"1": [
{ address: "0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB", name: "Steakhouse USDC", asset: "USDC" },
{ address: "0x2371e134e3455e0593363cBF89d3b6cf53740618", name: "Steakhouse USDT", asset: "USDT" },
],
"8453": [
{ address: "0xc1256Ae5FF1cf2719D4937adb3bbCCab2E00A2Ca", name: "Moonwell Flagship USDC", asset: "USDC" },
],
};
// ── MultiSend (for batched approve+deposit) ──
export const MULTISEND_CALL_ONLY: Record<SupportedYieldChain, string> = {
"1": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D",
"8453": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D",
};
// ── Function selectors ──
export const SELECTORS = {
// ERC-20
approve: "0x095ea7b3", // approve(address,uint256)
balanceOf: "0x70a08231", // balanceOf(address)
// Aave V3 Pool
supply: "0x617ba037", // supply(address,uint256,address,uint16)
withdraw: "0x69328dec", // withdraw(address,uint256,address)
getReserveData: "0x35ea6a75", // getReserveData(address)
// ERC-4626 (Morpho vaults)
deposit: "0x6e553f65", // deposit(uint256,address)
redeem: "0xba087652", // redeem(uint256,address,address)
convertToAssets: "0x07a2d13a", // convertToAssets(uint256)
maxDeposit: "0x402d267d", // maxDeposit(address)
// MultiSend
multiSend: "0x8d80ff0a", // multiSend(bytes)
} as const;
// ── ABI encoding helpers ──
export function padAddress(addr: string): string {
return addr.slice(2).toLowerCase().padStart(64, "0");
}
export function padUint256(value: bigint): string {
return value.toString(16).padStart(64, "0");
}
export function encodeApprove(spender: string, amount: bigint): string {
return `${SELECTORS.approve}${padAddress(spender)}${padUint256(amount)}`;
}
export function encodeAaveSupply(asset: string, amount: bigint, onBehalfOf: string): string {
return `${SELECTORS.supply}${padAddress(asset)}${padUint256(amount)}${padAddress(onBehalfOf)}${padUint256(0n)}`;
}
export function encodeAaveWithdraw(asset: string, amount: bigint, to: string): string {
return `${SELECTORS.withdraw}${padAddress(asset)}${padUint256(amount)}${padAddress(to)}`;
}
export function encodeMorphoDeposit(amount: bigint, receiver: string): string {
return `${SELECTORS.deposit}${padUint256(amount)}${padAddress(receiver)}`;
}
export function encodeMorphoRedeem(shares: bigint, receiver: string, owner: string): string {
return `${SELECTORS.redeem}${padUint256(shares)}${padAddress(receiver)}${padAddress(owner)}`;
}
export function encodeBalanceOf(address: string): string {
return `${SELECTORS.balanceOf}${padAddress(address)}`;
}
export function encodeConvertToAssets(shares: bigint): string {
return `${SELECTORS.convertToAssets}${padUint256(shares)}`;
}
export function encodeMaxDeposit(receiver: string): string {
return `${SELECTORS.maxDeposit}${padAddress(receiver)}`;
}
// ── Chain display names ──
export const YIELD_CHAIN_NAMES: Record<SupportedYieldChain, string> = {
"1": "Ethereum",
"8453": "Base",
};