|
|
@@ -17,6 +17,7 @@ import type { ParsedOperation } from '../monitor/types'
|
|
|
import { scaleAmount } from './ratio'
|
|
|
import { getTokenPrices, calculateCopyScale } from './price'
|
|
|
import { ensureSufficientBalances, getUsdcBalance, swapTokensBackToUsdc, USDC_MINT } from './swap'
|
|
|
+import { sendDiscordNotification } from '../discord'
|
|
|
|
|
|
// We import from the built SDK dist using relative path
|
|
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
|
@@ -112,6 +113,14 @@ export class CopyEngine {
|
|
|
|
|
|
console.log(`[CopyEngine] Manual close position TX: ${txid}`)
|
|
|
|
|
|
+ sendDiscordNotification({
|
|
|
+ operation: 'close_position',
|
|
|
+ status: 'success',
|
|
|
+ targetAddress: 'manual',
|
|
|
+ ourTxSig: txid,
|
|
|
+ ourNftMint: ourNftMint,
|
|
|
+ })
|
|
|
+
|
|
|
// Swap received tokens back to USDC (if enabled)
|
|
|
if (this.isSwapAfterCloseEnabled()) {
|
|
|
await sleep(3000)
|
|
|
@@ -226,9 +235,14 @@ export class CopyEngine {
|
|
|
// Check USDC balance before proceeding
|
|
|
const neededUsd = mintA === USDC_MINT || mintB === USDC_MINT ? ourUsd * 0.6 : ourUsd
|
|
|
if (!(await this.checkUsdcBalance(neededUsd))) {
|
|
|
- updateCopyHistory(historyId, {
|
|
|
+ const skipMsg = `Insufficient USDC balance for $${ourUsd.toFixed(2)} position`
|
|
|
+ updateCopyHistory(historyId, { status: 'skipped', errorMessage: skipMsg })
|
|
|
+ sendDiscordNotification({
|
|
|
+ operation: 'open_position',
|
|
|
status: 'skipped',
|
|
|
- errorMessage: `Insufficient USDC balance for $${ourUsd.toFixed(2)} position`,
|
|
|
+ targetAddress: op.signer,
|
|
|
+ targetTxSig: op.signature,
|
|
|
+ errorMessage: skipMsg,
|
|
|
})
|
|
|
return
|
|
|
}
|
|
|
@@ -305,10 +319,27 @@ export class CopyEngine {
|
|
|
tickLower: tickLower!,
|
|
|
tickUpper: tickUpper!,
|
|
|
})
|
|
|
+
|
|
|
+ sendDiscordNotification({
|
|
|
+ operation: 'open_position',
|
|
|
+ status: 'success',
|
|
|
+ targetAddress: op.signer,
|
|
|
+ targetTxSig: op.signature,
|
|
|
+ ourTxSig: txid,
|
|
|
+ ourNftMint: ourNftMint || undefined,
|
|
|
+ extraFields: [{ name: '金额', value: `$${ourUsd.toFixed(2)}`, inline: true }],
|
|
|
+ })
|
|
|
} catch (e) {
|
|
|
const msg = e instanceof Error ? e.message : String(e)
|
|
|
console.error(`[CopyEngine] Open position failed:`, msg)
|
|
|
updateCopyHistory(historyId, { status: 'failed', errorMessage: msg })
|
|
|
+ sendDiscordNotification({
|
|
|
+ operation: 'open_position',
|
|
|
+ status: 'failed',
|
|
|
+ targetAddress: op.signer,
|
|
|
+ targetTxSig: op.signature,
|
|
|
+ errorMessage: msg,
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -383,9 +414,14 @@ export class CopyEngine {
|
|
|
// Check USDC balance before proceeding
|
|
|
const neededUsd = mintA === USDC_MINT || mintB === USDC_MINT ? ourUsd * 0.6 : ourUsd
|
|
|
if (!(await this.checkUsdcBalance(neededUsd))) {
|
|
|
- updateCopyHistory(historyId, {
|
|
|
+ const skipMsg = `Insufficient USDC balance for $${ourUsd.toFixed(2)} add liquidity`
|
|
|
+ updateCopyHistory(historyId, { status: 'skipped', errorMessage: skipMsg })
|
|
|
+ sendDiscordNotification({
|
|
|
+ operation: 'add_liquidity',
|
|
|
status: 'skipped',
|
|
|
- errorMessage: `Insufficient USDC balance for $${ourUsd.toFixed(2)} add liquidity`,
|
|
|
+ targetAddress: op.signer,
|
|
|
+ targetTxSig: op.signature,
|
|
|
+ errorMessage: skipMsg,
|
|
|
})
|
|
|
return
|
|
|
}
|
|
|
@@ -434,10 +470,26 @@ export class CopyEngine {
|
|
|
ourAmountB: scaledAmountB.toString(),
|
|
|
status: 'success',
|
|
|
})
|
|
|
+ sendDiscordNotification({
|
|
|
+ operation: 'add_liquidity',
|
|
|
+ status: 'success',
|
|
|
+ targetAddress: op.signer,
|
|
|
+ targetTxSig: op.signature,
|
|
|
+ ourTxSig: txid,
|
|
|
+ ourNftMint: mapping.our_nft_mint,
|
|
|
+ extraFields: [{ name: '金额', value: `$${ourUsd.toFixed(2)}`, inline: true }],
|
|
|
+ })
|
|
|
} catch (e) {
|
|
|
const msg = e instanceof Error ? e.message : String(e)
|
|
|
console.error(`[CopyEngine] Add liquidity failed:`, msg)
|
|
|
updateCopyHistory(historyId, { status: 'failed', errorMessage: msg })
|
|
|
+ sendDiscordNotification({
|
|
|
+ operation: 'add_liquidity',
|
|
|
+ status: 'failed',
|
|
|
+ targetAddress: op.signer,
|
|
|
+ targetTxSig: op.signature,
|
|
|
+ errorMessage: msg,
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -510,10 +562,25 @@ export class CopyEngine {
|
|
|
ourTxSig: txid,
|
|
|
status: 'success',
|
|
|
})
|
|
|
+ sendDiscordNotification({
|
|
|
+ operation: 'decrease_liquidity',
|
|
|
+ status: 'success',
|
|
|
+ targetAddress: op.signer,
|
|
|
+ targetTxSig: op.signature,
|
|
|
+ ourTxSig: txid,
|
|
|
+ ourNftMint: mapping.our_nft_mint,
|
|
|
+ })
|
|
|
} catch (e) {
|
|
|
const msg = e instanceof Error ? e.message : String(e)
|
|
|
console.error(`[CopyEngine] Decrease liquidity failed:`, msg)
|
|
|
updateCopyHistory(historyId, { status: 'failed', errorMessage: msg })
|
|
|
+ sendDiscordNotification({
|
|
|
+ operation: 'decrease_liquidity',
|
|
|
+ status: 'failed',
|
|
|
+ targetAddress: op.signer,
|
|
|
+ targetTxSig: op.signature,
|
|
|
+ errorMessage: msg,
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -564,6 +631,15 @@ export class CopyEngine {
|
|
|
})
|
|
|
updatePositionMappingStatus(mapping.target_nft_mint, 'closed')
|
|
|
|
|
|
+ sendDiscordNotification({
|
|
|
+ operation: 'close_position',
|
|
|
+ status: 'success',
|
|
|
+ targetAddress: op.signer,
|
|
|
+ targetTxSig: op.signature,
|
|
|
+ ourTxSig: txid,
|
|
|
+ ourNftMint: mapping.our_nft_mint,
|
|
|
+ })
|
|
|
+
|
|
|
// Swap received tokens back to USDC (if enabled)
|
|
|
if (this.isSwapAfterCloseEnabled()) {
|
|
|
await sleep(3000)
|
|
|
@@ -579,6 +655,13 @@ export class CopyEngine {
|
|
|
const msg = e instanceof Error ? e.message : String(e)
|
|
|
console.error(`[CopyEngine] Close position failed:`, msg)
|
|
|
updateCopyHistory(historyId, { status: 'failed', errorMessage: msg })
|
|
|
+ sendDiscordNotification({
|
|
|
+ operation: 'close_position',
|
|
|
+ status: 'failed',
|
|
|
+ targetAddress: op.signer,
|
|
|
+ targetTxSig: op.signature,
|
|
|
+ errorMessage: msg,
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
}
|