@eulerxyz/euler-v2-sdk 0.2.0-beta → 0.2.2-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 +2 -2
- package/dist/src/entities/Account.d.ts.map +1 -1
- package/dist/src/entities/Account.js +2 -2
- package/dist/src/entities/Account.js.map +1 -1
- package/dist/src/entities/EVault.d.ts.map +1 -1
- package/dist/src/entities/EVault.js +3 -9
- package/dist/src/entities/EVault.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/plugins/pyth/pythPlugin.d.ts +7 -1
- package/dist/src/plugins/pyth/pythPlugin.d.ts.map +1 -1
- package/dist/src/plugins/pyth/pythPlugin.js +85 -9
- package/dist/src/plugins/pyth/pythPlugin.js.map +1 -1
- package/dist/src/sdk/buildSDK.js +1 -1
- package/dist/src/sdk/buildSDK.js.map +1 -1
- package/dist/src/sdk/defaultConfig.d.ts +2 -2
- package/dist/src/sdk/defaultConfig.d.ts.map +1 -1
- package/dist/src/sdk/defaultConfig.js +3 -3
- package/dist/src/sdk/defaultConfig.js.map +1 -1
- package/dist/src/services/accountService/accountServiceConfig.d.ts +1 -1
- package/dist/src/services/accountService/accountServiceConfig.d.ts.map +1 -1
- package/dist/src/services/executionService/encode.d.ts +15 -11
- package/dist/src/services/executionService/encode.d.ts.map +1 -1
- package/dist/src/services/executionService/encode.js +242 -23
- package/dist/src/services/executionService/encode.js.map +1 -1
- package/dist/src/services/executionService/executionService.d.ts +39 -4
- package/dist/src/services/executionService/executionService.d.ts.map +1 -1
- package/dist/src/services/executionService/executionService.js +335 -24
- package/dist/src/services/executionService/executionService.js.map +1 -1
- package/dist/src/services/executionService/executionServiceTypes.d.ts +118 -3
- package/dist/src/services/executionService/executionServiceTypes.d.ts.map +1 -1
- package/dist/src/services/executionService/executionServiceTypes.js.map +1 -1
- package/dist/src/services/executionService/index.d.ts +1 -1
- package/dist/src/services/executionService/index.d.ts.map +1 -1
- package/dist/src/services/executionService/index.js.map +1 -1
- package/dist/src/services/intrinsicApyService/adapters/intrinsicApyV3Adapter/intrinsicApyV3Adapter.d.ts +1 -0
- package/dist/src/services/intrinsicApyService/adapters/intrinsicApyV3Adapter/intrinsicApyV3Adapter.d.ts.map +1 -1
- package/dist/src/services/intrinsicApyService/adapters/intrinsicApyV3Adapter/intrinsicApyV3Adapter.js +14 -2
- package/dist/src/services/intrinsicApyService/adapters/intrinsicApyV3Adapter/intrinsicApyV3Adapter.js.map +1 -1
- package/dist/src/services/intrinsicApyService/adapters/intrinsicApyV3Adapter/intrinsicApyV3AdapterTypes.d.ts +1 -1
- package/dist/src/services/intrinsicApyService/adapters/intrinsicApyV3Adapter/intrinsicApyV3AdapterTypes.d.ts.map +1 -1
- package/dist/src/services/priceService/backendClient.d.ts +1 -0
- package/dist/src/services/priceService/backendClient.d.ts.map +1 -1
- package/dist/src/services/priceService/backendClient.js +14 -3
- package/dist/src/services/priceService/backendClient.js.map +1 -1
- package/dist/src/services/priceService/priceService.d.ts +2 -1
- package/dist/src/services/priceService/priceService.d.ts.map +1 -1
- package/dist/src/services/priceService/priceService.js +8 -25
- package/dist/src/services/priceService/priceService.js.map +1 -1
- package/dist/src/services/rewardsService/adapters/rewardsDirectAdapter/rewardsDirectAdapter.d.ts +8 -2
- package/dist/src/services/rewardsService/adapters/rewardsDirectAdapter/rewardsDirectAdapter.d.ts.map +1 -1
- package/dist/src/services/rewardsService/adapters/rewardsDirectAdapter/rewardsDirectAdapter.js +209 -42
- package/dist/src/services/rewardsService/adapters/rewardsDirectAdapter/rewardsDirectAdapter.js.map +1 -1
- package/dist/src/services/rewardsService/adapters/rewardsV3Adapter/rewardsV3Adapter.d.ts.map +1 -1
- package/dist/src/services/rewardsService/adapters/rewardsV3Adapter/rewardsV3Adapter.js +38 -6
- package/dist/src/services/rewardsService/adapters/rewardsV3Adapter/rewardsV3Adapter.js.map +1 -1
- package/dist/src/services/rewardsService/adapters/rewardsV3Adapter/rewardsV3AdapterTypes.d.ts +15 -0
- package/dist/src/services/rewardsService/adapters/rewardsV3Adapter/rewardsV3AdapterTypes.d.ts.map +1 -1
- package/dist/src/services/rewardsService/rewardsService.d.ts +13 -2
- package/dist/src/services/rewardsService/rewardsService.d.ts.map +1 -1
- package/dist/src/services/rewardsService/rewardsService.js +272 -14
- package/dist/src/services/rewardsService/rewardsService.js.map +1 -1
- package/dist/src/services/rewardsService/rewardsServiceTypes.d.ts +44 -5
- package/dist/src/services/rewardsService/rewardsServiceTypes.d.ts.map +1 -1
- package/dist/src/services/swapService/swapService.d.ts +5 -7
- package/dist/src/services/swapService/swapService.d.ts.map +1 -1
- package/dist/src/services/swapService/swapService.js +93 -99
- package/dist/src/services/swapService/swapService.js.map +1 -1
- package/dist/src/services/swapService/swapVerification.d.ts +28 -0
- package/dist/src/services/swapService/swapVerification.d.ts.map +1 -0
- package/dist/src/services/swapService/swapVerification.js +139 -0
- package/dist/src/services/swapService/swapVerification.js.map +1 -0
- package/dist/src/services/tokenlistService/tokenlistService.d.ts +1 -1
- package/dist/src/services/tokenlistService/tokenlistService.d.ts.map +1 -1
- package/dist/src/services/tokenlistService/tokenlistService.js +51 -7
- package/dist/src/services/tokenlistService/tokenlistService.js.map +1 -1
- package/dist/src/services/tokenlistService/tokenlistServiceTypes.d.ts +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 +12 -3
- package/dist/src/services/vaults/eVaultService/adapters/eVaultV3Adapter/eVaultV3AdapterConversions.js.map +1 -1
- package/dist/src/services/vaults/eVaultService/adapters/eVaultV3Adapter/eVaultV3AdapterTypes.d.ts +1 -1
- package/dist/src/services/vaults/eVaultService/adapters/eVaultV3Adapter/eVaultV3AdapterTypes.d.ts.map +1 -1
- package/dist/src/services/vaults/eVaultService/eVaultService.d.ts.map +1 -1
- package/dist/src/services/vaults/eVaultService/eVaultService.js +5 -9
- package/dist/src/services/vaults/eVaultService/eVaultService.js.map +1 -1
- package/dist/src/services/vaults/eVaultService/eVaultServiceConfig.d.ts +1 -1
- package/dist/src/services/vaults/eVaultService/eVaultServiceConfig.d.ts.map +1 -1
- package/dist/src/services/vaults/eulerEarnService/adapters/eulerEarnOnchainAdapter.d.ts +1 -1
- package/dist/src/services/vaults/eulerEarnService/eulerEarnServiceConfig.d.ts +1 -1
- package/dist/src/services/vaults/eulerEarnService/eulerEarnServiceConfig.d.ts.map +1 -1
- package/dist/src/services/vaults/vaultMetaService/adapters/VaultTypeV3Adapter.d.ts +1 -1
- package/dist/src/services/vaults/vaultMetaService/adapters/VaultTypeV3Adapter.d.ts.map +1 -1
- package/dist/src/services/walletService/adapters/walletOnchainAdapter.d.ts +3 -1
- package/dist/src/services/walletService/adapters/walletOnchainAdapter.d.ts.map +1 -1
- package/dist/src/services/walletService/adapters/walletOnchainAdapter.js +89 -43
- package/dist/src/services/walletService/adapters/walletOnchainAdapter.js.map +1 -1
- package/dist/src/utils/buildQuery.d.ts +8 -1
- package/dist/src/utils/buildQuery.d.ts.map +1 -1
- package/dist/src/utils/buildQuery.js +70 -11
- package/dist/src/utils/buildQuery.js.map +1 -1
- package/dist/src/utils/eulerLabels.d.ts +1 -0
- package/dist/src/utils/eulerLabels.d.ts.map +1 -1
- package/dist/src/utils/eulerLabels.js +21 -2
- package/dist/src/utils/eulerLabels.js.map +1 -1
- package/dist/src/utils/oracle.d.ts +1 -0
- package/dist/src/utils/oracle.d.ts.map +1 -1
- package/dist/src/utils/oracle.js +36 -0
- package/dist/src/utils/oracle.js.map +1 -1
- package/package.json +1 -1
|
@@ -9,6 +9,8 @@ import * as encodeHelpers from "./encode.js";
|
|
|
9
9
|
import { isEVCBatchOperation } from "./executionServiceTypes.js";
|
|
10
10
|
import { executeTransactionPlan, } from "./execute.js";
|
|
11
11
|
import { deriveStateOverrides, estimateGasForTransactionPlan, simulateTransactionPlan, } from "./simulate.js";
|
|
12
|
+
import { adjustForInterest, getSwapInputAmount, } from "../swapService/swapVerification.js";
|
|
13
|
+
import { SwapperMode } from "../swapService/swapServiceTypes.js";
|
|
12
14
|
const TOKENS_REQUIRING_ZERO_APPROVAL_RESET = {
|
|
13
15
|
1: [getAddress("0xdAC17F958D2ee523a2206206994597C13D831ec7")],
|
|
14
16
|
};
|
|
@@ -26,6 +28,124 @@ function cloneBatchEntries(entries) {
|
|
|
26
28
|
? { type: "operation", name: entry.name, items: [...entry.items] }
|
|
27
29
|
: entry);
|
|
28
30
|
}
|
|
31
|
+
function hasSuppliedPosition(position) {
|
|
32
|
+
return position.assets > 0n || position.shares > 0n;
|
|
33
|
+
}
|
|
34
|
+
function hasShareConversion(vault) {
|
|
35
|
+
return (typeof vault === "object" &&
|
|
36
|
+
vault !== null &&
|
|
37
|
+
"convertToShares" in vault &&
|
|
38
|
+
typeof vault.convertToShares === "function");
|
|
39
|
+
}
|
|
40
|
+
function getStateTransition(item) {
|
|
41
|
+
try {
|
|
42
|
+
const decoded = decodeFunctionData({
|
|
43
|
+
abi: ethereumVaultConnectorAbi,
|
|
44
|
+
data: item.data,
|
|
45
|
+
});
|
|
46
|
+
if (decoded.functionName === "enableCollateral" ||
|
|
47
|
+
decoded.functionName === "disableCollateral" ||
|
|
48
|
+
decoded.functionName === "enableController") {
|
|
49
|
+
const [account, vault] = decoded.args;
|
|
50
|
+
return {
|
|
51
|
+
kind: decoded.functionName === "enableController"
|
|
52
|
+
? "controller"
|
|
53
|
+
: "collateral",
|
|
54
|
+
action: decoded.functionName.startsWith("enable")
|
|
55
|
+
? "enable"
|
|
56
|
+
: "disable",
|
|
57
|
+
account,
|
|
58
|
+
vault,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch { }
|
|
63
|
+
try {
|
|
64
|
+
const decoded = decodeFunctionData({
|
|
65
|
+
abi: eVaultAbi,
|
|
66
|
+
data: item.data,
|
|
67
|
+
});
|
|
68
|
+
if (decoded.functionName === "disableController") {
|
|
69
|
+
return {
|
|
70
|
+
kind: "controller",
|
|
71
|
+
action: "disable",
|
|
72
|
+
account: item.onBehalfOfAccount,
|
|
73
|
+
vault: item.targetContract,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch { }
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
function stateTransitionKey(transition) {
|
|
81
|
+
return `${transition.kind}:${getAddress(transition.account)}:${getAddress(transition.vault)}`;
|
|
82
|
+
}
|
|
83
|
+
function normalizeEVCStateTransitions(entries) {
|
|
84
|
+
const entryRefs = entries.map((entry) => isEVCBatchOperation(entry)
|
|
85
|
+
? entry.items.map((item) => ({
|
|
86
|
+
item,
|
|
87
|
+
remove: false,
|
|
88
|
+
transition: getStateTransition(item),
|
|
89
|
+
}))
|
|
90
|
+
: [
|
|
91
|
+
{
|
|
92
|
+
item: entry,
|
|
93
|
+
remove: false,
|
|
94
|
+
transition: getStateTransition(entry),
|
|
95
|
+
},
|
|
96
|
+
]);
|
|
97
|
+
const refs = entryRefs.flat();
|
|
98
|
+
const collateralStacks = new Map();
|
|
99
|
+
const controllerLast = new Map();
|
|
100
|
+
for (const ref of refs) {
|
|
101
|
+
const transition = ref.transition;
|
|
102
|
+
if (!transition)
|
|
103
|
+
continue;
|
|
104
|
+
const key = stateTransitionKey(transition);
|
|
105
|
+
if (transition.kind === "collateral") {
|
|
106
|
+
const stack = collateralStacks.get(key) ?? [];
|
|
107
|
+
const previous = stack[stack.length - 1];
|
|
108
|
+
if (previous?.action === transition.action) {
|
|
109
|
+
ref.remove = true;
|
|
110
|
+
}
|
|
111
|
+
else if (previous) {
|
|
112
|
+
previous.ref.remove = true;
|
|
113
|
+
ref.remove = true;
|
|
114
|
+
stack.pop();
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
stack.push({ action: transition.action, ref });
|
|
118
|
+
}
|
|
119
|
+
collateralStacks.set(key, stack);
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
const previous = controllerLast.get(key);
|
|
123
|
+
if (previous?.action === transition.action) {
|
|
124
|
+
ref.remove = true;
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
controllerLast.set(key, { action: transition.action });
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const result = [];
|
|
131
|
+
entries.forEach((entry, index) => {
|
|
132
|
+
const refsForEntry = entryRefs[index] ?? [];
|
|
133
|
+
if (isEVCBatchOperation(entry)) {
|
|
134
|
+
const items = refsForEntry
|
|
135
|
+
.filter((ref) => !ref.remove)
|
|
136
|
+
.map((ref) => ref.item);
|
|
137
|
+
if (items.length > 0) {
|
|
138
|
+
result.push({ type: "operation", name: entry.name, items });
|
|
139
|
+
}
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const ref = refsForEntry[0];
|
|
143
|
+
if (ref && !ref.remove) {
|
|
144
|
+
result.push(ref.item);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
return result;
|
|
148
|
+
}
|
|
29
149
|
const WAD = 10n ** 18n;
|
|
30
150
|
// TODO explain how this service is coupled to the concrete abis of ERC4626, permit2 and EVK.
|
|
31
151
|
// this is a helper service, not a generic one.
|
|
@@ -399,6 +519,19 @@ export class ExecutionService {
|
|
|
399
519
|
encodeSwapFromWallet(args) {
|
|
400
520
|
return encodeHelpers.encodeSwapFromWallet(args);
|
|
401
521
|
}
|
|
522
|
+
encodeSwapAndBorrowFromWallet(args) {
|
|
523
|
+
const { evc } = this.getCoreAddresses(args.chainId);
|
|
524
|
+
return encodeHelpers.encodeSwapAndBorrowFromWallet(evc, args);
|
|
525
|
+
}
|
|
526
|
+
encodeSwapAndRepayFromWallet(args) {
|
|
527
|
+
return encodeHelpers.encodeSwapAndRepayFromWallet(args);
|
|
528
|
+
}
|
|
529
|
+
encodeWithdrawAndSwap(args) {
|
|
530
|
+
return encodeHelpers.encodeWithdrawAndSwap(args);
|
|
531
|
+
}
|
|
532
|
+
encodeRedeemAndSwap(args) {
|
|
533
|
+
return encodeHelpers.encodeRedeemAndSwap(args);
|
|
534
|
+
}
|
|
402
535
|
/**
|
|
403
536
|
* Encodes EVC batch items for swapping collateral: withdraw from vaultIn → swap → verify/skim to receiver; optional enable/disable collateral.
|
|
404
537
|
* Swap quote should come from swapService.fetchDepositQuote() or match the same structure (verify type skimMin).
|
|
@@ -531,7 +664,7 @@ export class ExecutionService {
|
|
|
531
664
|
* @param args.spender - Address that will be allowed to transfer the token (e.g. vault or Permit2)
|
|
532
665
|
* @param args.nonce - Unique nonce for this permit (e.g. from Permit2 nonce(owner, token, spender))
|
|
533
666
|
* @param args.sigDeadline - Signature deadline (defaults to now + 1 hour if omitted)
|
|
534
|
-
* @param args.expiration - Permit expiration (defaults to
|
|
667
|
+
* @param args.expiration - Permit expiration (defaults to now + 1 hour if omitted)
|
|
535
668
|
* @returns EIP-712 typed data (domain, types, primaryType, message) for signing
|
|
536
669
|
*/
|
|
537
670
|
getPermit2TypedData(args) {
|
|
@@ -658,7 +791,13 @@ export class ExecutionService {
|
|
|
658
791
|
}
|
|
659
792
|
}
|
|
660
793
|
}
|
|
661
|
-
|
|
794
|
+
const optimizedExecutableItems = executableItems.flatMap((item) => {
|
|
795
|
+
if (item.type !== "evcBatch")
|
|
796
|
+
return [item];
|
|
797
|
+
const items = normalizeEVCStateTransitions(item.items);
|
|
798
|
+
return items.length > 0 ? [{ type: "evcBatch", items }] : [];
|
|
799
|
+
});
|
|
800
|
+
return [...approvalByKey.values(), ...optimizedExecutableItems];
|
|
662
801
|
}
|
|
663
802
|
/**
|
|
664
803
|
* Appends a raw batch item to the last EVC batch in the plan, or creates one.
|
|
@@ -738,11 +877,11 @@ export class ExecutionService {
|
|
|
738
877
|
* @param args.chainId - Chain ID (used to resolve Permit2 address when usePermit2 is true)
|
|
739
878
|
* @param args.wallet - Wallet entity with token balances and allowances (assetForVault, assetForPermit2, etc.)
|
|
740
879
|
* @param args.usePermit2 - If true, prefer Permit2 path (approve Permit2 + sign PermitSingle) when allowance is insufficient (default true)
|
|
741
|
-
* @param args.unlimitedApproval - If true,
|
|
880
|
+
* @param args.unlimitedApproval - If true, direct approvals and Permit2 signed amounts use maxUint256/maxUint160 (default false). Token approvals to Permit2 use maxUint256.
|
|
742
881
|
* @returns The same plan array with requiredApproval[].resolved populated (approve and/or permit2 data to sign)
|
|
743
882
|
*/
|
|
744
883
|
resolveRequiredApprovalsWithWallet(args) {
|
|
745
|
-
const { plan, wallet, chainId, usePermit2 = true, unlimitedApproval =
|
|
884
|
+
const { plan, wallet, chainId, usePermit2 = true, unlimitedApproval = false, } = args;
|
|
746
885
|
const deployment = this.deploymentService.getDeployment(chainId);
|
|
747
886
|
const permit2 = deployment.addresses.coreAddrs.permit2;
|
|
748
887
|
for (const item of plan) {
|
|
@@ -783,7 +922,7 @@ export class ExecutionService {
|
|
|
783
922
|
if (!walletAsset || !allowances) {
|
|
784
923
|
if (usePermit2) {
|
|
785
924
|
// Need approval to permit2 and permit2 signature
|
|
786
|
-
resolvedItems.push(makeApprove(permit2,
|
|
925
|
+
resolvedItems.push(makeApprove(permit2, maxUint256));
|
|
787
926
|
resolvedItems.push(makePermit2(spender, unlimitedApproval ? maxUint160 : amount));
|
|
788
927
|
}
|
|
789
928
|
else {
|
|
@@ -810,7 +949,7 @@ export class ExecutionService {
|
|
|
810
949
|
}
|
|
811
950
|
// If assetForPermit2 is insufficient, we need both approval and permit2 signature
|
|
812
951
|
if (!hasSufficientPermit2Allowance) {
|
|
813
|
-
addApproveWithOptionalReset(permit2,
|
|
952
|
+
addApproveWithOptionalReset(permit2, maxUint256, assetForPermit2);
|
|
814
953
|
resolvedItems.push(makePermit2(spender, unlimitedApproval ? maxUint160 : amount));
|
|
815
954
|
}
|
|
816
955
|
else {
|
|
@@ -880,6 +1019,55 @@ export class ExecutionService {
|
|
|
880
1019
|
});
|
|
881
1020
|
}
|
|
882
1021
|
// ========== Transaction plan functions ==========
|
|
1022
|
+
/**
|
|
1023
|
+
* Builds a cleanup plan matching Lite's stale collateral/controller policy.
|
|
1024
|
+
*
|
|
1025
|
+
* Cleanup is derived from the provided account snapshot:
|
|
1026
|
+
* - no enabled controllers: disable all enabled collaterals
|
|
1027
|
+
* - enabled controllers but no active borrows: disable all collaterals, then controllers
|
|
1028
|
+
* - active borrows: disable only enabled collaterals with no supplied position
|
|
1029
|
+
*
|
|
1030
|
+
* If the sub-account snapshot is unavailable, no cleanup is planned.
|
|
1031
|
+
*/
|
|
1032
|
+
planCleanup(args) {
|
|
1033
|
+
const { account, subAccount } = args;
|
|
1034
|
+
if (typeof account.getSubAccount !== "function")
|
|
1035
|
+
return [];
|
|
1036
|
+
const subAccountSnapshot = account.getSubAccount(subAccount);
|
|
1037
|
+
if (!subAccountSnapshot)
|
|
1038
|
+
return [];
|
|
1039
|
+
const collaterals = subAccountSnapshot.enabledCollaterals ?? [];
|
|
1040
|
+
const controllers = subAccountSnapshot.enabledControllers ?? [];
|
|
1041
|
+
if (collaterals.length === 0 && controllers.length === 0)
|
|
1042
|
+
return [];
|
|
1043
|
+
const items = [];
|
|
1044
|
+
const disableAllCollaterals = () => {
|
|
1045
|
+
for (const collateral of collaterals) {
|
|
1046
|
+
items.push(this.encodeDisableCollateral(account.chainId, subAccount, collateral));
|
|
1047
|
+
}
|
|
1048
|
+
};
|
|
1049
|
+
if (controllers.length === 0) {
|
|
1050
|
+
disableAllCollaterals();
|
|
1051
|
+
return this.convertBatchItemsToPlan(items, "cleanup");
|
|
1052
|
+
}
|
|
1053
|
+
const hasActiveBorrow = subAccountSnapshot.positions.some((position) => position.borrowed > 0n);
|
|
1054
|
+
if (!hasActiveBorrow) {
|
|
1055
|
+
disableAllCollaterals();
|
|
1056
|
+
for (const controller of controllers) {
|
|
1057
|
+
items.push(this.encodeDisableController(controller, subAccount));
|
|
1058
|
+
}
|
|
1059
|
+
return this.convertBatchItemsToPlan(items, "cleanup");
|
|
1060
|
+
}
|
|
1061
|
+
const depositedVaults = new Set(subAccountSnapshot.positions
|
|
1062
|
+
.filter(hasSuppliedPosition)
|
|
1063
|
+
.map((position) => getAddress(position.vaultAddress)));
|
|
1064
|
+
for (const collateral of collaterals) {
|
|
1065
|
+
if (depositedVaults.has(getAddress(collateral)))
|
|
1066
|
+
continue;
|
|
1067
|
+
items.push(this.encodeDisableCollateral(account.chainId, subAccount, collateral));
|
|
1068
|
+
}
|
|
1069
|
+
return this.convertBatchItemsToPlan(items, "cleanup");
|
|
1070
|
+
}
|
|
883
1071
|
/**
|
|
884
1072
|
* Builds a transaction plan for depositing assets into a vault.
|
|
885
1073
|
* Use `maxUint256` for `amount` to deposit all available assets from the wallet.
|
|
@@ -894,7 +1082,7 @@ export class ExecutionService {
|
|
|
894
1082
|
* @returns Array of transaction plan items (required approvals + EVC batch)
|
|
895
1083
|
*/
|
|
896
1084
|
planDeposit(args) {
|
|
897
|
-
const { vault, amount, receiver, account, asset, enableCollateral } = args;
|
|
1085
|
+
const { vault, amount, receiver, account, asset, enableCollateral, wrappedNativeInfo, } = args;
|
|
898
1086
|
const plan = [];
|
|
899
1087
|
// Default: collateral is not enabled when account/position is not available
|
|
900
1088
|
const isCollateralEnabled = account?.isCollateralEnabled(receiver, vault) ?? false;
|
|
@@ -914,6 +1102,7 @@ export class ExecutionService {
|
|
|
914
1102
|
receiver,
|
|
915
1103
|
owner: account.owner,
|
|
916
1104
|
enableCollateral: !isCollateralEnabled && enableCollateral,
|
|
1105
|
+
wrappedNativeInfo,
|
|
917
1106
|
// Permit2 is handled separately in the plan
|
|
918
1107
|
});
|
|
919
1108
|
plan.push(...this.convertBatchItemsToPlan(batchItems, "deposit"));
|
|
@@ -933,7 +1122,7 @@ export class ExecutionService {
|
|
|
933
1122
|
* @returns Array of transaction plan items (required approvals + EVC batch)
|
|
934
1123
|
*/
|
|
935
1124
|
planMint(args) {
|
|
936
|
-
const { vault, shares, receiver, account, asset, enableCollateral, sharesToAssetsExchangeRateWad, } = args;
|
|
1125
|
+
const { vault, shares, receiver, account, asset, enableCollateral, sharesToAssetsExchangeRateWad, wrappedNativeInfo, } = args;
|
|
937
1126
|
const plan = [];
|
|
938
1127
|
// Default: collateral is not enabled when account/position is not available
|
|
939
1128
|
const isCollateralEnabled = account?.isCollateralEnabled(receiver, vault) ?? false;
|
|
@@ -956,6 +1145,7 @@ export class ExecutionService {
|
|
|
956
1145
|
receiver,
|
|
957
1146
|
owner: account.owner,
|
|
958
1147
|
enableCollateral: !isCollateralEnabled && enableCollateral,
|
|
1148
|
+
wrappedNativeInfo,
|
|
959
1149
|
// Permit2 is handled separately in the plan
|
|
960
1150
|
});
|
|
961
1151
|
plan.push(...this.convertBatchItemsToPlan(batchItems, "mint"));
|
|
@@ -992,11 +1182,13 @@ export class ExecutionService {
|
|
|
992
1182
|
}
|
|
993
1183
|
/**
|
|
994
1184
|
* Builds a transaction plan for redeeming vault shares for underlying assets.
|
|
1185
|
+
* Pass `shares` directly, or pass `assets` to derive shares from the account's populated vault state.
|
|
995
1186
|
* Use `maxUint256` for `shares` to redeem all available shares.
|
|
996
1187
|
*
|
|
997
1188
|
* @param args - Redeem plan arguments
|
|
998
1189
|
* @param args.vault - Address of the vault to redeem shares from
|
|
999
1190
|
* @param args.shares - Number of vault shares to redeem (use maxUint256 for "redeem all")
|
|
1191
|
+
* @param args.assets - Underlying asset amount used to calculate shares from the account vault snapshot
|
|
1000
1192
|
* @param args.owner - Sub-account address whose shares are being redeemed
|
|
1001
1193
|
* @param args.receiver - Address that will receive the underlying assets
|
|
1002
1194
|
* @param args.account - Account entity; used for chainId and position/collateral state
|
|
@@ -1004,10 +1196,11 @@ export class ExecutionService {
|
|
|
1004
1196
|
* @returns Array of transaction plan items (EVC batch; no approvals needed for redeem)
|
|
1005
1197
|
*/
|
|
1006
1198
|
planRedeem(args) {
|
|
1007
|
-
const { vault,
|
|
1199
|
+
const { vault, receiver, owner, account, disableCollateral = false, } = args;
|
|
1008
1200
|
const plan = [];
|
|
1009
1201
|
// Get position to check collateral state
|
|
1010
1202
|
const position = account?.getPosition(owner, vault);
|
|
1203
|
+
const shares = this.resolveRedeemShares(args, position);
|
|
1011
1204
|
// Build EVC batch items
|
|
1012
1205
|
const batchItems = this.encodeRedeem({
|
|
1013
1206
|
chainId: account.chainId,
|
|
@@ -1020,6 +1213,19 @@ export class ExecutionService {
|
|
|
1020
1213
|
plan.push(...this.convertBatchItemsToPlan(batchItems, "redeem"));
|
|
1021
1214
|
return plan;
|
|
1022
1215
|
}
|
|
1216
|
+
resolveRedeemShares(args, position) {
|
|
1217
|
+
if ("shares" in args && args.shares !== undefined)
|
|
1218
|
+
return args.shares;
|
|
1219
|
+
const vault = position?.vault;
|
|
1220
|
+
if (!hasShareConversion(vault)) {
|
|
1221
|
+
throw new Error("planRedeem with assets requires account position vault state with convertToShares. Populate the account vaults before planning asset-denominated redeem.");
|
|
1222
|
+
}
|
|
1223
|
+
// Asset-denominated redeem intentionally rounds shares down via
|
|
1224
|
+
// convertToShares. Calling withdraw(assets) rounds shares up, which can
|
|
1225
|
+
// burn rounding remainders. The populated vault conversion keeps EVault
|
|
1226
|
+
// virtual deposits in the share calculation.
|
|
1227
|
+
return vault.convertToShares(args.assets);
|
|
1228
|
+
}
|
|
1023
1229
|
/**
|
|
1024
1230
|
* Builds a transaction plan for borrowing from a liability vault.
|
|
1025
1231
|
* Use `maxUint256` for `collateral.amount` to deposit all available collateral asset from the wallet.
|
|
@@ -1076,6 +1282,7 @@ export class ExecutionService {
|
|
|
1076
1282
|
enableCollateral,
|
|
1077
1283
|
collateralVault: collateral?.vault,
|
|
1078
1284
|
collateralAmount: walletCollateral?.amount,
|
|
1285
|
+
collateralWrappedNativeInfo: walletCollateral?.wrappedNativeInfo,
|
|
1079
1286
|
collateralShareSource: savingsCollateral
|
|
1080
1287
|
? {
|
|
1081
1288
|
from: savingsCollateral.from,
|
|
@@ -1153,15 +1360,16 @@ export class ExecutionService {
|
|
|
1153
1360
|
if (!position) {
|
|
1154
1361
|
throw new Error(`Position not found. Liability vault: ${liabilityVault}, Account: ${receiver}`);
|
|
1155
1362
|
}
|
|
1363
|
+
const isMax = liabilityAmount === maxUint256;
|
|
1364
|
+
const approvalAmount = adjustForInterest(isMax ? position.borrowed : liabilityAmount);
|
|
1156
1365
|
// Add approval requirement (will be resolved later with Wallet data)
|
|
1157
1366
|
plan.push({
|
|
1158
1367
|
type: "requiredApproval",
|
|
1159
1368
|
token: position.asset,
|
|
1160
1369
|
owner: account.owner,
|
|
1161
1370
|
spender: liabilityVault,
|
|
1162
|
-
amount:
|
|
1371
|
+
amount: approvalAmount,
|
|
1163
1372
|
});
|
|
1164
|
-
const isMax = liabilityAmount === maxUint256;
|
|
1165
1373
|
// Build EVC batch items
|
|
1166
1374
|
const batchItems = this.encodeRepayFromWallet({
|
|
1167
1375
|
chainId: account.chainId,
|
|
@@ -1288,7 +1496,7 @@ export class ExecutionService {
|
|
|
1288
1496
|
* @returns Array of transaction plan items (EVC batch: withdraw, swap, verify/repay). Throws if positions not found or liability is zero.
|
|
1289
1497
|
*/
|
|
1290
1498
|
planRepayWithSwap(args) {
|
|
1291
|
-
const { swapQuote, account, cleanupOnMax = false } = args;
|
|
1499
|
+
const { swapQuote, account, cleanupOnMax = false, swapperMode } = args;
|
|
1292
1500
|
const plan = [];
|
|
1293
1501
|
const liabilityPosition = account?.getPosition(swapQuote.accountOut, swapQuote.receiver);
|
|
1294
1502
|
const fromPosition = account?.getPosition(swapQuote.accountIn, swapQuote.vaultIn);
|
|
@@ -1306,6 +1514,7 @@ export class ExecutionService {
|
|
|
1306
1514
|
maxWithdraw,
|
|
1307
1515
|
isMax,
|
|
1308
1516
|
disableControllerOnMax: true,
|
|
1517
|
+
swapperMode,
|
|
1309
1518
|
});
|
|
1310
1519
|
if (cleanupOnMax && isMax) {
|
|
1311
1520
|
this.appendMaxRepayCleanup({
|
|
@@ -1334,7 +1543,7 @@ export class ExecutionService {
|
|
|
1334
1543
|
* @returns Array of transaction plan items (approval to SwapVerifier + EVC batch)
|
|
1335
1544
|
*/
|
|
1336
1545
|
planDepositWithSwapFromWallet(args) {
|
|
1337
|
-
const { swapQuote, amount, tokenIn, account, enableCollateral } = args;
|
|
1546
|
+
const { swapQuote, amount, tokenIn, account, enableCollateral, wrappedNativeInfo, } = args;
|
|
1338
1547
|
const plan = [];
|
|
1339
1548
|
// Approval goes to the transferFromSender contract (which uses permit2 transferFrom internally)
|
|
1340
1549
|
plan.push({
|
|
@@ -1358,6 +1567,7 @@ export class ExecutionService {
|
|
|
1358
1567
|
amount,
|
|
1359
1568
|
sender: account.owner,
|
|
1360
1569
|
enableCollateral: shouldEnableCollateral,
|
|
1570
|
+
wrappedNativeInfo,
|
|
1361
1571
|
});
|
|
1362
1572
|
plan.push(...this.convertBatchItemsToPlan(batchItems, "depositWithSwapFromWallet"));
|
|
1363
1573
|
return plan;
|
|
@@ -1374,7 +1584,7 @@ export class ExecutionService {
|
|
|
1374
1584
|
* @returns Array of transaction plan items (approval to SwapVerifier + EVC batch)
|
|
1375
1585
|
*/
|
|
1376
1586
|
planSwapFromWallet(args) {
|
|
1377
|
-
const { swapQuote, amount, tokenIn, account } = args;
|
|
1587
|
+
const { swapQuote, amount, tokenIn, account, wrappedNativeInfo } = args;
|
|
1378
1588
|
const plan = [];
|
|
1379
1589
|
plan.push({
|
|
1380
1590
|
type: "requiredApproval",
|
|
@@ -1388,10 +1598,102 @@ export class ExecutionService {
|
|
|
1388
1598
|
swapQuote,
|
|
1389
1599
|
amount,
|
|
1390
1600
|
sender: account.owner,
|
|
1601
|
+
wrappedNativeInfo,
|
|
1391
1602
|
});
|
|
1392
1603
|
plan.push(...this.convertBatchItemsToPlan(batchItems, "swapFromWallet"));
|
|
1393
1604
|
return plan;
|
|
1394
1605
|
}
|
|
1606
|
+
planSwapAndBorrowFromWallet(args) {
|
|
1607
|
+
const { swapQuote, amount, tokenIn, account, borrowVault, borrowAmount, borrowAccount = swapQuote.accountOut, receiver = account.owner, collateralVault = swapQuote.receiver, wrappedNativeInfo, } = args;
|
|
1608
|
+
const plan = [];
|
|
1609
|
+
plan.push({
|
|
1610
|
+
type: "requiredApproval",
|
|
1611
|
+
token: tokenIn,
|
|
1612
|
+
owner: account.owner,
|
|
1613
|
+
spender: swapQuote.verify.verifierAddress,
|
|
1614
|
+
amount,
|
|
1615
|
+
});
|
|
1616
|
+
const enableController = !(account?.isControllerEnabled(borrowAccount, borrowVault) ?? false);
|
|
1617
|
+
const enableCollateral = !(account?.isCollateralEnabled(borrowAccount, collateralVault) ?? false);
|
|
1618
|
+
const currentController = account?.getCurrentController(borrowAccount);
|
|
1619
|
+
const batchItems = this.encodeSwapAndBorrowFromWallet({
|
|
1620
|
+
chainId: account.chainId,
|
|
1621
|
+
swapQuote,
|
|
1622
|
+
amount,
|
|
1623
|
+
sender: account.owner,
|
|
1624
|
+
borrowAccount,
|
|
1625
|
+
collateralVault,
|
|
1626
|
+
borrowVault,
|
|
1627
|
+
borrowAmount,
|
|
1628
|
+
receiver,
|
|
1629
|
+
currentController: currentController || undefined,
|
|
1630
|
+
enableController,
|
|
1631
|
+
enableCollateral,
|
|
1632
|
+
wrappedNativeInfo,
|
|
1633
|
+
});
|
|
1634
|
+
plan.push(...this.convertBatchItemsToPlan(batchItems, "swapAndBorrowFromWallet"));
|
|
1635
|
+
return plan;
|
|
1636
|
+
}
|
|
1637
|
+
planSwapAndRepayFromWallet(args) {
|
|
1638
|
+
const { swapQuote, amount, tokenIn, account, liabilityVault = swapQuote.receiver, repayAccount = swapQuote.accountOut, isMax, cleanupOnMax = false, wrappedNativeInfo, } = args;
|
|
1639
|
+
const plan = [];
|
|
1640
|
+
plan.push({
|
|
1641
|
+
type: "requiredApproval",
|
|
1642
|
+
token: tokenIn,
|
|
1643
|
+
owner: account.owner,
|
|
1644
|
+
spender: swapQuote.verify.verifierAddress,
|
|
1645
|
+
amount,
|
|
1646
|
+
});
|
|
1647
|
+
const liabilityPosition = account?.getPosition(repayAccount, liabilityVault);
|
|
1648
|
+
const resolvedIsMax = isMax ??
|
|
1649
|
+
(liabilityPosition !== undefined &&
|
|
1650
|
+
liabilityPosition.borrowed <= BigInt(swapQuote.amountOutMin || 0));
|
|
1651
|
+
const batchItems = this.encodeSwapAndRepayFromWallet({
|
|
1652
|
+
chainId: account.chainId,
|
|
1653
|
+
swapQuote,
|
|
1654
|
+
amount,
|
|
1655
|
+
sender: account.owner,
|
|
1656
|
+
liabilityVault,
|
|
1657
|
+
repayAccount,
|
|
1658
|
+
isMax: resolvedIsMax,
|
|
1659
|
+
disableControllerOnMax: true,
|
|
1660
|
+
wrappedNativeInfo,
|
|
1661
|
+
});
|
|
1662
|
+
if (cleanupOnMax && resolvedIsMax && liabilityPosition) {
|
|
1663
|
+
this.appendMaxRepayCleanup({
|
|
1664
|
+
account,
|
|
1665
|
+
liabilityPosition,
|
|
1666
|
+
receiver: repayAccount,
|
|
1667
|
+
batchItems,
|
|
1668
|
+
});
|
|
1669
|
+
}
|
|
1670
|
+
plan.push(...this.convertBatchItemsToPlan(batchItems, "swapAndRepayFromWallet"));
|
|
1671
|
+
return plan;
|
|
1672
|
+
}
|
|
1673
|
+
planWithdrawAndSwap(args) {
|
|
1674
|
+
const { account, vault, assets, owner, swapQuote } = args;
|
|
1675
|
+
const batchItems = this.encodeWithdrawAndSwap({
|
|
1676
|
+
chainId: account.chainId,
|
|
1677
|
+
vault,
|
|
1678
|
+
assets,
|
|
1679
|
+
owner,
|
|
1680
|
+
sender: account.owner,
|
|
1681
|
+
swapQuote,
|
|
1682
|
+
});
|
|
1683
|
+
return this.convertBatchItemsToPlan(batchItems, "withdrawAndSwap");
|
|
1684
|
+
}
|
|
1685
|
+
planRedeemAndSwap(args) {
|
|
1686
|
+
const { account, vault, shares, owner, swapQuote } = args;
|
|
1687
|
+
const batchItems = this.encodeRedeemAndSwap({
|
|
1688
|
+
chainId: account.chainId,
|
|
1689
|
+
vault,
|
|
1690
|
+
shares,
|
|
1691
|
+
owner,
|
|
1692
|
+
sender: account.owner,
|
|
1693
|
+
swapQuote,
|
|
1694
|
+
});
|
|
1695
|
+
return this.convertBatchItemsToPlan(batchItems, "redeemAndSwap");
|
|
1696
|
+
}
|
|
1395
1697
|
/**
|
|
1396
1698
|
* Builds a transaction plan for swapping collateral from one vault to another (withdraw → swap → deposit/skim).
|
|
1397
1699
|
*
|
|
@@ -1401,7 +1703,7 @@ export class ExecutionService {
|
|
|
1401
1703
|
* @returns Array of transaction plan items (EVC batch: withdraw, swap, verify/skim, optional enable/disable collateral)
|
|
1402
1704
|
*/
|
|
1403
1705
|
planSwapCollateral(args) {
|
|
1404
|
-
const { swapQuote, account } = args;
|
|
1706
|
+
const { swapQuote, account, swapperMode } = args;
|
|
1405
1707
|
const plan = [];
|
|
1406
1708
|
// Check if source collateral needs to be disabled (when all is swapped)
|
|
1407
1709
|
// Default: when position is not available, assume amounts are zero, so we don't disable collateral
|
|
@@ -1420,6 +1722,7 @@ export class ExecutionService {
|
|
|
1420
1722
|
enableCollateral,
|
|
1421
1723
|
disableCollateralOnMax: true,
|
|
1422
1724
|
isMax,
|
|
1725
|
+
swapperMode,
|
|
1423
1726
|
});
|
|
1424
1727
|
plan.push(...this.convertBatchItemsToPlan(batchItems, "swapCollateral"));
|
|
1425
1728
|
return plan;
|
|
@@ -1433,11 +1736,11 @@ export class ExecutionService {
|
|
|
1433
1736
|
* @returns Array of transaction plan items (EVC batch: enableController, borrow, swap, verify/repay, optional disableController)
|
|
1434
1737
|
*/
|
|
1435
1738
|
planSwapDebt(args) {
|
|
1436
|
-
const { swapQuote, account } = args;
|
|
1739
|
+
const { swapQuote, account, swapperMode } = args;
|
|
1437
1740
|
const plan = [];
|
|
1438
|
-
const
|
|
1439
|
-
const isMax =
|
|
1440
|
-
?
|
|
1741
|
+
const liabilityPosition = account?.getPosition(swapQuote.accountIn, swapQuote.receiver);
|
|
1742
|
+
const isMax = liabilityPosition
|
|
1743
|
+
? liabilityPosition.borrowed <= BigInt(swapQuote.amountOutMin)
|
|
1441
1744
|
: false;
|
|
1442
1745
|
const enableController = !(account?.isControllerEnabled(swapQuote.accountOut, swapQuote.vaultIn) ??
|
|
1443
1746
|
false);
|
|
@@ -1448,6 +1751,7 @@ export class ExecutionService {
|
|
|
1448
1751
|
enableController,
|
|
1449
1752
|
disableControllerOnMax: true,
|
|
1450
1753
|
isMax,
|
|
1754
|
+
swapperMode,
|
|
1451
1755
|
});
|
|
1452
1756
|
plan.push(...this.convertBatchItemsToPlan(batchItems, "swapDebt"));
|
|
1453
1757
|
return plan;
|
|
@@ -1510,7 +1814,7 @@ export class ExecutionService {
|
|
|
1510
1814
|
* @param args.liabilityAmount - Current debt amount; defaults to the old-vault borrowed amount in account data
|
|
1511
1815
|
* @param args.oldLiabilityAsset - Optional old liability asset; defaults to the old-vault account position asset
|
|
1512
1816
|
* @param args.newLiabilityAsset - New liability underlying asset, used to verify this is a same-asset migration
|
|
1513
|
-
* @param args.sweepExcess - Whether to redeem and skim the migration cushion back into the new vault (default true)
|
|
1817
|
+
* @param args.sweepExcess - Whether to redeem and skim the migration cushion back into the new vault when the old vault has no pre-existing supplied shares (default true)
|
|
1514
1818
|
* @param args.transferRemainingSharesToOwner - Whether to transfer new-vault shares to the owner when liabilityAccount differs from owner (default true)
|
|
1515
1819
|
* @returns Array of transaction plan items (EVC batch; no token approvals)
|
|
1516
1820
|
*/
|
|
@@ -1534,6 +1838,7 @@ export class ExecutionService {
|
|
|
1534
1838
|
getAddress(liabilityAccount) !== getAddress(account.owner)
|
|
1535
1839
|
? account.owner
|
|
1536
1840
|
: undefined;
|
|
1841
|
+
const shouldSweepExcess = sweepExcess && !(oldPosition && hasSuppliedPosition(oldPosition));
|
|
1537
1842
|
const batchItems = this.encodeMigrateSameAssetDebt({
|
|
1538
1843
|
chainId: account.chainId,
|
|
1539
1844
|
oldLiabilityVault,
|
|
@@ -1542,7 +1847,7 @@ export class ExecutionService {
|
|
|
1542
1847
|
account: liabilityAccount,
|
|
1543
1848
|
enableController,
|
|
1544
1849
|
disableController: true,
|
|
1545
|
-
sweepExcess,
|
|
1850
|
+
sweepExcess: shouldSweepExcess,
|
|
1546
1851
|
transferRemainingSharesTo,
|
|
1547
1852
|
});
|
|
1548
1853
|
plan.push(...this.convertBatchItemsToPlan(batchItems, "migrateSameAssetDebt"));
|
|
@@ -1619,7 +1924,7 @@ export class ExecutionService {
|
|
|
1619
1924
|
* @returns Array of transaction plan items (optional approval + EVC batch). Throws if swapQuote.accountIn !== swapQuote.accountOut.
|
|
1620
1925
|
*/
|
|
1621
1926
|
planMultiplyWithSwap(args) {
|
|
1622
|
-
const { collateralVault, collateralAmount, collateralAsset, collateralShareSource, account, swapQuote, } = args;
|
|
1927
|
+
const { collateralVault, collateralAmount, collateralAsset, collateralShareSource, collateralWrappedNativeInfo, account, swapQuote, swapperMode, } = args;
|
|
1623
1928
|
const plan = [];
|
|
1624
1929
|
// 1. Check if collateral approval is needed (only if depositing collateral)
|
|
1625
1930
|
if (!collateralShareSource && collateralAmount > 0n) {
|
|
@@ -1638,13 +1943,14 @@ export class ExecutionService {
|
|
|
1638
1943
|
const receiver = swapQuote.accountIn;
|
|
1639
1944
|
const liabilityVault = swapQuote.vaultIn;
|
|
1640
1945
|
const longVault = swapQuote.receiver;
|
|
1641
|
-
const liabilityAmount =
|
|
1946
|
+
const liabilityAmount = getSwapInputAmount(swapQuote, swapperMode ?? SwapperMode.EXACT_IN);
|
|
1642
1947
|
// 2. Determine if collateral needs to be enabled
|
|
1643
1948
|
const hasCollateralInput = collateralShareSource
|
|
1644
1949
|
? collateralShareSource.shares > 0n
|
|
1645
1950
|
: collateralAmount > 0n;
|
|
1646
1951
|
const enableCollateral = hasCollateralInput &&
|
|
1647
1952
|
!(account?.isCollateralEnabled(receiver, collateralVault) ?? false);
|
|
1953
|
+
const enableCollateralLong = !(account?.isCollateralEnabled(receiver, longVault) ?? false);
|
|
1648
1954
|
const resolvedCollateralShareSource = collateralShareSource
|
|
1649
1955
|
? {
|
|
1650
1956
|
...collateralShareSource,
|
|
@@ -1671,7 +1977,9 @@ export class ExecutionService {
|
|
|
1671
1977
|
currentController: currentController || undefined,
|
|
1672
1978
|
enableController,
|
|
1673
1979
|
collateralShareSource: resolvedCollateralShareSource,
|
|
1980
|
+
collateralWrappedNativeInfo,
|
|
1674
1981
|
swapQuote,
|
|
1982
|
+
enableCollateralLong,
|
|
1675
1983
|
// Permit2 is handled separately in the plan
|
|
1676
1984
|
});
|
|
1677
1985
|
plan.push(...this.convertBatchItemsToPlan(batchItems, "multiplyWithSwap"));
|
|
@@ -1693,7 +2001,7 @@ export class ExecutionService {
|
|
|
1693
2001
|
* @returns Array of transaction plan items (optional approval + EVC batch)
|
|
1694
2002
|
*/
|
|
1695
2003
|
planMultiplySameAsset(args) {
|
|
1696
|
-
const { collateralVault, collateralAmount, collateralAsset, collateralShareSource, liabilityVault, liabilityAmount, longVault, receiver, account, } = args;
|
|
2004
|
+
const { collateralVault, collateralAmount, collateralAsset, collateralShareSource, collateralWrappedNativeInfo, liabilityVault, liabilityAmount, longVault, receiver, account, } = args;
|
|
1697
2005
|
const plan = [];
|
|
1698
2006
|
// 1. Check if collateral approval is needed (only if depositing collateral)
|
|
1699
2007
|
if (!collateralShareSource && collateralAmount > 0n) {
|
|
@@ -1712,6 +2020,7 @@ export class ExecutionService {
|
|
|
1712
2020
|
: collateralAmount > 0n;
|
|
1713
2021
|
const enableCollateral = hasCollateralInput &&
|
|
1714
2022
|
!(account?.isCollateralEnabled(receiver, collateralVault) ?? false);
|
|
2023
|
+
const enableCollateralLong = !(account?.isCollateralEnabled(receiver, longVault) ?? false);
|
|
1715
2024
|
const resolvedCollateralShareSource = collateralShareSource
|
|
1716
2025
|
? {
|
|
1717
2026
|
...collateralShareSource,
|
|
@@ -1738,6 +2047,8 @@ export class ExecutionService {
|
|
|
1738
2047
|
currentController: currentController || undefined,
|
|
1739
2048
|
enableController,
|
|
1740
2049
|
collateralShareSource: resolvedCollateralShareSource,
|
|
2050
|
+
collateralWrappedNativeInfo,
|
|
2051
|
+
enableCollateralLong,
|
|
1741
2052
|
// Permit2 is handled separately in the plan
|
|
1742
2053
|
});
|
|
1743
2054
|
plan.push(...this.convertBatchItemsToPlan(batchItems, "multiplySameAsset"));
|