diff --git a/api-reference/solve-rfq/overview.mdx b/api-reference/solve-rfq/overview.mdx new file mode 100644 index 0000000..5afc4f1 --- /dev/null +++ b/api-reference/solve-rfq/overview.mdx @@ -0,0 +1,58 @@ +--- +title: "Overview" +description: "Request a firm, liquidity-backed quote through LI.FI Intents, or route a swap against public on-chain liquidity" +--- + +Solve RFQ covers the two ways to get an executable price out of Sprinter. + +| | **LI.FI Intents** | **Swap API** | +|---|---|---| +| **Liquidity** | Sprinter Liquidity — underwritten, reserved for your quote | Public on-chain AMM liquidity | +| **Price** | Firm. Reserved for 15s and filled at exactly that price | Indicative, subject to slippage | +| **Use for** | Redemptions, subscriptions, and any flow where the user is promised a price | Generic token swaps, and as a fallback when no Sprinter route exists | +| **Requires** | Asset onboarded and route configured with Sprinter | Nothing — any supported pair | +| **Base URL** | `https://api.sprinter.tech` | `https://swaps.sprinter.tech/{network}` | +| **Auth** | `X-Auth-Token` header | HTTP Basic | + + +**Default to LI.FI Intents.** It is the path that draws on Sprinter Liquidity, which is what makes an instant fill at a promised price possible. Reach for the Swap API when the pair is not onboarded with Sprinter, or as a fallback when a quote does not return. + + +## LI.FI Intents + +Two calls. The first prices the order and holds the liquidity; the second turns that into a transaction the user signs. + +``` +GET /lifi-intents/rfq → quote (liquidity reserved, 15s) +POST /lifi-intents/transaction → same quote + unsigned open() calldata + → user sends it; Sprinter fills +``` + +| Endpoint | Description | +|----------|-------------| +| [`GET /lifi-intents/rfq`](/api-reference/sprinter/lifi-intents/rfq) | Firm quote backed by reserved Sprinter liquidity | +| [`POST /lifi-intents/transaction`](/api-reference/sprinter/lifi-intents/transaction) | Escrow `open` transaction for a quote | + +Authenticate the RFQ call with your API key in the `X-Auth-Token` header. The transaction call carries the quote itself, so it needs no header. + +The responses follow LI.FI's own [intents API](https://docs.li.fi/lifi-intents/intents-api/request-quote) shapes, with one difference worth coding for: when Sprinter cannot serve a request it returns **`404`**, not a `200` with an empty `quotes` array. + + +Quotes only return for assets Sprinter has onboarded — underwritten, allocated liquidity to, and configured routes for. See the [Asset Issuer quickstart](/quickstart/asset-issuer) for what onboarding involves. + + +## Swap API + +Route a swap against public on-chain liquidity and get back executable call data. No onboarding, no reservation, no firm price. + +| Endpoint | Description | +|----------|-------------| +| [`GET /v1/route`](/api-reference/solve/get-v1route) | Optimal swap route and execution call data | + +See the [Swap API overview](/api-reference/solve/overview) for base URLs, authentication, and the response format. + +## Not this: the Liquidity API + +[Sprinter Liquidity](/api-reference/sprinter/liquidity/overview) exposes the borrow-quote and signing endpoints directly. That surface is for **crosschain solvers** running their own fill infrastructure — it hands you a borrow authorization, not a transaction, and expects you to settle the intent yourself. + +If you are an asset issuer, wallet, or application asking Sprinter for a price, use LI.FI Intents. The RFQ endpoint runs the same pricing and reservation pipeline and returns something you can sign. diff --git a/api-reference/sprinter/lifi-intents/rfq.mdx b/api-reference/sprinter/lifi-intents/rfq.mdx new file mode 100644 index 0000000..cf17ef5 --- /dev/null +++ b/api-reference/sprinter/lifi-intents/rfq.mdx @@ -0,0 +1,156 @@ +--- +title: "Request a LI.FI Intents Quote" +sidebarTitle: "RFQ" +openapi: get /lifi-intents/rfq +--- + +Prices an order against Sprinter liquidity and **reserves that liquidity** for the quote's validity window. The response is shaped like a single element of LI.FI's [request-quote](https://docs.li.fi/lifi-intents/intents-api/request-quote) response, so an existing LI.FI intents client can consume it unchanged. + + +A quote is valid for **15 seconds**. The reservation expires with it. Call [`POST /lifi-intents/transaction`](/api-reference/sprinter/lifi-intents/transaction) immediately — do not cache a quote or show it to a user for confirmation before converting it. + + +## Behaviour + +| | | +|---|---| +| **Exclusivity** | Always exclusive to Sprinter. `metadata.exclusiveFor` returns the filler address | +| **Protocol** | Always `lifi-escrow`. Your API key must be provisioned for it | +| **Quotes returned** | Exactly one, or an error. There is no empty `quotes` array | +| **Amount basis** | `type=ExactInput` (default) reads `amount` as the input; `ExactOutput` reads it as the output | +| **Token defaults** | `srcToken` defaults to the same token symbol as `token`, resolved on the source chain | + +## Errors + +| Status | Meaning | Retry? | +|--------|---------|--------| +| `400` | No route configured for this chain/token pair, or invalid parameters | No — fix the request or ask about onboarding the route | +| `404` | Route exists, but no pool can serve it right now — capacity is reserved by other in-flight quotes, or pricing is unavailable | Yes, after a short backoff. Reservations expire in 15s, so pressure clears quickly | +| `401` | Missing or unrecognized `X-Auth-Token` | No | + + +`404` is a capacity answer, not a validity answer. Fall back to your own path if it persists, but a single retry a few seconds later often succeeds. + + + +```bash cURL +curl --request GET \ + --url 'https://api.sprinter.tech/lifi-intents/rfq?srcChain=eip155:8453&dstChain=eip155:42161&amount=100000000&token=0xaf88d065e77c8cC2239327C5EDb3A432268e5831&user=0x1F98431c8aD98523631AE4a59f267346ea31F984' \ + --header 'X-Auth-Token: YOUR_API_KEY' +``` + +```python Python +import requests + +response = requests.get( + "https://api.sprinter.tech/lifi-intents/rfq", + params={ + "srcChain": "eip155:8453", + "dstChain": "eip155:42161", + "amount": "100000000", + "token": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", + "user": "0x1F98431c8aD98523631AE4a59f267346ea31F984", + }, + headers={"X-Auth-Token": "YOUR_API_KEY"}, +) +quote = response.json()["quotes"][0] +``` + +```javascript JavaScript +const params = new URLSearchParams({ + srcChain: "eip155:8453", + dstChain: "eip155:42161", + amount: "100000000", + token: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", + user: "0x1F98431c8aD98523631AE4a59f267346ea31F984", +}); + +const response = await fetch( + `https://api.sprinter.tech/lifi-intents/rfq?${params}`, + { headers: { "X-Auth-Token": "YOUR_API_KEY" } } +); +const { quotes } = await response.json(); +const quote = quotes[0]; +``` + +```go Go +package main + +import ( + "fmt" + "io" + "net/http" +) + +func main() { + url := "https://api.sprinter.tech/lifi-intents/rfq" + + "?srcChain=eip155:8453&dstChain=eip155:42161&amount=100000000" + + "&token=0xaf88d065e77c8cC2239327C5EDb3A432268e5831" + + "&user=0x1F98431c8aD98523631AE4a59f267346ea31F984" + + req, _ := http.NewRequest("GET", url, nil) + req.Header.Set("X-Auth-Token", "YOUR_API_KEY") + resp, _ := http.DefaultClient.Do(req) + defer resp.Body.Close() + body, _ := io.ReadAll(resp.Body) + fmt.Println(string(body)) +} +``` + + + +```json 200 +{ + "quotes": [ + { + "validUntil": 1754481615, + "eta": 45, + "quoteId": "3f8a1c72-95e4-4d6b-b0a1-2c7e9f4d8a13", + "provider": "sprinter", + "preview": { + "inputs": [ + { + "user": "0x00010000022105141f98431c8ad98523631ae4a59f267346ea31f984", + "asset": "0x0001000002210514833589fcd6edb6e08f4c7c32d4f71b54bda02913", + "amount": "100000000" + } + ], + "outputs": [ + { + "receiver": "0x0001000002a4b1141f98431c8ad98523631ae4a59f267346ea31f984", + "asset": "0x0001000002a4b114af88d065e77c8cc2239327c5edb3a432268e5831", + "amount": "99850000" + } + ] + }, + "metadata": { + "exclusiveFor": "0x4c4A2f8c81640e47606d3fd77B353E87Ba015584" + }, + "failureHandling": "refund-automatic" + } + ] +} +``` + +```json 404 +{ + "error": "no available pools for request" +} +``` + + +## Address format + +`user`, `receiver` and `asset` inside `preview` are [ERC-7930](https://eips.ethereum.org/EIPS/eip-7930) interoperable addresses — chain id and account packed into one byte string: + +``` +version(2) | chainType(2) | chainRefLen(1) | chainRef(n) | addrLen(1) | addr(20) +``` + +`0x0001000002210514833589fc...2913` decodes to USDC on Base (`0x2105` = 8453). + +`metadata.exclusiveFor` is a plain 20-byte hex address, not ERC-7930. + +## Next step + +Pass the quote object straight to [`POST /lifi-intents/transaction`](/api-reference/sprinter/lifi-intents/transaction) to get the transaction that opens the order. diff --git a/api-reference/sprinter/lifi-intents/transaction.mdx b/api-reference/sprinter/lifi-intents/transaction.mdx new file mode 100644 index 0000000..83a895d --- /dev/null +++ b/api-reference/sprinter/lifi-intents/transaction.mdx @@ -0,0 +1,140 @@ +--- +title: "Build the Escrow Open Transaction" +sidebarTitle: "Transaction" +openapi: post /lifi-intents/transaction +--- + +Turns a quote into an unsigned `open` call on the LI.FI input settler escrow. POST the quote object you received from [`GET /lifi-intents/rfq`](/api-reference/sprinter/lifi-intents/rfq); you get the same object back with `transactionRequest` populated. + +Sending that transaction escrows the inputs on the origin chain and broadcasts the order to solvers. + + +Include the `quoteId` from the RFQ response. Without it the endpoint still returns valid calldata, but **no liquidity is reserved** and the order is not guaranteed a Sprinter fill — you get no error saying so. + + +## What the endpoint fills in + +You supply `preview`; everything else is derived: + +| Field | Derived as | +|---|---| +| `nonce` | Generated per request | +| `fillDeadline` | ~6 minutes out — 1 minute exclusive to Sprinter, then 5 minutes open to any solver | +| `expires` | `fillDeadline` + a settlement buffer: ~13 minutes for same-chain orders, ~12 hours for cross-chain | +| `inputOracle` / output oracle | From Sprinter's configuration | +| Exclusivity | Encoded per output; defaults to Sprinter's filler address | +| `value` | Sum of native-token inputs, hex encoded. `0x0` for ERC-20-only orders | + +You can override `nonce`, `expires`, `fillDeadline` and `inputOracle` by setting them in the `order` object on the request, and override the exclusive filler with `metadata.exclusiveFor`. Leave them unset unless you have a specific reason — the defaults are what the reservation is priced against. + +## Constraints + +- Every entry in `preview.inputs` must be on the same origin chain. Mixed origins are rejected with `400`. +- The returned transaction must be sent by `transactionRequest.from` — the payer named in the first input. +- Send it promptly. Converting the quote extends the reservation by one minute; after that the liquidity is released. + + +```bash cURL +curl --request POST \ + --url 'https://api.sprinter.tech/lifi-intents/transaction' \ + --header 'Content-Type: application/json' \ + --data @quote.json +``` + +```python Python +import requests + +# `quote` is quotes[0] from the RFQ response, passed through unchanged +response = requests.post( + "https://api.sprinter.tech/lifi-intents/transaction", + json=quote, +) +tx = response.json()["transactionRequest"] +``` + +```javascript JavaScript +// `quote` is quotes[0] from the RFQ response, passed through unchanged +const response = await fetch( + "https://api.sprinter.tech/lifi-intents/transaction", + { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(quote), + } +); +const { transactionRequest } = await response.json(); + +// send it from the user's wallet +const hash = await walletClient.sendTransaction({ + to: transactionRequest.to, + data: transactionRequest.data, + value: BigInt(transactionRequest.value), + chainId: transactionRequest.chainId, +}); +``` + +```go Go +package main + +import ( + "bytes" + "fmt" + "io" + "net/http" +) + +func main() { + // quoteJSON is quotes[0] from the RFQ response, passed through unchanged + resp, _ := http.Post( + "https://api.sprinter.tech/lifi-intents/transaction", + "application/json", + bytes.NewReader(quoteJSON), + ) + defer resp.Body.Close() + body, _ := io.ReadAll(resp.Body) + fmt.Println(string(body)) +} +``` + + + +```json 200 +{ + "validUntil": 1754481615, + "eta": 45, + "quoteId": "3f8a1c72-95e4-4d6b-b0a1-2c7e9f4d8a13", + "provider": "sprinter", + "preview": { + "inputs": [ + { + "user": "0x00010000022105141f98431c8ad98523631ae4a59f267346ea31f984", + "asset": "0x0001000002210514833589fcd6edb6e08f4c7c32d4f71b54bda02913", + "amount": "100000000" + } + ], + "outputs": [ + { + "receiver": "0x0001000002a4b1141f98431c8ad98523631ae4a59f267346ea31f984", + "asset": "0x0001000002a4b114af88d065e77c8cc2239327c5edb3a432268e5831", + "amount": "99850000" + } + ] + }, + "metadata": { + "exclusiveFor": "0x4c4A2f8c81640e47606d3fd77B353E87Ba015584" + }, + "failureHandling": "refund-automatic", + "transactionRequest": { + "from": "0x1F98431c8aD98523631AE4a59f267346ea31F984", + "to": "0x6E9a1b3F0c5D2a8B4e7C1f9A3d6B0e5C8f2A4d71", + "chainId": 8453, + "data": "0xff2b0c2b0000000000000000000000000000000000000000000000000000000000000020", + "value": "0x0" + } +} +``` + + +## After the fill + +Sprinter fills on the destination chain within the exclusivity window and is repaid when the escrow settles. If nobody fills before `fillDeadline`, the order is reclaimable on the escrow contract — `failureHandling` is `refund-automatic`, so nothing is stranded. diff --git a/api-reference/sprinter/liquidity/overview.mdx b/api-reference/sprinter/liquidity/overview.mdx index 95329bf..68e0dc7 100644 --- a/api-reference/sprinter/liquidity/overview.mdx +++ b/api-reference/sprinter/liquidity/overview.mdx @@ -9,6 +9,12 @@ The Liquidity API exposes **Sprinter Intent Liquidity** that can be accessed thr These are **zero-collateral** loans — solvers borrow without locking upfront capital. Repayment is secured by the intent protocol's escrow and settlement flow. + +**This is the solver-facing surface.** It returns a borrow authorization and expects you to run your own fill and settlement. + +If you are an asset issuer, wallet, or application that wants a price and a transaction to send, use [Solve RFQ](/api-reference/solve-rfq/overview) instead. [`GET /lifi-intents/rfq`](/api-reference/sprinter/lifi-intents/rfq) runs this same pricing and reservation pipeline and hands back something you can sign. + + ## Base URL ``` diff --git a/api-reference/sprinter/openapi.json b/api-reference/sprinter/openapi.json index b14beca..2894ff5 100644 --- a/api-reference/sprinter/openapi.json +++ b/api-reference/sprinter/openapi.json @@ -2298,6 +2298,185 @@ } } } + }, + "/lifi-intents/rfq": { + "get": { + "description": "Prices a LI.FI intents order against Sprinter liquidity and reserves that liquidity for the quote's validity window. The response is shaped like a single element of LI.FI's own request-quote response.", + "tags": [ + "Liquidity" + ], + "summary": "Request a LI.FI intents quote backed by Sprinter liquidity", + "security": [ + { + "ApiKeyAuth": [] + } + ], + "parameters": [ + { + "description": "Source CAIP chain ID (e.g., eip155:8453)", + "name": "srcChain", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "description": "Destination CAIP chain ID (e.g., eip155:42161)", + "name": "dstChain", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "description": "Amount in the smallest denomination", + "name": "amount", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "description": "Destination (borrow) token address (hex)", + "name": "token", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "description": "User address on the source chain (hex)", + "name": "user", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "description": "Source token address (hex). Defaults to the destination token's symbol on the source chain", + "name": "srcToken", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "description": "Receiver address on the destination chain (hex); defaults to user", + "name": "receiver", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "description": "Quote algorithm type (ExactInput or ExactOutput); defaults to ExactInput", + "name": "type", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "LI.FI intents quotes", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/lifiintents.QuoteResponse" + } + } + } + }, + "400": { + "description": "Bad request due to invalid input, or no route configured for this pair", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/responses.ErrorResponse" + } + } + } + }, + "404": { + "description": "No pool could serve the request right now (capacity exhausted or pricing unavailable)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/responses.ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/responses.ErrorResponse" + } + } + } + } + } + } + }, + "/lifi-intents/transaction": { + "post": { + "description": "Turns a quote into an unsigned `open` call on the LI.FI intents input settler escrow. When the quote carries a `quoteId` from the RFQ endpoint, the liquidity reservation is re-keyed to the resulting on-chain order id.", + "tags": [ + "Liquidity" + ], + "summary": "Build the escrow open transaction for a lifi-intents quote", + "requestBody": { + "description": "A quote from the RFQ response", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/lifiintents.Quote" + } + } + } + }, + "responses": { + "200": { + "description": "The same quote with transactionRequest populated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/lifiintents.Quote" + } + } + } + }, + "400": { + "description": "Bad request due to invalid input", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/responses.ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/responses.ErrorResponse" + } + } + } + } + } + } } }, "components": { @@ -2979,6 +3158,199 @@ } } }, + "lifiintents.Input": { + "type": "object", + "required": [ + "amount", + "asset", + "user" + ], + "properties": { + "user": { + "type": "string", + "description": "Payer, as an ERC-7930 interoperable address." + }, + "asset": { + "type": "string", + "description": "Input token, as an ERC-7930 interoperable address." + }, + "amount": { + "type": "string", + "description": "Amount in the smallest denomination." + } + } + }, + "lifiintents.Metadata": { + "type": "object", + "properties": { + "exclusiveFor": { + "type": "string", + "description": "Address granted exclusivity over the fill. Defaults to Sprinter's filler address." + } + } + }, + "lifiintents.Order": { + "type": "object", + "description": "Optional overrides for the escrow open call. Any field left unset is derived by the transaction endpoint.", + "properties": { + "nonce": { + "type": "string" + }, + "expires": { + "type": "integer", + "description": "Unix timestamp after which the order can no longer settle." + }, + "fillDeadline": { + "type": "integer", + "description": "Unix timestamp after which the order can no longer be filled." + }, + "inputOracle": { + "type": "string" + } + } + }, + "lifiintents.Output": { + "type": "object", + "required": [ + "amount", + "asset", + "receiver" + ], + "properties": { + "receiver": { + "type": "string", + "description": "Recipient, as an ERC-7930 interoperable address." + }, + "asset": { + "type": "string", + "description": "Output token, as an ERC-7930 interoperable address." + }, + "amount": { + "type": "string", + "description": "Amount in the smallest denomination." + } + } + }, + "lifiintents.Preview": { + "type": "object", + "required": [ + "inputs", + "outputs" + ], + "properties": { + "inputs": { + "type": "array", + "minItems": 1, + "description": "Tokens escrowed on the origin chain. Every input must sit on the same origin chain.", + "items": { + "$ref": "#/components/schemas/lifiintents.Input" + } + }, + "outputs": { + "type": "array", + "minItems": 1, + "description": "Tokens delivered to the receiver.", + "items": { + "$ref": "#/components/schemas/lifiintents.Output" + } + } + } + }, + "lifiintents.Quote": { + "type": "object", + "required": [ + "preview" + ], + "properties": { + "preview": { + "$ref": "#/components/schemas/lifiintents.Preview" + }, + "quoteId": { + "type": "string", + "description": "Identifier for the liquidity reservation backing this quote. Pass the quote back to /lifi-intents/transaction to keep it." + }, + "validUntil": { + "type": "integer", + "description": "Unix timestamp after which the quote and its reservation expire." + }, + "eta": { + "type": "integer", + "description": "Estimated fill duration in seconds." + }, + "provider": { + "type": "string", + "description": "Always `sprinter`." + }, + "failureHandling": { + "type": "string", + "description": "Always `refund-automatic` \u2014 an unfilled order is reclaimable on the escrow." + }, + "partialFill": { + "type": "boolean", + "description": "Whether the order may be partially filled. Sprinter quotes are all-or-nothing." + }, + "metadata": { + "$ref": "#/components/schemas/lifiintents.Metadata" + }, + "order": { + "$ref": "#/components/schemas/lifiintents.Order" + }, + "transactionRequest": { + "$ref": "#/components/schemas/lifiintents.TransactionRequest" + } + } + }, + "lifiintents.QuoteResponse": { + "type": "object", + "required": [ + "quotes" + ], + "properties": { + "quotes": { + "type": "array", + "description": "Quotes offered for the request. Sprinter returns exactly one.", + "items": { + "$ref": "#/components/schemas/lifiintents.Quote" + } + } + } + }, + "lifiintents.TransactionRequest": { + "type": "object", + "description": "Unsigned transaction calling open() on the input settler escrow. Send it from the user's wallet.", + "required": [ + "chainId", + "data", + "from", + "to", + "value" + ], + "properties": { + "from": { + "type": "string" + }, + "to": { + "type": "string", + "description": "The LI.FI input settler escrow contract." + }, + "chainId": { + "type": "integer" + }, + "data": { + "type": "string" + }, + "value": { + "type": "string", + "description": "Hex-encoded native value; `0x0` unless an input is the native token." + }, + "gasPrice": { + "type": "string" + }, + "gasLimit": { + "type": "string" + } + } + }, "liquidity.BorrowCost": { "description": "Borrow authorisation signature and details.", "type": "object", @@ -3296,4 +3668,4 @@ "description": "Production server" } ] -} +} \ No newline at end of file diff --git a/index.mdx b/index.mdx index d9bfb74..90465ef 100644 --- a/index.mdx +++ b/index.mdx @@ -50,8 +50,11 @@ Pick the path that matches what you're building: Lock collateral, draw credit, repay, and manage earn vaults — with an interactive playground. + + Get a firm, liquidity-backed quote through LI.FI Intents — or route a swap against public liquidity. + - Discover available liquidity, quote a borrow, and get signing authorization. + For solvers: discover available liquidity, quote a borrow, and get signing authorization. diff --git a/introduction.mdx b/introduction.mdx index 25f0fb2..e5cad92 100644 --- a/introduction.mdx +++ b/introduction.mdx @@ -19,7 +19,7 @@ Apps plug in through a single API and get the full credit stack: flexible terms, ## Who builds on Sprinter -- **Asset issuers** — offer instant redemptions and subscriptions on assets that settle T+1 to T+30, without holding an idle liquidity buffer. Built on **Sprinter Liquidity**. See [Redemption & Subscription Liquidity](/stash-v1/redemption-liquidity). +- **Asset issuers** — offer instant redemptions and subscriptions on assets that settle T+1 to T+30, without holding an idle liquidity buffer. Built on **Sprinter Liquidity**. See the [Asset Issuer quickstart](/quickstart/asset-issuer). - **Crosschain Solvers** — access zero-collateral crosschain liquidity to fill intents, repaid from the user's source-chain deposit. Built on **Sprinter Liquidity**. - **Neobanks & Card Programmes** — let users spend against their DeFi holdings without selling, while the program earns yield on held assets. Built on the **Sprinter Credit** API. - **Wallets & AI agents** — credit lines users borrow against their holdings, and autonomous, policy-bound credit for agents. Built on **Sprinter Credit**. diff --git a/mint.json b/mint.json index 5b64712..9ee86ee 100644 --- a/mint.json +++ b/mint.json @@ -72,8 +72,13 @@ "group": "Sprinter Liquidity", "pages": [ "stash-v1/overview", - "stash-v1/redemption-liquidity", - "stash-v1/contracts" + "solve-rfq" + ] + }, + { + "group": "Pricing", + "pages": [ + "pricing" ] }, { @@ -144,12 +149,20 @@ ] }, { - "group": "Swaps", + "group": "Solve RFQ", "pages": [ - "api-reference/solve/overview", + "api-reference/solve-rfq/overview", { - "group": "Swap Actions", + "group": "LI.FI Intents", "pages": [ + "api-reference/sprinter/lifi-intents/rfq", + "api-reference/sprinter/lifi-intents/transaction" + ] + }, + { + "group": "Swap API", + "pages": [ + "api-reference/solve/overview", "api-reference/solve/get-v1route" ] } @@ -160,6 +173,16 @@ "api-reference/sprinter/openapi.json", "api-reference/solve/openapi.yaml" ], + "redirects": [ + { + "source": "/stash-v1/redemption-liquidity", + "destination": "/quickstart/asset-issuer" + }, + { + "source": "/stash-v1/contracts", + "destination": "/stash-v1/overview" + } + ], "logo": { "light": "/logo/light.svg", "dark": "/logo/dark.svg" diff --git a/pricing.mdx b/pricing.mdx new file mode 100644 index 0000000..6bd963f --- /dev/null +++ b/pricing.mdx @@ -0,0 +1,105 @@ +--- +title: "Pricing & Credit Facilities" +description: "How Sprinter prices short-duration credit, and the two ways to access it — shared liquidity or a dedicated committed facility" +--- + +Sprinter lends against a **settlement delay**. Credit is priced per day outstanding, so the cost of a fill is a function of how long your rail takes to settle — not of how volatile the asset is. The credit is repaid by the settlement itself, which is why it needs almost no collateral. + +There are two ways to access that credit. + +## Facility types + +| | **Shared liquidity** | **Dedicated facility** | +|---|---|---| +| **Capacity** | Drawn just-in-time from Sprinter's general pool, shared across all counterparties | A committed cap underwritten and reserved for your flow | +| **Availability** | Whatever is free at the moment you quote — a request can be declined | Held for you up to the cap | +| **Commitment** | None. No agreement, no minimum | A facility agreement with a fixed initial term | +| **Pricing** | Per fill, charged per day outstanding | Per day outstanding, plus a minimum return on committed capital | +| **Best for** | Getting live quickly; variable or unproven volume | A published instant-redemption promise; predictable capacity | +| **Start with** | The [Asset Issuer quickstart](/quickstart/asset-issuer) — no commercial agreement needed | [Talk to us](https://t.me/sprinter_tech/1) — sizing and rate are set during underwriting | + +The two can be used together: a dedicated facility for the committed base, shared liquidity for overflow. + +## What drives the price + +Credit is priced per day outstanding, so the spread is set by the length of your settlement rail: + +| Settlement rail | Capital locked | Relative spread per fill | +|---|---|---| +| Same-day | Hours | Lowest | +| T+1 | ~1 day | Low | +| T+2 – T+3 | 2–3 days | Moderate | +| T+5 – T+7 | 5–7 days | High | +| T+8 – T+30 | up to 30 days | Highest | + +A committed facility is quoted as an annual rate on committed capacity; just-in-time draws are charged per day and repaid by the settlement. They are the same price expressed two ways. + +**Who bears the cost** is a per-facility decision: the end user as a deducted fee, the issuer as a subsidy for a par experience, or a blend. + +## Shared liquidity + +Quote through [`GET /lifi-intents/rfq`](/api-reference/sprinter/lifi-intents/rfq) and Sprinter prices against its general pool. The quote is firm for its validity window and the liquidity is reserved behind it, but nothing is reserved before you ask. + +- **No commitment and no minimum.** You pay only on fills. +- **Capacity is not guaranteed.** If no pool can serve the size at that moment the endpoint returns `404`, and you fall back to your own path. Keep that fallback — a declined quote should never block a holder from redeeming. +- **Onboarding still applies.** Sprinter only quotes assets it has underwritten and configured routes for. + +## Dedicated facility + +A dedicated facility commits capacity to a single asset or flow, so instant redemption can be a promise you publish rather than a best effort. Terms are agreed per facility during underwriting — the tables below are the shape of what gets specified, not fixed values. + +### Facility parameters + +| Parameter | What it specifies | +|---|---| +| **Total facility cap** | The committed ceiling. Normally callable in tranches rather than funded upfront | +| **Initial pool at launch** | Capital deployed on day one, before the first capital call | +| **Per-draw order limit** | Maximum value Sprinter will fill in a single transaction | +| **In-window fill rate** | Execution SLA for orders inside a valid quote window | +| **Inventory settlement** | The rail and cycle that repays drawn capital | +| **Supported networks** | Chains the facility is configured for | + +### Capital management + +- **Capital calls.** Scaling above the initial pool runs through LP capital calls with an agreed notice period. The cap can be extended by mutual agreement. +- **Repayment.** Drawn capital is repaid by your native settlement rail. Utilisation should stay within any daily cap on that rail — breaching it pushes redemptions into your queue and extends the days capital stays locked. + +### Replenishment + +Deployed capital recycles into the facility once the underlying settles. The replenishment cycle is the settlement rail, so a slower rail means the same committed capital supports less throughput: + +| Settlement rail | Days capital locked | Effect on the facility | +|---|---|---| +| T+1 | ~1 business day | Capital turns over quickly; a smaller cap covers more volume | +| T+4 | ~4 business days, longer across holidays in either calendar | Each draw is locked through the cycle | +| T+30 | up to 30 days | Throughput is capped by the facility size, not the rail | + +Drawn capital is locked until the cycle clears, then recycles automatically. Quote expiry is set per facility — short enough to price accurately, long enough for the redemption to reach your rail. + +### Commercials + +| Term | Shape | +|---|---| +| **Rate within the rail's daily cap** | A fixed spread in basis points over the settlement cycle, additive on top of your own mint and redeem fees | +| **Volume beyond the daily cap** | Priced and underwritten separately | +| **Minimum facility return** | An annualised floor on committed capital, measured monthly. Redemption fees count toward it; the issuer pays any shortfall monthly in arrears. Applies to committed capital only | +| **Term** | A fixed initial term, then rolling by mutual agreement | + + + The minimum return is what makes capacity a commitment rather than an intention — it is the price of capital being held for you whether or not you draw on it. It applies only to committed capital, never to shared-liquidity fills. + + +## Underwriting + +Both routes require the asset to be onboarded first; a dedicated facility additionally needs the facility agreement. Underwriting takes 1–2 weeks and runs concurrently with KYB and contract scoping. See [what Sprinter underwrites](/quickstart/asset-issuer#what-sprinter-underwrites) for the full list. + +## Next steps + + + + Onboard an asset and integrate the two runtime calls. + + + Facility sizing, rate, and asset underwriting. + + diff --git a/quickstart/asset-issuer.mdx b/quickstart/asset-issuer.mdx index c0507c8..d19b55a 100644 --- a/quickstart/asset-issuer.mdx +++ b/quickstart/asset-issuer.mdx @@ -7,34 +7,52 @@ description: "Onboard a T+X asset with Sprinter, then offer instant redemptions If you issue an asset that settles on a delay — a tokenized treasury, a bond fund, a yield-bearing stablecoin, a structured vault — Sprinter can front the liquidity so your holders enter and exit instantly, while the underlying settles on your own rail in the background. +Most tokenized assets share the same friction in both directions. A holder who wants out waits for your redemption rail — T+1 for a tokenized treasury, T+4 for a bond fund, T+30 for some structured products — or takes a discount on a thin secondary market. A holder who wants in, especially from another chain, waits for settlement before the position exists. Sprinter closes both gaps. + + + The credit is repaid by the settlement itself — your redemption or subscription mechanism — not by liquidating the asset. That is why it needs almost no collateral, and why the price is a function of **how long the rail takes**, not of how volatile the asset is. + + +### Why issuers integrate + +- **No idle redemption buffer.** Instead of parking 3–10% of TVL to fund instant exits, outsource that function. Capital that would otherwise sit idle on your balance sheet earns yield in ours. +- **Instant on both sides.** Exits settle immediately in USDC; crosschain deposits credit the position immediately while settlement completes behind it. +- **Works on any settlement path.** Yield-bearing stablecoins, tokenized treasuries and funds, structured and tranched products, RWA-backed tokens. If it has a defined settlement path and a measurable delay, we can front it. +- **Crosschain by default.** Sprinter's solver network services deposits and exits across supported networks, so a holder on one chain can enter or exit a position on another. +- **Optional par experience.** By default Sprinter earns a spread on each fill. Issuers who want a frictionless experience can subsidise that spread so the end user transacts at par — $10 exited returns $10, with no visible fee. The financing cost shifts from the user to you, as a UX and acquisition investment. + Your tokenized asset is onboarded first. Sprinter quotes only assets it has underwritten, allocated liquidity to and configured routes for, so onboarding is step 1 and the runtime calls follow from there. -Two paths. The **solver model** described here gets you live without protocol changes. The **facility model** commits dedicated capacity and is agreed commercially — see [Redemption & Subscription Liquidity](/stash-v1/redemption-liquidity). +Two paths. The flow described here draws on **shared liquidity** and gets you live without a commercial agreement. A **dedicated facility** commits capacity to your flow and is agreed commercially — see [Pricing & Credit Facilities](/pricing) for both, and what a fill costs. The sequence is one onboarding phase, then three runtime steps per redemption: 1. **Onboard the asset** — one time. Underwriting, liquidity allocation, route configuration -2. **Quote** — ask Sprinter what it will pay for the position -3. **Create intent** — publish the redemption as an exclusive limit order to Sprinter +2. **Quote** — ask Sprinter what it will pay for the position. Liquidity is reserved against the answer +3. **Open the order** — hand the quote back and get a transaction to send 4. **Settle** — Sprinter fills instantly; you settle the underlying on your rail --- ## Step 1 — Onboard the asset -This is a joint process, not a self-serve API call. Sprinter has to understand the settlement path before it will lend against it, then commit capital and wire up routing. +This is a joint process, not a self-serve API call. Sprinter has to understand the settlement path before it will lend against it, then commit capital and wire up routing. The assessment is about the *settlement path*, not the asset's price. -### What you submit +### What Sprinter underwrites | | Why Sprinter needs it | |---|---| -| **Settlement rail** — mechanism, cadence, business-day convention, valuation cut-off | Sets how long capital is locked, which sets the price | -| **Caps** — daily or per-valuation limits on redemption volume, and what happens to requests that breach them | Determines how much can be fronted before hitting your queue | -| **Price source** — NAV stream or oracle, update frequency, acceptable staleness | Sprinter quotes off this; stale prices mean no quote | +| **Settlement rail** — mechanism, cadence, business-day convention, valuation cut-off, and how variable it is | Sets how long capital is locked, which sets the price | +| **Rail reliability and caps** — historical settlement performance, daily or per-valuation limits on volume, and what happens to requests that breach them | Determines how much can be fronted before hitting your queue | +| **Price source** — NAV stream or oracle, update cadence, acceptable staleness | Sprinter quotes off this; stale prices mean no quote | +| **Issuer reserve adequacy** — whether you maintain your own instant buffer, and how it refreshes | Sizes how much Sprinter needs to front | +| **Secondary market depth** — availability of a fallback exit for positions held during the settlement window | A second exit path lowers the risk premium | | **Contract addresses** — the token, plus any dedicated mint/redeem or express contracts | Integration and route configuration | -| **Eligibility** — whether Sprinter needs whitelisting on the redemption rail, and the KYB steps | Sprinter must be able to actually redeem what it holds | +| **Eligibility** — whitelisting on the redemption rail, KYB steps, and any transfer restrictions that apply to Sprinter as counterparty | Sprinter must be able to actually redeem what it holds | | **Chains** — launch chain priority and planned expansion | Determines which pools and routes are configured | +Underwriting typically takes 1–2 weeks and runs concurrently with onboarding and contract scoping. + ### Confirm the asset is live Before wiring up runtime calls, check that your token is returned by [supported tokens for a chain](/api-reference/sprinter/liquidity/returns-supported-tokens-for-a-chain). If it isn't there, onboarding is not complete and quotes will not return. @@ -52,49 +70,71 @@ Once the asset is live, this runs per redemption.
```mermaid flowchart TD - A[Holder submits redemption] --> B[Request borrow quote from Sprinter Liquidity API] + A[Holder submits redemption] --> B[GET /lifi-intents/rfq
liquidity reserved for 15s] B --> C{Quote returned?} - C -->|Yes| D[Create intent as exclusive limit order
filler = quote address] + C -->|Yes| D[POST /lifi-intents/transaction
returns open call data] C -->|No| E[Fall back to native redemption queue] - D --> F[Sprinter fills instantly in USDC on the holder's chain] - F --> G[Sprinter holds the position and settles on your T+X rail] - G --> H[Settlement repays Sprinter — capital recycles] - D -.->|intent expires unfilled| I[You reclaim funds on the intent contract] + D --> F[Send the transaction — inputs escrowed on-chain] + F --> G[Sprinter fills instantly in USDC on the holder's chain] + G --> H[Sprinter holds the position and settles on your T+X rail] + H --> I[Settlement repays Sprinter — capital recycles] + F -.->|order expires unfilled| J[You reclaim funds on the escrow contract] ```
### Step 2 — Request a quote -Ask the Sprinter Liquidity API what it will pay for the position on the holder's chosen chain. See [Get the borrow quote](/api-reference/sprinter/liquidity/get-the-borrow-quote-for-a-liquidity-transaction-based-on-the-input-data) for the request and response schema. +Call [`GET /lifi-intents/rfq`](/api-reference/sprinter/lifi-intents/rfq) with the position, the holder's chain, and where the proceeds should land. -The quote returns a price and the **address that will fill it**. Keep that address — step 3 needs it. +```bash +curl --request GET \ + --url 'https://api.sprinter.tech/lifi-intents/rfq?srcChain=eip155:8453&dstChain=eip155:8453&amount=100000000&token=0x833589fcd6edb6e08f4c7c32d4f71b54bda02913&srcToken=YOUR_ASSET_ADDRESS&user=HOLDER_ADDRESS' \ + --header 'X-Auth-Token: YOUR_API_KEY' +``` + +The response is a firm price with **liquidity already reserved against it**. Keep the whole quote object — step 3 takes it verbatim. + + + A quote is valid for **15 seconds**, and the reservation expires with it. Go straight from step 2 to step 3 — do not park a quote behind a user confirmation screen. If the holder needs to confirm, confirm first and quote after. + - Quotes are time-bounded. Treat a returned quote as valid only for its stated window and re-quote rather than reusing a stale one. If no quote returns for an onboarded asset — capacity is exhausted, the price is stale, or the size exceeds a limit — fall back to your native redemption queue. Sprinter declining a fill should never block a holder from redeeming. + If no quote returns for an onboarded asset, fall back to your native redemption queue. A `404` means no pool can serve the size right now and is worth one retry after a short backoff; a `400` means the route is not configured and retrying will not help. Sprinter declining a fill should never block a holder from redeeming. -### Step 3 — Create the intent +### Step 3 — Open the order -Publish the redemption as an intent through your intent protocol — for example with the [LI.FI SDK](https://docs.li.fi/sdk/overview), creating a [LI.FI intent](https://docs.li.fi/lifi-intents/intents-api/create-and-submit). +POST the quote back to [`POST /lifi-intents/transaction`](/api-reference/sprinter/lifi-intents/transaction). You get the same object with a `transactionRequest` on it — an unsigned `open` call on the escrow contract. -Two things matter: +```bash +curl --request POST \ + --url 'https://api.sprinter.tech/lifi-intents/transaction' \ + --header 'Content-Type: application/json' \ + --data @quote.json +``` -- Create it as an **exclusive limit order**, not an open order -- Set the **quote's address as the exclusive filler**, so only Sprinter can fill at the quoted price +Send that transaction from the holder's wallet. It escrows the position and publishes the order. -This is what makes the fill deterministic: the holder is quoted a price, and that exact price is what fills. +You no longer construct the intent yourself. Sprinter builds it as an exclusive limit order with itself as the filler, priced at the quote, with the deadlines already set — which is what makes the fill deterministic: the holder is quoted a price, and that exact price is what fills. + + + Include the `quoteId` from step 2 — it is what ties the order to the reserved liquidity. Post a quote without one and you still get valid call data, but nothing is held for it. + ### Step 4 — Settle, or reclaim **If filled:** the holder receives USDC immediately on their chosen chain. Sprinter holds the position and settles it through your native rail. When settlement completes, Sprinter is repaid and the capital recycles into the next fill. -**If the intent expires unfilled:** you reclaim the funds on the intent contract. Nothing is stranded — an unfilled intent is a no-op. +**If the order expires unfilled:** you reclaim the funds on the escrow contract. Nothing is stranded — an unfilled order is a no-op. ## Next steps - - How the product works, pricing shape, and underwriting criteria. + + What a fill costs, and whether you want shared liquidity or a dedicated facility. + + + Endpoint reference for both runtime calls, and when to use the Swap API instead. Facility sizing, pricing, and asset underwriting. diff --git a/resources/glossary.mdx b/resources/glossary.mdx index 7842153..7be0e5e 100644 --- a/resources/glossary.mdx +++ b/resources/glossary.mdx @@ -37,6 +37,10 @@ An entity (user, app, or agent) granted access to a Sprinter Credit line on beha The act of drawing funds from an open credit line up to the available credit limit. +### Exclusive Fill + +An order published so that only one named filler may execute it, for a defined window. Sprinter quotes are exclusive to Sprinter's filler address, which is what makes the quoted price the executed price. After the exclusivity window ends, the order typically opens to any solver before its fill deadline. + ### Fill A fill represents the full lifecycle: detecting a user intent, borrowing liquidity, executing the transaction, repaying liquidity, and realizing solver and protocol profits. @@ -45,6 +49,10 @@ A fill represents the full lifecycle: detecting a user intent, borrowing liquidi A single number indicating how close a position is to liquidation, calculated as `(Collateral Value x Maintenance LTV) / Outstanding Debt`. A Health Factor above 1.0 is safe; below 1.0 the position is eligible for liquidation. +### Intent + +An order that states the outcome a user wants — this asset out, that asset in, on this chain — without specifying how to achieve it. The user escrows the inputs; a solver competes to deliver the outputs and is repaid from escrow on settlement. + ### Intent Systems A model where users specify desired outcomes, and solvers or order flow networks execute transactions accordingly. @@ -89,6 +97,10 @@ The Sprinter Credit component that makes credit configurable. Every credit line Collateral assets that continue to generate yield while locked in Sprinter Credit, making credit cheaper by design. Sprinter Credit integrates with DeFi strategies from Gauntlet and YO for this purpose. +### Solve RFQ + +Sprinter's request-for-quote surface: you describe a trade and Sprinter returns a firm price with the liquidity reserved behind it, plus a transaction that opens the order. Unlike a [borrow quote](#borrow-quote), which is an estimate for solvers, an RFQ quote is a commitment for the life of its validity window. See [Solve RFQ](/solve-rfq). + ### Solvers Automated agents that find and execute the most efficient way to fulfill a user's intent, optimizing for cost, speed, and security. diff --git a/solve-rfq.mdx b/solve-rfq.mdx new file mode 100644 index 0000000..e9dc4c3 --- /dev/null +++ b/solve-rfq.mdx @@ -0,0 +1,58 @@ +--- +title: "Solve RFQ" +description: "How you get a price out of Sprinter Liquidity — a firm quote with the liquidity already held behind it" +--- + +Solve RFQ is how you get a price out of Sprinter Liquidity. You describe the trade; Sprinter answers with a price and **holds the liquidity behind that answer** while you decide. + +That second half is the part that matters. Most quoting is an estimate: a router prices a path, and what you actually get depends on what the pool looks like when your transaction lands. An RFQ quote from Sprinter is a commitment — the capital to fill it is reserved the moment the quote is issued. + +## Why the price can be firm + +Three things have to be true at once, and they are the reason this sits on top of Sprinter Liquidity rather than beside it: + +| | | +|---|---| +| **The capital exists** | Sprinter Liquidity has already underwritten the asset, allocated liquidity to it, and configured the route. Nothing is sourced at quote time | +| **It is reserved** | Issuing a quote takes that liquidity off the shelf for the life of the quote, so a second request cannot spend it | +| **The fill is exclusive** | The resulting order is published as an exclusive limit order to Sprinter's filler, so the price you were quoted is the price that executes | + +Take any one away and the quote degrades into an estimate. This is the difference between telling a holder "roughly this" and telling them a number. + + + A quote is short-lived by design — it is capital held out of use. Quote, then act. The window is measured in seconds, not minutes, and treating a quote as cacheable is the most common integration mistake. + + +## Two ways to consume it + +| | **LI.FI Intents** | **Swap API** | +|---|---|---| +| **Backed by** | Sprinter Liquidity — reserved for your quote | Public on-chain AMM liquidity | +| **Price** | Firm | Indicative, subject to slippage | +| **Use for** | Redemptions, subscriptions, any flow where a user is promised a price | Generic token swaps, and as a fallback when no Sprinter route exists | +| **Requires** | The asset onboarded with Sprinter | Nothing — any supported pair | + +Default to LI.FI Intents. Reach for the Swap API when the pair is not onboarded, or as a fallback when a quote does not return. + +## What it is not + +- **Not a router.** Solve RFQ does not search for the best path across venues. It answers one question: what will Sprinter pay, right now, for this position. +- **Not always available.** Capacity is finite. A request can be declined, and your integration needs a fallback — for an issuer that means your native redemption queue. +- **Not a credit line.** Sprinter Credit is collateralized borrowing against assets you hold. Solve RFQ prices a settlement delay and is repaid by the settlement itself. + +## Where to go next + + + + The two runtime calls, end to end, with onboarding. + + + Endpoints, parameters, auth, and error behaviour. + + + What a fill costs, and shared liquidity versus a dedicated facility. + + + The capital layer underneath — where the liquidity comes from. + + diff --git a/stash-v1/contracts.mdx b/stash-v1/contracts.mdx deleted file mode 100644 index bf31ce2..0000000 --- a/stash-v1/contracts.mdx +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: "Sprinter Liquidity Contracts" -description: "Smart contract addresses and details for the Sprinter Liquidity hub, mining, and pools" ---- - -# Sprinter Liquidity - -Central to Sprinter Liquidity are the [**Liquidity Hub**](#liquidity-hub), [**Liquidity Mining**](#liquidity-mining-contract) and [**Liquidity Pools**](#liquidity-pools) smart contracts which manage and distribute liquidity. - -Liquidity authorization is managed and controlled by Sprinter's [**Multi-Party Computation (MPC)**](#liquidity-authorization-via-mpc) network. - -## Liquidity Hub - -**Contract Address (Base):** -`0xa593A9bBBc65be342FF610a01e96da2EB8539FF2` - -### Functionality: - -- **Allocation:** Hub allocates liquidity across supported chains based on solver demand. -- **Yield:** Idle liquidity is deployed into lending protocols like Aave. -- **Withdrawals:** LPs redeem their LP tokens for USDC when available. - -## Liquidity Mining Contract - -**Contract Address (Base):** -`0x479D158959B59328E89f0fbF7DfeBb198c313C21` - -### Functionality: - -- **Depositing Liquidity:** LPs deposit USDC and receive `spUSDC-LP` tokens. -- **Lockups:** `spUSDC-LP` tokens can be committed to this contract for fixed terms (e.g. 3, 6 or 9 months). Parameters are governance-controlled and all activity is verifiable on-chain. - -## Liquidity Pools - -Deployed across multiple chains, these on-chain vaults serve solver requests. - -### Key Pools - -- **Aave USDC Pool** (Base, OP, Arbitrum): - `0x7C255279c098fdF6c3116D2BecD9978002c09f4b` - -- **Standard USDC Pool** (Base, OP, Arbitrum): - `0xB58Bb9643884abbbad64FA7eBc874c5481E5c032` - -### Functionality - -- **Crosschain Execution:** Pools enable real-time execution of swaps and bridges. -- **Collateral-Free Borrowing:** Solvers access liquidity backed by hub-signed approvals. -- **Rebalancing:** Liquidity is auto-optimized across chains. -- **Risk Management:** Protocol maintains loan-to-value ratios to ensure solvency. - -## Liquidity Authorization via MPC - -Sprinter Liquidity relies on a secure **Multi-Party Computation (MPC)** network to authorize the release of credit and liquidity during cross-chain operations. - -### What the MPC Does - -- **Validates and Signs liquidity quotes**: When a solver calls the Sprinter Liquidity API and is approved for a fill, the MPC validates the intent, user deposit and then co-signs the authorization. -- **Authorizes cross-chain releases**: The MPC authorizes any transfers required for inventory management across the Liquidity Pools and the Liquidity Hub (e.g., on Base, Arbitrum). -- **Enforces protocol limits**: MPC logic verifies borrowing caps, rate limits, and repayment preconditions before authorizing transactions. - -### Why MPC Matters - -- **Trust-Minimized Security**: No single signer can approve a transfer — it requires a quorum (e.g. 3-of-5 or 4-of-7 threshold). -- **Decentralized Control**: The MPC signer set is governed on-chain and can evolve over time as governance decentralizes. -- **Programmable Logic**: Validators inside the MPC check for vault solvency, repayment windows, and risk heuristics before signing. - -### Governance & Oversight - -The **Super Admin Multisig** manages: - -- Rotation or upgrade of MPC key shares -- Approval and removal of validator nodes -- Emergency pauses or overrides to protect protocol funds - -The **Operations Multisig** may interact with MPC flows for day-to-day liquidity tuning, such as temporarily adjusting caps or triggering manual resets if required. - - -MPC signing happens off-chain but is fully verifiable and auditable via Sprinter's on-chain replay logs and relay receipts. - diff --git a/stash-v1/overview.mdx b/stash-v1/overview.mdx index dee2535..c0d4b1c 100644 --- a/stash-v1/overview.mdx +++ b/stash-v1/overview.mdx @@ -7,8 +7,14 @@ description: "Sprinter Liquidity is a credit-based liquidity protocol for crossc Sprinter Liquidity is a credit-based liquidity protocol that connects stablecoin LPs with the actors who need funding for a settlement delay — crosschain solvers filling intents, and asset issuers offering instant redemptions and subscriptions on assets that settle T+X. It bridges the gap between passive capital and high-frequency demand for short-duration credit. +## Two ways to access it + +**[Solve RFQ](/solve-rfq)** is the path for asset issuers, wallets and applications: you get a firm quote with liquidity reserved behind it, plus a transaction to send. Sprinter builds the order and fills it. + +The **Liquidity API** is the path for crosschain solvers running their own fill infrastructure: you get a borrow quote and an MPC-signed authorization, and you run the fill and settlement yourself. See the [Integration Guide](/stash-v1/integration-guide). + - Issuing an asset with a settlement delay? See [Redemption & Subscription Liquidity](/stash-v1/redemption-liquidity) for the issuer-facing product, and the [Asset Issuer quickstart](/quickstart/asset-issuer) to integrate. + Issuing an asset with a settlement delay? Go to the [Asset Issuer quickstart](/quickstart/asset-issuer) for onboarding and the two runtime calls, and [Pricing & Credit Facilities](/pricing) for what a fill costs and whether you want shared liquidity or a dedicated facility. ## Why Sprinter Liquidity? @@ -120,4 +126,11 @@ _Initial fee split is reviewed monthly by governance._ ## Start integrating -For DeFi solvers: check out the [Sprinter Liquidity Integration Guide](/stash-v1/integration-guide). + + + Quote and fill through LI.FI Intents — two API calls, no fill infrastructure of your own. + + + Borrow zero-collateral credit on demand and run your own fills. + + diff --git a/stash-v1/redemption-liquidity.mdx b/stash-v1/redemption-liquidity.mdx deleted file mode 100644 index 0e9c34d..0000000 --- a/stash-v1/redemption-liquidity.mdx +++ /dev/null @@ -1,75 +0,0 @@ ---- -title: "Redemption & Subscription Liquidity" -description: "Instant exit and entry on assets that settle T+X — for stablecoin and tokenized-asset issuers" ---- - -## Overview - -Most yield-bearing and tokenized assets share the same friction in both directions: **settlement takes time**. A holder who wants out waits for the issuer's redemption rail — T+1 for a tokenized treasury, T+4 for a bond fund, T+30 for some structured products — or accepts a discount on a thin secondary market. A holder who wants in, especially from another chain, waits for settlement to complete before the position exists. - -Sprinter closes both gaps. We front the liquidity at the moment the user acts, then settle the underlying on the issuer's own rail in the background. - -Every asset is onboarded before it can be quoted — Sprinter underwrites the settlement path, allocates liquidity against it and configures routes. See the [Asset Issuer quickstart](/quickstart/asset-issuer) for what onboarding involves. - - - The credit is repaid by the settlement itself — the issuer's redemption or subscription mechanism — not by liquidating the asset. That is why it needs almost no collateral, and why the price is a function of **how long the rail takes**, not of how volatile the asset is. - - -## Why issuers integrate - -- **No idle redemption buffer.** Instead of parking 3–10% of TVL to fund instant exits, outsource that function. Capital that would otherwise sit idle on your balance sheet earns yield in ours. -- **Instant on both sides.** Exits settle immediately in USDC; crosschain deposits credit the position immediately while settlement completes behind it. -- **Works on any settlement path.** Yield-bearing stablecoins, tokenized treasuries and funds, structured and tranched products, RWA-backed tokens. If it has a defined settlement path and a measurable delay, we can front it. -- **Crosschain by default.** Sprinter's solver network services deposits and exits across supported networks, so a holder on one chain can enter or exit a position on another. -- **Optional par experience.** By default Sprinter earns a spread on each fill. Issuers who want a frictionless experience can subsidise that spread so the end user transacts at par — $10 exited returns $10, with no visible fee. The financing cost shifts from the user to you, as a UX and acquisition investment. - -## Two integration models - -They can be used separately or together. - -| | Facility model | Solver model | -|---|---|---| -| **Shape** | You commit a facility with Sprinter, sized as a fixed amount or a share of TVL | Sprinter quotes and fills through an intent protocol on the secondary market | -| **How it settles** | Sprinter honours instant credits and exits directly, then queues the underlying settlement | Sprinter buys the position, delivers USDC instantly, then processes the redemption through your native queue | -| **Best for** | Predictable capacity, a published instant-redemption promise to your users | Getting live quickly with no protocol changes | -| **Integration effort** | Asset onboarding plus a facility agreement | Asset onboarding, then API quote plus intent creation — see the [quickstart](/quickstart/asset-issuer) | - -## How pricing works - -Credit is priced **per day outstanding**, so the spread is set by the length of your settlement rail: - -| Settlement rail | Capital locked | Relative spread per fill | -|---|---|---| -| Same-day | Hours | Lowest | -| T+1 | ~1 day | Low | -| T+2 – T+3 | 2–3 days | Moderate | -| T+5 – T+7 | 5–7 days | High | -| T+8 – T+30 | up to 30 days | Highest | - -A committed facility is quoted as an annual rate on committed capacity; just-in-time draws are charged per day and repaid by the settlement. They are the same price expressed two ways. Facility size, rate and any collateral requirement are set per asset during underwriting. - -**Who bears the cost** is a per-facility decision: the end user as a deducted fee, the issuer as a subsidy for a par experience, or a blend. - -## Underwriting - -Before committing a facility, Sprinter underwrites the asset. The assessment is about the *settlement path*, not the asset's price: - -- **Settlement delay** on entry and exit, and its variability — holidays, business-day conventions, valuation cut-offs -- **Rail reliability** — historical settlement performance, and any daily or per-valuation caps on redemption volume -- **Price source** — NAV stream or oracle, its cadence and staleness bounds -- **Issuer reserve adequacy** — whether you maintain your own instant buffer, and how it refreshes -- **Secondary market depth** — availability of a fallback exit for positions held during the settlement window -- **Eligibility mechanics** — whitelisting, KYC and any transfer restrictions that apply to Sprinter as counterparty - -Underwriting typically takes 1–2 weeks and runs concurrently with onboarding and contract scoping. - -## Next steps - - - - Integrate instant redemptions in three API steps. - - - Facility sizing, pricing, and asset underwriting. - -