diff --git a/README.md b/README.md index fad48e40..4621b171 100644 --- a/README.md +++ b/README.md @@ -126,8 +126,8 @@ export NANONETS_API_KEY="..." export OPENAI_API_KEY="..." # SUPABASE, used to store file content after it's read once: https://supabase.com/ -export NEXT_PUBLIC_SUPABASE_URL="..." -export NEXT_PUBLIC_SUPABASE_ANON_KEY="..." +export SUPABASE_URL="..." +export SUPABASE_ANON_KEY="..." # DROPBOX, used for the Dropbox Sign API features: https://developers.hellosign.com/api/reference/signature-request/ export DROPBOX_CLIENT_ID="..." diff --git a/app/.eslintrc.js b/app/.eslintrc.js index 8790b6a9..85c3e14e 100644 --- a/app/.eslintrc.js +++ b/app/.eslintrc.js @@ -169,6 +169,7 @@ module.exports = { "unicorn/no-array-reduce": "off", "unicorn/consistent-destructuring": "off", "unicorn/no-array-for-each": "off", + "unicorn/no-abusive-eslint-disable": "off", // a11y "jsx-a11y/anchor-is-valid": "off", diff --git a/app/.npmrc b/app/.npmrc new file mode 100644 index 00000000..cd2efafd --- /dev/null +++ b/app/.npmrc @@ -0,0 +1,2 @@ +@aufacicenta:registry=https://npm.pkg.github.com +//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN} \ No newline at end of file diff --git a/app/next.config.js b/app/next.config.js index 58d94477..eec885bc 100644 --- a/app/next.config.js +++ b/app/next.config.js @@ -17,14 +17,6 @@ module.exports = { eslint: { ignoreDuringBuilds: true, }, - async headers() { - return [ - { - source: "/api/:path*", - headers: [{ key: "Access-Control-Allow-Origin", value: process.env.NEXT_PUBLIC_ORIGIN }], - }, - ]; - }, webpack: (config) => { const oneOf = config.module.rules.find((rule) => typeof rule.oneOf === "object"); diff --git a/app/package.json b/app/package.json index d743b7b2..3dcf2ade 100644 --- a/app/package.json +++ b/app/package.json @@ -17,85 +17,53 @@ "plop": "plop" }, "dependencies": { - "@dropbox/sign": "^1.1.3", - "@google-cloud/aiplatform": "^3.2.0", - "@near-wallet-selector/coin98-wallet": "^8.5.1", - "@near-wallet-selector/core": "^8.5.1", - "@near-wallet-selector/here-wallet": "^8.5.1", - "@near-wallet-selector/ledger": "^8.5.1", - "@near-wallet-selector/math-wallet": "^8.5.1", - "@near-wallet-selector/meteor-wallet": "^8.5.1", - "@near-wallet-selector/modal-ui": "^8.5.1", - "@near-wallet-selector/my-near-wallet": "^8.5.1", - "@near-wallet-selector/near-wallet": "^8.5.1", - "@near-wallet-selector/nearfi": "^8.5.1", - "@near-wallet-selector/nightly": "^8.5.1", - "@near-wallet-selector/nightly-connect": "^8.5.1", - "@near-wallet-selector/sender": "^8.5.1", - "@near-wallet-selector/wallet-connect": "^8.5.1", "@popperjs/core": "^2.11.5", - "@radix-ui/react-accordion": "^1.1.2", - "@radix-ui/react-dialog": "^1.0.5", - "@radix-ui/react-dropdown-menu": "^2.0.6", - "@radix-ui/react-icons": "^1.3.0", "@supabase/supabase-js": "^2.33.1", + "@tanstack/react-query": "^5.29.0", "@types/js-cookie": "^3.0.3", + "@wagmi/core": "^2.6.17", + "@web3modal/siwe": "^4.1.5", + "@web3modal/wagmi": "^4.1.5", "ag-grid-community": "^27.3.0", "ag-grid-react": "^27.3.0", "axios": "^1.5.0", - "bn.js": "^5.2.0", - "chart.js": "^3.8.2", - "chartjs-adapter-moment": "^1.0.0", - "class-variance-authority": "^0.7.0", "clsx": "^2.0.0", "dropzone": "^6.0.0-beta.2", - "filesize": "^10.1.0", + "eslint-config-next": "^14.2.1", + "ethers": "^6.12.0", "final-form": "^4.20.4", "final-form-arrays": "^3.0.2", - "highlight.js": "^11.9.0", "ipfs-http-client": "^60.0.1", - "jimp": "^0.22.8", "js-cookie": "^3.0.5", "lodash": "^4.17.21", - "marked": "^9.1.2", - "marked-highlight": "^2.0.6", "materialize-css": "^1.0.0-rc.2", "moment": "^2.29.1", - "near-api-js": "^2.1.4", - "next": "12.2.0", + "next": "^14.2.1", "next-i18next": "^8.2.0", - "openai": "^4.3.1", "react": "^18.2.0", - "react-countdown": "^2.3.5", "react-dom": "^18.2.0", "react-final-form": "^6.5.7", "react-final-form-arrays": "^3.1.3", "react-final-form-listeners": "^1.0.3", - "react-grid-system": "^7.1.2", + "react-grid-system": "^8.2.0", "react-popper": "^2.2.5", "react-transition-group": "^4.4.1", - "replicate": "^0.12.3", "rxjs": "^7.8.1", - "square": "^30.0.0", - "tailwind-merge": "^1.14.0", - "tailwindcss-animate": "^1.0.7", + "siwe": "^2.1.4", "uuid": "^9.0.0", + "viem": "^2.9.20", + "wagmi": "^2.5.19", "winston": "^3.9.0", "ws": "^8.13.0" }, "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/dropzone": "^5.7.4", "@types/lodash": "^4.14.177", "@types/node": "^14.14.35", - "@types/node-cron": "^3.0.8", - "@types/pixelmatch": "^5.2.4", - "@types/react": "^17.0.3", - "@types/react-dom": "^17.0.9", + "@types/react": "^18.2.79", + "@types/react-dom": "^18.2.25", "@types/react-final-form-listeners": "^1.0.0", "@types/react-transition-group": "^4.4.3", "@types/uuid": "^8.3.4", - "@types/ws": "^8.5.5", "autoprefixer": "^10.4.16", "eslint-plugin-unused-imports": "^2.0.0", "inquirer-directory": "^2.2.0", @@ -103,7 +71,6 @@ "postcss": "^8.4.31", "sass": "^1.63.6", "sass-loader": "^12.3.0", - "tailwindcss": "^3.3.3", "tslib": "^2.6.2", "typed-scss-modules": "^4.1.1", "typescript": "^5.2.2" diff --git a/app/postcss.config.js b/app/postcss.config.js deleted file mode 100644 index 12a703d9..00000000 --- a/app/postcss.config.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -}; diff --git a/app/public/favicon.ico b/app/public/favicon.ico index abdee927..50a7bcc8 100644 Binary files a/app/public/favicon.ico and b/app/public/favicon.ico differ diff --git a/app/public/fonts/PPNeueMachina-InktrapRegular.otf b/app/public/fonts/PPNeueMachina-InktrapRegular.otf new file mode 100644 index 00000000..d45a16e4 Binary files /dev/null and b/app/public/fonts/PPNeueMachina-InktrapRegular.otf differ diff --git a/app/public/fonts/PPNeueMachina-InktrapRegular.ttf b/app/public/fonts/PPNeueMachina-InktrapRegular.ttf new file mode 100644 index 00000000..5498da9b Binary files /dev/null and b/app/public/fonts/PPNeueMachina-InktrapRegular.ttf differ diff --git a/app/public/fonts/PPNeueMachina-InktrapRegular.woff b/app/public/fonts/PPNeueMachina-InktrapRegular.woff new file mode 100644 index 00000000..b08c2e5d Binary files /dev/null and b/app/public/fonts/PPNeueMachina-InktrapRegular.woff differ diff --git a/app/public/fonts/PPNeueMachina-InktrapRegular.woff2 b/app/public/fonts/PPNeueMachina-InktrapRegular.woff2 new file mode 100644 index 00000000..cbbbcbb4 Binary files /dev/null and b/app/public/fonts/PPNeueMachina-InktrapRegular.woff2 differ diff --git a/app/public/fonts/PPNeueMachina-InktrapSemibold.otf b/app/public/fonts/PPNeueMachina-InktrapSemibold.otf new file mode 100644 index 00000000..341c1581 Binary files /dev/null and b/app/public/fonts/PPNeueMachina-InktrapSemibold.otf differ diff --git a/app/public/fonts/PPNeueMachina-InktrapSemibold.ttf b/app/public/fonts/PPNeueMachina-InktrapSemibold.ttf new file mode 100644 index 00000000..6f2bc3c6 Binary files /dev/null and b/app/public/fonts/PPNeueMachina-InktrapSemibold.ttf differ diff --git a/app/public/fonts/PPNeueMachina-InktrapSemibold.woff b/app/public/fonts/PPNeueMachina-InktrapSemibold.woff new file mode 100644 index 00000000..c5dc10db Binary files /dev/null and b/app/public/fonts/PPNeueMachina-InktrapSemibold.woff differ diff --git a/app/public/fonts/PPNeueMachina-InktrapSemibold.woff2 b/app/public/fonts/PPNeueMachina-InktrapSemibold.woff2 new file mode 100644 index 00000000..553759ef Binary files /dev/null and b/app/public/fonts/PPNeueMachina-InktrapSemibold.woff2 differ diff --git a/app/public/icons/icomoon.eot b/app/public/icons/icomoon.eot index e58c9479..e2143c67 100644 Binary files a/app/public/icons/icomoon.eot and b/app/public/icons/icomoon.eot differ diff --git a/app/public/icons/icomoon.svg b/app/public/icons/icomoon.svg index b53d4f06..301c10eb 100644 --- a/app/public/icons/icomoon.svg +++ b/app/public/icons/icomoon.svg @@ -7,7 +7,6 @@ - @@ -81,7 +80,7 @@ - + @@ -291,7 +290,7 @@ - + @@ -1010,14 +1009,6 @@ - - - - - - - - - - + + \ No newline at end of file diff --git a/app/public/icons/icomoon.ttf b/app/public/icons/icomoon.ttf index 771a2e59..bd863c23 100644 Binary files a/app/public/icons/icomoon.ttf and b/app/public/icons/icomoon.ttf differ diff --git a/app/public/icons/icomoon.woff b/app/public/icons/icomoon.woff index e61b860c..fd764379 100644 Binary files a/app/public/icons/icomoon.woff and b/app/public/icons/icomoon.woff differ diff --git a/app/public/locales/en/head.json b/app/public/locales/en/head.json index 37842636..178c7bd6 100644 --- a/app/public/locales/en/head.json +++ b/app/public/locales/en/head.json @@ -1,4 +1,4 @@ { - "head.og.description": "Chat with your files. Intelligent PDF file reader.", - "head.og.title": "AI File Agent" + "head.og.description": "Súper Únderground Artists, Collections & Events", + "head.og.title": "svpervnder" } diff --git a/app/src/app/chat/dropbox-chat/DropboxChat.module.scss b/app/src/app/chat/dropbox-chat/DropboxChat.module.scss deleted file mode 100644 index ca6d6271..00000000 --- a/app/src/app/chat/dropbox-chat/DropboxChat.module.scss +++ /dev/null @@ -1,98 +0,0 @@ -@import "src/theme/base"; -@import "src/theme/forms/variables"; -@import "src/ui/fileagent/navbar/variables"; - -@mixin width { - @include atLargeTablet { - max-width: 50vw; - margin: 0 auto; - } -} - -.dropbox-chat { - position: relative; - display: block; - min-height: 100vh; - - &__textarea { - @include atLargeTablet { - padding: $space-l; - padding-top: 0; - } - position: fixed; - right: 0; - bottom: 0; - left: 0; - width: 100%; - border-top: 1px solid var(--color-horizontal-line-background); - padding: $space-default; - padding-top: 0; - background-color: var(--color-background); - - &--actions { - @include width; - display: flex; - justify-content: flex-end; - padding: $space-s; - - button { - margin-left: $space-default; - } - } - - &--card { - @include width; - } - - &--card-actions { - @include atLargeTablet { - flex-direction: row; - } - flex-direction: column; - padding-top: 0; - - &-button { - @include atLargeTablet { - margin-left: $space-default; - } - margin-left: auto; - } - } - - &--card-field { - min-height: 63px; - padding: $space-default !important; - font-size: $input-font-size !important; - background-color: var(--color-market-card-background); - transition: height 0.2s ease-in-out; - } - } - - &__messages { - @include atLargeTablet { - padding-top: $navbar-height; - padding-bottom: 270px; - } - padding-top: $navbar-height-mobile; - padding-bottom: 280px; - overflow-y: scroll; - - &--item { - border-bottom: 1px solid var(--color-horizontal-line-background); - - > div { - @include width; - display: flex; - padding-top: $space-m; - } - - &:nth-child(odd) { - background-color: var(--color-background-contrast); - } - - &:last-child { - border-bottom: none; - } - } - } -} diff --git a/app/src/app/chat/dropbox-chat/DropboxChat.module.scss.d.ts b/app/src/app/chat/dropbox-chat/DropboxChat.module.scss.d.ts deleted file mode 100644 index 4818f6d0..00000000 --- a/app/src/app/chat/dropbox-chat/DropboxChat.module.scss.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -export type Styles = { - "dropbox-chat": string; - "dropbox-chat__messages": string; - "dropbox-chat__messages--item": string; - "dropbox-chat__textarea": string; - "dropbox-chat__textarea--actions": string; - "dropbox-chat__textarea--card": string; - "dropbox-chat__textarea--card-actions": string; - "dropbox-chat__textarea--card-actions-button": string; - "dropbox-chat__textarea--card-field": string; - "z-depth-0": string; - "z-depth-1": string; - "z-depth-1-half": string; - "z-depth-2": string; - "z-depth-3": string; - "z-depth-4": string; - "z-depth-5": string; -}; - -export type ClassNames = keyof Styles; - -declare const styles: Styles; - -export default styles; diff --git a/app/src/app/chat/dropbox-chat/DropboxChat.test.tsx b/app/src/app/chat/dropbox-chat/DropboxChat.test.tsx deleted file mode 100644 index 134f03cc..00000000 --- a/app/src/app/chat/dropbox-chat/DropboxChat.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { screen, render } from "tests"; - -import { DropboxChat } from "./DropboxChat"; - -describe("DropboxChat", () => { - it("renders children correctly", () => { - render(DropboxChat); - - const element = screen.getByText("DropboxChat"); - - expect(element).toBeInTheDocument(); - }); -}); diff --git a/app/src/app/chat/dropbox-chat/DropboxChat.tsx b/app/src/app/chat/dropbox-chat/DropboxChat.tsx deleted file mode 100644 index 3d3e0f9e..00000000 --- a/app/src/app/chat/dropbox-chat/DropboxChat.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import clsx from "clsx"; -import { Field, useForm } from "react-final-form"; -import { useEffect } from "react"; - -import { Card } from "ui/card/Card"; -import { Button } from "ui/button/Button"; -import { Dropzone } from "ui/dropzone/Dropzone"; -import { useMessageContext } from "context/message/useMessageContext"; -import { ChatContextMessage } from "context/message/MessageContext.types"; -import { MessageFileType } from "ui/dropzone/message-file-type/MessageFileType"; -import { MessageTextType } from "ui/dropzone/message-text-type/MessageTextType"; -import { useFormContext } from "context/form/useFormContext"; - -import { DropboxChatProps, FormFieldNames } from "./DropboxChat.types"; -import styles from "./DropboxChat.module.scss"; - -export const DropboxChat: React.FC = ({ className, onSubmit }) => { - const form = useForm(); - - const formContext = useFormContext(); - - const { messages, actions, clearMessages, saveMessageThread } = useMessageContext(); - - useEffect(() => { - if (!form) return; - - formContext.setForm(form); - }, [form]); - - useEffect(() => { - const element = document.querySelector(`#messages`); - - if (!element) return; - - element.scrollIntoView({ behavior: "smooth", block: "end" }); - }, [messages]); - - const onKeyDown = async (event: KeyboardEvent) => { - const { textarea, defaultHeight } = formContext.updateTextareaHeight(); - - if (event.key === "Backspace" && !textarea.textContent) { - event.preventDefault(); - - textarea.style.height = defaultHeight; - } - - if (event.key === "Enter" && !event.shiftKey) { - event.preventDefault(); - - await form.submit(); - - textarea.style.height = defaultHeight; - } - }; - - const getMessageTypeComponent = (message: ChatContextMessage) => { - switch (message.type) { - case "text": - return ( - - ); - case "file": - return ( - - ); - - default: - return null; - } - }; - - return ( -
-
- {messages.map((message) => getMessageTypeComponent(message))} -
- -
-
- - -
- - - - - - - -
- -
-
-
-
-
- ); -}; diff --git a/app/src/app/chat/dropbox-chat/DropboxChat.types.ts b/app/src/app/chat/dropbox-chat/DropboxChat.types.ts deleted file mode 100644 index 6c09b437..00000000 --- a/app/src/app/chat/dropbox-chat/DropboxChat.types.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { ReactNode } from "react"; - -export enum FormFieldNames { - message = "message", -} - -export type ChatFormValues = { - message: string; -}; - -export type DropboxChatContainerProps = { - children?: ReactNode; - className?: string; -}; - -export type DropboxChatProps = { - onSubmit: (event?: Partial>) => - | Promise< - | { - [key: string]: any; - } - | undefined - > - | undefined; - children?: ReactNode; - className?: string; -}; diff --git a/app/src/app/chat/dropbox-chat/DropboxChatContainer.tsx b/app/src/app/chat/dropbox-chat/DropboxChatContainer.tsx deleted file mode 100644 index 1de077f5..00000000 --- a/app/src/app/chat/dropbox-chat/DropboxChatContainer.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { Form as RFForm } from "react-final-form"; -import { useEffect } from "react"; - -import { useMessageContext } from "context/message/useMessageContext"; -import { useFormContext } from "context/form/useFormContext"; -import { useAuthorizationContext } from "context/authorization/useAuthorizationContext"; - -import { DropboxChat } from "./DropboxChat"; -import { ChatFormValues } from "./DropboxChat.types"; - -export const DropboxChatContainer = () => { - const messageContext = useMessageContext(); - - const formContext = useFormContext(); - - const authContext = useAuthorizationContext(); - - useEffect(() => { - messageContext.displayInitialMessage(); - }, []); - - useEffect(() => { - authContext.verifyDropboxESignAuthorization(); - authContext.verifySquareAPIAuthorization(); - }, []); - - const onSubmit = async (values: ChatFormValues) => { - formContext.submit(values); - }; - - return ( - { - changeValue(state, field, () => value); - }, - }} - onSubmit={onSubmit} - render={({ handleSubmit }) => } - /> - ); -}; diff --git a/app/src/app/home/Home.module.scss b/app/src/app/home/Home.module.scss deleted file mode 100644 index 6d28b306..00000000 --- a/app/src/app/home/Home.module.scss +++ /dev/null @@ -1,44 +0,0 @@ -@import "src/theme/base"; - -.home { - display: block; - - &__latest-price-markets-table { - margin-top: $space-ml; - } - - &__title { - @include atLargeTablet { - margin-bottom: 0; - } - margin-right: $space-ml; - margin-bottom: $space-default; - color: var(--color-button-secondary-text); - } - - &__title-row { - @include atLargeTablet { - flex-direction: row; - } - display: flex; - flex-direction: column; - margin-bottom: $space-ml; - } - - &__actions-row { - @include atLargeTablet { - flex-direction: row; - - > div { - align-self: center; - } - } - display: flex; - - > div { - &:nth-child(n + 2) { - margin-left: $space-default; - } - } - } -} diff --git a/app/src/app/home/Home.tsx b/app/src/app/home/Home.tsx deleted file mode 100644 index b0473279..00000000 --- a/app/src/app/home/Home.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import clsx from "clsx"; -import { useTranslation } from "next-i18next"; -import { useState } from "react"; -import dynamic from "next/dynamic"; - -import { MainPanel } from "ui/mainpanel/MainPanel"; -import { Typography } from "ui/typography/Typography"; -import { PriceMarket } from "app/market/price-market/PriceMarket"; -import { Button } from "ui/button/Button"; -import { CreatePriceMarketModalProps } from "app/market/price-market/create-price-market-modal/CreatePriceMarketModal.types"; -import { NearMarketContractContextController } from "context/near/market-contract/NearMarketContractContextController"; - -import { HomeProps } from "./Home.types"; -import styles from "./Home.module.scss"; -import { LatestPriceMarketsTableContainer } from "./latest-price-markets-table/LatestPriceMarketsTableContainer"; - -const CreatePriceMarketModal = dynamic( - () => - import("app/market/price-market/create-price-market-modal/CreatePriceMarketModal").then( - (mod) => mod.CreatePriceMarketModal, - ), - { ssr: false }, -); - -export const Home: React.FC = ({ className, marketId }) => { - const [isCreatePriceMarketModalVisible, setIsCreatePriceMarketModalVisible] = useState(false); - - const { t } = useTranslation(["home", "common"]); - - const onClickCloseCreateMarketModal = () => { - setIsCreatePriceMarketModalVisible(false); - }; - - const onClickCreateMarketButton = () => { - // @TODO check if there's a connected wallet, otherwise display the "connect wallet modal" - setIsCreatePriceMarketModalVisible(true); - }; - - return ( - <> -
- -
- {t("home.title")} -
-
- -
-
- -
-
-
- - - - - -
- -
-
-
- - {isCreatePriceMarketModalVisible && } - - ); -}; diff --git a/app/src/app/home/Home.types.ts b/app/src/app/home/Home.types.ts deleted file mode 100644 index 898cfe4e..00000000 --- a/app/src/app/home/Home.types.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { ReactNode } from "react"; - -import { AccountId } from "providers/near/contracts/prompt-wars/prompt-wars.types"; - -export type HomeProps = { - marketId: string; - children?: ReactNode; - className?: string; -}; - -export type HomeContainerProps = { - marketId: AccountId; - children?: ReactNode; - className?: string; -}; diff --git a/app/src/app/home/HomeContainer.tsx b/app/src/app/home/HomeContainer.tsx deleted file mode 100644 index 43586400..00000000 --- a/app/src/app/home/HomeContainer.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { GenericLoader } from "ui/generic-loader/GenericLoader"; -import { PromptWars } from "app/prompt-wars/PromptWars"; - -import { HomeContainerProps } from "./Home.types"; - -export const HomeContainer = ({ marketId }: HomeContainerProps) => { - if (!marketId) { - return ; - } - - return ; -}; diff --git a/app/src/app/home/latest-price-markets-table/LatestPriceMarketsTable.module.scss b/app/src/app/home/latest-price-markets-table/LatestPriceMarketsTable.module.scss deleted file mode 100644 index a530fab6..00000000 --- a/app/src/app/home/latest-price-markets-table/LatestPriceMarketsTable.module.scss +++ /dev/null @@ -1,13 +0,0 @@ -@import "src/theme/base"; -@import "src/ui/table/variables"; -@import "src/ui/table/mixins"; - -.latest-price-markets-table { - @include table; - @include tableStripped; - @include tableSm; - - &__responsive { - @include tableResponsive; - } -} diff --git a/app/src/app/home/latest-price-markets-table/LatestPriceMarketsTable.test.tsx b/app/src/app/home/latest-price-markets-table/LatestPriceMarketsTable.test.tsx deleted file mode 100644 index 7ec21dba..00000000 --- a/app/src/app/home/latest-price-markets-table/LatestPriceMarketsTable.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { screen, render } from "tests"; - -import { LatestPriceMarketsTable } from "./LatestPriceMarketsTable"; - -describe("LatestPriceMarketsTable", () => { - it("renders children correctly", () => { - render(LatestPriceMarketsTable); - - const element = screen.getByText("LatestPriceMarketsTable"); - - expect(element).toBeInTheDocument(); - }); -}); diff --git a/app/src/app/home/latest-price-markets-table/LatestPriceMarketsTable.tsx b/app/src/app/home/latest-price-markets-table/LatestPriceMarketsTable.tsx deleted file mode 100644 index 068aba81..00000000 --- a/app/src/app/home/latest-price-markets-table/LatestPriceMarketsTable.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import clsx from "clsx"; - -import { useNearMarketFactoryContractContext } from "context/near/market-factory-contract/useNearMarketFactoryContractContext"; -import { NearMarketContractContextController } from "context/near/market-contract/NearMarketContractContextController"; -import { Typography } from "ui/typography/Typography"; - -import { LatestPriceMarketsTableProps } from "./LatestPriceMarketsTable.types"; -import styles from "./LatestPriceMarketsTable.module.scss"; -import { PriceMarketTableRow } from "./price-market-table-row/PriceMarketTableRow"; - -export const LatestPriceMarketsTable: React.FC = ({ className }) => { - const { latestPriceMarketsIds } = useNearMarketFactoryContractContext(); - - return ( -
- - - - - - - - - - - - - {latestPriceMarketsIds.map((marketId) => ( - - - - ))} - -
- Description - - Total Value Locked - - Your Stake - - Ends in - - Status - {null}
-
- ); -}; diff --git a/app/src/app/home/latest-price-markets-table/LatestPriceMarketsTable.types.ts b/app/src/app/home/latest-price-markets-table/LatestPriceMarketsTable.types.ts deleted file mode 100644 index 18d8b3f3..00000000 --- a/app/src/app/home/latest-price-markets-table/LatestPriceMarketsTable.types.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { ReactNode } from "react"; - -export type LatestPriceMarketsTableProps = { - children?: ReactNode; - className?: string; -}; diff --git a/app/src/app/home/latest-price-markets-table/LatestPriceMarketsTableContainer.tsx b/app/src/app/home/latest-price-markets-table/LatestPriceMarketsTableContainer.tsx deleted file mode 100644 index 445003da..00000000 --- a/app/src/app/home/latest-price-markets-table/LatestPriceMarketsTableContainer.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { useEffect } from "react"; - -import { useNearMarketFactoryContractContext } from "context/near/market-factory-contract/useNearMarketFactoryContractContext"; -import { Card } from "ui/card/Card"; -import { Typography } from "ui/typography/Typography"; - -import { LatestPriceMarketsTable } from "./LatestPriceMarketsTable"; - -export const LatestPriceMarketsTableContainer = () => { - const { fetchLatestPriceMarkets, latestPriceMarketsIds, actions } = useNearMarketFactoryContractContext(); - - useEffect(() => { - fetchLatestPriceMarkets(); - }, []); - - return ( - - - {latestPriceMarketsIds.length === 0 || actions.fetchLatestPriceMarkets.isLoading ? ( - Fetching latest price markets - ) : ( - - )} - - - ); -}; diff --git a/app/src/app/home/latest-price-markets-table/price-market-table-row/PriceMarketTableRow.module.scss b/app/src/app/home/latest-price-markets-table/price-market-table-row/PriceMarketTableRow.module.scss deleted file mode 100644 index eabb4739..00000000 --- a/app/src/app/home/latest-price-markets-table/price-market-table-row/PriceMarketTableRow.module.scss +++ /dev/null @@ -1,14 +0,0 @@ -@import "src/theme/base"; -@import "src/ui/typography/mixins"; - -.price-market-table-row { - td { - p { - color: var(--color-typography-text); - } - } - - &__link { - @include miniDescription; - } -} diff --git a/app/src/app/home/latest-price-markets-table/price-market-table-row/PriceMarketTableRow.module.scss.d.ts b/app/src/app/home/latest-price-markets-table/price-market-table-row/PriceMarketTableRow.module.scss.d.ts deleted file mode 100644 index 06af4c48..00000000 --- a/app/src/app/home/latest-price-markets-table/price-market-table-row/PriceMarketTableRow.module.scss.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -export type Styles = { - "price-market-table-row": string; - "price-market-table-row__link": string; - "z-depth-0": string; - "z-depth-1": string; - "z-depth-1-half": string; - "z-depth-2": string; - "z-depth-3": string; - "z-depth-4": string; - "z-depth-5": string; -}; - -export type ClassNames = keyof Styles; - -declare const styles: Styles; - -export default styles; diff --git a/app/src/app/home/latest-price-markets-table/price-market-table-row/PriceMarketTableRow.test.tsx b/app/src/app/home/latest-price-markets-table/price-market-table-row/PriceMarketTableRow.test.tsx deleted file mode 100644 index f66bde78..00000000 --- a/app/src/app/home/latest-price-markets-table/price-market-table-row/PriceMarketTableRow.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { screen, render } from "tests"; - -import { PriceMarketTableRow } from "./PriceMarketTableRow"; - -describe("PriceMarketTableRow", () => { - it("renders children correctly", () => { - render(PriceMarketTableRow); - - const element = screen.getByText("PriceMarketTableRow"); - - expect(element).toBeInTheDocument(); - }); -}); diff --git a/app/src/app/home/latest-price-markets-table/price-market-table-row/PriceMarketTableRow.tsx b/app/src/app/home/latest-price-markets-table/price-market-table-row/PriceMarketTableRow.tsx deleted file mode 100644 index 51aaa3a5..00000000 --- a/app/src/app/home/latest-price-markets-table/price-market-table-row/PriceMarketTableRow.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import clsx from "clsx"; -import { useEffect } from "react"; -import Countdown from "react-countdown"; - -import { useNearMarketContractContext } from "context/near/market-contract/useNearMarketContractContext"; -import { Typography } from "ui/typography/Typography"; -import { useWalletStateContext } from "context/wallet/state/useWalletStateContext"; -import currency from "providers/currency"; -import { useRoutes } from "hooks/useRoutes/useRoutes"; - -import { PriceMarketTableRowProps } from "./PriceMarketTableRow.types"; -import styles from "./PriceMarketTableRow.module.scss"; - -export const PriceMarketTableRow: React.FC = ({ className }) => { - const walletState = useWalletStateContext(); - const routes = useRoutes(); - - const { - fetchMarketContractValues, - marketContractValues, - calculateTotalOutcomeTokensPosition, - outcomeTokensExtended, - bettingPeriodExpired, - marketId, - } = useNearMarketContractContext(); - - useEffect(() => { - fetchMarketContractValues(); - }, []); - - useEffect(() => { - calculateTotalOutcomeTokensPosition(); - }, [marketContractValues]); - - const getOutcomeTokensPosition = () => { - if (!walletState.isConnected) { - return "connect wallet"; - } - - if (outcomeTokensExtended?.length) { - return outcomeTokensExtended.map((token, index) => - index === outcomeTokensExtended.length - 1 - ? `${token.value}: ${currency.convert.fromUIntAmount( - token.balance_of!, - marketContractValues?.collateralTokenMetadata.decimals!, - )} (${token.position?.toFixed(2)}%)` - : `${token.value}: ${currency.convert.fromUIntAmount( - token.balance_of!, - marketContractValues?.collateralTokenMetadata.decimals!, - )} (${token.position?.toFixed(2)}%), `, - ); - } - - return "calculating"; - }; - - if (!marketContractValues) { - return null; - } - - return ( - - - {marketContractValues.market.description} - - - - - - {getOutcomeTokensPosition()} - - - - {!bettingPeriodExpired() ? : "—"} - - - - - {marketContractValues.isResolved ? "resolved" : "unresolved"} - - - - - See details - - - - ); -}; diff --git a/app/src/app/home/latest-price-markets-table/price-market-table-row/PriceMarketTableRow.types.ts b/app/src/app/home/latest-price-markets-table/price-market-table-row/PriceMarketTableRow.types.ts deleted file mode 100644 index 0517de82..00000000 --- a/app/src/app/home/latest-price-markets-table/price-market-table-row/PriceMarketTableRow.types.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ReactNode } from "react"; - -import { AccountId } from "providers/near/contracts/market/market.types"; - -export type PriceMarketTableRowProps = { - marketId: AccountId; - children?: ReactNode; - className?: string; -}; diff --git a/app/src/app/market/outcome-tokens-position/OutcomeTokensPosition.module.scss b/app/src/app/market/outcome-tokens-position/OutcomeTokensPosition.module.scss deleted file mode 100644 index 79eb77be..00000000 --- a/app/src/app/market/outcome-tokens-position/OutcomeTokensPosition.module.scss +++ /dev/null @@ -1,32 +0,0 @@ -@import "src/theme/base"; - -.outcome-tokens-position { - display: block; - - &__card { - margin-bottom: $space-default; - background-color: var(--color-market-card-background-contrast); - - &--content { - padding-top: $space-default; - padding-bottom: $space-default; - } - } - - &__row { - display: flex; - justify-content: space-between; - margin-right: -$space-default; - margin-left: -$space-default; - - &:nth-child(odd) { - background-color: var(--color-background-contrast); - } - } - - &__col { - padding: $space-xs $space-default; - text-transform: capitalize; - color: var(--color-typography-text); - } -} diff --git a/app/src/app/market/outcome-tokens-position/OutcomeTokensPosition.module.scss.d.ts b/app/src/app/market/outcome-tokens-position/OutcomeTokensPosition.module.scss.d.ts deleted file mode 100644 index 870303d2..00000000 --- a/app/src/app/market/outcome-tokens-position/OutcomeTokensPosition.module.scss.d.ts +++ /dev/null @@ -1,20 +0,0 @@ -export type Styles = { - "outcome-tokens-position": string; - "outcome-tokens-position__card": string; - "outcome-tokens-position__card--content": string; - "outcome-tokens-position__col": string; - "outcome-tokens-position__row": string; - "z-depth-0": string; - "z-depth-1": string; - "z-depth-1-half": string; - "z-depth-2": string; - "z-depth-3": string; - "z-depth-4": string; - "z-depth-5": string; -}; - -export type ClassNames = keyof Styles; - -declare const styles: Styles; - -export default styles; diff --git a/app/src/app/market/outcome-tokens-position/OutcomeTokensPosition.test.tsx b/app/src/app/market/outcome-tokens-position/OutcomeTokensPosition.test.tsx deleted file mode 100644 index 36ed4d6e..00000000 --- a/app/src/app/market/outcome-tokens-position/OutcomeTokensPosition.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { screen, render } from "tests"; - -import { OutcomeTokensPosition } from "./OutcomeTokensPosition"; - -describe("OutcomeTokensPosition", () => { - it("renders children correctly", () => { - render(OutcomeTokensPosition); - - const element = screen.getByText("OutcomeTokensPosition"); - - expect(element).toBeInTheDocument(); - }); -}); diff --git a/app/src/app/market/outcome-tokens-position/OutcomeTokensPosition.tsx b/app/src/app/market/outcome-tokens-position/OutcomeTokensPosition.tsx deleted file mode 100644 index d809a564..00000000 --- a/app/src/app/market/outcome-tokens-position/OutcomeTokensPosition.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import clsx from "clsx"; -import { useEffect } from "react"; -import { useTranslation } from "next-i18next"; - -import { useNearMarketContractContext } from "context/near/market-contract/useNearMarketContractContext"; -import { useWalletStateContext } from "context/wallet/state/useWalletStateContext"; -import { Typography } from "ui/typography/Typography"; -import { Card } from "ui/card/Card"; -import currency from "providers/currency"; - -import styles from "./OutcomeTokensPosition.module.scss"; -import { OutcomeTokensPositionProps } from "./OutcomeTokensPosition.types"; - -export const OutcomeTokensPosition: React.FC = ({ className }) => { - const walletState = useWalletStateContext(); - - const { marketContractValues, calculateTotalOutcomeTokensPosition, outcomeTokensExtended } = - useNearMarketContractContext(); - - useEffect(() => { - calculateTotalOutcomeTokensPosition(); - }, [marketContractValues, walletState.isConnected]); - - const { t } = useTranslation(["prompt-wars"]); - - return ( - - - Your position - {outcomeTokensExtended?.length ? ( - <> - {outcomeTokensExtended?.map((token) => ( -
- - {token.value} - - - {currency.convert.fromUIntAmount( - token.balance_of!, - marketContractValues?.collateralTokenMetadata.decimals!, - )} - - - {token.position?.toFixed(2)}% - -
- ))} - - ) : ( - - {t("promptWars.OutcomeTokensPosition.miniDescription")} - - )} -
-
- ); -}; diff --git a/app/src/app/market/outcome-tokens-position/OutcomeTokensPosition.types.ts b/app/src/app/market/outcome-tokens-position/OutcomeTokensPosition.types.ts deleted file mode 100644 index 125a748e..00000000 --- a/app/src/app/market/outcome-tokens-position/OutcomeTokensPosition.types.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { ReactNode } from "react"; - -export type OutcomeTokensPositionProps = { - children?: ReactNode; - className?: string; -}; diff --git a/app/src/app/market/price-market/PriceMarket.module.scss b/app/src/app/market/price-market/PriceMarket.module.scss deleted file mode 100644 index ec5403be..00000000 --- a/app/src/app/market/price-market/PriceMarket.module.scss +++ /dev/null @@ -1,69 +0,0 @@ -@import "src/theme/base"; - -.price-market { - display: block; - - &__title-row { - @include atLargeTablet { - flex-direction: row; - } - display: flex; - flex-direction: column; - margin-bottom: $space-ml; - - a { - text-align: left; - text-transform: none; - } - } - - &__current-result-element { - &--create-market { - display: flex; - flex-direction: column; - align-items: flex-end; - - p { - margin-bottom: $space-default; - } - } - - &--time-left { - text-align: right; - - &-warn { - color: var(--color-status-warning); - } - } - - &--current-price { - text-align: left; - } - } - - &__info-card { - margin-bottom: $space-s; - } - - &__start-end-time { - margin-bottom: $space-m; - - &--text { - display: flex; - justify-content: space-between; - color: var(--color-status-warning); - - span { - text-decoration: none; - - &:last-child { - margin-left: 3px; - } - } - } - } - - &__dates-element { - margin-bottom: $space-default; - } -} diff --git a/app/src/app/market/price-market/PriceMarket.module.scss.d.ts b/app/src/app/market/price-market/PriceMarket.module.scss.d.ts deleted file mode 100644 index f119ccec..00000000 --- a/app/src/app/market/price-market/PriceMarket.module.scss.d.ts +++ /dev/null @@ -1,25 +0,0 @@ -export type Styles = { - "price-market": string; - "price-market__current-result-element--create-market": string; - "price-market__current-result-element--current-price": string; - "price-market__current-result-element--time-left": string; - "price-market__current-result-element--time-left-warn": string; - "price-market__dates-element": string; - "price-market__info-card": string; - "price-market__start-end-time": string; - "price-market__start-end-time--text": string; - "price-market__title-row": string; - "z-depth-0": string; - "z-depth-1": string; - "z-depth-1-half": string; - "z-depth-2": string; - "z-depth-3": string; - "z-depth-4": string; - "z-depth-5": string; -}; - -export type ClassNames = keyof Styles; - -declare const styles: Styles; - -export default styles; diff --git a/app/src/app/market/price-market/PriceMarket.test.tsx b/app/src/app/market/price-market/PriceMarket.test.tsx deleted file mode 100644 index 4c5ed29b..00000000 --- a/app/src/app/market/price-market/PriceMarket.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { screen, render } from "tests"; - -import { PriceMarket } from "./PriceMarket"; - -describe("PriceMarket", () => { - it("renders children correctly", () => { - render(PriceMarket); - - const element = screen.getByText("PriceMarket"); - - expect(element).toBeInTheDocument(); - }); -}); diff --git a/app/src/app/market/price-market/PriceMarket.tsx b/app/src/app/market/price-market/PriceMarket.tsx deleted file mode 100644 index 5ba1c0af..00000000 --- a/app/src/app/market/price-market/PriceMarket.tsx +++ /dev/null @@ -1,185 +0,0 @@ -import Countdown from "react-countdown"; -import clsx from "clsx"; -import { useTranslation } from "next-i18next"; -import { useEffect, useState } from "react"; -import dynamic from "next/dynamic"; - -import { Grid } from "ui/grid/Grid"; -import { MarketCard } from "ui/pulse/market-card/MarketCard"; -import { Card } from "ui/card/Card"; -import { SwapCardProps } from "ui/pulse/swap-card/SwapCard.types"; -import switchboard from "providers/switchboard"; -import currency from "providers/currency"; -import { Typography } from "ui/typography/Typography"; -import date from "providers/date"; -import { Button } from "ui/button/Button"; -import { useNearMarketContractContext } from "context/near/market-contract/useNearMarketContractContext"; -import { GenericLoader } from "ui/generic-loader/GenericLoader"; - -import { PriceMarketProps } from "./PriceMarket.types"; -import styles from "./PriceMarket.module.scss"; -import { CreatePriceMarketModalProps } from "./create-price-market-modal/CreatePriceMarketModal.types"; - -const SwapCard = dynamic(() => import("ui/pulse/swap-card/SwapCard").then((mod) => mod.SwapCard), { - ssr: false, -}); - -const CreatePriceMarketModal = dynamic( - () => import("./create-price-market-modal/CreatePriceMarketModal").then((mod) => mod.CreatePriceMarketModal), - { ssr: false }, -); - -export const PriceMarket: React.FC = ({ className, marketId }) => { - const [currentPrice, setCurrentPrice] = useState(currency.convert.toFormattedString(0)); - const [isBettingEnabled, setIsBettingEnabled] = useState(true); - const [isCreatePriceMarketModalVisible, setIsCreatePriceMarketModalVisible] = useState(false); - - const { t } = useTranslation(["price-market"]); - - const { - marketContractValues, - onClickResolveMarket, - bettingPeriodExpired, - actions: nearMarketContractContextActions, - fetchMarketContractValues, - selectedOutcomeToken, - } = useNearMarketContractContext(); - - const updateCurrentPrice = async () => { - const price = await switchboard.fetchCurrentPrice(switchboard.jobs.testnet.near.btcUsd); - setCurrentPrice(currency.convert.toFormattedString(price)); - }; - - useEffect(() => { - fetchMarketContractValues(); - }, [marketId]); - - useEffect(() => { - if (nearMarketContractContextActions.fetchMarketContractValues.isLoading) { - return undefined; - } - - updateCurrentPrice(); - setIsBettingEnabled(!bettingPeriodExpired()); - - const interval = setInterval(async () => { - updateCurrentPrice(); - - if (bettingPeriodExpired()) { - updateCurrentPrice(); - setIsBettingEnabled(false); - clearInterval(interval); - } - }, 5000); - - return () => { - clearInterval(interval); - }; - }, [marketId, nearMarketContractContextActions.fetchMarketContractValues.isLoading]); - - if (!marketContractValues) { - // @TODO render PriceMarket skeleton template - return ; - } - - const { buySellTimestamp, isOver, isResolutionWindowExpired, isResolved } = marketContractValues; - - const diff = date.client(buySellTimestamp).fromNow(); - const isBettingPeriodEnding = () => date.client(buySellTimestamp).diff(date.now()) < 1000 * 60; - - const onClickCloseCreateMarketModal = () => { - setIsCreatePriceMarketModalVisible(false); - }; - - const onClickCreateMarketButton = () => { - // @TODO check if there's a connected wallet, otherwise display the "connect wallet modal" - setIsCreatePriceMarketModalVisible(true); - }; - - const getCurrentResultElement = () => { - if (isResolved || (isOver && isResolutionWindowExpired)) { - return ( -
- - {t("priceMarket.description.createNextMarketPriceEarnFees")} - - -
- ); - } - - return ( - <> - - - {t("priceMarket.description.currentPrice")} - {currentPrice} - - - {t("priceMarket.description.timeLeftToBet")} - - - - - - - {t("priceMarket.miniDescription.betsEnd")} {diff}. - - - ); - }; - - const getDatesElement = () => { - if (bettingPeriodExpired()) { - return ( - - {t("priceMarket.description.bettingEnded")} - {t("priceMarket.description.beReady")} - - - ); - } - - return null; - }; - - return ( - <> -
- - - - - {getDatesElement()}
} - marketContractValues={marketContractValues} - onClickResolveMarket={onClickResolveMarket} - marketId={marketId} - /> - - - - - {selectedOutcomeToken && ( - - )} - - - - - {isCreatePriceMarketModalVisible && } - - ); -}; diff --git a/app/src/app/market/price-market/PriceMarket.types.ts b/app/src/app/market/price-market/PriceMarket.types.ts deleted file mode 100644 index 39c86a20..00000000 --- a/app/src/app/market/price-market/PriceMarket.types.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { ReactNode } from "react"; - -import { AccountId } from "providers/near/contracts/market/market.types"; - -export type PriceMarketProps = { - marketId: AccountId; - children?: ReactNode; - className?: string; -}; - -export type PriceMarketContainerProps = { - marketId: AccountId; - head: { - title: string; - description: string; - url: string; - }; -}; diff --git a/app/src/app/market/price-market/PriceMarketContainer.tsx b/app/src/app/market/price-market/PriceMarketContainer.tsx deleted file mode 100644 index 9a7bf1e3..00000000 --- a/app/src/app/market/price-market/PriceMarketContainer.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { NearMarketContractContextController } from "context/near/market-contract/NearMarketContractContextController"; -import { MainPanel } from "ui/mainpanel/MainPanel"; -import { Typography } from "ui/typography/Typography"; -import { useRoutes } from "hooks/useRoutes/useRoutes"; -import { Icon } from "ui/icon/Icon"; - -import styles from "./PriceMarket.module.scss"; -import { PriceMarket } from "./PriceMarket"; -import { PriceMarketContainerProps } from "./PriceMarket.types"; - -export const PriceMarketContainer = ({ marketId }: PriceMarketContainerProps) => { - const routes = useRoutes(); - - return ( - - {/* @TODO make it a smart breadcrumbs component */} -
- - back to latest price markets - -
- - - -
- ); -}; diff --git a/app/src/app/market/price-market/create-price-market-modal/CreatePriceMarketModal.module.scss b/app/src/app/market/price-market/create-price-market-modal/CreatePriceMarketModal.module.scss deleted file mode 100644 index 562d8303..00000000 --- a/app/src/app/market/price-market/create-price-market-modal/CreatePriceMarketModal.module.scss +++ /dev/null @@ -1,77 +0,0 @@ -@import "src/theme/base"; -@import "src/theme/forms/variables"; - -.create-price-market-modal { - display: block; - - &__modal-content { - padding-top: 0; - } - - &__categories { - margin-bottom: $space-ml; - } - - &__market-details-card { - border-radius: 14px; - background-color: var(--color-dark-10); - } - - &__spacer { - margin-top: $space-m; - } - - &__token { - display: flex; - font-size: $input-font-size; - - &--icon-box { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - align-self: center; - width: 18px; - height: 18px; - margin-right: $space-s; - border-radius: 50%; - background-color: var(--color-status-critical); - } - - &--icon { - width: 100%; - color: var(--color-background); - } - } - - &__market-options { - display: block; - - &--option { - display: flex; - justify-content: space-between; - - &-input { - width: 100%; - padding-right: $space-default; - } - - &-add-remove { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - height: $input-height; - border-radius: $border-radius-input; - padding: $input-padding; - color: var(--color-typography-text); - background: $input-background; - - &:hover { - background: var(--color-background); - cursor: pointer; - } - } - } - } -} diff --git a/app/src/app/market/price-market/create-price-market-modal/CreatePriceMarketModal.module.scss.d.ts b/app/src/app/market/price-market/create-price-market-modal/CreatePriceMarketModal.module.scss.d.ts deleted file mode 100644 index b8ae7ccd..00000000 --- a/app/src/app/market/price-market/create-price-market-modal/CreatePriceMarketModal.module.scss.d.ts +++ /dev/null @@ -1,27 +0,0 @@ -export type Styles = { - "create-price-market-modal": string; - "create-price-market-modal__categories": string; - "create-price-market-modal__market-details-card": string; - "create-price-market-modal__market-options": string; - "create-price-market-modal__market-options--option": string; - "create-price-market-modal__market-options--option-add-remove": string; - "create-price-market-modal__market-options--option-input": string; - "create-price-market-modal__modal-content": string; - "create-price-market-modal__spacer": string; - "create-price-market-modal__token": string; - "create-price-market-modal__token--icon": string; - "create-price-market-modal__token--icon-box": string; - "z-depth-0": string; - "z-depth-1": string; - "z-depth-1-half": string; - "z-depth-2": string; - "z-depth-3": string; - "z-depth-4": string; - "z-depth-5": string; -}; - -export type ClassNames = keyof Styles; - -declare const styles: Styles; - -export default styles; diff --git a/app/src/app/market/price-market/create-price-market-modal/CreatePriceMarketModal.test.tsx b/app/src/app/market/price-market/create-price-market-modal/CreatePriceMarketModal.test.tsx deleted file mode 100644 index c5b4acac..00000000 --- a/app/src/app/market/price-market/create-price-market-modal/CreatePriceMarketModal.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { screen, render } from "tests"; - -import { CreatePriceMarketModal } from "./CreatePriceMarketModal"; - -describe("CreatePriceMarketModal", () => { - it("renders children correctly", () => { - render(CreatePriceMarketModal); - - const element = screen.getByText("CreatePriceMarketModal"); - - expect(element).toBeInTheDocument(); - }); -}); diff --git a/app/src/app/market/price-market/create-price-market-modal/CreatePriceMarketModal.tsx b/app/src/app/market/price-market/create-price-market-modal/CreatePriceMarketModal.tsx deleted file mode 100644 index e18e643c..00000000 --- a/app/src/app/market/price-market/create-price-market-modal/CreatePriceMarketModal.tsx +++ /dev/null @@ -1,186 +0,0 @@ -import clsx from "clsx"; -import { Form as RFForm } from "react-final-form"; -import { useTranslation } from "next-i18next"; -import { OnChange } from "react-final-form-listeners"; -import { useEffect, useState } from "react"; - -import { Modal } from "ui/modal/Modal"; -import { Grid } from "ui/grid/Grid"; -import { Form } from "ui/form/Form"; -import { Card } from "ui/card/Card"; -import { Typography } from "ui/typography/Typography"; -import { Button } from "ui/button/Button"; -import date from "providers/date"; -import { PartialCreatePriceMarketContractArgs } from "context/near/market-factory-contract/NearMarketFactoryContractContext.types"; -import { useNearMarketFactoryContractContext } from "context/near/market-factory-contract/useNearMarketFactoryContractContext"; -import { useToastContext } from "hooks/useToastContext/useToastContext"; -import pulse from "providers/pulse"; -import currency from "providers/currency"; -import switchboard from "providers/switchboard"; - -import styles from "./CreatePriceMarketModal.module.scss"; -import { CreatePriceMarketModalForm, CreatePriceMarketModalProps } from "./CreatePriceMarketModal.types"; - -export const CreatePriceMarketModal: React.FC = ({ onClose, className }) => { - const [marketDescription, setMarketDescription] = useState(); - const [marketEndDate, setMarketEndDate] = useState(); - const [marketEndTime, setMarketEndTime] = useState("12:00"); - - const MarketFactoryContract = useNearMarketFactoryContractContext(); - - const { t } = useTranslation(["price-market", "common"]); - const toast = useToastContext(); - - const getMarketDescription = async () => { - const currentPrice = (await switchboard.fetchCurrentPrice(switchboard.jobs.testnet.near.btcUsd)).toFixed(2); - - if (!marketEndDate) { - setMarketDescription( - `Will ${pulse.getConfig().priceMarket.defaultBaseCurrency.symbol} be above ${currency.convert.toFormattedString( - currentPrice, - )} in ...?`, - ); - - return; - } - - const marketEndDateTime = date.parse - .fromDefaultFormat(`${marketEndDate} ${marketEndTime}`) - .utcOffset(date.constants.DEFAULT_TIMEZONE_OFFSET); - - setMarketDescription( - `Will ${pulse.getConfig().priceMarket.defaultBaseCurrency.symbol} be above ${currency.convert.toFormattedString( - currentPrice, - )} ${date.timeFromNow.asDefault(marketEndDateTime.valueOf())}?`, - ); - }; - - useEffect(() => { - getMarketDescription(); - }, [marketEndDate, marketEndTime]); - - const onSubmit = async (values: CreatePriceMarketModalForm) => { - try { - const startsAt = date.parse - .fromDefaultFormat(`${values.marketStartDate} ${values.marketStartTime}`) - .utcOffset(date.constants.DEFAULT_TIMEZONE_OFFSET); - - const endsAt = date.parse - .fromDefaultFormat(`${values.marketEndDate} ${values.marketEndTime}`) - .utcOffset(date.constants.DEFAULT_TIMEZONE_OFFSET); - - const resolutionWindow = endsAt.clone().add(5, "minutes"); - - const args: PartialCreatePriceMarketContractArgs = { - startsAt: date.toNanoseconds(startsAt.valueOf()), - endsAt: date.toNanoseconds(endsAt.valueOf()), - resolutionWindow: date.toNanoseconds(resolutionWindow.valueOf()), - }; - - // @TODO validate that dates are in the future - await MarketFactoryContract.createPriceMarket(args); - } catch { - toast.trigger({ - variant: "error", - withTimeout: true, - title: "Oops, our bad.", - children: While creating the market. Try again?, - }); - } - }; - - const onChangeMarketEndDate = (value: string, mutator: (...args: any[]) => any) => { - setMarketEndDate(value); - mutator(); - }; - - const onChangeMarketEndTime = (value: string, mutator: (...args: any[]) => any) => { - setMarketEndTime(value); - mutator(); - }; - - return ( - - { - utils.changeValue(state, "marketDescription", () => marketDescription); - }, - }} - render={({ form, handleSubmit }) => ( -
- - {t("priceMarket.createPriceMarketModal.title")} - - - - - {t("priceMarket.createPriceMarketModal.marketDetails")} - - - - {t("priceMarket.createPriceMarketModal.input.descriptionOfTheMarket")} - - - - -
- - {t("priceMarket.createPriceMarketModal.input.marketStartDatetime")} - - - - - {t("priceMarket.createPriceMarketModal.input.marketStartDate")} - - - - - - {t("priceMarket.createPriceMarketModal.input.marketStartTime")} - - - - -
- - {t("priceMarket.createPriceMarketModal.input.marketEndDatetime")} - - - - - {t("priceMarket.createPriceMarketModal.input.marketEndDate")} - - - - {(value) => onChangeMarketEndDate(value, form.mutators.setMarketDescription)} - - - - - {t("priceMarket.createPriceMarketModal.input.marketEndTime")} - - - - {(value) => onChangeMarketEndTime(value, form.mutators.setMarketDescription)} - - - - - - - - - - - )} - /> - - ); -}; diff --git a/app/src/app/market/price-market/create-price-market-modal/CreatePriceMarketModal.types.ts b/app/src/app/market/price-market/create-price-market-modal/CreatePriceMarketModal.types.ts deleted file mode 100644 index db75113c..00000000 --- a/app/src/app/market/price-market/create-price-market-modal/CreatePriceMarketModal.types.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { ReactNode } from "react"; - -export type CreatePriceMarketModalProps = { - onClose: () => void; - children?: ReactNode; - className?: string; -}; - -export type CreatePriceMarketModalForm = { - marketStartDate: string; - marketStartTime: string; - marketEndDate: string; - marketEndTime: string; -}; diff --git a/app/src/app/prompt-wars/PromptWars.module.scss b/app/src/app/prompt-wars/PromptWars.module.scss deleted file mode 100644 index 77a456b8..00000000 --- a/app/src/app/prompt-wars/PromptWars.module.scss +++ /dev/null @@ -1,45 +0,0 @@ -@import "src/theme/base"; - -.prompt-wars { - display: flex; - flex-direction: column; - justify-content: space-between; - height: 100%; - - &__logo { - @include atLargeTablet { - display: block; - } - display: none; - } - - &__title-row { - @include atLargeTablet { - flex-direction: row; - } - display: flex; - flex-direction: column; - margin-bottom: $space-ml; - - &--description { - @include atLargeTablet { - max-width: 280px; - margin-top: 0; - margin-left: $space-default; - padding: $space-default; - } - display: flex; - flex-direction: column; - justify-content: center; - margin-top: $space-default; - } - } - - &__game-row { - margin-bottom: $space-ml; - - &--col-left { - margin-bottom: $space-ml; - } - } -} diff --git a/app/src/app/prompt-wars/PromptWars.module.scss.d.ts b/app/src/app/prompt-wars/PromptWars.module.scss.d.ts deleted file mode 100644 index 444ee943..00000000 --- a/app/src/app/prompt-wars/PromptWars.module.scss.d.ts +++ /dev/null @@ -1,21 +0,0 @@ -export type Styles = { - "prompt-wars": string; - "prompt-wars__game-row": string; - "prompt-wars__game-row--col-left": string; - "prompt-wars__logo": string; - "prompt-wars__title-row": string; - "prompt-wars__title-row--description": string; - "z-depth-0": string; - "z-depth-1": string; - "z-depth-1-half": string; - "z-depth-2": string; - "z-depth-3": string; - "z-depth-4": string; - "z-depth-5": string; -}; - -export type ClassNames = keyof Styles; - -declare const styles: Styles; - -export default styles; diff --git a/app/src/app/prompt-wars/PromptWars.test.tsx b/app/src/app/prompt-wars/PromptWars.test.tsx deleted file mode 100644 index 8bdea61e..00000000 --- a/app/src/app/prompt-wars/PromptWars.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { screen, render } from "tests"; - -import { PromptWars } from "./PromptWars"; - -describe("PromptWars", () => { - it("renders children correctly", () => { - render(PromptWars); - - const element = screen.getByText("PromptWars"); - - expect(element).toBeInTheDocument(); - }); -}); diff --git a/app/src/app/prompt-wars/PromptWars.tsx b/app/src/app/prompt-wars/PromptWars.tsx deleted file mode 100644 index 767c0e0d..00000000 --- a/app/src/app/prompt-wars/PromptWars.tsx +++ /dev/null @@ -1,136 +0,0 @@ -import clsx from "clsx"; -import { useEffect, useState } from "react"; -import { useTranslation } from "next-i18next"; - -import { MainPanel } from "ui/mainpanel/MainPanel"; -import { PromptWarsLogo } from "ui/icons/PromptWarsLogo"; -import { Grid } from "ui/grid/Grid"; -import { Typography } from "ui/typography/Typography"; -import { ImgPromptCard } from "ui/pulse/img-prompt-card/ImgPromptCard"; -import { GenericLoader } from "ui/generic-loader/GenericLoader"; -import { PromptInputCard } from "ui/pulse/prompt-input-card/PromptInputCard"; -import { FaqsModal } from "ui/pulse/prompt-wars/faqs-modal/FaqsModal"; -import { useNearPromptWarsMarketContractContext } from "context/near/prompt-wars-market-contract/useNearPromptWarsMarketContractContext"; -import { useToastContext } from "hooks/useToastContext/useToastContext"; -import { Prompt } from "providers/near/contracts/prompt-wars/prompt-wars.types"; -import { ResultsModal } from "ui/pulse/prompt-wars/results-modal/ResultsModal"; - -import styles from "./PromptWars.module.scss"; -import { PromptWarsProps } from "./PromptWars.types"; - -export const PromptWars: React.FC = ({ marketId, className }) => { - const [isFAQsModalVisible, displayFAQsModal] = useState(false); - const [isResultsModalVisible, displayResultsModal] = useState(false); - - const { marketContractValues, fetchMarketContractValues, ftTransferCall, sell, create, actions } = - useNearPromptWarsMarketContractContext(); - - const { t } = useTranslation(["prompt-wars"]); - - const toast = useToastContext(); - - useEffect(() => { - fetchMarketContractValues(); - }, [marketId]); - - useEffect(() => { - const interval = setInterval(() => { - fetchMarketContractValues(); - }, 5000); - - return () => { - clearInterval(interval); - }; - }, [marketId]); - - if (!marketContractValues || actions.create.isLoading) { - // @TODO render PriceMarket skeleton template - return ; - } - - const onSubmit = async (prompt: Prompt) => { - if (marketContractValues.isOver) { - toast.trigger({ - variant: "error", - title: t("promptWars.marketisover.title"), - children: {t("promptwars.marketisover.description")}, - }); - - return; - } - - await ftTransferCall(prompt); - }; - - const onClaimDepositUnresolved = async () => { - await sell(); - }; - - const onClickCloseFAQsModal = () => { - displayFAQsModal(false); - }; - - const onClickFAQsButton = () => { - displayFAQsModal(true); - }; - - const onClickCloseResultsModal = () => { - displayResultsModal(false); - }; - - const onClickSeeResults = () => { - displayResultsModal(true); - }; - - const onClickCreateNewGame = async () => { - await create(); - }; - - return ( - <> - - -
- -
- - {t("promptWars.description")}{" "} - - {t("promptWars.faqs")} - - -
-
- -
- - - } - onClaimDepositUnresolved={onClaimDepositUnresolved} - onClickSeeResults={onClickSeeResults} - onClickCreateNewGame={onClickCreateNewGame} - /> - - - - - -
-
-
- - {isFAQsModalVisible && } - - {isResultsModalVisible && ( - - )} - - ); -}; diff --git a/app/src/app/prompt-wars/PromptWars.types.ts b/app/src/app/prompt-wars/PromptWars.types.ts deleted file mode 100644 index 309c0869..00000000 --- a/app/src/app/prompt-wars/PromptWars.types.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { ReactNode } from "react"; - -import { AccountId } from "providers/near/contracts/market/market.types"; - -export type PromptWarsProps = { - marketId: AccountId; - children?: ReactNode; - className?: string; -}; - -export type PromptWarsContainerProps = { - marketId: AccountId; - head: { - title: string; - description: string; - url: string; - }; -}; diff --git a/app/src/app/prompt-wars/PromptWarsContainer.tsx b/app/src/app/prompt-wars/PromptWarsContainer.tsx deleted file mode 100644 index f16b3068..00000000 --- a/app/src/app/prompt-wars/PromptWarsContainer.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import dynamic from "next/dynamic"; - -import { NearPromptWarsMarketContractContextController } from "context/near/prompt-wars-market-contract/NearPromptWarsMarketContractContextController"; - -import { PromptWarsContainerProps, PromptWarsProps } from "./PromptWars.types"; - -const PromptWars = dynamic(() => import("./PromptWars").then((mod) => mod.PromptWars), { ssr: false }); - -export const PromptWarsContainer = ({ marketId }: PromptWarsContainerProps) => ( - - - -); diff --git a/app/src/app/prompt-wars/previous-rounds/PreviousRounds.module.scss b/app/src/app/prompt-wars/previous-rounds/PreviousRounds.module.scss deleted file mode 100644 index d9aa975f..00000000 --- a/app/src/app/prompt-wars/previous-rounds/PreviousRounds.module.scss +++ /dev/null @@ -1,6 +0,0 @@ -@import "src/theme/base"; - -.previous-rounds { - min-height: 100vh; - padding-bottom: $space-xxl; -} diff --git a/app/src/app/prompt-wars/previous-rounds/PreviousRounds.module.scss.d.ts b/app/src/app/prompt-wars/previous-rounds/PreviousRounds.module.scss.d.ts deleted file mode 100644 index 528a4510..00000000 --- a/app/src/app/prompt-wars/previous-rounds/PreviousRounds.module.scss.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -export type Styles = { - "previous-rounds": string; - "z-depth-0": string; - "z-depth-1": string; - "z-depth-1-half": string; - "z-depth-2": string; - "z-depth-3": string; - "z-depth-4": string; - "z-depth-5": string; -}; - -export type ClassNames = keyof Styles; - -declare const styles: Styles; - -export default styles; diff --git a/app/src/app/prompt-wars/previous-rounds/PreviousRounds.test.tsx b/app/src/app/prompt-wars/previous-rounds/PreviousRounds.test.tsx deleted file mode 100644 index 6f39fc40..00000000 --- a/app/src/app/prompt-wars/previous-rounds/PreviousRounds.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { screen, render } from "tests"; - -import { PreviousRounds } from "./PreviousRounds"; - -describe("PreviousRounds", () => { - it("renders children correctly", () => { - render(PreviousRounds); - - const element = screen.getByText("PreviousRounds"); - - expect(element).toBeInTheDocument(); - }); -}); diff --git a/app/src/app/prompt-wars/previous-rounds/PreviousRounds.tsx b/app/src/app/prompt-wars/previous-rounds/PreviousRounds.tsx deleted file mode 100644 index 0f5816d3..00000000 --- a/app/src/app/prompt-wars/previous-rounds/PreviousRounds.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import clsx from "clsx"; - -import { PreviousRoundsTable } from "ui/pulse/prompt-wars/previous-rounds-table/PreviousRoundsTable"; -import { MainPanel } from "ui/mainpanel/MainPanel"; -import { Card } from "ui/card/Card"; - -import { PreviousRoundsProps } from "./PreviousRounds.types"; -import styles from "./PreviousRounds.module.scss"; - -export const PreviousRounds: React.FC = ({ className, markets }) => ( - <> - - - - - - - - -); diff --git a/app/src/app/prompt-wars/previous-rounds/PreviousRounds.types.ts b/app/src/app/prompt-wars/previous-rounds/PreviousRounds.types.ts deleted file mode 100644 index d78a99e9..00000000 --- a/app/src/app/prompt-wars/previous-rounds/PreviousRounds.types.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { ReactNode } from "react"; - -import { AccountId } from "providers/near/contracts/prompt-wars/prompt-wars.types"; - -export type PreviousRoundsProps = { - markets: Array; - children?: ReactNode; - className?: string; -}; - -export type PreviousRoundsContainerProps = { - markets: Array; - children?: ReactNode; - className?: string; -}; diff --git a/app/src/app/prompt-wars/previous-rounds/PreviousRoundsContainer.tsx b/app/src/app/prompt-wars/previous-rounds/PreviousRoundsContainer.tsx deleted file mode 100644 index 7a3b0b05..00000000 --- a/app/src/app/prompt-wars/previous-rounds/PreviousRoundsContainer.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import { PreviousRounds } from "./PreviousRounds"; -import { PreviousRoundsContainerProps } from "./PreviousRounds.types"; - -export const PreviousRoundsContainer = ({ markets }: PreviousRoundsContainerProps) => ( - -); diff --git a/app/src/context/authorization/AuthorizationContext.tsx b/app/src/context/authorization/AuthorizationContext.tsx deleted file mode 100644 index 831e4458..00000000 --- a/app/src/context/authorization/AuthorizationContext.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { createContext } from "react"; - -import { AuthorizationContextType } from "./AuthorizationContext.types"; - -export const AuthorizationContext = createContext(undefined); diff --git a/app/src/context/authorization/AuthorizationContext.types.ts b/app/src/context/authorization/AuthorizationContext.types.ts deleted file mode 100644 index 5070f1e4..00000000 --- a/app/src/context/authorization/AuthorizationContext.types.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { OAuthTokenStoreKey } from "api/oauth/oauth.types"; -import { ReactNode } from "react"; - -export type AccessTokens = { - [OAuthTokenStoreKey.dropbox_esign]?: string; - [OAuthTokenStoreKey.square_api]?: string; -}; - -export type AuthItem = { - name: string; - isAuthorized: boolean; - key: OAuthTokenStoreKey; -}; - -export type AuthorizationContextControllerProps = { - children: ReactNode; -}; - -export type AuthorizationContextType = { - accessTokens: AccessTokens; - authItems: Array; - revokeAuth: (key: OAuthTokenStoreKey) => void; - getGuestId: () => string | null; - generateGuestId: () => string; - verifyDropboxESignAuthorization: () => Promise; - verifySquareAPIAuthorization: () => Promise; -}; diff --git a/app/src/context/authorization/AuthorizationContextController.tsx b/app/src/context/authorization/AuthorizationContextController.tsx deleted file mode 100644 index c47af215..00000000 --- a/app/src/context/authorization/AuthorizationContextController.tsx +++ /dev/null @@ -1,107 +0,0 @@ -import React, { useState } from "react"; -import { OAuthTokenStoreKey } from "api/oauth/oauth.types"; -import Cookies from "js-cookie"; -import { v4 as uuidv4 } from "uuid"; - -import { useLocalStorage } from "hooks/useLocalStorage/useLocalStorage"; -import { LocalStorageKeys } from "hooks/useLocalStorage/useLocalStorage.types"; - -import { - AccessTokens, - AuthItem, - AuthorizationContextControllerProps, - AuthorizationContextType, -} from "./AuthorizationContext.types"; -import { AuthorizationContext } from "./AuthorizationContext"; - -export const AuthorizationContextController = ({ children }: AuthorizationContextControllerProps) => { - const [accessTokens, setAccessTokens] = useState({}); - const [authItems, setAuthItems] = useState>([ - { name: "Dropbox Sign™", isAuthorized: false, key: OAuthTokenStoreKey.dropbox_esign }, - { name: "Square™", isAuthorized: false, key: OAuthTokenStoreKey.square_api }, - ]); - - const ls = useLocalStorage(); - - const generateGuestId = () => { - const id = `guest-${uuidv4().slice(0, 4)}`; - - ls.set(LocalStorageKeys.guestId, id); - - return id; - }; - - const getGuestId = () => ls.get(LocalStorageKeys.guestId); - - const revokeAuth = (key: OAuthTokenStoreKey) => { - Cookies.remove(key); - - setAccessTokens((prev) => ({ ...prev, [key]: null })); - - setAuthItems((prev) => { - const i = prev.findIndex((item) => item.key === key); - - const item = prev[i]; - - return Object.assign([], { ...prev, [i]: { ...item, isAuthorized: false } }); - }); - }; - - const verifyDropboxESignAuthorization = async () => { - try { - const dropboxESignAuthResponse = Cookies.get(OAuthTokenStoreKey.dropbox_esign); - - const value = JSON.parse(dropboxESignAuthResponse!); - - setAccessTokens((prev) => ({ - ...prev, - [OAuthTokenStoreKey.dropbox_esign]: value.access_token, - })); - - setAuthItems((prev) => { - const i = prev.findIndex((item) => item.key === OAuthTokenStoreKey.dropbox_esign); - - const item = prev[i]; - - return Object.assign([], { ...prev, [i]: { ...item, isAuthorized: true } }); - }); - } catch (error) { - console.log(error); - } - }; - - const verifySquareAPIAuthorization = async () => { - try { - const squareApiAuthResponse = Cookies.get(OAuthTokenStoreKey.square_api); - - const value = JSON.parse(squareApiAuthResponse!); - - setAccessTokens((prev) => ({ - ...prev, - [OAuthTokenStoreKey.square_api]: value.accessToken, - })); - - setAuthItems((prev) => { - const i = prev.findIndex((item) => item.key === OAuthTokenStoreKey.square_api); - - const item = prev[i]; - - return Object.assign([], { ...prev, [i]: { ...item, isAuthorized: true } }); - }); - } catch (error) { - console.log(error); - } - }; - - const props: AuthorizationContextType = { - verifyDropboxESignAuthorization, - verifySquareAPIAuthorization, - accessTokens, - getGuestId, - generateGuestId, - authItems, - revokeAuth, - }; - - return {children}; -}; diff --git a/app/src/context/authorization/useAuthorizationContext.tsx b/app/src/context/authorization/useAuthorizationContext.tsx deleted file mode 100644 index a9a2a7f5..00000000 --- a/app/src/context/authorization/useAuthorizationContext.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { useContext } from "react"; - -import { AuthorizationContext } from "./AuthorizationContext"; - -export const useAuthorizationContext = () => { - const context = useContext(AuthorizationContext); - - if (context === undefined) { - throw new Error("useAuthorizationContext must be used within a AuthorizationContext"); - } - - return context; -}; diff --git a/app/src/context/evm/larskristo-hellheads/LarskristoHellheadsContext.tsx b/app/src/context/evm/larskristo-hellheads/LarskristoHellheadsContext.tsx new file mode 100644 index 00000000..98b03926 --- /dev/null +++ b/app/src/context/evm/larskristo-hellheads/LarskristoHellheadsContext.tsx @@ -0,0 +1,5 @@ +import { createContext } from "react"; + +import { LarskristoHellheadsContextType } from "./LarskristoHellheadsContext.types"; + +export const LarskristoHellheadsContext = createContext(undefined); diff --git a/app/src/context/evm/larskristo-hellheads/LarskristoHellheadsContext.types.ts b/app/src/context/evm/larskristo-hellheads/LarskristoHellheadsContext.types.ts new file mode 100644 index 00000000..679a3834 --- /dev/null +++ b/app/src/context/evm/larskristo-hellheads/LarskristoHellheadsContext.types.ts @@ -0,0 +1,48 @@ +import { ReactNode } from "react"; + +import { ZeroXAddress } from "../wallet-selector/EvmWalletSelectorContext.types"; + +export type LarskristoHellheadsContextControllerProps = { + children: ReactNode; +}; + +export type LarskristoHellheadsContextActions = { + fetchContractValues: { isLoading: boolean }; + getTokenPrice: { isLoading: boolean }; + buyToken: { isPending: boolean; isConfirmed: boolean; transactionHash?: string }; + setTokenForSale: { isPending: boolean; isConfirmed: boolean; transactionHash?: string }; +}; + +export type LarskristoHellheadsContractValues = { + name: string; + symbol: string; +}; + +export type TokenPrice = { + rawValue: bigint; + formattedValue: string; + exchangeRate?: number; + exchangeRateFormatted?: string; +}; + +export type Royalty = { + rawValue: bigint; + percentage: number; + percentageFormatted: string; +}; + +export type LarskristoHellheadsContextType = { + contractValues?: LarskristoHellheadsContractValues; + contractAddress?: string; + actions: LarskristoHellheadsContextActions; + owner?: ZeroXAddress; + tokenPrice?: TokenPrice; + royalty?: Royalty; + fetchContractValues: (address: string) => Promise; + ownerOf: (tokenId: number) => Promise; + getTokenPrice: (tokenId: number, options?: { excludeExchangeRate?: boolean }) => Promise; + royaltyInfo: (tokenId: number) => Promise; + buyToken: (tokenId: number) => Promise; + setTokenForSale: (tokenId: number, price: string) => Promise; + connectedAccountIsOwner: () => boolean; +}; diff --git a/app/src/context/evm/larskristo-hellheads/LarskristoHellheadsContextController.tsx b/app/src/context/evm/larskristo-hellheads/LarskristoHellheadsContextController.tsx new file mode 100644 index 00000000..71ab5fea --- /dev/null +++ b/app/src/context/evm/larskristo-hellheads/LarskristoHellheadsContextController.tsx @@ -0,0 +1,277 @@ +import React, { useEffect, useState } from "react"; +import { getContract } from "viem"; +import { useAccount } from "wagmi"; +import { ethers } from "ethers"; + +import { LarsKristoHellheads__factory } from "providers/evm/contracts/larskristohellheads/LarsKristoHellheads__factory"; +import currency from "providers/currency"; +import { ZeroXAddress } from "../wallet-selector/EvmWalletSelectorContext.types"; +import evm from "providers/evm"; + +import { LarskristoHellheadsContext } from "./LarskristoHellheadsContext"; +import { + LarskristoHellheadsContextActions, + LarskristoHellheadsContextControllerProps, + LarskristoHellheadsContextType, + LarskristoHellheadsContractValues, + Royalty, + TokenPrice, +} from "./LarskristoHellheadsContext.types"; + +const SEPOLIA_TESTNET_ADDRESS = "0x2abbf9c29606b4c752944942aa9952ac2cdf552b"; +const ETHEREUM_MAINNET_ADDRESS = "0x5D003EBE7348d6D3aC1a397619ED2016711d7615"; + +export const LarskristoHellheadsContextController = ({ children }: LarskristoHellheadsContextControllerProps) => { + const [contractAddress, setContractAddress] = useState(); + const [contractValues, setContractValues] = useState(); + const [owner, setOwner] = useState<`0x${string}`>(); + const [tokenPrice, setTokenPrice] = useState(); + const [royalty, setRoyaltyInfo] = useState(); + const [actions, setActions] = useState({ + fetchContractValues: { + isLoading: false, + }, + buyToken: { + isPending: false, + isConfirmed: false, + }, + setTokenForSale: { + isPending: false, + isConfirmed: false, + }, + getTokenPrice: { + isLoading: false, + }, + }); + + const { address: connectedAccountAddress } = useAccount(); + const { publicClient } = evm; + + const getContractInstance = () => + getContract({ + address: contractAddress as ZeroXAddress, + abi: LarsKristoHellheads__factory.abi, + client: publicClient, + }); + + const connectedAccountIsOwner = () => owner === connectedAccountAddress; + + const setTokenForSale = async (tokenId: number, price: string) => { + try { + setActions((prev) => ({ + ...prev, + setTokenForSale: { + isPending: true, + isConfirmed: false, + }, + })); + + const contract = getContractInstance(); + + const hash = await contract.write.setTokenForSale([BigInt(tokenId), ethers.parseEther(price)], { + account: connectedAccountAddress as ZeroXAddress, + chain: undefined, + }); + + console.log({ hash }); + + const receipt = await publicClient.waitForTransactionReceipt({ hash }); + + console.log({ receipt }); + + setActions((prev) => ({ + ...prev, + setTokenForSale: { + isPending: false, + isConfirmed: true, + transactionHash: receipt.transactionHash, + }, + })); + } catch (error) { + console.error(error); + } + }; + + const buyToken = async (tokenId: number) => { + try { + setActions((prev) => ({ + ...prev, + buyToken: { + isPending: true, + isConfirmed: false, + }, + })); + + const contract = getContractInstance(); + + const hash = await contract.write.buyToken([BigInt(tokenId)], { + account: connectedAccountAddress as ZeroXAddress, + value: tokenPrice?.rawValue!, + chain: undefined, + }); + + console.log({ hash }); + + const receipt = await publicClient.waitForTransactionReceipt({ hash }); + + console.log({ receipt }); + + setActions((prev) => ({ + ...prev, + buyToken: { + isPending: false, + isConfirmed: true, + transactionHash: receipt.transactionHash, + }, + })); + } catch (error) { + console.error(error); + } + }; + + const getTokenPrice = async (tokenId: number, options?: { excludeExchangeRate?: boolean }) => { + try { + setActions((prev) => ({ + ...prev, + getTokenPrice: { + isLoading: true, + }, + })); + + const contract = getContractInstance(); + + const rawValue = await contract.read.getTokenPrice([BigInt(tokenId)]); + const formattedValue = ethers.formatEther(rawValue); + + const values: TokenPrice = { + rawValue, + formattedValue, + }; + + if (!options?.excludeExchangeRate) { + const exchangeRate = await currency.getCoinCurrentPrice("ethereum", "usd"); + const exchangeRateFormatted = currency.formatFiatCurrency(Number(formattedValue) * exchangeRate); + values.exchangeRate = exchangeRate; + values.exchangeRateFormatted = exchangeRateFormatted; + } + + setTokenPrice(values); + + setActions((prev) => ({ + ...prev, + getTokenPrice: { + isLoading: false, + }, + })); + + return values; + } catch (error) { + console.error(error); + setTokenPrice(undefined); + } + + setActions((prev) => ({ + ...prev, + getTokenPrice: { + isLoading: false, + }, + })); + + return { + rawValue: BigInt(0), + formattedValue: "0.00", + }; + }; + + const royaltyInfo = async (tokenId: number) => { + try { + const contract = getContractInstance(); + + const [, rawValue] = await contract.read.royaltyInfo([BigInt(tokenId), tokenPrice!.rawValue]); + const percentage = Number(ethers.formatEther(rawValue)) / Number(ethers.formatEther(tokenPrice!.rawValue)); + + setRoyaltyInfo({ + rawValue, + percentage, + percentageFormatted: `${(percentage * 100).toFixed(2)}%`, + }); + } catch (error) { + console.error(error); + } + }; + + const ownerOf = async (tokenId: number) => { + try { + const contract = getContractInstance(); + + const result = await contract.read.ownerOf([BigInt(tokenId)]); + + setOwner(result); + } catch (error) { + console.error(error); + } + }; + + const fetchContractValues = async (address: string) => { + setActions((prev) => ({ + ...prev, + fetchContractValues: { + isLoading: true, + }, + })); + + try { + const contract = getContract({ + address: address as ZeroXAddress, + abi: LarsKristoHellheads__factory.abi, + client: publicClient, + }); + + const [name, symbol] = await Promise.all([contract.read.name(), contract.read.symbol()]); + + const values: LarskristoHellheadsContractValues = { + name, + symbol, + }; + + setContractValues({ ...values }); + } catch (error) { + console.error(error); + } + + setActions((prev) => ({ + ...prev, + fetchContractValues: { + isLoading: false, + }, + })); + }; + + useEffect(() => { + const address = + process.env.NEXT_PUBLIC_DEFAULT_NETWORK_ENV === "testnet" ? SEPOLIA_TESTNET_ADDRESS : ETHEREUM_MAINNET_ADDRESS; + setContractAddress(address); + + (async () => { + await fetchContractValues(address); + })(); + }, []); + + const props: LarskristoHellheadsContextType = { + fetchContractValues, + contractValues, + actions, + contractAddress, + ownerOf, + owner, + buyToken, + getTokenPrice, + tokenPrice, + royaltyInfo, + royalty, + connectedAccountIsOwner, + setTokenForSale, + }; + + return {children}; +}; diff --git a/app/src/context/evm/larskristo-hellheads/useLarskristoHellheadsContext.tsx b/app/src/context/evm/larskristo-hellheads/useLarskristoHellheadsContext.tsx new file mode 100644 index 00000000..06dd6801 --- /dev/null +++ b/app/src/context/evm/larskristo-hellheads/useLarskristoHellheadsContext.tsx @@ -0,0 +1,13 @@ +import { useContext } from "react"; + +import { LarskristoHellheadsContext } from "./LarskristoHellheadsContext"; + +export const useLarskristoHellheadsContext = () => { + const context = useContext(LarskristoHellheadsContext); + + if (context === undefined) { + throw new Error("useLarskristoHellheadsContext must be used within a LarskristoHellheadsContext"); + } + + return context; +}; diff --git a/app/src/context/evm/wallet-selector/EvmWalletSelectorContext.tsx b/app/src/context/evm/wallet-selector/EvmWalletSelectorContext.tsx new file mode 100644 index 00000000..6ee53c55 --- /dev/null +++ b/app/src/context/evm/wallet-selector/EvmWalletSelectorContext.tsx @@ -0,0 +1,5 @@ +import { createContext } from "react"; + +import { EvmWalletSelectorContextType } from "./EvmWalletSelectorContext.types"; + +export const EvmWalletSelectorContext = createContext(undefined); diff --git a/app/src/context/evm/wallet-selector/EvmWalletSelectorContext.types.ts b/app/src/context/evm/wallet-selector/EvmWalletSelectorContext.types.ts new file mode 100644 index 00000000..37eb6c7d --- /dev/null +++ b/app/src/context/evm/wallet-selector/EvmWalletSelectorContext.types.ts @@ -0,0 +1,12 @@ +import { Config } from "@wagmi/core"; +import { ReactNode } from "react"; + +export type ZeroXAddress = `0x${string}`; + +export type EvmWalletSelectorContextControllerProps = { + children: ReactNode; +}; + +export type EvmWalletSelectorContextType = { + wagmiConfig: Config; +}; diff --git a/app/src/context/evm/wallet-selector/EvmWalletSelectorContextController.tsx b/app/src/context/evm/wallet-selector/EvmWalletSelectorContextController.tsx new file mode 100644 index 00000000..7bcfb154 --- /dev/null +++ b/app/src/context/evm/wallet-selector/EvmWalletSelectorContextController.tsx @@ -0,0 +1,64 @@ +import React, { useState } from "react"; +import { defaultWagmiConfig } from "@web3modal/wagmi/react/config"; +import { createWeb3Modal } from "@web3modal/wagmi/react"; +import { WagmiProvider, cookieStorage, createStorage, http } from "wagmi"; +import { mainnet, sepolia } from "wagmi/chains"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { createConfig } from "@wagmi/core"; + +import { EvmWalletSelectorContext } from "./EvmWalletSelectorContext"; +import { + EvmWalletSelectorContextControllerProps, + EvmWalletSelectorContextType, +} from "./EvmWalletSelectorContext.types"; + +const projectId = process.env.NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID; + +if (!projectId) { + throw new Error("No WalletConnect Project Id found"); +} + +const metadata = { + name: "Web3Modal", + description: "Web3Modal Example", + url: "https://web3modal.com", + icons: ["https://avatars.githubusercontent.com/u/37784886"], +}; + +const chains = [mainnet, sepolia] as const; +const wagmiConfig = defaultWagmiConfig({ + chains, + projectId, + metadata, + ssr: true, + storage: createStorage({ + storage: cookieStorage, + }), +}); + +createWeb3Modal({ + wagmiConfig, + projectId, +}); + +export const EvmWalletSelectorContextController = ({ children }: EvmWalletSelectorContextControllerProps) => { + const [queryClient] = useState(() => new QueryClient()); + + const props: EvmWalletSelectorContextType = { + wagmiConfig: createConfig({ + chains, + transports: { + [mainnet.id]: http(), + [sepolia.id]: http(), + }, + }), + }; + + return ( + + + {children} + + + ); +}; diff --git a/app/src/context/evm/wallet-selector/useEvmWalletSelectorContext.tsx b/app/src/context/evm/wallet-selector/useEvmWalletSelectorContext.tsx new file mode 100644 index 00000000..133648b9 --- /dev/null +++ b/app/src/context/evm/wallet-selector/useEvmWalletSelectorContext.tsx @@ -0,0 +1,13 @@ +import { useContext } from "react"; + +import { EvmWalletSelectorContext } from "./EvmWalletSelectorContext"; + +export const useEvmWalletSelectorContext = () => { + const context = useContext(EvmWalletSelectorContext); + + if (context === undefined) { + throw new Error("useEvmWalletSelectorContext must be used within a EvmWalletSelectorContext"); + } + + return context; +}; diff --git a/app/src/context/file/FileContext.ts b/app/src/context/file/FileContext.ts deleted file mode 100644 index 5abd9898..00000000 --- a/app/src/context/file/FileContext.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { createContext } from "react"; - -import { FileContextType } from "./FileContext.types"; - -export const FileContext = createContext(undefined); diff --git a/app/src/context/file/FileContext.types.ts b/app/src/context/file/FileContext.types.ts deleted file mode 100644 index 2d43b4a3..00000000 --- a/app/src/context/file/FileContext.types.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { ReactNode } from "react"; -import { FileObject as SupabaseFileObject } from "@supabase/storage-js/src/lib/types"; - -import { DropzoneFileExtended } from "ui/dropzone/Dropzone.types"; - -export type FileContextControllerProps = { - children: ReactNode; -}; - -export type FileObject = SupabaseFileObject; - -export type FileContextType = { - extendFileObjects: (files: Array) => Array; - upload: (file: DropzoneFileExtended) => void; - queue: () => void; - getStorageBucketName: () => string; - getUserFiles: () => void; - userFiles: FileObject[]; -}; diff --git a/app/src/context/file/FileContextController.tsx b/app/src/context/file/FileContextController.tsx deleted file mode 100644 index cb2c9884..00000000 --- a/app/src/context/file/FileContextController.tsx +++ /dev/null @@ -1,159 +0,0 @@ -/* eslint-disable no-param-reassign */ -import React, { useCallback, useState } from "react"; -import { FileObject } from "@supabase/storage-js/src/lib/types"; - -import { useObservable } from "hooks/useObservable/useObservable"; -import { DropzoneFileExtended } from "ui/dropzone/Dropzone.types"; -import { useMessageContext } from "context/message/useMessageContext"; -import supabase from "providers/supabase"; -import { MessageFileType } from "ui/dropzone/message-file-type/MessageFileType"; -import { Typography } from "ui/typography/Typography"; -import { FormFieldNames } from "app/chat/dropbox-chat/DropboxChat.types"; -import { useAuthorizationContext } from "context/authorization/useAuthorizationContext"; - -import { FileContext } from "./FileContext"; -import { FileContextControllerProps, FileContextType } from "./FileContext.types"; - -export const FileContextController = ({ children }: FileContextControllerProps) => { - const [userFiles, setUserFiles] = useState([]); - - const observable = useObservable(); - - const queuedFiles: DropzoneFileExtended[] = []; - - const messageContext = useMessageContext(); - - const authContext = useAuthorizationContext(); - - const getStorageBucketName = () => - authContext.getGuestId() === null ? authContext.generateGuestId() : authContext.getGuestId()!; - - const getUserFiles = async () => { - try { - const { data, error } = await supabase.client.storage.from(getStorageBucketName()!).list(undefined, { - limit: 100, - offset: 0, - sortBy: { column: "name", order: "asc" }, - }); - - if (error) { - throw error; - } - - setUserFiles(data || []); - } catch (error) { - console.log(error); - } - }; - - const upload = useCallback(async (file: DropzoneFileExtended) => { - try { - const bucketName = getStorageBucketName(); - - await supabase.storage.uploadFile(bucketName, file); - - messageContext.updateMessage({ - role: "assistant", - content: `File "${file.name}" uploaded successfully. What would you like to do with it?`, - beforeContentComponent: ( - - NOTE: This file is assigned to a temporary account.{" "} - Create an account to keep it. - - ), - afterContentComponent: , - type: "file", - file, - id: messageContext.transformId(file.upload!.uuid), - }); - } catch (error) { - console.error(error); - - if ((error as Error).message === "ERR_FILE_EXISTS") { - messageContext.updateMessage({ - role: "assistant", - content: `File "${file.name}" already exists.`, - afterContentComponent: , - type: "file", - file, - id: messageContext.transformId(file.upload!.uuid), - }); - - return; - } - - if ((error as Error).message === "ERR_NETWORK_ERROR") { - messageContext.updateMessage({ - role: "assistant", - content: `File "${file.name}" failed to upload. Is your wi-fi on?`, - type: "file", - file, - id: messageContext.transformId(file.upload!.uuid), - }); - - return; - } - - messageContext.updateMessage({ - role: "assistant", - content: `File "${file.name}" failed to upload. Please, try again.`, - type: "file", - file, - id: messageContext.transformId(file.upload!.uuid), - }); - } - }, []); - - const queue = useCallback(() => { - if (queuedFiles.length === 0) { - return; - } - - const file = queuedFiles.shift(); - - upload(file!); - }, []); - - const extendFileObjects = ($files: Array) => { - const extendFile = (file: DropzoneFileExtended) => { - file.progressObservable = observable.create(file.upload!.uuid, 0); - file.setProgress = observable.set; - - queuedFiles.push(file); - - messageContext.appendMessage({ - role: "assistant", - content: `File "${file.name}" added to the queue.`, - type: "file", - file, - id: file.upload!.uuid, - }); - }; - - try { - if (typeof $files === "object" && !Array.isArray($files)) { - for (let i = 0; i < ($files as FileList).length; i += 1) { - const file = ($files as FileList).item(i); - extendFile(file as DropzoneFileExtended); - } - } else { - $files.forEach((file) => extendFile(file)); - } - } catch (error) { - console.log(error); - } - - return $files; - }; - - const props: FileContextType = { - extendFileObjects, - upload, - queue, - getStorageBucketName, - getUserFiles, - userFiles, - }; - - return {children}; -}; diff --git a/app/src/context/file/useFileContext.tsx b/app/src/context/file/useFileContext.tsx deleted file mode 100644 index 5fe9f6f5..00000000 --- a/app/src/context/file/useFileContext.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { useContext } from "react"; - -import { FileContext } from "./FileContext"; - -export const useFileContext = () => { - const context = useContext(FileContext); - - if (context === undefined) { - throw new Error("useFileContext must be used within a FileContext"); - } - - return context; -}; diff --git a/app/src/context/form/FormContext.tsx b/app/src/context/form/FormContext.tsx deleted file mode 100644 index 33852a6b..00000000 --- a/app/src/context/form/FormContext.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { createContext } from "react"; - -import { FormContextType } from "./FormContext.types"; - -export const FormContext = createContext(undefined); diff --git a/app/src/context/form/FormContext.types.ts b/app/src/context/form/FormContext.types.ts deleted file mode 100644 index 2f7573f6..00000000 --- a/app/src/context/form/FormContext.types.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { FormApi } from "final-form"; -import { Dispatch, ReactNode, SetStateAction } from "react"; - -import { ChatFormValues } from "app/chat/dropbox-chat/DropboxChat.types"; - -export type FormState = FormApi, Partial>>; - -export type FormContextControllerProps = { - children: ReactNode; -}; - -export type FormContextType = { - setForm: Dispatch>; - setCurrentMessageMetadata: Dispatch>>; - setFieldValue: (field: string, text: string) => void; - updateTextareaHeight: (id?: string) => { textarea: HTMLTextAreaElement; defaultHeight: string }; - resetTextareaHeight: () => void; - submit: (values: ChatFormValues) => Promise; -}; diff --git a/app/src/context/form/FormContextController.tsx b/app/src/context/form/FormContextController.tsx deleted file mode 100644 index dc744c7a..00000000 --- a/app/src/context/form/FormContextController.tsx +++ /dev/null @@ -1,172 +0,0 @@ -import React, { useEffect, useState } from "react"; -import { setTimeout } from "timers"; -import { sample } from "lodash"; -import { APIChatHeaderKeyNames, CurrentMessageMetadata, FileAgentRequest, FileAgentResponse } from "api/chat/types"; -import { OAuthTokenStoreKey } from "api/oauth/oauth.types"; -import axios from "axios"; - -import { useMessageContext } from "context/message/useMessageContext"; -import { ChatFormValues, FormFieldNames } from "app/chat/dropbox-chat/DropboxChat.types"; -import { ChatContextMessage, TextChatCompletionMessage } from "context/message/MessageContext.types"; -import { useRoutes } from "hooks/useRoutes/useRoutes"; -import { useAuthorizationContext } from "context/authorization/useAuthorizationContext"; -import { useFileContext } from "context/file/useFileContext"; - -import { FormContextControllerProps, FormContextType, FormState } from "./FormContext.types"; -import { FormContext } from "./FormContext"; - -const defaultHeight = "63px"; - -const processingMessages = [ - "Processing...", - "Please wait...", - "Still on it...", - "Hold on...", - "Almost there...", - "Huge file?", - "Please be patient...", -]; - -const updateTextareaHeight = (id: string = "#message") => { - const textarea = document.querySelector(id)! as HTMLTextAreaElement; - - textarea.style.height = defaultHeight; - textarea.style.height = `${textarea.scrollHeight}px`; - - return { textarea, defaultHeight }; -}; - -const resetTextareaHeight = (id: string = "#message") => { - setTimeout(() => { - const textarea = document.querySelector(id)! as HTMLTextAreaElement; - - textarea.style.height = defaultHeight; - }, 100); -}; - -export const FormContextController = ({ children }: FormContextControllerProps) => { - const [form, setForm] = useState(undefined); - const [currentMessageMetadata, setCurrentMessageMetadata] = useState({}); - - const messageContext = useMessageContext(); - - const routes = useRoutes(); - - const authContext = useAuthorizationContext(); - - const fileContext = useFileContext(); - - useEffect(() => { - setCurrentMessageMetadata({ bucketName: fileContext.getStorageBucketName() }); - }, []); - - const setFieldValue = (field: string, text: string) => { - form?.mutators.setValue(field, text); - - setTimeout(() => { - updateTextareaHeight(); - - form?.focus(field); - }, 100); - }; - - const submit = async (values: ChatFormValues) => { - if (!form) return; - - messageContext.setActions((prev) => ({ ...prev, isProcessingRequest: true })); - - const message: ChatContextMessage = { content: values.message, role: "user", type: "text" }; - - messageContext.appendMessage(message); - - const loadingMessage = messageContext.appendMessage({ - readOnly: true, - type: "text", - content: processingMessages[0], - role: "assistant", - }); - - const processingInterval = setInterval(() => { - const content = sample(processingMessages)!; - - messageContext.updateMessage({ - ...loadingMessage, - content, - }); - }, 10000); - - try { - form.reset(); - - resetTextareaHeight(); - - const messages = messageContext.getPlainMessages(); - - const currentMessage = messageContext.extractApiRequestValues(message); - - const headers: Record = {}; - - if (authContext.accessTokens[OAuthTokenStoreKey.dropbox_esign]) { - headers[APIChatHeaderKeyNames.x_dropbox_access_token] = - authContext.accessTokens[OAuthTokenStoreKey.dropbox_esign]!; - } - - if (authContext.accessTokens[OAuthTokenStoreKey.square_api]) { - headers[APIChatHeaderKeyNames.x_square_access_token] = authContext.accessTokens[OAuthTokenStoreKey.square_api]!; - } - - const options = { - method: "POST", - body: JSON.stringify({ - messages, - currentMessage, - currentMessageMetadata, - } as FileAgentRequest), - headers, - timeout: 600000, - }; - - const result = await (process.env.NEXT_PUBLIC_CHAT_AI_API === "openai" - ? axios.post(routes.api.chat.openai.completionsAPI(), options) - : axios.post(routes.api.chat.googleai.completionsAPI(), options)); - - console.log(result); - - messageContext.deleteMessage(loadingMessage.id!); - - messageContext.appendMessage({ ...result.data.choices[0].message } as TextChatCompletionMessage); - } catch (error) { - console.log(error); - - messageContext.deleteMessage(loadingMessage.id!); - - messageContext.appendMessage({ - content: `Apologies, I wasn't able to complete your request. - - - Maybe the file is too large? - - The content may be unreadable - - Check your internet connection`, - role: "assistant", - readOnly: true, - type: "text", - }); - - form.mutators.setValue(FormFieldNames.message, values.message); - } - - messageContext.setActions((prev) => ({ ...prev, isProcessingRequest: false })); - - clearInterval(processingInterval); - }; - - const props: FormContextType = { - setForm, - setFieldValue, - setCurrentMessageMetadata, - updateTextareaHeight, - resetTextareaHeight, - submit, - }; - - return {children}; -}; diff --git a/app/src/context/form/useFormContext.tsx b/app/src/context/form/useFormContext.tsx deleted file mode 100644 index 00507d4a..00000000 --- a/app/src/context/form/useFormContext.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { useContext } from "react"; - -import { FormContext } from "./FormContext"; - -export const useFormContext = () => { - const context = useContext(FormContext); - - if (context === undefined) { - throw new Error("useFormContext must be used within a FormContext"); - } - - return context; -}; diff --git a/app/src/context/message/MessageContext.ts b/app/src/context/message/MessageContext.ts deleted file mode 100644 index 8a62843c..00000000 --- a/app/src/context/message/MessageContext.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { createContext } from "react"; - -import { MessageContextType } from "./MessageContext.types"; - -export const MessageContext = createContext(undefined); diff --git a/app/src/context/message/MessageContext.types.ts b/app/src/context/message/MessageContext.types.ts deleted file mode 100644 index 83f92bdd..00000000 --- a/app/src/context/message/MessageContext.types.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { ChatCompletionMessage } from "openai/resources/chat"; -import { Dispatch, ReactNode, SetStateAction } from "react"; - -import { SquareGetLocationsMetadata } from "providers/chat/functions/square/square.types"; -import { DropzoneFileExtended } from "ui/dropzone/Dropzone.types"; - -export enum SquareAPILabel { - square_get_locations_request_success = "square:get_locations:request:success", - square_get_locations_request_error = "square:get_locations:request:error", - square_get_payments_request_success = "square:get_payments:request:success", - square_get_payments_request_error = "square:get_payments:request:error", - square_search_orders_request_success = "square:search_orders:request:success", - square_search_orders_request_error = "square:search_orders:request:error", - square_request_auth_error = "square:request:auth:error", -} - -export enum DropboxESignLabel { - dropbox_esign_request_success = "dropbox:esign:request:success", - dropbox_esign_request_error = "dropbox:esign:request:error", - dropbox_esign_unauthorized = "dropbox:esign:unauthorized", -} - -export enum ChatLabel { - chat_extract_pdf_success = "chat:extract:pdf:success", - chat_extract_pdf_error = "chat:extract:pdf:error", - chat_completion_success = "chat:completion:success", - chat_completion_error = "chat:completion:error", -} - -export type ChatMessageBase = ChatCompletionMessage & { - id?: string; - beforeContentComponent?: ReactNode; - afterContentComponent?: ReactNode; - hasInnerHtml?: boolean; // Setting this to true will render text with Markdown parsing and or HTML parsing such as anchor elements - readOnly?: boolean; - type?: "text" | "file"; - label?: DropboxESignLabel | ChatLabel | SquareAPILabel; - metadata?: SquareGetLocationsMetadata; -}; - -export type TextChatCompletionMessage = { - type: "text"; -} & ChatMessageBase; - -export type FileChatCompletionMessage = { - type: "file"; - file: DropzoneFileExtended; -} & ChatMessageBase; - -export type ChatContextMessage = FileChatCompletionMessage | TextChatCompletionMessage; - -export type MessageContextActions = { - isProcessingRequest: boolean; -}; - -export type MessageContextControllerProps = { - children: ReactNode; -}; - -export type MessageContextType = { - messages: Array; - actions: MessageContextActions; - setActions: Dispatch>; - last: () => ChatContextMessage; - displayInitialMessage: () => void; - clearMessages: () => void; - saveMessageThread: () => void; - loadMessageThread: (index: number) => void; - getMessageById: (id: string) => ChatContextMessage | undefined; - appendMessage: (message: ChatContextMessage) => ChatContextMessage; - updateMessage: (message: ChatContextMessage) => ChatContextMessage; - deleteMessage: (id: ChatContextMessage["id"]) => void; - transformId: (id: string) => string; - getPlainMessages: () => Array>; - extractApiRequestValues: (message: ChatContextMessage) => Pick; -}; diff --git a/app/src/context/message/MessageContextController.tsx b/app/src/context/message/MessageContextController.tsx deleted file mode 100644 index bdf060e9..00000000 --- a/app/src/context/message/MessageContextController.tsx +++ /dev/null @@ -1,264 +0,0 @@ -import React, { useState } from "react"; -import { v4 as uuidv4 } from "uuid"; - -import { useLocalStorage } from "hooks/useLocalStorage/useLocalStorage"; -import { MessageFileType } from "ui/dropzone/message-file-type/MessageFileType"; -import { FormFieldNames } from "app/chat/dropbox-chat/DropboxChat.types"; -import { DropzoneFileExtended } from "ui/dropzone/Dropzone.types"; -import { useChatSidebarContext } from "context/chat-sidebar/useChatSidebarContext"; -import { LocalStorageKeys } from "hooks/useLocalStorage/useLocalStorage.types"; - -import { MessageContext } from "./MessageContext"; -import { - ChatContextMessage, - MessageContextActions, - MessageContextControllerProps, - MessageContextType, -} from "./MessageContext.types"; - -const transformId = (id: string) => `x${id}`; - -export const MessageContextController = ({ children }: MessageContextControllerProps) => { - const [messages, setMessages] = useState>([]); - const [actions, setActions] = useState({ - isProcessingRequest: false, - }); - - const ls = useLocalStorage(); - - const chatSidebarContext = useChatSidebarContext(); - - const last = () => messages[messages.length - 1]; - - const extractApiRequestValues = (message: ChatContextMessage) => ({ - role: message.role, - content: message.content, - }); - - const extractLocalStorageValues = (message: ChatContextMessage) => { - const val = { - id: message.id, - role: message.role, - content: message.content, - type: message.type, - hasInnerHtml: message.hasInnerHtml, - readOnly: message.readOnly, - label: message.label, - metadata: message.metadata, - }; - - if (message.type === "file") { - (val as any).file = { - name: message.file.name, - } as Pick; - } - - return val; - }; - - const getPlainMessages = () => - messages - .map((message) => { - if (message.readOnly) { - return null; - } - - return extractApiRequestValues(message); - }) - .filter(Boolean) as ChatContextMessage[]; - - const getLocalStorageMessages = (value: ChatContextMessage[]) => - value - .map((message) => { - if (message.readOnly) { - return null; - } - - return extractLocalStorageValues(message); - }) - .filter(Boolean) as ChatContextMessage[]; - - const getMessageById = (id: string) => messages.find((message) => message.id === id); - - const appendMessage = (message: ChatContextMessage) => { - const id = message.id ? transformId(message.id) : transformId(uuidv4()); - - const msg = { ...message, id }; - - setMessages((prev) => { - const val = [...prev, msg]; - - ls.set(LocalStorageKeys.messages, getLocalStorageMessages(val)); - - return val; - }); - - return msg; - }; - - const deleteMessage = (id: ChatContextMessage["id"]) => { - setMessages((prev) => { - const i = prev.findIndex((item) => item.id === id!); - - const $prev = prev; - - $prev.splice(i, 1); - - const val = Object.assign([], { ...$prev }); - - ls.set(LocalStorageKeys.messages, getLocalStorageMessages(val)); - - return val; - }); - }; - - const updateMessage = (message: ChatContextMessage) => { - setMessages((prev) => { - const i = prev.findIndex((item) => item.id === message.id!); - - const val = Object.assign([], { ...prev, [i]: { ...message, id: message.id! } }); - - ls.set(LocalStorageKeys.messages, getLocalStorageMessages(val)); - - return val; - }); - - return message; - }; - - const clearMessages = () => { - setMessages([]); - - ls.set(LocalStorageKeys.messages, []); - - appendMessage({ - content: `Chat history cleared!`, - role: "assistant", - readOnly: true, - type: "text", - }); - }; - - const saveMessageThread = () => { - try { - const threads = ls.get(LocalStorageKeys.threads) || []; - - threads?.push(getLocalStorageMessages(messages)); - - ls.set(LocalStorageKeys.threads, threads); - - appendMessage({ - content: `Thread saved!`, - role: "assistant", - readOnly: true, - type: "text", - }); - } catch (error) { - console.log(error); - - appendMessage({ - content: `I couldn't save the thread. Please, try again.`, - role: "assistant", - readOnly: true, - type: "text", - }); - } - }; - - const loadMessageThread = (index: number) => { - try { - setMessages([]); - - const threads = ls.get(LocalStorageKeys.threads) || []; - - const lsMessages = threads[index]; - - ls.set(LocalStorageKeys.messages, lsMessages); - - lsMessages.forEach((message) => { - appendMessage({ - ...message, - id: undefined, - type: message.type === "file" ? "text" : message.type, - afterContentComponent: - message.type === "file" ? ( - - ) : undefined, - }); - }); - - chatSidebarContext.close(); - } catch { - appendMessage({ - content: `I couldn't load the thread. Please, try again.`, - role: "assistant", - readOnly: true, - type: "text", - }); - } - }; - - const displayInitialMessage = () => { - const lsMessages = ls.get(LocalStorageKeys.messages); - - if (lsMessages && lsMessages?.length > 0) { - ls.set(LocalStorageKeys.messages, []); - - appendMessage({ - content: `Welcome back!`, - role: "assistant", - readOnly: true, - type: "text", - }); - - lsMessages.forEach((message) => { - appendMessage({ - ...message, - id: undefined, - type: message.type === "file" ? "text" : message.type, - afterContentComponent: - message.type === "file" ? ( - - ) : undefined, - }); - }); - - return; - } - - appendMessage({ - content: `Hello, I'm an intelligent File Agent. You can upload PDF files (more file types in the way) and I'll try to understand and do things with them if you ask me to. - - Try uploading your first file by dragging and dropping it in the box below or by clicking the box and selecting a file from your computer.`, - role: "assistant", - readOnly: true, - type: "text", - }); - }; - - const props: MessageContextType = { - messages, - displayInitialMessage, - clearMessages, - saveMessageThread, - loadMessageThread, - getMessageById, - appendMessage, - updateMessage, - deleteMessage, - getPlainMessages, - extractApiRequestValues, - setActions, - actions, - transformId, - last, - }; - - return {children}; -}; diff --git a/app/src/context/message/useMessageContext.tsx b/app/src/context/message/useMessageContext.tsx deleted file mode 100644 index 16566f7a..00000000 --- a/app/src/context/message/useMessageContext.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { useContext } from "react"; - -import { MessageContext } from "./MessageContext"; - -export const useMessageContext = () => { - const context = useContext(MessageContext); - - if (context === undefined) { - throw new Error("useMessageContext must be used within a MessageContext"); - } - - return context; -}; diff --git a/app/src/context/near/market-contract/NearMarketContractContext.ts b/app/src/context/near/market-contract/NearMarketContractContext.ts deleted file mode 100644 index 1b8f1e80..00000000 --- a/app/src/context/near/market-contract/NearMarketContractContext.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { createContext } from "react"; - -import { NearMarketContractContextType } from "./NearMarketContractContext.types"; - -export const NearMarketContractContext = createContext(undefined); diff --git a/app/src/context/near/market-contract/NearMarketContractContext.types.ts b/app/src/context/near/market-contract/NearMarketContractContext.types.ts deleted file mode 100644 index bed7c630..00000000 --- a/app/src/context/near/market-contract/NearMarketContractContext.types.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { ReactNode } from "react"; - -import { - AccountId, - MarketContractMethods, - MarketContractValues, - OutcomeToken, -} from "providers/near/contracts/market/market.types"; - -export type NearMarketContractContextControllerProps = { - marketId: AccountId; - preventLoad?: boolean; - children: ReactNode; -}; - -export type NearMarketContractContextType = { - fetchMarketContractValues: () => Promise; - onClickResolveMarket: () => Promise; - onClickOutcomeToken: (outcomeToken: OutcomeToken) => void; - bettingPeriodExpired: () => boolean; - calculateTotalOutcomeTokensPosition: () => Promise; - marketId: AccountId; - getBalanceOf: MarketContractMethods["balance_of"]; - getAmountMintable: MarketContractMethods["get_amount_mintable"]; - getAmountPayable: MarketContractMethods["get_amount_payable"]; - sell: MarketContractMethods["sell"]; - marketContractValues?: MarketContractValues; - actions: NearMarketContractContextActions; - selectedOutcomeToken?: OutcomeToken; - outcomeTokensExtended?: OutcomeToken[]; -}; - -export type NearMarketContractContextActions = { fetchMarketContractValues: { isLoading: boolean } }; diff --git a/app/src/context/near/market-contract/NearMarketContractContextController.tsx b/app/src/context/near/market-contract/NearMarketContractContextController.tsx deleted file mode 100644 index 3c15920c..00000000 --- a/app/src/context/near/market-contract/NearMarketContractContextController.tsx +++ /dev/null @@ -1,321 +0,0 @@ -import React, { useEffect, useState } from "react"; - -import { useWalletStateContext } from "context/wallet/state/useWalletStateContext"; -import { - BalanceOfArgs, - GetAmountMintableArgs, - GetAmountPayableArgs, - MarketContractValues, - OutcomeToken, - SellArgs, -} from "providers/near/contracts/market/market.types"; -import { useToastContext } from "hooks/useToastContext/useToastContext"; -import { MarketContract } from "providers/near/contracts/market"; -import { Typography } from "ui/typography/Typography"; -import date from "providers/date"; -import currency from "providers/currency"; - -import { NearMarketContractContext } from "./NearMarketContractContext"; -import { - NearMarketContractContextActions, - NearMarketContractContextControllerProps, -} from "./NearMarketContractContext.types"; - -export const NearMarketContractContextController = ({ - children, - marketId, -}: NearMarketContractContextControllerProps) => { - const [outcomeTokensExtended, setOutcomeTokensExtended] = useState(); - const [marketContractValues, setMarketContractValues] = useState(); - const [selectedOutcomeToken, setSelectedOutcomeToken] = useState(undefined); - const [actions, setActions] = useState({ - fetchMarketContractValues: { - isLoading: false, - }, - }); - - const toast = useToastContext(); - const walletState = useWalletStateContext(); - - const fetchMarketContractValues = async () => { - setActions((prev) => ({ - ...prev, - fetchMarketContractValues: { - isLoading: true, - }, - })); - - try { - const contract = await MarketContract.loadFromGuestConnection(marketId); - const market = await contract.getMarketData(); - const price = await contract.getPricingData(); - const resolutionWindow = await contract.getResolutionWindow(); - const buySellTimestamp = await contract.getBuySellTimestamp(); - const blockTimestamp = await contract.getBlockTimestamp(); - const isOver = await contract.isOver(); - const isOpen = await contract.isOpen(); - const isResolutionWindowExpired = await contract.isResolutionWindowExpired(); - const isResolved = await contract.isResolved(); - const collateralTokenMetadata = await contract.getCollateralTokenMetadata(); - const feeRatio = await contract.getFeeRatio(); - const resolution = await contract.getResolutionData(); - - if (price) { - market.description = `Will ${price.base_currency_symbol} be above ${currency.convert.toFormattedString( - price.value, - )}?`; - } - - const outcomeTokens = ( - await Promise.all( - market.options.map((_option, outcomeId) => contract.getOutcomeToken({ outcome_id: outcomeId })), - ) - ).filter(Boolean); - - if (!outcomeTokens) { - throw new Error("ERR_FAILED_TO_FETCH_OUTCOME_TOKENS"); - } - - setMarketContractValues({ - market, - resolutionWindow, - isOver, - isResolved, - isOpen, - isResolutionWindowExpired, - collateralTokenMetadata, - outcomeTokens: outcomeTokens as Array, - feeRatio, - buySellTimestamp, - blockTimestamp, - resolution: { - ...resolution, - // @TODO set to actual feed_id from current contract - feed_id: "CfHFMUiP8BbTGkt9AvTFYzVPgoNxCz16zPD6huoRUwUB", - }, - price, - }); - - setSelectedOutcomeToken(outcomeTokens[0]); - } catch { - toast.trigger({ - variant: "error", - withTimeout: true, - // @TODO i18n - title: "Failed to fetch market data", - children: Try refreshing the page, or check your internet connection., - }); - } - - setActions((prev) => ({ - ...prev, - fetchMarketContractValues: { - isLoading: false, - }, - })); - }; - - const updatePriceMarketDescription = async () => { - const market = marketContractValues?.market; - const price = marketContractValues?.price; - - if (!market || !price) { - return; - } - - market.description = - date.now().valueOf() > market.ends_at - ? `Will ${price.base_currency_symbol} be above ${currency.convert.toFormattedString(price.value)}?` - : `Will ${price.base_currency_symbol} be above ${currency.convert.toFormattedString( - price.value, - )} ${date.timeFromNow.asDefault(market.ends_at)}?`; - - setMarketContractValues((prev) => ({ - ...prev!, - price, - })); - }; - - useEffect(() => { - if (!marketContractValues?.price) { - return undefined; - } - - updatePriceMarketDescription(); - - const interval = setInterval(async () => { - updatePriceMarketDescription(); - }, 5000); - - return () => { - clearInterval(interval); - }; - }, [marketContractValues?.price]); - - const assertWalletConnection = () => { - if (!walletState.isConnected) { - toast.trigger({ - variant: "info", - withTimeout: true, - // @TODO i18n - title: "Wallet is not connected", - children: Check your internet connection, your NEAR balance and try again., - }); - - throw new Error("ERR_USE_NEAR_MARKET_CONTRACT_INVALID_WALLET_CONNECTION"); - } - }; - - const getBalanceOf = async (args: BalanceOfArgs) => { - try { - const contract = await MarketContract.loadFromGuestConnection(marketId); - const balance = await contract.balanceOf(args); - - return balance; - } catch { - return 0; - } - }; - - const getAmountMintable = async (args: GetAmountMintableArgs) => { - try { - assertWalletConnection(); - - const [contract] = await MarketContract.loadFromWalletConnection(walletState.context.connection!, marketId); - const balance = await contract.getAmountMintable(args); - - return balance; - } catch { - toast.trigger({ - variant: "error", - withTimeout: true, - // @TODO i18n - title: "Failed to fetch amount mintable", - children: ( - Check your internet connection, your NEAR wallet connection and try again. - ), - }); - } - - return [0, 0, 0, 0, 0]; - }; - - const getAmountPayable = async (args: GetAmountPayableArgs) => { - try { - assertWalletConnection(); - - const [contract] = await MarketContract.loadFromWalletConnection(walletState.context.connection!, marketId); - const balance = await contract.getAmountPayable(args); - - return balance; - } catch { - toast.trigger({ - variant: "error", - withTimeout: true, - // @TODO i18n - title: "Failed to fetch amount payable", - children: ( - Check your internet connection, your NEAR wallet connection and try again. - ), - }); - } - - return [0, 0]; - }; - - const sell = async (args: SellArgs) => { - try { - assertWalletConnection(); - - await MarketContract.sell(walletState.context.wallet!, marketId, args); - - toast.trigger({ - variant: "confirmation", - withTimeout: false, - // @TODO i18n - title: "Success", - children: ( - {`Sold ${currency.convert.toDecimalsPrecisionString( - args.amount, - marketContractValues?.collateralTokenMetadata?.decimals!, - )} of "${marketContractValues?.market.options[args.outcome_id]}"`} - ), - }); - } catch { - toast.trigger({ - variant: "error", - withTimeout: true, - // @TODO i18n - title: "Failed to call sell method", - children: ( - Check your internet connection, your NEAR wallet connection and try again. - ), - }); - } - }; - - const calculateTotalOutcomeTokensPosition = async () => { - if (!walletState.isConnected || !marketContractValues?.outcomeTokens) { - return; - } - - const promises = marketContractValues.outcomeTokens.map((token) => - getBalanceOf({ outcome_id: token.outcome_id, account_id: walletState.address! }).then((balance_of) => ({ - ...token, - balance_of, - value: marketContractValues.market.options[token.outcome_id], - position: token.total_supply === 0 ? 0 : (balance_of / token.total_supply) * 100, - })), - ); - - const result = await Promise.all(promises); - - setOutcomeTokensExtended(result); - }; - - const onClickResolveMarket = async () => { - try { - assertWalletConnection(); - - const result = await MarketContract.aggregatorRead(walletState.context.wallet!, marketId); - - return result; - } catch { - toast.trigger({ - variant: "error", - withTimeout: true, - // @TODO i18n - title: "Failed to resolve market", - children: Check your internet connection, your NEAR balance and try again., - }); - - return false; - } - }; - - const onClickOutcomeToken = (outcomeToken: OutcomeToken) => { - setSelectedOutcomeToken(outcomeToken); - }; - - const bettingPeriodExpired = () => - !!marketContractValues?.buySellTimestamp && date.now().valueOf() > marketContractValues.buySellTimestamp; - - const props = { - marketContractValues, - fetchMarketContractValues, - getBalanceOf, - getAmountMintable, - getAmountPayable, - sell, - onClickResolveMarket, - onClickOutcomeToken, - bettingPeriodExpired, - actions, - selectedOutcomeToken, - marketId, - calculateTotalOutcomeTokensPosition, - outcomeTokensExtended, - }; - - return {children}; -}; diff --git a/app/src/context/near/market-contract/useNearMarketContractContext.tsx b/app/src/context/near/market-contract/useNearMarketContractContext.tsx deleted file mode 100644 index b08333fe..00000000 --- a/app/src/context/near/market-contract/useNearMarketContractContext.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { useContext } from "react"; - -import { NearMarketContractContext } from "./NearMarketContractContext"; - -export const useNearMarketContractContext = () => { - const context = useContext(NearMarketContractContext); - - if (context === undefined) { - throw new Error("useNearMarketContractContext must be used within a NearMarketContractContext"); - } - - return context; -}; diff --git a/app/src/context/near/market-factory-contract/NearMarketFactoryContractContext.ts b/app/src/context/near/market-factory-contract/NearMarketFactoryContractContext.ts deleted file mode 100644 index a49f25bd..00000000 --- a/app/src/context/near/market-factory-contract/NearMarketFactoryContractContext.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { createContext } from "react"; - -import { NearMarketFactoryContractContextType } from "./NearMarketFactoryContractContext.types"; - -export const NearMarketFactoryContractContext = createContext( - undefined, -); diff --git a/app/src/context/near/market-factory-contract/NearMarketFactoryContractContext.types.ts b/app/src/context/near/market-factory-contract/NearMarketFactoryContractContext.types.ts deleted file mode 100644 index 025ba769..00000000 --- a/app/src/context/near/market-factory-contract/NearMarketFactoryContractContext.types.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { ReactNode } from "react"; - -import { DeployMarketContractArgs } from "providers/near/contracts/market-factory/market-factory.types"; -import { AccountId } from "providers/near/contracts/market/market.types"; - -export type NearMarketFactoryContractContextControllerProps = { - children: ReactNode; -}; - -export type NearMarketFactoryContractContextType = { - fetchLatestPriceMarket: () => Promise; - fetchLatestPriceMarkets: () => Promise; - createMarket: (args: DeployMarketContractArgs) => Promise; - createPriceMarket: (args: PartialCreatePriceMarketContractArgs) => Promise; - latestPriceMarketsIds: string[]; - actions: NearMarketFactoryContractContextActions; - marketId?: AccountId; -}; - -export type PartialCreatePriceMarketContractArgs = { - startsAt: DeployMarketContractArgs["market"]["starts_at"]; - endsAt: DeployMarketContractArgs["market"]["ends_at"]; - resolutionWindow: DeployMarketContractArgs["resolution"]["window"]; -}; - -export type NearMarketFactoryContractContextActions = { fetchLatestPriceMarkets: { isLoading: boolean } }; diff --git a/app/src/context/near/market-factory-contract/NearMarketFactoryContractContextController.tsx b/app/src/context/near/market-factory-contract/NearMarketFactoryContractContextController.tsx deleted file mode 100644 index 1e2cc66b..00000000 --- a/app/src/context/near/market-factory-contract/NearMarketFactoryContractContextController.tsx +++ /dev/null @@ -1,211 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import React, { useState } from "react"; - -import { useWalletStateContext } from "context/wallet/state/useWalletStateContext"; -import { useToastContext } from "hooks/useToastContext/useToastContext"; -import { Typography } from "ui/typography/Typography"; -import date from "providers/date"; -import { DeployMarketContractArgs } from "providers/near/contracts/market-factory/market-factory.types"; -import near from "providers/near"; -import { MarketFactoryContract } from "providers/near/contracts/market-factory"; -import pulse from "providers/pulse"; -import switchboard from "providers/switchboard"; -import { DEFAULT_FEE_RATIO } from "providers/near/getConfig"; - -import { - NearMarketFactoryContractContextActions, - NearMarketFactoryContractContextControllerProps, - PartialCreatePriceMarketContractArgs, -} from "./NearMarketFactoryContractContext.types"; -import { NearMarketFactoryContractContext } from "./NearMarketFactoryContractContext"; - -export const NearMarketFactoryContractContextController = ({ - children, -}: NearMarketFactoryContractContextControllerProps) => { - const [marketId, setMarketId] = useState(""); - const [latestPriceMarketsIds, setLatestPriceMarketsIds] = useState([]); - const [actions, setActions] = useState({ - fetchLatestPriceMarkets: { - isLoading: false, - }, - }); - - const toast = useToastContext(); - const walletState = useWalletStateContext(); - - const assertWalletConnection = () => { - if (!walletState.isConnected) { - toast.trigger({ - variant: "error", - withTimeout: true, - // @TODO i18n - title: "Wallet is not connected", - children: Check your internet connection, your NEAR balance and try again., - }); - - throw new Error("ERR_MARKET_FACTORY_WALLET_IS_NOT_CONNECTED"); - } - }; - - const fetchLatestPriceMarkets = async () => { - setActions((prev) => ({ - ...prev, - fetchLatestPriceMarkets: { - isLoading: true, - }, - })); - - try { - const marketFactory = await MarketFactoryContract.loadFromGuestConnection(); - const marketsList = await marketFactory.get_markets_list(); - - if (!marketsList) { - throw new Error("ERR_FAILED_TO_FETCH_MARKETS"); - } - - marketsList.reverse(); - - const latest = marketsList.slice(0, 7); - - const first = [...latest].shift(); - - setLatestPriceMarketsIds(latest.filter((name) => name !== first)); - } catch { - toast.trigger({ - variant: "error", - withTimeout: true, - // @TODO i18n - title: "Failed to fetch latest price markets", - children: Try refreshing the page, or check your internet connection., - }); - } - - setActions((prev) => ({ - ...prev, - fetchLatestPriceMarkets: { - isLoading: false, - }, - })); - }; - - const fetchLatestPriceMarket = async () => { - try { - const marketFactory = await MarketFactoryContract.loadFromGuestConnection(); - const marketsList = await marketFactory.get_markets_list(); - - if (!marketsList) { - throw new Error("ERR_FAILED_TO_FETCH_MARKETS"); - } - - const latestMarketId = marketsList.pop(); - - if (!latestMarketId) { - throw new Error("ERR_MARKET_FACTORY_HAS_NO_MARKETS"); - } - - setMarketId(latestMarketId); - } catch { - toast.trigger({ - variant: "error", - withTimeout: true, - // @TODO i18n - title: "Failed to fetch recent markets", - children: Try refreshing the page, or check your internet connection., - }); - } - }; - - const createMarket = async (args: DeployMarketContractArgs) => { - try { - assertWalletConnection(); - - const contractAddress = near.getConfig().marketFactoryAccountId; - const contract = new MarketFactoryContract(contractAddress, undefined, walletState.context.wallet); - - await contract.createMarket(args); - } catch (error) { - console.log(error); - } - }; - - const createPriceMarket = async ({ - startsAt: starts_at, - endsAt: ends_at, - resolutionWindow, - }: PartialCreatePriceMarketContractArgs) => { - try { - assertWalletConnection(); - - const contractAddress = near.getConfig().marketFactoryAccountId; - const contract = new MarketFactoryContract(contractAddress, undefined, walletState.context.wallet); - - const dao_account_id = near.getConfig().marketDaoAccountId; - - const collateralToken = pulse.getConfig().COLLATERAL_TOKENS[0]; - - // @TODO set to the corresponding Switchboard aggregator feed address - const ix = { - address: [ - 173, 62, 255, 125, 45, 251, 162, 167, 128, 129, 25, 33, 146, 248, 118, 134, 118, 192, 215, 84, 225, 222, 198, - 48, 70, 49, 212, 195, 84, 136, 96, 56, - ], - }; - - const current_price = (await switchboard.fetchCurrentPrice(switchboard.jobs.testnet.near.btcUsd)).toFixed(2); - - const createPriceMarketArgs: DeployMarketContractArgs = { - market: { - description: "", - info: "", - category: "crypto", - options: ["yes", "no"], - starts_at, - ends_at, - utc_offset: date.constants.DEFAULT_TIMEZONE_OFFSET, - }, - collateral_token: { - id: collateralToken.accountId, - decimals: collateralToken.decimals, - balance: 0, - fee_balance: 0, - }, - fees: { - // 2% of 6 precision decimals - fee_ratio: DEFAULT_FEE_RATIO, - }, - resolution: { - window: resolutionWindow, - ix, - }, - management: { - dao_account_id, - }, - price: { - value: Number(current_price), - base_currency_symbol: pulse.getConfig().priceMarket.defaultBaseCurrency.symbol, - target_currency_symbol: pulse.getConfig().priceMarket.defaultTargetCurrency.symbol, - }, - }; - - await contract.createMarket(createPriceMarketArgs); - - await fetchLatestPriceMarket(); - } catch (error) { - console.log(error); - } - }; - - const props = { - fetchLatestPriceMarket, - fetchLatestPriceMarkets, - createMarket, - createPriceMarket, - latestPriceMarketsIds, - marketId, - actions, - }; - - return ( - {children} - ); -}; diff --git a/app/src/context/near/market-factory-contract/useNearMarketFactoryContractContext.tsx b/app/src/context/near/market-factory-contract/useNearMarketFactoryContractContext.tsx deleted file mode 100644 index 48712b1a..00000000 --- a/app/src/context/near/market-factory-contract/useNearMarketFactoryContractContext.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { useContext } from "react"; - -import { NearMarketFactoryContractContext } from "./NearMarketFactoryContractContext"; - -export const useNearMarketFactoryContractContext = () => { - const context = useContext(NearMarketFactoryContractContext); - - if (context === undefined) { - throw new Error("useNearMarketFactoryContractContext must be used within a NearMarketFactoryContractContext"); - } - - return context; -}; diff --git a/app/src/context/near/prompt-wars-market-contract/NearPromptWarsMarketContractContext.ts b/app/src/context/near/prompt-wars-market-contract/NearPromptWarsMarketContractContext.ts deleted file mode 100644 index db196dd9..00000000 --- a/app/src/context/near/prompt-wars-market-contract/NearPromptWarsMarketContractContext.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { createContext } from "react"; - -import { NearPromptWarsMarketContractContextContextType } from "./NearPromptWarsMarketContractContextContext.types"; - -export const NearPromptWarsMarketContractContext = createContext< - NearPromptWarsMarketContractContextContextType | undefined ->(undefined); diff --git a/app/src/context/near/prompt-wars-market-contract/NearPromptWarsMarketContractContextContext.types.ts b/app/src/context/near/prompt-wars-market-contract/NearPromptWarsMarketContractContextContext.types.ts deleted file mode 100644 index acb88129..00000000 --- a/app/src/context/near/prompt-wars-market-contract/NearPromptWarsMarketContractContextContext.types.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { ReactNode } from "react"; - -import { - AccountId, - GetOutcomeTokenArgs, - OutcomeToken, - Prompt, - PromptWarsMarketContractValues, -} from "providers/near/contracts/prompt-wars/prompt-wars.types"; - -export type NearPromptWarsMarketContractContextControllerProps = { - marketId: AccountId; - preventLoad?: boolean; - children: ReactNode; -}; - -export type NearPromptWarsMarketContractContextContextType = { - fetchMarketContractValues: () => Promise; - ftTransferCall: (prompt: Prompt) => Promise; - sell: () => Promise; - create: () => Promise; - getOutcomeToken: (args: GetOutcomeTokenArgs) => Promise; - marketId: AccountId; - marketContractValues?: PromptWarsMarketContractValues; - actions: NearPromptWarsMarketContractContextContextActions; -}; - -export type NearPromptWarsMarketContractContextContextActions = { - fetchMarketContractValues: { isLoading: boolean }; - ftTransferCall: { - isLoading: boolean; - }; - create: { - isLoading: boolean; - }; -}; diff --git a/app/src/context/near/prompt-wars-market-contract/NearPromptWarsMarketContractContextController.tsx b/app/src/context/near/prompt-wars-market-contract/NearPromptWarsMarketContractContextController.tsx deleted file mode 100644 index 8186f971..00000000 --- a/app/src/context/near/prompt-wars-market-contract/NearPromptWarsMarketContractContextController.tsx +++ /dev/null @@ -1,326 +0,0 @@ -import React, { useState } from "react"; -import { setTimeout } from "timers"; -import { useRouter } from "next/router"; - -import { useToastContext } from "hooks/useToastContext/useToastContext"; -import { Typography } from "ui/typography/Typography"; -import { PromptWarsMarketContract } from "providers/near/contracts/prompt-wars/contract"; -import { - GetOutcomeTokenArgs, - Prompt, - PromptWarsMarketContractStatus, - PromptWarsMarketContractValues, -} from "providers/near/contracts/prompt-wars/prompt-wars.types"; -import { useWalletStateContext } from "context/wallet/state/useWalletStateContext"; -import { FungibleTokenContract } from "providers/near/contracts/fungible-token/contract"; -import currency from "providers/currency"; -import { useRoutes } from "hooks/useRoutes/useRoutes"; - -import { - NearPromptWarsMarketContractContextContextActions, - NearPromptWarsMarketContractContextControllerProps, -} from "./NearPromptWarsMarketContractContextContext.types"; -import { NearPromptWarsMarketContractContext } from "./NearPromptWarsMarketContractContext"; - -let marketContract: PromptWarsMarketContract; - -export const NearPromptWarsMarketContractContextController = ({ - children, - marketId, -}: NearPromptWarsMarketContractContextControllerProps) => { - const [marketContractValues, setMarketContractValues] = useState(); - const [actions, setActions] = useState({ - fetchMarketContractValues: { - isLoading: false, - }, - ftTransferCall: { - isLoading: false, - }, - create: { - isLoading: false, - }, - }); - - const routes = useRoutes(); - const router = useRouter(); - - const toast = useToastContext(); - - const walletState = useWalletStateContext(); - - const getMarketStatus = (values: PromptWarsMarketContractValues): PromptWarsMarketContractStatus => { - if (!values) { - return PromptWarsMarketContractStatus.LOADING; - } - - if (values?.isOpen) { - return PromptWarsMarketContractStatus.OPEN; - } - - if (values?.isOver && values.isResolved) { - return PromptWarsMarketContractStatus.RESOLVED; - } - - if (values?.isOver && !values.isRevealWindowExpired) { - return PromptWarsMarketContractStatus.REVEALING; - } - - if (values?.isOver && !values.isResolutionWindowExpired) { - return PromptWarsMarketContractStatus.RESOLVING; - } - - if (values?.isOver && values.isExpiredUnresolved) { - return PromptWarsMarketContractStatus.UNRESOLVED; - } - - return PromptWarsMarketContractStatus.CLOSED; - }; - - const fetchMarketContractValues = async () => { - setActions((prev) => ({ - ...prev, - fetchMarketContractValues: { - isLoading: true, - }, - })); - - try { - // Wait 1 second to allow flags to change - setTimeout(async () => { - try { - const contract = await PromptWarsMarketContract.loadFromGuestConnection(marketId); - - const [ - market, - resolution, - fees, - management, - collateralToken, - outcomeIds, - isResolved, - isOpen, - isOver, - isRevealWindowExpired, - isResolutionWindowExpired, - isExpiredUnresolved, - ] = await Promise.all([ - contract.get_market_data(), - contract.get_resolution_data(), - contract.get_fee_data(), - contract.get_management_data(), - contract.get_collateral_token_metadata(), - contract.get_outcome_ids(), - contract.is_resolved(), - contract.is_open(), - contract.is_over(), - contract.is_reveal_window_expired(), - contract.is_resolution_window_expired(), - contract.is_expired_unresolved(), - ]); - - const values: PromptWarsMarketContractValues = { - market, - resolution, - fees, - management, - collateralToken, - outcomeIds, - isResolved, - isOpen, - isOver, - isRevealWindowExpired, - isResolutionWindowExpired, - isExpiredUnresolved, - status: PromptWarsMarketContractStatus.LOADING, - }; - - const status = getMarketStatus(values); - - values.status = status; - - setMarketContractValues(values); - } catch (error) { - console.log(error); - } - }, 1000); - } catch { - toast.trigger({ - variant: "error", - withTimeout: true, - title: "Failed to fetch market data", - children: Try refreshing the page, or check your internet connection., - }); - } - - setActions((prev) => ({ - ...prev, - fetchMarketContractValues: { - isLoading: false, - }, - })); - }; - - const assertWalletConnection = () => { - if (!walletState.isConnected) { - toast.trigger({ - variant: "info", - withTimeout: true, - title: "Wallet is not connected", - children: Check your internet connection, your NEAR balance and try again., - }); - - throw new Error("ERR_USE_NEAR_MARKET_CONTRACT_INVALID_WALLET_CONNECTION"); - } - }; - - const ftTransferCall = async (prompt: Prompt) => { - if (!marketContractValues) { - return; - } - - try { - assertWalletConnection(); - - setActions((prev) => ({ - ...prev, - ftTransferCall: { - ...prev.ftTransferCall, - isLoading: true, - }, - })); - - const amount = marketContractValues.fees.price.toString(); - const msg = JSON.stringify({ CreateOutcomeTokenArgs: { prompt: JSON.stringify(prompt) } }); - - await FungibleTokenContract.ftTransferCall( - walletState.context.wallet!, - marketContractValues.collateralToken.id!, - { - receiver_id: marketId, - amount, - msg, - }, - ); - - setActions((prev) => ({ - ...prev, - ftTransferCall: { - ...prev.ftTransferCall, - isLoading: false, - }, - })); - - toast.trigger({ - variant: "confirmation", - withTimeout: false, - title: "Your prompt was successfully submitted", - children: ( - {`Transferred USDT ${currency.convert.toDecimalsPrecisionString( - amount, - marketContractValues.collateralToken.decimals!, - )} to ${marketId}`} - ), - }); - - fetchMarketContractValues(); - } catch { - toast.trigger({ - variant: "error", - title: "Failed to make transfer call", - children: Check your internet connection, connect your wallet and try again., - }); - } - }; - - const sell = async () => { - try { - assertWalletConnection(); - - await PromptWarsMarketContract.sell(walletState.context.wallet!, marketId); - - toast.trigger({ - variant: "confirmation", - withTimeout: false, - title: "Success", - children: Check your new wallet balance., - }); - } catch { - toast.trigger({ - variant: "error", - withTimeout: true, - title: "Failed to call sell method", - children: ( - Check your internet connection, your NEAR wallet connection and try again. - ), - }); - } - }; - - const getOutcomeToken = async (args: GetOutcomeTokenArgs) => { - try { - if (!marketContract) { - marketContract = await PromptWarsMarketContract.loadFromGuestConnection(marketId); - } - - const outcomeToken = await marketContract.get_outcome_token(args); - - return outcomeToken; - } catch (error) { - console.log(error); - } - - return undefined; - }; - - const create = async () => { - setActions((prev) => ({ - ...prev, - create: { - isLoading: true, - }, - })); - - try { - const response = await fetch(routes.api.promptWars.create()); - - if (!response.ok) { - throw new Error("ERR_USE_NEAR_PROMPT_WARS_MARKET_CONTRACT_CREATE_FAILED"); - } - - router.push(routes.dashboard.promptWars.home()); - } catch (error) { - console.log(error); - - toast.trigger({ - variant: "error", - withTimeout: false, - title: "Failed to create a new market", - children: The server must have run out of funds. Please try again later., - }); - } - - setActions((prev) => ({ - ...prev, - create: { - isLoading: false, - }, - })); - }; - - const props = { - fetchMarketContractValues, - marketContractValues, - ftTransferCall, - sell, - getOutcomeToken, - actions, - marketId, - create, - }; - - return ( - - {children} - - ); -}; diff --git a/app/src/context/near/prompt-wars-market-contract/useNearPromptWarsMarketContractContext.tsx b/app/src/context/near/prompt-wars-market-contract/useNearPromptWarsMarketContractContext.tsx deleted file mode 100644 index 2813e587..00000000 --- a/app/src/context/near/prompt-wars-market-contract/useNearPromptWarsMarketContractContext.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { useContext } from "react"; - -import { NearPromptWarsMarketContractContext } from "./NearPromptWarsMarketContractContext"; - -export const useNearPromptWarsMarketContractContext = () => { - const context = useContext(NearPromptWarsMarketContractContext); - - if (context === undefined) { - throw new Error("useNearPromptWarsMarketContractContext must be used within a NearPromptWarsMarketContractContext"); - } - - return context; -}; diff --git a/app/src/context/near/wallet-selector/NearWalletSelectorContext.ts b/app/src/context/near/wallet-selector/NearWalletSelectorContext.ts deleted file mode 100644 index f209ee6e..00000000 --- a/app/src/context/near/wallet-selector/NearWalletSelectorContext.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { createContext } from "react"; - -import { NearWalletSelectorContextType } from "./NearWalletSelectorContext.types"; - -export const NearWalletSelectorContext = createContext(undefined); diff --git a/app/src/context/near/wallet-selector/NearWalletSelectorContext.types.ts b/app/src/context/near/wallet-selector/NearWalletSelectorContext.types.ts deleted file mode 100644 index 3aae9b43..00000000 --- a/app/src/context/near/wallet-selector/NearWalletSelectorContext.types.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { WalletSelector } from "@near-wallet-selector/core"; -import { WalletSelectorModal } from "@near-wallet-selector/modal-ui"; -import { ReactNode } from "react"; - -export type NearWalletSelectorContextControllerProps = { - children: ReactNode; -}; - -export type NearWalletSelectorContextType = { - selector?: WalletSelector; - modal?: WalletSelectorModal; - initModal: (contractId: string) => void; - signOut: () => Promise; -}; - -export type NEARSignInOptions = { - contractId?: string; - methodNames?: string[]; - successUrl?: string; - failureUrl?: string; -}; diff --git a/app/src/context/near/wallet-selector/NearWalletSelectorContextController.tsx b/app/src/context/near/wallet-selector/NearWalletSelectorContextController.tsx deleted file mode 100644 index 7447c2bc..00000000 --- a/app/src/context/near/wallet-selector/NearWalletSelectorContextController.tsx +++ /dev/null @@ -1,253 +0,0 @@ -import React, { useEffect, useState } from "react"; -import { BrowserWallet, NetworkId, setupWalletSelector, WalletSelector } from "@near-wallet-selector/core"; -import { setupModal, WalletSelectorModal } from "@near-wallet-selector/modal-ui"; -import { setupNearWallet } from "@near-wallet-selector/near-wallet"; -import { setupNearFi } from "@near-wallet-selector/nearfi"; -import { setupHereWallet } from "@near-wallet-selector/here-wallet"; -import { setupMathWallet } from "@near-wallet-selector/math-wallet"; -import { setupSender } from "@near-wallet-selector/sender"; -import { setupNightly } from "@near-wallet-selector/nightly"; -import { setupMeteorWallet } from "@near-wallet-selector/meteor-wallet"; -import { setupLedger } from "@near-wallet-selector/ledger"; -import { setupCoin98Wallet } from "@near-wallet-selector/coin98-wallet"; -import { setupMyNearWallet } from "@near-wallet-selector/my-near-wallet"; - -import near from "providers/near"; -import { useWalletStateContext } from "context/wallet/state/useWalletStateContext"; -import { WalletSelectorChain } from "context/wallet-selector/WalletSelectorContext.types"; -import { useRoutes } from "hooks/useRoutes/useRoutes"; -import { setupGuestWallet } from "providers/near/wallet-selector/setupGuestWallet"; -import { useLocalStorage } from "hooks/useLocalStorage/useLocalStorage"; - -import { NearWalletSelectorContextControllerProps } from "./NearWalletSelectorContext.types"; -import { NearWalletSelectorContext } from "./NearWalletSelectorContext"; - -export const NearWalletSelectorContextController = ({ children }: NearWalletSelectorContextControllerProps) => { - const [selector, setSelector] = useState(); - const [modal, setModal] = useState(); - - const walletStateContext = useWalletStateContext(); - - const routes = useRoutes(); - const ls = useLocalStorage(); - - const initGuestConnection = async (accountId: string) => { - console.log(`initGuestConnection: ${accountId}`); - - try { - const connection = await near.initWalletConnection(); - - const { near: nearAPI, wallet: nearWalletConnection } = connection; - - const wallet = await selector?.wallet("guest-wallet"); - - await (wallet as BrowserWallet)?.signIn({ contractId: near.getConfig().factoryWalletId }); - - walletStateContext.setContext({ - wallet, - connection: nearWalletConnection, - provider: nearAPI, - guest: { - address: accountId, - }, - }); - - walletStateContext.setIsConnected(true); - walletStateContext.setAddress(accountId); - walletStateContext.setNetwork(near.getConfig().networkId as NetworkId); - walletStateContext.setChain(WalletSelectorChain.near); - walletStateContext.setExplorer(near.getConfig().explorerUrl); - - const accountBalance = await near.getAccountBalance(nearAPI, accountId); - - walletStateContext.setBalance(near.formatAccountBalance(accountBalance.available, 8)); - } catch (error) { - console.log(error); - } - - walletStateContext.setActions((prev) => ({ - ...prev, - isGettingGuestWallet: false, - })); - }; - - const onSignedIn = async (s: WalletSelector) => { - try { - const connection = await near.initWalletConnection(); - - const { near: nearAPI, wallet: nearWalletConnection } = connection; - - walletStateContext.setContext({ - connection: nearWalletConnection, - provider: nearAPI, - guest: { - address: near.getConfig().guestWalletId, - }, - }); - - const wallet = await s?.wallet(); - - if (!wallet) { - return; - } - - const [account] = await wallet.getAccounts(); - - walletStateContext.setContext({ - wallet, - connection: nearWalletConnection, - provider: nearAPI, - guest: { - address: account.accountId, - }, - }); - - walletStateContext.setIsConnected(s.isSignedIn()); - walletStateContext.setAddress(account.accountId); - walletStateContext.setNetwork(near.getConfig().networkId as NetworkId); - walletStateContext.setChain(WalletSelectorChain.near); - walletStateContext.setExplorer(near.getConfig().explorerUrl); - - const accountBalance = await near.getAccountBalance(nearAPI, account.accountId); - - walletStateContext.setBalance(near.formatAccountBalance(accountBalance.available, 8)); - } catch (error) { - console.log(error); - } - }; - - const signOut = async () => { - try { - const wallet = await selector?.wallet()!; - - await wallet.signOut(); - } catch (error) { - console.log(error); - } - - walletStateContext.reset(); - }; - - useEffect(() => { - (async () => { - try { - const network = near.getConfig().networkId as NetworkId; - - const walletSelector = await setupWalletSelector({ - network, - modules: [ - setupGuestWallet(), - setupNearWallet(), - setupMyNearWallet(), - setupNearFi(), - setupHereWallet(), - setupMathWallet(), - setupSender(), - setupNightly(), - setupMeteorWallet(), - setupLedger(), - setupCoin98Wallet(), - ], - }); - - const onSignedInSub = walletSelector.on("signedIn", () => onSignedIn(walletSelector)); - - setSelector(walletSelector); - - return () => { - onSignedInSub.remove(); - }; - } catch (error) { - console.log(error); - } - - return undefined; - })(); - }, []); - - useEffect(() => { - if (!selector) { - return; - } - - (async () => { - try { - const wallet = await selector?.wallet(); - - if (!wallet) { - return; - } - - onSignedIn(selector!); - } catch (error) { - console.log(error); - } - })(); - }, [selector]); - - useEffect(() => { - (async () => { - try { - if (ls.get("near_app_wallet_auth_key") !== null) { - console.log(`existing non-guest wallet connected`); - - return; - } - - walletStateContext.setActions((prev) => ({ - ...prev, - isGettingGuestWallet: true, - })); - - const walletAuthKey = ls.get<{ - accountId: string; - allKeys: Array; - }>("promptwars_wallet_auth_key"); - - if (walletAuthKey !== null && /^guest-/i.test(walletAuthKey?.accountId)) { - initGuestConnection(walletAuthKey.accountId); - - return; - } - - const response = await fetch(routes.api.promptWars.createGuestAccount()); - const result = await response.json(); - - ls.set("near-wallet-selector:selectedWalletId", JSON.stringify("guest-wallet")); - ls.set(Object.keys(result)[0], result[Object.keys(result)[0]]); - ls.set(Object.keys(result)[1], result[Object.keys(result)[1]]); - ls.set(Object.keys(result)[2], result[Object.keys(result)[2]]); - - console.log(result); - - const { accountId } = result.promptwars_wallet_auth_key; - - initGuestConnection(accountId); - } catch (error) { - console.log(error); - - walletStateContext.setActions((prev) => ({ - ...prev, - isGettingGuestWallet: false, - })); - } - })(); - }, []); - - const initModal = (contractId: string) => { - setModal( - setupModal(selector!, { - contractId, - }), - ); - }; - - const props = { - selector, - modal, - initModal, - signOut, - }; - - return {children}; -}; diff --git a/app/src/context/near/wallet-selector/useNearWalletSelectorContext.tsx b/app/src/context/near/wallet-selector/useNearWalletSelectorContext.tsx deleted file mode 100644 index a015fdbd..00000000 --- a/app/src/context/near/wallet-selector/useNearWalletSelectorContext.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { useContext } from "react"; - -import { NearWalletSelectorContext } from "context/near/wallet-selector/NearWalletSelectorContext"; - -export const useNearWalletSelectorContext = () => { - const context = useContext(NearWalletSelectorContext); - - if (context === undefined) { - throw new Error("useNearWalletSelectorContext must be used within a NearWalletSelectorContext"); - } - - return context; -}; diff --git a/app/src/context/theme/ThemeContextController.tsx b/app/src/context/theme/ThemeContextController.tsx index cb8b8c48..897b2e3a 100644 --- a/app/src/context/theme/ThemeContextController.tsx +++ b/app/src/context/theme/ThemeContextController.tsx @@ -7,10 +7,10 @@ import { LocalStorageKeys } from "hooks/useLocalStorage/useLocalStorage.types"; import { ThemeContext } from "./ThemeContext"; import { ThemeContextControllerProps } from "./ThemeContext.types"; -const themes: Theme[] = ["fileagent", "fileagent-dark"]; +const themes: Theme[] = ["svpervnder"]; export const ThemeContextController = ({ children }: ThemeContextControllerProps) => { - const [theme, setTheme] = useState("fileagent"); + const [theme, setTheme] = useState("svpervnder"); const localStorage = useLocalStorage(); diff --git a/app/src/context/wallet-selector/WalletSelectorContext.ts b/app/src/context/wallet-selector/WalletSelectorContext.ts deleted file mode 100644 index 09c43777..00000000 --- a/app/src/context/wallet-selector/WalletSelectorContext.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { createContext } from "react"; - -import { WalletSelectorContextType } from "./WalletSelectorContext.types"; - -export const WalletSelectorContext = createContext(undefined); diff --git a/app/src/context/wallet-selector/WalletSelectorContext.types.ts b/app/src/context/wallet-selector/WalletSelectorContext.types.ts deleted file mode 100644 index af3db8ee..00000000 --- a/app/src/context/wallet-selector/WalletSelectorContext.types.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Near, WalletConnection as NEARWalletConnection } from "near-api-js"; -import { ReactNode } from "react"; - -import { NEARSignInOptions } from "context/near/wallet-selector/NearWalletSelectorContext.types"; - -export type WalletSelectorContextControllerProps = { - children: ReactNode; -} & WalletSelectorContextType; - -export enum WalletSelectorChain { - near = "near", -} - -export type WalletSelectorContextType = { - address?: string | null; - network?: string; - explorer?: string; - balance: string; - chain?: WalletSelectorChain; - isConnected: boolean; - onSetChain: (chain: WalletSelectorChain) => void; - onClickConnect: (args?: NEARSignInOptions) => void; - onClickDisconnect: () => void; - onSignedIn: () => void; - context: { - connection: NEARWalletConnection | undefined; - provider: Near | undefined; - guest: { address: string }; - }; -}; diff --git a/app/src/context/wallet-selector/WalletSelectorContextController.tsx b/app/src/context/wallet-selector/WalletSelectorContextController.tsx deleted file mode 100644 index 41b1c4ab..00000000 --- a/app/src/context/wallet-selector/WalletSelectorContextController.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import React from "react"; - -import { WalletSelectorContext } from "./WalletSelectorContext"; -import { WalletSelectorContextControllerProps } from "./WalletSelectorContext.types"; - -export const WalletSelectorContextController = ({ children, ...props }: WalletSelectorContextControllerProps) => ( - {children} -); diff --git a/app/src/context/wallet/state/WalletStateContext.ts b/app/src/context/wallet/state/WalletStateContext.ts deleted file mode 100644 index 6f207472..00000000 --- a/app/src/context/wallet/state/WalletStateContext.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { createContext } from "react"; - -import { WalletStateContextType } from "./WalletStateContext.types"; - -export const WalletStateContext = createContext(undefined); diff --git a/app/src/context/wallet/state/WalletStateContext.types.ts b/app/src/context/wallet/state/WalletStateContext.types.ts deleted file mode 100644 index 2019acf8..00000000 --- a/app/src/context/wallet/state/WalletStateContext.types.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { NetworkId, Wallet } from "@near-wallet-selector/core"; -import { Near, WalletConnection as NEARWalletConnection } from "near-api-js"; -import { Dispatch, SetStateAction } from "react"; - -import { WalletSelectorChain } from "context/wallet-selector/WalletSelectorContext.types"; - -export type Address = string | undefined; -export type Explorer = string | undefined; -export type Balance = string | undefined; -export type Chain = WalletSelectorChain | undefined; -export type IsConnected = boolean; -export type Network = NetworkId | undefined; - -export type Context = { - wallet?: Wallet; - connection?: NEARWalletConnection; - provider?: Near; - guest: { address: Address }; -}; - -export type StateActions = { - isGettingGuestWallet: boolean; -}; - -export type WalletStateContextType = { - reset: () => void; - setAddress: Dispatch>; - setNetwork: Dispatch>; - setExplorer: Dispatch>; - setBalance: Dispatch>; - setChain: Dispatch>; - setIsConnected: Dispatch>; - setContext: Dispatch>; - setActions: Dispatch>; - address: Address; - network: Network; - explorer: Explorer; - balance: Balance; - chain: Chain; - isConnected: IsConnected; - context: Context; - actions: StateActions; -}; diff --git a/app/src/context/wallet/state/WalletStateContextController.tsx b/app/src/context/wallet/state/WalletStateContextController.tsx deleted file mode 100644 index c27e1211..00000000 --- a/app/src/context/wallet/state/WalletStateContextController.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { ReactNode, useState } from "react"; -import { NetworkId } from "@near-wallet-selector/core"; - -import { Address, Balance, Chain, Context, Explorer, IsConnected, StateActions } from "./WalletStateContext.types"; -import { WalletStateContext } from "./WalletStateContext"; - -export const WalletStateContextController = ({ children }: { children: ReactNode }) => { - const [network, setNetwork] = useState("testnet"); - const [explorer, setExplorer] = useState(undefined); - const [chain, setChain] = useState(undefined); - const [address, setAddress] = useState
(undefined); - const [balance, setBalance] = useState("0.00"); - const [isConnected, setIsConnected] = useState(false); - const [context, setContext] = useState({ - connection: undefined, - provider: undefined, - guest: { - address: "", - }, - }); - const [actions, setActions] = useState({ - isGettingGuestWallet: false, - }); - - const reset = () => { - setNetwork(undefined); - setExplorer(undefined); - setChain(undefined); - setAddress(undefined); - setBalance("0.00"); - setIsConnected(false); - setActions({ isGettingGuestWallet: false }); - }; - - const props = { - setNetwork, - setAddress, - setExplorer, - setChain, - setBalance, - setIsConnected, - setContext, - setActions, - network, - address, - explorer, - chain, - balance, - isConnected, - reset, - context, - actions, - }; - - return {children}; -}; diff --git a/app/src/context/wallet/state/useWalletStateContext.tsx b/app/src/context/wallet/state/useWalletStateContext.tsx deleted file mode 100644 index 7183f0f8..00000000 --- a/app/src/context/wallet/state/useWalletStateContext.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { useContext } from "react"; - -import { WalletStateContext } from "context/wallet/state/WalletStateContext"; - -export const useWalletStateContext = () => { - const context = useContext(WalletStateContext); - - if (context === undefined) { - throw new Error("useWalletStateContext must be used within a WalletStateContext"); - } - - return context; -}; diff --git a/app/src/hooks/useDebounce/useDebounce.ts b/app/src/hooks/useDebounce/useDebounce.ts index 0430834b..95349551 100644 --- a/app/src/hooks/useDebounce/useDebounce.ts +++ b/app/src/hooks/useDebounce/useDebounce.ts @@ -1,6 +1,6 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import { useRef, useCallback } from "react"; -// eslint-disable-next-line @typescript-eslint/no-explicit-any export function useDebounce void>(callback: T, delay: number): T[] { const functionTimeoutHandler = useRef(null); @@ -15,7 +15,7 @@ export function useDebounce void>(callback: T, del }, []); const debouncedCallback = useCallback( - (...args) => { + (...args: any[]) => { cancelDebouncedCallback(); functionTimeoutHandler.current = setTimeout(() => { debouncedFunction.current(...args); diff --git a/app/src/hooks/useLocalStorage/useLocalStorage.types.ts b/app/src/hooks/useLocalStorage/useLocalStorage.types.ts index 8bb21d64..e412848d 100644 --- a/app/src/hooks/useLocalStorage/useLocalStorage.types.ts +++ b/app/src/hooks/useLocalStorage/useLocalStorage.types.ts @@ -3,4 +3,5 @@ export enum LocalStorageKeys { threads = "threads", messages = "messages", theme = "theme", + openAISessionID = "openAISessionID", } diff --git a/app/src/hooks/useRoutes/useRoutes.tsx b/app/src/hooks/useRoutes/useRoutes.tsx index 16fbc7eb..3e0f0a88 100644 --- a/app/src/hooks/useRoutes/useRoutes.tsx +++ b/app/src/hooks/useRoutes/useRoutes.tsx @@ -14,6 +14,7 @@ type RouteMap = { dropboxESign: () => string; openai: { completionsAPI: () => string; + assistantsAPI: () => string; }; googleai: { completionsAPI: () => string; @@ -38,18 +39,19 @@ export const routes: RouteMap = { }, api: { promptWars: { - createGuestAccount: () => `${process.env.NEXT_PUBLIC_ORIGIN}/api/prompt-wars/create-guest-account`, - create: () => `${process.env.NEXT_PUBLIC_ORIGIN}/api/prompt-wars/create`, - reveal: () => `${process.env.NEXT_PUBLIC_ORIGIN}/api/prompt-wars/reveal`, - resolve: () => `${process.env.NEXT_PUBLIC_ORIGIN}/api/prompt-wars/resolve`, + createGuestAccount: () => `/api/prompt-wars/create-guest-account`, + create: () => `/api/prompt-wars/create`, + reveal: () => `/api/prompt-wars/reveal`, + resolve: () => `/api/prompt-wars/resolve`, }, chat: { - dropboxESign: () => `${process.env.NEXT_PUBLIC_ORIGIN}/api/chat/dropbox-e-sign`, + dropboxESign: () => `/api/chat/dropbox-e-sign`, openai: { - completionsAPI: () => `${process.env.NEXT_PUBLIC_ORIGIN}/api/chat/openai/completions`, + completionsAPI: () => `/api/chat/openai/completions`, + assistantsAPI: () => `/api/chat/openai/assistant`, }, googleai: { - completionsAPI: () => `${process.env.NEXT_PUBLIC_ORIGIN}/api/chat/googleai/completions`, + completionsAPI: () => `/api/chat/googleai/completions`, }, }, }, diff --git a/app/src/layouts/chat-layout/ChatLayout.tsx b/app/src/layouts/chat-layout/ChatLayout.tsx deleted file mode 100644 index 5fcab9fa..00000000 --- a/app/src/layouts/chat-layout/ChatLayout.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import clsx from "clsx"; -import Head from "next/head"; -import { useRouter } from "next/router"; - -import { MainPanel } from "ui/mainpanel/MainPanel"; -import { ToastContextController } from "context/toast/ToastContextController"; -import { FileContextController } from "context/file/FileContextController"; -import { MessageContextController } from "context/message/MessageContextController"; -import { FormContextController } from "context/form/FormContextController"; -import { Navbar } from "ui/fileagent/navbar/Navbar"; -import { AuthorizationContextController } from "context/authorization/AuthorizationContextController"; -import { ThemeContextController } from "context/theme/ThemeContextController"; -import { ChatSidebar } from "ui/fileagent/chat-sidebar/ChatSidebar"; -import { ChatSidebarContextController } from "context/chat-sidebar/ChatSidebarContextController"; -import { Sheet } from "ui/shadcn/sheet/Sheet"; - -import { ChatLayoutProps } from "./ChatLayout.types"; -import styles from "./ChatLayout.module.scss"; - -export const ChatLayout: React.FC = ({ children }) => { - const { locale } = useRouter(); - - return ( - <> - - - - - - - - - - - - - - - -