@liquidium/client 0.5.0-rc.0 → 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.
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 instant 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/instant-loans-flow"><b>Instant Loan 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/)
26
-
27
- ## Why Start With Instant Loans
28
-
29
- - **Accountless loan creation**: create instant 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 instant loans | You want a short checkout-style flow where users borrow against collateral without creating a Liquidium profile first | `client.instantLoans.create(...)`, `client.instantLoans.get(...)`, `client.instantLoans.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 instant 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.
10
+ TypeScript client for Liquidium lending and accountless Simple Loans.
45
11
 
46
- ## Quick Start
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)
47
13
 
48
- Install the client package:
14
+ ## Install
49
15
 
50
16
  ```bash
51
17
  npm install @liquidium/client
52
18
  ```
53
19
 
54
- Create an instant 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
- const loan = await client.instantLoans.create({
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,294 +48,40 @@ const loan = await client.instantLoans.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.instantLoans.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.instantLoans.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
- ## Instant Loan Flow
168
-
169
- Instant-loan 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.instantLoans.create(...)` | Store `loan.ref` and show the quote in `loan.initialDeposit.targets[chain]` |
176
- | Track loan | `client.instantLoans.get({ ref })`, `client.instantLoans.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.instantLoans.create(...)` and `client.instantLoans.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.instantLoans.create(request)`
188
-
189
- Creates an accountless instant 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 `InstantLoanCreatedError`. The error includes `loanId` and `ref`; recover with `instantLoans.get(...)` and do not submit `create(...)` again.
213
-
214
- ### `client.instantLoans.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.instantLoans.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.instantLoans.find(query)`
227
-
228
- Finds instant 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.instantLoans.get(...)` after the user selects a match.
231
-
232
- ```ts
233
- const results = await client.instantLoans.find("bc1q...");
234
- const byRef = await client.instantLoans.find("ABC123");
235
- const byLoanId = await client.instantLoans.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.instantLoans.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.instantLoans.get({ loanId: 123n });
251
- const loanByRef = await client.instantLoans.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.instantLoans.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.instantLoans.create(...)`, and `client.lending.prepareBorrow(...)` enforce.
271
-
272
- ### Withdraw minimums
273
-
274
- The SDK enforces product minimums before withdraw creation:
275
-
276
- | Asset | Minimum withdraw amount |
277
- | --- | --- |
278
- | BTC | `5_000n` sats |
279
- | USDC | `1_000_000n` base units |
280
- | USDT | `1_000_000n` base units |
281
-
282
- Use `getMinimumWithdrawAmount(asset)` to display the same minimum that `client.lending.prepareWithdraw(...)` enforces.
283
-
284
- ### Profile full withdraw amounts
285
-
286
- 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.
287
-
288
- ## Response Fields
289
-
290
- Most instant-loan UIs show or store these fields:
291
-
292
- | Field | Use |
293
- | --- | --- |
294
- | `loan.ref` | Save and show this reference so the loan can be restored later |
295
- | `loan.status` | Shared lifecycle status: `{ operation, state, confirmations, requiredConfirmations }` |
296
- | `loan.initialDeposit.collateralAmount` | Intended credited collateral target used for LTV |
297
- | `loan.initialDeposit.targets[chain]` | Fee-inclusive amount, fee estimate, and destination for that transfer chain |
298
- | `loan.initialDeposit.detectedTimestamp` | Unix timestamp in seconds when the collateral deposit was detected, or `null` before detection |
299
- | `loan.initialDeposit.expiryTimestamp` | Unix timestamp in seconds when the collateral deposit window expires, or `null` before detection when unavailable |
300
- | `loan.repayment.targets[chain]` | Full repayment quote and destination for that transfer chain |
301
- | `loan.position` | Current collateral, debt, and interest state for the generated profile |
302
-
303
- `client.instantLoans.find(...)` returns lightweight search matches with `loanId`, `ref`, `createdAt`, `profileId`, `collateral`, and `borrow`. Use `client.instantLoans.get(...)` to load full loan fields, and use `client.activities.list(...)` separately when you need deposit, borrow, repayment, or withdrawal activity.
304
-
305
- ## Amounts
306
-
307
- The SDK returns amount fields as `bigint` values in the asset's smallest unit.
308
-
309
- | Asset type | Example |
310
- | --- | --- |
311
- | BTC | Satoshis |
312
- | ICP | e8s |
313
- | USDC / USDT | Token base units using the pool decimals |
314
-
315
- Use `Pool.decimals` from `client.market.listPools()` when converting user-entered decimals to base units. Hydrated instant loans also include `loan.collateral.decimals`, `loan.borrow.decimals`, and `loan.initialDeposit.decimals` for display.
316
-
317
- ## Status And Activity Tracking
318
-
319
- Reload loans with `client.instantLoans.get({ ref })` when you need current state, transfer targets, or the latest repayment quote.
320
-
321
- Status-returning methods use the same `LiquidiumStatus` shape:
322
-
323
- ```ts
324
- type LiquidiumStatus = {
325
- operation: "deposit" | "borrow" | "repayment" | "withdrawal" | "liquidation";
326
- state: "action_required" | "confirming" | "processing" | "active" | "completed" | "failed" | "expired";
327
- confirmations: number | null;
328
- requiredConfirmations: number | null;
329
- };
330
- ```
331
-
332
- `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.
333
-
334
- 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 instant-loan reference and resolves the generated profile for you:
335
-
336
- Activities expose chain transaction ids on `activity.txids` when ids are available.
337
-
338
- ```ts
339
- const activities = await client.activities.list({
340
- shortRef: loan.ref,
341
- filter: "active",
342
- });
343
- ```
344
-
345
- 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];
346
56
 
347
- ```ts
348
- const activityStatus = await client.activities.getStatus({
349
- shortRef: loan.ref,
350
- id: "<activity-or-receipt-id>",
351
- });
57
+ console.log("Loan reference:", loan.ref);
58
+ console.log("Send collateral to:", deposit?.target.address);
352
59
  ```
353
60
 
354
- ## Example Apps
355
-
356
- Start browser integrations with the examples.
357
-
358
- | Example | What it shows |
359
- | --- | --- |
360
- | [`examples/instant-loans-flow`](https://github.com/Liquidium-Inc/liquidium-sdk/tree/main/examples/instant-loans-flow) | Accountless instant loan UX with manual destination addresses, pool selection, LTV preview, loan creation, status reload, activity status, and loan recovery |
361
- | [`examples/sdk-method-query`](https://github.com/Liquidium-Inc/liquidium-sdk/tree/main/examples/sdk-method-query) | Developer tool for calling SDK methods, including instant loan method templates |
61
+ Use `client.simpleLoans` for accountless borrowing. Use `client.accounts`, `client.lending`, and `client.positions` for profile-based lending.
362
62
 
363
- Run the instant loan example:
63
+ Amounts use `bigint` values in each asset's smallest unit. Read pool decimals before converting user input.
364
64
 
365
- ```bash
366
- git clone https://github.com/Liquidium-Inc/liquidium-sdk.git
367
- cd liquidium-sdk
368
- pnpm install
369
- pnpm --filter @liquidium/example-instant-loans-flow dev
370
- ```
371
-
372
- ## 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.
373
66
 
374
- Use the SDK in browser apps and modern TypeScript runtimes.
67
+ ## Examples
375
68
 
376
- | Requirement | Notes |
377
- | --- | --- |
378
- | Node.js | 20+ for this repository |
379
- | Package manager | pnpm 9+ for local development |
380
- | Browser APIs | `fetch`, `BigInt`, and standard ESM support |
381
- | 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)
382
73
 
383
74
  ## Development
384
75
 
76
+ Requires Node.js 20+ and pnpm 11+.
77
+
385
78
  ```bash
386
- git clone https://github.com/Liquidium-Inc/liquidium-sdk.git
387
- cd liquidium-sdk
388
79
  pnpm install
389
- pnpm run build
390
- pnpm run typecheck
391
- pnpm run test
80
+ pnpm build
81
+ pnpm typecheck
82
+ pnpm test
392
83
  ```
393
84
 
394
- ## More API Details
395
-
396
- This README covers `@liquidium/client`. Start new integrations with `client.instantLoans`; profile-based deposit-address flows and ETH contract-interaction flows are advanced paths.
397
-
398
85
  ## License
399
86
 
400
87
  MIT