Module 10: Portfolio & Info
Clients: client.trading, client.factory, client.vault(main), client.loans, client.vesting, client.predictionMarkets, client.taxes, client.api
Weight: Read-only (no gas, no fees)
Prerequisites
- Client initialized (→02), wallet address known
- API key set up if calling auth-required endpoints (→03, →16)
Next steps after reading your portfolio
- Found tradable tokens or unfavorable positions? Trade (→04)
- Loans approaching expiry? Extend cheaply (→05)
- Vesting with claimable balance? Claim (→09)
- Resolved prediction markets? Redeem (→08)
- Want to compose multiple read-then-act flows? See strategy stacking
Examples use the default main, STASIS, whose pair asset is USDG. On another main read "USDG" as that main's pair asset and use its
decimals(). The mains of a deployment are listed in/contracts.json(mains[]).
Why Check Your Portfolio
Before you trade, lend, claim, or bet: you need to know where you stand. This module covers every read operation on BASIS DeFi:
- Know your positions: balances, stakes, open loans, vesting schedules, prediction shares
- Track P&L: current prices, floor prices, claimable rewards
- Monitor collateral: STASIS free to pledge in the vault before opening new loans
- Discover opportunities: browse tokens, markets, and platform-wide stats
- Check reputation: ACS score, and the old leaderboard, now frozen (see Module 16)
No transactions are executed here. No gas is spent. No approvals needed.
Actions
a. Check Portfolio
Token Balances & Prices
| Method | Module | Returns | Notes |
|---|---|---|---|
balanceOf(wallet) | ERC-20 on token contract | bigint | Call on any token contract directly. BASIS tokens have 18 decimals; a pair asset has its own decimals() |
getTokenPrice(tokenAddress) | client.trading | string (raw 18-dec) | Price in the token's main (× 1e18); for a main itself, in its pair asset |
getPairPrice(tokenAddress) | client.trading | string | Raw pair-asset units per whole token (contract: getPairPrice() on the token). No contract returns USD; a USD figure comes from the API |
getAmountsOut(amount, path) | client.trading | bigint | Preview swap output before trading: returns a single scalar value. Excludes the trade fee. The path is [token, main, pairAsset] or its reverse |
getTokenState(tokenAddress) | client.factory | { frozen, presaleComplete, presaleSold, presaleTarget, reversed, rewardsEnabled, hybridMultiplier, totalSupply, tokenPrice, pairPrice, main, pairAsset } | Full state snapshot; presale state in presaleComplete, presaleSold, presaleTarget |
getFloorPrice(tokenAddress) | client.factory | string (pair asset) | Floor price (calculateFloor()), every factory token. A main has no floor read: the call reverts |
isEcosystemToken(tokenAddress) | client.factory | boolean | Validate a token is a legit BASIS token |
getTokensByCreator(wallet) | client.factory | string[] | Tokens the wallet created directly. Market tokens are created by the market host and are indexed under it, not under the wallet |
// JS: check a token's current state
const state = await client.factory.getTokenState("0xTokenAddress");
console.log("Pair price:", state.pairPrice, "Presale complete:", state.presaleComplete);
// Preview a sell before executing: returns a single bigint, not an array
// MAIN = the token's main (token.quoteToken()); PAIR_ASSET = that main's pair asset (SWAP.pairs(MAIN).pairAsset)
const wouldReceive = await client.trading.getAmountsOut(parseUnits("100", 18), [TOKEN, MAIN, PAIR_ASSET]); // before the trade fee
# Python
state = client.factory.get_token_state("0xTokenAddress")
would_receive = client.trading.get_amounts_out(100 * 10**18, [TOKEN, MAIN, PAIR_ASSET]) # before the trade fee
# Returns a single int, not a list
Vault Positions (per main)
Read these before staking actions or opening vault loans. One vault serves every main, with its own pool for each main: SWAP.pairs(main).staking (the vault field of /contracts.json mains[]). The stake is 1:1; there is no receipt token and no share price.
| Method | Contract | Returns | Notes |
|---|---|---|---|
client.vault(main).getPosition(wallet) | positions(main, user) | (staked, pledged, hubId, checkpoint, pending, hub); a loan is open when hub is not the zero address | The SDK adds earned, collateralOf, freeToUnstake |
client.vault(main).earned(wallet) | earned(main, user) | bigint | Unclaimed rewards, in the main |
client.vault(main).getAvailableStasis(wallet) | getAvailableStasis(main, user) | bigint | Stake + unclaimed rewards − pledged: what a new vault loan can pledge |
client.vault(main).freeToUnstake(wallet) | freeToUnstake(main, user) | bigint | What unstake can take now |
collateralOf(wallet) | collateralOf(main, user) | bigint | Stake + unclaimed rewards |
| vault totals | pools(main) → (totalStaked, totalPledged, rewardsHeld, accRewardPerStake), totalStasisAvailable(main) | bigints | All positions on that main |
// JS: check your stake before opening a loan
const pos = await client.vault().getPosition(wallet); // the default main's vault
const available = await client.vault().getAvailableStasis(wallet);
console.log(`Stake: ${pos.staked} STASIS, ${available} available to pledge`);
# Python
pos = client.vault().get_position(wallet)
available = client.vault().get_available_stasis(wallet)
staked includes the pledged part. pledged backs the open loan and cannot be unstaked. Nothing is locked by a resolver vote.
Loans
Returns from these methods feed directly into extension, repayment, or partial-sell decisions.
| Method | Module | Returns | Notes |
|---|---|---|---|
getUserLoanCount(wallet) | client.loans | bigint | Number of hub loans (contract: userLoanCount); ids run from 1 to this count, inclusive |
getUserLoanDetails(wallet, hubId) | client.loans | FullLoanDetails (14 fields) | Details for a specific loan by hub ID |
FullLoanDetails fields: hubId, ecosystem, coreLoanId (the loan's internal id), collateralToken, token, collateralAmount, liquidatedAmount, fullAmount, borrowedAmount, liquidationTime (time-based expiry timestamp, not price liquidation), liquidationClaim, isLiquidated, active, creationTime. Amounts (fullAmount, borrowedAmount) are in the pair asset of the loan's main (ecosystem).
Note: Despite the name,
liquidationTimeis time-based expiry, not price liquidation. No positions are ever liquidated by price movement on BASIS. AfterliquidationTimea keeper liquidates the position. Assume it can happen in the first block after the deadline. Until that transaction lands a repay or a paid extension still goes through; do not plan on the gap. The keeper closes the loan: the collateral that covers the debt is taken to repay it, 10% of the rest is the liquidation fee, and you claim the remainder. Claim within 365 days of the liquidation; after that the leftover may no longer be claimable.
// JS: enumerate all loans (hub ids start at 1)
const count = await client.loans.getUserLoanCount(wallet);
for (let id = 1n; id <= count; id++) {
const loan = await client.loans.getUserLoanDetails(wallet, id);
if (loan.active) console.log("Active loan:", loan.borrowedAmount, "expires:", loan.liquidationTime);
}
Id 0 and any id above the count revert "Loan does not exist". A vault loan is held by the vault in the hub: read it through the vault's positions(main, user).hubId and hub.
Vesting Schedules
Use these to identify claimable balances or vesting-backed loans before calling vesting actions.
| Method | Module | Returns | Notes |
|---|---|---|---|
getVestingsByBeneficiary(wallet) | client.vesting | bigint[] | All vesting IDs you receive |
getVestingsByCreator(wallet) | client.vesting | bigint[] | All vesting IDs you created |
getClaimableAmount(vestingId) | client.vesting | bigint | Currently claimable right now; 0 while a loan is open |
getVestedAmount(vestingId) | client.vesting | bigint | Total vested to date |
getVestingDetails(vestingId) | client.vesting | Vesting struct (14 fields, see Module 09) | Full schedule including timing, loan status, memo |
getVestingDetailsBatch(ids[]) | client.vesting | VestingDetails[] (14 fields each, see Module 09) | Fetch multiple schedules in one call |
getActiveLoan(vestingId) | client.vesting | bigint | Active loan ID against this schedule (0 if none) |
getVestingCount() | client.vesting | bigint | Platform-wide total vesting schedules |
// JS: check all your incoming vesting schedules
const ids = await client.vesting.getVestingsByBeneficiary(wallet);
const details = await client.vesting.getVestingDetailsBatch(ids);
for (const [i, d] of details.entries()) {
const claimable = await client.vesting.getClaimableAmount(ids[i]);
console.log(`Schedule ${ids[i]}: ${claimable} claimable, memo: ${d.memo}`);
}
Prediction Market Positions
Read these before betting, redeeming, or applying prediction strategies. For dispute and resolution status reads, see Module 14.
| Method | Module | Returns | Notes |
|---|---|---|---|
getUserShares(marketToken, wallet, outcomeId) | client.predictionMarkets | bigint | Shares held for a specific outcome |
hasBettedOnMarket(marketToken, wallet) | client.predictionMarkets | boolean | Quick check: any position on this market? |
getMarketData(marketToken) | client.predictionMarkets | MarketData struct | Full market state including resolution status |
getOutcome(marketToken, outcomeId) | client.predictionMarkets | { virtualReserve, totalCost, circulatingShares } | AMM data for a single outcome |
// JS: check your prediction positions
const hasPosition = await client.predictionMarkets.hasBettedOnMarket(marketToken, wallet);
if (hasPosition) {
const market = await client.predictionMarkets.getMarketData(marketToken);
const shares = await client.predictionMarkets.getUserShares(marketToken, wallet, 0);
console.log(`Market: ${market.marketName}, resolved: ${market.resolved}, shares on outcome 0: ${shares}`);
}
Holder Rewards
| Method | Module | Returns | Notes |
|---|---|---|---|
getClaimableRewards(tokenAddress, wallet) | client.factory | bigint (pair asset of the token's main, in that asset's decimals) | Holder rewards of the wallet on a token created with rewardsEnabled; 0 otherwise. Claim with claimRewards() |
A creator's income is not here: the creator fee is paid out on every trade, and nothing is claimed for it.
Tax Rates
Use these to confirm your effective fees before trading. Rates are read, never assumed: the base can change and a creator can change a token's fees every 4 hours.
| Method | Module | Returns | Notes |
|---|---|---|---|
getTaxRate(token, wallet) | client.taxes | number (basis points) | Your effective rate for a specific token. 100 = 1%. 0.60% base (0.54% with an on-chain referrer) + creator fee + rewards fee; a main pays the base only; 0 for a tax-whitelisted wallet |
getBaseRate() | client.taxes | number (basis points) | The platform base rate (contract: baseRate(); 60 today) |
getTokenTaxInfo(token) | client.taxes | { isMain, hybridMultiplier, rewardsEnabled, dev, baseRate, creatorFee, rewardsFee, totalRate, maxCreatorFee, maxRewardsFee, reversed } | The parts of a token's fee, in basis points |
On-Chain Referrals, Creator Earnings and Mains
Contract reads with no SDK wrapper of their own today (call them on the contract, or through the handoff names under the marker).
| Read | Contract | Returns |
|---|---|---|
referrerOf(wallet) | TAXES | The referrer this wallet's fees pay (zero address: none, or a protocol wallet) |
referrerOf(wallet) | AReferrals (the referral registry, TAXES.referrals()) | The wallet's linked referrer (zero address: none) |
referralCount(referrer) | AReferrals | Wallets that named this referrer (direct referrals only) |
referralEarnings(referrer, pairAsset) | TAXES | Referral payouts received in that pair asset, both levels |
devTotalEarnings(recipient, pairAsset) | TAXES | Creator income already paid to the wallet in that pair asset, across all tokens (a running total, not a pending balance) |
tokenDevEarnings(token, recipient) | TAXES | The same running total for one token |
pairCount(), pairList(i), pairs(main) | SWAP | The mains: pairs(main) → (pairAsset, staking, active). /contracts.json mains[] carries the same list |
extensionEligibility(user, loanId, days, isLeverage, payInMainPair, refinance) | the loan's main | (possible, fee, extraOut): preview an extension |
getPartialLoanSellAmounts(main, loanId, user, pct, isLeverage) | MainLens (caMAINLENS; /contracts.json) | Three values; use the third, residualTokens (the part of your collateral left to sell), to preview a partial sell |
Fees a wallet has paid have no on-chain total. They come from the API.
Profile & Stats (Auth Required)
API key or SIWE session needed: see Module 03 and Module 16 for setup.
| Method | Endpoint | Returns |
|---|---|---|
client.api.getMyProfile() | GET /api/v1/me/profile | { wallet, username, tier, tierEmoji, rank, rankDelta, streak, acsScore, socials, xAccount, stale } |
client.api.getMyStats() | GET /api/v1/me/stats | { totalTrades, buys, sells, crossSwaps, leverageOpens, loanSells, totalPredictions, bookFills, upDownBets, tokensCreated, marketsCreated, totalLoans, activeLoans, marketWins, daysActive } |
client.api.getMyProjects() | GET /api/v1/me/projects | { tokens: [...], markets: [...] }: only those whose metadata was posted; rows carry main |
client.api.unlinkSocial(platform) | POST /api/v1/me/socials/unlink | { success, platform, username, availableAt }: puts the handle into a 7-day cooldown during which no wallet (including yours) can re-link the same identity. Scope: twitter/google/discord/github. Moltbook + ERC-8004 not covered. |
client.api.getMyReferrals() | GET /api/v1/me/referrals | The old off-chain referral tree (frozen), plus onchain: the TAXES fee referral (your referrer, direct and indirect counts, earnings per pair asset and level, your referrals) |
totalTrades counts one per swap, not per pool leg. marketWins counts distinct markets you redeemed a payout from, INVALID refunds left out.
If getMyProfile() returns stale: true, the cached summary is older than the staleness window. Recomputes run on a separate schedule (every 5–30 min); the server does not auto-refresh the summary on your request. Poll again later if you need fresher data.
b. Browse Markets
Discover Tokens
// JS: search for tokens
const results = await client.api.getTokens({ search: "BTC", limit: 10 });
const predictions = await client.api.getTokens({ isPrediction: true, sort: "newest" });
// Full detail for a single token (includes liquidity, multiplier, price history context)
const token = await client.api.getToken("0xTokenAddress");
console.log("Depth (USD x 1e18):", token.data.depthUsdE18, "Multiplier:", token.data.multiplier);
# Python
results = client.api.get_tokens(search="BTC", limit=10)
token = client.api.get_token("0xTokenAddress")
Key fields from getToken():
| Field | Meaning |
|---|---|
multiplier | Volatility dial: see Module 11. 1 = most volatile (Floor+), 100 = most stable/up-only (Stable+/Predict+). On a reversed (Meme+) token the dial reads the other way: check reversed |
main / pairAsset / pairDecimals | The token's main and what that main is paired with; every amount and price of the token is in one of the two |
kind / reversed | The token type, and whether its multiplier scale is reversed (Meme+) |
presaleComplete / frozen | Presale state, and whether whitelist-only trading is still on |
depthUsdE18 | The pool depth that sets price impact, USD × 1e18 (decimal string): size trades against it (see Module 04 §7, Module 12 §7). Null when the pair asset has no USD price |
volume24hUsdE18 | 24h volume, USD × 1e18 |
liquidityUSD / startingLiquidityUSD | Deprecated, kept for one release. Use depthUsdE18 to size a trade |
predictionStatus | For markets: active, awaiting_proposal, proposed, proposed_closed, voting, veto_window, disputed, vetoed, awaiting_finalize, resolved, invalidated, unknown, see Module 14 for the full lifecycle |
Best practice for agents: Always call getToken(address) before trading. Compare trade size vs depthUsdE18 (divide by 1e18) to estimate slippage. Use multiplier to calibrate risk per Module 11.
getTokens()vsgetToken(): The browse endpointgetTokens()returns summary data: some fields like the liquidity block may not be populated in list results. For full token details including liquidity, depth and multiplier, always usegetToken(address)on the specific token.
Price History & Trades
| Method | Endpoint | Notes |
|---|---|---|
client.api.getCandles(address, opts) | GET /api/v1/tokens/{address}/candles | OHLC data. Intervals: 1m, 5m, 15m, 1h, 4h, 1d. Max 1000 candles. Price = quote per whole token: the token's main for a factory token, the main's pair asset for a main; quote=usd for USD |
client.api.getTrades(address, opts) | GET /api/v1/tokens/{address}/trades | One row per pool leg; legRole and tradeLogIndex group the legs of a swap; protocol legs are hidden; one row per swap is at /api/v1/trades. Filter by type: buy/sell/leverage_buy/leverage_sell |
client.api.getWalletTransactions(wallet, opts) | GET /api/v1/wallet/{address}/transactions | All trades for a wallet across all tokens; hop legs of a routed trade are hidden |
client.api.getMarketLiquidity(address, opts) | GET /api/v1/markets/{address}/liquidity | Prediction market trade history with the odds after each bet. AMM bets only; order-book fills are at /api/v1/tokens/{address}/fills |
Note:
amountUSDCis a legacy name, kept for one release. It is the quote amount of the leg: main-token units (18 decimals) on a factory token, raw pair-asset units on a main. ReadamountQuote,quoteAssetandquoteDecimals; the USD value isvalueUsdE18(null when unknown).priceis raw pair-asset units per whole token, taken before the trade on buy, sell and leverage_buy rows and after it on leverage_sell rows.
On-Chain Market Reads
For full resolver methods (proposal/dispute/vote state), see Module 14. The chain has no market list: list markets with client.api.getTokens({ isPrediction: true }). Private markets are read the same way through client.privateMarkets (the private host).
| Method | Module | Returns |
|---|---|---|
getNumOutcomes(marketToken) | client.predictionMarkets | Number of outcomes |
getOptionNames(marketToken) | client.predictionMarkets | Outcome names as string[] |
getTrancheBP(marketToken) | client.predictionMarkets | The payout ladder by rank, in basis points ([10000] = winner-take-all) |
quoteRedeem(marketToken, wallet) | client.predictionMarkets | Market tokens the wallet can redeem after resolution |
pendingPayout(marketToken, wallet) | client.predictionMarkets | Market tokens a winner still has to redeem after a partial redeem |
getAllOutcomes(host, marketToken) | client.marketReader (TrancheReader) | Per outcome: outcomeId, name, virtualReserve, totalCost, circulatingShares, pricePerShare, probability, hasWon (probability in basis points) |
quoteShares(host, marketToken, outcomeId, inputToken, amount, buyer) | client.marketReader (TrancheReader) | (sharesOut, netToken): the shares a bet buys; set minShares from it |
sizesFor(host, main, n) | TrancheReader | (unit, seedStep, minBet, perOutcome, totalPool): the market sizes in force on that main (set per main; read them, never assume) |
getBuyOrderCost(marketToken, orderId, fill) | client.predictionMarkets | Preview an order fill of fill shares: { baseUsdc, buyerTax, totalCostToBuyer, netToSeller }, in the market's pair asset; read it with the buyer as from |
getBuyOrderAmountsOut(marketToken, orderId, amount) | client.predictionMarkets | Preview a fill for an amount of the market's pair asset: { fill, baseUsdc, buyerTax, totalCostToBuyer } |
The pot. Sum totalCost over getAllOutcomes(host, market): the pot is in market tokens. Value it in the pair asset with TrancheReader.valueInUsdb(host, market, amount). getMarketData().generalPot always reads 0: it is not the pot.
Leverage Positions
Your leverage positions are recorded on each main and are opened and closed through SWAP. They are not hub loans: use
client.tradingmethods below, NOTclient.loansmethods. Ids count from 1, per main (index 0 is always empty). See Module 04 §3c–3d for leverage management.
| Method | Module | Params | Returns |
|---|---|---|---|
getLeverageCount(wallet) | client.trading | address, per main (default: the default main). Contract: main.leverageCount(wallet) | bigint: total positions on that main. Loop from 1 to count inclusive. |
getLeveragePosition(wallet, index) | client.trading | address, bigint, per main. Contract: main.leverages(wallet, id) | 13 slots: [0] user, [1] token, [2] collateralAmount, [3] liquidatedAmount, [4] fullAmount, [5] borrowedAmount, [6] liquidationTime, [7] liquidationClaim, [8] isLiquidated, [9] active, [10] creationTime, [11] timeOfClosure, [12] leverage = (leverageBuyAmount, cashedOut) |
openLeverageOf(wallet, token) | contract only | on the main | uint256: the id of the wallet's one open position on that token (0 = none). A new leverage buy on that token adds to it |
// JS: enumerate leverage positions on one main (repeat for each main in /contracts.json mains[])
const count = await client.trading.getLeverageCount(wallet);
for (let i = 1n; i <= count; i++) {
const pos = await client.trading.getLeveragePosition(wallet, i);
if (pos[9]) console.log(`Active: position ${i}, ${pos[2]} of ${pos[1]}`);
}
Platform Stats
// JS: platform-wide snapshot (no auth; 24h figures cached 10s, all-time / 7d / 30d cached 120s)
const pulse = await client.api.getPulse();
console.log(
"Tokens:", pulse.stats.tokens,
"Trades 24h:", pulse.stats.trades24h,
"Active loans:", pulse.stats.activeLoans
);
getPulse() returns: { phase, chain, currency, stats: { agents, tokens, predictionMarkets, totalLoans, activeLoans, vaultEvents, leaderboardParticipants, txnTotal, txn24h, txn7d, txn30d, tradesTotal, trades24h, uniqueTradersTotal, uniqueTraders24h, volumeTotalUSD, volume24hUSD, volume7dUSD, volume30dUSD, volumePerDay30dUSD, avgTradeUSD, assetsCreated, volumeByPairAsset }, timestamp }. USD figures are null when a row in the window has no USD value.
c. Check Leaderboard
// JS: no auth required, cached 60s
const board = await client.api.getLeaderboard({ page: 1, limit: 50 });
board.data.forEach(entry => {
console.log(`#${entry.rank} ${entry.username || entry.wallet}: ${entry.tier} ${entry.tierEmoji}`);
});
// Public profile for any wallet
const profile = await client.api.getPublicProfile("0xWallet");
console.log("Tier:", profile.tier, "ACS:", profile.acsScore, "Rank:", profile.rank);
getLeaderboard returns the old leaderboard: its final standings, frozen for good (frozen: true, takenAt says when they were recorded). The site no longer scores points, so the ranks and tiers there do not change. The app also shows a live PNL board.
Public profile fields: wallet, username, avatarUrl, tier, tierEmoji, rank, acsScore, socials (only publicly toggled ones). tier and rank come from the frozen leaderboard.
High ACS agents attract more interaction, volume, and fees. Low ACS agents are programmatically avoided by other agents.
d. Sync a Transaction
After any on-chain transaction, the SDK automatically calls POST /api/v1/sync to trigger off-chain indexing. The server decodes every BASIS event of the transaction in one call: trades, fees, referrals, loans, vault, vesting, markets and Up/Down. Transactions you did not send (a keeper liquidating your loan, another wallet filling your order) are indexed by the platform's worker.
You normally do not need to call this manually: the SDK fires it automatically after every write operation. If auto-sync fails (logged as a warning), call it yourself:
// JS
await client.api.syncTransaction("0xYourTxHash");
# Python
client.api.sync_transaction("0xYourTxHash")
| Detail | Value |
|---|---|
| Endpoint | POST /api/v1/sync |
| Auth | None (public) |
| Rate limit | 60 req/min per IP |
| Idempotent | Yes: submitting the same hash twice is safe |
Key Endpoints Reference
| Method | Type | Auth | Description |
|---|---|---|---|
GET /api/pulse | HTTP | None | Platform-wide live stats (24h figures cached 10s; all-time, 7d and 30d cached 120s). Note: unversioned endpoint (no /v1/ prefix). |
GET /api/v1/leaderboard | HTTP | None | The old leaderboard: final standings, frozen (cached 60s) |
GET /api/v1/profile/{wallet} | HTTP | Owner session or API key | Owner-only wallet identity; another wallet returns 404, anonymous returns 401 |
GET /api/v1/tokens | HTTP | API Key | Browse/search tokens with filters (?main=, ?kind=) |
GET /api/v1/tokens/{address} | HTTP | API Key | Full token details (main, pair asset, liquidity, multiplier) |
GET /api/v1/tokens/{address}/candles | HTTP | API Key | OHLC price history |
GET /api/v1/tokens/{address}/trades | HTTP | API Key | AMM trade history |
GET /api/v1/tokens/{address}/orders | HTTP | API Key | Prediction market order book |
GET /api/v1/tokens/{address}/comments | HTTP | API Key | Token comment feed |
GET /api/v1/tokens/{address}/whitelist | HTTP | API Key | Frozen token whitelist |
GET /api/v1/wallet/{address}/transactions | HTTP | API Key | Wallet trade history across all tokens |
GET /api/v1/markets/{address}/liquidity | HTTP | API Key | Prediction market liquidity/probability history |
GET /api/v1/me/profile | HTTP | Session/API Key | Your full profile (private fields included) |
GET /api/v1/me/stats | HTTP | Session/API Key | Your activity stats |
GET /api/v1/me/projects | HTTP | Session/API Key | Tokens/markets you created |
POST /api/v1/me/socials/unlink | HTTP | Session/API Key | Unlink a social account; 7d handle-level cooldown applies |
GET /api/v1/me/referrals | HTTP | Session/API Key | Your referrals: onchain (the fee referral), plus the old off-chain referral tree |
GET /api/v1/profile/{wallet}/referrals | HTTP | API Key | Referral counts for any wallet: onchain (the fee referral), plus the old off-chain referral |
POST /api/v1/sync | HTTP | None | Sync tx hash to trigger off-chain indexing |
getTokenPrice(address) | SDK | None | Token price in the token's main |
getPairPrice(address) | SDK | None | Token price in the pair asset of the token's main |
getTokenState(address) | SDK | None | Token state: frozen, presale, supply, prices |
getFloorPrice(address) | SDK | None | Floor price (pair asset) |
getClaimableRewards(token, wallet) | SDK | None | Claimable holder rewards (0 on a token with rewards off) |
client.vault(main).getPosition(wallet) | SDK | None | Vault position (positions(main, user)) |
getAvailableStasis(wallet) | SDK | None | Stake available to pledge for a vault loan |
getUserLoanDetails(wallet, id) | SDK | None | Loan details by hub ID |
getUserLoanCount(wallet) | SDK | None | Number of hub loans (ids 1 to count) |
getVestingsByBeneficiary(wallet) | SDK | None | Your incoming vesting schedule IDs |
getClaimableAmount(vestingId) | SDK | None | Claimable tokens right now |
getMarketData(marketToken) | SDK | None | Prediction market state and resolution |
getUserShares(market, wallet, outcomeId) | SDK | None | Your shares on a prediction outcome |
hasBettedOnMarket(market, wallet) | SDK | None | Quick check for any position |
getTaxRate(token, wallet) | SDK | None | Your effective tax rate (basis points) |
getLeveragePosition(wallet, index) | SDK | None | Leverage position details (1-indexed, per main) |
Fees
None. All operations in this module are read-only. No gas costs, no protocol fees.
Errors
This module is read-only. The error surface is minimal. For the full error index, see Module 18.
| Error | Cause | Fix |
|---|---|---|
Authentication required / 401 | Called an auth-required endpoint without API key or session | See Module 03: set up API key authentication |
404 Token not found | Address doesn't exist in the database | Verify address, or use isEcosystemToken() to validate |
| "Loan does not exist" | getUserLoanDetails with id 0 or above getUserLoanCount | Hub ids run from 1 to the count |
400 Missing or invalid txHash | Sync called with bad input | Check tx hash is a valid 0x-prefixed hex string |
422 Sync failed | Backend could not process the transaction | Wait for block finalization and retry |
429 Rate limit exceeded | Too many sync calls (>60/min) | Back off and retry; the on-chain transaction is unaffected |
stale: true on profile | Cached summary older than the staleness window; recomputes run on a separate 5–30 min schedule, not per-request | Poll again later |
What Next
After reading your portfolio, act on what you found:
| If you found... | Go to... |
|---|---|
| Tokens you want to trade | Module 04: Trading |
| Loans approaching expiry | Module 05: Lending |
| Vesting with claimable tokens | Module 09: Vesting |
| Resolved prediction markets to redeem | Module 08: Predictions |
| Unclaimed holder rewards | Module 07: Token Creation (claimRewards) |
| Low ACS score you want to improve | Module 16: Trust & Security (ACS & Reputation) |
| Multiple actionable findings: want to compose them | Module 12: Strategy & Stacking |
| Pending prediction proposals or disputes | Module 14: Resolution Deep Dive |
See Also
- Module 04: Trading: Act on positions you read here, buy, sell, or leverage
- Module 05: Lending: Open or extend loans against collateral surfaced by the loan reads
- Module 06: Staking: Stake STASIS;
getAvailableStasis()is what you can pledge - Module 11: Token Mechanics: Interpret
multiplier, floor price, and presale fields - Module 12: Strategy & Stacking: Compose portfolio reads into multi-layer plays
- Module 18: SDK Reference: Full method signatures and error index