├── .dockerignore ├── .env.example ├── .eslintrc.base.cjs ├── .github ├── pr-title-checker-config.json ├── pull_request_template.md ├── release-drafter.yml └── workflows │ ├── ci.yml │ ├── deploy_dev.yml │ ├── deploy_production.yml │ ├── deploy_staging.yml │ ├── pr_title_checker.yml │ ├── release-drafter.yml │ └── storybook.yml ├── .gitignore ├── .husky └── pre-commit ├── .prettierignore ├── .prettierrc ├── .verdaccio └── config.yml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── apps ├── data-populator │ ├── .env.example │ ├── .eslintrc.cjs │ ├── .gitignore │ ├── CHANGELOG.md │ ├── Dockerfile │ ├── README.md │ ├── app │ │ ├── .client │ │ │ ├── privy-button.tsx │ │ │ ├── privy-login-button.tsx │ │ │ ├── privy-logout-button.tsx │ │ │ ├── privy-logout.tsx │ │ │ ├── privy-provider.tsx │ │ │ ├── privy-refresh.tsx │ │ │ ├── privy-revalidate.tsx │ │ │ ├── providers.tsx │ │ │ ├── useBatchCreateAtom.tsx │ │ │ └── useUserWallet.tsx │ │ ├── .server │ │ │ ├── auth.ts │ │ │ ├── csv-editor.tsx │ │ │ ├── db.ts │ │ │ ├── env.ts │ │ │ ├── multivault.ts │ │ │ ├── privy.ts │ │ │ ├── theme.ts │ │ │ └── viem.ts │ │ ├── assets │ │ │ ├── derp-face-1.png │ │ │ ├── derp-face-10.png │ │ │ ├── derp-face-11.png │ │ │ ├── derp-face-12.jpg │ │ │ ├── derp-face-2.png │ │ │ ├── derp-face-3.png │ │ │ ├── derp-face-4.png │ │ │ ├── derp-face-5.png │ │ │ ├── derp-face-6.png │ │ │ ├── derp-face-7.png │ │ │ ├── derp-face-8.png │ │ │ └── derp-face-9.png │ │ ├── components │ │ │ ├── bridge-to-base.tsx │ │ │ ├── built-on-base.tsx │ │ │ ├── container.tsx │ │ │ ├── error-list.tsx │ │ │ ├── error-page.tsx │ │ │ ├── get-started.tsx │ │ │ ├── header-logo.tsx │ │ │ ├── header.tsx │ │ │ ├── history-modal.tsx │ │ │ ├── home-banner.tsx │ │ │ ├── info-popover.tsx │ │ │ ├── info-tooltip.tsx │ │ │ ├── navigation-link.tsx │ │ │ ├── pagination-component.tsx │ │ │ ├── progress-modal.tsx │ │ │ ├── proofread-modal.tsx │ │ │ ├── revalidate-button.tsx │ │ │ ├── search-and-sort.tsx │ │ │ ├── search.tsx │ │ │ ├── skeleton.tsx │ │ │ ├── sort-select.tsx │ │ │ ├── sort.tsx │ │ │ ├── submit-button.tsx │ │ │ ├── ui │ │ │ │ ├── progress.tsx │ │ │ │ ├── scroll-area.tsx │ │ │ │ └── table.tsx │ │ │ ├── usd-tooltip.tsx │ │ │ └── wrong-network-button.tsx │ │ ├── consts │ │ │ ├── assets.ts │ │ │ ├── emails.ts │ │ │ ├── errors.ts │ │ │ ├── general.ts │ │ │ ├── index.ts │ │ │ └── paths.ts │ │ ├── entry.client.tsx │ │ ├── entry.server.tsx │ │ ├── layouts │ │ │ ├── full-page-layout.tsx │ │ │ ├── root-layout.tsx │ │ │ └── two-panel-layout.tsx │ │ ├── lib │ │ │ ├── abis │ │ │ │ ├── chainalysisOracle.ts │ │ │ │ ├── chainlinkEthUsdOracle.ts │ │ │ │ └── multivault.ts │ │ │ ├── hooks │ │ │ │ ├── useBatchCreateAtomWagmi.tsx │ │ │ │ ├── useBatchCreateTriple.tsx │ │ │ │ ├── useContractWriteAndWait.tsx │ │ │ │ ├── useCopy.tsx │ │ │ │ ├── useCreateAtom.tsx │ │ │ │ ├── useCreateTriple.tsx │ │ │ │ ├── useDepositAtom.tsx │ │ │ │ ├── useDepositTriple.tsx │ │ │ │ ├── useGetWalletBalance.tsx │ │ │ │ ├── useGoBack.tsx │ │ │ │ ├── useLiveLoader.ts │ │ │ │ ├── useLoaderFetcher.tsx │ │ │ │ ├── useMultivaultContract.tsx │ │ │ │ ├── useOffChainFetcher.tsx │ │ │ │ ├── usePollRequestDetails.tsx │ │ │ │ ├── useRedeemAtom.tsx │ │ │ │ ├── useRedeemTriple.tsx │ │ │ │ ├── useSearchAndSortParams.tsx │ │ │ │ └── useTransactionReducer.ts │ │ │ ├── services │ │ │ │ ├── attestor.ts │ │ │ │ ├── cid.ts │ │ │ │ ├── cloudinary.ts │ │ │ │ ├── evm.ts │ │ │ │ ├── image.ts │ │ │ │ ├── offchain-store.ts │ │ │ │ ├── phosphor.ts │ │ │ │ ├── pinata.ts │ │ │ │ ├── populate.ts │ │ │ │ ├── request.ts │ │ │ │ └── supabase.ts │ │ │ ├── state │ │ │ │ └── store.ts │ │ │ ├── styles.ts │ │ │ └── utils │ │ │ │ ├── app.ts │ │ │ │ ├── cache-map.ts │ │ │ │ ├── cellHighlight.ts │ │ │ │ ├── chains.ts │ │ │ │ ├── client-hints.tsx │ │ │ │ ├── csv.ts │ │ │ │ ├── environment.ts │ │ │ │ ├── http-requests.ts │ │ │ │ ├── image.ts │ │ │ │ ├── logger.ts │ │ │ │ ├── misc.tsx │ │ │ │ ├── mock.ts │ │ │ │ ├── nonce-provider.tsx │ │ │ │ ├── params.ts │ │ │ │ ├── privy.ts │ │ │ │ ├── proofread.ts │ │ │ │ ├── redirect.ts │ │ │ │ ├── request-info.tsx │ │ │ │ ├── schema.ts │ │ │ │ ├── sort.ts │ │ │ │ ├── use-tx-reducer.ts │ │ │ │ └── wagmi.ts │ │ ├── polyfills.ts │ │ ├── root.tsx │ │ ├── routes │ │ │ ├── _index.tsx │ │ │ ├── actions+ │ │ │ │ ├── logout.tsx │ │ │ │ └── set-theme.tsx │ │ │ ├── api.csv-editor.tsx │ │ │ ├── app+ │ │ │ │ ├── index.tsx │ │ │ │ └── playground.tsx │ │ │ ├── app.tsx │ │ │ ├── login.tsx │ │ │ └── resources+ │ │ │ │ ├── get-request-details.tsx │ │ │ │ └── get-vault-details.tsx │ │ ├── styles │ │ │ └── globals.css │ │ └── types │ │ │ ├── claim.ts │ │ │ ├── claimr.ts │ │ │ ├── identity.ts │ │ │ ├── index.ts │ │ │ ├── navigation.ts │ │ │ ├── pagination.ts │ │ │ ├── privy.ts │ │ │ ├── quest-temp.ts │ │ │ ├── quest.ts │ │ │ ├── session.ts │ │ │ ├── tags.ts │ │ │ ├── transaction.ts │ │ │ ├── user.ts │ │ │ └── vault.ts │ ├── data │ │ ├── coinmarketcap-currencies │ │ │ └── coinmarketcap_cryptocurrency_data.csv │ │ ├── coinmarketcap-exchanges │ │ │ └── coinmarketcap_exchanges_data.csv │ │ ├── crypto-thought-leaders │ │ │ └── crypto-thought-leaders.csv │ │ ├── dapp-list-base │ │ │ └── dapp_list_base_nodes.csv │ │ ├── portcos │ │ │ ├── polymorphic.csv │ │ │ ├── spaceship.csv │ │ │ └── superscrypt.csv │ │ ├── predicates │ │ │ └── predicates.csv │ │ ├── pro-crypto-politicians │ │ │ ├── all-people.json │ │ │ ├── anti-crypto-politicians.csv │ │ │ └── pro-crypto-politicians.csv │ │ ├── token2049 │ │ │ └── token2049_2024.csv │ │ ├── top-100-movies │ │ │ └── imdb_top_100_movies.csv │ │ ├── top-100-series │ │ │ ├── imdb_top_100_series.csv │ │ │ └── tag_metadata.csv │ │ ├── top-anime-series │ │ │ └── top-anime-series.csv │ │ ├── top-web3-developer-tooling │ │ │ └── top-web3-developer-tooling.csv │ │ └── upcoming-crypto-conferences │ │ │ ├── upcoming-crypto-conferences 4.csv │ │ │ └── upcoming-crypto-conferences.csv │ ├── docker-compose.yml │ ├── package.json │ ├── postcss.config.js │ ├── project.json │ ├── public │ │ └── favicon.ico │ ├── tailwind.config.ts │ ├── tests │ │ └── sample.test.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ ├── tsconfig.spec.json │ ├── vite.config.ts │ ├── vitest.config.ts │ └── vitest.setup.ts ├── portal │ ├── .eslintrc.cjs │ ├── .gitignore │ ├── CHANGELOG.md │ ├── Dockerfile │ ├── README.md │ ├── app │ │ ├── .client │ │ │ ├── privy-button.tsx │ │ │ ├── privy-login-button.tsx │ │ │ ├── privy-logout-button.tsx │ │ │ ├── privy-logout.tsx │ │ │ ├── privy-provider.tsx │ │ │ ├── privy-refresh.tsx │ │ │ ├── privy-revalidate.tsx │ │ │ ├── privy-switch-wallet.tsx │ │ │ ├── privy-verified-links.tsx │ │ │ └── providers.tsx │ │ ├── .server │ │ │ ├── api.ts │ │ │ ├── auth.ts │ │ │ ├── cloudinary.ts │ │ │ ├── emitter.ts │ │ │ ├── env.ts │ │ │ ├── form.ts │ │ │ ├── multivault.ts │ │ │ ├── ofac.ts │ │ │ ├── og.tsx │ │ │ ├── onboarding.ts │ │ │ ├── privy.ts │ │ │ ├── quest.ts │ │ │ ├── relics.ts │ │ │ ├── stream.ts │ │ │ ├── theme.ts │ │ │ ├── toast.ts │ │ │ └── viem.ts │ │ ├── assets │ │ │ ├── derp-face-1.png │ │ │ ├── derp-face-10.png │ │ │ ├── derp-face-11.png │ │ │ ├── derp-face-12.jpg │ │ │ ├── derp-face-2.png │ │ │ ├── derp-face-3.png │ │ │ ├── derp-face-4.png │ │ │ ├── derp-face-5.png │ │ │ ├── derp-face-6.png │ │ │ ├── derp-face-7.png │ │ │ ├── derp-face-8.png │ │ │ ├── derp-face-9.png │ │ │ ├── intuition-logo.svg │ │ │ ├── intuition-qr-icon.svg │ │ │ └── og-background.png │ │ ├── components │ │ │ ├── alert-dialog.tsx │ │ │ ├── audio-player.tsx │ │ │ ├── bridge-to-base.tsx │ │ │ ├── built-on-base.tsx │ │ │ ├── claim │ │ │ │ └── claim-position-row.tsx │ │ │ ├── container.tsx │ │ │ ├── create-claim │ │ │ │ ├── create-claim-form.tsx │ │ │ │ ├── create-claim-modal.tsx │ │ │ │ ├── create-claim-popovers.tsx │ │ │ │ └── create-claim-review.tsx │ │ │ ├── create-identity │ │ │ │ ├── create-caip10-account-form.tsx │ │ │ │ ├── create-identity-form.tsx │ │ │ │ ├── create-identity-modal.tsx │ │ │ │ └── create-identity-review.tsx │ │ │ ├── detail-info-card.tsx │ │ │ ├── edit-profile │ │ │ │ ├── form.tsx │ │ │ │ └── modal.tsx │ │ │ ├── edit-social-links-modal.tsx │ │ │ ├── error-list.tsx │ │ │ ├── error-page.tsx │ │ │ ├── explore │ │ │ │ ├── ExploreHeader.tsx │ │ │ │ ├── ExploreSearch.tsx │ │ │ │ ├── ExploreSearchClaimInput.tsx │ │ │ │ └── ExploreSearchForm │ │ │ │ │ ├── ExploreAddTags │ │ │ │ │ ├── ExploreAddTags.tsx │ │ │ │ │ └── ExploreAddTags.utils.ts │ │ │ │ │ ├── ExploreSearchForm.tsx │ │ │ │ │ └── ExploreSearchInput │ │ │ │ │ └── ExploreSearchInput.tsx │ │ │ ├── follow │ │ │ │ ├── follow-button.tsx │ │ │ │ ├── follow-form.tsx │ │ │ │ ├── follow-modal.tsx │ │ │ │ ├── follow-review.tsx │ │ │ │ ├── follow-toast.tsx │ │ │ │ └── unfollow-button.tsx │ │ │ ├── global-loading.tsx │ │ │ ├── header-logo.tsx │ │ │ ├── header.tsx │ │ │ ├── home │ │ │ │ ├── home-banner.tsx │ │ │ │ ├── home-section-header.tsx │ │ │ │ └── home-stats-header.tsx │ │ │ ├── identity-input.tsx │ │ │ ├── identity │ │ │ │ ├── identity-position-row.tsx │ │ │ │ ├── identity-search-combo-box-item.tsx │ │ │ │ └── identity-search-combo-box.tsx │ │ │ ├── image-chooser.tsx │ │ │ ├── info-popover.tsx │ │ │ ├── info-tooltip.tsx │ │ │ ├── list │ │ │ │ ├── active-positions-on-claims.tsx │ │ │ │ ├── active-positions-on-identities.tsx │ │ │ │ ├── activity.tsx │ │ │ │ ├── claims.tsx │ │ │ │ ├── follow.tsx │ │ │ │ ├── identities.tsx │ │ │ │ ├── list-claims.tsx │ │ │ │ ├── list-header.tsx │ │ │ │ ├── list.tsx │ │ │ │ ├── positions-on-claim.tsx │ │ │ │ ├── positions-on-identity.tsx │ │ │ │ ├── tags.tsx │ │ │ │ └── users.tsx │ │ │ ├── lists │ │ │ │ ├── add-identities-list-form.tsx │ │ │ │ ├── add-identities-list-modal.tsx │ │ │ │ ├── add-identities-review.tsx │ │ │ │ ├── add-identities.tsx │ │ │ │ ├── add-list-existing-cta.tsx │ │ │ │ ├── featured-lists-carousel.tsx │ │ │ │ ├── list-identity-card-portal.tsx │ │ │ │ ├── list-identity-display-card.tsx │ │ │ │ ├── list-overview.tsx │ │ │ │ ├── list-skeletons.tsx │ │ │ │ ├── list-tab-identity-display.tsx │ │ │ │ └── list-utils.ts │ │ │ ├── loading-logo.tsx │ │ │ ├── navigation-link.tsx │ │ │ ├── nested-tabs.tsx │ │ │ ├── pagination-component.tsx │ │ │ ├── points-card │ │ │ │ └── points-card.tsx │ │ │ ├── profile-social-accounts.tsx │ │ │ ├── profile │ │ │ │ ├── connections-header.tsx │ │ │ │ ├── data-about-header.tsx │ │ │ │ ├── data-created-header.tsx │ │ │ │ ├── image-modal.tsx │ │ │ │ ├── overview-about-header.tsx │ │ │ │ ├── overview-created-header.tsx │ │ │ │ └── overview-staking-header.tsx │ │ │ ├── quest │ │ │ │ ├── activities │ │ │ │ │ ├── create-claim-activity.tsx │ │ │ │ │ ├── stake-claim-activity.tsx │ │ │ │ │ ├── stake-claim-underlying-identities-activity.tsx │ │ │ │ │ └── stake-identity-activity.tsx │ │ │ │ ├── activity-container.tsx │ │ │ │ ├── create-atom-activity.tsx │ │ │ │ ├── detail │ │ │ │ │ ├── claim-with-hoverable.tsx │ │ │ │ │ ├── identity-with-hoverable.tsx │ │ │ │ │ └── layout.tsx │ │ │ │ ├── mdx-content-wrapper.tsx │ │ │ │ ├── quest-card-button.tsx │ │ │ │ ├── quest-card.tsx │ │ │ │ ├── quest-criteria-card.tsx │ │ │ │ ├── quest-criteria-display.tsx │ │ │ │ ├── quest-points-display.tsx │ │ │ │ ├── quest-set-card.tsx │ │ │ │ ├── quest-set-progress-card.tsx │ │ │ │ ├── quest-status-card.tsx │ │ │ │ ├── quest-status-indicator.tsx │ │ │ │ └── quest-success-modal.tsx │ │ │ ├── read-only-banner.tsx │ │ │ ├── referral-card │ │ │ │ ├── referral-card.tsx │ │ │ │ ├── referral-points-display.tsx │ │ │ │ └── referral-row.tsx │ │ │ ├── relic-card │ │ │ │ └── relic-card.tsx │ │ │ ├── relic-onboarding-video │ │ │ │ └── relic-onboarding-video.tsx │ │ │ ├── relic-point-card │ │ │ │ └── relic-point-card.tsx │ │ │ ├── remix-link.tsx │ │ │ ├── revalidate-button.tsx │ │ │ ├── save-list │ │ │ │ ├── save-button.tsx │ │ │ │ ├── save-form.tsx │ │ │ │ ├── save-list-modal.tsx │ │ │ │ ├── save-review.tsx │ │ │ │ ├── save-toast.tsx │ │ │ │ └── unsave-button.tsx │ │ │ ├── search-and-sort.tsx │ │ │ ├── search.tsx │ │ │ ├── segmented-nav.tsx │ │ │ ├── share-cta.tsx │ │ │ ├── share-modal.tsx │ │ │ ├── sidebar-nav.tsx │ │ │ ├── site-wide-banner.tsx │ │ │ ├── skeleton.tsx │ │ │ ├── sort-select.tsx │ │ │ ├── sort.tsx │ │ │ ├── stake │ │ │ │ ├── stake-actions.tsx │ │ │ │ ├── stake-button.tsx │ │ │ │ ├── stake-fee-breakdown.tsx │ │ │ │ ├── stake-form.tsx │ │ │ │ ├── stake-input.tsx │ │ │ │ ├── stake-modal.tsx │ │ │ │ ├── stake-review.tsx │ │ │ │ └── stake-toast.tsx │ │ │ ├── staking-radio-group.tsx │ │ │ ├── submit-button.tsx │ │ │ ├── support │ │ │ │ ├── support-card.tsx │ │ │ │ ├── support-faq.tsx │ │ │ │ ├── support-header-card.tsx │ │ │ │ └── support-socials.tsx │ │ │ ├── tags │ │ │ │ ├── add-tags.tsx │ │ │ │ ├── tag-utils.ts │ │ │ │ ├── tags-form.tsx │ │ │ │ ├── tags-list-input-portal.tsx │ │ │ │ ├── tags-modal.tsx │ │ │ │ ├── tags-review.tsx │ │ │ │ └── tags-search-combo-box.tsx │ │ │ ├── theme-test.tsx │ │ │ ├── transaction-state.tsx │ │ │ ├── usd-tooltip.tsx │ │ │ └── wrong-network-button.tsx │ │ ├── consts │ │ │ ├── assets.ts │ │ │ ├── emails.ts │ │ │ ├── errors.ts │ │ │ ├── feature-flags.ts │ │ │ ├── general.ts │ │ │ ├── index.ts │ │ │ ├── paths.ts │ │ │ └── quest.ts │ │ ├── entry.client.tsx │ │ ├── entry.server.tsx │ │ ├── layouts │ │ │ ├── full-page-layout.tsx │ │ │ ├── root-layout.tsx │ │ │ └── two-panel-layout.tsx │ │ ├── lib │ │ │ ├── abis │ │ │ │ ├── chainalysisOracle.ts │ │ │ │ ├── chainlinkEthUsdOracle.ts │ │ │ │ ├── multivault.ts │ │ │ │ └── relics.ts │ │ │ ├── graphql │ │ │ │ └── client.ts │ │ │ ├── hooks │ │ │ │ ├── useBatchCreateTriple.tsx │ │ │ │ ├── useContractWriteAndWait.tsx │ │ │ │ ├── useCopy.tsx │ │ │ │ ├── useCreateAtom.tsx │ │ │ │ ├── useCreateTriple.tsx │ │ │ │ ├── useDepositAtom.tsx │ │ │ │ ├── useDepositTriple.tsx │ │ │ │ ├── useFilteredIdentitySearch.tsx │ │ │ │ ├── useGetWalletBalance.tsx │ │ │ │ ├── useGoBack.tsx │ │ │ │ ├── useHandleCloseAttempt.tsx │ │ │ │ ├── useIdentityServerSearch.tsx │ │ │ │ ├── useImageUploadFetcher.tsx │ │ │ │ ├── useInvalidItems.tsx │ │ │ │ ├── useInviteCodeFetcher.tsx │ │ │ │ ├── useLiveLoader.ts │ │ │ │ ├── useLoaderFetcher.tsx │ │ │ │ ├── useMultivaultContract.tsx │ │ │ │ ├── useOffChainFetcher.tsx │ │ │ │ ├── usePrivySocialLinking.ts │ │ │ │ ├── useQuestCompletion.tsx │ │ │ │ ├── useQuestMdxContent.tsx │ │ │ │ ├── useRedeemAtom.tsx │ │ │ │ ├── useRedeemTriple.tsx │ │ │ │ ├── useSearchAndSortParams.tsx │ │ │ │ └── useTransactionReducer.ts │ │ │ ├── schemas │ │ │ │ ├── create-claim-schema.ts │ │ │ │ ├── create-identity-schema.ts │ │ │ │ ├── reval-schema.ts │ │ │ │ └── update-profile-schema.ts │ │ │ ├── services │ │ │ │ ├── activity.ts │ │ │ │ ├── claims.ts │ │ │ │ ├── connections.ts │ │ │ │ ├── identities.ts │ │ │ │ ├── lists.ts │ │ │ │ ├── phosphor.ts │ │ │ │ ├── points.ts │ │ │ │ ├── positions.ts │ │ │ │ ├── pricefeeds.ts │ │ │ │ ├── protocol.ts │ │ │ │ ├── relic.ts │ │ │ │ ├── stats.ts │ │ │ │ ├── tags.ts │ │ │ │ └── users.ts │ │ │ ├── state │ │ │ │ └── store.ts │ │ │ └── utils │ │ │ │ ├── app.ts │ │ │ │ ├── client-hints.tsx │ │ │ │ ├── environment.ts │ │ │ │ ├── fake-data.ts │ │ │ │ ├── http-requests.ts │ │ │ │ ├── logger.ts │ │ │ │ ├── maintenance.ts │ │ │ │ ├── misc.tsx │ │ │ │ ├── nonce-provider.tsx │ │ │ │ ├── params.ts │ │ │ │ ├── quest.tsx │ │ │ │ ├── redirect.ts │ │ │ │ ├── request-info.tsx │ │ │ │ ├── use-tx-reducer.ts │ │ │ │ └── wagmi.ts │ │ ├── polyfills.ts │ │ ├── root.tsx │ │ ├── routes │ │ │ ├── _index.tsx │ │ │ ├── actions+ │ │ │ │ ├── clear-onboarding-cookie.tsx │ │ │ │ ├── create-claim.tsx │ │ │ │ ├── create-emitter.tsx │ │ │ │ ├── create-identity.tsx │ │ │ │ ├── create-profile.tsx │ │ │ │ ├── edit-profile.tsx │ │ │ │ ├── logout.tsx │ │ │ │ ├── reconcile-positions.tsx │ │ │ │ ├── redeem-invite-code.tsx │ │ │ │ ├── reval.tsx │ │ │ │ ├── set-theme.tsx │ │ │ │ ├── upload-image.tsx │ │ │ │ └── upload-with-metadata.tsx │ │ │ ├── app+ │ │ │ │ ├── activity+ │ │ │ │ │ ├── _layout.tsx │ │ │ │ │ ├── global.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── personal.tsx │ │ │ │ ├── claim+ │ │ │ │ │ ├── $id+ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── $id.tsx │ │ │ │ ├── explore+ │ │ │ │ │ └── _index+ │ │ │ │ │ │ ├── _layout.tsx │ │ │ │ │ │ ├── claims.tsx │ │ │ │ │ │ ├── identities.tsx │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── lists.tsx │ │ │ │ ├── help-center+ │ │ │ │ │ ├── faq.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── home.tsx │ │ │ │ ├── identity+ │ │ │ │ │ ├── $id+ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── $id.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── list+ │ │ │ │ │ ├── $id+ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── $id.tsx │ │ │ │ ├── lists.tsx │ │ │ │ ├── maintenance+ │ │ │ │ │ └── reconcile-positions.tsx │ │ │ │ ├── profile+ │ │ │ │ │ ├── $wallet+ │ │ │ │ │ │ ├── connections.tsx │ │ │ │ │ │ ├── data-about.tsx │ │ │ │ │ │ ├── data-created.tsx │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── lists.tsx │ │ │ │ │ ├── $wallet.tsx │ │ │ │ │ └── _index+ │ │ │ │ │ │ ├── _layout.tsx │ │ │ │ │ │ ├── connections.tsx │ │ │ │ │ │ ├── data-about.tsx │ │ │ │ │ │ ├── data-created.tsx │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── lists.tsx │ │ │ │ └── quest+ │ │ │ │ │ ├── chapter+ │ │ │ │ │ ├── $id.tsx │ │ │ │ │ ├── 1-1-create_atom.tsx │ │ │ │ │ ├── 1-2-stake_identity.tsx │ │ │ │ │ ├── 1-3-create_claim.tsx │ │ │ │ │ ├── 1-4-stake_claim.tsx │ │ │ │ │ ├── 1-5-counter_stake_claim.tsx │ │ │ │ │ ├── 1-6-always_true.tsx │ │ │ │ │ └── 1-7-test_atom.tsx │ │ │ │ │ ├── content │ │ │ │ │ ├── 3b5315bb-f29b-4320-9997-6928b4bbf3e9-closing.mdx │ │ │ │ │ ├── 3b5315bb-f29b-4320-9997-6928b4bbf3e9-intro.mdx │ │ │ │ │ ├── 3b5315bb-f29b-4320-9997-6928b4bbf3e9-main.mdx │ │ │ │ │ ├── 89ef2072-2428-4695-994e-3c83c3f7f3be-closing.mdx │ │ │ │ │ ├── 89ef2072-2428-4695-994e-3c83c3f7f3be-intro.mdx │ │ │ │ │ ├── 89ef2072-2428-4695-994e-3c83c3f7f3be-main.mdx │ │ │ │ │ ├── 90cf4398-f7e5-4ec7-8088-c64d2da6a715-closing.mdx │ │ │ │ │ ├── 90cf4398-f7e5-4ec7-8088-c64d2da6a715-intro.mdx │ │ │ │ │ ├── 90cf4398-f7e5-4ec7-8088-c64d2da6a715-main.mdx │ │ │ │ │ ├── ac22e180-9923-4481-9cba-31e88f223e58-closing.mdx │ │ │ │ │ ├── ac22e180-9923-4481-9cba-31e88f223e58-intro.mdx │ │ │ │ │ ├── ac22e180-9923-4481-9cba-31e88f223e58-main-2.mdx │ │ │ │ │ ├── ac22e180-9923-4481-9cba-31e88f223e58-main.mdx │ │ │ │ │ ├── b4b7e0ed-a69a-4a0a-bf9b-8bf0afe979f9-closing.mdx │ │ │ │ │ ├── b4b7e0ed-a69a-4a0a-bf9b-8bf0afe979f9-intro.mdx │ │ │ │ │ ├── b4b7e0ed-a69a-4a0a-bf9b-8bf0afe979f9-main.mdx │ │ │ │ │ ├── dacdd63d-f978-433e-aeb0-54d165e8f936-closing.mdx │ │ │ │ │ ├── dacdd63d-f978-433e-aeb0-54d165e8f936-intro.mdx │ │ │ │ │ ├── dacdd63d-f978-433e-aeb0-54d165e8f936-main.mdx │ │ │ │ │ └── primitive-island-lore.mdx │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── narrative+ │ │ │ │ │ └── $id.tsx │ │ │ ├── app.tsx │ │ │ ├── create.tsx │ │ │ ├── event+ │ │ │ │ ├── attest.tsx │ │ │ │ └── create.tsx │ │ │ ├── intro+ │ │ │ │ └── index.tsx │ │ │ ├── invite.tsx │ │ │ ├── login.tsx │ │ │ ├── maintenance.tsx │ │ │ ├── privacy+ │ │ │ │ ├── index.tsx │ │ │ │ └── style.css │ │ │ ├── readonly+ │ │ │ │ ├── _layout.tsx │ │ │ │ ├── claim+ │ │ │ │ │ ├── $id+ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── $id.tsx │ │ │ │ ├── identity+ │ │ │ │ │ ├── $id+ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── $id.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── list+ │ │ │ │ │ ├── $id+ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── $id.tsx │ │ │ │ └── profile+ │ │ │ │ │ ├── $wallet+ │ │ │ │ │ ├── data-about.tsx │ │ │ │ │ ├── data-created.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── lists.tsx │ │ │ │ │ └── $wallet.tsx │ │ │ ├── refresh.tsx │ │ │ ├── resources+ │ │ │ │ ├── check-quest-success.tsx │ │ │ │ ├── create-claim.tsx │ │ │ │ ├── create-og.ts │ │ │ │ ├── create.tsx │ │ │ │ ├── get-claim.tsx │ │ │ │ ├── get-identities-by-ids.tsx │ │ │ │ ├── get-identities-by-param.tsx │ │ │ │ ├── get-identities.tsx │ │ │ │ ├── get-vault-details.tsx │ │ │ │ ├── search-claims-by-ids.tsx │ │ │ │ ├── search-identities-by-tags.tsx │ │ │ │ ├── search-identities.tsx │ │ │ │ ├── stake.tsx │ │ │ │ └── tag.tsx │ │ │ ├── restricted.tsx │ │ │ ├── sanctioned.tsx │ │ │ ├── sentry-example-page.tsx │ │ │ ├── terms+ │ │ │ │ ├── index.tsx │ │ │ │ └── style.css │ │ │ └── the-big-bang.tsx │ │ ├── styles │ │ │ └── globals.css │ │ └── types │ │ │ ├── claim.ts │ │ │ ├── claimr.ts │ │ │ ├── identity.ts │ │ │ ├── index.ts │ │ │ ├── navigation.ts │ │ │ ├── pagination.ts │ │ │ ├── privy.ts │ │ │ ├── quest-temp.ts │ │ │ ├── quest.ts │ │ │ ├── session.ts │ │ │ ├── tags.ts │ │ │ ├── transaction.ts │ │ │ ├── user.ts │ │ │ └── vault.ts │ ├── content-collections.ts │ ├── instrumentation.server.mjs │ ├── package.json │ ├── postcss.config.js │ ├── project.json │ ├── public │ │ ├── favicon.ico │ │ └── fonts │ │ │ ├── Geist-Medium.otf │ │ │ ├── Geist-Regular.otf │ │ │ └── Geist-SemiBold.otf │ ├── tailwind.config.js │ ├── tests │ │ └── sample.test.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ ├── tsconfig.spec.json │ ├── vite.config.ts │ ├── vitest.config.ts │ └── vitest.setup.ts └── template │ ├── .eslintrc.cjs │ ├── .gitignore │ ├── CHANGELOG.md │ ├── Dockerfile │ ├── README.md │ ├── app │ ├── .client │ │ ├── privy-button.tsx │ │ ├── privy-login-button.tsx │ │ ├── privy-logout-button.tsx │ │ ├── privy-logout.tsx │ │ ├── privy-provider.tsx │ │ ├── privy-refresh.tsx │ │ ├── privy-revalidate.tsx │ │ └── providers.tsx │ ├── .server │ │ ├── auth.ts │ │ ├── env.ts │ │ ├── multivault.ts │ │ ├── privy.ts │ │ ├── theme.ts │ │ └── viem.ts │ ├── assets │ │ ├── derp-face-1.png │ │ ├── derp-face-10.png │ │ ├── derp-face-11.png │ │ ├── derp-face-12.jpg │ │ ├── derp-face-2.png │ │ ├── derp-face-3.png │ │ ├── derp-face-4.png │ │ ├── derp-face-5.png │ │ ├── derp-face-6.png │ │ ├── derp-face-7.png │ │ ├── derp-face-8.png │ │ └── derp-face-9.png │ ├── components │ │ ├── bridge-to-base.tsx │ │ ├── built-on-base.tsx │ │ ├── container.tsx │ │ ├── error-list.tsx │ │ ├── error-page.tsx │ │ ├── get-started.tsx │ │ ├── header-logo.tsx │ │ ├── header.tsx │ │ ├── home-banner.tsx │ │ ├── info-popover.tsx │ │ ├── info-tooltip.tsx │ │ ├── navigation-link.tsx │ │ ├── pagination-component.tsx │ │ ├── revalidate-button.tsx │ │ ├── search-and-sort.tsx │ │ ├── search.tsx │ │ ├── skeleton.tsx │ │ ├── sort-select.tsx │ │ ├── sort.tsx │ │ ├── submit-button.tsx │ │ ├── usd-tooltip.tsx │ │ └── wrong-network-button.tsx │ ├── consts │ │ ├── assets.ts │ │ ├── emails.ts │ │ ├── errors.ts │ │ ├── general.ts │ │ ├── index.ts │ │ └── paths.ts │ ├── entry.client.tsx │ ├── entry.server.tsx │ ├── layouts │ │ ├── full-page-layout.tsx │ │ ├── root-layout.tsx │ │ └── two-panel-layout.tsx │ ├── lib │ │ ├── abis │ │ │ ├── chainalysisOracle.ts │ │ │ ├── chainlinkEthUsdOracle.ts │ │ │ ├── multivault.ts │ │ │ └── relics.ts │ │ ├── hooks │ │ │ ├── useBatchCreateTriple.tsx │ │ │ ├── useContractWriteAndWait.tsx │ │ │ ├── useCopy.tsx │ │ │ ├── useCreateAtom.tsx │ │ │ ├── useCreateTriple.tsx │ │ │ ├── useDepositAtom.tsx │ │ │ ├── useDepositTriple.tsx │ │ │ ├── useGetWalletBalance.tsx │ │ │ ├── useGoBack.tsx │ │ │ ├── useLiveLoader.ts │ │ │ ├── useLoaderFetcher.tsx │ │ │ ├── useMultivaultContract.tsx │ │ │ ├── useOffChainFetcher.tsx │ │ │ ├── useRedeemAtom.tsx │ │ │ ├── useRedeemTriple.tsx │ │ │ ├── useSearchAndSortParams.tsx │ │ │ └── useTransactionReducer.ts │ │ ├── services │ │ │ ├── phosphor.ts │ │ │ └── pricefeeds.ts │ │ ├── state │ │ │ └── store.ts │ │ └── utils │ │ │ ├── app.ts │ │ │ ├── client-hints.tsx │ │ │ ├── environment.ts │ │ │ ├── http-requests.ts │ │ │ ├── logger.ts │ │ │ ├── misc.tsx │ │ │ ├── nonce-provider.tsx │ │ │ ├── params.ts │ │ │ ├── redirect.ts │ │ │ ├── request-info.tsx │ │ │ ├── use-tx-reducer.ts │ │ │ └── wagmi.ts │ ├── polyfills.ts │ ├── root.tsx │ ├── routes │ │ ├── _index.tsx │ │ ├── actions+ │ │ │ ├── logout.tsx │ │ │ └── set-theme.tsx │ │ ├── app+ │ │ │ ├── index.tsx │ │ │ ├── playground-hydration-search.tsx │ │ │ ├── playground-hydration.tsx │ │ │ └── playground.tsx │ │ ├── app.tsx │ │ ├── login.tsx │ │ └── resources+ │ │ │ └── get-vault-details.tsx │ ├── styles │ │ └── globals.css │ └── types │ │ ├── claim.ts │ │ ├── claimr.ts │ │ ├── identity.ts │ │ ├── index.ts │ │ ├── navigation.ts │ │ ├── pagination.ts │ │ ├── privy.ts │ │ ├── quest-temp.ts │ │ ├── quest.ts │ │ ├── session.ts │ │ ├── tags.ts │ │ ├── transaction.ts │ │ ├── user.ts │ │ └── vault.ts │ ├── package.json │ ├── postcss.config.js │ ├── project.json │ ├── public │ └── favicon.ico │ ├── tailwind.config.ts │ ├── tests │ └── sample.test.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ ├── tsconfig.spec.json │ ├── vite.config.ts │ ├── vitest.config.ts │ └── vitest.setup.ts ├── docs ├── decisions │ └── 000-template.md ├── guiding-principles │ ├── component-grouping.md │ ├── remix-progressive-enhancement.md │ └── tailwind-styling.md ├── portal-deployments.md ├── remix-cookies.md ├── remix-flat-routes.md └── tailwind-theme-plugin.md ├── jest.config.ts ├── jest.preset.js ├── nx.json ├── package.json ├── packages ├── 1ui │ ├── .env.example │ ├── .eslintrc.cjs │ ├── .storybook │ │ ├── decorators.tsx │ │ ├── global.css │ │ ├── main.ts │ │ ├── manager.ts │ │ ├── preview.tsx │ │ ├── templates │ │ │ └── DocumentationTemplate.mdx │ │ ├── theme.ts │ │ └── vite.config.ts │ ├── CHANGELOG.md │ ├── CONTRIBUTING.md │ ├── README.md │ ├── components.json │ ├── package.json │ ├── postcss.config.js │ ├── project.json │ ├── src │ │ ├── components │ │ │ ├── Accordion │ │ │ │ ├── Accordion.mdx │ │ │ │ ├── Accordion.spec.tsx │ │ │ │ ├── Accordion.stories.tsx │ │ │ │ ├── Accordion.tsx │ │ │ │ └── index.ts │ │ │ ├── ActivePositionCard │ │ │ │ ├── ActivePositionCard.mdx │ │ │ │ ├── ActivePositionCard.spec.tsx │ │ │ │ ├── ActivePositionCard.stories.tsx │ │ │ │ ├── ActivePositionCard.tsx │ │ │ │ └── index.ts │ │ │ ├── AlertDialog │ │ │ │ ├── AlertDialog.mdx │ │ │ │ ├── AlertDialog.spec.tsx │ │ │ │ ├── AlertDialog.stories.tsx │ │ │ │ ├── AlertDialog.tsx │ │ │ │ └── index.ts │ │ │ ├── Avatar │ │ │ │ ├── Avatar.mdx │ │ │ │ ├── Avatar.spec.tsx │ │ │ │ ├── Avatar.stories.tsx │ │ │ │ ├── Avatar.tsx │ │ │ │ └── index.ts │ │ │ ├── Badge │ │ │ │ ├── Badge.mdx │ │ │ │ ├── Badge.spec.tsx │ │ │ │ ├── Badge.stories.tsx │ │ │ │ ├── Badge.tsx │ │ │ │ └── index.ts │ │ │ ├── Banner │ │ │ │ ├── Banner.mdx │ │ │ │ ├── Banner.spec.tsx │ │ │ │ ├── Banner.stories.tsx │ │ │ │ ├── Banner.tsx │ │ │ │ └── index.ts │ │ │ ├── Button │ │ │ │ ├── Button.spec.tsx │ │ │ │ ├── Button.stories.tsx │ │ │ │ ├── Button.tsx │ │ │ │ └── index.tsx │ │ │ ├── Checkbox │ │ │ │ ├── Checkbox.mdx │ │ │ │ ├── Checkbox.spec.tsx │ │ │ │ ├── Checkbox.stories.tsx │ │ │ │ ├── Checkbox.tsx │ │ │ │ └── index.ts │ │ │ ├── Claim │ │ │ │ ├── Claim.mdx │ │ │ │ ├── Claim.spec.tsx │ │ │ │ ├── Claim.stories.tsx │ │ │ │ ├── Claim.tsx │ │ │ │ └── index.ts │ │ │ ├── ClaimPositionRow │ │ │ │ ├── ClaimPositionRow.mdx │ │ │ │ ├── ClaimPositionRow.spec.tsx │ │ │ │ ├── ClaimPositionRow.stories.tsx │ │ │ │ ├── ClaimPositionRow.tsx │ │ │ │ ├── ClaimPositionRow.utils.ts │ │ │ │ └── index.ts │ │ │ ├── ClaimRow │ │ │ │ ├── ClaimRow.mdx │ │ │ │ ├── ClaimRow.spec.tsx │ │ │ │ ├── ClaimRow.stories.tsx │ │ │ │ ├── ClaimRow.tsx │ │ │ │ └── index.ts │ │ │ ├── ClaimStakeCard │ │ │ │ ├── ClaimStakeCard.mdx │ │ │ │ ├── ClaimStakeCard.spec.tsx │ │ │ │ ├── ClaimStakeCard.stories.tsx │ │ │ │ ├── ClaimStakeCard.tsx │ │ │ │ └── index.ts │ │ │ ├── ClaimStatus │ │ │ │ ├── ClaimStatus.mdx │ │ │ │ ├── ClaimStatus.spec.tsx │ │ │ │ ├── ClaimStatus.stories.tsx │ │ │ │ ├── ClaimStatus.tsx │ │ │ │ └── index.ts │ │ │ ├── Command │ │ │ │ ├── Command.mdx │ │ │ │ ├── Command.spec.tsx │ │ │ │ ├── Command.stories.tsx │ │ │ │ ├── Command.tsx │ │ │ │ └── index.ts │ │ │ ├── ContextMenu │ │ │ │ ├── ContextMenu.mdx │ │ │ │ ├── ContextMenu.spec.tsx │ │ │ │ ├── ContextMenu.stories.tsx │ │ │ │ ├── ContextMenu.tsx │ │ │ │ └── index.ts │ │ │ ├── Copy │ │ │ │ ├── Copy.mdx │ │ │ │ ├── Copy.spec.tsx │ │ │ │ ├── Copy.stories.tsx │ │ │ │ ├── Copy.tsx │ │ │ │ └── index.ts │ │ │ ├── Dialog │ │ │ │ ├── Dialog.mdx │ │ │ │ ├── Dialog.spec.tsx │ │ │ │ ├── Dialog.stories.tsx │ │ │ │ ├── Dialog.tsx │ │ │ │ └── index.ts │ │ │ ├── DropdownMenu │ │ │ │ ├── DropdownMenu.mdx │ │ │ │ ├── DropdownMenu.spec.tsx │ │ │ │ ├── DropdownMenu.stories.tsx │ │ │ │ ├── DropdownMenu.tsx │ │ │ │ └── index.ts │ │ │ ├── EmptyStateCard │ │ │ │ ├── EmptyStateCard.mdx │ │ │ │ ├── EmptyStateCard.spec.tsx │ │ │ │ ├── EmptyStateCard.stories.tsx │ │ │ │ ├── EmptyStateCard.tsx │ │ │ │ └── index.ts │ │ │ ├── ErrorStateCard │ │ │ │ ├── ErrorStateCard.mdx │ │ │ │ ├── ErrorStateCard.spec.tsx │ │ │ │ ├── ErrorStateCard.stories.tsx │ │ │ │ ├── ErrorStateCard.tsx │ │ │ │ └── index.ts │ │ │ ├── FeaturedListCard │ │ │ │ ├── FeaturedListCard.mdx │ │ │ │ ├── FeaturedListCard.spec.tsx │ │ │ │ ├── FeaturedListCard.stories.tsx │ │ │ │ ├── FeaturedListCard.tsx │ │ │ │ └── index.ts │ │ │ ├── FollowPosition │ │ │ │ ├── FollowPosition.mdx │ │ │ │ ├── FollowPosition.spec.tsx │ │ │ │ ├── FollowPosition.stories.tsx │ │ │ │ ├── FollowPosition.tsx │ │ │ │ └── index.ts │ │ │ ├── HoverCard │ │ │ │ ├── HoverCard.mdx │ │ │ │ ├── HoverCard.spec.tsx │ │ │ │ ├── HoverCard.stories.tsx │ │ │ │ ├── HoverCard.tsx │ │ │ │ └── index.ts │ │ │ ├── Icon │ │ │ │ ├── Icon.spec.tsx │ │ │ │ ├── Icon.sprites.svg │ │ │ │ ├── Icon.stories.tsx │ │ │ │ ├── Icon.tsx │ │ │ │ ├── Icon.types.ts │ │ │ │ └── index.ts │ │ │ ├── IdentityCard │ │ │ │ ├── IdentityCard.mdx │ │ │ │ ├── IdentityCard.spec.tsx │ │ │ │ ├── IdentityCard.stories.tsx │ │ │ │ ├── IdentityCard.tsx │ │ │ │ └── index.ts │ │ │ ├── IdentityInput │ │ │ │ ├── IdentityInput.mdx │ │ │ │ ├── IdentityInput.spec.tsx │ │ │ │ ├── IdentityInput.stories.tsx │ │ │ │ ├── IdentityInput.tsx │ │ │ │ └── index.ts │ │ │ ├── IdentityPosition │ │ │ │ ├── IdentityPosition.mdx │ │ │ │ ├── IdentityPosition.spec.tsx │ │ │ │ ├── IdentityPosition.stories.tsx │ │ │ │ ├── IdentityPosition.tsx │ │ │ │ └── index.ts │ │ │ ├── IdentityRow │ │ │ │ ├── IdentityRow.mdx │ │ │ │ ├── IdentityRow.spec.tsx │ │ │ │ ├── IdentityRow.stories.tsx │ │ │ │ ├── IdentityRow.tsx │ │ │ │ └── index.ts │ │ │ ├── IdentityStakeCard │ │ │ │ ├── IdentityStakeCard.mdx │ │ │ │ ├── IdentityStakeCard.spec.tsx │ │ │ │ ├── IdentityStakeCard.stories.tsx │ │ │ │ ├── IdentityStakeCard.tsx │ │ │ │ └── index.ts │ │ │ ├── IdentityTag │ │ │ │ ├── IdentityTag.mdx │ │ │ │ ├── IdentityTag.spec.tsx │ │ │ │ ├── IdentityTag.stories.tsx │ │ │ │ ├── IdentityTag.tsx │ │ │ │ └── index.ts │ │ │ ├── Indicators │ │ │ │ ├── Indicators.mdx │ │ │ │ ├── Indicators.spec.tsx │ │ │ │ ├── Indicators.stories.tsx │ │ │ │ ├── Indicators.tsx │ │ │ │ ├── components │ │ │ │ │ ├── ClaimValueDisplay.tsx │ │ │ │ │ ├── FeesAccrued.tsx │ │ │ │ │ ├── IdentityValueDisplay.tsx │ │ │ │ │ ├── MonetaryValue.tsx │ │ │ │ │ ├── PositionValueDisplay.tsx │ │ │ │ │ └── index.ts │ │ │ │ └── index.ts │ │ │ ├── InfoCard │ │ │ │ ├── InfoCard.mdx │ │ │ │ ├── InfoCard.spec.tsx │ │ │ │ ├── InfoCard.stories.tsx │ │ │ │ ├── InfoCard.tsx │ │ │ │ └── index.ts │ │ │ ├── Input │ │ │ │ ├── Input.mdx │ │ │ │ ├── Input.spec.tsx │ │ │ │ ├── Input.stories.tsx │ │ │ │ ├── Input.tsx │ │ │ │ └── index.ts │ │ │ ├── Label │ │ │ │ ├── Label.mdx │ │ │ │ ├── Label.spec.tsx │ │ │ │ ├── Label.stories.tsx │ │ │ │ ├── Label.tsx │ │ │ │ └── index.ts │ │ │ ├── ListCard │ │ │ │ ├── ListCard.mdx │ │ │ │ ├── ListCard.spec.tsx │ │ │ │ ├── ListCard.stories.tsx │ │ │ │ ├── ListCard.tsx │ │ │ │ └── index.ts │ │ │ ├── ListGrid │ │ │ │ ├── ListGrid.mdx │ │ │ │ ├── ListGrid.spec.tsx │ │ │ │ ├── ListGrid.stories.tsx │ │ │ │ ├── ListGrid.tsx │ │ │ │ └── index.ts │ │ │ ├── ListHeaderCard │ │ │ │ ├── ListHeaderCard.mdx │ │ │ │ ├── ListHeaderCard.spec.tsx │ │ │ │ ├── ListHeaderCard.stories.tsx │ │ │ │ ├── ListHeaderCard.tsx │ │ │ │ └── index.ts │ │ │ ├── ListIdentityCard │ │ │ │ ├── ListIdentityCard.mdx │ │ │ │ ├── ListIdentityCard.spec.tsx │ │ │ │ ├── ListIdentityCard.stories.tsx │ │ │ │ ├── ListIdentityCard.tsx │ │ │ │ └── index.ts │ │ │ ├── Pagination │ │ │ │ ├── Pagination.mdx │ │ │ │ ├── Pagination.spec.tsx │ │ │ │ ├── Pagination.stories.tsx │ │ │ │ ├── Pagination.tsx │ │ │ │ └── index.ts │ │ │ ├── PieChart │ │ │ │ ├── PieChart.mdx │ │ │ │ ├── PieChart.spec.tsx │ │ │ │ ├── PieChart.stories.tsx │ │ │ │ ├── PieChart.tsx │ │ │ │ └── index.ts │ │ │ ├── Popover │ │ │ │ ├── Popover.mdx │ │ │ │ ├── Popover.spec.tsx │ │ │ │ ├── Popover.stories.tsx │ │ │ │ ├── Popover.tsx │ │ │ │ └── index.ts │ │ │ ├── PositionCard │ │ │ │ ├── PositionCard.mdx │ │ │ │ ├── PositionCard.spec.tsx │ │ │ │ ├── PositionCard.stories.tsx │ │ │ │ ├── PositionCard.tsx │ │ │ │ ├── components │ │ │ │ │ ├── PositionCardFeesAccrued.tsx │ │ │ │ │ ├── PositionCardLastUpdated.tsx │ │ │ │ │ ├── PositionCardOwnership.tsx │ │ │ │ │ ├── PositionCardStaked.tsx │ │ │ │ │ └── index.ts │ │ │ │ └── index.ts │ │ │ ├── ProfileCard │ │ │ │ ├── ProfileCard.mdx │ │ │ │ ├── ProfileCard.stories.tsx │ │ │ │ ├── ProfileCard.tsx │ │ │ │ ├── components │ │ │ │ │ ├── ProfileCardHeader.tsx │ │ │ │ │ ├── ProfileCardStatItem.tsx │ │ │ │ │ └── index.ts │ │ │ │ └── index.ts │ │ │ ├── ProgressBar │ │ │ │ ├── ProgressBar.mdx │ │ │ │ ├── ProgressBar.spec.tsx │ │ │ │ ├── ProgressBar.stories.tsx │ │ │ │ ├── ProgressBar.tsx │ │ │ │ └── index.ts │ │ │ ├── ProgressCard │ │ │ │ ├── ProgressCard.mdx │ │ │ │ ├── ProgressCard.spec.tsx │ │ │ │ ├── ProgressCard.stories.tsx │ │ │ │ ├── ProgressCard.tsx │ │ │ │ └── index.ts │ │ │ ├── QuestHeaderCard │ │ │ │ ├── QuestHeaderCard.mdx │ │ │ │ ├── QuestHeaderCard.spec.tsx │ │ │ │ ├── QuestHeaderCard.stories.tsx │ │ │ │ ├── QuestHeaderCard.tsx │ │ │ │ └── index.ts │ │ │ ├── RadioGroup │ │ │ │ ├── RadioGroup.mdx │ │ │ │ ├── RadioGroup.spec.tsx │ │ │ │ ├── RadioGroup.stories.tsx │ │ │ │ ├── RadioGroup.tsx │ │ │ │ └── index.ts │ │ │ ├── Resizable │ │ │ │ ├── Resizable.mdx │ │ │ │ ├── Resizable.spec.tsx │ │ │ │ ├── Resizable.stories.tsx │ │ │ │ ├── Resizable.tsx │ │ │ │ └── index.ts │ │ │ ├── ScrollArea │ │ │ │ ├── ScrollArea.mdx │ │ │ │ ├── ScrollArea.spec.tsx │ │ │ │ ├── ScrollArea.stories.tsx │ │ │ │ ├── ScrollArea.tsx │ │ │ │ └── index.ts │ │ │ ├── SegmentedControl │ │ │ │ ├── SegmentedControl.mdx │ │ │ │ ├── SegmentedControl.spec.tsx │ │ │ │ ├── SegmentedControl.stories.tsx │ │ │ │ ├── SegmentedControl.tsx │ │ │ │ └── index.ts │ │ │ ├── Select │ │ │ │ ├── Select.mdx │ │ │ │ ├── Select.spec.tsx │ │ │ │ ├── Select.stories.tsx │ │ │ │ ├── Select.tsx │ │ │ │ └── index.ts │ │ │ ├── Separator │ │ │ │ ├── Separator.mdx │ │ │ │ ├── Separator.spec.tsx │ │ │ │ ├── Separator.stories.tsx │ │ │ │ ├── Separator.tsx │ │ │ │ └── index.ts │ │ │ ├── SidebarLayout │ │ │ │ ├── SidebarLayout.mdx │ │ │ │ ├── SidebarLayout.spec.tsx │ │ │ │ ├── SidebarLayout.stories.tsx │ │ │ │ ├── components │ │ │ │ │ ├── SidebarLayout.tsx │ │ │ │ │ ├── SidebarLayoutContent.tsx │ │ │ │ │ ├── SidebarLayoutNav.tsx │ │ │ │ │ ├── SidebarLayoutNavAvatar.tsx │ │ │ │ │ ├── SidebarLayoutNavBody.tsx │ │ │ │ │ ├── SidebarLayoutNavHeader.tsx │ │ │ │ │ ├── SidebarLayoutNavHeaderButton.tsx │ │ │ │ │ ├── SidebarLayoutProvider.tsx │ │ │ │ │ ├── SidebarNavItem.tsx │ │ │ │ │ └── index.ts │ │ │ │ ├── constants.ts │ │ │ │ └── index.ts │ │ │ ├── Skeleton │ │ │ │ ├── Skeleton.mdx │ │ │ │ ├── Skeleton.spec.tsx │ │ │ │ ├── Skeleton.stories.tsx │ │ │ │ ├── Skeleton.tsx │ │ │ │ └── index.ts │ │ │ ├── SocialLinks │ │ │ │ ├── SocialLinks.mdx │ │ │ │ ├── SocialLinks.spec.tsx │ │ │ │ ├── SocialLinks.stories.tsx │ │ │ │ ├── SocialLinks.tsx │ │ │ │ └── index.ts │ │ │ ├── StakeButton │ │ │ │ ├── StakeButton.mdx │ │ │ │ ├── StakeButton.spec.tsx │ │ │ │ ├── StakeButton.stories.tsx │ │ │ │ ├── StakeButton.tsx │ │ │ │ └── index.ts │ │ │ ├── StakeTVL │ │ │ │ ├── StakeTVL.mdx │ │ │ │ ├── StakeTVL.spec.tsx │ │ │ │ ├── StakeTVL.stories.tsx │ │ │ │ ├── StakeTVL.tsx │ │ │ │ └── index.ts │ │ │ ├── StakeholdersList │ │ │ │ ├── StakeholdersList.mdx │ │ │ │ ├── StakeholdersList.spec.tsx │ │ │ │ ├── StakeholdersList.stories.tsx │ │ │ │ ├── StakeholdersList.tsx │ │ │ │ └── index.ts │ │ │ ├── Switch │ │ │ │ ├── Switch.mdx │ │ │ │ ├── Switch.spec.tsx │ │ │ │ ├── Switch.stories.tsx │ │ │ │ ├── Switch.tsx │ │ │ │ └── index.ts │ │ │ ├── Table │ │ │ │ ├── Table.mdx │ │ │ │ ├── Table.spec.tsx │ │ │ │ ├── Table.stories.tsx │ │ │ │ ├── Table.tsx │ │ │ │ └── index.ts │ │ │ ├── Tabs │ │ │ │ ├── Tabs.mdx │ │ │ │ ├── Tabs.spec.tsx │ │ │ │ ├── Tabs.stories.tsx │ │ │ │ ├── Tabs.tsx │ │ │ │ └── index.ts │ │ │ ├── Tag │ │ │ │ ├── Tag.mdx │ │ │ │ ├── Tag.spec.tsx │ │ │ │ ├── Tag.stories.tsx │ │ │ │ ├── Tag.tsx │ │ │ │ └── index.ts │ │ │ ├── Tags │ │ │ │ ├── Tags.mdx │ │ │ │ ├── Tags.spec.tsx │ │ │ │ ├── Tags.stories.tsx │ │ │ │ ├── Tags.tsx │ │ │ │ └── index.ts │ │ │ ├── TagsListInput │ │ │ │ ├── TagsListInput.mdx │ │ │ │ ├── TagsListInput.spec.tsx │ │ │ │ ├── TagsListInput.stories.tsx │ │ │ │ ├── TagsListInput.tsx │ │ │ │ └── index.ts │ │ │ ├── Text │ │ │ │ ├── Text.spec.tsx │ │ │ │ ├── Text.stories.tsx │ │ │ │ ├── Text.tsx │ │ │ │ └── index.ts │ │ │ ├── Textarea │ │ │ │ ├── Textarea.mdx │ │ │ │ ├── Textarea.spec.tsx │ │ │ │ ├── Textarea.stories.tsx │ │ │ │ ├── Textarea.tsx │ │ │ │ └── index.ts │ │ │ ├── Toaster │ │ │ │ ├── Toaster.mdx │ │ │ │ ├── Toaster.stories.tsx │ │ │ │ ├── Toaster.tsx │ │ │ │ └── index.ts │ │ │ ├── Tooltip │ │ │ │ ├── Tooltip.mdx │ │ │ │ ├── Tooltip.spec.tsx │ │ │ │ ├── Tooltip.stories.tsx │ │ │ │ ├── Tooltip.tsx │ │ │ │ └── index.ts │ │ │ ├── TransactionStatusCard │ │ │ │ ├── TransactionStatusCard.mdx │ │ │ │ ├── TransactionStatusCard.spec.tsx │ │ │ │ ├── TransactionStatusCard.stories.tsx │ │ │ │ ├── TransactionStatusCard.tsx │ │ │ │ └── index.ts │ │ │ ├── TransactionStatusIndicator │ │ │ │ ├── TransactionStatusIndicator.mdx │ │ │ │ ├── TransactionStatusIndicator.spec.tsx │ │ │ │ ├── TransactionStatusIndicator.stories.tsx │ │ │ │ ├── TransactionStatusIndicator.tsx │ │ │ │ ├── TransactionStatusIndicator.utils.spec.tsx │ │ │ │ ├── TransactionStatusIndicator.utils.ts │ │ │ │ └── index.ts │ │ │ ├── Trunctacular │ │ │ │ ├── Trunctacular.mdx │ │ │ │ ├── Trunctacular.spec.tsx │ │ │ │ ├── Trunctacular.stories.tsx │ │ │ │ ├── Trunctacular.tsx │ │ │ │ └── index.ts │ │ │ ├── ValueDisplay │ │ │ │ ├── ValueDisplay.mdx │ │ │ │ ├── ValueDisplay.spec.tsx │ │ │ │ ├── ValueDisplay.stories.tsx │ │ │ │ ├── ValueDisplay.tsx │ │ │ │ └── index.ts │ │ │ └── index.tsx │ │ ├── docs │ │ │ ├── dark-theme.mdx │ │ │ ├── introduction.mdx │ │ │ ├── light-theme.mdx │ │ │ └── palette.mdx │ │ ├── index.d.ts │ │ ├── index.ts │ │ ├── styles │ │ │ ├── globals.css │ │ │ ├── index.ts │ │ │ ├── palette.ts │ │ │ ├── theme-plugin.ts │ │ │ ├── theme-preset.ts │ │ │ ├── themes.ts │ │ │ └── utils.ts │ │ ├── types │ │ │ ├── currency.ts │ │ │ ├── general.ts │ │ │ ├── index.ts │ │ │ ├── quest.ts │ │ │ └── transactions.ts │ │ └── utils │ │ │ ├── date.spec.ts │ │ │ ├── date.ts │ │ │ ├── index.ts │ │ │ ├── number.spec.ts │ │ │ ├── number.ts │ │ │ ├── progress.ts │ │ │ ├── wallet.spec.ts │ │ │ └── wallet.ts │ ├── tailwind.config.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ ├── tsconfig.spec.json │ ├── tsconfig.typecheck.json │ ├── tsup.config.ts │ ├── types.d.ts │ ├── vitest.config.ts │ └── vitest.setup.ts ├── api │ ├── .env.example │ ├── .eslintrc.cjs │ ├── .gitignore │ ├── CHANGELOG.md │ ├── README.md │ ├── openapi-ts.config.js │ ├── package.json │ ├── project.json │ ├── src │ │ ├── api-client │ │ │ ├── core │ │ │ │ ├── ApiError.ts │ │ │ │ ├── ApiRequestOptions.ts │ │ │ │ ├── ApiResult.ts │ │ │ │ ├── CancelablePromise.ts │ │ │ │ ├── OpenAPI.ts │ │ │ │ └── request.ts │ │ │ ├── index.ts │ │ │ ├── services.gen.ts │ │ │ └── types.gen.ts │ │ ├── index.d.ts │ │ └── index.ts │ ├── tests │ │ └── sample.test.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ └── vitest.config.ts ├── graphql │ ├── .env.example │ ├── .eslintrc.cjs │ ├── .gitignore │ ├── CHANGELOG.md │ ├── README.md │ ├── codegen.ts │ ├── package.json │ ├── project.json │ ├── schema.graphql │ ├── src │ │ ├── client.ts │ │ ├── constants.ts │ │ ├── fragments │ │ │ ├── account.graphql │ │ │ ├── atom.graphql │ │ │ ├── deposit.graphql │ │ │ ├── event.graphql │ │ │ ├── follow.graphql │ │ │ ├── position.graphql │ │ │ ├── redemption.graphql │ │ │ ├── stat.graphql │ │ │ ├── triple.graphql │ │ │ └── vault.graphql │ │ ├── generated │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── mutations │ │ │ └── pin-thing.graphql │ │ └── queries │ │ │ ├── accounts.graphql │ │ │ ├── atoms.graphql │ │ │ ├── claims.graphql │ │ │ ├── events.graphql │ │ │ ├── follows.graphql │ │ │ ├── lists.graphql │ │ │ ├── points.graphql │ │ │ ├── positions.graphql │ │ │ ├── signals.graphql │ │ │ ├── stats.graphql │ │ │ ├── tags.graphql │ │ │ ├── triples.graphql │ │ │ └── vaults.graphql │ ├── tests │ │ └── client.test.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ ├── tsup.config.ts │ └── vitest.config.ts ├── protocol │ ├── .env.example │ ├── .eslintrc.cjs │ ├── .gitignore │ ├── CHANGELOG.md │ ├── CONTRIBUTING.md │ ├── README.md │ ├── package.json │ ├── project.json │ ├── scripts │ │ ├── CustomMulticall3.json │ │ ├── EthMultiVault.json │ │ └── generate.mjs │ ├── src │ │ ├── abi.ts │ │ ├── deployments.ts │ │ ├── index.ts │ │ └── multivault.ts │ ├── tests │ │ ├── bytecode.ts │ │ ├── constants.ts │ │ ├── deploy.ts │ │ ├── globalSetup.ts │ │ ├── multivault.test.ts │ │ ├── setup.ts │ │ └── utils.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ ├── tsup.config.ts │ └── vitest.config.ts └── sdk │ ├── .env.example │ ├── .eslintrc.cjs │ ├── .gitignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── project.json │ ├── src │ └── index.ts │ ├── tests │ └── sample.test.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ └── vitest.config.ts ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── project.json ├── render.yaml ├── tools ├── .eslintrc.cjs ├── .gitignore ├── README.md ├── generators.json ├── jest.config.ts ├── package.json ├── project.json ├── src │ ├── generators │ │ └── ui-component │ │ │ ├── files │ │ │ ├── __name__.mdx │ │ │ ├── __name__.spec.tsx.template │ │ │ ├── __name__.stories.tsx.template │ │ │ ├── __name__.tsx.template │ │ │ └── index.ts.template │ │ │ ├── generator.spec.ts │ │ │ ├── generator.ts │ │ │ ├── schema.d.ts │ │ │ └── schema.json │ └── index.ts ├── tsconfig.json ├── tsconfig.lib.json └── tsconfig.spec.json └── tsconfig.base.json /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env* 3 | tmp/ 4 | dist/ 5 | .git -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/.env.example -------------------------------------------------------------------------------- /.github/pr-title-checker-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "LABEL": { 3 | "name": "title needs formatting", 4 | "color": "CDAC11" 5 | }, 6 | "CHECKS": { 7 | "regexp": "^([A-Z]{3,}-[0-9]+|[A-Z]{3,}-[0-9]+( )[A-Z]{3,}-[0-9]+) ((feat|fix|chore)[(](portal|1ui|core|subgraph|protocol|sdk|substream|api|tools|repo|graphql|template|data-populator)(,(portal|1ui|core|subgraph|protocol|sdk|substream|api|tools|repo|graphql|template|data-populator))*[)]): .+$", 8 | "regexpFlags": "i" 9 | }, 10 | "MESSAGES": { 11 | "success": "All good", 12 | "failure": "Doesn't match required format", 13 | "notice": "" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Affected Packages 2 | 3 | Apps 4 | 5 | - [ ] data populator 6 | - [ ] portal 7 | - [ ] template 8 | 9 | Packages 10 | 11 | - [ ] 1ui 12 | - [ ] api 13 | - [ ] graphql 14 | - [ ] protocol 15 | - [ ] sdk 16 | 17 | Tools 18 | 19 | - [ ] tools 20 | 21 | ## Overview 22 | 23 | Overview of the changes in the PR. 24 | 25 | ## Screen Captures 26 | 27 | If applicable, add screenshots or screen captures of your changes. 28 | 29 | ## Declaration 30 | 31 | - [ ] I hereby declare that I have abided by the rules and regulations as outlined in the [CONTRIBUTING.md](https://github.com/0xIntuition/intuition-ts/blob/main/CONTRIBUTING.md) 32 | -------------------------------------------------------------------------------- /.github/workflows/pr_title_checker.yml: -------------------------------------------------------------------------------- 1 | # https://github.com/marketplace/actions/pr-title-checker 2 | # https://github.com/thehanimo/pr-title-checker 3 | 4 | name: 'PR Title Checker' 5 | 6 | on: 7 | pull_request_target: 8 | types: [opened, edited, synchronize, reopened, labeled, unlabeled] 9 | 10 | jobs: 11 | check: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: thehanimo/pr-title-checker@v1.4.2 15 | with: 16 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 17 | pass_on_octokit_error: false 18 | configuration_path: '.github/pr-title-checker-config.json' 19 | -------------------------------------------------------------------------------- /.github/workflows/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name: Release Drafter 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | types: [opened, reopened, synchronize] 9 | 10 | permissions: 11 | contents: read 12 | 13 | jobs: 14 | update_release_draft: 15 | permissions: 16 | # write permission is required to create a GitHub release 17 | contents: write 18 | # write permission is required for autolabeler 19 | pull-requests: write 20 | runs-on: ubuntu-latest 21 | steps: 22 | - uses: release-drafter/release-drafter@v6 23 | env: 24 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .vscode/ 3 | out/ 4 | /dist/ 5 | tmp/ 6 | 7 | .nx/cache 8 | .nx/workspace-data 9 | packages/1ui/storybook-static 10 | 11 | .env* 12 | !.env.example 13 | .secrets 14 | act.sh 15 | 16 | # Verdaccio local registry files 17 | .verdaccio-db.json 18 | .npmrc 19 | 20 | # Build outputs 21 | /dist/ 22 | **/dist/ 23 | packages/*/dist/ -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | pnpm pre-commit -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | **/*.yaml 2 | **/*.template 3 | /.nx/workspace-data -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "prettier-plugin-tailwindcss", 4 | "@ianvs/prettier-plugin-sort-imports" 5 | ], 6 | "pluginSearchDirs": ["./node_modules"], 7 | "semi": false, 8 | "singleQuote": true, 9 | "printWidth": 80, 10 | "tabWidth": 2, 11 | "importOrder": [ 12 | "^react$", 13 | "", 14 | "^@0xintuition/(.*)$", 15 | "", 16 | "", 17 | "", 18 | "^[./]" 19 | ], 20 | "importOrderParserPlugins": [ 21 | "classProperties", 22 | "typescript", 23 | "jsx", 24 | "importAssertions" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /apps/data-populator/.env.example: -------------------------------------------------------------------------------- 1 | # PINATA AND IPFS 2 | PINATA_JWT_KEY= 3 | PINATA_GATEWAY_KEY= 4 | IPFS_GATEWAY= 5 | PRIVATE_KEY= 6 | PRIVATE_KEY_DEV= 7 | ADDITIONAL_STAKE_ATOM=100000000000 # 1e-7 ether (1^12) 8 | ADDITIONAL_STAKE_TRIPLE=100000000000 # 1e-7 ether (1^12) 9 | # SUPABASE 10 | SUPABASE_URL= 11 | SUPABASE_KEY= 12 | # ENVIRONMENT 13 | VITE_DEPLOY_ENV=development 14 | # CLOUDINARY 15 | CLOUDINARY_CLOUD_NAME= 16 | CLOUDINARY_API_KEY= 17 | CLOUDINARY_API_SECRET= 18 | # PRIVY ENV 19 | PRIVY_APP_ID= 20 | PRIVY_AUTH_URL= 21 | PRIVY_APP_SECRET= 22 | PRIVY_VERIFICATION_KEY= 23 | VITE_ORIGIN_URL= 24 | VITE_ALCHEMY_API_KEY= -------------------------------------------------------------------------------- /apps/data-populator/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.base.cjs'], 3 | env: { 4 | node: true, 5 | jest: true, 6 | }, 7 | overrides: [ 8 | { 9 | files: ['*.ts', '*.tsx', '*.js', '*.jsx'], 10 | rules: {}, 11 | }, 12 | { 13 | files: ['*.ts', '*.tsx'], 14 | rules: { 15 | '@typescript-eslint/no-unused-vars': [ 16 | 'error', 17 | { 18 | varsIgnorePattern: '^React$', 19 | }, 20 | ], 21 | }, 22 | }, 23 | { 24 | files: ['*.js', '*.jsx'], 25 | rules: {}, 26 | }, 27 | { 28 | files: ['*.json'], 29 | parser: 'jsonc-eslint-parser', 30 | rules: {}, 31 | }, 32 | ], 33 | } 34 | -------------------------------------------------------------------------------- /apps/data-populator/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | /.cache 4 | /build 5 | .env 6 | /.content-collections 7 | .DS_Store 8 | # Sentry Config File 9 | .sentryclirc 10 | 11 | # Sentry Config File 12 | .env.sentry-build-plugin 13 | -------------------------------------------------------------------------------- /apps/data-populator/app/.client/privy-refresh.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react' 2 | 3 | import { usePrivy } from '@privy-io/react-auth' 4 | import { useRevalidator } from '@remix-run/react' 5 | 6 | export default function PrivyRefresh() { 7 | const { ready, getAccessToken } = usePrivy() 8 | const { revalidate } = useRevalidator() 9 | 10 | useEffect(() => { 11 | async function refresh() { 12 | if (ready) { 13 | await getAccessToken() 14 | revalidate() 15 | } 16 | } 17 | 18 | refresh() 19 | }, [ready, revalidate]) 20 | 21 | return
22 | } 23 | -------------------------------------------------------------------------------- /apps/data-populator/app/.client/privy-revalidate.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react' 2 | 3 | import { usePrivy } from '@privy-io/react-auth' 4 | import { useRevalidator } from '@remix-run/react' 5 | 6 | export default function PrivyRevalidate() { 7 | const { ready, authenticated, user: privyUser } = usePrivy() 8 | const { revalidate } = useRevalidator() 9 | 10 | useEffect(() => { 11 | // if privyUser has changed, revalidate the page 12 | if (ready && authenticated && privyUser) { 13 | revalidate() 14 | } 15 | // omits authenticate from the exhaustive deps 16 | // eslint-disable-next-line react-hooks/exhaustive-deps 17 | }, [ready, privyUser, revalidate]) 18 | 19 | return
20 | } 21 | -------------------------------------------------------------------------------- /apps/data-populator/app/.server/db.ts: -------------------------------------------------------------------------------- 1 | // This is a placeholder. Replace with actual database logic later. 2 | export const db = { 3 | // Add mock methods as needed 4 | } 5 | -------------------------------------------------------------------------------- /apps/data-populator/app/.server/theme.ts: -------------------------------------------------------------------------------- 1 | import { Theme, themesList } from '@0xintuition/1ui' 2 | 3 | import * as cookie from 'cookie' 4 | 5 | const cookieName = 'theme' 6 | 7 | export function getTheme(request: Request): Theme | undefined { 8 | const cookieHeader = request.headers.get('Cookie') 9 | const parsed = cookieHeader && cookie.parse(cookieHeader)[cookieName] 10 | 11 | if (themesList.includes(parsed as Theme)) { 12 | return parsed as Theme 13 | } 14 | 15 | return undefined 16 | } 17 | 18 | // Cookie value set by the server 19 | export function setTheme(theme?: Theme) { 20 | if (theme) { 21 | return cookie.serialize(cookieName, theme, { path: '/' }) 22 | } 23 | return cookie.serialize(cookieName, '', { path: '/', maxAge: 0 }) 24 | } 25 | -------------------------------------------------------------------------------- /apps/data-populator/app/assets/derp-face-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/data-populator/app/assets/derp-face-1.png -------------------------------------------------------------------------------- /apps/data-populator/app/assets/derp-face-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/data-populator/app/assets/derp-face-10.png -------------------------------------------------------------------------------- /apps/data-populator/app/assets/derp-face-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/data-populator/app/assets/derp-face-11.png -------------------------------------------------------------------------------- /apps/data-populator/app/assets/derp-face-12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/data-populator/app/assets/derp-face-12.jpg -------------------------------------------------------------------------------- /apps/data-populator/app/assets/derp-face-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/data-populator/app/assets/derp-face-2.png -------------------------------------------------------------------------------- /apps/data-populator/app/assets/derp-face-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/data-populator/app/assets/derp-face-3.png -------------------------------------------------------------------------------- /apps/data-populator/app/assets/derp-face-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/data-populator/app/assets/derp-face-4.png -------------------------------------------------------------------------------- /apps/data-populator/app/assets/derp-face-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/data-populator/app/assets/derp-face-5.png -------------------------------------------------------------------------------- /apps/data-populator/app/assets/derp-face-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/data-populator/app/assets/derp-face-6.png -------------------------------------------------------------------------------- /apps/data-populator/app/assets/derp-face-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/data-populator/app/assets/derp-face-7.png -------------------------------------------------------------------------------- /apps/data-populator/app/assets/derp-face-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/data-populator/app/assets/derp-face-8.png -------------------------------------------------------------------------------- /apps/data-populator/app/assets/derp-face-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/data-populator/app/assets/derp-face-9.png -------------------------------------------------------------------------------- /apps/data-populator/app/components/container.tsx: -------------------------------------------------------------------------------- 1 | import type { ReactNode } from 'react' 2 | 3 | import { cn } from '@lib/utils/misc' 4 | 5 | export default function Container({ 6 | children, 7 | className, 8 | }: { 9 | children: ReactNode 10 | className?: string 11 | }) { 12 | return ( 13 |
14 | {children} 15 |
16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /apps/data-populator/app/components/error-list.tsx: -------------------------------------------------------------------------------- 1 | export default function ErrorList({ 2 | id, 3 | errors, 4 | }: { 5 | id?: string 6 | errors?: Array | null 7 | }) { 8 | return errors?.length ? ( 9 |
    10 | {errors.map((error, i) => ( 11 |
  • 12 | {error} 13 |
  • 14 | ))} 15 |
16 | ) : null 17 | } 18 | -------------------------------------------------------------------------------- /apps/data-populator/app/components/revalidate-button.tsx: -------------------------------------------------------------------------------- 1 | import { Button, ButtonSize, ButtonVariant } from '@0xintuition/1ui' 2 | 3 | import { useRevalidator } from '@remix-run/react' 4 | 5 | interface RevalidateButtonProps { 6 | className?: string 7 | } 8 | 9 | export function RevalidateButton({ className }: RevalidateButtonProps) { 10 | const revalidator = useRevalidator() 11 | 12 | return ( 13 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /apps/data-populator/app/components/search.tsx: -------------------------------------------------------------------------------- 1 | import { Input } from '@0xintuition/1ui' 2 | 3 | interface SearchProps { 4 | handleSearchChange: (event: React.ChangeEvent) => void 5 | } 6 | 7 | export function Search({ handleSearchChange }: SearchProps) { 8 | return ( 9 | 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /apps/data-populator/app/components/sort.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { SortDirection } from '@0xintuition/api' 4 | 5 | import { SortOption, SortSelect } from '@components/sort-select' 6 | 7 | interface SortProps { 8 | options: SortOption[] 9 | handleSortChange: (newSortBy: T, newDirection: SortDirection) => void 10 | } 11 | 12 | export function Sort({ options, handleSortChange }: SortProps) { 13 | return 14 | } 15 | -------------------------------------------------------------------------------- /apps/data-populator/app/components/usd-tooltip.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | Tooltip, 3 | TooltipContent, 4 | TooltipProvider, 5 | TooltipTrigger, 6 | } from '@0xintuition/1ui' 7 | 8 | export const UsdTooltip = ({ 9 | ethValue, 10 | usdValue, 11 | }: { 12 | ethValue: string 13 | usdValue: string 14 | }) => { 15 | return ( 16 | 17 | 18 | {ethValue} ETH 19 | ${usdValue} USD 20 | 21 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /apps/data-populator/app/consts/assets.ts: -------------------------------------------------------------------------------- 1 | export const HOME_BANNER_MP4 = 2 | 'https://res.cloudinary.com/dfpwy9nyv/video/upload/f_auto:video,q_auto/v1/Portal%20Assets/home-banner-video' 3 | -------------------------------------------------------------------------------- /apps/data-populator/app/consts/emails.ts: -------------------------------------------------------------------------------- 1 | export const SUPPORT_EMAIL_ADDRESS = 'support@intuition.systems' 2 | -------------------------------------------------------------------------------- /apps/data-populator/app/consts/errors.ts: -------------------------------------------------------------------------------- 1 | export const NO_WALLET_ERROR = 'No wallet found in session' 2 | export const NO_PARAM_ID_ERROR = 'Invalid or missing param ID' 3 | export const NO_USER_IDENTITY_ERROR = 'No user identity found' 4 | export const NO_IDENTITY_ERROR = 'No identity found' 5 | export const INVALID_CREATOR_ID_ERROR = 'Invalid or missing creator ID' 6 | export const GENERIC_ERROR_MSG = 'An error occurred' 7 | export const NO_CLAIM_ERROR = 'No claim found' 8 | export const NO_USER_TOTALS_ERROR = 'No user totals found' 9 | export const NO_CONNECTIONS_DATA_ERROR = 'No connections data found' 10 | export const NO_FOLLOW_CLAIM_ERROR = 'No follow claim found' 11 | -------------------------------------------------------------------------------- /apps/data-populator/app/consts/index.ts: -------------------------------------------------------------------------------- 1 | export * from './assets' 2 | export * from './emails' 3 | export * from './errors' 4 | export * from './general' 5 | export * from './paths' 6 | -------------------------------------------------------------------------------- /apps/data-populator/app/consts/paths.ts: -------------------------------------------------------------------------------- 1 | export const PATHS = { 2 | // Root paths 3 | ROOT: '/', 4 | APP: '/app', 5 | DATA_POPULATOR: '/data-populator', 6 | // General 7 | LOGIN: '/login', 8 | } 9 | -------------------------------------------------------------------------------- /apps/data-populator/app/entry.client.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * By default, Remix will handle hydrating your app on the client for you. 3 | * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨ 4 | * For more information, see https://remix.run/file-conventions/entry.client 5 | */ 6 | 7 | // import './polyfills' 8 | import { startTransition, StrictMode } from 'react' 9 | 10 | import { RemixBrowser } from '@remix-run/react' 11 | import { hydrateRoot } from 'react-dom/client' 12 | 13 | startTransition(() => { 14 | hydrateRoot( 15 | document, 16 | 17 | 18 | , 19 | ) 20 | }) 21 | -------------------------------------------------------------------------------- /apps/data-populator/app/layouts/full-page-layout.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | interface FullPageLayoutProps { 4 | children: React.ReactNode 5 | } 6 | 7 | const FullPageLayout: React.FC = ({ children }) => { 8 | return ( 9 |
10 | {children} 11 |
12 | ) 13 | } 14 | 15 | export default FullPageLayout 16 | -------------------------------------------------------------------------------- /apps/data-populator/app/layouts/root-layout.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | interface RootLayoutProps { 4 | children: React.ReactNode 5 | } 6 | 7 | const RootLayout: React.FC = ({ children }) => { 8 | return ( 9 |
10 |
11 | {children} 12 |
13 |
14 | ) 15 | } 16 | 17 | export default RootLayout 18 | -------------------------------------------------------------------------------- /apps/data-populator/app/lib/hooks/useBatchCreateAtomWagmi.tsx: -------------------------------------------------------------------------------- 1 | import { CURRENT_ENV } from '@consts/general' 2 | import { getChainEnvConfig } from '@lib/utils/environment' 3 | import { GetContractReturnType } from 'viem' 4 | 5 | import { useContractWriteAndWait } from './useContractWriteAndWait' 6 | import { useMultivaultContract } from './useMultivaultContract' 7 | 8 | export const useBatchCreateAtomWagmi = () => { 9 | const multivault = useMultivaultContract( 10 | getChainEnvConfig(CURRENT_ENV).chainId.toString(), 11 | ) as GetContractReturnType 12 | 13 | return useContractWriteAndWait({ 14 | ...multivault, 15 | // @ts-ignore TODO: Fix type for useContractWriteAndWait 16 | functionName: 'batchCreateAtom', 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /apps/data-populator/app/lib/hooks/useBatchCreateTriple.tsx: -------------------------------------------------------------------------------- 1 | import { CURRENT_ENV } from 'app/consts' 2 | import type { GetContractReturnType } from 'viem' 3 | 4 | import { getChainEnvConfig } from '../utils/environment' 5 | import { useContractWriteAndWait } from './useContractWriteAndWait' 6 | import { useMultivaultContract } from './useMultivaultContract' 7 | 8 | export const useBatchCreateTriple = () => { 9 | const multivault = useMultivaultContract( 10 | getChainEnvConfig(CURRENT_ENV).chainId.toString(), 11 | ) as GetContractReturnType 12 | 13 | return useContractWriteAndWait({ 14 | ...multivault, 15 | // @ts-ignore TODO: Fix type for useContractWriteAndWait 16 | functionName: 'batchCreateTriple', 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /apps/data-populator/app/lib/hooks/useCopy.tsx: -------------------------------------------------------------------------------- 1 | import { useCallback, useState } from 'react' 2 | 3 | export const useCopy = (duration = 2000) => { 4 | const [copied, setCopied] = useState(false) 5 | 6 | const copy = useCallback( 7 | (text: string) => { 8 | navigator.clipboard.writeText(text) 9 | setCopied(true) 10 | setTimeout(() => setCopied(false), duration) 11 | }, 12 | [duration], 13 | ) 14 | 15 | return { copied, copy } 16 | } 17 | -------------------------------------------------------------------------------- /apps/data-populator/app/lib/hooks/useCreateAtom.tsx: -------------------------------------------------------------------------------- 1 | import { CURRENT_ENV } from 'app/consts' 2 | import type { GetContractReturnType } from 'viem' 3 | 4 | import { getChainEnvConfig } from '../utils/environment' 5 | import { useContractWriteAndWait } from './useContractWriteAndWait' 6 | import { useMultivaultContract } from './useMultivaultContract' 7 | 8 | export const useCreateAtom = () => { 9 | const multivault = useMultivaultContract( 10 | getChainEnvConfig(CURRENT_ENV).chainId.toString(), 11 | ) as GetContractReturnType 12 | 13 | return useContractWriteAndWait({ 14 | ...multivault, 15 | // @ts-ignore TODO: Fix type for useContractWriteAndWait 16 | functionName: 'createAtom', 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /apps/data-populator/app/lib/hooks/useCreateTriple.tsx: -------------------------------------------------------------------------------- 1 | import { CURRENT_ENV } from 'app/consts' 2 | import type { GetContractReturnType } from 'viem' 3 | 4 | import { getChainEnvConfig } from '../utils/environment' 5 | import { useContractWriteAndWait } from './useContractWriteAndWait' 6 | import { useMultivaultContract } from './useMultivaultContract' 7 | 8 | export const useCreateTriple = () => { 9 | const multivault = useMultivaultContract( 10 | getChainEnvConfig(CURRENT_ENV).chainId.toString(), 11 | ) as GetContractReturnType 12 | 13 | return useContractWriteAndWait({ 14 | ...multivault, 15 | // @ts-ignore TODO: Fix type for useContractWriteAndWait 16 | functionName: 'createTriple', 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /apps/data-populator/app/lib/hooks/useDepositAtom.tsx: -------------------------------------------------------------------------------- 1 | import { CURRENT_ENV } from 'app/consts' 2 | import type { GetContractReturnType } from 'viem' 3 | 4 | import { getChainEnvConfig } from '../utils/environment' 5 | import { useContractWriteAndWait } from './useContractWriteAndWait' 6 | import { useMultivaultContract } from './useMultivaultContract' 7 | 8 | export const useDepositAtom = (contract: string) => { 9 | const multivault = useMultivaultContract( 10 | contract, 11 | getChainEnvConfig(CURRENT_ENV).chainId, 12 | ) as GetContractReturnType 13 | 14 | return useContractWriteAndWait({ 15 | ...multivault, 16 | // @ts-ignore TODO: Fix type for useContractWriteAndWait 17 | functionName: 'depositAtom', 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /apps/data-populator/app/lib/hooks/useDepositTriple.tsx: -------------------------------------------------------------------------------- 1 | import { CURRENT_ENV } from 'app/consts' 2 | import type { GetContractReturnType } from 'viem' 3 | 4 | import { getChainEnvConfig } from '../utils/environment' 5 | import { useContractWriteAndWait } from './useContractWriteAndWait' 6 | import { useMultivaultContract } from './useMultivaultContract' 7 | 8 | export const useDepositTriple = (contract: string) => { 9 | const multivault = useMultivaultContract( 10 | contract, 11 | getChainEnvConfig(CURRENT_ENV).chainId, 12 | ) as GetContractReturnType 13 | 14 | return useContractWriteAndWait({ 15 | ...multivault, 16 | // @ts-ignore TODO: Fix type for useContractWriteAndWait 17 | functionName: 'depositTriple', 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /apps/data-populator/app/lib/hooks/useGoBack.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from 'react' 2 | 3 | import { useLocation, useNavigate } from '@remix-run/react' 4 | 5 | function useGoBack({ fallbackRoute }: { fallbackRoute: string }) { 6 | const navigate = useNavigate() 7 | const location = useLocation() 8 | const hasNavigated = useRef(false) 9 | 10 | useEffect(() => { 11 | hasNavigated.current = true 12 | }, [location]) 13 | 14 | return () => { 15 | if (hasNavigated.current && window.history.length > 2) { 16 | navigate(-1) 17 | } else { 18 | window.location.href = fallbackRoute 19 | } 20 | } 21 | } 22 | 23 | export { useGoBack } 24 | -------------------------------------------------------------------------------- /apps/data-populator/app/lib/hooks/useLiveLoader.ts: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react' 2 | 3 | import { useLoaderData, useRevalidator } from '@remix-run/react' 4 | import { useEventSource } from 'remix-utils/sse/react' 5 | 6 | export function useLiveLoader(events: string[]) { 7 | // eslint-disable-next-line react-hooks/rules-of-hooks 8 | const eventSources = events.map((event) => useEventSource(`/event/${event}`)) 9 | 10 | const { revalidate } = useRevalidator() 11 | useEffect(() => { 12 | revalidate() 13 | // eslint-disable-next-line react-hooks/exhaustive-deps 14 | }, eventSources) 15 | 16 | return useLoaderData() 17 | } 18 | -------------------------------------------------------------------------------- /apps/data-populator/app/lib/hooks/useLoaderFetcher.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from 'react' 2 | 3 | import { useFetcher } from '@remix-run/react' 4 | 5 | export function useLoaderFetcher(resourceUrl: string) { 6 | const loaderFetcher = useFetcher() 7 | const loaderFetcherRef = useRef(loaderFetcher.load) 8 | 9 | useEffect(() => { 10 | loaderFetcherRef.current = loaderFetcher.load 11 | }, [loaderFetcher.load]) 12 | 13 | useEffect(() => { 14 | loaderFetcherRef.current(resourceUrl) 15 | }, [resourceUrl]) 16 | 17 | return loaderFetcher 18 | } 19 | -------------------------------------------------------------------------------- /apps/data-populator/app/lib/hooks/useRedeemAtom.tsx: -------------------------------------------------------------------------------- 1 | import { CURRENT_ENV } from 'app/consts' 2 | import { type GetContractReturnType } from 'viem' 3 | 4 | import { getChainEnvConfig } from '../utils/environment' 5 | import { useContractWriteAndWait } from './useContractWriteAndWait' 6 | import { useMultivaultContract } from './useMultivaultContract' 7 | 8 | export const useRedeemAtom = (contract: string) => { 9 | const multivault = useMultivaultContract( 10 | contract, 11 | getChainEnvConfig(CURRENT_ENV).chainId, 12 | ) as GetContractReturnType 13 | 14 | return useContractWriteAndWait({ 15 | ...multivault, 16 | // @ts-ignore TODO: Fix type for useContractWriteAndWait 17 | functionName: 'redeemAtom', 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /apps/data-populator/app/lib/hooks/useRedeemTriple.tsx: -------------------------------------------------------------------------------- 1 | import { CURRENT_ENV } from 'app/consts' 2 | import { type GetContractReturnType } from 'viem' 3 | 4 | import { getChainEnvConfig } from '../utils/environment' 5 | import { useContractWriteAndWait } from './useContractWriteAndWait' 6 | import { useMultivaultContract } from './useMultivaultContract' 7 | 8 | export const useRedeemTriple = (contract: string) => { 9 | const multivault = useMultivaultContract( 10 | contract, 11 | getChainEnvConfig(CURRENT_ENV).chainId, 12 | ) as GetContractReturnType 13 | 14 | return useContractWriteAndWait({ 15 | ...multivault, 16 | // @ts-ignore TODO: Fix type for useContractWriteAndWait 17 | functionName: 'redeemTriple', 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /apps/data-populator/app/lib/styles.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from 'clsx' 2 | import { twMerge } from 'tailwind-merge' 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /apps/data-populator/app/lib/utils/cellHighlight.ts: -------------------------------------------------------------------------------- 1 | export interface CellHighlight { 2 | rowIndex: number 3 | cellIndex: number 4 | } 5 | 6 | export function detectAdjacentDuplicates(data: string[][]): CellHighlight[] { 7 | const highlights: CellHighlight[] = [] 8 | 9 | for (let cellIndex = 0; cellIndex < data[0].length; cellIndex++) { 10 | for (let rowIndex = 1; rowIndex < data.length - 1; rowIndex++) { 11 | if (data[rowIndex][cellIndex] === data[rowIndex + 1][cellIndex]) { 12 | highlights.push({ rowIndex, cellIndex }) 13 | highlights.push({ rowIndex: rowIndex + 1, cellIndex }) 14 | } 15 | } 16 | } 17 | 18 | return highlights 19 | } 20 | -------------------------------------------------------------------------------- /apps/data-populator/app/lib/utils/logger.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Logs only in development mode 3 | */ 4 | /* eslint-disable @typescript-eslint/no-explicit-any */ 5 | const logger = (...args: any[]) => { 6 | if (process.env.NODE_ENV !== 'production') { 7 | return console.log(...args) 8 | } 9 | } 10 | 11 | export default logger 12 | -------------------------------------------------------------------------------- /apps/data-populator/app/lib/utils/mock.ts: -------------------------------------------------------------------------------- 1 | import { toHex } from 'viem' 2 | 3 | // write a function to generate n random atoms and apply toHex to each 4 | export function generateRandomAtoms(n: number): `0x${string}`[] { 5 | return Array.from({ length: n }, () => 6 | toHex(Math.random().toString(36).substring(2, 15)), 7 | ) 8 | } 9 | -------------------------------------------------------------------------------- /apps/data-populator/app/lib/utils/nonce-provider.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | export const NonceContext = React.createContext('') 4 | export const NonceProvider = NonceContext.Provider 5 | export const useNonce = () => React.useContext(NonceContext) 6 | -------------------------------------------------------------------------------- /apps/data-populator/app/lib/utils/privy.ts: -------------------------------------------------------------------------------- 1 | import { User } from '@privy-io/server-auth' 2 | 3 | export function hasSmartWallet(user: User | null): boolean { 4 | if (!user) { 5 | return false 6 | } 7 | 8 | if ('smartWallet' in user && user.smartWallet) { 9 | return true 10 | } 11 | 12 | const externalWallet = user.linkedAccounts.find( 13 | (account) => 14 | account.type === 'wallet' && account.connectorType === 'injected', 15 | ) 16 | 17 | return !externalWallet 18 | } 19 | -------------------------------------------------------------------------------- /apps/data-populator/app/lib/utils/request-info.tsx: -------------------------------------------------------------------------------- 1 | import { useRouteLoaderData } from '@remix-run/react' 2 | 3 | import { type loader as rootLoader } from '../../root' 4 | import { invariant } from './misc' 5 | 6 | /** 7 | * @returns the request info from the root loader 8 | */ 9 | export function useRequestInfo() { 10 | const data = useRouteLoaderData('root') 11 | invariant(data?.requestInfo, 'No requestInfo found in root loader') 12 | 13 | return data.requestInfo 14 | } 15 | -------------------------------------------------------------------------------- /apps/data-populator/app/lib/utils/use-tx-reducer.ts: -------------------------------------------------------------------------------- 1 | import { useReducer, type Reducer } from 'react' 2 | 3 | /** 4 | * This hook takes in a reducer and an initial state and returns the state and dispatch function. It's a generic hook that can be used for any reducer and initial state. 5 | * Without any additional configuration, it uses the default state and reducer in this file, but these can be overridden by passing in a custom reducer and initial state when needed. 6 | */ 7 | 8 | export function useGenericTxState( 9 | reducer: Reducer, 10 | initialState: S, 11 | ) { 12 | const [state, dispatch] = useReducer(reducer, initialState) 13 | return { state, dispatch } 14 | } 15 | -------------------------------------------------------------------------------- /apps/data-populator/app/lib/utils/wagmi.ts: -------------------------------------------------------------------------------- 1 | import { createConfig } from '@privy-io/wagmi' 2 | import { base, baseSepolia } from 'viem/chains' 3 | import { Config } from 'wagmi' 4 | 5 | import { transportsMap } from './chains' 6 | 7 | export const wagmiConfig: Config = createConfig({ 8 | chains: [base, baseSepolia], 9 | transports: { 10 | [base.id]: transportsMap(base.id), 11 | [baseSepolia.id]: transportsMap(baseSepolia.id), 12 | }, 13 | }) 14 | -------------------------------------------------------------------------------- /apps/data-populator/app/polyfills.ts: -------------------------------------------------------------------------------- 1 | import { Buffer } from 'buffer' 2 | 3 | // bare minimum polyfills to get vite working with web3 tooling 4 | 5 | if (typeof window !== 'undefined') { 6 | window.Buffer = window.Buffer ?? Buffer 7 | } 8 | 9 | export {} 10 | -------------------------------------------------------------------------------- /apps/data-populator/app/routes/actions+/logout.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from '@remix-run/node' 2 | import { logout } from '@server/auth' 3 | 4 | export async function loader() { 5 | return redirect('/') 6 | } 7 | 8 | export async function action() { 9 | return logout({ redirectTo: '/login' }) 10 | } 11 | -------------------------------------------------------------------------------- /apps/data-populator/app/routes/api.csv-editor.tsx: -------------------------------------------------------------------------------- 1 | import { action, loader } from '../.server/csv-editor' 2 | 3 | export { loader, action } 4 | -------------------------------------------------------------------------------- /apps/data-populator/app/styles/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | html, 6 | body { 7 | overflow-x: hidden; 8 | touch-action: pan-y; 9 | -webkit-overflow-scrolling: touch; 10 | } 11 | 12 | * { 13 | -webkit-tap-highlight-color: transparent; 14 | } 15 | -------------------------------------------------------------------------------- /apps/data-populator/app/types/claim.ts: -------------------------------------------------------------------------------- 1 | export const ClaimElement = { 2 | Subject: 'subject', 3 | Predicate: 'predicate', 4 | Object: 'object', 5 | } as const 6 | 7 | export type ClaimElementType = (typeof ClaimElement)[keyof typeof ClaimElement] 8 | -------------------------------------------------------------------------------- /apps/data-populator/app/types/claimr.ts: -------------------------------------------------------------------------------- 1 | export type ClaimrPointsType = { 2 | xp: number 3 | ref_xp: number 4 | ugc_xp: number 5 | rank: number 6 | } 7 | -------------------------------------------------------------------------------- /apps/data-populator/app/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './claimr' 2 | export * from './claim' 3 | export * from './identity' 4 | export * from './navigation' 5 | export * from './pagination' 6 | export * from './privy' 7 | export * from './quest' 8 | export * from './quest-temp' 9 | export * from './tags' 10 | export * from './transaction' 11 | export * from './user' 12 | export * from './vault' 13 | -------------------------------------------------------------------------------- /apps/data-populator/app/types/navigation.ts: -------------------------------------------------------------------------------- 1 | export type RedirectOptions = { 2 | redirectTo?: string 3 | } 4 | -------------------------------------------------------------------------------- /apps/data-populator/app/types/pagination.ts: -------------------------------------------------------------------------------- 1 | export interface PaginationType { 2 | currentPage: number 3 | limit: number 4 | totalEntries: number 5 | totalPages: number 6 | } 7 | -------------------------------------------------------------------------------- /apps/data-populator/app/types/quest.ts: -------------------------------------------------------------------------------- 1 | export type QuestSet = { 2 | imgSrc: string 3 | title: string 4 | description: string 5 | summary: string 6 | navigatePath: string 7 | } 8 | 9 | export const MDXContentVariant = { 10 | LORE: 'lore', 11 | DEFAULT: 'default', 12 | } 13 | 14 | export type MDXContentVariantType = 15 | (typeof MDXContentVariant)[keyof typeof MDXContentVariant] 16 | -------------------------------------------------------------------------------- /apps/data-populator/app/types/session.ts: -------------------------------------------------------------------------------- 1 | import { SessionUser } from './user' 2 | 3 | declare global { 4 | type SessionData = { 5 | count: number 6 | user?: SessionUser 7 | } 8 | 9 | type SessionFlashData = { 10 | error: string 11 | } 12 | } 13 | 14 | export {} 15 | -------------------------------------------------------------------------------- /apps/data-populator/app/types/tags.ts: -------------------------------------------------------------------------------- 1 | export type TagType = { 2 | name: string 3 | id: string 4 | } 5 | -------------------------------------------------------------------------------- /apps/data-populator/data/top-100-series/tag_metadata.csv: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "http://schema.org", 3 | "@type": "Thing", 4 | "Name": "TV Series", 5 | "Description": "A TV series that captivates audiences with engaging storylines, compelling characters, and high-quality production. This series has garnered widespread acclaim and continues to be a favorite among viewers.", 6 | "Image": "https://www.the-sun.com/wp-content/uploads/sites/6/2021/04/NINTCHDBPICT000377559478.jpg?w=620", 7 | "url": "" 8 | } -------------------------------------------------------------------------------- /apps/data-populator/postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /apps/data-populator/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/data-populator/public/favicon.ico -------------------------------------------------------------------------------- /apps/data-populator/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | optimizeDeps: { 4 | include: ['mini-svg-data-uri'], 5 | }, 6 | presets: [], 7 | content: ['./src/**/*.{js,jsx,ts,tsx}'], 8 | theme: { 9 | extend: {}, 10 | }, 11 | plugins: [], 12 | } 13 | -------------------------------------------------------------------------------- /apps/data-populator/tests/sample.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest' 2 | 3 | describe('Sample suite', () => { 4 | it('is a sample test', () => { 5 | expect(8).toEqual(8) 6 | }) 7 | }) 8 | -------------------------------------------------------------------------------- /apps/data-populator/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /apps/data-populator/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "types": ["jest", "node"] 6 | }, 7 | "include": [ 8 | "jest.config.ts", 9 | "src/**/*.test.ts", 10 | "src/**/*.spec.ts", 11 | "src/**/*.test.tsx", 12 | "src/**/*.spec.tsx", 13 | "src/**/*.test.js", 14 | "src/**/*.spec.js", 15 | "src/**/*.test.jsx", 16 | "src/**/*.spec.jsx", 17 | "src/**/*.d.ts" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /apps/data-populator/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { configDefaults, defineConfig, type UserConfig } from 'vitest/config' 2 | 3 | const config = defineConfig({ 4 | test: { 5 | ...configDefaults, 6 | globals: true, 7 | environment: 'jsdom', 8 | setupFiles: './vitest.setup.ts', 9 | }, 10 | }) as UserConfig 11 | 12 | export default config 13 | -------------------------------------------------------------------------------- /apps/data-populator/vitest.setup.ts: -------------------------------------------------------------------------------- 1 | import * as matchers from '@testing-library/jest-dom/matchers' 2 | import { cleanup } from '@testing-library/react' 3 | import { afterEach, expect } from 'vitest' 4 | 5 | expect.extend(matchers) 6 | 7 | afterEach(() => { 8 | cleanup() 9 | }) 10 | -------------------------------------------------------------------------------- /apps/portal/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.base.cjs'], 3 | env: { 4 | node: true, 5 | jest: true, 6 | }, 7 | overrides: [ 8 | { 9 | files: ['*.ts', '*.tsx', '*.js', '*.jsx'], 10 | rules: {}, 11 | }, 12 | { 13 | files: ['*.ts', '*.tsx'], 14 | rules: { 15 | '@typescript-eslint/no-unused-vars': [ 16 | 'error', 17 | { 18 | varsIgnorePattern: '^React$', 19 | }, 20 | ], 21 | }, 22 | }, 23 | { 24 | files: ['*.js', '*.jsx'], 25 | rules: {}, 26 | }, 27 | { 28 | files: ['*.json'], 29 | parser: 'jsonc-eslint-parser', 30 | rules: {}, 31 | }, 32 | ], 33 | } 34 | -------------------------------------------------------------------------------- /apps/portal/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | /.cache 4 | /build 5 | .env 6 | /.content-collections 7 | .DS_Store 8 | # Sentry Config File 9 | .sentryclirc 10 | 11 | # Sentry Config File 12 | .env.sentry-build-plugin 13 | -------------------------------------------------------------------------------- /apps/portal/app/.client/privy-revalidate.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react' 2 | 3 | import { usePrivy } from '@privy-io/react-auth' 4 | import { useRevalidator } from '@remix-run/react' 5 | 6 | export default function PrivyRevalidate() { 7 | const { ready, authenticated, user: privyUser } = usePrivy() 8 | const { revalidate } = useRevalidator() 9 | 10 | useEffect(() => { 11 | // if privyUser has changed, revalidate the page 12 | if (ready && authenticated && privyUser) { 13 | revalidate() 14 | } 15 | // omits authenticate from the exhaustive deps 16 | // eslint-disable-next-line react-hooks/exhaustive-deps 17 | }, [ready, privyUser, revalidate]) 18 | 19 | return
20 | } 21 | -------------------------------------------------------------------------------- /apps/portal/app/.server/api.ts: -------------------------------------------------------------------------------- 1 | import { ApiError } from '@0xintuition/api' 2 | 3 | import logger from '@lib/utils/logger' 4 | 5 | import { setupAPI } from './auth' 6 | 7 | export const fetchWrapper = async ( 8 | request: Request, 9 | { 10 | method, 11 | args, 12 | }: { 13 | method: (arg: A) => Promise 14 | args: A 15 | }, 16 | ): Promise => { 17 | try { 18 | await setupAPI(request) 19 | return await method(args) 20 | } catch (error: unknown) { 21 | if (error instanceof ApiError) { 22 | logger(`${error.name} - ${error.status}: ${error.message} ${error.url}`) 23 | } 24 | throw error 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /apps/portal/app/.server/emitter.ts: -------------------------------------------------------------------------------- 1 | import { EventEmitter } from 'events' 2 | 3 | import { remember } from '@epic-web/remember' 4 | 5 | export const emitter = remember('emitter', () => { 6 | const eventEmitter = new EventEmitter() 7 | eventEmitter.setMaxListeners(20) 8 | return eventEmitter 9 | }) 10 | -------------------------------------------------------------------------------- /apps/portal/app/.server/form.ts: -------------------------------------------------------------------------------- 1 | import { json, redirect } from '@remix-run/node' 2 | import { createFormAction } from 'remix-forms' 3 | 4 | const formAction = createFormAction({ redirect, json }) 5 | 6 | export { formAction } 7 | -------------------------------------------------------------------------------- /apps/portal/app/.server/ofac.ts: -------------------------------------------------------------------------------- 1 | import { chainalysisOracleAbi } from '@lib/abis/chainalysisOracle' 2 | import { mainnetClient } from '@server/viem' 3 | import { Address } from 'viem' 4 | 5 | export async function isSanctioned(wallet: Address) { 6 | const walletIsSanctioned = (await mainnetClient.readContract({ 7 | address: '0x40C57923924B5c5c5455c48D93317139ADDaC8fb', 8 | abi: chainalysisOracleAbi, 9 | functionName: 'isSanctioned', 10 | args: [wallet], 11 | })) as Promise 12 | return walletIsSanctioned 13 | } 14 | -------------------------------------------------------------------------------- /apps/portal/app/.server/onboarding.ts: -------------------------------------------------------------------------------- 1 | import { createCookie } from '@remix-run/node' 2 | 3 | export const onboardingModalCookie = createCookie('onboarding-modal', { 4 | maxAge: 31_536_000, 5 | }) 6 | -------------------------------------------------------------------------------- /apps/portal/app/.server/relics.ts: -------------------------------------------------------------------------------- 1 | import { relicsAbi } from '@lib/abis/relics' 2 | import { mainnetClient } from '@server/viem' 3 | import { RELIC_CONTRACT_ADDRESS } from 'app/consts' 4 | import { type Address } from 'viem' 5 | 6 | export async function getRelicCount(wallet: Address) { 7 | const relicCount = (await mainnetClient.readContract({ 8 | address: RELIC_CONTRACT_ADDRESS, 9 | abi: relicsAbi, 10 | functionName: 'balanceOf', 11 | args: [wallet], 12 | })) as number 13 | 14 | return relicCount 15 | } 16 | -------------------------------------------------------------------------------- /apps/portal/app/.server/stream.ts: -------------------------------------------------------------------------------- 1 | import { eventStream } from 'remix-utils/sse/server' 2 | 3 | import { emitter } from './emitter' 4 | 5 | export function createEventStream(request: Request, eventName: string) { 6 | return eventStream(request.signal, (send) => { 7 | const handle = () => { 8 | send({ 9 | data: String(Date.now()), 10 | }) 11 | } 12 | 13 | emitter.addListener(eventName, handle) 14 | 15 | return () => { 16 | emitter.removeListener(eventName, handle) 17 | } 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /apps/portal/app/.server/theme.ts: -------------------------------------------------------------------------------- 1 | import { Theme, themesList } from '@0xintuition/1ui' 2 | 3 | import * as cookie from 'cookie' 4 | 5 | const cookieName = 'theme' 6 | 7 | export function getTheme(request: Request): Theme | undefined { 8 | const cookieHeader = request.headers.get('Cookie') 9 | const parsed = cookieHeader && cookie.parse(cookieHeader)[cookieName] 10 | 11 | if (themesList.includes(parsed as Theme)) { 12 | return parsed as Theme 13 | } 14 | 15 | return undefined 16 | } 17 | 18 | // Cookie value set by the server 19 | export function setTheme(theme?: Theme) { 20 | if (theme) { 21 | return cookie.serialize(cookieName, theme, { path: '/' }) 22 | } 23 | return cookie.serialize(cookieName, '', { path: '/', maxAge: 0 }) 24 | } 25 | -------------------------------------------------------------------------------- /apps/portal/app/assets/derp-face-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/portal/app/assets/derp-face-1.png -------------------------------------------------------------------------------- /apps/portal/app/assets/derp-face-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/portal/app/assets/derp-face-10.png -------------------------------------------------------------------------------- /apps/portal/app/assets/derp-face-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/portal/app/assets/derp-face-11.png -------------------------------------------------------------------------------- /apps/portal/app/assets/derp-face-12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/portal/app/assets/derp-face-12.jpg -------------------------------------------------------------------------------- /apps/portal/app/assets/derp-face-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/portal/app/assets/derp-face-2.png -------------------------------------------------------------------------------- /apps/portal/app/assets/derp-face-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/portal/app/assets/derp-face-3.png -------------------------------------------------------------------------------- /apps/portal/app/assets/derp-face-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/portal/app/assets/derp-face-4.png -------------------------------------------------------------------------------- /apps/portal/app/assets/derp-face-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/portal/app/assets/derp-face-5.png -------------------------------------------------------------------------------- /apps/portal/app/assets/derp-face-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/portal/app/assets/derp-face-6.png -------------------------------------------------------------------------------- /apps/portal/app/assets/derp-face-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/portal/app/assets/derp-face-7.png -------------------------------------------------------------------------------- /apps/portal/app/assets/derp-face-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/portal/app/assets/derp-face-8.png -------------------------------------------------------------------------------- /apps/portal/app/assets/derp-face-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/portal/app/assets/derp-face-9.png -------------------------------------------------------------------------------- /apps/portal/app/assets/og-background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/portal/app/assets/og-background.png -------------------------------------------------------------------------------- /apps/portal/app/components/container.tsx: -------------------------------------------------------------------------------- 1 | import type { ReactNode } from 'react' 2 | 3 | import { cn } from '@lib/utils/misc' 4 | 5 | export default function Container({ 6 | children, 7 | className, 8 | }: { 9 | children: ReactNode 10 | className?: string 11 | }) { 12 | return ( 13 |
14 | {children} 15 |
16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /apps/portal/app/components/error-list.tsx: -------------------------------------------------------------------------------- 1 | export default function ErrorList({ 2 | id, 3 | errors, 4 | }: { 5 | id?: string 6 | errors?: Array | null 7 | }) { 8 | return errors?.length ? ( 9 |
    10 | {errors.map((error, i) => ( 11 |
  • 12 | {error} 13 |
  • 14 | ))} 15 |
16 | ) : null 17 | } 18 | -------------------------------------------------------------------------------- /apps/portal/app/components/explore/ExploreSearchForm/ExploreAddTags/ExploreAddTags.utils.ts: -------------------------------------------------------------------------------- 1 | import { IdentityPresenter } from '@0xintuition/api' 2 | 3 | import { TagType } from 'app/types/tags' 4 | 5 | export const isClickOutsideOfTagsInteractionZone = ( 6 | tagsContainerRef: React.RefObject, 7 | popoverContentRef: React.RefObject, 8 | target: EventTarget | null, 9 | ) => 10 | !tagsContainerRef.current?.contains(target as Node) && 11 | !popoverContentRef.current?.contains(target as Node) 12 | 13 | export const isTagAlreadySelected = ( 14 | selection: IdentityPresenter, 15 | selectedTags: TagType[], 16 | ) => selectedTags.filter((tag) => tag.id === selection.id).length > 0 17 | -------------------------------------------------------------------------------- /apps/portal/app/components/header.tsx: -------------------------------------------------------------------------------- 1 | import PrivyLogoutButton from '@client/privy-logout-button' 2 | import { HeaderLogo } from '@components/header-logo' 3 | import { ClientOnly } from 'remix-utils/client-only' 4 | 5 | export function Header() { 6 | return ( 7 |
8 | 9 | {() => } 10 |
11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /apps/portal/app/components/lists/list-tab-identity-display.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { Avatar } from '@0xintuition/1ui' 4 | 5 | export function ListTabIdentityDisplay({ 6 | imgSrc, 7 | children, 8 | }: { 9 | imgSrc?: string | null 10 | children: React.ReactNode 11 | }) { 12 | return ( 13 |
14 | 19 | {children} 20 |
21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /apps/portal/app/components/lists/list-utils.ts: -------------------------------------------------------------------------------- 1 | import { IdentityPresenter } from '@0xintuition/api' 2 | 3 | import { getSpecialPredicate } from '@lib/utils/app' 4 | import { CURRENT_ENV } from 'app/consts' 5 | 6 | export const createIdentityArrays = ( 7 | identities: IdentityPresenter[], 8 | objectVaultId: string, 9 | ) => { 10 | const subjectIdentityVaultIds = identities.map( 11 | (identity) => identity.vault_id, 12 | ) 13 | const predicateHasTagVaultIds = identities.map( 14 | () => getSpecialPredicate(CURRENT_ENV).tagPredicate.vaultId, 15 | ) 16 | const objectIdentityVaultIds = identities.map(() => objectVaultId) 17 | 18 | return { 19 | subjectIdentityVaultIds, 20 | predicateHasTagVaultIds, 21 | objectIdentityVaultIds, 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /apps/portal/app/components/nested-tabs.tsx: -------------------------------------------------------------------------------- 1 | import { Outlet } from '@remix-run/react' 2 | 3 | import { OptionType, SegmentedNav } from './segmented-nav' 4 | 5 | interface NestedTabsProps { 6 | outlet: typeof Outlet 7 | options: OptionType[] 8 | } 9 | 10 | export function NestedTabs({ 11 | outlet: OutletComponent, 12 | options, 13 | }: NestedTabsProps) { 14 | return ( 15 |
16 | 17 | 18 |
19 | ) 20 | } 21 | -------------------------------------------------------------------------------- /apps/portal/app/components/remix-link.tsx: -------------------------------------------------------------------------------- 1 | import { Link } from '@remix-run/react' 2 | 3 | const RemixLink = ({ 4 | href, 5 | onClick, 6 | children, 7 | }: { 8 | href: string 9 | onClick: (e: React.MouseEvent) => void 10 | children: React.ReactNode 11 | }) => ( 12 | 13 | {children} 14 | 15 | ) 16 | 17 | export default RemixLink 18 | -------------------------------------------------------------------------------- /apps/portal/app/components/revalidate-button.tsx: -------------------------------------------------------------------------------- 1 | import { Button, ButtonSize, ButtonVariant } from '@0xintuition/1ui' 2 | 3 | import { useRevalidator } from '@remix-run/react' 4 | 5 | interface RevalidateButtonProps { 6 | className?: string 7 | } 8 | 9 | export function RevalidateButton({ className }: RevalidateButtonProps) { 10 | const revalidator = useRevalidator() 11 | 12 | return ( 13 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /apps/portal/app/components/search.tsx: -------------------------------------------------------------------------------- 1 | import { Input } from '@0xintuition/1ui' 2 | 3 | interface SearchProps { 4 | handleSearchChange: (event: React.ChangeEvent) => void 5 | } 6 | 7 | export function Search({ handleSearchChange }: SearchProps) { 8 | return ( 9 | 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /apps/portal/app/components/sort.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { SortDirection } from '@0xintuition/api' 4 | 5 | import { SortOption, SortSelect } from '@components/sort-select' 6 | 7 | interface SortProps { 8 | options: SortOption[] 9 | handleSortChange: (newSortBy: T, newDirection: SortDirection) => void 10 | } 11 | 12 | export function Sort({ options, handleSortChange }: SortProps) { 13 | return 14 | } 15 | -------------------------------------------------------------------------------- /apps/portal/app/components/tags/tag-utils.ts: -------------------------------------------------------------------------------- 1 | import { IdentityPresenter } from '@0xintuition/api' 2 | 3 | import { getSpecialPredicate } from '@lib/utils/app' 4 | import { CURRENT_ENV } from 'app/consts' 5 | 6 | export const createTagArrays = ( 7 | tags: IdentityPresenter[], 8 | subjectVaultId: string, 9 | ) => { 10 | const subjectIdentityVaultIds = tags.map(() => subjectVaultId) 11 | const predicateHasTagVaultIds = tags.map( 12 | () => getSpecialPredicate(CURRENT_ENV).tagPredicate.vaultId, 13 | ) 14 | const objectTagVaultIds = tags.map((tag) => tag.vault_id) 15 | 16 | return { subjectIdentityVaultIds, predicateHasTagVaultIds, objectTagVaultIds } 17 | } 18 | -------------------------------------------------------------------------------- /apps/portal/app/components/usd-tooltip.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | Tooltip, 3 | TooltipContent, 4 | TooltipProvider, 5 | TooltipTrigger, 6 | } from '@0xintuition/1ui' 7 | 8 | export const UsdTooltip = ({ 9 | ethValue, 10 | usdValue, 11 | }: { 12 | ethValue: string 13 | usdValue: string 14 | }) => { 15 | return ( 16 | 17 | 18 | {ethValue} ETH 19 | ${usdValue} USD 20 | 21 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /apps/portal/app/consts/emails.ts: -------------------------------------------------------------------------------- 1 | export const SUPPORT_EMAIL_ADDRESS = 'support@intuition.systems' 2 | -------------------------------------------------------------------------------- /apps/portal/app/consts/errors.ts: -------------------------------------------------------------------------------- 1 | export const NO_WALLET_ERROR = 'No wallet found in session' 2 | export const NO_PARAM_ID_ERROR = 'Invalid or missing param ID' 3 | export const NO_USER_IDENTITY_ERROR = 'No user identity found' 4 | export const NO_IDENTITY_ERROR = 'No identity found' 5 | export const INVALID_CREATOR_ID_ERROR = 'Invalid or missing creator ID' 6 | export const GENERIC_ERROR_MSG = 'An error occurred' 7 | export const NO_CLAIM_ERROR = 'No claim found' 8 | export const NO_USER_TOTALS_ERROR = 'No user totals found' 9 | export const NO_CONNECTIONS_DATA_ERROR = 'No connections data found' 10 | export const NO_FOLLOW_CLAIM_ERROR = 'No follow claim found' 11 | -------------------------------------------------------------------------------- /apps/portal/app/consts/feature-flags.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/portal/app/consts/feature-flags.ts -------------------------------------------------------------------------------- /apps/portal/app/consts/index.ts: -------------------------------------------------------------------------------- 1 | export * from './assets' 2 | export * from './emails' 3 | export * from './errors' 4 | export * from './general' 5 | export * from './paths' 6 | export * from './quest' 7 | -------------------------------------------------------------------------------- /apps/portal/app/layouts/full-page-layout.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | interface FullPageLayoutProps { 4 | children: React.ReactNode 5 | } 6 | 7 | const FullPageLayout: React.FC = ({ children }) => { 8 | return ( 9 |
10 | {children} 11 |
12 | ) 13 | } 14 | 15 | export default FullPageLayout 16 | -------------------------------------------------------------------------------- /apps/portal/app/lib/graphql/client.ts: -------------------------------------------------------------------------------- 1 | import { GraphQLClient } from 'graphql-request' 2 | 3 | if (process.env.POINTS_GRAPHQL_ENDPOINT === undefined) { 4 | throw new Error('Points API endpoint not defined') 5 | } 6 | 7 | export const pointsClient = new GraphQLClient( 8 | process.env.POINTS_GRAPHQL_ENDPOINT, 9 | ) 10 | -------------------------------------------------------------------------------- /apps/portal/app/lib/hooks/useBatchCreateTriple.tsx: -------------------------------------------------------------------------------- 1 | import { CURRENT_ENV } from 'app/consts' 2 | import type { GetContractReturnType } from 'viem' 3 | 4 | import { getChainEnvConfig } from '../utils/environment' 5 | import { useContractWriteAndWait } from './useContractWriteAndWait' 6 | import { useMultivaultContract } from './useMultivaultContract' 7 | 8 | export const useBatchCreateTriple = () => { 9 | const multivault = useMultivaultContract( 10 | getChainEnvConfig(CURRENT_ENV).chainId.toString(), 11 | ) as GetContractReturnType 12 | 13 | return useContractWriteAndWait({ 14 | ...multivault, 15 | // @ts-ignore TODO: Fix type for useContractWriteAndWait 16 | functionName: 'batchCreateTriple', 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /apps/portal/app/lib/hooks/useCopy.tsx: -------------------------------------------------------------------------------- 1 | import { useCallback, useState } from 'react' 2 | 3 | export const useCopy = (duration = 2000) => { 4 | const [copied, setCopied] = useState(false) 5 | 6 | const copy = useCallback( 7 | (text: string) => { 8 | navigator.clipboard.writeText(text) 9 | setCopied(true) 10 | setTimeout(() => setCopied(false), duration) 11 | }, 12 | [duration], 13 | ) 14 | 15 | return { copied, copy } 16 | } 17 | -------------------------------------------------------------------------------- /apps/portal/app/lib/hooks/useCreateAtom.tsx: -------------------------------------------------------------------------------- 1 | import { CURRENT_ENV } from 'app/consts' 2 | import type { GetContractReturnType } from 'viem' 3 | 4 | import { getChainEnvConfig } from '../utils/environment' 5 | import { useContractWriteAndWait } from './useContractWriteAndWait' 6 | import { useMultivaultContract } from './useMultivaultContract' 7 | 8 | export const useCreateAtom = () => { 9 | const multivault = useMultivaultContract( 10 | getChainEnvConfig(CURRENT_ENV).chainId.toString(), 11 | ) as GetContractReturnType 12 | 13 | return useContractWriteAndWait({ 14 | ...multivault, 15 | // @ts-ignore TODO: Fix type for useContractWriteAndWait 16 | functionName: 'createAtom', 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /apps/portal/app/lib/hooks/useCreateTriple.tsx: -------------------------------------------------------------------------------- 1 | import { CURRENT_ENV } from 'app/consts' 2 | import type { GetContractReturnType } from 'viem' 3 | 4 | import { getChainEnvConfig } from '../utils/environment' 5 | import { useContractWriteAndWait } from './useContractWriteAndWait' 6 | import { useMultivaultContract } from './useMultivaultContract' 7 | 8 | export const useCreateTriple = () => { 9 | const multivault = useMultivaultContract( 10 | getChainEnvConfig(CURRENT_ENV).chainId.toString(), 11 | ) as GetContractReturnType 12 | 13 | return useContractWriteAndWait({ 14 | ...multivault, 15 | // @ts-ignore TODO: Fix type for useContractWriteAndWait 16 | functionName: 'createTriple', 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /apps/portal/app/lib/hooks/useDepositAtom.tsx: -------------------------------------------------------------------------------- 1 | import { CURRENT_ENV } from 'app/consts' 2 | import type { GetContractReturnType } from 'viem' 3 | 4 | import { getChainEnvConfig } from '../utils/environment' 5 | import { useContractWriteAndWait } from './useContractWriteAndWait' 6 | import { useMultivaultContract } from './useMultivaultContract' 7 | 8 | export const useDepositAtom = (contract: string) => { 9 | const multivault = useMultivaultContract( 10 | contract, 11 | getChainEnvConfig(CURRENT_ENV).chainId, 12 | ) as GetContractReturnType 13 | 14 | return useContractWriteAndWait({ 15 | ...multivault, 16 | // @ts-ignore TODO: Fix type for useContractWriteAndWait 17 | functionName: 'depositAtom', 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /apps/portal/app/lib/hooks/useDepositTriple.tsx: -------------------------------------------------------------------------------- 1 | import { CURRENT_ENV } from 'app/consts' 2 | import type { GetContractReturnType } from 'viem' 3 | 4 | import { getChainEnvConfig } from '../utils/environment' 5 | import { useContractWriteAndWait } from './useContractWriteAndWait' 6 | import { useMultivaultContract } from './useMultivaultContract' 7 | 8 | export const useDepositTriple = (contract: string) => { 9 | const multivault = useMultivaultContract( 10 | contract, 11 | getChainEnvConfig(CURRENT_ENV).chainId, 12 | ) as GetContractReturnType 13 | 14 | return useContractWriteAndWait({ 15 | ...multivault, 16 | // @ts-ignore TODO: Fix type for useContractWriteAndWait 17 | functionName: 'depositTriple', 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /apps/portal/app/lib/hooks/useGoBack.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from 'react' 2 | 3 | import { useLocation, useNavigate } from '@remix-run/react' 4 | 5 | function useGoBack({ fallbackRoute }: { fallbackRoute: string }) { 6 | const navigate = useNavigate() 7 | const location = useLocation() 8 | const hasNavigated = useRef(false) 9 | 10 | useEffect(() => { 11 | hasNavigated.current = true 12 | }, [location]) 13 | 14 | return () => { 15 | if (hasNavigated.current && window.history.length > 2) { 16 | navigate(-1) 17 | } else { 18 | window.location.href = fallbackRoute 19 | } 20 | } 21 | } 22 | 23 | export { useGoBack } 24 | -------------------------------------------------------------------------------- /apps/portal/app/lib/hooks/useHandleCloseAttempt.tsx: -------------------------------------------------------------------------------- 1 | import { useCallback, useState } from 'react' 2 | 3 | export default function useHandleCloseAttempt(onClose: () => void) { 4 | const [showAlertDialog, setShowAlertDialog] = useState(false) 5 | const [isTransactionComplete, setIsTransactionComplete] = useState(false) 6 | const handleCloseAttempt = useCallback(() => { 7 | if (isTransactionComplete) { 8 | onClose() 9 | } else { 10 | setShowAlertDialog(true) 11 | } 12 | }, [isTransactionComplete, onClose]) 13 | 14 | return { 15 | showAlertDialog, 16 | setShowAlertDialog, 17 | isTransactionComplete, 18 | setIsTransactionComplete, 19 | handleCloseAttempt, 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /apps/portal/app/lib/hooks/useImageUploadFetcher.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react' 2 | 3 | import logger from '@lib/utils/logger' 4 | import { useFetcher } from '@remix-run/react' 5 | import { type UploadApiResponse } from 'cloudinary' 6 | 7 | export function useImageUploadFetcher() { 8 | const imageUploadFetcher = useFetcher() 9 | 10 | useEffect(() => { 11 | if (imageUploadFetcher.state === 'submitting') { 12 | logger('Uploading...') 13 | } else if (imageUploadFetcher.state === 'idle' && imageUploadFetcher.data) { 14 | logger('Upload complete:', imageUploadFetcher.data) 15 | } 16 | }, [imageUploadFetcher.state, imageUploadFetcher.data]) 17 | 18 | return imageUploadFetcher 19 | } 20 | -------------------------------------------------------------------------------- /apps/portal/app/lib/hooks/useInviteCodeFetcher.tsx: -------------------------------------------------------------------------------- 1 | import { SubmissionResult } from '@conform-to/react' 2 | import logger from '@lib/utils/logger' 3 | import { useFetcher } from '@remix-run/react' 4 | 5 | export interface InviteCodeFetcher { 6 | status: 'success' | 'error' 7 | submission: SubmissionResult | null 8 | error?: string 9 | } 10 | 11 | export function useInviteCodeFetcher() { 12 | const inviteCodeFetcher = useFetcher() 13 | const lastInviteCodeSubmission = inviteCodeFetcher.data?.submission 14 | logger('offchainfetcher data in hook', inviteCodeFetcher.data) 15 | 16 | return { 17 | inviteCodeFetcher, 18 | lastInviteCodeSubmission, 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /apps/portal/app/lib/hooks/useLiveLoader.ts: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react' 2 | 3 | import { useLoaderData, useRevalidator } from '@remix-run/react' 4 | import { useEventSource } from 'remix-utils/sse/react' 5 | 6 | export function useLiveLoader(events: string[]) { 7 | // eslint-disable-next-line react-hooks/rules-of-hooks 8 | const eventSources = events.map((event) => useEventSource(`/event/${event}`)) 9 | 10 | const { revalidate } = useRevalidator() 11 | useEffect(() => { 12 | revalidate() 13 | // eslint-disable-next-line react-hooks/exhaustive-deps 14 | }, eventSources) 15 | 16 | return useLoaderData() 17 | } 18 | -------------------------------------------------------------------------------- /apps/portal/app/lib/hooks/useLoaderFetcher.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from 'react' 2 | 3 | import { useFetcher } from '@remix-run/react' 4 | 5 | export function useLoaderFetcher(resourceUrl: string) { 6 | const loaderFetcher = useFetcher() 7 | const loaderFetcherRef = useRef(loaderFetcher.load) 8 | 9 | useEffect(() => { 10 | loaderFetcherRef.current = loaderFetcher.load 11 | }, [loaderFetcher.load]) 12 | 13 | useEffect(() => { 14 | loaderFetcherRef.current(resourceUrl) 15 | }, [resourceUrl]) 16 | 17 | return loaderFetcher 18 | } 19 | -------------------------------------------------------------------------------- /apps/portal/app/lib/hooks/useRedeemAtom.tsx: -------------------------------------------------------------------------------- 1 | import { CURRENT_ENV } from 'app/consts' 2 | import { type GetContractReturnType } from 'viem' 3 | 4 | import { getChainEnvConfig } from '../utils/environment' 5 | import { useContractWriteAndWait } from './useContractWriteAndWait' 6 | import { useMultivaultContract } from './useMultivaultContract' 7 | 8 | export const useRedeemAtom = (contract: string) => { 9 | const multivault = useMultivaultContract( 10 | contract, 11 | getChainEnvConfig(CURRENT_ENV).chainId, 12 | ) as GetContractReturnType 13 | 14 | return useContractWriteAndWait({ 15 | ...multivault, 16 | // @ts-ignore TODO: Fix type for useContractWriteAndWait 17 | functionName: 'redeemAtom', 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /apps/portal/app/lib/hooks/useRedeemTriple.tsx: -------------------------------------------------------------------------------- 1 | import { CURRENT_ENV } from 'app/consts' 2 | import { type GetContractReturnType } from 'viem' 3 | 4 | import { getChainEnvConfig } from '../utils/environment' 5 | import { useContractWriteAndWait } from './useContractWriteAndWait' 6 | import { useMultivaultContract } from './useMultivaultContract' 7 | 8 | export const useRedeemTriple = (contract: string) => { 9 | const multivault = useMultivaultContract( 10 | contract, 11 | getChainEnvConfig(CURRENT_ENV).chainId, 12 | ) as GetContractReturnType 13 | 14 | return useContractWriteAndWait({ 15 | ...multivault, 16 | // @ts-ignore TODO: Fix type for useContractWriteAndWait 17 | functionName: 'redeemTriple', 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /apps/portal/app/lib/schemas/create-claim-schema.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | export function createClaimSchema() { 4 | return z.object({ 5 | subject_id: z.string({ 6 | required_error: 'Please select a subject.', 7 | }), 8 | predicate_id: z.string({ 9 | required_error: 'Please select a predicate.', 10 | }), 11 | object_id: z.string({ 12 | required_error: 'Please select an object.', 13 | }), 14 | creator: z.string().optional(), 15 | }) 16 | } 17 | -------------------------------------------------------------------------------- /apps/portal/app/lib/schemas/reval-schema.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod' 2 | 3 | export function revalSchema() { 4 | return z.object({ 5 | eventName: z.string(), 6 | }) 7 | } 8 | -------------------------------------------------------------------------------- /apps/portal/app/lib/services/pricefeeds.ts: -------------------------------------------------------------------------------- 1 | import { chainlinkEthUsdOracleAbi } from '@lib/abis/chainlinkEthUsdOracle' 2 | import { mainnetClient } from '@server/viem' 3 | import { formatUnits } from 'viem' 4 | 5 | export async function getEthPrice() { 6 | const ethPrice = (await mainnetClient.readContract({ 7 | address: '0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419', 8 | abi: chainlinkEthUsdOracleAbi, 9 | functionName: 'latestAnswer', 10 | })) as Promise 11 | return formatUnits(BigInt(await ethPrice), 8) 12 | } 13 | -------------------------------------------------------------------------------- /apps/portal/app/lib/utils/logger.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Logs only in development mode 3 | */ 4 | /* eslint-disable @typescript-eslint/no-explicit-any */ 5 | const logger = (...args: any[]) => { 6 | if (process.env.NODE_ENV !== 'production') { 7 | return console.log(...args) 8 | } 9 | } 10 | 11 | export default logger 12 | -------------------------------------------------------------------------------- /apps/portal/app/lib/utils/maintenance.ts: -------------------------------------------------------------------------------- 1 | import { PATHS } from '@consts/paths' 2 | import { redirect } from '@remix-run/node' 3 | 4 | export function getMaintenanceMode() { 5 | const maintenanceMode = process.env.FF_FULL_LOCKDOWN_ENABLED === 'true' 6 | if (maintenanceMode) { 7 | throw redirect(PATHS.MAINTENANCE) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /apps/portal/app/lib/utils/nonce-provider.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | export const NonceContext = React.createContext('') 4 | export const NonceProvider = NonceContext.Provider 5 | export const useNonce = () => React.useContext(NonceContext) 6 | -------------------------------------------------------------------------------- /apps/portal/app/lib/utils/request-info.tsx: -------------------------------------------------------------------------------- 1 | import { useRouteLoaderData } from '@remix-run/react' 2 | 3 | import { type loader as rootLoader } from '../../root' 4 | import { invariant } from './misc' 5 | 6 | /** 7 | * @returns the request info from the root loader 8 | */ 9 | export function useRequestInfo() { 10 | const data = useRouteLoaderData('root') 11 | invariant(data?.requestInfo, 'No requestInfo found in root loader') 12 | 13 | return data.requestInfo 14 | } 15 | -------------------------------------------------------------------------------- /apps/portal/app/lib/utils/use-tx-reducer.ts: -------------------------------------------------------------------------------- 1 | import { useReducer, type Reducer } from 'react' 2 | 3 | /** 4 | * This hook takes in a reducer and an initial state and returns the state and dispatch function. It's a generic hook that can be used for any reducer and initial state. 5 | * Without any additional configuration, it uses the default state and reducer in this file, but these can be overridden by passing in a custom reducer and initial state when needed. 6 | */ 7 | 8 | export function useGenericTxState( 9 | reducer: Reducer, 10 | initialState: S, 11 | ) { 12 | const [state, dispatch] = useReducer(reducer, initialState) 13 | return { state, dispatch } 14 | } 15 | -------------------------------------------------------------------------------- /apps/portal/app/polyfills.ts: -------------------------------------------------------------------------------- 1 | import { Buffer } from 'buffer' 2 | 3 | // bare minimum polyfills to get vite working with web3 tooling 4 | 5 | if (typeof window !== 'undefined') { 6 | window.Buffer = window.Buffer ?? Buffer 7 | } 8 | 9 | export {} 10 | -------------------------------------------------------------------------------- /apps/portal/app/routes/actions+/clear-onboarding-cookie.tsx: -------------------------------------------------------------------------------- 1 | import { ActionFunctionArgs, json } from '@remix-run/node' 2 | import { onboardingModalCookie } from '@server/onboarding' 3 | 4 | export async function action({ request }: ActionFunctionArgs) { 5 | const formData = await request.formData() 6 | if (formData.get('action') === 'clearOnboardingCookie') { 7 | return json( 8 | { success: true }, 9 | { 10 | headers: { 11 | 'Set-Cookie': await onboardingModalCookie.serialize( 12 | {}, 13 | { 14 | expires: new Date(0), 15 | maxAge: 0, 16 | }, 17 | ), 18 | }, 19 | }, 20 | ) 21 | } 22 | return json({ success: false }) 23 | } 24 | -------------------------------------------------------------------------------- /apps/portal/app/routes/actions+/logout.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from '@remix-run/node' 2 | import { logout } from '@server/auth' 3 | 4 | export async function loader() { 5 | return redirect('/') 6 | } 7 | 8 | export async function action() { 9 | return logout({ redirectTo: '/login' }) 10 | } 11 | -------------------------------------------------------------------------------- /apps/portal/app/routes/app+/activity+/_layout.tsx: -------------------------------------------------------------------------------- 1 | import { NestedTabs } from '@components/nested-tabs' 2 | import { Outlet } from '@remix-run/react' 3 | import { activityRouteOptions } from 'app/consts' 4 | import FullPageLayout from 'app/layouts/full-page-layout' 5 | 6 | export default function ActivityLayout() { 7 | return ( 8 | 9 | 10 | 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /apps/portal/app/routes/app+/activity+/index.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from '@remix-run/node' 2 | import { PATHS } from 'app/consts' 3 | 4 | export async function loader() { 5 | return redirect(PATHS.GLOBAL_ACTIVITY) 6 | } 7 | -------------------------------------------------------------------------------- /apps/portal/app/routes/app+/explore+/_index+/_layout.tsx: -------------------------------------------------------------------------------- 1 | import { NestedTabs } from '@components/nested-tabs' 2 | import { Outlet } from '@remix-run/react' 3 | import { exploreRouteOptions } from 'app/consts' 4 | import FullPageLayout from 'app/layouts/full-page-layout' 5 | 6 | export default function ExploreLayout() { 7 | return ( 8 | 9 | 10 | 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /apps/portal/app/routes/app+/explore+/_index+/index.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from '@remix-run/node' 2 | import { PATHS } from 'app/consts' 3 | 4 | export async function loader() { 5 | return redirect(PATHS.EXPLORE_IDENTITIES) 6 | } 7 | -------------------------------------------------------------------------------- /apps/portal/app/routes/app+/index.tsx: -------------------------------------------------------------------------------- 1 | import { PATHS } from '@consts/paths' 2 | import { redirect } from '@remix-run/node' 3 | 4 | export async function loader() { 5 | throw redirect(PATHS.HOME) 6 | } 7 | 8 | export default function App() { 9 | return ( 10 |
11 |
App Route
12 |
13 | ) 14 | } 15 | -------------------------------------------------------------------------------- /apps/portal/app/routes/app+/lists.tsx: -------------------------------------------------------------------------------- 1 | import { invariant } from '@lib/utils/misc' 2 | import { LoaderFunctionArgs, redirect } from '@remix-run/node' 3 | import { requireUserWallet } from '@server/auth' 4 | import { NO_WALLET_ERROR, PATHS } from 'app/consts' 5 | 6 | export async function loader({ request }: LoaderFunctionArgs) { 7 | const wallet = await requireUserWallet(request) 8 | invariant(wallet, NO_WALLET_ERROR) 9 | 10 | return redirect(PATHS.EXPLORE_LISTS) 11 | } 12 | -------------------------------------------------------------------------------- /apps/portal/app/routes/app+/quest+/content/3b5315bb-f29b-4320-9997-6928b4bbf3e9-closing.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Chapter 2: Intention Closing' 3 | summary: 'Indicate your conviction and support of an identity.' 4 | --- 5 | 6 | Your focus sharpens, honing in on the Atom. As it starts to solidify, a sense of clarity washes over you. The once-blurry edges become defined, the perfect circle now crisp and clear in your vision. You feel the weight of its significance, a tiny fragment of the universe revealing itself to you... 7 | -------------------------------------------------------------------------------- /apps/portal/app/routes/app+/quest+/content/ac22e180-9923-4481-9cba-31e88f223e58-closing.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Chapter 4: Expression Closing' 3 | summary: 'Express agreement or disagreement while shaping community wisdom.' 4 | --- 5 | 6 | As your gaze intensifies on the Triple of Atoms, the connections between them grow ever more solid, the glow of their unity casting a radiant light. Each Atom pulses with energy, their bonds strengthened by your unwavering focus. The sense of harmony and order brings a brief moment of peace to your surroundings... 7 | -------------------------------------------------------------------------------- /apps/portal/app/routes/app+/quest+/content/dacdd63d-f978-433e-aeb0-54d165e8f936-closing.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Chapter 3: Language' 3 | summary: 'Practice creating a claim, or verifiable statement, to express your opinion about a web3 project or topic.' 4 | --- 5 | 6 | As the patterns of connection crystallize, you feel a profound sense of alignment. Each Atom, once isolated, now finds its place in a grander scheme. The flames, though still present, become a steady background warmth, fueling your resolve... 7 | 8 | You observe the newly formed structures with a mix of awe and curiosity. The standardized formations pulse with a rhythmic energy, a silent testament to their newfound unity. You sense that this is just the beginning, a nascent stage of a much larger transformation... 9 | -------------------------------------------------------------------------------- /apps/portal/app/routes/readonly+/_layout.tsx: -------------------------------------------------------------------------------- 1 | import { Outlet } from '@remix-run/react' 2 | 3 | // This is the parent loader and layout for the /readonly routes 4 | // We can add any loader logic we need to here 5 | 6 | export default function ReadOnlyLayout() { 7 | return 8 | } 9 | -------------------------------------------------------------------------------- /apps/portal/app/routes/readonly+/index.tsx: -------------------------------------------------------------------------------- 1 | import logger from '@lib/utils/logger' 2 | import { json } from '@remix-run/node' 3 | import { useLoaderData } from '@remix-run/react' 4 | 5 | export async function loader() { 6 | const test = 'this is the readonly index loader running' 7 | logger('this is the readonly index loader running') 8 | 9 | return json({ 10 | test, 11 | }) 12 | } 13 | 14 | export default function ReadOnly() { 15 | const { test } = useLoaderData() 16 | logger('test', test) 17 | 18 | return ( 19 |
20 |
ReadOnly Route
21 |
22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /apps/portal/app/styles/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | html, 6 | body { 7 | overflow-x: hidden; 8 | touch-action: pan-y; 9 | -webkit-overflow-scrolling: touch; 10 | } 11 | 12 | * { 13 | -webkit-tap-highlight-color: transparent; 14 | } 15 | -------------------------------------------------------------------------------- /apps/portal/app/types/claim.ts: -------------------------------------------------------------------------------- 1 | export const ClaimElement = { 2 | Subject: 'subject', 3 | Predicate: 'predicate', 4 | Object: 'object', 5 | } as const 6 | 7 | export type ClaimElementType = (typeof ClaimElement)[keyof typeof ClaimElement] 8 | -------------------------------------------------------------------------------- /apps/portal/app/types/claimr.ts: -------------------------------------------------------------------------------- 1 | export type ClaimrPointsType = { 2 | xp: number 3 | ref_xp: number 4 | ugc_xp: number 5 | rank: number 6 | } 7 | -------------------------------------------------------------------------------- /apps/portal/app/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './claimr' 2 | export * from './claim' 3 | export * from './identity' 4 | export * from './navigation' 5 | export * from './pagination' 6 | export * from './privy' 7 | export * from './quest' 8 | export * from './quest-temp' 9 | export * from './tags' 10 | export * from './transaction' 11 | export * from './user' 12 | export * from './vault' 13 | -------------------------------------------------------------------------------- /apps/portal/app/types/navigation.ts: -------------------------------------------------------------------------------- 1 | export type RedirectOptions = { 2 | redirectTo?: string 3 | } 4 | -------------------------------------------------------------------------------- /apps/portal/app/types/pagination.ts: -------------------------------------------------------------------------------- 1 | export interface PaginationType { 2 | currentPage: number 3 | limit: number 4 | totalEntries: number 5 | totalPages: number 6 | } 7 | -------------------------------------------------------------------------------- /apps/portal/app/types/quest.ts: -------------------------------------------------------------------------------- 1 | export type QuestSet = { 2 | imgSrc: string 3 | title: string 4 | description: string 5 | summary: string 6 | navigatePath: string 7 | } 8 | 9 | export const MDXContentVariant = { 10 | LORE: 'lore', 11 | DEFAULT: 'default', 12 | } 13 | 14 | export type MDXContentVariantType = 15 | (typeof MDXContentVariant)[keyof typeof MDXContentVariant] 16 | -------------------------------------------------------------------------------- /apps/portal/app/types/session.ts: -------------------------------------------------------------------------------- 1 | import { SessionUser } from './user' 2 | 3 | declare global { 4 | type SessionData = { 5 | count: number 6 | user?: SessionUser 7 | } 8 | 9 | type SessionFlashData = { 10 | error: string 11 | } 12 | } 13 | 14 | export {} 15 | -------------------------------------------------------------------------------- /apps/portal/app/types/tags.ts: -------------------------------------------------------------------------------- 1 | export type TagType = { 2 | name: string 3 | id: string 4 | } 5 | -------------------------------------------------------------------------------- /apps/portal/instrumentation.server.mjs: -------------------------------------------------------------------------------- 1 | import * as Sentry from '@sentry/remix' 2 | 3 | Sentry.init({ 4 | dsn: 'https://de49927453262eeb56a313be2d02c052@o4507699051560960.ingest.us.sentry.io/4507699076399104', 5 | tracesSampleRate: 0.5, 6 | autoInstrumentRemix: true, 7 | }) 8 | -------------------------------------------------------------------------------- /apps/portal/postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /apps/portal/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/portal/public/favicon.ico -------------------------------------------------------------------------------- /apps/portal/public/fonts/Geist-Medium.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/portal/public/fonts/Geist-Medium.otf -------------------------------------------------------------------------------- /apps/portal/public/fonts/Geist-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/portal/public/fonts/Geist-Regular.otf -------------------------------------------------------------------------------- /apps/portal/public/fonts/Geist-SemiBold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/portal/public/fonts/Geist-SemiBold.otf -------------------------------------------------------------------------------- /apps/portal/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | presets: [], 4 | content: ['./src/**/*.{js,jsx,ts,tsx}'], 5 | theme: { 6 | extend: {}, 7 | }, 8 | plugins: [], 9 | } 10 | -------------------------------------------------------------------------------- /apps/portal/tests/sample.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest' 2 | 3 | describe('Sample suite', () => { 4 | it('is a sample test', () => { 5 | expect(8).toEqual(8) 6 | }) 7 | }) 8 | -------------------------------------------------------------------------------- /apps/portal/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /apps/portal/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "types": ["jest", "node"] 6 | }, 7 | "include": [ 8 | "jest.config.ts", 9 | "src/**/*.test.ts", 10 | "src/**/*.spec.ts", 11 | "src/**/*.test.tsx", 12 | "src/**/*.spec.tsx", 13 | "src/**/*.test.js", 14 | "src/**/*.spec.js", 15 | "src/**/*.test.jsx", 16 | "src/**/*.spec.jsx", 17 | "src/**/*.d.ts" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /apps/portal/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { configDefaults, defineConfig, type UserConfig } from 'vitest/config' 2 | 3 | const config = defineConfig({ 4 | test: { 5 | ...configDefaults, 6 | globals: true, 7 | environment: 'jsdom', 8 | setupFiles: './vitest.setup.ts', 9 | }, 10 | }) as UserConfig 11 | 12 | export default config 13 | -------------------------------------------------------------------------------- /apps/portal/vitest.setup.ts: -------------------------------------------------------------------------------- 1 | import * as matchers from '@testing-library/jest-dom/matchers' 2 | import { cleanup } from '@testing-library/react' 3 | import { afterEach, expect } from 'vitest' 4 | 5 | expect.extend(matchers) 6 | 7 | afterEach(() => { 8 | cleanup() 9 | }) 10 | -------------------------------------------------------------------------------- /apps/template/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.base.cjs'], 3 | env: { 4 | node: true, 5 | jest: true, 6 | }, 7 | overrides: [ 8 | { 9 | files: ['*.ts', '*.tsx', '*.js', '*.jsx'], 10 | rules: {}, 11 | }, 12 | { 13 | files: ['*.ts', '*.tsx'], 14 | rules: { 15 | '@typescript-eslint/no-unused-vars': [ 16 | 'error', 17 | { 18 | varsIgnorePattern: '^React$', 19 | }, 20 | ], 21 | }, 22 | }, 23 | { 24 | files: ['*.js', '*.jsx'], 25 | rules: {}, 26 | }, 27 | { 28 | files: ['*.json'], 29 | parser: 'jsonc-eslint-parser', 30 | rules: {}, 31 | }, 32 | ], 33 | } 34 | -------------------------------------------------------------------------------- /apps/template/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | /.cache 4 | /build 5 | .env 6 | /.content-collections 7 | .DS_Store 8 | # Sentry Config File 9 | .sentryclirc 10 | 11 | # Sentry Config File 12 | .env.sentry-build-plugin 13 | -------------------------------------------------------------------------------- /apps/template/app/.client/privy-refresh.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react' 2 | 3 | import { usePrivy } from '@privy-io/react-auth' 4 | import { useRevalidator } from '@remix-run/react' 5 | 6 | export default function PrivyRefresh() { 7 | const { ready, getAccessToken } = usePrivy() 8 | const { revalidate } = useRevalidator() 9 | 10 | useEffect(() => { 11 | async function refresh() { 12 | if (ready) { 13 | await getAccessToken() 14 | revalidate() 15 | } 16 | } 17 | 18 | refresh() 19 | }, [ready, revalidate]) 20 | 21 | return
22 | } 23 | -------------------------------------------------------------------------------- /apps/template/app/.client/privy-revalidate.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react' 2 | 3 | import { usePrivy } from '@privy-io/react-auth' 4 | import { useRevalidator } from '@remix-run/react' 5 | 6 | export default function PrivyRevalidate() { 7 | const { ready, authenticated, user: privyUser } = usePrivy() 8 | const { revalidate } = useRevalidator() 9 | 10 | useEffect(() => { 11 | // if privyUser has changed, revalidate the page 12 | if (ready && authenticated && privyUser) { 13 | revalidate() 14 | } 15 | // omits authenticate from the exhaustive deps 16 | // eslint-disable-next-line react-hooks/exhaustive-deps 17 | }, [ready, privyUser, revalidate]) 18 | 19 | return
20 | } 21 | -------------------------------------------------------------------------------- /apps/template/app/.server/theme.ts: -------------------------------------------------------------------------------- 1 | import { Theme, themesList } from '@0xintuition/1ui' 2 | 3 | import * as cookie from 'cookie' 4 | 5 | const cookieName = 'theme' 6 | 7 | export function getTheme(request: Request): Theme | undefined { 8 | const cookieHeader = request.headers.get('Cookie') 9 | const parsed = cookieHeader && cookie.parse(cookieHeader)[cookieName] 10 | 11 | if (themesList.includes(parsed as Theme)) { 12 | return parsed as Theme 13 | } 14 | 15 | return undefined 16 | } 17 | 18 | // Cookie value set by the server 19 | export function setTheme(theme?: Theme) { 20 | if (theme) { 21 | return cookie.serialize(cookieName, theme, { path: '/' }) 22 | } 23 | return cookie.serialize(cookieName, '', { path: '/', maxAge: 0 }) 24 | } 25 | -------------------------------------------------------------------------------- /apps/template/app/assets/derp-face-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/template/app/assets/derp-face-1.png -------------------------------------------------------------------------------- /apps/template/app/assets/derp-face-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/template/app/assets/derp-face-10.png -------------------------------------------------------------------------------- /apps/template/app/assets/derp-face-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/template/app/assets/derp-face-11.png -------------------------------------------------------------------------------- /apps/template/app/assets/derp-face-12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/template/app/assets/derp-face-12.jpg -------------------------------------------------------------------------------- /apps/template/app/assets/derp-face-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/template/app/assets/derp-face-2.png -------------------------------------------------------------------------------- /apps/template/app/assets/derp-face-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/template/app/assets/derp-face-3.png -------------------------------------------------------------------------------- /apps/template/app/assets/derp-face-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/template/app/assets/derp-face-4.png -------------------------------------------------------------------------------- /apps/template/app/assets/derp-face-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/template/app/assets/derp-face-5.png -------------------------------------------------------------------------------- /apps/template/app/assets/derp-face-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/template/app/assets/derp-face-6.png -------------------------------------------------------------------------------- /apps/template/app/assets/derp-face-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/template/app/assets/derp-face-7.png -------------------------------------------------------------------------------- /apps/template/app/assets/derp-face-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/template/app/assets/derp-face-8.png -------------------------------------------------------------------------------- /apps/template/app/assets/derp-face-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/template/app/assets/derp-face-9.png -------------------------------------------------------------------------------- /apps/template/app/components/container.tsx: -------------------------------------------------------------------------------- 1 | import type { ReactNode } from 'react' 2 | 3 | import { cn } from '@lib/utils/misc' 4 | 5 | export default function Container({ 6 | children, 7 | className, 8 | }: { 9 | children: ReactNode 10 | className?: string 11 | }) { 12 | return ( 13 |
14 | {children} 15 |
16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /apps/template/app/components/error-list.tsx: -------------------------------------------------------------------------------- 1 | export default function ErrorList({ 2 | id, 3 | errors, 4 | }: { 5 | id?: string 6 | errors?: Array | null 7 | }) { 8 | return errors?.length ? ( 9 |
    10 | {errors.map((error, i) => ( 11 |
  • 12 | {error} 13 |
  • 14 | ))} 15 |
16 | ) : null 17 | } 18 | -------------------------------------------------------------------------------- /apps/template/app/components/header.tsx: -------------------------------------------------------------------------------- 1 | import PrivyLogoutButton from '@client/privy-logout-button' 2 | import { HeaderLogo } from '@components/header-logo' 3 | import { ClientOnly } from 'remix-utils/client-only' 4 | 5 | export function Header() { 6 | return ( 7 |
8 | 9 | {() => } 10 |
11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /apps/template/app/components/revalidate-button.tsx: -------------------------------------------------------------------------------- 1 | import { Button, ButtonSize, ButtonVariant } from '@0xintuition/1ui' 2 | 3 | import { useRevalidator } from '@remix-run/react' 4 | 5 | interface RevalidateButtonProps { 6 | className?: string 7 | } 8 | 9 | export function RevalidateButton({ className }: RevalidateButtonProps) { 10 | const revalidator = useRevalidator() 11 | 12 | return ( 13 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /apps/template/app/components/search.tsx: -------------------------------------------------------------------------------- 1 | import { Input } from '@0xintuition/1ui' 2 | 3 | interface SearchProps { 4 | handleSearchChange: (event: React.ChangeEvent) => void 5 | } 6 | 7 | export function Search({ handleSearchChange }: SearchProps) { 8 | return ( 9 | 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /apps/template/app/components/sort.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { SortDirection } from '@0xintuition/api' 4 | 5 | import { SortOption, SortSelect } from '@components/sort-select' 6 | 7 | interface SortProps { 8 | options: SortOption[] 9 | handleSortChange: (newSortBy: T, newDirection: SortDirection) => void 10 | } 11 | 12 | export function Sort({ options, handleSortChange }: SortProps) { 13 | return 14 | } 15 | -------------------------------------------------------------------------------- /apps/template/app/components/usd-tooltip.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | Tooltip, 3 | TooltipContent, 4 | TooltipProvider, 5 | TooltipTrigger, 6 | } from '@0xintuition/1ui' 7 | 8 | export const UsdTooltip = ({ 9 | ethValue, 10 | usdValue, 11 | }: { 12 | ethValue: string 13 | usdValue: string 14 | }) => { 15 | return ( 16 | 17 | 18 | {ethValue} ETH 19 | ${usdValue} USD 20 | 21 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /apps/template/app/consts/assets.ts: -------------------------------------------------------------------------------- 1 | export const HOME_BANNER_MP4 = 2 | 'https://res.cloudinary.com/dfpwy9nyv/video/upload/f_auto:video,q_auto/v1/Portal%20Assets/home-banner-video' 3 | -------------------------------------------------------------------------------- /apps/template/app/consts/emails.ts: -------------------------------------------------------------------------------- 1 | export const SUPPORT_EMAIL_ADDRESS = 'support@intuition.systems' 2 | -------------------------------------------------------------------------------- /apps/template/app/consts/errors.ts: -------------------------------------------------------------------------------- 1 | export const NO_WALLET_ERROR = 'No wallet found in session' 2 | export const NO_PARAM_ID_ERROR = 'Invalid or missing param ID' 3 | export const NO_USER_IDENTITY_ERROR = 'No user identity found' 4 | export const NO_IDENTITY_ERROR = 'No identity found' 5 | export const INVALID_CREATOR_ID_ERROR = 'Invalid or missing creator ID' 6 | export const GENERIC_ERROR_MSG = 'An error occurred' 7 | export const NO_CLAIM_ERROR = 'No claim found' 8 | export const NO_USER_TOTALS_ERROR = 'No user totals found' 9 | export const NO_CONNECTIONS_DATA_ERROR = 'No connections data found' 10 | export const NO_FOLLOW_CLAIM_ERROR = 'No follow claim found' 11 | -------------------------------------------------------------------------------- /apps/template/app/consts/index.ts: -------------------------------------------------------------------------------- 1 | export * from './assets' 2 | export * from './emails' 3 | export * from './errors' 4 | export * from './general' 5 | export * from './paths' 6 | -------------------------------------------------------------------------------- /apps/template/app/consts/paths.ts: -------------------------------------------------------------------------------- 1 | export const PATHS = { 2 | // Root paths 3 | ROOT: '/', 4 | APP: '/app', 5 | // General 6 | LOGIN: '/login', 7 | } 8 | -------------------------------------------------------------------------------- /apps/template/app/entry.client.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * By default, Remix will handle hydrating your app on the client for you. 3 | * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨ 4 | * For more information, see https://remix.run/file-conventions/entry.client 5 | */ 6 | 7 | // import './polyfills' 8 | import { startTransition, StrictMode } from 'react' 9 | 10 | import { RemixBrowser } from '@remix-run/react' 11 | import { hydrateRoot } from 'react-dom/client' 12 | 13 | startTransition(() => { 14 | hydrateRoot( 15 | document, 16 | 17 | 18 | , 19 | ) 20 | }) 21 | -------------------------------------------------------------------------------- /apps/template/app/layouts/full-page-layout.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | interface FullPageLayoutProps { 4 | children: React.ReactNode 5 | } 6 | 7 | const FullPageLayout: React.FC = ({ children }) => { 8 | return ( 9 |
10 | {children} 11 |
12 | ) 13 | } 14 | 15 | export default FullPageLayout 16 | -------------------------------------------------------------------------------- /apps/template/app/layouts/root-layout.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | interface RootLayoutProps { 4 | children: React.ReactNode 5 | } 6 | 7 | const RootLayout: React.FC = ({ children }) => { 8 | return ( 9 |
10 |
11 | {children} 12 |
13 |
14 | ) 15 | } 16 | 17 | export default RootLayout 18 | -------------------------------------------------------------------------------- /apps/template/app/lib/hooks/useBatchCreateTriple.tsx: -------------------------------------------------------------------------------- 1 | import { CURRENT_ENV } from 'app/consts' 2 | import type { GetContractReturnType } from 'viem' 3 | 4 | import { getChainEnvConfig } from '../utils/environment' 5 | import { useContractWriteAndWait } from './useContractWriteAndWait' 6 | import { useMultivaultContract } from './useMultivaultContract' 7 | 8 | export const useBatchCreateTriple = () => { 9 | const multivault = useMultivaultContract( 10 | getChainEnvConfig(CURRENT_ENV).chainId.toString(), 11 | ) as GetContractReturnType 12 | 13 | return useContractWriteAndWait({ 14 | ...multivault, 15 | // @ts-ignore TODO: Fix type for useContractWriteAndWait 16 | functionName: 'batchCreateTriple', 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /apps/template/app/lib/hooks/useCopy.tsx: -------------------------------------------------------------------------------- 1 | import { useCallback, useState } from 'react' 2 | 3 | export const useCopy = (duration = 2000) => { 4 | const [copied, setCopied] = useState(false) 5 | 6 | const copy = useCallback( 7 | (text: string) => { 8 | navigator.clipboard.writeText(text) 9 | setCopied(true) 10 | setTimeout(() => setCopied(false), duration) 11 | }, 12 | [duration], 13 | ) 14 | 15 | return { copied, copy } 16 | } 17 | -------------------------------------------------------------------------------- /apps/template/app/lib/hooks/useCreateAtom.tsx: -------------------------------------------------------------------------------- 1 | import { CURRENT_ENV } from 'app/consts' 2 | import type { GetContractReturnType } from 'viem' 3 | 4 | import { getChainEnvConfig } from '../utils/environment' 5 | import { useContractWriteAndWait } from './useContractWriteAndWait' 6 | import { useMultivaultContract } from './useMultivaultContract' 7 | 8 | export const useCreateAtom = () => { 9 | const multivault = useMultivaultContract( 10 | getChainEnvConfig(CURRENT_ENV).chainId.toString(), 11 | ) as GetContractReturnType 12 | 13 | return useContractWriteAndWait({ 14 | ...multivault, 15 | // @ts-ignore TODO: Fix type for useContractWriteAndWait 16 | functionName: 'createAtom', 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /apps/template/app/lib/hooks/useCreateTriple.tsx: -------------------------------------------------------------------------------- 1 | import { CURRENT_ENV } from 'app/consts' 2 | import type { GetContractReturnType } from 'viem' 3 | 4 | import { getChainEnvConfig } from '../utils/environment' 5 | import { useContractWriteAndWait } from './useContractWriteAndWait' 6 | import { useMultivaultContract } from './useMultivaultContract' 7 | 8 | export const useCreateTriple = () => { 9 | const multivault = useMultivaultContract( 10 | getChainEnvConfig(CURRENT_ENV).chainId.toString(), 11 | ) as GetContractReturnType 12 | 13 | return useContractWriteAndWait({ 14 | ...multivault, 15 | // @ts-ignore TODO: Fix type for useContractWriteAndWait 16 | functionName: 'createTriple', 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /apps/template/app/lib/hooks/useDepositAtom.tsx: -------------------------------------------------------------------------------- 1 | import { CURRENT_ENV } from 'app/consts' 2 | import type { GetContractReturnType } from 'viem' 3 | 4 | import { getChainEnvConfig } from '../utils/environment' 5 | import { useContractWriteAndWait } from './useContractWriteAndWait' 6 | import { useMultivaultContract } from './useMultivaultContract' 7 | 8 | export const useDepositAtom = (contract: string) => { 9 | const multivault = useMultivaultContract( 10 | contract, 11 | getChainEnvConfig(CURRENT_ENV).chainId, 12 | ) as GetContractReturnType 13 | 14 | return useContractWriteAndWait({ 15 | ...multivault, 16 | // @ts-ignore TODO: Fix type for useContractWriteAndWait 17 | functionName: 'depositAtom', 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /apps/template/app/lib/hooks/useDepositTriple.tsx: -------------------------------------------------------------------------------- 1 | import { CURRENT_ENV } from 'app/consts' 2 | import type { GetContractReturnType } from 'viem' 3 | 4 | import { getChainEnvConfig } from '../utils/environment' 5 | import { useContractWriteAndWait } from './useContractWriteAndWait' 6 | import { useMultivaultContract } from './useMultivaultContract' 7 | 8 | export const useDepositTriple = (contract: string) => { 9 | const multivault = useMultivaultContract( 10 | contract, 11 | getChainEnvConfig(CURRENT_ENV).chainId, 12 | ) as GetContractReturnType 13 | 14 | return useContractWriteAndWait({ 15 | ...multivault, 16 | // @ts-ignore TODO: Fix type for useContractWriteAndWait 17 | functionName: 'depositTriple', 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /apps/template/app/lib/hooks/useGoBack.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from 'react' 2 | 3 | import { useLocation, useNavigate } from '@remix-run/react' 4 | 5 | function useGoBack({ fallbackRoute }: { fallbackRoute: string }) { 6 | const navigate = useNavigate() 7 | const location = useLocation() 8 | const hasNavigated = useRef(false) 9 | 10 | useEffect(() => { 11 | hasNavigated.current = true 12 | }, [location]) 13 | 14 | return () => { 15 | if (hasNavigated.current && window.history.length > 2) { 16 | navigate(-1) 17 | } else { 18 | window.location.href = fallbackRoute 19 | } 20 | } 21 | } 22 | 23 | export { useGoBack } 24 | -------------------------------------------------------------------------------- /apps/template/app/lib/hooks/useLiveLoader.ts: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react' 2 | 3 | import { useLoaderData, useRevalidator } from '@remix-run/react' 4 | import { useEventSource } from 'remix-utils/sse/react' 5 | 6 | export function useLiveLoader(events: string[]) { 7 | // eslint-disable-next-line react-hooks/rules-of-hooks 8 | const eventSources = events.map((event) => useEventSource(`/event/${event}`)) 9 | 10 | const { revalidate } = useRevalidator() 11 | useEffect(() => { 12 | revalidate() 13 | // eslint-disable-next-line react-hooks/exhaustive-deps 14 | }, eventSources) 15 | 16 | return useLoaderData() 17 | } 18 | -------------------------------------------------------------------------------- /apps/template/app/lib/hooks/useLoaderFetcher.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from 'react' 2 | 3 | import { useFetcher } from '@remix-run/react' 4 | 5 | export function useLoaderFetcher(resourceUrl: string) { 6 | const loaderFetcher = useFetcher() 7 | const loaderFetcherRef = useRef(loaderFetcher.load) 8 | 9 | useEffect(() => { 10 | loaderFetcherRef.current = loaderFetcher.load 11 | }, [loaderFetcher.load]) 12 | 13 | useEffect(() => { 14 | loaderFetcherRef.current(resourceUrl) 15 | }, [resourceUrl]) 16 | 17 | return loaderFetcher 18 | } 19 | -------------------------------------------------------------------------------- /apps/template/app/lib/hooks/useRedeemAtom.tsx: -------------------------------------------------------------------------------- 1 | import { CURRENT_ENV } from 'app/consts' 2 | import { type GetContractReturnType } from 'viem' 3 | 4 | import { getChainEnvConfig } from '../utils/environment' 5 | import { useContractWriteAndWait } from './useContractWriteAndWait' 6 | import { useMultivaultContract } from './useMultivaultContract' 7 | 8 | export const useRedeemAtom = (contract: string) => { 9 | const multivault = useMultivaultContract( 10 | contract, 11 | getChainEnvConfig(CURRENT_ENV).chainId, 12 | ) as GetContractReturnType 13 | 14 | return useContractWriteAndWait({ 15 | ...multivault, 16 | // @ts-ignore TODO: Fix type for useContractWriteAndWait 17 | functionName: 'redeemAtom', 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /apps/template/app/lib/hooks/useRedeemTriple.tsx: -------------------------------------------------------------------------------- 1 | import { CURRENT_ENV } from 'app/consts' 2 | import { type GetContractReturnType } from 'viem' 3 | 4 | import { getChainEnvConfig } from '../utils/environment' 5 | import { useContractWriteAndWait } from './useContractWriteAndWait' 6 | import { useMultivaultContract } from './useMultivaultContract' 7 | 8 | export const useRedeemTriple = (contract: string) => { 9 | const multivault = useMultivaultContract( 10 | contract, 11 | getChainEnvConfig(CURRENT_ENV).chainId, 12 | ) as GetContractReturnType 13 | 14 | return useContractWriteAndWait({ 15 | ...multivault, 16 | // @ts-ignore TODO: Fix type for useContractWriteAndWait 17 | functionName: 'redeemTriple', 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /apps/template/app/lib/services/pricefeeds.ts: -------------------------------------------------------------------------------- 1 | import { chainlinkEthUsdOracleAbi } from '@lib/abis/chainlinkEthUsdOracle' 2 | import { mainnetClient } from '@server/viem' 3 | import { formatUnits } from 'viem' 4 | 5 | export async function getEthPrice() { 6 | const ethPrice = (await mainnetClient.readContract({ 7 | address: '0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419', 8 | abi: chainlinkEthUsdOracleAbi, 9 | functionName: 'latestAnswer', 10 | })) as Promise 11 | return formatUnits(BigInt(await ethPrice), 8) 12 | } 13 | -------------------------------------------------------------------------------- /apps/template/app/lib/utils/logger.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Logs only in development mode 3 | */ 4 | /* eslint-disable @typescript-eslint/no-explicit-any */ 5 | const logger = (...args: any[]) => { 6 | if (process.env.NODE_ENV !== 'production') { 7 | return console.log(...args) 8 | } 9 | } 10 | 11 | export default logger 12 | -------------------------------------------------------------------------------- /apps/template/app/lib/utils/nonce-provider.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | export const NonceContext = React.createContext('') 4 | export const NonceProvider = NonceContext.Provider 5 | export const useNonce = () => React.useContext(NonceContext) 6 | -------------------------------------------------------------------------------- /apps/template/app/lib/utils/request-info.tsx: -------------------------------------------------------------------------------- 1 | import { useRouteLoaderData } from '@remix-run/react' 2 | 3 | import { type loader as rootLoader } from '../../root' 4 | import { invariant } from './misc' 5 | 6 | /** 7 | * @returns the request info from the root loader 8 | */ 9 | export function useRequestInfo() { 10 | const data = useRouteLoaderData('root') 11 | invariant(data?.requestInfo, 'No requestInfo found in root loader') 12 | 13 | return data.requestInfo 14 | } 15 | -------------------------------------------------------------------------------- /apps/template/app/lib/utils/use-tx-reducer.ts: -------------------------------------------------------------------------------- 1 | import { useReducer, type Reducer } from 'react' 2 | 3 | /** 4 | * This hook takes in a reducer and an initial state and returns the state and dispatch function. It's a generic hook that can be used for any reducer and initial state. 5 | * Without any additional configuration, it uses the default state and reducer in this file, but these can be overridden by passing in a custom reducer and initial state when needed. 6 | */ 7 | 8 | export function useGenericTxState( 9 | reducer: Reducer, 10 | initialState: S, 11 | ) { 12 | const [state, dispatch] = useReducer(reducer, initialState) 13 | return { state, dispatch } 14 | } 15 | -------------------------------------------------------------------------------- /apps/template/app/polyfills.ts: -------------------------------------------------------------------------------- 1 | import { Buffer } from 'buffer' 2 | 3 | // bare minimum polyfills to get vite working with web3 tooling 4 | 5 | if (typeof window !== 'undefined') { 6 | window.Buffer = window.Buffer ?? Buffer 7 | } 8 | 9 | export {} 10 | -------------------------------------------------------------------------------- /apps/template/app/routes/actions+/logout.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from '@remix-run/node' 2 | import { logout } from '@server/auth' 3 | 4 | export async function loader() { 5 | return redirect('/') 6 | } 7 | 8 | export async function action() { 9 | return logout({ redirectTo: '/login' }) 10 | } 11 | -------------------------------------------------------------------------------- /apps/template/app/routes/app+/index.tsx: -------------------------------------------------------------------------------- 1 | export default function App() { 2 | return
App route
3 | } 4 | -------------------------------------------------------------------------------- /apps/template/app/routes/app.tsx: -------------------------------------------------------------------------------- 1 | import logger from '@lib/utils/logger' 2 | import { invariant } from '@lib/utils/misc' 3 | import { json, LoaderFunctionArgs } from '@remix-run/node' 4 | import { Outlet } from '@remix-run/react' 5 | import { requireUserWallet } from '@server/auth' 6 | 7 | export async function loader({ request }: LoaderFunctionArgs) { 8 | logger('[Loader] Entering app loader') 9 | 10 | const wallet = await requireUserWallet(request) 11 | invariant(wallet, 'Unauthorized') 12 | 13 | return json({ 14 | wallet, 15 | }) 16 | } 17 | 18 | export default function App() { 19 | return ( 20 |
21 | 22 |
23 | ) 24 | } 25 | -------------------------------------------------------------------------------- /apps/template/app/styles/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | html, 6 | body { 7 | overflow-x: hidden; 8 | touch-action: pan-y; 9 | -webkit-overflow-scrolling: touch; 10 | } 11 | 12 | * { 13 | -webkit-tap-highlight-color: transparent; 14 | } 15 | -------------------------------------------------------------------------------- /apps/template/app/types/claim.ts: -------------------------------------------------------------------------------- 1 | export const ClaimElement = { 2 | Subject: 'subject', 3 | Predicate: 'predicate', 4 | Object: 'object', 5 | } as const 6 | 7 | export type ClaimElementType = (typeof ClaimElement)[keyof typeof ClaimElement] 8 | -------------------------------------------------------------------------------- /apps/template/app/types/claimr.ts: -------------------------------------------------------------------------------- 1 | export type ClaimrPointsType = { 2 | xp: number 3 | ref_xp: number 4 | ugc_xp: number 5 | rank: number 6 | } 7 | -------------------------------------------------------------------------------- /apps/template/app/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './claimr' 2 | export * from './claim' 3 | export * from './identity' 4 | export * from './navigation' 5 | export * from './pagination' 6 | export * from './privy' 7 | export * from './quest' 8 | export * from './quest-temp' 9 | export * from './tags' 10 | export * from './transaction' 11 | export * from './user' 12 | export * from './vault' 13 | -------------------------------------------------------------------------------- /apps/template/app/types/navigation.ts: -------------------------------------------------------------------------------- 1 | export type RedirectOptions = { 2 | redirectTo?: string 3 | } 4 | -------------------------------------------------------------------------------- /apps/template/app/types/pagination.ts: -------------------------------------------------------------------------------- 1 | export interface PaginationType { 2 | currentPage: number 3 | limit: number 4 | totalEntries: number 5 | totalPages: number 6 | } 7 | -------------------------------------------------------------------------------- /apps/template/app/types/quest.ts: -------------------------------------------------------------------------------- 1 | export type QuestSet = { 2 | imgSrc: string 3 | title: string 4 | description: string 5 | summary: string 6 | navigatePath: string 7 | } 8 | 9 | export const MDXContentVariant = { 10 | LORE: 'lore', 11 | DEFAULT: 'default', 12 | } 13 | 14 | export type MDXContentVariantType = 15 | (typeof MDXContentVariant)[keyof typeof MDXContentVariant] 16 | -------------------------------------------------------------------------------- /apps/template/app/types/session.ts: -------------------------------------------------------------------------------- 1 | import { SessionUser } from './user' 2 | 3 | declare global { 4 | type SessionData = { 5 | count: number 6 | user?: SessionUser 7 | } 8 | 9 | type SessionFlashData = { 10 | error: string 11 | } 12 | } 13 | 14 | export {} 15 | -------------------------------------------------------------------------------- /apps/template/app/types/tags.ts: -------------------------------------------------------------------------------- 1 | export type TagType = { 2 | name: string 3 | id: string 4 | } 5 | -------------------------------------------------------------------------------- /apps/template/postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /apps/template/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/apps/template/public/favicon.ico -------------------------------------------------------------------------------- /apps/template/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | optimizeDeps: { 4 | include: ['mini-svg-data-uri'], 5 | }, 6 | presets: [], 7 | content: ['./src/**/*.{js,jsx,ts,tsx}'], 8 | theme: { 9 | extend: {}, 10 | }, 11 | plugins: [], 12 | } 13 | -------------------------------------------------------------------------------- /apps/template/tests/sample.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest' 2 | 3 | describe('Sample suite', () => { 4 | it('is a sample test', () => { 5 | expect(8).toEqual(8) 6 | }) 7 | }) 8 | -------------------------------------------------------------------------------- /apps/template/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /apps/template/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "types": ["jest", "node"] 6 | }, 7 | "include": [ 8 | "jest.config.ts", 9 | "src/**/*.test.ts", 10 | "src/**/*.spec.ts", 11 | "src/**/*.test.tsx", 12 | "src/**/*.spec.tsx", 13 | "src/**/*.test.js", 14 | "src/**/*.spec.js", 15 | "src/**/*.test.jsx", 16 | "src/**/*.spec.jsx", 17 | "src/**/*.d.ts" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /apps/template/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { configDefaults, defineConfig, type UserConfig } from 'vitest/config' 2 | 3 | const config = defineConfig({ 4 | test: { 5 | ...configDefaults, 6 | globals: true, 7 | environment: 'jsdom', 8 | setupFiles: './vitest.setup.ts', 9 | }, 10 | }) as UserConfig 11 | 12 | export default config 13 | -------------------------------------------------------------------------------- /apps/template/vitest.setup.ts: -------------------------------------------------------------------------------- 1 | import * as matchers from '@testing-library/jest-dom/matchers' 2 | import { cleanup } from '@testing-library/react' 3 | import { afterEach, expect } from 'vitest' 4 | 5 | expect.extend(matchers) 6 | 7 | afterEach(() => { 8 | cleanup() 9 | }) 10 | -------------------------------------------------------------------------------- /docs/decisions/000-template.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/docs/decisions/000-template.md -------------------------------------------------------------------------------- /docs/guiding-principles/tailwind-styling.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/docs/guiding-principles/tailwind-styling.md -------------------------------------------------------------------------------- /jest.config.ts: -------------------------------------------------------------------------------- 1 | import { getJestProjectsAsync } from '@nx/jest' 2 | 3 | export default async () => ({ 4 | projects: await getJestProjectsAsync(), 5 | }) 6 | -------------------------------------------------------------------------------- /jest.preset.js: -------------------------------------------------------------------------------- 1 | const nxPreset = require('@nx/jest/preset').default 2 | 3 | module.exports = { ...nxPreset } 4 | -------------------------------------------------------------------------------- /packages/1ui/.env.example: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/packages/1ui/.env.example -------------------------------------------------------------------------------- /packages/1ui/.storybook/global.css: -------------------------------------------------------------------------------- 1 | .docs-story { 2 | @apply bg-background; 3 | } 4 | -------------------------------------------------------------------------------- /packages/1ui/.storybook/manager.ts: -------------------------------------------------------------------------------- 1 | import { addons } from '@storybook/manager-api' 2 | 3 | import { darkTheme } from './theme' 4 | 5 | addons.setConfig({ 6 | theme: darkTheme, 7 | }) 8 | -------------------------------------------------------------------------------- /packages/1ui/.storybook/templates/DocumentationTemplate.mdx: -------------------------------------------------------------------------------- 1 | import { 2 | Controls, 3 | Description, 4 | Meta, 5 | Primary, 6 | Stories, 7 | Title, 8 | } from '@storybook/blocks' 9 | 10 | 11 | 12 | 13 | 14 | <Description /> 15 | 16 | <Primary /> 17 | 18 | ## Inputs 19 | 20 | The component accepts the following inputs (props): 21 | 22 | <Controls /> 23 | 24 | --- 25 | 26 | ## Variations 27 | 28 | Here are the variations of this component. 29 | 30 | <Stories /> 31 | -------------------------------------------------------------------------------- /packages/1ui/.storybook/theme.ts: -------------------------------------------------------------------------------- 1 | import { create } from '@storybook/theming/create' 2 | 3 | export const darkTheme = create({ 4 | base: 'dark', 5 | brandTitle: 'Intuition', 6 | brandUrl: 'https://intuition.systems/', 7 | brandImage: 8 | 'https://assets-global.website-files.com/65cdf366e68587fd384547f0/65d8fe503890d1bc9776916c_intuition-logo-type-ws.svg', 9 | brandTarget: '_blank', 10 | }) 11 | -------------------------------------------------------------------------------- /packages/1ui/.storybook/vite.config.ts: -------------------------------------------------------------------------------- 1 | import autoprefixer from 'autoprefixer' 2 | import tailwindcss from 'tailwindcss' 3 | import { defineConfig } from 'vite' 4 | import tsconfigPaths from 'vite-tsconfig-paths' 5 | 6 | import themePreset from '../src/styles/theme-preset' 7 | 8 | export default defineConfig({ 9 | plugins: [tsconfigPaths()], 10 | css: { 11 | postcss: { 12 | plugins: [tailwindcss(themePreset), autoprefixer], 13 | }, 14 | }, 15 | }) 16 | -------------------------------------------------------------------------------- /packages/1ui/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "default", 4 | "rsc": false, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "src/styles/globals.css", 9 | "baseColor": "slate", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/1ui/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [require('tailwindcss'), require('autoprefixer')], 3 | } 4 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Accordion/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Accordion' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/ActivePositionCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ActivePositionCard' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/AlertDialog/index.ts: -------------------------------------------------------------------------------- 1 | export * from './AlertDialog' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Avatar/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Avatar' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Badge/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Badge' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Banner/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Banner' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Button/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './Button' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Checkbox/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Checkbox' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Claim/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Claim' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/ClaimPositionRow/ClaimPositionRow.utils.ts: -------------------------------------------------------------------------------- 1 | export const ClaimPositionRowVariant = { 2 | claim: 'claim', 3 | user: 'user', 4 | } as const 5 | export type ClaimPositionRowVariantType = keyof typeof ClaimPositionRowVariant 6 | -------------------------------------------------------------------------------- /packages/1ui/src/components/ClaimPositionRow/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ClaimPositionRow' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/ClaimRow/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ClaimRow' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/ClaimStakeCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ClaimStakeCard' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/ClaimStatus/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ClaimStatus' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Command/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Command' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/ContextMenu/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ContextMenu' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Copy/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Copy' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Dialog/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Dialog' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/DropdownMenu/index.ts: -------------------------------------------------------------------------------- 1 | export * from './DropdownMenu' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/EmptyStateCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from './EmptyStateCard' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/ErrorStateCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ErrorStateCard' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/FeaturedListCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from './FeaturedListCard' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/FollowPosition/index.ts: -------------------------------------------------------------------------------- 1 | export * from './FollowPosition' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/HoverCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from './HoverCard' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Icon/Icon.spec.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { render } from '@testing-library/react' 4 | 5 | import { Icon } from './Icon' 6 | 7 | describe('Icon', () => { 8 | it('should render appropriate element', () => { 9 | const { asFragment } = render(<Icon name="book" />) 10 | expect(asFragment()).toMatchInlineSnapshot(` 11 | <DocumentFragment> 12 | <svg 13 | class="h-6 w-6" 14 | > 15 | <use 16 | href="/src/components/Icon/Icon.sprites.svg#book" 17 | /> 18 | </svg> 19 | </DocumentFragment> 20 | `) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Icon/Icon.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import * as React from 'react' 4 | 5 | import { cn } from '../../styles' 6 | // eslint-disable-next-line 7 | // @ts-ignore 8 | import spriteSheet from './Icon.sprites.svg' 9 | import { IconNameType } from './Icon.types' 10 | 11 | export interface IconProps extends React.SVGProps<SVGSVGElement> { 12 | name: IconNameType 13 | } 14 | 15 | const Icon = ({ name, className }: IconProps) => { 16 | return ( 17 | <svg className={cn(`h-6 w-6`, className)}> 18 | <use href={`${spriteSheet}#${name}`} /> 19 | </svg> 20 | ) 21 | } 22 | 23 | export { Icon } 24 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Icon/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Icon' 2 | export * from './Icon.types' 3 | -------------------------------------------------------------------------------- /packages/1ui/src/components/IdentityCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from './IdentityCard' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/IdentityInput/index.ts: -------------------------------------------------------------------------------- 1 | export * from './IdentityInput' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/IdentityPosition/index.ts: -------------------------------------------------------------------------------- 1 | export * from './IdentityPosition' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/IdentityRow/index.ts: -------------------------------------------------------------------------------- 1 | export * from './IdentityRow' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/IdentityStakeCard/IdentityStakeCard.mdx: -------------------------------------------------------------------------------- 1 | import { Canvas, Controls, Meta, Source, Title } from '@storybook/blocks' 2 | 3 | import * as Stories from './IdentityStakeCard.stories' 4 | 5 | <Meta of={Stories} /> 6 | 7 | <Title /> 8 | 9 | #### A display card to show a user's stake position. 10 | 11 | <Source 12 | dark 13 | language="tsx" 14 | code={` 15 | import { IdentityStakeCard } from '@0xintuition/1ui' 16 | 17 | <IdentityStakeCard 18 | tvl={4.928} 19 | holders={69} 20 | onBuyClick={() => doSomething()} 21 | onViewAllClick={() => doSomething()} 22 | /> 23 | `} /> 24 | 25 | <Canvas of={Stories.BasicUsage} sourceState="none" /> 26 | 27 | ## Properties 28 | 29 | <Controls /> 30 | -------------------------------------------------------------------------------- /packages/1ui/src/components/IdentityStakeCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from './IdentityStakeCard' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/IdentityTag/index.ts: -------------------------------------------------------------------------------- 1 | export * from './IdentityTag' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Indicators/Indicators.spec.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { render } from '@testing-library/react' 4 | 5 | import { MonetaryValue } from './components' 6 | 7 | describe('MonetaryValue', () => { 8 | it('should render the MonetaryValue component', () => { 9 | const { asFragment } = render( 10 | <MonetaryValue value={0.345} currency="ETH" />, 11 | ) 12 | expect(asFragment()).toMatchInlineSnapshot(` 13 | <DocumentFragment> 14 | <div 15 | class="text-primary text-lg font-medium" 16 | > 17 | 0.345 ETH 18 | </div> 19 | </DocumentFragment> 20 | `) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Indicators/Indicators.tsx: -------------------------------------------------------------------------------- 1 | export const Indicators = () => { 2 | return <></> 3 | } 4 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Indicators/components/MonetaryValue.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | Text, 3 | TextProps, 4 | TextVariant, 5 | TextVariantType, 6 | TextWeight, 7 | } from 'components/Text' 8 | import { Currency, CurrencyType } from 'types' 9 | 10 | interface MonetaryValueProps extends TextProps { 11 | value: number 12 | currency?: CurrencyType 13 | textVariant?: TextVariantType 14 | } 15 | 16 | const MonetaryValue = ({ 17 | value, 18 | currency = Currency.ETH, 19 | textVariant = TextVariant.bodyLarge, 20 | ...props 21 | }: MonetaryValueProps) => { 22 | return ( 23 | <Text variant={textVariant} weight={TextWeight.medium} {...props}> 24 | {value} {currency} 25 | </Text> 26 | ) 27 | } 28 | 29 | export { MonetaryValue } 30 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Indicators/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ClaimValueDisplay' 2 | export * from './FeesAccrued' 3 | export * from './IdentityValueDisplay' 4 | export * from './MonetaryValue' 5 | export * from './PositionValueDisplay' 6 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Indicators/index.ts: -------------------------------------------------------------------------------- 1 | export * from './components' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/InfoCard/InfoCard.mdx: -------------------------------------------------------------------------------- 1 | import { Canvas, Controls, Meta, Source, Title } from '@storybook/blocks' 2 | 3 | import * as Stories from './InfoCard.stories' 4 | 5 | <Meta of={Stories} /> 6 | 7 | <Title /> 8 | 9 | #### Claim creator info card. 10 | 11 | <Source 12 | dark 13 | language="tsx" 14 | code={` 15 | import { InfoCard } from '@0xintuition/1ui' 16 | 17 | <InfoCard 18 | variant="user" 19 | username="super dave" 20 | avatarImgSrc="image.jpg" 21 | timestamp="2024-05-10T00:00:00Z" 22 | /> 23 | `} /> 24 | 25 | <Canvas of={Stories.BasicUsage} sourceState="none" /> 26 | 27 | ## Properties 28 | 29 | <Controls /> 30 | -------------------------------------------------------------------------------- /packages/1ui/src/components/InfoCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from './InfoCard' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Input/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Input' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Label/Label.spec.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { render } from '@testing-library/react' 4 | 5 | import { Label } from './Label' 6 | 7 | describe('Label', () => { 8 | it('should render appropriate element', () => { 9 | const { asFragment } = render( 10 | <Label htmlFor="email">Your email address</Label>, 11 | ) 12 | expect(asFragment()).toMatchInlineSnapshot(` 13 | <DocumentFragment> 14 | <label 15 | class="text-base font-normal leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" 16 | for="email" 17 | > 18 | Your email address 19 | </label> 20 | </DocumentFragment> 21 | `) 22 | }) 23 | }) 24 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Label/Label.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import type { Meta, StoryObj } from '@storybook/react' 4 | 5 | import { Label } from './Label' 6 | 7 | const meta: Meta<typeof Label> = { 8 | title: 'Components/Form Elements/Label', 9 | component: Label, 10 | } 11 | 12 | export default meta 13 | 14 | type Story = StoryObj<typeof Label> 15 | 16 | export const BasicUsage: Story = { 17 | args: {}, 18 | render: (args) => ( 19 | <Label htmlFor="email" {...args}> 20 | Your email address 21 | </Label> 22 | ), 23 | } 24 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Label/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Label' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/ListCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ListCard' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/ListGrid/ListGrid.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | export interface ListGridProps extends React.HTMLAttributes<HTMLDivElement> { 4 | children?: React.ReactNode 5 | variant?: 'explore' | 'profile' 6 | } 7 | 8 | const ListGrid: React.FC<ListGridProps> = ({ 9 | children, 10 | variant = 'profile', 11 | ...props 12 | }) => { 13 | const gridClasses = 14 | variant === 'explore' 15 | ? 'w-full grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4' 16 | : 'w-full grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-4' 17 | 18 | return ( 19 | <div className={gridClasses} {...props}> 20 | {children} 21 | </div> 22 | ) 23 | } 24 | 25 | export { ListGrid } 26 | -------------------------------------------------------------------------------- /packages/1ui/src/components/ListGrid/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ListGrid' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/ListHeaderCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ListHeaderCard' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/ListIdentityCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ListIdentityCard' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Pagination/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Pagination' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/PieChart/PieChart.mdx: -------------------------------------------------------------------------------- 1 | import { Canvas, Controls, Meta, Source, Title } from '@storybook/blocks' 2 | 3 | import * as Stories from './PieChart.stories' 4 | 5 | <Meta of={Stories} /> 6 | 7 | <Title /> 8 | 9 | #### A pie chart to show percentage filled. 10 | 11 | <Source 12 | dark 13 | language="tsx" 14 | code={` 15 | import { PieChart } from '@0xintuition/1ui' 16 | 17 | <PieChart percentage={50} /> 18 | `} /> 19 | 20 | <Canvas of={Stories.BasicUsage} sourceState="none" /> 21 | 22 | ## Properties 23 | 24 | <Controls /> 25 | -------------------------------------------------------------------------------- /packages/1ui/src/components/PieChart/index.ts: -------------------------------------------------------------------------------- 1 | export * from './PieChart' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Popover/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Popover' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/PositionCard/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './PositionCardFeesAccrued' 2 | export * from './PositionCardLastUpdated' 3 | export * from './PositionCardOwnership' 4 | export * from './PositionCardStaked' 5 | -------------------------------------------------------------------------------- /packages/1ui/src/components/PositionCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from './PositionCard' 2 | export * from './components' 3 | -------------------------------------------------------------------------------- /packages/1ui/src/components/ProfileCard/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ProfileCardHeader' 2 | export * from './ProfileCardStatItem' 3 | -------------------------------------------------------------------------------- /packages/1ui/src/components/ProfileCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ProfileCard' 2 | export * from './components' 3 | -------------------------------------------------------------------------------- /packages/1ui/src/components/ProgressBar/ProgressBar.mdx: -------------------------------------------------------------------------------- 1 | import { Canvas, Controls, Meta, Source, Title } from '@storybook/blocks' 2 | 3 | import * as Stories from './ProgressBar.stories' 4 | 5 | <Meta of={Stories} /> 6 | 7 | <Title /> 8 | 9 | #### Progress bar to percentage progress 10 | 11 | <Source 12 | dark 13 | language="tsx" 14 | code={` 15 | import { ProgressBar } from '@0xintuition/1ui' 16 | 17 | <ProgressBar 18 | percentage={50} 19 | primaryClassName={'bg-primary'} 20 | secondaryClassName={'bg-muted'} 21 | /> 22 | `} /> 23 | 24 | <Canvas of={Stories.BasicUsage} sourceState="none" /> 25 | 26 | ## Properties 27 | 28 | <Controls /> 29 | -------------------------------------------------------------------------------- /packages/1ui/src/components/ProgressBar/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ProgressBar' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/ProgressCard/ProgressCard.mdx: -------------------------------------------------------------------------------- 1 | import { Canvas, Controls, Meta, Source, Title } from '@storybook/blocks' 2 | 3 | import * as Stories from './ProgressCard.stories' 4 | 5 | <Meta of={Stories} /> 6 | 7 | <Title /> 8 | 9 | #### Generic progress card banner display 10 | 11 | <Source 12 | dark 13 | language="tsx" 14 | code={` 15 | import { ProgressCard } from '@0xintuition/1ui' 16 | 17 | <ProgressCard numberTotal={10} numberCompleted={5} /> 18 | `} /> 19 | 20 | <Canvas of={Stories.BasicUsage} sourceState="none" /> 21 | 22 | ## Properties 23 | 24 | <Controls /> 25 | -------------------------------------------------------------------------------- /packages/1ui/src/components/ProgressCard/ProgressCard.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react' 2 | 3 | import { ProgressCard } from './ProgressCard' 4 | 5 | const meta: Meta<typeof ProgressCard> = { 6 | title: 'Components/ProgressCard', 7 | component: ProgressCard, 8 | } 9 | 10 | export default meta 11 | 12 | type Story = StoryObj<typeof ProgressCard> 13 | 14 | export const BasicUsage: Story = { 15 | args: { 16 | numberTotal: 10, 17 | numberCompleted: 5, 18 | }, 19 | render: (args) => ( 20 | <div className="w-[600px]"> 21 | <ProgressCard {...args} /> 22 | </div> 23 | ), 24 | } 25 | -------------------------------------------------------------------------------- /packages/1ui/src/components/ProgressCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ProgressCard' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/QuestHeaderCard/QuestHeaderCard.mdx: -------------------------------------------------------------------------------- 1 | import { Canvas, Controls, Meta, Source, Title } from '@storybook/blocks' 2 | 3 | import * as Stories from './QuestHeaderCard.stories' 4 | 5 | <Meta of={Stories} /> 6 | 7 | <Title /> 8 | 9 | #### A card to show quest data to a user. 10 | 11 | <Source 12 | dark 13 | language="tsx" 14 | code={` 15 | import { QuestHeaderCard } from '@0xintuition/1ui' 16 | 17 | <QuestHeaderCard 18 | title="Primitive Island" 19 | subtitle="Continue your journey." 20 | numberOfCompletedQuests={1} 21 | totalNumberOfQuests={10} 22 | onButtonClick={() => doSomething} 23 | /> 24 | `} /> 25 | 26 | <Canvas of={Stories.BasicUsage} sourceState="none" /> 27 | 28 | ## Properties 29 | 30 | <Controls /> 31 | -------------------------------------------------------------------------------- /packages/1ui/src/components/QuestHeaderCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from './QuestHeaderCard' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/RadioGroup/index.ts: -------------------------------------------------------------------------------- 1 | export * from './RadioGroup' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Resizable/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Resizable' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/ScrollArea/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ScrollArea' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/SegmentedControl/index.ts: -------------------------------------------------------------------------------- 1 | export * from './SegmentedControl' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Select/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Select' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Separator/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Separator' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/SidebarLayout/components/SidebarLayout.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from 'styles' 2 | 3 | import { useSidebarLayoutContext } from './SidebarLayoutProvider' 4 | 5 | export const SidebarLayout = ({ 6 | ...props 7 | }: React.HTMLAttributes<HTMLDivElement>) => { 8 | const { isMobileView, isCollapsed } = useSidebarLayoutContext() 9 | return ( 10 | <div 11 | className={cn( 12 | 'flex h-full w-full overflow-x-hidden', 13 | isMobileView && 'flex-col', 14 | isMobileView && !isCollapsed && 'overflow-hidden', 15 | )} 16 | {...props} 17 | ></div> 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /packages/1ui/src/components/SidebarLayout/components/SidebarLayoutNavBody.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from 'styles' 2 | 3 | import { useSidebarLayoutContext } from './SidebarLayoutProvider' 4 | 5 | export const SidebarLayoutNavBody = ({ 6 | className, 7 | ...props 8 | }: React.HTMLAttributes<HTMLDivElement>) => { 9 | const { isMobileView, isCollapsed } = useSidebarLayoutContext() 10 | return ( 11 | <div 12 | className={cn( 13 | 'h-full w-full p-2', 14 | isMobileView && 15 | 'fixed top-[3.45rem] left-0 right-0 bottom-0 bg-background overflow-none z-50 h-auto from-primary/10 to-primary/2 bg-gradient-to-b', 16 | isMobileView && isCollapsed && 'collapse', 17 | className, 18 | )} 19 | {...props} 20 | /> 21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /packages/1ui/src/components/SidebarLayout/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './SidebarLayoutProvider' 2 | export * from './SidebarLayout' 3 | export * from './SidebarLayoutNav' 4 | export * from './SidebarLayoutNavHeader' 5 | export * from './SidebarLayoutNavHeaderButton' 6 | export * from './SidebarLayoutContent' 7 | export * from './SidebarLayoutNavAvatar' 8 | export * from './SidebarLayoutNavBody' 9 | export * from './SidebarNavItem' 10 | -------------------------------------------------------------------------------- /packages/1ui/src/components/SidebarLayout/constants.ts: -------------------------------------------------------------------------------- 1 | export const SIDEBAR_LOCAL_STORAGE_VARIABLE = 'isSideBarCollapsed' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/SidebarLayout/index.ts: -------------------------------------------------------------------------------- 1 | export * from './components' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Skeleton/Skeleton.mdx: -------------------------------------------------------------------------------- 1 | import { Canvas, Controls, Meta, Source, Title } from '@storybook/blocks' 2 | 3 | import * as Stories from './Skeleton.stories' 4 | 5 | <Meta of={Stories} /> 6 | 7 | <Title /> 8 | 9 | #### Skeleton component for fallback UI 10 | 11 | <Source 12 | dark 13 | language="tsx" 14 | code={` 15 | import { Skeleton } from '@0xintuition/1ui' 16 | 17 | <Skeleton /> 18 | `} /> 19 | 20 | <Canvas of={Stories.BasicUsage} sourceState="none" /> 21 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Skeleton/Skeleton.spec.tsx: -------------------------------------------------------------------------------- 1 | import { render } from '@testing-library/react' 2 | 3 | import { Skeleton } from './Skeleton' 4 | 5 | describe('Skeleton', () => { 6 | it('should render appropriate element', () => { 7 | const { asFragment } = render(<Skeleton className="h-[1rem] w-20" />) 8 | expect(asFragment()).toMatchInlineSnapshot(` 9 | <DocumentFragment> 10 | <div 11 | class="animate-pulse rounded-md bg-muted h-[1rem] w-20" 12 | /> 13 | </DocumentFragment> 14 | `) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Skeleton/Skeleton.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react' 2 | 3 | import { Skeleton } from './Skeleton' 4 | 5 | const meta: Meta<typeof Skeleton> = { 6 | title: 'Components/Skeleton', 7 | component: Skeleton, 8 | } 9 | 10 | export default meta 11 | 12 | type Story = StoryObj<typeof Skeleton> 13 | 14 | export const BasicUsage: Story = { 15 | args: {}, 16 | render: (args) => <Skeleton {...args} />, 17 | } 18 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Skeleton/Skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from 'styles' 2 | 3 | export interface SkeletonProps {} 4 | 5 | function Skeleton({ 6 | className, 7 | ...props 8 | }: React.HTMLAttributes<HTMLDivElement>) { 9 | return ( 10 | <div 11 | className={cn('animate-pulse rounded-md bg-muted', className)} 12 | {...props} 13 | /> 14 | ) 15 | } 16 | 17 | export { Skeleton } 18 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Skeleton/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Skeleton' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/SocialLinks/index.ts: -------------------------------------------------------------------------------- 1 | export * from './SocialLinks' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/StakeButton/index.ts: -------------------------------------------------------------------------------- 1 | export * from './StakeButton' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/StakeTVL/index.ts: -------------------------------------------------------------------------------- 1 | export * from './StakeTVL' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/StakeholdersList/index.ts: -------------------------------------------------------------------------------- 1 | export * from './StakeholdersList' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Switch/Switch.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import type { Meta, StoryObj } from '@storybook/react' 4 | 5 | import { Switch } from '.' 6 | import { Label } from '..' 7 | 8 | const meta: Meta<typeof Switch> = { 9 | title: 'Components/Form Elements/Switch', 10 | component: Switch, 11 | } 12 | 13 | export default meta 14 | 15 | type Story = StoryObj<typeof Switch> 16 | 17 | export const BasicUsage: Story = { 18 | args: {}, 19 | render: (args) => ( 20 | <div className="flex items-center space-x-3"> 21 | <Switch id="airplane-mode" {...args} /> 22 | <Label htmlFor="airplane-mode">Airplane Mode</Label> 23 | </div> 24 | ), 25 | } 26 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Switch/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Switch' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Table/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Table' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Tabs/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Tabs' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Tag/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Tag' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Tags/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Tags' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/TagsListInput/index.ts: -------------------------------------------------------------------------------- 1 | export * from './TagsListInput' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Text/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Text' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Textarea/Textarea.mdx: -------------------------------------------------------------------------------- 1 | import { Canvas, Controls, Meta, Source, Title } from '@storybook/blocks' 2 | 3 | import { Button } from '..' 4 | 5 | import * as Stories from './Textarea.stories' 6 | 7 | <Meta of={Stories} /> 8 | 9 | <Title /> 10 | 11 | #### Displays a form textarea or a component that looks like a textarea. 12 | 13 | <Source 14 | dark 15 | language="tsx" 16 | code={` 17 | import { Textarea } from '@0xintuition/1ui' 18 | 19 | <Textarea /> 20 | `} /> 21 | 22 | <Canvas of={Stories.BasicUsage} sourceState="none" /> 23 | 24 | ## Properties 25 | 26 | <Controls /> 27 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Textarea/Textarea.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import type { Meta, StoryObj } from '@storybook/react' 4 | 5 | import { Textarea } from './Textarea' 6 | 7 | const meta: Meta<typeof Textarea> = { 8 | title: 'Components/Form Elements/Textarea', 9 | component: Textarea, 10 | argTypes: { 11 | placeholder: { 12 | description: 'Placeholder text', 13 | table: { 14 | type: { summary: 'string' }, 15 | }, 16 | control: 'text', 17 | }, 18 | }, 19 | } 20 | 21 | export default meta 22 | 23 | type Story = StoryObj<typeof Textarea> 24 | 25 | export const BasicUsage: Story = { 26 | args: { placeholder: '' }, 27 | render: (args) => <Textarea {...args} className="w-[400px]" />, 28 | } 29 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Textarea/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Textarea' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Toaster/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Toaster' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Tooltip/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Tooltip' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/TransactionStatusCard/TransactionStatusCard.mdx: -------------------------------------------------------------------------------- 1 | import { Canvas, Controls, Meta, Source, Title } from '@storybook/blocks' 2 | 3 | import * as Stories from './TransactionStatusCard.stories' 4 | 5 | <Meta of={Stories} /> 6 | 7 | <Title /> 8 | 9 | #### Displays a card with an icon and label per transaction status. 10 | 11 | <Source 12 | dark 13 | language="tsx" 14 | code={` 15 | import { TransactionStatusCard } from '@0xintuition/1ui' 16 | 17 | <TransactionStatusCard status="awaiting" /> 18 | `} /> 19 | 20 | <Canvas of={Stories.BasicUsage} sourceState="none" /> 21 | 22 | ## Properties 23 | 24 | <Controls /> 25 | -------------------------------------------------------------------------------- /packages/1ui/src/components/TransactionStatusCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from './TransactionStatusCard' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/TransactionStatusIndicator/TransactionStatusIndicator.mdx: -------------------------------------------------------------------------------- 1 | import { Canvas, Controls, Meta, Source, Title } from '@storybook/blocks' 2 | 3 | import * as Stories from './TransactionStatusIndicator.stories' 4 | 5 | <Meta of={Stories} /> 6 | 7 | <Title /> 8 | 9 | #### Displays an icon and label per transaction status. 10 | 11 | <Source 12 | dark 13 | language="tsx" 14 | code={` 15 | import { TransactionStatusIndicator } from '@0xintuition/1ui' 16 | 17 | <TransactionStatusIndicator status="awaiting" /> 18 | `} /> 19 | 20 | <Canvas of={Stories.BasicUsage} sourceState="none" /> 21 | 22 | ## Properties 23 | 24 | <Controls /> 25 | -------------------------------------------------------------------------------- /packages/1ui/src/components/TransactionStatusIndicator/index.ts: -------------------------------------------------------------------------------- 1 | export * from './TransactionStatusIndicator' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/Trunctacular/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Trunctacular' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/components/ValueDisplay/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ValueDisplay' 2 | -------------------------------------------------------------------------------- /packages/1ui/src/docs/introduction.mdx: -------------------------------------------------------------------------------- 1 | import { Meta, Source } from '@storybook/blocks' 2 | 3 | <Meta title="Documentation/Introduction" /> 4 | 5 | # Introduction 6 | 7 | 1ui is a web3-enabled [React](https://react.dev/) component library by Intuition Systems. 8 | 9 | ## Usage 10 | 11 | <Source dark language="bash" code={`pnpm install @0xintuition/1ui`} /> 12 | 13 | <Source dark language="bash" code={`npm install @0xintuition/1ui`} /> 14 | 15 | <Source dark language="bash" code={`yarn add @0xintuition/1ui`} /> 16 | -------------------------------------------------------------------------------- /packages/1ui/src/index.d.ts: -------------------------------------------------------------------------------- 1 | import './styles/globals.css' 2 | 3 | export * from './styles' 4 | export * from './components' 5 | export * from './utils' 6 | export * from './types' 7 | -------------------------------------------------------------------------------- /packages/1ui/src/index.ts: -------------------------------------------------------------------------------- 1 | import './styles/globals.css' 2 | 3 | export * from './styles' 4 | export * from './components' 5 | export * from './utils' 6 | export * from './types' 7 | -------------------------------------------------------------------------------- /packages/1ui/src/styles/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | ::-webkit-scrollbar { 6 | @apply w-2; 7 | @apply h-2; 8 | } 9 | 10 | ::-webkit-scrollbar-track { 11 | @apply bg-primary/10; 12 | @apply rounded-sm; 13 | } 14 | 15 | ::-webkit-scrollbar-thumb { 16 | @apply bg-primary/20; 17 | @apply rounded-sm; 18 | } 19 | 20 | ::-webkit-scrollbar-thumb:hover { 21 | @apply bg-primary/40; 22 | } 23 | -------------------------------------------------------------------------------- /packages/1ui/src/styles/index.ts: -------------------------------------------------------------------------------- 1 | // export theme-plugin , theme-preset, hexToHSL, themes 2 | 3 | export * from './theme-plugin' 4 | export * from './utils' 5 | export * from './palette' 6 | export { default as themePreset } from './theme-preset' 7 | -------------------------------------------------------------------------------- /packages/1ui/src/styles/theme-preset.ts: -------------------------------------------------------------------------------- 1 | import containerQueries from '@tailwindcss/container-queries' 2 | import type { Config } from 'tailwindcss' 3 | import animatePlugin from 'tailwindcss-animate' 4 | 5 | import { themePlugin } from './theme-plugin' 6 | 7 | export default { 8 | darkMode: ['class'], 9 | content: [ 10 | './components/**/*.{ts,tsx}', // Include all TypeScript and TSX files in components 11 | './components/**/*.{ts,tsx}', // Include all TypeScript and TSX files in the ui directory 12 | './**/*.tsx', // Include all TSX files in the entire package 13 | './index.ts', // Include the index file if it's used for exports 14 | ], 15 | plugins: [themePlugin, animatePlugin, containerQueries], 16 | } satisfies Config 17 | -------------------------------------------------------------------------------- /packages/1ui/src/styles/utils.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from 'clsx' 2 | import { twMerge } from 'tailwind-merge' 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | 8 | export function colorMix(color: string, opacity?: number) { 9 | return `color-mix(in srgb, var(--${color}) calc(${opacity || '<alpha-value>'} * 100%), transparent)` 10 | } 11 | 12 | export enum Theme { 13 | DARK = 'dark', 14 | LIGHT = 'light', 15 | SYSTEM = 'system', 16 | } 17 | 18 | export const themesList: Array<Theme> = Object.values(Theme) 19 | 20 | export function isTheme(value: unknown): value is Theme { 21 | return typeof value === 'string' && themesList.includes(value as Theme) 22 | } 23 | -------------------------------------------------------------------------------- /packages/1ui/src/types/currency.ts: -------------------------------------------------------------------------------- 1 | export const Currency = { 2 | ETH: 'ETH', 3 | } as const 4 | 5 | export type CurrencyType = (typeof Currency)[keyof typeof Currency] 6 | -------------------------------------------------------------------------------- /packages/1ui/src/types/general.ts: -------------------------------------------------------------------------------- 1 | export const Identity = { 2 | user: 'user', 3 | nonUser: 'non-user', 4 | } as const 5 | export type IdentityType = (typeof Identity)[keyof typeof Identity] 6 | 7 | export const ClaimPosition = { 8 | claimFor: 'for', 9 | claimAgainst: 'against', 10 | } as const 11 | export type ClaimPositionType = 12 | (typeof ClaimPosition)[keyof typeof ClaimPosition] 13 | -------------------------------------------------------------------------------- /packages/1ui/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './currency' 2 | export * from './general' 3 | export * from './quest' 4 | export * from './transactions' 5 | -------------------------------------------------------------------------------- /packages/1ui/src/types/quest.ts: -------------------------------------------------------------------------------- 1 | export const QuestStatus = { 2 | notStarted: 'not-started', 3 | inProgress: 'in-progress', 4 | claimable: 'claimable', 5 | completed: 'completed', 6 | disabled: 'disabled', 7 | } as const 8 | 9 | export type QuestStatusType = (typeof QuestStatus)[keyof typeof QuestStatus] 10 | 11 | export const QuestCriteriaStatus = { 12 | notStarted: 'not-started', 13 | partiallyFulfilled: 'partially-fulfilled', 14 | fulfilled: 'fulfilled', 15 | } as const 16 | 17 | export type QuestCriteriaStatusType = 18 | (typeof QuestCriteriaStatus)[keyof typeof QuestCriteriaStatus] 19 | 20 | export type QuestCriteriaType = { 21 | status: QuestCriteriaStatusType 22 | criteria: string 23 | } 24 | -------------------------------------------------------------------------------- /packages/1ui/src/utils/date.ts: -------------------------------------------------------------------------------- 1 | // TODO: allow this to accept a format string 2 | export const formatDate = (timestamp: string): string => { 3 | return new Intl.DateTimeFormat('en-US', { 4 | year: 'numeric', 5 | month: 'long', 6 | day: 'numeric', 7 | }).format(new Date(timestamp)) 8 | } 9 | -------------------------------------------------------------------------------- /packages/1ui/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './date' 2 | export * from './number' 3 | export * from './wallet' 4 | export * from './progress' 5 | -------------------------------------------------------------------------------- /packages/1ui/src/utils/number.ts: -------------------------------------------------------------------------------- 1 | // Utility function to format large numbers 2 | export const formatNumber = (value: number): string => { 3 | if (value >= 1000000) { 4 | const millions = value / 1000000 5 | return millions >= 100 6 | ? `${Math.round(millions)}M` 7 | : `${millions.toFixed(1).replace(/\.?0+$/, '')}M` 8 | } else if (value >= 1000) { 9 | const thousands = value / 1000 10 | return thousands >= 100 11 | ? `${Math.round(thousands)}K` 12 | : `${thousands.toFixed(1).replace(/\.?0+$/, '')}K` 13 | } 14 | return value.toString() 15 | } 16 | -------------------------------------------------------------------------------- /packages/1ui/src/utils/progress.ts: -------------------------------------------------------------------------------- 1 | export function getProgressPercentage( 2 | numberCompleted: number, 3 | numberTotal: number, 4 | ) { 5 | return numberTotal > 0 ? Math.floor((numberCompleted / numberTotal) * 100) : 0 6 | } 7 | -------------------------------------------------------------------------------- /packages/1ui/src/utils/wallet.spec.ts: -------------------------------------------------------------------------------- 1 | import { formatWalletAddress } from './wallet' 2 | 3 | describe('formatWalletAddress', () => { 4 | it('should format did address correctly', () => { 5 | const address = 'did:0x1234567890abcdef1234567890abcdef12345678' 6 | expect(formatWalletAddress(address)).toBe('did:0x1234...5678') 7 | }) 8 | 9 | it('should format eth address correctly', () => { 10 | const address = '0x1234567890abcdef1234567890abcdef12345678' 11 | expect(formatWalletAddress(address)).toBe('0x1234...5678') 12 | }) 13 | 14 | it('should return ENS address as is', () => { 15 | const address = 'someperson.eth' 16 | expect(formatWalletAddress(address)).toBe(address) 17 | }) 18 | }) 19 | -------------------------------------------------------------------------------- /packages/1ui/src/utils/wallet.ts: -------------------------------------------------------------------------------- 1 | // Utility function to format wallet address 2 | export const formatWalletAddress = (address: string): string => { 3 | if (address) { 4 | if (address.startsWith('did:')) { 5 | const ethAddress = address.slice(4) // Remove 'did:' prefix 6 | return `did:${ethAddress.slice(0, 6)}...${ethAddress.slice(-4)}` 7 | } else if (address.endsWith('.eth')) { 8 | return address 9 | } 10 | return `${address.slice(0, 6)}...${address.slice(-4)}` 11 | } 12 | return address 13 | } 14 | -------------------------------------------------------------------------------- /packages/1ui/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import { themePreset } from './src/styles' 2 | 3 | module.exports = { 4 | presets: [themePreset], 5 | content: ['./src/**/*.{js,jsx,ts,tsx}'], 6 | theme: { 7 | extend: {}, 8 | }, 9 | plugins: [], 10 | } 11 | -------------------------------------------------------------------------------- /packages/1ui/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "jsx": "react-jsx", 5 | "baseUrl": "./src", 6 | "outDir": "../../dist/packages/1ui", 7 | "composite": true, 8 | "moduleResolution": "bundler", 9 | "types": ["jest", "node", "vitest"] 10 | }, 11 | "include": ["src"] 12 | } 13 | -------------------------------------------------------------------------------- /packages/1ui/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "types": ["node", "vite/client"] 5 | }, 6 | "exclude": [ 7 | "**/*.spec.ts", 8 | "**/*.test.ts", 9 | "**/*.spec.tsx", 10 | "**/*.test.tsx", 11 | "**/*.spec.js", 12 | "**/*.test.js", 13 | "**/*.spec.jsx", 14 | "**/*.test.jsx" 15 | ], 16 | "include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"] 17 | } 18 | -------------------------------------------------------------------------------- /packages/1ui/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "types": ["jest", "node"] 6 | }, 7 | "include": [ 8 | "jest.config.ts", 9 | "src/**/*.test.ts", 10 | "src/**/*.spec.ts", 11 | "src/**/*.test.tsx", 12 | "src/**/*.spec.tsx", 13 | "src/**/*.test.js", 14 | "src/**/*.spec.js", 15 | "src/**/*.test.jsx", 16 | "src/**/*.spec.jsx", 17 | "src/**/*.d.ts" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /packages/1ui/tsconfig.typecheck.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "composite": false, 5 | "declaration": true, 6 | "emitDeclarationOnly": false, 7 | "types": ["node"], 8 | "typeRoots": ["./types.d.ts", "../../node_modules/@types"] 9 | }, 10 | "include": ["src/**/*", ".storybook/**/*", "**/*.mdx", "types.d.ts"], 11 | "exclude": ["**/*.spec.ts", "**/*.spec.tsx", "**/*.test.ts", "**/*.test.tsx"] 12 | } 13 | -------------------------------------------------------------------------------- /packages/1ui/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup' 2 | 3 | export default defineConfig({ 4 | entry: ['src/index.ts'], 5 | treeshake: true, 6 | sourcemap: 'inline', 7 | minify: true, 8 | clean: true, 9 | dts: true, 10 | splitting: false, 11 | format: ['cjs', 'esm'], 12 | external: ['react'], 13 | injectStyle: true, 14 | }) 15 | -------------------------------------------------------------------------------- /packages/1ui/types.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.mdx' { 2 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 3 | let MDXComponent: (props: any) => JSX.Element 4 | export default MDXComponent 5 | } 6 | -------------------------------------------------------------------------------- /packages/1ui/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import tsconfigPaths from 'vite-tsconfig-paths' 2 | import { 3 | configDefaults, 4 | defineConfig, 5 | mergeConfig, 6 | type UserConfig, 7 | } from 'vitest/config' 8 | 9 | import viteConfig from './.storybook/vite.config' 10 | 11 | const config = mergeConfig( 12 | viteConfig, 13 | defineConfig({ 14 | test: { 15 | ...configDefaults, 16 | globals: true, 17 | environment: 'jsdom', 18 | setupFiles: './vitest.setup.ts', 19 | }, 20 | plugins: [tsconfigPaths()], 21 | }) as UserConfig, 22 | ) 23 | 24 | export default config 25 | -------------------------------------------------------------------------------- /packages/1ui/vitest.setup.ts: -------------------------------------------------------------------------------- 1 | import * as matchers from '@testing-library/jest-dom/matchers' 2 | import { cleanup } from '@testing-library/react' 3 | import { afterEach, expect } from 'vitest' 4 | 5 | expect.extend(matchers) 6 | 7 | afterEach(() => { 8 | cleanup() 9 | }) 10 | -------------------------------------------------------------------------------- /packages/api/.env.example: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/packages/api/.env.example -------------------------------------------------------------------------------- /packages/api/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.base.cjs'], 3 | ignorePatterns: ['core/**/*'], 4 | env: { 5 | node: true, 6 | jest: true, 7 | }, 8 | overrides: [ 9 | { 10 | files: ['*.ts', '*.tsx', '*.js', '*.jsx'], 11 | rules: {}, 12 | }, 13 | { 14 | files: ['*.ts', '*.tsx'], 15 | rules: {}, 16 | }, 17 | { 18 | files: ['*.js', '*.jsx'], 19 | rules: {}, 20 | }, 21 | ], 22 | } 23 | -------------------------------------------------------------------------------- /packages/api/.gitignore: -------------------------------------------------------------------------------- 1 | *.log -------------------------------------------------------------------------------- /packages/api/openapi-ts.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is intended to set all configs for OpenAPI Codegen 3 | * DO NOT edit any files in the `src/api-client` folder directly - it is generated using these settings 4 | */ 5 | import { defineConfig } from '@hey-api/openapi-ts' 6 | 7 | const openApiUrl = process.env.API_URL || 'https://dev.api.intuition.systems' 8 | 9 | export default defineConfig({ 10 | client: 'fetch', 11 | input: `${openApiUrl}/api-docs/openapi.json`, 12 | output: { 13 | format: 'prettier', 14 | path: './src/api-client', 15 | }, 16 | exportCore: true, 17 | types: { 18 | enums: 'javascript', 19 | }, 20 | schemas: false, 21 | }) 22 | -------------------------------------------------------------------------------- /packages/api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@0xintuition/api", 3 | "version": "0.2.0", 4 | "description": "API", 5 | "main": "src/index.js", 6 | "exports": { 7 | ".": "./src/index.js" 8 | }, 9 | "types": "src/index.d.ts", 10 | "scripts": { 11 | "lint:fix": "pnpm lint --fix", 12 | "codegen": "openapi-ts" 13 | }, 14 | "files": [ 15 | "dist/**/*", 16 | "src/**/*", 17 | "README.md", 18 | "LICENSE" 19 | ], 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/0xIntuition/intuition-ts", 23 | "directory": "packages/api" 24 | }, 25 | "devDependencies": { 26 | "prettier": "^3.2.5", 27 | "typescript": "^5.4.5", 28 | "vite": "^5.2.11", 29 | "vitest": "^1.3.1" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/api/src/api-client/core/ApiRequestOptions.ts: -------------------------------------------------------------------------------- 1 | export type ApiRequestOptions = { 2 | readonly method: 3 | | 'GET' 4 | | 'PUT' 5 | | 'POST' 6 | | 'DELETE' 7 | | 'OPTIONS' 8 | | 'HEAD' 9 | | 'PATCH' 10 | readonly url: string 11 | readonly path?: Record<string, unknown> 12 | readonly cookies?: Record<string, unknown> 13 | readonly headers?: Record<string, unknown> 14 | readonly query?: Record<string, unknown> 15 | readonly formData?: Record<string, unknown> 16 | readonly body?: any 17 | readonly mediaType?: string 18 | readonly responseHeader?: string 19 | readonly errors?: Record<number, string> 20 | } 21 | -------------------------------------------------------------------------------- /packages/api/src/api-client/core/ApiResult.ts: -------------------------------------------------------------------------------- 1 | export type ApiResult<TData = any> = { 2 | readonly body: TData 3 | readonly ok: boolean 4 | readonly status: number 5 | readonly statusText: string 6 | readonly url: string 7 | } 8 | -------------------------------------------------------------------------------- /packages/api/src/api-client/index.ts: -------------------------------------------------------------------------------- 1 | // This file is auto-generated by @hey-api/openapi-ts 2 | export { ApiError } from './core/ApiError' 3 | export { CancelablePromise, CancelError } from './core/CancelablePromise' 4 | export { OpenAPI, type OpenAPIConfig } from './core/OpenAPI' 5 | export * from './services.gen' 6 | export * from './types.gen' 7 | -------------------------------------------------------------------------------- /packages/api/src/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './api-client' 2 | -------------------------------------------------------------------------------- /packages/api/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './api-client' 2 | -------------------------------------------------------------------------------- /packages/api/tests/sample.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest' 2 | 3 | // Sample comment to see version change 4 | describe('Sample suite', () => { 5 | it('is a sample test', () => { 6 | expect(8).toEqual(8) 7 | }) 8 | }) 9 | -------------------------------------------------------------------------------- /packages/api/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "include": ["src/**/*.ts"], 4 | "compilerOptions": { 5 | "baseUrl": "./src", 6 | "rootDir": "src", 7 | "outDir": "../../dist/packages/api" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/api/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /packages/api/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitest/config' 2 | 3 | // https://vitest.dev/config/ 4 | export default defineConfig({ 5 | test: {}, 6 | }) 7 | -------------------------------------------------------------------------------- /packages/graphql/.env.example: -------------------------------------------------------------------------------- 1 | HASURA_PROJECT_ENDPOINT= 2 | HASURA_GRAPHQL_ADMIN_SECRET= -------------------------------------------------------------------------------- /packages/graphql/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.base.cjs'], 3 | env: { 4 | node: true, 5 | jest: true, 6 | }, 7 | overrides: [ 8 | { 9 | files: ['*.ts', '*.tsx', '*.js', '*.jsx'], 10 | rules: {}, 11 | }, 12 | { 13 | files: ['*.ts', '*.tsx'], 14 | rules: {}, 15 | }, 16 | { 17 | files: ['*.js', '*.jsx'], 18 | rules: {}, 19 | }, 20 | ], 21 | ignorePatterns: ['generated'], 22 | } 23 | -------------------------------------------------------------------------------- /packages/graphql/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/packages/graphql/.gitignore -------------------------------------------------------------------------------- /packages/graphql/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.2.1 (2024-06-11) 2 | 3 | This was a version bump only for @0xintuition/graphql to align it with other projects, there were no code changes. 4 | 5 | ## 0.2.0 (2024-06-04) 6 | 7 | ### Features 8 | 9 | - **1ui:** update tsconfig styles path to ui-styles 10 | 11 | ### Fixes 12 | 13 | - **1ui:** remove build command 14 | 15 | - **1ui:** modify build command 16 | 17 | - **1ui:** workspace root remove 18 | 19 | ### ❤️ Thank You 20 | 21 | - Alexander Mann 22 | - Rahul 23 | 24 | ## 0.1.0 (2024-05-28) 25 | 26 | Initial release! 27 | 28 | ### ❤️ Thank You 29 | 30 | - 0xjojikun 31 | - alexander-mann 32 | - Rahul 33 | -------------------------------------------------------------------------------- /packages/graphql/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@0xintuition/graphql", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "packages/graphql/src", 5 | "projectType": "library", 6 | "tags": [], 7 | "targets": { 8 | "lint": { 9 | "executor": "@nx/eslint:lint", 10 | "options": { 11 | "lintFilePatterns": ["packages/graphql/**/*.{ts,tsx,js,jsx}"] 12 | } 13 | }, 14 | "test": { 15 | "executor": "@nx/vite:test", 16 | "options": { 17 | "config": "packages/graphql/vitest.config.ts" 18 | } 19 | }, 20 | "nx-release-publish": { 21 | "dependsOn": ["build"], 22 | "options": { 23 | "packageRoot": "dist/{projectRoot}" 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/graphql/src/constants.ts: -------------------------------------------------------------------------------- 1 | export const API_URL_LOCAL = 'http://localhost:8080/v1/graphql' 2 | export const API_URL_DEV = 3 | 'https://prod.base-sepolia.intuition-api.com/v1/graphql' 4 | export const API_URL_PROD = 'https://prod.base.intuition-api.com/v1/graphql' 5 | -------------------------------------------------------------------------------- /packages/graphql/src/fragments/deposit.graphql: -------------------------------------------------------------------------------- 1 | fragment DepositEventFragment on events { 2 | deposit { 3 | vault_id 4 | sender_assets_after_total_fees 5 | shares_for_receiver 6 | receiver { 7 | id 8 | } 9 | sender { 10 | id 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/graphql/src/fragments/redemption.graphql: -------------------------------------------------------------------------------- 1 | fragment RedemptionEventFragment on events { 2 | redemption { 3 | vault_id 4 | receiver_id 5 | shares_redeemed_by_sender 6 | assets_for_receiver 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/graphql/src/fragments/stat.graphql: -------------------------------------------------------------------------------- 1 | fragment StatDetails on stats { 2 | contract_balance 3 | total_accounts 4 | total_fees 5 | total_atoms 6 | total_triples 7 | total_positions 8 | total_signals 9 | } 10 | -------------------------------------------------------------------------------- /packages/graphql/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './generated/index' 2 | export * from './constants' 3 | export { 4 | configureClient, 5 | fetcher, 6 | createServerClient, 7 | type ClientConfig, 8 | } from './client' 9 | -------------------------------------------------------------------------------- /packages/graphql/src/mutations/pin-thing.graphql: -------------------------------------------------------------------------------- 1 | mutation pinThing( 2 | $name: String! 3 | $description: String 4 | $image: String 5 | $url: String 6 | ) { 7 | pinThing( 8 | thing: { description: $description, image: $image, name: $name, url: $url } 9 | ) { 10 | uri 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/graphql/src/queries/claims.graphql: -------------------------------------------------------------------------------- 1 | query GetClaimsByAddress($address: String) { 2 | claims_aggregate(where: { account_id: { _eq: $address } }) { 3 | aggregate { 4 | count 5 | } 6 | nodes { 7 | account { 8 | label 9 | } 10 | triple { 11 | subject { 12 | label 13 | } 14 | predicate { 15 | label 16 | } 17 | object { 18 | label 19 | } 20 | } 21 | id 22 | vault_id 23 | counter_vault_id 24 | shares 25 | counter_shares 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/graphql/src/queries/points.graphql: -------------------------------------------------------------------------------- 1 | query GetFeeTransfers($address: String!, $cutoff_timestamp: bigint) { 2 | before_cutoff: fee_transfers_aggregate( 3 | where: { 4 | block_timestamp: { _lte: $cutoff_timestamp } 5 | sender_id: { _eq: $address } 6 | } 7 | ) { 8 | aggregate { 9 | sum { 10 | amount 11 | } 12 | } 13 | } 14 | 15 | after_cutoff: fee_transfers_aggregate( 16 | where: { 17 | block_timestamp: { _gt: $cutoff_timestamp } 18 | sender_id: { _eq: $address } 19 | } 20 | ) { 21 | aggregate { 22 | sum { 23 | amount 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/graphql/src/queries/stats.graphql: -------------------------------------------------------------------------------- 1 | query GetStats { 2 | stats { 3 | ...StatDetails 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/graphql/src/queries/tags.graphql: -------------------------------------------------------------------------------- 1 | query GetTags($subjectId: numeric!, $predicateId: numeric!) { 2 | triples( 3 | where: { 4 | _and: [ 5 | { subject_id: { _eq: $subjectId } } 6 | { predicate_id: { _eq: $predicateId } } 7 | ] 8 | } 9 | ) { 10 | ...TripleMetadata 11 | } 12 | } 13 | 14 | query GetTagsCustom($where: triples_bool_exp) { 15 | triples(where: $where) { 16 | ...TripleMetadata 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/graphql/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "include": ["src/**/*.ts"], 4 | "exclude": [], 5 | "compilerOptions": { 6 | "moduleResolution": "bundler", 7 | "baseUrl": "./src", 8 | "rootDir": "src", 9 | "outDir": "../../dist/packages/graphql" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/graphql/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /packages/graphql/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup' 2 | 3 | export default defineConfig({ 4 | entry: ['src/index.ts'], 5 | format: ['cjs', 'esm'], 6 | dts: true, 7 | splitting: false, 8 | sourcemap: true, 9 | clean: true, 10 | external: ['react', 'graphql'], 11 | treeshake: true, 12 | noExternal: ['./src/generated/**'], 13 | }) 14 | -------------------------------------------------------------------------------- /packages/graphql/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitest/config' 2 | 3 | // https://vitest.dev/config/ 4 | export default defineConfig({ 5 | test: {}, 6 | }) 7 | -------------------------------------------------------------------------------- /packages/protocol/.env.example: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/packages/protocol/.env.example -------------------------------------------------------------------------------- /packages/protocol/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.base.cjs'], 3 | env: { 4 | node: true, 5 | jest: true, 6 | }, 7 | overrides: [ 8 | { 9 | files: ['*.ts', '*.tsx', '*.js', '*.jsx'], 10 | rules: {}, 11 | }, 12 | { 13 | files: ['*.ts', '*.tsx'], 14 | rules: {}, 15 | }, 16 | { 17 | files: ['*.js', '*.jsx'], 18 | rules: {}, 19 | }, 20 | ], 21 | } 22 | -------------------------------------------------------------------------------- /packages/protocol/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/packages/protocol/.gitignore -------------------------------------------------------------------------------- /packages/protocol/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.1.2 (2024-06-04) 2 | 3 | ### Fixes 4 | 5 | - **1ui:** remove build command 6 | 7 | - **1ui:** modify build command 8 | 9 | - **1ui:** workspace root remove 10 | 11 | ### ❤️ Thank You 12 | 13 | - Rahul 14 | 15 | ## 0.1.0 (2024-05-28) 16 | 17 | Initial release! 18 | 19 | ### ❤️ Thank You 20 | 21 | - 0xjojikun 22 | - alexander-mann 23 | - Rahul 24 | -------------------------------------------------------------------------------- /packages/protocol/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to protocol 2 | -------------------------------------------------------------------------------- /packages/protocol/scripts/generate.mjs: -------------------------------------------------------------------------------- 1 | import fs from 'fs' 2 | 3 | import obj from './EthMultiVault.json' assert { type: 'json' } 4 | const abi = obj.abi 5 | const bytecode = obj.bytecode.object 6 | 7 | console.log('Generating abi.ts') 8 | fs.writeFileSync( 9 | './src/abi.ts', 10 | `export const abi = ${JSON.stringify(abi, null, 2)} as const;`, 11 | ) 12 | 13 | console.log('Generating bytecode.ts') 14 | fs.writeFileSync( 15 | './tests/bytecode.ts', 16 | `export const bytecode = '${bytecode}';`, 17 | ) 18 | 19 | console.log('Done') 20 | -------------------------------------------------------------------------------- /packages/protocol/src/deployments.ts: -------------------------------------------------------------------------------- 1 | import { Address } from 'viem' 2 | import { base, baseSepolia } from 'viem/chains' 3 | 4 | const deployments: Record<number, Address> = {} 5 | 6 | deployments[base.id] = '0x430BbF52503Bd4801E51182f4cB9f8F534225DE5' 7 | deployments[baseSepolia.id] = '0x1A6950807E33d5bC9975067e6D6b5Ea4cD661665' 8 | 9 | export { deployments } 10 | -------------------------------------------------------------------------------- /packages/protocol/src/index.ts: -------------------------------------------------------------------------------- 1 | export { Multivault } from './multivault' 2 | export { abi } from './abi' 3 | export { deployments } from './deployments' 4 | -------------------------------------------------------------------------------- /packages/protocol/tests/constants.ts: -------------------------------------------------------------------------------- 1 | // Test accounts 2 | export const ACCOUNTS = [ 3 | '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', 4 | '0x70997970C51812dc3A010C7d01b50e0d17dc79C8', 5 | '0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC', 6 | '0x90F79bf6EB2c4f870365E785982E1f101E93b906', 7 | '0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65', 8 | '0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc', 9 | '0x976EA74026E726554dB657fA54763abd0C3a0aa9', 10 | '0x14dC79964da2C08b23698B3D3cc7Ca32193d9955', 11 | '0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f', 12 | '0xa0Ee7A142d267C1f36714E4a8F75612F20a79720', 13 | ] as const 14 | 15 | // Named accounts 16 | export const [ALICE, BOB] = ACCOUNTS 17 | -------------------------------------------------------------------------------- /packages/protocol/tests/globalSetup.ts: -------------------------------------------------------------------------------- 1 | import { startProxy } from '@viem/anvil' 2 | 3 | export default async function () { 4 | return await startProxy({ 5 | port: 8545, // By default, the proxy will listen on port 8545. 6 | host: '::', // By default, the proxy will listen on all interfaces. 7 | options: { 8 | chainId: 123, 9 | }, 10 | }) 11 | } 12 | -------------------------------------------------------------------------------- /packages/protocol/tests/setup.ts: -------------------------------------------------------------------------------- 1 | import { fetchLogs } from '@viem/anvil' 2 | import { afterEach } from 'vitest' 3 | 4 | import { pool } from './utils.js' 5 | 6 | afterEach(async (context) => { 7 | context.onTestFailed(async () => { 8 | // If a test fails, you can fetch and print the logs of your anvil instance. 9 | const logs = await fetchLogs('http://localhost:8545', pool) 10 | // Only print the 20 most recent log messages. 11 | console.log(...logs.slice(-20)) 12 | }) 13 | }) 14 | -------------------------------------------------------------------------------- /packages/protocol/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "include": ["src/**/*.ts"], 4 | "exclude": [], 5 | "compilerOptions": { 6 | "rootDir": "src", 7 | "outDir": "../../dist/packages/protocol" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/protocol/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /packages/protocol/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup' 2 | 3 | export default defineConfig({ 4 | entry: ['src/index.ts'], 5 | format: ['cjs', 'esm'], 6 | dts: true, 7 | splitting: false, 8 | sourcemap: true, 9 | clean: true, 10 | }) 11 | -------------------------------------------------------------------------------- /packages/protocol/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitest/config' 2 | 3 | // https://vitest.dev/config/ 4 | export default defineConfig({ 5 | test: { 6 | globalSetup: ['./tests/globalSetup.ts'], 7 | setupFiles: ['./tests/setup.ts'], 8 | }, 9 | }) 10 | -------------------------------------------------------------------------------- /packages/sdk/.env.example: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/packages/sdk/.env.example -------------------------------------------------------------------------------- /packages/sdk/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.base.cjs'], 3 | env: { 4 | node: true, 5 | jest: true, 6 | }, 7 | overrides: [ 8 | { 9 | files: ['*.ts', '*.tsx', '*.js', '*.jsx'], 10 | rules: {}, 11 | }, 12 | { 13 | files: ['*.ts', '*.tsx'], 14 | rules: {}, 15 | }, 16 | { 17 | files: ['*.js', '*.jsx'], 18 | rules: {}, 19 | }, 20 | ], 21 | } 22 | -------------------------------------------------------------------------------- /packages/sdk/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/packages/sdk/.gitignore -------------------------------------------------------------------------------- /packages/sdk/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.2.1 (2024-06-11) 2 | 3 | This was a version bump only for @0xintuition/sdk to align it with other projects, there were no code changes. 4 | 5 | ## 0.2.0 (2024-06-04) 6 | 7 | ### Features 8 | 9 | - **1ui:** update tsconfig styles path to ui-styles 10 | 11 | ### Fixes 12 | 13 | - **1ui:** remove build command 14 | 15 | - **1ui:** modify build command 16 | 17 | - **1ui:** workspace root remove 18 | 19 | ### ❤️ Thank You 20 | 21 | - Alexander Mann 22 | - Rahul 23 | 24 | ## 0.1.0 (2024-05-28) 25 | 26 | Initial release! 27 | 28 | ### ❤️ Thank You 29 | 30 | - 0xjojikun 31 | - alexander-mann 32 | - Rahul 33 | -------------------------------------------------------------------------------- /packages/sdk/README.md: -------------------------------------------------------------------------------- 1 | # Intuition sdk 2 | 3 | This library consists of high level logic that combines both on-chain and off-chain 4 | 5 | ## Building 6 | 7 | Run `nx build @0xintuition/sdk` to build the library. 8 | 9 | ## Running unit tests 10 | 11 | Run `nx test @0xintuition/sdk` to execute the unit tests 12 | -------------------------------------------------------------------------------- /packages/sdk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@0xintuition/sdk", 3 | "version": "0.3.1", 4 | "description": "Backend SDK", 5 | "main": "src/index.js", 6 | "exports": { 7 | ".": "./src/index.js" 8 | }, 9 | "types": "src/index.d.ts", 10 | "scripts": { 11 | "lint:fix": "pnpm lint --fix" 12 | }, 13 | "files": [ 14 | "dist/**/*", 15 | "src/**/*", 16 | "README.md", 17 | "LICENSE" 18 | ], 19 | "repository": { 20 | "type": "git", 21 | "url": "https://github.com/0xIntuition/intuition-ts", 22 | "directory": "packages/sdk" 23 | }, 24 | "dependencies": {}, 25 | "devDependencies": { 26 | "typescript": "^5.4.5", 27 | "vite": "^5.2.11", 28 | "vitest": "^1.3.1" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/sdk/src/index.ts: -------------------------------------------------------------------------------- 1 | console.log('test') 2 | -------------------------------------------------------------------------------- /packages/sdk/tests/sample.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest' 2 | 3 | describe('Sample suite', () => { 4 | it('is a sample test', () => { 5 | expect(8).toEqual(8) 6 | }) 7 | }) 8 | -------------------------------------------------------------------------------- /packages/sdk/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "include": ["src/**/*.ts"], 4 | "exclude": [], 5 | "compilerOptions": { 6 | "outDir": "../../dist/packages/sdk" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/sdk/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /packages/sdk/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitest/config' 2 | 3 | // https://vitest.dev/config/ 4 | export default defineConfig({ 5 | test: {}, 6 | }) 7 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | # executable/launchable applications 3 | - 'apps/*' 4 | # all packages in subdirs of packages/ and components/ 5 | - 'packages/*' 6 | -------------------------------------------------------------------------------- /project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@0xintuition/intuition-ts", 3 | "$schema": "node_modules/nx/schemas/project-schema.json", 4 | "targets": { 5 | "local-registry": { 6 | "executor": "@nx/js:verdaccio", 7 | "options": { 8 | "port": 4873, 9 | "config": ".verdaccio/config.yml", 10 | "storage": "tmp/local-registry/storage" 11 | } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tools/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../.eslintrc.base.cjs'], 3 | ignorePatterns: ['!**/*'], 4 | overrides: [ 5 | { 6 | files: ['*.ts', '*.tsx', '*.js', '*.jsx'], 7 | rules: {}, 8 | }, 9 | { 10 | files: ['*.ts', '*.tsx'], 11 | rules: {}, 12 | }, 13 | { 14 | files: ['*.js', '*.jsx'], 15 | rules: {}, 16 | }, 17 | { 18 | files: ['*.json'], 19 | parser: 'jsonc-eslint-parser', 20 | rules: { 21 | '@nx/dependency-checks': 'error', 22 | }, 23 | }, 24 | { 25 | files: ['./package.json', './generators.json'], 26 | parser: 'jsonc-eslint-parser', 27 | rules: { 28 | '@nx/nx-plugin-checks': 'error', 29 | }, 30 | }, 31 | ], 32 | } 33 | -------------------------------------------------------------------------------- /tools/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/tools/.gitignore -------------------------------------------------------------------------------- /tools/README.md: -------------------------------------------------------------------------------- 1 | # automation-tools 2 | 3 | This library contains automation tools such as Generators and Executors to help speed up development. 4 | 5 | ## Running unit tests 6 | 7 | Run `nx test @0xintuition/automation-tools` to execute the unit tests via [Jest](https://jestjs.io). 8 | -------------------------------------------------------------------------------- /tools/generators.json: -------------------------------------------------------------------------------- 1 | { 2 | "generators": { 3 | "ui-component": { 4 | "factory": "./src/generators/ui-component/generator", 5 | "schema": "./src/generators/ui-component/schema.json", 6 | "description": "ui-component generator" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tools/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: '@0xintuition/automation-tools', 4 | preset: '../jest.preset.js', 5 | transform: { 6 | '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }], 7 | }, 8 | moduleFileExtensions: ['ts', 'js', 'html'], 9 | coverageDirectory: '../coverage/tools', 10 | } 11 | -------------------------------------------------------------------------------- /tools/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@0xintuition/automation-tools", 3 | "private": true, 4 | "dependencies": {}, 5 | "type": "commonjs", 6 | "main": "./src/index.js", 7 | "typings": "./src/index.d.ts", 8 | "generators": "./generators.json", 9 | "scripts": { 10 | "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .", 11 | "lint:fix": "pnpm lint --fix" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tools/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@0xintuition/automation-tools", 3 | "$schema": "../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "tools/src", 5 | "projectType": "library", 6 | "tags": [], 7 | "targets": { 8 | "lint": { 9 | "executor": "@nx/eslint:lint", 10 | "options": { 11 | "lintFilePatterns": ["tools/**/*.{ts,tsx,js,jsx}"] 12 | } 13 | }, 14 | "test": { 15 | "executor": "@nx/jest:jest", 16 | "options": { 17 | "jestConfig": "tools/jest.config.ts" 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tools/src/generators/ui-component/files/__name__.tsx.template: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | export interface <%= className %>Props {} 4 | 5 | const <%= className %> = ({ ...props }: <%= className %>Props) => { 6 | return <>{/* Implement UI here */}</> 7 | } 8 | 9 | export { <%= className %> } -------------------------------------------------------------------------------- /tools/src/generators/ui-component/files/index.ts.template: -------------------------------------------------------------------------------- 1 | export * from './<%= className %>'; -------------------------------------------------------------------------------- /tools/src/generators/ui-component/schema.d.ts: -------------------------------------------------------------------------------- 1 | export interface uiComponentGeneratorSchema { 2 | name: string 3 | } 4 | -------------------------------------------------------------------------------- /tools/src/generators/ui-component/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/schema", 3 | "$id": "uiComponentGenerator", 4 | "title": "", 5 | "type": "object", 6 | "properties": { 7 | "name": { 8 | "type": "string", 9 | "description": "", 10 | "$default": { 11 | "$source": "argv", 12 | "index": 0 13 | }, 14 | "x-prompt": "What would you like to name the component?" 15 | } 16 | }, 17 | "required": ["name"] 18 | } 19 | -------------------------------------------------------------------------------- /tools/src/index.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xIntuition/intuition-ts/2ce0021d4f8d88016f3ed0ff43beefc5e572d1c4/tools/src/index.ts -------------------------------------------------------------------------------- /tools/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "module": "commonjs" 5 | }, 6 | "files": [], 7 | "include": [], 8 | "references": [ 9 | { 10 | "path": "./tsconfig.lib.json" 11 | }, 12 | { 13 | "path": "./tsconfig.spec.json" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /tools/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "declaration": true, 5 | "types": ["node"] 6 | }, 7 | "include": ["src/**/*.ts"], 8 | "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /tools/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "types": ["jest", "node"] 6 | }, 7 | "include": [ 8 | "jest.config.ts", 9 | "src/**/*.test.ts", 10 | "src/**/*.spec.ts", 11 | "src/**/*.d.ts" 12 | ] 13 | } 14 | --------------------------------------------------------------------------------