Skip to main content
Morpho is a decentralized lending protocol deployed on Tempo that enables capital-efficient borrowing. Using the cbBTC/pathUSD market, your app can let users supply cbBTC as collateral and borrow pathUSD against it. This recipe demonstrates how to integrate Morpho lending into your app using Privy embedded wallets and the Morpho SDK.

Install dependencies

npm install @privy-io/node viem @morpho-org/morpho-sdk @morpho-org/blue-sdk

1. Configure the Morpho market

Define the market parameters for the cbBTC/pathUSD market on Tempo. These parameters uniquely identify the Morpho Blue market your app will interact with.
import {MarketParams} from '@morpho-org/blue-sdk';

const TEMPO_CHAIN_ID = 4217;

const MORPHO_BLUE_ADDRESS = '0x10EE9AAC980A180dd4DcFc96C746d60B0EA88f97';
const CBBTC_ADDRESS = '0x20C000000000000000000000c412Ec89D0c08be5';
const PATHUSD_ADDRESS = '0x20C0000000000000000000000000000000000000';

const cbbtcPathUsdMarket = new MarketParams({
  loanToken: PATHUSD_ADDRESS,
  collateralToken: CBBTC_ADDRESS,
  oracle: '0xa59e9ACD8499343ae7b944df898fc20388ACD245',
  irm: '0x112fd4042E442C3C12C67AD23587b0afe36eB74E',
  lltv: 770000000000000000n // 77% loan-to-value
});
These parameters are fixed for each Morpho Blue market — they are set by the market creator at deployment and cannot be changed. The lltv (liquidation loan-to-value) determines the maximum ratio of debt to collateral before a position becomes liquidatable. To find these values for any market, query the Morpho Blue contract or look them up on the Morpho app.
Both cbBTC and pathUSD use 6 decimals on Tempo. When specifying amounts, 1_000_000n equals 1 cbBTC or 1 pathUSD. Note that cbBTC uses 8 decimals on other chains but 6 on Tempo.

2. Set up the Privy wallet and viem client

Create a viem wallet client from the Privy embedded wallet and extend it with the Morpho SDK. The morphoViemExtension adds Morpho market methods directly to the client.
import {PrivyClient} from '@privy-io/node';
import {createViemAccount} from '@privy-io/node/viem';
import {createWalletClient, createPublicClient, http} from 'viem';
import {tempo} from 'viem/chains';
import {morphoViemExtension} from '@morpho-org/morpho-sdk';

const privy = new PrivyClient({
  appId: process.env.PRIVY_APP_ID!,
  appSecret: process.env.PRIVY_APP_SECRET!
});

const account = createViemAccount(privy, {
  walletId: 'insert-wallet-id',
  address: 'insert-wallet-address'
});

const client = createWalletClient({
  account,
  chain: tempo,
  transport: http()
}).extend(morphoViemExtension({supportSignature: true}));

const publicClient = createPublicClient({
  chain: tempo,
  transport: http()
});

3. Supply collateral and borrow

Use the Morpho SDK to construct and send transactions atomically via Bundler3. The SDK handles ERC-20 approvals, Morpho setAuthorization for the GeneralAdapter1, and Permit/Permit2 signatures automatically through its requirements system.
const market = client.morpho.marketV1(cbbtcPathUsdMarket, TEMPO_CHAIN_ID);

const collateralAmount = 100_000n; // 0.1 cbBTC (6 decimals on Tempo)
const borrowAmount = 4_000_000_000n; // 4,000 pathUSD (6 decimals) — well under 77% LLTV

const userAddress = client.account.address;
const positionData = await market.getPositionData(userAddress);

const {buildTx, getRequirements} = market.supplyCollateralBorrow({
  amount: collateralAmount,
  borrowAmount,
  userAddress,
  positionData
});

// Resolve requirements (ERC-20 approvals, Morpho authorizations, Permit signatures)
let signature;
for (const req of await getRequirements()) {
  if ('sign' in req) {
    signature = await req.sign(client, userAddress);
  } else {
    const hash = await client.sendTransaction(req);
    await publicClient.waitForTransactionReceipt({hash});
  }
}

// Execute the atomic supply + borrow transaction
const hash = await client.sendTransaction(buildTx(signature));
const receipt = await publicClient.waitForTransactionReceipt({hash});
console.log('Supply + borrow tx:', receipt.transactionHash);
The SDK bundles supplyCollateral and borrow into a single atomic transaction via Bundler3. It also includes an LLTV buffer check to prevent the new position from being instantly liquidatable.
Always verify that the borrow amount stays safely below the liquidation threshold. The market LLTV is 77%, meaning a position is liquidated when the debt value exceeds 77% of the collateral value. Use a safety buffer (e.g., borrow at most 70% of max) to avoid liquidation from price movements.

4. Repay and withdraw collateral

To close the position, repay the borrowed pathUSD and withdraw the cbBTC collateral. The SDK bundles repay and withdraw into a single atomic transaction (repay executes first, then withdraw).
const fresh = await market.getPositionData(userAddress);

// Repay full debt and withdraw all collateral
const {buildTx, getRequirements} = market.repayWithdrawCollateral({
  shares: fresh.borrowShares, // repay full debt using shares
  withdrawAmount: fresh.collateral, // withdraw all collateral
  userAddress,
  positionData: fresh
});

let signature;
for (const req of await getRequirements()) {
  if ('sign' in req) {
    signature = await req.sign(client, userAddress);
  } else {
    const hash = await client.sendTransaction(req);
    await publicClient.waitForTransactionReceipt({hash});
  }
}

const hash = await client.sendTransaction(buildTx(signature));
const receipt = await publicClient.waitForTransactionReceipt({hash});
console.log('Repay + withdraw tx:', receipt.transactionHash);
Repaying by shares instead of a fixed asset amount ensures the full debt is repaid, including any interest that accrued since the borrow.

5. Check position health

Monitor a position’s health factor to alert users before liquidation risk becomes critical. The AccrualPosition returned by getPositionData includes a built-in healthFactor getter (WAD-scaled).
const WAD = 10n ** 18n;

const positionData = await market.getPositionData(userAddress);

// healthFactor is WAD-scaled: > 1e18 means healthy, < 1e18 means liquidatable
const healthFactor = positionData.borrowAssets > 0n ? positionData.healthFactor : null;

console.log('Health factor:', healthFactor ? Number(healthFactor) / 1e18 : 'No debt');
console.log('Max borrow (pathUSD):', Number(positionData.maxBorrowAssets) / 1e6);
console.log('Current LTV:', positionData.ltv ? Number(positionData.ltv) / 1e18 : 0);

Market parameters

ParameterValue
CollateralcbBTC (0x20C000000000000000000000c412Ec89D0c08be5)
Loan tokenpathUSD (0x20C0000000000000000000000000000000000000)
LLTV77%
OracleChainlinkOracleV2 (0xa59e9ACD8499343ae7b944df898fc20388ACD245)
ChainTempo Mainnet (chain ID 4217)
Morpho Blue0x10EE9AAC980A180dd4DcFc96C746d60B0EA88f97

Morpho SDK

TypeScript SDK reference for Morpho protocol interactions

Sending transactions on Tempo

Create embedded wallets and send transactions on Tempo