Skip to content

Resolving Contract Addresses

About this page

Protocol: JustLend DAO · Network: TRON (Mainnet + Nile) · Scope: map human-facing symbols (jUSDT, USDT, and other contract labels) to on-chain Base58 and hexadecimal addresses without hard-coding them in an integration.

Machine-readable registry

contracts.json is the published machine-readable address registry, generated from the MCP server's src/core/chains.ts. Before consuming it, check _meta.last_generated and _meta.schema_version for freshness and schema compatibility. The root object contains a networks map, and each network contains optional contract categories such as jtokens, comptroller, governance, strx, and interest_rate_models.

Address formats

Every deployed-contract address uses the same three fields:

Field Use
address.base58 TRON Base58Check (T…) for wallets, Tronscan, and TronWeb
address.hex_evm EVM-style 0x… address for ABI and cross-chain tooling
address.hex_tron TRON-internal 0x41… address for low-level TronGrid/TronWeb calls

jToken records

For a network that exposes SBM markets, jTokens are keyed by symbol at networks.<network>.jtokens.<symbol>. A jToken record contains symbol, status, underlying_symbol, decimal metadata, nested delegator and underlying records, and, when applicable, a delegate contract record. Native TRX has no TRC20 underlying address, so its underlying record contains a note instead.

Filter status === "active" before directing new supply or borrow positions. Legacy markets remain queryable for unwinding existing positions but are closed to new supply and borrow.

Example: resolve a jToken from its underlying symbol

import contracts from './contracts.json' with { type: 'json' };

function jTokenForUnderlying(underlyingSymbol, network = 'mainnet') {
  const jtokens = contracts.networks?.[network]?.jtokens ?? {};
  const jtoken = Object.values(jtokens).find(
    (entry) =>
      entry.underlying_symbol === underlyingSymbol &&
      entry.status === 'active'
  );

  if (!jtoken) {
    throw new Error(`No active jToken for ${underlyingSymbol} on ${network}`);
  }

  return {
    symbol: jtoken.symbol,
    jTokenAddress: jtoken.delegator.address.base58,
    jTokenHex: jtoken.delegator.address.hex_tron,
    underlyingAddress: jtoken.underlying?.address?.base58 ?? null,
  };
}

console.log(jTokenForUnderlying('USDT'));

The returned underlyingAddress is null for native TRX. Use the nested delegator address as the jToken address. When present, the delegate address is the upgradeable implementation and is not the user-facing market address.

Live market data fallback

Use the public market list (GET https://openapi.just.network/lend/jtoken, documented in APIs §3.1) when you also need live rates, balances, prices, or collateral factors. Join response.data.tokenList[].address with networks.<network>.jtokens.*.delegator.address.base58. For TRC20 markets, underlyingAddress can also be matched with networks.<network>.jtokens.*.underlying.address.base58; do not use this fallback for native TRX, whose API response uses the TRON zero address while the registry has no underlying address. Do not replace the registry's static contract addresses with an unverified API response.

JustLend V2 (Moolah)

The current contracts.json registry is for deployed protocol contracts and SBM jTokens; it does not enumerate the live Moolah vault and isolated-market catalog. Resolve those identifiers through the documented V2 read endpoints in APIs §3.4, then use the returned vaultAddress or market id when constructing requests.