diff --git a/.changeset/config.json b/.changeset/config.json deleted file mode 100644 index 953b662a94..0000000000 --- a/.changeset/config.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "$schema": "https://unpkg.com/@changesets/config@2.0.0/schema.json", - "changelog": [ - "@changesets/changelog-github", - { "repo": "sushiswap/sushiswap" } - ], - "commit": false, - "fixed": [], - "linked": [], - "access": "public", - "baseBranch": "origin/master", - "updateInternalDependencies": "patch", - "privatePackages": { - "tag": false, - "version": false - }, - "ignore": [ - "@sushiswap/token-list-api", - "@sushiswap/tokens-api", - - "@sushiswap/storybook", - "@sushiswap/tron", - "web", - - "eslint-config-sushi", - "@sushiswap/jest-config", - "@sushiswap/nextjs-config", - "@sushiswap/tailwindcss-config", - "@sushiswap/typescript-config", - - "@sushiswap/client", - "@sushiswap/database", - "@sushiswap/graph-client", - "@sushiswap/hooks", - "@sushiswap/notifications", - "@sushiswap/react-query", - "@sushiswap/steer-sdk", - "@sushiswap/telemetry", - "@sushiswap/ui" - ] -} diff --git a/.github/actions/install/action.yml b/.github/actions/install/action.yml index 07d1f50e36..44b223c3d5 100644 --- a/.github/actions/install/action.yml +++ b/.github/actions/install/action.yml @@ -4,17 +4,6 @@ description: "Install dependencies" runs: using: "composite" steps: - - name: Set up pnpm - uses: pnpm/action-setup@v4 - with: - version: 9.4.0 - - - name: Set up node - uses: actions/setup-node@v4 - with: - cache: pnpm - node-version: 20 - - name: Set up foundry uses: foundry-rs/foundry-toolchain@v1 @@ -22,6 +11,5 @@ runs: # shell: bash # run: npx playwright install --with-deps chromium - - name: Install dependencies - shell: bash - run: pnpm install --ignore-scripts \ No newline at end of file + - name: Set up pnpm + uses: sushi-labs/actions/.github/actions/pnpm@master \ No newline at end of file diff --git a/.github/workflows/changesets.yaml b/.github/workflows/changesets.yaml deleted file mode 100644 index 22e22c47d4..0000000000 --- a/.github/workflows/changesets.yaml +++ /dev/null @@ -1,83 +0,0 @@ -name: Changesets -on: - push: - branches: [master] - workflow_dispatch: - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - verify: - name: Verify - uses: ./.github/workflows/verify.yml - secrets: inherit - - changesets: - name: Create version pull request - runs-on: ubuntu-latest - timeout-minutes: 5 - - steps: - - name: Clone repository - uses: actions/checkout@v4 - with: - # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits - fetch-depth: 0 - submodules: 'recursive' - - - name: Install dependencies - uses: ./.github/actions/install - - - name: Create Version Pull Request - uses: changesets/action@v1 - with: - commit: 'chore: version package' - title: 'chore: version package' - version: pnpm changeset:version - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - release: - name: Release - needs: verify - runs-on: ubuntu-latest - timeout-minutes: 5 - permissions: - contents: write - id-token: write - pull-requests: write - - steps: - - name: Clone repository - uses: actions/checkout@v4 - with: - submodules: 'recursive' - - - name: Install dependencies - uses: ./.github/actions/install - - - name: Publish to NPM - uses: changesets/action@v1 - with: - createGithubReleases: ${{ github.ref == 'refs/heads/main' }} - publish: pnpm changeset:publish - version: pnpm changeset:version - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - - - name: Publish Prerelease - if: steps.changesets.outputs.published != 'true' - continue-on-error: true - env: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - npm config set "//registry.npmjs.org/:_authToken" "$NPM_TOKEN" - git reset --hard origin/main - pnpm clean - pnpm changeset version --no-git-tag --snapshot canary - pnpm changeset:prepublish - pnpm changeset publish --no-git-tag --snapshot canary --tag canary \ No newline at end of file diff --git a/.github/workflows/chromatic.yml b/.github/workflows/chromatic.yml index b0b45dbed2..8fcfbb5233 100644 --- a/.github/workflows/chromatic.yml +++ b/.github/workflows/chromatic.yml @@ -1,4 +1,4 @@ -name: 'Chromatic' +name: Chromatic on: pull_request: @@ -14,9 +14,9 @@ jobs: publish: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: - submodules: true + submodules: 'recursive' fetch-depth: 0 - name: Install dependencies uses: ./.github/actions/install diff --git a/.github/workflows/apps-web-e2e.yml b/.github/workflows/e2e.yml similarity index 69% rename from .github/workflows/apps-web-e2e.yml rename to .github/workflows/e2e.yml index 9ec64b064e..d74605718e 100644 --- a/.github/workflows/apps-web-e2e.yml +++ b/.github/workflows/e2e.yml @@ -1,4 +1,4 @@ -name: Sushi - apps / web +name: E2E on: pull_request: @@ -7,11 +7,8 @@ on: - ".github/workflows/apps-web-e2e.yml" - "apps/web/**" - "config/nextjs/**" - - "config/router/**" - "config/tailwindcss/**" - "config/typescript/**" - - "config/viem/**" - - "config/wagmi/**" - "packages/**" workflow_dispatch: @@ -25,38 +22,22 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: - e2e: - runs-on: buildjet-4vcpu-ubuntu-2204 + test: + runs-on: ubuntu-latest + # runs-on: buildjet-4vcpu-ubuntu-2204 timeout-minutes: 15 strategy: matrix: block-number: [61755107] chain-id: [137] - node-version: [20] - pnpm-version: [9.4.0] steps: - name: Clone repository uses: actions/checkout@v4 with: - fetch-depth: 2 - submodules: true - - # Has to be before setup node for caching to work - - uses: pnpm/action-setup@v4 - with: - version: ${{ matrix.pnpm-version }} - - - name: Setup Node.js - uses: buildjet/setup-node@v3 - with: - cache: 'pnpm' - node-version: ${{ matrix.node-version }} - - - name: Install Foundry - uses: foundry-rs/foundry-toolchain@v1 + submodules: 'recursive' - name: Install dependencies - run: pnpm install --frozen-lockfile --prefer-offline + uses: ./.github/actions/install - name: Install Playwright Browsers run: pnpm playwright install --with-deps chromium diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index d19313c81c..f9f26837b1 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -1,12 +1,7 @@ -name: Sushi - verify -# on: -# workflow_call: -# workflow_dispatch: +name: Verify on: workflow_call: workflow_dispatch: - # pull_request: - # types: [opened, synchronize] env: TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} TURBO_TEAM: ${{ secrets.TURBO_TEAM }} diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 22eb5f7c0d..28a76ad92d 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -8,7 +8,6 @@ "VisualStudioExptTeam.vscodeintellicode", "wix.vscode-import-cost", "GraphQL.vscode-graphql", - "mattpocock.ts-error-translator", "bierner.markdown-mermaid", "biomejs.biome" ] diff --git a/.vscode/launch.json b/.vscode/launch.json index 88a79f221e..d32a0f6a77 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -2,25 +2,33 @@ "version": "0.2.0", "configurations": [ { - "name": "LOCAL: Minikube", - "profile": "local", - "type": "cloudcode.kubernetes", + "name": "Next.js: debug server-side", + "type": "node-terminal", "request": "launch", - "skaffoldConfig": "${workspaceFolder}/skaffold.yaml", - "watch": false, - "cleanUp": true, - "portForward": true + "cwd": "${workspaceFolder}/apps/web", + "command": "npm run dev" }, { - "name": "STAGING: GKE", - "profile": "staging", - "type": "cloudcode.kubernetes", + "name": "Next.js: debug client-side", + "type": "chrome", "request": "launch", - "skaffoldConfig": "${workspaceFolder}/skaffold.yaml", - "watch": false, - "cleanUp": false, - "portForward": true, - "imageRegistry": "gcr.io/sushi-api-414412" + "url": "http://localhost:3000" + }, + { + "name": "Next.js: debug full stack", + "type": "node", + "request": "launch", + "cwd": "${workspaceFolder}/apps/web", + "program": "${workspaceFolder}/node_modules/.bin/next", + "runtimeArgs": ["--inspect"], + "skipFiles": ["/**"], + "serverReadyAction": { + "action": "debugWithEdge", + "killOnServerStop": true, + "pattern": "- Local:.+(https?://.+)", + "uriFormat": "%s", + "webRoot": "${workspaceFolder}" + } } ] } diff --git a/apis/token-list/package.json b/apis/token-list/package.json index 09adc354c0..842f80e58d 100644 --- a/apis/token-list/package.json +++ b/apis/token-list/package.json @@ -12,7 +12,6 @@ "@vercel/node": "3.0.9" }, "devDependencies": { - "@sushiswap/jest-config": "workspace:*", "@tsconfig/esm": "1.0.4", "@tsconfig/strictest": "2.0.2", "typescript": "5.5.4", diff --git a/apis/tokens/package.json b/apis/tokens/package.json index 66c8410451..346e24f015 100644 --- a/apis/tokens/package.json +++ b/apis/tokens/package.json @@ -32,12 +32,11 @@ "@wagmi/core": "2.13.5", "drizzle-orm": "^0.29.5", "postgres": "^3.4.3", - "sushi": "4.0.2", + "sushi": "4.0.5", "viem": "2.21.4", "zod": "3.23.8" }, "devDependencies": { - "@sushiswap/jest-config": "workspace:*", "@tsconfig/esm": "1.0.4", "@tsconfig/strictest": "2.0.2", "@types/node": "20", diff --git a/apps/tron/.env.example b/apps/tron/.env.example deleted file mode 100644 index 218639a524..0000000000 --- a/apps/tron/.env.example +++ /dev/null @@ -1 +0,0 @@ -NEXT_TELEMETRY_DISABLED=1 \ No newline at end of file diff --git a/apps/tron/.env.test b/apps/tron/.env.test deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/apps/tron/.eslintrc.js b/apps/tron/.eslintrc.js deleted file mode 100644 index a3daeaa1ab..0000000000 --- a/apps/tron/.eslintrc.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - // extends: ['sushi/next'], - extends: 'next/core-web-vitals', -} diff --git a/apps/tron/README.md b/apps/tron/README.md deleted file mode 100644 index c7e6a371ea..0000000000 --- a/apps/tron/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# Tron - -Tron application - -## Quickstart - -```sh -cp .env.example .env -cp .env.test .env.test.local -``` - -## Development - -```sh -pnpm exec turbo run dev --filter tron -``` - -## Build - -```sh -pnpm exec turbo run build --filter tron -``` \ No newline at end of file diff --git a/apps/tron/next.config.mjs b/apps/tron/next.config.mjs deleted file mode 100644 index a316dd26b1..0000000000 --- a/apps/tron/next.config.mjs +++ /dev/null @@ -1,20 +0,0 @@ -import defaultNextConfig from '@sushiswap/nextjs-config' - -/** @type {import('next').NextConfig} */ -const nextConfig = { - ...defaultNextConfig, - logging: { - fetches: { - fullUrl: true, - }, - }, - transpilePackages: [], - async redirects() { - return [] - }, - async rewrites() { - return [] - }, -} - -export default nextConfig diff --git a/apps/tron/package.json b/apps/tron/package.json deleted file mode 100644 index 9ebff0f943..0000000000 --- a/apps/tron/package.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "name": "@sushiswap/tron", - "version": "0.0.0", - "private": true, - "scripts": { - "build": "next build", - "check": "tsc --pretty --noEmit", - "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next && rm -rf .swc", - "dev": "next dev", - "lint": "TIMING=1 next lint", - "lint:fix": "TIMING=1 next lint --fix", - "start": "next start" - }, - "dependencies": { - "@heroicons/react": "2.0.13", - "@radix-ui/react-slot": "1.0.2", - "@sentry/nextjs": "8.30.0", - "@sushiswap/hooks": "workspace:*", - "@sushiswap/nextjs-config": "workspace:*", - "@sushiswap/react-query": "workspace:*", - "@sushiswap/tailwindcss-config": "workspace:*", - "@sushiswap/ui": "workspace:*", - "@tanstack/react-query": "5.51.16", - "@tanstack/react-query-devtools": "4.28.0", - "@tanstack/react-query-persist-client": "4.28.0", - "@tanstack/react-table": "8.9.1", - "@vercel/analytics": "1.3.1", - "@vercel/edge-config": "1.2.0", - "lodash.once": "4.1.1", - "next": "14.2.11", - "next-themes": "0.2.1", - "react": "18.2.0", - "react-dom": "18.2.0", - "react-infinite-scroll-component": "6.1.0", - "react-slider": "2.0.4", - "react-virtualized-auto-sizer": "1.0.7", - "sharp": "0.32.6", - "sushi": "4.0.2", - "tiny-invariant": "1.3.1", - "zod": "3.23.8" - }, - "devDependencies": { - "@next/eslint-plugin-next": "14.2.11", - "@sushiswap/typescript-config": "workspace:*", - "@tsconfig/next": "2.0.1", - "@types/lodash.once": "4.1.9", - "@types/node": "20", - "@types/react": "18.2.14", - "@types/react-dom": "18.2.6", - "@types/react-slider": "1.3.1", - "@types/react-virtualized-auto-sizer": "1.0.1", - "autoprefixer": "10.4.14", - "eslint-config-next": "14.2.11", - "eslint-config-sushi": "workspace:*", - "postcss": "8.4.23", - "tailwindcss": "3.3.2", - "typescript": "5.5.4", - "unimported": "1.30.0" - } -} diff --git a/apps/tron/postcss.config.js b/apps/tron/postcss.config.js deleted file mode 100644 index 33ad091d26..0000000000 --- a/apps/tron/postcss.config.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -} diff --git a/apps/tron/src/app/global-error.tsx b/apps/tron/src/app/global-error.tsx deleted file mode 100644 index 0edff8f5d2..0000000000 --- a/apps/tron/src/app/global-error.tsx +++ /dev/null @@ -1,24 +0,0 @@ -'use client' - -import * as Sentry from '@sentry/nextjs' -import NextError from 'next/error' -import { useEffect } from 'react' - -export default function GlobalError({ - error, -}: { - error: Error & { digest?: string } -}) { - useEffect(() => { - Sentry.captureException(error) - }, [error]) - - return ( - - - {/* This is the default Next.js error component but it doesn't allow omitting the statusCode property yet. */} - - - - ) -} diff --git a/apps/tron/src/app/header.tsx b/apps/tron/src/app/header.tsx deleted file mode 100644 index 0c9826752d..0000000000 --- a/apps/tron/src/app/header.tsx +++ /dev/null @@ -1,109 +0,0 @@ -'use client' - -import { classNames } from '@sushiswap/ui' -import { - NavigationMenu, - NavigationMenuContent, - NavigationMenuItem, - NavigationMenuLink, - NavigationMenuList, - NavigationMenuTrigger, - navigationMenuTriggerStyle, -} from '@sushiswap/ui' -import { SushiIcon } from '@sushiswap/ui/icons/SushiIcon' -import Link from 'next/link' -import React, { FC } from 'react' - -interface NavigationListItemProps extends React.ComponentPropsWithoutRef<'a'> { - href: string -} - -const NavigationListItem: FC = ({ - className, - title, - children, - href, -}) => { - return ( -
  • - - -
    {title}
    -

    - {children} -

    - -
    -
  • - ) -} - -export const Navigation: FC = () => { - return ( -
    - -
    - - - - - Swap - - - - - Pool - - - - - Explore - -
      - - Pools - - - Tokens - - - Transactions - -
    -
    -
    -
    -
    -
    Wallet Connector
    -
    -
    - ) -} - -export const Header: FC = () => { - return -} diff --git a/apps/tron/src/app/layout.tsx b/apps/tron/src/app/layout.tsx deleted file mode 100644 index 92e9065c1d..0000000000 --- a/apps/tron/src/app/layout.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import '@sushiswap/ui/index.css' - -import type { Metadata } from 'next' -import { Inter, Roboto_Mono } from 'next/font/google' -import React from 'react' -import { Header } from './header' -import { Providers } from './providers' -import { Trackers } from './trackers' - -const inter = Inter({ - subsets: ['latin'], - display: 'swap', - variable: '--font-inter', -}) - -const roboto_mono = Roboto_Mono({ - subsets: ['latin'], - display: 'swap', - variable: '--font-roboto-mono', -}) - -export const metadata: Metadata = { - title: { - default: 'Sushi 🍣', - template: '%s | Sushi 🍣', - }, - description: - 'A Decentralised Finance (DeFi) app with features such as swap, cross chain swap, streaming, vesting, and permissionless market making for liquidity providers.', -} - -export default function RootLayout({ - children, -}: { children: React.ReactNode }) { - return ( - // - - - - - - - - -
    -
    - {children} - -
    - - - ) -} diff --git a/apps/tron/src/app/loading.tsx b/apps/tron/src/app/loading.tsx deleted file mode 100644 index 75da76e366..0000000000 --- a/apps/tron/src/app/loading.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import { Splash } from '@sushiswap/ui' -import React from 'react' - -export default function Loading() { - return -} diff --git a/apps/tron/src/app/providers.tsx b/apps/tron/src/app/providers.tsx deleted file mode 100644 index 04e09d4cc2..0000000000 --- a/apps/tron/src/app/providers.tsx +++ /dev/null @@ -1,12 +0,0 @@ -'use client' - -import { BaseProviders } from '@sushiswap/ui' -import { QueryClientProvider } from '../providers/query-client-provider' - -export function Providers({ children }: { children: React.ReactNode }) { - return ( - - {children} - - ) -} diff --git a/apps/tron/src/app/swap/_components/widget.tsx b/apps/tron/src/app/swap/_components/widget.tsx deleted file mode 100644 index 598c30c984..0000000000 --- a/apps/tron/src/app/swap/_components/widget.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { FC } from 'react' - -export const Widget: FC = () => { - return null -} diff --git a/apps/tron/src/app/swap/page.tsx b/apps/tron/src/app/swap/page.tsx deleted file mode 100644 index c0b501220d..0000000000 --- a/apps/tron/src/app/swap/page.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { Container } from '@sushiswap/ui' -import { Widget } from './_components/widget' -import { Providers } from './providers' - -export const metadata = { - title: 'SushiSwap on Tron', -} - -export default function SwapSimplePage() { - return ( - - - - - - ) -} diff --git a/apps/tron/src/app/swap/providers.tsx b/apps/tron/src/app/swap/providers.tsx deleted file mode 100644 index c60700dec1..0000000000 --- a/apps/tron/src/app/swap/providers.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { SwapProvider } from './swap-provider' - -export async function Providers({ children }: { children: React.ReactNode }) { - return {children} -} diff --git a/apps/tron/src/app/swap/swap-provider.tsx b/apps/tron/src/app/swap/swap-provider.tsx deleted file mode 100644 index f6c7e971a0..0000000000 --- a/apps/tron/src/app/swap/swap-provider.tsx +++ /dev/null @@ -1,57 +0,0 @@ -'use client' - -import { FC, createContext, useContext, useMemo, useReducer } from 'react' - -type Action = { type: 'bar' } -type Dispatch = (action: Action) => void -type State = { foo: string } -type SwapProviderProps = { children: React.ReactNode } - -const SwapContext = createContext< - { state: State; dispatch: Dispatch } | undefined ->(undefined) - -function swapReducer(_state: State, action: Action) { - switch (action.type) { - case 'bar': { - return { foo: 'bar' } - } - default: { - throw new Error(`Unhandled action type: ${action.type}`) - } - } -} - -const SwapProvider: FC = ({ children }) => { - const [state, dispatch] = useReducer(swapReducer, { foo: 'foo' }) - return ( - { - return { state, dispatch } - }, [state])} - > - {children} - - ) -} - -const useSwapContext = () => { - const context = useContext(SwapContext) - if (!context) { - throw new Error('Hook can only be used inside Swap Provider') - } - - return context -} - -const useSwapState = () => { - const context = useSwapContext() - return context.state -} - -const useSwapDispatch = () => { - const context = useSwapContext() - return context.dispatch -} - -export { SwapProvider, useSwapState, useSwapDispatch } diff --git a/apps/tron/src/app/trackers.tsx b/apps/tron/src/app/trackers.tsx deleted file mode 100644 index a1300bf30b..0000000000 --- a/apps/tron/src/app/trackers.tsx +++ /dev/null @@ -1,13 +0,0 @@ -'use client' - -import { GoogleAnalytics } from '@sushiswap/ui' -import { Analytics as VercelAnalytics } from '@vercel/analytics/react' - -export function Trackers() { - return ( - <> - - - - ) -} diff --git a/apps/tron/src/providers/edge-config-provider.tsx b/apps/tron/src/providers/edge-config-provider.tsx deleted file mode 100644 index 8720c46065..0000000000 --- a/apps/tron/src/providers/edge-config-provider.tsx +++ /dev/null @@ -1,32 +0,0 @@ -'use client' - -import once from 'lodash.once' -import { createContext, useContext } from 'react' - -interface EdgeConfigProviderProps { - config: T - children: React.ReactNode -} - -const createEdgeConfigContext = once(() => { - return createContext(null) -}) - -const useEdgeConfig = () => { - const context = useContext(createEdgeConfigContext()) - if (!context) { - throw new Error('useEdgeConfig must be used within a EdgeConfigProvider') - } - - return context -} - -const EdgeProvider = ({ - config, - children, -}: EdgeConfigProviderProps) => { - const EdgeContext = createEdgeConfigContext() - return {children} -} - -export { EdgeProvider, useEdgeConfig } diff --git a/apps/tron/src/providers/query-client-provider.tsx b/apps/tron/src/providers/query-client-provider.tsx deleted file mode 100644 index 7a714bf403..0000000000 --- a/apps/tron/src/providers/query-client-provider.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { createQueryClient } from '@sushiswap/react-query' -// import { ReactQueryDevtools } from '@tanstack/react-query-devtools' -import { QueryClientProvider as _QueryClientProvider } from '@tanstack/react-query' -import { FC, ReactNode } from 'react' - -const client = createQueryClient() - -export const QueryClientProvider: FC<{ children: ReactNode }> = ({ - children, -}) => { - return ( - <_QueryClientProvider client={client}> - {children} - {/* */} - - ) -} diff --git a/apps/tron/tailwind.config.js b/apps/tron/tailwind.config.js deleted file mode 100644 index 0ec1d5e5f6..0000000000 --- a/apps/tron/tailwind.config.js +++ /dev/null @@ -1,23 +0,0 @@ -import sharedConfig from '@sushiswap/tailwindcss-config' - -// @ts-check -/** @type {import('tailwindcss').Config} */ -const tailwindConfig = { - darkMode: 'class', - presets: [sharedConfig], - theme: { - extend: { - display: ['group-hover'], - visibility: ['group-hover'], - keyframes: { - dash: { - to: { - 'stroke-dashoffset': '0', - }, - }, - }, - }, - }, -} - -export default tailwindConfig diff --git a/apps/tron/tsconfig.json b/apps/tron/tsconfig.json deleted file mode 100644 index d74d5101bd..0000000000 --- a/apps/tron/tsconfig.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "compilerOptions": { - "baseUrl": ".", - "target": "ESNext", - "lib": ["DOM", "DOM.Iterable", "ESNext"], - "allowJs": true, - "skipLibCheck": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "noEmit": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "bundler", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "preserve", - "incremental": true, - "plugins": [ - { - "name": "next" - } - ] - }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"] -} diff --git a/apps/tron/turbo.json b/apps/tron/turbo.json deleted file mode 100644 index affdd7c31d..0000000000 --- a/apps/tron/turbo.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "extends": ["//"], - "tasks": { - "build": { - "inputs": [ - "public", - "src/**", - "package.json", - "next.config.mjs", - "postcss.config.js", - "sentry.client.config.ts", - "sentry.edge.config.ts", - "sentry.server.config.ts", - "tailwind.config.js", - "tsconfig.json", - ".env.production.local", - ".env.local", - ".env.production", - ".env" - ], - "outputs": [".next/**", "!.next/cache/**"], - "dependsOn": ["^build"] - }, - "check": { - "dependsOn": ["^build"], - "cache": false - }, - "dev": { - "dependsOn": ["^build"], - "cache": false, - "persistent": true, - "inputs": [ - "$TURBO_DEFAULT$", - ".env.development.local", - ".env.local", - ".env.development", - ".env" - ] - }, - "test": { - "inputs": ["test/**", ".env.test.local", ".env.test", ".env"], - "outputs": ["test-results/**"], - "dependsOn": ["build"] - } - } -} diff --git a/apps/web/.env.example b/apps/web/.env.example index d14d60ab3b..f32ddc7c1b 100644 --- a/apps/web/.env.example +++ b/apps/web/.env.example @@ -14,3 +14,5 @@ DRPC_ID= SUSHI_DATA_API_HOST= NEXT_PUBLIC_SUSHI_DATA_API_HOST= + +NODE_OPTIONS=--inspect \ No newline at end of file diff --git a/apps/web/package.json b/apps/web/package.json index dcc7a1f987..517b75f5ae 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -12,7 +12,8 @@ "lint": "TIMING=1 next lint", "lint:fix": "TIMING=1 next lint --fix", "start": "next start", - "test": "npx playwright test -c test/playwright.config.ts" + "test": "npx playwright test -c test/playwright.config.ts", + "test:unit": "vitest --watch=false src" }, "dependencies": { "@aptos-labs/ts-sdk": "^1.22.1", @@ -46,7 +47,6 @@ "@sushiswap/hooks": "workspace:*", "@sushiswap/nextjs-config": "workspace:*", "@sushiswap/notifications": "workspace:*", - "@sushiswap/react-query": "workspace:*", "@sushiswap/steer-sdk": "workspace:*", "@sushiswap/tailwindcss-config": "workspace:*", "@sushiswap/telemetry": "workspace:*", @@ -95,7 +95,7 @@ "react-window": "1.8.7", "sharp": "0.32.6", "strapi-sdk-js": "2.3.3", - "sushi": "4.0.2", + "sushi": "4.0.5", "swr": "2.1.5", "tiny-invariant": "1.3.1", "viem": "2.21.4", @@ -107,7 +107,6 @@ "@next/env": "14.2.11", "@next/eslint-plugin-next": "14.2.11", "@playwright/test": "1.45.0", - "@sushiswap/jest-config": "workspace:*", "@sushiswap/typescript-config": "workspace:*", "@tsconfig/next": "2.0.1", "@types/cors": "2.8.13", @@ -137,6 +136,7 @@ "tailwindcss": "3.3.2", "tsx": "^4.16.5", "typescript": "5.4.5", - "unimported": "1.30.0" + "unimported": "1.30.0", + "vitest": "2.0.5" } } diff --git a/apps/web/src/app/(cms)/academy/[article-slug]/page.tsx b/apps/web/src/app/(cms)/academy/[article-slug]/page.tsx index d94be30101..9f56871c36 100644 --- a/apps/web/src/app/(cms)/academy/[article-slug]/page.tsx +++ b/apps/web/src/app/(cms)/academy/[article-slug]/page.tsx @@ -72,7 +72,7 @@ export async function generateMetadata({ params }: Props): Promise { export default async function Page({ params }: Props) { let article let moreArticles - let body + let body: string try { const articleP = getAcademyArticles({ @@ -86,7 +86,7 @@ export default async function Page({ params }: Props) { }) article = (await articleP).articles[0] - body = await getGhostBody(article.ghostSlug) + body = await getGhostBody(article.ghostSlug).then(({ html }) => html) moreArticles = (await moreArticlesP).articles } catch { return notFound() diff --git a/apps/web/src/app/(cms)/academy/components/difficulty-card-bar.tsx b/apps/web/src/app/(cms)/academy/components/difficulty-card-bar.tsx index bd5645f508..aa14d5fd78 100644 --- a/apps/web/src/app/(cms)/academy/components/difficulty-card-bar.tsx +++ b/apps/web/src/app/(cms)/academy/components/difficulty-card-bar.tsx @@ -17,7 +17,7 @@ function DifficultyCard({ difficulty }: { difficulty: Difficulty }) { return ( html) moreArticles = (await moreArticlesP).articles } catch { return notFound() diff --git a/apps/web/src/app/(cms)/layout.tsx b/apps/web/src/app/(cms)/layout.tsx index 69357812ad..6c3f9b30b9 100644 --- a/apps/web/src/app/(cms)/layout.tsx +++ b/apps/web/src/app/(cms)/layout.tsx @@ -1,6 +1,8 @@ import { Header } from './header' import { Providers } from './providers' +export const fetchCache = 'default-no-store' + export default function Layout({ children }: { children: React.ReactNode }) { return ( diff --git a/apps/web/src/app/(cms)/lib/ghost/addGhostBody.ts b/apps/web/src/app/(cms)/lib/ghost/addGhostBody.ts index e058681438..ac92068d62 100644 --- a/apps/web/src/app/(cms)/lib/ghost/addGhostBody.ts +++ b/apps/web/src/app/(cms)/lib/ghost/addGhostBody.ts @@ -8,7 +8,7 @@ export async function addGhostBody>( data: T, ghostSlug: string, ) { - const ghostBody = await getGhostBody(ghostSlug) + const { html: ghostBody } = await getGhostBody(ghostSlug) return { ...data, diff --git a/apps/web/src/app/(cms)/lib/ghost/ghost.ts b/apps/web/src/app/(cms)/lib/ghost/ghost.ts index 114d255407..720e8a8d9f 100644 --- a/apps/web/src/app/(cms)/lib/ghost/ghost.ts +++ b/apps/web/src/app/(cms)/lib/ghost/ghost.ts @@ -46,17 +46,9 @@ function processVideos(html: string) { export async function getGhostBody(slug: string) { const ghostClient = getGhostClient() - let html + const { html, ...rest } = await ghostClient.posts.read({ + slug, + }) - try { - ;({ html } = await ghostClient.posts.read({ - slug, - })) - } catch {} - - if (!html) { - return '' - } - - return processVideos(html) + return { html: html ? processVideos(html) : '', ...rest } } diff --git a/apps/web/src/app/(evm)/(trade)/header.tsx b/apps/web/src/app/(evm)/(trade)/header.tsx index 94558372a6..a29d66cb5b 100644 --- a/apps/web/src/app/(evm)/(trade)/header.tsx +++ b/apps/web/src/app/(evm)/(trade)/header.tsx @@ -11,7 +11,7 @@ export const Header: FC = () => { const chainId = useChainId() return ( } /> ) diff --git a/apps/web/src/app/(evm)/(trade)/layout.tsx b/apps/web/src/app/(evm)/(trade)/layout.tsx index 38318e300e..22e5d017b6 100644 --- a/apps/web/src/app/(evm)/(trade)/layout.tsx +++ b/apps/web/src/app/(evm)/(trade)/layout.tsx @@ -1,5 +1,3 @@ -import { HotJar } from '@sushiswap/ui' - import { Header } from './header' import { Providers } from './providers' @@ -12,7 +10,6 @@ export default function TradeLayout({
    {children}
    - ) } diff --git a/apps/web/src/app/(evm)/[chainId]/header.tsx b/apps/web/src/app/(evm)/[chainId]/header.tsx index 94558372a6..a29d66cb5b 100644 --- a/apps/web/src/app/(evm)/[chainId]/header.tsx +++ b/apps/web/src/app/(evm)/[chainId]/header.tsx @@ -11,7 +11,7 @@ export const Header: FC = () => { const chainId = useChainId() return ( } /> ) diff --git a/apps/web/src/app/(evm)/[chainId]/layout.tsx b/apps/web/src/app/(evm)/[chainId]/layout.tsx index 623f202f64..61262566ca 100644 --- a/apps/web/src/app/(evm)/[chainId]/layout.tsx +++ b/apps/web/src/app/(evm)/[chainId]/layout.tsx @@ -1,5 +1,3 @@ -import { HotJar } from '@sushiswap/ui' - import { isSupportedChainId } from 'src/config' import { Header } from './header' import notFound from './not-found' @@ -19,7 +17,6 @@ export default function PoolLayout({
    {children}
    - ) } diff --git a/apps/web/src/app/(evm)/[chainId]/pool/incentivize/page.tsx b/apps/web/src/app/(evm)/[chainId]/pool/incentivize/page.tsx index 0ea853e438..9d381e1244 100644 --- a/apps/web/src/app/(evm)/[chainId]/pool/incentivize/page.tsx +++ b/apps/web/src/app/(evm)/[chainId]/pool/incentivize/page.tsx @@ -1,6 +1,5 @@ 'use client' -import { useAngleRewardTokens } from '@sushiswap/react-query' import { Button, ChipInput, @@ -30,6 +29,7 @@ import { import format from 'date-fns/format' import { useRouter } from 'next/navigation' import { useMemo, useState } from 'react' +import { useAngleRewardTokens } from 'src/lib/hooks/react-query' import { Web3Input } from 'src/lib/wagmi/components/web3-input' import { useConcentratedLiquidityPool } from 'src/lib/wagmi/hooks/pools/hooks/useConcentratedLiquidityPool' import { diff --git a/apps/web/src/app/(evm)/_common/header-elements.tsx b/apps/web/src/app/(evm)/_common/header-elements.tsx index 349f01ada4..824df1d6c0 100644 --- a/apps/web/src/app/(evm)/_common/header-elements.tsx +++ b/apps/web/src/app/(evm)/_common/header-elements.tsx @@ -15,7 +15,14 @@ import { import { ChainId, ChainKey } from 'sushi/chain' import { isAggregatorOnlyChainId } from 'sushi/config' -export const headerElements = (chainId?: ChainId): NavigationElement[] => [ +interface HeaderElements { + chainId?: ChainId + includeOnramper?: boolean +} + +export const headerElements = ( + { chainId, includeOnramper }: HeaderElements = { includeOnramper: true }, +): NavigationElement[] => [ { title: 'Explore', items: EXPLORE_NAVIGATION_LINKS(chainId), @@ -34,11 +41,13 @@ export const headerElements = (chainId?: ChainId): NavigationElement[] => [ The easiest way to trade. - - - Onramp with fiat. - - + {includeOnramper ? ( + + + Onramp with fiat. + + + ) : null} diff --git a/apps/web/src/app/(evm)/_common/ui/price-provider/config.ts b/apps/web/src/app/(evm)/_common/ui/price-provider/config.ts new file mode 100644 index 0000000000..7ed42559d6 --- /dev/null +++ b/apps/web/src/app/(evm)/_common/ui/price-provider/config.ts @@ -0,0 +1,4 @@ +import ms from 'ms' + +export const UPDATE_INTERVAL = ms('15s') +export const STALE_TIME = ms('60s') diff --git a/apps/web/src/app/(evm)/_common/ui/price-provider/price-provider/price-provider.tsx b/apps/web/src/app/(evm)/_common/ui/price-provider/price-provider/price-provider.tsx new file mode 100644 index 0000000000..8502933954 --- /dev/null +++ b/apps/web/src/app/(evm)/_common/ui/price-provider/price-provider/price-provider.tsx @@ -0,0 +1,169 @@ +'use client' + +import { + createContext, + useCallback, + useContext, + useEffect, + useMemo, + useReducer, + useState, +} from 'react' +import { ChainId } from 'sushi' +import { useChainId } from 'wagmi' +import { + PriceWorker, + PriceWorkerPostMessageType, + PriceWorkerReceiveMessage, + PriceWorkerReceiveMessageType, +} from '../price-worker/types' +import { Provider, ProviderActions, ProviderState } from './types' + +function reducer(state: ProviderState, action: ProviderActions): ProviderState { + switch (action.type) { + case 'UPDATE_CHAIN_STATE': { + const currentChain = state.chains.get(action.payload.chainId) + + if (currentChain) { + state.chains.set(action.payload.chainId, { + ...currentChain, + ...action.payload, + priceMap: action.payload.priceMap || currentChain.priceMap, + }) + } else { + const { isError, isLoading, isUpdating, lastModified } = action.payload + + if ( + isError === undefined || + isLoading === undefined || + isUpdating === undefined || + lastModified === undefined + ) { + throw new Error('Invalid initial chain state') + } + + state.chains.set(action.payload.chainId, { + chainId: action.payload.chainId, + isError, + isLoading, + isUpdating, + lastModified, + priceMap: action.payload.priceMap || undefined, + }) + } + + return { + ...state, + } + } + default: + return state + } +} + +const PriceProviderContext = createContext({} as Provider) + +interface PriceProviderContextProps { + children: React.ReactNode +} + +export function PriceProvider({ children }: PriceProviderContextProps) { + const [worker, setWorker] = useState() + const [state, dispatch] = useReducer(reducer, { + chains: new Map(), + ready: false, + }) + + const chainId = useChainId() + + useEffect(() => { + const worker = new Worker( + new URL('../price-worker/price-worker.ts', import.meta.url), + ) + + worker.postMessage({ + type: PriceWorkerPostMessageType.Initialize, + canUseSharedArrayBuffer: false, + }) + + worker.onmessage = (event: MessageEvent) => { + switch (event.data.type) { + case PriceWorkerReceiveMessageType.ChainState: + dispatch({ + type: 'UPDATE_CHAIN_STATE', + payload: event.data.payload, + }) + break + } + } + + setWorker(worker as unknown as PriceWorker) + + return () => { + worker.terminate() + } + }, []) + + const incrementChainId = useCallback( + (chainId: ChainId) => { + if (worker) { + worker.postMessage({ + type: PriceWorkerPostMessageType.IncrementChainId, + chainId, + }) + } + }, + [worker], + ) + + const decrementChainId = useCallback( + (chainId: ChainId) => { + if (worker) { + worker.postMessage({ + type: PriceWorkerPostMessageType.DecrementChainId, + chainId, + }) + } + }, + [worker], + ) + + useEffect(() => { + if (worker) { + incrementChainId(chainId) + } + + return () => { + if (worker) { + decrementChainId(chainId) + } + } + }, [worker, chainId, decrementChainId, incrementChainId]) + + return ( + ({ ...state, ready: !!worker }), [state, worker]), + mutate: useMemo( + () => ({ + incrementChainId, + decrementChainId, + }), + [incrementChainId, decrementChainId], + ), + }} + > + {children} + + ) +} + +export function usePriceProvider() { + const context = useContext(PriceProviderContext) + + if (!context) { + throw new Error('usePriceProvider must be used within a PriceProvider') + } + + return context +} diff --git a/apps/web/src/app/(evm)/_common/ui/price-provider/price-provider/types.ts b/apps/web/src/app/(evm)/_common/ui/price-provider/price-provider/types.ts new file mode 100644 index 0000000000..defc641d5b --- /dev/null +++ b/apps/web/src/app/(evm)/_common/ui/price-provider/price-provider/types.ts @@ -0,0 +1,34 @@ +import type { ChainId } from 'sushi' +import { PriceWorkerReceiveMessageChainState } from '../price-worker/types' + +export interface ProviderChainState { + chainId: ChainId + + priceMap?: Map + + lastModified: number + + isLoading: boolean + isUpdating: boolean + isError: boolean +} + +export interface ProviderState { + chains: Map + ready: boolean +} + +export interface ProviderMutations { + incrementChainId: (chainId: ChainId) => void + decrementChainId: (chainId: ChainId) => void +} + +export interface Provider { + state: ProviderState + mutate: ProviderMutations +} + +export type ProviderActions = { + type: 'UPDATE_CHAIN_STATE' + payload: PriceWorkerReceiveMessageChainState['payload'] +} diff --git a/apps/web/src/app/(evm)/_common/ui/price-provider/price-provider/use-price.ts b/apps/web/src/app/(evm)/_common/ui/price-provider/price-provider/use-price.ts new file mode 100644 index 0000000000..19c47060d5 --- /dev/null +++ b/apps/web/src/app/(evm)/_common/ui/price-provider/price-provider/use-price.ts @@ -0,0 +1,32 @@ +'use client' + +import { useMemo } from 'react' +import type { ChainId } from 'sushi/chain' +import type { Address } from 'viem' +import { usePrices } from './use-prices' + +export function usePrice({ + chainId, + address, + enabled: _enabled = true, +}: { + chainId: ChainId | undefined + address: Address | undefined + enabled?: boolean +}) { + const enabled = chainId && address && _enabled + + const { data, ...rest } = usePrices({ + chainId, + enabled, + }) + + return useMemo(() => { + const price = address ? data?.get(address) : undefined + + return { + data: price, + ...rest, + } + }, [address, data, rest]) +} diff --git a/apps/web/src/app/(evm)/_common/ui/price-provider/price-provider/use-prices.ts b/apps/web/src/app/(evm)/_common/ui/price-provider/price-provider/use-prices.ts new file mode 100644 index 0000000000..e06d0a50b1 --- /dev/null +++ b/apps/web/src/app/(evm)/_common/ui/price-provider/price-provider/use-prices.ts @@ -0,0 +1,110 @@ +'use client' + +import { useEffect, useMemo } from 'react' +import { + type Address, + type ChainId, + Fraction, + withoutScientificNotation, +} from 'sushi' +import { parseUnits } from 'viem' +import { usePriceProvider } from './price-provider' + +export type PriceMap = { + has: (address: Address) => boolean + get: (address: Address) => number | undefined + getFraction: (address: Address) => Fraction | undefined +} + +export function usePrices({ + chainId, + enabled = true, +}: { chainId: ChainId | undefined; enabled?: boolean }) { + // Important to use state, not state.chains directly, as the reference to state.chains won't be changing and the component won't re-render + // It's not best practice, but it's controlled here in the hook and not exposed + const { state, mutate } = usePriceProvider() + + useEffect(() => { + if (state.ready && chainId && enabled) { + mutate.incrementChainId(chainId) + } + + return () => { + if (state.ready && chainId && enabled) { + mutate.decrementChainId(chainId) + } + } + }, [chainId, enabled, mutate, state.ready]) + + const chain = useMemo( + () => (chainId ? state.chains.get(chainId) : undefined), + [state, chainId], + ) + + return useMemo(() => { + if (!chainId) { + return { + data: undefined, + lastModified: 0, + isLoading: false, + isUpdating: false, + isError: false, + } + } + + if (!chain) + return { + data: undefined, + lastModified: 0, + isLoading: true, + isUpdating: false, + isError: false, + } + + if (!chain.priceMap) + return { + data: undefined, + lastModified: chain.lastModified, + isLoading: chain.isLoading, + isUpdating: chain.isUpdating, + isError: chain.isError, + } + + const data: PriceMap = { + has: (_address: Address) => { + const address = BigInt(_address) + + return chain.priceMap!.has(address) + }, + get: (_address: Address) => { + const address = BigInt(_address) + + const price = chain.priceMap!.get(address) + return price + }, + getFraction: (_address: Address) => { + const address = BigInt(_address) + + const price = chain.priceMap!.get(address) + if (price) { + return new Fraction( + parseUnits( + withoutScientificNotation(String(price)) || '0', + 18, + ).toString(), + parseUnits('1', 18).toString(), + ) + } + return undefined + }, + } + + return { + data, + lastModified: chain.lastModified, + isLoading: chain.isLoading, + isUpdating: chain.isUpdating, + isError: chain.isError, + } + }, [chainId, chain]) +} diff --git a/apps/web/src/app/(evm)/_common/ui/price-provider/price-worker/price-worker.ts b/apps/web/src/app/(evm)/_common/ui/price-provider/price-worker/price-worker.ts new file mode 100644 index 0000000000..5bc0cea61c --- /dev/null +++ b/apps/web/src/app/(evm)/_common/ui/price-provider/price-worker/price-worker.ts @@ -0,0 +1,228 @@ +import { ChainId } from 'sushi' +import { SUSHI_DATA_API_HOST } from 'sushi/config/subgraph' +import { UPDATE_INTERVAL } from '../config' +import { + PriceWorkerPostMessage, + PriceWorkerPostMessageType, + PriceWorkerReceiveMessage, + PriceWorkerReceiveMessageType, + WorkerChainState, +} from './types' + +{ + const state = { + chains: new Map(), + intervals: new Map(), + canUseSharedArrayBuffer: false, + } + + function sendMessage(message: PriceWorkerReceiveMessage) { + self.postMessage(message) + } + + self.onmessage = async ({ + data: _data, + }: MessageEvent) => { + const data = Array.isArray(_data) ? _data : [_data] + + let shouldUpdateIntervals = false + + for (const message of data) { + switch (message.type) { + case PriceWorkerPostMessageType.Initialize: { + const { canUseSharedArrayBuffer } = message + state.canUseSharedArrayBuffer = canUseSharedArrayBuffer + break + } + case PriceWorkerPostMessageType.IncrementChainId: { + const { chainId } = message + if (incrementChainId(chainId)) { + shouldUpdateIntervals = true + updateChainId(chainId) + } + break + } + case PriceWorkerPostMessageType.DecrementChainId: { + const { chainId } = message + if (decrementChainId(chainId)) { + shouldUpdateIntervals = true + } + break + } + case PriceWorkerPostMessageType.RefetchChainId: { + const { chainId } = message + const chainState = state.chains.get(chainId) + if (chainState) { + updateChainId(chainId) + } + break + } + } + } + + if (shouldUpdateIntervals) { + updateIntervals() + } + } + + function incrementChainId(chainId: ChainId) { + const chainState = state.chains.get(chainId) + if (chainState) { + chainState.listenerCount++ + return chainState.listenerCount === 1 + } + + state.chains.set(chainId, { + chainId, + listenerCount: 1, + priceMap: new Map(), + lastModified: 0, + isLoading: true, + isUpdating: false, + isError: false, + }) + + sendMessage({ + type: PriceWorkerReceiveMessageType.ChainState, + payload: { + chainId, + lastModified: 0, + isLoading: true, + isUpdating: false, + isError: false, + }, + }) + + return true + } + + function decrementChainId(chainId: ChainId) { + const chainState = state.chains.get(chainId) + if (chainState && chainState.listenerCount > 0) { + chainState.listenerCount-- + return chainState.listenerCount === 0 + } + + return false + } + + function updateIntervals() { + state.chains.forEach((chainState) => { + const currentInterval = state.intervals.get(chainState.chainId) + + if (isActive(chainState) && !currentInterval) { + state.intervals.set( + chainState.chainId, + setInterval(() => { + updateChainId(chainState.chainId) + }, UPDATE_INTERVAL), + ) + } else if (!isActive(chainState) && currentInterval) { + clearInterval(currentInterval) + state.intervals.delete(chainState.chainId) + } + }) + } + + async function updateChainId(chainId: ChainId) { + const chainState = state.chains.get(chainId) + if (!chainState) { + return + } + + chainState.isUpdating = true + + sendMessage({ + type: PriceWorkerReceiveMessageType.ChainState, + payload: { + chainId, + isUpdating: chainState.isUpdating, + }, + }) + + let sendPrices = false + + try { + const { data: newPriceMap, lastModified } = + await fetchPriceData(chainState) + updatePriceData(chainState.priceMap, newPriceMap) + chainState.lastModified = lastModified + chainState.isError = false + + sendPrices = true + } catch (error: unknown) { + console.error('Failed to fetch priceMap', chainId, error) + chainState.isError = true + } finally { + chainState.isUpdating = false + chainState.isLoading = false + } + + sendMessage({ + type: PriceWorkerReceiveMessageType.ChainState, + payload: { + chainId, + lastModified: chainState.lastModified, + isLoading: chainState.isLoading, + isUpdating: chainState.isUpdating, + isError: chainState.isError, + priceMap: sendPrices ? chainState.priceMap : undefined, + }, + }) + } + + async function fetchPriceData({ chainId, lastModified }: WorkerChainState) { + let url = `${SUSHI_DATA_API_HOST}/price/v1/${chainId}` + if (lastModified) { + url += `?onlyPricesUpdateSince=${lastModified}` + } + + const response = await fetch(url, { + headers: { + Accept: 'application/octet-stream', + }, + cache: 'no-store', + }) + + if (!response.ok) { + throw new Error('Network response was not ok') + } + + const buffer = Buffer.from(await response.arrayBuffer()) + + const priceMap = new Map() + for (let i = 0; i < buffer.byteLength; i += 24) { + const address = BigInt( + `0x${buffer + .subarray(i, i + 20) + .toString('hex') + .padStart(40, '0')}`, + ) + const price = buffer.readFloatLE(i + 20) + + priceMap.set(address, price) + } + + return { + data: priceMap, + lastModified: Number(response.headers.get('Last-Updated')!), + } + } + + function updatePriceData( + oldPriceData: Map, + newPriceMap: Map, + ) { + for (const [address, price] of newPriceMap) { + if (price === 0 || !Number.isFinite(price)) { + oldPriceData.delete(address) + } else { + oldPriceData.set(address, price) + } + } + } + + function isActive(chain: WorkerChainState) { + return chain.listenerCount > 0 + } +} diff --git a/apps/web/src/app/(evm)/_common/ui/price-provider/price-worker/types.ts b/apps/web/src/app/(evm)/_common/ui/price-provider/price-worker/types.ts new file mode 100644 index 0000000000..cebf006f33 --- /dev/null +++ b/apps/web/src/app/(evm)/_common/ui/price-provider/price-worker/types.ts @@ -0,0 +1,65 @@ +import type { ChainId } from 'sushi' + +export enum PriceWorkerPostMessageType { + Initialize = 'Initialize', + IncrementChainId = 'IncrementChainId', + DecrementChainId = 'DecrementChainId', + RefetchChainId = 'RefetchChainId', +} + +type Initialize = { + type: PriceWorkerPostMessageType.Initialize + canUseSharedArrayBuffer: boolean +} + +type IncrementChainId = { + chainId: ChainId + type: PriceWorkerPostMessageType.IncrementChainId +} + +type DecrementChainId = { + chainId: ChainId + type: PriceWorkerPostMessageType.DecrementChainId +} + +type RefetchChainId = { + chainId: ChainId + type: PriceWorkerPostMessageType.RefetchChainId +} + +export type PriceWorkerPostMessage = + | Initialize + | IncrementChainId + | DecrementChainId + | RefetchChainId + +export enum PriceWorkerReceiveMessageType { + ChainState = 'ChainState', + ChainPriceData = 'ChainPriceData', +} + +export type PriceWorkerReceiveMessageChainState = { + type: PriceWorkerReceiveMessageType.ChainState + payload: Partial> & { + chainId: ChainId + } +} + +export type PriceWorkerReceiveMessage = PriceWorkerReceiveMessageChainState + +export type PriceWorker = (typeof Worker)['prototype'] & { + postMessage(message: PriceWorkerPostMessage | PriceWorkerPostMessage[]): void +} + +export interface WorkerChainState { + chainId: ChainId + listenerCount: number + + priceMap: Map + + lastModified: number + + isLoading: boolean + isUpdating: boolean + isError: boolean +} diff --git a/apps/web/src/app/(evm)/claims/components/Header.tsx b/apps/web/src/app/(evm)/claims/components/Header.tsx index 18bf5051d8..a97aabde09 100644 --- a/apps/web/src/app/(evm)/claims/components/Header.tsx +++ b/apps/web/src/app/(evm)/claims/components/Header.tsx @@ -11,7 +11,7 @@ export const Header: FC = () => { const chainId = useChainId() return ( } /> ) diff --git a/apps/web/src/app/(evm)/providers.tsx b/apps/web/src/app/(evm)/providers.tsx index 6d3d2a477d..ac6c71d933 100644 --- a/apps/web/src/app/(evm)/providers.tsx +++ b/apps/web/src/app/(evm)/providers.tsx @@ -6,6 +6,7 @@ import { BaseProviders, OnramperProvider } from '@sushiswap/ui' import { QueryClientProvider } from '../../providers/query-client-provider' import { WagmiProvider } from '../../providers/wagmi-provider' +import { PriceProvider } from './_common/ui/price-provider/price-provider/price-provider' export function Providers({ children, @@ -15,7 +16,9 @@ export function Providers({ - {children} + + {children} + diff --git a/apps/web/src/app/(evm)/stake/header.tsx b/apps/web/src/app/(evm)/stake/header.tsx index 94558372a6..a29d66cb5b 100644 --- a/apps/web/src/app/(evm)/stake/header.tsx +++ b/apps/web/src/app/(evm)/stake/header.tsx @@ -11,7 +11,7 @@ export const Header: FC = () => { const chainId = useChainId() return ( } /> ) diff --git a/apps/web/src/app/(evm)/stake/layout.tsx b/apps/web/src/app/(evm)/stake/layout.tsx index e49a382204..72f4da9724 100644 --- a/apps/web/src/app/(evm)/stake/layout.tsx +++ b/apps/web/src/app/(evm)/stake/layout.tsx @@ -1,5 +1,4 @@ import { Container } from '@sushiswap/ui' -import { HotJar } from '@sushiswap/ui' import { BarHeader } from 'src/ui/stake' import { Header } from './header' import { Providers } from './providers' @@ -25,7 +24,6 @@ export default function Layout({ children }: { children: React.ReactNode }) { - ) } diff --git a/apps/web/src/app/(landing)/layout.tsx b/apps/web/src/app/(landing)/layout.tsx index f146f0fa61..22c5b53470 100644 --- a/apps/web/src/app/(landing)/layout.tsx +++ b/apps/web/src/app/(landing)/layout.tsx @@ -1,7 +1,8 @@ -import { HotJar, classNames } from '@sushiswap/ui' +import { classNames } from '@sushiswap/ui' import React from 'react' import { QueryClientProvider } from 'src/providers/query-client-provider' import { WagmiProvider } from 'src/providers/wagmi-provider' +import { PriceProvider } from '~evm/_common/ui/price-provider/price-provider/price-provider' import { Header } from './header' export default function LandingLayout({ @@ -10,11 +11,13 @@ export default function LandingLayout({ return ( -
    -
    -
    {children}
    -
    - + + {/* A CurrencyInput component is used on the landing page */} +
    +
    +
    {children}
    +
    +
    ) diff --git a/apps/web/src/app/(legal)/privacy-policy/page.tsx b/apps/web/src/app/(legal)/privacy-policy/page.tsx deleted file mode 100644 index 911d8433d4..0000000000 --- a/apps/web/src/app/(legal)/privacy-policy/page.tsx +++ /dev/null @@ -1,293 +0,0 @@ -import { Container, LinkExternal, Separator, classNames } from '@sushiswap/ui' -import React from 'react' - -// I know this thing is overengineered, but... - -type TextBlock = { - title: string | undefined - paragraphs: { title: string | undefined; paragraphs: string[] }[] - type: 'text' -} - -type NumberedListBlock = { - title: string - index: number - paragraphs: string[] - type: 'numbered-list' -} - -type Block = TextBlock | NumberedListBlock - -const text = [ - { - title: '', - paragraphs: [ - { - paragraphs: [ - `This privacy policy applies to this website and any services provided in the ordinary course of business. Our website is https://www.sushi.com (“The Website”) and is owned and operated by Sushi Labs (“The Company”). This policy governs the privacy of users who choose to use our website or engage with any of our services, both with and without consideration (“Users”).`, - `The policy sets out the different areas where user privacy is concerned and outlines the obligations and requirements of the users, the website, and The Company. Furthermore, this policy details how this website and company process, store, and protect user data and information.`, - ], - }, - ], - type: 'text', - }, - { - title: '1. The Website', - index: 1, - paragraphs: [ - `This website and its owners take a proactive approach to user privacy and ensure the necessary steps are taken to protect the privacy of its users throughout their visiting experience.`, - `The website and all company data are hosted, stored, and maintained within the European Union to avoid doubt. As such, European Union law applies to the storage of Data.`, - ], - type: 'numbered-list', - }, - { - title: '2. Use of Cookies', - index: 2, - paragraphs: [ - `This website uses cookies to improve the user's experience. Where applicable, this website uses a cookie control system that allows the user to allow or disallow cookies on their computer or device on their first visit. This complies with recent legislation requiring websites to obtain explicit user consent before leaving behind or reading files such as cookies on a user's computer or device.`, - `Cookies are small files saved to the user's computer's hard drive that track, save, and store information about the user's interactions and website usage. This allows the website, through its server, to provide the users with a tailored experience within this website.`, - `Users are advised that if they wish to deny the use and saving of cookies from this website onto their computer's hard drive, they should take necessary steps within their web browser's security settings to block all cookies from this website and its external serving vendors.`, - - {`This website uses tracking software to monitor its visitors to - understand better how they use it. Google Analytics provides this - software, which uses cookies to track visitor usage. The software will - save a cookie to your computer's hard drive to track and monitor your - engagement and usage of the website but will not store, save, or collect - personal information. You can read Google's privacy policy here for - further information: `} - - http://www.google.com/privacy.html - - , - `Other cookies may be stored on your computer's hard drive by external vendors when this website uses referral programs, sponsored links, or adverts. Such cookies are used for conversion and referral tracking and typically expire after 30 days, though some may take longer. No personal information is stored, saved, or collected.`, - ], - type: 'numbered-list', - }, - { - title: '3. Contact & Communication', - index: 3, - paragraphs: [ - `Users contacting this website and The Company do so at their discretion and provide any personal details requested at their own risk. Your personal information is kept private and securely stored until it is no longer required or has no use, as detailed in the Data Protection Laws. Every effort has been made to ensure a safe and secure form-to-email submission process, but users should be advised that they use such form-to-email processes at their own risk.`, - `This website and its owners use any information submitted to provide further information about the products/services they offer or to assist you in answering any questions or queries you may have submitted.`, - `This includes using your details to subscribe to any email newsletter program the website operates, but only if this was made clear to you and your express permission was granted when submitting any form to the email process. Or whereby you, the consumer, have previously purchased from or inquired about purchasing a product or service from the company that the email newsletter relates to. This is not an entire list of your user rights regarding receiving email marketing material. Your details are not passed on to any third parties.`, - `By sending your personal information to the company or the website, you grant consent to contact by the company, subject to the above conditions. Any data the company holds relating to individuals will be stored and destroyed once no communication has occurred between the user and the company for 12 months.`, - `The company will never knowingly or willingly pass information it holds on Users (for clarity, this includes clients, prospects, or website users) onto a third party without the user's consent.`, - ], - type: 'numbered-list', - }, - { - title: '4. Email', - index: 4, - paragraphs: [ - `From time to time, The Company operates various email campaigns (at all times, we refer to these as a Newsletter Program) to inform subscribers about products and services supplied by this website. Users can subscribe through an online automated process should they wish to do so, but they do so at their discretion. Some subscriptions may be manually processed through a prior written agreement with the user.`, - `Subscriptions are taken in compliance with Spam Laws detailed in the Privacy and Electronic Communications Regulations 2003. All personal details relating to subscriptions are held securely per the Data Protection Laws. No personal details are passed on to third parties nor shared with companies/people outside of the company that operates this website. Under the Data Protection Laws, you may request a copy of personal information about you through this website's email newsletter program. A small fee will be payable. If you would like a copy of the information held on you, please write to the business address at the bottom of this policy.`, - `Email marketing campaigns published by this website or its owners may contain tracking facilities within the email. Subscriber activity is tracked and stored in a database for future analysis and evaluation. Such tracked activity may include the opening of emails, forwarding of emails, clicking links within the email content, times, dates, and frequency of activity [this is by no far a comprehensive list].`, - `This information is used to refine future email campaigns and supply users with more relevant content based on their activity.`, - `In compliance with EU Spam Laws, the Privacy and Electronic Communications Regulations 2003, and GDPR, subscribers can unsubscribe anytime through an automated system. This process is detailed at the footer of each email campaign. If an automated unsubscription system is unavailable, clear instructions on unsubscribing will be detailed instead.`, - `Our email campaigns are always run through third-party providers such as Mailchimp. Users are advised to refer to these third-party companies' specific terms and conditions. Users can easily remove themselves from any email communication by “unsubscribing.”`, - `The Company holds no liability for any damages or losses associated with using any third-party email service provider. In engaging with the company or continuing use of the website, you hereby expressly accept that the Company holds no such liability.`, - ], - type: 'numbered-list', - }, - { - title: '5. External Links', - index: 5, - paragraphs: [ - `While every effort has been made to include quality, safe, and relevant external links within this website, users are advised to exercise caution before clicking any external links mentioned throughout this website (external links are clickable text/banner/image links to other websites).`, - `Despite their best efforts, the owners of this website and the company cannot guarantee or verify the contents of any externally linked website. Users should, therefore, note that they click on external links at their own risk, and this website and its owners cannot be held liable for any damages or implications caused by visiting any external links mentioned.`, - ], - type: 'numbered-list', - }, - { - title: '6. Adverts and Sponsored Links', - index: 6, - paragraphs: [ - `This website may contain sponsored links and adverts. These will typically be served through our advertising partners, who may have detailed privacy policies relating directly to the adverts they serve.`, - `Clicking on any such adverts will send you to the advertiser's website through a referral program, which may use cookies to track the number of referrals sent from this website. This may include the use of cookies, which may, in turn, be saved on your computer's hard drive. Users should note that they click on sponsored external links at their own risk. This website and its owners cannot be held liable for any damages or implications caused by visiting any external links mentioned.`, - `Despite their best efforts, the owners of this website and the company cannot guarantee or verify the contents of any externally linked website. Users should, therefore, note that they click on external links at their own risk, and this website and its owners cannot be held liable for any damages or implications caused by visiting any external links mentioned.`, - ], - type: 'numbered-list', - }, - { - title: '7. Social Media Platforms', - index: 7, - paragraphs: [ - `Communication, engagement, and actions taken through external social media platforms that this website, the company, and its owners participate in are custom to the terms and conditions and privacy policies held with each social media platform.`, - `Users are advised to use social media platforms wisely and communicate/engage with them with due care and caution regarding their privacy and personal details. Neither this website nor its owners will ever ask for personal or sensitive information through social media platforms, and users wishing to discuss sensitive details should be encouraged to contact them through primary communication channels such as telephone or email.`, - `This website may use social sharing buttons that help share content directly from web pages to the social media platform. Before using such social sharing buttons, users are advised to do so at their discretion and note that the social media platform may track and save your request to share a web page through your social media platform account.`, - `The Company holds responsibility for all comments, posts, or any other action taken on social media belonging to the company. Social media can easily be identified as belonging to the company by the account's name on the relevant social media platform. All comments and actions made on social media are not intended to cause offense or serve as a defamatory action. Every posting will be checked for accuracy.`, - `If you believe your intellectual property rights, personal rights, or any other rights have been infringed by any action on social media, you must notify the company as soon as possible so that the company can rectify and remove the post.`, - ], - type: 'numbered-list', - }, - { - title: '8. Shortened Links in Social Media', - index: 8, - paragraphs: [ - `This website and its owners may share links to relevant web pages through their social media platform accounts. Some social media platforms shorten lengthy domains and URLs to third-party pages by default.`, - `Users are advised to exercise caution and good judgment before clicking any shortened URLs published by this website and its owners on social media platforms. Despite the best efforts to ensure only genuine URLs are published, many social media platforms are prone to spam and hacking. Therefore, this website and its owners cannot be held liable for any damages or implications caused by visiting shortened links.`, - ], - type: 'numbered-list', - }, - { - title: '9. Governing Law and Jurisdiction', - index: 9, - paragraphs: [ - `This privacy policy and all items posted on behalf of the company are strictly subject to the laws of the United Kingdom (England and Wales). Any disagreement arising from the use of personal information shall be resolved through the Courts of England and Wales.`, - `The User expressly agrees that by using the company's website or engaging in social media, they are accepting the terms of this privacy policy.`, - `Any disagreement and all notices are to be delivered to the company registered office.`, - `If any part of this policy is found to be defective, the remaining elements of the policy shall remain in place.`, - `The Company's registered office and address for service can be found on the website.`, - ], - type: 'numbered-list', - }, - { - title: 'Special GDPR Notice', - paragraphs: [ - { - paragraphs: [ - 'Under the GDPR, which came into force in 2018, citizens of the European Union have the right to track their data. By using the company website, you hereby agree to the following terms and consent for such data to be stored as contained per this GDPR notice.', - ], - }, - { - title: 'Data Control Officer', - paragraphs: [ - 'The data control officer is based at the company headquarters, which can be found in our Terms and Conditions document. You can reach the Data controller by emailing the company at contact@sushi.com, located on the company website, or using the methods contained within the company website to contact us.', - `The company does not collect personal information or store any information about you. Communications are held and retained on third-party servers for reference purposes. The company will never email you marketing communications.`, - ], - }, - { - title: 'Purpose of the processing', - paragraphs: [ - `The information is collected in the interest of Know Your Client and Anti Money Laundering regulations. The company is allowing individuals to participate in a crowdfunding exercise. Some jurisdictions do not allow citizens and residents to participate in such activities. We, therefore, are required to collect basic information on those who participate to demonstrate, when necessary, that citizens and residents of that jurisdiction did not participate in the crowdfunding. The legal basis for this processing of data is found in international law (different laws from different countries), including but not limited to The UK Financial Services Act, The US Securities Legislation, European Monetary statutes and regulations (including those of its member states), Chinese Financial Code, anti-money laundering laws, and antiterrorism laws.`, - ], - }, - { - title: `Third Parties`, - paragraphs: [ - `Data may occasionally be shared with third parties to conduct a Know Your Client assessment so that participants can prove their location, residence, and citizenship. All parties accessing your data will be members of the necessary data-controlling bodies of their respective countries, such as the Information Commissioners Office of the United Kingdom.`, - ], - }, - { - title: `Recipients of the Data`, - paragraphs: [ - `Gresham International’s compliance team will always have access to the data. The Information Commissioner Office regulates them and will not share that data with any third party.`, - ], - }, - { - title: `Safeguards`, - paragraphs: [ - `Your data will never be shared with any third party without your consent or court order provided by a court of competent jurisdiction within the country making the request.`, - ], - }, - { - title: `Retention Period`, - paragraphs: [ - `All data will be stored for at least six months and a maximum of two years.`, - ], - }, - { - title: `The Existence of Your Rights`, - paragraphs: [ - `Nothing within this agreement or the company’s process impacts your rights under the GDPR.`, - ], - }, - { - title: `The right to withdraw consent`, - paragraphs: [ - `You may request the right to know the company's information about you. This request can only be made once, as data is only captured once during registration and participation. We must keep all information relating to you as anti-money laundering and antiterrorism laws require.`, - ], - }, - { - title: `The right to lodge a complaint`, - paragraphs: [ - `Citizens of the EU may file a complaint with the relevant data controller within their country. Complaints should first be made to the company so that we can investigate any issues relating to the storage or use of your data.`, - ], - }, - { - title: `Source of Data`, - paragraphs: [ - `All data collected on you will be done so by your submission of the information and collection of information from the machine you access the website with. Data collection is limited to what is contained in our registration method, and the information your computer automatically transmits to our company when accessing our site, such as cookies and IP data, is limited to that contained in our registration method.`, - ], - }, - ], - type: 'text', - }, -] as Block[] - -function numberedBlock(block: NumberedListBlock) { - return ( -
    -

    {block.title}

    -
    - {block.paragraphs.map((paragraph, i) => { - return ( -
    - - {block.index}.{i + 1} - -

    {paragraph}

    -
    - ) - })} -
    -
    - ) -} - -function textBlock(block: TextBlock) { - const subtitle = (title: string | undefined) => { - if (title) { - return

    {title}

    - } - } - - return ( -
    -

    {block.title}

    -
    - {block.paragraphs.map((paragraph) => { - return ( -
    - {subtitle(paragraph.title)} - - {paragraph.paragraphs.map((paragraph) => ( -

    {paragraph}

    - ))} -
    -
    - ) - })} -
    -
    - ) -} - -function contentBlock(block: (typeof text)[number]) { - switch (block.type) { - case 'text': - return textBlock(block) - case 'numbered-list': - return numberedBlock(block) - } -} - -export default function Page() { - return ( - -
    -

    Sushi Labs - Privacy Policy

    -

    - Last modified: March 26, 2024 -

    -
    - -
    - {text.map((block) => contentBlock(block))} -
    -
    - ) -} diff --git a/apps/web/src/app/(legal)/terms-of-service/layout.tsx b/apps/web/src/app/(legal)/terms-of-service/layout.tsx deleted file mode 100644 index f0c5216b2e..0000000000 --- a/apps/web/src/app/(legal)/terms-of-service/layout.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { Navigation } from '@sushiswap/ui' -import { Metadata } from 'next' -import { headerElements } from '../../(evm)/_common/header-elements' - -export const metadata: Metadata = { - title: 'Terms Of Service', -} - -export default function Layout({ children }: { children: React.ReactNode }) { - return ( - <> - -
    {children}
    - - ) -} diff --git a/apps/web/src/app/(legal)/terms-of-service/page.tsx b/apps/web/src/app/(legal)/terms-of-service/page.tsx deleted file mode 100644 index 3ce1211cf2..0000000000 --- a/apps/web/src/app/(legal)/terms-of-service/page.tsx +++ /dev/null @@ -1,189 +0,0 @@ -import { Container, Separator } from '@sushiswap/ui' -import React from 'react' - -type NumberedListBlock = { - title: string - index: number - paragraphs: string[] - type: 'numbered-list' -} - -type Block = NumberedListBlock - -const text = [ - { - title: 'Article 1: Acceptance of Terms', - index: 1, - paragraphs: [ - - {`The following Terms of Service ("Terms"), including any documents, policies, and guidelines incorporated herein by reference, collectively govern the access to and use of the "Interface" provided by `} - Sushi Labs - {` (hereinafter referred to as "`} - Sushi - {`," "we," "us," or "our") by any individual, entity, group, x or association (hereinafter referred to as "User," "you," or "your").`} - , - `By accessing, browsing, or otherwise using the Interface, or by acknowledging acceptance of these Terms through the Interface, you affirm that you have read, understood, and consent to be bound by these Terms, including, but not limited to, our Privacy Policy and any Disclosures referenced herein, along with any limitations, waivers, and restrictions applicable to any claims you may assert, which may limit your rights.`, - `Your use or access to the Interface constitutes acceptance of a binding arbitration agreement, waiver of the right to participate in a class action, and any other clauses contained within. Some of which significantly affect your rights to resolve disputes.`, - `Sushi reserves the right to modify, amend, or revise these Terms without prior notice or consent. Following such changes, continued access or use of the Interface constitutes acceptance of the revised Terms. If you disagree with the revised Terms, you must cease using the Interface. You should review the terms each time you access the Website. `, - ], - type: 'numbered-list', - }, - { - title: 'Article 2: Definition of Interface', - index: 2, - paragraphs: [ - `For these Terms, "Interface" refers to any platform, software, feature, or functionality developed, administered, or contributed to by Sushi, including but not limited to Sushi Swap, and encompasses the services described herein.`, - ], - type: 'numbered-list', - }, - { - title: 'Article 3: Dispute Resolution; Arbitration Agreement', - index: 3, - paragraphs: [ - - {`Any dispute or claim arising out of or related to the Interface or use - thereof (including these terms) shall be subject to an informal - negotiation process initiated by email to `} -
    - tos@sushiswap.com - - {`. Upon - receipt of a complaint, Sushi shall have sixty (60) days to respond. - Only after a response, if no resolution is achieved, may you file an - Arbitration Claim with the London International Court of Arbitration. - Your time to file such a claim is 30 (thirty) days from the response - from Sushi. ANY AND ALL CLAIMS SHALL BE SUBJECT TO ARBITRATION, WHICH - HEREIN, INCORPORATED FOR REFERENCE AND BINDING ON THE PARTIES. BOTH - PARTIES AGREE TO BE BOUND BY THE DECISION OF ARBITRATION. Any disputes - shall be conclusively resolved by arbitration under the London Court of - International Arbitration (LCIA) Rules in force at the time, one single - arbitrator shall be appointed, the initiating party shall pay all fees, - and processes shall be conducted in English and confidentially. This - clause survives the termination of these Terms.`} - , - ], - type: 'numbered-list', - }, - { - title: 'Article 4: Disputes and Waivers', - index: 4, - paragraphs: [ - `You waive the right to bring disputes as a plaintiff or class member in any class or representative action and waive any right to a jury trial. This waiver applies globally, irrespective of the laws of any country.`, - `YOU HEREBY WAIVE ANY RIGHT TO BE PART OF A JURY TRIAL AND ANY RIGHT TO TAKE PART IN, ORCHESTRATE, OR OTHERWISE ENGAGE IN ANY CLASS ACTION OR GROUP LAWSUIT.`, - `You and Sushi agree that any losses you sustain shall be limited to a maximum claim of $10,000 - TEN THOUSAND US DOLLARS.`, - ], - type: 'numbered-list', - }, - { - title: 'Article 5: Governing Law', - index: 5, - paragraphs: [ - `These Terms and any disputes arising under or related thereto shall be governed by the laws of the Republic of Seychelles, disregarding conflict of law principles.`, - ], - type: 'numbered-list', - }, - { - title: 'Article 6: The Interface', - index: 6, - paragraphs: [ - `The Interface is a conduit for aggregating and publishing information on digital asset swapping, staking, and bonding technologies. It facilitates interactions for intended transactions without providing financial services or advice.`, - `Sushi does not provide financial services, financial advice, tax services, or any other services or advice linked to any financial instrument. In using the interface, you warrant and undertake that you have the requisite knowledge and understanding of Blockchain Technology.`, - `The Interface is provided on an ‘as is’ basis with no guarantees of performance, success, or any certification that functions will work 100% of the time. You use the Interface at your own risk.`, - ], - type: 'numbered-list', - }, - { - title: 'Article 7: Access and Use', - index: 7, - paragraphs: [ - `By using the Interface, you represent that you are of legal age, possess the necessary technical knowledge, comply with all applicable laws, are not located in restricted territories, and do not intend to use the Interface for illegal activities or transactions prohibited by law.`, - `If using the Interface is illegal or contrary to the laws of the country where you are based or a citizen, you should NOT use it.`, - ], - type: 'numbered-list', - }, - { - title: 'Article 8: Prohibited and Acceptable Uses', - index: 8, - paragraphs: [ - `Users must not misuse the Interface in ways that are illegal, fraudulent, or harmful to others. Acceptable uses of the Interface are limited to informational purposes for those with the requisite technical sophistication.`, - ], - type: 'numbered-list', - }, - { - title: 'Article 9: Risks and Limitations', - index: 9, - paragraphs: [ - `Users acknowledge and accept the inherent risks associated with using the Interface, including the lack of a business model for Sushi, the volatility and legal uncertainties of blockchain technology and digital assets, and the absence of any warranties or guarantees regarding the Interface or the Middleware.`, - ], - type: 'numbered-list', - }, - { - title: 'Article 10: Waiver and Indemnification', - index: 10, - paragraphs: [ - `Users agree to indemnify and hold harmless Sushi and its affiliates from any claims, damages, or expenses arising from their use of the Interface, violation of these Terms, or infringement of any third-party rights.`, - `Users waive any claims and agree to hold harmless Sushi, including any director, shareholder, member, consultant, accountant, lawyer, agent, or any party acting on behalf of Sushi, for any losses actual or anticipated, including those losses known or unknown at the time the User used the interface.`, - `The user waives any right to claim alter-ego status within the United States of America. The User does not believe that, when using the interface, they are working with or engaging with any US-based firm or person.`, - ], - type: 'numbered-list', - }, - { - title: 'Article 11: Miscellaneous', - index: 11, - paragraphs: [ - `These Terms, including the Privacy Policy and any disclosures incorporated by reference, constitute the entire agreement between you and Sushi regarding the Interface and supersede all prior agreements and understandings, whether written or oral, related to the subject matter.`, - `These terms and any dispute shall be governed by the laws of the Republic of Seychelles, with the courts of England and Wales having exclusive jurisdiction over the relationship and any disputes arising therefrom.`, - `The User may not assign these Terms at any time. Sushi may assign these terms to any new or other entity undertaking work on its behalf and assuming responsibility for the interface.`, - ], - type: 'numbered-list', - }, -] as Block[] - -function numberedBlock(block: NumberedListBlock, index: number) { - return ( -
    -

    {block.title}

    -
    - {block.paragraphs.map((paragraph, i) => { - return ( -
    - - {index + 1}.{i + 1} - -

    {paragraph}

    -
    - ) - })} -
    -
    - ) -} - -function contentBlock(block: (typeof text)[number], index: number) { - switch (block.type) { - case 'numbered-list': - return numberedBlock(block, index) - } -} - -export default function Page() { - return ( - -
    -

    - Sushi Labs - Terms of Service -

    -

    - Last modified: March 26, 2024 -

    -
    - -
    - {text.map((block, i) => contentBlock(block, i))} -
    -
    - ) -} diff --git a/apps/web/src/app/(non-evm)/aptos/swap/layout.tsx b/apps/web/src/app/(non-evm)/aptos/swap/layout.tsx index 06150d5e94..fad478c549 100644 --- a/apps/web/src/app/(non-evm)/aptos/swap/layout.tsx +++ b/apps/web/src/app/(non-evm)/aptos/swap/layout.tsx @@ -1,5 +1,3 @@ -import { HotJar } from '@sushiswap/ui' - import { Providers } from './providers' export const metadata = { @@ -16,7 +14,6 @@ export default function SwapLayout({
    {children}
    - ) } diff --git a/apps/web/src/app/_common/cookies/announce-cookie-change.ts b/apps/web/src/app/_common/cookies/announce-cookie-change.ts new file mode 100644 index 0000000000..107cd5e1ff --- /dev/null +++ b/apps/web/src/app/_common/cookies/announce-cookie-change.ts @@ -0,0 +1,4 @@ +export function announceCookieChange() { + const event = new Event('cookieChange') + document.dispatchEvent(event) +} diff --git a/apps/web/src/app/_common/cookies/cookie-dialog-container.tsx b/apps/web/src/app/_common/cookies/cookie-dialog-container.tsx new file mode 100644 index 0000000000..cc02cac7f3 --- /dev/null +++ b/apps/web/src/app/_common/cookies/cookie-dialog-container.tsx @@ -0,0 +1,18 @@ +import { cookies } from 'next/headers' +import { Suspense } from 'react' +import { CookieDialog } from './cookie-dialog' + +export function CookieDialogContainer() { + return ( + + <_CookieDialogContainer /> + + ) +} + +function _CookieDialogContainer() { + const cookiez = cookies() + const cookiesConfirmed = cookiez.has('accepted-cookies') + + return +} diff --git a/apps/web/src/app/_common/cookies/cookie-dialog.tsx b/apps/web/src/app/_common/cookies/cookie-dialog.tsx new file mode 100644 index 0000000000..f83395a9db --- /dev/null +++ b/apps/web/src/app/_common/cookies/cookie-dialog.tsx @@ -0,0 +1,208 @@ +'use client' + +import { useIsMounted } from '@sushiswap/hooks' +import { + Button, + Dialog, + DialogContent, + DialogFooter, + DialogHeader, + DialogTitle, + LinkExternal, + Separator, + Switch, +} from '@sushiswap/ui' +import { useCallback, useEffect, useState } from 'react' +import { announceCookieChange } from './announce-cookie-change' + +type BaseAction = 'accept' | 'reject' | 'manage' + +function BaseCookieDialog({ + onAction, +}: { onAction: (action: BaseAction) => void }) { + return ( + e.preventDefault()} + > +
    + Sushi Labs and our third-party service providers may use cookies as set + forth in our{' '} + Cookie Policy, + which process your personal data. You may manage your cookie preferences + below. Even if you reject all cookies, you hereby consent to the + collection of your personal data by us and our service providers as you + use our services, through technologies other than cookies, as described + in our{' '} + Privacy Policy + , including when such collection may be considered an interception of + communications by third parties. +
    + +
    + + + +
    +
    + ) +} + +const cookieTypes = ['essential', 'functional', 'performance'] as const + +export type CookieType = (typeof cookieTypes)[number] + +type ManageAction = + | { + type: 'confirm' + } + | { + type: 'set' + cookieType: CookieType + enabled: boolean + } + | { + type: 'reject' + } + +function ManageCookieDialog({ + cookieSet, + onAction, +}: { cookieSet: Set; onAction: (action: ManageAction) => void }) { + return ( + <> + + + Manage cookie preferences + +
    +
    + Strictly Neccessary Cookies + +
    + +
    + Performance Cookies + + onAction({ type: 'set', cookieType: 'performance', enabled }) + } + /> +
    + +
    + Functional Cookies + + onAction({ type: 'set', cookieType: 'functional', enabled }) + } + /> +
    +
    + + + + +
    + + ) +} + +export function CookieDialog({ open: _open }: { open: boolean }) { + const [open, setOpen] = useState(_open) + const [page, setPage] = useState<'base' | 'manage'>('base') + + const isMounted = useIsMounted() + + const [enabledCookieSet, setEnabledCookieSet] = useState>( + new Set(cookieTypes), + ) + + const onConfirm = useCallback((cookieSet: Set) => { + const cookieString = Array.from(cookieSet).join(',') + document.cookie = `accepted-cookies=${cookieString}; max-age=31536000; path=/` + announceCookieChange() + + setOpen(false) + }, []) + + const onBaseAction = useCallback( + (action: BaseAction) => { + switch (action) { + case 'accept': + onConfirm(new Set(cookieTypes)) + break + case 'reject': + onConfirm(new Set(['essential'])) + break + case 'manage': + setPage('manage') + break + } + }, + [onConfirm], + ) + + const onManageAction = useCallback( + (action: ManageAction) => { + switch (action.type) { + case 'confirm': + onConfirm(enabledCookieSet) + break + case 'reject': + onConfirm(new Set(['essential'])) + break + case 'set': + setEnabledCookieSet((prev) => { + const next = new Set(prev) + if (action.enabled) { + next.add(action.cookieType) + } else { + next.delete(action.cookieType) + } + return next + }) + break + } + }, + [enabledCookieSet, onConfirm], + ) + + useEffect(() => { + // Auto-accept in development and test environments + if ( + process.env.NODE_ENV !== 'production' || + process.env.NEXT_PUBLIC_APP_ENV === 'test' + ) { + onConfirm(new Set(cookieTypes)) + } + }, [onConfirm]) + + return ( + + {page === 'base' ? ( + + ) : ( + + )} + + ) +} diff --git a/apps/web/src/app/_common/cookies/get-enabled-cookies.ts b/apps/web/src/app/_common/cookies/get-enabled-cookies.ts new file mode 100644 index 0000000000..939d9c7713 --- /dev/null +++ b/apps/web/src/app/_common/cookies/get-enabled-cookies.ts @@ -0,0 +1,22 @@ +import type { CookieType } from './cookie-dialog' + +export function parseEnabledCookieTypes( + cookieString: string, +): Set | undefined { + const acceptedCookieString = cookieString + .split('; ') + .find((cookie) => cookie.startsWith('accepted-cookies=')) + + if (acceptedCookieString) { + const cookieTypes = acceptedCookieString.split('=')[1].split(',') + return new Set(cookieTypes) as Set + } + + return undefined +} + +export function getEnabledCookieTypes() { + if (typeof document === 'undefined') return undefined + + return parseEnabledCookieTypes(document.cookie) +} diff --git a/apps/web/src/app/_common/cookies/use-enabled-cookies.ts b/apps/web/src/app/_common/cookies/use-enabled-cookies.ts new file mode 100644 index 0000000000..0114eac8fe --- /dev/null +++ b/apps/web/src/app/_common/cookies/use-enabled-cookies.ts @@ -0,0 +1,29 @@ +'use client' + +import { useEffect, useMemo, useState } from 'react' +import { parseEnabledCookieTypes } from './get-enabled-cookies' + +export function useEnabledCookies() { + const [cookieString, setCookieString] = useState( + typeof document === 'undefined' ? '' : document.cookie, + ) + + useEffect(() => { + if (typeof document === 'undefined') return + setCookieString(document.cookie) + }, []) + + useEffect(() => { + const onCookieChange = () => { + setCookieString(document.cookie) + } + + document.addEventListener('cookieChange', onCookieChange) + + return () => { + document.removeEventListener('cookieChange', onCookieChange) + } + }, []) + + return useMemo(() => parseEnabledCookieTypes(cookieString), [cookieString]) +} diff --git a/apps/web/src/app/layout.tsx b/apps/web/src/app/layout.tsx index 1766db4a9c..b1bfb72448 100644 --- a/apps/web/src/app/layout.tsx +++ b/apps/web/src/app/layout.tsx @@ -4,6 +4,7 @@ import { ToastContainer } from '@sushiswap/notifications' import type { Metadata } from 'next' import { Inter, Roboto_Mono } from 'next/font/google' import React from 'react' +import { CookieDialogContainer } from './_common/cookies/cookie-dialog-container' import { Trackers } from './trackers' const inter = Inter({ @@ -58,6 +59,7 @@ export default function RootLayout({ + {children} diff --git a/apps/web/src/app/(legal)/privacy-policy/layout.tsx b/apps/web/src/app/legal/[slug]/layout.tsx similarity index 65% rename from apps/web/src/app/(legal)/privacy-policy/layout.tsx rename to apps/web/src/app/legal/[slug]/layout.tsx index b771b76604..21315f1278 100644 --- a/apps/web/src/app/(legal)/privacy-policy/layout.tsx +++ b/apps/web/src/app/legal/[slug]/layout.tsx @@ -1,15 +1,10 @@ import { Navigation } from '@sushiswap/ui' -import { Metadata } from 'next' import { headerElements } from '../../(evm)/_common/header-elements' -export const metadata: Metadata = { - title: 'Privacy Policy', -} - export default function Layout({ children }: { children: React.ReactNode }) { return ( <> - +
    {children}
    ) diff --git a/apps/web/src/app/legal/[slug]/page.tsx b/apps/web/src/app/legal/[slug]/page.tsx new file mode 100644 index 0000000000..35feb1ff40 --- /dev/null +++ b/apps/web/src/app/legal/[slug]/page.tsx @@ -0,0 +1,67 @@ +import { Container, Separator } from '@sushiswap/ui' +import React from 'react' +import { getGhostBody } from 'src/app/(cms)/lib/ghost/ghost' + +export const revalidate = 86400 + +export const dynamicParams = false + +const pages = { + ['privacy-policy']: { title: 'Privacy Policy' }, + ['terms-of-service']: { title: 'Terms of Service' }, + ['cookie-policy']: { title: 'Cookie Policy' }, +} + +export async function generateStaticParams() { + return Object.keys(pages).map((slug) => ({ slug: slug })) +} + +type Props = { + params: { slug: keyof typeof pages } +} + +export async function generateMetadata({ params }: Props) { + const page = pages[params.slug] + + return { + title: page.title, + } +} + +export default async function Page({ params }: Props) { + const page = pages[params.slug] + + const { title, html: body, updated_at } = await getGhostBody(params.slug) + + if (!title) { + throw new Error(`${page.title}: title missing`) + } + + if (!updated_at) { + throw new Error(`${page.title}: updated_at missing`) + } + + const lastModified = new Date(updated_at).toLocaleDateString('en-US', { + year: 'numeric', + month: 'long', + day: 'numeric', + }) + + return ( + +
    +

    {title}

    +

    + Last modified: {lastModified} +

    +
    + +
    + + ) +} diff --git a/apps/web/src/app/tokenlist-request/page.tsx b/apps/web/src/app/tokenlist-request/page.tsx index c395a4d1f7..3e3dce1184 100644 --- a/apps/web/src/app/tokenlist-request/page.tsx +++ b/apps/web/src/app/tokenlist-request/page.tsx @@ -2,7 +2,6 @@ import { CameraIcon } from '@heroicons/react/24/outline' import { zodResolver } from '@hookform/resolvers/zod' -import { useApplyForTokenList } from '@sushiswap/react-query' import { Container, Form, @@ -24,6 +23,7 @@ import { NetworkIcon } from '@sushiswap/ui/icons/NetworkIcon' import React, { useCallback, useEffect } from 'react' import { DropzoneOptions, useDropzone } from 'react-dropzone' import { useForm } from 'react-hook-form' +import { useApplyForTokenList } from 'src/lib/hooks/react-query' import { Chain, ChainId } from 'sushi/chain' import { type Address, isAddress } from 'viem' diff --git a/apps/web/src/app/trackers.tsx b/apps/web/src/app/trackers.tsx index 712af1a24f..fa946c013b 100644 --- a/apps/web/src/app/trackers.tsx +++ b/apps/web/src/app/trackers.tsx @@ -1,14 +1,20 @@ 'use client' -import { GoogleAnalytics } from '@sushiswap/ui' +import { GoogleAnalytics, HotJar } from '@sushiswap/ui' import { Analytics as VercelAnalytics } from '@vercel/analytics/react' import { SpeedInsights } from '@vercel/speed-insights/next' +import { useEnabledCookies } from './_common/cookies/use-enabled-cookies' export function Trackers() { + const enabledCookies = useEnabledCookies() + + const performanceEnabled = !!enabledCookies?.has('performance') + return ( <> - + + ) diff --git a/apps/web/src/instrumentation.ts b/apps/web/src/instrumentation.ts index 9bd367cbed..90587d52c8 100644 --- a/apps/web/src/instrumentation.ts +++ b/apps/web/src/instrumentation.ts @@ -1,7 +1,62 @@ import { captureRequestError } from '@sentry/nextjs' +function bigintSeriliazer() { + const originalStringify = JSON.stringify + const stringify = (value: any, replacer?: any, space?: string | number) => { + return originalStringify( + value, + function (key: string, value: any) { + if (typeof value === 'bigint') { + // Check if the reviver supports BigInt + try { + if (replacer && !Array.isArray(replacer)) { + return replacer.call(this, key, value) + } + } catch {} + + return { + __type: 'bigint', + value: value.toString(), + } + } + if (Array.isArray(replacer)) { + // If replacer is an array, only include the keys specified in the array + return replacer.includes(key) ? value : undefined + } + if (replacer) { + return replacer.call(this, key, value) + } + return value + }, + space, + ) + } + JSON.stringify = stringify + + const originalParse = JSON.parse + const parse = ( + text: string, + reviver?: (this: any, key: string, value: any) => any, + ) => { + return originalParse(text, function (key: string, value: any) { + if (value && typeof value === 'object' && value.__type === 'bigint') { + value = BigInt(value.value) + } + if (reviver) { + return reviver.call(this, key, value) + } + return value + }) + } + JSON.parse = parse + + return { stringify, parse } +} + +export const { stringify, parse } = bigintSeriliazer() + export async function register() { - await import('sushi/bigint-serializer') + bigintSeriliazer() if (process.env.NEXT_RUNTIME === 'nodejs') { await import('../sentry.server.config') diff --git a/apps/web/src/lib/hooks/api/useCrossChainTrade.ts b/apps/web/src/lib/hooks/api/useCrossChainTrade.ts index 83dfb1f89b..502bc0a066 100644 --- a/apps/web/src/lib/hooks/api/useCrossChainTrade.ts +++ b/apps/web/src/lib/hooks/api/useCrossChainTrade.ts @@ -1,5 +1,5 @@ -import { NativeAddress, apiAdapter02To01 } from '@sushiswap/react-query' import { UseQueryOptions, useQuery } from '@tanstack/react-query' +import { NativeAddress, apiAdapter02To01 } from 'src/lib/hooks/react-query' import { CrossChainTradeSchema, GetCrossChainTradeParams, diff --git a/apps/web/src/lib/hooks/api/useV2Pool.ts b/apps/web/src/lib/hooks/api/useV2Pool.ts index 3deb0df628..ea71b2a91b 100644 --- a/apps/web/src/lib/hooks/api/useV2Pool.ts +++ b/apps/web/src/lib/hooks/api/useV2Pool.ts @@ -1,13 +1,12 @@ 'use client' import { useMemo } from 'react' -import 'sushi/bigint-serializer' import { Amount } from 'sushi/currency' import { V2Pool, getV2Pool } from '@sushiswap/graph-client/data-api' import { useQuery } from '@tanstack/react-query' +import { stringify } from 'src/instrumentation' import { PoolId } from 'sushi' -import { stringify } from 'sushi/bigint-serializer' import { isSushiSwapV2ChainId } from 'sushi/config' import { getTokensFromPool } from '../useTokensFromPool' diff --git a/packages/react-query/src/hooks/index.ts b/apps/web/src/lib/hooks/react-query/index.ts similarity index 100% rename from packages/react-query/src/hooks/index.ts rename to apps/web/src/lib/hooks/react-query/index.ts diff --git a/packages/react-query/src/hooks/pools/index.ts b/apps/web/src/lib/hooks/react-query/pools/index.ts similarity index 100% rename from packages/react-query/src/hooks/pools/index.ts rename to apps/web/src/lib/hooks/react-query/pools/index.ts diff --git a/packages/react-query/src/hooks/pools/useConcentratedLiquidityPoolStats.ts b/apps/web/src/lib/hooks/react-query/pools/useConcentratedLiquidityPoolStats.ts similarity index 100% rename from packages/react-query/src/hooks/pools/useConcentratedLiquidityPoolStats.ts rename to apps/web/src/lib/hooks/react-query/pools/useConcentratedLiquidityPoolStats.ts diff --git a/apps/web/src/lib/hooks/react-query/prices/index.ts b/apps/web/src/lib/hooks/react-query/prices/index.ts new file mode 100644 index 0000000000..186f5d26a7 --- /dev/null +++ b/apps/web/src/lib/hooks/react-query/prices/index.ts @@ -0,0 +1 @@ +export * from './useAllPrices' diff --git a/packages/react-query/src/hooks/prices/useAllPrices.ts b/apps/web/src/lib/hooks/react-query/prices/useAllPrices.ts similarity index 100% rename from packages/react-query/src/hooks/prices/useAllPrices.ts rename to apps/web/src/lib/hooks/react-query/prices/useAllPrices.ts diff --git a/packages/react-query/src/hooks/rewards/index.ts b/apps/web/src/lib/hooks/react-query/rewards/index.ts similarity index 100% rename from packages/react-query/src/hooks/rewards/index.ts rename to apps/web/src/lib/hooks/react-query/rewards/index.ts diff --git a/packages/react-query/src/hooks/rewards/useAngleRewardTokens.ts b/apps/web/src/lib/hooks/react-query/rewards/useAngleRewardTokens.ts similarity index 100% rename from packages/react-query/src/hooks/rewards/useAngleRewardTokens.ts rename to apps/web/src/lib/hooks/react-query/rewards/useAngleRewardTokens.ts diff --git a/packages/react-query/src/hooks/rewards/useAngleRewards.ts b/apps/web/src/lib/hooks/react-query/rewards/useAngleRewards.ts similarity index 98% rename from packages/react-query/src/hooks/rewards/useAngleRewards.ts rename to apps/web/src/lib/hooks/react-query/rewards/useAngleRewards.ts index 9c2a6defab..f934a98593 100644 --- a/packages/react-query/src/hooks/rewards/useAngleRewards.ts +++ b/apps/web/src/lib/hooks/react-query/rewards/useAngleRewards.ts @@ -7,8 +7,7 @@ import z from 'zod' import { isMerklChainId } from 'sushi/config' -import { usePrices } from '../prices' - +import { usePrices } from '~evm/_common/ui/price-provider/price-provider/use-prices' import { angleRewardsPoolsValidator, angleRewardsValidator } from './validator' type TransformedRewardsPerToken = Record< diff --git a/packages/react-query/src/hooks/rewards/useAngleRewardsMultipleChains.ts b/apps/web/src/lib/hooks/react-query/rewards/useAngleRewardsMultipleChains.ts similarity index 80% rename from packages/react-query/src/hooks/rewards/useAngleRewardsMultipleChains.ts rename to apps/web/src/lib/hooks/react-query/rewards/useAngleRewardsMultipleChains.ts index 841e6c09b2..18f0f28a87 100644 --- a/packages/react-query/src/hooks/rewards/useAngleRewardsMultipleChains.ts +++ b/apps/web/src/lib/hooks/react-query/rewards/useAngleRewardsMultipleChains.ts @@ -30,10 +30,18 @@ export const useAngleRewardsMultipleChains = ({ return res .map((el, i) => { if (isPromiseRejected(el)) return null + + const chainPrices = prices.get(chainIds[i])! + const data = angleRewardsSelect({ chainId: chainIds[i]!, data: el.value[chainIds[i]!], - prices: prices.get(chainIds[i]!), + prices: { + get: (address: Address) => + +(chainPrices.get(address) || 0)?.toFixed(18), + getFraction: (address: Address) => chainPrices.get(address), + has: (address: Address) => chainPrices.has(address), + }, }) return data diff --git a/packages/react-query/src/hooks/rewards/validator.ts b/apps/web/src/lib/hooks/react-query/rewards/validator.ts similarity index 100% rename from packages/react-query/src/hooks/rewards/validator.ts rename to apps/web/src/lib/hooks/react-query/rewards/validator.ts diff --git a/packages/react-query/src/hooks/strapi/index.ts b/apps/web/src/lib/hooks/react-query/strapi/index.ts similarity index 100% rename from packages/react-query/src/hooks/strapi/index.ts rename to apps/web/src/lib/hooks/react-query/strapi/index.ts diff --git a/packages/react-query/src/hooks/strapi/useActiveBanners.ts b/apps/web/src/lib/hooks/react-query/strapi/useActiveBanners.ts similarity index 100% rename from packages/react-query/src/hooks/strapi/useActiveBanners.ts rename to apps/web/src/lib/hooks/react-query/strapi/useActiveBanners.ts diff --git a/packages/react-query/src/hooks/tokenlist/index.ts b/apps/web/src/lib/hooks/react-query/tokenlist/index.ts similarity index 100% rename from packages/react-query/src/hooks/tokenlist/index.ts rename to apps/web/src/lib/hooks/react-query/tokenlist/index.ts diff --git a/packages/react-query/src/hooks/tokenlist/types.ts b/apps/web/src/lib/hooks/react-query/tokenlist/types.ts similarity index 100% rename from packages/react-query/src/hooks/tokenlist/types.ts rename to apps/web/src/lib/hooks/react-query/tokenlist/types.ts diff --git a/packages/react-query/src/hooks/tokenlist/useApplyForTokenList.ts b/apps/web/src/lib/hooks/react-query/tokenlist/useApplyForTokenList.ts similarity index 100% rename from packages/react-query/src/hooks/tokenlist/useApplyForTokenList.ts rename to apps/web/src/lib/hooks/react-query/tokenlist/useApplyForTokenList.ts diff --git a/packages/react-query/src/hooks/tokenlist/useOtherTokenLists.ts b/apps/web/src/lib/hooks/react-query/tokenlist/useOtherTokenLists.ts similarity index 100% rename from packages/react-query/src/hooks/tokenlist/useOtherTokenLists.ts rename to apps/web/src/lib/hooks/react-query/tokenlist/useOtherTokenLists.ts diff --git a/packages/react-query/src/hooks/tokenlist/useTokenList.ts b/apps/web/src/lib/hooks/react-query/tokenlist/useTokenList.ts similarity index 100% rename from packages/react-query/src/hooks/tokenlist/useTokenList.ts rename to apps/web/src/lib/hooks/react-query/tokenlist/useTokenList.ts diff --git a/packages/react-query/src/hooks/tokenlist/validator.ts b/apps/web/src/lib/hooks/react-query/tokenlist/validator.ts similarity index 100% rename from packages/react-query/src/hooks/tokenlist/validator.ts rename to apps/web/src/lib/hooks/react-query/tokenlist/validator.ts diff --git a/packages/react-query/src/hooks/tokens/index.ts b/apps/web/src/lib/hooks/react-query/tokens/index.ts similarity index 100% rename from packages/react-query/src/hooks/tokens/index.ts rename to apps/web/src/lib/hooks/react-query/tokens/index.ts diff --git a/packages/react-query/src/hooks/tokens/useToken.ts b/apps/web/src/lib/hooks/react-query/tokens/useToken.ts similarity index 100% rename from packages/react-query/src/hooks/tokens/useToken.ts rename to apps/web/src/lib/hooks/react-query/tokens/useToken.ts diff --git a/packages/react-query/src/hooks/tokens/useTokenSecurity.ts b/apps/web/src/lib/hooks/react-query/tokens/useTokenSecurity.ts similarity index 100% rename from packages/react-query/src/hooks/tokens/useTokenSecurity.ts rename to apps/web/src/lib/hooks/react-query/tokens/useTokenSecurity.ts diff --git a/packages/react-query/src/hooks/tokens/useTokens.ts b/apps/web/src/lib/hooks/react-query/tokens/useTokens.ts similarity index 100% rename from packages/react-query/src/hooks/tokens/useTokens.ts rename to apps/web/src/lib/hooks/react-query/tokens/useTokens.ts diff --git a/packages/react-query/src/hooks/trade/apiAdapter.ts b/apps/web/src/lib/hooks/react-query/trade/apiAdapter.ts similarity index 100% rename from packages/react-query/src/hooks/trade/apiAdapter.ts rename to apps/web/src/lib/hooks/react-query/trade/apiAdapter.ts diff --git a/packages/react-query/src/hooks/trade/index.ts b/apps/web/src/lib/hooks/react-query/trade/index.ts similarity index 100% rename from packages/react-query/src/hooks/trade/index.ts rename to apps/web/src/lib/hooks/react-query/trade/index.ts diff --git a/packages/react-query/src/hooks/trade/types.ts b/apps/web/src/lib/hooks/react-query/trade/types.ts similarity index 100% rename from packages/react-query/src/hooks/trade/types.ts rename to apps/web/src/lib/hooks/react-query/trade/types.ts diff --git a/packages/react-query/src/hooks/trade/useTrade.ts b/apps/web/src/lib/hooks/react-query/trade/useTrade.ts similarity index 90% rename from packages/react-query/src/hooks/trade/useTrade.ts rename to apps/web/src/lib/hooks/react-query/trade/useTrade.ts index fe716df639..a36bc3692e 100644 --- a/packages/react-query/src/hooks/trade/useTrade.ts +++ b/apps/web/src/lib/hooks/react-query/trade/useTrade.ts @@ -17,7 +17,7 @@ import { Amount, Native, Price, type Type } from 'sushi/currency' import { Fraction, Percent, ZERO } from 'sushi/math' import { isLsd, isStable, isWrapOrUnwrap } from 'sushi/router' import { Address, stringify, zeroAddress } from 'viem' -import { usePrice } from '../prices' +import { usePrices } from '~evm/_common/ui/price-provider/price-provider/use-prices' import { apiAdapter02To01 } from './apiAdapter' import type { UseTradeParams, UseTradeQuerySelect } from './types' import { tradeValidator02 } from './validator02' @@ -127,27 +127,28 @@ export const useTrade = (variables: UseTradeParams) => { gasPrice, tokenTax, } = variables - const { data: _price } = usePrice({ + const { data: prices } = usePrices({ chainId, - address: Native.onChain(chainId).wrapped.address, - enabled: isWNativeSupported(chainId), }) - const price = useMemo(() => { - return Native.onChain(chainId).wrapped.address === zeroAddress - ? new Fraction(0) - : _price - }, [_price, chainId]) + const [nativePrice, tokenOutPrice] = useMemo(() => { + const result = [new Fraction(0), undefined] - // const { data: tokenInPrice } = usePrice({ - // chainId, - // address: fromToken?.wrapped.address, - // }) + if (prices) { + if ( + isWNativeSupported(chainId) && + Native.onChain(chainId).wrapped.address !== zeroAddress + ) { + result[0] = prices.getFraction(Native.onChain(chainId).wrapped.address) + } - const { data: tokenOutPrice } = usePrice({ - chainId, - address: toToken?.wrapped.address, - }) + if (toToken) { + result[1] = prices.getFraction(toToken.wrapped.address) + } + } + + return result + }, [chainId, prices, toToken]) const select: UseTradeQuerySelect = useCallback( (data) => { @@ -214,8 +215,8 @@ export const useTrade = (variables: UseTradeParams) => { minAmountOut, gasSpent: gasSpent?.toSignificant(4), gasSpentUsd: - price && gasSpent - ? gasSpent.multiply(price.asFraction).toSignificant(4) + nativePrice && gasSpent + ? gasSpent.multiply(nativePrice.asFraction).toSignificant(4) : undefined, fee: !isWrapOrUnwrap({ fromToken, toToken }) && @@ -258,7 +259,7 @@ export const useTrade = (variables: UseTradeParams) => { amount, chainId, fromToken, - price, + nativePrice, tokenOutPrice, slippagePercentage, toToken, diff --git a/packages/react-query/src/hooks/trade/validator01.ts b/apps/web/src/lib/hooks/react-query/trade/validator01.ts similarity index 100% rename from packages/react-query/src/hooks/trade/validator01.ts rename to apps/web/src/lib/hooks/react-query/trade/validator01.ts diff --git a/packages/react-query/src/hooks/trade/validator02.ts b/apps/web/src/lib/hooks/react-query/trade/validator02.ts similarity index 100% rename from packages/react-query/src/hooks/trade/validator02.ts rename to apps/web/src/lib/hooks/react-query/trade/validator02.ts diff --git a/packages/react-query/src/hooks/useBalances.ts b/apps/web/src/lib/hooks/react-query/useBalances.ts similarity index 100% rename from packages/react-query/src/hooks/useBalances.ts rename to apps/web/src/lib/hooks/react-query/useBalances.ts diff --git a/packages/react-query/src/hooks/useBalancesRefetch.ts b/apps/web/src/lib/hooks/react-query/useBalancesRefetch.ts similarity index 100% rename from packages/react-query/src/hooks/useBalancesRefetch.ts rename to apps/web/src/lib/hooks/react-query/useBalancesRefetch.ts diff --git a/apps/web/src/lib/hooks/useSimulateTrade.ts b/apps/web/src/lib/hooks/useSimulateTrade.ts index 9212ccad22..1655901543 100644 --- a/apps/web/src/lib/hooks/useSimulateTrade.ts +++ b/apps/web/src/lib/hooks/useSimulateTrade.ts @@ -1,6 +1,6 @@ -import { UseTradeReturn } from '@sushiswap/react-query' import { EstimateGasErrorType, EstimateGasReturnType } from '@wagmi/core' import { useEffect, useMemo, useRef } from 'react' +import { UseTradeReturn } from 'src/lib/hooks/react-query' import { useDerivedStateSimpleSwap } from 'src/ui/swap/simple/derivedstate-simple-swap-provider' import { isRouteProcessor5ChainId } from 'sushi/config' import { Hex, RawContractError } from 'viem' diff --git a/apps/web/src/lib/hooks/useTokenAmountDollarValues.ts b/apps/web/src/lib/hooks/useTokenAmountDollarValues.ts index a2538343e3..b891a6c902 100644 --- a/apps/web/src/lib/hooks/useTokenAmountDollarValues.ts +++ b/apps/web/src/lib/hooks/useTokenAmountDollarValues.ts @@ -1,12 +1,13 @@ 'use client' -import { usePrices } from '@sushiswap/react-query' import { useMemo } from 'react' +import { usePrices } from 'src/app/(evm)/_common/ui/price-provider/price-provider/use-prices' +import type { ChainId } from 'sushi' import { Amount, Type } from 'sushi/currency' import { ZERO } from 'sushi/math' interface Params { - chainId: number + chainId: ChainId amounts: (Amount | undefined)[] | null | undefined } diff --git a/apps/web/src/lib/swap/cross-chain/actions/getCrossChainTrade.ts b/apps/web/src/lib/swap/cross-chain/actions/getCrossChainTrade.ts index 24d92c9cf0..f3c5670d6b 100644 --- a/apps/web/src/lib/swap/cross-chain/actions/getCrossChainTrade.ts +++ b/apps/web/src/lib/swap/cross-chain/actions/getCrossChainTrade.ts @@ -1,4 +1,4 @@ -import { tradeValidator02 } from '@sushiswap/react-query' +import { tradeValidator02 } from 'src/lib/hooks/react-query' import { SushiXSwap2ChainId } from 'sushi/config' import { RouteStatus } from 'sushi/router' import { Address } from 'viem' diff --git a/apps/web/src/lib/swap/cross-chain/actions/getSquidCrossChainTrade.ts b/apps/web/src/lib/swap/cross-chain/actions/getSquidCrossChainTrade.ts index a90e3c81bf..a2d2e06b9d 100644 --- a/apps/web/src/lib/swap/cross-chain/actions/getSquidCrossChainTrade.ts +++ b/apps/web/src/lib/swap/cross-chain/actions/getSquidCrossChainTrade.ts @@ -5,7 +5,7 @@ import { RouteRequest, SquidCallType, } from '@0xsquid/squid-types' -import { NativeAddress } from '@sushiswap/react-query' +import { NativeAddress } from 'src/lib/hooks/react-query' import { routeProcessor4Abi_processRoute, squidRouterAbi } from 'sushi/abi' import { ROUTE_PROCESSOR_4_ADDRESS, diff --git a/apps/web/src/lib/swap/cross-chain/actions/getStargateCrossChainTrade.ts b/apps/web/src/lib/swap/cross-chain/actions/getStargateCrossChainTrade.ts index 495a04cba8..c75e9adcc8 100644 --- a/apps/web/src/lib/swap/cross-chain/actions/getStargateCrossChainTrade.ts +++ b/apps/web/src/lib/swap/cross-chain/actions/getStargateCrossChainTrade.ts @@ -1,4 +1,4 @@ -import { NativeAddress } from '@sushiswap/react-query' +import { NativeAddress } from 'src/lib/hooks/react-query' import { stargateAdapterAbi_getFee } from 'sushi/abi' import { STARGATE_ADAPTER_ADDRESS, diff --git a/apps/web/src/lib/swap/cross-chain/actions/getTrade.ts b/apps/web/src/lib/swap/cross-chain/actions/getTrade.ts index c0aa25f0ff..d159a6516a 100644 --- a/apps/web/src/lib/swap/cross-chain/actions/getTrade.ts +++ b/apps/web/src/lib/swap/cross-chain/actions/getTrade.ts @@ -2,7 +2,7 @@ import { UseTradeParams, // getTradeQueryApiVersion, tradeValidator02, -} from '@sushiswap/react-query' +} from 'src/lib/hooks/react-query' import { API_BASE_URL } from 'sushi/config' import { RouteStatus } from 'sushi/router' import { Address } from 'viem' diff --git a/apps/web/src/lib/swap/cross-chain/lib/SquidAdapter.ts b/apps/web/src/lib/swap/cross-chain/lib/SquidAdapter.ts index 3537e214e5..85c80b4075 100644 --- a/apps/web/src/lib/swap/cross-chain/lib/SquidAdapter.ts +++ b/apps/web/src/lib/swap/cross-chain/lib/SquidAdapter.ts @@ -1,5 +1,5 @@ import { Token as SquidToken } from '@0xsquid/squid-types' -import { tradeValidator02 } from '@sushiswap/react-query' +import { tradeValidator02 } from 'src/lib/hooks/react-query' import { squidRouterAbi } from 'sushi/abi' import { ChainId } from 'sushi/chain' import { SquidAdapterChainId } from 'sushi/config' diff --git a/apps/web/src/lib/swap/cross-chain/lib/StargateAdapter.ts b/apps/web/src/lib/swap/cross-chain/lib/StargateAdapter.ts index 04f728e474..e6b125c097 100644 --- a/apps/web/src/lib/swap/cross-chain/lib/StargateAdapter.ts +++ b/apps/web/src/lib/swap/cross-chain/lib/StargateAdapter.ts @@ -1,4 +1,4 @@ -import { NativeAddress } from '@sushiswap/react-query' +import { NativeAddress } from 'src/lib/hooks/react-query' import { STARGATE_CHAIN_ID, STARGATE_CHAIN_PATHS, diff --git a/apps/web/src/lib/wagmi/components/token-security-view.tsx b/apps/web/src/lib/wagmi/components/token-security-view.tsx index c513f2e31f..e81556b261 100644 --- a/apps/web/src/lib/wagmi/components/token-security-view.tsx +++ b/apps/web/src/lib/wagmi/components/token-security-view.tsx @@ -2,15 +2,15 @@ import { ExclamationTriangleIcon, HandThumbUpIcon, } from '@heroicons/react/24/solid' +import { Button, Explainer, List, SelectIcon, classNames } from '@sushiswap/ui' +import { GoPlusLabsIcon } from '@sushiswap/ui/icons/GoPlusLabsIcon' +import { useMemo, useState } from 'react' import { TokenSecurity, TokenSecurityLabel, TokenSecurityMessage, TokenSecurityResponse, -} from '@sushiswap/react-query' -import { Button, Explainer, List, SelectIcon, classNames } from '@sushiswap/ui' -import { GoPlusLabsIcon } from '@sushiswap/ui/icons/GoPlusLabsIcon' -import { useMemo, useState } from 'react' +} from 'src/lib/hooks/react-query' import { Token } from 'sushi/currency' const isTokenSecurityIssue = { diff --git a/apps/web/src/lib/wagmi/components/token-selector/hooks/use-my-tokens.ts b/apps/web/src/lib/wagmi/components/token-selector/hooks/use-my-tokens.ts index 73c70e691b..1f406a1068 100644 --- a/apps/web/src/lib/wagmi/components/token-selector/hooks/use-my-tokens.ts +++ b/apps/web/src/lib/wagmi/components/token-selector/hooks/use-my-tokens.ts @@ -3,9 +3,9 @@ import { getTokenListBalances, } from '@sushiswap/graph-client/data-api' import { useCustomTokens } from '@sushiswap/hooks' -import { NativeAddress } from '@sushiswap/react-query' import { useQuery } from '@tanstack/react-query' import { useMemo } from 'react' +import { NativeAddress } from 'src/lib/hooks/react-query' import { Amount, Native, Token, Type } from 'sushi/currency' import type { Address } from 'viem' diff --git a/apps/web/src/lib/wagmi/components/token-selector/token-lists/common/token-selector-currency-list.tsx b/apps/web/src/lib/wagmi/components/token-selector/token-lists/common/token-selector-currency-list.tsx index c251b31341..78817a720a 100644 --- a/apps/web/src/lib/wagmi/components/token-selector/token-lists/common/token-selector-currency-list.tsx +++ b/apps/web/src/lib/wagmi/components/token-selector/token-lists/common/token-selector-currency-list.tsx @@ -1,10 +1,10 @@ -import { NativeAddress } from '@sushiswap/react-query' import React, { FC, memo, useMemo } from 'react' +import { NativeAddress } from 'src/lib/hooks/react-query' import { ChainId } from 'sushi/chain' import { Amount, Native, Type } from 'sushi/currency' -import { Fraction } from 'sushi/math' import { useAccount } from 'wagmi' +import type { PriceMap } from 'src/app/(evm)/_common/ui/price-provider/price-provider/use-prices' import type { Token } from 'sushi/currency' import { Address } from 'viem' import { TokenSelectorImportRow } from './token-selector-import-row' @@ -21,7 +21,7 @@ interface TokenSelectorCurrencyListProps { } selected: Type | undefined balancesMap: Map> | undefined - pricesMap: Map | undefined + pricesMap: PriceMap | undefined isBalanceLoading: boolean importConfig?: { onImport: (currency: Token) => void @@ -50,7 +50,7 @@ export const TokenSelectorCurrencyList: FC = balance: balancesMap?.get( currency.isNative ? NativeAddress : currency.address, ), - price: pricesMap?.get( + price: pricesMap?.getFraction( currency.isNative ? Native.onChain(currency.chainId).wrapped.address : currency.address, diff --git a/apps/web/src/lib/wagmi/components/token-selector/token-lists/common/token-selector-import-row.tsx b/apps/web/src/lib/wagmi/components/token-selector/token-lists/common/token-selector-import-row.tsx index 2163824ca9..d77fcb659f 100644 --- a/apps/web/src/lib/wagmi/components/token-selector/token-lists/common/token-selector-import-row.tsx +++ b/apps/web/src/lib/wagmi/components/token-selector/token-lists/common/token-selector-import-row.tsx @@ -1,4 +1,3 @@ -import { useTokenSecurity } from '@sushiswap/react-query' import { BrowserEvent, InterfaceElementName, @@ -19,6 +18,7 @@ import { Button } from '@sushiswap/ui' import { Currency } from '@sushiswap/ui' import { List } from '@sushiswap/ui' import { FC, useCallback, useState } from 'react' +import { useTokenSecurity } from 'src/lib/hooks/react-query' import { Chain } from 'sushi/chain' import { Token } from 'sushi/currency' import { shortenAddress } from 'sushi/format' diff --git a/apps/web/src/lib/wagmi/components/token-selector/token-lists/common/token-selector-row.tsx b/apps/web/src/lib/wagmi/components/token-selector/token-lists/common/token-selector-row.tsx index 45cbc1728b..b9a1862d07 100644 --- a/apps/web/src/lib/wagmi/components/token-selector/token-lists/common/token-selector-row.tsx +++ b/apps/web/src/lib/wagmi/components/token-selector/token-lists/common/token-selector-row.tsx @@ -3,7 +3,6 @@ import { CheckCircleIcon, ExclamationCircleIcon, } from '@heroicons/react/20/solid' -import { NativeAddress } from '@sushiswap/react-query' import { BrowserEvent, InterfaceElementName, @@ -23,6 +22,7 @@ import { import { Badge } from '@sushiswap/ui' import { Currency } from '@sushiswap/ui' import React, { CSSProperties, FC, memo, useCallback } from 'react' +import { NativeAddress } from 'src/lib/hooks/react-query' import { Chain } from 'sushi/chain' import { Amount, Type } from 'sushi/currency' import { Fraction, ZERO } from 'sushi/math' diff --git a/apps/web/src/lib/wagmi/components/token-selector/token-lists/token-selector-chip-bar.tsx b/apps/web/src/lib/wagmi/components/token-selector/token-lists/token-selector-chip-bar.tsx index 39f723a357..f9d5d77aef 100644 --- a/apps/web/src/lib/wagmi/components/token-selector/token-lists/token-selector-chip-bar.tsx +++ b/apps/web/src/lib/wagmi/components/token-selector/token-lists/token-selector-chip-bar.tsx @@ -1,6 +1,5 @@ import { XMarkIcon } from '@heroicons/react/20/solid' import { usePinnedTokens } from '@sushiswap/hooks' -import { NativeAddress } from '@sushiswap/react-query' import { BrowserEvent, InterfaceElementName, @@ -8,6 +7,7 @@ import { TraceEvent, } from '@sushiswap/telemetry' import { Button, Currency, IconButton, buttonIconVariants } from '@sushiswap/ui' +import { NativeAddress } from 'src/lib/hooks/react-query' import type { ChainId } from 'sushi/chain' import { Type } from 'sushi/currency' import { useChipTokens } from '../hooks/use-chip-tokens' diff --git a/apps/web/src/lib/wagmi/components/token-selector/token-lists/token-selector-custom-list.tsx b/apps/web/src/lib/wagmi/components/token-selector/token-lists/token-selector-custom-list.tsx index c322168e35..1ca5bbbaa7 100644 --- a/apps/web/src/lib/wagmi/components/token-selector/token-lists/token-selector-custom-list.tsx +++ b/apps/web/src/lib/wagmi/components/token-selector/token-lists/token-selector-custom-list.tsx @@ -1,7 +1,7 @@ import { isTokenListChainId } from '@sushiswap/graph-client/data-api' -import { usePrices } from '@sushiswap/react-query' import { List } from '@sushiswap/ui' import { useMemo } from 'react' +import { usePrices } from 'src/app/(evm)/_common/ui/price-provider/price-provider/use-prices' import { Address } from 'sushi' import type { ChainId } from 'sushi/chain' import type { Type } from 'sushi/currency' diff --git a/apps/web/src/lib/wagmi/components/token-selector/token-lists/token-selector-my-tokens.tsx b/apps/web/src/lib/wagmi/components/token-selector/token-lists/token-selector-my-tokens.tsx index 8d17002e19..83869f84a8 100644 --- a/apps/web/src/lib/wagmi/components/token-selector/token-lists/token-selector-my-tokens.tsx +++ b/apps/web/src/lib/wagmi/components/token-selector/token-lists/token-selector-my-tokens.tsx @@ -1,6 +1,6 @@ import { TokenListChainId } from '@sushiswap/graph-client/data-api' -import { usePrices } from '@sushiswap/react-query' import { List } from '@sushiswap/ui' +import { usePrices } from 'src/app/(evm)/_common/ui/price-provider/price-provider/use-prices' import type { Type } from 'sushi/currency' import { useAccount } from 'wagmi' import { useMyTokens } from '../hooks/use-my-tokens' diff --git a/apps/web/src/lib/wagmi/components/token-selector/token-lists/token-selector-search.tsx b/apps/web/src/lib/wagmi/components/token-selector/token-lists/token-selector-search.tsx index fe7b00aabc..58740c0cca 100644 --- a/apps/web/src/lib/wagmi/components/token-selector/token-lists/token-selector-search.tsx +++ b/apps/web/src/lib/wagmi/components/token-selector/token-lists/token-selector-search.tsx @@ -1,9 +1,9 @@ import { TokenListChainId } from '@sushiswap/graph-client/data-api' import { useCustomTokens } from '@sushiswap/hooks' -import { usePrices } from '@sushiswap/react-query' import { List } from '@sushiswap/ui' import { useMemo } from 'react' import InfiniteScroll from 'react-infinite-scroll-component' +import { usePrices } from 'src/app/(evm)/_common/ui/price-provider/price-provider/use-prices' import type { Type } from 'sushi/currency' import type { Address } from 'viem' import { useSearchTokens } from '../hooks/use-search-tokens' diff --git a/apps/web/src/lib/wagmi/components/token-selector/token-lists/token-selector-trending-tokens.tsx b/apps/web/src/lib/wagmi/components/token-selector/token-lists/token-selector-trending-tokens.tsx index 42b21d6217..446f96c61e 100644 --- a/apps/web/src/lib/wagmi/components/token-selector/token-lists/token-selector-trending-tokens.tsx +++ b/apps/web/src/lib/wagmi/components/token-selector/token-lists/token-selector-trending-tokens.tsx @@ -1,6 +1,6 @@ import { TrendingTokensChainId } from '@sushiswap/graph-client/data-api' -import { usePrices } from '@sushiswap/react-query' import { List } from '@sushiswap/ui' +import { usePrices } from 'src/app/(evm)/_common/ui/price-provider/price-provider/use-prices' import type { Type } from 'sushi/currency' import { useTrendingTokens } from '../hooks/use-trending-tokens' import { diff --git a/apps/web/src/lib/wagmi/components/token-selector/token-selector-states.tsx b/apps/web/src/lib/wagmi/components/token-selector/token-selector-states.tsx index 852f40e931..3cd43aee73 100644 --- a/apps/web/src/lib/wagmi/components/token-selector/token-selector-states.tsx +++ b/apps/web/src/lib/wagmi/components/token-selector/token-selector-states.tsx @@ -144,6 +144,7 @@ export function TokenSelectorStates({ chainId={chainId} onSelect={onSelect} selected={selected} + includeNative={includeNative} /> ) : null} diff --git a/apps/web/src/lib/wagmi/components/user-portfolio/portfolio-claimables/index.tsx b/apps/web/src/lib/wagmi/components/user-portfolio/portfolio-claimables/index.tsx index 3baed7c39a..57d5d7aa55 100644 --- a/apps/web/src/lib/wagmi/components/user-portfolio/portfolio-claimables/index.tsx +++ b/apps/web/src/lib/wagmi/components/user-portfolio/portfolio-claimables/index.tsx @@ -43,21 +43,22 @@ export const PortfolioClaimables = () => { [data], ) + // TODO: Add error state return (
    Total Balance - {isLoading ? ( + {isLoading || !data ? ( ) : (
    - {formatUSD(data!.totalUSD)} + {formatUSD(data.totalUSD || 0)}
    )}
    - {isLoading ? ( + {isLoading || !data ? (
    @@ -90,7 +91,7 @@ export const PortfolioClaimables = () => { {farmClaimables.length ? ( ) : null} - {data?.furoClaimables.length ? ( + {data.furoClaimables.length ? ( ) : null} diff --git a/apps/web/src/lib/wagmi/components/user-portfolio/portfolio-positions/index.tsx b/apps/web/src/lib/wagmi/components/user-portfolio/portfolio-positions/index.tsx index 2736a08004..502a376a3e 100644 --- a/apps/web/src/lib/wagmi/components/user-portfolio/portfolio-positions/index.tsx +++ b/apps/web/src/lib/wagmi/components/user-portfolio/portfolio-positions/index.tsx @@ -29,23 +29,24 @@ export const PortfolioPositions = () => { const id = useAccount() const { data, isLoading } = usePortfolioPositions(id.address) + // TODO: Add error state return (
    Total Balance
    - {isLoading ? ( + {isLoading || !data ? ( ) : (
    - {formatUSD(data!.totalUSD)} + {formatUSD(data.totalUSD)}
    )}
    - {isLoading ? ( + {isLoading || !data ? (
    @@ -78,13 +79,13 @@ export const PortfolioPositions = () => { className="overflow-y-auto h-full" defaultValue={['v2', 'v3', 'alm']} > - {data?.v2Positions.length ? ( + {data.v2Positions.length ? ( ) : null} - {data?.v3Positions.length ? ( + {data.v3Positions.length ? ( ) : null} - {data?.smartPositions.length ? ( + {data.smartPositions.length ? ( ) : null} diff --git a/apps/web/src/lib/wagmi/components/user-portfolio/portfolio-tokens/index.tsx b/apps/web/src/lib/wagmi/components/user-portfolio/portfolio-tokens/index.tsx index c5505e8cc4..b73fe58ada 100644 --- a/apps/web/src/lib/wagmi/components/user-portfolio/portfolio-tokens/index.tsx +++ b/apps/web/src/lib/wagmi/components/user-portfolio/portfolio-tokens/index.tsx @@ -27,13 +27,14 @@ export const PortfolioTokens = () => { const { address } = useAccount() const { data, isLoading } = usePortfolioWallet(address) + // TODO: Add error state return (
    Total Balance
    - {isLoading ? ( + {isLoading || !data ? ( <> @@ -41,21 +42,21 @@ export const PortfolioTokens = () => { ) : ( <>
    - {formatUSD(data!.totalUSD)} + {formatUSD(data.totalUSD)}
    0 + data.amountUSD24Change > 0 ? 'text-green' - : data!.amountUSD24Change < 0 + : data.amountUSD24Change < 0 ? 'text-red' : 'text-muted-foreground', )} > - {`${data!.amountUSD24Change > 0 ? '+' : ''}${formatUSD( - data!.amountUSD24Change, - )} (${formatPercent(data!.percentageChange24h)})`} + {`${data.amountUSD24Change > 0 ? '+' : ''}${formatUSD( + data.amountUSD24Change, + )} (${formatPercent(data.percentageChange24h)})`}
    )} @@ -63,7 +64,7 @@ export const PortfolioTokens = () => {
    - {isLoading ? ( + {isLoading || !data ? (
    {Array.from({ length: 12 }).map((_, i) => (
    {
    ))}
    - ) : data?.tokens.length ? ( + ) : data.tokens.length ? ( ) : null}
    diff --git a/apps/web/src/lib/wagmi/components/user-profile/DefaultView.tsx b/apps/web/src/lib/wagmi/components/user-profile/DefaultView.tsx index 57a4695823..126d2d84d5 100644 --- a/apps/web/src/lib/wagmi/components/user-profile/DefaultView.tsx +++ b/apps/web/src/lib/wagmi/components/user-profile/DefaultView.tsx @@ -6,7 +6,6 @@ import { InboxArrowDownIcon, LinkIcon, } from '@heroicons/react/24/outline' -import { usePrice } from '@sushiswap/react-query' import { BrowserEvent, InterfaceElementName, @@ -27,6 +26,7 @@ import { Amount, Native } from 'sushi/currency' import { Fraction } from 'sushi/math' import { zeroAddress } from 'viem' import { useBalance, useDisconnect } from 'wagmi' +import { usePrice } from '~evm/_common/ui/price-provider/price-provider/use-price' import { ProfileView } from './ProfileView' interface DefaultProps { diff --git a/apps/web/src/lib/wagmi/components/wagmi-header-components.tsx b/apps/web/src/lib/wagmi/components/wagmi-header-components.tsx index 7ead52c63b..455b975829 100644 --- a/apps/web/src/lib/wagmi/components/wagmi-header-components.tsx +++ b/apps/web/src/lib/wagmi/components/wagmi-header-components.tsx @@ -8,7 +8,7 @@ import { WalletConnectionResult, sendAnalyticsEvent, } from '@sushiswap/telemetry' -import { Suspense, useEffect } from 'react' +import { useEffect } from 'react' import { useAccount } from 'wagmi' import { HeaderNetworkSelector } from './header-network-selector' import { UserPortfolio } from './user-portfolio' @@ -40,9 +40,9 @@ export const WagmiHeaderComponents: React.FC = ({ }, [address, chainId, connector, previousConnectedChainId]) return ( - + <> - + ) } diff --git a/apps/web/src/lib/wagmi/components/web3-input/Currency/CurrencyInput.tsx b/apps/web/src/lib/wagmi/components/web3-input/Currency/CurrencyInput.tsx index 6e59b163ce..959e3ff386 100644 --- a/apps/web/src/lib/wagmi/components/web3-input/Currency/CurrencyInput.tsx +++ b/apps/web/src/lib/wagmi/components/web3-input/Currency/CurrencyInput.tsx @@ -1,7 +1,6 @@ 'use client' import { useIsMounted } from '@sushiswap/hooks' -import { usePrice } from '@sushiswap/react-query' import { Button, SelectIcon, TextField, classNames } from '@sushiswap/ui' import { Currency } from '@sushiswap/ui' import { SkeletonBox } from '@sushiswap/ui' @@ -18,6 +17,7 @@ import { ChainId } from 'sushi/chain' import { Token, Type, tryParseAmount } from 'sushi/currency' import { Percent } from 'sushi/math' import { useAccount } from 'wagmi' +import { usePrice } from '~evm/_common/ui/price-provider/price-provider/use-price' import { TokenSelector } from '../../token-selector/token-selector' import { BalancePanel } from './BalancePanel' import { PricePanel } from './PricePanel' @@ -85,7 +85,7 @@ const CurrencyInput: FC = ({ currency, }) - const { data: price, isInitialLoading: isPriceLoading } = usePrice({ + const { data: price, isLoading: isPriceLoading } = usePrice({ chainId: currency?.chainId, address: currency?.wrapped?.address, enabled: !hidePricing, diff --git a/apps/web/src/lib/wagmi/components/web3-input/Currency/PricePanel.tsx b/apps/web/src/lib/wagmi/components/web3-input/Currency/PricePanel.tsx index 7b910252cb..6925fdfe44 100644 --- a/apps/web/src/lib/wagmi/components/web3-input/Currency/PricePanel.tsx +++ b/apps/web/src/lib/wagmi/components/web3-input/Currency/PricePanel.tsx @@ -6,7 +6,7 @@ import { warningSeverityClassName, } from 'src/lib/swap/warningSeverity' import { tryParseAmount } from 'sushi/currency' -import { Fraction, ZERO } from 'sushi/math' +import { ZERO } from 'sushi/math' import { CurrencyInputProps } from './CurrencyInput' type PricePanel = Pick< @@ -14,7 +14,7 @@ type PricePanel = Pick< 'loading' | 'currency' | 'value' | 'priceImpact' > & { error?: string - price: Fraction | undefined + price: number | undefined } export const PricePanel: FC = ({ @@ -31,10 +31,10 @@ export const PricePanel: FC = ({ ) const [big, portion] = ( parsedValue && price - ? `${price.asFraction - .multiply(parsedValue) - .divide(10 ** parsedValue.currency.decimals) - .toFixed(2)}` + ? `${( + (price * Number(parsedValue.quotient)) / + 10 ** parsedValue.currency.decimals + ).toFixed(2)}` : '0.00' ).split('.') @@ -53,14 +53,14 @@ export const PricePanel: FC = ({ return (

    - {!loading && price?.equalTo(ZERO) ? ( + {!loading && price === 0 ? ( Price not available ) : ( <> $ {big}.{portion} )} - {!(!loading && price?.equalTo(ZERO)) && priceImpact && ( + {!(!loading && price === 0) && priceImpact && ( { +const createWagmiConfig = ({ useCookies }: { useCookies: boolean }) => { const isTest = process.env.NEXT_PUBLIC_APP_ENV === 'test' const config = (() => { if (isTest) { return createTestConfig() as unknown as PublicWagmiConfig } - return createProductionConfig() + return createProductionConfig({ useCookies }) })() return config -})() +} + +let wagmiConfigSingleton: PublicWagmiConfig | undefined = undefined +export const getWagmiConfig = ({ useCookies }: { useCookies: boolean }) => { + if (typeof window === 'undefined') { + return createWagmiConfig({ useCookies }) + } + + if (!wagmiConfigSingleton) { + wagmiConfigSingleton = createWagmiConfig({ useCookies }) + } + + return wagmiConfigSingleton +} export const getWagmiInitialState = ( cookieHeaders: string | null | undefined, + functionalCookiesEnabled: boolean, ) => { - const initialState = cookieToInitialState(wagmiConfig, cookieHeaders) + const initialState = cookieToInitialState( + getWagmiConfig({ useCookies: functionalCookiesEnabled }), + cookieHeaders, + ) return initialState } diff --git a/apps/web/src/lib/wagmi/config/production.ts b/apps/web/src/lib/wagmi/config/production.ts index ff1fa0f879..36f571f1b4 100644 --- a/apps/web/src/lib/wagmi/config/production.ts +++ b/apps/web/src/lib/wagmi/config/production.ts @@ -13,7 +13,13 @@ import { import { gtagEvent } from '@sushiswap/ui' import { ChainId } from 'sushi/chain' import { publicTransports } from 'sushi/config' -import { http, cookieStorage, createConfig, createStorage } from 'wagmi' +import { + http, + type Storage, + cookieStorage, + createConfig, + createStorage, +} from 'wagmi' import { Writeable } from 'zod' import { publicWagmiConfig } from './public' @@ -52,7 +58,9 @@ const connectors = connectorsForWallets( }, ) -export const createProductionConfig = () => { +export const createProductionConfig = ({ + useCookies, +}: { useCookies: boolean }) => { const transports = Object.entries(publicTransports).reduce( (acc, [chainId, transport]) => { const transportUrl = transport({ chain: undefined }).value?.url! @@ -73,16 +81,21 @@ export const createProductionConfig = () => { {} as Writeable, ) + let storage: Storage | undefined = undefined + if (useCookies) { + storage = createStorage({ + storage: cookieStorage, + }) + } else if (typeof window !== 'undefined') { + storage = createStorage({ storage: window.localStorage }) + } + return createConfig({ ...publicWagmiConfig, transports, pollingInterval, connectors, - storage: createStorage({ - storage: cookieStorage, - }), + storage, ssr: true, }) } - -export const config = createProductionConfig() diff --git a/apps/web/src/lib/wagmi/hooks/positions/hooks/useConcentratedLiquidityPositions.ts b/apps/web/src/lib/wagmi/hooks/positions/hooks/useConcentratedLiquidityPositions.ts index 6ba9f679bb..30e5d31822 100644 --- a/apps/web/src/lib/wagmi/hooks/positions/hooks/useConcentratedLiquidityPositions.ts +++ b/apps/web/src/lib/wagmi/hooks/positions/hooks/useConcentratedLiquidityPositions.ts @@ -1,11 +1,12 @@ import { useCustomTokens } from '@sushiswap/hooks' -import { useAllPrices, usePrices } from '@sushiswap/react-query' import { useQuery } from '@tanstack/react-query' +import { useAllPrices } from 'src/lib/hooks/react-query' import { SushiSwapV3ChainId } from 'sushi/config' import { Amount, Token } from 'sushi/currency' import { Position, SushiSwapV3Pool } from 'sushi/pool/sushiswap-v3' import { useMemo } from 'react' +import { usePrices } from 'src/app/(evm)/_common/ui/price-provider/price-provider/use-prices' import { Address } from 'viem' import { useConfig } from 'wagmi' import { getConcentratedLiquidityPool } from '../../pools/actions/getConcentratedLiquidityPool' @@ -51,8 +52,7 @@ export const useConcentratedLiquidityPositions = ({ isError: isChainPricesError, isLoading: isChainPricesInitialLoading, } = usePrices({ - chainId: chainIds.length ? chainIds[0] : undefined, - enabled: chainIds.length === 1, + chainId: chainIds?.length === 1 ? chainIds[0] : undefined, }) const prices = useMemo(() => { diff --git a/apps/web/src/lib/wagmi/hooks/steer/useSteerAccountPositionsExtended.ts b/apps/web/src/lib/wagmi/hooks/steer/useSteerAccountPositionsExtended.ts index 6dd1adafc5..8387f4ccdf 100644 --- a/apps/web/src/lib/wagmi/hooks/steer/useSteerAccountPositionsExtended.ts +++ b/apps/web/src/lib/wagmi/hooks/steer/useSteerAccountPositionsExtended.ts @@ -1,7 +1,7 @@ import { SmartPoolChainId } from '@sushiswap/graph-client/data-api' -import { useAllPrices } from '@sushiswap/react-query' import { useMemo } from 'react' import { useSmartPools } from 'src/lib/hooks/api/userSmartPools' +import { useAllPrices } from 'src/lib/hooks/react-query' import { ID } from 'sushi' import { Amount, Token } from 'sushi/currency' import { Address } from 'viem' diff --git a/apps/web/src/providers/query-client-provider.tsx b/apps/web/src/providers/query-client-provider.tsx index ea0019e30b..ec4b347c56 100644 --- a/apps/web/src/providers/query-client-provider.tsx +++ b/apps/web/src/providers/query-client-provider.tsx @@ -1,15 +1,47 @@ 'use client' -import { createQueryClient } from '@sushiswap/react-query' -// import { ReactQueryDevtools } from '@tanstack/react-query-devtools' -import { QueryClientProvider as _QueryClientProvider } from '@tanstack/react-query' +import * as Sentry from '@sentry/nextjs' +import { + QueryCache, + QueryClient, + QueryClientProvider as _QueryClientProvider, +} from '@tanstack/react-query' import { FC, ReactNode } from 'react' -const client = createQueryClient() +const queryClientConfig = { + defaultOptions: { + queries: { + gcTime: 1000 * 60 * 60 * 24, // 24 hours + }, + }, + queryCache: new QueryCache({ + onError: (error, query) => { + if (error instanceof Error) { + if (error.name === 'ConnectorNotConnectedError') return + } + Sentry.captureException(error, { data: { query } }) + }, + }), +} + +let clientQueryClientSingleton: QueryClient | undefined = undefined +const getQueryClient = () => { + if (typeof window === 'undefined') { + return new QueryClient(queryClientConfig) + } + + if (!clientQueryClientSingleton) { + clientQueryClientSingleton = new QueryClient(queryClientConfig) + } + + return clientQueryClientSingleton +} export const QueryClientProvider: FC<{ children: ReactNode }> = ({ children, }) => { + const client = getQueryClient() + return ( <_QueryClientProvider client={client}> {children} diff --git a/apps/web/src/providers/wagmi-provider.tsx b/apps/web/src/providers/wagmi-provider.tsx index 12ff418696..f38b6cc3db 100644 --- a/apps/web/src/providers/wagmi-provider.tsx +++ b/apps/web/src/providers/wagmi-provider.tsx @@ -10,10 +10,12 @@ import { import { useIsMounted } from '@sushiswap/hooks' import { useTheme } from 'next-themes' import { type FC, type ReactNode, useMemo } from 'react' +import { useEnabledCookies } from 'src/app/_common/cookies/use-enabled-cookies' import { WagmiSentry } from 'src/lib/wagmi/components/wagmi-sentry' import { WagmiStoreVersionCheck } from 'src/lib/wagmi/components/wagmi-store-version-check' -import { getWagmiInitialState, wagmiConfig } from 'src/lib/wagmi/config' +import { getWagmiConfig, getWagmiInitialState } from 'src/lib/wagmi/config' import { WagmiProvider as _WagmiProvider } from 'wagmi' + const darkTheme: Theme = { ...rainbowDarkTheme({ borderRadius: 'medium', @@ -49,8 +51,8 @@ const lightTheme: Theme = { const Disclaimer: DisclaimerComponent = ({ Text, Link }) => ( By connecting your wallet, you agree to Sushi Labs{"' "} - Terms of Service and{' '} - Privacy Policy + Terms of Service and{' '} + Privacy Policy ) @@ -58,7 +60,11 @@ export const WagmiProvider: FC<{ children: ReactNode cookie?: string | null }> = ({ children, cookie }) => { - const initialState = getWagmiInitialState(cookie) + const enabledCookies = useEnabledCookies() + + const functionalCookiesEnabled = !!enabledCookies?.has('functional') + + const initialState = getWagmiInitialState(cookie, functionalCookiesEnabled) const isMounted = useIsMounted() const { resolvedTheme } = useTheme() @@ -72,7 +78,12 @@ export const WagmiProvider: FC<{ }, [resolvedTheme, isMounted]) return ( - <_WagmiProvider config={wagmiConfig} initialState={initialState}> + <_WagmiProvider + config={getWagmiConfig({ + useCookies: functionalCookiesEnabled, + })} + initialState={initialState} + >

    > = ({ diff --git a/apps/web/src/ui/pool/RewardsV3NameCell.tsx b/apps/web/src/ui/pool/RewardsV3NameCell.tsx index 52e018a889..cb70dae545 100644 --- a/apps/web/src/ui/pool/RewardsV3NameCell.tsx +++ b/apps/web/src/ui/pool/RewardsV3NameCell.tsx @@ -1,7 +1,6 @@ 'use client' import { InformationCircleIcon } from '@heroicons/react/24/outline' -import { AngleRewardsPool } from '@sushiswap/react-query' import { Chip, HoverCard, @@ -14,6 +13,7 @@ import { Currency } from '@sushiswap/ui' import { NetworkIcon } from '@sushiswap/ui/icons/NetworkIcon' import { Row } from '@tanstack/react-table' import React, { FC } from 'react' +import { AngleRewardsPool } from 'src/lib/hooks/react-query' import { unwrapToken } from 'sushi/currency' import { DistributionDataTable } from './DistributionDataTable' diff --git a/apps/web/src/ui/pool/SelectPricesWidget.tsx b/apps/web/src/ui/pool/SelectPricesWidget.tsx index b157f0a0d9..103be5ea42 100644 --- a/apps/web/src/ui/pool/SelectPricesWidget.tsx +++ b/apps/web/src/ui/pool/SelectPricesWidget.tsx @@ -54,7 +54,7 @@ import { import { RadioGroup } from '@headlessui/react' import { LockClosedIcon, LockOpenIcon } from '@heroicons/react/24/solid' import { ExclamationTriangleIcon } from '@heroicons/react/24/solid' -import { useConcentratedLiquidityPoolStats } from '@sushiswap/react-query' +import { useConcentratedLiquidityPoolStats } from 'src/lib/hooks/react-query' import { useConcentratedLiquidityPositionsFromTokenId } from 'src/lib/wagmi/hooks/positions/hooks/useConcentratedPositionsFromTokenId' import { Address } from 'sushi' import { formatPercent } from 'sushi/format' diff --git a/apps/web/src/ui/pool/Steer/SteerLiquidityDistributionWidget/SteerTokenDistributionBar.tsx b/apps/web/src/ui/pool/Steer/SteerLiquidityDistributionWidget/SteerTokenDistributionBar.tsx index 458b576185..6a30762428 100644 --- a/apps/web/src/ui/pool/Steer/SteerLiquidityDistributionWidget/SteerTokenDistributionBar.tsx +++ b/apps/web/src/ui/pool/Steer/SteerLiquidityDistributionWidget/SteerTokenDistributionBar.tsx @@ -1,10 +1,10 @@ 'use client' -import { usePrices } from '@sushiswap/react-query' import { SteerVault, getTokenRatios } from '@sushiswap/steer-sdk' import { useQuery } from '@tanstack/react-query' import React from 'react' -import { stringify } from 'sushi/bigint-serializer' +import { usePrices } from 'src/app/(evm)/_common/ui/price-provider/price-provider/use-prices' +import { stringify } from 'src/instrumentation' interface SteerTokenDistributionBarProps { vault: SteerVault @@ -19,16 +19,8 @@ export function SteerTokenDistributionBar({ queryFn: async () => { if (!prices) return - const numPrices = Object.entries(prices).reduce>( - (acc, [key, value]) => { - acc[key] = Number(value.toFixed(18)) - return acc - }, - {}, - ) - try { - return getTokenRatios({ vault, prices: numPrices }) + return getTokenRatios({ vault, prices }) } catch (e) { console.error(e) } diff --git a/apps/web/src/ui/pool/Steer/SteerStrategyLiquidityChart/SteerStrategyLiquidityDistribution.tsx b/apps/web/src/ui/pool/Steer/SteerStrategyLiquidityChart/SteerStrategyLiquidityDistribution.tsx index d724f2249a..8b461d18ba 100644 --- a/apps/web/src/ui/pool/Steer/SteerStrategyLiquidityChart/SteerStrategyLiquidityDistribution.tsx +++ b/apps/web/src/ui/pool/Steer/SteerStrategyLiquidityChart/SteerStrategyLiquidityDistribution.tsx @@ -1,8 +1,8 @@ 'use client' -import { useConcentratedLiquidityPoolStats } from '@sushiswap/react-query' import { SkeletonBox } from '@sushiswap/ui' import React, { FC, useMemo } from 'react' +import { useConcentratedLiquidityPoolStats } from 'src/lib/hooks/react-query' import { SushiSwapV3ChainId } from 'sushi/config' import { TickMath, tickToPrice } from 'sushi/pool/sushiswap-v3' import type { PoolId } from 'sushi/types' diff --git a/apps/web/src/ui/pool/V3FeesTable.tsx b/apps/web/src/ui/pool/V3FeesTable.tsx index 56d7b8b304..72a6ca6ea0 100644 --- a/apps/web/src/ui/pool/V3FeesTable.tsx +++ b/apps/web/src/ui/pool/V3FeesTable.tsx @@ -248,7 +248,7 @@ export const V3FeesTable: FC<{ pools: V3BasePool[]; chainId: ChainId }> = ({ loading={!pools} columns={COLUMNS} data={data} - linkFormatter={(row) => Chain.from(chainId).getAccountUrl(row.address)} + linkFormatter={(row) => Chain.from(chainId)!.getAccountUrl(row.address)} /> ) } diff --git a/apps/web/src/ui/pool/V3PositionView.tsx b/apps/web/src/ui/pool/V3PositionView.tsx index 9d9e322792..3560b3df59 100644 --- a/apps/web/src/ui/pool/V3PositionView.tsx +++ b/apps/web/src/ui/pool/V3PositionView.tsx @@ -2,7 +2,6 @@ import { CogIcon } from '@heroicons/react-v1/outline' import { SlippageToleranceStorageKey, TTLStorageKey } from '@sushiswap/hooks' -import { useAngleRewards } from '@sushiswap/react-query' import { Card, CardContent, @@ -34,6 +33,7 @@ import { Button } from '@sushiswap/ui' import { FormattedNumber } from '@sushiswap/ui' import { SkeletonText } from '@sushiswap/ui' import { FC, useMemo, useState } from 'react' +import { useAngleRewards } from 'src/lib/hooks/react-query' import { useConcentratedPositionInfo } from 'src/lib/wagmi/hooks/positions/hooks/useConcentratedPositionInfo' import { useConcentratedPositionOwner } from 'src/lib/wagmi/hooks/positions/hooks/useConcentratedPositionOwner' import { useConcentratedLiquidityPositionsFromTokenId } from 'src/lib/wagmi/hooks/positions/hooks/useConcentratedPositionsFromTokenId' diff --git a/apps/web/src/ui/pool/columns.tsx b/apps/web/src/ui/pool/columns.tsx index 7134912ba3..086c956968 100644 --- a/apps/web/src/ui/pool/columns.tsx +++ b/apps/web/src/ui/pool/columns.tsx @@ -1,5 +1,4 @@ import { Pool } from '@sushiswap/graph-client/data-api' -import { AngleRewardsPool } from '@sushiswap/react-query' import { PoolHasSteerVaults } from '@sushiswap/steer-sdk' import { Badge, @@ -17,6 +16,7 @@ import { NetworkIcon } from '@sushiswap/ui/icons/NetworkIcon' import { ColumnDef } from '@tanstack/react-table' import formatDistance from 'date-fns/formatDistance' import React, { useMemo } from 'react' +import { AngleRewardsPool } from 'src/lib/hooks/react-query' import { ConcentratedLiquidityPositionWithV3Pool } from 'src/lib/wagmi/hooks/positions/types' import type { MaybeNestedPool, diff --git a/apps/web/src/ui/stake/XSushiPrice.tsx b/apps/web/src/ui/stake/XSushiPrice.tsx index b1522a90f6..2155c89834 100644 --- a/apps/web/src/ui/stake/XSushiPrice.tsx +++ b/apps/web/src/ui/stake/XSushiPrice.tsx @@ -1,7 +1,7 @@ import { ArrowTrendingUpIcon } from '@heroicons/react/20/solid' -import { usePrices } from '@sushiswap/react-query' import { Button, SkeletonText } from '@sushiswap/ui' import { useMemo, useState } from 'react' +import { usePrices } from 'src/app/(evm)/_common/ui/price-provider/price-provider/use-prices' import { useTokenAmountDollarValues } from 'src/lib/hooks' import { ChainId } from 'sushi/chain' import { @@ -45,7 +45,7 @@ export const XSushiPrice = ({ }) const price = useMemo(() => { - const _sushiPrice = prices?.get(SUSHI_ADDRESS[ChainId.ETHEREUM]) + const _sushiPrice = prices?.getFraction(SUSHI_ADDRESS[ChainId.ETHEREUM]) const sushiPrice = _sushiPrice !== undefined diff --git a/apps/web/src/ui/swap/cross-chain/cross-chain-swap-header.tsx b/apps/web/src/ui/swap/cross-chain/cross-chain-swap-header.tsx index 89e884acd8..1d14dc6bea 100644 --- a/apps/web/src/ui/swap/cross-chain/cross-chain-swap-header.tsx +++ b/apps/web/src/ui/swap/cross-chain/cross-chain-swap-header.tsx @@ -1,7 +1,6 @@ 'use client' import { ArrowTrendingUpIcon } from '@heroicons/react/20/solid' -import { usePrices } from '@sushiswap/react-query' import { Button, typographyVariants } from '@sushiswap/ui' import { SkeletonText } from '@sushiswap/ui' import React, { useMemo, useState } from 'react' @@ -9,6 +8,7 @@ import { useTokenAmountDollarValues } from 'src/lib/hooks' import { Amount, Price, Token, tryParseAmount } from 'sushi/currency' import { formatUSD } from 'sushi/format' +import { usePrices } from 'src/app/(evm)/_common/ui/price-provider/price-provider/use-prices' import { useDerivedStateCrossChainSwap } from './derivedstate-cross-chain-swap-provider' export const CrossChainSwapHeader = () => { @@ -49,12 +49,12 @@ export const CrossChainSwapHeader = () => { decimals: token1.decimals, }) - const _token0Price = prices0?.get(token0.wrapped.address) + const _token0Price = prices0?.getFraction(token0.wrapped.address) const token0Price = _token0Price ? tryParseAmount('1', token0)?.multiply(_token0Price) : undefined - const _token1Price = prices1?.get(token1.wrapped.address) + const _token1Price = prices1?.getFraction(token1.wrapped.address) const token1Price = _token1Price ? tryParseAmount('1', token1)?.multiply(_token1Price) : undefined diff --git a/apps/web/src/ui/swap/cross-chain/cross-chain-swap-token-not-found-dialog.tsx b/apps/web/src/ui/swap/cross-chain/cross-chain-swap-token-not-found-dialog.tsx index 5ca4e8a861..be3689d8ce 100644 --- a/apps/web/src/ui/swap/cross-chain/cross-chain-swap-token-not-found-dialog.tsx +++ b/apps/web/src/ui/swap/cross-chain/cross-chain-swap-token-not-found-dialog.tsx @@ -1,7 +1,6 @@ 'use client' import { useCustomTokens } from '@sushiswap/hooks' -import { useTokenSecurity } from '@sushiswap/react-query' import { Dialog, DialogContent, @@ -16,6 +15,7 @@ import { Currency } from '@sushiswap/ui' import { List } from '@sushiswap/ui' import { NetworkIcon } from '@sushiswap/ui/icons/NetworkIcon' import React, { useCallback, useMemo } from 'react' +import { useTokenSecurity } from 'src/lib/hooks/react-query' import { Chain } from 'sushi/chain' import { defaultCurrency, diff --git a/apps/web/src/ui/swap/simple/derivedstate-simple-swap-provider.tsx b/apps/web/src/ui/swap/simple/derivedstate-simple-swap-provider.tsx index 1251a52d70..6bb6a1ab46 100644 --- a/apps/web/src/ui/swap/simple/derivedstate-simple-swap-provider.tsx +++ b/apps/web/src/ui/swap/simple/derivedstate-simple-swap-provider.tsx @@ -1,6 +1,5 @@ 'use client' -import { useTrade as useApiTrade } from '@sushiswap/react-query' import { watchChainId } from '@wagmi/core' import { useLogger } from 'next-axiom' import { usePathname, useRouter, useSearchParams } from 'next/navigation' @@ -13,6 +12,7 @@ import { useMemo, useState, } from 'react' +import { useTrade as useApiTrade } from 'src/lib/hooks/react-query' import { useSlippageTolerance } from 'src/lib/hooks/useSlippageTolerance' import { useTokenWithCache } from 'src/lib/wagmi/hooks/tokens/useTokenWithCache' import { ChainId, TestnetChainId } from 'sushi/chain' diff --git a/apps/web/src/ui/swap/simple/simple-swap-header.tsx b/apps/web/src/ui/swap/simple/simple-swap-header.tsx index 1ae9ab1dca..27b5bcb5f6 100644 --- a/apps/web/src/ui/swap/simple/simple-swap-header.tsx +++ b/apps/web/src/ui/swap/simple/simple-swap-header.tsx @@ -1,7 +1,6 @@ 'use client' import { ArrowTrendingUpIcon } from '@heroicons/react/20/solid' -import { usePrices } from '@sushiswap/react-query' import { Button, FormattedNumber, @@ -11,6 +10,7 @@ import { import React, { useMemo, useState } from 'react' import { Price, tryParseAmount } from 'sushi/currency' import { formatUSD } from 'sushi/format' +import { usePrices } from '~evm/_common/ui/price-provider/price-provider/use-prices' import { useTokenAmountDollarValues } from '../../../lib/hooks' import { useDerivedStateSimpleSwap } from './derivedstate-simple-swap-provider' @@ -35,15 +35,14 @@ export const SimpleSwapHeader = () => { const price = useMemo(() => { if (!token0 || !token1) return '0.00' - const token0Price = prices?.has(token0.wrapped.address) - ? tryParseAmount('1', token0)?.multiply( - prices.get(token0.wrapped.address)!, - ) + const token0PriceFraction = prices?.getFraction(token0.wrapped.address) + const token0Price = token0PriceFraction + ? tryParseAmount('1', token0)?.multiply(token0PriceFraction) : undefined - const token1Price = prices?.has(token1.wrapped.address) - ? tryParseAmount('1', token1)?.multiply( - prices.get(token1.wrapped.address)!, - ) + + const token1PriceFraction = prices?.getFraction(token1.wrapped.address) + const token1Price = token1PriceFraction + ? tryParseAmount('1', token1)?.multiply(token1PriceFraction) : undefined let price diff --git a/apps/web/src/ui/swap/simple/simple-swap-token-not-found-dialog.tsx b/apps/web/src/ui/swap/simple/simple-swap-token-not-found-dialog.tsx index 3058ab4de5..508382e7af 100644 --- a/apps/web/src/ui/swap/simple/simple-swap-token-not-found-dialog.tsx +++ b/apps/web/src/ui/swap/simple/simple-swap-token-not-found-dialog.tsx @@ -1,7 +1,6 @@ 'use client' import { useCustomTokens } from '@sushiswap/hooks' -import { useTokenSecurity } from '@sushiswap/react-query' import { Button, Dialog, @@ -14,6 +13,7 @@ import { Message, } from '@sushiswap/ui' import React, { useCallback, useMemo } from 'react' +import { useTokenSecurity } from 'src/lib/hooks/react-query' import { Chain } from 'sushi/chain' import { defaultCurrency, diff --git a/apps/web/src/ui/swap/simple/simple-swap-trade-review-dialog.tsx b/apps/web/src/ui/swap/simple/simple-swap-trade-review-dialog.tsx index a235d45b4e..db4d1ff863 100644 --- a/apps/web/src/ui/swap/simple/simple-swap-trade-review-dialog.tsx +++ b/apps/web/src/ui/swap/simple/simple-swap-trade-review-dialog.tsx @@ -1,7 +1,6 @@ 'use client' import { createErrorToast, createToast } from '@sushiswap/notifications' -import { UseTradeReturn } from '@sushiswap/react-query' import { BrowserEvent, InterfaceElementName, @@ -36,6 +35,7 @@ import React, { useMemo, useRef, } from 'react' +import { UseTradeReturn } from 'src/lib/hooks/react-query' import { useSimulateTrade } from 'src/lib/hooks/useSimulateTrade' import { useSlippageTolerance } from 'src/lib/hooks/useSlippageTolerance' import { useBalanceWeb3Refetch } from 'src/lib/wagmi/hooks/balances/useBalanceWeb3Refetch' diff --git a/apps/web/src/ui/swap/trade-route-path-view.tsx b/apps/web/src/ui/swap/trade-route-path-view.tsx index 546695f8d2..f5d6d61159 100644 --- a/apps/web/src/ui/swap/trade-route-path-view.tsx +++ b/apps/web/src/ui/swap/trade-route-path-view.tsx @@ -1,6 +1,5 @@ 'use client' -import { TradeLegType, UseTradeReturn } from '@sushiswap/react-query' import { InterfaceElementName, SwapEventName, @@ -20,6 +19,7 @@ import { ScrollArea, } from '@sushiswap/ui' import React, { FC, ReactNode, useEffect, useRef, useState } from 'react' +import { TradeLegType, UseTradeReturn } from 'src/lib/hooks/react-query' import { ChainId } from 'sushi/chain' import { Native, Token, Type, WETH9 } from 'sushi/currency' diff --git a/apps/web/src/ui/swap/twap/twap.tsx b/apps/web/src/ui/swap/twap/twap.tsx index 99dbd7313c..f7ce419abe 100644 --- a/apps/web/src/ui/swap/twap/twap.tsx +++ b/apps/web/src/ui/swap/twap/twap.tsx @@ -7,11 +7,6 @@ import { } from '@orbs-network/twap-ui-sushiswap' import { useConnectModal } from '@rainbow-me/rainbowkit' import { useCustomTokens } from '@sushiswap/hooks' -import { - useOtherTokenListsQuery, - usePrice, - useTokens, -} from '@sushiswap/react-query' import { Button, Dialog, @@ -26,6 +21,7 @@ import { } from '@sushiswap/ui' import { useTheme } from 'next-themes' import { ReactNode, useCallback, useEffect, useMemo } from 'react' +import { useOtherTokenListsQuery, useTokens } from 'src/lib/hooks/react-query' import { useSortedTokenList } from 'src/lib/wagmi/components/token-selector/hooks/use-sorted-token-list' import { ChainId } from 'sushi/chain' import { Currency } from 'sushi/currency' @@ -34,6 +30,7 @@ import { useAccount, useChainId, useSwitchChain } from 'wagmi' import { TokenSelector } from 'src/lib/wagmi/components/token-selector/token-selector' import { Checker } from 'src/lib/wagmi/systems/Checker' import { Address } from 'viem' +import { usePrice } from '~evm/_common/ui/price-provider/price-provider/use-price' import { useDerivedStateSimpleSwap, useSimpleSwapTrade, @@ -116,11 +113,10 @@ const usePriceUSD = (address?: Address) => { const { data: price } = usePrice({ chainId, - enabled: true, address, }) - return price?.toSignificant(6) + return String(price) } const getTokenLogo = (currency: Currency) => { diff --git a/apps/web/test/helpers/pool.ts b/apps/web/test/helpers/pool.ts index 7ae6641459..5d2623d972 100644 --- a/apps/web/test/helpers/pool.ts +++ b/apps/web/test/helpers/pool.ts @@ -1,6 +1,6 @@ import { Page, expect } from '@playwright/test' -import { NativeAddress } from '@sushiswap/react-query' import { NextFixture } from 'next/experimental/testmode/playwright' +import { NativeAddress } from 'src/lib/hooks/react-query' import { SUSHISWAP_V2_FACTORY_ADDRESS, SUSHISWAP_V3_FACTORY_ADDRESS, diff --git a/apps/web/test/helpers/swap.ts b/apps/web/test/helpers/swap.ts index 82b8e4868d..e7854af14a 100644 --- a/apps/web/test/helpers/swap.ts +++ b/apps/web/test/helpers/swap.ts @@ -1,5 +1,5 @@ import { Page, expect } from '@playwright/test' -import { NativeAddress } from '@sushiswap/react-query' +import { NativeAddress } from 'src/lib/hooks/react-query' import { API_BASE_URL } from 'sushi/config' import { Amount, Native, Type } from 'sushi/currency' import { BaseActions } from './base' // Adjust the import path as necessary diff --git a/apps/web/test/setup.ts b/apps/web/test/setup.ts index c44951a680..e69de29bb2 100644 --- a/apps/web/test/setup.ts +++ b/apps/web/test/setup.ts @@ -1 +0,0 @@ -import '@testing-library/jest-dom' diff --git a/apps/web/test/swap/scripts/generate-swaps.ts b/apps/web/test/swap/scripts/generate-swaps.ts index fb3d44cb9a..d041f6df45 100644 --- a/apps/web/test/swap/scripts/generate-swaps.ts +++ b/apps/web/test/swap/scripts/generate-swaps.ts @@ -1,5 +1,8 @@ import fs from 'fs' -import { type UseTradeParams, tradeValidator02 } from '@sushiswap/react-query' +import { + type UseTradeParams, + tradeValidator02, +} from 'src/lib/hooks/react-query' import { ChainId } from 'sushi/chain' import { API_BASE_URL, diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json index f26cb394a6..7a2a3eff59 100644 --- a/apps/web/tsconfig.json +++ b/apps/web/tsconfig.json @@ -4,7 +4,8 @@ "target": "ESNext", "lib": ["DOM", "DOM.Iterable", "ESNext"], "paths": { - "~aptos/*": ["src/app/(non-evm)/aptos/*"] + "~aptos/*": ["src/app/(non-evm)/aptos/*"], + "~evm/*": ["src/app/(evm)/*"], }, "allowJs": true, "skipLibCheck": true, diff --git a/config/eslint/package.json b/config/eslint/package.json index c28936ae33..71566afde7 100644 --- a/config/eslint/package.json +++ b/config/eslint/package.json @@ -18,7 +18,7 @@ "react/index.js" ], "dependencies": { - "@vercel/style-guide": "5.0.1", + "@vercel/style-guide": "6.0.0", "eslint-config-turbo": "2.0.5", "eslint-plugin-mdx": "2.2.0", "eslint-plugin-only-warn": "1.1.0", diff --git a/config/jest/README.md b/config/jest/README.md deleted file mode 100644 index 84cc59cb80..0000000000 --- a/config/jest/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Jest Config - -... diff --git a/config/jest/jest-preset.js b/config/jest/jest-preset.js deleted file mode 100644 index 546065f6dd..0000000000 --- a/config/jest/jest-preset.js +++ /dev/null @@ -1,19 +0,0 @@ -/** @type {import('ts-jest').JestConfigWithTsJest} */ -const jestConfig = { - verbose: true, - roots: [''], - - moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], - modulePathIgnorePatterns: [ - '/test/__fixtures__', - '/node_modules', - '/dist', - ], - testEnvironment: 'node', - preset: 'ts-jest', - transform: { - '^.+\\.tsx?$': ['ts-jest', { useESM: true }], - }, -} - -module.exports = jestConfig diff --git a/config/jest/node/jest-preset.js b/config/jest/node/jest-preset.js deleted file mode 100644 index 546065f6dd..0000000000 --- a/config/jest/node/jest-preset.js +++ /dev/null @@ -1,19 +0,0 @@ -/** @type {import('ts-jest').JestConfigWithTsJest} */ -const jestConfig = { - verbose: true, - roots: [''], - - moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], - modulePathIgnorePatterns: [ - '/test/__fixtures__', - '/node_modules', - '/dist', - ], - testEnvironment: 'node', - preset: 'ts-jest', - transform: { - '^.+\\.tsx?$': ['ts-jest', { useESM: true }], - }, -} - -module.exports = jestConfig diff --git a/config/jest/package.json b/config/jest/package.json deleted file mode 100644 index c2ce88dbb3..0000000000 --- a/config/jest/package.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "@sushiswap/jest-config", - "version": "0.0.0", - "private": true, - "description": "Sushi Jest Config", - "keywords": [ - "sushi", - "jest", - "config" - ], - "homepage": "https://www.sushi.com", - "repository": { - "type": "git", - "url": "https://github.com/sushiswap/sushiswap.git", - "directory": "packages/config/jest" - }, - "license": "MIT", - "author": "Matthew Lilley ", - "sideEffects": false, - "files": [ - "jest-preset.js" - ], - "dependencies": { - "jest-environment-jsdom": "29.7.0" - }, - "devDependencies": { - "@types/node": "20" - } -} diff --git a/config/nextjs/index.js b/config/nextjs/index.js index ec086789cd..bdf43a9316 100644 --- a/config/nextjs/index.js +++ b/config/nextjs/index.js @@ -16,7 +16,6 @@ const defaultNextConfig = { '@sushiswap/database', '@sushiswap/graph-client', '@sushiswap/hooks', - '@sushiswap/react-query', '@sushiswap/router', '@sushiswap/tines', '@sushiswap/ui', diff --git a/package.json b/package.json index f8212b5e53..e101e41cf8 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,6 @@ "private": true, "scripts": { "build": "dotenv -- turbo run build", - "changeset": "changeset", - "changeset:publish": "changeset publish", - "changeset:version": "changeset version && pnpm install --lockfile-only", "check": "turbo run check --no-cache", "clean": "turbo run clean && rm -rf node_modules", "dev": "dotenv -- turbo run dev --no-cache --parallel --continue", @@ -24,17 +21,12 @@ }, "devDependencies": { "@biomejs/biome": "1.5.2", - "@changesets/changelog-github": "0.4.8", - "@changesets/cli": "2.26.2", - "@types/jest": "29.5.5", "@types/node": "20", "dotenv-cli": "6.0.0", "eslint": "8.43.0", "eslint-config-turbo": "2.0.5", - "jest": "29.7.0", "just-pnpm": "1.0.2", "sort-package-json": "2.6.0", - "ts-jest": "29.1.1", "tsx": "4.19.0", "turbo": "2.0.5" }, diff --git a/packages/client/package.json b/packages/client/package.json index 3fc9337871..ca06697aa1 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -66,7 +66,7 @@ "@sushiswap/steer-sdk": "workspace:*", "@whatwg-node/fetch": "0.8.4", "deepmerge-ts": "^4.3.0", - "sushi": "4.0.2", + "sushi": "4.0.5", "tslib": "latest", "viem": "2.21.4", "zod": "3.23.8" diff --git a/packages/client/src/functions.ts b/packages/client/src/functions.ts index 0e6590a38b..b80d48a7d0 100644 --- a/packages/client/src/functions.ts +++ b/packages/client/src/functions.ts @@ -14,6 +14,15 @@ export function parseArgs(args?: Partial) { }, '?') } +function jsonParse(text: string): T { + return JSON.parse(text, (_key: string, value: any) => { + if (value && typeof value === 'object' && value.__type === 'bigint') { + value = BigInt(value.value) + } + return value + }) +} + export async function get(url: string): Promise { const res = await fetch(url) @@ -21,7 +30,7 @@ export async function get(url: string): Promise { throw new Error(`Failed to fetch ${url}: ${res.status} ${res.statusText}`) } - await import('sushi/bigint-serializer') + const text = await res.text() - return res.json() as T + return jsonParse(text) } diff --git a/packages/database/package.json b/packages/database/package.json index 922314b0ef..5bcd56c9e8 100644 --- a/packages/database/package.json +++ b/packages/database/package.json @@ -47,26 +47,19 @@ "prepublishOnly": "pnpm build", "pull": "prisma db pull", "push": "prisma db push --skip-generate", - "studio": "prisma studio", - "test": "jest --passWithNoTests" - }, - "jest": { - "preset": "@sushiswap/jest-config" + "studio": "prisma studio" }, "dependencies": { "@prisma/client": "5.6.0", "@prisma/extension-accelerate": "^0.6.2" }, "devDependencies": { - "@sushiswap/jest-config": "workspace:*", "@tsconfig/esm": "1.0.4", "@tsconfig/strictest": "2.0.2", - "@types/jest": "29.5.5", "@types/node": "20", "dotenv": "16.3.1", - "jest": "29.7.0", "prisma": "5.6.0", - "sushi": "4.0.2", + "sushi": "4.0.5", "typescript": "5.5.4" } } diff --git a/packages/graph-client/package.json b/packages/graph-client/package.json index b0147bca85..b2abaa4cbf 100644 --- a/packages/graph-client/package.json +++ b/packages/graph-client/package.json @@ -69,7 +69,7 @@ "graphql": "16.6.0", "graphql-request": "^7.0.1", "json-bigint": "^1.0.0", - "sushi": "4.0.2", + "sushi": "4.0.5", "viem": "2.21.4" }, "devDependencies": { diff --git a/packages/graph-client/src/subgraphs/data-api/queries/analytics/day-buckets.ts b/packages/graph-client/src/subgraphs/data-api/queries/analytics/day-buckets.ts index 92606fedc0..da6c994039 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/analytics/day-buckets.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/analytics/day-buckets.ts @@ -35,7 +35,7 @@ export async function getAnalyticsDayBuckets( variables: GetAnalyticsDayBuckets, options?: RequestOptions, ) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` try { const result = await request( { diff --git a/packages/graph-client/src/subgraphs/data-api/queries/features/chain-ids-by-feature.ts b/packages/graph-client/src/subgraphs/data-api/queries/features/chain-ids-by-feature.ts index 9358ee5c73..b047af60fa 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/features/chain-ids-by-feature.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/features/chain-ids-by-feature.ts @@ -19,7 +19,7 @@ export async function getChainIdsByFeature( variables: GetChainIdsByFeature, options?: RequestOptions, ) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` const result = await request( { url, diff --git a/packages/graph-client/src/subgraphs/data-api/queries/pool/pools.ts b/packages/graph-client/src/subgraphs/data-api/queries/pool/pools.ts index be176bd0ef..2e837ee28e 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/pool/pools.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/pool/pools.ts @@ -63,7 +63,7 @@ export const PoolsQuery = graphql( export type GetPools = VariablesOf export async function getPools(variables: GetPools, options?: RequestOptions) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` try { const result = await request( { diff --git a/packages/graph-client/src/subgraphs/data-api/queries/pool/top-evm-pools.ts b/packages/graph-client/src/subgraphs/data-api/queries/pool/top-evm-pools.ts index ff2ea1c68c..495a4e7758 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/pool/top-evm-pools.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/pool/top-evm-pools.ts @@ -47,7 +47,7 @@ export async function getTopPools( variables: GetTopPools, options?: RequestOptions, ) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` try { if (!isChainId(parseInt(variables.chainId))) { throw new Error( diff --git a/packages/graph-client/src/subgraphs/data-api/queries/pool/top-non-evm-pools.ts b/packages/graph-client/src/subgraphs/data-api/queries/pool/top-non-evm-pools.ts index c2c282483d..7548ae1039 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/pool/top-non-evm-pools.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/pool/top-non-evm-pools.ts @@ -46,7 +46,7 @@ export async function getTopNonEvmPools( variables: GetTopNonEvmPools, options?: RequestOptions, ) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` try { const result = await request( { diff --git a/packages/graph-client/src/subgraphs/data-api/queries/pool/v2-pool.ts b/packages/graph-client/src/subgraphs/data-api/queries/pool/v2-pool.ts index 1aaad48092..996f8aadb7 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/pool/v2-pool.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/pool/v2-pool.ts @@ -92,7 +92,7 @@ export async function getV2Pool( variables: GetV2Pool, options?: RequestOptions, ) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` const chainId = Number(variables.chainId) as ChainId if (!isSushiSwapV2ChainId(chainId)) { diff --git a/packages/graph-client/src/subgraphs/data-api/queries/pool/v3-pool.ts b/packages/graph-client/src/subgraphs/data-api/queries/pool/v3-pool.ts index 2dbd8b7840..4b7ccc092e 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/pool/v3-pool.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/pool/v3-pool.ts @@ -101,7 +101,7 @@ export async function getV3Pool( variables: GetV3Pool, options?: RequestOptions, ) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` const chainId = Number(variables.chainId) as ChainId if (!isSushiSwapV3ChainId(chainId)) { diff --git a/packages/graph-client/src/subgraphs/data-api/queries/portfolio/portfolio-claimables.ts b/packages/graph-client/src/subgraphs/data-api/queries/portfolio/portfolio-claimables.ts index 1536041d9c..0cdf14a38b 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/portfolio/portfolio-claimables.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/portfolio/portfolio-claimables.ts @@ -204,7 +204,7 @@ export async function getPortfolioClaimables( variables: GetPortfolioClaimables, options?: RequestOptions, ) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` const result = await request( { url, document: PortfolioClaimablesQuery, variables }, diff --git a/packages/graph-client/src/subgraphs/data-api/queries/portfolio/portfolio-history.ts b/packages/graph-client/src/subgraphs/data-api/queries/portfolio/portfolio-history.ts index dbcb7f49ea..108599635b 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/portfolio/portfolio-history.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/portfolio/portfolio-history.ts @@ -65,7 +65,7 @@ export async function getPortfolioHistory( variables: GetPortfolioHistory, options?: RequestOptions, ) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` const result = await request( { url, document: PortfolioHistoryQuery, variables }, diff --git a/packages/graph-client/src/subgraphs/data-api/queries/portfolio/portfolio-positions.ts b/packages/graph-client/src/subgraphs/data-api/queries/portfolio/portfolio-positions.ts index 3cd0e7e82c..84bdad29ad 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/portfolio/portfolio-positions.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/portfolio/portfolio-positions.ts @@ -184,7 +184,7 @@ export async function getPortfolioPositions( variables: GetPortfolioPositions, options?: RequestOptions, ) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` const result = await request( { url, document: PortfolioPositionsQuery, variables }, diff --git a/packages/graph-client/src/subgraphs/data-api/queries/portfolio/portfolio-wallet.ts b/packages/graph-client/src/subgraphs/data-api/queries/portfolio/portfolio-wallet.ts index 3d7f87d580..efe3f21dab 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/portfolio/portfolio-wallet.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/portfolio/portfolio-wallet.ts @@ -41,7 +41,7 @@ export async function getPortfolioWallet( variables: GetPortfolioWallet, options?: RequestOptions, ) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` const result = await request( { url, document: PortfolioWalletQuery, variables }, diff --git a/packages/graph-client/src/subgraphs/data-api/queries/smart-pool/smart-pools.ts b/packages/graph-client/src/subgraphs/data-api/queries/smart-pool/smart-pools.ts index 25d2ddfa0d..50b74f5f82 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/smart-pool/smart-pools.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/smart-pool/smart-pools.ts @@ -61,7 +61,7 @@ export async function getSmartPools( variables: GetSmartPools, options?: RequestOptions, ) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` const result = await request( { diff --git a/packages/graph-client/src/subgraphs/data-api/queries/smart-pool/vault.ts b/packages/graph-client/src/subgraphs/data-api/queries/smart-pool/vault.ts index 93d548b497..f914c9a60d 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/smart-pool/vault.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/smart-pool/vault.ts @@ -68,7 +68,7 @@ export const VaultQuery = graphql( export type GetVault = VariablesOf export async function getVault(variables: GetVault, options?: RequestOptions) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` try { const result = await request( { diff --git a/packages/graph-client/src/subgraphs/data-api/queries/smart-pool/vaults.ts b/packages/graph-client/src/subgraphs/data-api/queries/smart-pool/vaults.ts index a6def2e5f0..1a57c15b2c 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/smart-pool/vaults.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/smart-pool/vaults.ts @@ -72,7 +72,7 @@ export async function getVaults( variables: GetVaults, options?: RequestOptions, ) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` const result = await request( { diff --git a/packages/graph-client/src/subgraphs/data-api/queries/sushi-bar/history.ts b/packages/graph-client/src/subgraphs/data-api/queries/sushi-bar/history.ts index 4e9b593dc9..34130315e7 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/sushi-bar/history.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/sushi-bar/history.ts @@ -47,10 +47,15 @@ export async function getSushiBarHistory( variables: GetSushiBarHistory, options?: RequestOptions, ) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` const result = await request( - { url, document: SushiBarHistory, variables, requestHeaders: SUSHI_REQUEST_HEADERS }, + { + url, + document: SushiBarHistory, + variables, + requestHeaders: SUSHI_REQUEST_HEADERS, + }, options, ) if (result) { diff --git a/packages/graph-client/src/subgraphs/data-api/queries/sushi-bar/stats.ts b/packages/graph-client/src/subgraphs/data-api/queries/sushi-bar/stats.ts index eddd09de3d..13451362b8 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/sushi-bar/stats.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/sushi-bar/stats.ts @@ -30,10 +30,15 @@ export async function getSushiBarStats( variables: GetSushiBarStats, options?: RequestOptions, ) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` const result = await request( - { url, document: SushiBarStats, variables, requestHeaders: SUSHI_REQUEST_HEADERS }, + { + url, + document: SushiBarStats, + variables, + requestHeaders: SUSHI_REQUEST_HEADERS, + }, options, ) if (result) { diff --git a/packages/graph-client/src/subgraphs/data-api/queries/token-list/token-list-balances.ts b/packages/graph-client/src/subgraphs/data-api/queries/token-list/token-list-balances.ts index 0f5af72b70..9ef56b1e50 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/token-list/token-list-balances.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/token-list/token-list-balances.ts @@ -29,7 +29,7 @@ export async function getTokenListBalances( variables: GetTokenListBalances, options?: RequestOptions, ) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` const result = await request( { diff --git a/packages/graph-client/src/subgraphs/data-api/queries/token-list/token-list.ts b/packages/graph-client/src/subgraphs/data-api/queries/token-list/token-list.ts index 209bf760e9..0083ffa3b2 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/token-list/token-list.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/token-list/token-list.ts @@ -28,7 +28,7 @@ export async function getTokenList( variables: GetTokenList, options?: RequestOptions, ) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` const result = await request( { diff --git a/packages/graph-client/src/subgraphs/data-api/queries/trending-tokens/trending-tokens.ts b/packages/graph-client/src/subgraphs/data-api/queries/trending-tokens/trending-tokens.ts index 31f1933e96..85075ba5de 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/trending-tokens/trending-tokens.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/trending-tokens/trending-tokens.ts @@ -28,7 +28,7 @@ export async function getTrendingTokens( variables: GetTrendingTokens, options?: RequestOptions, ) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` const result = await request( { diff --git a/packages/graph-client/src/subgraphs/data-api/queries/v2/buckets.ts b/packages/graph-client/src/subgraphs/data-api/queries/v2/buckets.ts index b385b4c437..c908733882 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/v2/buckets.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/v2/buckets.ts @@ -37,7 +37,7 @@ export async function getV2PoolBuckets( variables: GetV2PoolBuckets, options?: RequestOptions, ) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` const chainId = Number(variables.chainId) as ChainId if (!isSushiSwapV2ChainId(chainId)) { diff --git a/packages/graph-client/src/subgraphs/data-api/queries/v2/burns.ts b/packages/graph-client/src/subgraphs/data-api/queries/v2/burns.ts index acc9818e68..05a3acb4ec 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/v2/burns.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/v2/burns.ts @@ -29,7 +29,7 @@ export async function getSushiV2Burns( { ...variables }: GetSushiV2Burns, options?: RequestOptions, ) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` const result = await request( { url, document: SushiV2BurnsQuery, variables }, diff --git a/packages/graph-client/src/subgraphs/data-api/queries/v2/mints.ts b/packages/graph-client/src/subgraphs/data-api/queries/v2/mints.ts index 1e5bca7ff4..2f86b2c6e0 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/v2/mints.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/v2/mints.ts @@ -29,7 +29,7 @@ export async function getSushiV2Mints( { ...variables }: GetSushiV2Mints, options?: RequestOptions, ) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` const result = await request( { url, document: SushiV2MintsQuery, variables }, diff --git a/packages/graph-client/src/subgraphs/data-api/queries/v2/positions.ts b/packages/graph-client/src/subgraphs/data-api/queries/v2/positions.ts index e90d8f77a3..9c34105ee1 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/v2/positions.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/v2/positions.ts @@ -74,7 +74,7 @@ export async function getV2Positions( variables: GetV2Positions, options?: RequestOptions, ) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` const chainId = Number(variables.chainId) as ChainId if (!isSushiSwapV2ChainId(chainId)) { diff --git a/packages/graph-client/src/subgraphs/data-api/queries/v2/swaps.ts b/packages/graph-client/src/subgraphs/data-api/queries/v2/swaps.ts index dc408d02af..045b712e6c 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/v2/swaps.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/v2/swaps.ts @@ -31,7 +31,7 @@ export async function getSushiV2Swaps( { ...variables }: GetSushiV2Swaps, options?: RequestOptions, ) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` const result = await request( { url, document: SushiV2SwapsQuery, variables }, diff --git a/packages/graph-client/src/subgraphs/data-api/queries/v3/buckets.ts b/packages/graph-client/src/subgraphs/data-api/queries/v3/buckets.ts index 75280101c4..3ca4986a22 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/v3/buckets.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/v3/buckets.ts @@ -37,7 +37,7 @@ export async function getV3PoolBuckets( variables: GetV3PoolBuckets, options?: RequestOptions, ) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` const chainId = Number(variables.chainId) as ChainId if (!isSushiSwapV3ChainId(chainId)) { diff --git a/packages/graph-client/src/subgraphs/data-api/queries/v3/burns.ts b/packages/graph-client/src/subgraphs/data-api/queries/v3/burns.ts index 2158838aee..084213e571 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/v3/burns.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/v3/burns.ts @@ -30,7 +30,7 @@ export async function getSushiV3Burns( { ...variables }: GetSushiV3Burns, options?: RequestOptions, ) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` const result = await request( { url, document: SushiV3BurnsQuery, variables }, diff --git a/packages/graph-client/src/subgraphs/data-api/queries/v3/collects.ts b/packages/graph-client/src/subgraphs/data-api/queries/v3/collects.ts index caac31bb78..d921957e7b 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/v3/collects.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/v3/collects.ts @@ -28,7 +28,7 @@ export async function getSushiV3Collects( { ...variables }: GetSushiV3Collects, options?: RequestOptions, ) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` const result = await request( { url, document: SushiV3CollectsQuery, variables }, diff --git a/packages/graph-client/src/subgraphs/data-api/queries/v3/mints.ts b/packages/graph-client/src/subgraphs/data-api/queries/v3/mints.ts index c1f46a6569..2675975bca 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/v3/mints.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/v3/mints.ts @@ -31,7 +31,7 @@ export async function getSushiV3Mints( { ...variables }: GetSushiV3Mints, options?: RequestOptions, ) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` const result = await request( { url, document: SushiV3MintsQuery, variables }, diff --git a/packages/graph-client/src/subgraphs/data-api/queries/v3/pools-by-tokens.ts b/packages/graph-client/src/subgraphs/data-api/queries/v3/pools-by-tokens.ts index 09ab71aa80..014e9dcca8 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/v3/pools-by-tokens.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/v3/pools-by-tokens.ts @@ -61,7 +61,7 @@ export async function getV3BasePoolsByToken( variables: GetV3BasePoolsByTokens, options?: RequestOptions, ): Promise[]> { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` const chainId = variables.chainId as ChainId if (!isSushiSwapV3ChainId(chainId)) { diff --git a/packages/graph-client/src/subgraphs/data-api/queries/v3/pools.ts b/packages/graph-client/src/subgraphs/data-api/queries/v3/pools.ts index 2aa7b2d998..e992a1b3e7 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/v3/pools.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/v3/pools.ts @@ -62,7 +62,7 @@ export async function getV3BasePools( variables: GetV3BasePools, options?: RequestOptions, ): Promise[]> { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` const chainId = variables.chainId as ChainId if (!isSushiSwapV3ChainId(chainId)) { diff --git a/packages/graph-client/src/subgraphs/data-api/queries/v3/swaps.ts b/packages/graph-client/src/subgraphs/data-api/queries/v3/swaps.ts index adcc1c66c1..e127572e86 100644 --- a/packages/graph-client/src/subgraphs/data-api/queries/v3/swaps.ts +++ b/packages/graph-client/src/subgraphs/data-api/queries/v3/swaps.ts @@ -30,7 +30,7 @@ export async function getSushiV3Swaps( { ...variables }: GetSushiV3Swaps, options?: RequestOptions, ) { - const url = `https://${SUSHI_DATA_API_HOST}` + const url = `${SUSHI_DATA_API_HOST}/graphql` const result = await request( { url, document: SushiV3SwapsQuery, variables }, diff --git a/packages/hooks/package.json b/packages/hooks/package.json index d785c6cb46..ff3d20496e 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -33,11 +33,7 @@ "build": "tsc", "check": "tsc --pretty --noEmit", "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist", - "dev": "tsc -w", - "test": "jest --passWithNoTests" - }, - "jest": { - "preset": "@sushiswap/jest-config" + "dev": "tsc -w" }, "dependencies": { "copy-to-clipboard": "3.3.3", @@ -45,16 +41,13 @@ "viem": "2.21.4" }, "devDependencies": { - "@sushiswap/jest-config": "workspace:*", "@tsconfig/node20": "20.1.4", "@tsconfig/strictest": "2.0.2", - "@types/jest": "29.5.5", "@types/react": "18.2.14", "@types/react-dom": "18.2.6", - "jest": "29.7.0", "react": "18.2.0", "react-dom": "18.2.0", - "sushi": "4.0.2", + "sushi": "4.0.5", "tailwindcss": "3.3.2", "typescript": "5.5.4" }, diff --git a/packages/notifications/package.json b/packages/notifications/package.json index ac9a5ca0a0..b04713a2a5 100644 --- a/packages/notifications/package.json +++ b/packages/notifications/package.json @@ -40,8 +40,7 @@ "build": "tsc", "check": "tsc --pretty --noEmit", "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist", - "dev": "tsc --watch", - "test": "jest --passWithNoTests" + "dev": "tsc --watch" }, "dependencies": { "@heroicons/react": "2.0.13", @@ -55,7 +54,7 @@ "@tsconfig/strictest": "2.0.2", "@types/react": "18.2.14", "@types/react-dom": "18.2.6", - "sushi": "4.0.2", + "sushi": "4.0.5", "typescript": "5.5.4" }, "peerDependencies": { diff --git a/packages/react-query/README.md b/packages/react-query/README.md deleted file mode 100644 index d780d75985..0000000000 --- a/packages/react-query/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# React Query - -React Query library diff --git a/packages/react-query/package.json b/packages/react-query/package.json deleted file mode 100644 index 73fd67c2d7..0000000000 --- a/packages/react-query/package.json +++ /dev/null @@ -1,105 +0,0 @@ -{ - "name": "@sushiswap/react-query", - "version": "0.0.0", - "private": true, - "description": "Sushi React Query", - "keywords": [ - "sushi", - "react", - "query" - ], - "homepage": "https://www.sushi.com", - "repository": { - "type": "git", - "url": "https://github.com/sushiswap/sushiswap.git", - "directory": "packages/abi" - }, - "license": "MIT", - "author": "Matthew Lilley ", - "sideEffects": true, - "type": "module", - "exports": { - ".": "./dist/index.js", - "./*": [ - "./dist/*.js", - "./dist/*/index.js" - ] - }, - "typesVersions": { - "*": { - "*": [ - "src/*", - "src/*/index" - ] - } - }, - "files": [ - "dist" - ], - "scripts": { - "build": "tsc", - "check": "tsc --pretty --noEmit", - "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist", - "dev": "tsc --watch", - "test": "jest --passWithNoTests" - }, - "dependencies": { - "@sushiswap/hooks": "workspace:*", - "@sushiswap/telemetry": "workspace:*", - "@tanstack/react-query": "5.51.16", - "@tanstack/react-query-devtools": "4.28.0", - "ms": "2.1.3", - "nanoid": "4.0.0", - "zod": "3.23.8" - }, - "devDependencies": { - "@sentry/nextjs": "8.30.0", - "@sushiswap/client": "workspace:*", - "@sushiswap/database": "workspace:*", - "@sushiswap/graph-client": "workspace:*", - "@sushiswap/jest-config": "workspace:*", - "@tsconfig/node20": "20.1.4", - "@tsconfig/strictest": "2.0.2", - "@types/ms": "0.7.34", - "@types/react": "18.2.14", - "@types/react-dom": "18.2.6", - "jest": "29.7.0", - "next": "14.2.11", - "react": "18.2.0", - "react-dom": "18.2.0", - "sushi": "4.0.2", - "typescript": "5.5.4", - "viem": "2.21.4", - "wagmi": "2.12.10" - }, - "peerDependencies": { - "@sentry/nextjs": "8.30.0", - "@sushiswap/client": "*", - "next": "14.2.11", - "react": "18.2.0", - "react-dom": "18.2.0", - "sushi": "*", - "viem": "2.21.4", - "wagmi": "2.12.10" - }, - "peerDependenciesMeta": { - "@sushiswap/client": { - "optional": true - }, - "react": { - "optional": false - }, - "react-dom": { - "optional": false - }, - "sushi": { - "optional": true - }, - "viem": { - "optional": true - }, - "wagmi": { - "optional": true - } - } -} diff --git a/packages/react-query/src/hooks/prices/index.ts b/packages/react-query/src/hooks/prices/index.ts deleted file mode 100644 index 3fc3887546..0000000000 --- a/packages/react-query/src/hooks/prices/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './useAllPrices' -export * from './usePrice' -export * from './usePrices' diff --git a/packages/react-query/src/hooks/prices/usePrice.ts b/packages/react-query/src/hooks/prices/usePrice.ts deleted file mode 100644 index 9818227299..0000000000 --- a/packages/react-query/src/hooks/prices/usePrice.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { useMemo } from 'react' -import type { Fraction } from 'sushi' -import { Address } from 'viem' -import { usePrices } from './usePrices' - -interface UsePrice { - chainId: number | undefined - address: Address | undefined - enabled?: boolean -} - -export const usePrice = ({ chainId, address, enabled = true }: UsePrice) => { - const usePricesQuery = usePrices({ - chainId, - enabled, - }) - - return useMemo(() => { - return { - ...usePricesQuery, - data: (address ? usePricesQuery.data?.get(address) : undefined) as - | Fraction - | undefined, - } - }, [usePricesQuery, address]) -} diff --git a/packages/react-query/src/hooks/prices/usePrices.ts b/packages/react-query/src/hooks/prices/usePrices.ts deleted file mode 100644 index 52a1bedc82..0000000000 --- a/packages/react-query/src/hooks/prices/usePrices.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { useQuery } from '@tanstack/react-query' -import ms from 'ms' -import { LowercaseMap } from 'sushi' -import { API_BASE_URL } from 'sushi/config' -import { withoutScientificNotation } from 'sushi/format' -import { Fraction } from 'sushi/math' -import { Address, parseUnits } from 'viem' - -interface UsePrices { - chainId: number | undefined - enabled?: boolean -} - -export const usePrices = ({ chainId, enabled = true }: UsePrices) => { - return useQuery({ - queryKey: [`${API_BASE_URL}/price/v1/${chainId}`], - queryFn: async () => { - const data: Record = await fetch( - `${API_BASE_URL}/price/v1/${chainId}`, - ).then((response) => response.json()) - - const priceMap = new LowercaseMap() - - Object.entries(data).forEach(([address, _price]) => { - const price = withoutScientificNotation(_price.toFixed(18)) - if (typeof price !== 'undefined') { - priceMap.set( - address as Address, - new Fraction( - parseUnits(price, 18).toString(), - parseUnits('1', 18).toString(), - ), - ) - } - }) - - return priceMap - }, - staleTime: ms('15s'), - gcTime: ms('1m'), - enabled: Boolean(chainId && enabled), - }) -} diff --git a/packages/react-query/src/index.ts b/packages/react-query/src/index.ts deleted file mode 100644 index 3257c155c9..0000000000 --- a/packages/react-query/src/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -import * as Sentry from '@sentry/nextjs' -import { - QueryCache, - QueryClient, - type QueryClientConfig, -} from '@tanstack/react-query' - -const queryClientConfig = { - defaultOptions: { - queries: { - gcTime: 1000 * 60 * 60 * 24, // 24 hours - }, - }, - queryCache: new QueryCache({ - onError: (error, query) => { - if (error instanceof Error) { - if (error.name === 'ConnectorNotConnectedError') return - } - Sentry.captureException(error, { data: { query } }) - }, - }), -} - -export const createQueryClient = ( - config: QueryClientConfig | undefined = queryClientConfig, -) => { - return new QueryClient(config) -} - -export * from './hooks' diff --git a/packages/react-query/tsconfig.json b/packages/react-query/tsconfig.json deleted file mode 100644 index e60d4ad8df..0000000000 --- a/packages/react-query/tsconfig.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "extends": [ - "@tsconfig/strictest/tsconfig", - "@tsconfig/node20/tsconfig" - ], - "include": [ - "src" - ], - "exclude": [ - "node_modules", - "dist", - ".turbo" - ], - "compilerOptions": { - "rootDir": "./src", - "outDir": "./dist", - "jsx": "react-jsx", - "lib": [ - "ESNext", - "DOM" - ], - "module": "ESNext", - "moduleResolution": "Bundler", - "target": "ESNext", - "sourceMap": true, - "declaration": true, - "declarationMap": true - } -} \ No newline at end of file diff --git a/packages/steer-sdk/package.json b/packages/steer-sdk/package.json index 8faadda0d4..4284b447ce 100644 --- a/packages/steer-sdk/package.json +++ b/packages/steer-sdk/package.json @@ -55,7 +55,7 @@ "dependencies": { "@steerprotocol/contracts": "2.1.0-beta.14", "@sushiswap/database": "workspace:*", - "sushi": "4.0.2", + "sushi": "4.0.5", "tslib": "latest", "viem": "2.21.4" }, diff --git a/packages/steer-sdk/src/utils/getSteerTokenRatios.ts b/packages/steer-sdk/src/utils/getSteerTokenRatios.ts index f6aa137a27..9c892a4cff 100644 --- a/packages/steer-sdk/src/utils/getSteerTokenRatios.ts +++ b/packages/steer-sdk/src/utils/getSteerTokenRatios.ts @@ -1,4 +1,4 @@ -import { getAddress } from 'viem' +import { type Address } from 'viem' import type { SteerVault } from '../types/steer-vault' interface GetTokenRatiosProps { @@ -6,12 +6,12 @@ interface GetTokenRatiosProps { SteerVault, 'chainId' | 'token0' | 'token1' | 'reserve0' | 'reserve1' > - prices: Record + prices: Pick, 'get' | 'has'> } async function getTokenRatios({ vault, prices }: GetTokenRatiosProps) { - const token0PriceUSD = prices[getAddress(vault.token0.address)] || 0 - const token1PriceUSD = prices[getAddress(vault.token1.address)] || 0 + const token0PriceUSD = prices.get(vault.token0.address) || 0 + const token1PriceUSD = prices.get(vault.token1.address) || 0 const reserve0 = Number(vault.reserve0) / 10 ** vault.token0.decimals const reserve1 = Number(vault.reserve1) / 10 ** vault.token1.decimals diff --git a/packages/telemetry/package.json b/packages/telemetry/package.json index 072ae28407..bc2490740d 100644 --- a/packages/telemetry/package.json +++ b/packages/telemetry/package.json @@ -38,8 +38,7 @@ "build": "tsc", "check": "tsc --pretty --noEmit", "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist", - "dev": "tsc --watch", - "test": "jest --passWithNoTests" + "dev": "tsc --watch" }, "devDependencies": { "@tsconfig/esm": "1.0.4", diff --git a/packages/ui/package.json b/packages/ui/package.json index 3b1bec86e7..f95a5cc572 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -49,8 +49,7 @@ "build": "tsc", "check": "tsc --pretty --noEmit", "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist", - "dev": "tsc --watch", - "test": "jest --passWithNoTests" + "dev": "tsc --watch" }, "dependencies": { "@fontsource-variable/inter": "5.0.1", @@ -79,7 +78,6 @@ "@radix-ui/react-tooltip": "1.0.6", "@react-hook/window-scroll": "1.3.0", "@sushiswap/hooks": "workspace:*", - "@sushiswap/react-query": "workspace:*", "@sushiswap/tailwindcss-config": "workspace:*", "@sushiswap/telemetry": "workspace:*", "@tailwindcss/aspect-ratio": "0.4.2", @@ -106,7 +104,6 @@ "use-resize-observer": "9.1.0" }, "devDependencies": { - "@sushiswap/jest-config": "workspace:*", "@sushiswap/typescript-config": "workspace:*", "@types/gtag.js": "0.0.19", "@types/react": "18.2.14", @@ -119,7 +116,7 @@ "postcss": "8.4.23", "react": "18.2.0", "react-dom": "18.2.0", - "sushi": "4.0.2", + "sushi": "4.0.5", "tailwindcss": "3.3.2", "typescript": "5.5.4", "wagmi": "2.12.10" diff --git a/packages/ui/src/components/global-footer.tsx b/packages/ui/src/components/global-footer.tsx index 50178dbe4e..77023f1058 100644 --- a/packages/ui/src/components/global-footer.tsx +++ b/packages/ui/src/components/global-footer.tsx @@ -220,7 +220,7 @@ const Component = ({ children, maxWidth = '5xl', ...props }: FooterProps) => {
    Terms of Use diff --git a/packages/ui/src/components/scripts.tsx b/packages/ui/src/components/scripts.tsx index 32f56249a8..2ae417977a 100644 --- a/packages/ui/src/components/scripts.tsx +++ b/packages/ui/src/components/scripts.tsx @@ -2,7 +2,9 @@ import Script from 'next/script' -export const GoogleAnalytics = () => { +export const GoogleAnalytics = ({ enabled }: { enabled: boolean }) => { + if (!enabled) return null + return ( <>