Skip to content

Commit 9a078a3

Browse files
committed
feat: add makina adapter
1 parent 4ece7f6 commit 9a078a3

2 files changed

Lines changed: 177 additions & 0 deletions

File tree

src/adaptors/makina/index.ts

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/**
2+
* Makina Protocol
3+
*
4+
* DeFiLlama slug: makina
5+
* DefiLlama page: https://defillama.com/protocol/makina
6+
* App: https://makina.finance/
7+
* API Docs: https://api.makina.finance/v1/docs
8+
* Protocol docs: https://docs.makina.finance/
9+
*/
10+
11+
const utils = require('../utils');
12+
13+
import { Pool } from '../../types/Pool';
14+
import { MakinaStrategiesResponse } from './types';
15+
16+
const PROJECT = 'makina';
17+
18+
// API Docs: https://api.makina.finance/v1/docs
19+
const API_BASE_URL = 'https://api.makina.finance/v1';
20+
21+
const CHAIN_ID_TO_CHAIN_KEY = {
22+
1: 'ethereum',
23+
143: 'monad',
24+
999: 'hyperevm',
25+
8453: 'base',
26+
42161: 'arbitrum',
27+
43114: 'avalanche',
28+
57073: 'ink',
29+
};
30+
31+
const ENDPOINTS = {
32+
GET_STRATEGIES: `${API_BASE_URL}/strategies`,
33+
};
34+
35+
const apy = async () => {
36+
const response = await utils.getData(ENDPOINTS.GET_STRATEGIES);
37+
const strategies: MakinaStrategiesResponse['data'] = response.data;
38+
39+
const apys: Pool[] = [];
40+
41+
const supportedStrategies = strategies.strategies.filter((s) => {
42+
return (
43+
CHAIN_ID_TO_CHAIN_KEY[s.accountingToken.chainId] &&
44+
CHAIN_ID_TO_CHAIN_KEY[s.hubChainId]
45+
);
46+
});
47+
48+
const priceKeys = [
49+
...new Set(
50+
supportedStrategies.map(
51+
(s) =>
52+
`${CHAIN_ID_TO_CHAIN_KEY[s.accountingToken.chainId]}:${
53+
s.accountingToken.address
54+
}`
55+
)
56+
),
57+
];
58+
const { pricesByAddress } = await utils.getPrices(priceKeys, null);
59+
60+
for (const strategy of supportedStrategies) {
61+
const { aum, accountingToken, sharePrice } = strategy;
62+
63+
const price = pricesByAddress[accountingToken.address.toLowerCase()];
64+
// `aum` is denominated in the accounting token's base units.
65+
const aumBaseUnits = BigInt(aum);
66+
const scale = 10n ** BigInt(accountingToken.decimals);
67+
const whole = aumBaseUnits / scale;
68+
const fraction = aumBaseUnits % scale;
69+
const aumInTokens = Number(whole) + Number(fraction) / Number(scale);
70+
71+
if (price == null) continue;
72+
const tvlUsd = aumInTokens * price;
73+
74+
apys.push({
75+
pool: `makina-${strategy.address}-${
76+
CHAIN_ID_TO_CHAIN_KEY[strategy.hubChainId]
77+
}`,
78+
chain: utils.formatChain(CHAIN_ID_TO_CHAIN_KEY[strategy.hubChainId]),
79+
project: PROJECT,
80+
symbol: strategy.shareToken.symbol,
81+
token: strategy.shareToken.address,
82+
underlyingTokens: [accountingToken.address],
83+
apyBase: strategy.apy7d != null ? strategy.apy7d * 100 : null,
84+
pricePerShare: sharePrice, // underlying assets per share (e.g. ERC-4626 convertToAssets / 1 share); NOT a USD price. Omit when not applicable.
85+
tvlUsd,
86+
url: `https://makina.finance/strategy/${strategy.address}`,
87+
});
88+
}
89+
90+
return apys;
91+
};
92+
93+
module.exports = {
94+
protocolId: '6964',
95+
timetravel: false,
96+
apy: apy,
97+
url: 'https://makina.finance/explore',
98+
};

src/adaptors/makina/types.ts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
export interface Token {
2+
/**
3+
* Token contract address
4+
* @example "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
5+
*/
6+
address: string;
7+
/**
8+
* Chain ID
9+
* @example 1
10+
*/
11+
chainId: number;
12+
/**
13+
* Token name
14+
* @example "USD Coin"
15+
*/
16+
name: string;
17+
/**
18+
* Token symbol
19+
* @example "USDC"
20+
*/
21+
symbol: string;
22+
/**
23+
* Token decimals
24+
* @example 6
25+
*/
26+
decimals: number;
27+
}
28+
29+
export type MakinaStrategiesResponse = {
30+
data: {
31+
strategies: Array<{
32+
slug: string | null;
33+
address: string;
34+
hubChainId: number;
35+
name: string;
36+
logoURI: string | null;
37+
38+
/**
39+
* 7-day average annualized yield
40+
* @example 0.0829
41+
*/
42+
apy7d: number | null;
43+
44+
/**
45+
* 30-day average annualized yield
46+
* @example 0.0477
47+
*/
48+
apy30d: number | null;
49+
50+
shareToken: Token;
51+
accountingToken: Token;
52+
depositToken: Token;
53+
54+
/**
55+
* Live total value of all assets in the accounting token base units. Equals `lastReportedAum` adjusted for any deposits/redeems indexed after `lastReportedAumBlock`.
56+
* @example "15333281570441"
57+
*/
58+
aum: string;
59+
60+
/**
61+
* The most recent on-chain reported AUM (from the latest TotalAumUpdated event), in the accounting token base units.
62+
* @example "15333281570441"
63+
*/
64+
lastReportedAum: string;
65+
66+
/**
67+
* Block number at which `lastReportedAum` was reported on-chain.
68+
* @example "23000000"
69+
*/
70+
lastReportedAumBlock: string;
71+
72+
/**
73+
* The price per share, expressed in accounting tokens per share (human-readable, de-scaled by the accounting token's decimals).
74+
* @example 1.020766
75+
*/
76+
sharePrice: number;
77+
}>;
78+
};
79+
};

0 commit comments

Comments
 (0)