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.
Define the market parameters for the cbBTC/pathUSD market on Tempo. These parameters uniquely identify the Morpho Blue market your app will interact with.
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.
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()});
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.
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.
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 collateralconst {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.
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).