@liquidium/client 0.4.1 → 0.5.0-rc.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
@@ -54,7 +54,13 @@ npm install @liquidium/client
54
54
  Create an instant loan, display the deposit target, and restore the loan by reference:
55
55
 
56
56
  ```ts
57
- import { LiquidiumClient, type Pool, type SupplyTarget } from "@liquidium/client";
57
+ import {
58
+ Asset,
59
+ Chain,
60
+ LiquidiumClient,
61
+ type Pool,
62
+ type SupplyTarget,
63
+ } from "@liquidium/client";
58
64
 
59
65
  const client = new LiquidiumClient();
60
66
 
@@ -63,8 +69,8 @@ const [pools, prices] = await Promise.all([
63
69
  client.market.getAssetPrices(),
64
70
  ]);
65
71
 
66
- const collateralPool = requirePool(pools, "BTC");
67
- const borrowPool = requirePool(pools, "USDC");
72
+ const collateralPool = requirePool(pools, Asset.BTC, Chain.BTC);
73
+ const borrowPool = requirePool(pools, Asset.USDC, Chain.ETH);
68
74
 
69
75
  const collateralAmount = 50_000n; // BTC sats
70
76
  const borrowAmount = 9_000_000n; // USDC base units
@@ -85,34 +91,44 @@ if (ltv.validationErrors.length > 0) {
85
91
  }
86
92
 
87
93
  const loan = await client.instantLoans.create({
88
- collateralPoolId: collateralPool.id,
89
- borrowPoolId: borrowPool.id,
90
- collateralAsset: "BTC",
91
- borrowAsset: "USDC",
92
- collateralAmount,
93
- borrowAmount,
94
- ltvMaxBps: ltv.maxAllowedLtvBps,
95
- depositWindowSeconds: 3_600n,
96
- borrowDestination: {
97
- type: "External",
98
- address: "0x2222222222222222222222222222222222222222",
94
+ collateral: {
95
+ poolId: collateralPool.id,
96
+ asset: Asset.BTC,
97
+ amount: collateralAmount,
99
98
  },
100
- refundDestination: {
101
- type: "External",
102
- address: "bc1qrefunddestination",
99
+ borrow: {
100
+ poolId: borrowPool.id,
101
+ asset: Asset.USDC,
102
+ amount: borrowAmount,
103
+ chain: Chain.ETH,
104
+ destination: "0x2222222222222222222222222222222222222222",
103
105
  },
106
+ refund: {
107
+ chain: Chain.BTC,
108
+ destination: "1BoatSLRHtKNngkdXEeobR76b53LETtpyT",
109
+ },
110
+ ltvMaxBps: ltv.maxAllowedLtvBps,
111
+ depositWindowSeconds: 3_600n,
104
112
  });
105
113
 
114
+ const initialDeposit = loan.initialDeposit.targets[Chain.BTC];
115
+ if (!initialDeposit) {
116
+ throw new Error("Missing BTC initial-deposit target.");
117
+ }
118
+
106
119
  console.log("Save this loan reference:", loan.ref);
107
- console.log("Send initial deposit amount:", loan.initialDeposit.amount.toString());
108
- console.log("Send collateral to:", formatSupplyTarget(loan.initialDeposit.target));
120
+ console.log("Send initial deposit amount:", initialDeposit.amount.toString());
121
+ console.log("Send collateral to:", formatSupplyTarget(initialDeposit.target));
109
122
 
110
123
  const restoredLoan = await client.instantLoans.get({ ref: loan.ref });
124
+ const repayment = restoredLoan.repayment.targets[Chain.ETH];
111
125
 
112
126
  console.log("Loan status:", restoredLoan.status);
113
- console.log("Restored initial deposit amount:", restoredLoan.initialDeposit.amount.toString());
114
- console.log("Repay amount:", restoredLoan.repayment.amount.toString());
115
- console.log("Repay target:", formatSupplyTarget(restoredLoan.repayment.target));
127
+ console.log("Repay amount:", repayment?.amount.toString() ?? "0");
128
+ console.log(
129
+ "Repay target:",
130
+ repayment ? formatSupplyTarget(repayment.target) : "No repayment due"
131
+ );
116
132
 
117
133
  const activities = await client.activities.list({ shortRef: loan.ref });
118
134
 
@@ -123,26 +139,28 @@ const foundLoans = await client.instantLoans.find(loan.ref);
123
139
  console.log("Found loan reference:", foundLoans[0]?.ref);
124
140
  console.log("Found loan collateral:", foundLoans[0]?.collateral.amount.toString());
125
141
 
126
- function requirePool(pools: Pool[], asset: string): Pool {
127
- const pool = pools.find((candidatePool) => candidatePool.asset === asset);
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
+ );
128
150
 
129
151
  if (!pool) {
130
- throw new Error(`Missing ${asset} pool.`);
152
+ throw new Error(`Missing ${chain}/${asset} pool.`);
131
153
  }
132
154
 
133
155
  if (pool.frozen) {
134
- throw new Error(`${asset} pool is frozen.`);
156
+ throw new Error(`${chain}/${asset} pool is frozen.`);
135
157
  }
136
158
 
137
159
  return pool;
138
160
  }
139
161
 
140
162
  function formatSupplyTarget(target: SupplyTarget): string {
141
- if (target.type === "nativeAddress") {
142
- return target.address;
143
- }
144
-
145
- return target.account;
163
+ return target.address;
146
164
  }
147
165
  ```
148
166
 
@@ -154,13 +172,15 @@ Instant-loan integrations use this sequence:
154
172
  | --- | --- | --- |
155
173
  | Load market data | `client.market.listPools()` and `client.market.getAssetPrices()` | Show supported collateral and borrow assets |
156
174
  | Validate amounts | `client.quote.calculateLtv(...)` | Block too-small borrow amounts, invalid LTV, or frozen-pool input before creating a loan |
157
- | Create loan | `client.instantLoans.create(...)` | Store `loan.ref` and show `loan.initialDeposit.amount` plus `loan.initialDeposit.target` |
175
+ | Create loan | `client.instantLoans.create(...)` | Store `loan.ref` and show the quote in `loan.initialDeposit.targets[chain]` |
158
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 |
159
- | Repay loan | Read `loan.repayment` | Ask the user to send `loan.repayment.amount` to `loan.repayment.target`; amount is `0n` when no repayment is due |
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 |
160
178
 
161
- `client.instantLoans.create(...)` and `client.instantLoans.get(...)` return the generated Liquidium profile, current position state, an initial deposit quote with its transfer target, and a repayment quote with its transfer target. Repayment amount fields are zero when the loan has no debt. Users do not manage the generated profile.
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.
162
180
 
163
- `client.market.listPools()` returns only pools whose asset and chain variants are supported by this SDK version. Canister pools for unsupported variants such as `ICP` or `SOL` are omitted from the returned list.
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.
164
184
 
165
185
  ## Core API
166
186
 
@@ -170,18 +190,26 @@ Creates an accountless instant loan and returns generated transfer targets.
170
190
 
171
191
  | Field | Description |
172
192
  | --- | --- |
173
- | `collateralPoolId` | Pool that receives the collateral deposit |
174
- | `borrowPoolId` | Pool the loan borrows from |
175
- | `collateralAsset` | Collateral asset symbol, for example `"BTC"` |
176
- | `borrowAsset` | Borrow asset symbol, for example `"USDC"` |
177
- | `collateralAmount` | Intended credited collateral amount in base units, before deposit/inflow fees |
178
- | `borrowAmount` | Borrow amount in base units. The SDK rejects values below the asset minimum. |
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 |
179
196
  | `ltvMaxBps` | Maximum LTV in basis points, where `6_000n` is 60% |
180
197
  | `depositWindowSeconds` | How long the user has to send collateral |
181
- | `borrowDestination` | External address that receives borrowed funds |
182
- | `refundDestination` | External address that receives collateral refunds |
183
198
 
184
- `borrowDestination` and `refundDestination` can be address strings or account objects such as `{ type: "External", address: "bc1q..." }`.
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.
185
213
 
186
214
  ### `client.instantLoans.get({ ref })`
187
215
 
@@ -265,13 +293,11 @@ Most instant-loan UIs show or store these fields:
265
293
  | --- | --- |
266
294
  | `loan.ref` | Save and show this reference so the loan can be restored later |
267
295
  | `loan.status` | Shared lifecycle status: `{ operation, state, confirmations, requiredConfirmations }` |
268
- | `loan.initialDeposit.amount` | Fee-inclusive collateral amount to send after creation or restore |
269
296
  | `loan.initialDeposit.collateralAmount` | Intended credited collateral target used for LTV |
270
- | `loan.initialDeposit.target` | Address or ICRC account where the user sends collateral |
297
+ | `loan.initialDeposit.targets[chain]` | Fee-inclusive amount, fee estimate, and destination for that transfer chain |
271
298
  | `loan.initialDeposit.detectedTimestamp` | Unix timestamp in seconds when the collateral deposit was detected, or `null` before detection |
272
299
  | `loan.initialDeposit.expiryTimestamp` | Unix timestamp in seconds when the collateral deposit window expires, or `null` before detection when unavailable |
273
- | `loan.repayment.amount` | Full amount to repay, including fee and interest buffer. Zero when no repayment is due |
274
- | `loan.repayment.target` | Address or ICRC account where the user sends repayment |
300
+ | `loan.repayment.targets[chain]` | Full repayment quote and destination for that transfer chain |
275
301
  | `loan.position` | Current collateral, debt, and interest state for the generated profile |
276
302
 
277
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.
@@ -283,6 +309,7 @@ The SDK returns amount fields as `bigint` values in the asset's smallest unit.
283
309
  | Asset type | Example |
284
310
  | --- | --- |
285
311
  | BTC | Satoshis |
312
+ | ICP | e8s |
286
313
  | USDC / USDT | Token base units using the pool decimals |
287
314
 
288
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.