Skip to main content
CONFIDENTIAL & PROPRIETARY © 2025 Inkwell Finance, Inc. All Rights Reserved. This document is for informational purposes only and does not constitute legal, tax, or investment advice, nor an offer to sell or a solicitation to buy any security or other financial instrument. Any examples, structures, or flows described here are design intent only and may change.

Overview

This guide walks through the technical steps for integrating Leviathan Embedded Lending into your protocol. The integration is SDK-driven — your frontend calls the @leviathan/sdk/embedded package, which handles all communication with Leviathan’s on-chain programs.
PrerequisitesBefore starting integration, your protocol must complete the onboarding process. Onboarding establishes your protocol’s whitelist, approved functions, and revenue split configuration on-chain.

SDK Installation

Install the Leviathan SDK:
pnpm add @leviathan/sdk
The SDK requires @solana/web3.js as a peer dependency:
pnpm add @solana/web3.js

Core Client

The EmbeddedLendingClient is your primary integration surface:
import { EmbeddedLendingClient } from "@leviathan/sdk/embedded";
import { Connection, PublicKey } from "@solana/web3.js";

const connection = new Connection("https://api.mainnet-beta.solana.com");
const protocolId = new PublicKey("your-protocol-whitelist-pda");

const client = new EmbeddedLendingClient({
  connection,
  protocolId,
});
The protocolId is the on-chain address of your protocol’s whitelist configuration, created during onboarding.

Key Operations

Check Credit Line Eligibility

Before offering lending features, check whether a user qualifies:
const userWallet = new PublicKey("user-wallet-address");

const eligibility = await client.checkEligibility(userWallet);

if (eligibility.eligible) {
  // User qualifies — show lending UI
  console.log(`Credit limit: ${eligibility.creditLimit}`);
  console.log(`Rate tier: ${eligibility.rateTier}`);
} else {
  // User does not qualify — hide or disable lending features
  console.log(`Reason: ${eligibility.reason}`);
}
Eligibility is determined by the user’s on-chain credit score from leviathan-score. Users with insufficient history or low scores may not qualify.

Create Agreement

Before a user can borrow, they must accept the lending agreement:
const agreement = await client.createAgreement({
  borrower: userWallet,
  creditLimit: eligibility.creditLimit,
  rateBps: eligibility.rateBps,
  termDays: 180,
  agreementHash: "sha256-of-legal-document",
});

// User signs the agreement transaction
const signedTx = await walletAdapter.signTransaction(agreement.transaction);
await connection.sendRawTransaction(signedTx.serialize());
The agreement links the legal terms (hashed) with the on-chain credit line parameters. Both parties can verify that the on-chain state matches the signed document.

Originate a Loan

When a user draws on their credit line:
const loan = await client.originateLoan({
  borrower: userWallet,
  amount: 10_000_000, // in smallest units
  purpose: "margin-trade", // protocol-defined purpose tag
});

// User signs the loan origination transaction
const signedTx = await walletAdapter.signTransaction(loan.transaction);
await connection.sendRawTransaction(signedTx.serialize());

console.log(`Loan PDA: ${loan.loanPda}`);
console.log(`Capital available for use within protocol`);
Once originated, capital is deployed into a policy-gated environment scoped to your protocol’s approved function set.

Validate Capital Usage

Before executing an action with borrowed capital, validate that it conforms to the protocol’s function gate:
const validation = await client.validateAction({
  loanPda: loan.loanPda,
  targetProgram: new PublicKey("target-contract"),
  functionSelector: "swap",
  amount: 5_000_000,
});

if (validation.permitted) {
  // Proceed with the action
} else {
  // Action would be rejected — do not submit
  console.log(`Blocked: ${validation.reason}`);
}
This client-side check mirrors the on-chain enforcement — use it to prevent users from submitting transactions that would be rejected, improving UX.

Query Loan State

Monitor a user’s active loan:
const state = await client.getLoanState(loan.loanPda);

console.log(`Outstanding: ${state.outstandingBalance}`);
console.log(`Repaid: ${state.totalRepaid}`);
console.log(`Repayment cap: ${state.repaymentCap}`);
console.log(`Health: ${state.healthFactor}`);
console.log(`Status: ${state.status}`);

Manage Splitters

Query the revenue split configuration for a loan:
const splitter = await client.getSplitterConfig(loan.loanPda);

console.log(`Repayment share: ${splitter.repaymentPct}%`);
console.log(`Borrower share: ${splitter.borrowerPct}%`);
console.log(`Protocol share: ${splitter.protocolPct}%`);
console.log(`Total routed: ${splitter.totalRouted}`);

Integration Pattern

The recommended integration pattern follows this flow:
┌──────────────────────────────────────────────────────┐
│                 Protocol Frontend                     │
│                                                      │
│  1. Check eligibility ──► Show/hide lending UI       │
│  2. Create agreement  ──► User accepts terms         │
│  3. Originate loan    ──► Capital available           │
│  4. Validate actions  ──► Client-side gate check     │
│  5. Execute actions   ──► On-chain policy enforced   │
│  6. Query state       ──► Show repayment progress    │
│                                                      │
│  SDK handles: PDA derivation, tx construction,       │
│  account lookups, policy checks                      │
│                                                      │
│  On-chain handles: Credit scoring, policy            │
│  enforcement, revenue splitting, loan lifecycle      │
└──────────────────────────────────────────────────────┘
Your protocol frontend is responsible for:
  • Calling the SDK at the right points in your user flow
  • Presenting lending options within your existing UI
  • Handling wallet signing via your existing wallet adapter
  • Displaying loan state and repayment progress
Leviathan’s on-chain programs handle:
  • Credit assessment and eligibility
  • Policy enforcement and function gating
  • Revenue split execution
  • Loan lifecycle state transitions

Requirements

Protocol Requirements

  • Whitelisted — your protocol must be registered through the onboarding process
  • Verifiable revenue — user activity within your protocol must generate verifiable on-chain revenue
  • Contract stability — your protocol’s contract addresses and function signatures should be stable (changes require whitelist updates)

Technical Requirements

  • Solana wallet integration — your frontend must support Solana wallet signing
  • SDK compatibility — TypeScript/JavaScript frontend with @solana/web3.js support
  • RPC access — reliable Solana RPC endpoint for transaction submission and account queries

Error Handling

The SDK provides typed errors for common failure modes:
ErrorMeaning
NotEligibleUser does not meet credit criteria
CreditLineExhaustedUser has reached their borrowing limit
FunctionNotPermittedAction targets a non-approved function
LoanNotActiveAttempting to use capital from a non-active loan
PolicyViolationTransaction violates protocol policy constraints
Handle these in your UI to provide clear feedback to users.

Next Steps