@gearbox-protocol/sdk 14.12.0-next.21 → 14.12.0-next.23
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/abi/IWithdrawalCompressorV313.js +2 -1
- package/dist/cjs/abi/compressors/withdrawalCompressor.js +2 -1
- package/dist/cjs/plugins/delayed-withdrawal/DelayedWithdrawalPlugin.js +1 -5
- package/dist/cjs/preview/preview/applyInnerOperations.js +83 -58
- package/dist/cjs/preview/preview/applyQuotaChanges.js +43 -0
- package/dist/cjs/preview/preview/errors.js +0 -16
- package/dist/cjs/preview/preview/index.js +2 -0
- package/dist/cjs/preview/preview/previewAdjustCreditAccount.js +19 -8
- package/dist/cjs/preview/preview/previewCloseOrRepayCreditAccount.js +18 -7
- package/dist/cjs/preview/preview/previewOpenCreditAccount.js +18 -6
- package/dist/cjs/preview/preview/types.js +30 -0
- package/dist/cjs/preview/preview/unwrapNativeCollateral.js +10 -4
- package/dist/cjs/sdk/OnchainSDK.js +3 -6
- package/dist/cjs/sdk/accounts/CreditAccountsServiceV310.js +45 -37
- package/dist/cjs/sdk/accounts/withdrawal-compressor/AbstractWithdrawalCompressorContract.js +14 -22
- package/dist/cjs/sdk/accounts/withdrawal-compressor/addresses.js +6 -18
- package/dist/cjs/sdk/accounts/withdrawal-compressor/createWithdrawalCompressor.js +3 -5
- package/dist/esm/abi/IWithdrawalCompressorV313.js +2 -1
- package/dist/esm/abi/compressors/withdrawalCompressor.js +2 -1
- package/dist/esm/plugins/delayed-withdrawal/DelayedWithdrawalPlugin.js +2 -9
- package/dist/esm/preview/preview/applyInnerOperations.js +90 -59
- package/dist/esm/preview/preview/applyQuotaChanges.js +19 -0
- package/dist/esm/preview/preview/errors.js +0 -15
- package/dist/esm/preview/preview/index.js +1 -0
- package/dist/esm/preview/preview/previewAdjustCreditAccount.js +20 -8
- package/dist/esm/preview/preview/previewCloseOrRepayCreditAccount.js +18 -7
- package/dist/esm/preview/preview/previewOpenCreditAccount.js +20 -6
- package/dist/esm/preview/preview/types.js +16 -0
- package/dist/esm/preview/preview/unwrapNativeCollateral.js +12 -4
- package/dist/esm/sdk/OnchainSDK.js +3 -6
- package/dist/esm/sdk/accounts/CreditAccountsServiceV310.js +45 -37
- package/dist/esm/sdk/accounts/withdrawal-compressor/AbstractWithdrawalCompressorContract.js +14 -22
- package/dist/esm/sdk/accounts/withdrawal-compressor/addresses.js +6 -18
- package/dist/esm/sdk/accounts/withdrawal-compressor/createWithdrawalCompressor.js +3 -5
- package/dist/types/abi/IWithdrawalCompressorV313.d.ts +4 -0
- package/dist/types/abi/compressors/withdrawalCompressor.d.ts +4 -0
- package/dist/types/permissionless/bindings/compressors/withdrawal-compressor.d.ts +4 -0
- package/dist/types/preview/preview/applyInnerOperations.d.ts +8 -33
- package/dist/types/preview/preview/applyQuotaChanges.d.ts +24 -0
- package/dist/types/preview/preview/errors.d.ts +0 -12
- package/dist/types/preview/preview/index.d.ts +1 -0
- package/dist/types/preview/preview/previewAdjustCreditAccount.d.ts +1 -1
- package/dist/types/preview/preview/previewOpenCreditAccount.d.ts +1 -1
- package/dist/types/preview/preview/types.d.ts +81 -0
- package/dist/types/preview/preview/unwrapNativeCollateral.d.ts +19 -4
- package/dist/types/sdk/OnchainSDK.d.ts +3 -6
- package/dist/types/sdk/accounts/CreditAccountsServiceV310.d.ts +5 -1
- package/dist/types/sdk/accounts/types.d.ts +32 -3
- package/dist/types/sdk/accounts/withdrawal-compressor/WithdrawalCompressorV313Contract.d.ts +4 -0
- package/dist/types/sdk/accounts/withdrawal-compressor/addresses.d.ts +1 -2
- package/dist/types/sdk/accounts/withdrawal-compressor/createWithdrawalCompressor.d.ts +2 -4
- package/dist/types/sdk/accounts/withdrawal-compressor/types.d.ts +7 -0
- package/package.json +1 -1
|
@@ -786,8 +786,7 @@ class CreditAccountsServiceV310 extends import_base.SDKConstruct {
|
|
|
786
786
|
token,
|
|
787
787
|
intent
|
|
788
788
|
}) {
|
|
789
|
-
|
|
790
|
-
return compressor.getWithdrawalRequestResult(
|
|
789
|
+
return this.sdk.withdrawalCompressor.getWithdrawalRequestResult(
|
|
791
790
|
creditAccount,
|
|
792
791
|
token,
|
|
793
792
|
amount,
|
|
@@ -800,8 +799,7 @@ class CreditAccountsServiceV310 extends import_base.SDKConstruct {
|
|
|
800
799
|
async getPendingWithdrawals({
|
|
801
800
|
creditAccount
|
|
802
801
|
}) {
|
|
803
|
-
const
|
|
804
|
-
const { claimable, pending } = await compressor.getCurrentWithdrawals(creditAccount);
|
|
802
|
+
const { claimable, pending } = await this.sdk.withdrawalCompressor.getCurrentWithdrawals(creditAccount);
|
|
805
803
|
return {
|
|
806
804
|
claimableNow: claimable,
|
|
807
805
|
pending
|
|
@@ -843,6 +841,45 @@ class CreditAccountsServiceV310 extends import_base.SDKConstruct {
|
|
|
843
841
|
};
|
|
844
842
|
return [storeExpectedBalances, ...preview.requestCalls, compareBalances];
|
|
845
843
|
}
|
|
844
|
+
/**
|
|
845
|
+
* {@inheritDoc ICreditAccountsService.assembleClaimDelayedCalls}
|
|
846
|
+
**/
|
|
847
|
+
assembleClaimDelayedCalls({
|
|
848
|
+
creditFacade,
|
|
849
|
+
claimableNow
|
|
850
|
+
}) {
|
|
851
|
+
const record = claimableNow.outputs.reduce(
|
|
852
|
+
(acc, o) => {
|
|
853
|
+
const token = o.token.toLowerCase();
|
|
854
|
+
acc[token] = (acc[token] || 0n) + o.amount;
|
|
855
|
+
return acc;
|
|
856
|
+
},
|
|
857
|
+
{}
|
|
858
|
+
);
|
|
859
|
+
const balances = Object.entries(record).filter(([, a]) => a > 10n);
|
|
860
|
+
const storeExpectedBalances = {
|
|
861
|
+
target: creditFacade,
|
|
862
|
+
callData: (0, import_viem.encodeFunctionData)({
|
|
863
|
+
abi: import_generated.iCreditFacadeMulticallV310Abi,
|
|
864
|
+
functionName: "storeExpectedBalances",
|
|
865
|
+
args: [
|
|
866
|
+
balances.map(([token, amount]) => ({
|
|
867
|
+
token,
|
|
868
|
+
amount: amount > 10n ? amount - 10n : 0n
|
|
869
|
+
}))
|
|
870
|
+
]
|
|
871
|
+
})
|
|
872
|
+
};
|
|
873
|
+
const compareBalances = {
|
|
874
|
+
target: creditFacade,
|
|
875
|
+
callData: (0, import_viem.encodeFunctionData)({
|
|
876
|
+
abi: import_generated.iCreditFacadeMulticallV310Abi,
|
|
877
|
+
functionName: "compareBalances",
|
|
878
|
+
args: []
|
|
879
|
+
})
|
|
880
|
+
};
|
|
881
|
+
return [storeExpectedBalances, ...claimableNow.claimCalls, compareBalances];
|
|
882
|
+
}
|
|
846
883
|
/**
|
|
847
884
|
* {@inheritDoc ICreditAccountsService.startDelayedWithdrawal}
|
|
848
885
|
**/
|
|
@@ -886,44 +923,15 @@ class CreditAccountsServiceV310 extends import_base.SDKConstruct {
|
|
|
886
923
|
const cm = this.sdk.marketRegister.findCreditManager(
|
|
887
924
|
creditAccount.creditManager
|
|
888
925
|
);
|
|
889
|
-
const record = claimableNow.outputs.reduce(
|
|
890
|
-
(acc, o) => {
|
|
891
|
-
const token = o.token.toLowerCase();
|
|
892
|
-
acc[token] = (acc[token] || 0n) + o.amount;
|
|
893
|
-
return acc;
|
|
894
|
-
},
|
|
895
|
-
{}
|
|
896
|
-
);
|
|
897
|
-
const balances = Object.entries(record).filter(([, a]) => a > 10n);
|
|
898
|
-
const storeExpectedBalances = {
|
|
899
|
-
target: cm.creditFacade.address,
|
|
900
|
-
callData: (0, import_viem.encodeFunctionData)({
|
|
901
|
-
abi: import_generated.iCreditFacadeMulticallV310Abi,
|
|
902
|
-
functionName: "storeExpectedBalances",
|
|
903
|
-
args: [
|
|
904
|
-
balances.map(([token, amount]) => ({
|
|
905
|
-
token,
|
|
906
|
-
amount: amount > 10n ? amount - 10n : 0n
|
|
907
|
-
}))
|
|
908
|
-
]
|
|
909
|
-
})
|
|
910
|
-
};
|
|
911
|
-
const compareBalances = {
|
|
912
|
-
target: cm.creditFacade.address,
|
|
913
|
-
callData: (0, import_viem.encodeFunctionData)({
|
|
914
|
-
abi: import_generated.iCreditFacadeMulticallV310Abi,
|
|
915
|
-
functionName: "compareBalances",
|
|
916
|
-
args: []
|
|
917
|
-
})
|
|
918
|
-
};
|
|
919
926
|
const quotaCalls = zeroDebt ? [] : this.#prepareUpdateQuotas(cm.creditFacade.address, {
|
|
920
927
|
minQuota,
|
|
921
928
|
averageQuota
|
|
922
929
|
});
|
|
923
930
|
const operationCalls = [
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
931
|
+
...this.assembleClaimDelayedCalls({
|
|
932
|
+
creditFacade: cm.creditFacade.address,
|
|
933
|
+
claimableNow
|
|
934
|
+
}),
|
|
927
935
|
...quotaCalls
|
|
928
936
|
];
|
|
929
937
|
const calls = zeroDebt ? operationCalls : await this.#prependPriceUpdates(
|
|
@@ -107,7 +107,7 @@ class AbstractWithdrawalCompressorContract extends import_base.BaseContract {
|
|
|
107
107
|
claimable: claimable.map(
|
|
108
108
|
(w) => toClaimableWithdrawal(w, creditManager, this.version >= 313)
|
|
109
109
|
),
|
|
110
|
-
pending: pending.map(toPendingWithdrawal).sort((a, b) => a.claimableAt < b.claimableAt ? -1 : 1)
|
|
110
|
+
pending: pending.map((w) => toPendingWithdrawal(w, creditManager, this.version >= 313)).sort((a, b) => a.claimableAt < b.claimableAt ? -1 : 1)
|
|
111
111
|
};
|
|
112
112
|
}
|
|
113
113
|
/**
|
|
@@ -127,8 +127,8 @@ class AbstractWithdrawalCompressorContract extends import_base.BaseContract {
|
|
|
127
127
|
return {
|
|
128
128
|
token: resp.token,
|
|
129
129
|
amountIn: resp.amountIn,
|
|
130
|
-
outputs: resp.outputs
|
|
131
|
-
requestCalls: resp.requestCalls
|
|
130
|
+
outputs: [...resp.outputs],
|
|
131
|
+
requestCalls: [...resp.requestCalls],
|
|
132
132
|
claimableAt: resp.claimableAt
|
|
133
133
|
};
|
|
134
134
|
}
|
|
@@ -180,21 +180,8 @@ class AbstractWithdrawalCompressorContract extends import_base.BaseContract {
|
|
|
180
180
|
]);
|
|
181
181
|
}
|
|
182
182
|
}
|
|
183
|
-
function toWithdrawalOutput(o) {
|
|
184
|
-
return { token: o.token, isDelayed: o.isDelayed, amount: o.amount };
|
|
185
|
-
}
|
|
186
|
-
function toMultiCall(c) {
|
|
187
|
-
return { target: c.target, callData: c.callData };
|
|
188
|
-
}
|
|
189
183
|
function toWithdrawableAsset(a, creditManager) {
|
|
190
|
-
return {
|
|
191
|
-
creditManager,
|
|
192
|
-
token: a.token,
|
|
193
|
-
withdrawalPhantomToken: a.withdrawalPhantomToken,
|
|
194
|
-
underlying: a.underlying,
|
|
195
|
-
withdrawalLength: a.withdrawalLength,
|
|
196
|
-
maxWithdrawals: a.maxWithdrawals
|
|
197
|
-
};
|
|
184
|
+
return { creditManager, ...a };
|
|
198
185
|
}
|
|
199
186
|
function toClaimableWithdrawal(w, creditManager, decodeIntent) {
|
|
200
187
|
let intent;
|
|
@@ -205,17 +192,22 @@ function toClaimableWithdrawal(w, creditManager, decodeIntent) {
|
|
|
205
192
|
token: w.token,
|
|
206
193
|
withdrawalPhantomToken: w.withdrawalPhantomToken,
|
|
207
194
|
withdrawalTokenSpent: w.withdrawalTokenSpent,
|
|
208
|
-
outputs: w.outputs
|
|
209
|
-
claimCalls: w.claimCalls
|
|
195
|
+
outputs: [...w.outputs],
|
|
196
|
+
claimCalls: [...w.claimCalls],
|
|
210
197
|
intent
|
|
211
198
|
};
|
|
212
199
|
}
|
|
213
|
-
function toPendingWithdrawal(w) {
|
|
200
|
+
function toPendingWithdrawal(w, creditManager, decodeIntent) {
|
|
201
|
+
let intent;
|
|
202
|
+
if (decodeIntent && w.extraData && w.extraData !== "0x") {
|
|
203
|
+
intent = { ...(0, import_intent_codec.decodeDelayedIntent)(w.extraData), creditManager };
|
|
204
|
+
}
|
|
214
205
|
return {
|
|
215
206
|
token: w.token,
|
|
216
207
|
withdrawalPhantomToken: w.withdrawalPhantomToken,
|
|
217
|
-
expectedOutputs: w.expectedOutputs
|
|
218
|
-
claimableAt: w.claimableAt
|
|
208
|
+
expectedOutputs: [...w.expectedOutputs],
|
|
209
|
+
claimableAt: w.claimableAt,
|
|
210
|
+
intent
|
|
219
211
|
};
|
|
220
212
|
}
|
|
221
213
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -23,28 +23,16 @@ __export(addresses_exports, {
|
|
|
23
23
|
module.exports = __toCommonJS(addresses_exports);
|
|
24
24
|
const WITHDRAWAL_COMPRESSORS = {
|
|
25
25
|
Mainnet: {
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
address: "0x83e5AaC6590Cf9c6Dd323851a0D66fEc2Bc4F5A3",
|
|
27
|
+
version: 313
|
|
28
28
|
},
|
|
29
29
|
Monad: {
|
|
30
|
-
|
|
30
|
+
address: "0x36F3d0Bb73CBC2E94fE24dF0f26a689409cF9023",
|
|
31
|
+
version: 310
|
|
31
32
|
}
|
|
32
33
|
};
|
|
33
|
-
function getWithdrawalCompressorAddress(network
|
|
34
|
-
|
|
35
|
-
if (!deployments) {
|
|
36
|
-
return void 0;
|
|
37
|
-
}
|
|
38
|
-
if (version !== void 0) {
|
|
39
|
-
const address2 = deployments[version];
|
|
40
|
-
return address2 ? { address: address2, version } : void 0;
|
|
41
|
-
}
|
|
42
|
-
const latest = Object.keys(deployments).map(Number).sort((a, b) => b - a)[0];
|
|
43
|
-
if (latest === void 0) {
|
|
44
|
-
return void 0;
|
|
45
|
-
}
|
|
46
|
-
const address = deployments[latest];
|
|
47
|
-
return address ? { address, version: latest } : void 0;
|
|
34
|
+
function getWithdrawalCompressorAddress(network) {
|
|
35
|
+
return WITHDRAWAL_COMPRESSORS[network];
|
|
48
36
|
}
|
|
49
37
|
// Annotate the CommonJS export names for ESM import in node:
|
|
50
38
|
0 && (module.exports = {
|
|
@@ -25,12 +25,10 @@ var import_addresses = require("./addresses.js");
|
|
|
25
25
|
var import_WithdrawalCompressorV310Contract = require("./WithdrawalCompressorV310Contract.js");
|
|
26
26
|
var import_WithdrawalCompressorV311Contract = require("./WithdrawalCompressorV311Contract.js");
|
|
27
27
|
var import_WithdrawalCompressorV313Contract = require("./WithdrawalCompressorV313Contract.js");
|
|
28
|
-
function createWithdrawalCompressor(sdk
|
|
29
|
-
const location = (0, import_addresses.getWithdrawalCompressorAddress)(sdk.networkType
|
|
28
|
+
function createWithdrawalCompressor(sdk) {
|
|
29
|
+
const location = (0, import_addresses.getWithdrawalCompressorAddress)(sdk.networkType);
|
|
30
30
|
if (!location) {
|
|
31
|
-
throw new Error(
|
|
32
|
-
`no withdrawal compressor${version ? ` v${version}` : ""} on ${sdk.networkType}`
|
|
33
|
-
);
|
|
31
|
+
throw new Error(`no withdrawal compressor on ${sdk.networkType}`);
|
|
34
32
|
}
|
|
35
33
|
const cached = sdk.getContract(
|
|
36
34
|
location.address
|
|
@@ -72,7 +72,8 @@ const iWithdrawalCompressorV313Abi = [
|
|
|
72
72
|
{ name: "amount", type: "uint256", internalType: "uint256" }
|
|
73
73
|
]
|
|
74
74
|
},
|
|
75
|
-
{ name: "claimableAt", type: "uint256", internalType: "uint256" }
|
|
75
|
+
{ name: "claimableAt", type: "uint256", internalType: "uint256" },
|
|
76
|
+
{ name: "extraData", type: "bytes", internalType: "bytes" }
|
|
76
77
|
]
|
|
77
78
|
}
|
|
78
79
|
],
|
|
@@ -94,7 +94,8 @@ const withdrawalCompressorAbi = [
|
|
|
94
94
|
{ name: "amount", type: "uint256", internalType: "uint256" }
|
|
95
95
|
]
|
|
96
96
|
},
|
|
97
|
-
{ name: "claimableAt", type: "uint256", internalType: "uint256" }
|
|
97
|
+
{ name: "claimableAt", type: "uint256", internalType: "uint256" },
|
|
98
|
+
{ name: "extraData", type: "bytes", internalType: "bytes" }
|
|
98
99
|
]
|
|
99
100
|
}
|
|
100
101
|
],
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AddressMap,
|
|
3
|
-
BasePlugin
|
|
4
|
-
} from "../../sdk/index.js";
|
|
1
|
+
import { AddressMap, BasePlugin } from "../../sdk/index.js";
|
|
5
2
|
const MAP_LABEL = "delayedWithdrawal";
|
|
6
3
|
class DelayedWithdrawalPlugin extends BasePlugin {
|
|
7
4
|
#withdrawableAssets;
|
|
@@ -10,11 +7,7 @@ class DelayedWithdrawalPlugin extends BasePlugin {
|
|
|
10
7
|
return this.state;
|
|
11
8
|
}
|
|
12
9
|
this.#withdrawableAssets = new AddressMap(void 0, MAP_LABEL);
|
|
13
|
-
const
|
|
14
|
-
this.sdk.logger?.debug(
|
|
15
|
-
`loading delayed withdrawal plugin with compressor ${compressor.address}`
|
|
16
|
-
);
|
|
17
|
-
const resp = await compressor.getWithdrawableAssetsBatch();
|
|
10
|
+
const resp = await this.sdk.withdrawalCompressor.getWithdrawableAssetsBatch();
|
|
18
11
|
const byCreditManager = /* @__PURE__ */ new Map();
|
|
19
12
|
for (const cfg of resp) {
|
|
20
13
|
const assets = byCreditManager.get(cfg.creditManager) ?? [];
|
|
@@ -4,10 +4,16 @@ import {
|
|
|
4
4
|
} from "../../plugins/adapters/index.js";
|
|
5
5
|
import {
|
|
6
6
|
AssetsMap,
|
|
7
|
-
MAX_UINT256
|
|
8
|
-
MIN_INT96
|
|
7
|
+
MAX_UINT256
|
|
9
8
|
} from "../../sdk/index.js";
|
|
10
9
|
import { applyRWAWrapUnwrap } from "./applyRWAWrapUnwrap.js";
|
|
10
|
+
import {
|
|
11
|
+
ERROR_ADAPTER_CALL_OUTSIDE_BRACKET,
|
|
12
|
+
ERROR_MALFORMED_BRACKET,
|
|
13
|
+
ERROR_NON_ADAPTER_CALL_IN_BRACKET,
|
|
14
|
+
ERROR_UNPREVIEWABLE_ADAPTER_CALL,
|
|
15
|
+
ERROR_UNPREVIEWABLE_RWA_WRAP_UNWRAP
|
|
16
|
+
} from "./types.js";
|
|
11
17
|
function makeInnerOperationsState() {
|
|
12
18
|
return {
|
|
13
19
|
balances: new AssetsMap(),
|
|
@@ -21,41 +27,31 @@ function makeInnerOperationsState() {
|
|
|
21
27
|
function applyInnerOperations(sdk, multicall, state) {
|
|
22
28
|
let inBracket = false;
|
|
23
29
|
let storeSeen = false;
|
|
30
|
+
let error;
|
|
24
31
|
for (const op of multicall) {
|
|
32
|
+
let opError;
|
|
25
33
|
switch (op.operation) {
|
|
26
34
|
case "AddCollateral":
|
|
27
|
-
state
|
|
28
|
-
state.balances.inc(op.token, op.amount);
|
|
35
|
+
applyAddCollateral(state, op);
|
|
29
36
|
break;
|
|
30
|
-
case "WithdrawCollateral":
|
|
31
|
-
|
|
32
|
-
const amount = op.amount === MAX_UINT256 ? running > 0n ? running : 0n : op.amount;
|
|
33
|
-
state.balances.dec(op.token, amount);
|
|
34
|
-
state.collateralWithdrawn.inc(op.token, amount);
|
|
37
|
+
case "WithdrawCollateral":
|
|
38
|
+
applyWithdrawCollateral(state, op);
|
|
35
39
|
break;
|
|
36
|
-
}
|
|
37
40
|
case "IncreaseBorrowedAmount":
|
|
38
|
-
state
|
|
39
|
-
state.totalDebt += op.amount;
|
|
40
|
-
state.balances.inc(op.token, op.amount);
|
|
41
|
+
applyIncreaseDebt(state, op);
|
|
41
42
|
break;
|
|
42
|
-
case "DecreaseBorrowedAmount":
|
|
43
|
-
|
|
44
|
-
state.balances.dec(op.token, repaid);
|
|
45
|
-
state.totalDebt -= repaid;
|
|
46
|
-
if (state.debt > state.totalDebt) {
|
|
47
|
-
state.debt = state.totalDebt;
|
|
48
|
-
}
|
|
43
|
+
case "DecreaseBorrowedAmount":
|
|
44
|
+
applyDecreaseDebt(state, op);
|
|
49
45
|
break;
|
|
50
|
-
}
|
|
51
46
|
case "UpdateQuota":
|
|
52
47
|
state.quotaChanges.push({ token: op.token, balance: op.change });
|
|
53
48
|
break;
|
|
54
49
|
case "StoreExpectedBalances":
|
|
55
50
|
if (storeSeen) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
51
|
+
opError = {
|
|
52
|
+
code: ERROR_MALFORMED_BRACKET,
|
|
53
|
+
message: "duplicate storeExpectedBalances call"
|
|
54
|
+
};
|
|
59
55
|
}
|
|
60
56
|
storeSeen = true;
|
|
61
57
|
inBracket = true;
|
|
@@ -65,32 +61,83 @@ function applyInnerOperations(sdk, multicall, state) {
|
|
|
65
61
|
break;
|
|
66
62
|
case "CompareBalances":
|
|
67
63
|
if (!inBracket) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
64
|
+
opError = {
|
|
65
|
+
code: ERROR_MALFORMED_BRACKET,
|
|
66
|
+
message: "compareBalances without a preceding storeExpectedBalances"
|
|
67
|
+
};
|
|
71
68
|
}
|
|
72
69
|
inBracket = false;
|
|
73
70
|
break;
|
|
74
|
-
case "Execute":
|
|
75
|
-
|
|
76
|
-
if (inBracket) {
|
|
77
|
-
if (!(adapter instanceof AbstractAdapterContract)) {
|
|
78
|
-
throw new Error(
|
|
79
|
-
`call to ${op.adapter} between storeExpectedBalances and compareBalances is not an adapter call`
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
adapter.previewBalanceChanges(state.balances, op.calldata);
|
|
83
|
-
} else if (isRWAShare(sdk, adapter)) {
|
|
84
|
-
applyRWAWrapUnwrap(adapter, op.calldata, state.balances);
|
|
85
|
-
}
|
|
71
|
+
case "Execute":
|
|
72
|
+
opError = applyExecute(sdk, op, inBracket, state.balances);
|
|
86
73
|
break;
|
|
87
|
-
}
|
|
88
74
|
}
|
|
75
|
+
error ??= opError;
|
|
89
76
|
}
|
|
90
77
|
if (inBracket) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
78
|
+
error ??= {
|
|
79
|
+
code: ERROR_MALFORMED_BRACKET,
|
|
80
|
+
message: "storeExpectedBalances without a matching compareBalances"
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
return error;
|
|
84
|
+
}
|
|
85
|
+
function applyAddCollateral(state, op) {
|
|
86
|
+
state.collateralAdded.inc(op.token, op.amount);
|
|
87
|
+
state.balances.inc(op.token, op.amount);
|
|
88
|
+
}
|
|
89
|
+
function applyWithdrawCollateral(state, op) {
|
|
90
|
+
const running = state.balances.getOrZero(op.token);
|
|
91
|
+
const amount = op.amount === MAX_UINT256 ? running > 0n ? running : 0n : op.amount;
|
|
92
|
+
state.balances.dec(op.token, amount);
|
|
93
|
+
state.collateralWithdrawn.inc(op.token, amount);
|
|
94
|
+
}
|
|
95
|
+
function applyIncreaseDebt(state, op) {
|
|
96
|
+
state.debt += op.amount;
|
|
97
|
+
state.totalDebt += op.amount;
|
|
98
|
+
state.balances.inc(op.token, op.amount);
|
|
99
|
+
}
|
|
100
|
+
function applyDecreaseDebt(state, op) {
|
|
101
|
+
const repaid = op.amount > state.totalDebt ? state.totalDebt : op.amount;
|
|
102
|
+
state.balances.dec(op.token, repaid);
|
|
103
|
+
state.totalDebt -= repaid;
|
|
104
|
+
if (state.debt > state.totalDebt) {
|
|
105
|
+
state.debt = state.totalDebt;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function applyExecute(sdk, op, inBracket, balances) {
|
|
109
|
+
const adapter = sdk.getContract(op.adapter);
|
|
110
|
+
if (!inBracket) {
|
|
111
|
+
if (!isRWAShare(sdk, adapter)) {
|
|
112
|
+
return {
|
|
113
|
+
code: ERROR_ADAPTER_CALL_OUTSIDE_BRACKET,
|
|
114
|
+
message: `call to ${op.adapter} outside of a storeExpectedBalances/compareBalances bracket`
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
try {
|
|
118
|
+
applyRWAWrapUnwrap(adapter, op.calldata, balances);
|
|
119
|
+
return void 0;
|
|
120
|
+
} catch (e) {
|
|
121
|
+
return {
|
|
122
|
+
code: ERROR_UNPREVIEWABLE_RWA_WRAP_UNWRAP,
|
|
123
|
+
message: e instanceof Error ? e.message : String(e)
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (!(adapter instanceof AbstractAdapterContract)) {
|
|
128
|
+
return {
|
|
129
|
+
code: ERROR_NON_ADAPTER_CALL_IN_BRACKET,
|
|
130
|
+
message: `call to ${op.adapter} between storeExpectedBalances and compareBalances is not an adapter call`
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
try {
|
|
134
|
+
adapter.previewBalanceChanges(balances, op.calldata);
|
|
135
|
+
return void 0;
|
|
136
|
+
} catch (e) {
|
|
137
|
+
return {
|
|
138
|
+
code: ERROR_UNPREVIEWABLE_ADAPTER_CALL,
|
|
139
|
+
message: e instanceof Error ? e.message : String(e)
|
|
140
|
+
};
|
|
94
141
|
}
|
|
95
142
|
}
|
|
96
143
|
function isRWAShare(sdk, adapter) {
|
|
@@ -100,23 +147,7 @@ function isRWAShare(sdk, adapter) {
|
|
|
100
147
|
}
|
|
101
148
|
return false;
|
|
102
149
|
}
|
|
103
|
-
function applyQuotaChanges(initialQuotas, changes) {
|
|
104
|
-
const final = initialQuotas.clone();
|
|
105
|
-
for (const { token, balance: change } of changes) {
|
|
106
|
-
if (change === MIN_INT96) {
|
|
107
|
-
final.upsert(token, 0n);
|
|
108
|
-
} else {
|
|
109
|
-
const next = final.getOrZero(token) + change;
|
|
110
|
-
final.upsert(token, next > 0n ? next : 0n);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
return {
|
|
114
|
-
quotas: final.toAssets(0n),
|
|
115
|
-
quotasChange: final.difference(initialQuotas).toAssets()
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
150
|
export {
|
|
119
151
|
applyInnerOperations,
|
|
120
|
-
applyQuotaChanges,
|
|
121
152
|
makeInnerOperationsState
|
|
122
153
|
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { MIN_INT96 } from "../../sdk/index.js";
|
|
2
|
+
function applyQuotaChanges(initialQuotas, changes) {
|
|
3
|
+
const final = initialQuotas.clone();
|
|
4
|
+
for (const { token, balance: change } of changes) {
|
|
5
|
+
if (change === MIN_INT96) {
|
|
6
|
+
final.upsert(token, 0n);
|
|
7
|
+
} else {
|
|
8
|
+
const next = final.getOrZero(token) + change;
|
|
9
|
+
final.upsert(token, next > 0n ? next : 0n);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return {
|
|
13
|
+
quotas: final.toAssets(0n),
|
|
14
|
+
quotasChange: final.difference(initialQuotas).toAssets()
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export {
|
|
18
|
+
applyQuotaChanges
|
|
19
|
+
};
|
|
@@ -1,17 +1,3 @@
|
|
|
1
|
-
class InvalidTransactionValueError extends Error {
|
|
2
|
-
/** Transaction `msg.value`. */
|
|
3
|
-
value;
|
|
4
|
-
/** Amount of wrapped native token added as collateral. */
|
|
5
|
-
wethCollateral;
|
|
6
|
-
constructor(value, wethCollateral) {
|
|
7
|
-
super(
|
|
8
|
-
`transaction value ${value} exceeds WETH collateral ${wethCollateral}`
|
|
9
|
-
);
|
|
10
|
-
this.name = "InvalidTransactionValueError";
|
|
11
|
-
this.value = value;
|
|
12
|
-
this.wethCollateral = wethCollateral;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
1
|
class UnsupportedOperationError extends Error {
|
|
16
2
|
/** The parsed operation kind (the `operation` discriminant). */
|
|
17
3
|
operation;
|
|
@@ -22,6 +8,5 @@ class UnsupportedOperationError extends Error {
|
|
|
22
8
|
}
|
|
23
9
|
}
|
|
24
10
|
export {
|
|
25
|
-
InvalidTransactionValueError,
|
|
26
11
|
UnsupportedOperationError
|
|
27
12
|
};
|
|
@@ -5,9 +5,12 @@ import {
|
|
|
5
5
|
} from "../../sdk/index.js";
|
|
6
6
|
import {
|
|
7
7
|
applyInnerOperations,
|
|
8
|
-
applyQuotaChanges,
|
|
9
8
|
makeInnerOperationsState
|
|
10
9
|
} from "./applyInnerOperations.js";
|
|
10
|
+
import { applyQuotaChanges } from "./applyQuotaChanges.js";
|
|
11
|
+
import {
|
|
12
|
+
ERROR_UNPRICEABLE_TOKEN
|
|
13
|
+
} from "./types.js";
|
|
11
14
|
import { unwrapNativeCollateral } from "./unwrapNativeCollateral.js";
|
|
12
15
|
async function previewAdjustCreditAccount(input, operation, options) {
|
|
13
16
|
const { sdk, value = 0n } = input;
|
|
@@ -38,22 +41,30 @@ async function previewAdjustCreditAccount(input, operation, options) {
|
|
|
38
41
|
state.balances = initialBalances.clone();
|
|
39
42
|
state.debt = ca.debt;
|
|
40
43
|
state.totalDebt = ca.debt + ca.accruedInterest + ca.accruedFees;
|
|
41
|
-
applyInnerOperations(sdk, operation.multicall, state);
|
|
42
|
-
const collateralAdded = unwrapNativeCollateral(
|
|
44
|
+
let error = applyInnerOperations(sdk, operation.multicall, state);
|
|
45
|
+
const { assets: collateralAdded, error: unwrapError } = unwrapNativeCollateral(
|
|
43
46
|
state.collateralAdded.toAssets(),
|
|
44
47
|
value,
|
|
45
48
|
sdk.addressProvider.getAddress(AP_WETH_TOKEN, NO_VERSION)
|
|
46
49
|
);
|
|
50
|
+
error ??= unwrapError;
|
|
47
51
|
const { quotas, quotasChange } = applyQuotaChanges(
|
|
48
52
|
initialQuotas,
|
|
49
53
|
state.quotaChanges
|
|
50
54
|
);
|
|
51
55
|
const assets = state.balances.toAssets(1n);
|
|
52
56
|
const assetsChange = state.balances.difference(initialBalances).toAssets(1n);
|
|
53
|
-
const totalValue = assets.reduce(
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
+
const totalValue = assets.reduce((acc, { token, balance }) => {
|
|
58
|
+
try {
|
|
59
|
+
return acc + market.priceOracle.convert(token, market.underlying, balance);
|
|
60
|
+
} catch {
|
|
61
|
+
error ??= {
|
|
62
|
+
code: ERROR_UNPRICEABLE_TOKEN,
|
|
63
|
+
message: `cannot price token ${token}`
|
|
64
|
+
};
|
|
65
|
+
return acc;
|
|
66
|
+
}
|
|
67
|
+
}, 0n);
|
|
57
68
|
return {
|
|
58
69
|
operation: "AdjustCreditAccount",
|
|
59
70
|
creditManager: operation.creditManager,
|
|
@@ -66,7 +77,8 @@ async function previewAdjustCreditAccount(input, operation, options) {
|
|
|
66
77
|
quotas,
|
|
67
78
|
quotasChange,
|
|
68
79
|
assets,
|
|
69
|
-
assetsChange
|
|
80
|
+
assetsChange,
|
|
81
|
+
error
|
|
70
82
|
};
|
|
71
83
|
}
|
|
72
84
|
export {
|
|
@@ -21,23 +21,31 @@ async function previewCloseCreditAccount(input, operation, permanent, options) {
|
|
|
21
21
|
const market = sdk.marketRegister.findByCreditManager(
|
|
22
22
|
operation.creditManager
|
|
23
23
|
);
|
|
24
|
-
const { state } = await replayMulticall(sdk, operation, options);
|
|
24
|
+
const { state, error } = await replayMulticall(sdk, operation, options);
|
|
25
25
|
return {
|
|
26
26
|
operation: "CloseCreditAccount",
|
|
27
27
|
permanent,
|
|
28
28
|
creditManager: operation.creditManager,
|
|
29
29
|
creditAccount: operation.creditAccount,
|
|
30
|
-
|
|
30
|
+
// On a malformed multicall the withdrawn amount depends on best-effort
|
|
31
|
+
// replayed balances and may be unreliable
|
|
32
|
+
receivedAmount: state.collateralWithdrawn.getOrZero(market.underlying),
|
|
33
|
+
error
|
|
31
34
|
};
|
|
32
35
|
}
|
|
33
36
|
async function previewRepayCreditAccount(input, operation, permanent, options) {
|
|
34
37
|
const { sdk, value = 0n } = input;
|
|
35
|
-
const {
|
|
36
|
-
|
|
38
|
+
const {
|
|
39
|
+
ca,
|
|
40
|
+
state,
|
|
41
|
+
error: replayError
|
|
42
|
+
} = await replayMulticall(sdk, operation, options);
|
|
43
|
+
const { assets: collateralAdded, error: unwrapError } = unwrapNativeCollateral(
|
|
37
44
|
state.collateralAdded.toAssets(),
|
|
38
45
|
value,
|
|
39
46
|
sdk.addressProvider.getAddress(AP_WETH_TOKEN, NO_VERSION)
|
|
40
47
|
);
|
|
48
|
+
const error = replayError ?? unwrapError;
|
|
41
49
|
const initialTotalDebt = ca.debt + ca.accruedInterest + ca.accruedFees;
|
|
42
50
|
return {
|
|
43
51
|
operation: "RepayCreditAccount",
|
|
@@ -46,7 +54,10 @@ async function previewRepayCreditAccount(input, operation, permanent, options) {
|
|
|
46
54
|
creditAccount: operation.creditAccount,
|
|
47
55
|
collateralAdded,
|
|
48
56
|
debtRepaid: initialTotalDebt - state.totalDebt,
|
|
49
|
-
|
|
57
|
+
// On a malformed multicall the MAX_UINT256 withdrawal sentinel resolves
|
|
58
|
+
// against best-effort replayed balances and may be unreliable
|
|
59
|
+
collateralWithdrawn: state.collateralWithdrawn.toAssets(),
|
|
60
|
+
error
|
|
50
61
|
};
|
|
51
62
|
}
|
|
52
63
|
async function replayMulticall(sdk, operation, options) {
|
|
@@ -68,8 +79,8 @@ async function replayMulticall(sdk, operation, options) {
|
|
|
68
79
|
}
|
|
69
80
|
state.debt = ca.debt;
|
|
70
81
|
state.totalDebt = ca.debt + ca.accruedInterest + ca.accruedFees;
|
|
71
|
-
applyInnerOperations(sdk, operation.multicall, state);
|
|
72
|
-
return { ca, state };
|
|
82
|
+
const error = applyInnerOperations(sdk, operation.multicall, state);
|
|
83
|
+
return { ca, state, error };
|
|
73
84
|
}
|
|
74
85
|
export {
|
|
75
86
|
previewCloseOrRepayCreditAccount
|