|
|
@@ -311,12 +311,10 @@ export class CopyExecutor {
|
|
|
)
|
|
|
|
|
|
try {
|
|
|
- // Remove all liquidity with shouldClaimAndClose=true.
|
|
|
- // This removes liquidity, claims fees, AND closes the position account
|
|
|
- // in one step — no separate closePosition call needed.
|
|
|
- let followerTx: string
|
|
|
+ // Step 1: Remove all liquidity (without shouldClaimAndClose to avoid
|
|
|
+ // error 3007 on Token-2022 pools)
|
|
|
try {
|
|
|
- followerTx = await copyRemoveLiquidity(
|
|
|
+ await copyRemoveLiquidity(
|
|
|
this.connection,
|
|
|
this.follower,
|
|
|
new PublicKey(followerInfo.positionAddress),
|
|
|
@@ -325,18 +323,21 @@ export class CopyExecutor {
|
|
|
this.settings
|
|
|
)
|
|
|
} catch (removeErr) {
|
|
|
- // If remove fails (e.g. position already empty), try direct close
|
|
|
+ // Liquidity might already be removed (e.g. after a failed rebalance)
|
|
|
console.log(
|
|
|
- `[Executor] Remove liquidity failed (${removeErr}), trying direct close...`
|
|
|
- )
|
|
|
- followerTx = await copyClosePosition(
|
|
|
- this.connection,
|
|
|
- this.follower,
|
|
|
- new PublicKey(followerInfo.positionAddress),
|
|
|
- new PublicKey(followerInfo.lbPairAddress)
|
|
|
+ `[Executor] Remove liquidity failed (${removeErr}), proceeding to close...`
|
|
|
)
|
|
|
}
|
|
|
|
|
|
+ // Step 2: Close the empty position account (reclaims rent)
|
|
|
+ // copyClosePosition handles already-closed positions gracefully
|
|
|
+ const followerTx = await copyClosePosition(
|
|
|
+ this.connection,
|
|
|
+ this.follower,
|
|
|
+ new PublicKey(followerInfo.positionAddress),
|
|
|
+ new PublicKey(followerInfo.lbPairAddress)
|
|
|
+ )
|
|
|
+
|
|
|
await closeFollowerPosition(followerInfo.positionAddress)
|
|
|
await updateCopyTradeStatus(copyTrade.id, 'SUCCESS', {
|
|
|
followerTxSignature: followerTx,
|