Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
"ethers": "6.13.2",
"focus-visible": "5.2.1",
"js-cookie": "3.0.5",
"lightweight-charts": "4.2.0",
"next": "14.2.5",
"react": "18.3.1",
"react-dom": "18.3.1",
Expand Down
56 changes: 56 additions & 0 deletions src/app/api/boost-supply-diff/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { NextResponse } from 'next/server'
import { constants } from 'helpers'


type SupplyResponse = {
data: {
reserve: {
totalSupplies: string
supplyCap: string
}
}
}

export async function GET() {
// eslint-disable-next-line max-len
const aaveSubgraph = 'https://gateway.thegraph.com/api/007fa8d2e10d5b2394388e4ed945d8ab/subgraphs/id/Cd2gEDVeqnjBn1hSeqFMitw8Q1iiyV9FYUZkLNRcL87g'

try {
const response = await fetch(`${aaveSubgraph}?t=${new Date().getTime()}`, {
method: 'POST',
headers: {
'cache-control': 'no-store',
'content-type': 'application/json',
},
body: JSON.stringify({
query: `
{
reserve(id:"0xf1c9acdc66974dfb6decb12aa385b9cd01190e380x2f39d218133afab8f2b819b1066c7e434ad94e9e") {
totalSupplies
supplyCap
}
}
`,
}),
})

if (response?.status !== 200) {
throw new Error(`API request failed: ${response?.url}`)
}

const result = await response.json() as SupplyResponse

const { totalSupplies, supplyCap } = result.data.reserve
const supplyDiff = BigInt(supplyCap) * constants.blockchain.amount1 - BigInt(totalSupplies)

return NextResponse.json(supplyDiff.toString(), { status: 200 })
}
catch (error: any) {
const errorMessage = error?.message || error || 'Error'

return NextResponse.json({ error: errorMessage }, { status: 502 })
}
}


export const dynamic = 'force-dynamic'
15 changes: 15 additions & 0 deletions src/app/api/xlsx-export/calculateMaxWidths.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const calculateMaxWidths = (data: (string | number)[][]) => {
const maxWidths: number[] = []

data.forEach((row) => {
row.forEach((cell, index) => {
const cellLength = (cell) ? cell.toString().length : 0
maxWidths[index] = Math.max(maxWidths[index] || 0, cellLength)
})
})

return maxWidths.map((width) => ({ wch: Math.max(width, 10) }))
}


export default calculateMaxWidths
26 changes: 26 additions & 0 deletions src/app/api/xlsx-export/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { utils, write } from 'xlsx'
import { NextResponse } from 'next/server'

import calculateMaxWidths from './calculateMaxWidths'


export async function POST(request: Request) {
try {
const { data, format } = await request.json()
const contentType = request.headers.get('content-type') || 'application/json'

const workbook = utils.book_new()
const workSheet = utils.aoa_to_sheet(data)
workSheet['!cols'] = calculateMaxWidths(data)
utils.book_append_sheet(workbook, workSheet)

const result = write(workbook, { type: 'base64', bookType: format })

return NextResponse.json(result, { status: 200, headers: { 'content-type': contentType } })
}
catch (error: any) {
const errorMessage = error?.message || error || 'Error'

return NextResponse.json({ error: errorMessage }, { status: 500 })
}
}
16 changes: 16 additions & 0 deletions src/components/AmountInput/AmountInput.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.input {
text-overflow: ellipsis;

&:focus {
background-color: inherit;
border-radius: 0;
outline: none;
box-shadow: none;
appearance: none;
}

&:focus-visible {
outline: none !important;
box-shadow: none;
}
}
57 changes: 57 additions & 0 deletions src/components/AmountInput/AmountInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React, { RefObject, useId, useRef } from 'react'
import device from 'sw-modules/device'
import cx from 'classnames'

import s from './AmountInput.module.scss'


export type AmountInputProps = {
className?: string
value?: string
error?: boolean
disabled?: boolean
dataTestId?: string
isRequired?: boolean
onBlur?: () => void
onChange: (value: string, inputRef: RefObject<HTMLInputElement>) => void
}

const AmountInput: React.FC<AmountInputProps> = (props) => {
const {
value,
error,
disabled,
className,
isRequired,
dataTestId,
onBlur,
onChange,
} = props

const controlId = useId()
const { isMobile } = device.useData()
const testId = dataTestId || `input-${controlId}`
const inputRef = useRef<HTMLInputElement>(null)

return (
<input
className={cx(s.input, className, 'w-full', {
'text-moon': !error,
'text-volcano': error,
'text-h20': isMobile,
'text-t40m': !isMobile,
})}
ref={inputRef}
placeholder="0"
value={value}
disabled={disabled}
data-testid={testId}
required={isRequired}
onBlur={onBlur}
onChange={(event) => onChange(event.target.value, inputRef)}
/>
)
}


export default React.memo(AmountInput)
17 changes: 17 additions & 0 deletions src/components/AutoHeightToggle/AutoHeightToggle.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.container {
transition: .2s;
}

.content {
opacity: 1;

&.open {
transition: .6s;
}

&.close {
opacity: 0;
transition: .1s;
pointer-events: none;
}
}
74 changes: 74 additions & 0 deletions src/components/AutoHeightToggle/AutoHeightToggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React, { useRef } from 'react'
import { useIsomorphicLayoutEffect } from 'sw-hooks'
import cx from 'classnames'

import s from './AutoHeightToggle.module.scss'


export type AutoHeightToggleProps = {
className?: string
contentClassName?: string
children: React.ReactNode
toggleContent?: React.ReactNode
padding?: number
isOpen: boolean
dataTestId?: string
}

const AutoHeightToggle: React.FC<AutoHeightToggleProps> = (props) => {
const { className, children, toggleContent, contentClassName, isOpen, padding = 12, dataTestId } = props

const contentRef = useRef<HTMLDivElement>(null)
const childrenRef = useRef<HTMLDivElement>(null)
const containerRef = useRef<HTMLDivElement>(null)

useIsomorphicLayoutEffect(() => {
const isInit = containerRef.current && contentRef.current && childrenRef.current

if (!isInit) {
return
}

if (isOpen) {
const contentHeight = contentRef.current.clientHeight
const containerHeight = childrenRef.current.clientHeight
const marginTop = parseFloat(getComputedStyle(contentRef.current).marginTop)

containerRef.current.style.height = `calc(${padding * 2}rem + ${contentHeight + containerHeight + marginTop}px)`
}
else {
const height = childrenRef.current.clientHeight

containerRef.current.style.height = `calc(${padding * 2}rem + ${height}px)`
}
}, [ isOpen, toggleContent ])

const containerClassName = cx(className, s.container, `p-${padding} relative`)

const toggleContentClassName = cx(contentClassName, s.content, {
[s.open]: isOpen,
[s.close]: !isOpen,
})

return (
<div
ref={containerRef}
className={containerClassName}
data-testid={dataTestId}
>
<div ref={childrenRef}>
{children}
</div>
{
Boolean(toggleContent) && (
<div className={toggleContentClassName} ref={contentRef}>
{toggleContent}
</div>
)
}
</div>
)
}


export default React.memo(AutoHeightToggle)
37 changes: 37 additions & 0 deletions src/components/Bone/Bone.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
.bone {
opacity: 1;
background: rgb($color-moon-rgb / 0.03);
animation-name: fade-out, bone;
animation-fill-mode: forwards, forwards;
animation-direction: normal, alternate;
animation-iteration-count: 1, infinite;
animation-timing-function: ease-in-out, ease-in-out;
}

@for $i from 0 through 3 {
.delay-#{$i} {
animation-duration: 300ms, 1s;
animation-delay: #{$i * 200}ms, #{$i * 200 + 300}ms;
}
}

@keyframes fade-out {
0% {
opacity: 1;
}
100% {
opacity: .2;
}
}

@keyframes bone {
0% {
transform: translateY(6rem) scale(0.98);
opacity: .2;
}
85%,
100% {
transform: translateY(0) scale(1);
opacity: 1;
}
}
Loading