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.
164 lines
4.0 KiB
TypeScript
164 lines
4.0 KiB
TypeScript
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')
|
|
if (type !== 'application/json; charset=utf-8') {
|
|
return new Response()
|
|
}
|
|
|
|
const body = await request.json()
|
|
|
|
console.log('Body:', body)
|
|
|
|
const flatSchema = z.object({
|
|
type: z.literal('Flat'),
|
|
key: z.string(),
|
|
secret: z.string(),
|
|
symbol: z.string(),
|
|
side: z.enum(['Buy', 'Sell']),
|
|
qty: z.string(),
|
|
leverage: z.string().optional(),
|
|
takeProfit: z.string().optional(),
|
|
stopLoss: z.string().optional(),
|
|
})
|
|
const percentSchema = z.object({
|
|
type: z.literal('Percent'),
|
|
key: z.string(),
|
|
secret: z.string(),
|
|
symbol: z.string(),
|
|
side: z.enum(['Buy', 'Sell']),
|
|
entryPrice: z.string(),
|
|
qtyPercent: z.string(),
|
|
qtyDecimalPoint: z.string(),
|
|
leverage: z.string().default('1'),
|
|
takeProfitPercent: z.string().optional(),
|
|
stopLossPercent: z.string().optional(),
|
|
// tpslDecimalPoint: z.string().default('1'),
|
|
})
|
|
const closePositionSchema = z.object({
|
|
type: z.literal('Close Position'),
|
|
key: z.string(),
|
|
secret: z.string(),
|
|
symbol: z.string(),
|
|
})
|
|
const form = z
|
|
.union([flatSchema, percentSchema, closePositionSchema])
|
|
.safeParse(body)
|
|
|
|
if (!form.success) {
|
|
console.log(form.error)
|
|
return json({}, { status: 400 })
|
|
}
|
|
|
|
const { key, secret, symbol } = form.data
|
|
|
|
try {
|
|
let qty
|
|
let takeProfit
|
|
let stopLoss
|
|
let side
|
|
|
|
let isLeverage
|
|
if (form.data.type === 'Close Position') {
|
|
isLeverage = false
|
|
} else if (form.data.leverage) {
|
|
isLeverage = true
|
|
} else {
|
|
isLeverage = false
|
|
}
|
|
|
|
const client = new RestClientV5({
|
|
key: key,
|
|
secret: secret,
|
|
demoTrading: true,
|
|
})
|
|
|
|
if (form.data.type === 'Flat') {
|
|
qty = (
|
|
Number(form.data.qty) * Number(form.data.leverage || '1')
|
|
).toString()
|
|
takeProfit = form.data.takeProfit
|
|
stopLoss = form.data.stopLoss
|
|
side = form.data.side
|
|
} else if (form.data.type === 'Percent') {
|
|
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
|
|
|
|
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))
|
|
takeProfit = (
|
|
Number(form.data.entryPrice) *
|
|
(1 + Number(form.data.takeProfitPercent) / 100)
|
|
).toFixed(decimalLength)
|
|
stopLoss = (
|
|
Number(form.data.entryPrice) *
|
|
(1 - Number(form.data.stopLossPercent) / 100)
|
|
).toFixed(decimalLength)
|
|
side = form.data.side
|
|
} else {
|
|
const position = await client.getPositionInfo({
|
|
category: 'linear',
|
|
symbol: symbol,
|
|
})
|
|
|
|
console.log('closing')
|
|
console.log(position.result.list)
|
|
|
|
if (position.result.list.length <= 0) {
|
|
return new Response()
|
|
}
|
|
|
|
if (position.result.list[0].side === 'None')
|
|
return new Response()
|
|
side =
|
|
position.result.list[0].side === 'Buy'
|
|
? ('Sell' as const)
|
|
: ('Buy' as const)
|
|
qty = position.result.list[0].size
|
|
}
|
|
|
|
console.log({ qty, takeProfit, stopLoss })
|
|
const order = await client.submitOrder({
|
|
category: 'linear',
|
|
symbol,
|
|
side,
|
|
orderType: 'Market',
|
|
qty,
|
|
takeProfit: side === 'Buy' ? takeProfit : stopLoss,
|
|
stopLoss: side === 'Buy' ? stopLoss : takeProfit,
|
|
isLeverage: isLeverage ? 1 : 0,
|
|
})
|
|
return new Response()
|
|
} catch (error) {
|
|
console.log('Error', error)
|
|
} finally {
|
|
return new Response()
|
|
}
|
|
}
|