@kasufinance/kasu-sdk 2.14.0 → 2.15.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 +29 -5
- package/dist/bundle.cjs.js +561 -11
- package/dist/bundle.esm.js +553 -12
- package/dist/domain/index.d.ts +6 -1
- package/dist/domain/index.js +6 -2
- package/dist/domain/index.js.map +1 -1
- package/dist/domain/loan-contract.d.ts +16 -5
- package/dist/domain/loan-contract.js +16 -5
- package/dist/domain/loan-contract.js.map +1 -1
- package/dist/domain/pool-tvl.js +179 -0
- package/dist/domain/pool-tvl.js.map +1 -1
- package/dist/domain/requests.js +29 -19
- package/dist/domain/requests.js.map +1 -1
- package/dist/domain/strategy-details.d.ts +262 -0
- package/dist/domain/strategy-details.js +375 -0
- package/dist/domain/strategy-details.js.map +1 -0
- package/dist/facade/index.d.ts +1 -1
- package/dist/facade/index.js +2 -0
- package/dist/facade/index.js.map +1 -1
- package/dist/facade/strategies.d.ts +85 -3
- package/dist/facade/strategies.js +182 -6
- package/dist/facade/strategies.js.map +1 -1
- package/dist/facade/strategy-deployments.js +97 -0
- package/dist/facade/strategy-deployments.js.map +1 -0
- package/dist/facade/types.d.ts +82 -0
- package/dist/flows/deposit-flow.d.ts +19 -5
- package/dist/flows/deposit-flow.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/services/DataService/data-service.js +80 -9
- package/dist/services/DataService/data-service.js.map +1 -1
- package/dist/services/DataService/tvl-history.js +89 -0
- package/dist/services/DataService/tvl-history.js.map +1 -1
- package/dist/services/UserLending/queries.js +2 -7
- package/dist/services/UserLending/queries.js.map +1 -1
- package/dist/services/UserLending/subgraph-types.js.map +1 -1
- package/dist/services/UserLending/types.js.map +1 -1
- package/dist/services/UserLending/user-lending.js +72 -16
- package/dist/services/UserLending/user-lending.js.map +1 -1
- package/package.json +1 -1
- package/src/domain/index.ts +27 -1
- package/src/domain/loan-contract.ts +16 -5
- package/src/domain/strategy-details.ts +528 -0
- package/src/facade/index.ts +3 -0
- package/src/facade/strategies.ts +205 -10
- package/src/facade/types.ts +85 -0
- package/src/flows/deposit-flow.ts +19 -5
package/dist/domain/index.js
CHANGED
|
@@ -19,7 +19,10 @@
|
|
|
19
19
|
*
|
|
20
20
|
* `pickShortDescription` returns a string but AUTHORS none: it selects and
|
|
21
21
|
* cleans editorial the CMS already holds, and an absent blurb is
|
|
22
|
-
* `undefined`, never a sentence of its own.
|
|
22
|
+
* `undefined`, never a sentence of its own. The Details-screen parsers in
|
|
23
|
+
* `strategy-details.ts` (`splitBusinessTypes`, `parseFacility`,
|
|
24
|
+
* `groupRiskManagementItems`, …) are the same kind: they split and trim
|
|
25
|
+
* CMS text, and an unauthored field is `undefined`.
|
|
23
26
|
* 2. **Pure.** No network, no clock, no environment. Anything with I/O belongs
|
|
24
27
|
* in `facade/` (see `fetchUnusedPoolIds`).
|
|
25
28
|
*/
|
|
@@ -37,10 +40,11 @@ export { decodeRevert, extractRevertData } from './revert-errors';
|
|
|
37
40
|
export { CLEARING_WINDOW_SECONDS, computeSettlementWindow, deriveCycleDates, nextCycleBoundary, } from './settlement';
|
|
38
41
|
export { encodeCancelDepositCall, encodeCancelWithdrawalCall, encodeRequestWithdrawalCall, encodeStableTransfer, encodeWithdrawAtExpiryCall, SPONSORED_CALL_KINDS, SPONSORED_CALL_SELECTORS, SponsoredCallInputError, } from './sponsored-calls';
|
|
39
42
|
export { pickShortDescription } from './strategy-summary';
|
|
43
|
+
export { groupRiskManagementItems, parseFacility, readCmsStartDate, RISK_GROUP_ORDER, securityStructureOf, splitBusinessTypes, splitNumberedClauses, StrategyTotalsInputError, strategyTotalsUsd, } from './strategy-details';
|
|
40
44
|
export { getTrancheDisplayName, UPPER_MEZZANINE } from './tranche-display-name';
|
|
41
45
|
export { compareTrancheSeniority, derivePoolStatus, MIN_TRANCHE_CAPACITY, netTrancheApyBounds, pickDefaultTrancheId, poolAllTranchesFull, trancheApyBounds, trancheHasCapacity, trancheRiskRank, } from './tranches';
|
|
42
46
|
export { classifyWalletFailure, isUnpredictableGas, isUserRejected, } from './wallet-errors';
|
|
43
|
-
export { poolTvl } from './pool-tvl';
|
|
47
|
+
export { combineTvlHistories, poolTvl, TvlHistoryInputError } from './pool-tvl';
|
|
44
48
|
export { aggregateYieldHistory, epochTrancheYield } from './yield-history';
|
|
45
49
|
export { accruedInterest, dailyInterest, projectedAnnualEarnings, SECONDS_PER_WEEK, weeklyInterest, weightedAverageApy, } from './yields';
|
|
46
50
|
//# sourceMappingURL=index.js.map
|
package/dist/domain/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/domain/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/domain/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -141,19 +141,30 @@ export declare function buildLoanAgreementSignMessage(p: {
|
|
|
141
141
|
timestamp: number;
|
|
142
142
|
}): string;
|
|
143
143
|
/**
|
|
144
|
-
* The legacy `/contract/generate`
|
|
144
|
+
* The legacy `/contract/generate` message.
|
|
145
145
|
*
|
|
146
146
|
* ⚠️ BYTE-EXACT PROTOCOL STRING. kasu-backend rebuilds it as
|
|
147
147
|
* `` `I request contract content for ${address} at ${timestamp}.` `` from the
|
|
148
148
|
* `address` and `timestamp` fields of the request body — so the string signed
|
|
149
149
|
* and the body sent must agree exactly, INCLUDING the address casing. This
|
|
150
150
|
* builder lowercases, and the request body must carry the same lowercased
|
|
151
|
-
* address
|
|
151
|
+
* address.
|
|
152
152
|
*
|
|
153
153
|
* The backend takes this path whenever the four human-readable display fields
|
|
154
|
-
* are absent
|
|
155
|
-
*
|
|
156
|
-
* signs
|
|
154
|
+
* are absent. Only the retired kasu-fe-next app (retired 2026-11-05) and
|
|
155
|
+
* kasu-mobile builds from before 2026-09-06 signed it; every current consumer
|
|
156
|
+
* signs `buildLoanAgreementSignMessage`. The backend keeps accepting it until
|
|
157
|
+
* no such mobile build is left in use.
|
|
158
|
+
*
|
|
159
|
+
* It is NOT the `/contract/resolve` message. Resolve has a message of its own
|
|
160
|
+
* (`Requesting contract content for {address}/{id} at {timestamp}.`), which
|
|
161
|
+
* kasu-backend rebuilds and verifies, so it does not depend on this format.
|
|
162
|
+
*
|
|
163
|
+
* @deprecated Sign the human-readable loan-agreement message
|
|
164
|
+
* (`buildLoanAgreementSignMessage`, `contractMessage.format:
|
|
165
|
+
* 'loan-agreement'`) instead. Only the retired kasu-fe-next app and
|
|
166
|
+
* pre-2026-09-06 kasu-mobile builds used this format; it will be removed in
|
|
167
|
+
* the next major version.
|
|
157
168
|
*
|
|
158
169
|
* @param timestampMs ms-epoch, and the same value sent as the body's
|
|
159
170
|
* `timestamp`.
|
|
@@ -122,19 +122,30 @@ export function buildLoanAgreementSignMessage(p) {
|
|
|
122
122
|
].join('\n');
|
|
123
123
|
}
|
|
124
124
|
/**
|
|
125
|
-
* The legacy `/contract/generate`
|
|
125
|
+
* The legacy `/contract/generate` message.
|
|
126
126
|
*
|
|
127
127
|
* ⚠️ BYTE-EXACT PROTOCOL STRING. kasu-backend rebuilds it as
|
|
128
128
|
* `` `I request contract content for ${address} at ${timestamp}.` `` from the
|
|
129
129
|
* `address` and `timestamp` fields of the request body — so the string signed
|
|
130
130
|
* and the body sent must agree exactly, INCLUDING the address casing. This
|
|
131
131
|
* builder lowercases, and the request body must carry the same lowercased
|
|
132
|
-
* address
|
|
132
|
+
* address.
|
|
133
133
|
*
|
|
134
134
|
* The backend takes this path whenever the four human-readable display fields
|
|
135
|
-
* are absent
|
|
136
|
-
*
|
|
137
|
-
* signs
|
|
135
|
+
* are absent. Only the retired kasu-fe-next app (retired 2026-11-05) and
|
|
136
|
+
* kasu-mobile builds from before 2026-09-06 signed it; every current consumer
|
|
137
|
+
* signs `buildLoanAgreementSignMessage`. The backend keeps accepting it until
|
|
138
|
+
* no such mobile build is left in use.
|
|
139
|
+
*
|
|
140
|
+
* It is NOT the `/contract/resolve` message. Resolve has a message of its own
|
|
141
|
+
* (`Requesting contract content for {address}/{id} at {timestamp}.`), which
|
|
142
|
+
* kasu-backend rebuilds and verifies, so it does not depend on this format.
|
|
143
|
+
*
|
|
144
|
+
* @deprecated Sign the human-readable loan-agreement message
|
|
145
|
+
* (`buildLoanAgreementSignMessage`, `contractMessage.format:
|
|
146
|
+
* 'loan-agreement'`) instead. Only the retired kasu-fe-next app and
|
|
147
|
+
* pre-2026-09-06 kasu-mobile builds used this format; it will be removed in
|
|
148
|
+
* the next major version.
|
|
138
149
|
*
|
|
139
150
|
* @param timestampMs ms-epoch, and the same value sent as the body's
|
|
140
151
|
* `timestamp`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loan-contract.js","sourceRoot":"","sources":["../../src/domain/loan-contract.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"loan-contract.js","sourceRoot":"","sources":["../../src/domain/loan-contract.ts"],"names":[],"mappings":"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"}
|
package/dist/domain/pool-tvl.js
CHANGED
|
@@ -19,4 +19,183 @@
|
|
|
19
19
|
export function poolTvl(onChainBalance, offChainTvl) {
|
|
20
20
|
return parseFloat(onChainBalance) + parseFloat(offChainTvl);
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* What `combineTvlHistories` throws instead of returning a number it cannot
|
|
24
|
+
* stand behind. `leg` and `entry` are the zero-based position of the
|
|
25
|
+
* offending input, when there is one.
|
|
26
|
+
*/
|
|
27
|
+
export class TvlHistoryInputError extends Error {
|
|
28
|
+
constructor(code, leg, entry) {
|
|
29
|
+
const at = [
|
|
30
|
+
leg === undefined ? '' : ` at leg ${String(leg)}`,
|
|
31
|
+
entry === undefined ? '' : `, entry ${String(entry)}`,
|
|
32
|
+
].join('');
|
|
33
|
+
super(`combineTvlHistories: input refused (${code})${at}`);
|
|
34
|
+
this.name = 'TvlHistoryInputError';
|
|
35
|
+
this.code = code;
|
|
36
|
+
this.leg = leg;
|
|
37
|
+
this.entry = entry;
|
|
38
|
+
Object.setPrototypeOf(this, TvlHistoryInputError.prototype);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function isNonNegativeFinite(value) {
|
|
42
|
+
return typeof value === 'number' && Number.isFinite(value) && value >= 0;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Throws unless the leg is well formed. Index loops, not `forEach`: a hole in
|
|
46
|
+
* a sparse array is skipped by the array methods and would surface later as
|
|
47
|
+
* a raw `TypeError` instead of a refusal.
|
|
48
|
+
*/
|
|
49
|
+
function validateLeg(leg, legIndex) {
|
|
50
|
+
if (typeof leg !== 'object' || leg === null) {
|
|
51
|
+
throw new TvlHistoryInputError('leg', legIndex);
|
|
52
|
+
}
|
|
53
|
+
const { entries, usdRate, opening } = leg;
|
|
54
|
+
if (typeof usdRate !== 'number' ||
|
|
55
|
+
!Number.isFinite(usdRate) ||
|
|
56
|
+
usdRate <= 0) {
|
|
57
|
+
throw new TvlHistoryInputError('usd-rate', legIndex);
|
|
58
|
+
}
|
|
59
|
+
if (!Array.isArray(entries)) {
|
|
60
|
+
throw new TvlHistoryInputError('entries', legIndex);
|
|
61
|
+
}
|
|
62
|
+
const list = entries;
|
|
63
|
+
if (list.length === 0) {
|
|
64
|
+
throw new TvlHistoryInputError('empty-leg', legIndex);
|
|
65
|
+
}
|
|
66
|
+
let previous = -Infinity;
|
|
67
|
+
for (let index = 0; index < list.length; index += 1) {
|
|
68
|
+
const entry = list[index];
|
|
69
|
+
if (typeof entry !== 'object' || entry === null) {
|
|
70
|
+
throw new TvlHistoryInputError('entry', legIndex, index);
|
|
71
|
+
}
|
|
72
|
+
const { timestamp, tvl, kind } = entry;
|
|
73
|
+
if (!isNonNegativeFinite(timestamp)) {
|
|
74
|
+
throw new TvlHistoryInputError('timestamp', legIndex, index);
|
|
75
|
+
}
|
|
76
|
+
if (!isNonNegativeFinite(tvl)) {
|
|
77
|
+
throw new TvlHistoryInputError('tvl', legIndex, index);
|
|
78
|
+
}
|
|
79
|
+
if (kind !== 'clearing' && kind !== 'current') {
|
|
80
|
+
throw new TvlHistoryInputError('kind', legIndex, index);
|
|
81
|
+
}
|
|
82
|
+
if (kind === 'current' && index !== list.length - 1) {
|
|
83
|
+
throw new TvlHistoryInputError('current', legIndex, index);
|
|
84
|
+
}
|
|
85
|
+
if (timestamp < previous) {
|
|
86
|
+
throw new TvlHistoryInputError('order', legIndex, index);
|
|
87
|
+
}
|
|
88
|
+
previous = timestamp;
|
|
89
|
+
}
|
|
90
|
+
if (opening !== undefined && opening !== null) {
|
|
91
|
+
const first = list[0];
|
|
92
|
+
const { timestamp, tvl, kind } = (typeof opening === 'object' ? opening : {});
|
|
93
|
+
if (!isNonNegativeFinite(timestamp) ||
|
|
94
|
+
!isNonNegativeFinite(tvl) ||
|
|
95
|
+
kind !== 'clearing' ||
|
|
96
|
+
timestamp > first.timestamp) {
|
|
97
|
+
throw new TvlHistoryInputError('opening', legIndex);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return leg;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* A strategy's TVL in USD over time, from its deployments' histories — Tax
|
|
104
|
+
* Pay runs on Base (USDC) and on XDC (AUDD), and its total lent is both.
|
|
105
|
+
* Pure: the caller fetches each leg (`strategyDeployments` names them) and
|
|
106
|
+
* passes the exchange rates.
|
|
107
|
+
*
|
|
108
|
+
* A step merge by time. At every distinct timestamp where any leg has a
|
|
109
|
+
* clearing, the value is the sum over legs of that leg's latest point at or
|
|
110
|
+
* before then, times its `usdRate`. A leg's `opening` — what it held just
|
|
111
|
+
* before the window — is one more step: it counts from its own timestamp
|
|
112
|
+
* until the leg's first entry, and the leg is 0 before it (or throughout,
|
|
113
|
+
* before its first entry, without one).
|
|
114
|
+
* Points that share a timestamp — clearings run in one block, or two chains
|
|
115
|
+
* clearing in the same second — are one output point. The series ends with
|
|
116
|
+
* one `current` point at the latest of the legs' `current` timestamps, equal
|
|
117
|
+
* to the sum of their `current` values. Every leg must end in a `current`
|
|
118
|
+
* point, or none may.
|
|
119
|
+
*
|
|
120
|
+
* The window is the union of the legs' windows: the series starts at the
|
|
121
|
+
* earliest first entry of any leg. An `opening` is a value, never a point.
|
|
122
|
+
* Without it, two windows cut at offset clearing times would count the
|
|
123
|
+
* later-starting leg 0 at the left edge and draw a false step up; with it,
|
|
124
|
+
* only a genuine late start (`opening: null`) counts 0.
|
|
125
|
+
*
|
|
126
|
+
* Every leg and entry is validated first: a bad input — an empty leg
|
|
127
|
+
* included — throws `TvlHistoryInputError` (its `code` says why), so the
|
|
128
|
+
* result never holds `NaN` or `Infinity`. The inputs are not modified.
|
|
129
|
+
*
|
|
130
|
+
* ```ts
|
|
131
|
+
* const window = { count: 52 };
|
|
132
|
+
* const points = combineTvlHistories([
|
|
133
|
+
* { ...(await base.strategies.getPoolTvlHistoryWindow(basePool, window)), usdRate: 1 },
|
|
134
|
+
* { ...(await xdc.strategies.getPoolTvlHistoryWindow(xdcPool, window)), usdRate: audToUsd },
|
|
135
|
+
* ]);
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
export function combineTvlHistories(legs) {
|
|
139
|
+
if (!Array.isArray(legs) || legs.length === 0) {
|
|
140
|
+
throw new TvlHistoryInputError('legs');
|
|
141
|
+
}
|
|
142
|
+
const valid = [];
|
|
143
|
+
for (let index = 0; index < legs.length; index += 1) {
|
|
144
|
+
valid.push(validateLeg(legs[index], index));
|
|
145
|
+
}
|
|
146
|
+
const endsInCurrent = valid.map((leg) => leg.entries[leg.entries.length - 1].kind === 'current');
|
|
147
|
+
const odd = endsInCurrent.findIndex((ends) => ends !== endsInCurrent[0]);
|
|
148
|
+
if (odd !== -1)
|
|
149
|
+
throw new TvlHistoryInputError('current', odd);
|
|
150
|
+
const finalTimestamp = endsInCurrent[0]
|
|
151
|
+
? Math.max(...valid.map((leg) => leg.entries[leg.entries.length - 1].timestamp))
|
|
152
|
+
: undefined;
|
|
153
|
+
const clearingTimes = [
|
|
154
|
+
...new Set(valid.flatMap((leg) => leg.entries
|
|
155
|
+
.filter((entry) => entry.kind === 'clearing')
|
|
156
|
+
.map((entry) => entry.timestamp))),
|
|
157
|
+
]
|
|
158
|
+
.filter((t) => finalTimestamp === undefined || t < finalTimestamp)
|
|
159
|
+
.sort((a, b) => a - b);
|
|
160
|
+
// One cursor per leg: the times ascend, so each leg is walked once. A
|
|
161
|
+
// leg's `current` point is a step like any other, which keeps a chain
|
|
162
|
+
// whose subgraph lags behind the other's last clearing at its own latest.
|
|
163
|
+
const cursors = valid.map(() => -1);
|
|
164
|
+
const sumAt = (t) => {
|
|
165
|
+
let sum = 0;
|
|
166
|
+
valid.forEach((leg, index) => {
|
|
167
|
+
let cursor = cursors[index];
|
|
168
|
+
while (cursor + 1 < leg.entries.length &&
|
|
169
|
+
leg.entries[cursor + 1].timestamp <= t) {
|
|
170
|
+
cursor += 1;
|
|
171
|
+
}
|
|
172
|
+
cursors[index] = cursor;
|
|
173
|
+
// Before the first entry, the opening is the step — from its
|
|
174
|
+
// own time on, never earlier.
|
|
175
|
+
const opening = leg.opening;
|
|
176
|
+
const value = cursor >= 0
|
|
177
|
+
? leg.entries[cursor].tvl
|
|
178
|
+
: opening && opening.timestamp <= t
|
|
179
|
+
? opening.tvl
|
|
180
|
+
: 0;
|
|
181
|
+
sum += value * leg.usdRate;
|
|
182
|
+
});
|
|
183
|
+
if (!Number.isFinite(sum))
|
|
184
|
+
throw new TvlHistoryInputError('overflow');
|
|
185
|
+
return sum;
|
|
186
|
+
};
|
|
187
|
+
const combined = clearingTimes.map((t) => ({
|
|
188
|
+
timestamp: t,
|
|
189
|
+
tvlUsd: sumAt(t),
|
|
190
|
+
kind: 'clearing',
|
|
191
|
+
}));
|
|
192
|
+
if (finalTimestamp !== undefined) {
|
|
193
|
+
combined.push({
|
|
194
|
+
timestamp: finalTimestamp,
|
|
195
|
+
tvlUsd: sumAt(finalTimestamp),
|
|
196
|
+
kind: 'current',
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
return combined;
|
|
200
|
+
}
|
|
22
201
|
//# sourceMappingURL=pool-tvl.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pool-tvl.js","sourceRoot":"","sources":["../../src/domain/pool-tvl.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,OAAO,CAAC,cAAsB,EAAE,WAAmB;IAC/D,OAAO,UAAU,CAAC,cAAc,CAAC,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;AAChE,CAAC"}
|
|
1
|
+
{"version":3,"file":"pool-tvl.js","sourceRoot":"","sources":["../../src/domain/pool-tvl.ts"],"names":[],"mappings":"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"}
|
package/dist/domain/requests.js
CHANGED
|
@@ -95,16 +95,23 @@ export function cancelDeadline(request, nextEpochStart, nowSeconds) {
|
|
|
95
95
|
const isCancelled = (events) => events.some((e) => e.requestType === 'Cancelled');
|
|
96
96
|
const isForced = (events) => events.some((e) => e.requestType === 'Forced');
|
|
97
97
|
const initiatedEvent = (events) => events.find((e) => e.requestType === 'Initiated');
|
|
98
|
+
/** `assetAmount` of the `Initiated` event, or 0 when there is none. */
|
|
99
|
+
const initiatedAmountOf = (events) => {
|
|
100
|
+
const initiated = initiatedEvent(events);
|
|
101
|
+
return initiated ? Number(initiated.assetAmount || '0') : 0;
|
|
102
|
+
};
|
|
98
103
|
/**
|
|
99
104
|
* Subgraph behaviour: when a request is cancelled, the on-request
|
|
100
105
|
* `requestedAmount` field is reset to 0 (the lender's effective balance is
|
|
101
|
-
* restored). The
|
|
102
|
-
* `assetAmount
|
|
103
|
-
*
|
|
106
|
+
* restored). The amount cancelled survives on the `Cancelled` event's
|
|
107
|
+
* `assetAmount` — everything still outstanding at the cancel, top-ups
|
|
108
|
+
* included. Only when that event carries no figure does this fall back to the
|
|
109
|
+
* `Initiated` event, which holds the FIRST submission alone and so misses
|
|
110
|
+
* every top-up.
|
|
104
111
|
*/
|
|
105
|
-
const
|
|
106
|
-
const
|
|
107
|
-
return
|
|
112
|
+
const cancelledAmountOf = (events) => {
|
|
113
|
+
const cancelledEvent = events.find((e) => e.requestType === 'Cancelled');
|
|
114
|
+
return num(cancelledEvent === null || cancelledEvent === void 0 ? void 0 : cancelledEvent.assetAmount) || initiatedAmountOf(events);
|
|
108
115
|
};
|
|
109
116
|
/**
|
|
110
117
|
* A deposit is REALLOCATED when the timeline carries a `Reallocated` event, or
|
|
@@ -130,17 +137,15 @@ const numOrNull = (str) => {
|
|
|
130
137
|
* Convert a `UserRequest` into a `RequestState`. Pure — no clock, no network,
|
|
131
138
|
* no copy.
|
|
132
139
|
*
|
|
133
|
-
* BRANCH ORDER (this IS the behaviour
|
|
134
|
-
* `deriveTransactionView` check for check):
|
|
140
|
+
* BRANCH ORDER (this IS the behaviour):
|
|
135
141
|
*
|
|
136
142
|
* 1. a `Cancelled` event → `cancelled`, neutral, 0
|
|
137
143
|
* 2. a withdrawal with a `Forced` event → `forced`, outflow, −accepted
|
|
138
144
|
* 3. a reallocated deposit → `reallocated`, inflow, +accepted
|
|
139
|
-
* 4. a withdrawal partly filled
|
|
140
|
-
* remainder (cycle
|
|
145
|
+
* 4. a withdrawal partly filled (paid > 0) with
|
|
146
|
+
* a LIVE remainder (queued > 0, cycle open) → `partial`, outflow, −accepted
|
|
141
147
|
* 5. resolved (`status === 'Processed'`):
|
|
142
|
-
* withdrawal
|
|
143
|
-
* withdrawal, fully filled → `complete`, outflow, −accepted
|
|
148
|
+
* withdrawal (nothing left queued) → `complete`, outflow, −accepted
|
|
144
149
|
* deposit, nothing accepted → `rejected`, neutral, 0
|
|
145
150
|
* deposit, part rejected → `partial`, inflow, +accepted
|
|
146
151
|
* deposit, fully accepted → `complete`, inflow, +accepted
|
|
@@ -168,10 +173,10 @@ export function deriveRequestState(request) {
|
|
|
168
173
|
const isWithdrawal = request.requestType === 'Withdrawal';
|
|
169
174
|
const cancelled = isCancelled(request.events);
|
|
170
175
|
// Cancelled requests have `requestedAmount` zeroed on the request itself;
|
|
171
|
-
//
|
|
172
|
-
//
|
|
176
|
+
// take the amount from the Cancelled event so the row still carries
|
|
177
|
+
// "1500 cancelled" (1000 + a 500 top-up) instead of "0 cancelled".
|
|
173
178
|
const requested = cancelled
|
|
174
|
-
? num(request.requestedAmount) ||
|
|
179
|
+
? num(request.requestedAmount) || cancelledAmountOf(request.events)
|
|
175
180
|
: num(request.requestedAmount);
|
|
176
181
|
const accepted = num(request.acceptedAmount);
|
|
177
182
|
const rejected = num(request.rejectedAmount);
|
|
@@ -222,18 +227,23 @@ export function deriveRequestState(request) {
|
|
|
222
227
|
}
|
|
223
228
|
// 4. Withdrawal partly filled with a LIVE remainder: the request returns
|
|
224
229
|
// to the queue with a live Cancel. Checked BEFORE the resolved branch and
|
|
225
|
-
// via `isCycleClosed`, never via the sticky raw status.
|
|
230
|
+
// via `isCycleClosed`, never via the sticky raw status. `requested` is
|
|
231
|
+
// what is still OUTSTANDING, so "partly filled" is "something paid AND
|
|
232
|
+
// something still queued" — never a comparison of the two, which would
|
|
233
|
+
// turn on whether more was paid than is left.
|
|
226
234
|
if (isWithdrawal &&
|
|
227
235
|
accepted > 0 &&
|
|
228
|
-
|
|
236
|
+
requested > 0 &&
|
|
229
237
|
!isCycleClosed(request)) {
|
|
230
238
|
return Object.assign(Object.assign({}, base), { kind: 'outflow', amount: -accepted, statusCode: 'partial' });
|
|
231
239
|
}
|
|
232
240
|
// 5. Resolved — a rejection IS a resolution.
|
|
233
241
|
if (request.status === UserRequestStatus.PROCESSED) {
|
|
242
|
+
// A withdrawal is resolved only once nothing is left queued — a
|
|
243
|
+
// partly filled one returns to the queue (branch 4), and one cancelled
|
|
244
|
+
// with a remainder is branch 1 — so a resolved withdrawal is complete.
|
|
234
245
|
if (isWithdrawal) {
|
|
235
|
-
|
|
236
|
-
return Object.assign(Object.assign({}, base), { kind: 'outflow', amount: -accepted, statusCode: partly ? 'partial' : 'complete' });
|
|
246
|
+
return Object.assign(Object.assign({}, base), { kind: 'outflow', amount: -accepted, statusCode: 'complete' });
|
|
237
247
|
}
|
|
238
248
|
// Deposit: full reject vs partial vs full accept.
|
|
239
249
|
if (accepted === 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requests.js","sourceRoot":"","sources":["../../src/domain/requests.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAM3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"requests.js","sourceRoot":"","sources":["../../src/domain/requests.ts"],"names":[],"mappings":"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"}
|