You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

263 lines
6.2 KiB
TypeScript

import { db } from '$lib/db/index.js'
import { bybit_logs } from '$lib/db/schema.js'
import { json } from '@sveltejs/kit'
import { RestClientV5 } from 'bybit-api'
import { z } from 'zod'
export const POST = async ({ locals, request }) => {
const type = request.headers.get('Content-Type')
console.log(type)
if (!type || !type.startsWith('application/json')) {
return new Response()
}
const body = await request.json()
console.log('Body:', body)
const schema = z.object({
key: z.string(),
secret: z.string(),
symbol: z.string(),
entryPrice: z.string(),
qtyPercent: z.string(),
qtyDecimalPoint: z.string(),
leverage: z.string().default('1'),
takeProfitPercent: z.string(),
stopLossPercent: z.string(),
activePricePercent: z.string(),
trailingDistancePercent: z.string(),
demo: z.enum(['true', 'false']),
})
const form = schema.safeParse(body)
if (!form.success) {
console.log(form.error)
return json({}, { status: 400 })
}
const { key, secret, symbol, demo } = form.data
try {
const client = new RestClientV5({
key: key,
secret: secret,
demoTrading: demo === 'true',
})
client.switchPositionMode({
category: 'linear',
mode: 3,
})
const position = await client.getPositionInfo({
category: 'linear',
symbol: symbol,
})
console.log('Positions:', position.result.list)
if (
position.result.list.reduce(
(acc, curr) => acc + Number(curr.positionValue),
0,
) > 0
) {
console.log('Order exist, exiting...')
return new Response()
}
const wallet = await client.getWalletBalance({
accountType: 'UNIFIED',
coin: 'USDT',
})
console.log(
'Available Balance:',
wallet.result.list[0].totalAvailableBalance,
)
console.log('calculate:')
console.log('Entry Price:', form.data.entryPrice)
console.log('Qty Percent:', form.data.qtyPercent)
console.log(
'Wallet Balance:',
wallet.result.list[0].totalAvailableBalance,
)
const [price, decimals] = form.data.entryPrice.split('.')
console.log('Decimals', decimals)
console.log('Decimals Length', decimals?.length || 0)
const decimalLength = decimals?.length || 0
const qty = (
(Number(wallet.result.list[0].totalAvailableBalance) *
((Number(form.data.qtyPercent) / 100) *
Number(form.data.leverage || '1'))) /
Number(form.data.entryPrice)
).toFixed(Number(form.data.qtyDecimalPoint))
const takeProfitBuy = (
Number(form.data.entryPrice) *
(1 + Number(form.data.takeProfitPercent) / 100)
).toFixed(decimalLength)
const stopLossBuy = (
Number(form.data.entryPrice) *
(1 - Number(form.data.stopLossPercent) / 100)
).toFixed(decimalLength)
const takeProfitSell = (
Number(form.data.entryPrice) *
(1 - Number(form.data.takeProfitPercent) / 100)
).toFixed(decimalLength)
const stopLossSell = (
Number(form.data.entryPrice) *
(1 + Number(form.data.stopLossPercent) / 100)
).toFixed(decimalLength)
console.log({
qty,
takeProfitBuy,
stopLossBuy,
takeProfitSell,
stopLossSell,
})
const orders = await Promise.all([
await client.submitOrder({
category: 'linear',
symbol,
side: 'Buy',
orderType: 'Market',
qty,
takeProfit: takeProfitBuy,
stopLoss: stopLossBuy,
isLeverage: form.data.leverage ? 1 : 0,
positionIdx: 1,
}),
await client.submitOrder({
category: 'linear',
symbol,
side: 'Sell',
orderType: 'Market',
qty,
takeProfit: takeProfitSell,
stopLoss: stopLossSell,
isLeverage: form.data.leverage ? 1 : 0,
positionIdx: 2,
}),
])
console.log('Orders:', orders)
const activePriceBuy = (
Number(form.data.entryPrice) *
(1 + Number(form.data.activePricePercent) / 100)
).toFixed(decimalLength)
const activePriceSell = (
Number(form.data.entryPrice) *
(1 - Number(form.data.activePricePercent) / 100)
).toFixed(decimalLength)
const trailingDistance = (
Number(form.data.entryPrice) *
(Number(form.data.activePricePercent) / 100)
).toFixed(decimalLength)
const tradingStops = await Promise.all([
await client.setTradingStop({
category: 'linear',
activePrice: activePriceBuy,
trailingStop: trailingDistance,
symbol: symbol,
positionIdx: 1,
}),
await client.setTradingStop({
category: 'linear',
activePrice: activePriceSell,
trailingStop: trailingDistance,
symbol: symbol,
positionIdx: 2,
}),
])
console.log('Trading Stops:', tradingStops)
const buyOrder = orders[0]
const sellOrder = orders[1]
const buyTradingStop = tradingStops[0]
const sellTradingStop = tradingStops[1]
const logs = await Promise.all([
await db.insert(bybit_logs).values({
status: buyOrder.retCode === 0 ? 'success' : 'failed',
request: form.data,
payload: {
category: 'linear',
symbol,
side: 'Buy',
orderType: 'Market',
qty,
takeProfit: takeProfitBuy,
stopLoss: stopLossBuy,
isLeverage: form.data.leverage ? 1 : 0,
positionIdx: 1,
},
response: buyOrder,
createdAt: Date.now(),
}),
await db.insert(bybit_logs).values({
status: sellOrder.retCode === 0 ? 'success' : 'failed',
request: form.data,
payload: {
category: 'linear',
symbol,
side: 'Sell',
orderType: 'Market',
qty,
takeProfit: takeProfitSell,
stopLoss: stopLossSell,
isLeverage: form.data.leverage ? 1 : 0,
positionIdx: 1,
},
response: sellOrder,
createdAt: Date.now(),
}),
await db.insert(bybit_logs).values({
status: buyTradingStop.retCode === 0 ? 'success' : 'failed',
type: 'trading stop',
request: form.data,
payload: {
category: 'linear',
activePrice: activePriceBuy,
trailingStop: trailingDistance,
symbol: symbol,
positionIdx: 1,
},
response: buyTradingStop,
createdAt: Date.now(),
}),
await db.insert(bybit_logs).values({
status: sellTradingStop.retCode === 0 ? 'success' : 'failed',
type: 'trading stop',
request: form.data,
payload: {
category: 'linear',
activePrice: activePriceSell,
trailingStop: trailingDistance,
symbol: symbol,
positionIdx: 2,
},
response: sellTradingStop,
createdAt: Date.now(),
}),
])
return new Response()
} catch (error) {
console.log('Error', error)
} finally {
return new Response()
}
}