Skip to content

Commit 326a01c

Browse files
committed
Add Doma Protocol TVL adapter
Doma is a DomainFi protocol enabling fractionalization of web3 domains on the Doma L2 (Chain ID: 97477). TVL tracks USDC.e balances in protocol contracts: - DomaFractionalization (diamond proxy) - DomaLaunchpad contracts - Associated Uniswap V3 pools Addresses discovered dynamically via Blockscout explorer API.
1 parent efacee7 commit 326a01c

File tree

3 files changed

+120
-0
lines changed

3 files changed

+120
-0
lines changed

projects/doma/index.js

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
const { get } = require('../helper/http')
2+
const { sumTokens2 } = require('../helper/unwrapLPs')
3+
4+
// VERIFIED ADDRESSES - 2024-11-27 via explorer.doma.xyz
5+
// USDC.e (Bridged USDC via Stargate) - 6 decimals
6+
// https://explorer.doma.xyz/token/0x31EEf89D5215C305304a2fA5376a1f1b6C5dc477
7+
const USDC_E_ADDRESS = '0x31EEf89D5215C305304a2fA5376a1f1b6C5dc477'
8+
9+
// Blockscout explorer API (public, no auth required)
10+
const EXPLORER_API = 'https://explorer.doma.xyz/api/v2'
11+
12+
// Protocol contract name patterns to identify TVL-relevant holders
13+
const PROTOCOL_CONTRACT_PATTERNS = [
14+
'UniswapV3Pool',
15+
'DomaFractionalization',
16+
'DomaLaunchpad',
17+
]
18+
19+
/**
20+
* Fetches all USDC.e token holders from Blockscout explorer
21+
* and filters to only verified protocol contracts
22+
*/
23+
async function fetchProtocolHolders() {
24+
const holders = []
25+
let nextPageParams = null
26+
27+
// Paginate through all holders
28+
do {
29+
let url = `${EXPLORER_API}/tokens/${USDC_E_ADDRESS}/holders`
30+
if (nextPageParams) {
31+
const params = new URLSearchParams(nextPageParams)
32+
url += `?${params.toString()}`
33+
}
34+
35+
const response = await get(url)
36+
37+
if (!response?.items) {
38+
throw new Error(`Invalid explorer response: ${JSON.stringify(response)}`)
39+
}
40+
41+
// Filter to only verified protocol contracts
42+
for (const holder of response.items) {
43+
const address = holder?.address
44+
if (!address) continue
45+
46+
// Skip non-contracts (EOAs)
47+
if (!address.is_contract) continue
48+
49+
// Skip unverified contracts for safety
50+
if (!address.is_verified) continue
51+
52+
// Check if contract name matches protocol patterns
53+
const contractName = address.name || ''
54+
const isProtocolContract = PROTOCOL_CONTRACT_PATTERNS.some(pattern =>
55+
contractName.includes(pattern)
56+
)
57+
58+
// Also check implementation names for proxy contracts
59+
const implementations = address.implementations || []
60+
const isProxyToProtocol = implementations.some(impl =>
61+
PROTOCOL_CONTRACT_PATTERNS.some(pattern =>
62+
(impl.name || '').includes(pattern)
63+
)
64+
)
65+
66+
if (isProtocolContract || isProxyToProtocol) {
67+
holders.push({
68+
address: address.hash,
69+
name: contractName,
70+
balance: holder.value,
71+
})
72+
}
73+
}
74+
75+
nextPageParams = response.next_page_params
76+
} while (nextPageParams)
77+
78+
return holders
79+
}
80+
81+
async function tvl(api) {
82+
const protocolHolders = await fetchProtocolHolders()
83+
84+
if (protocolHolders.length === 0) {
85+
console.warn('No protocol contracts found holding USDC.e - TVL will be empty')
86+
return {}
87+
}
88+
89+
console.log(`Found ${protocolHolders.length} protocol contracts:`)
90+
protocolHolders.forEach(h => console.log(` - ${h.name || 'Unknown'}: ${h.address}`))
91+
92+
// Build token-owner pairs for on-chain balance queries
93+
const tokensAndOwners = protocolHolders.map(holder => [
94+
USDC_E_ADDRESS,
95+
holder.address,
96+
])
97+
98+
return sumTokens2({
99+
api,
100+
tokensAndOwners,
101+
resolveLP: false,
102+
})
103+
}
104+
105+
module.exports = {
106+
timetravel: false,
107+
misrepresentedTokens: true,
108+
methodology:
109+
'TVL is calculated by summing USDC.e balances held in Doma protocol contracts ' +
110+
'(DomaFractionalization, DomaLaunchpad, and associated Uniswap V3 pools). ' +
111+
'Protocol contracts are discovered via the Doma Blockscout explorer API by filtering ' +
112+
'verified contracts from USDC.e token holders. Balances are fetched via on-chain ' +
113+
'ERC-20 balanceOf() calls on the Doma network (Chain ID: 97477).',
114+
doma: { tvl },
115+
}

projects/helper/chains.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@
111111
"dfk",
112112
"dfs",
113113
"doge",
114+
"doma",
114115
"dogechain",
115116
"dsc",
116117
"duckchain",

projects/helper/tokenMapping.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ const fixBalancesTokens = {
6666
YLDS: { coingeckoId: 'usd-coin', decimals: 0 },
6767
'pm.sale.pool.3dxq3fk9llvhrqqwhodiap': { coingeckoId: 'usd-coin', decimals: 0 },
6868
},
69+
doma: {
70+
// USDC.e (Bridged USDC via Stargate) - Verified 2024-11-27 via explorer.doma.xyz/token/0x31EEf89D5215C305304a2fA5376a1f1b6C5dc477
71+
'0x31eef89d5215c305304a2fa5376a1f1b6c5dc477': { coingeckoId: 'usd-coin', decimals: 6 },
72+
},
6973
}
7074

7175
ibcChains.forEach(chain => fixBalancesTokens[chain] = { ...ibcMappings, ...(fixBalancesTokens[chain] || {}) })

0 commit comments

Comments
 (0)