add compound

master
TZGyn 3 months ago
parent e06983ea61
commit 6a65883448

@ -12,3 +12,14 @@ export const bybit_logs = pgTable('bybit_logs', (t) => ({
response: t.json('response').notNull(), response: t.json('response').notNull(),
createdAt: t.bigint('created_at', { mode: 'number' }).notNull(), createdAt: t.bigint('created_at', { mode: 'number' }).notNull(),
})) }))
export const stacking_config = pgTable('stacking_config', (t) => ({
id: t.text('id').primaryKey(),
threshhold: t.bigint('threshold', { mode: 'number' }).notNull(),
stackRate: t.integer('stack_rate').notNull(),
}))
export const current_stack = pgTable('current_stack', (t) => ({
id: t.text('id').primaryKey(),
stack: t.integer('stack').notNull(),
}))

@ -0,0 +1,14 @@
// nanoid code
const urlAlphabet =
'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'
export const nanoid = (size = 32) => {
let id = ''
let bytes = crypto.getRandomValues(new Uint8Array((size |= 0)))
while (size--) {
// Using the bitwise AND operator to "cap" the value of
// the random byte from 255 to 63, in that way we can make sure
// that the value will be a valid index for the "chars" string.
id += urlAlphabet[bytes[size] & 63]
}
return id
}

@ -0,0 +1,40 @@
import { db } from '$lib/db/index.js'
import { stacking_config } from '$lib/db/schema.js'
import { nanoid } from '$lib/nanoid.js'
import { eq } from 'drizzle-orm'
import { z } from 'zod'
export const POST = async ({ request }) => {
const body = await request.json()
const data = z
.object({
threshhold: z.number().min(0),
stackRate: z.number().min(0),
})
.safeParse(body)
if (!data.success) {
return new Response()
}
const existing = await db.query.stacking_config.findFirst()
if (!existing) {
await db.insert(stacking_config).values({
id: nanoid(),
stackRate: data.data.stackRate,
threshhold: data.data.threshhold,
})
} else {
await db
.update(stacking_config)
.set({
stackRate: data.data.stackRate,
threshhold: data.data.threshhold,
})
.where(eq(stacking_config.id, existing.id))
}
return new Response()
}

@ -24,6 +24,12 @@
icon: HomeIcon, icon: HomeIcon,
isActive: page.url.pathname === `/dashboard/crypto-data`, isActive: page.url.pathname === `/dashboard/crypto-data`,
}, },
{
title: 'Stack',
url: `/dashboard/stack`,
icon: CoinsIcon,
isActive: page.url.pathname === `/dashboard/stack`,
},
{ {
title: 'Download', title: 'Download',
url: `/dashboard/download`, url: `/dashboard/download`,

@ -0,0 +1,8 @@
import { db } from '$lib/db'
export const load = async () => {
const config = await db.query.stacking_config.findFirst()
return {
config,
}
}

@ -0,0 +1,38 @@
<script lang="ts">
import { Button } from '$lib/components/ui/button'
import { Input } from '$lib/components/ui/input'
let { config } = $props()
let stackRate = $state(config?.stackRate || 0)
let threshhold = $state(config?.threshold || 0)
</script>
<div class="p-4">
<div class="flex flex-col gap-4">
<div class="flex items-center gap-4">
<span>Threshold</span>
<Input bind:value={threshhold} type="number" class="flex-1" />
</div>
<div class="flex items-center gap-4">
<span>Stack Rate (+%):</span>
<Input bind:value={stackRate} type="number" class="flex-1" />
</div>
<Button
variant="secondary"
onclick={() => {
fetch('/api/bybit/stacking', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
stackRate,
threshhold,
}),
})
}}>
Submit
</Button>
</div>
</div>

@ -1,7 +1,13 @@
import { db } from '$lib/db/index.js' import { db } from '$lib/db/index.js'
import { bybit_logs } from '$lib/db/schema.js' import {
bybit_logs,
current_stack,
stacking_config,
} from '$lib/db/schema.js'
import { nanoid } from '$lib/nanoid.js'
import { json } from '@sveltejs/kit' import { json } from '@sveltejs/kit'
import { RestClientV5 } from 'bybit-api' import { RestClientV5 } from 'bybit-api'
import { eq } from 'drizzle-orm'
import { z } from 'zod' import { z } from 'zod'
export const POST = async ({ locals, request }) => { export const POST = async ({ locals, request }) => {
@ -11,6 +17,8 @@ export const POST = async ({ locals, request }) => {
return new Response() return new Response()
} }
const requestID = nanoid(6)
const body = await request.json() const body = await request.json()
console.log('Body:', body) console.log('Body:', body)
@ -27,6 +35,18 @@ export const POST = async ({ locals, request }) => {
stopLoss: z.string().optional(), stopLoss: z.string().optional(),
hedge: z.enum(['true', 'false']).optional(), hedge: z.enum(['true', 'false']).optional(),
}) })
const compoundingSchema = z.object({
type: z.literal('Compound'),
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(),
hedge: z.enum(['true', 'false']).optional(),
})
const percentSchema = z.object({ const percentSchema = z.object({
type: z.literal('Percent'), type: z.literal('Percent'),
key: z.string(), key: z.string(),
@ -51,7 +71,12 @@ export const POST = async ({ locals, request }) => {
side: z.enum(['Buy', 'Sell']).optional(), side: z.enum(['Buy', 'Sell']).optional(),
}) })
const form = z const form = z
.union([flatSchema, percentSchema, closePositionSchema]) .union([
flatSchema,
percentSchema,
closePositionSchema,
compoundingSchema,
])
.safeParse(body) .safeParse(body)
if (!form.success) { if (!form.success) {
@ -149,7 +174,7 @@ export const POST = async ({ locals, request }) => {
).toFixed(decimalLength) ).toFixed(decimalLength)
} }
positionIdx = form.data.side === 'Buy' ? 1 : 2 positionIdx = form.data.side === 'Buy' ? 1 : 2
} else { } else if (form.data.type === 'Close Position') {
const position = await client.getPositionInfo({ const position = await client.getPositionInfo({
category: 'linear', category: 'linear',
symbol: symbol, symbol: symbol,
@ -192,6 +217,21 @@ export const POST = async ({ locals, request }) => {
: ('Buy' as const) : ('Buy' as const)
qty = position.result.list[0].size qty = position.result.list[0].size
} }
} else {
const stacking_config =
await db.query.stacking_config.findFirst()
if (!stacking_config) {
return new Response()
}
qty = (
Number(form.data.qty) * Number(form.data.leverage || '1')
).toString()
takeProfit = form.data.takeProfit
stopLoss = form.data.stopLoss
side = form.data.side
positionIdx = form.data.side === 'Buy' ? 1 : 2
} }
console.log({ qty, takeProfit, stopLoss }) console.log({ qty, takeProfit, stopLoss })
@ -209,6 +249,64 @@ export const POST = async ({ locals, request }) => {
console.log('Order:', order) console.log('Order:', order)
if (form.data.type === 'Close Position') {
console.log('Close Position, checking for compound...')
const wallet = await client.getTransferableAmount({
coinName: 'USDT',
})
const balance = wallet.result.availableWithdrawal
console.log(`[REQUEST_${requestID}][COMPOUND]`)
console.log(
`[REQUEST_${requestID}][COMPOUND][AVAILABLE_BALANCE]`,
balance,
)
const config = await db.query.stacking_config.findFirst()
if (config) {
console.log(
`[REQUEST_${requestID}][COMPOUND][THRESHOLD]`,
config.threshhold,
)
if (parseFloat(balance) >= config.threshhold * 2) {
const withdrawAmount =
parseFloat(balance) - config.threshhold
console.log(
`[REQUEST_${requestID}][COMPOUNT][WITHDRAW_AMOUNT]`,
withdrawAmount,
)
const response = await client.createInternalTransfer(
crypto.randomUUID(),
'USDT',
withdrawAmount.toString(),
'UNIFIED',
'FUND',
)
console.log(
`[REQUEST_${requestID}][COMPOUNT][WITHDRAW_RESPONSE]`,
response,
)
const stack = await db.query.current_stack.findFirst()
if (stack) {
await db
.update(current_stack)
.set({
stack: stack.stack + config.stackRate,
})
.where(eq(current_stack.id, stack.id))
}
}
}
}
await db.insert(bybit_logs).values({ await db.insert(bybit_logs).values({
status: order.retCode === 0 ? 'success' : 'failed', status: order.retCode === 0 ? 'success' : 'failed',
request: form.data, request: form.data,

Loading…
Cancel
Save