Moonshift docs
Moonshift turns GPUs into assets on the XRP Ledger. Anyone can rent compute from them, own shares of what they earn, and borrow against those shares. Every payment, payout and loan is a transaction you can look up.
There are three sides to the product, and they share one ledger:
- Compute. Developers send tasks, like chat completions, through one OpenAI compatible endpoint. The router places each task on the GPU that best fits the priority they ask for.
- Shares. Each GPU issues shares. What the GPU earns from compute is paid out to its shareholders.
- Credit. Holders can lock shares and borrow USDC from lending rounds that lenders fund. Loans are priced from the borrower's on-chain history and the GPU's real revenue.
Amounts settle in USDC. The base URL for every route below is https://moonshift-protocol.vercel.app/api.
How the router works
A task is a unit of work: a set of prompts with a token budget, or a number of GPU minutes. You pick a priority and the router does the rest.
Priorities
| Cheapest | The lowest expected cost that still meets your deadline and budget. |
| Balanced | The plan closest to both the cheapest and the fastest at once. This is the default. |
| Fastest | The earliest finish that stays inside your budget. |
For every GPU it can use, the router prices run time, the earliest start that clears booked windows, the chance the capacity is taken back, and what a resume would cost. It can split a task across up to three GPUs. A single streamed reply always runs on one GPU at a time.
The price cap
Before a task starts, you set aside its quote plus a buffer of 10, 25 or 50 percent. That amount is locked on the ledger, so the GPU is sure to be paid and you are sure never to pay more. At settlement each GPU is paid for the work it served and the rest comes back to you in the same batch of transactions. If a task reaches its cap, it pauses until you raise the cap or cancel.
Resume on reclaim
Some capacity can be taken back by its provider with a short warning. When that happens the router saves the task's progress, plans the rest in the same priority, and continues on another GPU. For a chat completion the new GPU picks up from the text already written, so you get one continuous answer. The order's events show the move, and nothing is charged twice.
Lending and borrowing
Lending rounds
Lenders fund rounds. Each round is an XLS-65 single asset vault with a subscription phase, when it takes deposits, and an investment phase, when its capital is lent out. A round has a target APR, a size and a date when lenders can redeem. A first-loss cover sits in front of lenders.
Borrowing
A holder locks GPU shares and borrows USDC from the round that is lending. The loan is an XLS-66 loan with a fixed schedule of payments. Repaying in full releases the shares at once.
- You can never borrow more than you are approved for. An amount above the limit is refused, never shrunk.
- You can borrow against any GPU you hold shares in.
Credit grades
Every borrower has a score from 0 to 100 and a grade from A to E, with a confidence level. The grade sets the APR and how much can be borrowed against the shares. Grade E does not borrow.
Margin calls and liquidation
Each loan has two lines on its loan to value: a margin call line and a liquidation line. A risk keeper checks every open loan against the GPU's live share price. Crossing the margin call line starts a cure window to pay the loan down. Crossing the liquidation line transfers the locked shares to repay the loan. Both are on-chain transactions and both feed back into the borrower's score.
Credit data via Quicknode
Moonshift underwrites from what a wallet has actually done. We read the borrower's XRP Ledger history through Quicknode and turn it into factors: account age, payments in and out, counterparties, trust lines, balance stability and large outflows. Each factor links to the transactions it came from.
| Method | What we use it for |
|---|---|
account_tx | The full payment history, paged by marker. Age, volume, counterparties and repayments. |
account_info | Balance and sequence, for balance stability and whether the account is active. |
account_lines | Trust lines: which assets the account holds and how many issuers it deals with. |
account_objects | Open loans, locked collateral and offers that still bind the account. |
account_offers | Open orders on the book, which commit part of the balance. |
subscribe | A WebSocket on the borrower's account and on ledger closes, so the score updates the moment a transaction lands. |
server_info | Network status: the validated ledger index and the current fee, shown on the credit panel. |
Deep history pages never change, so they are cached and a refresh costs nothing. Our repository's docs/QUICKNODE.md lists each call with a command to reproduce it.
API reference
JSON over HTTPS. Amounts are decimal strings. Routes marked Signed in act for the wallet that signed in on Moonshift; the session is a cookie. Errors look like {"error": {"code": "OVER_LIMIT", "message": "..."}}.
const es = new EventSource("https://moonshift-protocol.vercel.app/api/events"); es.addEventListener("loan", (e) => console.log(JSON.parse(e.data))); es.addEventListener("credit", (e) => console.log(JSON.parse(e.data)));
GPUs and shares
/gpusEvery GPU that passes its health check, with its share price and the last 24 hours of revenue.
[ { "id": "gpu-a", "label": "GPU A", "hw": "NVIDIA T4 16GB", "model": "Qwen/Qwen2.5-1.5B-Instruct", "provider": "Akash Network", "state": "SERVING", "sharePrice": "48.335462", "navPerShare": "49.071536", "revenue24h": "0.297092", "utilizationPct": "100", "holdersCount": 40 } ]
/shares/buySigned inBuy shares of a GPU. Settles on the XRP Ledger order book and returns the validated transaction.
{ "gpuId": "gpu-a", "qty": "50" }
{ "hash": "9F3A01D7B2C64E58A1F0C3B9D2E7A6F41C8B5D0E3F2A1B9C8D7E6F5A4B3CC21E", "result": "tesSUCCESS", "validated": true }
/shares/sellSigned inSell shares back into the book.
{ "gpuId": "gpu-a", "qty": "20" }
{ "hash": "9F3A01D7B2C64E58A1F0C3B9D2E7A6F41C8B5D0E3F2A1B9C8D7E6F5A4B3CC21E", "result": "tesSUCCESS", "validated": true }
/portfolio/meSigned inThe signed-in account: USDC balance, shares per GPU, dividends received and loans.
{ "account": "U_rsinyUoeDm6hGgBPr4n1puN6a89hVfYUq9", "tdxBalance": "450.000000", "shares": [ { "gpuId": "gpu-a", "qty": "300" } ], "dividendsReceived": "23.352900", "loans": [] }
Compute and the router
/v1/chat/completionsOpenAI compatible. Add priority (cheapest, balanced or fastest) and the router picks the GPU. x_ms reports the GPUs used, any moves and the payment.
{ "model": "Qwen/Qwen2.5-1.5B-Instruct", "messages": [ { "role": "user", "content": "Explain VWAP in one line" } ], "max_tokens": 160, "priority": "balanced" }
{ "id": "chatcmpl_ord_7a3f19c2", "object": "chat.completion", "model": "Qwen/Qwen2.5-1.5B-Instruct", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "VWAP is the average price weighted by volume." }, "finish_reason": "stop" } ], "usage": { "prompt_tokens": 0, "completion_tokens": 11, "total_tokens": 11 }, "x_ms": { "order_id": "ord_7a3f19c2", "priority": "balanced", "price_usdc": "0.002000", "gpus": [ "GPU-A" ], "providers": [ "akash" ], "moves": [], "payment": "9F3A01D7B2C64E58A1F0C3B9D2E7A6F41C8B5D0E3F2A1B9C8D7E6F5A4B3CC21E" } }
/router/quotePrice one task in all three modes at once: cost, ETA and the GPUs each plan would use.
{ "kind": "inference", "tokens": 1200, "requests": 4, "deadlineSeconds": null, "budgetUsdc": null }
{ "quoteId": "q_5f1c2a9e", "default": "balanced", "options": { "cheapest": { "mode": "cheapest", "feasible": true, "priceUsdc": "0.001716", "etaSeconds": 36, "providers": [ "akash" ], "parts": [ "<part>" ] }, "balanced": { "mode": "balanced", "feasible": true, "priceUsdc": "0.002000", "etaSeconds": 12, "providers": [ "akash" ], "parts": [ "<part>" ] }, "fastest": { "mode": "fastest", "feasible": true, "priceUsdc": "0.002400", "etaSeconds": 9, "providers": [ "akash" ], "parts": [ "<part>" ] } }, "plansEvaluated": 312, "catalogAsOf": "2026-10-25T08:53:39Z" }
/router/ordersSigned inPlace a task. The price cap is set aside on the ledger first; what the task does not use is refunded at settlement.
{ "kind": "inference", "mode": "balanced", "bufferPct": 25, "maxTokens": 300, "requests": [ [ { "role": "user", "content": "Explain VWAP in one line" } ] ] }
{ "orderId": "ord_7a3f19c2", "status": "paid", "mode": "balanced", "priceUsdc": "0.002000", "capUsdc": "0.002500" }
/router/orders/:id/eventsServer-sent events for one order: quoted, paid, running, token, progress, moved, completed, settled.
[ { "event": "token", "data": { "orderId": "ord_7a3f19c2", "request": 0, "text": " weighted", "index": 41 } }, { "event": "moved", "data": { "from": "gpu-a", "to": "gpu-b", "reason": "RECLAIMED", "resumedAt": 180 } }, { "event": "settled", "data": { "orderId": "ord_7a3f19c2", "refundUsdc": "0.000500" } } ]
/modelsEvery model, the GPU it runs on, VRAM, context length and price per 1M tokens. A model is serving only while its GPU passes its health check.
{ "models": [ { "gpuId": "gpu-a", "modelId": "Qwen/Qwen2.5-1.5B-Instruct", "status": "serving", "vramGb": 5, "contextLength": 4096, "pricePer1MTokens": null, "endpoint": "/v1/chat/completions" } ] }
Lending and credit
/vaultThe lending rounds: the round lending now and the round taking deposits, with assets, debt, cover and APY.
{ "investing": { "round": 1, "phase": "investment", "assetsTotal": "6806.521531", "assetsAvailable": "5608.521531", "debtTotal": "1198.000000", "coverAvailable": "988.500000", "utilizationPct": "17.60", "targetApyPct": "13.19" }, "subscribing": { "round": 2, "phase": "subscription", "assetsTotal": "21785.000000" } }
/vault/depositSigned inDeposit USDC into the round taking deposits (an XLS-65 VaultDeposit).
{ "amount": "250" }
{ "round": 2, "tx": { "hash": "9F3A01D7B2C64E58A1F0C3B9D2E7A6F41C8B5D0E3F2A1B9C8D7E6F5A4B3CC21E", "result": "tesSUCCESS", "validated": true } }
/loans/quoteSigned inPrice a loan against GPU shares: APR, LTV with its margin call and liquidation lines, coverage and the credit profile behind it.
{ "gpuId": "gpu-b", "collateralShares": "100", "principal": "200" }
{ "quoteId": "8d2f0b7e-5c1a-4b2e-9d41-6a0f3e2c1b55", "principal": "200.000000", "collateralValue": "935.400000", "quote": { "decision": "approve", "apr": "0.1180", "ltv": "0.2138", "maxLtv": "0.35", "marginCallLtv": "0.45", "liquidationLtv": "0.55", "coverageRatio": "1.84" }, "terms": { "termSeconds": 1141200, "paymentTotal": 4 }, "credit": { "score": 75, "grade": "B", "confidence": "high" } }
/loans/openSigned inOpen the quoted loan: shares are locked, then an XLS-66 LoanSet pays out the USDC. Above the approved amount the api answers 409 OVER_LIMIT and opens nothing.
{ "quoteId": "8d2f0b7e-5c1a-4b2e-9d41-6a0f3e2c1b55" }
{ "id": "a41c9e02", "status": "open", "principal": "200.000000", "collateralShares": "100", "apr": "0.1180", "txs": { "escrow": "9F3A01D7B2C64E58A1F0C3B9D2E7A6F41C8B5D0E3F2A1B9C8D7E6F5A4B3CC21E", "loanSet": "9F3A01D7B2C64E58A1F0C3B9D2E7A6F41C8B5D0E3F2A1B9C8D7E6F5A4B3CC21E" } }
/loans/:id/paySigned inPay the next installment. /loans/:id/repay with mode full pays the loan off and returns the shares.
{ "mode": "next" }
{ "id": "a41c9e02", "status": "open", "txs": { "pay": "9F3A01D7B2C64E58A1F0C3B9D2E7A6F41C8B5D0E3F2A1B9C8D7E6F5A4B3CC21E" } }
/credit/:network/:addressA credit profile for any XRP Ledger account: score, grade, confidence and every factor, each linked to the transactions behind it.
{ "address": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "source": "quicknode", "score": 74, "grade": "B", "confidence": "high", "features": { "accountAgeDays": { "value": 1412, "points": 10, "txHashes": [ "9F3A01D7B2C64E58A1F0C3B9D2E7A6F41C8B5D0E3F2A1B9C8D7E6F5A4B3CC21E" ] } } }
/eventsOne server-sent events stream for the whole product: tx, usage, dividend, loan, vault, risk and credit events.
[ { "event": "loan", "data": { "id": "a41c9e02", "type": "margin_call" } }, { "event": "credit", "data": { "kind": "PROFILE_CHANGED", "scoreBefore": 72, "score": 75 } } ]
Models
Moonshift serves open models through the OpenAI client you already use. Point it at our base URL, choose a priority, and the router places the request. See every model, its GPU and price on the Models page.
from openai import OpenAI client = OpenAI(base_url="https://moonshift-protocol.vercel.app/api/v1", api_key="unused") r = client.chat.completions.create( model="Qwen/Qwen2.5-1.5B-Instruct", messages=[{"role": "user", "content": "Explain VWAP in one line"}], extra_body={"priority": "balanced"}, # cheapest | balanced | fastest ) print(r.choices[0].message.content) print(r.x_ms) # GPUs used, moves, price, payment hash