├── .env.example
├── .eslintignore
├── .eslintrc.yml
├── .github
└── workflows
│ └── lint.yml_bkp
├── .gitignore
├── .unimportedrc.json
├── LICENSE.txt
├── README.md
├── codegen.yaml
├── next-env.d.ts
├── next.config.js
├── package-lock.json
├── package.json
├── public
├── Browser Mock.svg
├── chain_assets
│ ├── aave.svg
│ ├── apwine.svg
│ ├── biconomy.svg
│ ├── boba.svg
│ ├── celo.svg
│ ├── celo_token.svg
│ ├── cusd.svg
│ ├── dai.svg
│ ├── dollar.svg
│ ├── eth.svg
│ ├── flux.svg
│ ├── gnosis.svg
│ ├── inch.svg
│ ├── livepeer.svg
│ ├── matic.svg
│ ├── metis.svg
│ ├── ocean.svg
│ ├── perp.svg
│ ├── sUSD.svg
│ ├── snx.svg
│ ├── solana.png
│ ├── spruce.svg
│ ├── stackos.svg
│ ├── telos.svg
│ ├── toncoin.svg
│ ├── uma.svg
│ ├── uniswap.svg
│ ├── unlock.svg
│ ├── usdc.svg
│ ├── weth.svg
│ ├── wmatic.svg
│ ├── yearn.svg
│ └── zkp.svg
├── favicon.ico
├── favicon.png
├── favicon.svg
├── fonts
│ └── v2
│ │ └── NueHaas
│ │ ├── NHaasGroteskTXPro-55Rg.ttf
│ │ ├── NHaasGroteskTXPro-56It.ttf
│ │ ├── NHaasGroteskTXPro-65Md.ttf
│ │ ├── NHaasGroteskTXPro-66MdIt.ttf
│ │ ├── NHaasGroteskTXPro-75Bd.ttf
│ │ └── NHaasGroteskTXPro-76BdIt.ttf
├── privacypolicy.html
├── termsofservice.html
├── v2
│ ├── icons
│ │ ├── accept.svg
│ │ ├── add user.svg
│ │ ├── add.svg
│ │ ├── alert.svg
│ │ ├── arrow left.svg
│ │ ├── arrow right.svg
│ │ ├── bell.svg
│ │ ├── bitcoin.svg
│ │ ├── bold_button.svg
│ │ ├── calendar-color.svg
│ │ ├── calendar.svg
│ │ ├── call.svg
│ │ ├── celo.svg
│ │ ├── celo_safe.svg
│ │ ├── chat.svg
│ │ ├── check double.svg
│ │ ├── checkBox.svg
│ │ ├── checkbox circle.svg
│ │ ├── chevron right.svg
│ │ ├── close.svg
│ │ ├── copy.svg
│ │ ├── desktop.svg
│ │ ├── discord.svg
│ │ ├── discover.svg
│ │ ├── doc.svg
│ │ ├── dot.svg
│ │ ├── down.svg
│ │ ├── dropdown.svg
│ │ ├── embed.svg
│ │ ├── error warning.svg
│ │ ├── export-download.svg
│ │ ├── export.svg
│ │ ├── filter.svg
│ │ ├── gdrive.svg
│ │ ├── group.svg
│ │ ├── image add.svg
│ │ ├── import.svg
│ │ ├── iotex.svg
│ │ ├── italics_button.svg
│ │ ├── key.svg
│ │ ├── link.svg
│ │ ├── loader.svg
│ │ ├── mail.svg
│ │ ├── metamask.svg
│ │ ├── multisig.svg
│ │ ├── new tab.svg
│ │ ├── notVisible.svg
│ │ ├── ol_button.svg
│ │ ├── openmask.svg
│ │ ├── pencil.svg
│ │ ├── phantom.svg
│ │ ├── phone.svg
│ │ ├── pie chart.svg
│ │ ├── projectDetails.svg
│ │ ├── qb.svg
│ │ ├── qr-scan.svg
│ │ ├── questbook.svg
│ │ ├── question.svg
│ │ ├── realms.svg
│ │ ├── realms_logo.svg
│ │ ├── reject.svg
│ │ ├── resubmit.svg
│ │ ├── safe.svg
│ │ ├── safe_logo.svg
│ │ ├── search.svg
│ │ ├── settings.svg
│ │ ├── share forward.svg
│ │ ├── share-box.svg
│ │ ├── share.svg
│ │ ├── swap.svg
│ │ ├── telegram.svg
│ │ ├── thumbs up.svg
│ │ ├── time.svg
│ │ ├── tonkey.svg
│ │ ├── twitter.svg
│ │ ├── ul_button.svg
│ │ ├── underline_button.svg
│ │ ├── unhappy.svg
│ │ ├── visible.svg
│ │ ├── wallet-connect.svg
│ │ └── wallet.svg
│ └── images
│ │ ├── Rectangle 6.svg
│ │ ├── banner.png
│ │ ├── builders.svg
│ │ ├── cover-image.svg
│ │ ├── default_profile_picture.png
│ │ ├── empty-body.svg
│ │ ├── profile-bg.png
│ │ ├── qb-discussion.svg
│ │ ├── qb-only-logo.svg
│ │ ├── reclaim_bg.svg
│ │ ├── safeguard.svg
│ │ └── tonBanner.png
└── workbox-7c2a5a06.js
├── sentry.client.config.ts
├── sentry.properties
├── sentry.server.config.ts
├── src
├── constants
│ ├── Networks.tsx
│ ├── addresses.ts
│ ├── applicantDetailsList.tsx
│ ├── chains.ts
│ ├── config.json
│ ├── safesEndpoints.json
│ ├── safesEndpointsTest.json
│ ├── safesSupported.json
│ ├── seo.tsx
│ └── strings.json
├── contexts
│ └── safeContext.tsx
├── contracts
│ └── abi
│ │ ├── ApplicationRegistryAbi.json
│ │ ├── ApplicationReviewRegistryAbi.json
│ │ ├── CommunicationAbi.json
│ │ ├── GrantAbi.json
│ │ ├── GrantFactoryAbi.json
│ │ ├── ReviewerGuard.json
│ │ ├── UtilityRegistryAbi.json
│ │ ├── WalletAbi.json
│ │ └── WorkspaceRegistryAbi.json
├── generated
│ ├── SupportedChainId.ts
│ ├── chainInfo.json
│ ├── contracts
│ │ ├── ApplicationRegistryAbi.ts
│ │ ├── ApplicationReviewRegistryAbi.ts
│ │ ├── CommunicationAbi.ts
│ │ ├── ERC20.ts
│ │ ├── ERC20Proxy.ts
│ │ ├── GrantAbi.ts
│ │ ├── GrantFactoryAbi.ts
│ │ ├── ReviewerGuard.ts
│ │ ├── UtilityRegistryAbi.ts
│ │ ├── WorkspaceRegistryAbi.ts
│ │ ├── common.ts
│ │ ├── factories
│ │ │ ├── ApplicationRegistryAbi__factory.ts
│ │ │ ├── ApplicationReviewRegistryAbi__factory.ts
│ │ │ ├── CommunicationAbi__factory.ts
│ │ │ ├── ERC20Proxy__factory.ts
│ │ │ ├── ERC20__factory.ts
│ │ │ ├── GrantAbi__factory.ts
│ │ │ ├── GrantFactoryAbi__factory.ts
│ │ │ ├── ReviewerGuard__factory.ts
│ │ │ ├── UtilityRegistryAbi__factory.ts
│ │ │ ├── WorkspaceRegistryAbi__factory.ts
│ │ │ └── index.ts
│ │ └── index.ts
│ ├── graphql.ts
│ ├── icons.tsx
│ └── mutation
│ │ ├── addComment.ts
│ │ ├── addComments.ts
│ │ ├── assignReviewers.ts
│ │ ├── batchGrantApplicationUpdate.ts
│ │ ├── createBuilder.ts
│ │ ├── createBuilderProfile.ts
│ │ ├── createInviteLink.ts
│ │ ├── createRFP.ts
│ │ ├── disburseRewardsFromSafe.ts
│ │ ├── editComment.ts
│ │ ├── generateToken.ts
│ │ ├── index.ts
│ │ ├── joinViaInviteLink.ts
│ │ ├── reSubmitProposal.ts
│ │ ├── reclaimProof.ts
│ │ ├── sendDocuSign.ts
│ │ ├── setRubrics.ts
│ │ ├── submitProposal.ts
│ │ ├── submitReviews.ts
│ │ ├── updateBuilderProfile.ts
│ │ ├── updateGrant.ts
│ │ ├── updateMetadataWorkspace.ts
│ │ ├── updateWorkspaceMember.ts
│ │ ├── verifyToken.ts
│ │ └── workspaceUpdateSafe.ts
├── global.d.ts
├── graphql
│ ├── apollo.tsx
│ └── subgraph.tsx
├── libraries
│ ├── data
│ │ ├── getAdminPublicKeysQuery.ts
│ │ ├── getApplicationDetailsQuery.ts
│ │ ├── getBuilderProfileQuery.ts
│ │ ├── getGrantManagersWithPublicKeyQuery.ts
│ │ ├── getGrantQuery.ts
│ │ ├── getMemberPublicKeysQuery.ts
│ │ ├── getQBAdminsQuery.ts
│ │ ├── getWorkspaceMemberExistsQuery.ts
│ │ ├── getWorkspaceMembersPublicKeysQuery.ts
│ │ └── getWorkspaceMembersQuery.ts
│ ├── graphql
│ │ ├── getAdminPublicKeys.graphql
│ │ ├── getApplicationDetails.graphql
│ │ ├── getBuilderProfile.graphql
│ │ ├── getGrant.graphql
│ │ ├── getGrantManagersWithPublicKey.graphql
│ │ ├── getLatestBlock.graphql
│ │ ├── getMemberPublicKeys.graphql
│ │ ├── getQBAdmins.graphql
│ │ ├── getWorkspaceMemberExists.graphql
│ │ ├── getWorkspaceMembers.graphql
│ │ └── getWorkspaceMembersPublicKeys.graphql
│ ├── hooks
│ │ ├── DAOSearchContext.ts
│ │ ├── QBAdminsContext.ts
│ │ ├── gasless
│ │ │ ├── useBiconomy.ts
│ │ │ ├── useNetwork.ts
│ │ │ └── useQuestbookAccount.ts
│ │ ├── useCreateMapping.tsx
│ │ ├── useCustomToast.tsx
│ │ ├── useFunctionCall.tsx
│ │ ├── useLinkYourMultisig.tsx
│ │ ├── useMultiChainQuery.ts
│ │ ├── useQBContract.ts
│ │ ├── useQuery.ts
│ │ ├── useSetupProfile.tsx
│ │ ├── useUpdateDaoVisibility.ts
│ │ └── utils
│ │ │ └── useChainId.ts
│ ├── logger.ts
│ ├── ui
│ │ ├── BackButton.tsx
│ │ ├── ConfirmationModal.tsx
│ │ ├── CopyIcon.tsx
│ │ ├── CustomSelect.tsx
│ │ ├── FlushedInput.tsx
│ │ ├── ImageUpload.tsx
│ │ ├── LinkYourMultisigModal
│ │ │ ├── DropdownSelect.tsx
│ │ │ ├── SafeSelect.tsx
│ │ │ ├── VerifySignerErrorState.tsx
│ │ │ ├── VerifySignerModal.tsx
│ │ │ └── index.tsx
│ │ ├── NavBar
│ │ │ ├── _components
│ │ │ │ ├── AccountDetails.tsx
│ │ │ │ ├── BackupWallet.tsx
│ │ │ │ ├── CreateNewWallet.tsx
│ │ │ │ ├── ImportConfirmationModal.tsx
│ │ │ │ ├── IssueWarning.tsx
│ │ │ │ ├── NotificationPopover.tsx
│ │ │ │ ├── RestoreWallet.tsx
│ │ │ │ ├── SignIn.tsx
│ │ │ │ ├── UpdateProfileModal.tsx
│ │ │ │ ├── googleRecovery.ts
│ │ │ │ ├── googleRecoveryTypes.ts
│ │ │ │ └── googleRecoveryUtils.ts
│ │ │ ├── _utils
│ │ │ │ └── constants.ts
│ │ │ └── index.tsx
│ │ ├── NetworkTransactionFlowStepperModal.tsx
│ │ ├── QRCodeModal.tsx
│ │ ├── RichTextEditor
│ │ │ ├── commentTextEditor.tsx
│ │ │ ├── commentTextViewer.tsx
│ │ │ ├── loader.tsx
│ │ │ ├── textEditor.tsx
│ │ │ └── textViewer.tsx
│ │ ├── SearchField.tsx
│ │ ├── SetupNotificationModal.tsx
│ │ └── navbarLayout.tsx
│ ├── utils
│ │ ├── amplitude.tsx
│ │ ├── appCopy.ts
│ │ ├── authToken.ts
│ │ ├── constants.tsx
│ │ ├── contextGenerator.ts
│ │ ├── copy.ts
│ │ ├── error.ts
│ │ ├── formatting.ts
│ │ ├── gasless.ts
│ │ ├── getSCWAddress.ts
│ │ ├── index.ts
│ │ ├── invite.ts
│ │ ├── ipfs.ts
│ │ ├── logger.ts
│ │ ├── multisig.ts
│ │ ├── pii.ts
│ │ ├── reviews.ts
│ │ ├── seo.ts
│ │ ├── token.ts
│ │ ├── types.ts
│ │ └── validations.ts
│ └── validator
│ │ ├── index.ts
│ │ ├── schema.yaml
│ │ └── utils
│ │ └── generateTypes.ts
├── pages
│ ├── _app.tsx
│ ├── _error.tsx
│ ├── dashboard.tsx
│ ├── grantees.tsx
│ ├── index.tsx
│ ├── profile
│ │ └── [address].tsx
│ ├── proposal_form.tsx
│ ├── proposal_recovery.tsx
│ ├── request_proposal.tsx
│ ├── settings.tsx
│ └── setup_profile.tsx
├── screens
│ ├── dashboard
│ │ ├── ActionList.tsx
│ │ ├── Banner.tsx
│ │ ├── Body.tsx
│ │ ├── Context.tsx
│ │ ├── FundBuilderDrawer.tsx
│ │ ├── FundBuilderModal.tsx
│ │ ├── FundingMethod.tsx
│ │ ├── ProposalList.tsx
│ │ ├── SafeGuardModal.tsx
│ │ ├── SendAnUpdateModal.tsx
│ │ ├── SetupProfileModal.tsx
│ │ ├── _components
│ │ │ ├── ActionList
│ │ │ │ ├── MultiSelect
│ │ │ │ │ └── index.tsx
│ │ │ │ └── SingleSelect
│ │ │ │ │ ├── Milestones.tsx
│ │ │ │ │ ├── Payouts.tsx
│ │ │ │ │ ├── ReviewProposal.tsx
│ │ │ │ │ ├── Reviews.tsx
│ │ │ │ │ └── index.tsx
│ │ │ ├── Body
│ │ │ │ ├── Empty.tsx
│ │ │ │ ├── MultiSelect
│ │ │ │ │ └── index.tsx
│ │ │ │ └── SingleSelect
│ │ │ │ │ ├── Discussions.tsx
│ │ │ │ │ ├── Proposal.tsx
│ │ │ │ │ └── index.tsx
│ │ │ ├── DashboardInput.tsx
│ │ │ ├── FilterTag.tsx
│ │ │ ├── FundBuilder
│ │ │ │ ├── ConnectWalletButton.tsx
│ │ │ │ ├── MilestoneChoose.tsx
│ │ │ │ ├── PaidByWallet.tsx
│ │ │ │ ├── PayFromChoose.tsx
│ │ │ │ ├── PayWithChoose.tsx
│ │ │ │ ├── ProposalDetails.tsx
│ │ │ │ ├── ToChoose.tsx
│ │ │ │ ├── TransactionInitiated.tsx
│ │ │ │ └── Verify.tsx
│ │ │ ├── HelloSignModal.tsx
│ │ │ ├── HeroBanner.tsx
│ │ │ ├── ProposalList
│ │ │ │ ├── Empty.tsx
│ │ │ │ └── ProposalCard.tsx
│ │ │ ├── QuickReplyButton.tsx
│ │ │ ├── RoleTag.tsx
│ │ │ ├── StateTag.tsx
│ │ │ └── ThreeColumnSkeleton.tsx
│ │ ├── _data
│ │ │ ├── getApplicantProposalsQuery.ts
│ │ │ ├── getApplicationActionsQuery.ts
│ │ │ ├── getBuilderInfoQuery.ts
│ │ │ ├── getCommentsQuery.ts
│ │ │ ├── getDocuSignTemplates.ts
│ │ │ ├── getFundsAllocatedQuery.ts
│ │ │ ├── getGrantDetailsForSEOQuery.ts
│ │ │ ├── getGrantsQuery.ts
│ │ │ ├── getMemberPublicKeysQuery.ts
│ │ │ ├── getPayoutQuery.ts
│ │ │ ├── getProposalDetailsForSEOQuery.ts
│ │ │ ├── getProposalsQuery.ts
│ │ │ ├── getSpecificApplicationActionQuery.ts
│ │ │ ├── getSpecificProposalCommentsQuery.ts
│ │ │ ├── getSpecificProposalQuery.ts
│ │ │ └── getSynapsId.ts
│ │ ├── _graphql
│ │ │ ├── getApplicantProposals.graphql
│ │ │ ├── getApplicationActionForProposal.graphql
│ │ │ ├── getApplicationActions.graphql
│ │ │ ├── getBuilderInfo.graphql
│ │ │ ├── getComments.graphql
│ │ │ ├── getDocusSignTemplates.graphql
│ │ │ ├── getFundTransfers.graphql
│ │ │ ├── getFundsAllocated.graphql
│ │ │ ├── getGrantDetailsForSEO.graphql
│ │ │ ├── getPayouts.graphql
│ │ │ ├── getProposalDetailsForSEO.graphql
│ │ │ ├── getProposals.graphql
│ │ │ ├── getSpecificProposal.graphql
│ │ │ ├── getSpecificProposalComments.graphql
│ │ │ └── getSynapsId.graphql
│ │ ├── _hooks
│ │ │ ├── useAddComment.ts
│ │ │ ├── useAddComments.ts
│ │ │ ├── useAssignReviewers.ts
│ │ │ ├── useDocuSign.ts
│ │ │ ├── useEditComment.ts
│ │ │ ├── usePayout.ts
│ │ │ ├── usePhantomWallet.ts
│ │ │ ├── useQuickReplies.tsx
│ │ │ ├── useSetRubrics.ts
│ │ │ ├── useSubmitReview.ts
│ │ │ ├── useSynaps.ts
│ │ │ └── useTonWallet.ts
│ │ ├── _utils
│ │ │ ├── constants.ts
│ │ │ ├── formatters.ts
│ │ │ ├── tonWalletUtils.ts
│ │ │ └── types.ts
│ │ └── index.tsx
│ ├── discover
│ │ ├── Context.tsx
│ │ ├── FeaturedSections.tsx
│ │ ├── Footer.tsx
│ │ ├── HeroBanner.tsx
│ │ ├── StatsBanner.tsx
│ │ ├── _components
│ │ │ ├── BuilderModal.tsx
│ │ │ ├── ProposalCard.tsx
│ │ │ ├── RFPCard.tsx
│ │ │ ├── rfpGrid.tsx
│ │ │ └── stateButton.tsx
│ │ ├── _graphql
│ │ │ ├── getAllFundTransfers.graphql
│ │ │ ├── getAllGrants.graphql
│ │ │ ├── getAllGrantsForMember.graphql
│ │ │ ├── getFundsAllocated.graphql
│ │ │ ├── getGrantProgramDetails.graphql
│ │ │ ├── getProposalNameAndAuthors.graphql
│ │ │ ├── getSectionGrants.graphql
│ │ │ ├── getSectionSubGrants.graphql
│ │ │ ├── getStats.graphql
│ │ │ └── getWorkspacesAndBuilderGrants.graphql
│ │ ├── _utils
│ │ │ ├── index.ts
│ │ │ └── types.ts
│ │ ├── data
│ │ │ ├── fundsTransfers.ts
│ │ │ ├── getAllGrants.ts
│ │ │ ├── getAllGrantsForMembers.ts
│ │ │ ├── getFundsAllocated.ts
│ │ │ ├── getGrantProgramDetails.ts
│ │ │ ├── getProposalNameAndAuthors.ts
│ │ │ ├── getSectionGrants.ts
│ │ │ ├── getSectionSubGrants.ts
│ │ │ ├── getStats.ts
│ │ │ └── getWorkspaceAndBuilderGrants.ts
│ │ ├── hooks
│ │ │ └── github.tsx
│ │ └── index.tsx
│ ├── grantees
│ │ ├── Context.tsx
│ │ ├── HeroBanner.tsx
│ │ ├── _components
│ │ │ ├── RFPCard.tsx
│ │ │ ├── rfpGrid.tsx
│ │ │ └── stateButton.tsx
│ │ ├── _graphql
│ │ │ └── getSectionGrants.graphql
│ │ ├── _utils
│ │ │ ├── constants.ts
│ │ │ └── types.ts
│ │ ├── data
│ │ │ └── getSectionGrants.tsx
│ │ ├── hooks
│ │ │ └── github.tsx
│ │ └── index.tsx
│ ├── profile
│ │ ├── Context.tsx
│ │ ├── _components
│ │ │ ├── GrantStats.tsx
│ │ │ ├── ProfileBanner.tsx
│ │ │ ├── ProfileModal.tsx
│ │ │ ├── ProofQrModal.tsx
│ │ │ ├── ProposalCard.tsx
│ │ │ └── stateButton.tsx
│ │ ├── _graphql
│ │ │ ├── getBuilderInfo.graphql
│ │ │ ├── getMyProposals.graphql
│ │ │ └── getUserNameAvailability.graphql
│ │ ├── _utils
│ │ │ ├── constant.ts
│ │ │ ├── formatters.ts
│ │ │ └── types.ts
│ │ ├── data
│ │ │ ├── getBuilderInfo.ts
│ │ │ ├── getMyProposals.ts
│ │ │ └── getUserNameAvailability.ts
│ │ ├── hooks
│ │ │ ├── checkUsernameAvailablity.tsx
│ │ │ └── generateProof.ts
│ │ └── index.tsx
│ ├── proposal_form
│ │ ├── Context.tsx
│ │ ├── _components
│ │ │ ├── SectionHeader.tsx
│ │ │ ├── SectionInput.tsx
│ │ │ ├── SectionRichTextEditor.tsx
│ │ │ ├── SectionSelect.tsx
│ │ │ ├── SelectArray.tsx
│ │ │ └── SelectRadioButton.tsx
│ │ ├── _data
│ │ │ ├── grantDetailsQuery.ts
│ │ │ ├── proposalDetailsQuery.ts
│ │ │ └── walletAddressCheckerQuery.ts
│ │ ├── _graphql
│ │ │ ├── grantDetails.graphql
│ │ │ ├── proposalDetails.graphql
│ │ │ └── walletAddressChecker.graphql
│ │ ├── _hooks
│ │ │ └── useSubmitProposal.tsx
│ │ ├── _utils
│ │ │ ├── constants.ts
│ │ │ ├── index.ts
│ │ │ └── types.ts
│ │ └── index.tsx
│ ├── proposal_recovery
│ │ ├── _graphql
│ │ │ └── getMigrationStatus.graphql
│ │ ├── data
│ │ │ └── getMigrationStatusQuery.ts
│ │ └── index.tsx
│ ├── request_proposal
│ │ ├── Context.tsx
│ │ ├── _components
│ │ │ ├── SelectDropdown.tsx
│ │ │ └── StepIndicator.tsx
│ │ ├── _data
│ │ │ ├── getGrantDetailsByIdQuery.ts
│ │ │ └── getGrantDetailsQuery.ts
│ │ ├── _graphql
│ │ │ ├── getGrantDetails.graphql
│ │ │ └── getGrantDetailsById.graphql
│ │ ├── _hooks
│ │ │ ├── useCreateRFP.ts
│ │ │ └── useUpdateRFP.ts
│ │ ├── _subscreens
│ │ │ ├── Payouts.tsx
│ │ │ ├── ProposalReview.tsx
│ │ │ └── ProposalSubmission.tsx
│ │ ├── _utils
│ │ │ ├── constants.ts
│ │ │ └── types.ts
│ │ └── index.tsx
│ ├── settings
│ │ ├── Context.tsx
│ │ ├── WorkspaceMemberCard.tsx
│ │ ├── _components
│ │ │ ├── AddMemberButton.tsx
│ │ │ └── DropdownIcon.tsx
│ │ ├── _graphql
│ │ │ ├── getWorkspaceDetails.graphql
│ │ │ └── getWorkspaceMembersByWorkspaceId.graphql
│ │ ├── _hooks
│ │ │ └── useUpdateGrantProgram.tsx
│ │ ├── _utils
│ │ │ └── types.ts
│ │ ├── data
│ │ │ ├── getWorkspaceDetailsQuery.ts
│ │ │ ├── getWorkspaceMembersByWorkspaceIdQuery.ts
│ │ │ └── index.ts
│ │ └── index.tsx
│ └── setup_profile
│ │ └── index.tsx
├── theme
│ ├── colors.tsx
│ ├── components
│ │ ├── button.tsx
│ │ ├── container.tsx
│ │ ├── divider.tsx
│ │ ├── header.tsx
│ │ ├── input.tsx
│ │ ├── link.tsx
│ │ ├── progress.tsx
│ │ └── text.tsx
│ └── index.tsx
└── types
│ ├── gasless.ts
│ ├── gen.d.ts
│ └── index.ts
├── styles
└── globals.css
└── tsconfig.json
/.env.example:
--------------------------------------------------------------------------------
1 | NEXT_PUBLIC_IS_TEST=
2 | NEXT_PUBLIC_INFURA_ID=
3 | CLIENT_ID=
4 | CLIENT_SECRET=
5 | BICO_AUTH_TOKEN=
6 | SOLANA_RPC=
7 | SENTRY_LOG_LEVEL=
8 | SENTRY_AUTH_TOKEN=
9 | API_ENDPOINT=
10 | NOTIF_BOT_USERNAME=
11 | INFURA_IPFS_PROJECT_ID=
12 | INFURA_IPFS_API_KEY=
13 | WALLETCONNECT_PROJECT_ID=
14 | BACKEND_URL=
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | src/generated
3 | src/pages/test.tsx
4 | out
5 | .next
6 | .vscode
7 | public
8 | contracts
--------------------------------------------------------------------------------
/.eslintrc.yml:
--------------------------------------------------------------------------------
1 | extends: '@creatoros'
2 | parserOptions:
3 | project: ./tsconfig.json
4 | plugins:
5 | - no-relative-import-paths
6 | - sonarjs
7 | rules:
8 | no-console: 'error'
9 | sonarjs/no-duplicated-branches: 'error'
10 | sonarjs/no-identical-functions: 'error'
11 | sonarjs/no-gratuitous-expressions: 'error'
12 | no-relative-import-paths/no-relative-import-paths:
13 | - error
14 | - rootDir: ''
--------------------------------------------------------------------------------
/.github/workflows/lint.yml_bkp:
--------------------------------------------------------------------------------
1 | name: Check PR health
2 |
3 | on: [pull_request]
4 |
5 | jobs:
6 | check-lint:
7 | runs-on: ubuntu-latest
8 | timeout-minutes: 10
9 |
10 | steps:
11 | - uses: actions/checkout@v2
12 |
13 | - name: Install Node
14 | uses: actions/setup-node@v1
15 | with:
16 | node-version: 16.x
17 |
18 | - name: Install packages
19 | run: npm i --legacy-peer-deps
20 |
21 | - name: Refresh packages
22 | run: npm run refresh
23 |
24 | - name: Check linting
25 | run: npm run lint
26 |
27 | - name: Check build
28 | run: npm run build
29 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | node_modules
5 | /.pnp
6 | .pnp.js
7 | src/.graphclientrc.yml
8 |
9 | # testing
10 | /coverage
11 | /pages/api/
12 | /pages/test.tsx
13 | tests/
14 |
15 | # next.js
16 | /.next/
17 | /out/
18 |
19 | # production
20 | /build
21 |
22 | # misc
23 | .DS_Store
24 | *.pem
25 |
26 | # debug
27 | npm-debug.log*
28 | yarn-debug.log*
29 | yarn-error.log*
30 |
31 | # local env files
32 | .env
33 | .env.local
34 | .env.development.local
35 | .env.test.local
36 | .env.production.local
37 |
38 | # vercel
39 | .vercel
40 |
41 | # typescript
42 | *.tsbuildinfo
43 |
44 | yarn.lock
45 |
46 | .env
47 | src/pages/test.tsx
48 | test/
49 | lib
50 | # Sentry
51 | .sentryclirc
52 |
53 | #service worker
54 | sw.js
55 | workbox-588899ac.js
--------------------------------------------------------------------------------
/.unimportedrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "aliases": {
3 | "src/*": [
4 | "./src",
5 | "./src/*"
6 | ],
7 | "entry": [
8 | "src/pages/**/*.{js,ts,tsx}",
9 | "next.config.js"
10 | ]
11 | },
12 | "ignoreUnresolved": [
13 | ".graphclient",
14 | "encoding",
15 | "public/favicon.ico",
16 | "src/types/gen",
17 | "styles/globals.css"
18 | ],
19 | "ignoreUnused": [
20 | "@apidevtools/json-schema-ref-parser",
21 | "@metamask/eth-sig-util",
22 | "@unstoppabledomains/resolution",
23 | "create-chakra-icons",
24 | "idriss-crypto",
25 | "js-yaml-loader",
26 | "json-schema-to-typescript",
27 | "linkifyjs",
28 | "lottie-react",
29 | "next",
30 | "next-plugin-yaml",
31 | "next-pwa",
32 | "next-transpile-modules",
33 | "openapi-typescript",
34 | "react",
35 | "react-apexcharts",
36 | "react-datepicker",
37 | "react-dom",
38 | "react-image-picker-editor",
39 | "ts-node"
40 | ],
41 | "ignoreUnimported": [
42 | "src/generated/contracts/ERC20.ts",
43 | "src/generated/contracts/ERC20Proxy.ts",
44 | "src/generated/contracts/factories/ERC20Proxy__factory.ts",
45 | "src/generated/contracts/factories/ERC20__factory.ts",
46 | "src/libraries/validator/utils/generateTypes.ts",
47 | "src/screens/dashboard/_utils/constants.ts",
48 | "src/screens/request_proposal/_utils/constants.ts"
49 | ]
50 | }
--------------------------------------------------------------------------------
/codegen.yaml:
--------------------------------------------------------------------------------
1 | schema:
2 | - https://the-graph.questbook.app/subgraphs/name/qb-subgraph-optimism-mainnet
3 | documents:
4 | - src/libraries/graphql/*.graphql
5 | - src/screens/dashboard/_graphql/*.graphql
6 | - src/screens/discover/_graphql/*.graphql
7 | - src/screens/proposal_form/_graphql/*.graphql
8 | - src/screens/profile/_graphql/*.graphql
9 | - src/screens/request_proposal/_graphql/*.graphql
10 | - src/screens/settings/_graphql/*.graphql
11 | overwrite: true
12 | generates:
13 | ./src/generated/graphql.ts:
14 | plugins:
15 | - typescript
16 | - typescript-operations
17 | - typescript-react-apollo
18 | config:
19 | scalars:
20 | BigDecimal: string
21 | BigInt: string
22 | Bytes: string
23 | skipTypename: false
24 | withComponent: false
25 | withHooks: true
26 | withHOC: false
27 | withRefetchFn: true
--------------------------------------------------------------------------------
/next-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | // NOTE: This file should not be edited
5 | // see https://nextjs.org/docs/basic-features/typescript for more information.
6 |
--------------------------------------------------------------------------------
/public/chain_assets/biconomy.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/public/chain_assets/cusd.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/public/chain_assets/dollar.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/chain_assets/eth.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/public/chain_assets/flux.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/chain_assets/gnosis.svg:
--------------------------------------------------------------------------------
1 |
2 |
7 |
--------------------------------------------------------------------------------
/public/chain_assets/livepeer.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/chain_assets/matic.svg:
--------------------------------------------------------------------------------
1 |
17 |
--------------------------------------------------------------------------------
/public/chain_assets/perp.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/public/chain_assets/solana.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/questbook/grants-frontend/e5b3129c808e83b7aa02ef306f21917f36cbd691/public/chain_assets/solana.png
--------------------------------------------------------------------------------
/public/chain_assets/spruce.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/public/chain_assets/unlock.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/questbook/grants-frontend/e5b3129c808e83b7aa02ef306f21917f36cbd691/public/favicon.ico
--------------------------------------------------------------------------------
/public/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/questbook/grants-frontend/e5b3129c808e83b7aa02ef306f21917f36cbd691/public/favicon.png
--------------------------------------------------------------------------------
/public/fonts/v2/NueHaas/NHaasGroteskTXPro-55Rg.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/questbook/grants-frontend/e5b3129c808e83b7aa02ef306f21917f36cbd691/public/fonts/v2/NueHaas/NHaasGroteskTXPro-55Rg.ttf
--------------------------------------------------------------------------------
/public/fonts/v2/NueHaas/NHaasGroteskTXPro-56It.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/questbook/grants-frontend/e5b3129c808e83b7aa02ef306f21917f36cbd691/public/fonts/v2/NueHaas/NHaasGroteskTXPro-56It.ttf
--------------------------------------------------------------------------------
/public/fonts/v2/NueHaas/NHaasGroteskTXPro-65Md.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/questbook/grants-frontend/e5b3129c808e83b7aa02ef306f21917f36cbd691/public/fonts/v2/NueHaas/NHaasGroteskTXPro-65Md.ttf
--------------------------------------------------------------------------------
/public/fonts/v2/NueHaas/NHaasGroteskTXPro-66MdIt.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/questbook/grants-frontend/e5b3129c808e83b7aa02ef306f21917f36cbd691/public/fonts/v2/NueHaas/NHaasGroteskTXPro-66MdIt.ttf
--------------------------------------------------------------------------------
/public/fonts/v2/NueHaas/NHaasGroteskTXPro-75Bd.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/questbook/grants-frontend/e5b3129c808e83b7aa02ef306f21917f36cbd691/public/fonts/v2/NueHaas/NHaasGroteskTXPro-75Bd.ttf
--------------------------------------------------------------------------------
/public/fonts/v2/NueHaas/NHaasGroteskTXPro-76BdIt.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/questbook/grants-frontend/e5b3129c808e83b7aa02ef306f21917f36cbd691/public/fonts/v2/NueHaas/NHaasGroteskTXPro-76BdIt.ttf
--------------------------------------------------------------------------------
/public/v2/icons/accept.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/add user.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/add.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/alert.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/arrow left.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/arrow right.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/bell.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/bitcoin.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/bold_button.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/v2/icons/calendar-color.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/v2/icons/calendar.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/call.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/chat.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/check double.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/checkBox.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/public/v2/icons/checkbox circle.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/chevron right.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/close.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/copy.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/v2/icons/desktop.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/discover.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/doc.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/v2/icons/dot.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/down.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/dropdown.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/embed.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/error warning.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/export-download.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/v2/icons/export.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/v2/icons/filter.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/gdrive.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/v2/icons/group.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/image add.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/import.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/v2/icons/italics_button.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/v2/icons/key.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/loader.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/mail.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/new tab.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/ol_button.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/v2/icons/pencil.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/phone.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/pie chart.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/qr-scan.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/question.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/reject.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/resubmit.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/search.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/share forward.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/share-box.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/share.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/v2/icons/swap.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/telegram.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/thumbs up.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/time.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/twitter.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/ul_button.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/v2/icons/underline_button.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/v2/icons/visible.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/v2/icons/wallet-connect.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/icons/wallet.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/v2/images/banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/questbook/grants-frontend/e5b3129c808e83b7aa02ef306f21917f36cbd691/public/v2/images/banner.png
--------------------------------------------------------------------------------
/public/v2/images/builders.svg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/questbook/grants-frontend/e5b3129c808e83b7aa02ef306f21917f36cbd691/public/v2/images/builders.svg
--------------------------------------------------------------------------------
/public/v2/images/default_profile_picture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/questbook/grants-frontend/e5b3129c808e83b7aa02ef306f21917f36cbd691/public/v2/images/default_profile_picture.png
--------------------------------------------------------------------------------
/public/v2/images/profile-bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/questbook/grants-frontend/e5b3129c808e83b7aa02ef306f21917f36cbd691/public/v2/images/profile-bg.png
--------------------------------------------------------------------------------
/public/v2/images/qb-only-logo.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/public/v2/images/tonBanner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/questbook/grants-frontend/e5b3129c808e83b7aa02ef306f21917f36cbd691/public/v2/images/tonBanner.png
--------------------------------------------------------------------------------
/sentry.client.config.ts:
--------------------------------------------------------------------------------
1 | // This file configures the initialization of Sentry on the server.
2 | // The config you add here will be used whenever the server handles a request.
3 | // https://docs.sentry.io/platforms/javascript/guides/nextjs/
4 |
5 | import { init } from '@sentry/nextjs'
6 |
7 | init({
8 | dsn: 'https://8fb977f0e4774e1fa01ae8d9e596e9d2@o1425922.ingest.sentry.io/6776175',
9 | // Adjust this value in production, or use tracesSampler for greater control
10 | tracesSampleRate: 1.0,
11 | enabled: process.env.NODE_ENV === 'production',
12 | // ...
13 | // Note: if you want to override the automatic release value, do not set a
14 | // `release` value here - use the environment variable `SENTRY_RELEASE`, so
15 | // that it will also get attached to your source maps
16 | })
--------------------------------------------------------------------------------
/sentry.properties:
--------------------------------------------------------------------------------
1 | defaults.url=https://sentry.io/
2 | defaults.org=questbook
3 | defaults.project=grants-tool
4 | # cli.executable=../path/to/bin/sentry-cli
--------------------------------------------------------------------------------
/sentry.server.config.ts:
--------------------------------------------------------------------------------
1 | export {}
--------------------------------------------------------------------------------
/src/constants/Networks.tsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-restricted-syntax */
2 |
3 | export enum NetworkType {
4 | EVM = 1,
5 | Solana = 2,
6 | TON = 3,
7 | }
8 |
9 |
--------------------------------------------------------------------------------
/src/constants/addresses.ts:
--------------------------------------------------------------------------------
1 | import { CHAIN_INFO } from 'src/constants/chains'
2 | import { AddressMap, QBContract } from 'src/types'
3 |
4 | export const WORKSPACE_REGISTRY_ADDRESS = compileAddresses('workspace')
5 | export const APPLICATION_REGISTRY_ADDRESS = compileAddresses('applications')
6 | export const APPLICATION_REVIEW_REGISTRY_ADDRESS = compileAddresses('reviews')
7 | export const GRANT_FACTORY_ADDRESS = compileAddresses('grantFactory')
8 | export const COMMUNICATION_ADDRESS = compileAddresses('communication')
9 |
10 | function compileAddresses(contract: QBContract) {
11 | return Object.values(CHAIN_INFO).reduce(
12 | (acc, chainInfo) => {
13 | acc[chainInfo.id] = chainInfo.qbContracts[contract]
14 | return acc
15 | }, { } as AddressMap
16 | )
17 | }
--------------------------------------------------------------------------------
/src/constants/applicantDetailsList.tsx:
--------------------------------------------------------------------------------
1 | export default [
2 | {
3 | title: 'Name',
4 | id: 'applicantName',
5 | inputType: 'short-form',
6 | isRequired: true,
7 | },
8 | {
9 | title: 'Email',
10 | id: 'applicantEmail',
11 | inputType: 'short-form',
12 | isRequired: true,
13 | pii: true
14 | },
15 | {
16 | title: 'Telegram',
17 | id: 'applicantTelegram',
18 | inputType: 'short-form',
19 | isRequired: false,
20 | },
21 | {
22 | title: 'Twitter',
23 | id: 'applicantTwitter',
24 | inputType: 'short-form',
25 | isRequired: false,
26 | },
27 | {
28 | title: 'Wallet Address',
29 | id: 'applicantAddress',
30 | inputType: 'short-form',
31 | isRequired: true
32 | },
33 | {
34 | title: 'Team Members',
35 | id: 'teamMembers',
36 | inputType: 'long-form',
37 | isRequired: false,
38 | },
39 |
40 | {
41 | title: 'Title',
42 | id: 'projectName',
43 | inputType: 'short-form',
44 | isRequired: true,
45 | },
46 | {
47 | title: 'Project Details',
48 | id: 'projectDetails',
49 | inputType: 'long-form',
50 | isRequired: true,
51 | },
52 | {
53 | title: 'Funding Ask',
54 | id: 'fundingAsk',
55 | inputType: 'long-form',
56 | isRequired: true,
57 | },
58 | {
59 | title: 'tl,dr',
60 | id: 'tldr',
61 | inputType: 'short-form',
62 | isRequired: false,
63 | }
64 | ]
65 |
--------------------------------------------------------------------------------
/src/constants/chains.ts:
--------------------------------------------------------------------------------
1 | import chainInfo from 'src/generated/chainInfo.json'
2 | import SupportedChainId from 'src/generated/SupportedChainId'
3 | import { ChainInfoMap } from 'src/types'
4 | import 'dotenv/config'
5 |
6 | // by default, we show all test nets
7 | export const SHOW_TEST_NETS = process.env.NEXT_PUBLIC_IS_TEST !== 'false'
8 | export const defaultChainId = process.env.NEXT_PUBLIC_IS_TEST === 'true'
9 | ? SupportedChainId.GOERLI_TESTNET
10 | : SupportedChainId.OPTIMISM_MAINNET
11 | export const CHAIN_INFO = chainInfo as ChainInfoMap
12 | export const USD_ASSET = '0x0000000000000000000000000000000000000001'
13 | export const USD_ICON = '/dollar_icon.svg'
14 | export const SOL_ETH_ASSET = '0x0000000000000000000000000000000000000002'
15 | export const USD_DECIMALS = 0
16 | export const SOL_ETH_DECIMALS = 9
17 |
18 | // when SHOW_TEST_NETS = true, we show every chain
19 | // otherwise only use mainnets
20 | export const ALL_SUPPORTED_CHAIN_IDS: SupportedChainId[] = Object.values(CHAIN_INFO)
21 | .map(({ id }) => id)
22 | // Changed this temporarily to show only the testnet for testing
23 | .filter(id => SHOW_TEST_NETS || !CHAIN_INFO[id].isTestNetwork)
24 |
25 | export { SupportedChainId }
26 |
--------------------------------------------------------------------------------
/src/constants/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "defaultDAOImagePath": "/images/default_dao.svg",
3 | "defaultDAOImageHash": "QmeNL8mChbLFJvhx3YnLa6mMKGHiXwgxPVRVWnQxW651dR",
4 | "supportLink": "https://discord.gg/a3SkQX6gnW",
5 | "defaultTokenUploadImagePath": "/images/default_token_upload.svg",
6 | "approvalLink": "https://www.notion.so/Why-Approve-Fund-Disbursal-ed6094e1a1c9410689c9321a0f5dbfae",
7 | "defaultRubricMaximumPoints": 5
8 | }
--------------------------------------------------------------------------------
/src/constants/safesEndpoints.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": "https://safe-transaction-mainnet.safe.global/api/",
3 | "40": "https://transaction.safe.telos.net/api/",
4 | "100": "https://safe-transaction.xdai.gnosis.io/api/",
5 | "42161": "https://safe-transaction.arbitrum.gnosis.io/api/",
6 | "43114": "https://safe-transaction.avalanche.gnosis.io/api/",
7 | "1313161554": "https://safe-transaction.aurora.gnosis.io/api/",
8 | "56": "https://safe-transaction-bsc.safe.global/api/",
9 | "246": "https://safe-transaction.ewc.gnosis.io/api/",
10 | "10": "https://safe-transaction.optimism.gnosis.io/api/",
11 | "137": "https://safe-transaction.polygon.gnosis.io/api/",
12 | "42220": "https://transaction-service.gnosis-safe-staging.celo-networks-dev.org/api/"
13 | }
14 |
--------------------------------------------------------------------------------
/src/constants/safesEndpointsTest.json:
--------------------------------------------------------------------------------
1 | {
2 | "4": "https://safe-transaction.rinkeby.gnosis.io/api/",
3 | "5": "https://safe-transaction.goerli.gnosis.io/api/",
4 | "73799": "https://safe-transaction.volta.gnosis.io/api/"
5 | }
6 |
--------------------------------------------------------------------------------
/src/constants/safesSupported.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": "Ethereum Mainnet",
3 | "40": "Telos",
4 | "100": "Gnosis",
5 | "42161": "Arbitrum One",
6 | "43114": "Avalanche C-Chain",
7 | "1313161554": "Aurora Mainnet",
8 | "56": "Binance Smart Chain",
9 | "246": "Energy Web Chain",
10 | "10": "Optimism",
11 | "137": "Polygon Mainnet",
12 | "42220": "Celo Mainnet",
13 | "4": "Rinkeby",
14 | "5": "Goerli",
15 | "73799": "Energy Web Volta",
16 | "1313161555": "Aurora Testnet"
17 | }
18 |
--------------------------------------------------------------------------------
/src/constants/seo.tsx:
--------------------------------------------------------------------------------
1 | const seoConfig = {
2 | title: 'Questbook',
3 | titleTemplate: '%s',
4 | description:
5 | 'Discover Opportunities in Web 3.0 and Earn in Crypto',
6 | // siteUrl: 'https://www.questbook.app/',
7 | siteUrl: 'https://beta.questbook.app/',
8 | twitter: {
9 | handle: '@questbookapp',
10 | site: '@questbookapp',
11 | cardType: 'summary_large_image',
12 | title: 'Questbook Grant',
13 | image: 'https://ipfs.io/ipfs/bafkreif2xxm6kfj3n5gksduce26xjyijhkh6qil7e3pj7yuysjaneh624y',
14 | },
15 | openGraph: {
16 | type: 'website',
17 | locale: 'en_US',
18 | url: 'https://beta.questbook.app/',
19 | title: 'Questbook',
20 | description:
21 | 'Discover Opportunities in Web 3.0 and Earn in Crypto',
22 | // eslint-disable-next-line camelcase
23 | site_name: 'Questbook',
24 | images: [
25 | {
26 | url: 'https://ipfs.io/ipfs/bafkreif2xxm6kfj3n5gksduce26xjyijhkh6qil7e3pj7yuysjaneh624y',
27 | width: 1240,
28 | height: 480,
29 | alt: 'Questbook Grant',
30 | },
31 | {
32 | url: 'https://ipfs.io/ipfs/bafkreif2xxm6kfj3n5gksduce26xjyijhkh6qil7e3pj7yuysjaneh624y',
33 | width: 1012,
34 | height: 506,
35 | alt: 'Questbook Grant',
36 | },
37 | ],
38 | },
39 | }
40 |
41 | export default seoConfig
42 |
--------------------------------------------------------------------------------
/src/contexts/safeContext.tsx:
--------------------------------------------------------------------------------
1 | import { createContext, ReactNode, useContext, useState } from 'react'
2 | import { EthereumMainnet } from '@questbook/supported-safes/lib/chains/ethereum-mainnet'
3 | import { SolanaMainnet } from '@questbook/supported-safes/lib/chains/solana-mainnet'
4 | import { TonKeyMainnet } from '@questbook/supported-safes/lib/chains/tonkey-mainnet'
5 | export const SafeContext = createContext<{safeObj: EthereumMainnet | SolanaMainnet | TonKeyMainnet| undefined, setSafeObj: (safe: EthereumMainnet | SolanaMainnet | TonKeyMainnet | undefined) => void} | null>(null)
6 |
7 | export const useSafeContext = () => useContext(SafeContext)
8 |
9 | export const SafeProvider = ({ children }: {children: ReactNode}) => {
10 | const [safeObj, setSafeObj] = useState()
11 | return (
12 |
13 | {children}
14 |
15 | )
16 | }
--------------------------------------------------------------------------------
/src/generated/SupportedChainId.ts:
--------------------------------------------------------------------------------
1 |
2 | enum SupportedChainId {
3 | CELO_MAINNET = 42220,
4 | GOERLI_TESTNET = 5,
5 | OPTIMISM_MAINNET = 10,
6 | POLYGON_MAINNET = 137,
7 | }
8 |
9 | export default SupportedChainId
--------------------------------------------------------------------------------
/src/generated/contracts/common.ts:
--------------------------------------------------------------------------------
1 | /* Autogenerated file. Do not edit manually. */
2 | /* tslint:disable */
3 | /* eslint-disable */
4 | import type { Listener } from "@ethersproject/providers";
5 | import type { Event, EventFilter } from "ethers";
6 |
7 | export interface TypedEvent<
8 | TArgsArray extends Array = any,
9 | TArgsObject = any
10 | > extends Event {
11 | args: TArgsArray & TArgsObject;
12 | }
13 |
14 | export interface TypedEventFilter<_TEvent extends TypedEvent>
15 | extends EventFilter {}
16 |
17 | export interface TypedListener {
18 | (...listenerArg: [...__TypechainArgsArray, TEvent]): void;
19 | }
20 |
21 | type __TypechainArgsArray = T extends TypedEvent ? U : never;
22 |
23 | export interface OnEvent {
24 | (
25 | eventFilter: TypedEventFilter,
26 | listener: TypedListener
27 | ): TRes;
28 | (eventName: string, listener: Listener): TRes;
29 | }
30 |
31 | export type MinEthersFactory = {
32 | deploy(...a: ARGS[]): Promise;
33 | };
34 |
35 | export type GetContractTypeFromFactory = F extends MinEthersFactory<
36 | infer C,
37 | any
38 | >
39 | ? C
40 | : never;
41 |
42 | export type GetARGsTypeFromFactory = F extends MinEthersFactory
43 | ? Parameters
44 | : never;
45 |
46 | export type PromiseOrValue = T | Promise;
47 |
--------------------------------------------------------------------------------
/src/generated/contracts/factories/index.ts:
--------------------------------------------------------------------------------
1 | /* Autogenerated file. Do not edit manually. */
2 | /* tslint:disable */
3 | /* eslint-disable */
4 | export { ApplicationRegistryAbi__factory } from "./ApplicationRegistryAbi__factory";
5 | export { ApplicationReviewRegistryAbi__factory } from "./ApplicationReviewRegistryAbi__factory";
6 | export { CommunicationAbi__factory } from "./CommunicationAbi__factory";
7 | export { GrantAbi__factory } from "./GrantAbi__factory";
8 | export { GrantFactoryAbi__factory } from "./GrantFactoryAbi__factory";
9 | export { ReviewerGuard__factory } from "./ReviewerGuard__factory";
10 | export { UtilityRegistryAbi__factory } from "./UtilityRegistryAbi__factory";
11 | export { WorkspaceRegistryAbi__factory } from "./WorkspaceRegistryAbi__factory";
12 |
--------------------------------------------------------------------------------
/src/generated/contracts/index.ts:
--------------------------------------------------------------------------------
1 | /* Autogenerated file. Do not edit manually. */
2 | /* tslint:disable */
3 | /* eslint-disable */
4 | export type { ApplicationRegistryAbi } from "./ApplicationRegistryAbi";
5 | export type { ApplicationReviewRegistryAbi } from "./ApplicationReviewRegistryAbi";
6 | export type { CommunicationAbi } from "./CommunicationAbi";
7 | export type { GrantAbi } from "./GrantAbi";
8 | export type { GrantFactoryAbi } from "./GrantFactoryAbi";
9 | export type { ReviewerGuard } from "./ReviewerGuard";
10 | export type { UtilityRegistryAbi } from "./UtilityRegistryAbi";
11 | export type { WorkspaceRegistryAbi } from "./WorkspaceRegistryAbi";
12 | export * as factories from "./factories";
13 | export { ApplicationRegistryAbi__factory } from "./factories/ApplicationRegistryAbi__factory";
14 | export { ApplicationReviewRegistryAbi__factory } from "./factories/ApplicationReviewRegistryAbi__factory";
15 | export { CommunicationAbi__factory } from "./factories/CommunicationAbi__factory";
16 | export { GrantAbi__factory } from "./factories/GrantAbi__factory";
17 | export { GrantFactoryAbi__factory } from "./factories/GrantFactoryAbi__factory";
18 | export { ReviewerGuard__factory } from "./factories/ReviewerGuard__factory";
19 | export { UtilityRegistryAbi__factory } from "./factories/UtilityRegistryAbi__factory";
20 | export { WorkspaceRegistryAbi__factory } from "./factories/WorkspaceRegistryAbi__factory";
21 |
--------------------------------------------------------------------------------
/src/generated/mutation/addComment.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const addCommentMutation = gql`mutation addComment($workspace: String!, $grant: String!, $application: String!, $isPrivate: Boolean!, $comment: JSON!, $sender: String!) {
3 | addComment(workspace: $workspace,grant:$grant ,application: $application,isPrivate:$isPrivate,comment:$comment,sender:$sender){
4 | record{
5 | _id
6 | }
7 | recordId
8 | }
9 | }`
--------------------------------------------------------------------------------
/src/generated/mutation/addComments.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const addBatchCommentsMutation = gql`mutation addComments($workspace: String!, $grant: String!, $application: [String!]!, $isPrivate: Boolean!, $comments: [JSON!]!) {
3 | addComments(workspace: $workspace,grant:$grant ,application: $application,isPrivate:$isPrivate,comments:$comments){
4 | record{
5 | _id
6 | }
7 | recordId
8 | }
9 | }`
--------------------------------------------------------------------------------
/src/generated/mutation/assignReviewers.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const assignReviewersMutation = gql`mutation assignReviewers($workspaceId: String!,$applicationId: String!,$grantAddress: String!, $reviewers: [String!]!, $active: [Boolean!]!){
3 | assignReviewers(workspaceId: $workspaceId, applicationId: $applicationId, grantAddress: $grantAddress, reviewers: $reviewers, active: $active){
4 | recordId
5 | record{
6 | _id
7 | }
8 | }
9 | }
10 | `
--------------------------------------------------------------------------------
/src/generated/mutation/batchGrantApplicationUpdate.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const batchGrantApplicationUpdateMutation = gql`
3 | mutation batchUpdateGrantApplication($id: [String!]!, $grant: String!, $workspaceId: String!, $applicantId: [String!], $state: [String!]!, $feedback: [JSON!]!){
4 | batchUpdateGrantApplication(id: $id, grant: $grant, workspaceId: $workspaceId, applicantId: $applicantId, state: $state, feedback: $feedback){
5 | recordId
6 | record{
7 | _id
8 | }
9 | }
10 | }
11 | `
--------------------------------------------------------------------------------
/src/generated/mutation/createBuilder.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const createBuilder = gql`mutation createBuilder($telegram: String!, $github: JSON!, $application: String, $email: String!, $twitter: String, $referral: JSON, $newsletter: Boolean) {
3 | createBuilder(telegram: $telegram, github: $github, application: $application, email: $email, twitter: $twitter, referral: $referral, newsletter: $newsletter) {
4 | recordId
5 | record {
6 | _id
7 | }
8 | }
9 | }
10 | `
--------------------------------------------------------------------------------
/src/generated/mutation/createBuilderProfile.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const createBuilderProfile = gql`
3 | mutation createBuilderProfile($telegram: String, $username: String!, $imageURL: String, $address: String!, $bio: String) {
4 | createProfile(telegram: $telegram, username: $username, imageURL: $imageURL, address: $address, bio: $bio) {
5 | recordId
6 | record {
7 | _id
8 | }
9 | }
10 | }
11 | `
--------------------------------------------------------------------------------
/src/generated/mutation/createInviteLink.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const createInviteLinkMutation = gql`
3 | mutation createInviteLink($w: String!, $r: String!, $k: String!, $createdBy: String!){
4 | createInviteLink(w: $w, r: $r, k: $k, createdBy: $createdBy){
5 | recordId
6 | record{
7 | _id
8 | }
9 | }
10 | }`
--------------------------------------------------------------------------------
/src/generated/mutation/disburseRewardsFromSafe.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const DisburseRewardSafeMutation = gql`
3 | mutation disburseRewardsFromSafe($applicationIds: [String!]!, $milestoneIds: [String!]!, $asset: String!, $tokenName: String!, $nonEvmAssetAddress: String!, $amounts: [Float!]!, $transactionHash: String!, $sender: String!, $grant: String!, $to: String!
4 | ) {
5 | disburseRewardsFromSafe(
6 | applicationIds: $applicationIds
7 | milestoneIds: $milestoneIds
8 | asset: $asset
9 | tokenName: $tokenName
10 | nonEvmAssetAddress: $nonEvmAssetAddress
11 | amounts: $amounts
12 | transactionHash: $transactionHash
13 | sender: $sender
14 | grant: $grant
15 | to: $to
16 | ){
17 | record {
18 | _id
19 | }
20 | }
21 | }`
--------------------------------------------------------------------------------
/src/generated/mutation/editComment.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const editCommentMutation = gql`mutation editComment($id: String! $isPrivate: Boolean!, $comment: JSON!) {
3 | editComment(id: $id,isPrivate:$isPrivate,comment:$comment){
4 | record{
5 | _id
6 | }
7 | recordId
8 | }
9 | }`
--------------------------------------------------------------------------------
/src/generated/mutation/generateToken.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const generateTokenMutation = gql`
3 | mutation generateToken($address: String!){
4 | generateToken(address: $address){
5 | recordId
6 | record{
7 | id: _id
8 | nonce
9 | }
10 | }
11 | }
12 | `
--------------------------------------------------------------------------------
/src/generated/mutation/index.ts:
--------------------------------------------------------------------------------
1 | export { DisburseRewardSafeMutation } from './disburseRewardsFromSafe'
2 | export { submitProposalMutation } from './submitProposal'
3 | export { reSubmitProposalMutation } from './reSubmitProposal'
4 | export { updateGrant } from './updateGrant'
5 | export { assignReviewersMutation } from './assignReviewers'
6 | export { submitReviewsMutation } from './submitReviews'
7 | export { setRubricsMutation } from './setRubrics'
8 | export { updateWorkspaceMemberMutation } from './updateWorkspaceMember'
9 | export { createInviteLinkMutation } from './createInviteLink'
10 | export { joinViaInviteLinkMutation } from './joinViaInviteLink'
11 | export { workspaceUpdateSafeMutation } from './workspaceUpdateSafe'
12 | export { generateTokenMutation } from './generateToken'
13 | export { verifyTokenMutation } from './verifyToken'
14 | export { addBatchCommentsMutation } from './addComments'
15 | export { batchGrantApplicationUpdateMutation } from './batchGrantApplicationUpdate'
--------------------------------------------------------------------------------
/src/generated/mutation/joinViaInviteLink.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const joinViaInviteLinkMutation = gql`mutation joinViaInviteLink($id: String!, $members: [String!]!, $roles: [Int!]!, $enabled: [Boolean!]!, $metadataHashes: [JSON!]!, $w: String!, $r: String!, $k: String!){
3 | joinViaInviteLink(id: $id, members: $members, roles: $roles, enabled: $enabled, metadataHashes: $metadataHashes, w: $w, r: $r, k: $k){
4 | recordId
5 | record{
6 | _id
7 | }
8 | }
9 | }
10 | `
--------------------------------------------------------------------------------
/src/generated/mutation/reSubmitProposal.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const reSubmitProposalMutation = gql `mutation updateGrantApplication(
3 | $id: String!,
4 | $grant: String!,
5 | $workspaceId: String!,
6 | $milestoneCount: Int,
7 | $milestones: JSON,
8 | $applicantId: String!,
9 | $applicantPublicKey: String,
10 | $fields:JSON
11 | $pii: JSON
12 | $state: String!
13 | $feedback: JSON
14 | ){
15 | updateGrantApplication(
16 | id: $id,
17 | grant: $grant,
18 | workspaceId: $workspaceId,
19 | milestoneCount: $milestoneCount,
20 | milestones: $milestones,
21 | applicantId: $applicantId,
22 | applicantPublicKey: $applicantPublicKey,
23 | fields:$fields
24 | pii: $pii
25 | state: $state
26 | feedback: $feedback
27 | ){
28 | record{
29 | _id
30 | }
31 | recordId
32 | }
33 | }`
--------------------------------------------------------------------------------
/src/generated/mutation/reclaimProof.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const reclaimProof = gql`mutation reclaimProof($type: String!, $address: String!, $proposalId: String, $pubKey: String){
3 | generateProof(type: $type, address: $address, proposalId: $proposalId, pubKey: $pubKey) {
4 | requestUrl
5 | statusUrl
6 | migrationId
7 | }
8 | }`
--------------------------------------------------------------------------------
/src/generated/mutation/sendDocuSign.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const sendDocuSign = gql`mutation sendDocuSign($id: String!, $proposalId: String!, $email: [JSON]!, $templateId: String!, $templateName: String!){
3 | sendDocuSign(id: $id, proposalId: $proposalId, email: $email, templateId: $templateId, templateName: $templateName){
4 | recordId
5 | record{
6 | _id
7 | }
8 | }
9 | }`
--------------------------------------------------------------------------------
/src/generated/mutation/setRubrics.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const setRubricsMutation = gql`mutation setRubric($workspaceId: String!, $grantId:String!, $metadataHash:JSON!){
3 | setRubric(workspaceId: $workspaceId, grantId: $grantId, metadataHash: $metadataHash){
4 | record{
5 | _id
6 | }
7 | recordId
8 | }
9 | }`
--------------------------------------------------------------------------------
/src/generated/mutation/submitProposal.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const submitProposalMutation = gql`mutation createNewGrantApplication(
3 | $grant: String!,
4 | $workspaceId: String!,
5 | $milestoneCount: Int!,
6 | $milestones: JSON!,
7 | $applicantId: String!,
8 | $applicantPublicKey: String!,
9 | $fields:JSON!
10 | $pii: JSON
11 | ){
12 | createNewGrantApplication(
13 | grant: $grant,
14 | workspaceId: $workspaceId,
15 | milestoneCount: $milestoneCount,
16 | milestones: $milestones,
17 | applicantId: $applicantId,
18 | applicantPublicKey: $applicantPublicKey,
19 | fields:$fields
20 | pii: $pii
21 | ){
22 | record{
23 | _id
24 | }
25 | recordId
26 | }
27 | }`
--------------------------------------------------------------------------------
/src/generated/mutation/submitReviews.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const submitReviewsMutation = gql`mutation submitReviews($workspaceId: String!,$applicationId: String!,$grantAddress: String!, $metadata: JSON!, $reviewerAddress: String!){
3 | submitReviews(workspaceId: $workspaceId, applicationId: $applicationId, grantAddress: $grantAddress, metadata: $metadata, reviewerAddress: $reviewerAddress){
4 | recordId
5 | record{
6 | _id
7 | }
8 | }
9 | }`
--------------------------------------------------------------------------------
/src/generated/mutation/updateBuilderProfile.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const updateBuilderProfile = gql`
3 | mutation updateBuilderProfile($telegram: String, $imageURL: String, $address: String!, $bio: String) {
4 | updateProfile(telegram: $telegram, imageURL: $imageURL, address: $address, bio: $bio) {
5 | recordId
6 | record {
7 | _id
8 | }
9 | }
10 | }
11 | `
--------------------------------------------------------------------------------
/src/generated/mutation/updateGrant.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client';
2 |
3 | export const updateGrant = gql`
4 | mutation updateGrant(
5 | $id: String!,
6 | $ownerId: String!,
7 | $title: String!,
8 | $bio: String!,
9 | $about: String!,
10 | $rewardCommitted: String!,
11 | $payoutType: String!,
12 | $link: String,
13 | $reviewType: String!,
14 | $fields: JSON!
15 | $milestones: [String]
16 | $workspace: String!,
17 | $rubrics: JSON
18 | ) {
19 | updateGrant(
20 | id: $id,
21 | ownerId: $ownerId,
22 | title: $title,
23 | bio: $bio,
24 | about: $about,
25 | rewardCommitted: $rewardCommitted,
26 | payoutType: $payoutType,
27 | link: $link,
28 | reviewType: $reviewType,
29 | fields: $fields
30 | milestones: $milestones
31 | workspace: $workspace,
32 | rubrics: $rubrics
33 | ) {
34 | recordId
35 | record {
36 | _id
37 | }
38 | }
39 | }
40 | `;
41 |
42 |
43 |
--------------------------------------------------------------------------------
/src/generated/mutation/updateMetadataWorkspace.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const updateMetadataWorkspaceMutation = gql`mutation updateWorkspaceMetadata($id: String!, $metadata: JSON!){
3 | updateWorkspaceMetadata(id: $id, metadata: $metadata){
4 | recordId
5 | record{
6 | _id
7 | }
8 | }
9 | }`
--------------------------------------------------------------------------------
/src/generated/mutation/updateWorkspaceMember.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const updateWorkspaceMemberMutation = gql`
3 | mutation updateWorkspaceMember($id: String!, $members: [String!]!, $roles: [Int!]!, $enabled: [Boolean!]!, $metadataHashes: [JSON!]!){
4 | updateWorkspaceMember(id: $id, members: $members, roles: $roles, enabled: $enabled, metadataHashes: $metadataHashes){
5 | recordId
6 | record{
7 | _id
8 | }
9 | }
10 | }
11 | `
--------------------------------------------------------------------------------
/src/generated/mutation/verifyToken.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const verifyTokenMutation = gql`
3 | mutation verifyToken($id: String!, $sign: String!){
4 | verifyToken(id: $id, sign: $sign){
5 | accessToken
6 | }
7 | }
8 | `
--------------------------------------------------------------------------------
/src/generated/mutation/workspaceUpdateSafe.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const workspaceUpdateSafeMutation = gql`
3 | mutation workspaceSafeUpdate($id: String!, $longSafeAddress: String!, $safeChainId: String!){
4 | workspaceSafeUpdate(id: $id, longSafeAddress: $longSafeAddress, safeChainId: $safeChainId){
5 | recordId
6 | record{
7 | _id
8 | }
9 | }
10 | }
11 | `
--------------------------------------------------------------------------------
/src/global.d.ts:
--------------------------------------------------------------------------------
1 | declare module '@biconomy/mexa';
2 |
3 | declare module '*.yaml' {
4 | const src: JSON
5 | export default src
6 | }
--------------------------------------------------------------------------------
/src/graphql/apollo.tsx:
--------------------------------------------------------------------------------
1 | import { ApolloClient, DocumentNode, InMemoryCache } from '@apollo/client'
2 | import logger from 'src/libraries/logger'
3 |
4 |
5 | export const ENDPOINT_CLIENT = process.env.BACKEND_URL
6 |
7 | export const client = new ApolloClient({
8 | uri: ENDPOINT_CLIENT,
9 | cache: new InMemoryCache(),
10 | queryDeduplication: true,
11 | defaultOptions: {
12 | watchQuery: {
13 | fetchPolicy: 'network-only',
14 | },
15 | query: {
16 | fetchPolicy: 'network-only',
17 | errorPolicy: 'all',
18 | },
19 | },
20 | })
21 |
22 |
23 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
24 | export async function executeMutation(mutation: DocumentNode, variables: any) {
25 | try {
26 | const response = await client.mutate({
27 | mutation,
28 | variables,
29 | context: {
30 | headers: {
31 | Authorization: `Bearer ${localStorage.getItem('authToken')}`,
32 | 'Content-Type': 'application/json',
33 | },
34 | },
35 | })
36 | const { data, errors } = response
37 |
38 | logger.info({ data, errors }, 'executeMutation')
39 | return data
40 | } catch(e) {
41 | logger.warn(e)
42 | }
43 | }
44 |
45 | export default client
46 |
47 |
--------------------------------------------------------------------------------
/src/graphql/subgraph.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | ApolloClient,
3 | HttpLink, InMemoryCache,
4 | } from '@apollo/client'
5 | import { CHAIN_INFO } from 'src/constants/chains'
6 | import { SupportedChainId } from 'src/constants/chains'
7 | import { GetLatestBlockDocument } from 'src/generated/graphql'
8 | import { delay } from 'src/libraries/utils'
9 |
10 | class SubgraphClient {
11 | client: ApolloClient<{ }>
12 |
13 | constructor(chainId: SupportedChainId) {
14 | const link = new HttpLink({ uri: CHAIN_INFO[chainId].subgraphClientUrl })
15 | const client = new ApolloClient({
16 | link,
17 | cache: new InMemoryCache(),
18 | })
19 | this.client = client
20 | this.waitForBlock = this.waitForBlock.bind(this)
21 | }
22 |
23 | async waitForBlock(blockNumber: number) {
24 | let latestBlockNumber = 0
25 | do {
26 | // Schedule a promise that will be ready once
27 | // the next Ethereum block will likely be available.
28 | const response = await this.client.query({
29 | query: GetLatestBlockDocument,
30 | fetchPolicy: 'network-only',
31 | })
32 | // eslint-disable-next-line no-underscore-dangle
33 | latestBlockNumber = response.data._meta.block.number
34 |
35 | // waiting for 4 seconds to fetch next block(s)
36 | await delay(4000)
37 | } while(latestBlockNumber < blockNumber)
38 | }
39 | }
40 |
41 | export default SubgraphClient
42 |
--------------------------------------------------------------------------------
/src/libraries/data/getAdminPublicKeysQuery.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 |
3 | export const getAdminPublicKeysQuery = gql`query getAdminPublicKeys($workspaceId: String!) {
4 | workspace(_id: $workspaceId) {
5 | members:membersFilter(filter: {_operators: {accessLevel: {
6 | ne:"reviewer"
7 | }}, enabled: true}) {
8 | id:_id
9 | actorId
10 | fullName
11 | publicKey
12 | }
13 | }
14 | }`
--------------------------------------------------------------------------------
/src/libraries/data/getBuilderProfileQuery.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const getBuilderProfileQuery = gql`query getBuilderInfo($wallet: String!){
3 | getProfile(filter:{
4 | address:$wallet
5 | }) {
6 | _id
7 | telegram
8 | username
9 | imageURL
10 | address
11 | }
12 | }`
--------------------------------------------------------------------------------
/src/libraries/data/getGrantManagersWithPublicKeyQuery.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const getGrantManagersWithPublicKeyQuery = gql`query getGrantManagersWithPublicKey($grantID: String!) {
3 | grantManagers(filter: {grant: $grantID}) {
4 | member {
5 | actorId,
6 | publicKey,
7 | enabled
8 | }
9 | }
10 | }`
--------------------------------------------------------------------------------
/src/libraries/data/getMemberPublicKeysQuery.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const getMemberPublicKeysQuery = gql`query getMemberPublicKeys($workspaceId: String!, $applicationIds: [String!]!) {
3 | workspace(_id: $workspaceId) {
4 | members: membersFilter(filter: {
5 | _operators:{
6 | accessLevel: {
7 | ne:"reviewer"
8 | }
9 | }
10 | enabled: false
11 | }) {
12 | actorId
13 | publicKey
14 | }
15 | }
16 | grantApplications(filter: {
17 | _operators:{
18 | _id: {
19 | in: $applicationIds
20 | }
21 | }
22 | }) {
23 | id:_id
24 | applicantId
25 | applicantPublicKey
26 | applicationReviewers {
27 | member(filter: {
28 | enabled: true
29 | }) {
30 | actorId
31 | publicKey
32 | }
33 | }
34 | }
35 | }
36 | `
--------------------------------------------------------------------------------
/src/libraries/data/getQBAdminsQuery.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const getQBAdminsQuery = gql`query getQBAdmins {
3 | qbAdmins {
4 | walletAddress
5 | }
6 | }
7 | `
--------------------------------------------------------------------------------
/src/libraries/data/getWorkspaceMemberExistsQuery.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const getWorkspaceMemberExistsQuery = gql`query getWorkspaceMemberExists($id: String!) {
3 | workspaceMember(_id: $id) {
4 | id:_id
5 | }
6 | }`
--------------------------------------------------------------------------------
/src/libraries/data/getWorkspaceMembersPublicKeysQuery.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const getWorkspaceMembersPublicKeysQuery = gql`query getWorkspaceMembersPublicKeys($workspaceId: String!) {
3 | workspaceMembers(filter: { workspace: $workspaceId, enabled: true }) {
4 | actorId
5 | publicKey
6 | }
7 | }`
--------------------------------------------------------------------------------
/src/libraries/data/getWorkspaceMembersQuery.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const getWorkspaceMembersQuery = gql`query getWorkspaceMembers($actorId: String!) {
3 | workspaceMembers(
4 | filter: { actorId: $actorId, enabled: true }
5 | sort: ADDEDAT_DESC
6 | ) {
7 | id:_id
8 | actorId
9 | enabled
10 | workspace {
11 | id:_id
12 | ownerId
13 | logoIpfsHash
14 | title
15 | supportedNetworks
16 | safe {
17 | id:_id
18 | chainId
19 | address
20 | }
21 | tokens {
22 | address
23 | label
24 | decimal
25 | iconHash
26 | }
27 | safe {
28 | address
29 | chainId
30 | }
31 | members: membersFilter(filter: { enabled: true }) {
32 | id:_id
33 | actorId
34 | publicKey
35 | fullName
36 | email
37 | accessLevel
38 | outstandingReviewIds
39 | lastReviewSubmittedAt
40 | profilePictureIpfsHash
41 | pii {
42 | id:_id
43 | data
44 | }
45 | }
46 | }
47 | }
48 | }
49 | `
--------------------------------------------------------------------------------
/src/libraries/graphql/getAdminPublicKeys.graphql:
--------------------------------------------------------------------------------
1 | query getAdminPublicKeys($workspaceId: String!) {
2 | workspace(_id: $workspaceId) {
3 | members:membersFilter(filter: {_operators: {accessLevel: {
4 | ne:"reviewer"
5 | }}, enabled: true}) {
6 | id:_id
7 | actorId
8 | fullName
9 | publicKey
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/src/libraries/graphql/getBuilderProfile.graphql:
--------------------------------------------------------------------------------
1 | query getBuilderInfo($wallet: String!){
2 | getProfile(filter:{
3 | address:$wallet
4 | }) {
5 | _id
6 | telegram
7 | username
8 | imageURL
9 | }
10 | }
--------------------------------------------------------------------------------
/src/libraries/graphql/getGrantManagersWithPublicKey.graphql:
--------------------------------------------------------------------------------
1 | query getGrantManagersWithPublicKey($grantID: String!) {
2 | grantManagers(filter: {grant: $grantID}) {
3 | member {
4 | actorId,
5 | publicKey,
6 | enabled
7 | }
8 | }
9 | }
--------------------------------------------------------------------------------
/src/libraries/graphql/getLatestBlock.graphql:
--------------------------------------------------------------------------------
1 | query getLatestBlock {
2 | _meta {
3 | block {
4 | number
5 | }
6 | }
7 | }
--------------------------------------------------------------------------------
/src/libraries/graphql/getMemberPublicKeys.graphql:
--------------------------------------------------------------------------------
1 | query getMemberPublicKeys($workspaceId: String!, $applicationIds: [String!]!) {
2 | workspace(_id: $workspaceId) {
3 | members: membersFilter(filter: {
4 | _operators:{
5 | accessLevel: {
6 | ne:"reviewer"
7 | }
8 | }
9 | enabled: false
10 | }) {
11 | actorId
12 | publicKey
13 | }
14 | }
15 | grantApplications(filter: {
16 | _operators:{
17 | _id: {
18 | in: $applicationIds
19 | }
20 | }
21 | }) {
22 | id:_id
23 | applicantId
24 | applicantPublicKey
25 | applicationReviewers {
26 | member(filter: {
27 | enabled: true
28 | }) {
29 | actorId
30 | publicKey
31 | }
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/libraries/graphql/getQBAdmins.graphql:
--------------------------------------------------------------------------------
1 | query getQBAdmins {
2 | qbAdmins {
3 | walletAddress
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/src/libraries/graphql/getWorkspaceMemberExists.graphql:
--------------------------------------------------------------------------------
1 | query getWorkspaceMemberExists($id: String!) {
2 | workspaceMember(_id: $id) {
3 | id:_id
4 | }
5 | }
--------------------------------------------------------------------------------
/src/libraries/graphql/getWorkspaceMembers.graphql:
--------------------------------------------------------------------------------
1 | query getWorkspaceMembers($actorId: String!) {
2 | workspaceMembers(
3 | filter: { actorId: $actorId, enabled: true }
4 | sort: ADDEDAT_DESC
5 | ) {
6 | id:_id
7 | actorId
8 | enabled
9 | workspace {
10 | id:_id
11 | ownerId
12 | logoIpfsHash
13 | title
14 | supportedNetworks
15 | safe {
16 | id:_id
17 | chainId
18 | address
19 | }
20 | tokens {
21 | address
22 | label
23 | decimal
24 | iconHash
25 | }
26 | safe {
27 | address
28 | chainId
29 | }
30 | members: membersFilter(filter: { enabled: true }) {
31 | id:_id
32 | actorId
33 | publicKey
34 | fullName
35 | email
36 | accessLevel
37 | outstandingReviewIds
38 | lastReviewSubmittedAt
39 | profilePictureIpfsHash
40 | pii {
41 | id:_id
42 | data
43 | }
44 | }
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/libraries/graphql/getWorkspaceMembersPublicKeys.graphql:
--------------------------------------------------------------------------------
1 | query getWorkspaceMembersPublicKeys($workspaceId: String!) {
2 | workspaceMembers(filter: { workspace: $workspaceId, enabled: true }) {
3 | actorId
4 | publicKey
5 | }
6 | }
--------------------------------------------------------------------------------
/src/libraries/hooks/DAOSearchContext.ts:
--------------------------------------------------------------------------------
1 | import { useState } from 'react'
2 | import { ContextGenerator } from 'src/libraries/utils/contextGenerator'
3 |
4 | const useDaoSearch = () => {
5 | const [searchString, setSearchString] = useState()
6 |
7 | return {
8 | searchString,
9 | setSearchString,
10 | }
11 | }
12 |
13 | export const {
14 | context: DAOSearchContext,
15 | contextMaker: DAOSearchContextMaker,
16 | } = ContextGenerator(useDaoSearch)
17 |
--------------------------------------------------------------------------------
/src/libraries/hooks/QBAdminsContext.ts:
--------------------------------------------------------------------------------
1 | import { useContext, useMemo } from 'react'
2 | import { defaultChainId } from 'src/constants/chains'
3 | import { useGetQbAdminsQuery } from 'src/generated/graphql'
4 | import { ContextGenerator } from 'src/libraries/utils/contextGenerator'
5 | import { ApiClientsContext, WebwalletContext } from 'src/pages/_app'
6 |
7 | const useGetQBAdmins = () => {
8 | const { subgraphClients } = useContext(ApiClientsContext)!
9 | const { webwallet, scwAddress } = useContext(WebwalletContext)!
10 |
11 | const { client } = subgraphClients[defaultChainId]
12 | const { data: adminData, loading, error } = useGetQbAdminsQuery({ client })
13 |
14 | const isQbAdmin = useMemo(() => {
15 | const scwLower = scwAddress?.toLowerCase()
16 | const webwalletLower = webwallet?.address?.toLowerCase()
17 |
18 | return !!adminData?.qbadmins.find(admin => {
19 | const adminLower = admin.walletAddress.toLowerCase()
20 | return adminLower === scwLower || adminLower === webwalletLower
21 | })
22 | }, [adminData, scwAddress, webwallet])
23 |
24 | return {
25 | isQbAdmin,
26 | loading,
27 | error,
28 | qbAdmins: adminData?.qbadmins.map((admin) => admin.walletAddress) || [],
29 | }
30 | }
31 |
32 | export const {
33 | context: QBAdminsContext,
34 | contextMaker: QBAdminsContextMaker,
35 | } = ContextGenerator(useGetQBAdmins)
36 |
--------------------------------------------------------------------------------
/src/libraries/hooks/gasless/useBiconomy.ts:
--------------------------------------------------------------------------------
1 | import { useContext, useEffect } from 'react'
2 | import logger from 'src/libraries/utils/logger'
3 | import { BiconomyContext, WebwalletContext } from 'src/pages/_app'
4 |
5 | export const useBiconomy = (props: { chainId?: string }) => {
6 | const { webwallet, scwAddress, nonce } = useContext(WebwalletContext)!
7 | const { biconomyDaoObjs, biconomyWalletClients, loadingBiconomyMap, initiateBiconomy } = useContext(BiconomyContext)!
8 |
9 | useEffect(() => {
10 | if(typeof window === 'undefined') {
11 | return
12 | }
13 |
14 | const chainId = props.chainId
15 |
16 | if(!webwallet || !nonce || !chainId) {
17 | return
18 | }
19 |
20 | initiateBiconomy(chainId)
21 | }, [initiateBiconomy, props.chainId, nonce])
22 |
23 | useEffect(() => {
24 | logger.info({ biconomyWalletClients, isPresent: biconomyWalletClients?.[props.chainId!], chainId: props.chainId, isPresentInt: biconomyWalletClients?.[parseInt(props.chainId!)] }, 'Biconomy Wallet Client')
25 | }, [biconomyWalletClients])
26 |
27 | return {
28 | biconomyDaoObj: (!!biconomyDaoObjs && props.chainId) ? biconomyDaoObjs[props.chainId] : undefined,
29 | biconomyWalletClient: (!!biconomyWalletClients && props.chainId) ? biconomyWalletClients[props.chainId] : undefined,
30 | scwAddress: scwAddress,
31 | loading: !!loadingBiconomyMap[props.chainId!],
32 | }
33 | }
--------------------------------------------------------------------------------
/src/libraries/hooks/gasless/useNetwork.ts:
--------------------------------------------------------------------------------
1 |
2 | import { useContext, useMemo } from 'react'
3 | import { CHAIN_INFO, defaultChainId } from 'src/constants/chains'
4 | import { WebwalletContext } from 'src/pages/_app'
5 |
6 | export const useNetwork = () => {
7 | const { network, switchNetwork } = useContext(WebwalletContext)!
8 |
9 | const data = useMemo(() => {
10 | if(network && network in CHAIN_INFO) {
11 | return CHAIN_INFO[network]
12 | }
13 |
14 | return CHAIN_INFO[defaultChainId]
15 | }, [network])
16 |
17 | return { activeChain: network, network, switchNetwork, data }
18 | }
19 |
--------------------------------------------------------------------------------
/src/libraries/hooks/gasless/useQuestbookAccount.ts:
--------------------------------------------------------------------------------
1 | import { useContext, useMemo } from 'react'
2 | import { WebwalletContext } from 'src/pages/_app'
3 |
4 | export const useQuestbookAccount = () => {
5 | const { webwallet, scwAddress, setNonce, nonce } = useContext(WebwalletContext)!
6 |
7 | // const [gaslessData, setGaslessData] = useState()
8 | const gaslessData2 = useMemo(() => {
9 | if(scwAddress && nonce && webwallet) {
10 | return {
11 | address: scwAddress,
12 | connector: {
13 | name: 'gasless-webwallet'
14 | }
15 | }
16 | }
17 |
18 | return undefined
19 | }, [webwallet, scwAddress, nonce])
20 |
21 | return { data: gaslessData2, nonce, setNonce }
22 | }
--------------------------------------------------------------------------------
/src/libraries/hooks/useQuery.ts:
--------------------------------------------------------------------------------
1 | import { useState } from 'react'
2 | import { DocumentNode } from '@apollo/client'
3 | import { logger } from 'ethers'
4 | import client from 'src/graphql/apollo'
5 |
6 | type UseQueryOptions = {
7 | query: DocumentNode
8 | };
9 |
10 |
11 | type QueryResult = T | undefined;
12 | export function useQuery({ query }: UseQueryOptions) {
13 | const [results, setResults] = useState>(undefined)
14 |
15 | async function fetchMore(variables?: Partial, reset?: boolean, retries = 2): Promise {
16 | if(reset) {
17 | setResults(undefined)
18 | }
19 |
20 | try {
21 | const { data, error } = await client.query({
22 | query,
23 | variables,
24 | })
25 |
26 | if(data) {
27 | setResults(data)
28 | }
29 |
30 | if(error) {
31 | logger.warn(error)
32 | if(retries > 0) {
33 | await fetchMore(variables, reset, retries - 1)
34 | logger.info(`Retrying... Attempts left: ${retries}`)
35 | }
36 | }
37 |
38 | return data
39 | } catch(error) {
40 | if(error && retries > 0) {
41 | logger.info(`Encountered 503 error. Retrying... Attempts left: ${retries}`)
42 | return await fetchMore(variables, reset, retries - 2)
43 | } else {
44 | logger.warn('Retries exhausted or different error encountered.')
45 | return undefined
46 | }
47 | }
48 | }
49 |
50 | return {
51 | results,
52 | fetchMore,
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/libraries/hooks/utils/useChainId.ts:
--------------------------------------------------------------------------------
1 | import { useMemo } from 'react'
2 | import { useNetwork } from 'src/libraries/hooks/gasless/useNetwork'
3 |
4 | /**
5 | * Return the chain ID if supported by the app, otherwise return undefined
6 | * @returns the chain ID if supported -- undefined otherwise
7 | */
8 | export default function useChainId() {
9 | // @TODO-gasless: Change here!
10 | const { data } = useNetwork()
11 | const id = useMemo(() => data.id, [data])
12 | return id
13 | }
14 |
--------------------------------------------------------------------------------
/src/libraries/logger.ts:
--------------------------------------------------------------------------------
1 | import P from 'pino'
2 |
3 | const logger = P()
4 |
5 | const defaultLogLevel = process.env.NODE_ENV === 'production' ? 'silent' : 'debug'
6 | const logLevel = process.env.LOG_LEVEL || defaultLogLevel
7 | logger.level = logLevel
8 |
9 | export default logger
--------------------------------------------------------------------------------
/src/libraries/ui/BackButton.tsx:
--------------------------------------------------------------------------------
1 | import { Button, ButtonProps, Text } from '@chakra-ui/react'
2 | import { useRouter } from 'next/router'
3 | import { ArrowLeft } from 'src/generated/icons'
4 |
5 | function BackButton(props: ButtonProps) {
6 | const buildComponent = () => {
7 | return (
8 | }
12 | onClick={
13 | () => {
14 | router.back()
15 | }
16 | }
17 | {...props}>
18 |
19 | Back
20 |
21 |
22 | )
23 | }
24 |
25 | const router = useRouter()
26 | return buildComponent()
27 | }
28 |
29 | export default BackButton
--------------------------------------------------------------------------------
/src/libraries/ui/CopyIcon.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Tooltip } from '@chakra-ui/react'
3 | import copy from 'copy-to-clipboard'
4 | import { Copy } from 'src/generated/icons'
5 |
6 | type Props = {
7 | text: string
8 | }
9 |
10 | function CopyIcon({ text }: Props) {
11 | const defaultTooltip = 'Copy'
12 | const copiedTooltip = 'Copied'
13 |
14 | const [tooltipLabel, setTooltipLabel] = React.useState(defaultTooltip)
15 |
16 | return (
17 |
18 | {
25 | copy(text)
26 | setTooltipLabel(copiedTooltip)
27 | }
28 | } />
29 |
30 |
31 | )
32 | }
33 |
34 | export default CopyIcon
35 |
--------------------------------------------------------------------------------
/src/libraries/ui/NavBar/_components/IssueWarning.tsx:
--------------------------------------------------------------------------------
1 | import { FaExclamationCircle } from 'react-icons/fa'
2 | import { Flex, Icon, Text } from '@chakra-ui/react'
3 |
4 | const IssueWarning = () => {
5 | return (
6 |
14 |
19 |
25 | Due to the ongoing issue with our subgraph node, we have temporarily disabled proposal submissions. Our team is actively working on resolving the problem. We apologize for any inconvenience.
26 |
27 |
28 | )
29 | }
30 |
31 | export default IssueWarning
--------------------------------------------------------------------------------
/src/libraries/ui/NavBar/_components/googleRecoveryTypes.ts:
--------------------------------------------------------------------------------
1 | interface GoogleRecoveryMechanismOptions {
2 | // Basic options
3 | googleClientId: string
4 | folderNameGD: string
5 | fileNameGD: string
6 |
7 | // Options handling multi key case.
8 | // TODO add more options maybe?
9 | allowMultiKeys: boolean
10 | handleExistingKey: 'Error' | 'Overwrite'
11 | }
12 |
13 | export interface Metadata {
14 | name: string
15 | parents: string[]
16 | mimeType: string
17 | }
18 |
19 | export type { GoogleRecoveryMechanismOptions }
--------------------------------------------------------------------------------
/src/libraries/ui/NavBar/_utils/constants.ts:
--------------------------------------------------------------------------------
1 | const DOMAIN_CACHE_KEY = 'current-domain'
2 | const ROLE_CACHE = 'role'
3 |
4 | export { DOMAIN_CACHE_KEY, ROLE_CACHE }
--------------------------------------------------------------------------------
/src/libraries/ui/QRCodeModal.tsx:
--------------------------------------------------------------------------------
1 | import { useContext } from 'react'
2 | import QRCode from 'react-qr-code'
3 | import { Box, Flex, Modal, ModalCloseButton, ModalContent, ModalOverlay, Text } from '@chakra-ui/react'
4 | import { NotificationContext } from 'src/pages/_app'
5 |
6 | function QRCodeModal() {
7 | const buildComponent = () => {
8 | return (
9 | {
15 | setQrCodeText(undefined)
16 | }
17 | }>
18 |
19 |
20 |
21 |
26 |
29 | Scan QR code with your phone camera
30 |
31 |
32 |
36 |
37 |
38 |
39 | )
40 | }
41 |
42 | const { qrCodeText, setQrCodeText } = useContext(NotificationContext)!
43 |
44 | return buildComponent()
45 | }
46 |
47 | export default QRCodeModal
--------------------------------------------------------------------------------
/src/libraries/ui/RichTextEditor/loader.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Center, CircularProgress } from '@chakra-ui/react'
3 |
4 | interface Props {
5 | size?: string | number
6 | mt?: string | number
7 | }
8 |
9 | function Loader({ size, mt }: Props) {
10 | return (
11 |
12 |
17 |
18 | )
19 | }
20 |
21 | Loader.defaultProps = {
22 | size: '32px',
23 | mt: 0,
24 | }
25 |
26 | export default Loader
--------------------------------------------------------------------------------
/src/libraries/ui/SearchField.tsx:
--------------------------------------------------------------------------------
1 | import { Input, InputGroup, InputGroupProps, InputLeftElement, InputProps } from '@chakra-ui/react'
2 | import { Search } from 'src/generated/icons'
3 |
4 | function SearchField(props: InputProps & {inputGroupProps?: InputGroupProps}) {
5 | const buildComponent = () => {
6 | return (
7 |
8 |
11 |
14 |
15 |
16 |
17 | )
18 | }
19 |
20 | return buildComponent()
21 | }
22 |
23 | export default SearchField
--------------------------------------------------------------------------------
/src/libraries/utils/amplitude.tsx:
--------------------------------------------------------------------------------
1 | import { createContext, useEffect, useState } from 'react'
2 | import { init, track } from '@amplitude/analytics-browser'
3 |
4 | const AMPLITUDE_API_KEY = process.env.AMPLITUDE_API_KEY!
5 |
6 | const AmplitudeContext = createContext<{
7 | trackAmplitudeEvent: (eventName: string, eventProperties: object) => void
8 | }>({
9 | trackAmplitudeEvent: () => {},
10 | })
11 |
12 | const AmplitudeProvider = ({ children }: { children: React.ReactNode }) => {
13 | const [initialized, setInitialized] = useState(false)
14 |
15 | useEffect(() => {
16 | if(!initialized) {
17 | init(AMPLITUDE_API_KEY, undefined, {
18 | defaultTracking: {
19 | sessions: true,
20 | attribution: true,
21 | pageViews: true,
22 | formInteractions: true,
23 | },
24 | })
25 | setInitialized(true)
26 | }
27 | }, [initialized])
28 |
29 | const trackAmplitudeEvent = (eventName: string, eventProperties: object) => {
30 | track(eventName, eventProperties)
31 | }
32 |
33 | return (
34 |
35 | {children}
36 |
37 | )
38 | }
39 |
40 | export {
41 | AmplitudeProvider,
42 | AmplitudeContext,
43 | }
--------------------------------------------------------------------------------
/src/libraries/utils/authToken.ts:
--------------------------------------------------------------------------------
1 | import { logger } from 'ethers'
2 | import { generateTokenMutation, verifyTokenMutation } from 'src/generated/mutation'
3 | import { executeMutation } from 'src/graphql/apollo'
4 |
5 | export const generateToken = async(address: string) => {
6 | const generate = await executeMutation(generateTokenMutation, { address })
7 | logger.info(generate.generateToken.record, 'generateToken')
8 | if(!generate?.generateToken?.record) {
9 | throw new Error('Unable to generate token')
10 | }
11 |
12 |
13 | return generate.generateToken.record
14 | }
15 |
16 | export const verifyToken = async(id: string, sign: string) => {
17 | const verify = await executeMutation(verifyTokenMutation, { id, sign })
18 | if(!verify?.verifyToken?.accessToken) {
19 | throw new Error('Unable to verify token')
20 | }
21 |
22 | return verify.verifyToken.accessToken
23 | }
--------------------------------------------------------------------------------
/src/libraries/utils/constants.tsx:
--------------------------------------------------------------------------------
1 | import { Metamask, Openmask, Phantom, WalletConnect } from 'src/generated/icons'
2 |
3 | export const MONTH_MAP: {[key: string]: string} = {
4 | '01': 'Jan',
5 | '02': 'Feb',
6 | '03': 'Mar',
7 | '04': 'Apr',
8 | '05': 'May',
9 | '06': 'Jun',
10 | '07': 'Jul',
11 | '08': 'Aug',
12 | '09': 'Sep',
13 | '10': 'Oct',
14 | '11': 'Nov',
15 | '12': 'Dec',
16 | }
17 |
18 | export const chainNames = new Map([
19 | ['1', 'Ethereum Mainnet'],
20 | ['5', 'Goerli Testnet'],
21 | ['10', 'Optimism Mainnet'],
22 | ['40', 'Telos Mainnet'],
23 | ['137', 'Polygon Mainnet'],
24 | ['42220', 'Celo Mainnet'],
25 | ['9001', 'Solana'],
26 | ['90001', 'Solana'],
27 | ['900001', 'Solana'],
28 | ])
29 |
30 | export const availableWallets = [{
31 | name: 'Metamask',
32 | icon: ,
35 | isPopular: true,
36 | id: 'injected',
37 | }, {
38 | name: 'WalletConnect',
39 | icon: ,
42 | isPopular: false,
43 | id: 'walletConnect'
44 | }]
45 |
46 | export const solanaWallets = [{
47 | name: 'Phantom',
48 | icon: ,
51 | isPopular: false,
52 | id: 'phantom',
53 | }]
54 | export const tonWallets = [{
55 | name: 'OpenMask',
56 | icon: ,
59 | ispopular:false,
60 | id:'openMask'
61 | }]
--------------------------------------------------------------------------------
/src/libraries/utils/contextGenerator.ts:
--------------------------------------------------------------------------------
1 | import { createContext, createElement, ReactNode } from 'react'
2 |
3 | /**
4 | * Makes a context for a store and a component to provide the store
5 | */
6 | export function ContextGenerator(store: () => T) {
7 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
8 | const context = createContext(undefined as any)
9 | return {
10 | context,
11 | contextMaker: ({ children }: {children: ReactNode}) => {
12 | const value = store()
13 | return createElement(context.Provider, { value }, children)
14 | },
15 | }
16 | }
--------------------------------------------------------------------------------
/src/libraries/utils/getSCWAddress.ts:
--------------------------------------------------------------------------------
1 | import { ethers } from 'ethers'
2 | import ABI from 'src/contracts/abi/WalletAbi.json'
3 |
4 | export const getSCWAddress = async(address: string) => {
5 | try {
6 | const scw = '0x050bca32264195976Fe00BcA566B548413A9E658'
7 | const fetchAddress = async(provider: string, address: string) => {
8 | const providerConfig = new ethers.providers.AlchemyProvider(provider, 'YKJ826SHB7c7rV5dDzcubjX8LzYRVdvn')
9 | const scwContract = new ethers.Contract(scw, ABI, providerConfig)
10 | const result = await scwContract.getAddressForCounterfactualWallet(address, 0)
11 | const check = await scwContract.isWalletExist(result)
12 | return check ? result : false
13 | }
14 |
15 | const optimismAddress = await fetchAddress('optimism', address)
16 | return { doesWalletExist: !!optimismAddress, walletAddress: optimismAddress ? optimismAddress : address }
17 | } catch(e) {
18 | throw new Error(`Error fetching address: ${e}`)
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/libraries/utils/index.ts:
--------------------------------------------------------------------------------
1 | export const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))
2 |
3 | export function getAvatar(initials: boolean, address: string | null | undefined) {
4 | let url = ''
5 | if(!address) {
6 | url = '/v2/images/default_profile_picture.png'
7 | // } else if(initials) {
8 | // address = address.toLowerCase()
9 | // // violet 2, teal 2, orange 2, crimson 2, pink 2
10 | // const colors = ['785EF0', '10AEBA', 'FF7545', 'FF4C4D', 'E281BF']
11 | // const colorId = address ? address.charCodeAt(0) % 5 : Math.floor(Math.random() * 5)
12 | // const color = colors[colorId]
13 | // url = `https://api.dicebear.com/7.x/identicon/svg?seed=${address}&fontSize=32&backgroundColor=%23${color}`
14 | } else {
15 | address = address.toLowerCase()
16 | url = `https://api.dicebear.com/7.x/identicon/svg?seed=${address}`
17 | }
18 |
19 | return url
20 |
21 | }
--------------------------------------------------------------------------------
/src/libraries/utils/logger.ts:
--------------------------------------------------------------------------------
1 | import P from 'pino'
2 |
3 | const logger = P()
4 |
5 | const defaultLogLevel = process.env.NODE_ENV === 'production' ? 'silent' : 'debug'
6 | const logLevel = process.env.LOG_LEVEL || defaultLogLevel
7 | logger.level = logLevel
8 |
9 | export default logger
--------------------------------------------------------------------------------
/src/libraries/utils/seo.ts:
--------------------------------------------------------------------------------
1 | import seoConfig from 'src/constants/seo'
2 |
3 | type GetSeoOptions = {
4 | omitOpenGraphImage?: boolean
5 | };
6 |
7 | function getSeo(options: GetSeoOptions = {}) {
8 | const { omitOpenGraphImage } = options
9 | const { images, ...openGraph } = seoConfig.openGraph
10 |
11 | return {
12 | ...seoConfig,
13 | openGraph: {
14 | ...openGraph,
15 | images: omitOpenGraphImage ? undefined : images,
16 | },
17 | }
18 | }
19 |
20 | export default getSeo
21 |
--------------------------------------------------------------------------------
/src/libraries/utils/token.ts:
--------------------------------------------------------------------------------
1 | import { CHAIN_INFO, SupportedChainId } from 'src/constants/chains'
2 | import { Grant } from 'src/generated/graphql'
3 | import { getUrlForIPFSHash } from 'src/libraries/utils/ipfs'
4 | import { ChainInfo } from 'src/types'
5 |
6 | export function getChainInfo(
7 | grant: {
8 | reward: Pick & {
9 | token?: Pick<
10 | Exclude,
11 | 'iconHash' | 'label' | 'decimal' | 'address'
12 | > | undefined | null
13 | }
14 | },
15 | chainId: SupportedChainId,
16 | ): ChainInfo['supportedCurrencies'][string] {
17 | // let chainInfo: ChainInfo['supportedCurrencies'][string]
18 | let tokenIcon: string
19 | let chainInfo =
20 | CHAIN_INFO[chainId]?.supportedCurrencies[grant.reward.asset.toLowerCase()]
21 |
22 | if(!chainInfo && grant.reward.token) {
23 | tokenIcon = getUrlForIPFSHash(grant.reward.token.iconHash)
24 | chainInfo = {
25 | address: grant.reward.token.address,
26 | label: grant.reward.token.label,
27 | pair: undefined,
28 | decimals: +grant.reward.token.decimal,
29 | icon: tokenIcon,
30 | }
31 | } else if(!chainInfo && !grant.reward.token) {
32 | chainInfo = {
33 | address: '',
34 | label: 'UNSUP',
35 | decimals: 18,
36 | pair: undefined,
37 | icon: '',
38 | }
39 | }
40 |
41 | return chainInfo
42 | }
43 |
--------------------------------------------------------------------------------
/src/libraries/utils/types.ts:
--------------------------------------------------------------------------------
1 | export type PIIForCommentType = {
2 | sender?: string
3 | message?: string
4 | timestamp?: number
5 | role?: string
6 | tag?: string
7 | pii?: {[key: string]: string}
8 | }
--------------------------------------------------------------------------------
/src/libraries/validator/utils/generateTypes.ts:
--------------------------------------------------------------------------------
1 | import { readFile, writeFile } from 'fs/promises'
2 | import { load } from 'js-yaml'
3 | import { compile } from 'json-schema-to-typescript'
4 | import path from 'path'
5 |
6 | const GEN_TYPES_FILE = './src/types/gen.d.ts'
7 |
8 | async function main() {
9 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
10 | const schema = await readYaml('src/libraries/validator/schema.yaml')
11 | // console.log('Generating types for schema...', schema)
12 | const result = await compile(schema.Validations, 'Schema', {
13 | maxItems: -1,
14 | $refOptions: {
15 | resolve: {
16 | file: {
17 | read: (file) => {
18 | const parsed = path.parse(file.url)
19 | return schema[parsed.name]
20 | }
21 | }
22 | }
23 | }
24 | })
25 | await writeFile(GEN_TYPES_FILE, result)
26 | }
27 |
28 | async function readYaml(file: string) {
29 | const yaml = await readFile(file, { encoding: 'utf-8' })
30 | return load(yaml) as T
31 | }
32 |
33 | main()
--------------------------------------------------------------------------------
/src/pages/grantees.tsx:
--------------------------------------------------------------------------------
1 | import _ from 'src/screens/grantees'
2 | export default _
--------------------------------------------------------------------------------
/src/pages/index.tsx:
--------------------------------------------------------------------------------
1 | import _ from 'src/screens/discover'
2 | export default _
3 |
--------------------------------------------------------------------------------
/src/pages/profile/[address].tsx:
--------------------------------------------------------------------------------
1 | import { GetServerSidePropsContext } from 'next'
2 | import _ from 'src/screens/profile'
3 | import { ProfileDataType } from 'src/screens/profile/_utils/types'
4 |
5 | export default _
6 |
7 | export async function getServerSideProps(context: GetServerSidePropsContext) {
8 | const { address } = context.query
9 |
10 |
11 | if(typeof address !== 'string') {
12 | return {
13 | parseError: true
14 | }
15 | }
16 |
17 | let dynamicData: ProfileDataType
18 |
19 | try {
20 | dynamicData = { address }
21 |
22 | } catch(error) {
23 | return {
24 | notFound: true,
25 | }
26 | }
27 |
28 | return {
29 | props: {
30 | dynamicData
31 | },
32 | }
33 | }
--------------------------------------------------------------------------------
/src/pages/proposal_form.tsx:
--------------------------------------------------------------------------------
1 | import _ from 'src/screens/proposal_form'
2 | export default _
--------------------------------------------------------------------------------
/src/pages/proposal_recovery.tsx:
--------------------------------------------------------------------------------
1 | import _ from 'src/screens/proposal_recovery'
2 | export default _
--------------------------------------------------------------------------------
/src/pages/request_proposal.tsx:
--------------------------------------------------------------------------------
1 | import _ from 'src/screens/request_proposal'
2 | export default _
--------------------------------------------------------------------------------
/src/pages/settings.tsx:
--------------------------------------------------------------------------------
1 | import _ from 'src/screens/settings'
2 | export default _
--------------------------------------------------------------------------------
/src/pages/setup_profile.tsx:
--------------------------------------------------------------------------------
1 | import _ from 'src/screens/setup_profile'
2 | export default _
--------------------------------------------------------------------------------
/src/screens/dashboard/ActionList.tsx:
--------------------------------------------------------------------------------
1 | // This renders the action-section, namely Reviews, Milestones and Payouts, that will show up as the third column
2 |
3 | import { useContext } from 'react'
4 | import { Flex } from '@chakra-ui/react'
5 | import MultiSelect from 'src/screens/dashboard/_components/ActionList/MultiSelect'
6 | import SingleSelect from 'src/screens/dashboard/_components/ActionList/SingleSelect'
7 | import { DashboardContext } from 'src/screens/dashboard/Context'
8 |
9 | function ActionList() {
10 | const buildComponent = () => (
11 |
18 | {selectedProposals.size > 1 ? : }
19 |
20 |
21 |
22 | )
23 |
24 | const { selectedProposals } = useContext(DashboardContext)!
25 |
26 | return buildComponent()
27 | }
28 |
29 | export default ActionList
--------------------------------------------------------------------------------
/src/screens/dashboard/Banner.tsx:
--------------------------------------------------------------------------------
1 | import { Flex, Text } from '@chakra-ui/react'
2 |
3 | function Banner({ message, link, linkText }: { message: string, link?: string, linkText?: string }) {
4 | return (
5 |
18 |
25 | {message}
26 |
27 | {
28 | link && linkText && (
29 | window.open(link, '_blank')}
36 | mx={2}
37 | >
38 | {linkText}
39 |
40 | )
41 | }
42 |
43 | )
44 | }
45 |
46 | export default Banner
47 |
--------------------------------------------------------------------------------
/src/screens/dashboard/Body.tsx:
--------------------------------------------------------------------------------
1 | // This renders the single proposal along with the Discussion section or the aggregated proposals, and shows up as the 2nd column
2 |
3 | import { useContext } from 'react'
4 | import { Flex } from '@chakra-ui/react'
5 | import Empty from 'src/screens/dashboard/_components/Body/Empty'
6 | import MultiSelect from 'src/screens/dashboard/_components/Body/MultiSelect'
7 | import SingleSelect from 'src/screens/dashboard/_components/Body/SingleSelect'
8 | import { DashboardContext } from 'src/screens/dashboard/Context'
9 |
10 | function Body() {
11 | const buildComponent = () => {
12 | return (
13 |
16 | {selectedProposals.size > 1 ? : selectedProposals.size === 1 ? : }
17 |
18 | )
19 | }
20 |
21 | const { selectedProposals } = useContext(DashboardContext)!
22 |
23 | return buildComponent()
24 | }
25 |
26 | export default Body
--------------------------------------------------------------------------------
/src/screens/dashboard/_components/Body/SingleSelect/index.tsx:
--------------------------------------------------------------------------------
1 | import { Flex, useMediaQuery } from '@chakra-ui/react'
2 | import Discussions from 'src/screens/dashboard/_components/Body/SingleSelect/Discussions'
3 | import Proposal from 'src/screens/dashboard/_components/Body/SingleSelect/Proposal'
4 | import ActionList from 'src/screens/dashboard/ActionList'
5 |
6 | function SingleSelect() {
7 | const buildComponent = () => (
8 |
12 |
13 | {
14 | isMobile[0] && (
15 | )
16 | }
17 |
18 |
19 | )
20 | const isMobile = useMediaQuery(['(max-width:959px)'])
21 |
22 | return buildComponent()
23 | }
24 |
25 | export default SingleSelect
--------------------------------------------------------------------------------
/src/screens/dashboard/_components/DashboardInput.tsx:
--------------------------------------------------------------------------------
1 | import { Input, InputProps } from '@chakra-ui/react'
2 |
3 | function DashboardInput(props: InputProps) {
4 | const buildComponent = () => {
5 | return (
6 |
14 | )
15 | }
16 |
17 | return buildComponent()
18 | }
19 |
20 | export default DashboardInput
--------------------------------------------------------------------------------
/src/screens/dashboard/_components/FundBuilder/PaidByWallet.tsx:
--------------------------------------------------------------------------------
1 | import { Flex, Text } from '@chakra-ui/react'
2 |
3 | const PaidByWallet = () => {
4 | const buildComponent = () => (
5 |
10 |
11 | Fund Builder
12 |
13 |
14 |
24 |
25 |
28 | Payouts done to the applicant through TON Wallet
29 |
30 |
31 |
32 |
33 | )
34 |
35 | return buildComponent()
36 | }
37 |
38 | export default PaidByWallet
--------------------------------------------------------------------------------
/src/screens/dashboard/_components/FundBuilder/PayFromChoose.tsx:
--------------------------------------------------------------------------------
1 | import { Flex, Image, Text } from '@chakra-ui/react'
2 |
3 | function PayFromChoose({ selectedMode }: { selectedMode: {logo: string | undefined, value: string | undefined} | undefined}) {
4 | const buildComponent = () => {
5 | return (
6 |
11 |
14 | Pay From
15 |
16 |
17 |
20 |
24 | {selectedMode?.value}
25 |
26 |
27 |
28 | )
29 | }
30 |
31 | return buildComponent()
32 | }
33 |
34 | export default PayFromChoose
--------------------------------------------------------------------------------
/src/screens/dashboard/_components/RoleTag.tsx:
--------------------------------------------------------------------------------
1 | import { Text } from '@chakra-ui/react'
2 | import { Roles } from 'src/types'
3 |
4 | interface Props {
5 | role: Roles
6 | isBuilder?: boolean
7 | }
8 |
9 | function RoleTag({ role, isBuilder = false }: Props) {
10 | const buildComponent = () => {
11 | return (
12 |
20 | {role === 'admin' || role === 'reviewer' ? config[role].text : role === 'builder' && isBuilder ? config.builder.text : config.community.text}
21 |
22 | )
23 | }
24 |
25 | const config = {
26 | admin: {
27 | bg: 'accent.azure',
28 | text: 'Admin'
29 | },
30 | reviewer: {
31 | bg: 'accent.carrot',
32 | text: 'Reviewer'
33 | },
34 | builder: {
35 | bg: 'accent.royal',
36 | text: 'Builder'
37 | },
38 | community: {
39 | bg: 'accent.orchid',
40 | text: 'Community'
41 | }
42 | }
43 |
44 | return buildComponent()
45 | }
46 |
47 | export default RoleTag
--------------------------------------------------------------------------------
/src/screens/dashboard/_components/ThreeColumnSkeleton.tsx:
--------------------------------------------------------------------------------
1 | import { useContext } from 'react'
2 | import { Flex, Skeleton, SkeletonText } from '@chakra-ui/react'
3 | import { GrantsProgramContext } from 'src/pages/_app'
4 |
5 | function ThreeColumnSkeleton() {
6 | const buildComponent = () => {
7 | return (
8 |
13 | {
14 | ['25%', '48%', '25%'].map((width, index) => {
15 | return (
16 |
22 | {loadingComponent()}
23 |
24 | )
25 | })
26 | }
27 |
28 | )
29 | }
30 |
31 | const loadingComponent = () => {
32 | return (
33 |
39 |
43 |
47 |
48 | )
49 | }
50 |
51 | const { isLoading } = useContext(GrantsProgramContext)!
52 |
53 | return buildComponent()
54 | }
55 |
56 | export default ThreeColumnSkeleton
--------------------------------------------------------------------------------
/src/screens/dashboard/_data/getApplicationActionsQuery.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const getApplicationActionsQuery = gql`
3 | query getApplicationActions($grantId: String!) {
4 | grantApplications(filter: { grant: $grantId }) {
5 | id:_id
6 | applicantId
7 | applicantPublicKey
8 | actions {
9 | id:_id
10 | updatedBy
11 | updatedAtS
12 | state
13 | feedback
14 | }
15 | grant {
16 | id:_id
17 | workspace {
18 | members:membersFilter {
19 | actorId
20 | fullName
21 | profilePictureIpfsHash
22 | publicKey
23 | accessLevel
24 | }
25 | supportedNetworks
26 | }
27 | }
28 | }
29 | }
30 | `
--------------------------------------------------------------------------------
/src/screens/dashboard/_data/getBuilderInfoQuery.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const getBuilderInfoQuery = gql`query getBuilderInfo($id: String!) {
3 | builder(applicationId: $id) {
4 | telegram
5 | }
6 | }`
--------------------------------------------------------------------------------
/src/screens/dashboard/_data/getCommentsQuery.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const getCommentsQuery = gql`query getComments($grantId: String!, $first: Int, $skip: Int) {
3 | comments(
4 | limit: $first
5 | skip: $skip
6 | filter: { grant: $grantId }
7 | sort:CREATEDATS_ASC
8 | ) {
9 | id:_id
10 | isPrivate
11 | commentsPublicHash
12 | createdAt
13 | commentsEncryptedData {
14 | id:_id
15 | data
16 | }
17 | workspace {
18 | members: membersFilter(filter: {
19 | enabled: true
20 | }) {
21 | actorId
22 | fullName
23 | profilePictureIpfsHash
24 | publicKey
25 | accessLevel
26 | }
27 | supportedNetworks
28 | }
29 | application {
30 | id:_id
31 | applicantPublicKey
32 | applicantId
33 | }
34 | }
35 | }
36 | `
--------------------------------------------------------------------------------
/src/screens/dashboard/_data/getDocuSignTemplates.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const getDocuSignTemplates = gql`mutation getDocuSignTemplates($id: String!){
3 | getDocuSignTemplates(id: $id){
4 | templates
5 | }
6 | }`
--------------------------------------------------------------------------------
/src/screens/dashboard/_data/getFundsAllocatedQuery.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const getFundsAllocatedQuery = gql`query getFundsAllocated($id: String!) {
3 | grantApplications(filter: {
4 | state: "approved",
5 | grant: $id
6 | }, sort: UPDATEDATS_DESC) {
7 | grant {
8 | totalGrantFundingDisbursedUSD
9 | }
10 | milestones {
11 | id: _id
12 | amount
13 | amountPaid
14 | }
15 | }
16 | }`
--------------------------------------------------------------------------------
/src/screens/dashboard/_data/getGrantDetailsForSEOQuery.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const getGrantDetailsForSEOQuery = gql`query getGrantDetailsForSEO($grantId: String!) {
3 | grant(_id: $grantId) {
4 | id:_id
5 | title
6 | workspace {
7 | id:_id
8 | logoIpfsHash
9 | }
10 | }
11 | }
12 | `
--------------------------------------------------------------------------------
/src/screens/dashboard/_data/getMemberPublicKeysQuery.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const getMemberPublicKeysQuery = gql`query getMemberPublicKeys($workspaceId: String!, $applicationIds: [String!]!) {
3 | workspace(_id: $workspaceId) {
4 | members: membersFilter(filter: {
5 | _operators:{
6 | accessLevel: {
7 | ne:"reviewer"
8 | }
9 | }
10 | enabled: false
11 | }) {
12 | actorId
13 | publicKey
14 | }
15 | }
16 | grantApplications(filter: {
17 | _operators:{
18 | _id: {
19 | in: $applicationIds
20 | }
21 | }
22 | }) {
23 | id:_id
24 | applicantId
25 | applicantPublicKey
26 | applicationReviewers {
27 | member(filter: {
28 | enabled: true
29 | }) {
30 | actorId
31 | publicKey
32 | }
33 | }
34 | }
35 | }
36 | `
--------------------------------------------------------------------------------
/src/screens/dashboard/_data/getPayoutQuery.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const getPayoutQuery = gql`query getPayouts($first: Int, $skip: Int, $proposalID: String!) {
3 | fundTransfers(
4 | limit: $first
5 | skip: $skip
6 | filter: {
7 | application: $proposalID
8 | _operators: {
9 | type: {
10 | in: ["funds_disbursed", "funds_disbursed_from_safe"]
11 | }
12 | }
13 | }
14 | ) {
15 | amount
16 | asset
17 | type
18 | createdAtS
19 | to
20 | transactionHash
21 | status
22 | executionTimestamp
23 | milestone {
24 | id: _id
25 | }
26 | grant {
27 | reward {
28 | id: _id
29 | asset
30 | committed
31 | token {
32 | id: _id
33 | label
34 | address
35 | chainId
36 | iconHash
37 | decimal
38 | }
39 | }
40 | }
41 | }
42 | }
43 | `
--------------------------------------------------------------------------------
/src/screens/dashboard/_data/getProposalDetailsForSEOQuery.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const getProposalDetailsForSEOQuery = gql`# This query is used in getServerSideProps for SEO
3 | query getProposalDetailsForSEO($proposalId: String!) {
4 | grantApplication(_id: $proposalId) {
5 | id:_id
6 | title: fieldFilterBySection(filter: { field: "projectName" }) {
7 | values {
8 | value
9 | }
10 | }
11 | grant {
12 | id:_id
13 | title
14 | workspace {
15 | id:_id
16 | logoIpfsHash
17 | }
18 | }
19 | }
20 | }
21 | `
--------------------------------------------------------------------------------
/src/screens/dashboard/_data/getSpecificApplicationActionQuery.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const getSpecificApplicationActionQuery = gql`query getApplicationActions($grantId: String!, $proposalId: String!) {
3 | grantApplications(filter: { grant: $grantId, _id:$proposalId }) {
4 | id:_id
5 | applicantId
6 | applicantPublicKey
7 | actions {
8 | id:_id
9 | updatedBy
10 | updatedAtS
11 | state
12 | feedback
13 | }
14 | grant {
15 | id:_id
16 | workspace {
17 | members:membersFilter {
18 | actorId
19 | fullName
20 | profilePictureIpfsHash
21 | publicKey
22 | accessLevel
23 | }
24 | supportedNetworks
25 | }
26 | }
27 | }
28 | }
29 | `
--------------------------------------------------------------------------------
/src/screens/dashboard/_data/getSpecificProposalCommentsQuery.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const getSpecificProposalCommentsQuery = gql`query getComments($grantId: String!, $proposalId: String!) {
3 | comments(
4 | filter: { grant: $grantId, application: $proposalId }
5 | sort:CREATEDAT_ASC
6 | ) {
7 | id:_id
8 | isPrivate
9 | commentsPublicHash
10 | createdAt
11 | updatedAt
12 | commentsEncryptedData {
13 | id:_id
14 | data
15 | }
16 | workspace {
17 | members: membersFilter(filter: {
18 | enabled: true
19 | }) {
20 | actorId
21 | fullName
22 | profilePictureIpfsHash
23 | publicKey
24 | accessLevel
25 | }
26 | supportedNetworks
27 | }
28 | application {
29 | id:_id
30 | applicantPublicKey
31 | applicantId
32 | }
33 | }
34 | }
35 | `
--------------------------------------------------------------------------------
/src/screens/dashboard/_data/getSynapsId.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const getSynapsId = gql`mutation getSynapseId($id:String!, $type:String!, $proposalId: String!){
3 | getSynapsId(id: $id, type: $type, proposalId: $proposalId){
4 | link
5 | }
6 | }`
--------------------------------------------------------------------------------
/src/screens/dashboard/_graphql/getApplicationActionForProposal.graphql:
--------------------------------------------------------------------------------
1 | query getApplicationActions($grantId: String!, $proposalId: String!) {
2 | grantApplications(filter: { grant: $grantId, _id:$proposalId }) {
3 | id:_id
4 | applicantId
5 | applicantPublicKey
6 | actions {
7 | id:_id
8 | updatedBy
9 | updatedAtS
10 | state
11 | feedback
12 | }
13 | grant {
14 | id:_id
15 | workspace {
16 | members:membersFilter {
17 | actorId
18 | fullName
19 | profilePictureIpfsHash
20 | publicKey
21 | accessLevel
22 | }
23 | supportedNetworks
24 | }
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/screens/dashboard/_graphql/getApplicationActions.graphql:
--------------------------------------------------------------------------------
1 | query getApplicationActions($grantId: String!) {
2 | grantApplications(filter: { grant: $grantId }) {
3 | id:_id
4 | applicantId
5 | applicantPublicKey
6 | actions {
7 | id:_id
8 | updatedBy
9 | updatedAtS
10 | state
11 | feedback
12 | }
13 | grant {
14 | id:_id
15 | workspace {
16 | members:membersFilter {
17 | actorId
18 | fullName
19 | profilePictureIpfsHash
20 | publicKey
21 | accessLevel
22 | }
23 | supportedNetworks
24 | }
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/screens/dashboard/_graphql/getBuilderInfo.graphql:
--------------------------------------------------------------------------------
1 | query getBuilderInfo($id: String!) {
2 | builder(applicationId: $id) {
3 | telegram
4 | }
5 | }
--------------------------------------------------------------------------------
/src/screens/dashboard/_graphql/getComments.graphql:
--------------------------------------------------------------------------------
1 | query getComments($grantId: String!, $first: Int, $skip: Int) {
2 | comments(
3 | limit: $first
4 | skip: $skip
5 | filter: { grant: $grantId }
6 | sort:CREATEDAT_ASC
7 | ) {
8 | id:_id
9 | isPrivate
10 | commentsPublicHash
11 | createdAt
12 | commentsEncryptedData {
13 | id:_id
14 | data
15 | }
16 | workspace {
17 | members: membersFilter(filter: {
18 | enabled: true
19 | }) {
20 | actorId
21 | fullName
22 | profilePictureIpfsHash
23 | publicKey
24 | accessLevel
25 | }
26 | supportedNetworks
27 | }
28 | application {
29 | id:_id
30 | applicantPublicKey
31 | applicantId
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/screens/dashboard/_graphql/getDocusSignTemplates.graphql:
--------------------------------------------------------------------------------
1 | mutation getDocuSignTemplates($id: String!){
2 | getDocuSignTemplates(id: $id){
3 | templates
4 | }
5 | }
--------------------------------------------------------------------------------
/src/screens/dashboard/_graphql/getFundTransfers.graphql:
--------------------------------------------------------------------------------
1 | query getPayouts($first: Int, $skip: Int,$proposalID: String!) {
2 | fundTransfers(limit: $first,skip: $skip,filter: {application: $proposalID, _operators:
3 | {
4 | type: {
5 | in: ["funds_disbursed", "funds_disbursed_from_safe"]
6 | }
7 | }}) {
8 | amount
9 | asset
10 | type
11 | createdAtS
12 | to
13 | transactionHash
14 | status
15 | executionTimestamp
16 | milestone {
17 | id:_id
18 | }
19 | grant {
20 | reward {
21 | id:_id
22 | asset
23 | committed
24 | token {
25 | id:_id
26 | label
27 | address
28 | chainId
29 | iconHash
30 | decimals
31 | }
32 | }
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/src/screens/dashboard/_graphql/getFundsAllocated.graphql:
--------------------------------------------------------------------------------
1 | query getFundsAllocated($id: String!) {
2 | grantApplications(filter: {
3 | state: "approved",
4 | grant: $id
5 | }, sort: UPDATEDATS_DESC) {
6 | milestones {
7 | id: _id
8 | amount
9 | amountPaid
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/src/screens/dashboard/_graphql/getGrantDetailsForSEO.graphql:
--------------------------------------------------------------------------------
1 | # This query is used in getServerSideProps for SEO
2 | query getGrantDetailsForSEO($grantId: String!) {
3 | grant(_id: $grantId) {
4 | id:_id
5 | title
6 | workspace {
7 | id:_id
8 | logoIpfsHash
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/screens/dashboard/_graphql/getPayouts.graphql:
--------------------------------------------------------------------------------
1 | query getPayouts($first: Int, $skip: Int, $proposalID: String!) {
2 | fundTransfers(limit: $first, skip: $skip,filter: {application: $proposalID, _operators: {
3 | type: {
4 | in: ["funds_disbursed", "funds_disbursed_from_safe"]
5 | }
6 | } }) {
7 | amount
8 | asset
9 | type
10 | createdAtS
11 | to
12 | transactionHash
13 | status
14 | executionTimestamp
15 | milestone {
16 | id:_id
17 | }
18 | grant {
19 | reward {
20 | id:_id
21 | asset
22 | committed
23 | token {
24 | id:_id
25 | label
26 | address
27 | decimal
28 | chainId
29 | iconHash
30 | }
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/src/screens/dashboard/_graphql/getProposalDetailsForSEO.graphql:
--------------------------------------------------------------------------------
1 | # This query is used in getServerSideProps for SEO
2 | query getProposalDetailsForSEO($proposalId: String!) {
3 | grantApplication(_id: $proposalId) {
4 | id:_id
5 | title: fieldFilterBySection(filter: { field: "projectName" }) {
6 | values {
7 | value
8 | }
9 | }
10 | grant {
11 | id:_id
12 | title
13 | workspace {
14 | id:_id
15 | logoIpfsHash
16 | }
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/screens/dashboard/_graphql/getSpecificProposalComments.graphql:
--------------------------------------------------------------------------------
1 | query getComments($grantId: String!, $proposalId: String!) {
2 | comments(
3 | filter: { grant: $grantId, application: $proposalId }
4 | sort:CREATEDAT_ASC
5 | ) {
6 | id:_id
7 | isPrivate
8 | commentsPublicHash
9 | createdAt
10 | updatedAt
11 | commentsEncryptedData {
12 | id:_id
13 | data
14 | }
15 | workspace {
16 | members: membersFilter(filter: {
17 | enabled: true
18 | }) {
19 | actorId
20 | fullName
21 | profilePictureIpfsHash
22 | publicKey
23 | accessLevel
24 | }
25 | supportedNetworks
26 | }
27 | application {
28 | id:_id
29 | applicantPublicKey
30 | applicantId
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/screens/dashboard/_graphql/getSynapsId.graphql:
--------------------------------------------------------------------------------
1 | mutation getSynapseId($id:String!, $type:String!){
2 | getSynapsId(id: $id, type: $type){
3 | link
4 | }
5 | }
--------------------------------------------------------------------------------
/src/screens/dashboard/_hooks/useDocuSign.ts:
--------------------------------------------------------------------------------
1 | import { useContext } from 'react'
2 | import { executeMutation } from 'src/graphql/apollo'
3 | import { GrantsProgramContext } from 'src/pages/_app'
4 | import { getDocuSignTemplates } from 'src/screens/dashboard/_data/getDocuSignTemplates'
5 |
6 | function GetDocuSignTemplates() {
7 |
8 | const { grant } = useContext(GrantsProgramContext)!
9 |
10 |
11 | const getHelloSignTemplates = async() => {
12 | const templates = await executeMutation(getDocuSignTemplates, { id: grant?.workspace?.id })
13 | return templates?.getDocuSignTemplates?.templates
14 | }
15 |
16 | return { getHelloSignTemplates }
17 | }
18 |
19 | export default GetDocuSignTemplates
--------------------------------------------------------------------------------
/src/screens/dashboard/_hooks/usePhantomWallet.ts:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react'
2 | import { PhantomProvider, WindowWithSolana } from 'src/types'
3 |
4 | export default function usePhantomWallet() {
5 | const [ phantomWalletAvailable, setPhantomWalletAvailable ] = useState(false)
6 | const [phantomWallet, setPhantomWallet] = useState()
7 | const [phantomWalletConnected, setPhantomWalletConnected] = useState(false)
8 |
9 | useEffect(() => {
10 | if('solana' in window) {
11 | const solWindow = window as WindowWithSolana
12 | if(solWindow?.solana?.isPhantom) {
13 | setPhantomWallet(solWindow.solana)
14 | setPhantomWalletAvailable(true)
15 | }
16 | }
17 | }, [])
18 |
19 | useEffect(() => {
20 | phantomWallet?.on('connect', () => {
21 | // console.log('phantom wallet connected ')
22 | setPhantomWalletConnected(true)
23 | })
24 | phantomWallet?.on('disconnect', () => {
25 | // console.log('phantom wallet disconnected')
26 | setPhantomWalletConnected(false)
27 | })
28 |
29 | }, [phantomWallet?.isConnected])
30 |
31 | return {
32 | phantomWalletAvailable,
33 | phantomWallet,
34 | phantomWalletConnected,
35 | setPhantomWalletConnected }
36 | }
--------------------------------------------------------------------------------
/src/screens/dashboard/_hooks/useSynaps.ts:
--------------------------------------------------------------------------------
1 | import { useContext } from 'react'
2 | import { executeMutation } from 'src/graphql/apollo'
3 | import { GrantsProgramContext } from 'src/pages/_app'
4 | import { getSynapsId } from 'src/screens/dashboard/_data/getSynapsId'
5 |
6 | function GetSynapsLink() {
7 |
8 | const { grant } = useContext(GrantsProgramContext)!
9 |
10 |
11 | const getSynapsLink = async(type: 'KYC' | 'KYB', proposalId: String) => {
12 | const synapsId = await executeMutation(getSynapsId, { id: grant?.workspace?.id, type, proposalId })
13 | return synapsId?.getSynapsId?.link
14 | }
15 |
16 | return { getSynapsLink }
17 | }
18 |
19 | export default GetSynapsLink
--------------------------------------------------------------------------------
/src/screens/dashboard/_utils/constants.ts:
--------------------------------------------------------------------------------
1 | const GRANT_CACHE_KEY = 'current-grant'
2 | const GRANT_PII = ['Personal Telegram Handle',
3 | 'Personal WeChat Handle',
4 | 'I confirm that I have studied the Grant Program Guidelines and the Ecosystem Map with the existing solutions on TON (please write \'yes\')',
5 | 'In case my proposal is approved, sign an official grant agreement and abide by its provisions in good faith',
6 | 'Any materials or links which can prove your achievement of building an App in Telegram with >10 thousand daily active users, or >1 million daily active users in any other internet platforms such as WeChat, QQ, Facebook, Google, Line, Kakao, etc. in the past',
7 | 'Education & Working experience & achievements of the founder and/or chief creator of Mini-app']
8 |
9 | export { GRANT_CACHE_KEY, GRANT_PII }
--------------------------------------------------------------------------------
/src/screens/dashboard/_utils/formatters.ts:
--------------------------------------------------------------------------------
1 | import moment from 'moment'
2 |
3 | const formatTime = (timestamp: number, isPayout: boolean = false) => {
4 | const now = Date.now()
5 | if(now - timestamp <= 24 * 60 * 60) {
6 | // Within a day
7 | return `${Math.floor((now - timestamp) / 24)}h`
8 | } else if(now - timestamp <= 7 * 24 * 60 * 60) {
9 | // Within a week
10 | return `${Math.floor((now - timestamp) / 7)}d`
11 | } else {
12 | return isPayout ? moment.unix(timestamp).format('DD MMM, YYYY') : moment.unix(timestamp).format('DD MMM')
13 | }
14 | }
15 |
16 | const formatAmount = (amount: number, symbol?: string): string => {
17 | const defaultSymbol = 'USD'
18 | if(!symbol) {
19 | symbol = defaultSymbol
20 | }
21 |
22 | if(amount >= 1e6) {
23 | return symbol === 'USD' ? `$${(amount / 1e6).toFixed(1)}M` : `${(amount / 1e6).toFixed(1)}M ${symbol}`
24 | } else if(amount >= 1e3) {
25 | return symbol === 'USD' ? `$${(amount / 1e3).toFixed(0)}K` : `${(amount / 1e3).toFixed(0)}K ${symbol}`
26 | } else {
27 | return symbol === 'USD' ? `$${amount}` : `${amount} ${symbol}`
28 | }
29 | }
30 |
31 |
32 | export { formatTime, formatAmount }
--------------------------------------------------------------------------------
/src/screens/dashboard/_utils/tonWalletUtils.ts:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 |
3 | export interface TokenDetailsInterface {
4 | tokenIcon: string
5 | tokenName: string
6 | symbol: string
7 | tokenValueAmount: number
8 | usdValueAmount: number
9 | mintAddress: string
10 | info: {
11 | decimals: number
12 | tokenAddress: string
13 | fiatConversion: number
14 | }
15 | fiatConversion: number
16 | }
17 | const getTokenUSDonDate = async(tokenName: string) => {
18 | const url = `https://api.coingecko.com/api/v3/simple/price?ids=${tokenName}&vs_currencies=usd`
19 | const tokenUsdValue = parseFloat((await axios.get(url)).data[tokenName].usd)
20 |
21 | return tokenUsdValue
22 | }
23 |
24 | const getToken = async() => {
25 | const TONTokenId: string = 'the-open-network'
26 |
27 | // const currentTime = (new Date()).toLocaleDateString().split('/').join('-')
28 |
29 | const tonUsdRate = await getTokenUSDonDate(TONTokenId)
30 | const details: TokenDetailsInterface = {
31 | tokenIcon: '/v2/icons/toncoin.svg',
32 | tokenName: 'TON',
33 | tokenValueAmount: 0,
34 | usdValueAmount: 0,
35 | mintAddress: '0x0000000',
36 | info: {
37 | decimals: 9,
38 | tokenAddress: TONTokenId,
39 | fiatConversion: tonUsdRate
40 | },
41 | fiatConversion: tonUsdRate,
42 | symbol: 'TON'
43 | }
44 | return details
45 | }
46 |
47 | export default getToken
--------------------------------------------------------------------------------
/src/screens/discover/_graphql/getAllFundTransfers.graphql:
--------------------------------------------------------------------------------
1 | query getAllFundsTransfer($first: Int, $skip: Int) {
2 | fundTransfers(limit:$first,skip:$skip) {
3 | grant{
4 | id:_id
5 | }
6 | amount
7 | type
8 | tokenUSDValue
9 | asset
10 | tokenName
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/screens/discover/_graphql/getAllGrants.graphql:
--------------------------------------------------------------------------------
1 | query GetAllGrants($first: Int, $skip: Int, $searchString: RegExpAsString!) {
2 | grants(
3 | limit: $first
4 | skip: $skip
5 | sort: CREATEDATS_DESC
6 | filter: {
7 | _operators: {
8 | title: {
9 | regex: $searchString
10 | }
11 | }
12 | }
13 | ) {
14 | id:_id
15 | title
16 | applications(limit: 1) {
17 | id: _id
18 | applicantId
19 | state
20 | }
21 | acceptingApplications
22 | fundTransfers {
23 | amount
24 | type
25 | tokenUSDValue
26 | asset
27 | tokenName
28 | }
29 | workspace {
30 | id:_id
31 | title
32 | isVisible
33 | logoIpfsHash
34 | supportedNetworks
35 | members(limit: 1) {
36 | id:_id
37 | actorId
38 | accessLevel
39 | }
40 | safe {
41 | chainId
42 | address
43 | }
44 | }
45 | reward {
46 | committed
47 | id:_id
48 | asset
49 | token {
50 | address
51 | label
52 | decimal
53 | iconHash
54 | }
55 | }
56 | deadlineS
57 | deadline
58 | numberOfApplications
59 | numberOfApplicationsSelected
60 | numberOfApplicationsPending
61 | createdAtS
62 | updatedAtS
63 | totalGrantFundingDisbursedUSD
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/screens/discover/_graphql/getFundsAllocated.graphql:
--------------------------------------------------------------------------------
1 | query getSectionGrants {
2 | sections {
3 | grants(sort: NUMBEROFAPPLICATIONS_DESC) {
4 | _id
5 | applications(filter: {
6 | state: "approved"
7 | }, sort: UPDATEDATS_DESC, limit: 2000) {
8 | milestones {
9 | id: _id
10 | amount
11 | }
12 | }
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/src/screens/discover/_graphql/getGrantProgramDetails.graphql:
--------------------------------------------------------------------------------
1 | query getGrantProgramDetails($workspaceID: String!) {
2 | grantProgram: grants(filter: {workspace: $workspaceID},sort: CREATEDATS_DESC) {
3 | id: _id
4 | title
5 | workspace {
6 | id: _id
7 | title
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/screens/discover/_graphql/getProposalNameAndAuthors.graphql:
--------------------------------------------------------------------------------
1 | query fetchNamesAndAuthors($ids: [String]!){
2 | grantApplications(filter: {
3 | _operators: {
4 | _id: {
5 | in: $ids
6 | }
7 | }
8 | }, limit: 1000, sort: UPDATEDATS_DESC ){
9 | _id
10 | name: fieldFilterBySection(
11 | filter:{
12 | field: "projectName"
13 | }
14 | ) {
15 | values{
16 | value
17 | }
18 | }
19 | author:fieldFilterBySection(filter: {
20 | field: "applicantName"
21 | } ){
22 | values {
23 | value
24 | }
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/src/screens/discover/_graphql/getStats.graphql:
--------------------------------------------------------------------------------
1 | query getStats {
2 | stats {
3 | builders
4 | proposals
5 | }
6 | }
--------------------------------------------------------------------------------
/src/screens/discover/_utils/index.ts:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * @description Extracts the builder info from the URL
4 | * @param {string} url - The URL to extract the builder info from
5 | */
6 | export const extractBuilderInfo = (url?: string): boolean => {
7 | let params: URLSearchParams
8 | if(url) {
9 | params = new URL(url).searchParams
10 | } else {
11 | params = new URLSearchParams(window.location.search)
12 | }
13 |
14 | const builderIdStr = params.get('isBuilder')
15 | if(typeof builderIdStr === 'string') {
16 | return true
17 | }
18 |
19 | return false
20 | }
--------------------------------------------------------------------------------
/src/screens/discover/data/fundsTransfers.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | import { client } from 'src/graphql/apollo'
3 | import { FundTransfer } from 'src/screens/discover/_utils/types'
4 |
5 | export const QUERY_FUNDSTRANSFERS = gql`
6 | query getAllFundsTransfer($first: Int, $skip: Int) {
7 | fundTransfers(limit:$first,skip:$skip) {
8 | grant{
9 | id:_id
10 | }
11 | amount
12 | type
13 | tokenUSDValue
14 | asset
15 | tokenName
16 | }
17 | }
18 | `
19 |
20 |
21 | export async function getAllFundsTransfers(): Promise {
22 | let records: FundTransfer[] = []
23 | let skip = 0
24 | let allData = false
25 |
26 | try {
27 | while(!allData) {
28 | const { data, error } = await client.query({
29 | query: QUERY_FUNDSTRANSFERS,
30 | variables: {
31 | skip,
32 | first: 500,
33 | },
34 | })
35 |
36 | if(data?.fundTransfers && !error) {
37 | records = records.concat(data.fundTransfers)
38 | skip += 500
39 |
40 | if(data?.fundTransfers.length === 0) {
41 | allData = true
42 | }
43 | }
44 | }
45 | } catch(error) {
46 | }
47 |
48 | return records
49 | }
50 |
--------------------------------------------------------------------------------
/src/screens/discover/data/getFundsAllocated.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const getFundsAllocated = gql`query getSectionGrants {
3 | sections {
4 | grants(sort: NUMBEROFAPPLICATIONS_DESC) {
5 | _id
6 | applications(filter: {
7 | state: "approved"
8 | }, sort: UPDATEDATS_DESC, limit: 10) {
9 | milestones {
10 | id: _id
11 | amount
12 | }
13 | }
14 | }
15 | }
16 | }`
--------------------------------------------------------------------------------
/src/screens/discover/data/getGrantProgramDetails.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 |
3 | export const GetGrantProgramDetails = gql`
4 | query getGrantProgramDetails($workspaceID: String!) {
5 | grantProgram: grants(filter: {workspace: $workspaceID},sort: CREATEDATS_DESC) {
6 | id: _id
7 | title
8 | workspace {
9 | id: _id
10 | title
11 | }
12 | }
13 | }`
--------------------------------------------------------------------------------
/src/screens/discover/data/getProposalNameAndAuthors.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const getProposalNameAndAuthorsQuery = gql`
3 | query fetchNamesAndAuthors($ids: [String]!){
4 | grantApplications(filter: {
5 | _operators: {
6 | _id: {
7 | in: $ids
8 | }
9 | }
10 | },limit: 1000, sort: UPDATEDATS_DESC){
11 | _id
12 | name: fieldFilterBySection(
13 | filter:{
14 | field: "projectName"
15 | }
16 | ) {
17 | values{
18 | value
19 | }
20 | }
21 | author:fieldFilterBySection(filter: {
22 | field: "applicantName"
23 | } ){
24 | values {
25 | value
26 | }
27 | }
28 | }
29 | }`
--------------------------------------------------------------------------------
/src/screens/discover/data/getSectionSubGrants.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 |
3 |
4 | export const getSectionSubGrantsQuery = gql`
5 | query getSectionSubGrants {
6 | grants(sort: NUMBEROFAPPLICATIONS_DESC, filter: { subgrant: true }) {
7 | id:_id
8 | title
9 | applications(filter: {
10 | state: "approved"
11 | }, limit: 2, sort: UPDATEDATS_DESC) {
12 | id: _id
13 | applicantId
14 | state
15 | createdAtS
16 | updatedAtS
17 | milestones {
18 | id: _id
19 | amount
20 | }
21 | }
22 | reward {
23 | id:_id
24 | asset
25 | committed
26 | token {
27 | id:_id
28 | label
29 | address
30 | decimal
31 | chainId
32 | iconHash
33 | }
34 | }
35 | acceptingApplications
36 | workspace {
37 | id:_id
38 | title
39 | isVisible
40 | logoIpfsHash
41 | supportedNetworks
42 | safe {
43 | chainId
44 | address
45 | }
46 | }
47 | link
48 | deadlineS
49 | deadline
50 | numberOfApplications
51 | numberOfApplicationsSelected
52 | numberOfApplicationsPending
53 | createdAtS
54 | updatedAtS
55 | totalGrantFundingDisbursedUSD
56 | }
57 | }
58 | `
--------------------------------------------------------------------------------
/src/screens/discover/data/getStats.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 |
3 | export const getStatsQuery = gql`query getStats {
4 | stats {
5 | builders
6 | proposals
7 | }
8 | }`
--------------------------------------------------------------------------------
/src/screens/discover/hooks/github.tsx:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import { logger } from 'ethers'
3 |
4 |
5 | export const useGithub = async(token: string):
6 | Promise<{
7 | username: string
8 | repos: number
9 | }> => {
10 | try {
11 | logger.info({ token }, 'useGithub')
12 | const response = await axios.get('https://api.github.com/user', {
13 | headers: {
14 | 'Authorization': `token ${token}`
15 | }
16 | })
17 | return {
18 | username: response.data.login,
19 | repos: response.data.public_repos
20 | }
21 | } catch(error) {
22 | logger.info({ error }, 'useGithub')
23 | return {
24 | username: '',
25 | repos: 0
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/src/screens/grantees/HeroBanner.tsx:
--------------------------------------------------------------------------------
1 | import { Flex, Text } from '@chakra-ui/react'
2 |
3 | function StatsBanner() {
4 | const buildComponent = () => {
5 | return (
6 |
15 |
23 | Grantee List
24 |
25 |
32 | These are all the grantees that have received grants via Questbook from different ecosystems including, Arbitrum, Ton, Compound and more
33 |
34 |
35 | )
36 | }
37 |
38 | return buildComponent()
39 | }
40 |
41 | export default StatsBanner
--------------------------------------------------------------------------------
/src/screens/grantees/_components/rfpGrid.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from 'react'
2 | import { Button, Grid, GridItem } from '@chakra-ui/react'
3 | import RFPCard from 'src/screens/grantees/_components/RFPCard'
4 | import { RecentProposals } from 'src/screens/grantees/_utils/types'
5 |
6 | type RFPGridProps = {
7 | proposals: RecentProposals
8 | }
9 |
10 | function RFPGrid({
11 | proposals
12 | }: RFPGridProps) {
13 | const [more, setMore] = useState(6)
14 |
15 | const buildComponent = () => (
16 | <>
17 |
22 | {
23 | proposals
24 | .slice(0, more)
25 | .map((proposal, index: number) => {
26 | return (
27 |
29 |
33 |
34 |
35 | )
36 | })
37 | }
38 |
39 | {
40 |
41 | more < proposals.length && proposals.length > 6 && (
42 |
52 | )
53 | }
54 | >
55 | )
56 |
57 | return buildComponent()
58 | }
59 |
60 | export default RFPGrid
--------------------------------------------------------------------------------
/src/screens/grantees/_graphql/getSectionGrants.graphql:
--------------------------------------------------------------------------------
1 | query getSectionGrants {
2 | sections {
3 | grants(sort: NUMBEROFAPPLICATIONS_DESC) {
4 | id: _id
5 | title
6 | workspace {
7 | _id
8 | logoIpfsHash
9 | }
10 | applications(filter: {
11 | state: "approved"
12 | }, sort: UPDATEDATS_DESC, limit: 10) {
13 | id: _id
14 | name: fieldFilterBySection(
15 | filter:{
16 | field: "projectName"
17 | }
18 | ) {
19 | values{
20 | value
21 | }
22 | }
23 | author:fieldFilterBySection(filter: {
24 | field: "applicantName"
25 | } ){
26 | values {
27 | value
28 | }
29 | }
30 | milestones {
31 | id: _id
32 | amount
33 | amountPaid
34 | }
35 | }
36 | }
37 | sectionName
38 | sectionLogoIpfsHash
39 | }
40 | }
--------------------------------------------------------------------------------
/src/screens/grantees/_utils/constants.ts:
--------------------------------------------------------------------------------
1 | export const inActiveProposals = [
2 | '0x318',
3 | '0x273',
4 | '0x26c',
5 | '0x291',
6 | '0x27b',
7 | '0x1de'
8 | ]
9 |
10 | export const completedProposals = [
11 | '0x36d',
12 | ]
--------------------------------------------------------------------------------
/src/screens/grantees/data/getSectionGrants.tsx:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 |
3 |
4 | export const getSectionGrantsQuery = gql`
5 | query getSectionGrants {
6 | sections {
7 | grants(sort: NUMBEROFAPPLICATIONS_DESC) {
8 | id: _id
9 | title
10 | workspace {
11 | _id
12 | logoIpfsHash
13 | }
14 | applications(filter: {
15 | state: "approved"
16 | }, sort: UPDATEDATS_DESC, limit: 1000) {
17 | id: _id
18 | name: fieldFilterBySection(
19 | filter:{
20 | field: "projectName"
21 | }
22 | ) {
23 | values{
24 | value
25 | }
26 | }
27 | author:fieldFilterBySection(filter: {
28 | field: "applicantName"
29 | } ){
30 | values {
31 | value
32 | }
33 | }
34 | milestones {
35 | id: _id
36 | amount
37 | amountPaid
38 | }
39 | }
40 | }
41 | sectionName
42 | sectionLogoIpfsHash
43 | }
44 | }
45 | `
--------------------------------------------------------------------------------
/src/screens/grantees/hooks/github.tsx:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import { logger } from 'ethers'
3 |
4 |
5 | export const useGithub = async(token: string):
6 | Promise<{
7 | username: string
8 | repos: number
9 | }> => {
10 | try {
11 | logger.info({ token }, 'useGithub')
12 | const response = await axios.get('https://api.github.com/user', {
13 | headers: {
14 | 'Authorization': `token ${token}`
15 | }
16 | })
17 | return {
18 | username: response.data.login,
19 | repos: response.data.public_repos
20 | }
21 | } catch(error) {
22 | logger.info({ error }, 'useGithub')
23 | return {
24 | username: '',
25 | repos: 0
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/src/screens/profile/_graphql/getBuilderInfo.graphql:
--------------------------------------------------------------------------------
1 | query getBuilderInfo($wallet: String!){
2 | getProfile(filter:{
3 | address:$wallet
4 | }) {
5 | _id
6 | telegram
7 | github
8 | bio
9 | twitter
10 | username
11 | imageURL
12 | proofs
13 | createdAt
14 | updatedAt
15 | }
16 | }
--------------------------------------------------------------------------------
/src/screens/profile/_graphql/getMyProposals.graphql:
--------------------------------------------------------------------------------
1 | query getMyProposals($wallet: String!) {
2 | grantApplications(filter: { applicantId: $wallet }) {
3 | id: _id
4 | name: fieldFilterBySection(filter: { field: "projectName" }) {
5 | values {
6 | value
7 | }
8 | }
9 | grant {
10 | id: _id
11 | title
12 | workspace {
13 | logoIpfsHash
14 | }
15 | }
16 | state
17 | milestones {
18 | id: _id
19 | amount
20 | amountPaid
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/screens/profile/_graphql/getUserNameAvailability.graphql:
--------------------------------------------------------------------------------
1 | query getUsernameAvailablity($username: String!){
2 | usernameCheck(username: $username) {
3 | isAvailable
4 | }
5 | }
--------------------------------------------------------------------------------
/src/screens/profile/_utils/constant.ts:
--------------------------------------------------------------------------------
1 | export const supportedProviders = [
2 | {
3 | 'name': 'arbitrum',
4 | 'icon': 'QmQfZEDeLroURuySnfKDF1XpwmU94cGULHZwQhaHPYZxiJ',
5 | },
6 | {
7 | 'name': 'compound',
8 | 'icon': 'QmP2MjriVUqyxNPz2bpDP58Y3iNsTkyHdMo9aBj4to7vvW',
9 | },
10 | {
11 | 'name': 'axelar',
12 | 'icon': 'QmbS1MwNDNPJt9ve4UYspg1WAqoYam6J6E2kVg24N9Nh3h',
13 | },
14 | {
15 | 'name': 'polygon',
16 | 'icon': 'QmNfAjH9v44rgQA2aNy6k6iGh7u786r9ca3eXhxB6gk7Hb',
17 | },
18 | {
19 | 'name': 'ens',
20 | 'icon': 'QmNrd1rxQx5BZzWFWY5ZSaFPhNXyijUSRCTLMVveHpK8LF',
21 | }
22 | ]
--------------------------------------------------------------------------------
/src/screens/profile/_utils/formatters.ts:
--------------------------------------------------------------------------------
1 | export const timeAgo = (timestamp: string): String => {
2 | const now = new Date().getTime()
3 | const then = new Date(timestamp).getTime()
4 | const diffInMs = now - then
5 |
6 | const seconds = diffInMs / 1000
7 | const minutes = seconds / 60
8 | const hours = minutes / 60
9 | const days = hours / 24
10 | const weeks = days / 7
11 | const months = days / 30
12 |
13 | if(minutes < 1) {
14 | return `${Math.floor(seconds)} second(s) ago`
15 | } else if(hours < 1) {
16 | return `${Math.floor(minutes)} minute(s) ago`
17 | } else if(days < 1) {
18 | return `${Math.floor(hours)} hour(s) ago`
19 | } else if(days < 7) {
20 | return `${Math.floor(days)} day(s) ago`
21 | } else if(days < 30) {
22 | return `${Math.floor(weeks)} week(s) ago`
23 | } else {
24 | return `${Math.floor(months)} month(s) ago`
25 | }
26 | }
--------------------------------------------------------------------------------
/src/screens/profile/data/getBuilderInfo.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 |
3 |
4 | export const getBuilderInfo = gql`query getBuilderInfo($wallet: String!){
5 | getProfile(filter:{
6 | address:$wallet
7 | }) {
8 | _id
9 | address
10 | telegram
11 | github
12 | bio
13 | twitter
14 | username
15 | imageURL
16 | compound
17 | ens
18 | axelar
19 | polygon
20 | arbitrum
21 | createdAt
22 | updatedAt
23 | }
24 | }`
--------------------------------------------------------------------------------
/src/screens/profile/data/getMyProposals.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const getMyProposals = gql`query getMyProposals($wallet: String!) {
3 | grantApplications(filter: { applicantId: $wallet }) {
4 | id: _id
5 | name: fieldFilterBySection(filter: { field: "projectName" }) {
6 | values {
7 | value
8 | }
9 | }
10 | grant {
11 | id: _id
12 | title
13 | workspace {
14 | logoIpfsHash
15 | tokens {
16 | _id
17 | chainId
18 | decimal
19 | label
20 | }
21 | }
22 | }
23 | state
24 | milestones {
25 | id: _id
26 | amount
27 | amountPaid
28 | }
29 | }
30 | }
31 | `
--------------------------------------------------------------------------------
/src/screens/profile/data/getUserNameAvailability.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const getUserNameAvailability = gql`query getUsernameAvailablity($username: String!){
3 | usernameCheck(username: $username) {
4 | isAvailable
5 | }
6 | }`
--------------------------------------------------------------------------------
/src/screens/profile/hooks/checkUsernameAvailablity.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react'
2 | import { useQuery } from 'src/libraries/hooks/useQuery'
3 | import { getUserNameAvailability } from 'src/screens/profile/data/getUserNameAvailability'
4 |
5 | const useCheckUsernameAvailability = (initialUsername: string = '') => {
6 | const [isUsernameAvailable, setIsUsernameAvailable] = useState(false)
7 | const [username, setUsername] = useState(initialUsername)
8 |
9 | const { fetchMore: fetchUsername } = useQuery({
10 | query: getUserNameAvailability,
11 | })
12 |
13 | const checkUsername = async(usernameToCheck: string): Promise => {
14 | const results = await fetchUsername({
15 | username: usernameToCheck,
16 | }, true) as { usernameCheck: { isAvailable: boolean } }
17 | return results?.usernameCheck?.isAvailable || false
18 | }
19 |
20 | useEffect(() => {
21 | if(username) {
22 | checkUsername(username).then((result: boolean) => {
23 | setIsUsernameAvailable(result)
24 | })
25 | } else {
26 | setIsUsernameAvailable(false)
27 | }
28 | }, [username])
29 |
30 | return { isUsernameAvailable, checkUsername, setUsername }
31 | }
32 |
33 | export default useCheckUsernameAvailability
--------------------------------------------------------------------------------
/src/screens/profile/hooks/generateProof.ts:
--------------------------------------------------------------------------------
1 | import { reclaimProof } from 'src/generated/mutation/reclaimProof'
2 | import { executeMutation } from 'src/graphql/apollo'
3 |
4 | export const generateProof = async(provider: string, address: string, proposalId?: string, pubKey?: string) => {
5 | try {
6 | const response = await executeMutation(reclaimProof, { type: provider, address, proposalId, pubKey })
7 | if(response.generateProof) {
8 | return {
9 | requestUrl: response.generateProof.requestUrl,
10 | statusUrl: response.generateProof.statusUrl,
11 | sessionId: response.generateProof.sessionId,
12 | migrationId: response?.generateProof?.migrationId,
13 | error: false
14 | }
15 | }
16 |
17 | return {
18 | requestUrl: '',
19 | statusUrl: '',
20 | sessionId: '',
21 | migrationId: '',
22 | error: true
23 | }
24 | } catch(e) {
25 | return {
26 | requestUrl: '',
27 | statusUrl: '',
28 | sessionId: '',
29 | migrationId: '',
30 | error: true
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/src/screens/proposal_form/_components/SectionHeader.tsx:
--------------------------------------------------------------------------------
1 | import { Text, TextProps } from '@chakra-ui/react'
2 |
3 | function SectionHeader(props: TextProps) {
4 | const buildComponent = () => {
5 | return (
6 |
14 | )
15 | }
16 |
17 | return buildComponent()
18 | }
19 |
20 | export default SectionHeader
--------------------------------------------------------------------------------
/src/screens/proposal_form/_components/SectionSelect.tsx:
--------------------------------------------------------------------------------
1 | import { Flex, FlexProps, NumberDecrementStepper, NumberIncrementStepper, NumberInput, NumberInputField, NumberInputProps, NumberInputStepper, Text } from '@chakra-ui/react'
2 |
3 | interface Props extends NumberInputProps {
4 | label: string
5 | flexProps?: FlexProps
6 | }
7 |
8 | function SectionSelect({ label, flexProps, ...props }: Props) {
9 | const buildComponent = () => {
10 | return (
11 |
16 |
23 | {label}
24 |
25 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | )
47 | }
48 |
49 | return buildComponent()
50 | }
51 |
52 | export default SectionSelect
--------------------------------------------------------------------------------
/src/screens/proposal_form/_data/grantDetailsQuery.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const grantDetailsQuery = gql`query grantDetails($grantId: String!) {
3 | grant(_id: $grantId) {
4 | id:_id
5 | creatorId
6 | title
7 | summary
8 | details
9 | reward {
10 | id:_id
11 | asset
12 | committed
13 | token {
14 | id:_id
15 | label
16 | address
17 | decimal
18 | iconHash
19 | chainId
20 | }
21 | }
22 | startDate
23 | deadline
24 | startDateS
25 | deadlineS
26 | payoutType
27 | reviewType
28 | link
29 | docIpfsHash
30 | acceptingApplications
31 | metadataHash
32 | funding
33 | workspace {
34 | id:_id
35 | title
36 | supportedNetworks
37 | logoIpfsHash
38 | safe {
39 | address
40 | chainId
41 | }
42 | }
43 | fields {
44 | id:_id
45 | title
46 | inputType
47 | possibleValues
48 | isPii
49 | }
50 | milestones
51 | }
52 | }`
--------------------------------------------------------------------------------
/src/screens/proposal_form/_data/walletAddressCheckerQuery.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const walletAddressCheckerQuery = gql`query walletAddressChecker($grantId:String!, $walletAddress:String!){
3 | grantApplications(filter:{grant: $grantId, applicantId: $walletAddress} ) {
4 | id:_id
5 | walletAddress
6 | applicantId
7 | createdAtS
8 | }
9 | }`
--------------------------------------------------------------------------------
/src/screens/proposal_form/_graphql/grantDetails.graphql:
--------------------------------------------------------------------------------
1 | query grantDetails($grantId: String!) {
2 | grant(_id: $grantId) {
3 | id:_id
4 | creatorId
5 | title
6 | summary
7 | details
8 | reward {
9 | id:_id
10 | asset
11 | committed
12 | token {
13 | id:_id
14 | label
15 | address
16 | decimal
17 | iconHash
18 | chainId
19 | }
20 | }
21 | startDate
22 | deadline
23 | startDateS
24 | deadlineS
25 | payoutType
26 | reviewType
27 | link
28 | docIpfsHash
29 | acceptingApplications
30 | metadataHash
31 | funding
32 | workspace {
33 | id:_id
34 | title
35 | supportedNetworks
36 | logoIpfsHash
37 | safe {
38 | address
39 | chainId
40 | }
41 | }
42 | fields {
43 | id:_id
44 | title
45 | inputType
46 | possibleValues
47 | isPii
48 | }
49 | milestones
50 | }
51 | }
--------------------------------------------------------------------------------
/src/screens/proposal_form/_graphql/walletAddressChecker.graphql:
--------------------------------------------------------------------------------
1 | query walletAddressChecker($grantId:String!, $walletAddress:String!){
2 | grantApplications(filter:{grant: $grantId, walletAddress: $walletAddress} ) {
3 | id:_id
4 | walletAddress
5 | applicantId
6 | createdAtS
7 | }
8 | }
--------------------------------------------------------------------------------
/src/screens/proposal_form/_utils/types.ts:
--------------------------------------------------------------------------------
1 | import { EditorState } from 'draft-js'
2 | import { GrantDetailsQuery, GrantField, ProposalDetailsQuery } from 'src/generated/graphql'
3 | import SupportedChainId from 'src/generated/SupportedChainId'
4 |
5 | export type FormType = 'submit' | 'resubmit'
6 |
7 | export type ProposalFormContextType = {
8 | grant: Grant
9 | proposal: Proposal
10 | chainId: SupportedChainId
11 | form: Form
12 | setForm: (form: Form) => void
13 | type: FormType
14 | error?: string
15 | telegram: string
16 | setTelegram: (telegram: string) => void
17 | twitter: string
18 | setTwitter: (twitter: string) => void
19 | referral: { type: string, value: string }
20 | setReferral: (referral: { type: string, value: string }) => void
21 | newsletter: string
22 | setNewsLetter: (newsletter: string) => void
23 | }
24 |
25 | export type Grant = GrantDetailsQuery['grant']
26 | export type Proposal = ProposalDetailsQuery['grantApplication']
27 |
28 | export type FormField = {
29 | id: string
30 | value: string
31 | } & GrantField
32 |
33 | export type MilestoneType = {
34 | index: number
35 | title: string
36 | amount: number
37 | details?: string
38 | deadline?: string
39 | }
40 |
41 | export type Form = {
42 | fields: FormField[]
43 | milestones: MilestoneType[]
44 | members: string[]
45 | details: EditorState
46 | }
--------------------------------------------------------------------------------
/src/screens/proposal_recovery/_graphql/getMigrationStatus.graphql:
--------------------------------------------------------------------------------
1 | query migrationStatus($id: MongoID!){
2 | migration(_id: $id){
3 | status
4 | }
5 | }
--------------------------------------------------------------------------------
/src/screens/proposal_recovery/data/getMigrationStatusQuery.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/client'
2 | export const getMigrationStatusQuery = gql`query migrationStatus($id: MongoID!){
3 | migration(_id: $id){
4 | status
5 | }
6 | }`
--------------------------------------------------------------------------------
/src/screens/request_proposal/_components/SelectDropdown.tsx:
--------------------------------------------------------------------------------
1 | import { Select, SingleValue, } from 'chakra-react-select'
2 |
3 | interface Props {
4 | options: T[]
5 | value?: SingleValue
6 | onChange: (value: SingleValue) => void
7 | placeholder?: string
8 | }
9 |
10 | function SelectDropdown({ options, placeholder, value, onChange }: Props) {
11 | return (
12 |