@gearbox-protocol/sdk 16.4.0-next.1 → 16.4.0-next.11
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/dist/cjs/dev/index.js +3 -2
- package/dist/cjs/dev/kycUtils.js +18 -35
- package/dist/cjs/dev/midasUtils.js +80 -16
- package/dist/cjs/dev/securitizeUtils.js +14 -10
- package/dist/cjs/dev/withdrawalUtils.js +3 -6
- package/dist/cjs/model/errors/index.js +1 -0
- package/dist/cjs/model/errors/operation-errors.js +9 -0
- package/dist/cjs/model/index.js +1 -0
- package/dist/cjs/onchain/accounts/intents/borrow.js +139 -0
- package/dist/cjs/onchain/accounts/intents/{collateral-money.js → collateral-valuation.js} +7 -7
- package/dist/cjs/onchain/accounts/intents/index.js +86 -2
- package/dist/cjs/onchain/accounts/intents/leverage-band.js +2 -12
- package/dist/cjs/onchain/accounts/intents/maxBorrow.js +89 -0
- package/dist/cjs/onchain/accounts/intents/maxWithdrawCollateral.js +14 -14
- package/dist/cjs/onchain/accounts/intents/open-strategy.js +6 -45
- package/dist/cjs/onchain/accounts/intents/realize.js +44 -0
- package/dist/cjs/onchain/accounts/intents/testing/sdk-mock.js +1 -0
- package/dist/cjs/onchain/accounts/intents/utils/common.js +19 -0
- package/dist/cjs/onchain/accounts/intents/utils/credit-account-slice.js +21 -0
- package/dist/cjs/onchain/accounts/intents/utils/index.js +2 -0
- package/dist/cjs/onchain/accounts/intents/utils/price-impact.js +3 -3
- package/dist/cjs/onchain/accounts/intents/withdraw-limits.js +8 -8
- package/dist/cjs/onchain/accounts/utils/midasUtils.js +7 -1
- package/dist/cjs/onchain/core/createAddressProvider.js +2 -5
- package/dist/cjs/onchain/index.js +4 -0
- package/dist/cjs/onchain/market/adapters/contracts/MidasGatewayAdapterContract.js +11 -3
- package/dist/cjs/onchain/positions/calcHealthFactor.js +3 -3
- package/dist/cjs/onchain/preview/index.js +2 -0
- package/dist/cjs/onchain/preview/preview/index.js +2 -0
- package/dist/cjs/onchain/preview/preview/midasGreenlistsAccount.js +17 -0
- package/dist/cjs/onchain/preview/preview/previewOpenStrategyPosition.js +5 -2
- package/dist/cjs/onchain/validation/bundles/checkCreditOperation.js +2 -1
- package/dist/cjs/onchain/validation/bundles/checkMidasAccountGreenlist.js +44 -0
- package/dist/cjs/onchain/validation/bundles/checkRWAOpening.js +15 -5
- package/dist/cjs/onchain/validation/bundles/index.js +2 -0
- package/dist/cjs/onchain/validation/index.js +2 -0
- package/dist/cjs/sdk/execute/ExecuteApi.js +65 -5
- package/dist/cjs/sdk/prepare/PrepareApi.js +86 -12
- package/dist/esm/dev/index.js +3 -3
- package/dist/esm/dev/kycUtils.js +17 -33
- package/dist/esm/dev/midasUtils.js +80 -18
- package/dist/esm/dev/securitizeUtils.js +15 -11
- package/dist/esm/dev/withdrawalUtils.js +3 -6
- package/dist/esm/model/errors/index.js +2 -2
- package/dist/esm/model/errors/operation-errors.js +9 -1
- package/dist/esm/model/index.js +2 -2
- package/dist/esm/onchain/accounts/intents/borrow.js +137 -0
- package/dist/esm/onchain/accounts/intents/{collateral-money.js → collateral-valuation.js} +7 -7
- package/dist/esm/onchain/accounts/intents/index.js +86 -2
- package/dist/esm/onchain/accounts/intents/leverage-band.js +2 -12
- package/dist/esm/onchain/accounts/intents/maxBorrow.js +87 -0
- package/dist/esm/onchain/accounts/intents/maxWithdrawCollateral.js +14 -14
- package/dist/esm/onchain/accounts/intents/open-strategy.js +6 -45
- package/dist/esm/onchain/accounts/intents/realize.js +44 -0
- package/dist/esm/onchain/accounts/intents/testing/sdk-mock.js +1 -0
- package/dist/esm/onchain/accounts/intents/utils/common.js +19 -1
- package/dist/esm/onchain/accounts/intents/utils/credit-account-slice.js +21 -1
- package/dist/esm/onchain/accounts/intents/utils/index.js +3 -3
- package/dist/esm/onchain/accounts/intents/utils/price-impact.js +3 -3
- package/dist/esm/onchain/accounts/intents/withdraw-limits.js +8 -8
- package/dist/esm/onchain/accounts/utils/midasUtils.js +8 -2
- package/dist/esm/onchain/core/createAddressProvider.js +2 -5
- package/dist/esm/onchain/index.js +3 -1
- package/dist/esm/onchain/market/adapters/contracts/MidasGatewayAdapterContract.js +11 -3
- package/dist/esm/onchain/positions/calcHealthFactor.js +3 -3
- package/dist/esm/onchain/preview/index.js +2 -1
- package/dist/esm/onchain/preview/preview/index.js +2 -1
- package/dist/esm/onchain/preview/preview/midasGreenlistsAccount.js +16 -0
- package/dist/esm/onchain/preview/preview/previewOpenStrategyPosition.js +5 -2
- package/dist/esm/onchain/validation/bundles/checkCreditOperation.js +2 -1
- package/dist/esm/onchain/validation/bundles/checkMidasAccountGreenlist.js +43 -0
- package/dist/esm/onchain/validation/bundles/checkRWAOpening.js +15 -5
- package/dist/esm/onchain/validation/bundles/index.js +2 -1
- package/dist/esm/onchain/validation/index.js +2 -1
- package/dist/esm/sdk/execute/ExecuteApi.js +65 -5
- package/dist/esm/sdk/prepare/PrepareApi.js +86 -12
- package/dist/types/dev/index.d.ts +3 -3
- package/dist/types/dev/kycUtils.d.ts +1 -5
- package/dist/types/dev/midasUtils.d.ts +15 -4
- package/dist/types/model/errors/index.d.ts +2 -2
- package/dist/types/model/errors/operation-errors.d.ts +14 -1
- package/dist/types/model/index.d.ts +2 -2
- package/dist/types/model/previews.d.ts +17 -2
- package/dist/types/onchain/accounts/index.d.ts +4 -3
- package/dist/types/onchain/accounts/intents/borrow.d.ts +141 -0
- package/dist/types/onchain/accounts/intents/{collateral-money.d.ts → collateral-valuation.d.ts} +8 -8
- package/dist/types/onchain/accounts/intents/index.d.ts +81 -2
- package/dist/types/onchain/accounts/intents/maxBorrow.d.ts +54 -0
- package/dist/types/onchain/accounts/intents/maxWithdrawCollateral.d.ts +3 -3
- package/dist/types/onchain/accounts/intents/open-strategy.d.ts +3 -17
- package/dist/types/onchain/accounts/intents/testing/sdk-mock.d.ts +2 -0
- package/dist/types/onchain/accounts/intents/tests/open-strategy.fixtures.d.ts +2 -2
- package/dist/types/onchain/accounts/intents/types.d.ts +15 -1
- package/dist/types/onchain/accounts/intents/utils/common.d.ts +15 -1
- package/dist/types/onchain/accounts/intents/utils/credit-account-slice.d.ts +14 -1
- package/dist/types/onchain/accounts/intents/utils/index.d.ts +3 -3
- package/dist/types/onchain/accounts/intents/withdraw-limits.d.ts +1 -1
- package/dist/types/onchain/accounts/utils/midasUtils.d.ts +2 -1
- package/dist/types/onchain/index.d.ts +7 -4
- package/dist/types/onchain/market/adapters/contracts/MidasGatewayAdapterContract.d.ts +8 -2
- package/dist/types/onchain/preview/index.d.ts +2 -1
- package/dist/types/onchain/preview/preview/index.d.ts +2 -1
- package/dist/types/onchain/preview/preview/midasGreenlistsAccount.d.ts +13 -0
- package/dist/types/onchain/validation/bundles/checkCreditOperation.d.ts +2 -2
- package/dist/types/onchain/validation/bundles/checkMidasAccountGreenlist.d.ts +22 -0
- package/dist/types/onchain/validation/bundles/checkRWAOpening.d.ts +6 -4
- package/dist/types/onchain/validation/bundles/index.d.ts +3 -2
- package/dist/types/onchain/validation/checks/checkDebtLimits.d.ts +2 -2
- package/dist/types/onchain/validation/index.d.ts +3 -2
- package/dist/types/sdk/execute/index.d.ts +2 -2
- package/dist/types/sdk/execute/types.d.ts +48 -6
- package/dist/types/sdk/index.d.ts +5 -4
- package/dist/types/sdk/prepare/PrepareApi.d.ts +15 -3
- package/dist/types/sdk/prepare/index.d.ts +4 -3
- package/dist/types/sdk/prepare/types.d.ts +176 -49
- package/package.json +1 -1
package/dist/esm/dev/kycUtils.js
CHANGED
|
@@ -4,23 +4,12 @@ import { OnchainSDK } from "../onchain/OnchainSDK.js";
|
|
|
4
4
|
import "../onchain/index.js";
|
|
5
5
|
import { iDSRegistryServiceAbi } from "../abi/rwa/iDSRegistryService.js";
|
|
6
6
|
import { iDSTokenAbi } from "../abi/rwa/iDSToken.js";
|
|
7
|
+
import { collectMidasGateways } from "./midasUtils.js";
|
|
7
8
|
import { midasGatewayAbi } from "./withdrawalAbi.js";
|
|
8
9
|
import { isAddressEqual, parseAbi, parseEther, zeroAddress } from "viem";
|
|
9
10
|
import { privateKeyToAccount } from "viem/accounts";
|
|
10
11
|
//#region src/dev/kycUtils.ts
|
|
11
12
|
/**
|
|
12
|
-
* Writes to a contract, mines a block and waits for the receipt
|
|
13
|
-
*/
|
|
14
|
-
async function writeAndWait(anvil, params) {
|
|
15
|
-
const hash = await anvil.writeContract(params);
|
|
16
|
-
await anvil.mine({ blocks: 1 });
|
|
17
|
-
await anvil.waitForTransactionReceipt({
|
|
18
|
-
hash,
|
|
19
|
-
pollingInterval: 100
|
|
20
|
-
});
|
|
21
|
-
return hash;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
13
|
* Resolves the account that performs the DS registry writes: either the admin
|
|
25
14
|
* private key, or the admin address impersonated on the fork
|
|
26
15
|
*/
|
|
@@ -98,36 +87,39 @@ async function registerSecuritizeInvestor(props) {
|
|
|
98
87
|
const { account, release } = await useSecuritizeAdmin(props);
|
|
99
88
|
try {
|
|
100
89
|
if (!investorExists) {
|
|
101
|
-
await
|
|
90
|
+
await anvil.writeContractSync({
|
|
102
91
|
account,
|
|
103
92
|
chain: anvil.chain,
|
|
104
93
|
address: registryService,
|
|
105
94
|
abi: iDSRegistryServiceAbi,
|
|
106
95
|
functionName: "registerInvestor",
|
|
107
|
-
args: [investorId, investorId]
|
|
96
|
+
args: [investorId, investorId],
|
|
97
|
+
throwOnReceiptRevert: true
|
|
108
98
|
});
|
|
109
99
|
logger?.debug(`Registered investor "${investorId}"`);
|
|
110
100
|
}
|
|
111
|
-
await
|
|
101
|
+
await anvil.writeContractSync({
|
|
112
102
|
account,
|
|
113
103
|
chain: anvil.chain,
|
|
114
104
|
address: registryService,
|
|
115
105
|
abi: iDSRegistryServiceAbi,
|
|
116
106
|
functionName: "addWallet",
|
|
117
|
-
args: [investor, investorId]
|
|
107
|
+
args: [investor, investorId],
|
|
108
|
+
throwOnReceiptRevert: true
|
|
118
109
|
});
|
|
119
110
|
logger?.debug(`Added wallet ${investor} for investor "${investorId}"`);
|
|
120
111
|
try {
|
|
121
|
-
await
|
|
112
|
+
await anvil.writeContractSync({
|
|
122
113
|
account,
|
|
123
114
|
chain: anvil.chain,
|
|
124
115
|
address: registryService,
|
|
125
116
|
abi: iDSRegistryServiceAbi,
|
|
126
117
|
functionName: "setCountry",
|
|
127
|
-
args: [investorId, "US"]
|
|
118
|
+
args: [investorId, "US"],
|
|
119
|
+
throwOnReceiptRevert: true
|
|
128
120
|
});
|
|
129
121
|
logger?.debug(`Set country for investor "${investorId}" to "US"`);
|
|
130
|
-
await
|
|
122
|
+
await anvil.writeContractSync({
|
|
131
123
|
account,
|
|
132
124
|
chain: anvil.chain,
|
|
133
125
|
address: registryService,
|
|
@@ -139,7 +131,8 @@ async function registerSecuritizeInvestor(props) {
|
|
|
139
131
|
BigInt(APPROVED),
|
|
140
132
|
MAX_UINT256,
|
|
141
133
|
"fake proof"
|
|
142
|
-
]
|
|
134
|
+
],
|
|
135
|
+
throwOnReceiptRevert: true
|
|
143
136
|
});
|
|
144
137
|
logger?.debug(`Set attributes for investor "${investorId}"`);
|
|
145
138
|
} catch (e) {
|
|
@@ -241,13 +234,14 @@ async function greenlistMidasGateway(props) {
|
|
|
241
234
|
logger?.debug(`midas: ${account} already has role ${role}`);
|
|
242
235
|
continue;
|
|
243
236
|
}
|
|
244
|
-
await
|
|
237
|
+
await anvil.writeContractSync({
|
|
245
238
|
account: admin,
|
|
246
239
|
chain: anvil.chain,
|
|
247
240
|
address: accessControl,
|
|
248
241
|
abi: iMidasAccessControlAbi,
|
|
249
242
|
functionName: "grantRole",
|
|
250
|
-
args: [role, account]
|
|
243
|
+
args: [role, account],
|
|
244
|
+
throwOnReceiptRevert: true
|
|
251
245
|
});
|
|
252
246
|
logger?.debug(`midas: granted role ${role} to ${account}`);
|
|
253
247
|
}
|
|
@@ -294,16 +288,6 @@ async function findMidasGateway(props) {
|
|
|
294
288
|
return candidates[index];
|
|
295
289
|
}
|
|
296
290
|
/**
|
|
297
|
-
* Collects the target contracts of all Midas gateway adapters of the loaded
|
|
298
|
-
* credit managers, same as the foundry tests do with
|
|
299
|
-
* `ICreditConfiguratorV3.allowedAdapters`
|
|
300
|
-
*/
|
|
301
|
-
function collectMidasGateways(sdk) {
|
|
302
|
-
const gateways = new AddressSet();
|
|
303
|
-
for (const cm of sdk.marketRegister.creditManagers) for (const adapter of cm.creditManager.adapters.values()) if (adapter.contractType === "ADAPTER::MIDAS_GATEWAY") gateways.add(adapter.targetContract);
|
|
304
|
-
return gateways.asArray();
|
|
305
|
-
}
|
|
306
|
-
/**
|
|
307
291
|
* Registers a wallet as an investor (fake KYC) in every Securitize DSToken and
|
|
308
292
|
* every Midas gateway of the markets loaded by `sdk`.
|
|
309
293
|
*
|
|
@@ -361,4 +345,4 @@ async function registerRWAInvestor(props) {
|
|
|
361
345
|
};
|
|
362
346
|
}
|
|
363
347
|
//#endregion
|
|
364
|
-
export { greenlistMidasGateway, registerMidasInvestor, registerRWAInvestor, registerSecuritizeInvestor
|
|
348
|
+
export { greenlistMidasGateway, registerMidasInvestor, registerRWAInvestor, registerSecuritizeInvestor };
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { AddressSet } from "../onchain/utils/AddressSet.js";
|
|
2
|
+
import { MidasGatewayAdapterContract } from "../onchain/market/adapters/contracts/MidasGatewayAdapterContract.js";
|
|
3
|
+
import "../onchain/index.js";
|
|
4
|
+
import { parseAbi, parseEther, toFunctionSelector } from "viem";
|
|
3
5
|
//#region src/dev/midasUtils.ts
|
|
4
6
|
/**
|
|
5
7
|
* Midas vaults inherit their own `Pausable`, whose global pause is guarded by
|
|
@@ -9,14 +11,24 @@ const iMidasPausableVaultAbi = parseAbi([
|
|
|
9
11
|
"function paused() external view returns (bool)",
|
|
10
12
|
"function pause() external",
|
|
11
13
|
"function unpause() external",
|
|
14
|
+
"function fnPaused(bytes4 fn) external view returns (bool)",
|
|
15
|
+
"function pauseFn(bytes4 fn) external",
|
|
16
|
+
"function unpauseFn(bytes4 fn) external",
|
|
12
17
|
"function pauseAdminRole() external view returns (bytes32)",
|
|
13
18
|
"function accessControl() external view returns (address)"
|
|
14
19
|
]);
|
|
15
20
|
const iMidasAccessControlAbi = parseAbi(["function hasRole(bytes32 role, address account) external view returns (bool)", "function grantRole(bytes32 role, address account) external"]);
|
|
16
21
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
22
|
+
* Selector for `DepositVault.depositInstant(address,uint256,uint256,bytes32)`,
|
|
23
|
+
* the 4-arg mint Gearbox adapters encode. Distinct from the custom-recipient
|
|
24
|
+
* overload.
|
|
25
|
+
*/
|
|
26
|
+
const DEPOSIT_INSTANT_SELECTOR = toFunctionSelector("depositInstant(address,uint256,uint256,bytes32)");
|
|
27
|
+
/**
|
|
28
|
+
* Unpauses a Midas issuance vault on an anvil fork so that `depositInstant`
|
|
29
|
+
* stops reverting with `Pausable: paused` (global) or `Pausable: fn paused`
|
|
30
|
+
* (per-selector), and returns a callback that restores the original pause
|
|
31
|
+
* state of each layer that was cleared.
|
|
20
32
|
*
|
|
21
33
|
* Impersonates `admin` and grants it `pauseAdminRole()` when missing, same as
|
|
22
34
|
* `greenlistMidasGateway` does with the greenlist roles. The grant is not
|
|
@@ -24,11 +36,20 @@ const iMidasAccessControlAbi = parseAbi(["function hasRole(bytes32 role, address
|
|
|
24
36
|
*/
|
|
25
37
|
async function unpauseMidasIssuanceVault(props) {
|
|
26
38
|
const { anvil, vault, admin, logger } = props;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
39
|
+
const [paused, depositInstantPaused] = await anvil.multicall({
|
|
40
|
+
allowFailure: false,
|
|
41
|
+
contracts: [{
|
|
42
|
+
address: vault,
|
|
43
|
+
abi: iMidasPausableVaultAbi,
|
|
44
|
+
functionName: "paused"
|
|
45
|
+
}, {
|
|
46
|
+
address: vault,
|
|
47
|
+
abi: iMidasPausableVaultAbi,
|
|
48
|
+
functionName: "fnPaused",
|
|
49
|
+
args: [DEPOSIT_INSTANT_SELECTOR]
|
|
50
|
+
}]
|
|
51
|
+
});
|
|
52
|
+
if (!paused && !depositInstantPaused) {
|
|
32
53
|
logger?.debug(`midas: issuance vault ${vault} is not paused`);
|
|
33
54
|
return async () => {};
|
|
34
55
|
}
|
|
@@ -50,7 +71,7 @@ async function unpauseMidasIssuanceVault(props) {
|
|
|
50
71
|
functionName: "hasRole",
|
|
51
72
|
args: [pauseAdminRole, admin]
|
|
52
73
|
});
|
|
53
|
-
logger?.debug(`midas: unpausing issuance vault ${vault} as ${admin}, access control ${accessControl}, pause admin role ${pauseAdminRole}`);
|
|
74
|
+
logger?.debug(`midas: unpausing issuance vault ${vault} as ${admin}, access control ${accessControl}, pause admin role ${pauseAdminRole}` + (paused ? ", global" : "") + (depositInstantPaused ? ", depositInstant" : ""));
|
|
54
75
|
await anvil.impersonateAccount({ address: admin });
|
|
55
76
|
try {
|
|
56
77
|
await anvil.setBalance({
|
|
@@ -58,22 +79,33 @@ async function unpauseMidasIssuanceVault(props) {
|
|
|
58
79
|
value: parseEther("100")
|
|
59
80
|
});
|
|
60
81
|
if (!isPauseAdmin) {
|
|
61
|
-
await
|
|
82
|
+
await anvil.writeContractSync({
|
|
62
83
|
account: admin,
|
|
63
84
|
chain: anvil.chain,
|
|
64
85
|
address: accessControl,
|
|
65
86
|
abi: iMidasAccessControlAbi,
|
|
66
87
|
functionName: "grantRole",
|
|
67
|
-
args: [pauseAdminRole, admin]
|
|
88
|
+
args: [pauseAdminRole, admin],
|
|
89
|
+
throwOnReceiptRevert: true
|
|
68
90
|
});
|
|
69
91
|
logger?.debug(`midas: granted pause admin role to ${admin}`);
|
|
70
92
|
}
|
|
71
|
-
await
|
|
93
|
+
if (paused) await anvil.writeContractSync({
|
|
94
|
+
account: admin,
|
|
95
|
+
chain: anvil.chain,
|
|
96
|
+
address: vault,
|
|
97
|
+
abi: iMidasPausableVaultAbi,
|
|
98
|
+
functionName: "unpause",
|
|
99
|
+
throwOnReceiptRevert: true
|
|
100
|
+
});
|
|
101
|
+
if (depositInstantPaused) await anvil.writeContractSync({
|
|
72
102
|
account: admin,
|
|
73
103
|
chain: anvil.chain,
|
|
74
104
|
address: vault,
|
|
75
105
|
abi: iMidasPausableVaultAbi,
|
|
76
|
-
functionName: "
|
|
106
|
+
functionName: "unpauseFn",
|
|
107
|
+
args: [DEPOSIT_INSTANT_SELECTOR],
|
|
108
|
+
throwOnReceiptRevert: true
|
|
77
109
|
});
|
|
78
110
|
} finally {
|
|
79
111
|
await anvil.stopImpersonatingAccount({ address: admin });
|
|
@@ -89,12 +121,22 @@ async function unpauseMidasIssuanceVault(props) {
|
|
|
89
121
|
address: admin,
|
|
90
122
|
value: parseEther("100")
|
|
91
123
|
});
|
|
92
|
-
await
|
|
124
|
+
if (paused) await anvil.writeContractSync({
|
|
125
|
+
account: admin,
|
|
126
|
+
chain: anvil.chain,
|
|
127
|
+
address: vault,
|
|
128
|
+
abi: iMidasPausableVaultAbi,
|
|
129
|
+
functionName: "pause",
|
|
130
|
+
throwOnReceiptRevert: true
|
|
131
|
+
});
|
|
132
|
+
if (depositInstantPaused) await anvil.writeContractSync({
|
|
93
133
|
account: admin,
|
|
94
134
|
chain: anvil.chain,
|
|
95
135
|
address: vault,
|
|
96
136
|
abi: iMidasPausableVaultAbi,
|
|
97
|
-
functionName: "
|
|
137
|
+
functionName: "pauseFn",
|
|
138
|
+
args: [DEPOSIT_INSTANT_SELECTOR],
|
|
139
|
+
throwOnReceiptRevert: true
|
|
98
140
|
});
|
|
99
141
|
} catch (e) {
|
|
100
142
|
logger?.warn(`midas: failed to pause issuance vault ${vault} back: ${e}`);
|
|
@@ -103,5 +145,25 @@ async function unpauseMidasIssuanceVault(props) {
|
|
|
103
145
|
}
|
|
104
146
|
};
|
|
105
147
|
}
|
|
148
|
+
function* midasGatewayAdapters(sdk) {
|
|
149
|
+
for (const cm of sdk.marketRegister.creditManagers) for (const adapter of cm.creditManager.adapters.values()) if (adapter instanceof MidasGatewayAdapterContract) yield adapter;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Target contracts of all Midas gateway adapters of the loaded credit managers,
|
|
153
|
+
* same as the foundry tests do with `ICreditConfiguratorV3.allowedAdapters`
|
|
154
|
+
*/
|
|
155
|
+
function collectMidasGateways(sdk) {
|
|
156
|
+
const gateways = new AddressSet();
|
|
157
|
+
for (const adapter of midasGatewayAdapters(sdk)) gateways.add(adapter.targetContract);
|
|
158
|
+
return gateways.asArray();
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* mTokens of all Midas gateway adapters of the loaded credit managers
|
|
162
|
+
*/
|
|
163
|
+
function collectMidasMTokens(sdk) {
|
|
164
|
+
const mTokens = new AddressSet();
|
|
165
|
+
for (const adapter of midasGatewayAdapters(sdk)) mTokens.add(adapter.mToken);
|
|
166
|
+
return mTokens.asArray();
|
|
167
|
+
}
|
|
106
168
|
//#endregion
|
|
107
|
-
export { unpauseMidasIssuanceVault };
|
|
169
|
+
export { collectMidasGateways, collectMidasMTokens, unpauseMidasIssuanceVault };
|
|
@@ -2,7 +2,7 @@ import { AddressSet } from "../onchain/utils/AddressSet.js";
|
|
|
2
2
|
import { OnchainSDK } from "../onchain/OnchainSDK.js";
|
|
3
3
|
import "../onchain/index.js";
|
|
4
4
|
import { iDSTokenAbi } from "../abi/rwa/iDSToken.js";
|
|
5
|
-
import { registerSecuritizeInvestor
|
|
5
|
+
import { registerSecuritizeInvestor } from "./kycUtils.js";
|
|
6
6
|
import { erc20Abi, isAddressEqual, parseAbi, zeroAddress } from "viem";
|
|
7
7
|
import { privateKeyToAccount } from "viem/accounts";
|
|
8
8
|
//#region src/dev/securitizeUtils.ts
|
|
@@ -64,7 +64,7 @@ async function issueDSTokens(props) {
|
|
|
64
64
|
const { timestamp } = await anvil.getBlock();
|
|
65
65
|
const issuanceTime = timestamp - lockPeriod - 1n;
|
|
66
66
|
try {
|
|
67
|
-
const
|
|
67
|
+
const receipt = await anvil.writeContractSync({
|
|
68
68
|
account,
|
|
69
69
|
chain: anvil.chain,
|
|
70
70
|
address: token,
|
|
@@ -77,14 +77,15 @@ async function issueDSTokens(props) {
|
|
|
77
77
|
0n,
|
|
78
78
|
"",
|
|
79
79
|
0n
|
|
80
|
-
]
|
|
80
|
+
],
|
|
81
|
+
throwOnReceiptRevert: true
|
|
81
82
|
});
|
|
82
83
|
logger?.debug({
|
|
83
84
|
issuanceTime,
|
|
84
85
|
investor,
|
|
85
86
|
amount
|
|
86
87
|
}, "issueTokensCustom successful");
|
|
87
|
-
return
|
|
88
|
+
return receipt.transactionHash;
|
|
88
89
|
} catch (e) {
|
|
89
90
|
logger?.debug(`issueTokensCustom failed: ${e}`);
|
|
90
91
|
}
|
|
@@ -93,14 +94,15 @@ async function issueDSTokens(props) {
|
|
|
93
94
|
investor,
|
|
94
95
|
amount
|
|
95
96
|
}, "Falling back to issueTokens");
|
|
96
|
-
return
|
|
97
|
+
return (await anvil.writeContractSync({
|
|
97
98
|
account,
|
|
98
99
|
chain: anvil.chain,
|
|
99
100
|
address: token,
|
|
100
101
|
abi: iDSTokenAbi,
|
|
101
102
|
functionName: "issueTokens",
|
|
102
|
-
args: [investor, amount]
|
|
103
|
-
|
|
103
|
+
args: [investor, amount],
|
|
104
|
+
throwOnReceiptRevert: true
|
|
105
|
+
})).transactionHash;
|
|
104
106
|
}
|
|
105
107
|
/**
|
|
106
108
|
* Resolves unique compliance configuration services of `tokens`: several
|
|
@@ -160,13 +162,14 @@ async function enableDSTokenBackDating(props) {
|
|
|
160
162
|
continue;
|
|
161
163
|
}
|
|
162
164
|
logger?.info(`Allowing back-dating on ${service}`);
|
|
163
|
-
await
|
|
165
|
+
await anvil.writeContractSync({
|
|
164
166
|
account,
|
|
165
167
|
chain: anvil.chain,
|
|
166
168
|
address: service,
|
|
167
169
|
abi: iDSComplianceConfigurationServiceAbi,
|
|
168
170
|
functionName: "setDisallowBackDating",
|
|
169
|
-
args: [false]
|
|
171
|
+
args: [false],
|
|
172
|
+
throwOnReceiptRevert: true
|
|
170
173
|
});
|
|
171
174
|
toRestore.push(service);
|
|
172
175
|
}
|
|
@@ -176,13 +179,14 @@ async function enableDSTokenBackDating(props) {
|
|
|
176
179
|
for (const service of services) {
|
|
177
180
|
logger?.info(`Disallowing back-dating on ${service}`);
|
|
178
181
|
try {
|
|
179
|
-
await
|
|
182
|
+
await anvil.writeContractSync({
|
|
180
183
|
account,
|
|
181
184
|
chain: anvil.chain,
|
|
182
185
|
address: service,
|
|
183
186
|
abi: iDSComplianceConfigurationServiceAbi,
|
|
184
187
|
functionName: "setDisallowBackDating",
|
|
185
|
-
args: [true]
|
|
188
|
+
args: [true],
|
|
189
|
+
throwOnReceiptRevert: true
|
|
186
190
|
});
|
|
187
191
|
} catch (e) {
|
|
188
192
|
logger?.warn(`Failed to restore disallowBackDating on ${service}: ${e}`);
|
|
@@ -204,18 +204,15 @@ async function fulfillMidasRedeemer(anvil, redeemer, logger) {
|
|
|
204
204
|
address: MIDAS_VAULT_ADMIN,
|
|
205
205
|
value: parseEther("100")
|
|
206
206
|
});
|
|
207
|
-
|
|
207
|
+
await anvil.writeContractSync({
|
|
208
208
|
chain: anvil.chain,
|
|
209
209
|
address: midasRedemptionVault,
|
|
210
210
|
account: MIDAS_VAULT_ADMIN,
|
|
211
211
|
abi: iMidasRedemptionVaultExtAbi,
|
|
212
212
|
functionName: "safeApproveRequest",
|
|
213
|
-
args: [requestId, mTokenRate]
|
|
213
|
+
args: [requestId, mTokenRate],
|
|
214
|
+
throwOnReceiptRevert: true
|
|
214
215
|
});
|
|
215
|
-
if ((await anvil.waitForTransactionReceipt({
|
|
216
|
-
hash,
|
|
217
|
-
pollingInterval: 100
|
|
218
|
-
})).status !== "success") throw new Error(`midas: safeApproveRequest tx ${hash} reverted`);
|
|
219
216
|
await anvil.stopImpersonatingAccount({ address: MIDAS_VAULT_ADMIN });
|
|
220
217
|
}
|
|
221
218
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "./base.js";
|
|
2
2
|
import { creditAccountFrozen, liquidatorNotEligible, notEmergencyLiquidator } from "./liquidation-errors.js";
|
|
3
|
-
import { creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, marketExpired, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, reservePriceLimited, rwaOpenRequirementsNotMet } from "./operation-errors.js";
|
|
3
|
+
import { accountNotMidasGreenlisted, creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, marketExpired, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, reservePriceLimited, rwaOpenRequirementsNotMet } from "./operation-errors.js";
|
|
4
4
|
import { unpriceableTokenError } from "./oracle-errors.js";
|
|
5
5
|
import { creditAccountNotEmpty, creditAccountNotFound, multipleDelayedWithdrawals, noDelayedRoute, noRecordedIntent, noStrategyTargetCollateral, unexpectedFailure, unsupportedCollateralToken, unsupportedTokenPair, withdrawalInProgress } from "./prepare-errors.js";
|
|
6
6
|
import { malformedTransaction } from "./preview-errors.js";
|
|
7
|
-
export { creditAccountFrozen, creditAccountNotEmpty, creditAccountNotFound, creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, liquidatorNotEligible, malformedTransaction, marketExpired, multipleDelayedWithdrawals, noDelayedRoute, noRecordedIntent, noStrategyTargetCollateral, notEmergencyLiquidator, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, reservePriceLimited, rwaOpenRequirementsNotMet, unexpectedFailure, unpriceableTokenError, unsupportedCollateralToken, unsupportedTokenPair, withdrawalInProgress };
|
|
7
|
+
export { accountNotMidasGreenlisted, creditAccountFrozen, creditAccountNotEmpty, creditAccountNotFound, creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, liquidatorNotEligible, malformedTransaction, marketExpired, multipleDelayedWithdrawals, noDelayedRoute, noRecordedIntent, noStrategyTargetCollateral, notEmergencyLiquidator, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, reservePriceLimited, rwaOpenRequirementsNotMet, unexpectedFailure, unpriceableTokenError, unsupportedCollateralToken, unsupportedTokenPair, withdrawalInProgress };
|
|
@@ -125,5 +125,13 @@ function rwaOpenRequirementsNotMet(args) {
|
|
|
125
125
|
...args
|
|
126
126
|
};
|
|
127
127
|
}
|
|
128
|
+
/** {@inheritDoc AccountNotMidasGreenlistedError} */
|
|
129
|
+
function accountNotMidasGreenlisted(args) {
|
|
130
|
+
return {
|
|
131
|
+
code: "accountNotMidasGreenlisted",
|
|
132
|
+
message: `The credit account is not Midas-greenlisted for ${args.token.symbol}.`,
|
|
133
|
+
...args
|
|
134
|
+
};
|
|
135
|
+
}
|
|
128
136
|
//#endregion
|
|
129
|
-
export { creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, marketExpired, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, reservePriceLimited, rwaOpenRequirementsNotMet };
|
|
137
|
+
export { accountNotMidasGreenlisted, creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, marketExpired, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, reservePriceLimited, rwaOpenRequirementsNotMet };
|
package/dist/esm/model/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import { ANALYTICS_POSITIONS_DEFAULT_LIMIT, ANALYTICS_POSITIONS_MAX_LIMIT, analy
|
|
|
15
15
|
import "./curators.js";
|
|
16
16
|
import "./delayed-intents.js";
|
|
17
17
|
import { creditAccountFrozen, liquidatorNotEligible, notEmergencyLiquidator } from "./errors/liquidation-errors.js";
|
|
18
|
-
import { creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, marketExpired, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, reservePriceLimited, rwaOpenRequirementsNotMet } from "./errors/operation-errors.js";
|
|
18
|
+
import { accountNotMidasGreenlisted, creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, marketExpired, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, reservePriceLimited, rwaOpenRequirementsNotMet } from "./errors/operation-errors.js";
|
|
19
19
|
import { unpriceableTokenError } from "./errors/oracle-errors.js";
|
|
20
20
|
import { creditAccountNotEmpty, creditAccountNotFound, multipleDelayedWithdrawals, noDelayedRoute, noRecordedIntent, noStrategyTargetCollateral, unexpectedFailure, unsupportedCollateralToken, unsupportedTokenPair, withdrawalInProgress } from "./errors/prepare-errors.js";
|
|
21
21
|
import { malformedTransaction } from "./errors/preview-errors.js";
|
|
@@ -32,4 +32,4 @@ import { chainFailedSchema, chainMetadataSchema, chainSucceededSchema, dataSourc
|
|
|
32
32
|
import { safeValue, sdkErr, sdkOk } from "./result.js";
|
|
33
33
|
import "./withdrawals.js";
|
|
34
34
|
import { positionClaimableWithdrawalSchema, positionPendingWithdrawalSchema, positionWithdrawalsSchema, withdrawalOutputAmountSchema } from "./withdrawals.schema.js";
|
|
35
|
-
export { ANALYTICS_POSITIONS_DEFAULT_LIMIT, ANALYTICS_POSITIONS_MAX_LIMIT, CHART_METRIC_UNITS, CHART_RANGES, CHART_UNAVAILABLE_CODES, FILTER_ALL, KYC_REGISTRATION_LINKS, POOL_OPPORTUNITY_CHART_METRICS, POOL_POSITION_CHART_METRICS, PROTOCOL_CHART_METRICS, RWA_FACTORY_SECURITIZE, RWA_FACTORY_TYPES, RWA_PROTOCOLS, SECURITIZE_REGISTER_VAULT_TYPES, STRATEGY_OPPORTUNITY_CHART_METRICS, STRATEGY_POSITION_CHART_METRICS, STRATEGY_POSITION_COLLATERAL_ERROR, amountSchema, analyticsChartQueryOptionsSchema, analyticsChartQueryParamsSchema, analyticsChartQuerySchema, analyticsPositionListOptionsSchema, analyticsPositionListQueryParamsSchema, analyticsPositionListQuerySchema, analyticsPositionPageSchema, analyticsPositionSchema, analyticsPositionSortFieldSchema, analyticsSortDirectionSchema, apyBreakdownSchema, asEstimated, assetTypeSchema, backendPreferred, booleanParamSchema, borrowRateBreakdownSchema, bpsSchema, chainFailedSchema, chainIdSchema, chainMetadataSchema, chainSucceededSchema, chartBundleSchemaFor, chartDenominationSchema, chartMetricSchema, chartQueryCodec, chartQueryParamsSchema, chartQuerySchema, chartRangeSchema, chartSeriesSchema, chartValueSchema, chartWindowSchema, compareTagOf, creditAccountFrozen, creditAccountNotEmpty, creditAccountNotFound, creditManagerPaused, curatorNameSchema, curatorSchema, dataSourceSchema, debtOutOfRange, delayedReceivedAssetSchema, encodeFlag, filterAllSchema, filterable, forbiddenToken, instantReceivedAssetSchema, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, isFilterSet, kycRequirementSchema, leverageOutOfRange, leverageSchema, liquidatableAccountFilterSchema, liquidatableAccountSchema, liquidationApprovalSchema, liquidationDetailsSchema, liquidationPositionId, liquidationPositionSchema, liquidatorNotEligible, malformedTransaction, marketExpired, matchesLiquidatableAccountFilter, matchesOpportunityFilter, matchesPositionFilter, multipleDelayedWithdrawals, noDelayedRoute, noRecordedIntent, noStrategyTargetCollateral, notEmergencyLiquidator, noticeKindSchema, noticeSchema, offchainOnly, onchainOnly, opportunityBaseSchema, opportunityDetailSchema, opportunityFilterQueryParamsSchema, opportunityFilterQuerySchema, opportunityFilterSchema, opportunityId, opportunityKeySchema, opportunityKindSchema, opportunitySchema, opportunityTotalsSchema, pnlBreakdownSchema, pointRewardsSchema, pointsProgramPnLSchema, pointsProgramSchema, pointsRewardsPnLSchema, poolOpportunityChartMetricSchema, poolOpportunityDetailSchema, poolOpportunityId, poolOpportunityKeySchema, poolOpportunitySchema, poolPaused, poolPositionChartMetricSchema, poolPositionId, poolPositionKeySchema, poolPositionSchema, poolSunset, positionClaimableWithdrawalSchema, positionCollateralSchema, positionFilterQueryParamsSchema, positionFilterQuerySchema, positionFilterSchema, positionId, positionKeySchema, positionKindSchema, positionPendingWithdrawalSchema, positionSchema, positionTransactionKindSchema, positionTransactionSchema, positionWithdrawalsSchema, positionsTotalsSchema, priceFeedDataSchema, priceFeedSummarySchema, protocolChartMetricSchema, quotaAssetSchema, quotaCountExceeded, quotaLimitReached, rateCurvePointSchema, rateCurveSchema, receivedAssetSchema, reservePriceLimited, responseMetadataSchema, responseSchema, rewardsPnLSchema, rewardsSchema, rwaOpenRequirementsNotMet, rwaProtocolSchema, safeValue, sdkErr, sdkOk, strategyOpportunityChartMetricSchema, strategyOpportunityDetailSchema, strategyOpportunityId, strategyOpportunityKeySchema, strategyOpportunitySchema, strategyPositionChartMetricSchema, strategyPositionId, strategyPositionKeySchema, strategyPositionSchema, timestampSchema, tokenAmountSchema, tokenQuotaRateSchema, tokenRewardsPnLSchema, tokenRewardsSchema, tokenSchema, tolerance, txCallSchema, underlyingTokenSchema, unexpectedFailure, unpriceableTokenError, unsupportedCollateralToken, unsupportedTokenPair, withdrawalInProgress, withdrawalOutputAmountSchema };
|
|
35
|
+
export { ANALYTICS_POSITIONS_DEFAULT_LIMIT, ANALYTICS_POSITIONS_MAX_LIMIT, CHART_METRIC_UNITS, CHART_RANGES, CHART_UNAVAILABLE_CODES, FILTER_ALL, KYC_REGISTRATION_LINKS, POOL_OPPORTUNITY_CHART_METRICS, POOL_POSITION_CHART_METRICS, PROTOCOL_CHART_METRICS, RWA_FACTORY_SECURITIZE, RWA_FACTORY_TYPES, RWA_PROTOCOLS, SECURITIZE_REGISTER_VAULT_TYPES, STRATEGY_OPPORTUNITY_CHART_METRICS, STRATEGY_POSITION_CHART_METRICS, STRATEGY_POSITION_COLLATERAL_ERROR, accountNotMidasGreenlisted, amountSchema, analyticsChartQueryOptionsSchema, analyticsChartQueryParamsSchema, analyticsChartQuerySchema, analyticsPositionListOptionsSchema, analyticsPositionListQueryParamsSchema, analyticsPositionListQuerySchema, analyticsPositionPageSchema, analyticsPositionSchema, analyticsPositionSortFieldSchema, analyticsSortDirectionSchema, apyBreakdownSchema, asEstimated, assetTypeSchema, backendPreferred, booleanParamSchema, borrowRateBreakdownSchema, bpsSchema, chainFailedSchema, chainIdSchema, chainMetadataSchema, chainSucceededSchema, chartBundleSchemaFor, chartDenominationSchema, chartMetricSchema, chartQueryCodec, chartQueryParamsSchema, chartQuerySchema, chartRangeSchema, chartSeriesSchema, chartValueSchema, chartWindowSchema, compareTagOf, creditAccountFrozen, creditAccountNotEmpty, creditAccountNotFound, creditManagerPaused, curatorNameSchema, curatorSchema, dataSourceSchema, debtOutOfRange, delayedReceivedAssetSchema, encodeFlag, filterAllSchema, filterable, forbiddenToken, instantReceivedAssetSchema, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, isFilterSet, kycRequirementSchema, leverageOutOfRange, leverageSchema, liquidatableAccountFilterSchema, liquidatableAccountSchema, liquidationApprovalSchema, liquidationDetailsSchema, liquidationPositionId, liquidationPositionSchema, liquidatorNotEligible, malformedTransaction, marketExpired, matchesLiquidatableAccountFilter, matchesOpportunityFilter, matchesPositionFilter, multipleDelayedWithdrawals, noDelayedRoute, noRecordedIntent, noStrategyTargetCollateral, notEmergencyLiquidator, noticeKindSchema, noticeSchema, offchainOnly, onchainOnly, opportunityBaseSchema, opportunityDetailSchema, opportunityFilterQueryParamsSchema, opportunityFilterQuerySchema, opportunityFilterSchema, opportunityId, opportunityKeySchema, opportunityKindSchema, opportunitySchema, opportunityTotalsSchema, pnlBreakdownSchema, pointRewardsSchema, pointsProgramPnLSchema, pointsProgramSchema, pointsRewardsPnLSchema, poolOpportunityChartMetricSchema, poolOpportunityDetailSchema, poolOpportunityId, poolOpportunityKeySchema, poolOpportunitySchema, poolPaused, poolPositionChartMetricSchema, poolPositionId, poolPositionKeySchema, poolPositionSchema, poolSunset, positionClaimableWithdrawalSchema, positionCollateralSchema, positionFilterQueryParamsSchema, positionFilterQuerySchema, positionFilterSchema, positionId, positionKeySchema, positionKindSchema, positionPendingWithdrawalSchema, positionSchema, positionTransactionKindSchema, positionTransactionSchema, positionWithdrawalsSchema, positionsTotalsSchema, priceFeedDataSchema, priceFeedSummarySchema, protocolChartMetricSchema, quotaAssetSchema, quotaCountExceeded, quotaLimitReached, rateCurvePointSchema, rateCurveSchema, receivedAssetSchema, reservePriceLimited, responseMetadataSchema, responseSchema, rewardsPnLSchema, rewardsSchema, rwaOpenRequirementsNotMet, rwaProtocolSchema, safeValue, sdkErr, sdkOk, strategyOpportunityChartMetricSchema, strategyOpportunityDetailSchema, strategyOpportunityId, strategyOpportunityKeySchema, strategyOpportunitySchema, strategyPositionChartMetricSchema, strategyPositionId, strategyPositionKeySchema, strategyPositionSchema, timestampSchema, tokenAmountSchema, tokenQuotaRateSchema, tokenRewardsPnLSchema, tokenRewardsSchema, tokenSchema, tolerance, txCallSchema, underlyingTokenSchema, unexpectedFailure, unpriceableTokenError, unsupportedCollateralToken, unsupportedTokenPair, withdrawalInProgress, withdrawalOutputAmountSchema };
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { insufficientBalance } from "../../../model/errors/operation-errors.js";
|
|
2
|
+
import { unsupportedCollateralToken } from "../../../model/errors/prepare-errors.js";
|
|
3
|
+
import "../../../model/index.js";
|
|
4
|
+
import { toToken } from "../../validation/helpers/token.js";
|
|
5
|
+
import { IntentPreviewError } from "../../validation/raise.js";
|
|
6
|
+
import "../../validation/index.js";
|
|
7
|
+
import { eq, toTargetDecimals } from "./utils/common.js";
|
|
8
|
+
import { assertCanBorrow, assertCollateralised, assertGrowthAllowed, assertMarketOperable, assertQuotaAvailable } from "./guards.js";
|
|
9
|
+
import { assertDebtLimits } from "./math.js";
|
|
10
|
+
import { unopenedAccountSlice } from "./utils/credit-account-slice.js";
|
|
11
|
+
import { collectPriceImpact } from "./utils/price-impact.js";
|
|
12
|
+
import { getQuotasForUpdate } from "./utils/quotas-for-update.js";
|
|
13
|
+
import { createRouterPaths } from "./utils/router-path.js";
|
|
14
|
+
import "./utils/index.js";
|
|
15
|
+
//#region src/onchain/accounts/intents/borrow.ts
|
|
16
|
+
/**
|
|
17
|
+
* Builds the state a borrow would leave behind.
|
|
18
|
+
*
|
|
19
|
+
* The debt is named rather than derived: a borrow asks for an amount, where an
|
|
20
|
+
* opening asks for a leverage and lets the collateral decide. Everything the
|
|
21
|
+
* loan pays out leaves the account, so the collateral alone backs it — which
|
|
22
|
+
* is what makes the health factor here a straight function of the two amounts.
|
|
23
|
+
*
|
|
24
|
+
* Produces no operation list, as opening never does: the caller hands the
|
|
25
|
+
* numbers and the calls to `sdk.accounts.openCA`, with `withdrawToken` set to
|
|
26
|
+
* the payout.
|
|
27
|
+
*/
|
|
28
|
+
async function buildBorrowState(props) {
|
|
29
|
+
const { sdk, creditManager, collateralAmount, borrowAmount, slippage = 0, quotaReserve, creditAccount: existing } = props;
|
|
30
|
+
const suite = sdk.marketRegister.findCreditManager(creditManager);
|
|
31
|
+
const market = sdk.marketRegister.findByCreditManager(creditManager);
|
|
32
|
+
assertMarketOperable(suite);
|
|
33
|
+
const underlying = market.pool.underlying.toLowerCase();
|
|
34
|
+
const collateralToken = props.collateralToken.toLowerCase();
|
|
35
|
+
const borrowToken = props.borrowToken.toLowerCase();
|
|
36
|
+
const convert = (from, to, amount) => market.priceOracle.safeConvert(from, to, amount).value;
|
|
37
|
+
if (eq(collateralToken, borrowToken)) throw new IntentPreviewError(unsupportedCollateralToken(toToken(sdk, collateralToken)), "borrow: the payout token cannot also be the collateral");
|
|
38
|
+
const rwaAsset = sdk.tokensMeta.rwaUnderlyings.get(underlying)?.asset?.toLowerCase();
|
|
39
|
+
const unwrapsPayout = !!rwaAsset && eq(borrowToken, rwaAsset);
|
|
40
|
+
if (rwaAsset && eq(borrowToken, underlying)) throw new IntentPreviewError(unsupportedCollateralToken(toToken(sdk, borrowToken)), `borrow: ${underlying} cannot leave the account, ask for the payout in ${rwaAsset}`);
|
|
41
|
+
if (collateralAmount <= 0n) throw new IntentPreviewError(insufficientBalance(), "borrow: no collateral supplied");
|
|
42
|
+
if (borrowAmount <= 0n) throw new IntentPreviewError(insufficientBalance(), "borrow: nothing to borrow");
|
|
43
|
+
const margin = convert(collateralToken, underlying, collateralAmount);
|
|
44
|
+
if (margin <= 0n) throw new IntentPreviewError(insufficientBalance(), "borrow: collateral is worth nothing in underlying");
|
|
45
|
+
const debt = eq(borrowToken, underlying) ? borrowAmount : unwrapsPayout ? toTargetDecimals(borrowAmount, borrowToken, underlying, sdk) : convert(borrowToken, underlying, borrowAmount);
|
|
46
|
+
assertDebtLimits(sdk, debt, suite.creditFacade, underlying);
|
|
47
|
+
assertCanBorrow(sdk, suite, debt);
|
|
48
|
+
const account = existing ?? unopenedAccountSlice({
|
|
49
|
+
creditManager,
|
|
50
|
+
creditFacade: suite.creditFacade.address,
|
|
51
|
+
underlying
|
|
52
|
+
});
|
|
53
|
+
const leg = eq(borrowToken, underlying) || unwrapsPayout ? void 0 : await createRouterPaths({
|
|
54
|
+
sdk,
|
|
55
|
+
creditAccount: account,
|
|
56
|
+
slippage
|
|
57
|
+
}).swap({
|
|
58
|
+
tokenIn: underlying,
|
|
59
|
+
tokenOut: borrowToken,
|
|
60
|
+
amount: debt,
|
|
61
|
+
keep: eq(collateralToken, underlying) ? collateralAmount : 0n
|
|
62
|
+
});
|
|
63
|
+
const unwrap = unwrapsPayout ? await sdk.accounts.assembleRWAUnwrapCalls(debt, creditManager) : void 0;
|
|
64
|
+
if (unwrapsPayout && !unwrap) throw new Error(`borrow: no unwrap calls found for ${borrowToken}`);
|
|
65
|
+
const assets = [{
|
|
66
|
+
token: collateralToken,
|
|
67
|
+
balance: collateralAmount
|
|
68
|
+
}];
|
|
69
|
+
const quotaIncrease = borrowCollateralQuota({
|
|
70
|
+
sdk,
|
|
71
|
+
creditManager,
|
|
72
|
+
assets,
|
|
73
|
+
quotaReserve
|
|
74
|
+
});
|
|
75
|
+
assertGrowthAllowed({
|
|
76
|
+
sdk,
|
|
77
|
+
suite,
|
|
78
|
+
market,
|
|
79
|
+
before: [],
|
|
80
|
+
after: assets
|
|
81
|
+
});
|
|
82
|
+
assertQuotaAvailable(sdk, market, quotaIncrease);
|
|
83
|
+
const snapshot = {
|
|
84
|
+
creditManager,
|
|
85
|
+
assets,
|
|
86
|
+
quotas: quotaIncrease,
|
|
87
|
+
totalDebt: debt,
|
|
88
|
+
totalValue: margin
|
|
89
|
+
};
|
|
90
|
+
const projection = sdk.positions.projection(snapshot, { availableLiquidityChange: -debt });
|
|
91
|
+
assertCollateralised(projection.safeHealthFactor, true);
|
|
92
|
+
const priced = (token, balance) => market.priceOracle.toTokenAmount(token, balance);
|
|
93
|
+
const payout = unwrapsPayout ? toTargetDecimals(debt, underlying, borrowToken, sdk) : leg ? leg.amount : debt;
|
|
94
|
+
return {
|
|
95
|
+
...projection,
|
|
96
|
+
currentPrice: sdk.positions.currentPrice(snapshot),
|
|
97
|
+
executionCost: void 0,
|
|
98
|
+
priceImpact: await collectPriceImpact(leg?.probe ? [leg.probe] : [], {
|
|
99
|
+
totalValue: margin,
|
|
100
|
+
netValue: margin - debt,
|
|
101
|
+
toUnderlying: (from, amount) => convert(from, underlying, amount)
|
|
102
|
+
}),
|
|
103
|
+
collateral: priced(collateralToken, collateralAmount),
|
|
104
|
+
borrowed: priced(borrowToken, payout),
|
|
105
|
+
minBorrowed: priced(borrowToken, leg ? leg.minAmount : payout),
|
|
106
|
+
slippage,
|
|
107
|
+
quotaIncrease,
|
|
108
|
+
calls: leg ? [...leg.calls] : unwrap ?? [],
|
|
109
|
+
creditAccount: existing?.creditAccount
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Quota a borrow buys for its collateral on an account that holds none yet.
|
|
114
|
+
*
|
|
115
|
+
* Shared with `maxBorrow`, because a quota short of the collateral's weighted
|
|
116
|
+
* value is what caps the loan: the two have to read the same number or the
|
|
117
|
+
* ceiling one offers is one the other refuses.
|
|
118
|
+
*
|
|
119
|
+
* @param props - {@link BorrowCollateralQuotaProps}
|
|
120
|
+
**/
|
|
121
|
+
function borrowCollateralQuota({ sdk, creditManager, assets, quotaReserve }) {
|
|
122
|
+
const suite = sdk.marketRegister.findCreditManager(creditManager);
|
|
123
|
+
const market = sdk.marketRegister.findByCreditManager(creditManager);
|
|
124
|
+
return getQuotasForUpdate({
|
|
125
|
+
assetsBefore: [],
|
|
126
|
+
assetsAfter: assets,
|
|
127
|
+
initialQuotas: [],
|
|
128
|
+
quotaReserve,
|
|
129
|
+
underlyingToken: market.pool.underlying,
|
|
130
|
+
liquidationThresholds: suite.creditManager.liquidationThresholds,
|
|
131
|
+
quotas: market.pool.pqk.quotas,
|
|
132
|
+
maxDebt: suite.creditFacade.maxDebt,
|
|
133
|
+
convert: (from, to, amount) => market.priceOracle.safeConvert(from, to, amount).value
|
|
134
|
+
}).quotaIncrease;
|
|
135
|
+
}
|
|
136
|
+
//#endregion
|
|
137
|
+
export { borrowCollateralQuota, buildBorrowState };
|
|
@@ -2,9 +2,9 @@ import { BigIntMath } from "../../utils/bigint-math.js";
|
|
|
2
2
|
import { PERCENTAGE_FACTOR } from "../../constants/math.js";
|
|
3
3
|
import "../../utils/index.js";
|
|
4
4
|
import { eq } from "./utils/common.js";
|
|
5
|
-
//#region src/onchain/accounts/intents/collateral-
|
|
6
|
-
/** {@inheritDoc
|
|
7
|
-
function
|
|
5
|
+
//#region src/onchain/accounts/intents/collateral-valuation.ts
|
|
6
|
+
/** {@inheritDoc CollateralValuation} */
|
|
7
|
+
function collateralValuation(creditAccount, sdk) {
|
|
8
8
|
const { market, creditManager } = sdk.marketRegister.findCreditManager(creditAccount.creditManager);
|
|
9
9
|
const { priceOracle } = market;
|
|
10
10
|
const { pqk } = market.pool;
|
|
@@ -20,21 +20,21 @@ function collateralMoney(creditAccount, sdk) {
|
|
|
20
20
|
const lt = (token) => BigInt(creditManager.liquidationThresholds.get(token) ?? 0);
|
|
21
21
|
const checkedUsd = (holding) => eq(holding.token, underlying) ? mainUsd(holding.token, holding.balance) ?? 0n : priceOracle.safeConvertMinUSD(holding.token, holding.balance).value;
|
|
22
22
|
/** A quota is underlying-denominated, and a closed market backs nothing. */
|
|
23
|
-
const
|
|
23
|
+
const quotaValue = (holding) => pqk.hasActiveQuota(holding.token) ? (mainUsd(underlying, holding.quota) ?? 0n) * PERCENTAGE_FACTOR : 0n;
|
|
24
24
|
const weigh = (holding) => {
|
|
25
25
|
const weighted = checkedUsd(holding) * lt(holding.token);
|
|
26
26
|
if (holding.quota === 0n) return weighted;
|
|
27
|
-
return BigIntMath.min(
|
|
27
|
+
return BigIntMath.min(quotaValue(holding), weighted);
|
|
28
28
|
};
|
|
29
29
|
return {
|
|
30
30
|
underlying,
|
|
31
31
|
counts: (holding) => holding.balance > 10n && (!masked || (holding.mask & creditAccount.enabledTokensMask) !== 0n),
|
|
32
32
|
weigh,
|
|
33
|
-
|
|
33
|
+
quotaValue,
|
|
34
34
|
mainUsd,
|
|
35
35
|
checkedUsd,
|
|
36
36
|
lt
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
39
|
//#endregion
|
|
40
|
-
export {
|
|
40
|
+
export { collateralValuation };
|