Skip to main content
Portal’s Enclave MPC API lets your users lend and borrow on Aave V3, Morpho Blue, SparkLend and Lista through the Yield.xyz integration. This guide covers discovering lending markets, building supply / borrow / repay / withdraw actions, signing and submitting the resulting transactions, and tracking positions.

Overview

The lend & borrow functionality allows you to:
  • Discover the lending integrations (protocols) and the markets your project has enabled, with live rates, LTVs, liquidation thresholds and liquidity
  • Supply tokens as collateral and borrow against them
  • Repay debt and withdraw collateral, or toggle a supplied asset as collateral
  • Track positions (supply and debt balances, health factor, LTV and available borrow) and liquidation history
To summarize: a user supplies collateral, can borrow up to the market’s maxLtv of its value, pays a floating borrow rate with no term, and is liquidated (partially, with a penalty) only if the position’s healthFactor drops below 1. The integration page explains the mechanics and why you might offer it. All endpoints live under https://api.portalhq.io/api/v3/clients/me/integrations/yield-xyz-borrow and return { "data": ... }. Chain ids are CAIP-2 everywhere (eip155:8453 for Base).

Prerequisites

Before using lend & borrow operations, ensure you have:
  • A properly initialized Portal client (see Create a client)
  • An active wallet with the required token(s) and gas on the target network (see Create a wallet)
  • Yield.xyz integration enabled in your Portal Dashboard, with the lending markets you want to offer enabled in the Yield.xyz dashboard (see Yield.xyz Borrow)
Lending integrations are live on mainnets only: there are no Sepolia, Base Sepolia or Amoy markets, so POST /api/v3/clients/me/fund cannot be used here. Test with small amounts on an inexpensive chain such as Base. The examples below use Aave V3 USDC on Base.

Discovering Integrations

Use the GET /api/v3/clients/me/integrations/yield-xyz-borrow/integrations endpoint to list the lending protocols, the networks each supports and the actions each exposes (including the argument schema per action). For complete API documentation, see the API reference.
Integration ids look like aave-borrow, morpho-blue-borrow, sparklend-borrow and lista-borrow; use the ids the endpoint returns rather than a fixed list. Use GET .../integrations/{integrationId} for one integration.

Discovering Markets

Use the GET /api/v3/clients/me/integrations/yield-xyz-borrow/markets endpoint to list lending markets. By default only markets you enabled in the Yield.xyz dashboard are returned (scope=enabled); pass scope=all to browse everything Yield.xyz supports. For complete API documentation, see the API reference.
Each market carries the fields you need to render a lending UI: loanToken, collateralTokens[] (with maxLtv, liquidationThreshold, liquidationPenalty, supplyRate), borrowRate, availableLiquidity, utilizationRate, isBorrowEnabled, minLoan and the fee settings. Treat market ids as opaque values returned by GET /markets (for example aave-borrow-base-0x833589fcd6edb6e08f4c7c32d4f71b54bda02913 for USDC on Base); they embed the Yield.xyz network slug, not the CAIP-2 chain id, so do not build them yourself.
If scope=enabled returns an empty list, no markets are enabled for your project yet. Enable them in the Yield.xyz dashboard, the same way you enable yield opportunities. Enabling only affects what GET /markets lists by default; actions can be built for any market id.

Supplying Collateral

To supply, use the POST /api/v3/clients/me/integrations/yield-xyz-borrow/actions endpoint to create the action and get the transaction(s) to sign. You’ll then sign each with the Enclave MPC API and report the hash back. For complete API documentation, see the API reference.

Step 1: Create the Supply Action

Pool-based protocols (Aave) require tokenAddress on supply and withdraw: the market’s loanToken.address to supply the loan asset, or one of collateralTokens[].token.address to supply a different collateral. Isolated-market protocols (Morpho Blue) infer it from marketId. GET .../integrations/{integrationId} returns the exact JSON schema for every action’s args.
Take note of data.id (the action id), each transaction’s id, and hasNextStep. A step can contain several transactions (here the ERC-20 approval and the supply), which you sign and submit in order, waiting for each to confirm. Some actions add further steps (hasNextStep: true), fetched with the step endpoint below. Yield.xyz builds the transactions even if the wallet does not hold the tokens yet; the balance check happens on-chain.

Step 2: Sign and Broadcast with the Enclave MPC API

signablePayload for EVM_TRANSACTION is a JSON string of the unsigned transaction. Parse it and pass the fields to the Enclave MPC API eth_sendTransaction method, which signs and broadcasts, returning the transaction hash.
Remove the gas parameters from the parsed payload if you want Portal to estimate gas for you. If you prefer to broadcast yourself, use eth_signTransaction instead and send the signed raw transaction as signedPayload in the next step, and Yield.xyz will broadcast it.

Step 3: Submit the Transaction Hash

Report the hash to Yield.xyz with POST /api/v3/clients/me/integrations/yield-xyz-borrow/transactions/{transactionId}/submit so it can track confirmation and unlock the next step. For complete API documentation, see the API reference.
The response includes the transaction status and an explorer link.

Step 4: Fetch the Next Step

When the action has hasNextStep: true, wait for the submitted transaction to confirm, then call POST /api/v3/clients/me/integrations/yield-xyz-borrow/actions/{id}/step to get the next transaction(s) and repeat steps 2–3. You can check progress at any time with GET .../actions/{id}. For complete API documentation, see the API reference.
The action is complete when status is SUCCESS and hasNextStep is false.

Borrowing

Borrowing uses the same action flow with "action": "borrow". Supplied assets on Aave are collateral by default; on other integrations, or if you disabled it, run an enableCollateral action first. You can also combine both in one flow with supplyAndBorrow.
Every action response carries metadata.predictedHealthFactor and metadata.predictedLtv. Show these to the user before they sign: a health factor at or below 1 means the position can be liquidated. The exact args each action accepts (amount, amountRaw, repayAll, tokenAddress, targetLtv and so on) are described per integration in GET .../integrations/{integrationId}.

Checking Positions

Retrieve a user’s position on an integration + network with the GET /api/v3/clients/me/integrations/yield-xyz-borrow/positions endpoint. For complete API documentation, see the API reference.
Each balance lists pendingActions, the actions currently available for that balance, with pre-filled args you can pass straight to POST .../actions.

Repaying and Withdrawing

Repay debt with "action": "repay" (pass "repayAll": true to clear the position, which avoids dust from accrued interest), then withdraw collateral with "action": "withdraw". Both follow the same sign → submit → step flow.

Action History and Liquidations

List a user’s past actions with GET /api/v3/clients/me/integrations/yield-xyz-borrow/actions?address=0xYourAddress (filter by integrationId, action or status), and their liquidation history with GET .../positions/liquidations?integrationId=morpho-blue-borrow&network=eip155:1&address=0xYourAddress (Morpho Blue integrations only). For complete API documentation, see the actions and liquidations references.

Transaction Processing

Lend & borrow actions can require multiple transactions across multiple steps. Process them sequentially: sign each with the Enclave MPC API, submit its hash, wait for on-chain confirmation (e.g. eth_getTransactionReceipt), then request the next step.
For account abstraction enabled Portal clients, eth_sendTransaction returns a user operation hash. Resolve it with GET /api/v3/clients/me/chains/{chain}/transactions/{userOpHash} and submit evmUserOperation.receipt.hash (the on-chain transaction hash) to Yield.xyz, never the user operation hash. Use the smart-account address (the client’s eip155 address) as address in every Borrow call.

Handling Errors

Yield.xyz Borrow errors are returned as Portal errors:
  • 400: invalid request (the message names the field), an unsupported chain id, a request Yield.xyz rejected (its message is passed through), or a Yield.xyz API key that is missing or was rejected
  • 404: unknown market, integration, action or transaction id
  • 429: Yield.xyz rate limit hit; back off and retry
  • 503: Yield.xyz is unreachable or failed upstream
  • 500 with id: INTEGRATION_RESPONSE_SCHEMA_DRIFT: Yield.xyz changed a response shape and Portal did not forward it. Treat it as a temporary outage of that feature; see Error codes
Response enumerations (action and transaction statuses, action types) may gain values over time; treat values you do not recognize as opaque rather than failing.

Best Practices

  1. Show the predicted health factor and LTV from metadata before the user signs a borrow or withdraw
  2. Process transactions sequentially and wait for confirmation before requesting the next step
  3. Use repayAll when closing a position so accrued interest does not leave dust
  4. Enable only the markets you support in the Yield.xyz dashboard so GET /markets returns exactly what your UI offers
  5. Handle INTEGRATION_RESPONSE_SCHEMA_DRIFT as a feature outage rather than a user error
  6. Keep gas on the wallet: every step is an on-chain transaction

Supported Networks

Lending integrations run on mainnets only; the exact list per protocol is returned by GET /api/v3/clients/me/integrations/yield-xyz-borrow/integrations (networks[], as CAIP-2). Aave V3 covers the major EVM chains (Ethereum eip155:1, Base eip155:8453, Arbitrum eip155:42161, Optimism eip155:10, Polygon eip155:137, Avalanche eip155:43114, and more); Morpho Blue covers Ethereum, Base and other EVM chains; SparkLend is Ethereum-only; Lista runs on BNB Chain (eip155:56) and Ethereum.

Next Steps