├── .browserslistrc
├── .env
├── .env.test
├── .eslintignore
├── .eslintrc.js
├── .github
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── ISSUE_TEMPLATE
│ ├── BUG_REPORT.yml
│ └── FEATURE_REQUEST.yml
├── PULL_REQUEST_TEMPLATE.md
├── dependabot.yml
├── stale.yml
└── workflows
│ ├── deploy.yml
│ ├── nodejs.yml
│ └── update-snapshot-packages.yml
├── .gitignore
├── .gitmodules
├── .gitpod.yml
├── .husky
├── post-checkout
├── post-merge
├── pre-commit
└── pre-push
├── .nvmrc
├── .prettierrc.js
├── LICENSE
├── README.md
├── babel.config.js
├── crowdin.yml
├── cypress.config.ts
├── cypress
├── e2e
│ ├── create-proposal.spec.cy.js
│ └── voting-proposal.spec.cy.js
└── support
│ ├── commands.js
│ └── e2e.js
├── index.html
├── package.json
├── postcss.config.js
├── public
├── .well-known
│ └── assetlinks.json
├── about
│ ├── big_planet.png
│ ├── main.png
│ └── small_planet.png
├── avatar.png
├── favicon.png
├── icon.svg
├── manifest.json
├── service-worker.js
└── stickers
│ ├── hooray.png
│ └── just_signed.png
├── src
├── App.vue
├── assets
│ ├── fonts
│ │ ├── Calibre-Medium-Custom.woff2
│ │ ├── Calibre-Semibold-Custom.woff2
│ │ ├── iconfont.css
│ │ ├── iconfont.eot
│ │ ├── iconfont.json
│ │ ├── iconfont.svg
│ │ ├── iconfont.ttf
│ │ ├── iconfont.woff
│ │ ├── iconfont.woff2
│ │ └── space-mono-v11-latin-700.woff2
│ └── icons
│ │ ├── coingecko.svg
│ │ ├── discord.svg
│ │ ├── github.svg
│ │ ├── lenster.svg
│ │ ├── shutter.svg
│ │ ├── signature.svg
│ │ ├── twitter.svg
│ │ ├── voted.svg
│ │ └── youtube.svg
├── components
│ ├── AboutMembersListItem.vue
│ ├── AboutSubheader.vue
│ ├── AvatarOverlayEdit.vue
│ ├── AvatarSpace.vue
│ ├── AvatarToken.vue
│ ├── AvatarUser.vue
│ ├── BaseAvatar.vue
│ ├── BaseBadge.vue
│ ├── BaseBlock.vue
│ ├── BaseButton.test.js
│ ├── BaseButton.vue
│ ├── BaseButtonIcon.vue
│ ├── BaseButtonRound.vue
│ ├── BaseCalendar.vue
│ ├── BaseCombobox.vue
│ ├── BaseComboboxMultiple.vue
│ ├── BaseContainer.vue
│ ├── BaseCounter.vue
│ ├── BaseIcon.vue
│ ├── BaseIndicator.vue
│ ├── BaseInput.vue
│ ├── BaseLink.vue
│ ├── BaseListbox.vue
│ ├── BaseListboxMultiple.vue
│ ├── BaseLoading.vue
│ ├── BaseMarkdown.vue
│ ├── BaseMenu.vue
│ ├── BaseMessage.vue
│ ├── BaseMessageBlock.vue
│ ├── BaseModal.vue
│ ├── BaseModalSelectItem.vue
│ ├── BaseNetworkItem.vue
│ ├── BaseNoResults.vue
│ ├── BasePill.vue
│ ├── BasePluginItem.vue
│ ├── BasePopover.vue
│ ├── BasePopoverHover.vue
│ ├── BaseProgressBar.vue
│ ├── BaseProgressRadial.vue
│ ├── BaseSearch.vue
│ ├── BaseSidebarNavigationItem.vue
│ ├── BaseSkinItem.vue
│ ├── BaseStrategyItem.vue
│ ├── BaseUser.vue
│ ├── BlockLink.vue
│ ├── BlockSpacesList.vue
│ ├── BlockSpacesListButtonMore.vue
│ ├── BlockSpacesListItem.vue
│ ├── BlockSpacesListSkeleton.vue
│ ├── ButtonBack.vue
│ ├── ButtonCard.vue
│ ├── ButtonFollow.vue
│ ├── ButtonPlayground.vue
│ ├── ButtonShare.vue
│ ├── ButtonTheme.vue
│ ├── ComboboxNetwork.vue
│ ├── ContainerParallelInput.vue
│ ├── ExploreMenuCategories.vue
│ ├── ExploreSkeletonLoading.vue
│ ├── ExploreSpaces.vue
│ ├── FooterLinks.vue
│ ├── FooterLinksItem.vue
│ ├── FooterSocials.vue
│ ├── FooterSocialsItem.vue
│ ├── FooterTitle.vue
│ ├── FormArray.vue
│ ├── FormObject.vue
│ ├── IconDiscord.vue
│ ├── IconInformationTooltip.vue
│ ├── IconSocial.vue
│ ├── IconVerifiedSpace.vue
│ ├── IndicatorAssetsChange.spec.js
│ ├── IndicatorAssetsChange.vue
│ ├── InputCheckbox.vue
│ ├── InputDate.vue
│ ├── InputEmail.vue
│ ├── InputNewsletter.vue
│ ├── InputNumber.vue
│ ├── InputRadio.vue
│ ├── InputSelect.vue
│ ├── InputSelectPrivacy.vue
│ ├── InputSelectVoteType.vue
│ ├── InputSelectVoteValidation.vue
│ ├── InputSocial.vue
│ ├── InputString.vue
│ ├── InputSwitch.vue
│ ├── InputUploadAvatar.vue
│ ├── InputUploadImage.vue
│ ├── InputUrl.vue
│ ├── LabelInput.vue
│ ├── LabelProposalState.vue
│ ├── LabelProposalVoted.vue
│ ├── LinkSpace.vue
│ ├── ListboxMultipleCategories.vue
│ ├── LoadingList.vue
│ ├── LoadingPage.vue
│ ├── LoadingRow.vue
│ ├── LoadingSpinner.vue
│ ├── MenuAccount.vue
│ ├── MenuLanguages.vue
│ ├── MessageWarningGnosisNetwork.vue
│ ├── MessageWarningValidation.vue
│ ├── ModalAccount.vue
│ ├── ModalConfirmAction.vue
│ ├── ModalControllerEdit.vue
│ ├── ModalDelegate.vue
│ ├── ModalMessage.vue
│ ├── ModalNotice.vue
│ ├── ModalPlugins.vue
│ ├── ModalPostVote.vue
│ ├── ModalProfileForm.vue
│ ├── ModalReceipt.vue
│ ├── ModalRevokeDelegate.vue
│ ├── ModalSelectDate.vue
│ ├── ModalSkins.vue
│ ├── ModalSpaces.vue
│ ├── ModalSpacesListItem.vue
│ ├── ModalStrategies.vue
│ ├── ModalStrategy.vue
│ ├── ModalTerms.vue
│ ├── ModalTreasury.vue
│ ├── ModalUnsupportedNetwork.vue
│ ├── ModalValidation.vue
│ ├── ModalVote.vue
│ ├── ModalVoteValidation.vue
│ ├── ModalVotingPrivacy.vue
│ ├── ModalVotingType.vue
│ ├── NavbarAccount.vue
│ ├── NavbarExtras.vue
│ ├── NavbarNotifications.vue
│ ├── PopoverHoverProfile.vue
│ ├── ProfileAboutBiography.vue
│ ├── ProfileAboutDelegate.vue
│ ├── ProfileAboutDelegateListItem.vue
│ ├── ProfileActivityList.vue
│ ├── ProfileActivityListItem.vue
│ ├── ProfileAddressCopy.vue
│ ├── ProfileName.vue
│ ├── ProfileSidebar.vue
│ ├── ProfileSidebarHeader.vue
│ ├── ProfileSidebarHeaderSkeleton.vue
│ ├── ProfileSidebarNavigation.vue
│ ├── ProposalsItem.vue
│ ├── ProposalsItemBody.vue
│ ├── ProposalsItemFooter.vue
│ ├── ProposalsItemResults.vue
│ ├── ProposalsItemTitle.vue
│ ├── SettingsDangerzoneBlock.vue
│ ├── SettingsDomainBlock.vue
│ ├── SettingsLinkBlock.vue
│ ├── SettingsMembersBlock.vue
│ ├── SettingsMembersPopoverButton.vue
│ ├── SettingsMembersPopoverContent.vue
│ ├── SettingsPluginsBlock.vue
│ ├── SettingsProfileBlock.vue
│ ├── SettingsProposalBlock.vue
│ ├── SettingsStrategiesBlock.vue
│ ├── SettingsSubSpacesBlock.vue
│ ├── SettingsTreasuriesBlock.vue
│ ├── SettingsTreasuriesBlockItem.vue
│ ├── SettingsValidationBlock.vue
│ ├── SettingsVotingBlock.vue
│ ├── SetupButtonBack.vue
│ ├── SetupButtonCreate.vue
│ ├── SetupButtonNext.vue
│ ├── SetupDomain.vue
│ ├── SetupDomainRegister.vue
│ ├── SetupExtras.vue
│ ├── SetupIntro.vue
│ ├── SetupMessageHelp.vue
│ ├── SetupProfile.vue
│ ├── SetupSidebarStepper.vue
│ ├── SetupStrategy.vue
│ ├── SetupStrategyAdvanced.vue
│ ├── SetupStrategyBasic.vue
│ ├── SetupStrategyVote.vue
│ ├── SidebarSpacesSkeleton.vue
│ ├── SidebarUnreadIndicator.vue
│ ├── SpaceCreateContent.vue
│ ├── SpaceCreatePlugins.vue
│ ├── SpaceCreateVoting.vue
│ ├── SpaceCreateVotingDateEnd.vue
│ ├── SpaceCreateVotingDateStart.vue
│ ├── SpaceCreateWarnings.vue
│ ├── SpaceProposalContent.vue
│ ├── SpaceProposalHeader.vue
│ ├── SpaceProposalInformation.vue
│ ├── SpaceProposalPage.vue
│ ├── SpaceProposalPlugins.vue
│ ├── SpaceProposalPluginsSidebar.vue
│ ├── SpaceProposalResults.vue
│ ├── SpaceProposalResultsError.vue
│ ├── SpaceProposalResultsList.vue
│ ├── SpaceProposalResultsListItem.vue
│ ├── SpaceProposalResultsProgressBar.vue
│ ├── SpaceProposalResultsQuorum.vue
│ ├── SpaceProposalResultsShutter.vue
│ ├── SpaceProposalVote.vue
│ ├── SpaceProposalVoteApproval.vue
│ ├── SpaceProposalVoteQuadratic.vue
│ ├── SpaceProposalVoteRankedChoice.vue
│ ├── SpaceProposalVoteSingleChoice.vue
│ ├── SpaceProposalVotesList.vue
│ ├── SpaceProposalVotesListItem.vue
│ ├── SpaceProposalVotesListItemChoice.vue
│ ├── SpaceProposalVotesModal.vue
│ ├── SpaceProposalsMenuFilter.vue
│ ├── SpaceProposalsNoProposals.vue
│ ├── SpaceProposalsNotice.vue
│ ├── SpaceSidebar.vue
│ ├── SpaceSidebarFooter.vue
│ ├── SpaceSidebarHeader.vue
│ ├── SpaceSidebarNavigation.vue
│ ├── SpaceSidebarSkeleton.vue
│ ├── SpaceSidebarSubspaces.vue
│ ├── SpaceWarningFlagged.vue
│ ├── StrategiesBlockWarning.vue
│ ├── StrategiesListItem.vue
│ ├── TextAutolinker.vue
│ ├── TextareaArray.vue
│ ├── TextareaAutosize.vue
│ ├── TextareaJson.vue
│ ├── TheFlashNotification.vue
│ ├── TheFooter.vue
│ ├── TheHeader.vue
│ ├── TheLayout.vue
│ ├── TheModalNotification.vue
│ ├── TheNavbar.vue
│ ├── TheSearchBar.vue
│ ├── TheSidebar.vue
│ ├── TreasuryAssetsList.vue
│ ├── TreasuryAssetsListItem.spec.js
│ ├── TreasuryAssetsListItem.vue
│ ├── TreasuryWalletsList.spec.js
│ ├── TreasuryWalletsList.vue
│ ├── TreasuryWalletsListItem.spec.js
│ ├── TreasuryWalletsListItem.vue
│ └── Ui
│ │ ├── Collapsible.vue
│ │ ├── CollapsibleContent.vue
│ │ ├── CollapsibleText.vue
│ │ ├── Input.vue
│ │ └── Select.vue
├── composables
│ ├── useAliasAction.ts
│ ├── useApolloQuery.ts
│ ├── useApp.ts
│ ├── useCategories.ts
│ ├── useClient.ts
│ ├── useCopy.ts
│ ├── useDelegate.ts
│ ├── useEns.ts
│ ├── useExtendedSpaces.ts
│ ├── useFlashNotification.ts
│ ├── useFollowSpace.ts
│ ├── useFormSpaceProposal.ts
│ ├── useFormSpaceSettings.ts
│ ├── useFormValidation.ts
│ ├── useGnosis.ts
│ ├── useI18n.ts
│ ├── useImageUpload.ts
│ ├── useInfiniteLoader.ts
│ ├── useIntl.ts
│ ├── useMeta.ts
│ ├── useModal.ts
│ ├── useModalNotification.ts
│ ├── useNetworksFilter.ts
│ ├── useNotifications.ts
│ ├── usePlugins.ts
│ ├── useProfiles.ts
│ ├── useProposalVotes.ts
│ ├── useProposals.ts
│ ├── useQuorum.ts
│ ├── useReportDownload.ts
│ ├── useSafe.ts
│ ├── useSharing.ts
│ ├── useSkin.ts
│ ├── useSkinsFilter.ts
│ ├── useSnapshot.ts
│ ├── useSpaceController.ts
│ ├── useSpaceSubscription.ts
│ ├── useSpaces.ts
│ ├── useStrategies.ts
│ ├── useTerms.ts
│ ├── useTreasury.ts
│ ├── useTxStatus.ts
│ ├── useUnseenProposals.ts
│ ├── useUsername.ts
│ └── useWeb3.ts
├── env.d.ts
├── helpers
│ ├── abi.ts
│ ├── apollo.ts
│ ├── auth.ts
│ ├── b64.ts
│ ├── beams.ts
│ ├── categories.json
│ ├── clientEIP712.ts
│ ├── clientGnosisSafe.ts
│ ├── connectors.json
│ ├── covalent.ts
│ ├── delegation.ts
│ ├── ens.ts
│ ├── i18n.ts
│ ├── interfaces.ts
│ ├── profile.ts
│ ├── queries.ts
│ ├── shutter.ts
│ ├── snapshot.ts
│ ├── utils.test.js
│ ├── utils.ts
│ └── validation.ts
├── locales
│ ├── ar-SA.json
│ ├── de-DE.json
│ ├── default.json
│ ├── es-ES.json
│ ├── fil-PH.json
│ ├── fr-FR.json
│ ├── hi-IN.json
│ ├── id-ID.json
│ ├── it-IT.json
│ ├── ja-JP.json
│ ├── ko-KR.json
│ ├── languages.json
│ ├── pt-PT.json
│ ├── ro-RO.json
│ ├── ru-RU.json
│ ├── tr-TR.json
│ ├── uk-UA.json
│ ├── vi-VN.json
│ └── zh-CN.json
├── main.ts
├── plugins
│ ├── README.md
│ ├── commentBox
│ │ ├── Proposal.vue
│ │ ├── components
│ │ │ ├── Comment.vue
│ │ │ ├── CommentBlock.vue
│ │ │ ├── CustomBlock.vue
│ │ │ ├── ListReply.vue
│ │ │ └── ReplyBlock.vue
│ │ └── plugin.json
│ ├── gnosis
│ │ ├── Create.vue
│ │ ├── ProposalSidebar.vue
│ │ ├── components
│ │ │ ├── Config.vue
│ │ │ └── CustomBlock.vue
│ │ ├── index.ts
│ │ └── plugin.json
│ ├── hal
│ │ ├── ProposalSidebar.vue
│ │ ├── components
│ │ │ └── CustomBlock.vue
│ │ └── plugin.json
│ ├── poap
│ │ ├── ProposalSidebar.vue
│ │ ├── components
│ │ │ └── CustomBlock.vue
│ │ ├── index.ts
│ │ └── plugin.json
│ ├── progress
│ │ ├── ProposalSidebar.vue
│ │ ├── components
│ │ │ └── CustomBlock.vue
│ │ ├── index.ts
│ │ ├── plugin.json
│ │ └── readme.md
│ ├── projectGalaxy
│ │ ├── ProposalSidebar.vue
│ │ ├── README.md
│ │ ├── components
│ │ │ └── CustomBlock.vue
│ │ ├── index.ts
│ │ └── plugin.json
│ ├── quorum
│ │ ├── examples.json
│ │ └── plugin.json
│ └── safeSnap
│ │ ├── Create.vue
│ │ ├── Proposal.vue
│ │ ├── components
│ │ ├── Config.vue
│ │ ├── Form
│ │ │ ├── ContractInteraction.vue
│ │ │ ├── ImportTransactionsButton.vue
│ │ │ ├── RawTransaction.vue
│ │ │ ├── SendAsset.vue
│ │ │ ├── Transaction.vue
│ │ │ ├── TransactionBatch.vue
│ │ │ └── TransferFunds.vue
│ │ ├── HandleOutcome.vue
│ │ ├── HandleOutcomeUma.vue
│ │ ├── Input
│ │ │ ├── Address.vue
│ │ │ ├── Amount.vue
│ │ │ ├── ArrayType.vue
│ │ │ └── MethodParameter.vue
│ │ ├── Modal
│ │ │ └── OptionApproval.vue
│ │ ├── SafeTransactions.vue
│ │ └── Tooltip.vue
│ │ ├── constants.ts
│ │ ├── index.ts
│ │ ├── logo.png
│ │ ├── plugin.json
│ │ └── utils
│ │ ├── abi.ts
│ │ ├── coins.ts
│ │ ├── decoder.ts
│ │ ├── index.ts
│ │ ├── multiSend.ts
│ │ ├── realityETH.ts
│ │ ├── realityModule.ts
│ │ ├── safe.ts
│ │ ├── transactions.ts
│ │ ├── umaModule.ts
│ │ └── validator.ts
├── router.ts
├── style.scss
├── vars.scss
└── views
│ ├── AboutView.vue
│ ├── DelegateView.vue
│ ├── ExploreView.vue
│ ├── PlaygroundView.vue
│ ├── ProfileAbout.vue
│ ├── ProfileActivity.vue
│ ├── ProfileView.vue
│ ├── RankingView.vue
│ ├── SetupView.vue
│ ├── SpaceAbout.vue
│ ├── SpaceCreate.vue
│ ├── SpaceProposal.vue
│ ├── SpaceProposals.vue
│ ├── SpaceSettings.vue
│ ├── SpaceTreasury.vue
│ ├── SpaceView.vue
│ ├── StrategyView.vue
│ └── TimelineView.vue
├── tailwind.config.js
├── tsconfig.json
├── vite.config.ts
├── vitest.ts
└── yarn.lock
/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not dead
4 |
--------------------------------------------------------------------------------
/.env:
--------------------------------------------------------------------------------
1 | VITE_HUB_URL=https://testnet.snapshot.org
2 | VITE_RELAYER_URL=https://testnet.snapshot.org
3 | VITE_SCORES_URL=https://score.snapshot.org
4 | VITE_IPFS_GATEWAY=snapshot.mypinata.cloud
5 | VITE_DEFAULT_NETWORK=1
6 | VITE_PUSHER_BEAMS_INSTANCE_ID=2e080021-d495-456d-b2cf-84f9fd718442
7 | VITE_SHUTTER_EON_PUBKEY=0x0e6493bbb4ee8b19aa9b70367685049ff01dc9382c46aed83f8bc07d2a5ba3e6030bd83b942c1fd3dff5b79bef3b40bf6b666e51e7f0be14ed62daaffad47435265f5c9403b1a801921981f7d8659a9bd91fe92fb1cf9afdb16178a532adfaf51a237103874bb03afafe9cab2118dae1be5f08a0a28bf488c1581e9db4bc23ca
8 | VITE_ENV=develop
9 |
--------------------------------------------------------------------------------
/.env.test:
--------------------------------------------------------------------------------
1 | CYPRESS_REMOTE_DEBUGGING_PORT=9222
2 | NETWORK_NAME=mainnet
3 | SECRET_WORDS='test test test test test test test test test test test junk'
4 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | src/plugins/*
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true
5 | },
6 | extends: [
7 | 'plugin:cypress/recommended',
8 | 'plugin:vue/vue3-recommended',
9 | 'eslint:recommended',
10 | '@vue/eslint-config-typescript/recommended',
11 | '@vue/eslint-config-prettier',
12 | '.eslintrc-auto-import.json'
13 | ],
14 | ignorePatterns: ['/node_modules/**/*.*'],
15 | parserOptions: {
16 | ecmaVersion: 2020
17 | },
18 | rules: {
19 | 'no-console': 'off',
20 | 'prefer-template': 'error',
21 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
22 | '@typescript-eslint/no-explicit-any': 'off',
23 | '@typescript-eslint/ban-ts-ignore': 'off',
24 | '@typescript-eslint/camelcase': 'off',
25 | '@typescript-eslint/no-undef': 'off',
26 | '@typescript-eslint/no-var-requires': 'off',
27 | '@typescript-eslint/no-use-before-define': ['error', { functions: false }],
28 | 'vue/script-setup-uses-vars': 'error'
29 | },
30 | globals: {
31 | $ref: 'readonly',
32 | defineProps: 'readonly',
33 | defineEmits: 'readonly',
34 | withDefaults: 'readonly'
35 | }
36 | };
37 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ### Issues
2 | *_(Include references to issues that this PR addresses)_*
3 |
4 | Fixes #
5 |
6 | ### Changes
7 | *_(Briefly describe the changes made in this PR)_*
8 |
9 | 1.
10 |
11 | ### How to test
12 | *_(Explain how the changes can be tested, including any required setup steps)_*
13 |
14 | 1.
15 |
16 | ### To-Do
17 | *_(List any outstanding tasks be addressed before or after this PR is merged)_*
18 |
19 | - [ ]
20 |
21 |
22 | ### Self-review checklist
23 | - [ ] I have performed a full self-review of my changes
24 | - [ ] I have tested my changes on a preview deployment
25 | - [ ] I have tested my changes on a custom domain
26 | - [ ] I have run end-to-end tests `yarn cypress:test:e2e`, and they have passed
27 |
28 | ### Additional notes or considerations
29 | *_(Include any other relevant information or context that may be helpful for the reviewer)_*
30 |
31 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: 'npm'
4 | directory: '/'
5 | schedule:
6 | interval: 'weekly'
7 | - package-ecosystem: 'gitsubmodule'
8 | directory: '/'
9 | schedule:
10 | interval: 'daily'
11 |
--------------------------------------------------------------------------------
/.github/stale.yml:
--------------------------------------------------------------------------------
1 | daysUntilStale: 120
2 | daysUntilClose: 14
3 | exemptLabels:
4 | - pinned
5 | - enhancement
6 | - bug
7 | staleLabel: stale
8 | markComment: >
9 | This issue has been automatically marked as stale because it has not had
10 | recent activity. It will be closed if no further activity occurs. Thank you
11 | for your contributions.
12 | closeComment: false
13 |
--------------------------------------------------------------------------------
/.github/workflows/deploy.yml:
--------------------------------------------------------------------------------
1 | name: Deploy
2 |
3 | on:
4 | workflow_dispatch:
5 | inputs:
6 | target:
7 | type: choice
8 | description: Target
9 | options:
10 | - stable
11 |
12 | jobs:
13 | deploy:
14 | runs-on: ubuntu-latest
15 |
16 | steps:
17 | # Checks-out repo on develop branch
18 | - uses: actions/checkout@v3
19 | with:
20 | ref: 'develop'
21 | # Overwrite target
22 | - run: |
23 | git checkout -b ${{ github.event.inputs.target }}
24 | git push --set-upstream origin ${{ github.event.inputs.target }} --force
25 |
--------------------------------------------------------------------------------
/.github/workflows/nodejs.yml:
--------------------------------------------------------------------------------
1 | name: Node CI
2 |
3 | on:
4 | push:
5 |
6 | jobs:
7 | build:
8 | runs-on: ubuntu-latest
9 |
10 | strategy:
11 | matrix:
12 | node-version: [16.x]
13 |
14 | steps:
15 | - name: Checkout repository
16 | uses: actions/checkout@v3
17 |
18 | - name: Use Node.js ${{ matrix.node-version }}
19 | uses: actions/setup-node@v3
20 | with:
21 | node-version: ${{ matrix.node-version }}
22 |
23 | - name: Install dependencies
24 | run: yarn
25 |
26 | - name: Build
27 | run: yarn run build
28 |
29 | - name: Lint
30 | run: yarn run lint
31 |
32 |
33 |
--------------------------------------------------------------------------------
/.github/workflows/update-snapshot-packages.yml:
--------------------------------------------------------------------------------
1 | name: Update Snapshot packages
2 |
3 | on:
4 | workflow_dispatch:
5 | schedule:
6 | - cron: 0 10 * * 1
7 |
8 | jobs:
9 | update-dep:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - uses: actions/checkout@v2
13 | - uses: actions/setup-node@v1
14 | with:
15 | node-version: '14.x'
16 | - name: Update snapshot.js
17 | run: |
18 | yarn upgrade @snapshot-labs/snapshot.js --latest
19 | - name: Update lock.js
20 | run: |
21 | yarn upgrade @snapshot-labs/lock --latest
22 | - name: Create Pull Request
23 | uses: peter-evans/create-pull-request@v3
24 | with:
25 | commit-message: Update Snapshot packages
26 | title: Update Snapshot packages
27 | body: |
28 | - Updates from snapshot.js or lock packages
29 |
30 | Auto-generated by Github Actions
31 | branch: update-snapshot-packages
32 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 | .yalc
5 | components.d.ts
6 | auto-imports.d.ts
7 | .eslintrc-auto-import.json
8 |
9 | # local env files
10 | .env.local
11 | .env.*.local
12 |
13 | # Log files
14 | npm-debug.log*
15 | yarn-debug.log*
16 | yarn-error.log*
17 | pnpm-debug.log*
18 |
19 | # Editor directories and files
20 | .idea
21 | .vscode
22 | *.suo
23 | *.ntvs*
24 | *.njsproj
25 | *.sln
26 | *.sw?
27 |
28 | # Vitest
29 |
30 | /coverage
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "snapshot-spaces"]
2 | path = snapshot-spaces
3 | url = https://github.com/snapshot-labs/snapshot-spaces
4 |
--------------------------------------------------------------------------------
/.gitpod.yml:
--------------------------------------------------------------------------------
1 | tasks:
2 | - name: Setup
3 | init: |
4 | yarn install --frozen-lockfile --silent --network-timeout 100000
5 | command: yarn dev
6 |
7 | ports:
8 | - port: 3000
9 | onOpen: open-preview
10 |
--------------------------------------------------------------------------------
/.husky/post-checkout:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(dirname "$0")/_/husky.sh"
3 |
4 | yarn run init-submodules
5 |
--------------------------------------------------------------------------------
/.husky/post-merge:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(dirname "$0")/_/husky.sh"
3 |
4 | yarn run init-submodules
5 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | . "$(dirname -- "$0")/_/husky.sh"
3 |
4 | npx lint-staged
--------------------------------------------------------------------------------
/.husky/pre-push:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | . "$(dirname -- "$0")/_/husky.sh"
3 |
4 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | v15.14.0
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | singleQuote: true,
3 | trailingComma: 'none',
4 | arrowParens: 'avoid'
5 | };
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) Snapshot Labs
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['@vue/cli-plugin-babel/preset']
3 | };
4 |
--------------------------------------------------------------------------------
/crowdin.yml:
--------------------------------------------------------------------------------
1 | files:
2 | - source: /src/locales/default.json
3 | translation: /src/locales/%locale%.json
4 |
--------------------------------------------------------------------------------
/cypress.config.ts:
--------------------------------------------------------------------------------
1 | const { defineConfig } = require('cypress');
2 | const synpressPlugins = require('@synthetixio/synpress/plugins');
3 |
4 | module.exports = defineConfig({
5 | userAgent: 'synpress',
6 | viewportHeight: 900,
7 | viewportWidth: 1280,
8 | screenshotOnRunFailure: false,
9 | video: false,
10 | chromeWebSecurity: true,
11 | defaultCommandTimeout: 30000,
12 | pageLoadTimeout: 30000,
13 | requestTimeout: 30000,
14 | e2e: {
15 | testIsolation: true,
16 | setupNodeEvents(on, config) {
17 | synpressPlugins(on, config);
18 | },
19 | baseUrl: 'http://localhost:8081/#/',
20 | supportFile: 'cypress/support/e2e.js'
21 | // specPattern: 'cypress/e2e/voting-proposal.spec.cy.js'
22 | }
23 | });
24 |
--------------------------------------------------------------------------------
/cypress/support/commands.js:
--------------------------------------------------------------------------------
1 | // ***********************************************
2 | // This example commands.js shows you how to
3 | // create various custom commands and overwrite
4 | // existing commands.
5 | //
6 | // For more comprehensive examples of custom
7 | // commands please read more here:
8 | // https://on.cypress.io/custom-commands
9 | // ***********************************************
10 | //
11 | //
12 | // -- This is a parent command --
13 | // Cypress.Commands.add('login', (email, password) => { ... })
14 | //
15 | //
16 | // -- This is a child command --
17 | // Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
18 | //
19 | //
20 | // -- This is a dual command --
21 | // Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
22 | //
23 | //
24 | // -- This will overwrite an existing command --
25 | // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
26 |
--------------------------------------------------------------------------------
/cypress/support/e2e.js:
--------------------------------------------------------------------------------
1 | import './commands';
2 | import '@synthetixio/synpress/support';
3 |
4 | beforeEach(() => {
5 | cy.visit('/');
6 | cy.get('[data-testid="button-connect-wallet"]').click();
7 | cy.get('[data-testid="button-connnect-wallet-injected"]').click();
8 | cy.acceptMetamaskAccess();
9 | });
10 |
11 | afterEach(() => {
12 | cy.disconnectMetamaskWalletFromAllDapps();
13 | cy.resetMetamaskAccount();
14 | });
15 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 | Snapshot
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {}
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/public/.well-known/assetlinks.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "relation": [
4 | "delegate_permission/common.handle_all_urls"
5 | ],
6 | "target": {
7 | "namespace": "android_app",
8 | "package_name": "org.snapshot",
9 | "sha256_cert_fingerprints": [
10 | "44:5B:B1:EE:DF:5C:2A:90:7D:7A:10:DF:18:67:68:54:8E:8E:62:C1:DF:84:06:F7:8D:8E:AD:67:2E:B2:5C:E5"
11 | ]
12 | }
13 | }
14 | ]
15 |
--------------------------------------------------------------------------------
/public/about/big_planet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bigint/snapshot/4394734b8ae05cbc99f386a6068592fe22328b20/public/about/big_planet.png
--------------------------------------------------------------------------------
/public/about/main.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bigint/snapshot/4394734b8ae05cbc99f386a6068592fe22328b20/public/about/main.png
--------------------------------------------------------------------------------
/public/about/small_planet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bigint/snapshot/4394734b8ae05cbc99f386a6068592fe22328b20/public/about/small_planet.png
--------------------------------------------------------------------------------
/public/avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bigint/snapshot/4394734b8ae05cbc99f386a6068592fe22328b20/public/avatar.png
--------------------------------------------------------------------------------
/public/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bigint/snapshot/4394734b8ae05cbc99f386a6068592fe22328b20/public/favicon.png
--------------------------------------------------------------------------------
/public/icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "Snapshot",
3 | "name": "Snapshot",
4 | "description": "Where decisions get made",
5 | "iconPath": "icon.svg",
6 | "icons": [
7 | {
8 | "src": "favicon.ico",
9 | "sizes": "64x64 32x32 24x24 16x16",
10 | "type": "image/x-icon"
11 | },
12 | {
13 | "src": "avatar.png",
14 | "type": "image/png",
15 | "sizes": "192x192"
16 | },
17 | {
18 | "src": "avatar.png",
19 | "type": "image/png",
20 | "sizes": "512x512"
21 | }
22 | ],
23 | "start_url": ".",
24 | "display": "standalone",
25 | "theme_color": "#000000",
26 | "background_color": "#ffffff"
27 | }
28 |
--------------------------------------------------------------------------------
/public/service-worker.js:
--------------------------------------------------------------------------------
1 | importScripts('https://js.pusher.com/beams/service-worker.js');
2 |
--------------------------------------------------------------------------------
/public/stickers/hooray.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bigint/snapshot/4394734b8ae05cbc99f386a6068592fe22328b20/public/stickers/hooray.png
--------------------------------------------------------------------------------
/public/stickers/just_signed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bigint/snapshot/4394734b8ae05cbc99f386a6068592fe22328b20/public/stickers/just_signed.png
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
24 |
27 |
32 |
36 |
37 |
38 |
39 |
40 |
41 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/src/assets/fonts/Calibre-Medium-Custom.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bigint/snapshot/4394734b8ae05cbc99f386a6068592fe22328b20/src/assets/fonts/Calibre-Medium-Custom.woff2
--------------------------------------------------------------------------------
/src/assets/fonts/Calibre-Semibold-Custom.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bigint/snapshot/4394734b8ae05cbc99f386a6068592fe22328b20/src/assets/fonts/Calibre-Semibold-Custom.woff2
--------------------------------------------------------------------------------
/src/assets/fonts/iconfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bigint/snapshot/4394734b8ae05cbc99f386a6068592fe22328b20/src/assets/fonts/iconfont.eot
--------------------------------------------------------------------------------
/src/assets/fonts/iconfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bigint/snapshot/4394734b8ae05cbc99f386a6068592fe22328b20/src/assets/fonts/iconfont.ttf
--------------------------------------------------------------------------------
/src/assets/fonts/iconfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bigint/snapshot/4394734b8ae05cbc99f386a6068592fe22328b20/src/assets/fonts/iconfont.woff
--------------------------------------------------------------------------------
/src/assets/fonts/iconfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bigint/snapshot/4394734b8ae05cbc99f386a6068592fe22328b20/src/assets/fonts/iconfont.woff2
--------------------------------------------------------------------------------
/src/assets/fonts/space-mono-v11-latin-700.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bigint/snapshot/4394734b8ae05cbc99f386a6068592fe22328b20/src/assets/fonts/space-mono-v11-latin-700.woff2
--------------------------------------------------------------------------------
/src/assets/icons/coingecko.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/github.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/lenster.svg:
--------------------------------------------------------------------------------
1 |
2 |
10 |
--------------------------------------------------------------------------------
/src/assets/icons/signature.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/twitter.svg:
--------------------------------------------------------------------------------
1 |
2 |
5 |
--------------------------------------------------------------------------------
/src/assets/icons/voted.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/youtube.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/components/AboutMembersListItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/components/AboutSubheader.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/components/AvatarOverlayEdit.vue:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
15 |
22 |
26 | {{ avatar ? $t('edit') : $t('upload') }}
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/components/AvatarSpace.vue:
--------------------------------------------------------------------------------
1 |
22 |
23 |
24 |
31 |
32 |
--------------------------------------------------------------------------------
/src/components/AvatarToken.vue:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 |
31 |
32 |
--------------------------------------------------------------------------------
/src/components/AvatarUser.vue:
--------------------------------------------------------------------------------
1 |
21 |
22 |
23 |
30 |
31 |
--------------------------------------------------------------------------------
/src/components/BaseBadge.vue:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
16 | {{ $t('isCore') }}
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/components/BaseButton.test.js:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { mount } from '@vue/test-utils';
3 | import BaseButton from './BaseButton.vue';
4 |
5 | describe('Button.vue', () => {
6 | it('should slot text', () => {
7 | const wrapper = mount(BaseButton, {
8 | slots: {
9 | default: 'Hello world'
10 | }
11 | });
12 |
13 | expect(wrapper.text()).toContain('Hello world');
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/src/components/BaseButtonIcon.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
17 |
18 |
--------------------------------------------------------------------------------
/src/components/BaseButtonRound.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
15 |
16 |
--------------------------------------------------------------------------------
/src/components/BaseContainer.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/components/BaseCounter.vue:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
15 |
16 |
--------------------------------------------------------------------------------
/src/components/BaseIcon.vue:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
20 |
21 |
--------------------------------------------------------------------------------
/src/components/BaseIndicator.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/components/BaseLink.vue:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
21 |
22 |
26 |
27 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/src/components/BaseLoading.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/components/BaseMessage.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
13 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/components/BaseMessageBlock.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/components/BaseModalSelectItem.vue:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
17 |
18 |
19 |
20 |
24 | {{ tag }}
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/components/BaseNetworkItem.vue:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
25 |
26 | {{
27 | $tc('inSpaces', [
28 | formatCompactNumber(networksSpacesCount?.[network.key] ?? 0)
29 | ])
30 | }}
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/components/BaseNoResults.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 | {{ text }}
11 |
12 |
{{ text }}
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/components/BasePill.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/components/BasePluginItem.vue:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
22 |
23 |
v{{ plugin.version }}
24 |
25 |
26 |
27 |
28 |
29 | {{ plugin.author }}
30 |
31 | {{
32 | $tc('inSpaces', [
33 | formatCompactNumber(pluginsSpacesCount?.[plugin.key] ?? 0)
34 | ])
35 | }}
36 |
37 |
38 |
42 | {{ $t('learnMore') }}
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/src/components/BaseProgressBar.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
13 |
14 |
--------------------------------------------------------------------------------
/src/components/BaseProgressRadial.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
12 |
13 |
14 |
22 |
--------------------------------------------------------------------------------
/src/components/BaseSidebarNavigationItem.vue:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/components/BaseSkinItem.vue:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 | {{ skin }}
14 |
15 | {{ $tc('inSpaces', [formatCompactNumber(skinsSpacesCount[skin] ?? 0)]) }}
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/components/BaseStrategyItem.vue:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 | {{ strategy.id }}
16 |
17 |
v{{ strategy.version }}
18 |
19 |
20 |
21 | {{ strategy.author }}
22 |
23 |
24 | {{ $tc('inSpaces', [formatCompactNumber(strategy.spacesCount)]) }}
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/components/BaseUser.vue:
--------------------------------------------------------------------------------
1 |
19 |
20 |
21 |
27 |
37 |
38 |
39 |
43 | {{ username }}
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/src/components/BlockSpacesListButtonMore.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
--------------------------------------------------------------------------------
/src/components/BlockSpacesListItem.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
14 |
21 |
22 |
23 | {{ space?.name }}
24 |
25 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/components/BlockSpacesListSkeleton.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
18 |
19 |
--------------------------------------------------------------------------------
/src/components/ButtonBack.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
16 |
17 |
--------------------------------------------------------------------------------
/src/components/ButtonCard.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
15 |
16 |
--------------------------------------------------------------------------------
/src/components/ButtonPlayground.vue:
--------------------------------------------------------------------------------
1 |
49 |
50 |
51 |
52 | {{ $t('settings.testInPlayground') }}
53 |
54 |
55 |
56 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/src/components/ButtonShare.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
--------------------------------------------------------------------------------
/src/components/ButtonTheme.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/components/ComboboxNetwork.vue:
--------------------------------------------------------------------------------
1 |
23 |
24 |
25 | emit('select', value.id)"
32 | @search="value => (query = value)"
33 | >
34 |
35 |
36 | {{ item.name }}
37 |
38 |
39 | #{{ item.id }}
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/src/components/ContainerParallelInput.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/components/ExploreSkeletonLoading.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
18 |
25 |
26 |
--------------------------------------------------------------------------------
/src/components/FooterLinks.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/components/FooterLinksItem.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/components/FooterSocials.vue:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/src/components/FooterSocialsItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/components/FooterTitle.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/components/FormObject.vue:
--------------------------------------------------------------------------------
1 |
42 |
43 |
44 |
45 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/src/components/IconDiscord.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/components/IconInformationTooltip.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/components/IconSocial.vue:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 |
17 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/components/IconVerifiedSpace.vue:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
28 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/src/components/IndicatorAssetsChange.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
18 |
19 | {{
20 | `${quote.quote_24h > quote.quote ? '' : '+'}${formatPercentNumber(
21 | (quote.quote - quote.quote_24h) / quote.quote_24h
22 | )}`
23 | }}
24 |
25 |
26 | {{ `($${formatNumber(quote.quote - quote.quote_24h)})` }}
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/components/InputCheckbox.vue:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
22 |
23 | {{ label }}
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/components/InputDate.vue:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 | {{ title }}
20 |
26 |
27 | {{ dateString }}
28 |
29 |
32 |
33 |
34 |
35 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/components/InputEmail.vue:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/components/InputNewsletter.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
32 |
33 |
--------------------------------------------------------------------------------
/src/components/InputNumber.vue:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 |
25 |
26 |
--------------------------------------------------------------------------------
/src/components/InputRadio.vue:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
22 |
23 | {{ label }}
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/components/InputSelect.vue:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 | {{ title }}
16 |
26 |
27 | {{ modelValue }}
28 |
29 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/src/components/InputSelectPrivacy.vue:
--------------------------------------------------------------------------------
1 |
21 |
22 |
23 |
24 |
33 |
34 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/components/InputSelectVoteType.vue:
--------------------------------------------------------------------------------
1 |
23 |
24 |
25 |
37 |
38 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/src/components/InputSelectVoteValidation.vue:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
23 |
24 |
25 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/components/InputSocial.vue:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 | emit('update:modelValue', value)"
23 | >
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/components/InputString.vue:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 |
28 |
37 |
38 |
--------------------------------------------------------------------------------
/src/components/InputUploadAvatar.vue:
--------------------------------------------------------------------------------
1 |
30 |
31 |
32 |
33 |
38 |
39 |
47 |
48 |
--------------------------------------------------------------------------------
/src/components/InputUploadImage.vue:
--------------------------------------------------------------------------------
1 |
31 |
32 |
33 |
34 |
42 |
43 |
44 |
58 |
--------------------------------------------------------------------------------
/src/components/InputUrl.vue:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
16 | emit('update:modelValue', input)"
24 | >
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/components/LabelInput.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/components/LabelProposalState.vue:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
21 |
27 |
28 |
29 |
47 |
--------------------------------------------------------------------------------
/src/components/LabelProposalVoted.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 | {{ $t('voted') }}
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/components/LinkSpace.vue:
--------------------------------------------------------------------------------
1 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/components/ListboxMultipleCategories.vue:
--------------------------------------------------------------------------------
1 |
23 |
24 |
25 |
38 |
39 |
--------------------------------------------------------------------------------
/src/components/LoadingList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
--------------------------------------------------------------------------------
/src/components/LoadingPage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/components/LoadingRow.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/components/MenuLanguages.vue:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 |
23 |
24 |
27 |
28 | {{
29 | languages[$i18n.locale]?.nativeName ?? languages[$i18n.locale]?.name
30 | }}
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/src/components/MessageWarningGnosisNetwork.vue:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 | {{
21 | $t('settings.gnosisWrongNetwork.base', {
22 | network: networks?.[networkKey]?.name,
23 | action: $t(`settings.gnosisWrongNetwork.${action}`)
24 | })
25 | }}
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/components/ModalConfirmAction.vue:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
{{ $t('confirmAction') }}
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | {{ $t('cancel') }}
25 |
26 |
32 | {{ $t('confirm') }}
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/src/components/ModalDelegate.vue:
--------------------------------------------------------------------------------
1 |
21 |
22 |
23 |
24 |
25 |
26 |
{{ $t('profile.about.delegate') }}
27 |
28 |
29 |
30 |
35 | {{ $t('delegate.to') }}
36 |
37 |
38 | {{ $t('space') }}
39 |
40 |
41 |
42 |
48 | {{ $t('confirm') }}
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/src/components/ModalMessage.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
{{ title }}
17 |
18 |
19 |
20 |
21 | {{ message }}
22 |
23 |
24 |
25 | {{ $t('continue') }}
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/src/components/ModalNotice.vue:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 | {{ title }}
10 |
11 |
12 |
13 |
14 |
15 |
16 |
22 | {{ $t('continue') }}
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/components/ModalReceipt.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 | {{ $t('receipt') }}
16 |
17 |
18 |
19 |
20 |
21 |
22 | #{{ authorIpfsHash.slice(0, 7) }}
23 |
24 |
25 |
26 |
27 |
28 | #{{ relayerIpfsHash.slice(0, 7) }}
29 |
30 |
31 |
32 |
37 |
38 | {{ $t('verifyOnSignatorio') }}
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/components/ModalSpaces.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
{{ $t('spaces') }}
17 |
18 |
19 |
20 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/components/ModalSpacesListItem.vue:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | {{ space.name }}
19 |
20 |
25 |
26 |
27 | {{
28 | $tc('members', {
29 | count: formatCompactNumber(space.followers || 0)
30 | })
31 | }}
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/src/components/ModalStrategies.vue:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 | {{ $t('strategiesPage') }}
17 |
18 |
19 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/components/ModalTerms.vue:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 |
23 |
24 | {{ $t('settings.terms.label') }}
25 |
26 |
27 |
28 | {{
29 | $tc('modalTerms.mustAgreeTo', {
30 | action,
31 | spaceName: space.name || 'spaces'
32 | })
33 | }}
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | {{ $t('cancel') }}
44 |
45 |
46 |
47 |
48 | {{ $t('agree') }}
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/src/components/ModalVotingPrivacy.vue:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
21 |
22 | {{ $t('privacy.title') }}
23 |
24 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/components/ModalVotingType.vue:
--------------------------------------------------------------------------------
1 |
24 |
25 |
26 |
27 |
28 | {{ $t('voting.selectVoting') }}
29 |
30 |
31 |
37 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/src/components/ProfileAboutBiography.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/components/ProfileActivityList.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 | {{
10 | title.toUpperCase()
11 | }}
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/components/ProfileAddressCopy.vue:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 |
17 |
26 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/src/components/ProfileName.vue:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
20 | {{ profile?.name || profile?.ens || shorten(address) }}
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/components/ProfileSidebar.vue:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
21 |
22 |
27 |
28 |
29 |
33 |
38 |
39 |
40 | {{ $t('profile.buttonEdit') }}
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/src/components/ProfileSidebarHeader.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
22 |
23 |
--------------------------------------------------------------------------------
/src/components/ProfileSidebarHeaderSkeleton.vue:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
--------------------------------------------------------------------------------
/src/components/ProfileSidebarNavigation.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ $t('profile.activity.header') }}
6 |
7 |
8 |
9 |
10 | {{ $t('profile.about.header') }}
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/components/ProposalsItemBody.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/components/ProposalsItemFooter.vue:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
23 | {{
24 | capitalize(
25 | getRelativeProposalPeriod(
26 | proposal.state,
27 | proposal.start,
28 | proposal.end
29 | )
30 | )
31 | }}
32 |
33 |
34 | -
35 | {{
36 | formatPercentNumber(
37 | Number(formatCompactNumber(proposal.scores_total / proposal.quorum))
38 | )
39 | }}
40 | {{ $t('quorumReached') }}
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/components/ProposalsItemResults.vue:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
18 |
23 |
24 |
27 |
28 | {{ shorten(choice, 32) }}
29 |
30 | {{ formatCompactNumber(proposal.scores[i]) }}
31 | {{ proposal.symbol || proposal.space.symbol }}
32 |
33 |
34 |
42 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/src/components/ProposalsItemTitle.vue:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
{{ proposal.title }}
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/components/SettingsDomainBlock.vue:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | {{ $t('learnMore') }}
21 |
22 |
23 |
24 |
25 |
26 |
27 |
35 |
36 |
42 |
43 |
44 |
45 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/src/components/SettingsLinkBlock.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
25 |
34 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/src/components/SettingsMembersPopoverButton.vue:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/components/SettingsMembersPopoverContent.vue:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
27 |
28 |
29 | {{ capitalize(role) }}
30 |
31 |
32 | {{ $t(`settings.members.${role}.description`) }}
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/components/SettingsProposalBlock.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
24 |
25 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/src/components/SettingsTreasuriesBlockItem.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
19 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/components/SetupButtonBack.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ $t('back') }}
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/components/SetupButtonCreate.vue:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
16 | {{ $t('createButton') }}
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/components/SetupButtonNext.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 | {{ $t(text) }}
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/components/SetupExtras.vue:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | {{ $t('setup.validationTitle') }}
32 |
33 |
34 |
35 |
36 |
37 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/components/SetupIntro.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 | {{ $t('header.description') }}
12 |
13 |
14 |
15 |
16 |
17 |
22 | {{ $t('getStarted') }}
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/components/SetupMessageHelp.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
12 |
13 | documentation
15 |
16 |
17 | Discord
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/components/SetupProfile.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/components/SetupStrategyAdvanced.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
26 |
27 |
--------------------------------------------------------------------------------
/src/components/SidebarSpacesSkeleton.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
--------------------------------------------------------------------------------
/src/components/SidebarUnreadIndicator.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
16 |
17 |
--------------------------------------------------------------------------------
/src/components/SpaceCreatePlugins.vue:
--------------------------------------------------------------------------------
1 |
23 |
24 |
25 |
26 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/src/components/SpaceCreateVotingDateEnd.vue:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
29 |
30 |
--------------------------------------------------------------------------------
/src/components/SpaceCreateVotingDateStart.vue:
--------------------------------------------------------------------------------
1 |
23 |
24 |
25 |
34 |
35 |
--------------------------------------------------------------------------------
/src/components/SpaceProposalPlugins.vue:
--------------------------------------------------------------------------------
1 |
19 |
20 |
21 |
27 |
28 |
--------------------------------------------------------------------------------
/src/components/SpaceProposalPluginsSidebar.vue:
--------------------------------------------------------------------------------
1 |
24 |
25 |
26 |
32 |
33 |
--------------------------------------------------------------------------------
/src/components/SpaceProposalResults.vue:
--------------------------------------------------------------------------------
1 |
34 |
35 |
36 |
40 |
48 |
49 |
56 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/src/components/SpaceProposalResultsError.vue:
--------------------------------------------------------------------------------
1 |
34 |
35 |
36 |
37 | {{ $t('resultsCalculating') }}
38 |
39 |
40 | {{ t('resultsError') }}
41 |
42 |
43 |
44 | {{ t('retry') }}
45 |
46 |
52 |
53 | {{ t('getHelp') }}
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/src/components/SpaceProposalResultsList.vue:
--------------------------------------------------------------------------------
1 |
29 |
30 |
31 |
32 |
41 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/src/components/SpaceProposalResultsProgressBar.vue:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
25 |
26 |
--------------------------------------------------------------------------------
/src/components/SpaceProposalResultsQuorum.vue:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
16 |
17 |
18 | {{ $t('settings.quorum.label') }}
19 |
20 |
21 |
22 |
26 |
29 | {{ formatCompactNumber(totalQuorumScore) }}
30 | /
31 | {{ formatCompactNumber(quorum) }}
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/src/components/SpaceProposalResultsShutter.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ $t('poweredBy') }}
4 |
5 |
6 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/components/SpaceProposalVoteApproval.vue:
--------------------------------------------------------------------------------
1 |
33 |
34 |
35 |
36 |
49 |
50 | {{ shorten(choice, 32) }}
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/src/components/SpaceProposalVoteSingleChoice.vue:
--------------------------------------------------------------------------------
1 |
30 |
31 |
32 |
33 |
41 |
42 | {{ shorten(choice, 32) }}
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/src/components/SpaceProposalVotesListItemChoice.vue:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
16 |
21 |
22 |
29 |
30 |
37 | {{ format(proposal, vote.choice) }}
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/components/SpaceProposalsNoProposals.vue:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 | {{ $t('noResultsFound') }}
13 |
14 |
15 |
16 | {{ $t('proposals.createProposal') }}
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/components/SpaceSidebar.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/components/SpaceSidebarSkeleton.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
19 |
20 |
21 | {{ $t('join') }}
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/components/SpaceSidebarSubspaces.vue:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 |
23 |
24 |
{{ $t('mainspace') }}
25 |
26 |
27 |
28 |
29 | {{ mainSpace.name }}
30 |
31 |
32 |
33 |
34 |
35 |
{{ $t('subspaces') }}
36 |
41 |
42 |
43 |
44 | {{ subSpace.name }}
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/src/components/SpaceWarningFlagged.vue:
--------------------------------------------------------------------------------
1 |
34 |
35 |
36 |
37 |
38 | {{ $t('warningSpace') }}
39 | {{
40 | $t('learnMore')
41 | }}
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/components/StrategiesBlockWarning.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 | {{ error.message }}
11 |
12 | {{ $t('learnMore') }}
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/components/TextAutolinker.vue:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/components/TextareaArray.vue:
--------------------------------------------------------------------------------
1 |
22 |
23 |
24 |
25 | {{ title || '' }}
26 |
27 |
34 |
35 |
--------------------------------------------------------------------------------
/src/components/TextareaJson.vue:
--------------------------------------------------------------------------------
1 |
24 |
25 |
26 |
30 |
31 |
--------------------------------------------------------------------------------
/src/components/TheFlashNotification.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
9 |
10 |
11 |
16 |
17 |
18 |
19 | {{ item.message }}
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/components/TheHeader.vue:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 |
13 | {{ $t('header.title') }}
14 |
15 |
16 | {{ $t('header.description') }}
17 |
18 |
21 |
26 | {{ $t('createASpace') }}
27 |
28 |
32 | {{ $t('learnMore') }}
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/components/TheLayout.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
22 |
27 |
28 |
29 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/src/components/TheModalNotification.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/components/TreasuryAssetsList.vue:
--------------------------------------------------------------------------------
1 |
21 |
22 |
23 |
24 |
25 |
26 |
{{ wallet.name }}
27 |
28 |
35 |
42 |
43 |
44 | {{ $t('treasury.assets.empty') }}
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/src/components/TreasuryWalletsList.vue:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
21 |
{{ $t('treasury.title') }}
22 |
23 |
31 |
39 |
40 |
45 |
46 |
47 | {{ $t('treasury.wallets.empty') }}
48 |
49 |
54 | {{ $t('treasury.wallets.addTreasury') }}
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/src/components/Ui/CollapsibleContent.vue:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
35 |
36 |
37 |
63 |
--------------------------------------------------------------------------------
/src/components/Ui/CollapsibleText.vue:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
23 |
24 |
31 |
32 |
43 | {{ text }}
44 |
45 |
46 |
47 |
48 |
55 |
--------------------------------------------------------------------------------
/src/components/Ui/Select.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
29 |
30 |
31 |
32 |
40 |
--------------------------------------------------------------------------------
/src/composables/useApolloQuery.ts:
--------------------------------------------------------------------------------
1 | import cloneDeep from 'lodash/cloneDeep';
2 | import { apolloClient } from '@/helpers/apollo';
3 | import { ensApolloClient } from '@/helpers/ens';
4 |
5 | export function useApolloQuery() {
6 | const loading = ref(false);
7 |
8 | async function apolloQuery(options, path = '') {
9 | try {
10 | loading.value = true;
11 | const response = await apolloClient.query(options);
12 | loading.value = false;
13 |
14 | return cloneDeep(!path ? response.data : response.data[path]);
15 | } catch (error) {
16 | loading.value = false;
17 | console.log(error);
18 | }
19 | }
20 |
21 | async function ensApolloQuery(options) {
22 | try {
23 | loading.value = true;
24 | const response = await ensApolloClient.query(options);
25 | loading.value = false;
26 |
27 | return response.data;
28 | } catch (error) {
29 | loading.value = false;
30 | console.log(error);
31 | }
32 | }
33 |
34 | return {
35 | apolloQuery,
36 | ensApolloQuery,
37 | queryLoading: computed(() => loading.value)
38 | };
39 | }
40 |
--------------------------------------------------------------------------------
/src/composables/useCategories.ts:
--------------------------------------------------------------------------------
1 | import categories from '@/helpers/categories.json';
2 |
3 | export function useCategories() {
4 | const { orderedSpaces } = useSpaces();
5 |
6 | // count spaces per category
7 | const spacesPerCategory = computed(() => {
8 | const spaces = orderedSpaces.value.reduce((counters, space) => {
9 | if (!space.private) {
10 | space.categories?.forEach((c: any) => counters[c]++);
11 | return counters;
12 | }
13 | }, Object.fromEntries(categories.map(c => [c, 0])));
14 | return spaces;
15 | });
16 |
17 | const categoriesOrderedBySpaceCount = computed(() => {
18 | return categories.sort(
19 | (a, b) => spacesPerCategory.value[b] - spacesPerCategory.value[a]
20 | );
21 | });
22 |
23 | return {
24 | categories,
25 | spacesPerCategory,
26 | categoriesOrderedBySpaceCount
27 | };
28 | }
29 |
--------------------------------------------------------------------------------
/src/composables/useCopy.ts:
--------------------------------------------------------------------------------
1 | import { useClipboard } from '@vueuse/core';
2 |
3 | export function useCopy() {
4 | const { t } = useI18n();
5 | const { copy, copied } = useClipboard();
6 | const { notify } = useFlashNotification();
7 |
8 | function copyToClipboard(text) {
9 | copy(text);
10 | if (copied) notify(t('notify.copied'));
11 | }
12 |
13 | return { copyToClipboard };
14 | }
15 |
--------------------------------------------------------------------------------
/src/composables/useFlashNotification.ts:
--------------------------------------------------------------------------------
1 | interface Notification {
2 | id: number;
3 | message: string;
4 | type: string;
5 | remove(): any;
6 | }
7 |
8 | const items = ref([]);
9 |
10 | export function useFlashNotification() {
11 | function notify(payload: any, duration = 4000) {
12 | const item: Notification = {
13 | id: Math.floor(Date.now() * Math.random()),
14 | message: Array.isArray(payload) ? payload[1] : payload,
15 | type: Array.isArray(payload) ? payload[0] : 'green',
16 | remove() {
17 | items.value.splice(
18 | items.value.findIndex(i => i.id === this.id),
19 | 1
20 | );
21 | }
22 | };
23 |
24 | items.value.push(item);
25 | setTimeout(() => item.remove(), duration);
26 | }
27 |
28 | return { notify, items };
29 | }
30 |
--------------------------------------------------------------------------------
/src/composables/useGnosis.ts:
--------------------------------------------------------------------------------
1 | import { getInstance } from '@snapshot-labs/lock/plugins/vue3';
2 | import { ExtendedSpace } from '@/helpers/interfaces';
3 |
4 | const defaultNetwork = import.meta.env.VITE_DEFAULT_NETWORK;
5 |
6 | export function useGnosis(space?: ExtendedSpace) {
7 | const { web3 } = useWeb3();
8 |
9 | const auth = getInstance();
10 | const connectorName = computed(() => auth.provider.value?.connectorName);
11 |
12 | const isGnosisSafe = computed(
13 | () =>
14 | web3.value?.walletConnectType === 'Gnosis Safe Multisig' ||
15 | web3.value?.walletConnectType === 'WalletConnect Safe App' ||
16 | connectorName.value === 'gnosis'
17 | );
18 |
19 | const networkKey = computed(() => web3.value.network.key);
20 |
21 | const spaceNetworkKey = computed(() => space?.network);
22 |
23 | const isGnosisAndNotDefaultNetwork = computed(() => {
24 | return isGnosisSafe.value && networkKey.value !== defaultNetwork;
25 | });
26 |
27 | const isGnosisAndNotSpaceNetwork = computed(() => {
28 | return isGnosisSafe.value && networkKey.value !== spaceNetworkKey.value;
29 | });
30 |
31 | return {
32 | isGnosisSafe,
33 | isGnosisAndNotDefaultNetwork,
34 | isGnosisAndNotSpaceNetwork
35 | };
36 | }
37 |
--------------------------------------------------------------------------------
/src/composables/useI18n.ts:
--------------------------------------------------------------------------------
1 | import { lsGet, lsSet } from '@/helpers/utils';
2 | import i18n, {
3 | defaultLocale,
4 | setI18nLanguage,
5 | loadLocaleMessages
6 | } from '@/helpers/i18n';
7 |
8 | const currentLocale = ref(lsGet('locale', defaultLocale));
9 |
10 | export function useI18n() {
11 | const { t, d, tc } = i18n.global;
12 |
13 | async function setLocale(locale) {
14 | currentLocale.value = locale;
15 | lsSet('locale', locale);
16 | await loadLocaleMessages(i18n, locale);
17 | setI18nLanguage(i18n, locale);
18 | }
19 |
20 | async function loadLocale() {
21 | await loadLocaleMessages(i18n, currentLocale.value);
22 | setI18nLanguage(i18n, currentLocale.value);
23 | }
24 |
25 | return {
26 | t,
27 | d,
28 | tc,
29 | setLocale,
30 | loadLocale,
31 | currentLocale
32 | };
33 | }
34 |
--------------------------------------------------------------------------------
/src/composables/useInfiniteLoader.ts:
--------------------------------------------------------------------------------
1 | export function useInfiniteLoader(loadBy = 6) {
2 | const loadingMore = ref(false);
3 | const stopLoadingMore = ref(false);
4 |
5 | async function loadMore(loadFn) {
6 | if (loadingMore.value) return;
7 | if (!stopLoadingMore.value) {
8 | loadingMore.value = true;
9 | await loadFn();
10 | loadingMore.value = false;
11 | }
12 | }
13 |
14 | return { loadBy, loadingMore, stopLoadingMore, loadMore };
15 | }
16 |
--------------------------------------------------------------------------------
/src/composables/useMeta.ts:
--------------------------------------------------------------------------------
1 | import { useHead } from '@vueuse/head';
2 |
3 | type metaInfo = {
4 | title: {
5 | key: string;
6 | params?: Record;
7 | };
8 | description: {
9 | key: string;
10 | params?: Record;
11 | };
12 | };
13 |
14 | export function useMeta(metaInfo: metaInfo) {
15 | const { t } = useI18n();
16 |
17 | useHead({
18 | title: t(metaInfo.title.key, metaInfo.title.params || {}),
19 | meta: [
20 | {
21 | name: 'description',
22 | content: t(metaInfo.description.key, metaInfo.description.params || {})
23 | }
24 | ]
25 | });
26 |
27 | return {};
28 | }
29 |
--------------------------------------------------------------------------------
/src/composables/useModal.ts:
--------------------------------------------------------------------------------
1 | const modalAccountOpen = ref(false);
2 | const isModalPostVoteOpen = ref(false);
3 |
4 | export function useModal() {
5 | return { modalAccountOpen, isModalPostVoteOpen };
6 | }
7 |
--------------------------------------------------------------------------------
/src/composables/useModalNotification.ts:
--------------------------------------------------------------------------------
1 | interface Notification {
2 | id: number;
3 | description: string;
4 | type: 'info' | 'warning' | 'warning-red';
5 | remove(): any;
6 | }
7 |
8 | const items = ref([]);
9 |
10 | export function useModalNotification() {
11 | function notifyModal(
12 | type: 'info' | 'warning' | 'warning-red',
13 | description: string
14 | ) {
15 | const item: Notification = {
16 | id: Math.floor(Date.now() * Math.random()),
17 | description,
18 | type,
19 | remove() {
20 | items.value.splice(
21 | items.value.findIndex(i => i.id === this.id),
22 | 1
23 | );
24 | }
25 | };
26 |
27 | items.value.push(item);
28 | }
29 |
30 | return { notifyModal, items };
31 | }
32 |
--------------------------------------------------------------------------------
/src/composables/useSafe.ts:
--------------------------------------------------------------------------------
1 | interface ExecutionStatus {
2 | batchError:
3 | | undefined
4 | | {
5 | num: number;
6 | message: string;
7 | };
8 | }
9 |
10 | const state = reactive({
11 | batchError: undefined
12 | });
13 |
14 | export function useSafe() {
15 | function setBatchError(num: number, message: string) {
16 | state.batchError = { num, message };
17 | }
18 |
19 | function clearBatchError() {
20 | state.batchError = undefined;
21 | }
22 |
23 | return {
24 | setBatchError,
25 | clearBatchError,
26 | safesnap: computed(() => state)
27 | };
28 | }
29 |
--------------------------------------------------------------------------------
/src/composables/useSkinsFilter.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Orders skins by spaces count and returns a list of skins
3 | * filtered by the search string (case insensitive).
4 | */
5 |
6 | import { SKINS_COUNT_QUERY } from '@/helpers/queries';
7 | import skins from '@/../snapshot-spaces/skins';
8 |
9 | const skinsSpacesCount: any = ref(null);
10 |
11 | export function useSkinsFilter() {
12 | const loading = ref(false);
13 |
14 | const filterSkins = (q = '') =>
15 | Object.keys(skins)
16 | .filter(s => s.toLowerCase().includes(q.toLowerCase()))
17 | .sort(
18 | (a, b) =>
19 | (skinsSpacesCount.value[b] ?? 0) - (skinsSpacesCount.value[a] ?? 0)
20 | );
21 |
22 | const { apolloQuery } = useApolloQuery();
23 |
24 | async function getSkinsSpacesCount() {
25 | if (skinsSpacesCount.value) return;
26 | loading.value = true;
27 | const res = await apolloQuery(
28 | {
29 | query: SKINS_COUNT_QUERY
30 | },
31 | 'skins'
32 | );
33 | skinsSpacesCount.value = res.reduce(
34 | (obj: any, item: any) => ({ ...obj, [item.id]: item.spacesCount }),
35 | {}
36 | );
37 |
38 | loading.value = false;
39 | }
40 |
41 | return {
42 | filterSkins,
43 | getSkinsSpacesCount,
44 | skinsSpacesCount,
45 | loadingSkins: loading
46 | };
47 | }
48 |
--------------------------------------------------------------------------------
/src/composables/useSnapshot.ts:
--------------------------------------------------------------------------------
1 | import { getBlockNumber } from '@snapshot-labs/snapshot.js/src/utils/web3';
2 | import getProvider from '@snapshot-labs/snapshot.js/src/utils/provider';
3 |
4 | const isLoading = ref(false);
5 | const error = ref(false);
6 |
7 | export function useSnapshot() {
8 | async function getSnapshot(network: string): Promise {
9 | try {
10 | isLoading.value = true;
11 | error.value = false;
12 | const currentBlock = await getBlockNumber(getProvider(network));
13 | console.log('Snapshot block number', currentBlock);
14 | return currentBlock - 4;
15 | } catch (e) {
16 | error.value = true;
17 | return 0;
18 | } finally {
19 | isLoading.value = false;
20 | }
21 | }
22 |
23 | return {
24 | getSnapshot,
25 | isSnapshotLoading: isLoading,
26 | errorFetchingSnapshot: error
27 | };
28 | }
29 |
--------------------------------------------------------------------------------
/src/composables/useTerms.ts:
--------------------------------------------------------------------------------
1 | import { lsSet, lsGet } from '@/helpers/utils';
2 |
3 | export function useTerms(spaceKey) {
4 | const modalTermsOpen = ref(false);
5 | const acceptedSpaces = ref(JSON.parse(lsGet('acceptedTerms', '[]')));
6 | const termsAccepted = ref(acceptedSpaces.value.includes(spaceKey));
7 |
8 | function acceptTerms() {
9 | acceptedSpaces.value.push(spaceKey);
10 | lsSet('acceptedTerms', JSON.stringify(acceptedSpaces.value));
11 | termsAccepted.value = true;
12 | }
13 |
14 | return { modalTermsOpen, termsAccepted, acceptTerms };
15 | }
16 |
--------------------------------------------------------------------------------
/src/composables/useTxStatus.ts:
--------------------------------------------------------------------------------
1 | const pendingCount = ref(0);
2 |
3 | export function useTxStatus() {
4 | watch(pendingCount, () => {
5 | if (pendingCount.value < 0) {
6 | pendingCount.value = 0;
7 | }
8 | });
9 | return { pendingCount };
10 | }
11 |
12 | export function watchTxStatus(cb) {
13 | watch(pendingCount, () => nextTick(cb));
14 | }
15 |
--------------------------------------------------------------------------------
/src/composables/useUsername.ts:
--------------------------------------------------------------------------------
1 | import { shorten } from '@/helpers/utils';
2 | import { Profile } from '@/helpers/interfaces';
3 |
4 | export function useUsername(
5 | address: Ref,
6 | profile?: Ref
7 | ) {
8 | const { web3Account } = useWeb3();
9 |
10 | const username = computed(() => {
11 | if (
12 | web3Account &&
13 | address.value.toLowerCase() === web3Account.value.toLowerCase()
14 | ) {
15 | return 'You';
16 | }
17 |
18 | if (profile?.value?.name) return profile.value.name;
19 | if (profile?.value?.ens) return profile.value.ens;
20 | return shorten(address.value);
21 | });
22 |
23 | return {
24 | username
25 | };
26 | }
27 |
--------------------------------------------------------------------------------
/src/env.d.ts:
--------------------------------------------------------------------------------
1 | interface ImportMetaEnv {
2 | readonly VITE_APP_TITLE: string;
3 | readonly VITE_HUB_URL: string;
4 | readonly VITE_RELAYER_URL: string;
5 | readonly VITE_SCORES_URL: string;
6 | readonly VITE_IPFS_GATEWAY: string;
7 | readonly VITE_DEFAULT_NETWORK: string;
8 | readonly VITE_PUSHER_BEAMS_INSTANCE_ID: string;
9 | }
10 |
--------------------------------------------------------------------------------
/src/helpers/abi.ts:
--------------------------------------------------------------------------------
1 | export const ERC20ABI = [
2 | 'function name() public view returns (string)',
3 | 'function decimals() view returns (uint32)',
4 | 'function symbol() view returns (string)'
5 | ];
6 |
--------------------------------------------------------------------------------
/src/helpers/apollo.ts:
--------------------------------------------------------------------------------
1 | import gql from 'graphql-tag';
2 | import {
3 | ApolloClient,
4 | createHttpLink,
5 | InMemoryCache
6 | } from '@apollo/client/core';
7 |
8 | // HTTP connection to the API
9 | const httpLink = createHttpLink({
10 | // You should use an absolute URL here
11 | uri: `${import.meta.env.VITE_HUB_URL}/graphql`
12 | });
13 |
14 | // Create the apollo client
15 | export const apolloClient = new ApolloClient({
16 | link: httpLink,
17 | cache: new InMemoryCache({
18 | addTypename: false
19 | }),
20 | defaultOptions: {
21 | query: {
22 | fetchPolicy: 'no-cache'
23 | }
24 | },
25 | typeDefs: gql`
26 | enum OrderDirection {
27 | asc
28 | desc
29 | }
30 | `
31 | });
32 |
--------------------------------------------------------------------------------
/src/helpers/auth.ts:
--------------------------------------------------------------------------------
1 | import injected from '@snapshot-labs/lock/connectors/injected';
2 | import walletconnect from '@snapshot-labs/lock/connectors/walletconnect';
3 | import portis from '@snapshot-labs/lock/connectors/portis';
4 | import connectors from '@/helpers/connectors.json';
5 | import walletlink from '@snapshot-labs/lock/connectors/walletlink';
6 | import gnosis from '@snapshot-labs/lock/connectors/gnosis';
7 | import stargazer from '@snapshot-labs/lock/connectors/stargazer';
8 | import kaikas from '@snapshot-labs/lock/connectors/kaikas';
9 |
10 | const options: any = { connectors: [] };
11 | const lockConnectors = {
12 | injected,
13 | walletconnect,
14 | walletlink,
15 | portis,
16 | stargazer,
17 | gnosis,
18 | kaikas
19 | };
20 |
21 | Object.entries(connectors).forEach((connector: any) => {
22 | options.connectors.push({
23 | key: connector[0],
24 | connector: lockConnectors[connector[0]],
25 | options: connector[1].options
26 | });
27 | });
28 |
29 | export default options;
30 |
--------------------------------------------------------------------------------
/src/helpers/b64.ts:
--------------------------------------------------------------------------------
1 | /// URL-safe Base64 encoding and decoding.
2 |
3 | const B64U_LOOKUP = {
4 | '/': '_',
5 | _: '/',
6 | '+': '-',
7 | '-': '+',
8 | '=': '.',
9 | '.': '='
10 | };
11 |
12 | export const encode = str =>
13 | btoa(str).replace(/(\+|\/|=)/g, m => B64U_LOOKUP[m]);
14 |
15 | export const decode = str =>
16 | atob(str.replace(/(-|_|\.)/g, m => B64U_LOOKUP[m]));
17 |
18 | export const encodeJson = json => encode(JSON.stringify(json));
19 | export const decodeJson = str => JSON.parse(decode(str));
20 |
--------------------------------------------------------------------------------
/src/helpers/beams.ts:
--------------------------------------------------------------------------------
1 | import * as PusherPushNotifications from '@pusher/push-notifications-web';
2 |
3 | let beams: any;
4 |
5 | try {
6 | beams = new PusherPushNotifications.Client({
7 | instanceId: (import.meta.env.VITE_PUSHER_BEAMS_INSTANCE_ID as string) ?? ''
8 | });
9 | } catch (e) {
10 | console.log(e);
11 | }
12 |
13 | export { beams };
14 |
--------------------------------------------------------------------------------
/src/helpers/categories.json:
--------------------------------------------------------------------------------
1 | [
2 | "protocol",
3 | "social",
4 | "investment",
5 | "grant",
6 | "service",
7 | "media",
8 | "creator",
9 | "collector"
10 | ]
11 |
--------------------------------------------------------------------------------
/src/helpers/clientEIP712.ts:
--------------------------------------------------------------------------------
1 | import Client from '@snapshot-labs/snapshot.js/src/sign';
2 |
3 | const hubUrl = import.meta.env.VITE_HUB_URL || 'https://testnet.snapshot.org';
4 | const client = new Client(hubUrl);
5 |
6 | export default client;
7 |
--------------------------------------------------------------------------------
/src/helpers/clientGnosisSafe.ts:
--------------------------------------------------------------------------------
1 | import Client from '@snapshot-labs/snapshot.js/src/sign';
2 |
3 | const relayerUrl =
4 | import.meta.env.VITE_RELAYER_URL || 'https://testnet.snapshot.org';
5 | const client = new Client(relayerUrl);
6 |
7 | export default client;
8 |
--------------------------------------------------------------------------------
/src/helpers/covalent.ts:
--------------------------------------------------------------------------------
1 | import snapshot from '@snapshot-labs/snapshot.js';
2 |
3 | const API_URL = 'https://api.covalenthq.com/v1';
4 | const API_KEY = 'ckey_2d082caf47f04a46947f4f212a8';
5 | export const ETHER_CONTRACT = '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee';
6 |
7 | export async function getTokenBalances(
8 | address: string,
9 | chainId: string
10 | ): Promise {
11 | const tokenBalanceUrl = `${API_URL}/${chainId}/address/${address}/balances_v2/?quote-currency=USD&format=JSON&nft=false&no-nft-fetch=true&key=${API_KEY}`;
12 | const tokenBalances = await snapshot.utils.getJSON(tokenBalanceUrl);
13 |
14 | const validTokenBalances = tokenBalances.data.items.filter(
15 | item =>
16 | item.contract_name &&
17 | item.contract_ticker_symbol &&
18 | item.logo_url &&
19 | item.quote
20 | );
21 |
22 | // If there is an ether item, move it to the top of the list
23 | const etherItem = validTokenBalances.find(
24 | item => item.contract_address === ETHER_CONTRACT
25 | );
26 | if (etherItem) {
27 | const index = validTokenBalances.findIndex(
28 | item => item.contract_address === ETHER_CONTRACT
29 | );
30 | validTokenBalances.splice(index, 1);
31 | validTokenBalances.unshift(etherItem);
32 | }
33 |
34 | return validTokenBalances;
35 | }
36 |
37 | export async function getTokenPrices(
38 | contract: string,
39 | chainId: string
40 | ): Promise {
41 | const tokenPricesUrl = `${API_URL}/pricing/historical_by_addresses_v2/${chainId}/USD/${contract}/?quote-currency=USD&format=JSON&key=${API_KEY}`;
42 | return await snapshot.utils.getJSON(tokenPricesUrl);
43 | }
44 |
--------------------------------------------------------------------------------
/src/helpers/delegation.ts:
--------------------------------------------------------------------------------
1 | import {
2 | SNAPSHOT_SUBGRAPH_URL,
3 | subgraphRequest
4 | } from '@snapshot-labs/snapshot.js/src/utils';
5 |
6 | export const contractAddress = '0x469788fE6E9E9681C6ebF3bF78e7Fd26Fc015446';
7 |
8 | export async function getDelegates(network: string, address: string) {
9 | const params = {
10 | delegations: {
11 | __args: {
12 | where: {
13 | delegator: address.toLowerCase()
14 | },
15 | first: 1000
16 | },
17 | space: true,
18 | delegate: true
19 | }
20 | };
21 | return await subgraphRequest(SNAPSHOT_SUBGRAPH_URL[network], params);
22 | }
23 |
24 | export async function getDelegators(network: string, address: string) {
25 | const params = {
26 | delegations: {
27 | __args: {
28 | where: {
29 | delegate: address.toLowerCase()
30 | },
31 | first: 1000
32 | },
33 | delegator: true,
34 | space: true
35 | }
36 | };
37 | return await subgraphRequest(SNAPSHOT_SUBGRAPH_URL[network], params);
38 | }
39 |
--------------------------------------------------------------------------------
/src/helpers/ens.ts:
--------------------------------------------------------------------------------
1 | import {
2 | ApolloClient,
3 | createHttpLink,
4 | InMemoryCache
5 | } from '@apollo/client/core';
6 |
7 | const uri =
8 | import.meta.env.VITE_DEFAULT_NETWORK === '5'
9 | ? 'https://api.thegraph.com/subgraphs/name/ensdomains/ensgoerli'
10 | : 'https://api.thegraph.com/subgraphs/name/ensdomains/ens';
11 |
12 | const httpLink = createHttpLink({ uri });
13 |
14 | export const ensApolloClient = new ApolloClient({
15 | link: httpLink,
16 | cache: new InMemoryCache({
17 | addTypename: false
18 | }),
19 | defaultOptions: {
20 | query: {
21 | fetchPolicy: 'no-cache'
22 | }
23 | }
24 | });
25 |
--------------------------------------------------------------------------------
/src/helpers/shutter.ts:
--------------------------------------------------------------------------------
1 | import { randomBytes } from '@ethersproject/random';
2 | import { BigNumber } from '@ethersproject/bignumber';
3 | import { arrayify, hexlify } from '@ethersproject/bytes';
4 | import { toUtf8Bytes, formatBytes32String } from '@ethersproject/strings';
5 | import shutterWasm from '@shutter-network/shutter-crypto/dist/shutter-crypto.wasm?url';
6 | import { init, encrypt } from '@shutter-network/shutter-crypto';
7 |
8 | export default async function encryptChoice(
9 | choice: string,
10 | id: string
11 | ): Promise {
12 | await init(shutterWasm);
13 |
14 | const bytesChoice = toUtf8Bytes(choice);
15 | const message = arrayify(bytesChoice);
16 | const eonPublicKey = arrayify(import.meta.env.VITE_SHUTTER_EON_PUBKEY);
17 |
18 | const is32ByteString = id.substring(0, 2) === '0x';
19 | const proposalId = arrayify(is32ByteString ? id : formatBytes32String(id));
20 |
21 | const sigma = arrayify(BigNumber.from(randomBytes(32)));
22 |
23 | const encryptedMessage = await encrypt(
24 | message,
25 | eonPublicKey,
26 | proposalId,
27 | sigma
28 | );
29 |
30 | return hexlify(encryptedMessage) ?? null;
31 | }
32 |
--------------------------------------------------------------------------------
/src/helpers/utils.test.js:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { calcFromSeconds, calcToSeconds } from './utils';
3 |
4 | describe('calcFromSeconds', () => {
5 | it('should return 3 for seconds from 10800 to 14399 and unit h', () => {
6 | expect(calcFromSeconds(60 * 60 * 3, 'h')).toBe(3);
7 | expect(calcFromSeconds(60 * 60 * 4 - 1, 'h')).toBe(3);
8 | });
9 |
10 | it('should return 3 for seconds from 259200 to 345599 and unit d', () => {
11 | expect(calcFromSeconds(60 * 60 * 24 * 3, 'd')).toBe(3);
12 | expect(calcFromSeconds(60 * 60 * 24 * 4 - 1, 'd')).toBe(3);
13 | });
14 |
15 | it('should return 3600 for 1 hour and 5400 for 1.5 hours', () => {
16 | expect(calcToSeconds(1, 'h')).toBe(3600);
17 | expect(calcToSeconds(1.5, 'h')).toBe(5400);
18 | });
19 |
20 | it('should return 86400 for 1 day and 129600 for 1.5 days', () => {
21 | expect(calcToSeconds(1, 'd')).toBe(86400);
22 | expect(calcToSeconds(1.5, 'd')).toBe(129600);
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/src/locales/languages.json:
--------------------------------------------------------------------------------
1 | {
2 | "en-US": {
3 | "name": "English"
4 | },
5 | "zh-CN": {
6 | "name": "Chinese",
7 | "nativeName": "简体中文"
8 | },
9 | "ja-JP": {
10 | "name": "Japanese",
11 | "nativeName": "日本語"
12 | },
13 | "ko-KR": {
14 | "name": "Korean",
15 | "nativeName": "한국어"
16 | },
17 | "fr-FR": {
18 | "name": "French",
19 | "nativeName": "Français"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/plugins/README.md:
--------------------------------------------------------------------------------
1 | Discover how to develop a plugin by following our comprehensive documentation at https://docs.snapshot.org/developer-guides/create
2 |
--------------------------------------------------------------------------------
/src/plugins/commentBox/Proposal.vue:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
17 |
18 |
--------------------------------------------------------------------------------
/src/plugins/commentBox/plugin.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Comment Box",
3 | "version": "0.0.1",
4 | "author": "spiritbro1",
5 | "website": "https://github.com/snapshot-labs/snapshot/tree/develop/src/plugins/commentBox",
6 | "icon": "ipfs://QmWpLpFpeQ3iH69uCeXXAfLu56YaL9mNESMGfeJ5XSpkhY"
7 | }
8 |
--------------------------------------------------------------------------------
/src/plugins/gnosis/Create.vue:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/plugins/gnosis/ProposalSidebar.vue:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
14 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/plugins/gnosis/plugin.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Gnosis Impact",
3 | "version": "0.0.1",
4 | "author": "davidalbela",
5 | "website": "https://...",
6 | "icon": "ipfs://QmPhmL1jPjaYKeKeEzyetAueNHCsGgrUVqSJasiTrcPWvx",
7 | "defaults": {
8 | "space": {},
9 | "proposal": {}
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/plugins/hal/ProposalSidebar.vue:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/plugins/hal/components/CustomBlock.vue:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
16 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/src/plugins/hal/plugin.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "HAL",
3 | "version": "1.0.0",
4 | "author": "hal.xyz",
5 | "website": "https://github.com/snapshot-labs/snapshot/tree/develop/src/plugins/hal",
6 | "icon": "ipfs://QmUjiGPfzTUT6KZJe2iDNtca9XnuVw9iXwQUB2ncCLSoMK"
7 | }
8 |
--------------------------------------------------------------------------------
/src/plugins/poap/ProposalSidebar.vue:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
22 |
23 |
--------------------------------------------------------------------------------
/src/plugins/poap/plugin.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Poap Module",
3 | "version": "1.0.0",
4 | "author": "Poap-xyz",
5 | "website": "https://github.com/snapshot-labs/snapshot/tree/develop/src/plugins/poap",
6 | "icon": "ipfs://QmSH2PsJUSpHUwS9XAoqLKRvF7qibrsqmBTdmM9Mmyv5fb"
7 | }
8 |
--------------------------------------------------------------------------------
/src/plugins/progress/ProposalSidebar.vue:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
21 |
22 |
--------------------------------------------------------------------------------
/src/plugins/progress/index.ts:
--------------------------------------------------------------------------------
1 | export default class Plugin {
2 | public author = 'nick';
3 | public version = '0.1.0';
4 | public name = 'progess';
5 | }
6 |
--------------------------------------------------------------------------------
/src/plugins/progress/plugin.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Progress",
3 | "version": "1.0.0",
4 | "author": "Deadeye07",
5 | "website": "https://github.com/Deadeye07/snapshot-develop/tree/master/src/plugins/progress",
6 | "icon": "ipfs://Qmd1Zpmscf5HBvh5ouu6AUcDTst28CKYyrpfGnPCqd73gZ"
7 | }
8 |
--------------------------------------------------------------------------------
/src/plugins/progress/readme.md:
--------------------------------------------------------------------------------
1 | # Progress
2 |
3 | ## Keep Track of [Snapshot.org](http://Snapshot.org) Proposal Progress
4 |
5 | Progress is a small and simple plugin for [Snapshot.org](http://Snapshot.org) that allows Spaces to inform DAO members the progress of a proposal _after_ voting has completed - how a proposal is progressing in being executed. Often, finding this information requires monitoring notificatiosn on Discord, Telegram and Twitter - what if we could just check back right at the source of the proposal on Snapshot? Yes please.
6 |
7 | ## Features
8 | * Creation of New Steps
9 | * Marking of steps as 'Completed'
10 | * Deletion of Steps (Only allowed for steps yet to be 'Completed')
11 | * Web3 Signature Authetication
12 | * Cool loading spinners
13 |
14 | ## Who can add, complete, and delete steps?
15 | Only a Proposals Author is able to view the Edit button, which displays options to do the following:
16 | - Create new Steps
17 | - Mark Steps as 'Complete'
18 | - Delete Steps
19 |
--------------------------------------------------------------------------------
/src/plugins/projectGalaxy/ProposalSidebar.vue:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
22 |
23 |
--------------------------------------------------------------------------------
/src/plugins/projectGalaxy/plugin.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Galxe",
3 | "version": "0.0.1",
4 | "author": "Galxe",
5 | "description": "Galxe OAT",
6 | "website": "https://github.com/snapshot-labs/snapshot/tree/develop/src/plugins/projectGalaxy",
7 | "icon": "https://ipfs.io/ipfs/bafkreibjxoeegwucimd4hjfn3xmxrmkes3je5gwa723gaqosirzgewutfq",
8 | "defaults": {
9 | "space": {
10 | "oats": {
11 | "": "/campaign/"
12 | }
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/plugins/quorum/plugin.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Quorum",
3 | "version": "0.1.0",
4 | "author": "lbeder",
5 | "website": "https://github.com/snapshot-labs/snapshot/tree/develop/src/plugins/quorum",
6 | "icon": "ipfs://Qmbyq2emXpjv1oFFJnhS3jL8aXZAqnya7zmNtKYXEs8jXa",
7 | "defaults": {
8 | "space": {
9 | "strategy": "static",
10 | "total": 1234
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/plugins/safeSnap/Create.vue:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
27 |
28 |
--------------------------------------------------------------------------------
/src/plugins/safeSnap/Proposal.vue:
--------------------------------------------------------------------------------
1 |
35 |
36 |
37 |
50 |
51 |
--------------------------------------------------------------------------------
/src/plugins/safeSnap/components/Input/Address.vue:
--------------------------------------------------------------------------------
1 |
33 |
34 |
35 |
42 | {{ label }}
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/plugins/safeSnap/components/Input/Amount.vue:
--------------------------------------------------------------------------------
1 |
54 |
55 |
56 |
63 | {{ label }}
64 |
65 |
66 |
--------------------------------------------------------------------------------
/src/plugins/safeSnap/components/Tooltip.vue:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Multisend address
21 |
25 | {{ shorten(multiSendAddress) }}
26 |
27 |
28 |
29 | {{ moduleType === 'reality' ? 'Reality' : 'UMA' }} Module address
30 |
31 |
35 | {{ shorten(moduleAddress) }}
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/plugins/safeSnap/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bigint/snapshot/4394734b8ae05cbc99f386a6068592fe22328b20/src/plugins/safeSnap/logo.png
--------------------------------------------------------------------------------
/src/plugins/safeSnap/plugin.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Gnosis SafeSnap",
3 | "version": "1.0.0",
4 | "author": "Gnosis",
5 | "website": "https://safe.gnosis.io",
6 | "icon": "ipfs://QmQjZaheMTLRrk22mrGCkGk2LNoNqqYMR8Bxtwa8mBHyc9",
7 | "defaults": {
8 | "space": {
9 | "safes": [
10 | {
11 | "network": "CHAIN_ID",
12 | "realityAddress": "0xSWITCH_WITH_REALITY_MODULE_ADDRESS",
13 | "umaAddress": "0xSWITCH_WITH_UMA_MODULE_ADDRESS"
14 | }
15 | ]
16 | },
17 | "proposal": {
18 | "safes": [
19 | {
20 | "network": "CHAIN_ID",
21 | "realityAddress": "0xSWITCH_WITH_REALITY_MODULE_ADDRESS",
22 | "umaAddress": "0xSWITCH_WITH_UMA_MODULE_ADDRESS"
23 | }
24 | ]
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/plugins/safeSnap/utils/coins.ts:
--------------------------------------------------------------------------------
1 | import { TokenAsset } from '@/helpers/interfaces';
2 |
3 | export const ETHEREUM_COIN: TokenAsset = {
4 | name: 'Ether',
5 | decimals: 18,
6 | symbol: 'ETH',
7 | logoUri:
8 | 'https://safe-transaction-assets.gnosis-safe.io/chains/1/currency_logo.png',
9 | address: 'main'
10 | };
11 | export const MATIC_COIN: TokenAsset = {
12 | name: 'MATIC',
13 | decimals: 18,
14 | symbol: 'MATIC',
15 | address: 'main',
16 | logoUri:
17 | 'https://safe-transaction-assets.gnosis-safe.io/chains/137/currency_logo.png'
18 | };
19 | const EWC_COIN: TokenAsset = {
20 | name: 'Energy Web Token',
21 | symbol: 'EWT',
22 | address: 'main',
23 | decimals: 18,
24 | logoUri:
25 | 'https://safe-transaction-assets.gnosis-safe.io/chains/246/currency_logo.png'
26 | };
27 | const XDAI_COIN: TokenAsset = {
28 | name: 'XDAI',
29 | symbol: 'XDAI',
30 | address: 'main',
31 | decimals: 18,
32 | logoUri:
33 | 'https://safe-transaction-assets.gnosis-safe.io/chains/100/currency_logo.png'
34 | };
35 | const BNB_COIN: TokenAsset = {
36 | name: 'BNB',
37 | symbol: 'BNB',
38 | address: 'main',
39 | decimals: 18,
40 | logoUri:
41 | 'https://safe-transaction-assets.gnosis-safe.io/chains/56/currency_logo.png'
42 | };
43 |
44 | export function getNativeAsset(network) {
45 | switch (parseInt(network)) {
46 | case 137:
47 | case 80001:
48 | return MATIC_COIN;
49 | case 100:
50 | return XDAI_COIN;
51 | case 246:
52 | return EWC_COIN;
53 | case 56:
54 | return BNB_COIN;
55 | }
56 |
57 | return ETHEREUM_COIN;
58 | }
59 |
--------------------------------------------------------------------------------
/src/plugins/safeSnap/utils/multiSend.ts:
--------------------------------------------------------------------------------
1 | import { pack } from '@ethersproject/solidity';
2 | import { Interface } from '@ethersproject/abi';
3 | import { hexDataLength } from '@ethersproject/bytes';
4 |
5 | import { SafeTransaction } from '@/helpers/interfaces';
6 | import { MULTI_SEND_ABI, MULTI_SEND_VERSIONS } from '../constants';
7 |
8 | export enum MULTI_SEND_VERSION {
9 | V1_3_0 = '1.3.0',
10 | V1_2_0 = '1.2.0',
11 | V1_1_1 = '1.1.1'
12 | }
13 |
14 | export function getMultiSend(
15 | network: number | string,
16 | version: MULTI_SEND_VERSION = MULTI_SEND_VERSION.V1_3_0
17 | ) {
18 | return MULTI_SEND_VERSIONS[version][network.toString()];
19 | }
20 |
21 | export function encodeTransactions(transactions: SafeTransaction[]) {
22 | const values = transactions.map(tx => [
23 | tx.operation,
24 | tx.to,
25 | tx.value,
26 | hexDataLength(tx.data || '0x'),
27 | tx.data || '0x'
28 | ]);
29 |
30 | const types = transactions.map(() => [
31 | 'uint8',
32 | 'address',
33 | 'uint256',
34 | 'uint256',
35 | 'bytes'
36 | ]);
37 |
38 | return pack(types.flat(1), values.flat(1));
39 | }
40 |
41 | export function createMultiSendTx(
42 | txs: SafeTransaction[],
43 | nonce: number,
44 | multiSendAddress: string
45 | ) {
46 | const multiSendContract = new Interface(MULTI_SEND_ABI);
47 | const transactionsEncoded = encodeTransactions(txs);
48 | const data = multiSendContract.encodeFunctionData('multiSend', [
49 | transactionsEncoded
50 | ]);
51 | return {
52 | to: multiSendAddress,
53 | operation: '1',
54 | value: '0',
55 | nonce: nonce.toString(),
56 | data
57 | };
58 | }
59 |
--------------------------------------------------------------------------------
/src/plugins/safeSnap/utils/realityETH.ts:
--------------------------------------------------------------------------------
1 | import { StaticJsonRpcProvider } from '@ethersproject/providers';
2 | import { BigNumber } from '@ethersproject/bignumber';
3 | import { multicall } from '@snapshot-labs/snapshot.js/src/utils';
4 | import { ORACLE_ABI } from '../constants';
5 |
6 | export const retrieveInfoFromOracle = async (
7 | provider: StaticJsonRpcProvider,
8 | network: string,
9 | oracleAddress: string,
10 | questionId: string | undefined
11 | ): Promise<{
12 | currentBond: BigNumber | undefined;
13 | isApproved: boolean;
14 | endTime: number | undefined;
15 | }> => {
16 | if (questionId) {
17 | const result = await multicall(network, provider, ORACLE_ABI, [
18 | [oracleAddress, 'getFinalizeTS', [questionId]],
19 | [oracleAddress, 'getBond', [questionId]],
20 | [oracleAddress, 'getBestAnswer', [questionId]]
21 | ]);
22 |
23 | const currentBond = BigNumber.from(result[1][0]);
24 | const answer = BigNumber.from(result[2][0]);
25 |
26 | return {
27 | currentBond,
28 | isApproved: answer.eq(BigNumber.from(1)),
29 | endTime: BigNumber.from(result[0][0]).toNumber()
30 | };
31 | }
32 | return {
33 | currentBond: undefined,
34 | isApproved: false,
35 | endTime: undefined
36 | };
37 | };
38 |
--------------------------------------------------------------------------------
/src/plugins/safeSnap/utils/safe.ts:
--------------------------------------------------------------------------------
1 | import { GNOSIS_SAFE_TRANSACTION_API_URLS } from '../constants';
2 | import { TokenAsset } from '@/helpers/interfaces';
3 | import memoize from 'lodash/memoize';
4 |
5 | async function callGnosisSafeTransactionApi(network: string, url: string) {
6 | const apiUrl = GNOSIS_SAFE_TRANSACTION_API_URLS[network];
7 | const response = await fetch(apiUrl + url);
8 | return response.json();
9 | }
10 |
11 | export const getGnosisSafeBalances = memoize(
12 | (network, safeAddress) => {
13 | const endpointPath = `/safes/${safeAddress}/balances/`;
14 | return callGnosisSafeTransactionApi(network, endpointPath);
15 | },
16 | (safeAddress, network) => `${safeAddress}_${network}`
17 | );
18 |
19 | export const getGnosisSafeCollectibles = memoize(
20 | (network, safeAddress) => {
21 | const endpointPath = `/safes/${safeAddress}/collectibles/`;
22 | return callGnosisSafeTransactionApi(network, endpointPath);
23 | },
24 | (safeAddress, network) => `${safeAddress}_${network}`
25 | );
26 |
27 | export const getGnosisSafeToken = memoize(
28 | async (network, tokenAddress): Promise => {
29 | const endpointPath = `/tokens/${tokenAddress}`;
30 | return callGnosisSafeTransactionApi(network, endpointPath);
31 | },
32 | (tokenAddress, network) => `${tokenAddress}_${network}`
33 | );
34 |
--------------------------------------------------------------------------------
/src/plugins/safeSnap/utils/validator.ts:
--------------------------------------------------------------------------------
1 | import { mustBeEthereumAddress, isArrayParameter } from '../index';
2 |
3 | export const isAddress = (type: string): boolean =>
4 | type.indexOf('address') === 0;
5 | export const isBoolean = (type: string): boolean => type.indexOf('bool') === 0;
6 | export const isString = (type: string): boolean => type.indexOf('string') === 0;
7 | export const isUint = (type: string): boolean => type.indexOf('uint') === 0;
8 | export const isInt = (type: string): boolean => type.indexOf('int') === 0;
9 | export const isByte = (type: string): boolean => type.indexOf('byte') === 0;
10 |
11 | export const isStringArray = (text: string): boolean => {
12 | try {
13 | const values = JSON.parse(text);
14 | return Array.isArray(values);
15 | } catch (e) {
16 | return false;
17 | }
18 | };
19 |
20 | export const isParameterValue = (type: string, value: string) => {
21 | if (type === 'address') {
22 | return mustBeEthereumAddress(value);
23 | } else if (isArrayParameter(type)) {
24 | return isStringArray(value);
25 | }
26 | return !!value;
27 | };
28 |
--------------------------------------------------------------------------------
/src/vars.scss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bigint/snapshot/4394734b8ae05cbc99f386a6068592fe22328b20/src/vars.scss
--------------------------------------------------------------------------------
/src/views/ProfileView.vue:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
22 |
23 |
24 |
28 |
29 |
30 |
31 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/src/views/SpaceTreasury.vue:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "esnext",
5 | "moduleResolution": "node",
6 | "strict": true,
7 | "jsx": "preserve",
8 | "sourceMap": true,
9 | "resolveJsonModule": true,
10 | "esModuleInterop": true,
11 | "lib": ["esnext", "dom"],
12 | "importHelpers": true,
13 | "allowSyntheticDefaultImports": true,
14 | "allowJs": true,
15 | "baseUrl": ".",
16 | "types": ["vite/client", "unplugin-icons/types/vue"],
17 | "paths": {
18 | "@/*": ["src/*"]
19 | },
20 | "noImplicitAny": false,
21 | "skipLibCheck": true,
22 | "outDir": "dist"
23 | },
24 | "include": [
25 | "src/**/*.ts",
26 | "src/**/*.d.ts",
27 | "src/**/*.tsx",
28 | "src/**/*.vue",
29 | "components.d.ts",
30 | "auto-imports.d.ts"
31 | ]
32 | }
33 |
--------------------------------------------------------------------------------
/vitest.ts:
--------------------------------------------------------------------------------
1 | import createFetchMock from 'vitest-fetch-mock';
2 | import { vi } from 'vitest';
3 |
4 | const fetchMock = createFetchMock(vi);
5 |
6 | // sets globalThis.fetch and globalThis.fetchMock to our mocked version
7 | fetchMock.enableMocks();
8 |
--------------------------------------------------------------------------------