@kasufinance/kasu-sdk 2.5.0 → 2.7.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 +144 -7
- package/dist/bundle.cjs.js +1667 -21
- package/dist/bundle.esm.js +1630 -22
- package/dist/domain/au-minimum.d.ts +135 -0
- package/dist/domain/au-minimum.js +154 -0
- package/dist/domain/au-minimum.js.map +1 -0
- package/dist/domain/index.d.ts +18 -3
- package/dist/domain/index.js +13 -3
- package/dist/domain/index.js.map +1 -1
- package/dist/domain/loan-contract.d.ts +174 -0
- package/dist/domain/loan-contract.js +160 -0
- package/dist/domain/loan-contract.js.map +1 -0
- package/dist/domain/requests.d.ts +219 -0
- package/dist/domain/requests.js +218 -0
- package/dist/domain/requests.js.map +1 -0
- package/dist/domain/settlement.d.ts +97 -0
- package/dist/domain/settlement.js +117 -0
- package/dist/domain/settlement.js.map +1 -0
- package/dist/domain/wallet-errors.d.ts +92 -0
- package/dist/domain/wallet-errors.js +155 -0
- package/dist/domain/wallet-errors.js.map +1 -0
- package/dist/facade/chain-configs.js +7 -1
- package/dist/facade/chain-configs.js.map +1 -1
- package/dist/facade/deposits.js +2 -1
- package/dist/facade/deposits.js.map +1 -1
- package/dist/facade/flows.d.ts +95 -0
- package/dist/facade/flows.js +116 -0
- package/dist/facade/flows.js.map +1 -0
- package/dist/facade/index.d.ts +3 -0
- package/dist/facade/index.js +3 -0
- package/dist/facade/index.js.map +1 -1
- package/dist/facade/kasu.d.ts +6 -2
- package/dist/facade/kasu.js +28 -3
- package/dist/facade/kasu.js.map +1 -1
- package/dist/facade/read-only.d.ts +12 -0
- package/dist/facade/read-only.js +13 -0
- package/dist/facade/read-only.js.map +1 -0
- package/dist/facade/user-portfolio.d.ts +18 -0
- package/dist/facade/user-portfolio.js +23 -0
- package/dist/facade/user-portfolio.js.map +1 -1
- package/dist/flows/deposit-flow.d.ts +301 -0
- package/dist/flows/deposit-flow.js +358 -0
- package/dist/flows/deposit-flow.js.map +1 -0
- package/dist/flows/flow.d.ts +72 -0
- package/dist/flows/flow.js +110 -0
- package/dist/flows/flow.js.map +1 -0
- package/dist/flows/index.d.ts +19 -0
- package/dist/flows/index.js +17 -0
- package/dist/flows/index.js.map +1 -0
- package/dist/flows/observable.d.ts +59 -0
- package/dist/flows/observable.js +81 -0
- package/dist/flows/observable.js.map +1 -0
- package/dist/flows/withdraw-flow.d.ts +99 -0
- package/dist/flows/withdraw-flow.js +83 -0
- package/dist/flows/withdraw-flow.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/services/DataService/data-service.js +3 -11
- package/dist/services/DataService/data-service.js.map +1 -1
- package/dist/services/DataService/directus-client.d.ts +26 -0
- package/dist/services/DataService/directus-client.js +38 -0
- package/dist/services/DataService/directus-client.js.map +1 -0
- package/dist/services/UserLending/user-lending.js +11 -7
- package/dist/services/UserLending/user-lending.js.map +1 -1
- package/package.json +8 -2
- package/src/domain/au-minimum.ts +192 -0
- package/src/domain/index.ts +73 -3
- package/src/domain/loan-contract.ts +275 -0
- package/src/domain/requests.ts +467 -0
- package/src/domain/settlement.ts +161 -0
- package/src/domain/wallet-errors.ts +173 -0
- package/src/facade/chain-configs.ts +7 -1
- package/src/facade/deposits.ts +2 -3
- package/src/facade/flows.ts +172 -0
- package/src/facade/index.ts +8 -0
- package/src/facade/kasu.ts +43 -3
- package/src/facade/read-only.ts +13 -0
- package/src/facade/user-portfolio.ts +24 -0
- package/src/flows/deposit-flow.ts +775 -0
- package/src/flows/flow.ts +108 -0
- package/src/flows/index.ts +45 -0
- package/src/flows/observable.ts +97 -0
- package/src/flows/withdraw-flow.ts +210 -0
- package/src/index.ts +9 -0
- package/src/services/DataService/data-service.ts +7 -25
- package/src/services/DataService/directus-client.ts +54 -0
- package/src/services/UserLending/user-lending.ts +17 -21
- package/dist/domain/deposit-bounds.test.d.ts +0 -1
- package/dist/domain/deposit-bounds.test.js +0 -135
- package/dist/domain/deposit-bounds.test.js.map +0 -1
- package/dist/domain/partners.test.d.ts +0 -1
- package/dist/domain/partners.test.js +0 -53
- package/dist/domain/partners.test.js.map +0 -1
- package/dist/domain/pools.test.d.ts +0 -1
- package/dist/domain/pools.test.js +0 -184
- package/dist/domain/pools.test.js.map +0 -1
- package/dist/domain/rates.test.d.ts +0 -1
- package/dist/domain/rates.test.js +0 -181
- package/dist/domain/rates.test.js.map +0 -1
- package/dist/domain/tranche-display-name.test.d.ts +0 -1
- package/dist/domain/tranche-display-name.test.js +0 -58
- package/dist/domain/tranche-display-name.test.js.map +0 -1
- package/dist/domain/tranches.test.d.ts +0 -1
- package/dist/domain/tranches.test.js +0 -206
- package/dist/domain/tranches.test.js.map +0 -1
- package/dist/facade/config.test.d.ts +0 -1
- package/dist/facade/config.test.js +0 -216
- package/dist/facade/config.test.js.map +0 -1
- package/dist/facade/facade.test.d.ts +0 -1
- package/dist/facade/facade.test.js +0 -201
- package/dist/facade/facade.test.js.map +0 -1
- package/dist/services/Locking/calculate-apy.test.d.ts +0 -1
- package/dist/services/Locking/calculate-apy.test.js +0 -41
- package/dist/services/Locking/calculate-apy.test.js.map +0 -1
- package/dist/tests/sample.test.d.ts +0 -1
- package/dist/tests/sample.test.js +0 -59
- package/dist/tests/sample.test.js.map +0 -1
- package/src/domain/deposit-bounds.test.ts +0 -200
- package/src/domain/partners.test.ts +0 -83
- package/src/domain/pools.test.ts +0 -260
- package/src/domain/rates.test.ts +0 -254
- package/src/domain/tranche-display-name.test.ts +0 -96
- package/src/domain/tranches.test.ts +0 -300
- package/src/facade/config.test.ts +0 -265
- package/src/facade/facade.test.ts +0 -250
- package/src/services/Locking/calculate-apy.test.ts +0 -52
- package/src/tests/sample.test.ts +0 -63
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cycles and the clearing window — the protocol's weekly clock, as numbers.
|
|
3
|
+
*
|
|
4
|
+
* Lifted verbatim from kasu-ui's `features/portfolio/lib/settlement-window.ts`
|
|
5
|
+
* and `features/lending/lib/cycle-dates.ts`. The two formatters that live
|
|
6
|
+
* beside `deriveCycleDates` there (`formatCycleDate`, `formatCycleCloseUtc`)
|
|
7
|
+
* print words and stay in the applications; everything here is unix seconds in
|
|
8
|
+
* and unix seconds out.
|
|
9
|
+
*
|
|
10
|
+
* The clearing window is the fixed 48 hours immediately preceding an epoch
|
|
11
|
+
* end. Inside it, pending requests are being processed and cannot be modified,
|
|
12
|
+
* and the countdown runs to the epoch end. Outside it, the countdown runs to
|
|
13
|
+
* the next clearing-window start.
|
|
14
|
+
*
|
|
15
|
+
* The epoch end comes straight from the chain (`nextEpochStartTimestamp`, i.e.
|
|
16
|
+
* the SDK's `getNextEpochDate`) — the same value the protocol's own
|
|
17
|
+
* `getNextClearingPeriodDate` derives from — so the window always lines up
|
|
18
|
+
* with the real weekly schedule (Tue 06:00 → Thu 06:00 UTC on Base) instead of
|
|
19
|
+
* a projected subgraph timestamp that can drift off the grid.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Clearing-window length — a fixed 48h protocol constant. Exported so every
|
|
23
|
+
* consumer derives the window from the same number this module runs on.
|
|
24
|
+
*/
|
|
25
|
+
export declare const CLEARING_WINDOW_SECONDS: number;
|
|
26
|
+
export type SettlementWindowState = {
|
|
27
|
+
phase: 'awaiting';
|
|
28
|
+
secondsUntilClearing: number;
|
|
29
|
+
nextClearingStart: number;
|
|
30
|
+
} | {
|
|
31
|
+
phase: 'clearing';
|
|
32
|
+
secondsUntilEpochEnd: number;
|
|
33
|
+
epochEnd: number;
|
|
34
|
+
} | {
|
|
35
|
+
phase: 'unknown';
|
|
36
|
+
};
|
|
37
|
+
export interface SettlementWindowInput {
|
|
38
|
+
/** Now, in unix seconds. */
|
|
39
|
+
nowSeconds: number;
|
|
40
|
+
/**
|
|
41
|
+
* Authoritative epoch end, in unix seconds — the chain's
|
|
42
|
+
* `nextEpochStartTimestamp` (SDK `getNextEpochDate`). During an epoch this
|
|
43
|
+
* is in the future; it refetches to the next boundary once it rolls.
|
|
44
|
+
*/
|
|
45
|
+
nextEpochStart: number;
|
|
46
|
+
/** Clearing-window length; defaults to the 48h protocol constant. */
|
|
47
|
+
clearingWindowSeconds?: number;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Which phase of the weekly cycle `nowSeconds` falls in, and how long is left
|
|
51
|
+
* of it.
|
|
52
|
+
*
|
|
53
|
+
* `'unknown'` when no epoch boundary has been loaded yet, or when the one on
|
|
54
|
+
* hand is stale (it has already elapsed — the on-chain value refetches to the
|
|
55
|
+
* next boundary shortly after rollover). A caller must render its "no cycle
|
|
56
|
+
* loaded" state there, never a zeroed countdown.
|
|
57
|
+
*/
|
|
58
|
+
export declare function computeSettlementWindow({ nowSeconds, nextEpochStart, clearingWindowSeconds, }: SettlementWindowInput): SettlementWindowState;
|
|
59
|
+
/**
|
|
60
|
+
* The next cycle boundary strictly after `nowSeconds`, in unix seconds — the
|
|
61
|
+
* cycle close (`nextEpochStart − 48h`) while the window is still open, the
|
|
62
|
+
* epoch end once we are inside it.
|
|
63
|
+
*
|
|
64
|
+
* `undefined` when there is no boundary left to wait for: no epoch boundary
|
|
65
|
+
* loaded, or a cached one that has already elapsed — the same staleness rule
|
|
66
|
+
* `computeSettlementWindow` applies before it reports `'unknown'`.
|
|
67
|
+
*
|
|
68
|
+
* Split out of the state machine because some consumers need the INSTANT
|
|
69
|
+
* rather than the phase: one to flush the cycle-dependent caches when the
|
|
70
|
+
* clock crosses it, one to move a pre-commit screen's snapshot clock at the
|
|
71
|
+
* same moment.
|
|
72
|
+
*/
|
|
73
|
+
export declare function nextCycleBoundary(nextEpochStart: number | undefined, nowSeconds: number, clearingWindowSeconds?: number): number | undefined;
|
|
74
|
+
export interface CycleDates {
|
|
75
|
+
/** Unix seconds — the next cycle close (clearing-window start). */
|
|
76
|
+
close: number;
|
|
77
|
+
/** Unix seconds — the outcome-confirmed-by boundary (close + 48h). */
|
|
78
|
+
outcome: number;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The cycle-close and outcome dates for a request submitted `now`.
|
|
82
|
+
*
|
|
83
|
+
* - The cycle "closes" (stops accepting requests, starts processing) at the
|
|
84
|
+
* start of the 48h clearing window, i.e. 48h before the epoch end.
|
|
85
|
+
* - Processing takes up to 48h, so the outcome is confirmed by the epoch end
|
|
86
|
+
* (close + 48h).
|
|
87
|
+
*
|
|
88
|
+
* Returns `null` when the epoch boundary is not available or is stale — a
|
|
89
|
+
* caller then omits the dates entirely (omit, don't stub).
|
|
90
|
+
*
|
|
91
|
+
* The common case is a request submitted OUTSIDE the clearing window: the
|
|
92
|
+
* close is `nextEpochStart − 48h` and the outcome is `nextEpochStart`. When
|
|
93
|
+
* the request lands INSIDE the current clearing window (that close is already
|
|
94
|
+
* in the past), it queues for the NEXT weekly cycle, so the close is advanced
|
|
95
|
+
* by whole weeks until it is in the future.
|
|
96
|
+
*/
|
|
97
|
+
export declare function deriveCycleDates(nextEpochStart: number | undefined, nowSeconds: number): CycleDates | null;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cycles and the clearing window — the protocol's weekly clock, as numbers.
|
|
3
|
+
*
|
|
4
|
+
* Lifted verbatim from kasu-ui's `features/portfolio/lib/settlement-window.ts`
|
|
5
|
+
* and `features/lending/lib/cycle-dates.ts`. The two formatters that live
|
|
6
|
+
* beside `deriveCycleDates` there (`formatCycleDate`, `formatCycleCloseUtc`)
|
|
7
|
+
* print words and stay in the applications; everything here is unix seconds in
|
|
8
|
+
* and unix seconds out.
|
|
9
|
+
*
|
|
10
|
+
* The clearing window is the fixed 48 hours immediately preceding an epoch
|
|
11
|
+
* end. Inside it, pending requests are being processed and cannot be modified,
|
|
12
|
+
* and the countdown runs to the epoch end. Outside it, the countdown runs to
|
|
13
|
+
* the next clearing-window start.
|
|
14
|
+
*
|
|
15
|
+
* The epoch end comes straight from the chain (`nextEpochStartTimestamp`, i.e.
|
|
16
|
+
* the SDK's `getNextEpochDate`) — the same value the protocol's own
|
|
17
|
+
* `getNextClearingPeriodDate` derives from — so the window always lines up
|
|
18
|
+
* with the real weekly schedule (Tue 06:00 → Thu 06:00 UTC on Base) instead of
|
|
19
|
+
* a projected subgraph timestamp that can drift off the grid.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Clearing-window length — a fixed 48h protocol constant. Exported so every
|
|
23
|
+
* consumer derives the window from the same number this module runs on.
|
|
24
|
+
*/
|
|
25
|
+
export const CLEARING_WINDOW_SECONDS = 48 * 60 * 60;
|
|
26
|
+
/**
|
|
27
|
+
* Weekly cadence — the epoch schedule is fixed weekly (Tue → Thu UTC on Base).
|
|
28
|
+
* Used only to roll a cycle forward when a request lands inside a window that
|
|
29
|
+
* has already closed.
|
|
30
|
+
*/
|
|
31
|
+
const WEEK_SECONDS = 7 * 24 * 60 * 60;
|
|
32
|
+
/**
|
|
33
|
+
* Which phase of the weekly cycle `nowSeconds` falls in, and how long is left
|
|
34
|
+
* of it.
|
|
35
|
+
*
|
|
36
|
+
* `'unknown'` when no epoch boundary has been loaded yet, or when the one on
|
|
37
|
+
* hand is stale (it has already elapsed — the on-chain value refetches to the
|
|
38
|
+
* next boundary shortly after rollover). A caller must render its "no cycle
|
|
39
|
+
* loaded" state there, never a zeroed countdown.
|
|
40
|
+
*/
|
|
41
|
+
export function computeSettlementWindow({ nowSeconds, nextEpochStart, clearingWindowSeconds = CLEARING_WINDOW_SECONDS, }) {
|
|
42
|
+
// No epoch boundary loaded yet, or a stale one that already elapsed.
|
|
43
|
+
if (nextEpochStart <= 0 || nextEpochStart <= nowSeconds) {
|
|
44
|
+
return { phase: 'unknown' };
|
|
45
|
+
}
|
|
46
|
+
const clearingStart = nextEpochStart - clearingWindowSeconds;
|
|
47
|
+
if (nowSeconds < clearingStart) {
|
|
48
|
+
return {
|
|
49
|
+
phase: 'awaiting',
|
|
50
|
+
secondsUntilClearing: clearingStart - nowSeconds,
|
|
51
|
+
nextClearingStart: clearingStart,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
// nowSeconds is in [clearingStart, nextEpochStart) — inside the window.
|
|
55
|
+
return {
|
|
56
|
+
phase: 'clearing',
|
|
57
|
+
secondsUntilEpochEnd: nextEpochStart - nowSeconds,
|
|
58
|
+
epochEnd: nextEpochStart,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The next cycle boundary strictly after `nowSeconds`, in unix seconds — the
|
|
63
|
+
* cycle close (`nextEpochStart − 48h`) while the window is still open, the
|
|
64
|
+
* epoch end once we are inside it.
|
|
65
|
+
*
|
|
66
|
+
* `undefined` when there is no boundary left to wait for: no epoch boundary
|
|
67
|
+
* loaded, or a cached one that has already elapsed — the same staleness rule
|
|
68
|
+
* `computeSettlementWindow` applies before it reports `'unknown'`.
|
|
69
|
+
*
|
|
70
|
+
* Split out of the state machine because some consumers need the INSTANT
|
|
71
|
+
* rather than the phase: one to flush the cycle-dependent caches when the
|
|
72
|
+
* clock crosses it, one to move a pre-commit screen's snapshot clock at the
|
|
73
|
+
* same moment.
|
|
74
|
+
*/
|
|
75
|
+
export function nextCycleBoundary(nextEpochStart, nowSeconds, clearingWindowSeconds = CLEARING_WINDOW_SECONDS) {
|
|
76
|
+
if (!nextEpochStart || nextEpochStart <= 0)
|
|
77
|
+
return undefined;
|
|
78
|
+
const clearingStart = nextEpochStart - clearingWindowSeconds;
|
|
79
|
+
if (nowSeconds < clearingStart)
|
|
80
|
+
return clearingStart;
|
|
81
|
+
if (nowSeconds < nextEpochStart)
|
|
82
|
+
return nextEpochStart;
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* The cycle-close and outcome dates for a request submitted `now`.
|
|
87
|
+
*
|
|
88
|
+
* - The cycle "closes" (stops accepting requests, starts processing) at the
|
|
89
|
+
* start of the 48h clearing window, i.e. 48h before the epoch end.
|
|
90
|
+
* - Processing takes up to 48h, so the outcome is confirmed by the epoch end
|
|
91
|
+
* (close + 48h).
|
|
92
|
+
*
|
|
93
|
+
* Returns `null` when the epoch boundary is not available or is stale — a
|
|
94
|
+
* caller then omits the dates entirely (omit, don't stub).
|
|
95
|
+
*
|
|
96
|
+
* The common case is a request submitted OUTSIDE the clearing window: the
|
|
97
|
+
* close is `nextEpochStart − 48h` and the outcome is `nextEpochStart`. When
|
|
98
|
+
* the request lands INSIDE the current clearing window (that close is already
|
|
99
|
+
* in the past), it queues for the NEXT weekly cycle, so the close is advanced
|
|
100
|
+
* by whole weeks until it is in the future.
|
|
101
|
+
*/
|
|
102
|
+
export function deriveCycleDates(nextEpochStart, nowSeconds) {
|
|
103
|
+
// No boundary loaded, or a stale one that already elapsed — the same
|
|
104
|
+
// staleness rule as `computeSettlementWindow`.
|
|
105
|
+
if (!nextEpochStart || nextEpochStart <= nowSeconds)
|
|
106
|
+
return null;
|
|
107
|
+
let close = nextEpochStart - CLEARING_WINDOW_SECONDS;
|
|
108
|
+
let outcome = nextEpochStart;
|
|
109
|
+
// Inside the current clearing window the close already passed; a request
|
|
110
|
+
// now is queued for the next weekly cycle.
|
|
111
|
+
while (close <= nowSeconds) {
|
|
112
|
+
close += WEEK_SECONDS;
|
|
113
|
+
outcome += WEEK_SECONDS;
|
|
114
|
+
}
|
|
115
|
+
return { close, outcome };
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=settlement.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settlement.js","sourceRoot":"","sources":["../../src/domain/settlement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAEpD;;;;GAIG;AACH,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAwBtC;;;;;;;;GAQG;AACH,MAAM,UAAU,uBAAuB,CAAC,EACpC,UAAU,EACV,cAAc,EACd,qBAAqB,GAAG,uBAAuB,GAC3B;IACpB,qEAAqE;IACrE,IAAI,cAAc,IAAI,CAAC,IAAI,cAAc,IAAI,UAAU,EAAE,CAAC;QACtD,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAChC,CAAC;IAED,MAAM,aAAa,GAAG,cAAc,GAAG,qBAAqB,CAAC;IAE7D,IAAI,UAAU,GAAG,aAAa,EAAE,CAAC;QAC7B,OAAO;YACH,KAAK,EAAE,UAAU;YACjB,oBAAoB,EAAE,aAAa,GAAG,UAAU;YAChD,iBAAiB,EAAE,aAAa;SACnC,CAAC;IACN,CAAC;IAED,wEAAwE;IACxE,OAAO;QACH,KAAK,EAAE,UAAU;QACjB,oBAAoB,EAAE,cAAc,GAAG,UAAU;QACjD,QAAQ,EAAE,cAAc;KAC3B,CAAC;AACN,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,iBAAiB,CAC7B,cAAkC,EAClC,UAAkB,EAClB,wBAAgC,uBAAuB;IAEvD,IAAI,CAAC,cAAc,IAAI,cAAc,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IAC7D,MAAM,aAAa,GAAG,cAAc,GAAG,qBAAqB,CAAC;IAC7D,IAAI,UAAU,GAAG,aAAa;QAAE,OAAO,aAAa,CAAC;IACrD,IAAI,UAAU,GAAG,cAAc;QAAE,OAAO,cAAc,CAAC;IACvD,OAAO,SAAS,CAAC;AACrB,CAAC;AASD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,gBAAgB,CAC5B,cAAkC,EAClC,UAAkB;IAElB,qEAAqE;IACrE,+CAA+C;IAC/C,IAAI,CAAC,cAAc,IAAI,cAAc,IAAI,UAAU;QAAE,OAAO,IAAI,CAAC;IAEjE,IAAI,KAAK,GAAG,cAAc,GAAG,uBAAuB,CAAC;IACrD,IAAI,OAAO,GAAG,cAAc,CAAC;IAC7B,yEAAyE;IACzE,2CAA2C;IAC3C,OAAO,KAAK,IAAI,UAAU,EAAE,CAAC;QACzB,KAAK,IAAI,YAAY,CAAC;QACtB,OAAO,IAAI,YAAY,CAAC;IAC5B,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wallet and RPC error predicates — pure functions over `unknown`.
|
|
3
|
+
*
|
|
4
|
+
* Every consumer has to tell three things apart when a write fails: the lender
|
|
5
|
+
* changed their mind, the call would revert, and everything else. The first
|
|
6
|
+
* two must never be reported as a failure the lender should retry or contact
|
|
7
|
+
* support about, and each wallet spells them differently, so the shapes are
|
|
8
|
+
* enumerated once here.
|
|
9
|
+
*
|
|
10
|
+
* Lifted from kasu-ui's `src/lib/web3/is-user-rejected.ts` and kasu-mobile's
|
|
11
|
+
* `src/features/lending/lib/errors.ts` — and now the UNION of the two, so
|
|
12
|
+
* neither app has to keep a wrapper on top of this one.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Did the lender reject the request in their wallet?
|
|
16
|
+
*
|
|
17
|
+
* Providers surface a rejection in different shapes, and the union of them is
|
|
18
|
+
* the point of this function existing once:
|
|
19
|
+
* - MetaMask and most EIP-1193 wallets: `code: 4001`
|
|
20
|
+
* - Coinbase Wallet and ethers v5: `code: 'ACTION_REJECTED'`
|
|
21
|
+
* - viem: a `UserRejectedRequestError` name
|
|
22
|
+
* - WalletConnect and some Privy paths: `Error('User rejected the request')`
|
|
23
|
+
* - a provider error WRAPPED by another layer, carrying the real code and
|
|
24
|
+
* message on a nested `error` — the shape Privy's embedded wallet
|
|
25
|
+
* surfaces on Expo, where the outer object says nothing useful
|
|
26
|
+
* - ethers' own `reason` field, which is often the only place the text lands
|
|
27
|
+
* - a PLAIN OBJECT carrying `message`, which `String(err)` would read as
|
|
28
|
+
* `"[object Object]"`
|
|
29
|
+
*
|
|
30
|
+
* Previously kasu-ui's implementation verbatim, with kasu-mobile keeping its
|
|
31
|
+
* own superset on top. That is precisely the drift this layer exists to stop —
|
|
32
|
+
* a rejection kasu-mobile recognised and kasu-ui did not was reported to the
|
|
33
|
+
* same lender as a failure on one app and a cancellation on the other. The
|
|
34
|
+
* union lives here; the mobile wrapper goes.
|
|
35
|
+
*
|
|
36
|
+
* ## The text is read for a SUBJECT, not for a keyword
|
|
37
|
+
*
|
|
38
|
+
* The words alone are not the signal. "Declined" and "request rejected" are
|
|
39
|
+
* also what a rate limiter, a risk engine and a KYC decision say, and those
|
|
40
|
+
* arrive wrapped in exactly the same envelope a wallet error does — ethers'
|
|
41
|
+
* `SERVER_ERROR` around `-32603` carries the upstream body on a nested
|
|
42
|
+
* `error.message`, so `{ error: { message: 'request rejected: rate limit
|
|
43
|
+
* exceeded' } }` is an RPC refusing to serve us, not a lender refusing to
|
|
44
|
+
* sign. Reporting one as the other tells a lender they cancelled something
|
|
45
|
+
* they never saw, and DROPS the real error on the floor.
|
|
46
|
+
*
|
|
47
|
+
* So a rejection is a machine-readable wallet code, or a sentence that names
|
|
48
|
+
* the party who did it: "user rejected", "declined by the user", "cancelled by
|
|
49
|
+
* the wallet". A bare "declined" is not a rejection, whatever else is on the
|
|
50
|
+
* envelope.
|
|
51
|
+
*
|
|
52
|
+
* Within that rule, being generous is the safe direction: calling a genuine
|
|
53
|
+
* fault a cancellation costs a lender one retry, while calling a deliberate
|
|
54
|
+
* rejection a failure sends them to support to report a bug that does not
|
|
55
|
+
* exist.
|
|
56
|
+
*/
|
|
57
|
+
export declare function isUserRejected(err: unknown): boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Did the wallet or RPC signal that the on-chain call would revert?
|
|
60
|
+
*
|
|
61
|
+
* ethers v5 raises `UNPREDICTABLE_GAS_LIMIT` when gas estimation reverts —
|
|
62
|
+
* most often an underlying `transferFrom` failing on an insufficient balance
|
|
63
|
+
* or allowance. Distinct from a rejection: nothing was refused by the lender,
|
|
64
|
+
* the transaction simply cannot succeed as composed, so the caller should
|
|
65
|
+
* re-check its preconditions rather than invite a retry.
|
|
66
|
+
*/
|
|
67
|
+
export declare function isUnpredictableGas(err: unknown): boolean;
|
|
68
|
+
/** A step that failed, as a code plus whether the lender chose it. */
|
|
69
|
+
export type WalletFailure<Step> = {
|
|
70
|
+
step: Step;
|
|
71
|
+
reason: 'cancelled';
|
|
72
|
+
} | {
|
|
73
|
+
step: Step;
|
|
74
|
+
reason: 'failed';
|
|
75
|
+
error: unknown;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* The `cancelled` / `failed` split, for a WALLET call on any step of any flow.
|
|
79
|
+
*
|
|
80
|
+
* A lender who pressed Reject is not a fault. Reporting one as the other is
|
|
81
|
+
* how a support queue fills with people who did exactly what they meant to.
|
|
82
|
+
*
|
|
83
|
+
* Generic in the step so both flows share one implementation — it was
|
|
84
|
+
* duplicated byte-for-byte in each of them, which is the same drift this
|
|
85
|
+
* layer exists to stop, one level up.
|
|
86
|
+
*
|
|
87
|
+
* Only pass it an error a WALLET produced. An HTTP port's throw is always a
|
|
88
|
+
* `failed`: the lender's wallet was not involved in it, so a backend that
|
|
89
|
+
* happens to word a refusal "declined" must never be shown to them as
|
|
90
|
+
* something they did.
|
|
91
|
+
*/
|
|
92
|
+
export declare function classifyWalletFailure<Step>(step: Step, err: unknown): WalletFailure<Step>;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wallet and RPC error predicates — pure functions over `unknown`.
|
|
3
|
+
*
|
|
4
|
+
* Every consumer has to tell three things apart when a write fails: the lender
|
|
5
|
+
* changed their mind, the call would revert, and everything else. The first
|
|
6
|
+
* two must never be reported as a failure the lender should retry or contact
|
|
7
|
+
* support about, and each wallet spells them differently, so the shapes are
|
|
8
|
+
* enumerated once here.
|
|
9
|
+
*
|
|
10
|
+
* Lifted from kasu-ui's `src/lib/web3/is-user-rejected.ts` and kasu-mobile's
|
|
11
|
+
* `src/features/lending/lib/errors.ts` — and now the UNION of the two, so
|
|
12
|
+
* neither app has to keep a wrapper on top of this one.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Did the lender reject the request in their wallet?
|
|
16
|
+
*
|
|
17
|
+
* Providers surface a rejection in different shapes, and the union of them is
|
|
18
|
+
* the point of this function existing once:
|
|
19
|
+
* - MetaMask and most EIP-1193 wallets: `code: 4001`
|
|
20
|
+
* - Coinbase Wallet and ethers v5: `code: 'ACTION_REJECTED'`
|
|
21
|
+
* - viem: a `UserRejectedRequestError` name
|
|
22
|
+
* - WalletConnect and some Privy paths: `Error('User rejected the request')`
|
|
23
|
+
* - a provider error WRAPPED by another layer, carrying the real code and
|
|
24
|
+
* message on a nested `error` — the shape Privy's embedded wallet
|
|
25
|
+
* surfaces on Expo, where the outer object says nothing useful
|
|
26
|
+
* - ethers' own `reason` field, which is often the only place the text lands
|
|
27
|
+
* - a PLAIN OBJECT carrying `message`, which `String(err)` would read as
|
|
28
|
+
* `"[object Object]"`
|
|
29
|
+
*
|
|
30
|
+
* Previously kasu-ui's implementation verbatim, with kasu-mobile keeping its
|
|
31
|
+
* own superset on top. That is precisely the drift this layer exists to stop —
|
|
32
|
+
* a rejection kasu-mobile recognised and kasu-ui did not was reported to the
|
|
33
|
+
* same lender as a failure on one app and a cancellation on the other. The
|
|
34
|
+
* union lives here; the mobile wrapper goes.
|
|
35
|
+
*
|
|
36
|
+
* ## The text is read for a SUBJECT, not for a keyword
|
|
37
|
+
*
|
|
38
|
+
* The words alone are not the signal. "Declined" and "request rejected" are
|
|
39
|
+
* also what a rate limiter, a risk engine and a KYC decision say, and those
|
|
40
|
+
* arrive wrapped in exactly the same envelope a wallet error does — ethers'
|
|
41
|
+
* `SERVER_ERROR` around `-32603` carries the upstream body on a nested
|
|
42
|
+
* `error.message`, so `{ error: { message: 'request rejected: rate limit
|
|
43
|
+
* exceeded' } }` is an RPC refusing to serve us, not a lender refusing to
|
|
44
|
+
* sign. Reporting one as the other tells a lender they cancelled something
|
|
45
|
+
* they never saw, and DROPS the real error on the floor.
|
|
46
|
+
*
|
|
47
|
+
* So a rejection is a machine-readable wallet code, or a sentence that names
|
|
48
|
+
* the party who did it: "user rejected", "declined by the user", "cancelled by
|
|
49
|
+
* the wallet". A bare "declined" is not a rejection, whatever else is on the
|
|
50
|
+
* envelope.
|
|
51
|
+
*
|
|
52
|
+
* Within that rule, being generous is the safe direction: calling a genuine
|
|
53
|
+
* fault a cancellation costs a lender one retry, while calling a deliberate
|
|
54
|
+
* rejection a failure sends them to support to report a bug that does not
|
|
55
|
+
* exist.
|
|
56
|
+
*/
|
|
57
|
+
export function isUserRejected(err) {
|
|
58
|
+
var _a;
|
|
59
|
+
if (!err)
|
|
60
|
+
return false;
|
|
61
|
+
if (typeof err === 'object') {
|
|
62
|
+
const e = err;
|
|
63
|
+
if (isRejectionCode(e.code))
|
|
64
|
+
return true;
|
|
65
|
+
// A wrapped provider error: the outer layer's code is its own, the
|
|
66
|
+
// inner one is the wallet's.
|
|
67
|
+
if (isRejectionCode((_a = e.error) === null || _a === void 0 ? void 0 : _a.code))
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
const lower = rejectionText(err).toLowerCase();
|
|
71
|
+
return USER_REJECTION_PATTERNS.some((pattern) => pattern.test(lower));
|
|
72
|
+
}
|
|
73
|
+
function isRejectionCode(code) {
|
|
74
|
+
return code === 4001 || code === 'ACTION_REJECTED';
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The wordings that name the wallet or the person at it.
|
|
78
|
+
*
|
|
79
|
+
* Each one carries a SUBJECT — the identifier a wallet library uses, or the
|
|
80
|
+
* verb with the party who performed it. That is what separates a lender
|
|
81
|
+
* pressing Reject from a server declining to answer, and it is why none of
|
|
82
|
+
* these is a bare "declined" or "rejected".
|
|
83
|
+
*/
|
|
84
|
+
const USER_REJECTION_PATTERNS = [
|
|
85
|
+
// Machine-readable markers that only a wallet layer emits, arriving as
|
|
86
|
+
// text because something in between stringified the error.
|
|
87
|
+
/action_rejected/,
|
|
88
|
+
/user_rejected/,
|
|
89
|
+
/userrejectedrequest/,
|
|
90
|
+
// "the user did it", in the orders the wallets write it.
|
|
91
|
+
/user\s+(?:has\s+)?(?:rejected|denied|declined|refused|cancell?ed)/,
|
|
92
|
+
/(?:rejected|denied|declined|refused|cancell?ed)\s+by\s+(?:the\s+)?(?:user|wallet|signer|owner)/,
|
|
93
|
+
// The wallet as the subject, which is how some embedded wallets word it.
|
|
94
|
+
/(?:wallet|signer)\s+(?:rejected|denied|declined|refused)/,
|
|
95
|
+
];
|
|
96
|
+
/**
|
|
97
|
+
* Every place a wallet might have put the words: the message, ethers' `reason`,
|
|
98
|
+
* the error's `name` (viem puts the whole signal there), and a wrapped error's
|
|
99
|
+
* own three. Joined rather than picked, because which one carries the text
|
|
100
|
+
* depends on how many layers wrapped it.
|
|
101
|
+
*
|
|
102
|
+
* A separator is used rather than a bare space: two fields must not be able to
|
|
103
|
+
* form a phrase across the join that neither of them said.
|
|
104
|
+
*/
|
|
105
|
+
function rejectionText(err) {
|
|
106
|
+
var _a, _b, _c;
|
|
107
|
+
if (typeof err !== 'object' || err === null)
|
|
108
|
+
return String(err);
|
|
109
|
+
const e = err;
|
|
110
|
+
return [
|
|
111
|
+
e.message,
|
|
112
|
+
e.reason,
|
|
113
|
+
e.name,
|
|
114
|
+
(_a = e.error) === null || _a === void 0 ? void 0 : _a.message,
|
|
115
|
+
(_b = e.error) === null || _b === void 0 ? void 0 : _b.reason,
|
|
116
|
+
(_c = e.error) === null || _c === void 0 ? void 0 : _c.name,
|
|
117
|
+
]
|
|
118
|
+
.filter((part) => typeof part === 'string')
|
|
119
|
+
.join(' | ');
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Did the wallet or RPC signal that the on-chain call would revert?
|
|
123
|
+
*
|
|
124
|
+
* ethers v5 raises `UNPREDICTABLE_GAS_LIMIT` when gas estimation reverts —
|
|
125
|
+
* most often an underlying `transferFrom` failing on an insufficient balance
|
|
126
|
+
* or allowance. Distinct from a rejection: nothing was refused by the lender,
|
|
127
|
+
* the transaction simply cannot succeed as composed, so the caller should
|
|
128
|
+
* re-check its preconditions rather than invite a retry.
|
|
129
|
+
*/
|
|
130
|
+
export function isUnpredictableGas(err) {
|
|
131
|
+
if (!err || typeof err !== 'object')
|
|
132
|
+
return false;
|
|
133
|
+
return err.code === 'UNPREDICTABLE_GAS_LIMIT';
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* The `cancelled` / `failed` split, for a WALLET call on any step of any flow.
|
|
137
|
+
*
|
|
138
|
+
* A lender who pressed Reject is not a fault. Reporting one as the other is
|
|
139
|
+
* how a support queue fills with people who did exactly what they meant to.
|
|
140
|
+
*
|
|
141
|
+
* Generic in the step so both flows share one implementation — it was
|
|
142
|
+
* duplicated byte-for-byte in each of them, which is the same drift this
|
|
143
|
+
* layer exists to stop, one level up.
|
|
144
|
+
*
|
|
145
|
+
* Only pass it an error a WALLET produced. An HTTP port's throw is always a
|
|
146
|
+
* `failed`: the lender's wallet was not involved in it, so a backend that
|
|
147
|
+
* happens to word a refusal "declined" must never be shown to them as
|
|
148
|
+
* something they did.
|
|
149
|
+
*/
|
|
150
|
+
export function classifyWalletFailure(step, err) {
|
|
151
|
+
return isUserRejected(err)
|
|
152
|
+
? { step, reason: 'cancelled' }
|
|
153
|
+
: { step, reason: 'failed', error: err };
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=wallet-errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wallet-errors.js","sourceRoot":"","sources":["../../src/domain/wallet-errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,MAAM,UAAU,cAAc,CAAC,GAAY;;IACvC,IAAI,CAAC,GAAG;QAAE,OAAO,KAAK,CAAC;IACvB,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC1B,MAAM,CAAC,GAAG,GAGT,CAAC;QACF,IAAI,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QACzC,mEAAmE;QACnE,6BAA6B;QAC7B,IAAI,eAAe,CAAC,MAAA,CAAC,CAAC,KAAK,0CAAE,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;IACpD,CAAC;IACD,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IAC/C,OAAO,uBAAuB,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;AAC1E,CAAC;AAED,SAAS,eAAe,CAAC,IAAa;IAClC,OAAO,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,iBAAiB,CAAC;AACvD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,uBAAuB,GAAsB;IAC/C,uEAAuE;IACvE,2DAA2D;IAC3D,iBAAiB;IACjB,eAAe;IACf,qBAAqB;IACrB,yDAAyD;IACzD,mEAAmE;IACnE,gGAAgG;IAChG,yEAAyE;IACzE,0DAA0D;CAC7D,CAAC;AAEF;;;;;;;;GAQG;AACH,SAAS,aAAa,CAAC,GAAY;;IAC/B,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;IAChE,MAAM,CAAC,GAAG,GAST,CAAC;IACF,OAAO;QACH,CAAC,CAAC,OAAO;QACT,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,IAAI;QACN,MAAA,CAAC,CAAC,KAAK,0CAAE,OAAO;QAChB,MAAA,CAAC,CAAC,KAAK,0CAAE,MAAM;QACf,MAAA,CAAC,CAAC,KAAK,0CAAE,IAAI;KAChB;SACI,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC;SAC1D,IAAI,CAAC,KAAK,CAAC,CAAC;AACrB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAY;IAC3C,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAClD,OAAQ,GAA0B,CAAC,IAAI,KAAK,yBAAyB,CAAC;AAC1E,CAAC;AAOD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,qBAAqB,CACjC,IAAU,EACV,GAAY;IAEZ,OAAO,cAAc,CAAC,GAAG,CAAC;QACtB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE;QAC/B,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;AACjD,CAAC"}
|
|
@@ -139,7 +139,13 @@ export const CHAIN_CONFIGS = {
|
|
|
139
139
|
ClearingCoordinator: '',
|
|
140
140
|
ExternalTVL: '',
|
|
141
141
|
},
|
|
142
|
-
|
|
142
|
+
// The frozen Plume history is indexed on the LEGACY Goldsky project,
|
|
143
|
+
// not the one the live chains use: the same path under the current
|
|
144
|
+
// project 404s. Verified 2026-09-05 — this URL answers
|
|
145
|
+
// `{ lendingPools { id name } }` with the three Plume pools; the
|
|
146
|
+
// current-project spelling returns HTTP 404. Note the `/gn` suffix,
|
|
147
|
+
// which the current project's URLs do not carry.
|
|
148
|
+
subgraphUrl: 'https://api.goldsky.com/api/public/project_cm9t3064xeuyn01tgctdo3c17/subgraphs/kasu-plume/prod/gn',
|
|
143
149
|
directusUrl: 'https://kasu-finance.directus.app/',
|
|
144
150
|
unusedPoolIds: [],
|
|
145
151
|
poolMetadataMapping: undefined,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chain-configs.js","sourceRoot":"","sources":["../../src/facade/chain-configs.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"chain-configs.js","sourceRoot":"","sources":["../../src/facade/chain-configs.ts"],"names":[],"mappings":"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"}
|
package/dist/facade/deposits.js
CHANGED
|
@@ -7,6 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
+
import { READ_ONLY_MESSAGE } from './read-only';
|
|
10
11
|
/**
|
|
11
12
|
* High-level facade for deposit and withdrawal operations.
|
|
12
13
|
*
|
|
@@ -35,7 +36,7 @@ export class DepositsFacade {
|
|
|
35
36
|
*/
|
|
36
37
|
assertWritable() {
|
|
37
38
|
if (this._isReadOnly) {
|
|
38
|
-
throw new Error(
|
|
39
|
+
throw new Error(READ_ONLY_MESSAGE);
|
|
39
40
|
}
|
|
40
41
|
}
|
|
41
42
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deposits.js","sourceRoot":"","sources":["../../src/facade/deposits.ts"],"names":[],"mappings":";;;;;;;;;
|
|
1
|
+
{"version":3,"file":"deposits.js","sourceRoot":"","sources":["../../src/facade/deposits.ts"],"names":[],"mappings":";;;;;;;;;AAIA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAGhD;;;;;GAKG;AACH,MAAM,OAAO,cAAc;IACvB,YACY,YAAyB,EACzB,QAAgB;IACxB;;;;OAIG;IACK,cAAc,KAAK;QAPnB,iBAAY,GAAZ,YAAY,CAAa;QACzB,aAAQ,GAAR,QAAQ,CAAQ;QAMhB,gBAAW,GAAX,WAAW,CAAQ;IAC5B,CAAC;IAEJ;;;;;;;OAOG;IACK,cAAc;QAClB,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACvC,CAAC;IACL,CAAC;IAED;;;;;;;;;;;;;;;;OAgBG;IACG,OAAO,CAAC,MAAqB;;;YAC/B,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,OAAO,MAAM,IAAI,CAAC,YAAY,CAAC,qBAAqB,CAChD,MAAM,CAAC,MAAM,EACb,MAAM,CAAC,SAAS,EAChB,MAAM,CAAC,MAAM,EACb,MAAA,MAAM,CAAC,QAAQ,mCAAI,IAAI,EACvB,MAAA,MAAM,CAAC,iBAAiB,mCAAI,CAAC,EAC7B,MAAA,MAAM,CAAC,WAAW,mCAAI,IAAI,EAC1B,MAAM,CAAC,YAAY,EACnB,MAAA,MAAM,CAAC,QAAQ,mCAAI,GAAG,CACzB,CAAC;QACN,CAAC;KAAA;IAED;;OAEG;IACG,QAAQ,CAAC,MAAsB;;YACjC,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,OAAO,MAAM,IAAI,CAAC,YAAY,CAAC,wBAAwB,CACnD,MAAM,CAAC,MAAM,EACb,MAAM,CAAC,SAAS,EAChB,MAAM,CAAC,MAAM,CAChB,CAAC;QACN,CAAC;KAAA;IAED;;OAEG;IACG,WAAW,CACb,MAAc,EACd,SAAiB,EACjB,WAAmB;;YAEnB,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,OAAO,MAAM,IAAI,CAAC,YAAY,CAAC,oBAAoB,CAC/C,MAAM,EACN,SAAS,EACT,WAAW,CACd,CAAC;QACN,CAAC;KAAA;IAED;;;;;OAKG;IACH,cAAc,CAAC,WAA0B;QACrC,OAAO,IAAI,CAAC,YAAY,CAAC,uBAAuB,CAC5C,WAAW,EACX,IAAI,CAAC,QAAQ,CAChB,CAAC;IACN,CAAC;IAED;;;OAGG;IACG,iBAAiB,CAAC,MAAc;;YAClC,OAAO,MAAM,IAAI,CAAC,YAAY,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAC7D,CAAC;KAAA;IAED;;OAEG;IACG,eAAe;;YACjB,OAAO,MAAM,IAAI,CAAC,YAAY,CAAC,eAAe,EAAE,CAAC;QACrD,CAAC;KAAA;CACJ"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { IERC20MetadataAbi } from '../contracts';
|
|
2
|
+
import { DepositFlow, DepositFlowOptions, DepositPorts, WithdrawFlow, WithdrawPorts } from '../flows';
|
|
3
|
+
import { DepositsFacade } from './deposits';
|
|
4
|
+
/**
|
|
5
|
+
* The ports a consumer MUST supply for a deposit, plus optional overrides for
|
|
6
|
+
* the ones the SDK can serve itself.
|
|
7
|
+
*
|
|
8
|
+
* The three required ones all reach the application's own backend or wallet:
|
|
9
|
+
* the SDK has no opinion on how a lender signs, which proxy the agreements
|
|
10
|
+
* service sits behind, or where the KYC signature is fetched — and it must not
|
|
11
|
+
* learn any of them, because it is a public package.
|
|
12
|
+
*/
|
|
13
|
+
export type DepositFlowPortOverrides = Pick<DepositPorts, 'signMessage' | 'generateContract' | 'getKycSignature'> & Partial<DepositPorts>;
|
|
14
|
+
/**
|
|
15
|
+
* Every withdraw port has an SDK default except `getKycSignature`, which has
|
|
16
|
+
* no default at all and which turns the KYC pre-check on by being supplied.
|
|
17
|
+
*/
|
|
18
|
+
export type WithdrawFlowPortOverrides = Partial<WithdrawPorts>;
|
|
19
|
+
/**
|
|
20
|
+
* Builds `DepositFlow` / `WithdrawFlow` instances wired to THIS Kasu instance:
|
|
21
|
+
* its chain's stable token, its `LendingPoolManager`, its signer.
|
|
22
|
+
*
|
|
23
|
+
* ```ts
|
|
24
|
+
* const flow = kasu.connect(signer).flows.deposit({
|
|
25
|
+
* signMessage: (m) => signer.signMessage(m),
|
|
26
|
+
* generateContract: (req) => postToMyProxy(req),
|
|
27
|
+
* getKycSignature: (p) => postToMyBackend(p),
|
|
28
|
+
* });
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* A flow built from a read-only instance constructs fine and reads fine — the
|
|
32
|
+
* write ports throw `READ_ONLY_MESSAGE` when the run reaches them, exactly as
|
|
33
|
+
* `kasu.deposits.deposit` does. Constructing is not the mistake; submitting is.
|
|
34
|
+
*
|
|
35
|
+
* It holds the `DepositsFacade` and NOTHING the facade already owns: no
|
|
36
|
+
* `UserLending`, no chain id, no signer. Two paths to one behaviour is how the
|
|
37
|
+
* KYC params a flow built came to differ from the ones `kasu.deposits`
|
|
38
|
+
* built — the same class of drift the flows themselves exist to end.
|
|
39
|
+
*/
|
|
40
|
+
export declare class FlowsFacade {
|
|
41
|
+
private readonly _deposits;
|
|
42
|
+
/**
|
|
43
|
+
* The chain's stable token, bound to whatever the Kasu instance holds.
|
|
44
|
+
* A factory rather than a contract: it is one `new Contract`, and a
|
|
45
|
+
* cached binding would outlive the config it was built from.
|
|
46
|
+
*/
|
|
47
|
+
private readonly _erc20;
|
|
48
|
+
/** The read-only flag `Kasu` already computed — never re-derived here. */
|
|
49
|
+
private readonly _isReadOnly;
|
|
50
|
+
/**
|
|
51
|
+
* The ERC-20 spender every deposit run approves: this chain's
|
|
52
|
+
* `LendingPoolManager`, which is the only contract the default deposit
|
|
53
|
+
* port calls. Passed to the flow so a consumer never has to hand-wire
|
|
54
|
+
* an address whose only wrong value grants an approval to the wrong
|
|
55
|
+
* contract.
|
|
56
|
+
*/
|
|
57
|
+
private readonly _spender;
|
|
58
|
+
constructor(_deposits: DepositsFacade,
|
|
59
|
+
/**
|
|
60
|
+
* The chain's stable token, bound to whatever the Kasu instance holds.
|
|
61
|
+
* A factory rather than a contract: it is one `new Contract`, and a
|
|
62
|
+
* cached binding would outlive the config it was built from.
|
|
63
|
+
*/
|
|
64
|
+
_erc20: () => IERC20MetadataAbi,
|
|
65
|
+
/** The read-only flag `Kasu` already computed — never re-derived here. */
|
|
66
|
+
_isReadOnly: boolean,
|
|
67
|
+
/**
|
|
68
|
+
* The ERC-20 spender every deposit run approves: this chain's
|
|
69
|
+
* `LendingPoolManager`, which is the only contract the default deposit
|
|
70
|
+
* port calls. Passed to the flow so a consumer never has to hand-wire
|
|
71
|
+
* an address whose only wrong value grants an approval to the wrong
|
|
72
|
+
* contract.
|
|
73
|
+
*/
|
|
74
|
+
_spender: string);
|
|
75
|
+
/**
|
|
76
|
+
* A deposit pipeline. `readAllowance`, `approve`, `deposit` and
|
|
77
|
+
* `buildKycParams` default to the SDK's own implementations; pass any of
|
|
78
|
+
* them to override (kasu-ui approves through its sponsored-gas path, for
|
|
79
|
+
* one).
|
|
80
|
+
*
|
|
81
|
+
* Each default is applied per key with `??`, not by spreading `ports` over
|
|
82
|
+
* them: `{ ...defaults, ...ports }` lets an EXPLICITLY undefined value
|
|
83
|
+
* delete the default it was meant to keep, and
|
|
84
|
+
* `approve: sponsoredGas ? sponsoredApprove : undefined` is exactly how a
|
|
85
|
+
* consumer writes a conditional override.
|
|
86
|
+
*/
|
|
87
|
+
deposit(ports: DepositFlowPortOverrides, opts?: DepositFlowOptions): DepositFlow;
|
|
88
|
+
/**
|
|
89
|
+
* A withdrawal pipeline. Both write ports and `buildKycParams` default to
|
|
90
|
+
* this instance; supplying `getKycSignature` turns the KYC pre-check on.
|
|
91
|
+
* Defaults are applied per key, for the reason `deposit()` gives.
|
|
92
|
+
*/
|
|
93
|
+
withdraw(ports?: WithdrawFlowPortOverrides): WithdrawFlow;
|
|
94
|
+
private _assertWritable;
|
|
95
|
+
}
|