@kasufinance/kasu-sdk 2.7.1 → 2.10.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 +162 -7
- package/dist/bundle.cjs.js +2292 -449
- package/dist/bundle.esm.js +2253 -451
- package/dist/domain/batch-proof.d.ts +210 -0
- package/dist/domain/batch-proof.js +384 -0
- package/dist/domain/batch-proof.js.map +1 -0
- package/dist/domain/explorer-urls.d.ts +33 -0
- package/dist/domain/explorer-urls.js +38 -0
- package/dist/domain/explorer-urls.js.map +1 -0
- package/dist/domain/fixed-term.d.ts +74 -0
- package/dist/domain/fixed-term.js +86 -0
- package/dist/domain/fixed-term.js.map +1 -0
- package/dist/domain/index.d.ts +12 -2
- package/dist/domain/index.js +7 -2
- package/dist/domain/index.js.map +1 -1
- package/dist/domain/partners.d.ts +29 -0
- package/dist/domain/partners.js +20 -0
- package/dist/domain/partners.js.map +1 -1
- package/dist/domain/requests.d.ts +24 -0
- package/dist/domain/requests.js +33 -0
- package/dist/domain/requests.js.map +1 -1
- package/dist/domain/sponsored-calls.d.ts +74 -0
- package/dist/domain/sponsored-calls.js +156 -0
- package/dist/domain/sponsored-calls.js.map +1 -0
- package/dist/domain/yields.d.ts +121 -0
- package/dist/domain/yields.js +151 -0
- package/dist/domain/yields.js.map +1 -0
- package/dist/facade/calls.d.ts +59 -0
- package/dist/facade/calls.js +89 -0
- package/dist/facade/calls.js.map +1 -0
- package/dist/facade/chain-configs.js +5 -0
- package/dist/facade/chain-configs.js.map +1 -1
- package/dist/facade/flows.d.ts +40 -3
- package/dist/facade/flows.js +36 -3
- package/dist/facade/flows.js.map +1 -1
- package/dist/facade/index.d.ts +3 -1
- package/dist/facade/index.js +1 -0
- package/dist/facade/index.js.map +1 -1
- package/dist/facade/kasu.d.ts +8 -2
- package/dist/facade/kasu.js +17 -4
- package/dist/facade/kasu.js.map +1 -1
- package/dist/facade/strategies.d.ts +43 -2
- package/dist/facade/strategies.js +80 -4
- package/dist/facade/strategies.js.map +1 -1
- package/dist/facade/types.d.ts +18 -0
- package/dist/flows/batch-errors.d.ts +74 -0
- package/dist/flows/batch-errors.js +83 -0
- package/dist/flows/batch-errors.js.map +1 -0
- package/dist/flows/batch-submission.d.ts +223 -0
- package/dist/flows/batch-submission.js +321 -0
- package/dist/flows/batch-submission.js.map +1 -0
- package/dist/flows/deposit-flow.d.ts +128 -4
- package/dist/flows/deposit-flow.js +233 -4
- package/dist/flows/deposit-flow.js.map +1 -1
- package/dist/flows/index.d.ts +6 -2
- package/dist/flows/index.js +3 -1
- package/dist/flows/index.js.map +1 -1
- package/dist/flows/withdraw-flow.d.ts +95 -4
- package/dist/flows/withdraw-flow.js +107 -2
- package/dist/flows/withdraw-flow.js.map +1 -1
- package/dist/services/DataService/queries.js +1 -0
- package/dist/services/DataService/queries.js.map +1 -1
- package/dist/services/UserLending/user-lending.d.ts +13 -0
- package/dist/services/UserLending/user-lending.js +25 -4
- package/dist/services/UserLending/user-lending.js.map +1 -1
- package/package.json +1 -1
- package/src/domain/batch-proof.ts +576 -0
- package/src/domain/explorer-urls.ts +74 -0
- package/src/domain/fixed-term.ts +115 -0
- package/src/domain/index.ts +56 -0
- package/src/domain/partners.ts +35 -0
- package/src/domain/requests.ts +37 -0
- package/src/domain/sponsored-calls.ts +213 -0
- package/src/domain/yields.ts +189 -0
- package/src/facade/calls.ts +135 -0
- package/src/facade/chain-configs.ts +5 -0
- package/src/facade/flows.ts +35 -2
- package/src/facade/index.ts +3 -0
- package/src/facade/kasu.ts +32 -2
- package/src/facade/strategies.ts +98 -7
- package/src/facade/types.ts +19 -0
- package/src/flows/batch-errors.ts +118 -0
- package/src/flows/batch-submission.ts +511 -0
- package/src/flows/deposit-flow.ts +379 -7
- package/src/flows/index.ts +34 -1
- package/src/flows/withdraw-flow.ts +219 -10
- package/src/services/DataService/queries.ts +1 -0
- package/src/services/UserLending/user-lending.ts +38 -10
package/README.md
CHANGED
|
@@ -100,13 +100,14 @@ a read-only `Kasu.create({ chain: 'plume' })` throws — pass your own provider
|
|
|
100
100
|
read its history.
|
|
101
101
|
|
|
102
102
|
Every entry lives in `CHAIN_CONFIGS`, including contract addresses, subgraph
|
|
103
|
-
URLs, the stable asset
|
|
103
|
+
URLs, the stable asset, public RPC defaults and the block explorer:
|
|
104
104
|
|
|
105
105
|
```ts
|
|
106
|
-
import { CHAIN_CONFIGS } from '@kasufinance/kasu-sdk';
|
|
106
|
+
import { CHAIN_CONFIGS, explorerTxUrl } from '@kasufinance/kasu-sdk';
|
|
107
107
|
|
|
108
108
|
CHAIN_CONFIGS.base.stableAsset; // { address, symbol, name, decimals, currencyCode }
|
|
109
109
|
CHAIN_CONFIGS.xdc.rpcUrls; // starting preference only — override with your own
|
|
110
|
+
explorerTxUrl(CHAIN_CONFIGS.base, txHash); // https://basescan.org/tx/0x… — throws on a malformed hash
|
|
110
111
|
```
|
|
111
112
|
|
|
112
113
|
You can also pass a whole `ChainConfigEntry` instead of a chain key.
|
|
@@ -115,10 +116,11 @@ You can also pass a whole `ChainConfigEntry` instead of a chain key.
|
|
|
115
116
|
|
|
116
117
|
| Facade | Methods | Purpose |
|
|
117
118
|
| ----------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------- |
|
|
118
|
-
| `kasu.strategies` | `getAll()`, `getVisible()`, `getById()`, `getPlatformStats()`, `getPerformanceFeePercent()`, `calculateDepositLimits()` | Browse pools, APY, capacity
|
|
119
|
+
| `kasu.strategies` | `getAll()`, `getVisible()`, `getById()`, `getPlatformStats()`, `getPerformanceFeePercent()`, `calculateDepositLimits()`, `getRiskPerformance(poolId)`, `getOriginator(poolId)` | Browse pools, APY, capacity, risk, originator |
|
|
119
120
|
| `kasu.deposits` | `deposit()`, `withdraw()`, `withdrawMax()`, `buildKycParams()`, `isClearingPending()` | Submit transactions |
|
|
120
121
|
| `kasu.portfolio` | `getPositions()`, `getTransactionHistory()`, `getRequestStates()` | Lender balances, yield, history |
|
|
121
122
|
| `kasu.flows` | `deposit(ports)`, `withdraw(ports?)` | Headless transaction pipelines |
|
|
123
|
+
| `kasu.calls` | `requestWithdrawal(params)`, `cancelDepositRequest(poolId, dNftId)`, `cancelWithdrawalRequest(poolId, wNftId)`, `withdrawAtExpiry(poolId, lockId)` | Encoded calls for a sponsored relay (read, then encode — never sends) |
|
|
122
124
|
|
|
123
125
|
On the instance itself: `kasu.connect(signer)`, `kasu.isReadOnly`,
|
|
124
126
|
`kasu.provider`, `kasu.chainConfig`, `kasu.isLiteDeployment`, and
|
|
@@ -142,7 +144,10 @@ application formats them in its own design system and language.
|
|
|
142
144
|
| Tranches | `trancheHasCapacity`, `poolAllTranchesFull`, `derivePoolStatus`, `trancheRiskRank`, `compareTrancheSeniority`, `pickDefaultTrancheId`, `trancheApyBounds`, `netTrancheApyBounds`, `MIN_TRANCHE_CAPACITY` |
|
|
143
145
|
| Deposit bounds | `resolveDepositBounds`, `resolveBoundShortcuts`, `isBelowMinimumCapacity`, `parseTrancheBound`, `floorToCents`, `ceilToCents` |
|
|
144
146
|
| Pools | `selectVisiblePools`, `poolMaxApy`, `pickHighestYieldTranche`, `maxNetRateCeiling` |
|
|
145
|
-
| Partners | `getCreditOriginator`, `getInstitutionalLender`, `APXIUM`, `INVOICEMATE`, `RIXON_CAPITAL`
|
|
147
|
+
| Partners | `getCreditOriginator`, `getInstitutionalLender`, `getStrategyRegion`, `APXIUM`, `INVOICEMATE`, `RIXON_CAPITAL` (each with a `region`) |
|
|
148
|
+
| Fixed term | `availableFixedTermConfigs`, `isFixedTermConfigId`, `lockDurationDays`, `lockDurationMonths`, `DAYS_PER_EPOCH`, `DAYS_PER_MONTH`, `MIN_DAYS_FOR_MONTHS` |
|
|
149
|
+
| Yields | `weeklyInterest`, `dailyInterest`, `accruedInterest`, `projectedAnnualEarnings`, `weightedAverageApy`, `SECONDS_PER_WEEK` — NET of the performance fee |
|
|
150
|
+
| Batch proof | `validateDepositBatchCalls`, `proveDepositInReceipt`, `DepositBatchMismatchError`, `ENTRY_POINT_V07` |
|
|
146
151
|
| Tranche display name | `getTrancheDisplayName`, `UPPER_MEZZANINE` |
|
|
147
152
|
| Requests | `deriveRequestState`, `submissionEvents`, `countSubmissions`, `firstSubmissionTimestamp`, `isCycleClosed` |
|
|
148
153
|
| Settlement | `computeSettlementWindow`, `nextCycleBoundary`, `deriveCycleDates`, `CLEARING_WINDOW_SECONDS` |
|
|
@@ -225,8 +230,103 @@ await flow.acceptContract(); // signs it and carries on
|
|
|
225
230
|
// or: flow.declineContract(); → phase 'declined', nothing submitted
|
|
226
231
|
```
|
|
227
232
|
|
|
233
|
+
### One atomic transaction: the `depositBatch` port
|
|
234
|
+
|
|
235
|
+
If your application can submit several calls as ONE atomic transaction (all
|
|
236
|
+
apply or none does), supply the optional `depositBatch` port. When the
|
|
237
|
+
allowance is short, the run then approves and deposits in a single batch
|
|
238
|
+
instead of two transactions. You decide how the batch is sent; the SDK decides
|
|
239
|
+
what is in it:
|
|
240
|
+
|
|
241
|
+
```ts
|
|
242
|
+
import { BatchRevertedError, type BatchCall } from '@kasufinance/kasu-sdk';
|
|
243
|
+
|
|
244
|
+
const flow = kasu.flows.deposit({
|
|
245
|
+
signMessage,
|
|
246
|
+
generateContract,
|
|
247
|
+
getKycSignature,
|
|
248
|
+
depositBatch: async (calls: BatchCall[]) => {
|
|
249
|
+
// calls[0]: stableAsset.approve(LendingPoolManager, amount) — EXACT amount
|
|
250
|
+
// calls[1]: LendingPoolManager.requestDepositWithKyc(…) — value 0
|
|
251
|
+
const tx = await submitAtomically(calls); // your mechanism
|
|
252
|
+
return tx; // anything with wait()
|
|
253
|
+
// Known to revert? throw new BatchRevertedError('ClearingIsPending')
|
|
254
|
+
},
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
// …after acceptContract(), a batched run parks on `awaiting-authorise`:
|
|
258
|
+
flow.authoriseTransfer(); // the lender's explicit go-ahead
|
|
259
|
+
// or: flow.declineTransfer(); → error { step: 'request', reason: 'cancelled' }
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
- The batch path is taken only when the allowance is short, the port is
|
|
263
|
+
supplied and the chain's stable token is known (`kasu.flows.deposit()` fills
|
|
264
|
+
it from the chain config). Otherwise the run is exactly the two-transaction
|
|
265
|
+
pipeline.
|
|
266
|
+
- A batch has no wallet prompt per call, so the run **parks for an explicit
|
|
267
|
+
authorisation** before any money moves. The agreement's TTL is checked again
|
|
268
|
+
after it, and the KYC signature is fetched only then.
|
|
269
|
+
- `state.batched` is `true` from the first state of a batched run. It never
|
|
270
|
+
enters `approve`, so it counts as a three-step run (`stepTotal` 3).
|
|
271
|
+
- Throw `BatchRevertedError(revertError)` when the batch is known to revert →
|
|
272
|
+
`{ step: 'request', reason: 'reverted', revertError }`. Throw a
|
|
273
|
+
`BatchSubmissionError` (or `BatchPendingError`) to report a submission
|
|
274
|
+
outcome: `pending` → `{ reason: 'pending' }`, `already-submitted` →
|
|
275
|
+
`{ reason: 'already-submitted' }`, `failed` → `{ reason: 'failed' }` — read
|
|
276
|
+
at its word, never through the revert decoder. Any other throw is read like a
|
|
277
|
+
direct deposit's: a wallet rejection is `cancelled`, everything else
|
|
278
|
+
`failed`.
|
|
279
|
+
|
|
280
|
+
### Submitting a sponsored batch: `submitBatch` (2.9.0)
|
|
281
|
+
|
|
282
|
+
For a submitter that relays the batch and is asked for its status later (a
|
|
283
|
+
sponsored-gas relay, for one), `submitBatch` owns the polling policy, the
|
|
284
|
+
receipt proof and the outcome taxonomy. Your ports do the I/O; the SDK decides
|
|
285
|
+
what each answer means:
|
|
286
|
+
|
|
287
|
+
```ts
|
|
288
|
+
import {
|
|
289
|
+
submitBatch,
|
|
290
|
+
validateDepositBatchCalls,
|
|
291
|
+
} from '@kasufinance/kasu-sdk';
|
|
292
|
+
|
|
293
|
+
depositBatch: (calls) => {
|
|
294
|
+
// Before signing: the batch is exactly this run's deposit, or it throws.
|
|
295
|
+
const { tranche, amount } = validateDepositBatchCalls(calls, {
|
|
296
|
+
stableAsset, spender, poolId, trancheId, amount, fixedTermConfigId,
|
|
297
|
+
});
|
|
298
|
+
return submitBatch(
|
|
299
|
+
// `pendingPool` is the strategy's pending pool (`ILendingPool.pendingPool()`):
|
|
300
|
+
// with it, only THAT contract's `DepositRequested` can prove the deposit.
|
|
301
|
+
{ calls, expect: { lender, tranche, amount, pendingPool } },
|
|
302
|
+
{
|
|
303
|
+
post: (calls) => postToMyRelay(calls), // → { transactionId }
|
|
304
|
+
getStatus: (id) => readMyRelayStatus(id), // normalised BatchStatusRead
|
|
305
|
+
getReceipt: (hash) => provider.waitForTransaction(hash, 1, 120_000),
|
|
306
|
+
now: Date.now,
|
|
307
|
+
sleep: (ms) => new Promise((r) => setTimeout(r, ms)),
|
|
308
|
+
},
|
|
309
|
+
);
|
|
310
|
+
},
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
- **An ambiguous result is never reported as failed.** Once the batch has been
|
|
314
|
+
posted only a revert proves nothing was deposited; a timeout, an unreadable
|
|
315
|
+
receipt, an unknown status or an unrecognised `post` error is a
|
|
316
|
+
`BatchPendingError`, and the run ends `{ reason: 'pending' }`. Tell the
|
|
317
|
+
lender it may still be processing — never "try again".
|
|
318
|
+
- `wait()` resolves only when `proveDepositInReceipt` finds THIS lender's
|
|
319
|
+
`DepositRequested` for the expected tranche AND amount inside their own user
|
|
320
|
+
operation — and, when `pendingPool` is given, emitted by that contract. A
|
|
321
|
+
handleOps receipt's `status` decides nothing.
|
|
322
|
+
- Polling: first read at once, then 3 s ×1.5 to a 10 s ceiling, for 10 minutes
|
|
323
|
+
(`DEFAULT_BATCH_POLLING_POLICY`; pass a partial policy to override).
|
|
324
|
+
- `checkBatchOutcome(transactionId, expect, ports)` is the one-read check for an
|
|
325
|
+
app's guard against lending twice after a `pending` run.
|
|
326
|
+
|
|
228
327
|
**Phases** — `idle`, `generating-sign`, `generating-fetch`, `awaiting-accept`,
|
|
229
|
-
`accepting-sign`, `approve`, `
|
|
328
|
+
`accepting-sign`, `approve`, `awaiting-authorise` (batch path only),
|
|
329
|
+
`request-sign`, `request-confirm`, and the
|
|
230
330
|
terminal `success` / `declined` / `error`. Each maps to one of four steps
|
|
231
331
|
(`generate`, `confirm`, `approve`, `request`); `stepIndex` and `stepTotal` are
|
|
232
332
|
published because the approve step drops out of the sequence when the allowance
|
|
@@ -246,7 +346,12 @@ type DepositFailure =
|
|
|
246
346
|
revertError: string; // e.g. 'ClearingIsPending'
|
|
247
347
|
error: unknown;
|
|
248
348
|
}
|
|
249
|
-
| { step: 'request'; reason: 'contract-expired' }
|
|
349
|
+
| { step: 'request'; reason: 'contract-expired' } // the 5-minute TTL
|
|
350
|
+
| {
|
|
351
|
+
step: 'request';
|
|
352
|
+
reason: 'pending' | 'already-submitted'; // batch path only — NOT failures
|
|
353
|
+
error: unknown;
|
|
354
|
+
};
|
|
250
355
|
```
|
|
251
356
|
|
|
252
357
|
A wallet rejection is `cancelled`, not a failure: the lender changed their
|
|
@@ -328,7 +433,57 @@ const checked = kasu.flows.withdraw({
|
|
|
328
433
|
```
|
|
329
434
|
|
|
330
435
|
`'max'` is a code you pass, not a balance you read: it routes to the all-shares
|
|
331
|
-
|
|
436
|
+
request, whose share count the SDK reads (`balanceOf`) at submission instead of
|
|
437
|
+
converting an asset figure — so no dust is stranded.
|
|
438
|
+
|
|
439
|
+
### Sponsored withdraw and cancel (2.10.0)
|
|
440
|
+
|
|
441
|
+
`kasu.calls` encodes the single `LendingPoolManager` calls a gas-sponsoring
|
|
442
|
+
relay carries. Each returns `{ kind, call }`: post `kind` and `[call]` exactly
|
|
443
|
+
as given — the relay judges the call by its kind, so never map one yourself.
|
|
444
|
+
|
|
445
|
+
```ts
|
|
446
|
+
import { submitSponsoredCall } from '@kasufinance/kasu-sdk';
|
|
447
|
+
|
|
448
|
+
const ports = {
|
|
449
|
+
post: ({ kind, call }) => postToMyRelay({ kind, calls: [call] }), // → { transactionId }
|
|
450
|
+
getStatus: (id) => readMyRelayStatus(id), // normalised BatchStatusRead
|
|
451
|
+
getReceipt: (hash) => provider.waitForTransaction(hash, 1, 120_000),
|
|
452
|
+
now: Date.now,
|
|
453
|
+
sleep: (ms) => new Promise((r) => setTimeout(r, ms)),
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
// Withdraw: the flow encodes the call (shares from convertToShares, or the
|
|
457
|
+
// whole balanceOf for 'max') and submits it through your port.
|
|
458
|
+
const flow = kasu.flows.withdraw({
|
|
459
|
+
submitCall: (call) =>
|
|
460
|
+
submitSponsoredCall({ call, expect: { sender: lender } }, ports),
|
|
461
|
+
});
|
|
462
|
+
flow.state.sponsored; // true, from the first state
|
|
463
|
+
await flow.start({ poolId, trancheId, amount: 'max', userAddress: lender });
|
|
464
|
+
|
|
465
|
+
// Cancel: encode, then submit the same way.
|
|
466
|
+
const cancel = kasu.calls.cancelDepositRequest(poolId, dNftId);
|
|
467
|
+
const submission = await submitSponsoredCall(
|
|
468
|
+
{ call: cancel, expect: { sender: lender } },
|
|
469
|
+
ports,
|
|
470
|
+
);
|
|
471
|
+
await submission.wait(); // resolves only when the lender's operation executed
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
- `submitSponsoredCall` is `submitBatch` for one call: the same polling policy
|
|
475
|
+
and outcome table, with `proveUserOperationInReceipt` as the proof — the
|
|
476
|
+
lender's own operation, from the EntryPoint, with `success` set. A reverted
|
|
477
|
+
operation is `BatchRevertedError`; anything unproven is `BatchPendingError`.
|
|
478
|
+
- On the sponsored path a withdrawal's failure can also be `{ reason:
|
|
479
|
+
'reverted', revertError }` and `{ reason: 'pending' | 'already-submitted' }`.
|
|
480
|
+
A wallet rejection thrown by `submitCall` (the lender declined to sign) is
|
|
481
|
+
`cancelled`. Any other throw from `submitCall` or `wait()` the SDK does not
|
|
482
|
+
recognise is `pending` — it may have left, so never tell the lender to try
|
|
483
|
+
again. A throw while encoding (a share read, an empty position) is `failed`:
|
|
484
|
+
nothing was sent.
|
|
485
|
+
- `cancelDeadline(requestState, nextEpochStart, nowSeconds)` is the "cancel
|
|
486
|
+
until" instant for a pending request (the next cycle close), or `null`.
|
|
332
487
|
|
|
333
488
|
## Low-level `KasuSdk`
|
|
334
489
|
|