@kasufinance/kasu-sdk 2.4.2 → 2.6.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/LICENSE +21 -0
- package/README.md +201 -253
- package/dist/bundle.cjs.js +5472 -1710
- package/dist/bundle.esm.js +5415 -1713
- 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/au-minimum.test.js +202 -0
- package/dist/domain/au-minimum.test.js.map +1 -0
- package/dist/domain/deposit-bounds.d.ts +62 -0
- package/dist/domain/deposit-bounds.js +84 -0
- package/dist/domain/deposit-bounds.js.map +1 -0
- package/dist/domain/deposit-bounds.test.d.ts +1 -0
- package/dist/domain/deposit-bounds.test.js +135 -0
- package/dist/domain/deposit-bounds.test.js.map +1 -0
- package/dist/domain/index.d.ts +40 -0
- package/dist/domain/index.js +33 -0
- package/dist/domain/index.js.map +1 -0
- 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/loan-contract.test.d.ts +1 -0
- package/dist/domain/loan-contract.test.js +255 -0
- package/dist/domain/loan-contract.test.js.map +1 -0
- package/dist/domain/partners.d.ts +34 -0
- package/dist/domain/partners.js +43 -0
- package/dist/domain/partners.js.map +1 -0
- package/dist/domain/partners.test.d.ts +1 -0
- package/dist/domain/partners.test.js +53 -0
- package/dist/domain/partners.test.js.map +1 -0
- package/dist/domain/pools.d.ts +70 -0
- package/dist/domain/pools.js +134 -0
- package/dist/domain/pools.js.map +1 -0
- package/dist/domain/pools.test.d.ts +1 -0
- package/dist/domain/pools.test.js +184 -0
- package/dist/domain/pools.test.js.map +1 -0
- package/dist/domain/rates.d.ts +83 -0
- package/dist/domain/rates.js +120 -0
- package/dist/domain/rates.js.map +1 -0
- package/dist/domain/rates.test.d.ts +1 -0
- package/dist/domain/rates.test.js +181 -0
- package/dist/domain/rates.test.js.map +1 -0
- package/dist/domain/requests.d.ts +181 -0
- package/dist/domain/requests.js +202 -0
- package/dist/domain/requests.js.map +1 -0
- package/dist/domain/requests.test.d.ts +1 -0
- package/dist/domain/requests.test.js +470 -0
- package/dist/domain/requests.test.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/settlement.test.d.ts +1 -0
- package/dist/domain/settlement.test.js +152 -0
- package/dist/domain/settlement.test.js.map +1 -0
- package/dist/domain/tranche-display-name.d.ts +17 -0
- package/dist/domain/tranche-display-name.js +30 -0
- package/dist/domain/tranche-display-name.js.map +1 -0
- package/dist/domain/tranche-display-name.test.d.ts +1 -0
- package/dist/domain/tranche-display-name.test.js +58 -0
- package/dist/domain/tranche-display-name.test.js.map +1 -0
- package/dist/domain/tranches.d.ts +89 -0
- package/dist/domain/tranches.js +150 -0
- package/dist/domain/tranches.js.map +1 -0
- package/dist/domain/tranches.test.d.ts +1 -0
- package/dist/domain/tranches.test.js +206 -0
- package/dist/domain/tranches.test.js.map +1 -0
- package/dist/domain/wallet-errors.d.ts +37 -0
- package/dist/domain/wallet-errors.js +56 -0
- package/dist/domain/wallet-errors.js.map +1 -0
- package/dist/domain/wallet-errors.test.d.ts +1 -0
- package/dist/domain/wallet-errors.test.js +71 -0
- package/dist/domain/wallet-errors.test.js.map +1 -0
- package/dist/facade/chain-configs.js +61 -1
- package/dist/facade/chain-configs.js.map +1 -1
- package/dist/facade/config.test.d.ts +1 -0
- package/dist/facade/config.test.js +216 -0
- package/dist/facade/config.test.js.map +1 -0
- package/dist/facade/deposits.d.ts +22 -1
- package/dist/facade/deposits.js +24 -1
- package/dist/facade/deposits.js.map +1 -1
- package/dist/facade/facade.test.d.ts +1 -0
- package/dist/{tests → facade}/facade.test.js +87 -5
- package/dist/facade/facade.test.js.map +1 -0
- package/dist/facade/index.d.ts +2 -1
- package/dist/facade/index.js +2 -0
- package/dist/facade/index.js.map +1 -1
- package/dist/facade/kasu.d.ts +49 -8
- package/dist/facade/kasu.js +117 -13
- package/dist/facade/kasu.js.map +1 -1
- package/dist/facade/strategies.d.ts +25 -0
- package/dist/facade/strategies.js +36 -0
- package/dist/facade/strategies.js.map +1 -1
- package/dist/facade/types.d.ts +57 -2
- package/dist/facade/unused-pool-ids.d.ts +31 -0
- package/dist/facade/unused-pool-ids.js +57 -0
- package/dist/facade/unused-pool-ids.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/index.d.ts +2 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/sdk-config.d.ts +11 -0
- package/dist/sdk-config.js +8 -1
- package/dist/sdk-config.js.map +1 -1
- package/dist/services/DataService/data-service.d.ts +5 -0
- package/dist/services/DataService/data-service.js +10 -12
- 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/Locking/calculate-apy.test.d.ts +1 -0
- package/dist/services/Locking/calculate-apy.test.js +41 -0
- package/dist/services/Locking/calculate-apy.test.js.map +1 -0
- package/dist/services/Locking/locking.d.ts +14 -0
- package/dist/services/Locking/locking.js +16 -2
- package/dist/services/Locking/locking.js.map +1 -1
- package/dist/services/UserLending/user-lending.js +11 -7
- package/dist/services/UserLending/user-lending.js.map +1 -1
- package/dist/tests/sample.test.js +46 -25
- package/dist/tests/sample.test.js.map +1 -1
- package/package.json +43 -12
- package/src/domain/au-minimum.test.ts +371 -0
- package/src/domain/au-minimum.ts +192 -0
- package/src/domain/deposit-bounds.test.ts +200 -0
- package/src/domain/deposit-bounds.ts +118 -0
- package/src/domain/index.ts +134 -0
- package/src/domain/loan-contract.test.ts +343 -0
- package/src/domain/loan-contract.ts +275 -0
- package/src/domain/partners.test.ts +83 -0
- package/src/domain/partners.ts +66 -0
- package/src/domain/pools.test.ts +260 -0
- package/src/domain/pools.ts +150 -0
- package/src/domain/rates.test.ts +254 -0
- package/src/domain/rates.ts +120 -0
- package/src/domain/requests.test.ts +653 -0
- package/src/domain/requests.ts +414 -0
- package/src/domain/settlement.test.ts +198 -0
- package/src/domain/settlement.ts +161 -0
- package/src/domain/tranche-display-name.test.ts +96 -0
- package/src/domain/tranche-display-name.ts +34 -0
- package/src/domain/tranches.test.ts +300 -0
- package/src/domain/tranches.ts +177 -0
- package/src/domain/wallet-errors.test.ts +100 -0
- package/src/domain/wallet-errors.ts +56 -0
- package/src/facade/chain-configs.ts +62 -1
- package/src/facade/config.test.ts +265 -0
- package/src/facade/deposits.ts +25 -0
- package/src/{tests → facade}/facade.test.ts +134 -5
- package/src/facade/index.ts +4 -0
- package/src/facade/kasu.ts +155 -12
- package/src/facade/strategies.ts +36 -0
- package/src/facade/types.ts +60 -2
- package/src/facade/unused-pool-ids.ts +59 -0
- package/src/facade/user-portfolio.ts +24 -0
- package/src/index.ts +8 -0
- package/src/sdk-config.ts +19 -1
- package/src/services/DataService/data-service.ts +14 -26
- package/src/services/DataService/directus-client.ts +54 -0
- package/src/services/Locking/calculate-apy.test.ts +52 -0
- package/src/services/Locking/locking.ts +16 -2
- package/src/services/UserLending/user-lending.ts +17 -21
- package/src/tests/sample.test.ts +54 -33
- package/.eslintignore +0 -3
- package/.eslintrc.json +0 -90
- package/.github/workflows/ci.yml +0 -39
- package/.github/workflows/gitleaks.yml +0 -22
- package/.github/workflows/main.yml +0 -41
- package/.gitleaksignore +0 -19
- package/.prettierignore +0 -3
- package/.prettierrc +0 -28
- package/CLAUDE.md +0 -410
- package/copy-abi.ps1 +0 -15
- package/dist/tests/facade.test.js.map +0 -1
- package/index.ts +0 -2
- package/jest-config.ts +0 -9
- package/jest.config.js +0 -8
- package/rollup.config.js +0 -45
- package/tsconfig.json +0 -27
- /package/dist/{tests/facade.test.d.ts → domain/au-minimum.test.d.ts} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tranches.js","sourceRoot":"","sources":["../../src/domain/tranches.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import * as fc from 'fast-check';
|
|
2
|
+
import { netEffectiveApy } from './rates';
|
|
3
|
+
import { compareTrancheSeniority, derivePoolStatus, MIN_TRANCHE_CAPACITY, netTrancheApyBounds, pickDefaultTrancheId, poolAllTranchesFull, trancheApyBounds, trancheHasCapacity, trancheRiskRank, } from './tranches';
|
|
4
|
+
/**
|
|
5
|
+
* Ported from kasu-ui `pick-default-tranche.test.ts` and the NUMERIC half of
|
|
6
|
+
* `format-tranche-apy.range.test.ts`. The formatting cases — whole-percent
|
|
7
|
+
* rendering, the en-dash shape, the locale table and the "collapse when both
|
|
8
|
+
* bounds print the same" rule — stay in kasu-ui: they are decided on rendered
|
|
9
|
+
* digits, which this layer never produces.
|
|
10
|
+
*/
|
|
11
|
+
// `id === name` keeps assertions readable; `poolCapacity` drives
|
|
12
|
+
// `trancheHasCapacity` (≥ 1 stable unit → selectable).
|
|
13
|
+
function tranche(name, poolCapacity, apy = '0.12') {
|
|
14
|
+
return { id: name, name, apy, poolCapacity };
|
|
15
|
+
}
|
|
16
|
+
function pool(tranches, enabled = true) {
|
|
17
|
+
return { id: 'p', poolName: 'p', enabled, tranches };
|
|
18
|
+
}
|
|
19
|
+
function rated(minApy, maxApy) {
|
|
20
|
+
return { minApy, maxApy };
|
|
21
|
+
}
|
|
22
|
+
/** The live performance fee on all deployments (subgraph units: 10 = 10%). */
|
|
23
|
+
const FEE = 10;
|
|
24
|
+
describe('trancheHasCapacity', () => {
|
|
25
|
+
it('accepts a tranche with at least one whole stable unit left', () => {
|
|
26
|
+
expect(trancheHasCapacity({ poolCapacity: '5000' })).toBe(true);
|
|
27
|
+
expect(trancheHasCapacity({ poolCapacity: String(MIN_TRANCHE_CAPACITY) })).toBe(true);
|
|
28
|
+
});
|
|
29
|
+
it('rejects sub-unit dust, zero and unparseable capacity', () => {
|
|
30
|
+
expect(trancheHasCapacity({ poolCapacity: '0.99' })).toBe(false);
|
|
31
|
+
expect(trancheHasCapacity({ poolCapacity: '0' })).toBe(false);
|
|
32
|
+
expect(trancheHasCapacity({ poolCapacity: '1.4551915228366852e-11' })).toBe(false);
|
|
33
|
+
expect(trancheHasCapacity({ poolCapacity: '' })).toBe(false);
|
|
34
|
+
expect(trancheHasCapacity({ poolCapacity: 'not-a-number' })).toBe(false);
|
|
35
|
+
});
|
|
36
|
+
it('reads the facade tranche shape (availableCapacity) identically', () => {
|
|
37
|
+
// `StrategyTranche` renames the same number; one gate, both shapes.
|
|
38
|
+
expect(trancheHasCapacity({ availableCapacity: '5000' })).toBe(true);
|
|
39
|
+
expect(trancheHasCapacity({ availableCapacity: '0' })).toBe(false);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
describe('trancheRiskRank / compareTrancheSeniority', () => {
|
|
43
|
+
it('ranks the waterfall safest-first by the RAW name', () => {
|
|
44
|
+
expect(trancheRiskRank(tranche('Senior', '1'))).toBe(0);
|
|
45
|
+
expect(trancheRiskRank(tranche('Mezzanine', '1'))).toBe(1);
|
|
46
|
+
expect(trancheRiskRank(tranche('Junior', '1'))).toBe(2);
|
|
47
|
+
});
|
|
48
|
+
it('is case- and whitespace-insensitive, and sorts unknown names last', () => {
|
|
49
|
+
expect(trancheRiskRank(tranche(' SENIOR ', '1'))).toBe(0);
|
|
50
|
+
expect(trancheRiskRank(tranche('Upper Mezzanine', '1'))).toBe(Number.POSITIVE_INFINITY);
|
|
51
|
+
});
|
|
52
|
+
it('sorts Senior → Mezzanine → Junior, keeping ties in input order', () => {
|
|
53
|
+
const tranches = [
|
|
54
|
+
tranche('Junior', '5000'),
|
|
55
|
+
tranche('Tranche B', '5000'),
|
|
56
|
+
tranche('Senior', '5000'),
|
|
57
|
+
tranche('Tranche A', '5000'),
|
|
58
|
+
tranche('Mezzanine', '5000'),
|
|
59
|
+
];
|
|
60
|
+
expect([...tranches].sort(compareTrancheSeniority).map((t) => t.name)).toEqual([
|
|
61
|
+
'Senior',
|
|
62
|
+
'Mezzanine',
|
|
63
|
+
'Junior',
|
|
64
|
+
'Tranche B',
|
|
65
|
+
'Tranche A',
|
|
66
|
+
]);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
describe('pickDefaultTrancheId', () => {
|
|
70
|
+
it('defaults to the lowest-risk tranche (Senior) when all have capacity', () => {
|
|
71
|
+
// Subgraph order is Junior → Mezzanine → Senior; the default must NOT
|
|
72
|
+
// be the highest-risk Junior that sits first (audit 3.2).
|
|
73
|
+
const id = pickDefaultTrancheId(pool([
|
|
74
|
+
tranche('Junior', '5000'),
|
|
75
|
+
tranche('Mezzanine', '5000'),
|
|
76
|
+
tranche('Senior', '5000'),
|
|
77
|
+
]));
|
|
78
|
+
expect(id).toBe('Senior');
|
|
79
|
+
});
|
|
80
|
+
it('picks the lowest-risk tranche that is still AVAILABLE (skips a full Senior)', () => {
|
|
81
|
+
const id = pickDefaultTrancheId(pool([
|
|
82
|
+
tranche('Junior', '5000'),
|
|
83
|
+
tranche('Mezzanine', '5000'),
|
|
84
|
+
tranche('Senior', '0'),
|
|
85
|
+
]));
|
|
86
|
+
expect(id).toBe('Mezzanine');
|
|
87
|
+
});
|
|
88
|
+
it('does not rank by APY — a Senior priced above Mezzanine is still preferred', () => {
|
|
89
|
+
// Real pools can price Senior above Mezzanine; risk is ranked by name,
|
|
90
|
+
// not rate.
|
|
91
|
+
const id = pickDefaultTrancheId(pool([
|
|
92
|
+
tranche('Mezzanine', '5000', '0.15'),
|
|
93
|
+
tranche('Senior', '5000', '0.18'),
|
|
94
|
+
]));
|
|
95
|
+
expect(id).toBe('Senior');
|
|
96
|
+
});
|
|
97
|
+
it('falls back to the lowest-risk tranche when every tranche is full', () => {
|
|
98
|
+
const id = pickDefaultTrancheId(pool([tranche('Junior', '0'), tranche('Senior', '0')]));
|
|
99
|
+
expect(id).toBe('Senior');
|
|
100
|
+
});
|
|
101
|
+
it('falls back to the first available tranche when names are unrecognised', () => {
|
|
102
|
+
const id = pickDefaultTrancheId(pool([tranche('Tranche B', '5000'), tranche('Tranche A', '5000')]));
|
|
103
|
+
expect(id).toBe('Tranche B');
|
|
104
|
+
});
|
|
105
|
+
it('returns an empty string for a pool with no tranches', () => {
|
|
106
|
+
expect(pickDefaultTrancheId(pool([]))).toBe('');
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
describe('poolAllTranchesFull', () => {
|
|
110
|
+
it('is true when every tranche lacks remaining capacity', () => {
|
|
111
|
+
expect(poolAllTranchesFull(pool([tranche('Junior', '0'), tranche('Senior', '0')]))).toBe(true);
|
|
112
|
+
});
|
|
113
|
+
it('is false when at least one tranche still has capacity', () => {
|
|
114
|
+
expect(poolAllTranchesFull(pool([tranche('Junior', '0'), tranche('Senior', '5000')]))).toBe(false);
|
|
115
|
+
});
|
|
116
|
+
it('is false for a pool with no tranches (nothing to be full)', () => {
|
|
117
|
+
expect(poolAllTranchesFull(pool([]))).toBe(false);
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
describe('derivePoolStatus', () => {
|
|
121
|
+
it('is "Coming soon" for a pool that is not yet enabled, full or not', () => {
|
|
122
|
+
expect(derivePoolStatus(pool([tranche('Senior', '5000')], false))).toBe('Coming soon');
|
|
123
|
+
expect(derivePoolStatus(pool([tranche('Senior', '0')], false))).toBe('Coming soon');
|
|
124
|
+
});
|
|
125
|
+
it('is "Full" for an enabled pool with no capacity anywhere', () => {
|
|
126
|
+
expect(derivePoolStatus(pool([tranche('Senior', '0')]))).toBe('Full');
|
|
127
|
+
});
|
|
128
|
+
it('is "Live" for an enabled pool with capacity, or with no tranches yet', () => {
|
|
129
|
+
expect(derivePoolStatus(pool([tranche('Senior', '5000')]))).toBe('Live');
|
|
130
|
+
expect(derivePoolStatus(pool([]))).toBe('Live');
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
describe('trancheApyBounds', () => {
|
|
134
|
+
it('spans the lowest minApy and the highest maxApy across tranches', () => {
|
|
135
|
+
expect(trancheApyBounds([rated('0.12', '0.12'), rated('0.185', '0.185')])).toEqual({ min: 0.12, max: 0.185 });
|
|
136
|
+
});
|
|
137
|
+
it('carries a single-option strategy as an equal pair', () => {
|
|
138
|
+
expect(trancheApyBounds([rated('0.1', '0.1')])).toEqual({
|
|
139
|
+
min: 0.1,
|
|
140
|
+
max: 0.1,
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
it('skips zero and non-finite rates rather than dragging the range down', () => {
|
|
144
|
+
// A tranche with no fixed-term config must not turn a 10.5% range into
|
|
145
|
+
// 0–10.5%.
|
|
146
|
+
expect(trancheApyBounds([rated('0', '0'), rated('0.105', '0.105')])).toEqual({ min: 0.105, max: 0.105 });
|
|
147
|
+
expect(trancheApyBounds([rated('not-a-number', 'x'), rated('0.12', '0.14')])).toEqual({ min: 0.12, max: 0.14 });
|
|
148
|
+
});
|
|
149
|
+
it('is null when nothing usable remains', () => {
|
|
150
|
+
expect(trancheApyBounds([])).toBeNull();
|
|
151
|
+
expect(trancheApyBounds([rated('0', '0')])).toBeNull();
|
|
152
|
+
expect(trancheApyBounds([rated('-0.1', '-0.1')])).toBeNull();
|
|
153
|
+
});
|
|
154
|
+
it('is null when only ONE side is usable — never half a range', () => {
|
|
155
|
+
expect(trancheApyBounds([rated('0.12', '0')])).toBeNull();
|
|
156
|
+
expect(trancheApyBounds([rated('0', '0.12')])).toBeNull();
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
describe('netTrancheApyBounds', () => {
|
|
160
|
+
it('reproduces the spec §2.5 card range: 14–22% gross is 13–20% net', () => {
|
|
161
|
+
const bounds = netTrancheApyBounds([rated('0.14', '0.22')], FEE);
|
|
162
|
+
expect(bounds).not.toBeNull();
|
|
163
|
+
expect(bounds === null || bounds === void 0 ? void 0 : bounds.min).toBeCloseTo(0.1252, 4);
|
|
164
|
+
expect(bounds === null || bounds === void 0 ? void 0 : bounds.max).toBeCloseTo(0.196, 4);
|
|
165
|
+
});
|
|
166
|
+
it('puts each bound through netEffectiveApy and nothing else', () => {
|
|
167
|
+
const bounds = netTrancheApyBounds([rated('0.12', '0.185')], FEE);
|
|
168
|
+
expect(bounds).toEqual({
|
|
169
|
+
min: netEffectiveApy(0.12, FEE),
|
|
170
|
+
max: netEffectiveApy(0.185, FEE),
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
it('returns the gross bounds unchanged at a zero fee', () => {
|
|
174
|
+
expect(netTrancheApyBounds([rated('0.14', '0.22')], 0)).toEqual({
|
|
175
|
+
min: 0.14,
|
|
176
|
+
max: 0.22,
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
it('FAILS CLOSED on an out-of-domain fee — never the gross range', () => {
|
|
180
|
+
// The raw subgraph integer (1000 = 10%) and a negative fee both land
|
|
181
|
+
// here. A caller that does not KNOW the fee must not call at all;
|
|
182
|
+
// substituting 0 would overstate the rate with nothing saying so.
|
|
183
|
+
expect(netTrancheApyBounds([rated('0.14', '0.22')], 1000)).toBeNull();
|
|
184
|
+
expect(netTrancheApyBounds([rated('0.14', '0.22')], -1)).toBeNull();
|
|
185
|
+
expect(netTrancheApyBounds([rated('0.14', '0.22')], NaN)).toBeNull();
|
|
186
|
+
});
|
|
187
|
+
it('is null when a 100% fee leaves the lender nothing', () => {
|
|
188
|
+
expect(netTrancheApyBounds([rated('0.14', '0.22')], 100)).toBeNull();
|
|
189
|
+
});
|
|
190
|
+
it('is null whenever the gross range is', () => {
|
|
191
|
+
expect(netTrancheApyBounds([], FEE)).toBeNull();
|
|
192
|
+
expect(netTrancheApyBounds([rated('0', '0')], FEE)).toBeNull();
|
|
193
|
+
});
|
|
194
|
+
it('never inverts the range it was given', () => {
|
|
195
|
+
fc.assert(fc.property(fc.double({ min: 0.0001, max: 0.99, noNaN: true }), fc.double({ min: 0.0001, max: 0.99, noNaN: true }), fc.double({ min: 0, max: 99, noNaN: true }), (a, b, feePercent) => {
|
|
196
|
+
const bounds = netTrancheApyBounds([
|
|
197
|
+
rated(String(Math.min(a, b)), String(Math.max(a, b))),
|
|
198
|
+
], feePercent);
|
|
199
|
+
if (!bounds)
|
|
200
|
+
return;
|
|
201
|
+
expect(bounds.min).toBeLessThanOrEqual(bounds.max);
|
|
202
|
+
expect(bounds.min).toBeGreaterThan(0);
|
|
203
|
+
}), { numRuns: 2000 });
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
//# sourceMappingURL=tranches.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tranches.test.js","sourceRoot":"","sources":["../../src/domain/tranches.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
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`.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Did the lender reject the request in their wallet?
|
|
15
|
+
*
|
|
16
|
+
* Providers surface a rejection in different shapes:
|
|
17
|
+
* - MetaMask and most EIP-1193 wallets: `code: 4001`
|
|
18
|
+
* - WalletConnect and some Privy paths: `Error('User rejected the request')`
|
|
19
|
+
* - ethers v5 wraps it as `ACTION_REJECTED`
|
|
20
|
+
* - Coinbase Wallet sometimes: `code: 'ACTION_REJECTED'` as a string
|
|
21
|
+
*
|
|
22
|
+
* This is kasu-ui's implementation verbatim. kasu-mobile's copy additionally
|
|
23
|
+
* reads a nested `error.code` / `error.message`, an ethers `reason`, and the
|
|
24
|
+
* words "request rejected" / "declined"; a consumer that needs those shapes
|
|
25
|
+
* should keep its own check on top rather than assume they are covered here.
|
|
26
|
+
*/
|
|
27
|
+
export declare function isUserRejected(err: unknown): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Did the wallet or RPC signal that the on-chain call would revert?
|
|
30
|
+
*
|
|
31
|
+
* ethers v5 raises `UNPREDICTABLE_GAS_LIMIT` when gas estimation reverts —
|
|
32
|
+
* most often an underlying `transferFrom` failing on an insufficient balance
|
|
33
|
+
* or allowance. Distinct from a rejection: nothing was refused by the lender,
|
|
34
|
+
* the transaction simply cannot succeed as composed, so the caller should
|
|
35
|
+
* re-check its preconditions rather than invite a retry.
|
|
36
|
+
*/
|
|
37
|
+
export declare function isUnpredictableGas(err: unknown): boolean;
|
|
@@ -0,0 +1,56 @@
|
|
|
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`.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Did the lender reject the request in their wallet?
|
|
15
|
+
*
|
|
16
|
+
* Providers surface a rejection in different shapes:
|
|
17
|
+
* - MetaMask and most EIP-1193 wallets: `code: 4001`
|
|
18
|
+
* - WalletConnect and some Privy paths: `Error('User rejected the request')`
|
|
19
|
+
* - ethers v5 wraps it as `ACTION_REJECTED`
|
|
20
|
+
* - Coinbase Wallet sometimes: `code: 'ACTION_REJECTED'` as a string
|
|
21
|
+
*
|
|
22
|
+
* This is kasu-ui's implementation verbatim. kasu-mobile's copy additionally
|
|
23
|
+
* reads a nested `error.code` / `error.message`, an ethers `reason`, and the
|
|
24
|
+
* words "request rejected" / "declined"; a consumer that needs those shapes
|
|
25
|
+
* should keep its own check on top rather than assume they are covered here.
|
|
26
|
+
*/
|
|
27
|
+
export function isUserRejected(err) {
|
|
28
|
+
if (!err)
|
|
29
|
+
return false;
|
|
30
|
+
if (typeof err === 'object') {
|
|
31
|
+
const code = err.code;
|
|
32
|
+
if (code === 4001 || code === 'ACTION_REJECTED')
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
36
|
+
const lower = msg.toLowerCase();
|
|
37
|
+
return (lower.includes('user rejected') ||
|
|
38
|
+
lower.includes('user denied') ||
|
|
39
|
+
lower.includes('rejected the request') ||
|
|
40
|
+
lower.includes('action_rejected'));
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Did the wallet or RPC signal that the on-chain call would revert?
|
|
44
|
+
*
|
|
45
|
+
* ethers v5 raises `UNPREDICTABLE_GAS_LIMIT` when gas estimation reverts —
|
|
46
|
+
* most often an underlying `transferFrom` failing on an insufficient balance
|
|
47
|
+
* or allowance. Distinct from a rejection: nothing was refused by the lender,
|
|
48
|
+
* the transaction simply cannot succeed as composed, so the caller should
|
|
49
|
+
* re-check its preconditions rather than invite a retry.
|
|
50
|
+
*/
|
|
51
|
+
export function isUnpredictableGas(err) {
|
|
52
|
+
if (!err || typeof err !== 'object')
|
|
53
|
+
return false;
|
|
54
|
+
return err.code === 'UNPREDICTABLE_GAS_LIMIT';
|
|
55
|
+
}
|
|
56
|
+
//# 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;;;;;;;;;;;GAWG;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,cAAc,CAAC,GAAY;IACvC,IAAI,CAAC,GAAG;QAAE,OAAO,KAAK,CAAC;IACvB,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC1B,MAAM,IAAI,GAAI,GAA0B,CAAC,IAAI,CAAC;QAC9C,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,iBAAiB;YAAE,OAAO,IAAI,CAAC;IACjE,CAAC;IACD,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC7D,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;IAChC,OAAO,CACH,KAAK,CAAC,QAAQ,CAAC,eAAe,CAAC;QAC/B,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC;QAC7B,KAAK,CAAC,QAAQ,CAAC,sBAAsB,CAAC;QACtC,KAAK,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CACpC,CAAC;AACN,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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { isUnpredictableGas, isUserRejected } from './wallet-errors';
|
|
2
|
+
/**
|
|
3
|
+
* `isUserRejected` cases ported from kasu-ui
|
|
4
|
+
* `src/lib/web3/is-user-rejected.test.ts`. `isUnpredictableGas` had no test in
|
|
5
|
+
* kasu-mobile; one is written here.
|
|
6
|
+
*/
|
|
7
|
+
describe('isUserRejected', () => {
|
|
8
|
+
it('detects EIP-1193 numeric code 4001', () => {
|
|
9
|
+
expect(isUserRejected({ code: 4001, message: 'whatever' })).toBe(true);
|
|
10
|
+
});
|
|
11
|
+
it('detects ACTION_REJECTED string code (ethers v5)', () => {
|
|
12
|
+
expect(isUserRejected({ code: 'ACTION_REJECTED', message: 'rejected' })).toBe(true);
|
|
13
|
+
});
|
|
14
|
+
it('detects "User rejected" message string', () => {
|
|
15
|
+
expect(isUserRejected(new Error('User rejected the request'))).toBe(true);
|
|
16
|
+
});
|
|
17
|
+
it('detects "User denied" message string', () => {
|
|
18
|
+
expect(isUserRejected(new Error('User denied transaction signature'))).toBe(true);
|
|
19
|
+
});
|
|
20
|
+
it('detects the ethers ACTION_REJECTED marker in a message', () => {
|
|
21
|
+
expect(isUserRejected(new Error('transaction failed: ACTION_REJECTED'))).toBe(true);
|
|
22
|
+
});
|
|
23
|
+
it('is case-insensitive', () => {
|
|
24
|
+
expect(isUserRejected(new Error('user REJECTED the request'))).toBe(true);
|
|
25
|
+
});
|
|
26
|
+
it('returns false for unrelated errors', () => {
|
|
27
|
+
expect(isUserRejected(new Error('Network error'))).toBe(false);
|
|
28
|
+
expect(isUserRejected(new Error('Insufficient funds'))).toBe(false);
|
|
29
|
+
});
|
|
30
|
+
it('returns false for null / undefined', () => {
|
|
31
|
+
expect(isUserRejected(null)).toBe(false);
|
|
32
|
+
expect(isUserRejected(undefined)).toBe(false);
|
|
33
|
+
});
|
|
34
|
+
it('handles non-Error throwables', () => {
|
|
35
|
+
expect(isUserRejected('user rejected')).toBe(true);
|
|
36
|
+
expect(isUserRejected('something else')).toBe(false);
|
|
37
|
+
});
|
|
38
|
+
it('is not fooled by a numeric code that only looks like 4001', () => {
|
|
39
|
+
expect(isUserRejected({ code: '4001' })).toBe(false);
|
|
40
|
+
expect(isUserRejected({ code: 4002 })).toBe(false);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
describe('isUnpredictableGas', () => {
|
|
44
|
+
it('detects the ethers v5 gas-estimation revert code', () => {
|
|
45
|
+
expect(isUnpredictableGas({ code: 'UNPREDICTABLE_GAS_LIMIT' })).toBe(true);
|
|
46
|
+
});
|
|
47
|
+
it('does not fire on a user rejection', () => {
|
|
48
|
+
expect(isUnpredictableGas({ code: 'ACTION_REJECTED' })).toBe(false);
|
|
49
|
+
expect(isUnpredictableGas({ code: 4001 })).toBe(false);
|
|
50
|
+
});
|
|
51
|
+
it('does not fire on the code appearing only in a message', () => {
|
|
52
|
+
// The code is the signal; a message mentioning it is not one, or a
|
|
53
|
+
// logged error string would be mistaken for a revert.
|
|
54
|
+
expect(isUnpredictableGas(new Error('UNPREDICTABLE_GAS_LIMIT'))).toBe(false);
|
|
55
|
+
expect(isUnpredictableGas('UNPREDICTABLE_GAS_LIMIT')).toBe(false);
|
|
56
|
+
});
|
|
57
|
+
it('returns false for null / undefined and for unrelated errors', () => {
|
|
58
|
+
expect(isUnpredictableGas(null)).toBe(false);
|
|
59
|
+
expect(isUnpredictableGas(undefined)).toBe(false);
|
|
60
|
+
expect(isUnpredictableGas(new Error('Network error'))).toBe(false);
|
|
61
|
+
});
|
|
62
|
+
it('reads the code off an ethers error object', () => {
|
|
63
|
+
const err = Object.assign(new Error('cannot estimate gas'), {
|
|
64
|
+
code: 'UNPREDICTABLE_GAS_LIMIT',
|
|
65
|
+
reason: 'execution reverted: ERC20: insufficient allowance',
|
|
66
|
+
});
|
|
67
|
+
expect(isUnpredictableGas(err)).toBe(true);
|
|
68
|
+
expect(isUserRejected(err)).toBe(false);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
//# sourceMappingURL=wallet-errors.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wallet-errors.test.js","sourceRoot":"","sources":["../../src/domain/wallet-errors.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-viable XDC RPCs only. `rpc.xdc.org` / `erpc.xdc.org` answer OPTIONS
|
|
3
|
+
* without `access-control-allow-origin`, so a browser call hangs on preflight
|
|
4
|
+
* — they must never appear here. The four below ship CORS `*` and are DISTINCT
|
|
5
|
+
* operators, so one vendor incident cannot exhaust the list. Order is a
|
|
6
|
+
* STARTING preference only; consumers are expected to fold the list into their
|
|
7
|
+
* own failover. Shared by both XDC deployments (same chain, same endpoints).
|
|
8
|
+
*/
|
|
9
|
+
const XDC_RPC_URLS = [
|
|
10
|
+
'https://rpc.ankr.com/xdc',
|
|
11
|
+
'https://rpc.xdcrpc.com',
|
|
12
|
+
'https://rpc.xinfin.network',
|
|
13
|
+
'https://rpc.primenumbers.xyz/',
|
|
14
|
+
];
|
|
1
15
|
/**
|
|
2
16
|
* Built-in chain configurations for Kasu-supported networks.
|
|
3
17
|
*
|
|
@@ -30,6 +44,17 @@ export const CHAIN_CONFIGS = {
|
|
|
30
44
|
directusUrl: 'https://kasu-finance.directus.app/',
|
|
31
45
|
unusedPoolIds: [],
|
|
32
46
|
poolMetadataMapping: undefined,
|
|
47
|
+
stableAsset: {
|
|
48
|
+
address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
|
|
49
|
+
symbol: 'USDC',
|
|
50
|
+
name: 'USD Coin',
|
|
51
|
+
decimals: 6,
|
|
52
|
+
currencyCode: 'USD',
|
|
53
|
+
},
|
|
54
|
+
rpcUrls: [
|
|
55
|
+
'https://base-rpc.publicnode.com',
|
|
56
|
+
'https://mainnet.base.org',
|
|
57
|
+
],
|
|
33
58
|
},
|
|
34
59
|
xdc: {
|
|
35
60
|
chainId: 50,
|
|
@@ -57,6 +82,14 @@ export const CHAIN_CONFIGS = {
|
|
|
57
82
|
'0x3b7cb493aa22f731db2ab424d918e7375e00f6a9': '0x03f93c8caa9a82e000d35673ba34a4c0e6e117a2',
|
|
58
83
|
'0xeda50c91a8c4ca8a83652b8542c0b3bd00a71fad': '0xc347a9e4aec8c8d11a149d2907deb2bf23b81c6f',
|
|
59
84
|
},
|
|
85
|
+
stableAsset: {
|
|
86
|
+
address: '0x9fe4e6321eeb7c4bc537570f015e4734b15002b8',
|
|
87
|
+
symbol: 'AUDD',
|
|
88
|
+
name: 'Novatti Australian Dollar',
|
|
89
|
+
decimals: 6,
|
|
90
|
+
currencyCode: 'AUD',
|
|
91
|
+
},
|
|
92
|
+
rpcUrls: XDC_RPC_URLS,
|
|
60
93
|
},
|
|
61
94
|
'xdc-usdc': {
|
|
62
95
|
chainId: 50,
|
|
@@ -80,6 +113,14 @@ export const CHAIN_CONFIGS = {
|
|
|
80
113
|
directusUrl: 'https://kasu-finance.directus.app/',
|
|
81
114
|
unusedPoolIds: [],
|
|
82
115
|
poolMetadataMapping: undefined,
|
|
116
|
+
stableAsset: {
|
|
117
|
+
address: '0xfa2958cb79b0491cc627c1557f441ef849ca8eb1',
|
|
118
|
+
symbol: 'USDC',
|
|
119
|
+
name: 'USD Coin',
|
|
120
|
+
decimals: 6,
|
|
121
|
+
currencyCode: 'USD',
|
|
122
|
+
},
|
|
123
|
+
rpcUrls: XDC_RPC_URLS,
|
|
83
124
|
},
|
|
84
125
|
plume: {
|
|
85
126
|
chainId: 98866,
|
|
@@ -98,10 +139,29 @@ export const CHAIN_CONFIGS = {
|
|
|
98
139
|
ClearingCoordinator: '',
|
|
99
140
|
ExternalTVL: '',
|
|
100
141
|
},
|
|
101
|
-
|
|
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',
|
|
102
149
|
directusUrl: 'https://kasu-finance.directus.app/',
|
|
103
150
|
unusedPoolIds: [],
|
|
104
151
|
poolMetadataMapping: undefined,
|
|
152
|
+
stableAsset: {
|
|
153
|
+
address: '0xdddD73F5Df1F0DC31373357beAC77545dC5A6f3F',
|
|
154
|
+
symbol: 'pUSD',
|
|
155
|
+
name: 'Plume USD',
|
|
156
|
+
decimals: 6,
|
|
157
|
+
currencyCode: 'USD',
|
|
158
|
+
},
|
|
159
|
+
// Retired — drained and wound down. No default RPC, so a read-only
|
|
160
|
+
// `Kasu.create({ chain: 'plume' })` throws rather than quietly
|
|
161
|
+
// pointing at an endpoint nobody maintains. Pass your own
|
|
162
|
+
// `signerOrProvider` to read the frozen history.
|
|
163
|
+
rpcUrls: [],
|
|
164
|
+
retired: true,
|
|
105
165
|
},
|
|
106
166
|
};
|
|
107
167
|
//# sourceMappingURL=chain-configs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chain-configs.js","sourceRoot":"","sources":["../../src/facade/chain-configs.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,aAAa,GAAoE;IAC1F,IAAI,EAAE;QACF,OAAO,EAAE,IAAI;QACb,IAAI,EAAE,cAAc;QACpB,gBAAgB,EAAE,KAAK;QACvB,SAAS,EAAE;YACP,QAAQ,EAAE,4CAA4C;YACtD,WAAW,EAAE,4CAA4C;YACzD,aAAa,EAAE,4CAA4C;YAC3D,kBAAkB,EAAE,4CAA4C;YAChE,WAAW,EAAE,4CAA4C;YACzD,aAAa,EAAE,4CAA4C;YAC3D,eAAe,EAAE,4CAA4C;YAC7D,QAAQ,EAAE,4CAA4C;YACtD,kBAAkB,EAAE,4CAA4C;YAChE,mBAAmB,EAAE,4CAA4C;YACjE,QAAQ,EAAE,4CAA4C;YACtD,WAAW,EAAE,4CAA4C;SAC5D;QACD,WAAW,EACP,qGAAqG;QACzG,WAAW,EAAE,oCAAoC;QACjD,aAAa,EAAE,EAAE;QACjB,mBAAmB,EAAE,SAAS;
|
|
1
|
+
{"version":3,"file":"chain-configs.js","sourceRoot":"","sources":["../../src/facade/chain-configs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|