diff --git a/.changeset/rich-trees-hope.md b/.changeset/rich-trees-hope.md new file mode 100644 index 0000000..0476c90 --- /dev/null +++ b/.changeset/rich-trees-hope.md @@ -0,0 +1,5 @@ +--- +"@mangrovedao/mgv": patch +--- + +Added check for aave markets diff --git a/src/actions/kandel/aave.ts b/src/actions/kandel/aave.ts new file mode 100644 index 0000000..c29e1ee --- /dev/null +++ b/src/actions/kandel/aave.ts @@ -0,0 +1,114 @@ +import type { + Address, + Client, + MulticallParameters, + ReadContractParameters, +} from 'viem' +import { multicall, readContract } from 'viem/actions' +import { + type CheckAaveAssetParams, + type aaveRouterCheckAssetABI, + checkAaveAssetParams, +} from '../../builder/kandel/aave.js' +import type { BuiltArgs, MarketParams } from '../../index.js' +import { getAction } from '../../utils/getAction.js' + +type ReadSingleParams = ReadContractParameters< + typeof aaveRouterCheckAssetABI, + 'checkAsset' +> + +export type CheckAaveAssetArgs = CheckAaveAssetParams & + Omit + +export async function checkAaveAsset( + client: Client, + aaveRouter: Address, + args: CheckAaveAssetArgs, +): Promise { + return getAction( + client, + readContract, + 'readContract', + )({ + ...(args as unknown as ReadSingleParams), + address: aaveRouter, + ...checkAaveAssetParams(args), + }) +} + +export type CheckAaveAssetsArgs = { tokens: Address[] } & Omit< + MulticallParameters, + 'contracts' | 'allowFailure' +> + +export async function checkAaveAssets( + client: Client, + aaveRouter: Address, + args: CheckAaveAssetsArgs, +): Promise { + return getAction( + client, + multicall, + 'multicall', + )({ + ...args, + contracts: args.tokens.map((token) => ({ + address: aaveRouter, + ...checkAaveAssetParams({ token }), + })), + allowFailure: false, + }) +} + +export type CheckAaveMarketArgs = { market: MarketParams } & Omit< + MulticallParameters, + 'contracts' | 'allowFailure' +> + +export async function checkAaveMarket( + client: Client, + aaveRouter: Address, + args: CheckAaveMarketArgs, +): Promise { + const tokens = [args.market.base.address, args.market.quote.address] + const available = await checkAaveAssets(client, aaveRouter, { + ...args, + tokens, + }) + return available.every((a) => a) +} + +export type CheckAaveMarketsArgs = { markets: MarketParams[] } & Omit< + MulticallParameters, + 'contracts' | 'allowFailure' +> + +export async function checkAaveMarkets( + client: Client, + aaveRouter: Address, + args: CheckAaveMarketsArgs, +): Promise { + const tokens = [ + ...new Set( + args.markets.flatMap((m) => [ + m.base.address.toLowerCase() as Address, + m.quote.address.toLowerCase() as Address, + ]), + ), + ] + const available = await checkAaveAssets(client, aaveRouter, { + ...args, + tokens, + }) + const tokensMap = tokens.reduce((acc, token, i) => { + acc.set(token, available[i] || false) + return acc + }, new Map()) + + return args.markets.filter( + (m) => + tokensMap.get(m.base.address.toLowerCase() as Address) && + tokensMap.get(m.quote.address.toLowerCase() as Address), + ) +} diff --git a/src/builder/kandel/aave.ts b/src/builder/kandel/aave.ts new file mode 100644 index 0000000..ba7b675 --- /dev/null +++ b/src/builder/kandel/aave.ts @@ -0,0 +1,24 @@ +import { type Address, type ContractFunctionParameters, parseAbi } from 'viem' + +export type CheckAaveAssetParams = { + token: Address +} + +export const aaveRouterCheckAssetABI = parseAbi([ + 'function checkAsset(address token) public view returns (bool)', +]) + +export function checkAaveAssetParams(params: CheckAaveAssetParams) { + return { + abi: aaveRouterCheckAssetABI, + functionName: 'checkAsset', + args: [params.token], + } satisfies Omit< + ContractFunctionParameters< + typeof aaveRouterCheckAssetABI, + 'view', + 'checkAsset' + >, + 'address' + > +} diff --git a/src/bundle/index.ts b/src/bundle/index.ts index 6becc96..7296b89 100644 --- a/src/bundle/index.ts +++ b/src/bundle/index.ts @@ -5,6 +5,7 @@ export type { KandelActions, KandelSeederActions, UserRouterActions, + AaveKandelActions, } from './public/index.js' export { @@ -14,4 +15,5 @@ export { kandelActions, kandelSeederActions, userRouterActions, + aaveKandelActions, } from './public/index.js' diff --git a/src/bundle/public/index.ts b/src/bundle/public/index.ts index 8d46f07..71e2dfe 100644 --- a/src/bundle/public/index.ts +++ b/src/bundle/public/index.ts @@ -7,8 +7,10 @@ export { mangroveActions, type MangroveActions } from './mangrove-actions.js' export { kandelActions, kandelSeederActions, + aaveKandelActions, type KandelActions, type KandelSeederActions, + type AaveKandelActions, } from './kandel-actions.js' export { type UserRouterActions, diff --git a/src/bundle/public/kandel-actions.ts b/src/bundle/public/kandel-actions.ts index 38898b9..249a1c9 100644 --- a/src/bundle/public/kandel-actions.ts +++ b/src/bundle/public/kandel-actions.ts @@ -1,4 +1,14 @@ import { type Address, type Client, zeroAddress } from 'viem' +import { + type CheckAaveAssetArgs, + type CheckAaveAssetsArgs, + type CheckAaveMarketArgs, + type CheckAaveMarketsArgs, + checkAaveAsset, + checkAaveAssets, + checkAaveMarket, + checkAaveMarkets, +} from '../../actions/kandel/aave.js' import { type SetLogicsArgs, type SetLogicsResult, @@ -91,3 +101,19 @@ export function kandelActions( getKandelState(client, actionParams, market, kandel, args), }) } + +export type AaveKandelActions = { + checkAaveAsset: (args: CheckAaveAssetArgs) => Promise + checkAaveAssets: (args: CheckAaveAssetsArgs) => Promise + checkAaveMarket: (args: CheckAaveMarketArgs) => Promise + checkAaveMarkets: (args: CheckAaveMarketsArgs) => Promise +} + +export function aaveKandelActions(aaveRouter: Address) { + return (client: Client): AaveKandelActions => ({ + checkAaveAsset: (args) => checkAaveAsset(client, aaveRouter, args), + checkAaveAssets: (args) => checkAaveAssets(client, aaveRouter, args), + checkAaveMarket: (args) => checkAaveMarket(client, aaveRouter, args), + checkAaveMarkets: (args) => checkAaveMarkets(client, aaveRouter, args), + }) +} diff --git a/src/index.ts b/src/index.ts index eb432d3..9e24602 100644 --- a/src/index.ts +++ b/src/index.ts @@ -120,6 +120,7 @@ export type { KandelActions, KandelSeederActions, UserRouterActions, + AaveKandelActions, } from './bundle/index.js' export { @@ -129,6 +130,7 @@ export { kandelActions, kandelSeederActions, userRouterActions, + aaveKandelActions, } from './bundle/index.js' // --- addresses ---