diff --git a/.gitignore b/.gitignore index c58ac68e..3581feab 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,8 @@ /node_modules /.pnp .pnp.js - +/src/graphql/node_modules +/src/graphql/src/generated # testing /coverage diff --git a/package.json b/package.json index 413b8fd1..f53b6dd8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "intuition-chrome-extension", "displayName": "Intuition Chrome Extension", - "version": "0.1.45", + "version": "0.1.46", "description": "", "author": "THP-Lab.org", "scripts": { @@ -24,8 +24,10 @@ "@radix-ui/react-slot": "^1.1.2", "@tanstack/react-query": "^5.69.0", "@types/three": "^0.175.0", + "@warzieram/graphql": "^0.5.31", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "ethers": "^6.15.0", "graphql": "^16.10.0", "graphql-request": "^7.1.2", "graphql-ws": "^6.0.4", @@ -75,7 +77,8 @@ "host_permissions": [ "https://*/*", "https://analytics.thp.box/*", - "https://prod.base.intuition-api.com/*", + "https://prod.base-sepolia-v-1-5.intuition.sh/v1/graphql", + "https://prod.base-mainnet-v-1-0.intuition.sh/*", "chrome-extension://*/*", "ws://localhost:*", "wws://localhost:*" @@ -101,7 +104,7 @@ "sidePanel" ], "content_security_policy": { - "extension_pages": "script-src 'self'; object-src 'self'; connect-src 'self' https://prod.base.intuition-api.com/ https://cloud.umami.is/ https://analytics.thp.box/ https://api.ipify.org wss://prod.base.intuition-api.com/v1/graphql ws://localhost:* wss://localhost:* https://dl.polyhaven.org https://www.gstatic.com;" + "extension_pages": "script-src 'self'; object-src 'self'; connect-src 'self' https://prod.base.intuition-api.com https://prod.base-mainnet-v-1-0.intuition.sh https://cloud.umami.is/ https://analytics.thp.box/ https://api.ipify.org https://prod.base-sepolia-v-1-5.intuition.sh/v1/graphql wss://prod.base-mainnet-v-1-0.intuition.sh/v1/graphql ws://localhost:* wss://localhost:* https://dl.polyhaven.org https://www.gstatic.com;" } }, "pnpm": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e8001e72..2044eecb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -44,12 +44,18 @@ importers: '@types/three': specifier: ^0.175.0 version: 0.175.0 + '@warzieram/graphql': + specifier: ^0.5.31 + version: 0.5.31(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)) class-variance-authority: specifier: ^0.7.1 version: 0.7.1 clsx: specifier: ^2.1.1 version: 2.1.1 + ethers: + specifier: ^6.15.0 + version: 6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) graphql: specifier: ^16.10.0 version: 16.10.0 @@ -209,6 +215,9 @@ packages: '@0xintuition/protocol@0.1.4': resolution: {integrity: sha512-4EKBpCKuOsSRVBXwUVER7/Zg1ZaNZexMrV8sHRVNPydaU1H3juy3RyH48XsjBgybAMmVUm+zbbLfYAcHSFy+Hw==} + '@adraffy/ens-normalize@1.10.1': + resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==} + '@adraffy/ens-normalize@1.11.0': resolution: {integrity: sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg==} @@ -1658,6 +1667,9 @@ packages: cpu: [x64] os: [win32] + '@noble/curves@1.2.0': + resolution: {integrity: sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==} + '@noble/curves@1.4.2': resolution: {integrity: sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==} @@ -1669,6 +1681,10 @@ packages: resolution: {integrity: sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==} engines: {node: ^14.21.3 || >=16} + '@noble/hashes@1.3.2': + resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==} + engines: {node: '>= 16'} + '@noble/hashes@1.4.0': resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} engines: {node: '>= 16'} @@ -3525,6 +3541,9 @@ packages: '@types/node@20.11.5': resolution: {integrity: sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w==} + '@types/node@22.7.5': + resolution: {integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==} + '@types/parse-json@4.0.2': resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} @@ -3602,6 +3621,9 @@ packages: '@vue/shared@3.3.4': resolution: {integrity: sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==} + '@warzieram/graphql@0.5.31': + resolution: {integrity: sha512-SosNLmu0qykhjoI2ca0hvQIASVQNLz2NoC/D+N/2kDAmqaCWjkQXino5WOHO9aYDLJQ2BDIupvNLKn299cwFjQ==} + '@webgpu/types@0.1.60': resolution: {integrity: sha512-8B/tdfRFKdrnejqmvq95ogp8tf52oZ51p3f4QD5m5Paey/qlX4Rhhy5Y8tgFMi7Ms70HzcMMw3EQjH/jdhTwlA==} @@ -3678,6 +3700,9 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + aes-js@4.0.0-beta.5: + resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==} + agent-base@7.1.3: resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} engines: {node: '>= 14'} @@ -4328,6 +4353,10 @@ packages: ethereum-cryptography@2.2.1: resolution: {integrity: sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==} + ethers@6.15.0: + resolution: {integrity: sha512-Kf/3ZW54L4UT0pZtsY/rf+EkBU7Qi5nnhonjUb8yTXcxH3cdcWrV2cRyk0Xk/4jK6OoHhxxZHriyhje20If2hQ==} + engines: {node: '>=14.0.0'} + event-target-shim@5.0.1: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} @@ -4551,6 +4580,25 @@ packages: ws: optional: true + graphql-ws@6.0.5: + resolution: {integrity: sha512-HzYw057ch0hx2gZjkbgk1pur4kAtgljlWRP+Gccudqm3BRrTpExjWCQ9OHdIsq47Y6lHL++1lTvuQHhgRRcevw==} + engines: {node: '>=20'} + peerDependencies: + '@fastify/websocket': ^10 || ^11 + crossws: ~0.3 + graphql: ^15.10.1 || ^16 + uWebSockets.js: ^20 + ws: ^8 + peerDependenciesMeta: + '@fastify/websocket': + optional: true + crossws: + optional: true + uWebSockets.js: + optional: true + ws: + optional: true + graphql@15.10.1: resolution: {integrity: sha512-BL/Xd/T9baO6NFzoMpiMD7YUZ62R6viR5tp/MULVEnbYJXZA//kRNW7J0j1w/wXArgL0sCxhDfK5dczSKn3+cg==} engines: {node: '>= 10.x'} @@ -6155,6 +6203,9 @@ packages: tslib@2.6.3: resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} + tslib@2.7.0: + resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} + tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -6241,6 +6292,9 @@ packages: undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + unique-string@3.0.0: resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==} engines: {node: '>=12'} @@ -6455,6 +6509,18 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + ws@8.17.1: + resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + ws@8.18.0: resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} engines: {node: '>=10.0.0'} @@ -6628,6 +6694,8 @@ snapshots: - utf-8-validate - zod + '@adraffy/ens-normalize@1.10.1': {} + '@adraffy/ens-normalize@1.11.0': {} '@ampproject/remapping@2.3.0': @@ -6658,6 +6726,29 @@ snapshots: transitivePeerDependencies: - '@types/react' + '@apollo/client@3.13.8(@types/react@18.2.48)(graphql-ws@6.0.5(graphql@16.10.0)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(graphql@16.10.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@graphql-typed-document-node/core': 3.2.0(graphql@16.10.0) + '@wry/caches': 1.0.1 + '@wry/equality': 0.5.7 + '@wry/trie': 0.5.0 + graphql: 16.10.0 + graphql-tag: 2.12.6(graphql@16.10.0) + hoist-non-react-statics: 3.3.2 + optimism: 0.18.1 + prop-types: 15.8.1 + rehackt: 0.1.0(@types/react@18.2.48)(react@18.2.0) + symbol-observable: 4.0.0 + ts-invariant: 0.10.3 + tslib: 2.8.1 + zen-observable-ts: 1.2.5 + optionalDependencies: + graphql-ws: 6.0.5(graphql@16.10.0)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + transitivePeerDependencies: + - '@types/react' + '@ardatan/relay-compiler@12.0.0(graphql@16.10.0)': dependencies: '@babel/core': 7.26.10 @@ -7340,6 +7431,7 @@ snapshots: - '@types/node' - bufferutil - cosmiconfig-toml-loader + - crossws - encoding - enquirer - supports-color @@ -7589,13 +7681,14 @@ snapshots: '@graphql-tools/utils': 10.8.6(graphql@16.10.0) '@whatwg-node/disposablestack': 0.0.6 graphql: 16.10.0 - graphql-ws: 6.0.4(graphql@16.10.0)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + graphql-ws: 6.0.5(graphql@16.10.0)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)) isomorphic-ws: 5.0.0(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)) tslib: 2.8.1 ws: 8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10) transitivePeerDependencies: - '@fastify/websocket' - bufferutil + - crossws - uWebSockets.js - utf-8-validate @@ -7745,6 +7838,7 @@ snapshots: - '@fastify/websocket' - '@types/node' - bufferutil + - crossws - encoding - supports-color - uWebSockets.js @@ -7795,6 +7889,7 @@ snapshots: - '@fastify/websocket' - '@types/node' - bufferutil + - crossws - uWebSockets.js - utf-8-validate @@ -8226,6 +8321,10 @@ snapshots: '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3': optional: true + '@noble/curves@1.2.0': + dependencies: + '@noble/hashes': 1.3.2 + '@noble/curves@1.4.2': dependencies: '@noble/hashes': 1.4.0 @@ -8238,6 +8337,8 @@ snapshots: dependencies: '@noble/hashes': 1.7.1 + '@noble/hashes@1.3.2': {} + '@noble/hashes@1.4.0': {} '@noble/hashes@1.6.0': {} @@ -10402,6 +10503,10 @@ snapshots: dependencies: undici-types: 5.26.5 + '@types/node@22.7.5': + dependencies: + undici-types: 6.19.8 + '@types/parse-json@4.0.2': {} '@types/prop-types@15.7.14': {} @@ -10527,6 +10632,25 @@ snapshots: '@vue/shared@3.3.4': {} + '@warzieram/graphql@0.5.31(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@apollo/client': 3.13.8(@types/react@18.2.48)(graphql-ws@6.0.5(graphql@16.10.0)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(graphql@16.10.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@graphql-codegen/typescript-document-nodes': 4.0.15(graphql@16.10.0) + '@tanstack/react-query': 5.69.0(react@18.2.0) + graphql: 16.10.0 + graphql-request: 7.1.2(graphql@16.10.0) + graphql-ws: 6.0.5(graphql@16.10.0)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + transitivePeerDependencies: + - '@fastify/websocket' + - '@types/react' + - crossws + - encoding + - react + - react-dom + - subscriptions-transport-ws + - uWebSockets.js + - ws + '@webgpu/types@0.1.60': {} '@whatwg-node/disposablestack@0.0.6': @@ -10590,6 +10714,8 @@ snapshots: acorn@8.14.1: {} + aes-js@4.0.0-beta.5: {} + agent-base@7.1.3: {} aggregate-error@3.1.0: @@ -11355,6 +11481,19 @@ snapshots: '@scure/bip32': 1.4.0 '@scure/bip39': 1.3.0 + ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10): + dependencies: + '@adraffy/ens-normalize': 1.10.1 + '@noble/curves': 1.2.0 + '@noble/hashes': 1.3.2 + '@types/node': 22.7.5 + aes-js: 4.0.0-beta.5 + tslib: 2.7.0 + ws: 8.17.1(bufferutil@4.0.9)(utf-8-validate@5.0.10) + transitivePeerDependencies: + - bufferutil + - utf-8-validate + event-target-shim@5.0.1: {} eventemitter3@5.0.1: {} @@ -11590,6 +11729,7 @@ snapshots: - '@fastify/websocket' - '@types/node' - bufferutil + - crossws - typescript - uWebSockets.js - utf-8-validate @@ -11622,6 +11762,12 @@ snapshots: optionalDependencies: ws: 8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10) + graphql-ws@6.0.5(graphql@16.10.0)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)): + dependencies: + graphql: 16.10.0 + optionalDependencies: + ws: 8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10) + graphql@15.10.1: {} graphql@16.10.0: {} @@ -13245,6 +13391,8 @@ snapshots: tslib@2.6.3: {} + tslib@2.7.0: {} + tslib@2.8.1: {} tsup@6.7.0(@swc/core@1.11.11(@swc/helpers@0.5.15))(postcss@8.4.31)(typescript@5.8.2): @@ -13321,6 +13469,8 @@ snapshots: undici-types@5.26.5: {} + undici-types@6.19.8: {} + unique-string@3.0.0: dependencies: crypto-random-string: 4.0.0 @@ -13560,6 +13710,11 @@ snapshots: wrappy@1.0.2: {} + ws@8.17.1(bufferutil@4.0.9)(utf-8-validate@5.0.10): + optionalDependencies: + bufferutil: 4.0.9 + utf-8-validate: 5.0.10 + ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10): optionalDependencies: bufferutil: 4.0.9 diff --git a/src/components/AtomAutocompleteInput.tsx b/src/components/AtomAutocompleteInput.tsx index bb34c781..2d859d30 100644 --- a/src/components/AtomAutocompleteInput.tsx +++ b/src/components/AtomAutocompleteInput.tsx @@ -1,18 +1,21 @@ import React, { useState, useEffect, useRef } from 'react'; import { useDebounce } from 'use-debounce'; -import { useGetAtomsQuery } from '@0xintuition/graphql'; +import { useGetAtomsQuery } from '@warzieram/graphql'; import { usePageMetadata } from "../hooks/usePageMetadata" import AtomForm from './AtomForm' import { Plus } from "lucide-react" import { UserRound } from "lucide-react" interface Atom { - id: string; + term_id?: string; label?: string | null; emoji?: string | null; image?: string | null; - vault?: string; - positionCount: number; + term?: { + vaults?: { + position_count: number; + }[] + }; } interface AtomAutocompleteInputProps { @@ -52,33 +55,26 @@ const AtomAutocompleteInput: React.FC = ({ label, on }; }, []); - const { data } = useGetAtomsQuery( - { - where: { - label: { - _ilike: `%${debouncedSearch}%`, - }, - }, - limit: 10, - orderBy: { - vault: { - position_count: 'desc', - }, - }, - }, - { - enabled: debouncedSearch.length >= 2, +const { data, loading, error } = useGetAtomsQuery({ + variables: { + where: { label: { _ilike: `%${debouncedSearch}%` } }, + limit: 10, + order_by: { vaults: { position_count: 'desc' } }, + }, + skip: debouncedSearch.length < 2 +}) + + const atoms: Atom[] = data?.atoms.map(atom => ({ + term_id: atom.term_id, + label: atom.label, + emoji: atom.emoji, + image: atom.image, + term: { + vaults: atom.term.vaults.map(v => ({ + position_count: v.position_count + })) } - ); - - const atoms: Atom[] = - data?.atoms.map(atom => ({ - id: atom.id, - label: atom.label, - emoji: atom.emoji, - image: atom.image, - positionCount: atom.vault.position_count, - })) || []; + })) || []; const handleSelect = (atom: Atom ) => { onSelect(atom); @@ -86,10 +82,10 @@ const AtomAutocompleteInput: React.FC = ({ label, on setCreatingAtom(false); setTimeout(() => { - const form = inputRef.current?.form; - if (!form || !inputRef.current) return; + const form = inputRef?.current?.form; + if (!form || !inputRef?.current) return; const elements = Array.from(form.elements) as HTMLElement[]; - const index = elements.indexOf(inputRef.current); + const index = elements.indexOf(inputRef?.current); const nextInput = elements[index + 1]; nextInput?.focus(); }, 0); @@ -117,7 +113,7 @@ const AtomAutocompleteInput: React.FC = ({ label, on
    {atoms.map((atom) => (
  • e.stopPropagation()} onClick={() => handleSelect(atom)} @@ -134,7 +130,9 @@ const AtomAutocompleteInput: React.FC = ({ label, on {atom.label} - {atom.positionCount.toLocaleString()} + {typeof atom.term?.vaults?.[0]?.position_count === 'number' + ? atom.term.vaults![0].position_count.toLocaleString() + : '0'}
  • diff --git a/src/components/AtomCard.tsx b/src/components/AtomCard.tsx index 44ca10e6..d0803faf 100644 --- a/src/components/AtomCard.tsx +++ b/src/components/AtomCard.tsx @@ -6,8 +6,8 @@ import { useAtomPosition } from "../hooks/useAtomPosition" import TagCreator from "./TagCreator" import Tags from "./ui/Tags" -interface AtomProps { - id: string +export interface AtomProps { + term_id: string data?: string | null type: string label?: string | null @@ -21,26 +21,32 @@ interface AtomProps { url?: string | null } | null } | null - vault?: { - position_count?: number - total_shares?: string - current_share_price?: string - total?: { - aggregate?: { - count?: number - sum?: { - shares?: string | number - } | null - } | null + positions_aggregate?: { + aggregate?: { + count?: number } - } | null - vault_id?: string + } + term?: { + vaults?: { + curve_id: string + current_share_price?: string + market_cap?: string + total_assets?: string + total_shares?: string + position_count?: number + positions_aggregate?: { + aggregate?: { + count?: number + } + } + }[] + } } interface AtomCardProps { atom: AtomProps tags?: string[] -} +} export const AtomCard: React.FC = ({ atom, tags }) => { try { @@ -52,9 +58,12 @@ export const AtomCard: React.FC = ({ atom, tags }) => { const thing = atom.value?.thing const navigate = useNavigate() const goToAtomPage = () => { - navigate(`/atoms/${atom.id || ''}`) + navigate(`/atoms/${atom.term_id || ''}`) } + const positionCount = atom?.term?.vaults[0]?.position_count ?? atom?.positions_aggregate?.aggregate?.count ?? 0 + + return (
    = ({ atom, tags }) => {

    - {Math.max((atom.vault?.position_count ?? 0) - 1, 0)} + {Math.max(positionCount - 1, 0)}

    - -
    - - - {filteredActions.map((action, index) => action.triple ? ( -
    -
    - {action.user.label} - {action.user.label} - {action.type === "vote" ? ( - - {action.isFor ? "voted FOR this claim:" : "voted AGAINST this claim:"} - - ) : ( - created this claim: - )} -
    - - -
    ) : null +
    +

    Feed followings

    + {items.length === 0 && !eventsLoading ? ( +

    No activity found.

    + ) : ( + items + .slice() + .sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime()) + .map((e) => { + if (!e.triple) return null; + const isDeposit = e.type === "Deposited"; + const sender = isDeposit ? e.deposit?.sender : e.redemption?.sender; + const senderImg = sender?.image ?? default_img; + const senderLabel = sender?.label; + return ( +
    +
    + {senderLabel} + + + {shortAddress(senderLabel)} + + {isDeposit ? "deposit" : "redeem"} + + + {new Date(e.created_at).toLocaleString()} + +
    + + +
    + ); + }) + )} + {eventsLoading && hasMore && ( +

    Loading...

    + )} + {!hasMore && ( +

    No more activity.

    )}
    - ) + ); } -export default Feed +export default Feed; diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index 169d48b7..5bddbfd7 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -1,13 +1,17 @@ +import { useQueryClient } from "@tanstack/react-query" +import { useGetTriplesByUriQuery } from "@warzieram/graphql" import React, { useEffect, useState } from "react" import { Link } from "react-router-dom" -import { useQueryClient } from "@tanstack/react-query" -import { useTheme } from "~/src/components/ThemeProvider" -import TabSystem from '../components/TabSystem'; +import { useTheme } from "~/src/components/ThemeProvider" import { useStorage } from "@plasmohq/storage/dist/hook" -import { useGetClaimsByUriQuery } from "~src/graphql/src" +import TabSystem from "~/src/components/TabSystem" import ClaimRowLite from "~src/components/ui/ClaimRowLite"; import AtomCard from "~src/components/AtomCard"; import EyeComponent from "~/src/components/3D/EyeComponent" +import AtomCard from "~src/components/AtomCard" +import ClaimRowLite from "~src/components/ui/ClaimRowLite" + +import TabSystem from "../components/TabSystem" function normalizeUrl(input: string): string { try { @@ -38,12 +42,13 @@ function buildUriRegex(rawUrl: string): string { function Home() { - const { theme } = useTheme() const [currentUrl, setCurrentUrl] = useState("") const [walletAddress] = useStorage("metamask-account", "") const [activeTab, setActiveTab] = useState("Claims") + const [startRequest, setStartRequest] = useState(false) - useQueryClient() + const queryClient = useQueryClient() + console.log(queryClient) const getCurrentUrl = async () => { const [tab] = await chrome.tabs.query({ @@ -80,29 +85,32 @@ function Home() { console.log("normalized URL:", currentUrl) console.log("uriRegex:", uriRegex) - const { data, isLoading, error } = useGetClaimsByUriQuery({uriRegex, address: walletAddress }) + const { data, loading, error } = useGetTriplesByUriQuery({variables: {uriRegex: uriRegex, address: walletAddress }}) const atoms = data?.atoms ?? [] - console.log("current wallet address:", walletAddress); + console.log("current wallet address:", walletAddress) console.log("Data :", data) const claims = Array.from( new Map( - atoms?.flatMap(atom => [...atom.as_object_claims_aggregate.nodes, ...atom.as_subject_claims_aggregate.nodes]) - .map(claim => [claim.triple_id, claim]) - + atoms + ?.flatMap((atom) => [ + ...atom.as_object_triples_aggregate.nodes, + ...atom.as_subject_triples_aggregate.nodes + ]) + .map((claim) => [claim.term_id, claim]) ).values() ) - - console.log("Claims :", claims); - - const atomsWithTags = atoms.map(atom => { - const tags = atom.as_subject_claims_aggregate.nodes - .filter(claim => claim.predicate.label === "has tag") - .map(claim => claim.object) + + console.log("Claims :", claims) + + const atomsWithTags = atoms.map((atom) => { + const tags = atom.as_subject_triples_aggregate.nodes + .filter((claim) => claim.predicate.label === "has tag") + .map((claim) => claim.object) .filter(Boolean) const uniqueTags = Array.from( - new Map(tags.map(tag => [tag.id, tag])).values() + new Map(tags.map((tag) => [tag.term_id, tag])).values() ) return { @@ -110,81 +118,85 @@ function Home() { tags: uniqueTags } }) - + console.log("Tags :", atomsWithTags) const tabs = [ { - label: 'Claims', - content: -
    - {isLoading ? "Chargement..." : (typeof data !== "undefined" && claims.length !== 0)? - ( claims.map((claim, index) => ( - console.log(claim), - - - - - )) - ) : ( -
    -

    No claims found for this URL.

    -

    - - - - Be the first - - -

    -
    - )} -
    + label: "Claims", + content: ( +
    + {loading ? ( + "Loading..." + ) : typeof data !== "undefined" && claims.length !== 0 ? ( + claims.map( + (claim, index) => ( + console.log(claim), + ( + + ) + ) + ) + ) : ( +
    +

    + No claims found for this URL. +

    +

    + + Be the first + +

    +
    + )} +
    + ) }, { - label: 'Atoms', - content: -
    - {isLoading ? "Chargement...": (typeof data !== "undefined" && atoms.length != 0)? - (atomsWithTags.map((atom) => { - return ( - - ); - })): - ( -
    -

    No atoms found for this URL.

    -

    - - - - Be the first - - -

    -
    - ) - - } - -
    - - }, - ]; - + label: "Atoms", + content: ( +
    + {loading ? ( + "Loading..." + ) : typeof data !== "undefined" && atoms.length != 0 ? ( + atomsWithTags.map((atom) => { + return ( + + ) + }) + ) : ( +
    +

    + No atoms found for this URL. +

    +

    + + Be the first + +

    +
    + )} +
    + ) + } + ] return (
    -

    INTUITION

    +

    + INTUITION +

    -

    - "Intuition lets you explore, vote, and debate verifiable facts — all directly from your browser." -

    +

    + "Intuition lets you explore, vote, and debate verifiable facts — all + directly from your browser." +

    - +
    - {error &&

    An error occurred while requesting this page.

    } - + {error && ( +

    + An error occurred while requesting this page. +

    + )} + { const { data, loading, error } = useEventsSubscription({ variables: { - addresses: walletAddress, + addresses: [walletAddress], limit: INITIAL_LIMIT } }) @@ -54,9 +54,10 @@ const RecentActivity: React.FC = () => { const isDeposit = Boolean(e.deposit_id) // ------ DEPOSIT ATOM ------ - if (isDeposit && e.deposit && !e.deposit.is_triple && e.atom) { - const senderImg = e.deposit.sender.image - const senderLabel = e.deposit.sender.label + if (isDeposit && e.deposit && e.atom) { + const senderImg = e.deposit.sender_assets_after_total_fees.image + const senderLabel = e.deposit?.sender?.id + console.log("TRIPLE LIVE FEED ", e.atom) return (
    @@ -75,10 +76,10 @@ const RecentActivity: React.FC = () => { } // ------ DEPOSIT TRIPLE ------ - if (isDeposit && e.deposit && e.deposit.is_triple && e.triple) { - const senderImg = e.deposit.sender.image - const senderLabel = e.deposit.sender.label - console.log("ID DU PREDICATE:", e.triple.predicate.id) + if (isDeposit && e.deposit && e.triple) { + const senderImg = e.deposit.sender_assets_after_total_fees.image + const senderLabel = e.deposit?.sender?.id + console.log("TRIPLE LIVE FEED ", e.triple) return (
    @@ -90,7 +91,6 @@ const RecentActivity: React.FC = () => { /> {renderSenderLink(senderLabel)} deposit :

    -
    diff --git a/src/pages/Search.tsx b/src/pages/Search.tsx index 95b47649..24e0e341 100644 --- a/src/pages/Search.tsx +++ b/src/pages/Search.tsx @@ -1,17 +1,29 @@ +import { + useGetTriplesWithPositionsLazyQuery, + useGetTriplesWithPositionsQuery, + type GetTriplesWithPositionsQuery, +} from "@warzieram/graphql" import React, { useEffect, useState } from "react" -import IntuitionSearchIcon from "~src/components/icons/IntuitionSearchBar" -import TabSystem from "../components/TabSystem" -import { useGetTriplesWithPositionsQuery } from "~src/graphql/src" -import ClaimRowLite from "~src/components/ui/ClaimRowLite"; + import { useStorage } from "@plasmohq/storage/dist/hook" +import IntuitionSearchIcon from "~src/components/icons/IntuitionSearchBar" +import ClaimRowLite from "~src/components/ui/ClaimRowLite" + +import TabSystem from "../components/TabSystem" const Search: React.FC = () => { const [isSidePanel, setIsSidePanel] = useState(false) const [searchTerm, setSearchTerm] = useState("") const [activeTab, setActiveTab] = useState("All") + const [offset, setOffset] = useState(0) + const [items, setItems] = useState( + [] + ) const [walletAddress] = useStorage("metamask-account", "") + const PAGE_SIZE = 20 + useEffect(() => { const checkWidth = () => { setIsSidePanel(window.innerWidth > 600) @@ -29,68 +41,95 @@ const Search: React.FC = () => { const { data: triplesData, - isLoading, + loading, error } = useGetTriplesWithPositionsQuery({ - where: { - _or: [ - { subject: { label: { _ilike: `%${searchTerm}%` } } }, - { predicate: { label: { _ilike: `%${searchTerm}%` } } }, - { object: { label: { _ilike: `%${searchTerm}%` } } } - ] + variables: { + where: { + _or: [ + { subject: { label: { _ilike: `%${searchTerm}%` } } }, + { predicate: { label: { _ilike: `%${searchTerm}%` } } }, + { object: { label: { _ilike: `%${searchTerm}%` } } } + ] + }, + limit: PAGE_SIZE, + address: walletAddress, + offset }, - address: walletAddress - }, { - enabled: !!searchTerm + skip: searchTerm.length < 2 }) - - const triples = triplesData?.triples || [] - - - const renderResults = () => { - console.log("Active tab:", activeTab) - console.log("All Triples:", triples) - - if (isLoading) return

    Loading...

    - if (error) return

    Error loading results.

    - if (!triples.length) return

    No results found.

    - - const filterFunctions: Record boolean> = { - All: () => true, - Tag: (triple) => triple.predicate?.label?.toLowerCase().includes("tag"), - Organization: (triple) => - triple.predicate?.label?.toLowerCase().includes("organization"), - User: (triple) => triple.predicate?.label?.toLowerCase().includes("follow") + // append the new data to the existing one when it changes + useEffect(() => { + if (!triplesData) return + if (offset === 0) { + setItems(triplesData.triples) + } else { + setItems((prev) => [...prev, ...triplesData.triples]) + } + }, [triplesData]) + + // adding a listener to adjust the offset on scroll + useEffect(() => { + const onScroll = () => { + if ( + window.innerHeight + window.scrollY >= + document.documentElement.scrollHeight - 10 + ) { + setOffset((prev) => prev + PAGE_SIZE) } - - const filteredTriples = triples.filter(filterFunctions[activeTab] || filterFunctions.All) - - - console.log("Filtered triples:", filteredTriples) - - - return ( -
    - {filteredTriples.length === 0 &&

    No results found.

    } - {filteredTriples.map((triple, index) => ( - - ))} -
    - ) } - + window.addEventListener("scroll", onScroll) + return () => window.removeEventListener("scroll", onScroll) + }, []) - const tabs = ["All", "Tag", "Organization", "User"].map((label) => ({ - label, - content: ( -
    - {renderResults()} + // reset the research when the user types + useEffect(() => { + setItems([]) + setOffset(0) + }, [searchTerm]) + + const renderResults = () => { + console.log("Active tab:", activeTab) + console.log("All Triples:", items) + + if (error) return

    Error loading results.

    + if (!items.length) return

    No results found.

    + + const filterFunctions: Record< + string, + (triple: GetTriplesWithPositionsQuery['triples'][number] ) => boolean + > = { + All: () => true, + Tag: (triple) => + triple.predicate?.label?.toLowerCase().includes("tag") || false, + Organization: (triple) => + triple.predicate?.label?.toLowerCase().includes("organization") || + false, + User: (triple) => + triple.predicate?.label?.toLowerCase().includes("follow") || false + } + + const filteredTriples = items.filter( + filterFunctions[activeTab] || filterFunctions.All + ) + + console.log("Filtered triples:", filteredTriples) + + return ( +
    + {filteredTriples.length === 0 &&

    No results found.

    } + {filteredTriples.map((triple, index) => ( + + ))} + {loading &&

    Loading...

    }
    ) + } + + const tabs = ["All", "Tag", "Organization", "User"].map((label) => ({ + label, + content:
    {renderResults()}
    })) return ( @@ -111,7 +150,6 @@ const Search: React.FC = () => { activeTab={activeTab} onTabChange={setActiveTab} /> -
    diff --git a/src/pages/TagsDetailPage.tsx b/src/pages/TagsDetailPage.tsx index ecd9a867..21e1d19d 100644 --- a/src/pages/TagsDetailPage.tsx +++ b/src/pages/TagsDetailPage.tsx @@ -1,6 +1,6 @@ import React from 'react' import { useParams, Link } from 'react-router-dom' -import { useGetAtomQuery } from "@0xintuition/graphql" +import { useGetAtomQuery } from "@warzieram/graphql" import AtomDisplay from '../components/ui/AtomDisplay' import SubjectTag from '../components/SubjectTag' import BackButton from '~/src/components/BackButton' @@ -12,14 +12,14 @@ const TagDetailPage: React.FC = () => { data, isLoading, error, - } = useGetAtomQuery({ - id: Number(tagId) ?? "" + } = useGetAtomQuery({ + variables: { term_id: tagId! } }) if (isLoading) return

    Loading the atom…

    if (error) return

    Loading error

    if (!data?.atom) return

    No atoms found for this ID

    - + return (
    diff --git a/src/pages/TagsPage.tsx b/src/pages/TagsPage.tsx index 10d699a9..aa4bbd90 100644 --- a/src/pages/TagsPage.tsx +++ b/src/pages/TagsPage.tsx @@ -1,20 +1,20 @@ -import React, { useState, useEffect } from 'react' -import { Link } from 'react-router-dom' -import { useGetListsTagsQuery } from '~src/graphql/src' -import { ImageWithFallback } from '../components/ui/ImageWithFallback' -import { Fingerprint } from 'lucide-react' -import { Tag } from 'lucide-react'; +import { useGetListsTagsQuery } from "@warzieram/graphql" +import { Fingerprint, Tag } from "lucide-react" +import React, { useEffect, useState } from "react" +import { Link } from "react-router-dom" +import { ImageWithFallback } from "../components/ui/ImageWithFallback" +import { useInfiniteScroll } from "../hooks/useInfiniteScroll" const HASHTAG_PREDICATE_ID = 4 const PAGE_SIZE = 18 const HashtagObjectsPage: React.FC = () => { const [offset, setOffset] = useState(0) - const [items, setItems] = useState([]) + const [items, setItems] = useState([]) const [hasMore, setHasMore] = useState(true) - const { data, isLoading, isFetching, isError, error } = useGetListsTagsQuery( - { + const { data, loading, error } = useGetListsTagsQuery({ + variables: { where: { _and: [ { as_object_triples: { predicate_id: { _eq: HASHTAG_PREDICATE_ID } } } @@ -23,59 +23,42 @@ const HashtagObjectsPage: React.FC = () => { triplesWhere: { predicate_id: { _eq: HASHTAG_PREDICATE_ID } }, limit: PAGE_SIZE, offset, - orderBy: [{ as_object_triples_aggregate: { count: 'desc' } }] - }, - { - keepPreviousData: true, - refetchOnWindowFocus: false + orderBy: [{ as_object_triples_aggregate: { count: "desc" } }] } - ) + }) - // accumulate pages useEffect(() => { - if (!data) return - if (offset === 0) { - setItems(data.atoms) - } else { - setItems(prev => [...prev, ...data.atoms]) + if (data?.atoms) { + setItems((prev) => + offset === 0 ? data.atoms : [...prev, ...data.atoms] + ) + setHasMore(data.atoms.length === PAGE_SIZE) } - setHasMore(data.atoms.length === PAGE_SIZE) }, [data, offset]) - useEffect(() => { - const onScroll = () => { - if (isLoading || isFetching || !hasMore) return - if ( - window.innerHeight + window.scrollY >= - document.documentElement.scrollHeight - 100 - ) { - setOffset(prev => prev + PAGE_SIZE) - } - } - window.addEventListener('scroll', onScroll) - return () => window.removeEventListener('scroll', onScroll) - }, [isLoading, isFetching, hasMore]) + useInfiniteScroll({ + loading, + hasMore, + onLoadMore: () => setOffset((prev) => prev + PAGE_SIZE) + }) - if (isError) return

    Error: {String(error)}

    - if (offset === 0 && isLoading) return

    Loading…

    + if (error) return

    Error: {String(error)}

    return (

    Tags list

    - - {items.map(atom => { + {items.map((atom) => { const count = atom.as_object_triples_aggregate.aggregate.count return ( + key={atom.term_id} + to={`/tags/${atom.term_id}`} + className="flex justify-between gap-3 items-center p-3 border border-border/10 bg-[hsl(var(--claims-bg))] rounded-xl mt-2 claims-hover-effect">
    {atom.image ? ( ) : ( @@ -86,16 +69,19 @@ const HashtagObjectsPage: React.FC = () => {

    {atom.label}

    - {(atom.value?.thing?.description ?? '').slice(0, 70)}… + {(atom.value?.thing?.description ?? "").slice(0, 70)}…

    - {count} + + {count} + + ) })} - {isFetching && hasMore && ( + {loading && hasMore && (

    Loading...

    )} {!hasMore && ( diff --git a/src/queryclient.ts b/src/queryclient.ts index 75b68f21..3e35da1d 100644 --- a/src/queryclient.ts +++ b/src/queryclient.ts @@ -1,5 +1,5 @@ import { GraphQLClient } from "graphql-request"; -const API_URL = "https://dev.base.intuition-api.com/v1/graphql"; +const API_URL = "https://prod.base-mainnet-v-1-0.intuition.sh/v1/graphql"; const graphqlClient = new GraphQLClient(API_URL); export default graphqlClient; diff --git a/src/styles/particles-canvas.css b/src/styles/particles-canvas.css index 77776d4a..f24be46c 100644 --- a/src/styles/particles-canvas.css +++ b/src/styles/particles-canvas.css @@ -16,4 +16,5 @@ left: 0; pointer-events: none; background-color: transparent; + filter: brightness(50%) contrast(80%); } \ No newline at end of file