1- const sdk = require ( "@defillama/sdk" ) ;
2-
31// KEA Credit Contract Addresses on Hedera
42const INVOICE_FACTORY_PROXY = "0x79914D3C80246FBC9E40409C4688A4141A3abbCe" ;
5- const INVOICE_NFT_PROXY = "0x28E99733E84dE18fF6f50024F6ad33483B3D7F80" ;
6-
7- // Token Addresses (Hedera format: 0.0.tokenId)
8- const TOKENS = {
9- PIXD_V1 : "0.0.9323052" , // 0x00000000000000000000000000000000008e422c (0-decimal)
10- KUSD_V2 : "0.0.9590855" , // 0x0000000000000000000000000000000000925847 (6-decimal)
11- } ;
123
134// Pool Status Constants - V1/V2
145const POOL_STATUS_V1V2 = {
@@ -37,11 +28,6 @@ const FACTORY_ABI = [
3728 "function totalPools() external view returns (uint256)" ,
3829] ;
3930
40- const NFT_ABI = [
41- "function getNextTokenId() external view returns (uint256)" ,
42- "function totalSupply() external view returns (uint256)" ,
43- ] ;
44-
4531const POOL_V1_ABI = [
4632 // V1 Pool ABI (simpler structure)
4733 "function getPoolInfo() external view returns (uint256 nftTokenId, uint256 targetAmount, uint256 currentAmount, uint256 interestRate, uint256 maturityDate, address borrower, uint8 status, uint256 platformFeePercentage, address treasuryWallet)" ,
@@ -52,25 +38,6 @@ const POOL_V3_ABI = [
5238 "function getPoolInfo() external view returns (uint256 nftTokenId, uint256 targetAmount, uint256 minAcceptableAmount, uint256 currentAmount, uint256 disbursedAmount, uint256 interestRate, uint256 originationDate, uint256 gracePeriodEndTime, uint256 maturityDate, address borrower, uint8 status, bool gracePeriodProcessed, address bridgeWalletAddress, uint256 supportedTokenCount)" ,
5339] ;
5440
55- /**
56- * Determine if a token ID represents V1 or V3
57- * Our first 12 NFTs are V1, rest are V3 (V2 was upgraded to V3 in place)
58- */
59- function getVersionFromTokenId ( tokenId ) {
60- return Number ( tokenId ) <= 12 ? "v1" : "v3" ;
61- }
62-
63- /**
64- * Get token configuration based on version
65- */
66- function getTokenConfig ( version ) {
67- return {
68- address : version === "v1" ? TOKENS . PIXD_V1 : TOKENS . KUSD_V2 ,
69- decimals : version === "v1" ? 0 : 6 ,
70- symbol : version === "v1" ? "PIXD" : "kUSD" ,
71- } ;
72- }
73-
7441/**
7542 * Calculate TVL for a single pool based on its status
7643 */
@@ -155,106 +122,25 @@ function calculatePoolTVL(poolInfo, version) {
155122 return tvlAmount ;
156123}
157124
158- /**
159- * Get pool info using the appropriate ABI based on pool index
160- * First 12 pools (index 0-11) are V1, rest are V3 (V2 upgraded to V3)
161- */
162- async function getPoolInfoWithVersion ( poolAddress , poolIndex ) {
163- // Determine version based on pool index (first 12 are V1, rest are V3)
164- const version = poolIndex < 12 ? "v1" : "v3" ;
165- const abi = version === "v1" ? POOL_V1_ABI [ 0 ] : POOL_V3_ABI [ 0 ] ;
166-
167- const result = await sdk . api . abi . call ( {
168- target : poolAddress ,
169- abi : abi ,
170- chain : "hedera" ,
171- } ) ;
172-
173- if ( result . output ) {
174- const tokenId = Number ( result . output [ 0 ] ) ;
175- return {
176- success : true ,
177- poolInfo : result . output ,
178- version,
179- tokenId,
180- } ;
181- } else {
182- return { success : false , error : "No output from pool call" } ;
183- }
184- }
185-
186125/**
187126 * Main TVL calculation for Hedera
188127 */
189- async function hederaTvl ( ) {
190- const balances = { } ;
191- let totalV1TVL = 0 ;
192- let totalV3TVL = 0 ;
193- let processedPools = 0 ;
194-
195- // Get total NFTs to understand scale
196- // Try getNextTokenId first (KEA Credit specific function)
197- let totalNFTs = 0 ;
198-
199- const nextTokenIdResult = await sdk . api . abi . call ( {
200- target : INVOICE_NFT_PROXY ,
201- abi : NFT_ABI [ 0 ] , // getNextTokenId
202- chain : "hedera" ,
203- } ) ;
204-
205- if ( nextTokenIdResult . output !== undefined ) {
206- totalNFTs = Number ( nextTokenIdResult . output ) - 1 ; // Next token ID - 1 = current total
207- } else {
208- throw new Error ( "getNextTokenId returned undefined" ) ;
209- }
210-
128+ async function hederaTvl ( api ) {
211129 // Get all pool addresses
212- const poolsResult = await sdk . api . abi . call ( {
213- target : INVOICE_FACTORY_PROXY ,
214- abi : FACTORY_ABI [ 0 ] ,
215- chain : "hedera" ,
216- } ) ;
217-
218- if ( poolsResult . output === undefined ) {
219- throw new Error (
220- `Factory getAllPools call failed: ${ JSON . stringify ( poolsResult ) } `
221- ) ;
222- }
223-
224- const poolAddresses = poolsResult . output || [ ] ;
225-
226- // Process each pool
227- for ( let i = 0 ; i < poolAddresses . length ; i ++ ) {
228- const poolAddress = poolAddresses [ i ] ;
229-
230- const poolResult = await getPoolInfoWithVersion ( poolAddress , i ) ;
231-
232- if ( ! poolResult . success ) {
233- continue ;
234- }
235-
236- const { poolInfo, version, tokenId } = poolResult ;
237-
238- // Calculate TVL for this pool
239- const poolTVL = calculatePoolTVL ( poolInfo , version ) ;
240-
241- if ( version === "v1" ) {
242- totalV1TVL += poolTVL ;
243- } else if ( version === "v3" ) {
244- totalV3TVL += poolTVL ;
245- }
246-
247- processedPools ++ ;
248- }
249-
250- const totalTVL = totalV1TVL + totalV3TVL ;
130+ const poolAddresses = await api . call ( { target : INVOICE_FACTORY_PROXY , abi : FACTORY_ABI [ 0 ] , } ) ;
131+ const v1Pools = poolAddresses . slice ( 0 , 12 )
132+ const v3Pools = poolAddresses . slice ( 12 )
133+ const poolV1Info = await api . multiCall ( { abi : POOL_V1_ABI [ 0 ] , calls : v1Pools } )
134+ const poolV3Info = await api . multiCall ( { abi : POOL_V3_ABI [ 0 ] , calls : v3Pools } )
251135
252- balances [ "usd-coin" ] = totalTVL ;
136+ const v1Tvls = poolV1Info . map ( info => calculatePoolTVL ( info , "v1" ) )
137+ const v3Tvls = poolV3Info . map ( info => calculatePoolTVL ( info , "v3" ) )
253138
254- return balances ;
139+ api . addUSDValue ( v1Tvls . concat ( v3Tvls ) . reduce ( ( a , b ) => a + b , 0 ) )
255140}
256141
257142module . exports = {
143+ misrepresentedTokens : true ,
258144 methodology :
259145 "TVL represents the total value locked in KEA Credit's RWA (Real World Assets) invoice tokenization platform on Hedera. Businesses tokenize their invoices as NFTs and receive funding from lenders through investment pools. TVL calculation includes: (1) Active pools - current invested amounts, (2) Funded pools - fully funded target amounts, (3) Partially funded pools - current invested amounts, (4) Pools in grace period - current amounts during active grace period. Excludes repaid, cancelled, defaulted, or refunded pools. The platform operates with two versions: V1 pools (NFT IDs 1-12) using 0-decimal PIXD tokens, and V3 pools (NFT IDs 13+) using 6-decimal kUSD tokens. Both tokens maintain 1:1 USD parity representing underlying invoice values." ,
260146 hedera : {
0 commit comments