Function bodies 94 total
FormControl function · typescript · L107-L123 (17 LOC)components/ui/form.tsx
function FormControl({ ...props }: React.ComponentProps<typeof Slot.Root>) {
const { error, formItemId, formDescriptionId, formMessageId } = useFormField()
return (
<Slot.Root
data-slot="form-control"
id={formItemId}
aria-describedby={
!error
? `${formDescriptionId}`
: `${formDescriptionId} ${formMessageId}`
}
aria-invalid={!!error}
{...props}
/>
)
}FormDescription function · typescript · L125-L136 (12 LOC)components/ui/form.tsx
function FormDescription({ className, ...props }: React.ComponentProps<"p">) {
const { formDescriptionId } = useFormField()
return (
<p
data-slot="form-description"
id={formDescriptionId}
className={cn("text-muted-foreground text-sm", className)}
{...props}
/>
)
}FormMessage function · typescript · L138-L156 (19 LOC)components/ui/form.tsx
function FormMessage({ className, ...props }: React.ComponentProps<"p">) {
const { error, formMessageId } = useFormField()
const body = error ? String(error?.message ?? "") : props.children
if (!body) {
return null
}
return (
<p
data-slot="form-message"
id={formMessageId}
className={cn("text-destructive text-sm", className)}
{...props}
>
{body}
</p>
)
}Input function · typescript · L5-L19 (15 LOC)components/ui/input.tsx
function Input({ className, type, ...props }: React.ComponentProps<"input">) {
return (
<input
type={type}
data-slot="input"
className={cn(
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
className
)}
{...props}
/>
)
}Label function · typescript · L8-L22 (15 LOC)components/ui/label.tsx
function Label({
className,
...props
}: React.ComponentProps<typeof LabelPrimitive.Root>) {
return (
<LabelPrimitive.Root
data-slot="label"
className={cn(
"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
className
)}
{...props}
/>
)
}SelectTrigger function · typescript · L27-L51 (25 LOC)components/ui/select.tsx
function SelectTrigger({
className,
size = "default",
children,
...props
}: React.ComponentProps<typeof SelectPrimitive.Trigger> & {
size?: "sm" | "default"
}) {
return (
<SelectPrimitive.Trigger
data-slot="select-trigger"
data-size={size}
className={cn(
"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:daSelectContent function · typescript · L53-L88 (36 LOC)components/ui/select.tsx
function SelectContent({
className,
children,
position = "item-aligned",
align = "center",
...props
}: React.ComponentProps<typeof SelectPrimitive.Content>) {
return (
<SelectPrimitive.Portal>
<SelectPrimitive.Content
data-slot="select-content"
className={cn(
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md",
position === "popper" &&
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:Citation: Repobility (2026). State of AI-Generated Code. https://repobility.com/research/
SelectLabel function · typescript · L90-L101 (12 LOC)components/ui/select.tsx
function SelectLabel({
className,
...props
}: React.ComponentProps<typeof SelectPrimitive.Label>) {
return (
<SelectPrimitive.Label
data-slot="select-label"
className={cn("text-muted-foreground px-2 py-1.5 text-xs", className)}
{...props}
/>
)
}SelectItem function · typescript · L103-L128 (26 LOC)components/ui/select.tsx
function SelectItem({
className,
children,
...props
}: React.ComponentProps<typeof SelectPrimitive.Item>) {
return (
<SelectPrimitive.Item
data-slot="select-item"
className={cn(
"focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
className
)}
{...props}
>
<span
data-slot="select-item-indicator"
className="absolute right-2 flex size-3.5 items-center justify-center"
>
<SelectPrimitive.ItemIndicator>
<CheckIcon className="size-4" />
</SelectPrimitive.ItemIndicator>
</span>
<SelectPrimitive.ItemText>SelectSeparator function · typescript · L130-L141 (12 LOC)components/ui/select.tsx
function SelectSeparator({
className,
...props
}: React.ComponentProps<typeof SelectPrimitive.Separator>) {
return (
<SelectPrimitive.Separator
data-slot="select-separator"
className={cn("bg-border pointer-events-none -mx-1 my-1 h-px", className)}
{...props}
/>
)
}SelectScrollUpButton function · typescript · L143-L159 (17 LOC)components/ui/select.tsx
function SelectScrollUpButton({
className,
...props
}: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {
return (
<SelectPrimitive.ScrollUpButton
data-slot="select-scroll-up-button"
className={cn(
"flex cursor-default items-center justify-center py-1",
className
)}
{...props}
>
<ChevronUpIcon className="size-4" />
</SelectPrimitive.ScrollUpButton>
)
}SelectScrollDownButton function · typescript · L161-L177 (17 LOC)components/ui/select.tsx
function SelectScrollDownButton({
className,
...props
}: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {
return (
<SelectPrimitive.ScrollDownButton
data-slot="select-scroll-down-button"
className={cn(
"flex cursor-default items-center justify-center py-1",
className
)}
{...props}
>
<ChevronDownIcon className="size-4" />
</SelectPrimitive.ScrollDownButton>
)
}Table function · typescript · L7-L20 (14 LOC)components/ui/table.tsx
function Table({ className, ...props }: React.ComponentProps<"table">) {
return (
<div
data-slot="table-container"
className="relative w-full overflow-x-auto"
>
<table
data-slot="table"
className={cn("w-full caption-bottom text-sm", className)}
{...props}
/>
</div>
)
}TableHeader function · typescript · L22-L30 (9 LOC)components/ui/table.tsx
function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
return (
<thead
data-slot="table-header"
className={cn("[&_tr]:border-b", className)}
{...props}
/>
)
}TableBody function · typescript · L32-L40 (9 LOC)components/ui/table.tsx
function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
return (
<tbody
data-slot="table-body"
className={cn("[&_tr:last-child]:border-0", className)}
{...props}
/>
)
}Source: Repobility analyzer · https://repobility.com
TableFooter function · typescript · L42-L53 (12 LOC)components/ui/table.tsx
function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
return (
<tfoot
data-slot="table-footer"
className={cn(
"bg-muted/50 border-t font-medium [&>tr]:last:border-b-0",
className
)}
{...props}
/>
)
}TableRow function · typescript · L55-L66 (12 LOC)components/ui/table.tsx
function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
return (
<tr
data-slot="table-row"
className={cn(
"hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors",
className
)}
{...props}
/>
)
}TableHead function · typescript · L68-L79 (12 LOC)components/ui/table.tsx
function TableHead({ className, ...props }: React.ComponentProps<"th">) {
return (
<th
data-slot="table-head"
className={cn(
"text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
className
)}
{...props}
/>
)
}TableCell function · typescript · L81-L92 (12 LOC)components/ui/table.tsx
function TableCell({ className, ...props }: React.ComponentProps<"td">) {
return (
<td
data-slot="table-cell"
className={cn(
"p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
className
)}
{...props}
/>
)
}TableCaption function · typescript · L94-L105 (12 LOC)components/ui/table.tsx
function TableCaption({
className,
...props
}: React.ComponentProps<"caption">) {
return (
<caption
data-slot="table-caption"
className={cn("text-muted-foreground mt-4 text-sm", className)}
{...props}
/>
)
}Tabs function · typescript · L9-L26 (18 LOC)components/ui/tabs.tsx
function Tabs({
className,
orientation = "horizontal",
...props
}: React.ComponentProps<typeof TabsPrimitive.Root>) {
return (
<TabsPrimitive.Root
data-slot="tabs"
data-orientation={orientation}
orientation={orientation}
className={cn(
"group/tabs flex gap-2 data-[orientation=horizontal]:flex-col",
className
)}
{...props}
/>
)
}TabsList function · typescript · L43-L57 (15 LOC)components/ui/tabs.tsx
function TabsList({
className,
variant = "default",
...props
}: React.ComponentProps<typeof TabsPrimitive.List> &
VariantProps<typeof tabsListVariants>) {
return (
<TabsPrimitive.List
data-slot="tabs-list"
data-variant={variant}
className={cn(tabsListVariants({ variant }), className)}
{...props}
/>
)
}TabsTrigger function · typescript · L59-L76 (18 LOC)components/ui/tabs.tsx
function TabsTrigger({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
return (
<TabsPrimitive.Trigger
data-slot="tabs-trigger"
className={cn(
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring text-foreground/60 hover:text-foreground dark:text-muted-foreground dark:hover:text-foreground relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 group-data-[variant=default]/tabs-list:data-[state=active]:shadow-sm group-data-[variant=line]/tabs-list:data-[state=active]:shadow-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
"group-data-[Repobility · MCP-ready · https://repobility.com
TabsContent function · typescript · L78-L89 (12 LOC)components/ui/tabs.tsx
function TabsContent({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.Content>) {
return (
<TabsPrimitive.Content
data-slot="tabs-content"
className={cn("flex-1 outline-none", className)}
{...props}
/>
)
}Textarea function · typescript · L5-L16 (12 LOC)components/ui/textarea.tsx
function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
return (
<textarea
data-slot="textarea"
className={cn(
"border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
className
)}
{...props}
/>
)
}ConnectButton function · typescript · L14-L104 (91 LOC)components/wallet/ConnectButton.tsx
export function ConnectButton({ onAuthenticated }: ConnectButtonProps) {
const { address, isConnected } = useAccount()
const { signMessageAsync } = useSignMessage()
const [isAuthenticating, setIsAuthenticating] = useState(false)
const [isAuthenticated, setIsAuthenticated] = useState(false)
useEffect(() => {
const checkSession = async () => {
const res = await fetch('/api/auth/wallet/check', { method: 'GET' }).catch(() => null)
if (res?.ok) {
const data = await res.json()
if (data.authenticated) setIsAuthenticated(true)
}
}
if (isConnected) checkSession()
}, [isConnected])
const handleSignIn = async () => {
if (!address) return
setIsAuthenticating(true)
try {
const timestamp = Date.now()
const message = `Welcome to TradingCup!\n\nPlease sign this message to verify your wallet ownership.\n\nWallet: ${address}\nTimestamp: ${timestamp}`
const signature = await signMessageAsync({ message })
LbankStatusBadge function · typescript · L5-L25 (21 LOC)components/wallet/LbankStatusBadge.tsx
export function LbankStatusBadge() {
const [connected, setConnected] = useState<boolean | null>(null)
useEffect(() => {
fetch('/api/lbank/status')
.then((r) => r.json())
.then((d) => setConnected(d.connected))
.catch(() => setConnected(false))
}, [])
if (connected === null) return <span className="inline-block h-2 w-2 rounded-full bg-zinc-600" />
return (
<span
className={`inline-block h-2 w-2 rounded-full shrink-0 ${
connected ? 'bg-green-400' : 'bg-zinc-500'
}`}
title={connected ? 'LBank 接続済み' : 'LBank 未接続'}
/>
)
}getKey function · typescript · L7-L12 (6 LOC)lib/crypto/encryption.ts
function getKey(): Buffer {
const key = process.env.ENCRYPTION_KEY
if (!key) throw new Error('ENCRYPTION_KEY is not set')
// Derive 32-byte key from the env string
return createHash('sha256').update(key).digest()
}encrypt function · typescript · L14-L28 (15 LOC)lib/crypto/encryption.ts
export function encrypt(plaintext: string): string {
const key = getKey()
const iv = randomBytes(IV_LENGTH)
const cipher = createCipheriv(ALGORITHM, key, iv)
const encrypted = Buffer.concat([
cipher.update(plaintext, 'utf8'),
cipher.final(),
])
const tag = cipher.getAuthTag()
// Format: iv(12) + tag(16) + encrypted
const combined = Buffer.concat([iv, tag, encrypted])
return combined.toString('base64')
}decrypt function · typescript · L30-L46 (17 LOC)lib/crypto/encryption.ts
export function decrypt(ciphertext: string): string {
const key = getKey()
const combined = Buffer.from(ciphertext, 'base64')
const iv = combined.subarray(0, IV_LENGTH)
const tag = combined.subarray(IV_LENGTH, IV_LENGTH + TAG_LENGTH)
const encrypted = combined.subarray(IV_LENGTH + TAG_LENGTH)
const decipher = createDecipheriv(ALGORITHM, key, iv)
decipher.setAuthTag(tag)
const decrypted = Buffer.concat([
decipher.update(encrypted),
decipher.final(),
])
return decrypted.toString('utf8')
}buildSignature function · typescript · L20-L39 (20 LOC)lib/lbank/api.ts
function buildSignature(params: Record<string, string>, secretKey: string): string {
// Sort params alphabetically
const sortedKeys = Object.keys(params).sort()
const sorted = sortedKeys.map((k) => `${k}=${params[k]}`).join('&')
// MD5 hash -> uppercase hex
const md5Hash = md5Uppercase(sorted)
// HmacSHA256 with secretKey -> HEX (LBank requires hex, not base64)
const signature = createHmac('sha256', secretKey)
.update(md5Hash)
.digest('hex')
console.log('[LBank sign] sorted keys:', sortedKeys)
console.log('[LBank sign] signed string:', sorted)
console.log('[LBank sign] md5:', md5Hash)
console.log('[LBank sign] signature:', signature)
return signature
}Repobility · severity-and-effort ranking · https://repobility.com
lbankPost function · typescript · L80-L107 (28 LOC)lib/lbank/api.ts
async function lbankPost<T>(
endpoint: string,
params: LBankRequestParams,
apiKey: string,
secretKey: string
): Promise<T> {
const { body, headers } = buildLBankRequest(params, apiKey, secretKey)
const res = await fetch(`${LBANK_BASE_URL}${endpoint}`, {
method: 'POST',
headers,
body: body.toString(),
})
if (!res.ok) {
throw new Error(`LBank API error: ${res.status} ${res.statusText}`)
}
const json: LBankResponse<T> = await res.json()
console.log('[LBank raw response]', JSON.stringify(json))
if (json.result !== 'true' && json.result !== 'True' && json.result !== true) {
throw new Error(`LBank error ${json.error_code}: ${json.msg ?? 'unknown error'}`)
}
return json.data as T
}getUSDTBalance function · typescript · L129-L137 (9 LOC)lib/lbank/api.ts
export async function getUSDTBalance(
apiKey: string,
secretKey: string
): Promise<number> {
const balances = await getAccountBalance(apiKey, secretKey)
const usdt = balances.find((b) => b.asset.toLowerCase() === 'usdt')
if (!usdt) return 0
return parseFloat(usdt.available) + parseFloat(usdt.freeze)
}getTransactionHistory function · typescript · L140-L156 (17 LOC)lib/lbank/api.ts
export async function getTransactionHistory(
apiKey: string,
secretKey: string,
symbol: string = 'izky_usdt',
startTime?: number,
endTime?: number,
limit: number = 100
): Promise<{
orderId: string
symbol: string
side: string
price: string
volume: string
dealVolume: string
dealPrice: string
transactTime: string
}[]> {getVolumeForPair function · typescript · L189-L211 (23 LOC)lib/lbank/api.ts
export async function getVolumeForPair(
apiKey: string,
secretKey: string,
startTimestamp: number
): Promise<number> {
const trades = await getTransactionHistory(
apiKey,
secretKey,
'izky_usdt',
startTimestamp,
undefined,
100
)
let totalVolume = 0
for (const trade of trades) {
// Volume in USDT = dealVolume * dealPrice (or use dealVolume directly if it's USDT side)
const vol = parseFloat(trade.dealVolume) * parseFloat(trade.dealPrice)
if (!isNaN(vol)) totalVolume += vol
}
return totalVolume
}createClient function · typescript · L3-L8 (6 LOC)lib/supabase/client.ts
export function createClient() {
return createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)
}createClient function · typescript · L5-L28 (24 LOC)lib/supabase/server.ts
export async function createClient() {
const cookieStore = await cookies()
return createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() {
return cookieStore.getAll()
},
setAll(cookiesToSet) {
try {
cookiesToSet.forEach(({ name, value, options }) =>
cookieStore.set(name, value, options)
)
} catch {
// Server component - cookies cannot be set
}
},
},
}
)
}createServiceClient function · typescript · L31-L42 (12 LOC)lib/supabase/server.ts
export function createServiceClient() {
return createSupabaseClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!,
{
auth: {
autoRefreshToken: false,
persistSession: false,
},
}
)
}proxy function · typescript · L5-L44 (40 LOC)proxy.ts
export async function proxy(request: NextRequest) {
let response = NextResponse.next({
request: {
headers: request.headers,
},
})
const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() {
return request.cookies.getAll()
},
setAll(cookiesToSet) {
cookiesToSet.forEach(({ name, value }) =>
request.cookies.set(name, value)
)
response = NextResponse.next({ request })
cookiesToSet.forEach(({ name, value, options }) =>
response.cookies.set(name, value, options)
)
},
},
}
)
const { data: { user } } = await supabase.auth.getUser()
// Admin routes: require authenticated Supabase user
if (request.nextUrl.pathname.startsWith('/admin') &&
!request.nextUrl.pathname.startsWith('/admin/login')) {
if (!user) {
return NextResponse.Citation: Repobility (2026). State of AI-Generated Code. https://repobility.com/research/
decryptAesGcm function · typescript · L122-L144 (23 LOC)supabase/functions/update-rankings/index.ts
async function decryptAesGcm(ciphertext: string, keyString: string): Promise<string> {
const combined = Uint8Array.from(atob(ciphertext), (c) => c.charCodeAt(0))
const iv = combined.slice(0, 12)
const tag = combined.slice(12, 28) // ignored by Web Crypto (tag is appended to ciphertext)
const encrypted = combined.slice(28)
const encryptedWithTag = new Uint8Array([...encrypted, ...tag])
const keyBytes = await crypto.subtle.digest(
'SHA-256',
new TextEncoder().encode(keyString)
)
const cryptoKey = await crypto.subtle.importKey(
'raw', keyBytes, { name: 'AES-GCM' }, false, ['decrypt']
)
const decrypted = await crypto.subtle.decrypt(
{ name: 'AES-GCM', iv },
cryptoKey,
encryptedWithTag
)
return new TextDecoder().decode(decrypted)
}buildLBankRequest function · typescript · L147-L195 (49 LOC)supabase/functions/update-rankings/index.ts
async function buildLBankRequest(
params: Record<string, string>,
apiKey: string,
secretKey: string
) {
const timestamp = Date.now().toString()
const echostr = Array.from({ length: 35 }, () =>
'abcdefghijklmnopqrstuvwxyz0123456789'.charAt(Math.floor(Math.random() * 36))
).join('')
const allParams: Record<string, string> = {
...params,
api_key: apiKey,
signature_method: 'HmacSHA256',
timestamp,
echostr,
}
// Sort and build string
const sorted = Object.keys(allParams)
.sort()
.map((k) => `${k}=${allParams[k]}`)
.join('&')
// MD5 hash (uppercase)
const md5Hash = await md5Uppercase(sorted)
// HmacSHA256 signature
const keyBytes = new TextEncoder().encode(secretKey)
const hmacKey = await crypto.subtle.importKey(
'raw', keyBytes, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']
)
const sigBytes = await crypto.subtle.sign('HMAC', hmacKey, new TextEncoder().encode(md5Hash))
const signature = Array.from(new Uint8Amd5Uppercase function · typescript · L197-L207 (11 LOC)supabase/functions/update-rankings/index.ts
async function md5Uppercase(str: string): Promise<string> {
const msgBuffer = new TextEncoder().encode(str)
const hashBuffer = await crypto.subtle.digest('MD5', msgBuffer).catch(() => {
// MD5 not available in some environments - fallback
throw new Error('MD5 not available')
})
return Array.from(new Uint8Array(hashBuffer))
.map((b) => b.toString(16).padStart(2, '0'))
.join('')
.toUpperCase()
}getLBankUSDTBalance function · typescript · L209-L220 (12 LOC)supabase/functions/update-rankings/index.ts
async function getLBankUSDTBalance(apiKey: string, secretKey: string): Promise<number> {
const { body, headers } = await buildLBankRequest({}, apiKey, secretKey)
const res = await fetch('https://api.lbkex.com/v2/supplement/user_info_account.do', {
method: 'POST',
headers,
body,
})
const json = await res.json()
const free = json?.data?.info?.free?.usdt ?? '0'
const freeze = json?.data?.info?.freeze?.usdt ?? '0'
return parseFloat(free) + parseFloat(freeze)
}getLBankVolume function · typescript · L222-L248 (27 LOC)supabase/functions/update-rankings/index.ts
async function getLBankVolume(
apiKey: string,
secretKey: string,
startTimestamp: number
): Promise<number> {
const { body, headers } = await buildLBankRequest(
{ symbol: 'izky_usdt', current_page: '1', page_length: '100' },
apiKey,
secretKey
)
const res = await fetch('https://api.lbkex.com/v2/supplement/transaction_history.do', {
method: 'POST',
headers,
body,
})
const json = await res.json()
const orders = json?.data?.orders ?? []
let total = 0
for (const order of orders) {
const t = parseInt(order.transactTime ?? '0')
if (t < startTimestamp) continue
const vol = parseFloat(order.dealVolume ?? '0') * parseFloat(order.dealPrice ?? '0')
if (!isNaN(vol)) total += vol
}
return total
}‹ prevpage 2 / 2