Plyra structures, stress-tests, and validates a credit pool before it goes to deal, and can settle it onchain when you are ready. The primary surface is the Plyra Workbench: describe a pool or paste a real prospectus, and the deterministic engine returns a Senior / Mezzanine / Equity tranche stack, risk-adjusted return per tranche, loss scenarios, and a line-by-line diff of the document against its own structure. The onchain protocol is the settlement layer underneath: the proof that a validated structure can be issued, tranched, and traded for real.
These docs are organized in two tracks. Track one covers the Workbench and the engine that powers it. Track two covers the onchain settlement protocol (Forge, Shield, Nexus, Trade) and its contracts. If you are a structurer or credit analyst sizing a pool, start with track one. You do not need a wallet, a testnet, or any onchain setup to get full value from the engine.
This quick start is for the onchain settlement layer (track two). If you only want to structure and validate a pool, you do not need any of these steps: see Validate your first prospectus in 60 seconds instead.
Use the Connect button in the header and switch to Avalanche Fuji if prompted.
Use the Avalanche Fuji faucet for test AVAX.
Use the app Faucet button to mint 100,000 test mUSDC. It has no real value.
Open Earn, Protect, Trade, Pools, or Nexus depending on what you want to test.
Forge splits one credit vault into Senior, Mezzanine, and Equity risk layers. Senior is paid first and absorbs losses last. Equity absorbs losses first and targets higher yield.
Yield flows top-down through tranches. Losses flow bottom-up. The contract tracks shares and claimable yield using pull-based accounting.
Shield lets a buyer pay premium for protection and a seller post collateral. If a credit event is confirmed, settlement pays the buyer.
CDS pools quote protection from pool liquidity. As utilization rises, spreads rise, making protection more expensive.
Nexus tracks collateral and obligations. Accounts must stay above the configured liquidation threshold.
AI contracts publish informational risk scores, proposals, queues, and detections with timelocks and review paths. They are not investment recommendations.
The fastest way to understand Plyra is to run it on a real deal. You need no wallet, no testnet, and no signup. Everything below runs in the Workbench against the deterministic engine.
Go to /workbench. This is the analyst desk: structure a pool on the left, read the suggested tranche stack, scenarios, and credit memo on the right.
Use the Load example: control to drop in a sample pool (solar, auto, or consumer). The engine computes a full Senior / Mezzanine / Equity structure instantly. No data of your own required.
Scroll to the validate box and paste deal terms into the Prospectus text area. You can paste a cover-page capital-structure table and the transaction summary from any public ABS offering document.
Press Validate against engine. Plyra extracts the document's claimed tranches and sizing, runs its own structure on the same pool, and shows a field-by-field diff: where the deal's stated terms agree with the engine and where they diverge.
The headline tells you how many fields fall inside tolerance. Agreement means the deal's claimed structure is consistent with what the engine would have built. Divergence flags exactly which terms to diligence.
The engine takes a pool description and returns a defensible structure using standard structured-credit math. Nothing here is a black box: each number is a closed-form calculation off your inputs and the asset-class defaults, so a skeptic can reproduce every figure by hand. The steps below are the methodology in plain language.
From the pool's expected loss and loss volatility, the engine sizes a Senior / Mezzanine / Equity stack. Subordination is set so the Senior attachment point sits a comfortable multiple above expected loss, the Mezzanine absorbs the next band, and the Equity takes first loss. Attachment and detachment points define each tranche's loss-absorbing window.
Lifetime expected loss on the pool is the cumulative default rate multiplied by loss given default (LGD = 1 minus recovery). A solar pool with a 6% cumulative default and 55% LGD carries roughly 3.3% expected lifetime loss. The engine uses mid-market defaults per asset class when a field is unstated, and every assumption is surfaced so you can override it.
For each rated tranche the engine computes modified duration (the price sensitivity to a parallel yield shift, in years) and DV01 (the dollar value of a one-basis-point move). These read the interest-rate risk of holding a tranche, separate from its credit risk, and let a desk compare tranches on a like-for-like rate basis.
Each tranche's coupon is netted against its expected loss to give a risk-adjusted return: what the tranche is expected to earn after credit losses are absorbed in the waterfall. This is how you compare a thin Senior coupon against a fat Equity coupon honestly, rather than chasing headline yield.
The breakeven loss rate for a tranche is the pool loss level at which that tranche's return goes to zero, the cumulative loss it can withstand before its principal is impaired. A wide gap between expected loss and a tranche's breakeven is the cushion; a narrow gap is the flag. The breakeven is the single most useful number for sizing first-loss protection.
src/lib/analyst/engine.ts and src/lib/analyst/prospectus.ts. The exported analyzePool(input) function returns the full AnalysisResult described in the Analyst API section.Document-vs-engine is the validation step. When you paste a prospectus, Plyra extracts the deal's claimed terms exactly as written, then runs its own deterministic structure on the same pool. The diff compares the two side by side: what the document claims, what the engine independently produced, and whether they agree. It is a second opinion on a deal's stated structure, not a rewrite of it.
| What it compares | The document's claimed tranche sizing and expected loss against the engine's independently computed values for the same pool. |
| Sizing tolerance | Tranche sizing within roughly 3 percentage points of the engine is read as agreement. A Senior claimed at 78% against an engine Senior of 80% agrees; an 8-point gap diverges. |
| Expected-loss tolerance | Pool expected loss within roughly 1.5 percentage points of the engine is read as agreement. Wider gaps flag a difference in default or recovery assumptions worth diligencing. |
| Agreement | Inside both tolerances means the deal's claimed structure is consistent with standard structured-credit math. It does not mean the deal is good, only that the terms are internally coherent. |
| Divergence | Outside tolerance flags exactly which field disagrees, so you can ask why: thinner subordination than the loss profile warrants, an aggressive recovery assumption, or a coupon that does not clear expected loss. |
| Missing fields | If the document does not state a value, the extractor returns n/a for it rather than inventing one, and notes what was missing. The diff only judges fields the document actually provides. |
The same engine that powers the Workbench is reachable as a set of HTTP endpoints, so a fintech can wire pre-deal structuring and prospectus validation directly into its own origination pipeline instead of using the dapp. All three endpoints accept a JSON body via POST. The structure and prospectus endpoints are pure functions of their input and return JSON; the memo endpoint streams. Rate limits apply per IP (the prospectus extractor is the tightest, since it is the heaviest call); a 429 means wait a minute and retry.
Send a pool description; receive the deterministic structure. The body is { pool } where pool is a PoolInput(asset class, pool size, weighted coupon, term, expected default, recovery, and so on; unstated fields fall back to mid-market defaults). The response is the full AnalysisResult JSON: the Senior / Mezzanine / Equity stack with attachment points, per-tranche risk-adjusted return, breakeven loss rates, DV01 and modified duration, and the pool-level expected loss. Because the engine is deterministic, the same pool always returns the same structure.
curl -X POST https://app.plyra.io/api/analyst/structure \
-H "Content-Type: application/json" \
-d '{
"pool": {
"assetClass": "solar-loans",
"poolSize": 50000000,
"numLoans": 200,
"grossCouponPct": 8.5,
"termYears": 20,
"annualDefaultRatePct": 6.0,
"recoveryRatePct": 45
}
}'
# -> AnalysisResult JSON: tranches, expectedLoss, breakeven, dv01, durationSend raw offering-document text; receive the extracted claim and the diff. The body is { text }. The response is { claim, diff }: claim is the deal's stated terms extracted exactly as written (a ProspectusClaim, with n/a for any field the document does not provide), and diff is the field-by-field comparison against the engine (a ProspectusDiff carrying the overall agreement flag and per-field results, the same shape the Workbench renders). See Reading the diff for the tolerances.
curl -X POST https://app.plyra.io/api/analyst/prospectus \
-H "Content-Type: application/json" \
-d '{ "text": "Class A Notes ... 80.0% ... Class B ... 12.0% ... residual ..." }'
# -> { claim, diff } : extracted terms + field-by-field agreementSend a pool and its computed analysis; receive a streamed credit memo. The body is { pool, analysis } (typically the same AnalysisResult returned by the structure endpoint). The response is a server-sent-events stream of the memo text as it is written: a concise institutional credit memo grounded only in the supplied numbers, never recomputed or invented. Read it as an SSE stream and append each chunk.
curl -N -X POST https://app.plyra.io/api/analyst \
-H "Content-Type: application/json" \
-d '{ "pool": { /* PoolInput */ }, "analysis": { /* AnalysisResult */ } }'
# -> text/event-stream: credit memo, streamed chunk by chunkThe engine is a structuring and stress-testing tool, not a rating agency, an underwriter, or an adviser. Knowing where its assumptions come from is part of trusting its output. The points below are the boundaries.
| Non-advisory | Plyra assesses structure and risk. It does not provide investment advice, recommend allocations, or opine on whether a deal is a good investment. The reader makes every capital decision. |
| Mid-market defaults | When a pool field is unstated (recovery rate, default timing, servicing fee, and similar), the engine fills it with a mid-market default for that asset class so it can produce a structure. Override any default with your own number; the output is only as good as the inputs. |
| Deterministic, not predictive | The same pool always returns the same structure. The engine models a structure consistent with the stated assumptions; it does not forecast actual losses, which depend on realized borrower behavior and macro conditions. |
| Extraction reads only the text | The prospectus extractor records what the document states and returns n/a for anything missing. It does not infer or model figures the document does not provide, so a sparse document yields a sparse claim. |
| Standard math, simplifying assumptions | Duration, DV01, expected loss, and breakeven use standard closed-form structured-credit formulas with simplifying assumptions (for example, flat-rate and level-loss timing). They are decision-support estimates, not a full cash-flow waterfall model. |
| Settlement is separate | The engine and the onchain protocol are independent. Validating a structure here does not issue, list, or settle anything onchain. The settlement layer (track two) is where a validated structure can be tranched and traded. |
Everything below is the onchain settlement layer: the second act, where a structure that checks out in the Workbench can be issued, tranched, protected, and traded for real. It runs on Avalanche Fuji testnet today. The user guides, contracts reference, SDK, and runbooks that follow are unchanged from the protocol build; they document how the rails work, not the pre-deal analyst flow above.
| Where | Earn (`/forge`) and vault detail pages. |
| Use case | Deposit mUSDC into Senior, Mezzanine, or Equity tranches. |
| Flow | Select vault -> select tranche -> enter amount -> approve mUSDC -> invest. |
| Position | You receive ERC-20 tranche tokens and mirrored vault shares. |
| Yield | When yield is available, anyone may trigger the waterfall. Users then claim yield from their tranche. |
| Withdrawal | Withdrawals burn tranche tokens and return underlying when the vault status permits it. |
Forge tranche positions are ERC-20 tokens. Wallets do not always discover testnet tokens automatically, so you may need to import the Senior, Mezzanine, or Equity token address manually after investing.
Go to Earn, open the vault you invested in, and find the tranche row for Senior, Mezzanine, or Equity.
Use the tranche token address shown by the app or read it from the vault's getTrancheParams(trancheId).token field.
In MetaMask, Core, Rabby, or another EVM wallet, choose Import token / Add custom token on Avalanche Fuji.
Paste the tranche token contract address. The wallet should fill symbol and decimals if it can read the token metadata.
Each vault has separate Senior, Mezzanine, and Equity token contracts, so import every tranche token you want to see.
| Senior tranche | trancheId 0 |
| Mezzanine tranche | trancheId 1 |
| Equity tranche | trancheId 2 |
| Decimals | 18 decimals in the current Fuji deployment. |
| Network | Avalanche Fuji. If the wallet is on another network, the token may appear missing. |
| Trading | Imported tranche tokens can be transferred as ERC-20s. App-level trading uses the Trade page and SecondaryMarketRouter. |
| Where | Protect (`/shield`) and CDS detail pages. |
| Buyer | Pays premium and receives payout if a qualifying credit event settles. |
| Seller | Posts collateral and earns premium while bearing credit-event payout risk. |
| Bilateral CDS | Single buyer and seller per contract in the current MVP. |
| Premiums | The current bilateral contract uses fixed-rate premium terms. |
| Settlement | Credit events are oracle-gated before settlement paths execute. |
| Where | Pools (`/pools`) and pool detail pages. |
| LPs | Deposit mUSDC as pool liquidity and receive pool shares. |
| Buyers | Buy protection directly from pool liquidity. |
| Pricing | Premiums are quoted from utilization-based bonding curve terms. |
| Utilization | Protection sold divided by available pool assets. Higher utilization means higher quoted spreads. |
| Cooldown | LP withdrawals respect protocol cooldown and collateralization rules. |
| Where | Nexus (`/nexus`) under Trade markets. |
| Current UI | Open a margin account and manage local mUSDC collateral on Fuji. |
| Contract design | NexusHub supports collateral accounting, obligations, liquidation, and cross-chain attestation hooks. |
| Health factor | Displayed from onchain margin ratio and health checks. |
| Liquidation | Unhealthy accounts can be liquidated by permissionless callers. |
| Cross-chain | Designed for Avalanche ICM/Teleporter attestations; current app remains Fuji-focused. |
| Where | Trade (`/trade`). |
| Swap | Use live token selectors for mUSDC and deployed tranche tokens. |
| Swap & Reinvest | Sell one token path and reinvest into a selected Forge vault/tranche. |
| Approval | The app checks allowance and prompts router approval when needed. |
| Slippage | Expected and minimum output are shown when a router quote is available. |
| AI dashboard | `/ai` displays risk scores, credit-event queues, liquidation monitoring, and strategy proposals. |
| Chat | The Plyra assistant is mounted across the app and receives page, wallet, vault, pool, CDS, and position context. |
| Position questions | When a wallet is connected, chat can summarize factual deposits, claimable yield, and buyer-side CDS protection. |
| Guardrail | The assistant must not recommend trades, allocations, or whether a position is a good idea. |
| Missing data | If a wallet is disconnected or data is unavailable, the assistant should say so plainly. |
AI Layer AIAnalyst | AIStrategyOptimizer | AIKeeper | AICreditEventDetector Yield Layer YieldVault | YieldVaultFactory | StrategyRouter | LPIncentiveGauge Composability Layer HedgeRouter | PoolRouter | FlashRebalancer | SecondaryMarketRouter Core Credit Layer Forge structured credit vaults Shield bilateral CDS and AMM pools Nexus margin and collateral accounting Avalanche Fuji C-Chain Chain ID 43113 | mUSDC test collateral | public deployed addresses
| ForgeFactory | 0x546adc848B9fB7Eb4328B1F4a639803E4AbD6DD6 |
| ShieldFactory | 0x3faB3a968Fb797d919edFC951C584Bf4628f0bb8 |
| CDSPoolFactory | 0x07240A23ADD639C6bC664Ade533e1bF4fCff6765 |
| NexusHub | 0x9E02F422626F597e6E04ec8cA3b2D0860C4FbFF5 |
| HedgeRouter | 0xE90C21Ae5c25c690aa9D857641f443933aF17CB2 |
| YieldVaultFactory | 0xA44D00ff6f98439FE545F887B095C446c196C431 |
| StrategyRouter | 0x1ca9652AC2a5c5807CEe4Ddd27DEAe368c09b9bC |
| SecondaryMarketRouter | 0xA56839826c16678C8018254AACc8c70d3763a8FA |
| AIAnalyst | 0x7EEAA78B562E7CC3666B189d2Ef8Afdb8D80BE4D |
| MockUSDC | 0x85F2106e0AbF059f36D1a794323dB4F8a1dDF577 |
| ProtocolTreasury | 0x85FFff0596681761dDb1C282827cd742C2F3E002 |
Full deployment metadata is maintained in the repository docs and SDK address map.
Plyra is designed to support Avalanche eERC privacy as an encrypted tranche-token mode for future Forge vaults. The first target is private Senior, Mezzanine, and Equity position balances while keeping aggregate vault analytics and auditor-ready compliance paths intact.
| First target | Encrypted Forge vaults using eERC Standalone tranche tokens. |
| Why | Institutional users should not leak position size, tranche exposure, or transfer amount through public ERC-20 balances. |
| What stays public | Vault metadata, aggregate TVL, risk state, tranche terms, and market-level analytics. |
| What gets encrypted | User tranche token balances and transfer amounts at the token layer. |
| Main constraint | ForgeVault still needs internal plaintext share mirrors for waterfall accounting, so arbitrary encrypted P2P transfers need a safe mirror-sync design. |
| Recommended v1 | Add encrypted vaults as a separate mode, gate eERC registration through investor verification, and start on Fuji before mainnet. |
The @meridianprotocol/sdk package is the onchain integration layer for the settlement protocol: addresses, ABIs, and constants for calling Forge, Shield, Nexus, and Trade with viem. It is distinct from the Analyst API, which is the HTTP surface for the pre-deal engine and needs no wallet or chain.
npm install @meridianprotocol/sdk viemimport { createPublicClient, http, parseUnits } from "viem";
import { avalancheFuji } from "viem/chains";
import { ADDRESSES, ForgeFactoryAbi, ForgeVaultAbi, ERC20Abi } from "@meridianprotocol/sdk";
const client = createPublicClient({
chain: avalancheFuji,
transport: http("https://api.avax-test.network/ext/bc/C/rpc"),
});
const addresses = ADDRESSES[43113];
const vaultCount = await client.readContract({
address: addresses.forgeFactory,
abi: ForgeFactoryAbi,
functionName: "vaultCount",
});
// Before investing, approve mUSDC to the selected ForgeVault.
await walletClient.writeContract({
address: addresses.mockUSDC,
abi: ERC20Abi,
functionName: "approve",
args: [vaultAddress, parseUnits("1000", 18)],
});
await walletClient.writeContract({
address: vaultAddress,
abi: ForgeVaultAbi,
functionName: "invest",
args: [0, parseUnits("1000", 18)], // 0 = Senior
});cd frontend
npm install
npm run build
npx playwright testforge build
forge test
forge coverage --report summarycd sdk
npm install
npm run buildcd indexer
npm install
npm run codegen
npm run dev| No real capital | The public app is on Avalanche Fuji and uses mock test collateral. |
| No advice | AI outputs and chat responses are informational only. |
| User-signed transactions | Users approve and submit transactions from self-custodial wallets. |
| Oracle risk | Credit events and risk scores depend on configured oracle/reporting contracts. |
| Contract risk | Mainnet launch should follow audit completion, deployment review, and operational runbooks. |
| Compliance docs | The app links a compliance one-pager for institutional pilot review. |