@eulerxyz/euler-v2-sdk 0.2.6-beta → 0.2.8-beta
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/src/entities/Account.d.ts +10 -2
- package/dist/src/entities/Account.d.ts.map +1 -1
- package/dist/src/entities/Account.js +15 -2
- package/dist/src/entities/Account.js.map +1 -1
- package/dist/src/entities/EVault.d.ts +6 -1
- package/dist/src/entities/EVault.d.ts.map +1 -1
- package/dist/src/entities/EVault.js.map +1 -1
- package/dist/src/entities/Portfolio.d.ts +143 -18
- package/dist/src/entities/Portfolio.d.ts.map +1 -1
- package/dist/src/entities/Portfolio.js +240 -36
- package/dist/src/entities/Portfolio.js.map +1 -1
- package/dist/src/plugins/keyring/keyringPlugin.d.ts.map +1 -1
- package/dist/src/plugins/keyring/keyringPlugin.js +67 -17
- package/dist/src/plugins/keyring/keyringPlugin.js.map +1 -1
- package/dist/src/plugins/pyth/pythPlugin.d.ts +3 -1
- package/dist/src/plugins/pyth/pythPlugin.d.ts.map +1 -1
- package/dist/src/plugins/pyth/pythPlugin.js +101 -6
- package/dist/src/plugins/pyth/pythPlugin.js.map +1 -1
- package/dist/src/plugins/types.d.ts +38 -2
- package/dist/src/plugins/types.d.ts.map +1 -1
- package/dist/src/plugins/types.js.map +1 -1
- package/dist/src/sdk/buildSDK.d.ts.map +1 -1
- package/dist/src/sdk/buildSDK.js +3 -2
- package/dist/src/sdk/buildSDK.js.map +1 -1
- package/dist/src/sdk/sdk.d.ts +15 -4
- package/dist/src/sdk/sdk.d.ts.map +1 -1
- package/dist/src/sdk/sdk.js +40 -3
- package/dist/src/sdk/sdk.js.map +1 -1
- package/dist/src/services/accountService/accountService.d.ts +7 -1
- package/dist/src/services/accountService/accountService.d.ts.map +1 -1
- package/dist/src/services/accountService/accountService.js +55 -1
- package/dist/src/services/accountService/accountService.js.map +1 -1
- package/dist/src/services/accountService/adapters/accountOnchainAdapter/accountOnchainAdapter.d.ts.map +1 -1
- package/dist/src/services/accountService/adapters/accountOnchainAdapter/accountOnchainAdapter.js +2 -2
- package/dist/src/services/accountService/adapters/accountOnchainAdapter/accountOnchainAdapter.js.map +1 -1
- package/dist/src/services/accountService/index.d.ts +1 -1
- package/dist/src/services/accountService/index.d.ts.map +1 -1
- package/dist/src/services/executionService/cowExecutor.d.ts +3 -0
- package/dist/src/services/executionService/cowExecutor.d.ts.map +1 -1
- package/dist/src/services/executionService/cowExecutor.js.map +1 -1
- package/dist/src/services/executionService/execute.d.ts +8 -0
- package/dist/src/services/executionService/execute.d.ts.map +1 -1
- package/dist/src/services/executionService/execute.js.map +1 -1
- package/dist/src/services/executionService/executionService.d.ts +70 -8
- package/dist/src/services/executionService/executionService.d.ts.map +1 -1
- package/dist/src/services/executionService/executionService.js +278 -124
- package/dist/src/services/executionService/executionService.js.map +1 -1
- package/dist/src/services/executionService/executionServiceTypes.d.ts +4 -0
- package/dist/src/services/executionService/executionServiceTypes.d.ts.map +1 -1
- package/dist/src/services/executionService/simulate.d.ts +29 -0
- package/dist/src/services/executionService/simulate.d.ts.map +1 -1
- package/dist/src/services/executionService/simulate.js +42 -5
- package/dist/src/services/executionService/simulate.js.map +1 -1
- package/dist/src/services/rewardsService/adapters/rewardsDirectAdapter/rewardsDirectAdapter.d.ts +2 -1
- package/dist/src/services/rewardsService/adapters/rewardsDirectAdapter/rewardsDirectAdapter.d.ts.map +1 -1
- package/dist/src/services/rewardsService/adapters/rewardsDirectAdapter/rewardsDirectAdapter.js +2 -2
- package/dist/src/services/rewardsService/adapters/rewardsDirectAdapter/rewardsDirectAdapter.js.map +1 -1
- package/dist/src/services/rewardsService/adapters/rewardsV3Adapter/rewardsV3Adapter.d.ts +2 -1
- package/dist/src/services/rewardsService/adapters/rewardsV3Adapter/rewardsV3Adapter.d.ts.map +1 -1
- package/dist/src/services/rewardsService/adapters/rewardsV3Adapter/rewardsV3Adapter.js +11 -2
- package/dist/src/services/rewardsService/adapters/rewardsV3Adapter/rewardsV3Adapter.js.map +1 -1
- package/dist/src/services/rewardsService/adapters/rewardsV3Adapter/rewardsV3AdapterTypes.d.ts +4 -0
- package/dist/src/services/rewardsService/adapters/rewardsV3Adapter/rewardsV3AdapterTypes.d.ts.map +1 -1
- package/dist/src/services/rewardsService/index.d.ts +4 -1
- package/dist/src/services/rewardsService/index.d.ts.map +1 -1
- package/dist/src/services/rewardsService/index.js +2 -0
- package/dist/src/services/rewardsService/index.js.map +1 -1
- package/dist/src/services/rewardsService/rewardCampaignEligibility.d.ts +32 -0
- package/dist/src/services/rewardsService/rewardCampaignEligibility.d.ts.map +1 -0
- package/dist/src/services/rewardsService/rewardCampaignEligibility.js +21 -0
- package/dist/src/services/rewardsService/rewardCampaignEligibility.js.map +1 -0
- package/dist/src/services/rewardsService/rewardsService.d.ts +6 -0
- package/dist/src/services/rewardsService/rewardsService.d.ts.map +1 -1
- package/dist/src/services/rewardsService/rewardsService.js +20 -3
- package/dist/src/services/rewardsService/rewardsService.js.map +1 -1
- package/dist/src/services/rewardsService/rewardsServiceTypes.d.ts +8 -5
- package/dist/src/services/rewardsService/rewardsServiceTypes.d.ts.map +1 -1
- package/dist/src/services/rewardsService/rewardsServiceTypes.js +1 -1
- package/dist/src/services/rewardsService/rewardsServiceTypes.js.map +1 -1
- package/dist/src/services/rewardsService/vaultRewardInfo.d.ts +25 -0
- package/dist/src/services/rewardsService/vaultRewardInfo.d.ts.map +1 -0
- package/dist/src/services/rewardsService/vaultRewardInfo.js +39 -0
- package/dist/src/services/rewardsService/vaultRewardInfo.js.map +1 -0
- package/dist/src/services/vaults/eVaultService/adapters/eVaultOnchainAdapter/eVaultLensTypes.d.ts +2 -1
- package/dist/src/services/vaults/eVaultService/adapters/eVaultOnchainAdapter/eVaultLensTypes.d.ts.map +1 -1
- package/dist/src/services/vaults/eVaultService/adapters/eVaultOnchainAdapter/eVaultLensTypes.js +1 -0
- package/dist/src/services/vaults/eVaultService/adapters/eVaultOnchainAdapter/eVaultLensTypes.js.map +1 -1
- package/dist/src/services/vaults/eVaultService/adapters/eVaultOnchainAdapter/vaultInfoConverter.d.ts.map +1 -1
- package/dist/src/services/vaults/eVaultService/adapters/eVaultOnchainAdapter/vaultInfoConverter.js +7 -0
- package/dist/src/services/vaults/eVaultService/adapters/eVaultOnchainAdapter/vaultInfoConverter.js.map +1 -1
- package/dist/src/services/vaults/eVaultService/adapters/eVaultV3Adapter/eVaultV3AdapterConversions.d.ts.map +1 -1
- package/dist/src/services/vaults/eVaultService/adapters/eVaultV3Adapter/eVaultV3AdapterConversions.js +17 -6
- package/dist/src/services/vaults/eVaultService/adapters/eVaultV3Adapter/eVaultV3AdapterConversions.js.map +1 -1
- package/dist/src/services/vaults/eulerEarnService/adapters/eulerEarnOnchainAdapter.d.ts.map +1 -1
- package/dist/src/services/vaults/eulerEarnService/adapters/eulerEarnOnchainAdapter.js +52 -17
- package/dist/src/services/vaults/eulerEarnService/adapters/eulerEarnOnchainAdapter.js.map +1 -1
- package/dist/src/utils/accountComputations.d.ts +41 -8
- package/dist/src/utils/accountComputations.d.ts.map +1 -1
- package/dist/src/utils/accountComputations.js +127 -77
- package/dist/src/utils/accountComputations.js.map +1 -1
- package/dist/src/utils/irm.d.ts +10 -2
- package/dist/src/utils/irm.d.ts.map +1 -1
- package/dist/src/utils/irm.js +33 -0
- package/dist/src/utils/irm.js.map +1 -1
- package/dist/src/utils/oracle.d.ts +16 -0
- package/dist/src/utils/oracle.d.ts.map +1 -1
- package/dist/src/utils/oracle.js +98 -0
- package/dist/src/utils/oracle.js.map +1 -1
- package/dist/src/utils/stateOverrides/approvalOverrides.d.ts +25 -8
- package/dist/src/utils/stateOverrides/approvalOverrides.d.ts.map +1 -1
- package/dist/src/utils/stateOverrides/approvalOverrides.js +76 -16
- package/dist/src/utils/stateOverrides/approvalOverrides.js.map +1 -1
- package/dist/src/utils/stateOverrides/balanceOverrides.d.ts +26 -7
- package/dist/src/utils/stateOverrides/balanceOverrides.d.ts.map +1 -1
- package/dist/src/utils/stateOverrides/balanceOverrides.js +72 -13
- package/dist/src/utils/stateOverrides/balanceOverrides.js.map +1 -1
- package/dist/src/utils/stateOverrides/getStateOverrides.d.ts +38 -0
- package/dist/src/utils/stateOverrides/getStateOverrides.d.ts.map +1 -1
- package/dist/src/utils/stateOverrides/getStateOverrides.js +14 -4
- package/dist/src/utils/stateOverrides/getStateOverrides.js.map +1 -1
- package/dist/src/utils/stateOverrides/index.d.ts +3 -2
- package/dist/src/utils/stateOverrides/index.d.ts.map +1 -1
- package/dist/src/utils/stateOverrides/index.js +2 -1
- package/dist/src/utils/stateOverrides/index.js.map +1 -1
- package/dist/src/utils/stateOverrides/slotHints.d.ts +78 -0
- package/dist/src/utils/stateOverrides/slotHints.d.ts.map +1 -0
- package/dist/src/utils/stateOverrides/slotHints.js +152 -0
- package/dist/src/utils/stateOverrides/slotHints.js.map +1 -0
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@ import { decodeFunctionData, encodeFunctionData, erc20Abi, getAddress, maxUint16
|
|
|
2
2
|
import { resolveBorrowCollateralPositions } from "../../utils/accountPositionClassification.js";
|
|
3
3
|
import { SwapperMode } from "../swapService/swapServiceTypes.js";
|
|
4
4
|
import { adjustForInterest, getSwapInputAmount, } from "../swapService/swapVerification.js";
|
|
5
|
+
import { isEVault, } from "../vaults/vaultMetaService/index.js";
|
|
5
6
|
import { ethereumVaultConnectorAbi } from "./abis/ethereumVaultConnectorAbi.js";
|
|
6
7
|
import { eVaultAbi } from "./abis/eVaultAbi.js";
|
|
7
8
|
import { permit2PermitAbi } from "./abis/permit2PermitAbi.js";
|
|
@@ -252,6 +253,7 @@ export class ExecutionService {
|
|
|
252
253
|
intrinsicApyService;
|
|
253
254
|
eulerLabelsService;
|
|
254
255
|
processPlugins;
|
|
256
|
+
prefetchPlugins;
|
|
255
257
|
constructor(deploymentService, walletService, providerService, vaultMetaService, priceService, rewardsService, intrinsicApyService, eulerLabelsService) {
|
|
256
258
|
this.deploymentService = deploymentService;
|
|
257
259
|
this.walletService = walletService;
|
|
@@ -289,6 +291,9 @@ export class ExecutionService {
|
|
|
289
291
|
setPluginProcessor(processPlugins) {
|
|
290
292
|
this.processPlugins = processPlugins;
|
|
291
293
|
}
|
|
294
|
+
setPluginPrefetcher(prefetchPlugins) {
|
|
295
|
+
this.prefetchPlugins = prefetchPlugins;
|
|
296
|
+
}
|
|
292
297
|
/** Derive storage overrides needed to simulate the plan against the current account state. */
|
|
293
298
|
async deriveStateOverrides(chainId, account, transactionPlan, options) {
|
|
294
299
|
assertNoCowSwapPlanItems(transactionPlan, "deriveStateOverrides");
|
|
@@ -297,7 +302,7 @@ export class ExecutionService {
|
|
|
297
302
|
/** Simulate the full transaction plan, including approval resolution and plugin-aware batch execution. */
|
|
298
303
|
async simulateTransactionPlan(chainId, account, transactionPlan, options) {
|
|
299
304
|
assertNoCowSwapPlanItems(transactionPlan, "simulateTransactionPlan");
|
|
300
|
-
const processedPlan = await this.processPlanPlugins(transactionPlan, account, chainId);
|
|
305
|
+
const processedPlan = await this.processPlanPlugins(transactionPlan, account, chainId, options?.prefetch);
|
|
301
306
|
const owner = this.getAccountOwner(account);
|
|
302
307
|
return simulateTransactionPlan(this.getSimulationContext(), chainId, owner, processedPlan, options);
|
|
303
308
|
}
|
|
@@ -319,9 +324,9 @@ export class ExecutionService {
|
|
|
319
324
|
* wallet allowances.
|
|
320
325
|
*/
|
|
321
326
|
async prepareTransactionPlan(args) {
|
|
322
|
-
const { plan, chainId, account, usePermit2 = true, unlimitedApproval = false, } = args;
|
|
327
|
+
const { plan, chainId, account, usePermit2 = true, unlimitedApproval = false, prefetch, } = args;
|
|
323
328
|
assertNoCowSwapPlanItems(plan, "prepareTransactionPlan");
|
|
324
|
-
const processedPlan = await this.processPlanPlugins(plan, account, chainId);
|
|
329
|
+
const processedPlan = await this.processPlanPlugins(plan, account, chainId, prefetch);
|
|
325
330
|
const owner = this.getAccountOwner(account);
|
|
326
331
|
const resolvedPlan = await this.resolveRequiredApprovals({
|
|
327
332
|
plan: processedPlan,
|
|
@@ -342,10 +347,24 @@ export class ExecutionService {
|
|
|
342
347
|
/** Estimate gas for the full transaction plan after applying the same simulation pipeline used for execution. */
|
|
343
348
|
async estimateGasForTransactionPlan(chainId, account, transactionPlan, options) {
|
|
344
349
|
assertNoCowSwapPlanItems(transactionPlan, "estimateGasForTransactionPlan");
|
|
345
|
-
const processedPlan = await this.processPlanPlugins(transactionPlan, account, chainId);
|
|
350
|
+
const processedPlan = await this.processPlanPlugins(transactionPlan, account, chainId, options?.prefetch);
|
|
346
351
|
const owner = this.getAccountOwner(account);
|
|
347
352
|
return estimateGasForTransactionPlan(this.getSimulationContext(), chainId, owner, processedPlan, options);
|
|
348
353
|
}
|
|
354
|
+
/**
|
|
355
|
+
* Estimate gas for a {@link TransactionPlanPrepared} envelope. Plugins and
|
|
356
|
+
* approval resolution were already applied by {@link prepareTransactionPlan},
|
|
357
|
+
* so this skips the plugin pipeline (TOS / Keyring / Pyth) entirely — the
|
|
358
|
+
* plan's batch items are used as-is. Net effect: per-call gas estimate
|
|
359
|
+
* drops from "plugin pipeline + estimate" to just the estimate, mirroring
|
|
360
|
+
* the simulatePreparedTransactionPlan / executePreparedTransactionPlan
|
|
361
|
+
* pattern.
|
|
362
|
+
*/
|
|
363
|
+
async estimateGasForPreparedTransactionPlan(prepared, options) {
|
|
364
|
+
assertNoCowSwapPlanItems(prepared.plan, "estimateGasForPreparedTransactionPlan");
|
|
365
|
+
const owner = this.getAccountOwner(prepared.account);
|
|
366
|
+
return estimateGasForTransactionPlan(this.getSimulationContext(), prepared.chainId, owner, prepared.plan, options);
|
|
367
|
+
}
|
|
349
368
|
/** Execute a transaction plan using caller-provided signing and send callbacks. */
|
|
350
369
|
async executeTransactionPlan(args) {
|
|
351
370
|
const { providerService } = this;
|
|
@@ -353,7 +372,7 @@ export class ExecutionService {
|
|
|
353
372
|
throw new Error("ExecutionService.executeTransactionPlan requires a providerService. Pass it to the ExecutionService constructor or call setProviderService().");
|
|
354
373
|
}
|
|
355
374
|
assertNoCowSwapPlanItems(args.plan, "executeTransactionPlan");
|
|
356
|
-
const processedPlan = await this.processPlanPlugins(args.plan, args.account, args.chainId);
|
|
375
|
+
const processedPlan = await this.processPlanPlugins(args.plan, args.account, args.chainId, args.prefetch);
|
|
357
376
|
assertNoCowSwapPlanItems(processedPlan, "executeTransactionPlan");
|
|
358
377
|
const helperArgs = {
|
|
359
378
|
...args,
|
|
@@ -399,7 +418,7 @@ export class ExecutionService {
|
|
|
399
418
|
}
|
|
400
419
|
return executeCowSwapTransactionPlan({
|
|
401
420
|
...args,
|
|
402
|
-
plan: await this.processPlanPlugins(args.plan, args.account, args.chainId),
|
|
421
|
+
plan: await this.processPlanPlugins(args.plan, args.account, args.chainId, args.prefetch),
|
|
403
422
|
deploymentService: this.deploymentService,
|
|
404
423
|
providerService,
|
|
405
424
|
});
|
|
@@ -417,11 +436,31 @@ export class ExecutionService {
|
|
|
417
436
|
describeBatch: (batch) => this.describeBatch(batch),
|
|
418
437
|
};
|
|
419
438
|
}
|
|
420
|
-
|
|
439
|
+
/**
|
|
440
|
+
* Run each plugin's processPlan in registration order. Plugins receive the
|
|
441
|
+
* plan as modified by previous plugins; errors are caught per-plugin so a
|
|
442
|
+
* single failing plugin can't poison the pipeline.
|
|
443
|
+
*
|
|
444
|
+
* `prefetch` carries form-level data each plugin pre-resolved via
|
|
445
|
+
* {@link prefetchPluginDataForPlan} — passing it lets the plugin skip its
|
|
446
|
+
* own network I/O (Hermes pulls, keyring hook reads, etc.).
|
|
447
|
+
*/
|
|
448
|
+
async processPlanPlugins(plan, account, chainId, prefetch) {
|
|
421
449
|
return this.processPlugins
|
|
422
|
-
? this.processPlugins(plan, account, chainId)
|
|
450
|
+
? this.processPlugins(plan, account, chainId, prefetch)
|
|
423
451
|
: plan;
|
|
424
452
|
}
|
|
453
|
+
/**
|
|
454
|
+
* Resolve each plugin's prefetch payload for a given plan once, so per-quote
|
|
455
|
+
* prepare/estimate/simulate calls can reuse the data instead of refetching.
|
|
456
|
+
* Returns an open record keyed by plugin name — known SDK slots are typed
|
|
457
|
+
* (`pyth`, `keyring`); external plugins populate their own keys.
|
|
458
|
+
*/
|
|
459
|
+
async prefetchPluginDataForPlan(plan, account, chainId) {
|
|
460
|
+
return this.prefetchPlugins
|
|
461
|
+
? this.prefetchPlugins(plan, account, chainId)
|
|
462
|
+
: {};
|
|
463
|
+
}
|
|
425
464
|
getAccountOwner(account) {
|
|
426
465
|
return typeof account === "string" ? account : account.owner;
|
|
427
466
|
}
|
|
@@ -1033,10 +1072,19 @@ export class ExecutionService {
|
|
|
1033
1072
|
const transferredPositions = new Set();
|
|
1034
1073
|
for (const collateral of activeCollaterals) {
|
|
1035
1074
|
batchItems.push(this.encodeDisableCollateral(account.chainId, receiver, collateral.vaultAddress));
|
|
1036
|
-
|
|
1075
|
+
// Only EVK vaults expose the transferFromMax used by the cleanup
|
|
1076
|
+
// sweep. Other vault types (e.g. Securitize RWA collaterals) don't
|
|
1077
|
+
// implement it and the underlying transfer would revert against the
|
|
1078
|
+
// ERC-20 whitelist anyway, taking the whole repay batch down. The
|
|
1079
|
+
// disable step above still runs for every active collateral.
|
|
1080
|
+
const isEvkCollateral = isEVault(collateral.vault);
|
|
1081
|
+
if (isEvkCollateral &&
|
|
1082
|
+
getAddress(receiver) !== getAddress(account.owner)) {
|
|
1037
1083
|
batchItems.push(this.encodeTransferFromMax(collateral.vaultAddress, receiver, account.owner));
|
|
1038
1084
|
}
|
|
1039
|
-
|
|
1085
|
+
if (isEvkCollateral) {
|
|
1086
|
+
transferredPositions.add(`${getAddress(receiver)}:${getAddress(collateral.vaultAddress)}`);
|
|
1087
|
+
}
|
|
1040
1088
|
}
|
|
1041
1089
|
if (sourceAccount && sourceVault) {
|
|
1042
1090
|
const sourcePositionKey = `${getAddress(sourceAccount)}:${getAddress(sourceVault)}`;
|
|
@@ -1113,6 +1161,14 @@ export class ExecutionService {
|
|
|
1113
1161
|
continue;
|
|
1114
1162
|
}
|
|
1115
1163
|
if (usePermit2) {
|
|
1164
|
+
// Skip Permit2 entirely when an existing direct token→vault
|
|
1165
|
+
// allowance already covers the requirement. Avoids prompting
|
|
1166
|
+
// the user for a Permit2 approve+signature when a prior
|
|
1167
|
+
// direct ERC-20 approval is sufficient.
|
|
1168
|
+
if (allowances.assetForVault >= amount) {
|
|
1169
|
+
approval.resolved = [];
|
|
1170
|
+
continue;
|
|
1171
|
+
}
|
|
1116
1172
|
// Check permit2 allowances
|
|
1117
1173
|
const assetForPermit2 = allowances.assetForPermit2;
|
|
1118
1174
|
const assetForVaultInPermit2 = allowances.assetForVaultInPermit2;
|
|
@@ -1204,45 +1260,58 @@ export class ExecutionService {
|
|
|
1204
1260
|
unlimitedApproval,
|
|
1205
1261
|
});
|
|
1206
1262
|
}
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
*/
|
|
1218
|
-
planCleanup(args) {
|
|
1219
|
-
const { account, subAccount } = args;
|
|
1263
|
+
buildCleanupBatchItems(account, subAccount, options = {}) {
|
|
1264
|
+
const { skipCollateralCleanup = false, controllerToKeep } = options;
|
|
1265
|
+
const normalizedControllerToKeep = controllerToKeep
|
|
1266
|
+
? getAddress(controllerToKeep)
|
|
1267
|
+
: undefined;
|
|
1268
|
+
const empty = () => ({
|
|
1269
|
+
items: [],
|
|
1270
|
+
disabledControllers: new Set(),
|
|
1271
|
+
disabledCollaterals: new Set(),
|
|
1272
|
+
});
|
|
1220
1273
|
if (typeof account.getSubAccount !== "function")
|
|
1221
|
-
return
|
|
1274
|
+
return empty();
|
|
1222
1275
|
const subAccountSnapshot = account.getSubAccount(subAccount);
|
|
1223
1276
|
if (!subAccountSnapshot)
|
|
1224
|
-
return
|
|
1277
|
+
return empty();
|
|
1225
1278
|
const collaterals = subAccountSnapshot.enabledCollaterals ?? [];
|
|
1226
1279
|
const controllers = subAccountSnapshot.enabledControllers ?? [];
|
|
1227
1280
|
if (collaterals.length === 0 && controllers.length === 0)
|
|
1228
|
-
return
|
|
1281
|
+
return empty();
|
|
1229
1282
|
const items = [];
|
|
1283
|
+
const disabledControllers = new Set();
|
|
1284
|
+
const disabledCollaterals = new Set();
|
|
1285
|
+
const disableCollateral = (collateral) => {
|
|
1286
|
+
if (skipCollateralCleanup)
|
|
1287
|
+
return;
|
|
1288
|
+
const normalizedCollateral = getAddress(collateral);
|
|
1289
|
+
disabledCollaterals.add(normalizedCollateral);
|
|
1290
|
+
items.push(this.encodeDisableCollateral(account.chainId, subAccount, normalizedCollateral));
|
|
1291
|
+
};
|
|
1230
1292
|
const disableAllCollaterals = () => {
|
|
1231
1293
|
for (const collateral of collaterals) {
|
|
1232
|
-
|
|
1294
|
+
disableCollateral(collateral);
|
|
1233
1295
|
}
|
|
1234
1296
|
};
|
|
1297
|
+
const disableController = (controller) => {
|
|
1298
|
+
const normalizedController = getAddress(controller);
|
|
1299
|
+
if (normalizedController === normalizedControllerToKeep)
|
|
1300
|
+
return;
|
|
1301
|
+
disabledControllers.add(normalizedController);
|
|
1302
|
+
items.push(this.encodeDisableController(normalizedController, subAccount));
|
|
1303
|
+
};
|
|
1235
1304
|
if (controllers.length === 0) {
|
|
1236
1305
|
disableAllCollaterals();
|
|
1237
|
-
return
|
|
1306
|
+
return { items, disabledControllers, disabledCollaterals };
|
|
1238
1307
|
}
|
|
1239
1308
|
const hasActiveBorrow = subAccountSnapshot.positions.some((position) => position.borrowed > 0n);
|
|
1240
1309
|
if (!hasActiveBorrow) {
|
|
1241
1310
|
disableAllCollaterals();
|
|
1242
1311
|
for (const controller of controllers) {
|
|
1243
|
-
|
|
1312
|
+
disableController(controller);
|
|
1244
1313
|
}
|
|
1245
|
-
return
|
|
1314
|
+
return { items, disabledControllers, disabledCollaterals };
|
|
1246
1315
|
}
|
|
1247
1316
|
const depositedVaults = new Set(subAccountSnapshot.positions
|
|
1248
1317
|
.filter(hasSuppliedPosition)
|
|
@@ -1250,9 +1319,25 @@ export class ExecutionService {
|
|
|
1250
1319
|
for (const collateral of collaterals) {
|
|
1251
1320
|
if (depositedVaults.has(getAddress(collateral)))
|
|
1252
1321
|
continue;
|
|
1253
|
-
|
|
1322
|
+
disableCollateral(collateral);
|
|
1254
1323
|
}
|
|
1255
|
-
return
|
|
1324
|
+
return { items, disabledControllers, disabledCollaterals };
|
|
1325
|
+
}
|
|
1326
|
+
// ========== Transaction plan functions ==========
|
|
1327
|
+
/**
|
|
1328
|
+
* Builds a cleanup plan matching Lite's stale collateral/controller policy.
|
|
1329
|
+
*
|
|
1330
|
+
* Cleanup is derived from the provided account snapshot:
|
|
1331
|
+
* - no enabled controllers: disable all enabled collaterals
|
|
1332
|
+
* - enabled controllers but no active borrows: disable all collaterals, then controllers
|
|
1333
|
+
* - active borrows: disable only enabled collaterals with no supplied position
|
|
1334
|
+
*
|
|
1335
|
+
* If the sub-account snapshot is unavailable, no cleanup is planned.
|
|
1336
|
+
*/
|
|
1337
|
+
planCleanup(args) {
|
|
1338
|
+
const { account, subAccount } = args;
|
|
1339
|
+
const cleanup = this.buildCleanupBatchItems(account, subAccount);
|
|
1340
|
+
return this.convertBatchItemsToPlan(cleanup.items, "cleanup");
|
|
1256
1341
|
}
|
|
1257
1342
|
/**
|
|
1258
1343
|
* Builds a transaction plan for depositing assets into a vault.
|
|
@@ -1430,8 +1515,18 @@ export class ExecutionService {
|
|
|
1430
1515
|
* @returns Array of transaction plan items (optional approval + EVC batch)
|
|
1431
1516
|
*/
|
|
1432
1517
|
planBorrow(args) {
|
|
1433
|
-
const { vault, amount, receiver, borrowAccount, account, collateral } = args;
|
|
1518
|
+
const { vault, amount, receiver, borrowAccount, account, collateral, skipCleanup = false, } = args;
|
|
1434
1519
|
const plan = [];
|
|
1520
|
+
const cleanup = skipCleanup
|
|
1521
|
+
? {
|
|
1522
|
+
items: [],
|
|
1523
|
+
disabledControllers: new Set(),
|
|
1524
|
+
disabledCollaterals: new Set(),
|
|
1525
|
+
}
|
|
1526
|
+
: this.buildCleanupBatchItems(account, borrowAccount, {
|
|
1527
|
+
skipCollateralCleanup: true,
|
|
1528
|
+
controllerToKeep: vault,
|
|
1529
|
+
});
|
|
1435
1530
|
const savingsCollateral = isSavingsCollateral(collateral)
|
|
1436
1531
|
? collateral
|
|
1437
1532
|
: undefined;
|
|
@@ -1439,13 +1534,19 @@ export class ExecutionService {
|
|
|
1439
1534
|
? collateral
|
|
1440
1535
|
: undefined;
|
|
1441
1536
|
const enableCollateral = collateral && collateral.amount > 0n
|
|
1442
|
-
?
|
|
1443
|
-
|
|
1537
|
+
? cleanup.disabledCollaterals.has(getAddress(collateral.vault)) ||
|
|
1538
|
+
!(account?.isCollateralEnabled(borrowAccount, collateral.vault) ??
|
|
1539
|
+
false)
|
|
1444
1540
|
: false;
|
|
1445
1541
|
// Check if controller needs to be enabled
|
|
1446
1542
|
// Default: controller is not enabled when account/sub-account is not available
|
|
1447
|
-
const
|
|
1448
|
-
const
|
|
1543
|
+
const currentControllerBeforeCleanup = account?.getCurrentController(borrowAccount);
|
|
1544
|
+
const currentController = currentControllerBeforeCleanup &&
|
|
1545
|
+
!cleanup.disabledControllers.has(getAddress(currentControllerBeforeCleanup))
|
|
1546
|
+
? currentControllerBeforeCleanup
|
|
1547
|
+
: undefined;
|
|
1548
|
+
const enableController = cleanup.disabledControllers.size > 0 ||
|
|
1549
|
+
!(account?.isControllerEnabled(borrowAccount, vault) ?? false);
|
|
1449
1550
|
if (walletCollateral && walletCollateral.amount > 0n) {
|
|
1450
1551
|
// Approval is needed from the account owner (who owns the wallet tokens)
|
|
1451
1552
|
// Add approval requirement (will be resolved later with Wallet data)
|
|
@@ -1457,29 +1558,32 @@ export class ExecutionService {
|
|
|
1457
1558
|
amount: walletCollateral.amount,
|
|
1458
1559
|
});
|
|
1459
1560
|
}
|
|
1460
|
-
const batchItems =
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1561
|
+
const batchItems = [
|
|
1562
|
+
...cleanup.items,
|
|
1563
|
+
...this.encodeBorrow({
|
|
1564
|
+
chainId: account.chainId,
|
|
1565
|
+
vault,
|
|
1566
|
+
amount,
|
|
1567
|
+
owner: account.owner,
|
|
1568
|
+
borrowAccount,
|
|
1569
|
+
receiver,
|
|
1570
|
+
enableController,
|
|
1571
|
+
currentController: currentController || undefined,
|
|
1572
|
+
enableCollateral,
|
|
1573
|
+
collateralVault: collateral?.vault,
|
|
1574
|
+
collateralAmount: walletCollateral?.amount,
|
|
1575
|
+
collateralWrappedNativeInfo: walletCollateral?.wrappedNativeInfo,
|
|
1576
|
+
collateralShareSource: savingsCollateral
|
|
1577
|
+
? {
|
|
1578
|
+
from: savingsCollateral.from,
|
|
1579
|
+
shares: savingsCollateral.amount,
|
|
1580
|
+
disableCollateralFrom: savingsCollateral.disableCollateralFrom &&
|
|
1581
|
+
(account?.isCollateralEnabled(savingsCollateral.from, savingsCollateral.vault) ??
|
|
1582
|
+
false),
|
|
1583
|
+
}
|
|
1584
|
+
: undefined,
|
|
1585
|
+
}),
|
|
1586
|
+
];
|
|
1483
1587
|
plan.push(...this.convertBatchItemsToPlan(batchItems, "borrow"));
|
|
1484
1588
|
return plan;
|
|
1485
1589
|
}
|
|
@@ -1862,9 +1966,16 @@ export class ExecutionService {
|
|
|
1862
1966
|
return plan;
|
|
1863
1967
|
}
|
|
1864
1968
|
planSwapAndBorrowFromWallet(args) {
|
|
1865
|
-
const { swapQuote, amount, tokenIn, account, borrowVault, borrowAmount, borrowAccount = swapQuote.accountOut, receiver = account.owner, collateralVault = swapQuote.receiver, wrappedNativeInfo, } = args;
|
|
1969
|
+
const { swapQuote, amount, tokenIn, account, borrowVault, borrowAmount, borrowAccount = swapQuote.accountOut, receiver = account.owner, collateralVault = swapQuote.receiver, wrappedNativeInfo, skipCleanup = false, } = args;
|
|
1866
1970
|
assertNonCowSwapQuote(swapQuote, "planSwapAndBorrowFromWallet");
|
|
1867
1971
|
const plan = [];
|
|
1972
|
+
const cleanup = skipCleanup
|
|
1973
|
+
? {
|
|
1974
|
+
items: [],
|
|
1975
|
+
disabledControllers: new Set(),
|
|
1976
|
+
disabledCollaterals: new Set(),
|
|
1977
|
+
}
|
|
1978
|
+
: this.buildCleanupBatchItems(account, borrowAccount);
|
|
1868
1979
|
plan.push({
|
|
1869
1980
|
type: "requiredApproval",
|
|
1870
1981
|
token: tokenIn,
|
|
@@ -1872,24 +1983,33 @@ export class ExecutionService {
|
|
|
1872
1983
|
spender: swapQuote.verify.verifierAddress,
|
|
1873
1984
|
amount,
|
|
1874
1985
|
});
|
|
1875
|
-
const enableController =
|
|
1876
|
-
|
|
1877
|
-
const
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1986
|
+
const enableController = cleanup.disabledControllers.size > 0 ||
|
|
1987
|
+
!(account?.isControllerEnabled(borrowAccount, borrowVault) ?? false);
|
|
1988
|
+
const enableCollateral = cleanup.disabledCollaterals.has(getAddress(collateralVault)) ||
|
|
1989
|
+
!(account?.isCollateralEnabled(borrowAccount, collateralVault) ?? false);
|
|
1990
|
+
const currentControllerBeforeCleanup = account?.getCurrentController(borrowAccount);
|
|
1991
|
+
const currentController = currentControllerBeforeCleanup &&
|
|
1992
|
+
!cleanup.disabledControllers.has(getAddress(currentControllerBeforeCleanup))
|
|
1993
|
+
? currentControllerBeforeCleanup
|
|
1994
|
+
: undefined;
|
|
1995
|
+
const batchItems = [
|
|
1996
|
+
...cleanup.items,
|
|
1997
|
+
...this.encodeSwapAndBorrowFromWallet({
|
|
1998
|
+
chainId: account.chainId,
|
|
1999
|
+
swapQuote,
|
|
2000
|
+
amount,
|
|
2001
|
+
sender: account.owner,
|
|
2002
|
+
borrowAccount,
|
|
2003
|
+
collateralVault,
|
|
2004
|
+
borrowVault,
|
|
2005
|
+
borrowAmount,
|
|
2006
|
+
receiver,
|
|
2007
|
+
currentController: currentController || undefined,
|
|
2008
|
+
enableController,
|
|
2009
|
+
enableCollateral,
|
|
2010
|
+
wrappedNativeInfo,
|
|
2011
|
+
}),
|
|
2012
|
+
];
|
|
1893
2013
|
plan.push(...this.convertBatchItemsToPlan(batchItems, "swapAndBorrowFromWallet"));
|
|
1894
2014
|
return plan;
|
|
1895
2015
|
}
|
|
@@ -2229,7 +2349,7 @@ export class ExecutionService {
|
|
|
2229
2349
|
* @returns Array of transaction plan items (optional approval + EVC batch). Throws if swapQuote.accountIn !== swapQuote.accountOut.
|
|
2230
2350
|
*/
|
|
2231
2351
|
planMultiplyWithSwap(args) {
|
|
2232
|
-
const { collateralVault, collateralAmount, collateralAsset, collateralShareSource, collateralWrappedNativeInfo, account, swapQuote, swapperMode, } = args;
|
|
2352
|
+
const { collateralVault, collateralAmount, collateralAsset, collateralShareSource, collateralWrappedNativeInfo, account, swapQuote, swapperMode, skipCleanup = false, } = args;
|
|
2233
2353
|
assertNonCowSwapQuote(swapQuote, "planMultiplyWithSwap", "planOpenPositionWithCoW");
|
|
2234
2354
|
const plan = [];
|
|
2235
2355
|
// 1. Check if collateral approval is needed (only if depositing collateral)
|
|
@@ -2249,14 +2369,23 @@ export class ExecutionService {
|
|
|
2249
2369
|
const receiver = swapQuote.accountIn;
|
|
2250
2370
|
const liabilityVault = swapQuote.vaultIn;
|
|
2251
2371
|
const longVault = swapQuote.receiver;
|
|
2372
|
+
const cleanup = skipCleanup
|
|
2373
|
+
? {
|
|
2374
|
+
items: [],
|
|
2375
|
+
disabledControllers: new Set(),
|
|
2376
|
+
disabledCollaterals: new Set(),
|
|
2377
|
+
}
|
|
2378
|
+
: this.buildCleanupBatchItems(account, receiver);
|
|
2252
2379
|
const liabilityAmount = getSwapInputAmount(swapQuote, swapperMode ?? SwapperMode.EXACT_IN);
|
|
2253
2380
|
// 2. Determine if collateral needs to be enabled
|
|
2254
2381
|
const hasCollateralInput = collateralShareSource
|
|
2255
2382
|
? collateralShareSource.shares > 0n
|
|
2256
2383
|
: collateralAmount > 0n;
|
|
2257
2384
|
const enableCollateral = hasCollateralInput &&
|
|
2258
|
-
|
|
2259
|
-
|
|
2385
|
+
(cleanup.disabledCollaterals.has(getAddress(collateralVault)) ||
|
|
2386
|
+
!(account?.isCollateralEnabled(receiver, collateralVault) ?? false));
|
|
2387
|
+
const enableCollateralLong = cleanup.disabledCollaterals.has(getAddress(longVault)) ||
|
|
2388
|
+
!(account?.isCollateralEnabled(receiver, longVault) ?? false);
|
|
2260
2389
|
const resolvedCollateralShareSource = collateralShareSource
|
|
2261
2390
|
? {
|
|
2262
2391
|
...collateralShareSource,
|
|
@@ -2266,28 +2395,36 @@ export class ExecutionService {
|
|
|
2266
2395
|
}
|
|
2267
2396
|
: undefined;
|
|
2268
2397
|
// 3. Determine if controller needs to be enabled
|
|
2269
|
-
const enableController =
|
|
2398
|
+
const enableController = cleanup.disabledControllers.size > 0 ||
|
|
2399
|
+
!(account?.isControllerEnabled(receiver, liabilityVault) ?? false);
|
|
2270
2400
|
// 4. Get current controller (may need to disable if different)
|
|
2271
|
-
const
|
|
2401
|
+
const currentControllerBeforeCleanup = account?.getCurrentController(receiver);
|
|
2402
|
+
const currentController = currentControllerBeforeCleanup &&
|
|
2403
|
+
!cleanup.disabledControllers.has(getAddress(currentControllerBeforeCleanup))
|
|
2404
|
+
? currentControllerBeforeCleanup
|
|
2405
|
+
: undefined;
|
|
2272
2406
|
// 5. Build EVC batch items
|
|
2273
|
-
const batchItems =
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2407
|
+
const batchItems = [
|
|
2408
|
+
...cleanup.items,
|
|
2409
|
+
...this.encodeMultiplyWithSwap({
|
|
2410
|
+
chainId: account.chainId,
|
|
2411
|
+
collateralVault,
|
|
2412
|
+
collateralAmount,
|
|
2413
|
+
liabilityVault,
|
|
2414
|
+
liabilityAmount,
|
|
2415
|
+
longVault,
|
|
2416
|
+
owner: account.owner,
|
|
2417
|
+
receiver,
|
|
2418
|
+
enableCollateral,
|
|
2419
|
+
currentController: currentController || undefined,
|
|
2420
|
+
enableController,
|
|
2421
|
+
collateralShareSource: resolvedCollateralShareSource,
|
|
2422
|
+
collateralWrappedNativeInfo,
|
|
2423
|
+
swapQuote,
|
|
2424
|
+
enableCollateralLong,
|
|
2425
|
+
// Permit2 is handled separately in the plan
|
|
2426
|
+
}),
|
|
2427
|
+
];
|
|
2291
2428
|
plan.push(...this.convertBatchItemsToPlan(batchItems, "multiplyWithSwap"));
|
|
2292
2429
|
return plan;
|
|
2293
2430
|
}
|
|
@@ -2348,8 +2485,15 @@ export class ExecutionService {
|
|
|
2348
2485
|
* @returns Array of transaction plan items (optional approval + EVC batch)
|
|
2349
2486
|
*/
|
|
2350
2487
|
planMultiplySameAsset(args) {
|
|
2351
|
-
const { collateralVault, collateralAmount, collateralAsset, collateralShareSource, collateralWrappedNativeInfo, liabilityVault, liabilityAmount, longVault, receiver, account, } = args;
|
|
2488
|
+
const { collateralVault, collateralAmount, collateralAsset, collateralShareSource, collateralWrappedNativeInfo, liabilityVault, liabilityAmount, longVault, receiver, account, skipCleanup = false, } = args;
|
|
2352
2489
|
const plan = [];
|
|
2490
|
+
const cleanup = skipCleanup
|
|
2491
|
+
? {
|
|
2492
|
+
items: [],
|
|
2493
|
+
disabledControllers: new Set(),
|
|
2494
|
+
disabledCollaterals: new Set(),
|
|
2495
|
+
}
|
|
2496
|
+
: this.buildCleanupBatchItems(account, receiver);
|
|
2353
2497
|
// 1. Check if collateral approval is needed (only if depositing collateral)
|
|
2354
2498
|
if (!collateralShareSource && collateralAmount > 0n) {
|
|
2355
2499
|
// Add approval requirement (will be resolved later with Wallet data)
|
|
@@ -2366,8 +2510,10 @@ export class ExecutionService {
|
|
|
2366
2510
|
? collateralShareSource.shares > 0n
|
|
2367
2511
|
: collateralAmount > 0n;
|
|
2368
2512
|
const enableCollateral = hasCollateralInput &&
|
|
2369
|
-
|
|
2370
|
-
|
|
2513
|
+
(cleanup.disabledCollaterals.has(getAddress(collateralVault)) ||
|
|
2514
|
+
!(account?.isCollateralEnabled(receiver, collateralVault) ?? false));
|
|
2515
|
+
const enableCollateralLong = cleanup.disabledCollaterals.has(getAddress(longVault)) ||
|
|
2516
|
+
!(account?.isCollateralEnabled(receiver, longVault) ?? false);
|
|
2371
2517
|
const resolvedCollateralShareSource = collateralShareSource
|
|
2372
2518
|
? {
|
|
2373
2519
|
...collateralShareSource,
|
|
@@ -2377,27 +2523,35 @@ export class ExecutionService {
|
|
|
2377
2523
|
}
|
|
2378
2524
|
: undefined;
|
|
2379
2525
|
// 3. Determine if controller needs to be enabled
|
|
2380
|
-
const enableController =
|
|
2526
|
+
const enableController = cleanup.disabledControllers.size > 0 ||
|
|
2527
|
+
!(account?.isControllerEnabled(receiver, liabilityVault) ?? false);
|
|
2381
2528
|
// 4. Get current controller (may need to disable if different)
|
|
2382
|
-
const
|
|
2529
|
+
const currentControllerBeforeCleanup = account?.getCurrentController(receiver);
|
|
2530
|
+
const currentController = currentControllerBeforeCleanup &&
|
|
2531
|
+
!cleanup.disabledControllers.has(getAddress(currentControllerBeforeCleanup))
|
|
2532
|
+
? currentControllerBeforeCleanup
|
|
2533
|
+
: undefined;
|
|
2383
2534
|
// 5. Build EVC batch items
|
|
2384
|
-
const batchItems =
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2535
|
+
const batchItems = [
|
|
2536
|
+
...cleanup.items,
|
|
2537
|
+
...this.encodeMultiplySameAsset({
|
|
2538
|
+
chainId: account.chainId,
|
|
2539
|
+
collateralVault,
|
|
2540
|
+
collateralAmount,
|
|
2541
|
+
liabilityVault,
|
|
2542
|
+
liabilityAmount,
|
|
2543
|
+
longVault,
|
|
2544
|
+
owner: account.owner,
|
|
2545
|
+
receiver,
|
|
2546
|
+
enableCollateral,
|
|
2547
|
+
currentController: currentController || undefined,
|
|
2548
|
+
enableController,
|
|
2549
|
+
collateralShareSource: resolvedCollateralShareSource,
|
|
2550
|
+
collateralWrappedNativeInfo,
|
|
2551
|
+
enableCollateralLong,
|
|
2552
|
+
// Permit2 is handled separately in the plan
|
|
2553
|
+
}),
|
|
2554
|
+
];
|
|
2401
2555
|
plan.push(...this.convertBatchItemsToPlan(batchItems, "multiplySameAsset"));
|
|
2402
2556
|
return plan;
|
|
2403
2557
|
}
|