@liquidium/client 0.5.0-rc.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +31 -348
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -2,104 +2,45 @@
2
2
  ![license](https://img.shields.io/badge/license-MIT-blue)
3
3
 
4
4
  <p align="center">
5
- <img src="https://raw.githubusercontent.com/Liquidium-Inc/liquidium-sdk/main/sdk.svg" alt="Liquidium SDK illustration" width="700" />
5
+ <img src="https://raw.githubusercontent.com/Liquidium-Inc/liquidium-sdk/main/sdk.svg" alt="Liquidium SDK" width="700" />
6
6
  </p>
7
7
 
8
- <h1 align="center">Liquidium SDK</h1>
8
+ # Liquidium SDK
9
9
 
10
- <p align="center">
11
- Use the Liquidium SDK from TypeScript apps. Start with accountless Simple Loans.
12
- </p>
13
-
14
- <p align="center">
15
- <a href="https://liquidium-inc.github.io/liquidium-sdk/"><b>SDK Docs</b></a> ·
16
- <a href="https://github.com/Liquidium-Inc/liquidium-sdk/tree/main/examples/simple-loans-flow"><b>Simple Loans Example</b></a> ·
17
- <a href="https://github.com/Liquidium-Inc/liquidium-sdk/tree/main/examples/sdk-method-query"><b>SDK Method Query Example</b></a> ·
18
- <a href="#core-api"><b>Core API</b></a>
19
- </p>
20
-
21
- ## Documentation
22
-
23
- Use the SDK docs for setup, guides, API reference, and examples.
24
-
25
- [Open the Liquidium SDK docs](https://liquidium-inc.github.io/liquidium-sdk/)
10
+ TypeScript client for Liquidium lending and accountless Simple Loans.
26
11
 
27
- ## Why Start With Simple Loans
12
+ [Documentation](https://liquidium-inc.github.io/liquidium-sdk/) · [API reference](https://liquidium-inc.github.io/liquidium-sdk/api-reference/) · [Simple Loans example](https://github.com/Liquidium-Inc/liquidium-sdk/tree/main/examples/simple-loans-flow)
28
13
 
29
- - **Accountless loan creation**: create simple loans without requiring a Liquidium profile.
30
- - **Generated transfer targets**: get collateral deposit and repayment targets from the SDK response.
31
- - **Reference-based restore**: save `loan.ref` and reload loan state from any browser session or support link.
32
- - **LTV checks**: use market pools and prices to validate collateral and borrow amounts before loan creation.
33
- - **Status and repayment quote**: reload lifecycle status, position state, and repayment amount in one call.
34
-
35
- ## Integration Paths
36
-
37
- Liquidium supports two borrowing and lending integration paths:
38
-
39
- | Path | Use when | Main SDK calls |
40
- | --- | --- | --- |
41
- | Recommended: accountless Simple Loans | You want a short checkout-style flow where users borrow against collateral without creating a Liquidium profile first | `client.simpleLoans.create(...)`, `client.simpleLoans.get(...)`, `client.simpleLoans.find(...)`, `client.activities.list(...)` |
42
- | Account-based profile flows | You want users to keep a Liquidium profile, manage positions across sessions, supply funds, borrow, withdraw, or use ETH contract-interaction deposits | `client.accounts.createProfile(...)`, `client.lending.supply(...)`, `client.lending.borrow(...)`, `client.lending.withdraw(...)`, `client.positions.listPositions(...)` |
43
-
44
- Use accountless Simple Loans for new borrow flows unless you need profile-level position management. Use account-based flows when your app owns the full lending dashboard experience.
45
-
46
- ## Quick Start
47
-
48
- Install the client package:
14
+ ## Install
49
15
 
50
16
  ```bash
51
17
  npm install @liquidium/client
52
18
  ```
53
19
 
54
- Create a simple loan, display the deposit target, and restore the loan by reference:
20
+ Use `npm install @liquidium/client@rc` when integrating against the current 0.5 release candidate. Untagged installs resolve to the latest stable release.
21
+
22
+ ## Usage
55
23
 
56
24
  ```ts
57
- import {
58
- Asset,
59
- Chain,
60
- LiquidiumClient,
61
- type Pool,
62
- type SupplyTarget,
63
- } from "@liquidium/client";
25
+ import { Asset, Chain, LiquidiumClient } from "@liquidium/client";
64
26
 
65
27
  const client = new LiquidiumClient();
66
28
 
67
- const [pools, prices] = await Promise.all([
68
- client.market.listPools(),
69
- client.market.getAssetPrices(),
29
+ const [collateralPool, borrowPool] = await Promise.all([
30
+ client.market.findPool({ asset: Asset.BTC, chain: Chain.BTC }),
31
+ client.market.findPool({ asset: Asset.USDC, chain: Chain.ETH }),
70
32
  ]);
71
33
 
72
- const collateralPool = requirePool(pools, Asset.BTC, Chain.BTC);
73
- const borrowPool = requirePool(pools, Asset.USDC, Chain.ETH);
74
-
75
- const collateralAmount = 50_000n; // BTC sats
76
- const borrowAmount = 9_000_000n; // USDC base units
77
-
78
- const ltv = client.quote.calculateLtv(
79
- {
80
- collateralPoolId: collateralPool.id,
81
- borrowPoolId: borrowPool.id,
82
- collateralAmount,
83
- borrowAmount,
84
- },
85
- pools,
86
- prices
87
- );
88
-
89
- if (ltv.validationErrors.length > 0) {
90
- throw new Error(ltv.validationErrors.map((error) => error.message).join(" "));
91
- }
92
-
93
34
  const loan = await client.simpleLoans.create({
94
35
  collateral: {
95
36
  poolId: collateralPool.id,
96
37
  asset: Asset.BTC,
97
- amount: collateralAmount,
38
+ amount: 50_000n,
98
39
  },
99
40
  borrow: {
100
41
  poolId: borrowPool.id,
101
42
  asset: Asset.USDC,
102
- amount: borrowAmount,
43
+ amount: 9_000_000n,
103
44
  chain: Chain.ETH,
104
45
  destination: "0x2222222222222222222222222222222222222222",
105
46
  },
@@ -107,298 +48,40 @@ const loan = await client.simpleLoans.create({
107
48
  chain: Chain.BTC,
108
49
  destination: "1BoatSLRHtKNngkdXEeobR76b53LETtpyT",
109
50
  },
110
- ltvMaxBps: ltv.maxAllowedLtvBps,
51
+ ltvMaxBps: 6_000n,
111
52
  depositWindowSeconds: 3_600n,
112
53
  });
113
54
 
114
- const initialDeposit = loan.initialDeposit.targets[Chain.BTC];
115
- if (!initialDeposit) {
116
- throw new Error("Missing BTC initial-deposit target.");
117
- }
118
-
119
- console.log("Save this loan reference:", loan.ref);
120
- console.log("Send initial deposit amount:", initialDeposit.amount.toString());
121
- console.log("Send collateral to:", formatSupplyTarget(initialDeposit.target));
122
-
123
- const restoredLoan = await client.simpleLoans.get({ ref: loan.ref });
124
- const repayment = restoredLoan.repayment.targets[Chain.ETH];
125
-
126
- console.log("Loan status:", restoredLoan.status);
127
- console.log("Repay amount:", repayment?.amount.toString() ?? "0");
128
- console.log(
129
- "Repay target:",
130
- repayment ? formatSupplyTarget(repayment.target) : "No repayment due"
131
- );
132
-
133
- const activities = await client.activities.list({ shortRef: loan.ref });
134
-
135
- console.log("Loan activities:", activities);
136
-
137
- const foundLoans = await client.simpleLoans.find(loan.ref);
138
-
139
- console.log("Found loan reference:", foundLoans[0]?.ref);
140
- console.log("Found loan collateral:", foundLoans[0]?.collateral.amount.toString());
141
-
142
- function requirePool(
143
- pools: Pool[],
144
- asset: Pool["asset"],
145
- chain: Pool["chain"]
146
- ): Pool {
147
- const pool = pools.find(
148
- (candidate) => candidate.asset === asset && candidate.chain === chain
149
- );
150
-
151
- if (!pool) {
152
- throw new Error(`Missing ${chain}/${asset} pool.`);
153
- }
154
-
155
- if (pool.frozen) {
156
- throw new Error(`${chain}/${asset} pool is frozen.`);
157
- }
158
-
159
- return pool;
160
- }
161
-
162
- function formatSupplyTarget(target: SupplyTarget): string {
163
- return target.address;
164
- }
165
- ```
166
-
167
- ## Simple Loans Flow
168
-
169
- Simple Loans integrations use this sequence:
170
-
171
- | Step | SDK call | What your app does |
172
- | --- | --- | --- |
173
- | Load market data | `client.market.listPools()` and `client.market.getAssetPrices()` | Show supported collateral and borrow assets |
174
- | Validate amounts | `client.quote.calculateLtv(...)` | Block too-small borrow amounts, invalid LTV, or frozen-pool input before creating a loan |
175
- | Create loan | `client.simpleLoans.create(...)` | Store `loan.ref` and show the quote in `loan.initialDeposit.targets[chain]` |
176
- | Track loan | `client.simpleLoans.get({ ref })`, `client.simpleLoans.find(...)`, and `client.activities.list({ shortRef: ref })` | Reload loan state, initial deposit quote, and repayment activity |
177
- | Repay loan | Read `loan.repayment.targets[chain]` | Ask the user to send the quote amount to its target; no quote means no repayment is due on that chain |
178
-
179
- `client.simpleLoans.create(...)` and `client.simpleLoans.get(...)` return the generated Liquidium profile, current position state, and transfer quotes keyed by the chain the user will send on. Users do not manage the generated profile.
180
-
181
- `client.market.listPools()` returns only pools whose asset and chain variants are supported by this SDK version. BTC, USDC, USDT, and ICP lending pools are returned. Future unsupported variants such as `SOL` are omitted from the returned list.
182
-
183
- `client.market.findPool({ chain, asset })` accepts the same Chain + Asset identifiers used by transfer flows. Chain-key identifiers resolve to their backing pool, so both `{ chain: "ETH", asset: "USDT" }` and `{ chain: "ICP", asset: "USDT" }` return the USDT pool.
184
-
185
- ## Core API
186
-
187
- ### `client.simpleLoans.create(request)`
188
-
189
- Creates an accountless simple loan and returns generated transfer targets.
190
-
191
- | Field | Description |
192
- | --- | --- |
193
- | `collateral` | Collateral `poolId`, `asset`, and intended credited `amount` in base units |
194
- | `borrow` | Borrow `poolId`, `asset`, `amount`, delivery `chain`, and `destination` |
195
- | `refund` | Refund `chain` and `destination` for returned collateral |
196
- | `ltvMaxBps` | Maximum LTV in basis points, where `6_000n` is 60% |
197
- | `depositWindowSeconds` | How long the user has to send collateral |
198
-
199
- `borrow.destination` and `refund.destination` can be address strings or typed account objects such as `{ type: "ChainAddress", address: "bc1q..." }`, `{ type: "IcPrincipal", address: "aaaaa-aa" }`, or `{ type: "IcrcAccount", address: "aaaaa-aa" }`. Prefer typed objects when the destination family matters.
200
-
201
- Destination validation is chain-specific and runs before loan creation:
202
-
203
- | Asset path | Chain | Valid destination family |
204
- | --- | --- | --- |
205
- | BTC L1 | `"BTC"` | BTC mainnet chain address |
206
- | ETH L1 USDC/USDT | `"ETH"` | EVM chain address |
207
- | ICP native | `"ICP"` | IC principal, ICRC account, or ICP account identifier |
208
- | ckBTC, ckUSDC, ckUSDT | `"ICP"` | IC principal |
209
-
210
- The SDK rejects mismatched L1-vs-IC destination families, such as an ETH address for a ck-ledger delivery or a BTC/EVM address for an ICP destination.
211
-
212
- If creation succeeds remotely but response hydration fails, the SDK throws `SimpleLoanCreatedError`. The error includes `loanId` and `ref`; recover with `simpleLoans.get(...)` and do not submit `create(...)` again.
213
-
214
- ### `client.simpleLoans.get({ ref })`
215
-
216
- Loads loan state from a saved user-facing reference.
217
-
218
- Use this for status pages, refreshes, and support links. The SDK combines canister state with the Liquidium SDK API lookup so the restored loan includes the original collateral deposit hint.
219
-
220
- ### `client.simpleLoans.get({ loanId })`
221
-
222
- Loads loan state by numeric canister loan id.
223
-
224
- Use this when your backend stores the numeric id instead of the short reference.
225
-
226
- ### `client.simpleLoans.find(query)`
227
-
228
- Finds simple loans by short reference, numeric canister loan id string, generated deposit or repayment address, borrow or refund destination address, or indexed transaction id/hash through the SDK API search index.
229
-
230
- Use this for recovery and manage pages where the user may paste any loan identifier. The method returns lightweight matches because address and transaction-id lookups can match many loans. Use `client.simpleLoans.get(...)` after the user selects a match.
231
-
232
- ```ts
233
- const results = await client.simpleLoans.find("bc1q...");
234
- const byRef = await client.simpleLoans.find("ABC123");
235
- const byLoanId = await client.simpleLoans.find("42");
236
-
237
- for (const result of results) {
238
- console.log(result.ref);
239
- console.log(result.loanId);
240
- console.log(result.collateral.asset, result.borrow.asset);
241
- console.log(result.collateral.amount);
242
- }
243
-
244
- const selectedLoan = await client.simpleLoans.get({ loanId: results[0].loanId });
245
- ```
246
-
247
- Call `get(...)` when you already have an exact canister identifier and want direct canister lookup without an array:
248
-
249
- ```ts
250
- const loanById = await client.simpleLoans.get({ loanId: 123n });
251
- const loanByRef = await client.simpleLoans.get({ ref: "ABC123" });
252
- ```
253
-
254
- ### `client.quote.calculateLtv(request, pools, prices)`
255
-
256
- Calculates implied LTV from selected pools, prices, borrow amount, and collateral amount.
257
-
258
- Use this before `client.simpleLoans.create(...)` so your app can block invalid input and choose a safe `ltvMaxBps`.
259
-
260
- ### Borrow minimums
261
-
262
- The SDK enforces product minimums before borrow creation:
263
-
264
- | Asset | Minimum borrow amount |
265
- | --- | --- |
266
- | BTC | `5_100n` sats |
267
- | USDC | `1_000_000n` base units |
268
- | USDT | `1_000_000n` base units |
269
-
270
- Use `getMinimumBorrowAmount(asset)` to display the same minimum that `client.quote.calculateLtv(...)`, `client.quote.getQuote(...)`, `client.simpleLoans.create(...)`, and `client.lending.prepareBorrow(...)` enforce.
271
-
272
- ### Same-asset borrowing
273
-
274
- Pools expose `sameAssetBorrowing` and `sameAssetBorrowingDustThreshold`. When the flag is disabled, same-asset collateral must be strictly below the base-unit dust threshold; equality is rejected. `client.quote.calculateLtv(...)`, `client.quote.getQuote(...)`, and `client.simpleLoans.create(...)` validate the requested collateral amount, while `client.lending.prepareBorrow(...)` validates the profile's current supplied balance before fetching a nonce or asking the wallet to sign.
275
-
276
- ### Withdraw minimums
277
-
278
- The SDK enforces product minimums before withdraw creation:
279
-
280
- | Asset | Minimum withdraw amount |
281
- | --- | --- |
282
- | BTC | `5_000n` sats |
283
- | USDC | `1_000_000n` base units |
284
- | USDT | `1_000_000n` base units |
285
-
286
- Use `getMinimumWithdrawAmount(asset)` to display the same minimum that `client.lending.prepareWithdraw(...)` enforces.
287
-
288
- ### Profile full withdraw amounts
289
-
290
- For profile-based withdraw flows, call `client.positions.getFullWithdrawAmount(profileId, poolId)` before building the withdraw request. The helper returns `{ amount, decimals }`: pass `amount` to `client.lending.withdraw(...)` or `client.lending.prepareWithdraw(...)`, and use `decimals` for display formatting. Do not add `earnedInterest`; the returned amount already uses the current supplied balance.
291
-
292
- ## Response Fields
293
-
294
- Most Simple Loans UIs show or store these fields:
295
-
296
- | Field | Use |
297
- | --- | --- |
298
- | `loan.ref` | Save and show this reference so the loan can be restored later |
299
- | `loan.status` | Shared lifecycle status: `{ operation, state, confirmations, requiredConfirmations }` |
300
- | `loan.initialDeposit.collateralAmount` | Intended credited collateral target used for LTV |
301
- | `loan.initialDeposit.targets[chain]` | Fee-inclusive amount, fee estimate, and destination for that transfer chain |
302
- | `loan.initialDeposit.detectedTimestamp` | Unix timestamp in seconds when the collateral deposit was detected, or `null` before detection |
303
- | `loan.initialDeposit.expiryTimestamp` | Unix timestamp in seconds when the collateral deposit window expires, or `null` before detection when unavailable |
304
- | `loan.repayment.targets[chain]` | Full repayment quote and destination for that transfer chain |
305
- | `loan.position` | Current collateral, debt, and interest state for the generated profile |
306
-
307
- `client.simpleLoans.find(...)` returns lightweight search matches with `loanId`, `ref`, `createdAt`, `profileId`, `collateral`, and `borrow`. Use `client.simpleLoans.get(...)` to load full loan fields, and use `client.activities.list(...)` separately when you need deposit, borrow, repayment, or withdrawal activity.
308
-
309
- ## Amounts
310
-
311
- The SDK returns amount fields as `bigint` values in the asset's smallest unit.
312
-
313
- | Asset type | Example |
314
- | --- | --- |
315
- | BTC | Satoshis |
316
- | ICP | e8s |
317
- | USDC / USDT | Token base units using the pool decimals |
318
-
319
- Use `Pool.decimals` from `client.market.listPools()` when converting user-entered decimals to base units. Hydrated simple loans also include `loan.collateral.decimals`, `loan.borrow.decimals`, and `loan.initialDeposit.decimals` for display.
320
-
321
- ## Status And Activity Tracking
322
-
323
- Reload loans with `client.simpleLoans.get({ ref })` when you need current state, transfer targets, or the latest repayment quote.
324
-
325
- Status-returning methods use the same `LiquidiumStatus` shape:
326
-
327
- ```ts
328
- type LiquidiumStatus = {
329
- operation: "deposit" | "borrow" | "repayment" | "withdrawal" | "liquidation";
330
- state: "action_required" | "confirming" | "processing" | "active" | "completed" | "failed" | "expired";
331
- confirmations: number | null;
332
- requiredConfirmations: number | null;
333
- };
334
- ```
335
-
336
- `action_required` means the user or app must do something, such as sending funds. `confirming` means a tx is known but still needs confirmations. `processing` means confirmations are sufficient and Liquidium or the protocol is still processing. `active` means the loan is live and waiting for the next repayment action.
337
-
338
- Use activities to track collateral deposits, borrow outflows, repayment deposits, confirmations, and fee top-ups. Activity confirmations are exposed on `activity.status`. Activity lists default to active items; pass `filter: "all"` when you need completed activity too. The activities module accepts the saved simple loan reference and resolves the generated profile for you:
339
-
340
- Activities expose chain transaction ids on `activity.txids` when ids are available.
341
-
342
- ```ts
343
- const activities = await client.activities.list({
344
- shortRef: loan.ref,
345
- filter: "active",
346
- });
347
- ```
348
-
349
- If you have a receipt or activity id from the flow, you can also load activity status:
55
+ const deposit = loan.initialDeposit.targets[Chain.BTC];
350
56
 
351
- ```ts
352
- const activityStatus = await client.activities.getStatus({
353
- shortRef: loan.ref,
354
- id: "<activity-or-receipt-id>",
355
- });
57
+ console.log("Loan reference:", loan.ref);
58
+ console.log("Send collateral to:", deposit?.target.address);
356
59
  ```
357
60
 
358
- ## Example Apps
359
-
360
- Start browser integrations with the examples.
361
-
362
- | Example | What it shows |
363
- | --- | --- |
364
- | [`examples/simple-loans-flow`](https://github.com/Liquidium-Inc/liquidium-sdk/tree/main/examples/simple-loans-flow) | Accountless Simple Loans UX with manual destination addresses, pool selection, LTV preview, loan creation, status reload, activity status, and loan recovery |
365
- | [`examples/sdk-method-query`](https://github.com/Liquidium-Inc/liquidium-sdk/tree/main/examples/sdk-method-query) | Developer tool for calling SDK methods, including Simple Loans method templates |
61
+ Use `client.simpleLoans` for accountless borrowing. Use `client.accounts`, `client.lending`, and `client.positions` for profile-based lending.
366
62
 
367
- Run the Simple Loans example:
63
+ Amounts use `bigint` values in each asset's smallest unit. Read pool decimals before converting user input.
368
64
 
369
- ```bash
370
- git clone https://github.com/Liquidium-Inc/liquidium-sdk.git
371
- cd liquidium-sdk
372
- pnpm install
373
- pnpm --filter @liquidium/example-simple-loans-flow dev
374
- ```
375
-
376
- ## Browser And Runtime Support
65
+ See the [quick start](https://liquidium-inc.github.io/liquidium-sdk/getting-started/quick-start/) for LTV validation, repayment, and recovery.
377
66
 
378
- Use the SDK in browser apps and modern TypeScript runtimes.
67
+ ## Examples
379
68
 
380
- | Requirement | Notes |
381
- | --- | --- |
382
- | Node.js | 20+ for this repository |
383
- | Package manager | pnpm 9+ for local development |
384
- | Browser APIs | `fetch`, `BigInt`, and standard ESM support |
385
- | Wallet UI | Bring your own wallet provider; wallet-backed examples use Dynamic |
69
+ - [Simple Loans](https://github.com/Liquidium-Inc/liquidium-sdk/tree/main/examples/simple-loans-flow)
70
+ - [SDK method query](https://github.com/Liquidium-Inc/liquidium-sdk/tree/main/examples/sdk-method-query)
71
+ - [Deposit address flow](https://github.com/Liquidium-Inc/liquidium-sdk/tree/main/examples/deposit-address-flow)
72
+ - [Contract interaction flow](https://github.com/Liquidium-Inc/liquidium-sdk/tree/main/examples/contract-interaction-flow)
386
73
 
387
74
  ## Development
388
75
 
76
+ Requires Node.js 20+ and pnpm 11+.
77
+
389
78
  ```bash
390
- git clone https://github.com/Liquidium-Inc/liquidium-sdk.git
391
- cd liquidium-sdk
392
79
  pnpm install
393
- pnpm run build
394
- pnpm run typecheck
395
- pnpm run test
80
+ pnpm build
81
+ pnpm typecheck
82
+ pnpm test
396
83
  ```
397
84
 
398
- ## More API Details
399
-
400
- This README covers `@liquidium/client`. Start new integrations with `client.simpleLoans`; profile-based deposit-address flows and ETH contract-interaction flows are advanced paths.
401
-
402
85
  ## License
403
86
 
404
87
  MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liquidium/client",
3
- "version": "0.5.0-rc.1",
3
+ "version": "0.5.0",
4
4
  "description": "The official client for the Liquidium protocol",
5
5
  "keywords": [
6
6
  "liquidium",