@kasufinance/kasu-sdk 2.6.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 +128 -3
- package/dist/bundle.cjs.js +1119 -254
- package/dist/bundle.esm.js +1109 -255
- package/dist/domain/index.d.ts +3 -2
- package/dist/domain/index.js +2 -2
- package/dist/domain/index.js.map +1 -1
- package/dist/domain/requests.d.ts +42 -4
- package/dist/domain/requests.js +20 -4
- package/dist/domain/requests.js.map +1 -1
- package/dist/domain/wallet-errors.d.ts +63 -8
- package/dist/domain/wallet-errors.js +115 -16
- package/dist/domain/wallet-errors.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/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 +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/services/DataService/data-service.js +0 -1
- package/dist/services/DataService/data-service.js.map +1 -1
- package/package.json +8 -2
- package/src/domain/index.ts +7 -1
- package/src/domain/requests.ts +57 -4
- package/src/domain/wallet-errors.ts +135 -18
- 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/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 +7 -0
- package/src/services/DataService/data-service.ts +0 -1
- package/dist/domain/au-minimum.test.d.ts +0 -1
- package/dist/domain/au-minimum.test.js +0 -202
- package/dist/domain/au-minimum.test.js.map +0 -1
- 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/loan-contract.test.d.ts +0 -1
- package/dist/domain/loan-contract.test.js +0 -255
- package/dist/domain/loan-contract.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/requests.test.d.ts +0 -1
- package/dist/domain/requests.test.js +0 -470
- package/dist/domain/requests.test.js.map +0 -1
- package/dist/domain/settlement.test.d.ts +0 -1
- package/dist/domain/settlement.test.js +0 -152
- package/dist/domain/settlement.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/domain/wallet-errors.test.d.ts +0 -1
- package/dist/domain/wallet-errors.test.js +0 -71
- package/dist/domain/wallet-errors.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 -278
- 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/au-minimum.test.ts +0 -371
- package/src/domain/deposit-bounds.test.ts +0 -200
- package/src/domain/loan-contract.test.ts +0 -343
- 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/requests.test.ts +0 -653
- package/src/domain/settlement.test.ts +0 -198
- package/src/domain/tranche-display-name.test.ts +0 -96
- package/src/domain/tranches.test.ts +0 -300
- package/src/domain/wallet-errors.test.ts +0 -100
- package/src/facade/config.test.ts +0 -265
- package/src/facade/facade.test.ts +0 -374
- package/src/services/Locking/calculate-apy.test.ts +0 -52
- package/src/tests/sample.test.ts +0 -63
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { DepositFlow, WithdrawFlow, } from '../flows';
|
|
11
|
+
import { READ_ONLY_MESSAGE } from './read-only';
|
|
12
|
+
/**
|
|
13
|
+
* Builds `DepositFlow` / `WithdrawFlow` instances wired to THIS Kasu instance:
|
|
14
|
+
* its chain's stable token, its `LendingPoolManager`, its signer.
|
|
15
|
+
*
|
|
16
|
+
* ```ts
|
|
17
|
+
* const flow = kasu.connect(signer).flows.deposit({
|
|
18
|
+
* signMessage: (m) => signer.signMessage(m),
|
|
19
|
+
* generateContract: (req) => postToMyProxy(req),
|
|
20
|
+
* getKycSignature: (p) => postToMyBackend(p),
|
|
21
|
+
* });
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* A flow built from a read-only instance constructs fine and reads fine — the
|
|
25
|
+
* write ports throw `READ_ONLY_MESSAGE` when the run reaches them, exactly as
|
|
26
|
+
* `kasu.deposits.deposit` does. Constructing is not the mistake; submitting is.
|
|
27
|
+
*
|
|
28
|
+
* It holds the `DepositsFacade` and NOTHING the facade already owns: no
|
|
29
|
+
* `UserLending`, no chain id, no signer. Two paths to one behaviour is how the
|
|
30
|
+
* KYC params a flow built came to differ from the ones `kasu.deposits`
|
|
31
|
+
* built — the same class of drift the flows themselves exist to end.
|
|
32
|
+
*/
|
|
33
|
+
export class FlowsFacade {
|
|
34
|
+
constructor(_deposits,
|
|
35
|
+
/**
|
|
36
|
+
* The chain's stable token, bound to whatever the Kasu instance holds.
|
|
37
|
+
* A factory rather than a contract: it is one `new Contract`, and a
|
|
38
|
+
* cached binding would outlive the config it was built from.
|
|
39
|
+
*/
|
|
40
|
+
_erc20,
|
|
41
|
+
/** The read-only flag `Kasu` already computed — never re-derived here. */
|
|
42
|
+
_isReadOnly,
|
|
43
|
+
/**
|
|
44
|
+
* The ERC-20 spender every deposit run approves: this chain's
|
|
45
|
+
* `LendingPoolManager`, which is the only contract the default deposit
|
|
46
|
+
* port calls. Passed to the flow so a consumer never has to hand-wire
|
|
47
|
+
* an address whose only wrong value grants an approval to the wrong
|
|
48
|
+
* contract.
|
|
49
|
+
*/
|
|
50
|
+
_spender) {
|
|
51
|
+
this._deposits = _deposits;
|
|
52
|
+
this._erc20 = _erc20;
|
|
53
|
+
this._isReadOnly = _isReadOnly;
|
|
54
|
+
this._spender = _spender;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* A deposit pipeline. `readAllowance`, `approve`, `deposit` and
|
|
58
|
+
* `buildKycParams` default to the SDK's own implementations; pass any of
|
|
59
|
+
* them to override (kasu-ui approves through its sponsored-gas path, for
|
|
60
|
+
* one).
|
|
61
|
+
*
|
|
62
|
+
* Each default is applied per key with `??`, not by spreading `ports` over
|
|
63
|
+
* them: `{ ...defaults, ...ports }` lets an EXPLICITLY undefined value
|
|
64
|
+
* delete the default it was meant to keep, and
|
|
65
|
+
* `approve: sponsoredGas ? sponsoredApprove : undefined` is exactly how a
|
|
66
|
+
* consumer writes a conditional override.
|
|
67
|
+
*/
|
|
68
|
+
deposit(ports, opts) {
|
|
69
|
+
var _a, _b, _c, _d, _e;
|
|
70
|
+
return new DepositFlow({
|
|
71
|
+
signMessage: ports.signMessage,
|
|
72
|
+
generateContract: ports.generateContract,
|
|
73
|
+
getKycSignature: ports.getKycSignature,
|
|
74
|
+
buildKycParams: (_a = ports.buildKycParams) !== null && _a !== void 0 ? _a : ((userAddress) => this._deposits.buildKycParams(userAddress)),
|
|
75
|
+
readAllowance: (_b = ports.readAllowance) !== null && _b !== void 0 ? _b : ((owner, spender) => this._erc20().allowance(owner, spender)),
|
|
76
|
+
approve: (_c = ports.approve) !== null && _c !== void 0 ? _c : ((spender, amount) => __awaiter(this, void 0, void 0, function* () {
|
|
77
|
+
this._assertWritable();
|
|
78
|
+
// The EXACT amount the flow asked for. Nothing here
|
|
79
|
+
// rounds it up, and nothing here substitutes
|
|
80
|
+
// MaxUint256.
|
|
81
|
+
return yield this._erc20().approve(spender, amount);
|
|
82
|
+
})),
|
|
83
|
+
deposit: (_d = ports.deposit) !== null && _d !== void 0 ? _d : ((params) => this._deposits.deposit(params)),
|
|
84
|
+
now: ports.now,
|
|
85
|
+
}, {
|
|
86
|
+
contractTtlMs: opts === null || opts === void 0 ? void 0 : opts.contractTtlMs,
|
|
87
|
+
// Per key here too, for the same reason the ports are: an
|
|
88
|
+
// explicit `spender: undefined` must not delete the default.
|
|
89
|
+
spender: (_e = opts === null || opts === void 0 ? void 0 : opts.spender) !== null && _e !== void 0 ? _e : this._spender,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* A withdrawal pipeline. Both write ports and `buildKycParams` default to
|
|
94
|
+
* this instance; supplying `getKycSignature` turns the KYC pre-check on.
|
|
95
|
+
* Defaults are applied per key, for the reason `deposit()` gives.
|
|
96
|
+
*/
|
|
97
|
+
withdraw(ports = {}) {
|
|
98
|
+
var _a, _b, _c;
|
|
99
|
+
return new WithdrawFlow({
|
|
100
|
+
buildKycParams: (_a = ports.buildKycParams) !== null && _a !== void 0 ? _a : ((userAddress) => this._deposits.buildKycParams(userAddress)),
|
|
101
|
+
getKycSignature: ports.getKycSignature,
|
|
102
|
+
withdraw: (_b = ports.withdraw) !== null && _b !== void 0 ? _b : ((params) => this._deposits.withdraw({
|
|
103
|
+
poolId: params.poolId,
|
|
104
|
+
trancheId: params.trancheId,
|
|
105
|
+
amount: params.amount,
|
|
106
|
+
})),
|
|
107
|
+
withdrawMax: (_c = ports.withdrawMax) !== null && _c !== void 0 ? _c : ((poolId, trancheId, userAddress) => this._deposits.withdrawMax(poolId, trancheId, userAddress)),
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
_assertWritable() {
|
|
111
|
+
if (this._isReadOnly) {
|
|
112
|
+
throw new Error(READ_ONLY_MESSAGE);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=flows.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flows.js","sourceRoot":"","sources":["../../src/facade/flows.ts"],"names":[],"mappings":"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"}
|
package/dist/facade/index.d.ts
CHANGED
|
@@ -2,6 +2,9 @@ export { Kasu } from './kasu';
|
|
|
2
2
|
export { StrategiesFacade } from './strategies';
|
|
3
3
|
export { DepositsFacade } from './deposits';
|
|
4
4
|
export { PortfolioFacade } from './user-portfolio';
|
|
5
|
+
export { FlowsFacade } from './flows';
|
|
6
|
+
export type { DepositFlowPortOverrides, WithdrawFlowPortOverrides, } from './flows';
|
|
7
|
+
export { READ_ONLY_MESSAGE } from './read-only';
|
|
5
8
|
export { CHAIN_CONFIGS } from './chain-configs';
|
|
6
9
|
export { fetchUnusedPoolIds } from './unused-pool-ids';
|
|
7
10
|
export type { SupportedChain, ChainConfigEntry, StableAsset, KasuOptions, Strategy, StrategyTranche, FixedTermOption, DepositParams, WithdrawParams, DepositLimits, KycParams, UserPositions, PlatformStats, } from './types';
|
package/dist/facade/index.js
CHANGED
|
@@ -4,6 +4,9 @@ export { Kasu } from './kasu';
|
|
|
4
4
|
export { StrategiesFacade } from './strategies';
|
|
5
5
|
export { DepositsFacade } from './deposits';
|
|
6
6
|
export { PortfolioFacade } from './user-portfolio';
|
|
7
|
+
export { FlowsFacade } from './flows';
|
|
8
|
+
// The one refusal every write path shares
|
|
9
|
+
export { READ_ONLY_MESSAGE } from './read-only';
|
|
7
10
|
// Chain configurations
|
|
8
11
|
export { CHAIN_CONFIGS } from './chain-configs';
|
|
9
12
|
// Directus-backed helpers (I/O — not part of `domain/`)
|
package/dist/facade/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/facade/index.ts"],"names":[],"mappings":"AAAA,mBAAmB;AACnB,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,gDAAgD;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/facade/index.ts"],"names":[],"mappings":"AAAA,mBAAmB;AACnB,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,gDAAgD;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAMtC,0CAA0C;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,uBAAuB;AACvB,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,wDAAwD;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/facade/kasu.d.ts
CHANGED
|
@@ -2,14 +2,16 @@ import { Provider } from '@ethersproject/providers';
|
|
|
2
2
|
import { Signer } from 'ethers';
|
|
3
3
|
import { KasuSdk } from '../kasu-sdk';
|
|
4
4
|
import { DepositsFacade } from './deposits';
|
|
5
|
+
import { FlowsFacade } from './flows';
|
|
5
6
|
import { StrategiesFacade } from './strategies';
|
|
6
7
|
import { ChainConfigEntry, KasuOptions } from './types';
|
|
7
8
|
import { PortfolioFacade } from './user-portfolio';
|
|
8
9
|
/**
|
|
9
10
|
* High-level entry point for external integrators.
|
|
10
11
|
*
|
|
11
|
-
* Provides
|
|
12
|
-
* exposes the underlying `KasuSdk` services via `.services` for
|
|
12
|
+
* Provides four domain facades — `strategies`, `deposits`, `portfolio`,
|
|
13
|
+
* `flows` — and exposes the underlying `KasuSdk` services via `.services` for
|
|
14
|
+
* power-users.
|
|
13
15
|
*
|
|
14
16
|
* ```ts
|
|
15
17
|
* import { Kasu } from '@kasufinance/kasu-sdk';
|
|
@@ -33,6 +35,8 @@ export declare class Kasu {
|
|
|
33
35
|
readonly deposits: DepositsFacade;
|
|
34
36
|
/** User positions, yields, transaction history. */
|
|
35
37
|
readonly portfolio: PortfolioFacade;
|
|
38
|
+
/** Headless deposit / withdraw state machines. */
|
|
39
|
+
readonly flows: FlowsFacade;
|
|
36
40
|
private readonly _sdk;
|
|
37
41
|
private readonly _chainConfig;
|
|
38
42
|
private readonly _signerOrProvider;
|
package/dist/facade/kasu.js
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import { providers, Signer } from 'ethers';
|
|
2
|
+
import { IERC20MetadataAbi__factory } from '../contracts';
|
|
2
3
|
import { KasuSdk } from '../kasu-sdk';
|
|
3
4
|
import { SdkConfig } from '../sdk-config';
|
|
4
5
|
import { CHAIN_CONFIGS } from './chain-configs';
|
|
5
6
|
import { DepositsFacade } from './deposits';
|
|
7
|
+
import { FlowsFacade } from './flows';
|
|
6
8
|
import { StrategiesFacade } from './strategies';
|
|
7
9
|
import { PortfolioFacade } from './user-portfolio';
|
|
8
10
|
/**
|
|
9
11
|
* High-level entry point for external integrators.
|
|
10
12
|
*
|
|
11
|
-
* Provides
|
|
12
|
-
* exposes the underlying `KasuSdk` services via `.services` for
|
|
13
|
+
* Provides four domain facades — `strategies`, `deposits`, `portfolio`,
|
|
14
|
+
* `flows` — and exposes the underlying `KasuSdk` services via `.services` for
|
|
15
|
+
* power-users.
|
|
13
16
|
*
|
|
14
17
|
* ```ts
|
|
15
18
|
* import { Kasu } from '@kasufinance/kasu-sdk';
|
|
@@ -33,8 +36,13 @@ export class Kasu {
|
|
|
33
36
|
this._signerOrProvider = signerOrProvider;
|
|
34
37
|
this._configOverrides = configOverrides;
|
|
35
38
|
this.strategies = new StrategiesFacade(sdk.DataService, sdk.UserLending);
|
|
36
|
-
|
|
39
|
+
// Derived ONCE and handed to every facade that needs it. Each of them
|
|
40
|
+
// re-deriving `Signer.isSigner` is how two facades come to disagree
|
|
41
|
+
// about whether the same instance can write.
|
|
42
|
+
const isReadOnly = !Signer.isSigner(signerOrProvider);
|
|
43
|
+
this.deposits = new DepositsFacade(sdk.UserLending, chainConfig.chainId.toString(), isReadOnly);
|
|
37
44
|
this.portfolio = new PortfolioFacade(sdk.DataService, sdk.UserLending, sdk.Portfolio);
|
|
45
|
+
this.flows = new FlowsFacade(this.deposits, () => erc20Of(chainConfig, signerOrProvider), isReadOnly, chainConfig.contracts.LendingPoolManager);
|
|
38
46
|
}
|
|
39
47
|
/**
|
|
40
48
|
* Create a Kasu instance with built-in chain config.
|
|
@@ -166,6 +174,23 @@ function rpcUrlsOf(chainConfig) {
|
|
|
166
174
|
var _a;
|
|
167
175
|
return (_a = chainConfig.rpcUrls) !== null && _a !== void 0 ? _a : [];
|
|
168
176
|
}
|
|
177
|
+
/**
|
|
178
|
+
* The chain's stable token, bound to whatever this instance holds.
|
|
179
|
+
*
|
|
180
|
+
* Built per call rather than cached: it is one `new Contract`, and a cached
|
|
181
|
+
* binding would outlive the signer a `connect()` replaced. A config with no
|
|
182
|
+
* `stableAsset` (a hand-written entry from before 2.5.0) throws here rather
|
|
183
|
+
* than inside ethers, naming the two ports that make the flow work without
|
|
184
|
+
* one.
|
|
185
|
+
*/
|
|
186
|
+
function erc20Of(chainConfig, signerOrProvider) {
|
|
187
|
+
var _a;
|
|
188
|
+
const address = (_a = stableAssetOf(chainConfig)) === null || _a === void 0 ? void 0 : _a.address;
|
|
189
|
+
if (!address) {
|
|
190
|
+
throw new Error('Kasu: this chain config has no stableAsset; pass readAllowance and approve ports explicitly');
|
|
191
|
+
}
|
|
192
|
+
return IERC20MetadataAbi__factory.connect(address, signerOrProvider);
|
|
193
|
+
}
|
|
169
194
|
/**
|
|
170
195
|
* The read-only provider used when the caller passes no `signerOrProvider`.
|
|
171
196
|
*
|
package/dist/facade/kasu.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kasu.js","sourceRoot":"","sources":["../../src/facade/kasu.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE3C,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,SAAS,EAAoB,MAAM,eAAe,CAAC;AAE5D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAOhD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD
|
|
1
|
+
{"version":3,"file":"kasu.js","sourceRoot":"","sources":["../../src/facade/kasu.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The refusal every write path shares when the instance holds a Provider
|
|
3
|
+
* rather than a Signer.
|
|
4
|
+
*
|
|
5
|
+
* One constant, because the message's job is to name the fix — `kasu.connect`
|
|
6
|
+
* — and three near-identical wordings across the facades would be three
|
|
7
|
+
* different pieces of advice for one problem. ethers' own
|
|
8
|
+
* "sending a transaction requires a signer" arrives several frames deeper,
|
|
9
|
+
* after the params have been encoded, and says nothing about how to get a
|
|
10
|
+
* signer onto THIS object.
|
|
11
|
+
*/
|
|
12
|
+
export declare const READ_ONLY_MESSAGE = "Kasu: this instance is read-only; call kasu.connect(signer) first";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The refusal every write path shares when the instance holds a Provider
|
|
3
|
+
* rather than a Signer.
|
|
4
|
+
*
|
|
5
|
+
* One constant, because the message's job is to name the fix — `kasu.connect`
|
|
6
|
+
* — and three near-identical wordings across the facades would be three
|
|
7
|
+
* different pieces of advice for one problem. ethers' own
|
|
8
|
+
* "sending a transaction requires a signer" arrives several frames deeper,
|
|
9
|
+
* after the params have been encoded, and says nothing about how to get a
|
|
10
|
+
* signer onto THIS object.
|
|
11
|
+
*/
|
|
12
|
+
export const READ_ONLY_MESSAGE = 'Kasu: this instance is read-only; call kasu.connect(signer) first';
|
|
13
|
+
//# sourceMappingURL=read-only.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-only.js","sourceRoot":"","sources":["../../src/facade/read-only.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAC1B,mEAAmE,CAAC"}
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import { BigNumber } from 'ethers';
|
|
2
|
+
import { GenerateContractResponse } from '../domain/loan-contract';
|
|
3
|
+
import { DepositParams, KycParams } from '../facade/types';
|
|
4
|
+
import { Flow } from './flow';
|
|
5
|
+
import { WaitableTransaction } from './observable';
|
|
6
|
+
/**
|
|
7
|
+
* The KYC-gated deposit pipeline, headless.
|
|
8
|
+
*
|
|
9
|
+
* This is the state machine kasu-ui and kasu-mobile each hand-wrote and then
|
|
10
|
+
* had to keep in step by hand: sign an auth message, generate the loan
|
|
11
|
+
* agreement, park while the lender reads it, sign it, approve the EXACT amount,
|
|
12
|
+
* fetch the KYC signature, submit, wait. Two implementations of one money path
|
|
13
|
+
* is one too many, so it lives here once and each application drives it from
|
|
14
|
+
* its own UI.
|
|
15
|
+
*
|
|
16
|
+
* **No React, no copy, no I/O of its own.** Every side effect is an injected
|
|
17
|
+
* port and every observable state is a code — `{ step: 'approve', reason:
|
|
18
|
+
* 'cancelled' }`, never "USDC approval was cancelled in your wallet". The
|
|
19
|
+
* applications keep their own `DEPOSIT_STEP_ERRORS` tables and map the codes to
|
|
20
|
+
* their words, in their design system and their language. Nothing in this file
|
|
21
|
+
* may be shown to a lender.
|
|
22
|
+
*
|
|
23
|
+
* ## Order, and why each step is where it is
|
|
24
|
+
*
|
|
25
|
+
* 1. **Allowance pre-check** — before anything is signed, because it decides
|
|
26
|
+
* `approvalRequired`, which decides `stepTotal`. A badge that said "3 of 4"
|
|
27
|
+
* and then silently became "3 of 3" would be describing a pipeline the
|
|
28
|
+
* lender is not in. A failed read assumes an approve IS needed: the safe
|
|
29
|
+
* default is a redundant approval, never a reverted deposit.
|
|
30
|
+
* 2. **`generating-sign`** — the lender signs the auth message
|
|
31
|
+
* (`buildLoanAgreementSignMessage`, or the legacy builder). kasu-backend
|
|
32
|
+
* reconstructs that string byte-for-byte to verify the signature.
|
|
33
|
+
* 3. **`generating-fetch`** — the agreements service returns the contract.
|
|
34
|
+
* 4. **`awaiting-accept`** — the run PARKS on a promise the consumer settles
|
|
35
|
+
* with `acceptContract()` or `declineContract()`. This is the only point at
|
|
36
|
+
* which a lender is committing to anything.
|
|
37
|
+
* 5. **`accepting-sign`** — the acceptance signature, which becomes the
|
|
38
|
+
* on-chain `depositData` via `encodeDepositData`.
|
|
39
|
+
* 6. **The 5-minute TTL guard** — checked AFTER the accept, because that is
|
|
40
|
+
* where the idling happens. An expired agreement is refused here rather than
|
|
41
|
+
* broadcast as a transaction that cannot succeed.
|
|
42
|
+
* 7. **`approve`** — the EXACT amount, never `MaxUint256`. House rule, and it
|
|
43
|
+
* is why the allowance drops to zero after every deposit and why step 1
|
|
44
|
+
* reads it fresh rather than trusting a cache.
|
|
45
|
+
* 8. **`request-sign` / `request-confirm`** — KYC signature, then the deposit,
|
|
46
|
+
* then the receipt.
|
|
47
|
+
*
|
|
48
|
+
* ## Failure codes
|
|
49
|
+
*
|
|
50
|
+
* A wallet rejection (`isUserRejected`) is `'cancelled'` — the lender changed
|
|
51
|
+
* their mind, and telling them something broke would be a lie. Only a WALLET
|
|
52
|
+
* call is ever classified that way: the HTTP ports are always `'failed'`,
|
|
53
|
+
* because a backend that words a refusal "declined" did not involve the
|
|
54
|
+
* lender's wallet. A reverted gas estimate on the request step
|
|
55
|
+
* (`isUnpredictableGas`) is `'insufficient-balance'` — nothing was refused, the
|
|
56
|
+
* transaction simply cannot succeed as composed. Everything else is `'failed'`
|
|
57
|
+
* and carries the original error for the consumer's crash reporter.
|
|
58
|
+
*
|
|
59
|
+
* ```ts
|
|
60
|
+
* const flow = new DepositFlow(ports);
|
|
61
|
+
* const stop = flow.subscribe((s) => render(s));
|
|
62
|
+
* await flow.start({ poolId, trancheId, amount, userAddress, ... });
|
|
63
|
+
* // …the consumer shows `flow.state.contract` and calls:
|
|
64
|
+
* await flow.acceptContract();
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
/**
|
|
68
|
+
* Where the run is. `success`, `declined` and `error` are terminal; everything
|
|
69
|
+
* else is in flight.
|
|
70
|
+
*/
|
|
71
|
+
export type DepositPhase = 'idle' | 'generating-sign' | 'generating-fetch' | 'awaiting-accept' | 'accepting-sign' | 'approve' | 'request-sign' | 'request-confirm' | 'success' | 'declined' | 'error';
|
|
72
|
+
/**
|
|
73
|
+
* The four steps a lender sees as a badge. `approve` drops out of the sequence
|
|
74
|
+
* when the allowance already covers the deposit, which is why `stepIndex` and
|
|
75
|
+
* `stepTotal` are published rather than derived by each consumer.
|
|
76
|
+
*/
|
|
77
|
+
export type DepositStep = 'generate' | 'confirm' | 'approve' | 'request';
|
|
78
|
+
/**
|
|
79
|
+
* Why a run did not reach `success`, as a code plus the step it happened on.
|
|
80
|
+
*
|
|
81
|
+
* The consumer maps this to its own words. `error` carries the underlying
|
|
82
|
+
* throw for a crash reporter — a `cancelled` and a `contract-expired` do not,
|
|
83
|
+
* because neither is a fault worth reporting.
|
|
84
|
+
*/
|
|
85
|
+
export type DepositFailure = {
|
|
86
|
+
step: DepositStep;
|
|
87
|
+
reason: 'cancelled';
|
|
88
|
+
} | {
|
|
89
|
+
step: DepositStep;
|
|
90
|
+
reason: 'failed';
|
|
91
|
+
error: unknown;
|
|
92
|
+
} | {
|
|
93
|
+
step: 'request';
|
|
94
|
+
reason: 'insufficient-balance';
|
|
95
|
+
error: unknown;
|
|
96
|
+
} | {
|
|
97
|
+
step: 'request';
|
|
98
|
+
reason: 'contract-expired';
|
|
99
|
+
};
|
|
100
|
+
export type { WaitableTransaction };
|
|
101
|
+
/** What the KYC signing service hands back. */
|
|
102
|
+
export interface KycSignature {
|
|
103
|
+
signature: string;
|
|
104
|
+
blockExpiration: number | string;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* The `/contract/generate` body, assembled by the flow and posted by the
|
|
108
|
+
* consumer's own port — through its server-side proxy (kasu-ui) or straight to
|
|
109
|
+
* the agreements service (kasu-mobile). The SDK never makes the call itself and
|
|
110
|
+
* never learns the URL or the key.
|
|
111
|
+
*/
|
|
112
|
+
export interface GenerateContractRequest {
|
|
113
|
+
/**
|
|
114
|
+
* The lender's address, LOWERCASED. The legacy message embeds this casing
|
|
115
|
+
* and kasu-backend rebuilds the string from the body, so the two must
|
|
116
|
+
* agree.
|
|
117
|
+
*/
|
|
118
|
+
address: string;
|
|
119
|
+
/** Signature over `signedMessage`. */
|
|
120
|
+
signature: string;
|
|
121
|
+
/** ms-epoch. The same value `signedMessage` states — do not re-clock it. */
|
|
122
|
+
timestamp: number;
|
|
123
|
+
/**
|
|
124
|
+
* The exact text that was signed. Sent so a consumer can log or assert on
|
|
125
|
+
* it; the backend rebuilds it from the other fields rather than trusting
|
|
126
|
+
* this one.
|
|
127
|
+
*/
|
|
128
|
+
signedMessage: string;
|
|
129
|
+
poolId: string;
|
|
130
|
+
trancheId: string;
|
|
131
|
+
/** `'0'` for a variable-rate deposit. */
|
|
132
|
+
fixedTermConfigId: string;
|
|
133
|
+
/**
|
|
134
|
+
* The deposit in DISPLAY units, forwarded verbatim from
|
|
135
|
+
* `DepositFlowInput.depositAmount`. kasu-backend cross-checks it against
|
|
136
|
+
* the leading number of `amountLabel`.
|
|
137
|
+
*/
|
|
138
|
+
depositAmount?: number;
|
|
139
|
+
/** The four human-readable fields, present only on the new format. */
|
|
140
|
+
strategyName?: string;
|
|
141
|
+
region?: string;
|
|
142
|
+
optionName?: string;
|
|
143
|
+
amountLabel?: string;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* The human-readable `/contract/generate` format (BD deck slide 19): the lender
|
|
147
|
+
* signs a statement naming the strategy, region, option and amount.
|
|
148
|
+
*
|
|
149
|
+
* `amountLabel` must be derived from the same value as `depositAmount` — the
|
|
150
|
+
* backend refuses a message that states an amount other than the one being
|
|
151
|
+
* executed. The SDK does not format it, because formatting is the
|
|
152
|
+
* application's (and its locale's) business.
|
|
153
|
+
*/
|
|
154
|
+
export interface LoanAgreementRequest {
|
|
155
|
+
format: 'loan-agreement';
|
|
156
|
+
strategyName: string;
|
|
157
|
+
region: string;
|
|
158
|
+
optionName: string;
|
|
159
|
+
amountLabel: string;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* The legacy `I request contract content for {address} at {timestamp}.`
|
|
163
|
+
* format, which kasu-backend still accepts and `/contract/resolve` has no
|
|
164
|
+
* alternative to.
|
|
165
|
+
*/
|
|
166
|
+
export interface LegacyContractRequest {
|
|
167
|
+
format: 'legacy';
|
|
168
|
+
}
|
|
169
|
+
export type ContractMessageRequest = LoanAgreementRequest | LegacyContractRequest;
|
|
170
|
+
/**
|
|
171
|
+
* Every side effect the pipeline needs, injected.
|
|
172
|
+
*
|
|
173
|
+
* `kasu.flows.deposit()` fills `readAllowance`, `approve`, `deposit` and
|
|
174
|
+
* `buildKycParams` from the SDK's own signer-bound implementations; the three
|
|
175
|
+
* that reach the consumer's own backend or wallet have no sensible default and
|
|
176
|
+
* are always supplied by the application.
|
|
177
|
+
*/
|
|
178
|
+
export interface DepositPorts {
|
|
179
|
+
/** EIP-191 personal sign. Rejects when the lender refuses. */
|
|
180
|
+
signMessage(message: string): Promise<string>;
|
|
181
|
+
/** POST the generate request; resolve with the agreements service's reply. */
|
|
182
|
+
generateContract(req: GenerateContractRequest): Promise<GenerateContractResponse>;
|
|
183
|
+
/** Build the Nexera KYC params. Defaults to `kasu.deposits.buildKycParams`. */
|
|
184
|
+
buildKycParams(userAddress: `0x${string}`): KycParams | Promise<KycParams>;
|
|
185
|
+
/** Exchange those params for a signature at the consumer's own backend. */
|
|
186
|
+
getKycSignature(params: KycParams): Promise<KycSignature>;
|
|
187
|
+
/** ERC-20 `allowance(owner, spender)`, in base units. */
|
|
188
|
+
readAllowance(owner: string, spender: string): Promise<BigNumber>;
|
|
189
|
+
/** ERC-20 `approve(spender, amount)`. The flow only ever passes the EXACT amount. */
|
|
190
|
+
approve(spender: string, amount: BigNumber): Promise<WaitableTransaction>;
|
|
191
|
+
/** `requestDepositWithKyc`. Defaults to `kasu.deposits.deposit`. */
|
|
192
|
+
deposit(params: DepositParams): Promise<WaitableTransaction>;
|
|
193
|
+
/** ms-epoch clock. Defaults to `Date.now`; injected so the TTL is testable. */
|
|
194
|
+
now?(): number;
|
|
195
|
+
}
|
|
196
|
+
/** Construction options. `kasu.flows.deposit()` fills `spender` in. */
|
|
197
|
+
export interface DepositFlowOptions {
|
|
198
|
+
/** Agreement validity window; defaults to `CONTRACT_TTL_MS`. */
|
|
199
|
+
contractTtlMs?: number;
|
|
200
|
+
/**
|
|
201
|
+
* The ERC-20 spender every run approves and deposits through, when the
|
|
202
|
+
* input does not name one. `kasu.flows.deposit()` passes this chain's
|
|
203
|
+
* `contracts.LendingPoolManager`, which is the only contract the default
|
|
204
|
+
* deposit port calls.
|
|
205
|
+
*/
|
|
206
|
+
spender?: string;
|
|
207
|
+
}
|
|
208
|
+
export interface DepositFlowInput {
|
|
209
|
+
poolId: string;
|
|
210
|
+
trancheId: string;
|
|
211
|
+
/** The deposit in BASE units (6dp for USDC and AUDD). */
|
|
212
|
+
amount: BigNumber;
|
|
213
|
+
/** `'0'` for a variable-rate deposit. */
|
|
214
|
+
fixedTermConfigId: string;
|
|
215
|
+
userAddress: `0x${string}`;
|
|
216
|
+
/**
|
|
217
|
+
* The ERC-20 spender, when it is NOT this chain's `LendingPoolManager`.
|
|
218
|
+
*
|
|
219
|
+
* Leave it out: `kasu.flows.deposit()` defaults it from the chain config,
|
|
220
|
+
* and the default deposit port calls no other contract. It exists for a
|
|
221
|
+
* consumer that replaced the `deposit` port with one that spends
|
|
222
|
+
* somewhere else — a wrong spender is an approval granted to the wrong
|
|
223
|
+
* contract and then a revert diagnosed as `insufficient-balance`.
|
|
224
|
+
*/
|
|
225
|
+
spender?: string;
|
|
226
|
+
/** Which signed-message format to use, and its fields. */
|
|
227
|
+
contractMessage: ContractMessageRequest;
|
|
228
|
+
/**
|
|
229
|
+
* The deposit in DISPLAY units, for the generate request only.
|
|
230
|
+
*
|
|
231
|
+
* NOT derived from `amount`: turning base units back into a display number
|
|
232
|
+
* is formatting, and formatting is the application's job — it is also the
|
|
233
|
+
* application that produced `amountLabel`, and kasu-backend refuses the two
|
|
234
|
+
* if they disagree. Pass the same value both were built from.
|
|
235
|
+
*/
|
|
236
|
+
depositAmount?: number;
|
|
237
|
+
}
|
|
238
|
+
export interface DepositState {
|
|
239
|
+
phase: DepositPhase;
|
|
240
|
+
/** The step `phase` belongs to; `null` only while idle. */
|
|
241
|
+
step: DepositStep | null;
|
|
242
|
+
/** 1-based badge position of `step`; `0` while idle. */
|
|
243
|
+
stepIndex: number;
|
|
244
|
+
/** `4`, or `3` when the allowance already covers the deposit. */
|
|
245
|
+
stepTotal: number;
|
|
246
|
+
/** Whether the approve step is in scope for this run. */
|
|
247
|
+
approvalRequired: boolean;
|
|
248
|
+
/** The generated agreement, from `generating-fetch` onwards. */
|
|
249
|
+
contract: GenerateContractResponse | null;
|
|
250
|
+
/** Set with `phase: 'error'`, cleared by `reset()`. */
|
|
251
|
+
failure: DepositFailure | null;
|
|
252
|
+
}
|
|
253
|
+
/** Generated agreements are valid for five minutes upstream. */
|
|
254
|
+
export declare const CONTRACT_TTL_MS: number;
|
|
255
|
+
/** What a run without a spender, from either source, fails with. */
|
|
256
|
+
export declare const NO_SPENDER_MESSAGE = "DepositFlow: no ERC-20 spender; build the flow with kasu.flows.deposit() or pass `spender` on the input";
|
|
257
|
+
export declare class DepositFlow extends Flow<DepositState, DepositFlowInput> {
|
|
258
|
+
private readonly _ports;
|
|
259
|
+
private readonly _ttlMs;
|
|
260
|
+
private readonly _defaultSpender;
|
|
261
|
+
private readonly _now;
|
|
262
|
+
/**
|
|
263
|
+
* The accept handshake. The run parks on this promise; `acceptContract`,
|
|
264
|
+
* `declineContract` and `reset` each settle it with an `AcceptOutcome`.
|
|
265
|
+
* Cleared the moment it settles so a stale resolver from an abandoned run
|
|
266
|
+
* can never leak into the next one.
|
|
267
|
+
*/
|
|
268
|
+
private _accept;
|
|
269
|
+
/**
|
|
270
|
+
* The run token that is between `acceptContract()` and the wallet
|
|
271
|
+
* settling, or `null`.
|
|
272
|
+
*
|
|
273
|
+
* A token rather than a boolean, because the flag has to belong to the RUN
|
|
274
|
+
* that set it: after `reset()` out of a wallet prompt that never answers,
|
|
275
|
+
* the abandoned run's `finally` may not arrive for minutes, and a boolean
|
|
276
|
+
* left standing refuses both Accept and Decline on every run after it.
|
|
277
|
+
* A stale token simply is not the current generation.
|
|
278
|
+
*/
|
|
279
|
+
private _acceptingFor;
|
|
280
|
+
constructor(_ports: DepositPorts, opts?: DepositFlowOptions);
|
|
281
|
+
/**
|
|
282
|
+
* Sign the agreement and resume the parked run. A no-op when nothing is
|
|
283
|
+
* parked, so a double tap cannot sign twice.
|
|
284
|
+
*/
|
|
285
|
+
acceptContract(): Promise<void>;
|
|
286
|
+
/**
|
|
287
|
+
* Back out of the agreement. The run ends on `declined` — a legitimate
|
|
288
|
+
* choice, not a failure, and `state.failure` stays null.
|
|
289
|
+
*
|
|
290
|
+
* Ignored once `acceptContract()` has opened the wallet: an agreement in
|
|
291
|
+
* the middle of being signed cannot also be refused. `reset()` is the way
|
|
292
|
+
* out of a prompt that never answers.
|
|
293
|
+
*/
|
|
294
|
+
declineContract(): void;
|
|
295
|
+
/** True only while THIS generation is waiting on the acceptance signature. */
|
|
296
|
+
private _isAccepting;
|
|
297
|
+
/** `reset()`: unpark the abandoned run and drop its handshake. */
|
|
298
|
+
protected _onAbandon(): void;
|
|
299
|
+
protected _run(input: DepositFlowInput, token: number): Promise<void>;
|
|
300
|
+
private _fail;
|
|
301
|
+
}
|