Skip to content

Commit ab51389

Browse files
committed
feat: add LOAN Protocol adapter for DefiLlama
1 parent 8e0b896 commit ab51389

File tree

2 files changed

+112
-0
lines changed

2 files changed

+112
-0
lines changed

projects/ithaca/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,4 @@ module.exports = {
2424
}),
2525
}
2626
};
27+

projects/loan-protocol/index.js

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
const { post } = require('../helper/http');
2+
const sdk = require('@defillama/sdk');
3+
4+
const tokenMapping = {
5+
'xtokens:XBTC': 'bitcoin',
6+
'xtokens:XLTC': 'litecoin',
7+
'xtokens:XETH': 'ethereum',
8+
'xtokens:XXRP': 'ripple',
9+
'eosio.token:XPR': 'proton',
10+
'xtokens:XMT': 'metal',
11+
'xtokens:XUST': 'terrausd-wormhole', // optional/legacy
12+
'xtokens:XLUNA': 'terra-luna-2', // optional/legacy
13+
'xtokens:XUSDC': 'usd-coin',
14+
'xtokens:XDOGE': 'dogecoin',
15+
'xtokens:XUSDT': 'tether',
16+
};
17+
18+
const API_ENDPOINT = 'https://proton.eosusa.io';
19+
const LENDING_CONTRACT = 'lending.loan';
20+
21+
function parseAsset(assetString) {
22+
if (!assetString) return { amount: 0, symbol: '' };
23+
const [amount, symbol] = assetString.split(' ');
24+
return { amount: parseFloat(amount), symbol };
25+
}
26+
27+
async function fetchMarkets() {
28+
const res = await post(`${API_ENDPOINT}/v1/chain/get_table_rows`, {
29+
code: LENDING_CONTRACT,
30+
scope: LENDING_CONTRACT,
31+
table: 'markets',
32+
limit: 100,
33+
json: true,
34+
});
35+
return res.rows || [];
36+
}
37+
38+
async function fetchLiquidity(tokenContract, symbol) {
39+
const res = await post(`${API_ENDPOINT}/v1/chain/get_table_rows`, {
40+
code: tokenContract,
41+
scope: LENDING_CONTRACT,
42+
table: 'accounts',
43+
limit: 100,
44+
json: true,
45+
});
46+
const rows = res.rows || [];
47+
const tokenBalance = rows.find(b => parseAsset(b.balance).symbol === symbol);
48+
return tokenBalance ? parseAsset(tokenBalance.balance).amount : 0;
49+
}
50+
51+
// ----------------------------
52+
// TVL = borrows + cash reserves
53+
// ----------------------------
54+
async function tvl() {
55+
const balances = {};
56+
const markets = await fetchMarkets();
57+
58+
const promises = markets.map(async (market) => {
59+
const totalVar = parseAsset(market.total_variable_borrows.quantity).amount;
60+
const totalStable = parseAsset(market.total_stable_borrows.quantity).amount;
61+
const totalBorrows = totalVar + totalStable;
62+
63+
const [ , symbol ] = market.underlying_symbol.sym.split(',');
64+
const tokenContract = market.underlying_symbol.contract;
65+
66+
// liquidity available in lending contract
67+
const cashAvailable = await fetchLiquidity(tokenContract, symbol);
68+
const totalSupplied = totalBorrows + cashAvailable;
69+
70+
const internalId = `${tokenContract}:${symbol}`;
71+
const cgkId = tokenMapping[internalId];
72+
if (!cgkId) return;
73+
74+
sdk.util.sumSingleBalance(balances, `coingecko:${cgkId}`, totalSupplied);
75+
});
76+
77+
await Promise.all(promises);
78+
return balances;
79+
}
80+
81+
// ----------------------------
82+
// Borrowed = borrows only
83+
// ----------------------------
84+
async function borrowed() {
85+
const balances = {};
86+
const markets = await fetchMarkets();
87+
88+
markets.forEach(market => {
89+
const totalVar = parseAsset(market.total_variable_borrows.quantity).amount;
90+
const totalStable = parseAsset(market.total_stable_borrows.quantity).amount;
91+
const totalBorrows = totalVar + totalStable;
92+
93+
const [ , symbol ] = market.underlying_symbol.sym.split(',');
94+
const tokenContract = market.underlying_symbol.contract;
95+
const internalId = `${tokenContract}:${symbol}`;
96+
const cgkId = tokenMapping[internalId];
97+
if (!cgkId) return;
98+
99+
sdk.util.sumSingleBalance(balances, `coingecko:${cgkId}`, totalBorrows);
100+
});
101+
102+
return balances;
103+
}
104+
105+
module.exports = {
106+
methodology: 'TVL = variable borrows + stable borrows + available liquidity in lending.loan. Borrowed = total outstanding borrows (variable + stable). Mapping is to CoinGecko IDs.',
107+
proton: {
108+
tvl,
109+
borrowed,
110+
}
111+
};

0 commit comments

Comments
 (0)