From 0406117533716a8363c777e866b82cae7f51d801 Mon Sep 17 00:00:00 2001 From: hthieu1110 Date: Sat, 3 Aug 2024 18:59:12 +0700 Subject: [PATCH] feat: gno projects_manager (#702) * wip: init screen * wip: opti simple button * wip: adding home for grants page * wip: Grant home page * fix: remove createStyleSheet * chore: adjust code * wip: detail page * wip: add detail page * wip: add detailf info of task * chore: fix lint * wip: add grants manager screen * chore: layout.padding => layout.spacing * wip: add grants manager * wip: add screen payment * wip: adding makeing request page * wip: adding pages of making grants request * feat: all pages of Grants, except step 5 * chore: refactor code due to change of components path * wip: integrate with formik + zustand * wip: refactor + add filter * Wip: add cover image + full flow create grant * chore: Refactor Grant => project + add progress bar * Wip: working on integration with Gno * update network json * chore: fix lint * feat: complete flow for funder/creator * fix: fix flex layout for projects list * chore: use empty value instead of fake one * fix: fix lint + gen network * fix: fix lint * fix: remove fake data * fix: fix json parser * fix: ipfs link * fix: generate ipfs key * fix: lint * fix: optimize error display * fix: handle tns name * fix: handle tns name * fix: handle empty userId * chore: update dependencies * wip * feat: update ui * wip: update code related to contracts change + handle token display * feat: add conflict solver in form Signed-off-by: Norman Meier * chore: run lint-fix Signed-off-by: Norman Meier * chore: pass CI Signed-off-by: Norman Meier * chore: revert uneeded changes Signed-off-by: Norman Meier * fix: inject buffer on all platforms Signed-off-by: Norman Meier * feat: add submit/accept contractor candidates * fix: use gnot and start conflict resolution ui Signed-off-by: Norman Meier * feat: add candiates review + adjust UI * tmp: working conflict resolution flow Signed-off-by: Norman Meier * fix: lint Signed-off-by: Norman Meier * feat: disable candidates button when no candidates Signed-off-by: Norman Meier * chore: optimize UI * feat: improve conflict solving flow Signed-off-by: Norman Meier * fix: conflict flow Signed-off-by: Norman Meier * chore: refactor ProjectsConflictsSolvingScreen * chore: refactor code * feat(DAppStore): update getFromFile.ts - Updated the key name from 'projectsProgram' to 'projects' - Updated the title and icon for the 'projects' option * chore: refactor code using aliases + execEscrowMethod * fix: fix style for project detail page * chore: regen Signed-off-by: Norman Meier * tmp Signed-off-by: Norman Meier * fix: linter errors Signed-off-by: Norman Meier * fix: tested contractor and proposer full flow Signed-off-by: Norman Meier * fix: add cypress root config Signed-off-by: Norman Meier * chore: run cypress on ci Signed-off-by: Norman Meier * chore: split e2e tests on ci Signed-off-by: Norman Meier * fix: script name Signed-off-by: Norman Meier * chore: use https remote Signed-off-by: Norman Meier * fix: properly setup go in ci Signed-off-by: Norman Meier * fix: enable gnodev server mode Signed-off-by: Norman Meier * fix: wait-on timeout Signed-off-by: Norman Meier * chore: big timeout Signed-off-by: Norman Meier * fix: use correct port Signed-off-by: Norman Meier * chore: bigger initial visit timeout Signed-off-by: Norman Meier * fix: test env Signed-off-by: Norman Meier * fix: first visit timeout Signed-off-by: Norman Meier * chore; headed mode Signed-off-by: Norman Meier * chore: error screenshot Signed-off-by: Norman Meier * chore: pin node version in e2e Signed-off-by: Norman Meier * chore: increase timeouts Signed-off-by: Norman Meier * chore: use node20 an increase timeout Signed-off-by: Norman Meier * chore: sync nvmrc and cypress node version Signed-off-by: Norman Meier * chore: record nad better confirm Signed-off-by: Norman Meier * chore: no record Signed-off-by: Norman Meier * chore: codegen Signed-off-by: Norman Meier * chore: pin and sync ci versions Signed-off-by: Norman Meier * chore: go mod tidy Signed-off-by: Norman Meier * chore: lint Signed-off-by: Norman Meier * chore: bring gno project manager code in monorepo Signed-off-by: Norman Meier * chore: sync with latest gno and dapp Signed-off-by: Norman Meier * tmp Signed-off-by: Norman Meier * fix: update gno clients to support breaking change Signed-off-by: Norman Meier * chore: use react-hook-form and zod instead of adding formik and yup Signed-off-by: Norman Meier * chore: remove dev artifact Signed-off-by: Norman Meier * chore: remove dev artifact Signed-off-by: Norman Meier * chore: rename preload helper test Signed-off-by: Norman Meier * chore: clean fixtures Signed-off-by: Norman Meier * fix: wait for upload end Signed-off-by: Norman Meier * chore: move jsonutil to pass ci Signed-off-by: Norman Meier * fix: use go1.20 in desktop build Signed-off-by: Norman Meier * chore: check gno mod files Signed-off-by: Norman Meier * fix: use xargs in gno-mod-tidy to make ci fail if tidy fails Signed-off-by: Norman Meier * fix: cross-platform xargs Signed-off-by: Norman Meier * chore: remove dev artifacts Signed-off-by: Norman Meier * chore: remove dev artifact Signed-off-by: Norman Meier * fix: gno version in e2e tests Signed-off-by: Norman Meier * chore: use namespaced packages paths Signed-off-by: Norman Meier * fix: gno mod tidy Signed-off-by: Norman Meier * chore: lint Signed-off-by: Norman Meier * chore: remove commented code and some console.log Signed-off-by: Norman Meier * fix: setup adena mock only if required Signed-off-by: Norman Meier * chore: revert tmp change Signed-off-by: Norman Meier * chore: cleanup Signed-off-by: Norman Meier * chore: disable by default Signed-off-by: Norman Meier * feat: allow to hide dapps behind dev mode Signed-off-by: Norman Meier --------- Signed-off-by: Norman Meier Co-authored-by: Norman Meier Co-authored-by: Eng. Juan Combetto Co-authored-by: n0izn0iz --- .github/workflows/buf-lint.yml | 6 +- .github/workflows/desktop-build.yml | 14 +- .github/workflows/e2e.yml | 37 + .github/workflows/gen.yml | 10 +- .github/workflows/gno-lint.yml | 15 +- .github/workflows/go.yml | 4 +- .github/workflows/js.yml | 4 +- .github/workflows/mobile-build-android.yml | 4 +- .github/workflows/mobile-build-ios.yml | 4 +- .github/workflows/rust.yml | 2 +- .nvmrc | 2 +- Makefile | 20 +- assets/icons/github.svg | 3 + assets/icons/no-tasks.svg | 3 + assets/icons/projects-completed.svg | 5 + assets/icons/projects-inProgress.svg | 5 + assets/icons/projects-open.svg | 4 + assets/icons/projects-program.svg | 10 + assets/icons/projects-review.svg | 5 + assets/project-success-payment.png | Bin 0 -> 23017 bytes cypress.config.ts | 11 + cypress/e2e/0_preload.cy.ts | 9 + cypress/e2e/lib.ts | 16 + cypress/e2e/projects-contractor.cy.ts | 93 ++ cypress/e2e/projects-funder.cy.ts | 102 ++ cypress/fixtures/image.png | Bin 0 -> 393421 bytes cypress/support/commands.ts | 37 + cypress/support/e2e.ts | 20 + gno/p/jsonutil/gno.mod | 7 + gno/p/jsonutil/jsonutil.gno | 131 +++ gno/p/ujson/gno.mod | 2 +- gno/r/projects_manager/filter.gno | 81 ++ gno/r/projects_manager/gno.mod | 9 + gno/r/projects_manager/projects_manager.gno | 941 ++++++++++++++++++ .../projects_manager_test.gno | 74 ++ gno/r/social_feeds/gno.mod | 4 +- go/pkg/networks/features.gen.go | 27 + networks.json | 865 +++++++++++++++- package.json | 22 +- packages/components/FlexRow.tsx | 2 +- packages/components/ProgressLine.tsx | 37 +- packages/components/Search/SearchBarInput.tsx | 16 +- .../components/Search/SearchBarResults.tsx | 2 +- .../components/TopMenu/TopMenuAccount.tsx | 11 +- packages/components/TopMenu/WalletView.tsx | 1 + packages/components/UserNameInline.tsx | 46 - packages/components/WalletProviderIcon.tsx | 3 + packages/components/buttons/IconButton.tsx | 1 + packages/components/buttons/PrimaryButton.tsx | 3 + .../buttons}/SimpleButton.tsx | 36 +- packages/components/buttons/SocialButton.tsx | 113 ++- .../connectWallet/ConnectAdenaButton.tsx | 1 + packages/components/hub/AssetRatioByChain.tsx | 6 +- packages/components/hub/HubLanding.tsx | 2 +- .../images/RoundedGradientImage.tsx | 23 +- packages/components/inputs/SelectInput.tsx | 3 + .../components/inputs/TextInputCustom.tsx | 2 + packages/components/layout/GridList.tsx | 10 + .../components/loaders/AnimatedLoader.tsx | 4 +- .../components/loaders/LoaderFullScreen.tsx | 2 +- .../components/modals/ConnectWalletModal.tsx | 3 + .../navigation/getNormalModeScreens.tsx | 68 ++ .../components/user/UsernameWithAvatar.tsx | 50 + packages/context/SidebarProvider.tsx | 57 +- .../WalletsProvider/WalletsProvider.tsx | 21 +- .../context/WalletsProvider/gnotest/index.tsx | 309 ++++++ packages/hooks/useNSNameInfo.ts | 3 +- .../networks/cosmos-hub-theta/currencies.ts | 1 + packages/networks/cosmos-hub/currencies.ts | 1 + packages/networks/cosmos-registry.ts | 1 + .../networks/ethereum-goerli/currencies.ts | 1 + packages/networks/ethereum/currencies.ts | 1 + packages/networks/features.ts | 17 +- packages/networks/gno-dev/currencies.ts | 11 + packages/networks/gno-dev/index.ts | 32 +- packages/networks/gno-portal/currencies.ts | 1 + packages/networks/gno-portal/index.ts | 18 +- packages/networks/gno-teritori/currencies.ts | 1 + packages/networks/gno-teritori/index.ts | 26 +- packages/networks/gno-test3/currencies.ts | 1 + packages/networks/gno-test4/currencies.ts | 1 + .../networks/osmosis-testnet/currencies.ts | 1 + packages/networks/osmosis/currencies.ts | 1 + .../networks/polygon-mumbai/currencies.ts | 1 + packages/networks/polygon/currencies.ts | 1 + packages/networks/saga-test2/index.ts | 1 + packages/networks/saga/index.ts | 1 + .../networks/teritori-localnet/currencies.ts | 1 + .../networks/teritori-testnet/currencies.ts | 1 + packages/networks/teritori/currencies.ts | 1 + packages/networks/types.ts | 1 + .../DAppStore/components/RightRail.tsx | 12 +- .../screens/DAppStore/query/getFromFile.ts | 12 + .../component/MarketplaceLeaderboardTable.tsx | 4 +- .../screens/Mini/Wallet/SendingToriScreen.tsx | 4 +- .../Projects/CompleteMilestoneScreen.tsx | 263 +++++ .../NewConflictSection.tsx | 82 ++ .../OngoingConflictSection.tsx | 298 ++++++ .../SettledConflictsSection.tsx | 204 ++++ .../ProjectsConflictSolvingScreen/index.tsx | 45 + .../ProjectsConflictSolvingScreen/types.ts | 2 + .../ProjectsDetailScreen/MilestoneDetail.tsx | 222 +++++ .../Projects/ProjectsDetailScreen/index.tsx | 74 ++ .../ConfirmAndSign.tsx | 338 +++++++ .../ProjectsMakeRequestScreen/Footer.tsx | 49 + .../ProjectsMakeRequestScreen/Milestones.tsx | 42 + .../ProjectsMakeRequestScreen/Preview.tsx | 68 ++ .../ShortPresentation.tsx | 248 +++++ .../TeamAndLinks.tsx | 159 +++ .../ProjectsMakeRequestScreen/index.tsx | 45 + .../ContractorCandidates.tsx | 177 ++++ .../MilestonesUpdateManager.tsx | 181 ++++ .../MyProjectsManager.tsx | 190 ++++ .../ProjectsManagerScreen/Requests.tsx | 342 +++++++ .../Projects/ProjectsManagerScreen/index.tsx | 99 ++ .../Projects/ProjectsManagerScreen/types.ts | 17 + .../Projects/ProjectsPaymentScreen.tsx | 248 +++++ packages/screens/Projects/ProjectsScreen.tsx | 104 ++ .../Projects/components/Breadcrumb.tsx | 132 +++ .../Projects/components/ButtonsGroup.tsx | 58 ++ .../Projects/components/FundProjectModal.tsx | 184 ++++ .../Projects/components/HeaderBackButton.tsx | 24 + .../screens/Projects/components/Milestone.tsx | 40 + .../Projects/components/MilestoneBoard.tsx | 181 ++++ .../Projects/components/MilestoneForm.tsx | 248 +++++ .../Projects/components/MilestoneItem.tsx | 162 +++ .../Projects/components/MilestoneList.tsx | 41 + .../components/MilestonePriorityTag.tsx | 20 + .../components/MilestoneStatusTag.tsx | 22 + .../Projects/components/ProjectBox.tsx | 249 +++++ .../components/ProjectInfo/LeftBlock.tsx | 207 ++++ .../components/ProjectInfo/RelatedUsers.tsx | 83 ++ .../components/ProjectInfo/RightBlock.tsx | 176 ++++ .../Projects/components/ProjectInfo/index.tsx | 41 + .../Projects/components/ProjectMilestones.tsx | 78 ++ .../Projects/components/ProjectStatusTag.tsx | 92 ++ .../ProjectsStatusFilterButtons.tsx | 63 ++ .../components/ResolveConflictButton.tsx | 28 + .../SubmitContractorCandidateModal.tsx | 128 +++ .../screens/Projects/components/TNSResult.tsx | 49 + packages/screens/Projects/defaultValues.ts | 32 + .../Projects/hooks/useEscrowContract.ts | 98 ++ .../Projects/hooks/useMakeRequestHook.tsx | 125 +++ .../screens/Projects/hooks/useProjects.ts | 114 +++ packages/screens/Projects/hooks/useUtils.ts | 20 + packages/screens/Projects/types.ts | 160 +++ packages/screens/Projects/utils.ts | 12 + .../screens/RiotGame/RiotGameEnrollScreen.tsx | 2 +- .../RiotGame/component/FightSectionHeader.tsx | 2 +- .../component/RipperGridSelectorModal.tsx | 2 +- .../component/RipperSelectorModal.tsx | 84 +- packages/screens/Settings/SettingsScreen.tsx | 1 + .../Settings/components/SettingItem.tsx | 9 +- packages/scripts/addrFromMnemo.ts | 27 + packages/scripts/gnoQuery.ts | 34 +- packages/scripts/inject-projects.ts | 113 +++ packages/scripts/install-gno.ts | 18 + packages/scripts/validateNetworks.ts | 18 + packages/utils/gno.ts | 2 +- packages/utils/navigation.ts | 17 + packages/utils/sidebar.ts | 7 + packages/utils/style/colors.ts | 1 + packages/utils/types/dapp-store.ts | 1 + packages/utils/wallet/getNativeWallet.ts | 2 +- packages/utils/walletProvider.ts | 1 + paralint.json | 2 +- tsconfig.json | 2 +- yarn.lock | 901 +++++++++++++++-- 168 files changed, 10827 insertions(+), 381 deletions(-) create mode 100644 .github/workflows/e2e.yml create mode 100644 assets/icons/github.svg create mode 100644 assets/icons/no-tasks.svg create mode 100644 assets/icons/projects-completed.svg create mode 100644 assets/icons/projects-inProgress.svg create mode 100644 assets/icons/projects-open.svg create mode 100644 assets/icons/projects-program.svg create mode 100644 assets/icons/projects-review.svg create mode 100644 assets/project-success-payment.png create mode 100644 cypress.config.ts create mode 100644 cypress/e2e/0_preload.cy.ts create mode 100644 cypress/e2e/lib.ts create mode 100644 cypress/e2e/projects-contractor.cy.ts create mode 100644 cypress/e2e/projects-funder.cy.ts create mode 100644 cypress/fixtures/image.png create mode 100644 cypress/support/commands.ts create mode 100644 cypress/support/e2e.ts create mode 100644 gno/p/jsonutil/gno.mod create mode 100644 gno/p/jsonutil/jsonutil.gno create mode 100644 gno/r/projects_manager/filter.gno create mode 100644 gno/r/projects_manager/gno.mod create mode 100644 gno/r/projects_manager/projects_manager.gno create mode 100644 gno/r/projects_manager/projects_manager_test.gno delete mode 100644 packages/components/UserNameInline.tsx rename packages/{screens/RiotGame/component => components/buttons}/SimpleButton.tsx (72%) create mode 100644 packages/components/user/UsernameWithAvatar.tsx create mode 100644 packages/context/WalletsProvider/gnotest/index.tsx create mode 100644 packages/screens/Projects/CompleteMilestoneScreen.tsx create mode 100644 packages/screens/Projects/ProjectsConflictSolvingScreen/NewConflictSection.tsx create mode 100644 packages/screens/Projects/ProjectsConflictSolvingScreen/OngoingConflictSection.tsx create mode 100644 packages/screens/Projects/ProjectsConflictSolvingScreen/SettledConflictsSection.tsx create mode 100644 packages/screens/Projects/ProjectsConflictSolvingScreen/index.tsx create mode 100644 packages/screens/Projects/ProjectsConflictSolvingScreen/types.ts create mode 100644 packages/screens/Projects/ProjectsDetailScreen/MilestoneDetail.tsx create mode 100644 packages/screens/Projects/ProjectsDetailScreen/index.tsx create mode 100644 packages/screens/Projects/ProjectsMakeRequestScreen/ConfirmAndSign.tsx create mode 100644 packages/screens/Projects/ProjectsMakeRequestScreen/Footer.tsx create mode 100644 packages/screens/Projects/ProjectsMakeRequestScreen/Milestones.tsx create mode 100644 packages/screens/Projects/ProjectsMakeRequestScreen/Preview.tsx create mode 100644 packages/screens/Projects/ProjectsMakeRequestScreen/ShortPresentation.tsx create mode 100644 packages/screens/Projects/ProjectsMakeRequestScreen/TeamAndLinks.tsx create mode 100644 packages/screens/Projects/ProjectsMakeRequestScreen/index.tsx create mode 100644 packages/screens/Projects/ProjectsManagerScreen/ContractorCandidates.tsx create mode 100644 packages/screens/Projects/ProjectsManagerScreen/MilestonesUpdateManager.tsx create mode 100644 packages/screens/Projects/ProjectsManagerScreen/MyProjectsManager.tsx create mode 100644 packages/screens/Projects/ProjectsManagerScreen/Requests.tsx create mode 100644 packages/screens/Projects/ProjectsManagerScreen/index.tsx create mode 100644 packages/screens/Projects/ProjectsManagerScreen/types.ts create mode 100644 packages/screens/Projects/ProjectsPaymentScreen.tsx create mode 100644 packages/screens/Projects/ProjectsScreen.tsx create mode 100644 packages/screens/Projects/components/Breadcrumb.tsx create mode 100644 packages/screens/Projects/components/ButtonsGroup.tsx create mode 100644 packages/screens/Projects/components/FundProjectModal.tsx create mode 100644 packages/screens/Projects/components/HeaderBackButton.tsx create mode 100644 packages/screens/Projects/components/Milestone.tsx create mode 100644 packages/screens/Projects/components/MilestoneBoard.tsx create mode 100644 packages/screens/Projects/components/MilestoneForm.tsx create mode 100644 packages/screens/Projects/components/MilestoneItem.tsx create mode 100644 packages/screens/Projects/components/MilestoneList.tsx create mode 100644 packages/screens/Projects/components/MilestonePriorityTag.tsx create mode 100644 packages/screens/Projects/components/MilestoneStatusTag.tsx create mode 100644 packages/screens/Projects/components/ProjectBox.tsx create mode 100644 packages/screens/Projects/components/ProjectInfo/LeftBlock.tsx create mode 100644 packages/screens/Projects/components/ProjectInfo/RelatedUsers.tsx create mode 100644 packages/screens/Projects/components/ProjectInfo/RightBlock.tsx create mode 100644 packages/screens/Projects/components/ProjectInfo/index.tsx create mode 100644 packages/screens/Projects/components/ProjectMilestones.tsx create mode 100644 packages/screens/Projects/components/ProjectStatusTag.tsx create mode 100644 packages/screens/Projects/components/ProjectsStatusFilterButtons.tsx create mode 100644 packages/screens/Projects/components/ResolveConflictButton.tsx create mode 100644 packages/screens/Projects/components/SubmitContractorCandidateModal.tsx create mode 100644 packages/screens/Projects/components/TNSResult.tsx create mode 100644 packages/screens/Projects/defaultValues.ts create mode 100644 packages/screens/Projects/hooks/useEscrowContract.ts create mode 100644 packages/screens/Projects/hooks/useMakeRequestHook.tsx create mode 100644 packages/screens/Projects/hooks/useProjects.ts create mode 100644 packages/screens/Projects/hooks/useUtils.ts create mode 100644 packages/screens/Projects/types.ts create mode 100644 packages/screens/Projects/utils.ts create mode 100644 packages/scripts/addrFromMnemo.ts create mode 100644 packages/scripts/inject-projects.ts create mode 100644 packages/scripts/install-gno.ts diff --git a/.github/workflows/buf-lint.yml b/.github/workflows/buf-lint.yml index 720134d9c6..df78049252 100644 --- a/.github/workflows/buf-lint.yml +++ b/.github/workflows/buf-lint.yml @@ -11,11 +11,11 @@ jobs: check-codegen: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: bufbuild/buf-setup-action@v1.28.0 + - uses: bufbuild/buf-setup-action@v1.31.0 with: - version: 1.28.0 + version: 1.31.0 github_token: ${{ secrets.GITHUB_TOKEN }} - name: Buf lint diff --git a/.github/workflows/desktop-build.yml b/.github/workflows/desktop-build.yml index cd9e42debc..5189e35dd4 100644 --- a/.github/workflows/desktop-build.yml +++ b/.github/workflows/desktop-build.yml @@ -14,16 +14,16 @@ jobs: - name: Cancel Previous Runs uses: styfle/cancel-workflow-action@0.12.1 - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: cache: "yarn" node-version-file: ".nvmrc" - uses: actions/setup-go@v3 with: - go-version: "1.19" + go-version: "1.20" - name: Install node modules run: yarn @@ -54,16 +54,16 @@ jobs: runs-on: ${{ matrix.runner }} continue-on-error: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: - cache: "npm" + cache: "yarn" node-version-file: ".nvmrc" - uses: actions/setup-go@v3 with: - go-version: "1.19" + go-version: "1.20" - name: Download web build uses: actions/download-artifact@v3 diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml new file mode 100644 index 0000000000..9af144d5b9 --- /dev/null +++ b/.github/workflows/e2e.yml @@ -0,0 +1,37 @@ +name: E2E Tests + +on: + push: + branches: + - main + pull_request: + merge_group: + +jobs: + e2e-tests: + runs-on: ubuntu-latest + steps: + - name: Cancel Previous Runs + uses: styfle/cancel-workflow-action@0.12.1 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + cache: "yarn" + node-version-file: ".nvmrc" + - uses: actions/setup-go@v3 + with: + go-version: "1.22" + - uses: cypress-io/github-action@v6 + with: + browser: chrome + build: make install-gno + start: | + yarn start --minify + make start.gnodev-e2e + wait-on: "http://localhost:8888, http://localhost:8081" + - name: Upload errors screenshots + uses: actions/upload-artifact@v4 + if: failure() + with: + name: cypress-screenshots + path: cypress/screenshots diff --git a/.github/workflows/gen.yml b/.github/workflows/gen.yml index 381b22bdcb..830a588365 100644 --- a/.github/workflows/gen.yml +++ b/.github/workflows/gen.yml @@ -11,22 +11,22 @@ jobs: check-codegen: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: cache: "yarn" node-version-file: ".nvmrc" - uses: actions/setup-go@v3 with: - go-version: "1.19" + go-version: "1.22" - uses: dtolnay/rust-toolchain@stable - - uses: bufbuild/buf-setup-action@v1.28.0 + - uses: bufbuild/buf-setup-action@v1.31.0 with: - version: 1.28.0 + version: 1.31.0 github_token: ${{ secrets.GITHUB_TOKEN }} - name: Install node modules diff --git a/.github/workflows/gno-lint.yml b/.github/workflows/gno-lint.yml index 608ddcbd2b..20a288ea15 100644 --- a/.github/workflows/gno-lint.yml +++ b/.github/workflows/gno-lint.yml @@ -18,7 +18,7 @@ jobs: go-version: "1.22" - name: Clean gno run: make clean-gno - + - name: Clone gno run: make clone-gno @@ -27,3 +27,16 @@ jobs: - name: Lint gno run: make lint-gno + + - name: gno mod tidy + run: make gno-mod-tidy + + - name: Check that there is no diff + run: | + mrdiff=$(git status --porcelain) + if [[ $mrdiff ]]; then + echo 'ERROR: Diff found!' + echo $mrdiff + git diff + exit 1 + fi diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index f7e7d475e3..d1a51b13be 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -11,11 +11,11 @@ jobs: go: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-go@v3 with: - go-version: "1.19" + go-version: "1.22" - name: Tidy go.mod run: make go-mod-tidy diff --git a/.github/workflows/js.yml b/.github/workflows/js.yml index 1e7b6e3341..208762797f 100644 --- a/.github/workflows/js.yml +++ b/.github/workflows/js.yml @@ -11,9 +11,9 @@ jobs: lint-and-build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: cache: "yarn" node-version-file: ".nvmrc" diff --git a/.github/workflows/mobile-build-android.yml b/.github/workflows/mobile-build-android.yml index 5928813bd9..f9b910175b 100644 --- a/.github/workflows/mobile-build-android.yml +++ b/.github/workflows/mobile-build-android.yml @@ -29,11 +29,11 @@ jobs: with: go-version: "1.20" - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: cache: "yarn" node-version-file: ".nvmrc" diff --git a/.github/workflows/mobile-build-ios.yml b/.github/workflows/mobile-build-ios.yml index 2820081553..9a76e9a7df 100644 --- a/.github/workflows/mobile-build-ios.yml +++ b/.github/workflows/mobile-build-ios.yml @@ -22,11 +22,11 @@ jobs: - name: Select xcode run: sudo xcode-select -s /Applications/Xcode_15.2.app - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: cache: "yarn" node-version-file: ".nvmrc" diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 06fd669fa2..48bcfa9b5d 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -11,7 +11,7 @@ jobs: rust: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable diff --git a/.nvmrc b/.nvmrc index d576022ca0..6569dfa4f3 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -18.1.0 \ No newline at end of file +20.8.1 diff --git a/Makefile b/Makefile index 60288082e2..089359f9d4 100644 --- a/Makefile +++ b/Makefile @@ -416,19 +416,37 @@ generate.internal-contracts-clients: node_modules npx tsx packages/scripts/makeTypescriptIndex $${outdir} || exit 1 ; \ done +.PHONY: install-gno +install-gno: node_modules + yarn install-gno + +.PHONY: start.gnodev-e2e +start.gnodev-e2e: + gnodev --unsafe-api --server-mode --add-account g193vp9tjhfpldvgg3gn433ayv8pn7rtfv8shyeq $$(find gno -name gno.mod -type f -exec dirname {} \;) + +.PHONY: clone-gno clone-gno: + mkdir -p gnobuild cd gnobuild && git clone https://github.com/gnolang/gno.git && cd gno && git checkout 9b114172063feaf2da4ae7ebb8263cada3ba699b cp -r ./gno/p ./gnobuild/gno/examples/gno.land/p/teritori +.PHONY: build-gno build-gno: cd gnobuild/gno/gnovm && make build +.PHONY: lint-gno lint-gno: ./gnobuild/gno/gnovm/build/gno lint ./gno/. -v +.PHONY: test-gno test-gno: ./gnobuild/gno/gnovm/build/gno test ./gno/... -v +.PHONY: gno-mod-tidy +gno-mod-tidy: + export gno=$$(pwd)/gnobuild/gno/gnovm/build/gno; \ + find gno -name gno.mod -type f | xargs -I'{}' sh -c 'cd $$(dirname {}); $$gno mod tidy' \; + +.PHONY: clean-gno clean-gno: rm -rf gnobuild - mkdir gnobuild diff --git a/assets/icons/github.svg b/assets/icons/github.svg new file mode 100644 index 0000000000..e47beb5ffd --- /dev/null +++ b/assets/icons/github.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/no-tasks.svg b/assets/icons/no-tasks.svg new file mode 100644 index 0000000000..696633adb9 --- /dev/null +++ b/assets/icons/no-tasks.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/projects-completed.svg b/assets/icons/projects-completed.svg new file mode 100644 index 0000000000..2c869a7177 --- /dev/null +++ b/assets/icons/projects-completed.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/icons/projects-inProgress.svg b/assets/icons/projects-inProgress.svg new file mode 100644 index 0000000000..5653f3d15e --- /dev/null +++ b/assets/icons/projects-inProgress.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/icons/projects-open.svg b/assets/icons/projects-open.svg new file mode 100644 index 0000000000..0350aed0b1 --- /dev/null +++ b/assets/icons/projects-open.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/icons/projects-program.svg b/assets/icons/projects-program.svg new file mode 100644 index 0000000000..2755ef7cc8 --- /dev/null +++ b/assets/icons/projects-program.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/icons/projects-review.svg b/assets/icons/projects-review.svg new file mode 100644 index 0000000000..9651dd76bd --- /dev/null +++ b/assets/icons/projects-review.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/project-success-payment.png b/assets/project-success-payment.png new file mode 100644 index 0000000000000000000000000000000000000000..eed3b2534d577f907f7a8d32e522ef42e1a5e58e GIT binary patch literal 23017 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

*T>-j11+EviarjFP**i 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 literal 0 HcmV?d00001 diff --git a/cypress.config.ts b/cypress.config.ts new file mode 100644 index 0000000000..546918bec2 --- /dev/null +++ b/cypress.config.ts @@ -0,0 +1,11 @@ +import { defineConfig } from "cypress"; + +export default defineConfig({ + viewportWidth: 1900, + viewportHeight: 1280, + e2e: { + setupNodeEvents(on, config) { + // implement node event listeners here + }, + }, +}); diff --git a/cypress/e2e/0_preload.cy.ts b/cypress/e2e/0_preload.cy.ts new file mode 100644 index 0000000000..8a76fbfa12 --- /dev/null +++ b/cypress/e2e/0_preload.cy.ts @@ -0,0 +1,9 @@ +// this helps to get accurate test times by running first and preloading the app + +describe("Preload", () => { + it("successfully loads", () => { + cy.visit("http://localhost:8081", { + timeout: 300000, + }); + }); +}); diff --git a/cypress/e2e/lib.ts b/cypress/e2e/lib.ts new file mode 100644 index 0000000000..8b214e269c --- /dev/null +++ b/cypress/e2e/lib.ts @@ -0,0 +1,16 @@ +export const changeTestUser = (user: string) => { + cy.window().then(async (win) => { + const newUserId = await (win as any).adena.SetTestUser(user); + cy.get(`*[data-testid='selected-wallet-${newUserId}']`).should("exist"); + }); +}; + +export const changeSelectedMilestoneStatus = (newStatus: string) => { + const getStatusDropdown = () => + cy.get("*[data-testid='milestone-select-new-status']", { timeout: 20000 }); + getStatusDropdown().click(); + const statusElem = getStatusDropdown().contains(newStatus); + statusElem.click(); + statusElem.should("not.exist"); + cy.contains("Change Status").click(); +}; diff --git a/cypress/e2e/projects-contractor.cy.ts b/cypress/e2e/projects-contractor.cy.ts new file mode 100644 index 0000000000..c3bfa71968 --- /dev/null +++ b/cypress/e2e/projects-contractor.cy.ts @@ -0,0 +1,93 @@ +import { changeSelectedMilestoneStatus, changeTestUser } from "./lib"; + +describe("Contractor proposer full flow", () => { + it("works", () => { + cy.request("http://127.0.0.1:8888/reset"); + + const projectName = "Test Project"; + const milestoneName = "Test Milestone"; + const judgeAddr = "g1nyz430dsujj56ygllcaujkzagz54v0l6yusspy"; + + cy.visit("http://localhost:8081/projects?network=gno-dev", { + timeout: 300000, + }); + + cy.contains("Create a Project").click(); + + cy.contains("Connect wallet").click({ force: true }); + cy.get("div[data-testid=connect-gnotest-wallet]").click({ force: true }); + cy.contains("Connect wallet").should("not.exist"); + changeTestUser("bob"); + + // first step: basic project info + cy.get("input[placeholder='Your Grant name']").type(projectName); + cy.get("textarea[placeholder='Your Grant description']").type( + "Bli blu Bli blu Bli blu Bli blu Bli blu", + ); + cy.get( + "input[placeholder='Address of the authority that will resolve conflicts']", + ).type(judgeAddr); + + cy.get("input[type=file]").selectFile("cypress/fixtures/image.png", { + force: true, + }); + cy.get("div[data-testid=loader-full-screen]", { timeout: 10000 }).should( + "not.exist", + ); + + cy.get("input[placeholder='Add 1-5 main Grant tags using comma...']").type( + "ui,ux,frontend", + ); + cy.contains("Next").click(); + + // second step: team info + // TODO: remove the default values and type them here + cy.contains("Next").click(); + + // third step: add milestones + cy.contains("Add").click(); + cy.get("input[placeholder='⚡️ Type name here...']").type("Test Milestone"); + cy.get("textarea[placeholder='Type description here...']").type( + "Bli blu bla bleh", + ); + cy.get("input[data-testid='milestone-budget']").clear().type("42"); + cy.get("input[data-testid='milestone-duration']").clear().type("3600"); + cy.get("div[data-testid='milestone-confirm']").click(); + cy.contains("Next").click(); + + // fourth step: review and create + cy.contains("Publish this request").click(); + cy.get("div[data-testid='confirm-and-sign']").click(); + cy.get("div[data-testid='confirm-and-sign']", { timeout: 20000 }).should( + "not.exist", + ); + cy.contains("Back to Project Program").click(); + + // check that the project is present in manager as funder + cy.contains("Projects Manager").click(); + cy.contains("My projects").click(); + cy.contains("Test Project").should("exist"); + cy.contains("Projects Program").click({ force: true }); + + // make alice fund the project + cy.contains(projectName).click(); + changeTestUser("alice"); + cy.contains("Fund this project").click(); + cy.get("div[data-testid='confirm-and-sign']").click(); + cy.get("div[data-testid='confirm-and-sign']", { timeout: 20000 }).should( + "not.exist", + ); + + // switch to bob and do milestone + changeTestUser("bob"); + cy.contains(milestoneName).click(); + // TODO: test in progress state + changeSelectedMilestoneStatus("Review"); + + // switch to alice and approve completion + changeTestUser("alice"); + changeSelectedMilestoneStatus("Completed"); + + cy.get("*[data-testid='project-status-COMPLETED']").should("exist"); + }); +}); diff --git a/cypress/e2e/projects-funder.cy.ts b/cypress/e2e/projects-funder.cy.ts new file mode 100644 index 0000000000..72216449f1 --- /dev/null +++ b/cypress/e2e/projects-funder.cy.ts @@ -0,0 +1,102 @@ +import { changeSelectedMilestoneStatus, changeTestUser } from "./lib"; + +describe("Funder proposer full flow", () => { + it("works", () => { + cy.request("http://127.0.0.1:8888/reset"); + + const projectName = "Test Project"; + const milestoneName = "Test Milestone"; + const judgeAddr = "g1nyz430dsujj56ygllcaujkzagz54v0l6yusspy"; + + cy.visit("http://localhost:8081/projects?network=gno-dev", { + timeout: 300000, + }); + + cy.contains("Create a Project").click(); + + cy.contains("Connect wallet").click({ force: true }); + cy.get("div[data-testid=connect-gnotest-wallet]").click({ force: true }); + cy.contains("Connect wallet").should("not.exist"); + changeTestUser("alice"); + + // first step: basic project info + cy.contains("A funder looking for a developer").click(); + cy.get("input[placeholder='Your Grant name']").type(projectName); + cy.get("textarea[placeholder='Your Grant description']").type( + "Bli blu Bli blu Bli blu Bli blu Bli blu", + ); + cy.get( + "input[placeholder='Address of the authority that will resolve conflicts']", + ).type(judgeAddr); + + cy.get("input[type=file]").selectFile("cypress/fixtures/image.png", { + force: true, + }); + cy.get("div[data-testid=loader-full-screen]", { timeout: 10000 }).should( + "not.exist", + ); + + cy.get("input[placeholder='Add 1-5 main Grant tags using comma...']").type( + "ui,ux,frontend", + ); + cy.contains("Next").click(); + + // second step: team info + // TODO: remove the default values and type them here + cy.contains("Next").click(); + + // third step: add milestones + cy.contains("Add").click(); + cy.get("input[placeholder='⚡️ Type name here...']").type("Test Milestone"); + cy.get("textarea[placeholder='Type description here...']").type( + "Bli blu bla bleh", + ); + cy.get("input[data-testid='milestone-budget']").clear().type("42"); + cy.get("input[data-testid='milestone-duration']").clear().type("3600"); + cy.get("div[data-testid='milestone-confirm']").click(); + cy.contains("Next").click(); + + // fourth step: review and create + cy.contains("Publish this request").click(); + cy.get("div[data-testid='confirm-and-sign']").click(); + cy.get("div[data-testid='confirm-and-sign']", { timeout: 20000 }).should( + "not.exist", + ); + cy.contains("Back to Project Program").click(); + + // check that the project is present in manager as contractor + cy.contains("Projects Manager").click(); + cy.contains("Test Project").should("exist"); + cy.contains("Projects Program").click({ force: true }); + + // make bob candidate to project + cy.contains(projectName).click(); + changeTestUser("bob"); + cy.contains("Submit your candidacy as contractor").click(); + cy.get("div[data-testid='confirm-and-sign']").click(); + cy.get("div[data-testid='confirm-and-sign']", { timeout: 20000 }).should( + "not.exist", + ); + + // accept bob candidacy + changeTestUser("alice"); + cy.contains("1 candidates").click({ timeout: 10000 }); + cy.contains("Accept").click(); + // check that the project is not present anymore in candidates list + cy.contains("Accept").should("not.exist"); + cy.go("back"); + + // switch to bob and do milestone + changeTestUser("bob"); + cy.contains("Test Project").click(); + cy.contains(milestoneName).click({ force: true }); + // TODO: test in progress state + changeSelectedMilestoneStatus("Review"); + + // switch to alice and approve completion + changeTestUser("alice"); + changeSelectedMilestoneStatus("Completed"); + + cy.get("*[data-testid='project-status-COMPLETED']").should("exist"); + }); +}); diff --git a/cypress/fixtures/image.png b/cypress/fixtures/image.png new file mode 100644 index 0000000000000000000000000000000000000000..540c94958b19282c126fb0270b01b62f6cf8188c GIT binary patch literal 393421 zcmV(%D^*QE zM>81sw_tT~V`MiIAS^R-I}L_xPgy!7`oL$5M-FvLBWGw`Mj;7oGzv~LA6hUEXHGOl zEF3){3^74Qkc4edCklmpX;M;5luQq5Tu5S9M~`t)VlN3+Mm2nHTUuaQaZW9ed0cxu z3tmbzP%ac@UsEg<2wYfDn0Hf=T`+BJVRLC&abiyU%5a8QE}UXAmw;mO+Mu9&Q(03- zUr|4XPa%Xs3&oUN_~4{kKpjvy8CfzccVU@pJ-L8J{oRGAjccrRKc;Cke_T1khe*}0e1l{~)1YUdg=DmiVy}c% zkZMJ-UJ`__-;y@I!gRPwiL+oNI5l~vocf}Bx)fwIm~5<)EN9e3gbprBCUnD6;>L}4-a&K1D5*uZw>1|pMYV`P zGTuN#LA-%xxjYGskjt8HX{grL-dbLR8o6!|1ncY7O0m=^O|%xT#cVj-Yn994a5x$t z^?J?FtBCwcrCa+X4D0oLxx7=Y7NIL>w-}<5)S{)7D{RFpSI|z?bqSWZZZl$9)zCbH zZfnG(-y-@=E&1(MGdD;3Pxhf+Z#)WXzVG9;;1}B8;Fc688JUXJ{=ExGFxvTEs)QnMJY_SMdU2qKw2Q#{+(WDLnh(|v2gC(wQJ`P zs5*#dJR%r83*6W=U61C%Iw@}8!bq3`HwliBuH4Xuzo#-S3b}XOO$=^0%Ap~Ui_;+7 z(1^Ijw?2et6w{&;UV9uMm~S-jZ^I&zLU(=f(4x*=no@y!T_ zWHSkU6h%?QJs;jOF~+gDh=|_?m7#@II{l8BttTf>j`zpoCl5!hd;y5@jdF%LB$_d< zB&CR#AsF|L@9!UWHrjXAR~n7R8dNF)bfjFdlv~ezlv@GP-h2~ulV*$~og#{r31S}#zm%C;SC|2bd2X^oFI-x zBb{%k3Dzm^W-E#{>td*rLUI|xB7kH2XT5M1|E4X9Ef)|x?;{OUD5Ii zNk_0rQE_zLu%^Q#;E*Wn&Vsm%gQQ`kTG<*+wyjtAv@q3bAT zm^03qe*@%L$+@CG9*;YtX3JY|;DuJk72Q7ox~k`W{O-FSl5;e1j&NWc1jeo3$(LLG za=Dz(*TccMIcf#ftY6_z2QZHD&$=8d7EA}fe93hxy<2X|5#t`Xf5y@~iPC`h=ytGWnrG+HRvSu{iVnZn306HYYse~C) zvE;NKw6bdEXy-5x6^k$ro`;EPEeP`Ye72GW=dy*c*&H`JN6iQK?>~5Ozc(sW_+BrP zVniG&y$r{w9H@IUCkG}9)&ROF+LBX71D!EWA{}oms2okM^^@fQNStP&{>jhnrxKZ5zN^v72(k4ss;fkq(cbakm}>eIN=+$ETD7K)fncMBkOTf zAIHkTkXq9fIrc162?;}|PNJCe$}Nvpj_oQsRgse^%#(DUn$2eYYNeVVG@t(YwAZ`W z=```K>)r4524PUa`<$3VV-@RmOHz#-LhYLa-1TWa-Ncb_Mj5IijH@IOmth*ym^NfH z;2Gd7Z>OT}?~u!U@o@jJxBqYy_G`dg7o@8dHZ!XeOkXk1ImDH;Y0;N5hly&bF@+qP zLtHVJ1J8gtSh)}B=sqOjsL$Zypq+AkW6;?f3|hls7!C(vIq5%5-T&K-O zOq7{$n@u}Q30sDX(a!Et3-UYWuDv*ivXH51GQM#cl zvf5PDyd3fN_S&*rhZDZ(07;^;F?ngzRYy8jH(_04+I&@2Vo>OE*)o)s3kY_OQMyGl zr>a7gYBd{Fib21#*BK65{d|^oCh!JFfBt^&UOj7wGt(vk=f)x(k~mY+rJFbwV@yRb z!$eCmj?D$7cr)?7-b~C}Eu3tg%4%BOtTm5&N2C7sHYkTxvHEb_J9-%UtE&^pxgwww zm6UJnu7Gk-ZiT{<97tD+8M<{)juc!`efZ&rM4S+=n$5yc*URmCD-2upupWkC+3RL9 zLA_q~@$K>Fuim}_#$92aQI2quXwsi`cfzckjx}5tS)NM;9l{NevnQ=K(DCfmIU}8e zoRRLi7w4c;y&Nb&7@RY%r8Df@zb2gRGw9e5XT@CIwS@(}aNt|OEg7GG@jUb*KxZ>m zmg!CdI%$q+klZ!EvDYG|O~s*>$zbtqVvatJA$)t=mgJT{&SEF-((>{punrx7X1ffo z8Q^R+4xMXsa0a-`YuZXk1gdQEt@lTruvQOlsh0!bVk*j8l$&~mpsK*Dh}ipHYdi=+ zJ-?`na~hI1Nd?we(LqINDN?*8*WxOP)i|RY(}BdB-{D!&d!&+U+#SR>32Ij zJD=Y9?6c2^I5@anZzr4G*@cm-w+11E8S8jFYKFD0?`OLCyaz7_vdWzGY;;RsyEE>& zkW43B`aSl>IqhYbzT+x=BA#!*)h4YesAJX8ks)r1z1ggzBJ)?52*H~pob{1Z*p4Xn{wY`9T}G@dudJ=eiJly$qo3XR?(=WH|K|H|fBfc~ zd*6Kj{k`w+-EDvRDL8j$XJ>bJcL&<-933?~^>#U54oA)XF*FJb^wQgda8vhL(Nt>Z zTs`Aj9a)xKt7FxC{uR3<;F!iZ4ib!WjcIgaOP#$s#zi+Gl9)3ChpH`Z=v1=_XBN)V z1t@1Mli~lVDA&@@$vM)&%grs!&CR(R3&0!#bq<_^1a|m!x9wm9A)Gom1_v0jQjrrR za(09{Z#Hfs0Pbx>jQ*EpOU!a!)4i#iWhih_e0y&`@oB28Bnlg@o zyu5}aet?R?qzsA3IOC)yWRv7fu!YI$W?^{v_~g;a<3Aoh ze)Ra@;5Y33gl+}&t@`FXp& z(f;}F-rbEaci`>re7CdPZnr_Xtk)jyHHYV6#>z*EUygyT!n( zOtdSLEmtB>@~l!Xr$dctYPe#WNj)W<1xc4`=Geu9iE=vRv^UNnQym@C71rlv-RoMJ zHe#`{dN~SRY-Hp+EB$Pa8oRV$YOx8bs|!r+fjDyRy!<&YUV9Nq;LW|h6xm|cj#Oi) zWMBv6YaP6(}@yGA4-@&vL!i3cW%P>97(zoR~=3uwI z(Q0Ghd0ri>as?2r-wy{5;p6%k6*jl}E&ujphZkl}nb?Arl9WwaIaI#QTCF48kdZ*nTA*{`%52yf;1aCkAi}fg=wHk5W^|K!8s}n) ztlD9fZVuNZ-FbwVI&kkinldgPlVc;UN7Jf4j*Wqi;$AD#w5VRrF^&#SI=AzHvmN!8 z2fQiL*3cs;R=#T#Y09_=>Le6!$~gvooKlW&z+ASPGsr>2SybG60Ov&P$hE46<0O?T zD5n8N6`3fCG*MBCODhq)X;J^C6~V+%M+|~TRGBm%kuk;@+7xe!GqkP)oF*E>l)|~l ziD9&<#}o0Je9#^J@yDY-{x~@~IXpS|bx;d@`7ZZjuot$5BfI}ui zB}3+H*|e3_nifOb8BU-i5vMhkbJnvO=Fn!Iq)T0%Gt|XEXJrQ7Og3xPP6lS&QuiOu z0zNV-I!OAs_@*k;WR?zf2?Lq4E})=sI9a?~aG29d^XAMP35U)Y$1;!h4wHf?|YQdLH!7WM;&Ifyo{$UL5Xj~( zF;vEoAI#*rk*S62YEC^IMqru%uB)k$6qh45a*;&4Yr>=CgmPI>FvQ%b!p^Q zD;3lr>r*tm+;b@9cxYq=ghRZ$ywXr9>81za&>*bAeTpfnm^to3wCnYac70=G*sA9N zI1kDfYPEhnB;$Jf``GR6b+Dch7H)GjKq%)Dw1dbqGj+8B5A^y&7r%ITM6VBv7~9t9Eh@P7#;OVWR=UHY>GTZ*6RB+`YT;^#-1=^AHf8K*6@d;a6YXzyH-?51S7m zmgDeU@hSmwPPbe~(vfkfZu*KU4I_l2Zng|@iQ9>ZtqaJ8r{XPY?NThA**H60lH8L> zDlu_|QZ^#e9*BTuaL)W&lynF+a{upML(;(^&B4VUa7fn@m?n%9*3EHmLiM8Ch_%NZ z5KIzIWQ>E}nWAof{ssagV;rk6Zi+Yzjd6=p#{J#I@mhm$n-;hF7RxmdP79laV$N3O zIQ8_h3O7TWm^co2g4H%wd5R(LRlzxU6cCOHkZCC7*g3=@T`1p>(nExR0?v{G&a|u= z<7_=lXR2(@#z`~2>2#C~b7&LbG4;xjmpOIns(G4%FZzAE0`o?{J^AI)(vv*9y9UnEv4$ZWeVq<40NcesAFg!$=N#1&HWF6OU_UkRuDF}fV9rmHNp;Bn8WfM z_aM&Wj!FqGr%4poV4F)mBqnn%T}f;D%e<%PKrI|bUQ&97X&q| zVhP$-H8FIY(*W6ob~aJ<6>vzMUYd^+SP^nexVSjclyjR1Del*G%`VBgQ%{(1+M97> z=;pKi-jiPr51))jwVPdm90K-|+J06GfPgNz@$gVcft)4rfS^ zh&!L%+1(hzxNU5-QScbo-Bz22Mg($YwsIJbdWY08jNE>&*Bfo>^w=n8Xp>@%x|$3v zPJ%whSyZyGzpNR%NSne&cU`H3pG!MrVwgju$tJD}H+HG(bJmk>8Z+#ivv77w*zWzG zM@Ve0YMsVu^HjZdC#v1 z;Icj%ZU+Id=ho%WOoW(OI-8OP1^J_JlvQ|E0UbDyUj*75)ac<7^6mJqAK6S*Xdxi& zm1``Dw@q}AUQPLz(TKAyIeq0-#*L_MKm6%gxcx;pL$nFu*k}AM9*2-ezXH$0l(U_k zTDb<4BiEF2aw$(VaFam<3wQUMy?ft$b9dMpe)Ii_{xKUVVhfMz_%kC1ACoUJ(H{<)Ll&8pie>A9W(=luh$QEj3C^u*Wm+iXIM6Yo zdy~J-5!Xjy4Qk;}pKK56e5vxSz1GfzXC(kml`F{zGgTgx!)wR`zanq9-P+sRySLZD zlfj+u?>*qg0uV>#F=&OOakJCxeRc5F@$o)5*BcLNTX3)VOW(}M3BxS@jVfdvv|5oq z0Xn93EE=x3k8a{6Isx5((dAQ~mbG2j-88w=%3i!2iiwP4p_Nk~XI{<#2c9Y31Zfy4-Z&H)-Y#>p>Z}}= z$3Z!#$h`IM>v4FC1^EC#tG8M(7I;v+wNds0-_Jt6m(5np$Qk9-nJL~lK>B{6R_0MJ zoP_8GI?XejS;%$F#6gA_G$OuP_8Q3&U$~=Z*k$_9Fbk5B=y4gss91DHDCT_7D z*#D&e)96`$FbHwl1IHY9J-?cx@Is5DbEH$PdwEVs%WZ(p+x0-Q`Vg1{-yR%2xQEZU z0^-!lp|wU$Fm62VG>?yuF=hSgX>Yu}Roe^#AITFhc-?DZIo!%{d&mD`Fxmw7>=Oi% za=^1tFNex>h|``;FYTU;n2eb8HzlZNr%vLWW2zK!R?`j)BdA%A@*}KBq)QnmX>ikW z#%I3HNV(*u0_4V8<6%CIW398T+(jcC%L2~=pPyTh9`jWSS4$#%fdX!#i%Ue>($WHj z%XvW@cUc+p^V+NCjdQZciU(NX>{MKoGr%oMhtQ%ca#{>^Y)sOP1F}tuqAq6TN*eZT zrCB)^4W>Ibf;S&ly)j=3@%-etgGcnkeAe@YQq!kcO}M*>g(`wB2v7(*Bt4oBe^aY< ziGyws(D_VBr+$r1LxvW}3>$G`(jAAco2xqe#%ff%$sQdW(td&S*~yNp!Y+z9?W|e4 z5yP0fiN8~!|Jx6PQLDZ^didm|*$nv;pt>%Ca|7d$lZh)3SM|z!%}$38)$xP~_8RVj zaT|9#&1SPR1l*uHgwn##mqByfIl>(E$>BZ@=s`FvhbJ()flt)p_2Z9~%FV4!AFd7y ziCcwjAA1rX=yF{;=x!xe>(t8K61k@)bmT4_=#W$rbGRz8pfZz3i_@3rBqjxQ)+!xS z3;T51iPE3?vh%^ogC)=NDF5qL*qz18IiOjUfrd*B8^%5>&Mvg1B2Futj^W@4xC?Vm zz!#|J#)>wEjL@lGd1Z;5Qy(Xl0Zk{bk##v1jNQWAB@D?qITRf8a`12*ypd!aL@S3- zym8=2XNVKHsiAY6BieE-wjyVQ(*wZSJl*a1 zIZ;My($TRQ?zEyf#;Ld<2le?OA@zRvuy^>hGt6g!IIIgyRBD)$owzaHGj84^HFe_pIYIDNxi8+%yf z<_EXsw)^D1QwgV`l7%|uTvQHc&gHo)le?GrmFcv%WSon{%oRE*DKbZA6IR!m7L%Z3 zB4(L64Tyzxwv98LJM#yNu*?b@#Lb*39dyPxxBWn>snE+ zoV$Hd5hpWN7U&(M$~IYTS?(R3vT7h9lFmMVWb$-A3aUNpz+^ZNhXHLIf_19Wq;nBf zQ452dGssoERwwKX@FXo%z=_mWnV&b54+X5X{4W@JAI7~!`Tmg#q8XT5XhYh-S}Nh}44i0b(i!D2xNzYDu3vs>?xpjf9OZDP-MpgCxQ7tD;S2aB zz#YayJHwpYbwDcP*kUVloTwu8!F=Hy0vVS&IVRZVOr6Od(AOxTnTl+h4C?x1Rj%H- zhjUrY4lEoYhv`!|lI6@M>e43cEKBVdsFi z=6Jt3!ub)b%8j@CTU+>P(}eF!N4#lS(Q z@1mZ*78m)|86xKpT$MwG068S-_6qgdYp+~5|ME*Oy);M6E#StyEYK>TE7+Ui(m(kZKPj)CO%11bvboUO<)CgaGOoN-R^mV!8io4GlguJX``SMNN1 zdi3A{mx_QmdEfD)fsY;>L7l$%IiG<6Nu>(>0LqBZ5Xd31I^Q|sk=Enhpynu-K|r*6 zN;V`x$16uR+)CIu1soBlBHJ9;0JE*y))sE@LWQduDp{vrX`Ey553>ykvve${pEc25 zgugAFTz&A{2@bLy?hp85Ajo@yE`m-VHnDRb%g$=Pmgk{i_a)V-WSE7#LcP^IetN%m zGzGe9KxmTv}!*Ka4DyPZPm>Z z&5ffG-$T_diZ!jXW#``}X}6S1WZcqgORv55+N-a<^2&t^FTecq99QdJ;hk4sTTrW} zqIaV>aI~8Mj_m^eBx3HJsDyCuAefX4jBt=TIl8!rmwU?%+%aGz2jb+@cI%>g6~t40`vmJ9q%f zab1os#MgjO=#MCco05$gm!9Y)l@w8s;0#ZAZV$HmedhKj+gq@3Tf9xUfqD?>Cz#WK z40ZA6B9w1BNU|=n`S1Z~)5rF}qesWR~@dqN(Ij4|IXB?aT55Qa|IcKz+b$rfdt`f#K zwC8hkM!6W$7*Q{0L-TM*yOl6=GoDnPx%aT7tW!QMFd+a90_FsC7v?TNuyXV7%}@D; z#sJ??Fw#`bx!qcs_Z1h8XMG6Aq2J1N#=h4T4$ftlhb1rU3=|EPGWCcy`TTy zYwf-3EFo=5$vwMJC#KLnIEHYo*6QnZ%ldb=C7!uzOPIs;fTD4|vxSZ$Yk%NVt@ZUH z!+1drxH;%%Qh+@unkla|Rh6+$)g4au4#v}Nw|ms-belj;kLhp#r=pPyI%i!h(aA#4 zQOy(S3Y?p{N#Y!k8*FS3``g>ZKi8PuLphASr>wb|iE$oYb*6zb?zs7okwH$4J7z+z zLGH-T@raC(y}phHZjM|1X&38k@$+7F5_Ho*CW7cSKoHq z)wLULK*9-hn#b}qi>p#)d0drIwrD4`U3}q1m%+HJ7@L;6zQ{OgGQn*g#!*Af$^7ul zG+&i_7ddljS8IeJPN=vb9ToRdh&~}Rpgg^uy}BMyx3V_;k#%L zr^XeUGb=$)QOI_OmGm)}CNN>O6{T}`uRl*?pDrDaL`7Dd4;fpLJk@@+}zcKrDZw!-$qyqn9~_c z_i2lRRGdSN&LXJ-o*pIAF>u)yGEOBiOar*ain1u8UO3m( zddc^y+In0BSK9+&jT|)&?LFk$`;Gp1I_0nWC&)WT8}nDiB;}Yemnphfp<9Lv-tyaKw1XA$Pl6K5@u;CqGGJslzpje1!Lu zRM%dy`L$6lfiA)jXIrkzG*DM$oX)y;H3!;oD|+b<0&*0*@}$nH)RJiN2uYl|J_qNj z0}!d;XCKNGlh%K;>Fa`|*`f)}Hd9iQs@mxPBj}uJrSp_%WD!I#%3Xci3oqRJ_zN%G zc2f_nyvKl6`0sRJxBA5dP_))q2Lw=W2PpBOlgdBbI-l-_zMzqH{5*l4cBCxvnee#Oa4{s zd2?jeIpr>~_QK09wU2u0oP!Rth9?9!h;dxc>Yv`{**utoTV4%wQgt{l;hgtj(2YuQ zFIgqvLdq4z+$#pT=bwKB0x*4A(Dllv8faK)cZf!G2kRo7J@P542N-zd_^69=B0v|3 z(ZyI`f^uPE;d-K)3U0;E{9VuKlMrWN2PoEMhT7*?OYWJOO!}Yox=>D9?h|-MzciiF zigQ$~t%~>^$$je{HWvpp`FLh zke9t4>2$s6C!Z_W(v*&yBIrJEFLgUBmN;i(PP0|IG;O6;K#p3u?>|sy$b8YYA)XGw z&rThT32)fn?s~<`oVz_nQ7R)50lBj_efi5MrvVO+F(o<0jJ}$3u?QE6P4tS2NBKWZ zI4g%&PZs>H1UefffX%yIjoB()?W(J8yedx*zCJU3+CmqIxsY;Nnv2f}Z%NIGXi&}r zxfbY{XVR*tU=2%+haniy`;*uJ;fSMECv)DFFlQw-WhobodliRrnm>KV>?VaqkLb{G*K-EcYSO7V%AF>h5rnEx&A1g>vt_naqwMxew#h z%x9Gx2lQk-)l8MW!glt^0pH(famNt1OrSxgS!hRdRVJ>(*75$YxgCzWV6Zdob(gqz z=gH4sXDYkO|4uds{A+=74ms-mQN%bkc(4tpq&~1#h`wSW+e9~qop@(%M!5M}{@bq5; zErwo-uZnE5g4sABj*91es-e^15Rk*JM$maW9jkISv&CqE9HtFn7aHd-G`m!ZBqAII z$eCa7#%$FHhXzzMH(!>!=fUUZiic=Q()n~XI2TKFq3B9NuE;ruTsg#=n=Y>*1K$^l z5Emb7DV?=B|9hQh$O&ni_V=%TZk>sr9;^d7sWuSDwa9J2hZ#C}*m%9cq7g{sFJG5c zBrK$y6A#E0I0pb7I3eUtZge2_0JWTDpi`lTjg8*Y5igqpn|iquPAU@X9*lY+((4me0#@|B*U`;`x`Gcfzv0&PoT?f(dV46(nlz|Tdz9kElhLNb zX?WY&h|Nw~?X`9|8}tM1pZaL$gO9oG8TMN^uYosfVpvVN zqN2m?7;;xdU=IIhR-{!7i$L?DQAxSQYdrFKZRqZguE#BL#4?4k8>m2z7LkYLluL3> zH@aR1>Mq5MVE#Fqp)w^E?!-@Y9A^5DuWmDAsK$kzI%HO6`pwcvoOk{tI@o3<#a7L! z32|Z^XPi+($h~pOnM)W=Azv;+4(BA+(rzw;9S+RMOBD_ra8z-Dv=Ol_3?auZr4B1g zux`-iiapti7zh8_Y)Eet21tZ+w_-yB4IeBTjKe)kB-3q2N1O-3oVD9E%Jq;v8yg55 zsX1zQ+Cpa`w2TjHY^mSeSzX-P+FJeSgYQ258haa~%LJE6Ed4z8XU9P%>lxhi7A}*L zvt%|R1N!p&b~yuc;vM$m8{7DrW=xE~TOd&J9qKLZT9rMrAY)Cgt0+U4l{gVjL5C^7 zv@Y}UVXxV3_9kGB32UGGu6GGM?2X1Qs zxRCHW!K_S9CIozA{W}2j{Ah1T?)vq@t!75R!Xn$Z zHX}x`0XodlmND*mH9BDq?Y4?oJLq(L_v&b$1QG4(8VS!}ZmBaK4*LXKw)x^~qyCuX z0tHnNamnILytt0+B;+We>Sz=0)HvT#HFvT(?}BUrH=TwevsV9&%!QUqoJ*yw z=)jyx#ilQ7qMRCp2r);4mk8%0YLqihO|QD`3olcyym!kPcOwP9;a1Mdaf^|8vB>?c zG>k!TE#4{gPPUVTqst(t7RvdKh-)agg$z!bfA}i4b>Ww4JM6WW!a3ucD!R_1t5_{T z&Rf%Rw@Aay32LdPlHjIpCd}%M``kQ+8ccG|KnLQOy3)$a>vAP6XL1g+iEC`j56>rS z;4KkPjV%5BPYg)<&B%shYMZQ>cl-Swr+W{0BG8dwlFe0d$bwUIz!hezCgqZtBXbPv zD|-$;7S4= zMnu`x~rEf(Fh zah2ob>?<6OP2CY!L7B3%tKDt&KI<&@fM3UhDI_5-eZCU&Q|kh9cvuN>LRUz;is`7H zMGx52>WheL^>feGv2%V#O&~5TVXkykQ{e5T+1vc9cYhTLS7n7P;p)8*rC=*YTeTA+ z7O%hIaHK}wowRvM( znC*(tMt?vD;$+GshGNNp9GI*5XD#}Gdn{M?O}{bcOv7yu;a0UWABueeI%|Pk&28Rz z_aI6x6*p*Of?2V$KXX_xvLZtF6(RZD{~=t$ojf>k}^>3EzxcZ3S_A zlir}?d~1;N*Iw$4r%NlDjB{60R&rqxam532aPJ?OK&i%m1^nbX0UFF19H3_Uw{r3D4B`al;2DP=fpT~Y~C97jA5?K zH{7%4sISa$E)hQ&IYR8w?2zBjKBdJS7{S?0 z9+X)3rfA}usvj@{-c*$eXYqw2TbrA*5o$ESNSXy{KmWX~wBg^t+wZ^gntpd5n(QIu zSmj@~04uQvn)jfc7^fMg5QhikkSlH{as}P^slX5ExE2K+4ar~IBgO&b)(&=bk~~+S zDM^@Hy$GZxHHUj3+l`wdR!1$Sp$CIzhlDvrQP)PCwS)xaeBj~!khEX8)*MU)xX)=m zr|@&L?zkSe%3?FqRlLMF9Hvo3yW;HC$0~S*@h)HX`7oxeSoUr)ymggwt z1BI&vUEFS1ee_&_u6l3lY=SVg(n8Ob_Im~K%37|FMB-}BrgSwdlXEy-l5gJPfwlCw zM7JPZSV^+QD59#xClqHK0ODn`#H3o%Oi-n;@fB|*s22I5qG z55x)1oh-8Yf+7$h>4I<=a7Y}mg{?4g0VHg6w6bKfM7pHi?P&+H=UZCW8WtVZX4Vk{`}i-zyJO_70&%C6^DEj2^K*z*pVp@>gc#5_7Q4V>d#6yIHSW^f$#+b1Q(Z%sFpW@M1EZK`^~B%R2_? zy`mM6SY%vv2*Nl=Te=JE%u`Du3_-2l^K~ZU$``lNow*l+QeK>^)^almBLHOnxyK)W z^EtGUM>s*t?9y8rVL`PR6fGXb_-q4g9#^H%8sZqFjjf`XiU$p9DNG7l^in!cnB$>g z?kWnc6OLjXu?Gs2(@2PmyC1N*6U%UgT@aY?XRR0F6sF&(3@J8YH6?eg8JN3ao@Fhacp|xIPnPyv5O! zm_!znN^$Nz*>`Twk}!-h9cxhaEu!l(#0B0wF2OfukYff8Q@8D$IZZcPBtQ#t9qX2t zRY}idfVNvCw!4r~PS*$VTrr2mMONIfscl$Y>ev}8N8+8<=8o*w^Q2n;Bcs?CDN&Js$sOn<-3HyG{}WqqTDMgk6FzF6BUPb#-W^HiF0(ZIOmAVtCtGQ32)w1 zsky)$rCQBZhae(hE}Gz*4^H3vFnff#_om$DAAkGn@4kEch1*1m8uF%Qd#wU(j;p+S zkynGR48F6e2W1^4ks{(XD!*76+v#P-`xD@1LxcqAAj-P7hh;Zrm$?e zJ;2*+yp@#mSi}j;rG>+W3>_*N_cN7U7+8z_2g2Jb&CaS(j)7f8cpzK-*deE_UCSU2 zU8xr0&xRy>%FInj(es9WZ zjv8I{W{Bdx)+nLr=v~V>)ruBrB( zQ*<$656-uULST6+Fd~R$@`g#C2qV;UDMxW@3w8jD4hyuIC&bz3lZ>PC`OtDgoHNca z=UQ$;$l<4-CIni4g>DmI$EhXT+l)Yvqi&+JJ+^i}`UuWt_PrX2#8p1*x$ksD9}gV> zIrJ$N%f3$yaADdhhp~Rf2_>9mZhKI7K-^$?bKvt1A?fjtB`Zbs;k+1sJ3}3r~-CA`JAUZ))M1@nvHNXBsW@JMI5>BuJ+=r$7|e4sHTR;5ERhbhS- zd!O|tL|Zo|+duU`!+rv4+t^Ry93fbm$>>Kd&uwje`BB&=EZQL`GK5viHSw9|0&vq5 z7JI#s8BahHu>j0ZJL(aAm<*K3U*;2ZnHbKx$E+>#N3vSTDDV`vP%g`08v1$ zzqT{TNylM`&@o2arR#OI^`6+Wt2k<-+Xrz=ZT5ei?=}+U9xfhdTr%NHUTyZSj^nIr zuFUt&T%CW3-15N^D;r{cx*D)kjp=MT`VgFp7z8EwW|e|dya_GmRy}JiURAA9bx(Em zWrhJexi@Fz&H2btmpJELtjo>Xjb33~f{9WzQmU;phdy>Al;a5Si!n_JV?Yj15OeC` zag$()bzY5kv=MX=?1FJA2gH{5nUX3`IE=Tc8WB~sAS-97Uxn_1gM1Ej3v9B`Z?w7R zDI?aH?xRcVar62*q^Ded`DK@5(9Df*<%U`fy7>zb2<9|n)vr@?RtH<69DwtJzX<1G z92F&(d1_*|DvSMHVd7hm%?Ig~Q%-@5^$b5CQ6YdKQ?=SH=Bi${C3#d z;WjRgptG-qs9P||+12@VIwr>)xFpD#kZU0dTL-8(A}2rfjx3&<=|>&@u2VFjAxnYF ze7QQ53%XT?TX6_Rr7f{79_n+?KUF7ruQ%@6%$Yw->3Q5&lnz%95tz7_b1o$pR~$uL zI#yj^E98`<_NAocQg3Yua)CFir*kd{=Y5%QvROe#sXAaY2$%70=1`^!${H?&oWL?K z^ZB8>3ccIe3u;fKHsQ>!L#5Kll5kViFhSJaYmoJ>G!WBp`U2=sP|ms=v$QwHU`!^) z@tp9gj9e0QS1p5}0nQ4{nxhNgx%oR>=fB0EZdilvU=8qdKsV zBFGhJ;GApcm~+yJaxxw!$O&&^90S^>7pL43o|fgz&XXBze%>jEwA%o2fBgQ3md~~i zwG(Ua;26#^hqQU*pV%+h+FNg}t^LA=`@PojkAmG8KIvdg8LbiSoEnp%sJJmi7&I{n zI+o;I#JMf+9PIACwRXJ77r}{kv|s;#2=24X`jRSb%3xqTk&>J0Y|LLZ_Z?|!J>}Q4 z^tqX!uN)la*)1K3EV;!V))Zqc8=SMk@EogkxN)z{IY*!uuB~2a_F6WxCmY6p8+*qG zo%+MGp^IP~)h#xKl{goBA@CUsK_|vl+z>%qaVirv;t)Z&XshpqaJrR`Ovg_HU3uOb zI*!g8v|QONj_P8Hi5zxEal@2wL#H)%#%I|Rrr1KZrP#rpdZF9xL7qM01%2XNj=Ff@ zH1y7;Tqytn+tM92ZZ>tbT@6l}OA%ccQ!WKW0!~d*mBwbPj&y5iYZ_#bn{)9-C_zsX z7KJ&5PoW%VJIMq%F;1FN3=PVu@!6^eCStl8m%P7(`+Sw_-;sN~$J2aS?$v}hYD`vf zZ^H6LIa1+IrdvebESSsV4S-5Hw4GHu%6l-#wH%#r<}9>E8`iV;B>l|2X*T&Hw6a)~ z>n6%gDQdx7G7c;;CC8-oP{}1acT-Df$Dr)TKacl*`Q@#*-r9ZZp@()ca(dZ{>VL)e zjuCX?oZ_Pjm3n5$vos#)gl$W-`kn^trDe-58ff68qb03(m-Lm@&DBM&g+RG=2B^0M zn;Ccbvi2$Vo9X_1@&~m60?e`VVc6<5+n?Bv-R$V5hXI3TZ@4y`><|0IPY{fduDw!3 zTUK&kClD@iIU-9%ffOfQASB90l!%vW7--Q;MfrJ?t)X}4sjX?dc=vC;w2F@6z?&QNT#?gn>Vypc%DiLL1YAVv? zSAU6eFh@UumwC6Emein=SCEuzIY1W}bW-t_^q{7rGE;K~x~ojH@rJF%sqg@^$tvam z3v(%Fkn^Gs_y^&f3%V3xErU*_Y?+!%jEhNYU7Sn82OFS$xanp{oRf?-teu%qCTk>X z51<81G0HjL1Qi&^$gn~U$c2)ddMhC}rIncbtk+}GN;E z`skyNzGk_@+Kwvf?IQWsxa(q3L=xk`64Oi=hxyMVMTs@-a1^mk4EK{nFl}C7OWFRK zX2%@$^z5_CTo>I6B;>EaBh3PBfFf>mGPN{M}6Q6dUajI~BFFA%Q8yXs9}UITMy!A=F2 z#nK$366MlGsD*=$?y^i=<4stgA%QLo<(8J(GOlUpnvIqwXPdJQ=4IR~qKjej)Fdk@ zxq1JlAe*yJh*L4CCd8PQ(xf#rQ4AB>^pm*xouLRDb}g9BABG$i*$Kbit?;Pt$3EK`}#{h{uTcUeBk7mJ$o&@TBB;nNmoOaEIJf zMP`_D19Ftl*!lGvfD_^%&v2yc0Ff$aw_jg_Zk9K!iv9ZNt{yYPWoCP<)DPyH=r1q_ z0@xkI~)aRe!U!T}mUeRM$SHAC|oETi@97Syzbct?Q#Zkgo=~$+!6uL6n zybI3JRPThKtKQcttJvB~2`yJX?J|N36sHXZr{rd;re?#UlG6vBZ83DwhCczxyr?nK z$<+kuWI;Udf^Si4G;TF-aE&!_anvqI+Q-hBF< z=hEkla-v?%3F@G`%t7aJj(2WW5()L@Yins&q2)At<@%L3=^S!|AyhD3 zKkbZj85g9Zgrqwab1HQenK68y$Zwgcz z%MQZSV0~OiCHhR-c%bjOsE@?SI&TL~t8Nz?C6#|U0!wkx4&*|=?uf6;3 z@9+NpgY0+wE8*_lci+vnh3z8sj&)ufsURd0vxh;PTVQwnxC3M%Ty7e-aiLB>Eqk>l z8^e*Ny!bNFi)S%lr->@bDoj;@oEtpEMx)8Tn#r)Y#Mgu4q8wC%Y;0HKS2VV47$&Ue zyBuIbTCksAT(iGUUoyZuaaWC=zjj zFiSAeN#qeJxHIWE74>=ysvKcZH10F^5^;fkrJZ^ns)F zR3q`tS}dD}2IQzTW@*m?xxCN4`Oe!PJ~Njf#}wAbHQb2lf-a++7|GF|#?l&fF0+hn zBmsLX>1K5E=0$t*rnwv8RxpQ>!wqp>PKF*_${FhLD$Y?roKbFtVwCeWxu$1LEVeX> zQe{Gi*#H}kH(zhC(yw@=sGyuOCWB^>SGn*(2=H_NO>kdRtPOij^j!wBphS-O& z1x9q#?{{6#{an89J8$*BKcDA)XIi)X^}p}y{^0CnO`w089bb!+JPkdA=EB7;Ob zvuvQiw9PVVUHJ`|Q)g~nye;FrzUTZMf}b3J?iv$sd-x&Ps{1Gg^!y!u4O?LKag+0} zI4K7aW5Mu{o3oU0i!5tjjo=+Um~=_&$|Sry~-a$~NU>6H6e3o3AkfCP8T z9P!YvJ%^w}DvVrCt(n_|n^kY*BDLQ_Qq^?I^FgxvLDLZF#>)*_LQV-Yab}|1**Pm| zlusn-#K-AMvpD+flv8tb*7%?s+jDqo+ab{Agq)BwcceoS^35j254p=B-g|-oF0Re9 z3As!HE~n&dsAXEbjLTQ3&>k{g4$h&Pk=s^VAEK3S7PO;IBQdp&`Wa$PGZ%AfN2OeX zE~e#YVcMyy5DwB|WSFGCd6V1s86gGajtUc}`E@>Y(*!vZe1%kMD1J7H~!9f2pbcT-2cV3Kc2PO$0vqV zpv%atZtnRrcQDfoR^#F#K5C$ADFF9Oowsfpk*yNf##lLX_Wt+9t+lcB!{z9pTrsX{FMCEV3O+P3vA3a20MELDIdopk`_>O+LBI*JlLGctI6ryHYP(hAfk2<3eHQo&u#~~>y0hd8jvcpu14|aS+>Fl;| z+VtqAN4;i>4-d(>B%D?*(za&hOc=P{%thHI=R_Q3Ks8=X$Z5i;6mE{wG;+{-YgXVO z8#YF<)&e!EQGBGM<^Ue6Y8Qmt3@J1{y|6IJcCCxcxHMOZTsGPO+#p=jqT|)2%MSgn z-EhDM<-o}|Wt@PMa6vUkt0iXTA`oG;ku@b?ZsC<_gRP!30&f<%k-;0onwitd1>tOR zVa&lR^PKv&T}_mGLGE)x&BhcT|ec3mSqCU@$YxmueZ}n#!J9a%zT;iw3ODa zSlC5oWgG>}xq!&GGR~rE>0D~$W-#k1!utz!BLmmc2dW*7w-(@p+t7xHaaU6# zs>-X!AF^&4$XOcY>gXg>3qPQ@#(I&0-1b99QirxP&BR~r4>!hH$M}>NKJ*T*2B#yO z17xNoTdAIaomIDqo?MX2!s`zf>&UXju5~4m7ca#bRSa5NaJA%n;701#e%Q(0Mi;ti z(3nSxfvy5EE{eEV0u;q24Aqma?Nw`&k~XPaO5>!RqfWx6B)PTZ zKNDvi-|<2ooR=3Z!nwP;u^U7ruHAM_3tIi2$8EmMuNQKr%&I|-rFG5mK` z6HpGZHHx?9WL(cWdQ=rhUDd)x5p!c0_pZ!Q7gOvuO916|G3spvLv`O2pTHJw~e zzX>|OQp!*Q#V<7FG~4}L{Q6dhs|d!4I8r_cxsHeyk;q|7##BiVOH+qK19A~j=&;69 zR@-wZOX~%*_utPQvm2NOWXuX0!CW(QaxUGRcr%GNnwXG7+((7J=CQhzA{;3$h)E~s zMK(b>;;D^toVcX&bRo>fsjE)Sd5#AxWRJXIhi;>12RRRX^RTvQ5A^uuFBcYGbYIrO zi-ZIsREa5EL?R&v$ZIftz1xGO&ZE09|BYKb&+RBc|4+(FJ1jFb6EJQapEc7>gHJu{t^Wgx$@ zH18tk{B`kL&)@!Q9stUZ@R+&}o1(u~hJaYvOv-(EcSBr%! zTNUL>UZJLX&NayW?8<`wcNIHXt}r(_JNx?eN%qv@=g^o@>*!st;*Dx-BqAACh}%zY zC#KV>nCrO9zA~XP5!W_7xB5B46>1%SYil9y!Rn>@u* zW^X?J9tZ<%RF7_0w{8RG?QI)2-jCi**|=fTc4y`g%^q|Q<{IOyOr55V?3~zn1kiOi z!FUIM*|-?4lBxQ&AibA6LvrRF;Wrk$(~vGP@6?vk#!P*`pB?7;JQMb9;n#m+j{+MN zUj5Ub{`BiVF<-`{9>l>Ismm8nE^6ddVU8SHTsrCA*4rFZ62~!7!8ieT)B2j%S0gHA zSQGF;x!5b=+}tGbQrCy9XuKkPc{_H~J2giNeWxe~gh5d(e_ci9LEV9H6DJ6X~)S}55(rR=e@58^&T4XQV#-s$ zrm%ES4nKyPnd`dAy_BthG+P?z#;V|!dhb27>l#Q$Xdx{enfIYMMbo-_%%Tc(>Evp$ zNE382izL4z=0My76vV?C*7mxjM7o)|wZ{22^V{E1L5qMSghLKiJ)vF2#2i+Rgl8jZ z;CzRD3%Uj2*4%$TdE>fGS~vkWL^z$CW{#3pZrhadp3#ZDdpB*`dt}Nt2ZD2{uyGPD zl4?_PDo1P7w2EOX5kp6RobBDMpJPWrn~6gn+Tqk3jPn?{xnsZdzQIp@>Qg`Zqxzeh zv6e5ba70lG*QOQ+8E4`nwX_7}l z6}5cZapYhAa*^wvotl$zR4)0W*IPMD{9B-++m0r1;ox01fA~jsj?zmO)7Je^%Iz}i z=kAPq?F&*Yl}@f2Wu2Y&!H9%bR_0wloV`vsW1cgf;3;CKe%iV6 zaxJ#uAA+L_CXL~)@O=-&dzziD>E`-_=*Dnv@WAv|sK?p4s0LJvgvVSB(VC$(!qxoO zL+8wbpvz4S z0_!2Odej8v_;&2e&t-W2E*Qr=UR0YlwJ|9+E(WHX5I?Fj`3V@&YXyg zqtlzN7-BxP;)tD5FU=YBQyH0z>u)C`>+l+=7{tpQ^&pxVhBrXDHznmBj7SbRCdWtRL|=qRtftE;4+ZhoSaJiR9b=$@u&!`6~~JHxUH5T{-?;pTe9x{{eWZlK}N@(VBi@rH}s43FZz z>^hTnbIDCyi_)xt&0;oXRz@K>c?rZR?!aMhtEAJ$T@27+oAUM zh%Yc+oxQ#Eo4fOQm4Bb$(is>>7I7r2V4i~R3HkH4*m{8plJIGr&L|KU+GT2E)?4TA z@Fo7iPOaQtb}K?$`IwOFXXb`{Ty|UW@xRG2?XEK}H}(eGTcPvp^19^7182P9-xuDm z)}PcFX9XVRf(p0tyHAZ%7k;Lhd&X>l>Su(bq}>SThWEItingxq=*HZ}KW=xcDckW2 zO8&>Fwd`Db8mAAp((3zapgIO|xg|BDs6{%PB3jm^!ktS0Mp+eWLQH?%Bd}H*2=}S+`6}I7jhYQXjSIa zRM@yZhYlTy;p)U=4?g(Vh7E9T>t5bKxtyCbtH2y2`_Q6yyfIoVl7JU-`J~soDbevis}&ZD;N-v4S|c zOXN3CM`0=MldAP8Wa?D$N1>W^>*BZDYtI>m* zMsA20J!VrwH*h-y*=o!^UtOX%%sGp7rg2KrWwC2DMg_Y2%EqmtIs%R=H=^1k=!$ct znt@Za*&Ah?XtOdapB1J}w%x1lRt3>!$qK+_uL+i*=I20Fkc0hU7p0nV)ttR+Q4k-v>W&C2 zJ7|^TO-gLE#jTbCa-Lh_V4RHH_~m&8MqNBD^Y$VP!_CRL@^ZmBN5Q;K!AGltTw$&N zm#Vj!vg%4>AV)0STH(xJ1brP}hf8zN)4%p+6+-hLhBrMQdDp*?Huwr zCA&TlQr%!&704+m7va^-t|NhpUEqNP;V4I*IKmR`LlcLd(8rM&r^c)tQ*sY(AVE4H z2jzB7LAYQXkc()m`dTL4n3w}{Sh}axci0@|q6ik%wm@qX9{N++j#?eeO$HHkIH8_> z_Vnpv(=Yz|`s-p2FZc7GKPTnfv2_`48F{eIj%AFN$fRExa8+sRF2{vm=)1rD%WH9h zdb&3Ttsqaa5dzxrsLfk)p9OJ%c~TF$IQ$Oj-l8SpPDPx7$n%QprGs*a;4%Z>>$*CA zlbGza3&06E;3?el_?3pa0^JKQ452RTA^f#e>*=s@;_P=$X|CL2W>E7+nZI&($t5)0 z>wnkBN$;3lMzD}&-D%}4s+I(@+l4I>ivNSVG9O>9C3FL3t`002z3YoKHsCrMgXpTp zx&5Pe@h9NM+`>O(=4?h)PR{gRvfcNR$moNE^K+u;zOr#3tyB;2Ef8ne6wVdtYFL_e zsaC;_CER~g&dPP?jY|dEJepVeyiM62rD@Kq zmSg-%mUugOJa}|r^7T`fu5vLSi-RRxR+^pjO;^~V`il1^c=OD&h`VPlz_?%j^7`y0 zcS7Ojv~$d;F`tAqYUUcAjtAYZnwu-c{R+t4{_AfIwm$dTYtGK8Hb18#+~FRvfE)`+ zkb_QjC+6p_fT1f?2xK2k)9RV%-2xex_OT2a!o`+^tNa$nz7ayj7$UChI@2h(3(D02 zEMeyOPjLIgB0)`0i}$2aF*jC1u2OSxZj88d*FAM{+KK1GgqxgPy5%qDpANab9|wxH z;g*`Lwv-0c!o<`c-R9B_PKXANjS5(kyQ0=g}(;m4EToN`J@z`O>UDEK!#M zQ+!OS2lj$4&g;A4r1eu`&8fW@_evR{=dQE(qqu{^ZTi3~bOxgR29wvB#h5Q+U)dFz z2j|f0jPoe@(HLyo7jb@(qxM__$nDq$Q&wi-v)vWAlR^BXf`!Yyiwzy5O8yz?qA2Lw2rK(2c(YC#&Kd zD%3SQSE!?my%nNLtr8x8HFXKjk$tJeTqeomf{gHTq!AY<**r+8aSp^;QgmB8=-%wu zSdIEOGOD)7mf4iK-em!DQ|FlOK8tsWNq;2wFfu%K)NxWSH&pRpp(Zya=Qf((PC|Mt zznH_xFmi#oEzpbdjxCtC`!`0A0!*QeMjn*^DI0}cQm%J%TNt&H^>RiM0$;LGfx2}P z&SKWdt!049P?hO8wAqKXG7crq6g87?6VAM?UAuMzHw~dD4o&a{x)ZdIsf3(P4gsERM|=5yXsfB2~*hYue3R(lAG>_P}FfoMvvB;48ycZ^Ci4 zNd{T9Z{QTcBEGW}O2>0USGEKiQb74UI<9L&)E>H|ptGm%3J(yX!o`WYm6Z(b`pbW% zO-nD=f)84_rYmOxruksR;srrB3OPY>kG^A3w zIyq+^1>OE)of2;rHNdzc+`x{n@th-P8ZV*NIk~LKEs@*8TV;&3$X1*)3%Y)^+Mf*f zuJL=dtVpXbfFmQ@QNXE(NWORoQAaQ5s@%u zm^Ds&-5Hm%(Hzaq`6SlDGTi5Z$fE-!b$Zu0d@?tm8yZ0gD>Ioe5f?q52^N;O=>ad440 zm@cr9>zBX$(?9>o0$^+fpm2-_YXqD%$P!kvYn)_R)b=B_Zm-Ma)a}c0fAlqix8#tN z6LNq^&Y`P9PCLX$w>c;;#Kut&Cq>T$?7mRB4r69j>KdD-G^Ty`9k zEaRlAVWF4~j0-3I-JB1~AMO>mJe-&3T)m3`oi&sr3_<9jvvR{%^vkzIT+(jX(Tzf` ztX#DFhd9@2vZ<*c7l@;b?%yxIWi{@6P4!+=G&(txgiFYYIam;*x%6@!>dMEFh1{1Q zTjDK;t8~U_B-BvD)XJ7pL5|H*Ekih-t;ucBn(v&sw=^Ac6~*Cmhjn+pFV3MhV~40W zfieA9w?3{(y2a2_(P64AF(;k?orHoqv4J7JwT=O+l;eTH?UoSnS3zgi017u=G{ynS zgj_e_mVgUAYIv1BT{2F}i8)8NY+xnyic^DfNZ;mqleKHtuidU?;I?Gy+>-ZXWtK;vkj5gv3^>T2d0w)LOqw zZO5m^I7=Wdq@&ZyHOO&hQ+J;$wa622#w8TYH3UgPnoR_ZIZGX{GszH}=ijNooA!{> zNxvkr@o?Tl_EXg1Ei2ZhoFNH0c6hmLk79UNL-(D89NEgG+JjG}3Q6D+J#`smGK5xf z@RR5LF^hngURvgl@S{^MwqD^L9S>g5i~Qvr;@r7qmjd(O*m36;I5@!YgMdqQ!PZzg zSC|`CGH%TJx$zsn%n3S2tyDC%Qn(CVNxF@TKa8GKGAhxQSqV55uC95x=Hueh_xsAf z^*!iDCFk1a`#M6&GM;e-IT2=K8deTW+x@0&2&J@+pd-_ZcPZYG`$cNsOURL(kl$Wv z1`bKEq?|?M>Bd4Zt93Me6h0J-U?(|;-a%1b5smPC0Xbjj|L6+C0GUd#@%-*w_a@}T z9DOMVy^?coSA}wN&Xpy=Yhx}UVe5mSoKE3N+ zUp%A}fshnMWGAi-s1sfR*_QU|jul&o8MR|rH_@{9>iRl&u%>N&X zaB=GB{B<{gKt~Xcj-P)yZx>e|2`3kn8}V{hMYygW-P>A@Zv1h=qrujOxe7uQX7ygZq1C9>4qE~HsH!l-%d`-SlOmc36n1fETX~Wv}j#m|=8KrlEr zbI{mn$VoXzt7+!soF@n~(Bne-qamZJum9+G(8STBM_#hYo`W#;aaodaOXb-jE8A-F z!}y-^fyWxJS{mXg>h?w8#($n$`y)7zk=5h;M`uubS86YoXxaLi86EX%{J2N+GSw2sauI> z6&Kyo{h{znT}jZ%xis60JkE3V&2nDd!8=#{5JGQvx7mEflbM8E+X|7K8ws^q)F|oX z+qlWOZ1$&>vlQp_aalJ>HvuC@+?b{;}U&P_eBJz-`>+Z)$>-QZ`B3cl@j*Qli=;LOFi zMmd;fN*||llX3aFn-&YmAu#7pDPJiu7eP_vw}j$4@r283R1oI?$CLXF5RYI}}sz+QeK9R||GSMlQaP@zUU#CJgn)E!bv7jk@q_Tdb>-^IO&lH!G6T(@DAe zi)U+$i+0`a)w?xqjyS{e^|Ny8_8xj{-P(<6vy4Mv4vN7t#;aPn$eUpt;-yT(@&)Sn z=GJm@l*T!}6Z;(EQ-S9!9afGpXbxF}aY;B9i=@s{B-~tV&m!nLbrvW}xq}_$gj*M3 zHF?}Qm4OE^M_ATl&!>O+H%57#3)27m^#)`>_&4OjUNRMFjQlJSH%nwd&333OAD1aq zJ#>+S=%DJwoUCK2PDd%|+&wFM&Ay9)G)mO{7?h=Y#AVZB4iU|;iQBoBoc~HMSEJUh z1vWqq%3Y#3hXxHrQz}trj;56T8qJy*tHvFQcki5O*FrMN#oRgHMhE%AdvV1a+ii&@ z&k|3`^?vi=>QvUbX$?5G9n0ux>P9(IF>c(^bEeU==S+IJ@ncrpTpd0~s^G&2;VKGI zgVrJ1J(Q3`63q&(Jw%&k&WSP?h zTEdk^m%=^d#2aftcFY`|e(9wbfBDjdnG>!F0a6dOWEHj5Zi>h1D!!DQqZVb#Rst64 zN_!t|VN=?KSGO|)Vz^9=%H*dOCFj~_fkD0`d zyyw+}5f63UNHDGp8?Q3J%1^S4Bq;Yb-mdNSU?e2oRBP9M@rzJR<@yo|Uha{H0a{Yd zz=M?AgL%{5F+zoI67Iy@99tLExsd0@1?65&%$b#SjDHxa5_E7CiRUeWx#?g3@khUd z4uIq8O*Yw=f9sN26}8N!RPXwnNkWCWk)J?))61Ac*OhW)LH1hiijZA`E-~i^D% z{Muh(8qwQ}{Ae0FiopcWFG|Xt3AB+jDPyagCX9=l#r9$O_&^>drjqb%|*J0hDq0rR|OrdU6h!!(#kar zc)46ikzTF>t2UarsOr*&5x_|{vaOt>DJM6AIVmT%o;bp(bkCl4G3oTN({o3jkW)>d zZFlG7vZYgka}9DeJ!feh!Vsj0Mi9PKv28TnoY4anq}xlQig9~Ma86nKGsYnhh?7nL zEkNcJTpwug5#?A@i8MI1R)a>SiZhg$G~2X+oe3M(CA!wp1$0DBH?DWBTpwP=y@9xO z5ldY!&ss2bb14R^zKz{n3AxBTKeCk_tT|#;Mjqf?S~nm^hy4ntk8z?e>w1H9e$nms zLT*&aIK&ECb$mK+>3U_7>HC|pdc@VU-I&voHjc`Yl2Ltqo4nL%Woe}#H;Z^Th(=S3 zLHzsj<$qs3Nj;>C*tv@gTL~E?^w@Y2J~JuD+?_XsaeKti8MKDA%Q`mO`dvPijxvs# zBiCV^2F>023AvPey~5OKp7-uQa72C`sZ^4@bmW%)aq$5SNE3`IJ-t6_6O&zb{FT!bs7^Y##ziNs20fwAIsAP=ExwfaZdL1+X1>OMjPe6B-dn| zKCbOowIQ!&;V2-DVuPrfYI&S(1xfR0?{iPj&EW>b+|1M=wP)Ko{zC2%R^(zH-8LBq z-g-Th_c3>9qiG$hZn{43wpZ9mwWxSX$XVsfz2eQJY&Qu;KxY+;=bVbO4$GxyGj!U- z8&bzONQfkr=l#mKE%!ShGy)nGP@x)AGBqa3k^)SO!$Z2dRSrc-WP_H4MPXP!>Rz09nfMs8Gj zdHq7Hp`GN%7_@p5A9YuFlrBO`oT|_spAy*Qk+cz8b5^@%sJhn3qrGZGq5p3;l(D_P(oPpMEpI6hEm`x+wJ}Od6~0oRO{DQIMt7Un~xR%M*?e)C)TK% zCLUHhcOIS!$mPWh2*)<(9NY;9s+{h7`WT3NnlzKgD6MYfjMN?F6W5M#2|bHyS5{sp z(z>8L{fEC+&RwxTp5kmAWtpXB5rw!-7CFfsFh|n#g?S_Mw@|HEQnWm9D;IjTMz2A+ zq#Ma><=Z~dSJWpd`9zx)%(I8vt0_8ioYX1w4AVLbC#sczYw=Y;CdZn1I%DZhuTug} z730dxb(M9!BwOlDEFsCGO~^F!ie3<|KSDhP61_G;1Ls)O@1G~Sy5g~!tdKF>YbbMrT9jsN=r8yg;;fAi4__FU6mkR; zlT8h@T;=xxnI;LB$`jCtK8QH!)=kIZEa=%k!#GjfGFF{ajJ<8XDe9Ul3J;#ieq zLZHtS8yAc}Y{uUS#?2(@<$@F%tQ+=j{YD0=O2qjt31?ElxA1YBzvz@4zgW2xcmlp{ zoj_o2BCQ;lOU=z;>9#y4`TjXTEhl(~%pZV|Y-*%Dv?IJaaWI%W{(yCq=OhN!rWQ#g-KUO5OkCtpoT zxi&M`<&%lGEUocv10MYh>Y8g2p0M=E&}^sWYZn1-T!-JW?c}0jO-9=Q>!~IoPvNv0 z(hD8qnv=`aYk+KxclENmIJJl=SYW4I?E(r0Y@wSO&V_7uc|neoapzB6kqohkSKJs8x0bc@(+hLYP;zpPG$s-;w1Tckx6f?*)iJxi_5(PJL)Q#IkoRZS z$u-vPCTFXQYm93lS8_?*m5npmCEHEZ8GRUpTn<-NZ0o$QAujji!#GQZRV}5OjVl4S z-n~VKdQ=a^wg&XQ?N3b2oxbqW^eazK?LkbBi#sV5PAq#~YSqLTcgp1uE|K5>_EH~# z4ddo6h^Nnav6v?jor~3AJHeb1Wk7B(^>(XGRI&cI`w;pC;wZl5q>zj^z&Rc_L^$F8 zVa#dBG-App!6xkFT#CoF83%oY-vGsc7Orj0<}EOe4xcmc7E^T_43lE-oPi@XCFd+M zE)tokI!CK+%71ubVyj@=*+e*1$m!%lPr@{yM#j0Fo;l5FNp5>McKVonQ%8|#vyyJ+ zn2Uphr!UN0_%$obkh=rW)k{wN+#+MjAcUeJshU?4A~LQeom_XvD`Qk4hu|FgBbk2V z+n|%DEoFT^7r;N_JhT@y=@{6OexCUO~~ow6nu+O zD{7!K5@EKoSCAVub7kr3gZ9Fr@Nvp{Id`Keo*ae3sX!Yk>X@nPt{S_NCuQEiHk`ocIkG?tOH8(-_1>L_LBER_b$T%A}V-xRHk8^bvy;9%YAC(rGs+CQ+I z#Il=iV;xVTuF^f7f}SaJs_hW1BRT?bsdwavH8g>54o|LAsvkVHi=E2`PuqC;LRom494`y`;3G$LA9$zYxAL5ri_s?uI>l&IoDEWr;i#k3oK;iQ zf-Syj;x%*vT!uf_=h9!_Fw4lF`pKJ2$}?&W{!&GZ#;m*WSp22bmRy$Jff3( z*dpU_aT2bRXD-EYBMw<9&d6cpW)9Ar0R2xrb@=4yVYd^J&yuBb17rRKWvN`kAAHiIL zj$6R;LvXkxyH+7wsXnd|Z2CX3HXvZeKWP^vVHnFd!o%3atco$7~U=qNneUX zH~l4X-f(%jx8G>9{!}b_*{~A6u9{_$;s^B$$}vTZ4jh*gg%PPi?-A9!-G`(($)ECZO23 zd4v}b;82(yHZx5aUQPQ(E$p;+j%+FU8s$DNC`Jz4AxUQB!9A-XKF_W8NjZvj3Iqo6 zNFFj0@(X+-+Dzih{(52){-;Yh$Ev(2Cs!)QF9ObBjaZpa$DL%vZDfYU)^6N`+Vn^=t zTqaQ9VAauTGA>hc4q=#_k~5{1BPZloY^zSKbmLS!9J|lmW##qJiN3$NIhF?}>-a8| zERCmK63z;_uix`K1)GJ0d=$t+&ejTf+fI_rGw-CFxVr=7?li_VJ4dc?Yay;cH_W+W z+ISgv2wQv$#f~n|y8>MPHs|J24n4nPhX`y)tSJH#(yTiu>u#L1;L*Y;ROM9a&REIe|~VOkLL2!K<$;GbO= z_&F3X)4$P|d%W?TghNs;MGNV28^h>;mEZv=5^^OthA?bt<-lAcpDENqP7Fdh2E~sl zEuAh7(9yWBVROkRUeU<8$G-^WwjyGzpLy&vbU!2J`1AFelW%R^FSI|bhugXHLm%4t zp`Gr2IB|4x;TVi-kW=SDUDusS@!`VpSJ@2Z0t;Z|Msb}SX>oS>#x=s1!a~usjru6@ zRwhowDGm_fmvn+~pZ(^K-H*VlKc;^4#~&%SrF-HVnQi#`!T(3yIy|qv2d!c)0cYzc ziq~m5+iaYe193{mDG$v|$d%+=1{~VDIjdq^P0UgLPx%9g1JJ!vCr+xXE3zG)hC}SG zst&g83cxkcfjVl9AoGbRXY<&?8l&FsU_b}9EF@`mE-`1$wR1zmR_D;oUpT-GjlYJY_{1eQ)ky#ro`IF*wr^64#@zqKu*6p1>*Af5ltKda2!9x z-(64ge#3q3j7%D%s%?~dkCO|+QQ20&;lpGd-8d7MkyYuYYI8$SiAr**J!%TYQU}YE zJ9u4)qY-iK)$piR>N%sAkn^_y%AAhE*&KF%(@uoPJ1pfop6TKebGao#eUy&MfWt-# zh->G+Y37>jMrd`t1Z#vd3ow)PV`z%2+w2DxvlNWaku!6f4XQ@*984&O)<$LKk=lR* zN!F1~Qf?xg+~bd+2cg|(9_Bcu!`;RP2C1|@!8e7CgK$vJn)Bs2g9M0)xjf=LPg5e^ z5IQL0yiEG|tjpqDCF>F0A}&ueiqYya5EF8Zaq>gV-TqY~P0*F%oZp<{lXF*pbXCUv z{O6pY{+Azr)@xh=+^0VEyU(To>$TVZ{AZVW+(fyRtCq-x7lCic6r^3wK&HYt`Lk!xLJhXBL46S{~bTgVv>X$f^noWbfkeO#A=MoYQ)Ut z1l_nDU*2pvo-Z1RbeWS$a!HwrqDBK?k{YKu%%e0G!vhZ~-5b z>$W?Dhl^_LZu~-AmRb@wG8JbLae2l_%H?m7kt5fH6vztL?elgjfoC{ECDE)QT|L?O z6T+?Hszxb#u|@Oj4B^3P{;rD{(Xe#)Sf)xLo`pHjXBY=Z)N22|6*#T#lKotJaj2$X|!k3ark z3}6A>!w-Lml_X&Ph$B<%+lQV)0M9O(fN{7vD0gD+Gyw@P2jetw3)3D0OgFZw<}R)m zUtI=9H}zVq_{eFa=H!BH$vAtdzz0g}Hq5wOdCS@~Sf{@Eet!C{!TuZ9OW&UhTJs(aEiorAim-+e32}ZES z7*;OI$vH`vmAQvq38cU{MA*=~^U#|m9Jh;tI4Rdp z$kAEt9@R?bhPe0JIz1=h#!SU!R@);7b3;ROZoQ{FLM`P|`%N}VvSnNK)HaRV)Du#U zAM_SdQE6|-lXEi{fZXZ1b6B~6oX%~+i8|m$=TNj7IcT;)!9T)XIm zSvhz{MH!U1N?t`cHLYCl_CC%S6?Qo;?G=OC?35&0SDcQ6ZT5ZR^Me7k1f1z{VCSo? z4+rUX$}(#amqsqetGt7Lyx>ln(@wlexnLY#4#tJV9OCtHd>n_19j33NkmR%y6OIgN=u0{oXHm83 zYgDpKs13gODNErbQk#bZZ>hWF#8gVIH6v$^@*Qm3bq+v>V`5P*!npWv;?9{I+6MoQ zvb4mLLUDL3{Fyv{^gGWF+=R%<>Cb=dC){D!tQ`6O+740236ot=VrBVirhSx}o2w(! z1>V4QhRx5>p&|*iEM2l9SIWv}L{3^!@}emeh+6~WP%w_Wl;8NqH@cD}lYxg}1DEya z@;ED#)iB~Js+vKEvT|l!9Hwq}1Q^QCO~oXV)8|tM%FIRGaF<=PV_lX0EmxnIed8;~ ztA-XSF*(Jc)kvgnjv5I$dFM)DVWwbPT^^WXcLK}YT-ACITxwdQk#)O%VMSREp^cs_m~+_L7?-sr^J<(Up}H=@2&j0A%XD%@v`23uUV^G(oaM_jWR#ot z8QY$Zh=Uz@d7e894L0Qd*F+(2{Svq{>gs{%9@bg<+1Fk^8W)$n{F7Q&l6uD6NH-d9 z9UZimq@18DFV`}XZsrWNIwL3EEcEU8E@4NfNY@f-r2Aep`$>%MQqUwBSC9+9VdD^k zRVC$em>LCH*Noh|8sMl4aE)&^%BF0bO~S2=9BKDMWd5l{9RGCN%}r2l#tqq`F&#&Ex1|?^Mj9noXXa(kVZY7WP^34=z=vc_nF6)gnNua z9AYbGuBo$fLHZ-%;tenl6jqci%j;1t~zcdW)G3D?=;kgBkQtV=Ja zmI`w$vArkI0A%1&zy%*AY5EQFGA<$ab0_9_R^7|*t3UA8h(~Ol$K`oST)4NUoT($z zG|GuQA8a65>`QjB?hF`O0%++|6j;$S9<;S4TQ7e3ee03G9 zV_7*EvDjRM;*4DBYpg;cJR9MN?oiE^M)pFC2|{FDb8}yt9jaY5Dcam~af-%^-3Q!vg-FGnuUO&wvhd2a3kRN5xy_E?;(Yqm}3?IR`NXzcJj zB!{j>F}(Z0r79;*fIB=L=;I}zo9HN3j!nh1oM^-7B?ddpp*-&`FHX%hZw+39My@k& zd6tMH(~<=hd3-@x2aASdNWbb(x41_R}Y*9p3q-0rkU&XlD$@2>Up&Y_25@-6{)( zhs|837HMsjl(W>LIjZc)Ig*vBA&%OrQZ`~O?Ok#$^MDw`oy&=>SS9N=aT&)Y@e=OM zy0~`|cIf8i-l&)BX5{Mlkvedsj9d|pDhp|~<-fLr+MZU1+#34g%-L8&dk^8{owbfG z-UI{b)2ezGGk9s{WL(Bko9z1DacEKwF?J1CClpO6f3j2ByN?Ituyh~yL#tw(8L(Mr z7(&D))T|LiqgGpe3ONOrqf?I}F%m(E_^ZQJ&75vd%^Y)LZknRv*pc%jHQ60)fr@eF z@^bEC?F8aH7F^hQNShw)T6fqHhDqdf2f8KXoP6WMZvQ-i1}RtU%W)=E+g{HJnGImn zy^?BTE}j}p!^QEWi`3o8G~J$6$h}{wlPXt}fH>8USX+*3W){WV8Ip{XUX(m~FVUt? zb2?0d)s0?4jv~^$9~NS2-+-oQQyH`^$kl+g)rmNpwhJN?xru&l=a2t<8a&<$+_?|Y zO5SA{9b*wOV66y*d@IgX6k_!?CFUM+B(-C*Ux1Jc+pC z9Oec$lr{#y#az@TPLNe?Y~ae9U$(uCWA0~uIQaEwaGMGfx~eogs>Chwo0iUoA+SDMDe z5R7P`3wDuZU8@?{?5XXo;y_Dg=>l?;1efX{XHgj~ZTjM1gdvO`rM*-i|9JF$C~Yas z8G0zOR!)I5nbu*g>sdk|4#oxKq@3arCFW4XP>=PB00iYcjMK!Cj-Q{LmvIhL(ItWq zD>9DK2$ySulW~^Yk;L5%PHnrPv~CVQtvV~mz%)r_c}>bmvK+DczWbs-D&C$89vXb; zy_^+wC?8UO)DAC(ciw84Q+0KmiK|;`YpaSC!;2x_r<-%dTyjnY{KQi8a;C_#Ess=o z^Qn|Wv!O*7uZcxUTnW1rtA2%@6P!uGp+&``ZVs^Zi%J^Lf^pec`--MrRJg!tF`aJB zW7`x~t~e*+NP~MIDiAT`TRLYcWuVn0^vty%qD#AloSkG`yt1-a za8i6|?KOUUWv>cI2C$SQ;z8**4Ru$l=`)r4G- zF4V@W^37&g`Z1*=J;?Hg7-Xi-?r_i1+%}k(iJX0P07YAP>pSrooD_Fx&I$SCoZ3pJ zK(%~ICGjS#GKiVxmRJXSDS{5 z=5d@HIZd3%gKngUKlU*?jdT7{)hAl@t+OXk-ikjX>{1>)qVi7Z&dCWm7{}DnZT7cw zPTNX&ISd?tqam4BI>;@P)c!dP1ojU z&fPgh_pg8bi#nZL0xha|Fp6LsGjuk}w{e^je3NVqXNuXl8~!9+gClx6I@rJ#4qn93 z-5FM5uU5_hy5yXG3A|ANneaLeoa5I- z8X5X^nSLTJlsmo%!N%o`&ew4ox?|VET-)naoJ+z{nGjXQAqsHAF^GXtYjV!q7)LGE zigfbLLY-~GE?r#X+3v5(vQK`m>XLlhN5R>MIir+2nS62{DK;o!<4W(e(#I9$>PCmG zn2=jFtg4D{qeiX>*G@TC9{QV0_r#mI2xo6_+-jxrPlCjhSG8=@l*MhVp+>j^CN#yz z6d#nlE50fE?37h`1L={5IoeLy?Ko#+IJSL_DY>=5uq|?qx{?$#DFH`?SgcF8S-+Tf zD+}j@oCVIAhw)ZVIaVzbC)#XPa;_{LWIM9+VIW7=b_v;%QckBpy7)M0Ns%*B9J zz)3kZDdk*nwZf5QH-H9{_5G-|;Z491G2+aJu|)yb7Ewyb)(K`;p?;&K_CjH^LuFz$wTDWWCkM@HFS4$bnJ}=9olHM;;T-^SsbkPHjdm{V zlV>{=ShH`%d)2(1b;I1bvzD_bPG2~E;;=W-pXETJ+zxdQ=kRui@WcVS+)cl}#S5%0 zSI4u?Bk`QwyE&vxb&j1a|i8ek{dONx2i((w5R93DqC+PBtF=$b)_I^n^t0)Qtb~_FRW(j4_w5O8Ibj`nkJl=v-M6XHVrRdrZd3wIH3c3&Qkm!8wAoK2RL!=C-Tz zz90lqGjlM_tj5gLfw^2+(hpZvLN8@2+9IKkm}~|aXQr%1IydlJoHUACi8c)jq3qcjJ$y= z_?8(z*VfJ5ch7d!+KNB4awMC~nTm0lGYv@h)^ko5M=jQdoZNnr4R|B_B;Ok6`l0y# zJ(^V$l3S@noOwX7FIAny90+{U&9a;;^wRHt|I#$m^HYaUoId^RvnSjpkk`*A=_s+j z4(4&a0!w{c96@Kc+DYYlxDf2&@V7@Ems-Y6DM?5OXM%XXHI3C5D+S})s5Ki)g&#&F zC49K)I^KG-&0%QUKj+~rKes&h){oJ>hMm576jjBa~@ zGd}9V#yofuvhvh9xMaEI&Uh8;2W^of)fFqC=#^e5&x(_4DT(LP9eLMH@zs41l%JN1 z8&Mmwl1W;)O61b>>}wEna!$ZGR3)2Ag*ZzEAmkf4Q#)Z3zCAPMK&E}2pKF{`K*|O` zXEtRv?a!J=de-)JY#KMfMuligF>1@SCpUm{lL>M(2IRIrCgb#RAWq6D2dJ7j@YX`D zK#mbB4zAXYWXiniRSu&*t^%tXxmp+JY@B!t&Y1;VA&zQ)p)M;Cmv+u-VBkt+N*#c6 z2dEUz&0{0CrFc4*n6o1JjVwM>VdUc9Ri67qMB~J{9iE4Bfgv0KfB+6>Ie1sh>EmRa zJLy|6fmDzytwq4c$ubw^KK$@jF{gxChFODfY31nhK693Gay}I38s{>ByYg~Dx)OLT z$YuR8$FNck9oEWy>x7I8%FP_R0Ot6k$JGuClh=V;N4ZXQ^^9_Y39Ax_v+|+_5m$^O z%Q)2LVTi%QUP{w_41V1YK7*D`#q)8y&f(lk3B+`%E3-z!$_b zw}ET6R<<(Eij;3kMYjX?tozCJZBM$!lRcYEt7AJh#=YRHqM&s zgTbGaQ?39WRxOYlyL_ZvToO*kHDyqhTx7GPigT63npyisJ80%8=A=3@>|k!%mY!}0 zv?uwHFSD3}h{41>`(&G94;YIpj?Fxamt(QXH%_0{+!%*FqM_?9t=G!cWr2eW+SXEK z?Y&xt1c01d>E%%ampdFlTmp^C2bwKDMi~KIF|MgB9ecV)FlYA>>*Acr3eIKN^%I}S zDC@TpasUo3pp39~fFt*kaAu54rxlExB|%54eNk=294QohYmgIjP_9xpJhe!>R7bl~ z5zb;$0%QY-8_;b4*n$fQIh~z=%gp&qAUHQfz`PjICgkFrJX&?juEW)|Z}Ep!Ou@xv z`f53D=_kjPuI~J$aD)q5;U^vBinpe=9n4}Q+$^H4X6Ra{5NFlre0;vSy0UWV;xY%~ zWSpI>O7M+L83A3HIaPj+G;|Grk&ddS=S+R&PX3;31w69FWG9O%u%&XGhT{4XrdQ?| zZgHa%CN9rZLh0iYb3wW{y?ITZMiL*S?i&p@6ysW5d@Cj39;Io*!aEKu4;f zs&zYaM7-HFw5c+4B8I`GxlI^tMY`S2aPHKtrF1lT@=swRc@s3chXBaRX>tz=Eepa8rTYQBY?{^ zs7HjIaH9+$j!aS?!p*g)>$kr3Ei9ee_4RSD2)eAmT#G#X`qwtUz87;fU~Pa?TH_eZRbPtMhWP0k+ib@yElpL{6|#nZ`@V zCE~iFE28Sd52cS-NLFM@G0wbt3YP8=WPdJ^Je47ScbwUszvhqx^bac?kzvz(a&aztF?gZBtI>Nmaz z%B?aNH{jo_T4Pp^Cg2>Wk{<0Bj$}+VYUbe*X|-LI#{yg+F5O%1eW2Hpfa{tJAt&Z) zluk9`<{IoMsb{Q4rPZs4Z98U;z4(%o@W=8n&kNIHj(CKidzf>_WtPZlXCPTATi!oN zvg`fOd5mv6Ekqljt(<;0xQ$N8_~rr%rg zYX0zYb;|GynMuN}l2w?w|EltHCKn1vkDO(MaT0F)z;zgO&-A3LTfUxwZ_k)VNmsBF zad|A$h?|Q}ysC_RVKaa?`Sy9zfoDu%Se`t1)c;|!YiauQiL+0AXe-gZwcKIsskTrK zqzO6kChY=pZ0vFfoA2~?>OJ>0C$}o(EF`O8CEv(pcw9HUrsf#?OMw&A0lMT? zLhHd=z6SmHcg~YUYx1kAUM1=zT|=6A6&p83>ESYmaBag9aDh0N%fU8^+0-ESIVtyv zuyTx9&)Q@N!Z2%$T)X9RzaE{JOUM=G5LN1woO6T*1ESL16y{>5eG^-{(#BCYxLGn6 z=tc*wmX->016~erjhvh==(?|{HbZBP_>^dg`V~zce0HD+$J-cCYK1K_e&AhB$}hoK5Djb93hC>l6lpXmHNEJEZX*2o(T*0OdG3uP16i_{{8aB-(UFl369qJ z*k>Mhe>m|!FMogM16!n=P7a=tq7V8|u}?8#U1c)P(vpZ%_S43ZsL24%;c9Q?r~q4( zdt(hH$<|ff>6n={Z3BEu=Qh&pX>nGR3xX*_Ud}Wm`L=^<$5#McqujZ&c02NdX0oCa zmopzD2KmzTOrAjba6kPe@<_3SBPiE4m--2><8!OhYNOXe++ZZN>FWu|Vw^?EvQaaa zYFtB&b*?5!&OP-xG53jYeFD&(JwZjC`&zw;Isg}p<4$S;=dGwJ&D_1K`dt!ssUSy@ zb0je5U-e>KLaq=e~71-SxU-Q0STEY;dXUHg&Cqxar`yIe)W z*_+C{g#j`3SSDjU@TstP6Qqk6oK-3yx9UZxmu0U6Aj$)g=_7dP3nFx~6A4%Yi z4BteXrKNu6>B$}3ugU2Wzc~GkPXM_`9&e084>X)vOlGiWu}(ura?mQ}Mz%SWd$Vr+ zpj-Jkljp71q@39qxwcvLd!|BMrxs@D6S5)K=yd-cI<%R98&%u1N)_pVc?fh4Skuc{ zR5NlrOis#i!Bv7TU)jhuswpdH?Aj&t|KaS+e)e3aFuwl;!Lb9!5((mf69>-B(U3;M zP9;JjM0N-fv1@24LLzDiHKY|WrFQ97l%|cTg9x^n$ktF=bQ29u`2E&;)_3jqefpZN zweEG_@B6jp@8`Ow=ecm|UJhRz+6U=KSjRjt8=B+Q+PBU35%`gaA>9`0^88gJww0MH%S*P9T;CgcR%1?oEqAxENcE`oEH5qLA4 z!VwV81PEp@7siRXNXGr58d)W7ZU^foq8ymB88Qy}I(~=lu&N(<|DXIe$A7mOr>j#1 zDY7^RtK2hn!&qJN-wX|5>^v&ma#sS+2l1A79r6Wzotyp&D|1-6)#d|u)6f;>R-DUQ zBvdTjjxATPX7>7=xmJj0L^3YZ)+n#Op)}_*cNKLQI%4hWst~E&CHU0VO*uQ&y*1$8 zDBe&Zu1wtB1mYmTJqHgS+IQet{6f`jA~C0zdjyYGl65V8T_s=fp?-=W+@l`Vl-qHY ziw;rH)2lY@%)aY@ucJt~+~(@(sxwv6vgzbz84k?ZLO1|NY?wET7S4E`jm+gP2HAm7 z*<+A#qK&95l+o1Ph)(f^Y9B|3!J}J*qx;Zt-Y>=jJRlwNQYf}raZW_u?GbFxO5vJ> zO8vAK%AP8hY$2U0x+&^EF~>Q%4m?NpwX z!({3khzZq)4<0(S&)I4p%qqw==Uj!8X>H$JsH+W$GJ5n%%%M;&`>E#B32T*^qgKSm z-RAj9Ch<0n93_NPvksTAWR5!F7_v3i`pUzUbOMf`ivqb!R@?rTmm@cIYz9tQ_r^|L z{m8qpj(qLZnX6~ceD~C;)89C8kE}bSaCZlwhAbPrEqpt$?-2jb!w(U3Y1HYwI!pg{ zgCU$#8MT4aAVOC#M~FR%hZ<;(MgzJ?&e0Am5_IU`!Nd2kwG8N(uYxcdl5q&kv0CRh zBJR{8NC*6Mb0Q8=p&U-GK?meWA*bGaohJe7;%H%A-R2@kvM$=;=bCcXS()2BGuK{j zg}RD9S28c6-caB5ViRI-n?VN$(-!~czoYrL_Cv+JuezQ3Jt`Ah935m^zapm;!i8}b z``EdJY|D$mkgu#c%WySk&8;t*jO*rb?d7Ua*HtNKXHN=&z8&BVlor@mP z&}%VzXnxWP<)m9`;mvAhwyJ-lQCX71!#(!7Iyplp2j19P1#`ys2{~;XB{#Q3Ty{^> z3%8!1PIyXgGl5$!>yu~*M>7RnSDYLL!nrJG-WGGN&YiofG^|5TU5{Tpa}}L|bN3MN z;5efX3p^*WEYFEJhAi*H4k_pV`IL%wp%1v*(;9F@_!hQFH0r`Ldtw|NZLx7nUq7)l zdTGNrnESyGf;m7pm>baXFZsjGI$(G4BEC+!E=T7`73GdM<@^TBon*qQ+RBZYgK?#1 zoV%(*j^-1V%E(pHqOfhkv;}Zx&Xmk;eM0?d=LHDCHhn>En{uwjT`RfWy7;;xUA>RO z`FF!@*^6k!QVCG+u! z{D$S2!@RI6a zfR$C{`c}47y8~>~UO(QABEfo0COV~?jljy8(KBs1KqBIL;Z4R_hi#q5?lOmM6hL?P zxx3CW<`ayAeCM8j&Xp^Exp@*4_ri`}xPZAk_1$~#{l;OI3qYF_!9$;1h_P^^b=W^4 z><&C@VO=mcXWy1>hEz2!&1__aWs0wn>?23-PCV<~&x)A~=L&K#E|_~q{`DS4_d+^R zSD3ppx_Y%3hrUak!QJ{A{F}TV8p3U3?h*;;FhW=%(p3993wC!sOE9T^0Z9LTBlLr$H#L>;8 zg*y;s3vtLv>)OtBX}DEX?$~c7@-QYpBJ0}Bg>fNVS3}Z`;^^w|oX#$gGX&juG16ux znrD`V8Q;uktydvmlwLZ4e1OE6GuVoI+*qyUpW4oQyzzL?b8+2L&H*_RjtMlOC*XJu z6_AUaE6ho`%vOb)jcmeAbvv~RX_+%4#B4dtjn%%bY7Oe-TxA0;*S4%hw}xBTMoB;8 zH%)nySw7A-dLt$-yANviRt1 z?{W?HUNDC6Z-*h88e)iy^WXi;{okd2_q*p0valed)-zFIwV?%6q1$XA0I8mq&R;1j z2M+Uxsir;-&}|aVD9jxg%iwq= zyR+&=B2~v0ES$cVa^c)KI0+}?267s?N7S^ny<86c5&$lAvrGrvuyZv_wUP69C6hsR z9eQtd%gf2R*-{PSYF8n6i*YN*W;c7OU@c_J5$QNNK{qRNz3X6hG~O~%m2rAD!N$(w zl?(5@__e$5y4yF(`+E7i7$ZQ3qf<373ZLujjf2< zg+Tn9z2vt=wBLBtWO)fK;zq2*`&3>NF`)Z56W3`S-4)yHh*kzs7U=YI8>dRv3g4_zE!iD(SKmvGt0XHw6Yb5`P9s$P88!VT)lOR=~9^pIQJBV zqnrIcPvO@Sf|P_qk1p}rg{94jj=+>D_s}xeYWxU#aAbX27C*?9*Wps=XbaIYRyk{P=d6h%~ zxDg)~Nja-(gXcotH%_rAkEa6#IJW!mzn`ik1MTXq8$Y{o=P6e_avSAWBn}wxrA^tDGrKof^N&m>Efy#AQv%{-uDi4=+HY3 zes<5wosN#fI((}dwk@X4PDdx>R57jO63 zr|d~6C*z*pt8!%XO=VlP=c?WGavhfCRrxld=FVz+xo933H;~IIxY}rFCzp6r#e+FV zNg}IF?O2y1B^=sta@lOaApB_$C6<5V0)E8k-um7Bba%J6SDURw;D)Oa(Fc z`w*1`V;XhqQFGk~ajA4>A1SF&dh8+s;R zP-lWVzi>7^onni%o_FYa(0L|C_qqslNG&^gbBv(Y=sX`xfH-fFJAW-btc{$2vzZR= z==Hc}oC@F2csTh+>fz{faK!R97}qAQJ)E3d%~z?}bm+!LYFRmD*NCH_VOkFT?p6@@ zMhelZb8@Z&%E`Fq9D#)sapUD^uQA8H5qu;1dZSzyo;>i8_Dw!H}>BH&}~{)5Dp8T-M`? zZ>VRgwiZirhLjU>GVZ&l&}jkJh&u(U0UB`I(gnV|;lEu7ci(+SiTfIF0`AT?tLy0V zg}3+HSd$ZP>ZdemMzQ*G2cCiMmm+SpV7KDjhMW6iHd?ni*My6%El{j?PlGTd?T}~Y zSfF!6{LsyaOJn0K3Ipdu=wzHWE^7P7KL!tJniqgY-Pa-Bz$6odPHwrc~@@szY{B=9# zZy5u0f)IBsdLtHp?yX~Ty0|)<#i(aDwc*N~l?iJlFL+11<=uVPhv)oAB<7@?griW2 z0Iq!8b46Tjt}e@P8&(dw$u_b~oP$<29m>eX$|*NgXV<}EWa|{NS^o#c#z{KN95q)T z+RD|$H9AJ>`vq6 zT=ti9b8yWKPUU}#qxuYW&~hXtlh-zZMw2e_EJ63Y7d$U?BZqP1IJrz%_YqRgDJw)R z$Z6ehaf^*ZW#iaRy$Q89G#e0_IT&{o%2_Y{oGbZn#gScyYmn~!^cXrAr^Vm9F z2iy8}i48cL>u%f6o%1CTj{2Lt=Fr&C?p+AkW=WQxOFxX;iMfw=G4yludI$><#m}t} zH@$?j@}jTUIci7B8>cxDB{MK}ZN~&!B=Y22>8=hmx?9pA&d4dQJM@jCC-FKHe?8hE z^lw0&DFJE%PI^(H_;DQ8qN{%aFKv>Q7%^; z`UXCwtz0%y=WNLTCmmb@QTqCWZ7%8KmMeOd?HD267UO0CYZR)zg=Qd2!)~Ja2kMZZ zIn_Sy2HB9apN1~CbCv2nV0h^g zGgTzzaC5W!K)StJfa{cTzJgViy=#r3)Am8jcfE_;?dE3A>iV3ZGez8l8p4UUW%^2A zZ|{tK zWGpL1bU@B?3_dXDiyk4#i#K~!t|zOH_kkG;;T{j-*mnhcfm}S?3?BvM+<0gYXBpH< zIQ^TkfKI|~B95rNhOu&VTZmIKPP#?&gb_hEJ`TXmN}Oc}$+|Oww0y1-&_x~%j+LwF z>Vh~sRg5bq*Hx-@M0}8OHfvOrtCuHSV1EeVey(WdKFSKd`;}4-SgC#5HtZVmtjT%x z-7_3H0c?s-aFLIE27u!4v+n>;U~3^=Pgars4a99P!Hu+U<=_%wTpuHemqUkV|G|F= zrwHn7J2d2O-mt2XaBIk2ZsP5~GxJp`hmQksh$Xp?e1ueT4#VbKYyh3EZYcLwzE`sm z;b^p4oogpYIBES;4wU4CFtxQj{Je0daBC%>qUlGAf@Zy8>zo#qhimg!C*^AAAx~)P z%dg^28^@c!=!SD-w6WzHKNrZEt?aj2$O#web}Q?2#kY_y`rM$-ka2*{2~gIwMyx*I3mZ8%~Z!Ef=SMo8`DTxEX*ol4!iyqK2C-*Ht$zJG{aGaB6Bc7}j(P z$bguc=t5UD&z57{W^VH^NqafuvYc$|CfOF_*2QKeyKF089w|w=PrUQT^}4@P-if-1 zkE@3oK{~`@>W2@0aye302XODjGszMrwP)PEs80e9keK)L3FZLE&mPjS?_q8&*_KU) zM%!)m>1G_0)dL@paf_AXB*}mdHEos7Zg1wgOkDlfc8i^s8|t?OIcRtD=1nPg=_m_x z=*`!EKBOzkFKA@ zq1Us7kz*zF#2?@Gxe+gWG4?s23~NfuMXtIFA>|gxef?84QH5}BIn=xPx%K5)IfE{s z%i>(uwZxpIb{)FK(UEy#N!PXV+&LSXyZlB-*JS}6711Bt2Hmi3T73{>jzr&5>`Yq- z7rLz+T&t&0I*N7;AL0!9spC#neKSd&9;sKWQ^Gjrs&WpvAzmfbhf3tzo(6KQ$I(C> z?T#>xqzvN{+h;}q+eBfGKwYDGgF{Y`sG6^ih3i^74hEy0h%*p%l=C9d%v4wEb-CPQ z)y$2N6LMyGIC71*w^T9Ta>UL=c1PZFghaJ8XY)1nG#R%v91-!|^X!b*^@2K4hkJ)fVZ`5B&LOw_u4b4?pKNgmOBHo<|hhB9{E(*l3NkOi*!eln*dZ zooL9p`v7>s+!p7)QJb#LW5HZ@TK{tOmYtmQU*}1hOLUx>S#vC#{kY z2qL&fvJZ<-qlq}0b5?bq&W`5^BNybpuE3jR1f32B8FjH5sq-~TA#+&2|J5jCa{)-G_&R-Nr7xnK6Z=@+n#TUg=@S?IGjOi zZ!+Ys$!QvP0MgAVIS5BK_F74%lw;o{N1YHO>Q`Lr? zZJb<8+!}E0;@ZQtW=YOdax@9o1;F)e)n*CdrVHVA;cX4JwDxgwPW8&1F*~d^Sv3Z4 zp_;ucqd21LIAR-p2>F0E=qBTiUp&t1|2{-3$kov@fJRESGIuz*zqsV(X}i;>YKyi# z-7R3jag;xge#;*1{pas>0anfp>h=W6-hudO{94!s-9VYDZZ&Mkp@Zs|hktok&G}%K z2glFde~N#-GS0A+ofB)Y4Z_`|fV`vo_g~V={hZ0FJ}y@tI71?{26iB>62vi9Y_;-H z%1w*iTkIU74&%)1Km0L(n?RJVBUapII;!B=ytJ@B=<7zGQg-#C>bVKQ&jDO(UQOLa z`IU$>5GBeP;T`%+wOsr1LpV2=Ak1)X{W`UOXz+4g z4n4@o#mAMCqfzeY)wnFjLAb2Mxu;4oy3A^v5g)g*aCFuN9o43^Z!~il2h`{aZq{fB zS8`yD26dayl3Ouuc35XfAgml_&d8i~y%Hz%jz~HL;|6Rn&sI8X`%q6;FMI;T9VaYg zbzJtpaE63+ST<>Q{IugM%{^TbAOvtq$e~+RA;@oU{1)B%?T!1-*Ol0S?!c!%4bB>I zzx>ttzn}l*XTg_TLl!p|vi2s*WSQwP;Fe!wxcVBJAxOllu&dInw9~{tS3nEV_ z$+@|OdbKFWN95R(B|vT-%=A5r@~XtOA9}-8#8EjEH;^NZm6~o}x2zer+smmuO4zIq zbT-AP3OQv%IXP#OZ;1h%nQ=}Ei#pT(*mRpoY;{w5@VSi%s$2`<=tw51=GX;M=lqA? z0VsFQ$D6q*hn|E4osC+juXt*$`wmLLsfV-EO8U7FXFOqXas=6GF9+HvF>!N!t3$ZW zY_$lNN$Qj!t}AJa=3;&uIWsmc%W<)Bwu#+-EjTNbB(u+VG`oKJ%X`mri;T0!Zc|7!8Aq$D4MguQ z{PLF&tgvt?TkiPBWLsFu4UmDb8u>$POgzhI0{oo6B5r za9d)wip^6nuFjEs%EKe3gdDC?&2Zgq; z5%%@4HdGhhDUOO@S58T`8^8hHonn828?Wp)Xz|>Q<;>lmac@En{nqAU*HM7S)b;%N z!@vBcOloXFqVvE<=3o-Pd-#|7wRaTfNLS)yoGA31NV_rC`2<~~?Xy)NTtToWtoQzk ze_W#FF7Q~n`r9Q)SD3ru%=&?&`ybeU=l%zpa{Dj2&DvgWfm|`}^Hzc76tt(ShN@37 za;pD?3v|wLWn8uOu{oR^*`-0Zai#T704`5TAI`xwZCg|A_75ug`rLE5GO4XkyLs2$uad^_565T--*mA32&GX7 zXPvhVM!B^`3c8^fva^~hAIit2QF4>DA(unIX4z>J`{w9uN1HeW+ zX6esB56p-hzyoU#sDU*4zrVOk0nT8ZoRe@Rzz4jbA^RGdFJTGMhIBYP38#Jq;S6S} zzuKFvs)3w3W60Hoah{XoG%#BZ`wMcc%>`azt-b)PQJQByg>T-AWws31N zXJO77G3FQ6|D6ds-61k#jk$i;yj#< zs(2P9r{}y3brZrN7w*1x3h^|~s2^~0`Wr6Nc~uNg2R{JFo%L{!HvL~BZqOZbLO`P zb#l%s<%oa8%{Ald9)$fEIl>I%GV)}d8?E0HapVZZ72RmYdnf{~laEAy2orX0a$>(?(qIacNRj=n~&eB37Dz&BVhy1a#7Q1|#9~R?;+=4jE zoFm!W+qO07$eyMOIPyp{Zt-xV#mf1XKiiKlf5rDDs4F+U&d#~nn?DwFS~>DmbMEvY zj%211@#R0PR2$zYBE>Ei&F zkP>kXIVq=_bJ#k4+`_fL^WzB0slnVClf7V^oRnidPU-?*O`LiF79+R} z`G%@*)=9d=NBGg=<>XutXIWp}C)J-s+^Co3=#eF$8#l)v($o3Tt<-3ncHip{B(qgA z(^Y#1a?LW)VgS~JoSY+58gaDUv(}J~Ac5Q9O@(u7(#6jux+vL}2IOeu5}%`y7GoFh zUel%d<}}s9knb4DI1B-3TdW*;o1><8HRtM%zP}0NJxV{vUh8tl3nSO30(qGv`)5ofS3dq+5cFcI`Uk(dLaf zhgCJpb{qtooTG0ehvs$7H%C9dqHf-#@P-)A z3vGLFAgA17 zegAS#zfO|0%C{K|;2V(@x^{Ael(USNdsi0bI@WHkRa+2aP*o#Vd<5*0UV->nX9w}bW!uoW_7A+v6bi=aVfhet~pjRg>Ee&XG?j_ z%U<*Gq8Qz4U>%hpCrpi8F>VYTjiGWbB<5a2@Tq^NX5u=Mb0>y!C+@lD92QRb(j~Gm z*G~%WcRsX}GonmbQ$x7getjgm1F|hi=;p@EDIhmHs@BT&!MKTNZmL4IadAq{fj6^D z&d9Ad9js(7-KVT(peX*0B*a&lHc4jbY7uZoyxeODtz7PINw`^-bGE9Jo5+sC4}Kuy z1Q+`1#ZP>-D90TL-+on3CAtjV&;`GOa>z-m_aoq5-|0WShc+6OY{>m~IQQl|>wzC{ zrYNU}WQ!lFH@_d&`79Ll7Y!SdToBHcKA1#v3q#D+HCYL#+Q{`bhL8MQK-cZ>E5^C? zfWTb2xIZgq&JR4$jJwq5lrJgE7&#B)Y{8YRvOS5Rf0O( zwx6@)oXJ~6oF$~oDLOL>*_v(@Q}_;W+5Cb^Hr^byhJHO)RU>gG*;D{`gjfhi68#Wv z_2nr3dOUi&jmW_` zay?VEJFHbfOnborQP#6<|EW?fXu4*L0%>aWj}1EBWAnZU7L@neFPfkCRw~yB(a%HU!ndigPIv zj%GCI2r`pb6>GQBTP*U;&d3M=QVqdoc9>l2FkRiBLp zn`}ezZvmWL2$uk7+q(^xiP6Vwu#P;jR(A(# z!u9cy!dni=UF1>fb$3;A;pD#h&8A$f%w7I5f^t{hNd-Jo!Il|9%qXz=DP zs3xxX!OA|6)5@{7f8WWUpv#2nF8vS5`%dEVz+Bb)j>5F%BK`hLZ}t^h>|eNN(H!e( zX*N%5ul9lcm)yu@DCfxNFE*uzrl~P;HnQQ?gD8aS9A%zLcH418&TNHomI-oGVl5HHrde$}z9lJg zE@lqGk#0TA>5;S04aqo?$?C;Va6E*yH?StxkcczTkJ)ZuS&r6XSgH7yA2swOoYJ`o zA$vakS-|0nTzbRA{bYwiJl+D`PbcrUB-?6_LRDq;4A12fT1{P-L%js5b8q~!!8tI8 zB-$XZ+QyNNYb4`HWi7_#$lMBa#Aw_c zGgcdQ2-h>$EjQPQ)6dv8iTv(3|P13oW)EO=~jV+9-($~ZZ79*5(;uPU9ote>Z1ntx(aY#25&xd33)L1 z#r+P@-gxj@mnY?v)7EFhGIEn{HcN^3wm$qZkCbt*eC=yr`{Ebh;dFKJawwdGZsKhK zXPCvfnWescHBX&TnWGNjOxqwXM(*}cObX-ro|ftwyp4S`)UnB^Ax6^rNtur6y6WF- zd1mGu&K@sU>vFMjG7iYOE_acQ2GEAC+&p^pEgx;^+wuOf5ESKhMGZnQlxY zc8Q;9_nLF20*gooN5DrQ*JiHlTpbE-^(O0_C6RHYCxUyrN-WE763wVg%#_tT{EfKY ze4y<@TwZsRTM*SkI?DD=>z5|}@g?#fadB(R&CuKdI&wW{ol(~2)Or^pfp+`3aE?Z< zCE)_Q{vg`;s_B-fw2ZAA;AJS|s@Nu)aCU30QRikvb|bh2dEpAAlXYiYk=Diak{pn8 zRSw+2xc9y9eJ`%N`tz_QtegvT!5q1zp__c`4F@Nx&j4`mdmpX6oSci7dwK5TXQJAG z6LDkTZo8psL?NA8pBwoYDdL!^lIwYDEL+}AWi^iZst)ce>@+~RAGeib?*UvblUDc#<{~Mlgxt-3l!s(s>7MGb z5JV5*{KSgf5RSC@A9R3#%+$?|03A=TI9^vDx#9hxqTK8}ATURkm3#Gz z;hgvMMmsno zT2E3bX4sY}*$>|GOiZe6ZQ%^z*3FFm?E>802>~{3Sk^hD%a`GtnazioIZ_`-UIcTh zcN`+X2D#A5rrYJ8^fB7hnuB)QZ2JSfhXg}$#qT)=hXM(<$#om3u9gyor&XhG;PgqO4IA)bMMrf5S$HtPSVw~UoDTC)Ms8>|)3 zj?GmlM~b)KG~~dX1S@T^P2C(_CcWO^MuGbT%i%cjW~GBu4Y=fGb0tWJjU%f;xE~hd zNX(#ThuxSc-RUH_m(DEGP6?_$+{?KfsOL&WJ06YrGm;TJX)%pi% zg>vtYm($9TadJ^6uDQx;#LThLYK+#W=BmrAb(?e@;oO%xW!y;2Y30_SOYG*Hw^)hJ zkZyJ#7!KzGy7Zf+MrS)}^cMTK&>XY`+nBi-qqsW@3gAffnuM_1 z;M+9oF=Dd_Ihuj)HWhFC{Bo;c2jrBbgy4FpT$ttOQ4VF{J?)P)- z4Y)Pxj-KS*cqcE5w6%M?T%)J~cM>DV6M~9ye7Fzw`%&3sWl#cfJ)68PgzT=%I(2C% z%O5zZe#Xod0{5mx`MF3Z*ArHLD%MmW$3Fv9VqH!r2j-R;>!_Kw#kv04RM5?awqDkn zqa?ql4e5q)fgBmk1$5W8-@N}10=#t_(lJ{#9nkNbvP!jrTn?2?WMErs*haSr`g*r5tn^n0b+ro8i4cx4^cW_yQ6LH;1Hcgz2>oFx-&sEJGgxg@;-CY`O=2D`Z zgKLCkR%)FO6sk!??dC)r>g@-05wWWJPF~J0=p_}ndb)LzTbc&tkDmRld3A5^L(9*`*r&`j_3ZIH{O%}^I*J?gtIGk?~ZQGWo!o9SP^!$_YXL>D#D=qk(wbm1J=Vg*<5RRJ1k(8Cw z$#K=;D>CaRmw$X^k8!_&awSb2Ni^ijz_C+7Dtf(~d_&C%2!)zu6qU8N!q}#X>jZA- zTb*unq1aQr_+)l;4tp(H)$l}lp;WlGS60Sq788=}@0a|C2od=4L z%M<1DOgZm$sh+A{=~E-ieDy0gDKbtmXt@+u>-{I|&Gh%tgP!IM^pS8m^(*DHar5~k z2t(4Up!O4T+}y9f{X@QNm7hDwW6|n1n0&hg-I{WAzxJcnZc5)gZPJpi++F{LuTq5~ zPNIbzj|FgBb|t=R%*DwSCYy4lkIaO1Fc-+}vU5HzohUOG&JnHO6Ti^WWy(5%<`RUt zO}d$}#?Uq9OgTp(q8*kl0$v$x89ED$L;r=Hvrc{?xcfqQ7b~~feWu27c68)fKX$~& zZ4KXIEkL9(^VRY2686-3UlPg zXcV$%ro>ubmSkUUrd4LJL#vxx(IAep!dsOfEfC99{O;+9r_GVud_lE4e_^I$o6e^4ZY@L=-aqeW_Z-9oLrejWel6MiblMCLa zpmueOW=yF;H{Kx+=W4Qy+J9Xy%KiQ$Eav^55OV#-nmRDDg}4!L3*%zt-k(*u?5-L+ zl$AN<${d;-5Gs&^!oTQf4dZBNy)i$?g>lIBwz|C~ z8DSi1${9O!AAgCgiL67SK3VC|r2?G*<(>ituDl$a8e@m}*o$s`(quuM!(m+Js&R5q zPPK~**c?UwTp}9C>E^NlL3Tm2FxM+{+4DD z?wMx&g7Xv>BQCNxl|x@J;=|{Hogz7kp0UJafr$JuCQUFl(-|T7CoJ;^&%V%SpC7 zK^EfNh=}`2Z7;B}#<&n?Bh*RdEiRVa?i&-=CBqHGbw@Pr09^xa0>Y6*aqi8gsvg)W z87#s2NZeZfj8t7~na{hcl$xyK&a#Ud&JEqVgn_xZzf4!x&nD@oa|$>k2TF|AAkGpu zH!+fPebtL@++22A1G;JxYZcnW+>FigS(Niqucg!cQ@xu+vqNH4LGd>M}B>l5?n(K8x;r@;GXnihU4HY{)m$x z{BiykCT@Y;^7qHa@#@0o*p-)~Fq&-&N#`WD#8!pE%OT4aS&%V=xDTJuy> z`$lKapa~bi$v7LigK>j2G&Nk?!MB9jkh9!IL%0~UEycIZAVb(T=jBwLBe68*xao!J zxZKI3CvQqP=@vuBhX!3>$5k*Vs!GOj!J$V$juO!2wyLK@ellxv3_3_#6vADjkk|O| zYx-HAGaGZ3+N#(VHjW~|Mh|TDg|*qm$fm>0IT=J*lndPcNl)FHwZ_Wu5%$> z$Mx0HTvq2=*DO72y+++QH7DaVaa4+!Q;cqV>1*emRvQ}5{ef&lM+e+c%51%M?3P%w znp4`)O$s=vHg#Ah>cTg227*pG+E4>-7#G6L4r`noG+Svo^ZQXB75k0lfxk{QL%0DP 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

&hdepF$Lm`Pw+kLRiq{OkjA^XX@1 zj~g3}aJW%jAq!W)7t@@5z)FwA{KJE7H{BqC$hpD{#C)}TU^pGCR6Oh%Y9Hw8BkjLD zv%0ugCG4*F2d@@3W@b|JQCJ*}(8>%j)8Q4W8OFg=$P9_9On2SA$Kl@W?)_PMQ`9FH z(I1^kg^`5Tjt>O*q%$1pY6G2uo9+8GV`m%&yYc1w&{ffKoh#^mI392fk`mHh@b<{38*!ytx<(K4c&INhEW&W*PM%#D029 z7fqfuU&cQqAc5}`Kw`4V?vnsW05zf&?+fsxL@V+nE1t?hk^!AGB{;JAI6Ymp*Zkax%_gIV#sHk$FHffD4qmNxR zbGT87;(|k4^W#gw#P3We1-W&;)>8bzbRtOm?=x0Sklj;HS$>lNhs``7u4RHRPPS{w z-1A3ACMs12vnj0BG91)4r(9g7#3Ofha=|<;!g(WU&Q!hF=1aKDK&ygRP>VSoXx%Xq zC->4e0-K|wxG|T2(I&2ES_w|3rMIx|78MLG6vgC(8x7=l;1Xr1_suo2-CiQ03R zMraSfCFA@m@;f{Ed>+tgo8td`Dmra|Bp+=~W|&NVSQr!Qlzz55(n7cI=`T0fmh zG?P$kIOCgXk{i*8KGjr7l1Lnln`b>FJTK(RVQyagaq{Sw_jE@X`R5!mZ_)8sGW-V5TCTmrRq8nu;+IG_+`j%I! zt6@Avyu*=7gs`wum|R(0@mGjU)x6P1;?LtB>k5@-7U$O%=L>@rQp@wJD)ExqB zBIjYv4)9HQMxfliyANmY;?F&Pb3DVsZPk)+=YSHI0TtBwo7$cK-9~%Z z=~kR7%#Dt5pwm~U=$P_%MnFr291R8eN-R8EhNuzUpyT)Q}Xy!=utrLF9#> zQGvDAcZEwdD2GdRP1lU@?m#xcpO{bpWP>__O-H1lM* zrG|OEDF>(L^OW7<%`qKP9U4l&H2~kJgJrg$$Vli|MZ_}At5RE@=-0b z|Lo=KZ@>NXOw7qjLRi-9Fn0R_PHk8=II#HSq|Nf=_0_3n*g$nLzL7{K9X<*kNyD2g zL;Ix%$vKqdz9O)U$CvI@w@`XI`sd8iZYtre7nAFy%qFpE5%#i*e<6b`$*X72Up}ek z-aL{hlr-=%nWtMhEVHd5Ydlewc*zW%8q$X+?DT1*)j=Gc6x|HoB)F{luWb~hpsZiN zR^FQyxe467PHGeJxom=7KZ-tQd{I)=n!UVWsC0!Bc7t7J{G7196C0XFVclS_r2;6> zx$evbCaAH_1%Kqp5 zY&gI_SWLTsW8G#JC}cO~8T}kVjMsBQQ={l;HJ0?c@8)3SbB0M(t2mFRC5^Wpn&ycV zdnLf=9Cs0JU%LF+Z-Fi7g?fVr5t}eEF&S!iK$sKV z#5kNHW#O1~80{ydqPaw!aqSmj+xbsund8vgD`^cYSknI~?%WveAS+m1Lb(?wXtl=Z z!~5;o)6>U5PH(60j!%!hb<@{T$OcHrk41WDLy4Ane4!F%oE+y09ECb45)`R|b`NLY z68f3me=u-UskA{T!yVLEe>f`iN@-ICYCzXc1bz0mICrk2{>=+-Vc6x1YMzd6;{tSI zXa7d1;9Z=LRijiLmb=?;sshj#UfbJSt_)sO{CKmyYv5A<@W8+r>BFPKhBq|78U?N_ zznF((dxgjdK4-;WSP3uBZ_G0zK?!D{ZOl`kiR5_q@%^tK-@kwN?n9z=lZxY|4AQW` zU!E??QjB|nvJv+{k7ScCnv5K^R6kH-_fBPSU`&Fb9#eBbFwaxr+ooL(?{a>BYsHG7 z`?)K^ey)E$5K%Fs|#fcTP}IZBoi7?^I3SZMf(pGDy>s31kh z4Qb$&GC3xy9i_RnGaD0m${D^yP+{BCKi_4jVQDG&X!9VxLth*NseiE(Tv9TAiE*!S zT7fgKwzgj7OGpBMwikc?hD&Ow4AO!)lrOPbN|~-A!k>A*(i}C-xp>?M(X{0ZKXn1B zIe4=z%HU2vGf0yM7r^UuyHQY&WS7(ZPSs4tv&nG>S3Dh;deA7p(8~TB%FzOBA%}te z8xzyxSE!K2m#<6e-IuiOCF4VUW#V<@Ct;j(eCV>P^VUQnmCt1IInKPj$nOM`6GNh$ zJ$3rxS!WY+{CZ18CjUx}jme1g7n=4#BCd65ubXeORbO{bMgq*gB20}#p`k)$Xds#K z>XhQqB~ga)=B_G3C%!4?9l?=f@}2cI;D5?9iWmqssxN`EW#9%xP(cikXd?QnNp8db2W7X2=Y2wgn)1Uq%mslLz- z?mBwfu->lToATg3{oLg224G$rFG4(ox$~Z`uKxb3T@mEoNgRzOb^tj2w3WbycmCwv zEVz63U-Ib4+P#1G`0i@WTUSeMOcHWh&W|J0Lmroj04Fu+)2|@s||oObBwL7t!=DSZuayrIO-uqm!2A7{y)2TufQWWDg*6TyZrvj z3WbHo^J#6t2^UmkrJRCllN>FL)32`GyZiX?-Pd>D-JhkG1TWI5%2Gsl8&q5w;0G`g z(Ul6GC%<*A>ahd)s;~Vp?l=muaXLArtxY6zB=9^GQ zlForB1&t2Sv(oyE~x#rFC8pa!IQfPKMbLBX;;MEFD|8Hylzq?%s@x*$Y zlv9_yDzt7VeILq81!6Lo17@TE8RL#g>YWRzN8iM5q}i8{U8-eEVB^)dB*4hWu`_F_ zR$Ctrup2c&yY02kN&FR&Q%IATTEfhJc4)#9GutVq^qlDIkb+xQDl7WZXzG?zxLG?z zU%p7BOt_Xpg$OV11<~eKF#M3 zBOV8AQpzoKiUAuz0c7U_B|MJsdGk)uK4x|z++l2-C$Mq%ah|q zNIRwYp(`HRX}bwuQ)!60f5fiXR~HLO2OuAb5U zG5K=y$ES;w z5PU0YZ>dCAXCL0b`}LP!pM3Y2pAm;DpfN86tNw^yylCg(#SC$S!u;OuOtj~GyO3o= z)-(O%VM1xur_RKTyUc`_{VoRzGs}fq*0vDy70pc8aG?;Oa>J)o58wzwDtZy6iMljj zS8F2c3B5HI+?!cytj9fyC-)O;rP*X3u&(E4Gt$HrKHUFgPwSCnQaU8~C?PZy(~Btu zNF@X=85@I6+U2!8m(OfI`|)*oXd~x~d6Q3bY_|DJB*&jWd;Ri7vJ_uW?I)-OJ4ytx zCFUa16lYEF2G=CfE?2IxdA|r<=+fuoRa~9`%32F3P zj-CEbqyTXAyg2R{Po|zwDQ#q8it=bKHmECW@-v%oB)5(>Q`tmbEX$FU+txTMzMs{Y zV_{()YT(=<{%OSK5_WH+gEB}q7*nq@pG`InN7Ov$6yz3SNqAdMc!MS1#zxjLj)T;#=wE|1=%eqciTF0XEs5q@yfMCKKURvM1X9!7~;XPB`JMXXhxSf=qJV2+|CJ^ArO*J0$0XW5m7}ZV)r{9wD zu>3}D|MIW??(d9G@B?U>8->@V{qFBxr^M`_K}P6nxpA@^S18+R7X_Rng%3wNOjZsP zBfQ_*W8quXOt3tQV|#I-W&orQ9Ses*=Sx>(;>#pbJf^8)}AKq==} zSzTK#Ko43r{OOgAnYE3L{T$QfGpl^8r;pOB2hJVb-TnH@c`d=w@-KS6^f+9KA)BBCdl-~M)r@6^!JM|XqMIa906q5u zF{uFU9x~X#j;va2>nIp=P3>$wf*dbjvI6kcR>FtNwO@-VcUVl3I;RB8Q`qP^sr(no z5|lb3Q-BX^3L2Y+3)OT34t3C_8u(f{ZH%SAF6~Q}vSN+eN*MO1C531E(t7^+^Cz9O z608xndL;l73D&}#eT>N->Vl-K*0qfg zwn|Wu>b^80BBty{2t!!MX-u^UqDAul+=6v#IWZLo5QjHM>}VO%OEuF?HiF(1YD`Kw zQX0N}1G$!=&MT5rQR^UG)ZB4R6C<=ygMa;^j5}vpXN+GE|3)yaS8f}n1y<;EDQiQR zN%I4yRuYK=-z08@a?}_QA!+~O6O%FctiPY!+(ly&MdN%?ll&NM7&J^M(+D8@EDJC;RDvV)9kP4qhHwfamuupkGk*(7M zp6YR}GCInW?h7FIp@BMjUT#dU?>yy|xExIfR-(#Q)o1r;q$6=3LQ#{=S%5;H_3eD+ zrm;R}Pv>+o-tC-RUd|o8ezelpRY0=1LXb7z9P#srdpRHrsg+W+7$C-9u=E|1A zos%@-?7>VXSI#Q=cDbL50cBXCYg(EecK2DNle`@jRjZGQ32;ryec;E*uK1QFu8&X9 zB=Vr+&Vw6{PEn3$ybGOVQkfG9Nt5wALsz8l(K)UdJjjo(K$~j`!#b8K(MZ&kSoPGGDOByU^ZGKQS)v=- z?sc}v5bg|m(9`>*%!|Mh!Pawl}sopLdA@AUNeaJJYTLK6L~ zOQg$QGMCwK5-&rIm^O!bg1`ls96dyX}>F@K*c*K}9J>J|z@u3iJ+4d8TJ(UaTa_3zOOM-)21Rg~C9gP`O$N zyzO?zlb+G(bbpjDX)hFaC_R+)d> z*H?IZ@5>(tKfc-wS?z$A4mQarkTKY*v51ShUsib=o9fm*7K{VDwqWp1FAi3Dt~>3G z7WiVemn6h-!&_P{mLRTAnYkXUMYh(JR{hk{&fer;j;(C86i4_BWXl1bX8=2gbgKwU1=QIU>#Fnb1TxQ(? z$zmgErz`5+NbN-Ia|b1F7n8T%Y<9B8o1s}DI|wIo zycy|W5_Bk)V7Pa*(t*}sabcmfkSvwtx@Orpv#^sR30Ow+?rdq6pKGr z^7`sW$IOOe_0xCn-@oJh9>TrDXl1LjRDZV4(wmt^lyp_sSrDq=RcWYU8xiA1-dJA}hR6UC|Il zeZJ6jwKC8r(hcCs(b#tH`|lq=-kseGqc#_26&ZbmF*UR?vJf)6U@Mh@%F4?8-S77< zS{IHZ#z9BSXh;of!L0g(2mE99-2?M)(buD&PuP=y$-qcuWD<7{?5nr1J7U6xScPn1 zECg2R)y&dll48+Lu~r&%OXLtY?*Fv^sic0;Jkl$($TK@p%us&E6-m=+#2-0x1~pCX zG3zjjYGk3kaiCh;X2A1!_vqQyv%h6UJ&-#*eu^US-#$&o|KUY^BbE8aDrY>z8YjcG>bqE@dnXW)CL}KYM zEmic{q?0j1L`LOvsSI0nHpd;(N=jyV$PJh2C${EDz$xga_0CW(F7HhkgJXHh7dZ?i zP41Kb`N&8zF*LEoyBLd4X~8P982WfsEP-tX&Mo)?q`D^PSaI0tH}TBJ+>%MC;oGr@ zfm9grm>s{LxMpYbZM>>zwZ%9ncWr37{6G_Je-RwI?7ZIjz^DE=E#Y@euRA)3+L+Y+ zi@7DO0J{R{CgR$1lT*M-7fk}kbg1RZ8OX&mw0YG^ey0LM%Hl=>y2UqH56(Xb9G^fU zfdI1e($DyE#`+_U2>%mgAk}iKaT`R1)R1m_H3O$;2F45!*vA_7O;Hg2g?7uhpD{~4*)Lq0a3uH>XL6fc zu|R31wn+J*zF1wQ6D|s!^_{~S>=*IntW_3gQh&S`i>=PgcTY{EHluxmmHF9+6j1Lz ze0=x*<9qjJ_BQ5cyl=hp^Q)^Xh0w;l2gJ#l>njxe_rCu6ph5|`z_Ob?^04+aLOK@F z6{_eJ#NP{Vy(|0QpYV%UwBIy~I{KdR{){X#oTtweDf{Kn}7WA^{dRz`U{-5pnrXS zVA+1V3>(KC=s^N^od$dc9c7`>ybjP_Aim4fJUc z6mXPk2xq?3ZW}y0zzI4rv5RFlYNC7e&7-Xh1R)YcT{#Cq_#g@{8uFSmi)CxxM0RB% zCV7HnBYFAE{WJ?U0G!oF2OZOnvzyvcJ){Iw6LQ$kI&u?3Y`*!6CEqwtZCKwqq*c~d zrNH6RH%+`oAnce<&LwC7)>PLx&K#*ZX1pFG*M006V=s^JXCqeja^-O3_?D*==?Pba zC1H5ztrjC)xP16Z8>L^vx z$_n^P@>VA!HDqANk$ZvLRdd_ARys3&)TZoQ?=b8onm_mHxl5OBO9u?U&HV9oooi5@ ziU}`|7iTISP0Haj z&6I=t-b#3NrF*Q`vlH)SMBcl$HnV+qcX#$7uzvjbVEf_P-r7CRi!0@OGkze1fiFVQ zhxbYz<_{QpT|90?`E6>Egr=@2eoBPB!oyYyg^e$NRIq8kCa*M{&q&8Su{z}jyV^v- zzCy@9%HSDki@xyw)}yV-0adv*;M;eROM} zCa9>F&|adaTxq!v@zy-Hl5%q6KIEXhxel|G-@JOtX(1>JHjJ;8m~>*U^ySV4MXI~U z+Xuv}nau99m)M)5Zz%NzowY!&ea^LLSG6kUL@w^TR?~bZs!(5>)GCs1&k3 z&CNNSlhfIqt(>FdXM8z@k7shjK42Bk3H$01fDYbom_{u1WIA#2LU z;mGM?h{sOciQHg=y@+_3!F;0|ik`ZQ>E5{odiP>#7e;plrwz(=l6^$dg}TcfUom;@ z0i7?28>ajq%9-}U*whqZGvB*i>1DQb{Y(yn%1p z@BH8@dC6#|w14GhHN-f4H*T<$@Ww5mOLkAI!Q6aG3JWSUsDdj%|J)z^(lw`sFSYNE z3pLQ$c=@I(syJ3;%#plsfU<+t zr^xCH6v8x{)$7zKOILCF-k%`O7Set#!sjzROm{?09(Z=)1|tyKT00_+}dQ_r=8j&mkuBV_9Rt^)#q{IP(GhW5zg=Tbh|ymN#B^{ zdYhJBPA;sK--gPog-X|G;RTUspJ#q=?crm5IS|JIvWD+=m%Cnbs+OSesC&s`UkG(=tLz#kzLl)gX%uKxo@RHiuHtE?&^?@nI&lrTxt; zV11I$|HDo^|NPA+Ox)R7U(fG6d4?KrhG!&BSYSMuS;!{vi`bMrVq}ap?^-4^UeqAG z*}oi5A<4-dCAAmy;5k^z(Tyy%TGcgem!3n@1_p60hmNS0-j>8wrk4`t3r}dqN?_w&ilbBz?6AXatmV&LxqeNR33TD@rQtL}g#I1=t3(WH}#~YlU zn6P21D?v0~WYaVwe=et8)uG>lOB=dm^4whk7cL*2JdvKCX+VNG99oK7PKBzH5bVT( zBF?1$f~Zs3HL9l~oNSOeAcHb9-`LF&gK%eCr;*>mL^&G|s_lacfGGDfNQ^Xeg#r9!`|wdQUdy zj;NbgDMNj%qRg?85;ZnGiQ@rxHi~Nb$XFzNd}^n=q&HWqqrL>NaBux~ zCCYU;7Ut5QccqK@?adSm3+oLn(XZ1s=k`Motc!5-7qOex+NLHaeW?v^VR_%*H`YGz zmA{>bg%c7 zqZ39}*h3w!a8;AgMwBUv3<6URX$r0M3!{Y)qmv0gs94>o6U{Nt^3xIQ7Vhx$EaeDR zTMh4&rAXE*gRW`=3eb32EQwl3EJ+Lr&`tY>I!3B6ZucOwdAPfK@N_4?`P{aeWtM`V z?W=FzJkL)jmzI)Cn=jGKWO6lmM@#%6OgWXx*BT4U41T!~yn|TO4z>D*e4Eyam5Lk0 z0C6&Y4Y_!=Y7Li7(owi_C2ms!6g$jf2ripZjm$=`szbylCu!m%eGyAgP-S7Dg`5s9 z@ghs9fuvrXH`@L(wvY<(NWK}bE~8dJV*;Qpx^8OFRncpWC^e%lI?{6tK4eQcbqwq( zWHxAPDVSpt{&fuDLfZV{EsHs3O^5Du*p4>rwiw4H?p()%PTsFAT%Y#ex?p5PXd>%i z2kj7n3S)Hfa@IF-fjD&H`Ze^~?u=g%&5{hVe#N)CG~Vfeee2pc>k{Xfoe0*9r~(`j zuE<3=mk~ffSfI1V{x^_7%#x+YL5`8N`><4H5ofK(X)q@}2(Do84d)Jo*)2EvSN6D7 zT(y)F@bIFHB$J+d%F8G}#~BmnpdFA?;}ea+EMqWAcFix_Z>sA}ooeoD2~9|?>e5*q zng4`{DjgDXgl&eXR5LV%YFnzD0g+hv!ntyfh;!{%A)LMe1y*jh3255(s#|klguUw7 z^3Ja@!$tIopxb14B>=U&^T&@*-`_iZ|NeyPgG#K&E7hu`-NNeFPp^2H+FzMJKA!Q9 z6bgftMmVHgl$QFKpIp8iuw=GCjUxo_#`i6ZbxHG0FA5)>q(2?*gKOsj+J|(rZ2UpEG2~Y^R=yp~ zDS7ALRw~w=`|h4RGzix+g{xlQ zIBM6vMJkAsdIMA+Smf1*SEtrR;95l>9fg({>I%*O*Z;Gz-L^ormTeM`K%He@Lh}cV za*=J<*7ms~B}Ak)62`KwahgkWyWb&oxw(6|yM3IWt37*p^z7BE=dYfA^;IsvzVyw} z^PKN@?iA_NmMk#Z%4aRCISvDZ(x@+6&mJ9UTtiFYsyrvI@z$q{!$B{6e%udtiu@H>A%=$8ch9M~t zwFIYtZ9estAZBLsO==DgZi_P>+*2I4B}U<8MUfEpK{k#QTZ0XUownzwl$yaD2cl9~HZgwv%8fhYH*UA$RYN%rrt%_Zy15vInNumN-tVMK*g=~HM% zAKd9u!KoH{GIl6U4pVrrY~z}kXf>MjI2b20F6JfqjML=J~HJIf&n;j9h;SuFy zBBk63^%|0I;kSDyb=el2g7 zAR^|z3c+|{UNyS7k|Mfk#n+grH*>7KQF|T4+YfCxE7hWFSaYl`#Qp5Zj;y&);7sF;P;mp1 zbd-*aUZpD$$BP0+iH$Ib)4DJGqe*9HptyN@vVC03!G^oXxm0$Ch4tT{R{4DAPru4- z#h0GEd6RM7xf6W(?>~Njbo9-W&8JJ*5+tB|Y%a5XFq6tIFx{UBbeie{$#4w_AWs)? zEKtR56q6DoDs{mR;QfnPmL@v zL?ICe;q<4%nY+XWG=^!{^EJ@tIrF%nD^Uf?#2;~CawvANOuvh! z&LJ1g9b|ZObPV6Pq55^dwAQv`sS~5R#TqYKo#elM&SZe$5pb$b*lVvc~$= zu7Y}ERi{1zUFay54U;c5tU^>-$ozb!G3{+o_d4b{bOpjVLee77i!nz ze+}1~Se>9X+O0vJzWyfVj4*JkF+hAfTdM*P#(mQC4U#g8!xuS3w1@G`LP#l{jhitp zW$Y*VN2;6T<8XjvwMKlse)Jmg-y@Q8TkC(Ce;Ukx^YZ1B={vQ}AO7nlZh8Zjx(TAZKMwgt0%diU_r;dbtf zaS2ZR_?)N7#?^M_&|WeSZ7$L`J#bvJl(PqdPRmtm6FN`utQ2;JuH9Kr{?P<3*k#)( z*J7M#B^4@~2e0+pPlaPg`GHS3%`UO*bbKpu`*MeADb~Y=9xxwK9MY#5CuOLe79E7K zjW#*}Om!&^P_8~gtEcLb`||xiet-YjVzovU;P!t?OU#F_{KL3M0 zch8v{r;w%J0uJkt|Di=Uil-v<#ve3rRB%;PTyRY@F-n*UR0NiU&s67le4u!Ed?3K> z9uP_5p~a7gNy*B+JbJRU9(gDU_C*PfHlLX5b8^}gpi7k1HT3XT2hA|pUB9Jcz>Kut`kyLQC6yRp5R&?@#)?f`L%ITmt zt9WP40&dD))7k0R2$EE*1#4T4Aan18qlr1uAwEaWFSn)4z6z}5-jevQ#OjJz!5k+* zR|1TKu@Q_)h6oL`JmAydVX0uO{itla)xmnggfloHGLA5 zTk+TUY}c+Mk1mu>JkW}XM80_8_ALhd^`XMt&d%R`^P*GoBS^i_6rX?K8oE9-4YhGu z^GjKmTBDIWfO5^UlU-2AL1x92G!4jYVa8bN%BRiQE{^i$OvtLUMhvrdG?nKUXaihQ z5#zSo=q_p1ix?9y;{YZ^mFd!GFzS;iq@1LZ<>*v>6}+7pu%$j~Fx=BB@_ryAaEU55 z$w~d+@JXoJ+U%gIj!N#%$+rREwCctk8_^0Ls;s(i3<3>nEKOdXn^tsXwxeo4r4zN| zYFGQsNd4sD$?@7A{#u=p&E#GVIU=4)wNoJX{bTN}#{*GqX|0Dx0)+2u=}MB83pZB6 z^tBfY#%C1D6s!uHCSGk)PW$_~!x%locqjNOH|5Ly*CFEn!-j9>WG{7YVXl43ktol2 z4CVT|JpNeiWUIhTslPiqb>YG}nHhl<94+K}{7y1!70+BbXJJ9A__q4YS)^-od zi?cK3*;(329^aGj`Quq{A8b?Gonf4ResOViCB0JMg+Rky>=T<`-Eb3idyTMWy00+5 zxB}t|snhldAePFL|j6Y>0RBB*w&g;$kmm@vR9(D@^+k4-sU`8WOoeH^n zF8gp)f*Zk9IpHhvgwO349X5xRpadaZUL3;_Z!L3tk_&3?fE|^j>^5@hkYnHh1z<|6 zo0+ekureWked*E5qeol0%^xYezB!~|$pkyOuo{!;i zSa!rXCP~k6B^#MibB4pk^&&Sl4i+Gcjn_)CNjM41J`7k}6$qRx*w!)|I6Cz;6H+Xv z8Te@}z94eVrE)lL$3(2e-(q*}Ag2Kc_TdyQ+~(qVd{iptNG$T<_&Lzr`XMFJD#nRKQxrtkhLBQ%b^72ay<3m0IY?UB@xZRMUmlL^hO@neW8?H|F zlbSPR>-`0eI-5E`D-~u| z4Cj}0p~{dTfr#}my<8ZCPcmJ6+$3Ggr|U%#qMU+?hGw^%bwu@@_yZo?e7ln&F`={46A`?)IDG`a+)#GL9z{f?Y)VYGf>W&{JE7?fawiUn!yq7_Ody9 z%#28!?Z1pf1AY$`7eTI6Wh@b22xrb#Py3r54x@o2dQ=YpaHcDXf+{W>L?eZ5mM~|S z1hPwOm{Miw0x4&9?{4qrc5|s}y{NKIFE^?i z-)Zul!X$xcFatYtB^6cmIq9TJsLwY+*_56SoHwaBG4$_5GPq=*7KvymcXF`tBoXGS*^yw*mJ$BAeA(3u4Zf> z#?wMqWCTp6ydd8=cNQggBxtC?r5T}ew#IE5MXZ^MuHhR8d^yKloUwcD?!tpJcI)h- z<;vNR^|nS_O(p@em5k{Gl$*dSOe7wx``DzBG@`l}7!E;U^F`*XzuS88)kMdYE7QT? z(pTd?N<~BC(-IWLp)1n&qAo=0JE|-EL=hkE2^U&>fLSx7Yn81m=2Y;|59tgTp6NWQ z+CwDZ^jq@bN@ zf9~FDxvH%*(#~Mos$02svA*D~b3+m(oTFisn-r|d#Jh_&nllrvX1Lwt<+lBOo{AtR zzO^o_KW7iUPG2&W^INflKJt2w{oUE)gU0-P;Pao;Uk}Jx%*mL2J=ZyN_}zE=1w1;W zU-F@@@cQXYKO?Bz{wY|5%4)gmr?!PXb|9ETwEv3m2cdjhHIV|+L-KzYy zkM;HTwp=+lci!CY+ul|RQKrjZ9N@DZJUra;R`i0X-*;iaF0}@6fk9u@n|4PLODu1M zVFg-yG|&$9Yl^C0`%L9L$u~(Qc&4g)-=SAaH=a*Vhr_k75zHJKQOR7aAL9`U^L$|% zgJ*WPYsa)(P(5HAq*lagkI+3gL}&6 zK_|dd*Jfwb(3$vRjZDj}5|<~J9nOfQUguP-NaQQ(Xk6aV4)B?V68i2e=ZaW-j^&EX zg)@dvH93_#*iX%!Rh1W#aVQt$0frDdE>)c&kl-EyVklEG9d$%_gF z!4}@ET`+Lt?Tm7UZkBR9>asF*$>g;Td4}WEA7azlB5LnbQ#4XskdFFvD)^_t;7&q` zzong>o$C`*j-+q;fgHPdayn5Y+lW^lArIfvic>!jk2Z<_7Uj^)1#-N#3RXalTE_(- zH|0i#7ZcXRIPpZ8IOCLbgEo0DBhZCxT{@ukOX+k>`<^uA?UzP~p$`wWdl@1sI;pbT z`#E4Uh|`HL9$6@9;fK?ye*wM?MX?7p{z)ueG<^`^KL0UC{IOQ>il*`8ay&KTIj;smHTBWVHB0^D z^rYcGhXbscewmQ?#YaE)3#_&Hh0*ER?|=Al&96lIp|;A zJ=|U_kS7FeBi#c7dYw=PfHoEy1Y_M=C>;e2OvSr+C38Ae#d6W_fRt^Kd|E!Z(0O?R zXU#p~#CLM@O3%UN!~2U9j*^+mPh3z)VBA0c6SH+jp?K<-S7I8*(!uZoHRcbA)5{vM@*@xh}$DbMWk`ADy0z% zwmKwI)TQ1D`?xoRpwDvHEYVCu8_5L&NZw$s?Mk6Q;9$AYXe(SjD?a$};C;NNC^Mk~ zL=TTP+cqaqx*|neFZuW}fZ)x=ih8E#4MH%F6p< zvR*@x+R>l^RvfCfP_*ZhtC}khzyID4er*M5`fbi6BQ;cM+QB#(O{EAEm|Qj zce(*>4CF+&k3~8i%{`(WHaeL|r50no_+*9h_Csn0cV{1-WM*eW){WzAru_+3e*x0L zy4#R!HSyw) zfH>Rff;E$KAUpKuZ7R!NR9P6~aIw8Fv45}?ZNExFjz3!8=%CGVcJW`AUTHL9krAny zMqS+_3=3%MztIe;E))J0HLVrT5?5u<<9 z<3@LQGP^w2*vil3Ueu~gEz(q*s6YSrA70|aiE*rwe*To%F8sKm-?>g-R~9d8a_jjn zUBk1%e5zayZsqp(8#NMhwVB4^LUtUtX`|%ojIo)Don82s?fH&ueEdxc=Mku-@gZmn3RX#4yu@>Z<%i{~%fYor4HyLvPm<|&3g-KZ-MAAvh zc#b;~OCmu4FOyoo2-7ez49`t+YF8!zoHfzy5-!t_-8Bg2pxnf@@rC5{4V=d5cw#(D zD)kD&!{GE!f4@iFVh@&Fx2OE9?7IBf^>}LH4?aWXj-59!E*Tf+P`sN^p~vTJ6-!&o zyNFr!qSBi6;>6oWtadu#Q7{T8NIgqRBTgI^? zoOR2);`FgTsM{Ioy%>J?Und2!d0t1vTRVKo#6vY!s^2?0dA}N}h5{%5c-jaNnW8^H z!b%govFy!2eT|BR^w7!Ij~Rc>Vh%0zQ8$b8!93FrF)ihSJO3AbGTKd;@EY|LI;A@BpXtQv-rB~(JjLPk|8nK}IAN8k?%>h>f;U?r zbX3Q1n=scFT6??peZeorK{1~gK;e* zGJe|kF=PXC&2GE4zN?iPc1$7EX~v;F_~*8ar43#bdqx0UWSBOLkpPal&qpmRo(;H4 zFoK!OWFv@ndW@n{e`JIdvMUf~xu6-`amUm+l8k$)a6&gb4is@o{(LCH@K~lnoLTZ_ zQD8d4k;9GqQ7cyE%YE}#o7+!=>(^l%?W=Q=Nq?%Dg4DwLT&V;yW@Zi$Mrx$$9XNRL0a1e{)t}T>{S-U&7d1AGbd^udQtWlb zmI*(2R-lbaf$q_4JEabv%CbU}G3TTY#PM)8!20wk7EVx;P&mqM7F8suN=R^SUy&-o ztMt~%1^Sws2?e^A{Y=vco|n-=F>9qcud4wC4LjH*oK6G2Cgdnba7n$i)k>oGP!}4% zK4hIe5fO0SSxOa$C_s#_Cm$qGL-|aV0QPY3ARgY4T)sBGG+~M#$yD;(rOUT3u~czd zjLXmI2fd}*PN}E`|4qtaVwirr{8Iay_R}SnwqH-s9U6CPyGI~~<|PMNx6Q{%w%Tt8 zyi|+8H}VWB8HN!UM!j6~Q=f6U1i16h!g9?if;P z+I_F$L|7tHqgr}nz^J9n(<2RP4K;755=I2Lelq{)Yu0wXeS30Re|ua@Z^Va-r|*tv z0H(MC-bV1>*dj{Zg55Wbd3>JkXfc4E9A8^{=cFqO0}`79Zrb)Q_TknAvdXXb`s;FCb*0cI zQ-W{h;O*-7^H9#tKAcewqj2zFN5Ifh4!gMW<<~1ceY^@52(=}WAj#4*!0C)*8U%5i zj2YZX-=r|}_^8mvhA%C25*8(AK*8vkb=Mu<*t~M;$+0BUG>0$tQLdu zzG^)S!A2D`RI4%GjrB9nO=y^iIl{#(RSUb$#^F>sEHW7LYIrYC@;{z?$%=ecR)4Ve z2Iek!nME(&sV@ayE*I z2%^{qahNU)>*yv)1e`q*`Y@?*eNzbk6gL(Kel??s9y%n4bFhc-#?~I775_LCdf~xNV)`pbhXm`G^m6d7&n`?a_|S)4$DhMnb!DsNdQp_H zv-*(B;!C>sg!}5vmh%h)TM)F?tgT)dawV2{ZB)U){oFgs_GgXk~ow2NDNHxh%u|a0CD5FSNj*fP4!__k^w~lWRfs$Y7amjbrNKB{P z`O!#8#y@Wu&c+n)^57Vt6zEh3F?}kw{TNtrL$wG?E#>Fzs#u6eqpBPQ8ds&(?jDmr z3VxNDqe@FnK#x=08asJ+`f`o*oi{A`k>k~JoxEJ3T15nX#Mc#z^l|^Y<7zRa!a_7! zpd43<){Yyzy_;pB^GH_#>f2AIFbnTdeHAjk1V_#qWH;|SKCQFnkchRGnc1r}>kih7 zJIl`LB+890muKdtvh}{c!BPM6LU{uT&D6%Ccl3+)_D@=nvqf1!&fpPMcQ zCM2arjM%6@!3+N%?qOi(gEbaoJSxRb1%>ZkKh)l2Bohl)q44!9ZF69On0GGW7ht~P7x3L ziEOm-8L3*4A;5VqR`L4-XAWB+4cbHsRU9J3u?$1Rqy$DwZCEP{@#(UZSXswJEmOOz z;Gx_uoH=n$l~E`sj5%f88^O3A5dmIo`I6k(k10z_qr2HXu4QhKE*{5!D*BjeD!`Kz zYSpMul>yJ#gdWPHFyl7*zU!zw`V*sIO1UALF|YQwjZtyb$B z$H%ogxkVn>NpG80A-kj`S(TP%BRWUn#!UD|NCtw3vkI$KgsiY6Ph4CI-+8 z$GU9s0pq|`qddoh8po?-?5IAZ_E+}`w(!t2G0qZB5$G2^%jHHnoy`@d_7Hj~;ye z<@ev8M8TYbjbc46>C4Fx`jq&q@zSgmGJPfyCmktNH75g3cfXhzNXHPVtC6-=9U$OL z?&lf@&$bbhtYuK?`0+I>^8c1(oHcsoHlJ>7E#0{TlVSjr_hQ{z+En!{?G=rC#2 zxIh~iDS=edxR1zcmbK|8zc5D;HJ(W7L)B0xJQ*8L#1~k@LtDq3Aji8WhIrS5q>m8+nt3g*6XKAz%*sY%>ojsAoDlgv&M&v9sd$wwqQ-JwJoF59)C9xW}HNDN(@ zcHB}oGCJ_nSJYsWC{D|jBbk^>`6g~(rb5~j^!U)kezTbT992wCI$OdSgN3mY?mY#d zfM!>_ZIs$0QMQ;7jMe;-jb8pH?nk{CBZw9-imP^FrQfiqJY6r9nWHzGp<%b#97a7gpjXq8;aHX%Wq=mIaUt`Pyxytbl17~$n0%ZFC^Xm=;Pi|Jp=iyjD@g$Z7>wOR}{)Ds#*-u?LI z^v$<_NvLWe2k>4WWwaFZ&hHw?U7t>FJz4N+6Lid{X(&W~Wu`I3xomW=Q{J7$V6m+6h(uBHObN#jL95J{+zAG?HcXXfjsH(O;M?@NI!i=3X=!536fRTz$Y5ySqwBa^{KkbiMj&NYK2z@kGTy8!i!mxDx^%mx zBhpTosDkOTcFCg{5!U1;xKS-267KF(c|zrX6Z*+DSs*w`Bl6R;`7R zE(dbTw8^pH8=0Slg$S3N%pSjkcg*)w2k=Ifr0;ge3am*e&>?cu_KzrE*ze{$U_oIz z<_)11d=cF7E(X&otJSftk&nJVad$J#aPj=bCg9FD9XY6FJ4u-7%Hy2xErwvsYHAku zYIP>vM`cy-{h(J)%_O4SMPUwY=~~U?{A=IK=2vcNcchndXZqwmnY{fY^2`IswbFpD`2g7_U^AvJ^rz9Mmac{TAg2e zyD=a3qnpxZ9XP%zdxcY{Z_>NWPi^ex&+91Dt4<;K@NmY{=XOrmwZ2{z9U_WXnd%zR z_L25BM56nb?;f|S5|Jfr<;9q41PM3vJ_D0cJUG8I!2hN~g79)6QIyEB`k#7y;oo0=`}%Lcl`p47(%8!*Wcdk#*Z5`zam;PeM z>vJJQr?Q3}I#rI(r@&R5!#>x6Q60(~2*nza$4RGF4m5o^v9Gm_9=}CG8u}33;=07- zG~kMcB;{Iw7ApnmQYkJ^IE-xjIE2%}1&}CnIW@D3)2O_BoC*9y7Vj&mOWFfX zYHm(CEQ(iwS}+LR&|<=+%QFJD&mE2O!p2+@{q;D6b2*15eA691HK-*WlbRQ!DuUel zgt1Oy-xLc|B`X}qQbq7KJ~W=>1z~+!dAEs{9|su;SAkr7nz@Dv*Yr-FdU%#^EC1pj z@=HsJrFbxlcUhd960xAum2>LYwJz!vb$om}k@a0UH}%XJyKVx`f*K#)f!hivVjZaM!jByZ_;>hh%E_N@@J5Xl}s=d#sCUMSsXi$MjgT< z(gaZ+t~(3@t06FF715g(F#_r;VZb^!4gB)K*t#{qI4vJK!R8|-mG$@6=oulc10jLW zFY|Fk79(A~U0SXsYwIRXm1-v`KP&RoW)flQ67Ct(7#chsQDE35XV3JhN!HHHlEWFJ zKHwS|RF5#kG269<>3S<()pQ03@^3sjeLUNUjTJ$%!cR`Zs{~faK{jSjPiB8ah3RW_ zgByDSUA3x(SnO$ic!F^7p0{GMaCR0GJvkgV@6=c!-QAeqn28S4NjGxyDjG_;uqM1b zfhkX@?PD15Vbp4F%6fa)IJiHPD(^3xAFM4lPFO}UpT?8xZHICebIoW~H@SNDv20|V zy!&6FW}VgJmovw*hTWCLnf?9Q@4mY~Tkuqxi8)RNbJ8jA!^NYw1N;oMBLM(@G}usC z^Um*=*Y1HhTV`#!au2^=o80?)_2(_-uCm4^y)d)55%Bw0MtZI6l03|&wR@JQ{1qVg z^CDc!o5Nx3bEW6Ew>LZk{PNr+=shE05)6UK^a%NmK4fURBkjWo_6_&09rtzz6tgD0 zTFS!ON-9(8P7lx?=k6iI7#VGM$2K-fQL6K?aN6l7YE6_Bp=2>Squ>+|Z?)k;l+&30W^p~S;Bx%_^&|or$v@6-9&IiEPPVucEN9J{Qj?jJQS6vj5mnF; z;A|so5-K?-(CJ{qRU69E9x6j|gN72Ec;9$Z`87D6DB^@I ztIbLYIkV2xidwpolln%aE*DH@0h=a6=?YGPxe_14bU{hEYCOrIP62Ut{z%*d&qAT5oa~^ zRktQU2^iD`>t!7dbn7NMrL8oaPJ07|LUu#~Oi)l99EpW()uB1bsAiO^|gNrcsdC*0@l6kaf3bjk^()_O5ssbPBCic!kp0?HW%_0+cbD#MaUH) zg1?9vt}uE5O4S+4=}Gj93R}?#`WP2dfFye1hr&%G!URa6kv76gR{%J=M^+k)s}7Ra zi#V7g!)VOI6e^nyjU}`-Rfu48f4;VQ@8tC1v2@XA>y0p_mtxdgWL1RSPTE$f&u$+) zUL9_ynXkUMcf1-H^cLYD;+nP9&`0l&Jb^Tgbx=;2ll}bv=G^B~#e>=1t%L2Fr>{tG zk=b3_7{yZ)+AQS^+~Z#XZ>pY#>5%K85=&?i3y@p&j`ZNwWu=WsJv~Nv!7i{g?wkuZo>ytjk4}b* zv22xicd=NC7c*~Eb$I<|`X0rykMXqs9O{E8KAYF-EndS6#>fH{MF`DATFxE*9L{2vzz_j!0w@=my-z znG@f*Pa5pX%*eV2xrG--I=o%aCKIlS9+i#c-DES%TgXDAmVa%N23U=Gmz#DJBYxy9nv?s1^6yjv@ivRUc6fdp@MP6{CVwC#%X!YfQ;JHZFL>b-iSFBl*gNjyyn8by?bi zyqYa46=_I+{_f?`;Z|N-nu+I%^y$&_O`cqYNejhBDIZ@ZM=ytt zPW{eFS2i%wX={9vfNi$d>qu-WbHOie8WYVd<@Ds_4I^4@n%#RNR}9BX@g}um;{_fE|=!!;x+9<+(Dt! zkdAW6Qt+!~D90-U@^H4eI#fD3J>5!`iuioTjUbygcC^<*z8tfQS!R#3d@YifjBsh- z;))hHd`epGv)earox2rFjyrC2Fe<Q2f`?{(E9!VQO@3L3lK2w zC(Fpqd{`{oF~T+*tTf`MW-5XOv{%36W!hcxtq2yeeqBpPy8HZIGZ8|#3G_6#6#nSPyJaMtLK`C>uIbL{*!1X3nCF=fl67|#ce6b!TL=4l)vEs& zBuj~jZcSfK$TRoY@YnWie7?adefe>soZo|72+aB7^PbWnC1sSE3c}m~)}$Pm)0EfM zCV23G)$rEm$$fbkWFGA5`S9*qx#PTNIK0H!Y8l3IeHYI{wkL#CYJM0i#v6P zua;XxvTk~Eg5~abbXuI>6t3m1CC_fm%<$-rra#y0DUrLOV~<^R)1(|N{pBK@n-k^m z9Q#E%269btf-~h-Ojj|d^NKSt9jC>%BY~UcEX5ri()%srk0#=#>`>1H*)qF}dfuT` z5M~WyidZ!Jm9sNj^j&c*EJHHKkT!Nr_~zDCwg7@i@#_*Mfw^KZ#Y8FP7~{DWr*DA8 zWHO(Mr?xgT!Q3OVdr$KTN0N5o&N~khL$?2SXy}G->*y$>*5irk;7mSFLNo!mHIl0x zXVh3@E{xiUzVXitn&=uiM`G?4{OY`Nf$dipxNm&wvvYFsCQ`w5vWl8$<%OryK(56( zkS611^EQ0b$rwHzH!SfwNTSgzLU~gyNxU$oZM1*XbEap|5 zipdqSs~^S$2jRip>~52{#R=m+WX-h$ zwKyhR9fcI_Tq7Rj4oSz6Sra+<Ug!D%6C{41C20D2s#xH5>ZRy)4 zAxnhB8kWY|%AmTu28PG{rD}b|?q;>AIvhIY$vA(sy|%HjKeI8vVgbjr6UQdrbWl&o zz`A3UsAnOQ>*o1~+8`hHO9o^FR*M^{ah@gMHl|PjvTwZaExQliW&~p%u+K z(0z+SyW5eh`dr-aS-E@CGc{j|sU+6PpaIuBs<8WFBU(3D4O0w@s6Va>cWb42=Y5Xd>n^f;Uofzq@QCRxZs0u@G+ z@yymnkllrw+S_%=Cf1|F-IHpJJlq^ocfo}TS9}t@xhN70;k!w?YT=HAn4Ag6^uod& zhcu*;@x@^9=@W)QYV?0hJBIMZ5~(fLyKZhjdbRm zG39r$r6Q4vm!$896al-xr`VASj;W{U%-5q$<}#~Z2)BAJBc1q}7Wnm>a)c;05&M*B zSlWiiY3qr9l@C&FP0}B1y*XLSd*j+UJ`ZQigscLbA)GPe(M7TWCqV!wvj5?#mf{5< zn4GX~h!oNmD#Ee=$gA&o7h}VtX&%8dMjA^XLTBEDC7Zby<(Nhk-b`kNYAZ1*@B5tQ zJajG90_@Xkv5S@x9`-3$dwb2MFKQL;e!wRgAHD(kL&mowCgkI7kDT5xv+9Aw9GHy^ zOQ&pD^9CmEqa&p3J@*SAp~v=f?A%9$4x@t6l)G#Powl(Ae5yFCiU#4V6_9e%5SSRm zm90pP38UfUtQb=W1*2^DnlDDFzeKBr?&9M7e7(LB8|cm^S&}nSpdF$z=o?f)LWT$~ zUn>;;2w|hewbj5%eFJAs!JD4*#+tAL8aF)cy;GsT2+fqI9Pxz+STm5bqpva@n@XHI zT4zpI+dt`(MUHOdNacrVV^2aUWMSSURF@=fSG zEGrzeGIIqLA9Nn5Y?dtEcAWB*MV{aevcnZr#;A**b)e5P*-4r)l^t{19V)8 zRk+_hJWyHuZq`4TcJVh4)%P~^a*G!yIalo}@jF?xl-_!OLLt?MAi3n9Vc3XiABjkA zlgVqa79b@-`Z$1xt(sU2AsQDlgV|^dDOKtAbo=>h70K(Vzdc(er)<|tl*>$frAR?< zl;X_V2ig5VQZBgl&B@l%&NnBocJNuskI>jW&BeWrK-NWi9BbAb#4(FGT^fj4=Cu&l z!<(@t;?882THC0#N0G`pF6CT)E4T~`Y~8`AiU*cci{%M(E8=5VmZ8p`&TN)vQioU) z@pYCaJuC*S6zI}dF*2~kr#Ac4~GEdC9nY}W7V%KYP zgs~x+!rwcSE(g0#)ywP6I;b>CwIJa%4sbu4!icdYIO;s7p5RY!3_&@gi^OtCnBQZ> zQIgk;&gShQdg~rcOEg$>tw~phkvq}jVH&qwxU_RbiH%60 z5b)Mhl2p=+JAk7sAHZVVjIuDVvBv(EKoxPYF8Vh6tlXykb%(M!|yFM;SRWCy%yT?8K0&sq&enxkSGl& z)q;nWwe8d6j|SX<)l@3v39SskHyN=iPx@9?4!~R#)Y9u63!Wa&5N@2zqNmsRa!ts6 z+=N`~W54K~no52B{k=lE&?mylbV;tQr}*8w!{re5gb&IOICB(On~$_ckgG}5{Wsq& zf2<7N>RZFMrrC(0iMvz!tmJrsYPMlpz@O7)+-(9T6hYG!Wc)oU=P)vFFtLm!MvHtA-L9{_7W zl)r9EwC`_`PGq#nI6aMM>Xm2mbX zlS57yJ$K1Cv9E;ZhB(NvTq?%M@AW(JWtdn%4qPs-!#S$Kc3Xvkt`ZGk?*mckwdVS-`g?Imz!zn9b)=o}VswB2&@4h}1J6_ov9gco9(w+9M&Md}4t5Kfo;+#OIH<@wQ#2O&u^L^e!sQC%0 zN_!gR>2c9+jG(H@g&yBzocRQzT>HRz|Gh82Tb-=XuGV4~pRgx=eEM!REoaVB?q)M$ zrS7UneQ3n2o|*fzLgLl=)eizzGyAZ&H_-h2X2$MndBNY?rZ_d7UJ0+HDSN=S7Un34 zc&!Vk11AoBdy~C=1^;NJ%X6^X*CywZrf$#t%#7F5r3gTO+u_LMB(;Z7?fBil{&2Xz zJT(;|krGiNSEUC;l7}O34eluyVvA+G_|OhO-(8yUwp)@pO6P@3gtfph!2j<^OhqrP zy=H{I#8sTAh@>V0Wim3UQY`UeYxA!j{pIFgzJ9)yXk^M;ufBcrlx2aEKUa;x;!CF% z%9>!~qRGCWAzag%dz`J#5oR~#XBW^cFVWP8u?(6}6s;8}YVT9N_M%H%r{$hRUPax{`;MUg8vMZ4fI;M;36TUlloI~q7(;eA~ zj`i#~ttYDOCNwSLb7)GH%gJJ#-Vs!i=N6!5r&TSWq|kaz_}uWDo|(%(cj+AW;Fs~M zaV6zdCR|EbQgZQ4Loum1`JmkN`1I0FJ|CxbMGL?;RMOTzk0Z zZ@<{GGuia1^69%>wh|U>#0unOV9sCZJO2}tgXUSgzuHbcHuUiA&r%M?t+LVe<5s}h zHqhHsNR|6OUD;pUySMvrcI{x#J2>DOhHsX2eD4ELPJFYbs{{8|dM}P?c~@WA+pZTT zsmTw#UESNC?{d4`EbodrKp78hZLG>21&jfe z9iSYk6#@{wD7yz^;7tA=PM*pV`Y?BQHmdAJY$PkUukJ;RIH4TgNOr@k73<3zOzl58 z_{-;i`R&W6!L6Olvv0qBo`MOuPiCjPNxZfACZOq}wGCV6767f0bu!Zq!0l(0-MHq& zqY`UOYesQ_Sp*PQD(B0Sgrq(cdXP}6Wqg-9?-Xlg2D^NhokQi6Pt&z*T-@}m7{=ew6*M>TN2L0(X&%n%2;*~$3e6;jPJ1iXJ2& zqreeD>XY&bRD%%J-16HXpM-&Nzl0>>5|T3#v*5NA=#-knI1me(838!=3H4XA%>q*m zLYy?D#PH?FoXMFpDMp;lF`gEAluAz29e48Xq}HI~Koc!sQmWjaElk{GDN1iB`<#Cv0( zSjedXj?9+ynXEPChOPgn=?CKienNG0%ID|ZB)?jiQ{A+$$C-Keeih2KB33i`Fo44F zPavme!@j<^k0187^XT2TeLqXNRkrruL-Dxn?3)0Hy`T2_x96wkH&#{(-o^RVwY7({ zs};WQigJS57xr;w@)r%_4BG9LgEjZZ10#3(t`0c+toq!?qTJrzId2V5Hnf_To#}j#pYOdFG(9NMj z*EykhR=cE0ekJpDnqT4+9g4N&IGrCfWbC9CeCf$?7VR^1i+fa>izO#YxkK@d)ZCkw zZ{B=&_@*`#FHX~^lF#Q|iOe@gTe%E9CYzf_xO$vq)MRn{GMgHc$kf#Qo608d;H?R8 zl14#Zi1s-=NPSO~cN6)AjZ8E)SUH(2Z+E_S!9juiHAyARC7d&D>|r zsHkM?Ra$2WKvnCKTNl7P;ZN=v9G1yF8HuG=LMt17_n>zX0(xU2>oDCFHa8Z7T<8^)WfVh zxD_z(`KYl!b8lvEZDx;h#oo-Gwvtvn4839>IA1nQ#dJwlPLN|8%+FiOwFt+_hPk4g z>a)ffR`-Td{LRm14%Bi=r|%cj&4{&WOtB8M!c~ZfnFDhWox5)e)E{ovM7dTc2`jzU zR@<#FXCK{mssF-MF7NTQ^P<9^&N-Q0ytlhwuys}rjJ&1?ns5{7BpQ5v{$Qo;W+6Gy zCv_S7D`1jhWo>os@pqf?f&Sq;S%1IVPj#-xP56^`rcd7g+qaYB%Y+F5zy7n@+@MUQ ziWtQ(wRT=#2VevYLyioXy;Rm0Ap3JDrr)hh(-7yv;kyMc3c-2 z{~rkO{~wTcMK+#0diIyEU*)#;pT2s&IYZr6kW-V~|F#d7x3`%0fyrO70_Rd~vnoft z5gW4I)wJ1`|L$-8qNed_|6n&1rX7sQ35o~VBt0?Y$x7wrAA&R=EY8ljy@nsvDn+lWJ=C#{;9g!f|;YEmoIVY-fa3ZGjU?sT<%G>xCQ@6JhGUP zeHWa6_~8xq^7R{uB5z~gY(v3({>2J9B+?;pNugvC5J|I>WZ=ZIk6ydvldY#unWV_b z2q%j`*4ODY7=*wSWf@l^p(xL{S�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 KMNUMnLSTYYh8Rl# literal 0 HcmV?d00001 diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts new file mode 100644 index 0000000000..95857aea4c --- /dev/null +++ b/cypress/support/commands.ts @@ -0,0 +1,37 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts new file mode 100644 index 0000000000..6a173d6fcb --- /dev/null +++ b/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/e2e.ts is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import "./commands"; + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/gno/p/jsonutil/gno.mod b/gno/p/jsonutil/gno.mod new file mode 100644 index 0000000000..8077020ff7 --- /dev/null +++ b/gno/p/jsonutil/gno.mod @@ -0,0 +1,7 @@ +module gno.land/p/teritori/jsonutil + +require ( + gno.land/p/demo/avl v0.0.0-latest + gno.land/p/demo/json v0.0.0-latest + gno.land/p/demo/users v0.0.0-latest +) diff --git a/gno/p/jsonutil/jsonutil.gno b/gno/p/jsonutil/jsonutil.gno new file mode 100644 index 0000000000..8bc5c05e68 --- /dev/null +++ b/gno/p/jsonutil/jsonutil.gno @@ -0,0 +1,131 @@ +package jsonutil + +import ( + "std" + "strconv" + "time" + + "gno.land/p/demo/avl" + "gno.land/p/demo/json" + "gno.land/p/demo/users" +) + +func UnionNode(variant string, value *json.Node) *json.Node { + return json.ObjectNode("", map[string]*json.Node{ + variant: value, + }) +} + +func MustUnion(value *json.Node) (string, *json.Node) { + obj := value.MustObject() + for key, value := range obj { + return key, value + } + + panic("no variant in union") +} + +func TimeNode(value time.Time) *json.Node { + j, err := value.MarshalJSON() + if err != nil { + panic(err) + } + + return json.StringNode("", string(j[1:len(j)-1])) +} + +func MustTime(value *json.Node) time.Time { + t := time.Time{} + err := t.UnmarshalJSON([]byte(value.String())) + if err != nil { + panic(err) + } + + return t +} + +func DurationNode(value time.Duration) *json.Node { + return Int64Node(value.Nanoseconds()) +} + +func MustDurationSeconds(value *json.Node) time.Duration { + return time.Duration(MustInt64(value)) * time.Second +} + +func EmptyObjectNode() *json.Node { + return json.ObjectNode("", nil) +} + +// int is always 64 bits in gno so we need a string to represent it without loss of precision in a lot of javascript environment, I wish bigint in json was more widely supported +func IntNode(value int) *json.Node { + return json.StringNode("", strconv.Itoa(value)) +} + +func MustInt(value *json.Node) int { + i, err := strconv.Atoi(value.MustString()) + if err != nil { + panic(err) + } + + return i +} + +func Uint32Node(value uint32) *json.Node { + return json.StringNode("", strconv.FormatUint(uint64(value), 10)) +} + +func MustUint32(value *json.Node) uint32 { + return uint32(MustInt(value)) +} + +func Int64Node(value int64) *json.Node { + return json.StringNode("", strconv.FormatInt(value, 10)) +} + +func MustInt64(value *json.Node) int64 { + return int64(MustInt(value)) +} + +func Uint64Node(value uint64) *json.Node { + return json.StringNode("", strconv.FormatUint(value, 10)) +} + +func MustUint64(value *json.Node) uint64 { + return uint64(MustInt(value)) // FIXME: full uint64 range support (currently limited to [-2^63, 2^63-1]) +} + +func AVLTreeNode(root *avl.Tree, transform func(elem interface{}) *json.Node) *json.Node { + if root == nil { + return EmptyObjectNode() + } + + fields := make(map[string]*json.Node) + root.Iterate("", "", func(key string, val interface{}) bool { + fields[key] = transform(val) + return false + }) + + return json.ObjectNode("", fields) +} + +func AddressNode(addr std.Address) *json.Node { + return json.StringNode("", addr.String()) +} + +func MustAddress(value *json.Node) std.Address { + addr := std.Address(value.MustString()) + if !addr.IsValid() { + panic("invalid address") + } + + return addr +} + +func AddressOrNameNode(aon users.AddressOrName) *json.Node { + return json.StringNode("", string(aon)) +} + +func MustAddressOrName(value *json.Node) users.AddressOrName { + aon := users.AddressOrName(value.MustString()) + return aon +} diff --git a/gno/p/ujson/gno.mod b/gno/p/ujson/gno.mod index c0f2d826c5..99fa7080c8 100644 --- a/gno/p/ujson/gno.mod +++ b/gno/p/ujson/gno.mod @@ -2,6 +2,6 @@ module gno.land/p/teritori/ujson require ( gno.land/p/demo/avl v0.0.0-latest - gno.land/p/teritori/utf16 v0.0.0-latest gno.land/p/demo/users v0.0.0-latest + gno.land/p/teritori/utf16 v0.0.0-latest ) diff --git a/gno/r/projects_manager/filter.gno b/gno/r/projects_manager/filter.gno new file mode 100644 index 0000000000..2913199307 --- /dev/null +++ b/gno/r/projects_manager/filter.gno @@ -0,0 +1,81 @@ +package projects_manager + +import ( + "std" + + "gno.land/p/demo/json" + "gno.land/p/demo/ufmt" + "gno.land/p/teritori/jsonutil" +) + +type Filter interface { + FromJSON(ast *json.Node) +} + +func FilterFromJSON(ast *json.Node) Filter { + if ast.IsNull() { + return nil + } + var filter Filter + key, member := jsonutil.MustUnion(ast) + switch key { + case "byCandidatesForFunder": + filter = &FilterByCandidatesForFunder{} + case "byFunder": + filter = &FilterByFunder{} + case "byContractor": + filter = &FilterByContractor{} + case "byContractorAndFunder": + filter = &FilterByContractorAndFunder{} + default: + panic(ufmt.Sprintf("invalid filter kind `%s`", key)) + } + filter.FromJSON(member) + return filter +} + +type FilterByCandidatesForFunder struct { + Funder std.Address +} + +func (f *FilterByCandidatesForFunder) FromJSON(ast *json.Node) { + obj := ast.MustObject() + f.Funder = jsonutil.MustAddress(obj["funder"]) +} + +var _ Filter = &FilterByCandidatesForFunder{} + +type FilterByFunder struct { + Funder std.Address +} + +func (f *FilterByFunder) FromJSON(ast *json.Node) { + obj := ast.MustObject() + f.Funder = jsonutil.MustAddress(obj["funder"]) +} + +var _ Filter = &FilterByFunder{} + +type FilterByContractor struct { + Contractor std.Address +} + +func (f *FilterByContractor) FromJSON(ast *json.Node) { + obj := ast.MustObject() + f.Contractor = jsonutil.MustAddress(obj["contractor"]) +} + +var _ Filter = &FilterByContractor{} + +type FilterByContractorAndFunder struct { + Contractor std.Address + Funder std.Address +} + +func (f *FilterByContractorAndFunder) FromJSON(ast *json.Node) { + obj := ast.MustObject() + f.Contractor = jsonutil.MustAddress(obj["contractor"]) + f.Funder = jsonutil.MustAddress(obj["funder"]) +} + +var _ Filter = &FilterByContractorAndFunder{} diff --git a/gno/r/projects_manager/gno.mod b/gno/r/projects_manager/gno.mod new file mode 100644 index 0000000000..379bd441e7 --- /dev/null +++ b/gno/r/projects_manager/gno.mod @@ -0,0 +1,9 @@ +module gno.land/r/teritori/projects_manager + +require ( + gno.land/p/demo/avl v0.0.0-latest + gno.land/p/demo/json v0.0.0-latest + gno.land/p/demo/seqid v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest + gno.land/p/teritori/jsonutil v0.0.0-latest +) diff --git a/gno/r/projects_manager/projects_manager.gno b/gno/r/projects_manager/projects_manager.gno new file mode 100644 index 0000000000..948bf7fe23 --- /dev/null +++ b/gno/r/projects_manager/projects_manager.gno @@ -0,0 +1,941 @@ +package projects_manager + +import ( + "std" + "strconv" + "strings" + "time" + + "gno.land/p/demo/avl" + "gno.land/p/demo/json" + "gno.land/p/demo/seqid" + "gno.land/p/demo/ufmt" + "gno.land/p/teritori/jsonutil" +) + +type ContractStatus uint32 + +const ( + CREATED ContractStatus = 1 + ACCEPTED ContractStatus = 2 + CANCELED ContractStatus = 3 + COMPLETED ContractStatus = 5 + REJECTED ContractStatus = 6 + CONFLICT ContractStatus = 7 + ABORTED_IN_FAVOR_OF_CONTRACTOR ContractStatus = 8 + ABORTED_IN_FAVOR_OF_FUNDER ContractStatus = 9 +) + +func (x ContractStatus) String() string { + switch x { + case CREATED: + return "CREATED" + case ACCEPTED: + return "ACCEPTED" + case CANCELED: + return "CANCELED" + case COMPLETED: + return "COMPLETED" + case REJECTED: + return "REJECTED" + case CONFLICT: + return "CONFLICT" + case ABORTED_IN_FAVOR_OF_CONTRACTOR: + return "ABORTED_IN_FAVOR_OF_CONTRACTOR" + case ABORTED_IN_FAVOR_OF_FUNDER: + return "ABORTED_IN_FAVOR_OF_FUNDER" + } + return "UNKNOWN" +} + +func (x ContractStatus) ToJSON() *json.Node { + return json.StringNode("", x.String()) +} + +type ConflictOutcome uint32 + +const ( + RESUME_CONTRACT ConflictOutcome = 1 + REFUND_FUNDER ConflictOutcome = 2 + PAY_CONTRACTOR ConflictOutcome = 3 +) + +func (x ConflictOutcome) String() string { + switch x { + case RESUME_CONTRACT: + return "RESUME_CONTRACT" + case REFUND_FUNDER: + return "REFUND_FUNDER" + case PAY_CONTRACTOR: + return "PAY_CONTRACTOR" + } + return "UNKNOWN" +} + +func (x ConflictOutcome) ToJSON() *json.Node { + return json.StringNode("", x.String()) +} + +type MilestoneStatus uint32 + +const ( + MS_OPEN MilestoneStatus = 1 + MS_PROGRESS MilestoneStatus = 2 + MS_REVIEW MilestoneStatus = 3 + MS_COMPLETED MilestoneStatus = 4 +) + +func (x MilestoneStatus) String() string { + switch x { + case MS_OPEN: + return "MS_OPEN" + case MS_PROGRESS: + return "MS_PROGRESS" + case MS_REVIEW: + return "MS_REVIEW" + case MS_COMPLETED: + return "MS_COMPLETED" + } + return "UNKNOWN" +} + +func (x MilestoneStatus) ToJSON() *json.Node { + return json.StringNode("", x.String()) +} + +type MilestonePriority uint32 + +const ( + MS_PRIORITY_HIGH MilestonePriority = 1 + MS_PRIORITY_MEDIUM MilestonePriority = 2 + MS_PRIORITY_LOW MilestonePriority = 3 +) + +func (x MilestonePriority) String() string { + switch x { + case MS_PRIORITY_HIGH: + return "MS_PRIORITY_HIGH" + case MS_PRIORITY_MEDIUM: + return "MS_PRIORITY_MEDIUM" + case MS_PRIORITY_LOW: + return "MS_PRIORITY_LOW" + } + return "UNKNOWN" +} + +func MilestonePriorityFromString(s string) MilestonePriority { + switch s { + case "MS_PRIORITY_HIGH": + return MS_PRIORITY_HIGH + case "MS_PRIORITY_MEDIUM": + return MS_PRIORITY_MEDIUM + case "MS_PRIORITY_LOW": + return MS_PRIORITY_LOW + } + panic("invalid MilestonePriority") +} + +func (x MilestonePriority) ToJSON() *json.Node { + return json.StringNode("", x.String()) +} + +type Milestone struct { + id uint64 + title string + desc string + amount int64 + paid int64 + duration time.Duration // marshal as seconds + link string // milestone reference link + funded bool + priority MilestonePriority + status MilestoneStatus +} + +func (ms Milestone) ToJSON() *json.Node { + return json.ObjectNode("", map[string]*json.Node{ + "id": json.StringNode("", strconv.FormatUint(ms.id, 10)), + "title": json.StringNode("", ms.title), + "desc": json.StringNode("", ms.desc), + "amount": json.StringNode("", strconv.FormatInt(ms.amount, 10)), + "paid": json.StringNode("", strconv.FormatInt(ms.paid, 10)), + "duration": json.NumberNode("", ms.duration.Seconds()), + "link": json.StringNode("", ms.link), + "funded": json.BoolNode("", ms.funded), + "priority": ms.priority.ToJSON(), + "status": ms.status.ToJSON(), + }) +} + +type Conflict struct { + initiator std.Address + createdAt time.Time + respondedAt *time.Time + resolvedAt *time.Time + initiatorMessage string + responseMessage *string + resolutionMessage *string + outcome *ConflictOutcome +} + +func (c Conflict) ToJSON() *json.Node { + children := map[string]*json.Node{ + "initiator": json.StringNode("", c.initiator.String()), + "createdAt": json.StringNode("", c.createdAt.Format(time.RFC3339)), + "initiatorMessage": json.StringNode("", c.initiatorMessage), + } + + if c.responseMessage != nil { + children["responseMessage"] = json.StringNode("", *c.responseMessage) + } + if c.respondedAt != nil { + children["respondedAt"] = json.StringNode("", c.respondedAt.Format(time.RFC3339)) + } + if c.resolvedAt != nil { + children["resolvedAt"] = json.StringNode("", c.resolvedAt.Format(time.RFC3339)) + } + if c.resolutionMessage != nil { + children["resolutionMessage"] = json.StringNode("", *c.resolutionMessage) + } + if c.outcome != nil { + children["outcome"] = c.outcome.ToJSON() + } + + return json.ObjectNode("", children) +} + +type Contract struct { + id uint64 + sender std.Address + contractor std.Address + contractorCandidates []std.Address + funder std.Address // funder address + paymentDenom string // banker denom + metadata string // store data forforimage, tags, name, description, links for twitter/github... + status ContractStatus + expireAt time.Time + funderFeedback string + contractorFeedback string + milestones []Milestone + pausedBy string + conflictHandler string // can be a realm path or a caller address + handlerCandidate string // conflict handler candidate suggested by one party + handlerSuggestor string // the suggestor off the conflict handler candidate + createdAt time.Time + budget int64 + funded bool + rejectReason string + conflicts []Conflict +} + +func (c Contract) ToJSON() *json.Node { + candidates := make([]*json.Node, len(c.contractorCandidates)) + for i, candidate := range c.contractorCandidates { + candidates[i] = json.StringNode("", candidate.String()) + } + + milestones := make([]*json.Node, len(c.milestones)) + for i, milestone := range c.milestones { + milestones[i] = milestone.ToJSON() + } + + conflicts := make([]*json.Node, len(c.conflicts)) + for i, conflict := range c.conflicts { + conflicts[i] = conflict.ToJSON() + } + + return json.ObjectNode("", map[string]*json.Node{ + "id": json.StringNode("", strconv.FormatUint(c.id, 10)), + "sender": json.StringNode("", c.sender.String()), + "contractor": json.StringNode("", c.contractor.String()), + "contractorCandidates": json.ArrayNode("", candidates), + "funder": json.StringNode("", c.funder.String()), + "paymentDenom": json.StringNode("", c.paymentDenom), + "metadata": json.StringNode("", c.metadata), + "status": c.status.ToJSON(), + "expireAt": json.StringNode("", c.expireAt.Format(time.RFC3339)), + "funderFeedback": json.StringNode("", c.funderFeedback), + "contractorFeedback": json.StringNode("", c.contractorFeedback), + "milestones": json.ArrayNode("", milestones), + "pausedBy": json.StringNode("", c.pausedBy), + "conflictHandler": json.StringNode("", c.conflictHandler), + "handlerCandidate": json.StringNode("", c.handlerCandidate), + "handlerSuggestor": json.StringNode("", c.handlerSuggestor), + "createdAt": json.StringNode("", c.createdAt.Format(time.RFC3339)), + "budget": json.StringNode("", strconv.FormatInt(c.budget, 10)), + "funded": json.BoolNode("", c.funded), + "rejectReason": json.StringNode("", c.rejectReason), + "conflicts": json.ArrayNode("", conflicts), + }) +} + +// State +var ( + contracts []*Contract + contractsByFunder = avl.NewTree() // std.Address(funder) => contractID => *Contract + contractsByContractor = avl.NewTree() // std.Address(contractor) => contractID => *Contract + contractsByFunderAndContractor = avl.NewTree() // std.Address(funder) + std.Address(contractor) => contractID => *Contract + contractsWithCandidates = avl.NewTree() // std.Address(funder) => contractID => *Contract +) + +func setIndices(contract *Contract) { + if contract == nil { + panic("contract is nil") + } + + if contract.contractor != "" { + contractorKey := std.Address(contract.contractor).String() + byIDTree, ok := contractsByContractor.Get(contractorKey) + if !ok { + byIDTree = avl.NewTree() + contractsByContractor.Set(contractorKey, byIDTree) + } + + byIDTree.(*avl.Tree).Set(seqid.ID(contract.id).String(), contract) + } + + if contract.funder != "" { + funderKey := std.Address(contract.funder).String() + byIDTree, ok := contractsByFunder.Get(funderKey) + if !ok { + byIDTree = avl.NewTree() + contractsByFunder.Set(funderKey, byIDTree) + } + + byIDTree.(*avl.Tree).Set(seqid.ID(contract.id).String(), contract) + } + + if contract.contractor != "" && contract.funder != "" { + byIDTree, ok := contractsByFunderAndContractor.Get(std.Address(contract.funder).String() + std.Address(contract.contractor).String()) + if !ok { + byIDTree = avl.NewTree() + contractsByFunderAndContractor.Set(std.Address(contract.funder).String()+std.Address(contract.contractor).String(), byIDTree) + } + + byIDTree.(*avl.Tree).Set(seqid.ID(contract.id).String(), contract) + } +} + +func CurrentRealm() string { + return std.CurrentRealm().Addr().String() +} + +type MilestoneDefinition struct { + Title string + Desc string + Amount int64 + Duration time.Duration + Link string + Priority MilestonePriority +} + +func CreateContract( + contractor std.Address, + funder std.Address, + paymentDenom string, + metadata string, + expiryDurationSeconds uint64, + milestones []MilestoneDefinition, + conflictHandler string, +) { + if contractor != "" && !contractor.IsValid() { + panic("invalid contractor address") + } + + if funder != "" && !funder.IsValid() { + panic("invalid funder address") + } + + caller := std.PrevRealm().Addr() + if expiryDurationSeconds == 0 { + panic("invalid expiryDuration") + } + if paymentDenom == "" { + panic("empty escrow token") + } + + // For now, one of funder or contract could be empty and can be set later + if contractor == "" && funder == "" { + panic("contractor and funder cannot be both empty") + } + + if contractor != caller && funder != caller { + panic("caller should be one of contractor or funder") + } + + if len(milestones) == 0 { + panic("milestones should not be empty") + } + + mss := make([]Milestone, 0, len(milestones)) + projectBudget := int64(0) + for _, ms := range milestones { + projectBudget += ms.Amount + mss = append(mss, Milestone{ + id: uint64(len(mss)), + title: ms.Title, + desc: ms.Desc, + amount: ms.Amount, + paid: 0, + duration: ms.Duration, + link: ms.Link, + priority: ms.Priority, + status: MS_OPEN, + }) + } + + // If contract creator is funder then he needs to send all the needed fund to contract + funded := false + if caller == funder { + sent := std.GetOrigSend() + amount := sent.AmountOf(paymentDenom) + if amount != projectBudget { + panic(ufmt.Sprintf("funder `%s` should send `%d%s`, got `%d%s`", caller, projectBudget, paymentDenom, amount, paymentDenom)) + } + funded = true + } + + expiryDuration := time.Duration(expiryDurationSeconds) * time.Second + now := time.Now() + + contractId := uint64(len(contracts)) + contracts = append(contracts, &Contract{ + id: contractId, + sender: caller, + contractor: contractor, + funder: funder, + paymentDenom: paymentDenom, + metadata: metadata, + status: CREATED, + expireAt: now.Add(expiryDuration), + milestones: mss, + conflictHandler: conflictHandler, + budget: projectBudget, + createdAt: now, + funded: funded, + }) + setIndices(contracts[contractId]) +} + +func CreateContractJSON( + contractor std.Address, + funder std.Address, + paymentDenom string, + metadata string, + expiryDurationSeconds uint64, + milestonesJSON string, + conflictHandler string, +) { + ast, err := json.Unmarshal([]byte(milestonesJSON)) + if err != nil { + panic(err) + } + vals := ast.MustArray() + milestones := make([]MilestoneDefinition, 0, len(vals)) + for _, val := range vals { + obj := val.MustObject() + milestone := MilestoneDefinition{ + Title: obj["title"].MustString(), + Desc: obj["desc"].MustString(), + Amount: jsonutil.MustInt64(obj["amount"]), + Duration: jsonutil.MustDurationSeconds(obj["duration"]), + Link: obj["link"].MustString(), + Priority: MilestonePriorityFromString(obj["priority"].MustString()), + } + milestones = append(milestones, milestone) + } + CreateContract(contractor, funder, paymentDenom, metadata, expiryDurationSeconds, milestones, conflictHandler) +} + +func CancelContract(contractId uint64) { + caller := std.PrevRealm().Addr() + if int(contractId) >= len(contracts) { + panic("invalid contract id") + } + + contract := contracts[contractId] + if contract.status != CREATED { + panic("contract can only be cancelled at CREATED status") + } + + if contract.sender != caller { + panic("not authorized to cancel the contract") + } + + contracts[contractId].status = CANCELED +} + +func RejectContract(contractId uint64, rejectReason string) { + caller := std.PrevRealm().Addr() + if int(contractId) >= len(contracts) { + panic("invalid contract id") + } + + contract := contracts[contractId] + if contract.status != CREATED { + panic("contract can only be cancelled at CREATED status") + } + + if contract.sender == contract.contractor && caller != contract.funder { + // If contract creator is contractor then only funder can reject + panic("only funder can reject a request from contractor") + } else if contract.sender == contract.funder && caller != contract.contractor { + // If contract creator is funder then only contractor can reject + panic("only contractor can reject a request from funder") + } + + contracts[contractId].status = REJECTED + contracts[contractId].rejectReason = rejectReason +} + +func AcceptContract(contractId uint64) { + caller := std.PrevRealm().Addr() + if int(contractId) >= len(contracts) { + panic("invalid contract id") + } + + contract := contracts[contractId] + if contract.status != CREATED { + panic("contract can only be accepted at CREATED status") + } + + if time.Now().After(contract.expireAt) { + panic("contract already expired") + } + + if contract.sender == caller { + panic("contract sender is not able to accept the contract") + } + + if contract.funder != caller && contract.contractor != caller { + panic("only contract counterparty is allowed to accept") + } + contracts[contractId].status = ACCEPTED +} + +// Submit a funder by putting funds for specific milestones +func SubmitFunder(contractId uint64) { + caller := std.PrevRealm().Addr() + if int(contractId) >= len(contracts) { + panic("invalid contract id") + } + + contract := contracts[contractId] + + if contract.status != CREATED { + panic("can only submit candidate to a CREATED contract") + } + + if contract.funder != "" { + panic("the contract has already a funder") + } + + if caller == contract.contractor { + panic("you cannot become a funder of your requested contract") + } + + sent := std.GetOrigSend() + amount := sent.AmountOf(contract.paymentDenom) + if amount != contract.budget { + panic("wrong amount of funds sent") + } + + contracts[contractId].funded = true + contracts[contractId].status = ACCEPTED + contracts[contractId].funder = caller +} + +// Accept candidate as a contractor +func AcceptContractor(contractId uint64, contractor std.Address) { + if !contractor.IsValid() { + panic("invalid contractor address") + } + + caller := std.PrevRealm().Addr() + if int(contractId) >= len(contracts) { + panic("invalid contract id") + } + + contract := contracts[contractId] + + if contract.status != CREATED { + panic("can only submit candidate to a CREATED contract") + } + + if contract.contractor != "" { + panic("the contract has already a contractor") + } + + if caller != contract.funder { + panic("Only contract funder can accept contractor") + } + + candidates := contracts[contractId].contractorCandidates + for _, candidate := range candidates { + // Accept the contract if the address already submitted candidate request + if candidate == contractor { + contracts[contractId].status = ACCEPTED + } + } + + contracts[contractId].contractor = contractor + + funderKey := contract.funder.String() + byIDTreeIface, ok := contractsWithCandidates.Get(funderKey) + if !ok { + byIDTreeIface = avl.NewTree() + contractsWithCandidates.Set(funderKey, byIDTreeIface) + } + byIDTree := byIDTreeIface.(*avl.Tree) + byIDTree.Remove(seqid.ID(contract.id).String()) + if byIDTree.Size() == 0 { + contractsWithCandidates.Remove(funderKey) + } +} + +func SubmitContractorCandidate(contractId uint64) { + caller := std.PrevRealm().Addr() + if int(contractId) >= len(contracts) { + panic("invalid contract id") + } + + contract := contracts[contractId] + + if contract.status != CREATED { + panic("can only submit candidate to a CREATED contract") + } + + if contract.contractor != "" { + panic("the contract has already a contractor") + } + + if caller == contract.funder { + panic("you cannot become a contractor of your funded contract") + } + + candidates := contracts[contractId].contractorCandidates + for _, candidate := range candidates { + if candidate == caller { + panic("already a contractor candidate") + } + } + + contracts[contractId].contractorCandidates = append(candidates, caller) + + funderKey := contract.funder.String() + byIDTree, ok := contractsWithCandidates.Get(funderKey) + if !ok { + byIDTree = avl.NewTree() + contractsWithCandidates.Set(funderKey, byIDTree) + } + byIDTree.(*avl.Tree).Set(seqid.ID(contract.id).String(), contract) +} + +// Complete any milestone in review status and pay the needed amount +func CompleteMilestoneAndPay(contractId uint64, milestoneId uint64) { + caller := std.PrevRealm().Addr() + if int(contractId) >= len(contracts) { + panic("invalid contract id") + } + + contract := contracts[contractId] + if contract.funder != caller { + panic("only contract funder can pay the milestone") + } + + if contract.status != ACCEPTED { + panic("only accepted contract can be paid") + } + + milestone := contract.milestones[milestoneId] + if milestone.status != MS_REVIEW { + panic("can only complete and pay a milestone which is in review status") + } + + // Pay the milestone + unpaid := milestone.amount - milestone.paid + if unpaid > 0 { + banker := std.GetBanker(std.BankerTypeRealmSend) + banker.SendCoins( + std.CurrentRealm().Addr(), + contract.contractor, + std.Coins{std.Coin{contract.paymentDenom, int64(unpaid)}}) + contracts[contractId].milestones[milestoneId].paid += unpaid + } + + contracts[contractId].milestones[milestoneId].status = MS_COMPLETED + + // If finish all milestone then complete the contract + completedCount := 0 + for _, milestone := range contract.milestones { + if milestone.status == MS_COMPLETED { + completedCount++ + } + } + + if completedCount == len(contract.milestones) { + contracts[contractId].status = COMPLETED + } +} + +// Set milestone status +func ChangeMilestoneStatus(contractId uint64, milestoneId int, newStatus MilestoneStatus) { + if newStatus == MS_COMPLETED { + panic("use CompleteMilestoneAndPay to complete and pay the milestone") + } + + if int(contractId) >= len(contracts) { + panic("invalid contract id") + } + contract := contracts[contractId] + + caller := std.PrevRealm().Addr() + if contract.funder != caller && contract.contractor != caller { + panic("only contract participant can execute the action") + } + + if contract.status != ACCEPTED { + panic("contract is not on accepted status") + } + + if len(contract.milestones) <= milestoneId { + panic("milestone Id does not exist in contract") + } + milestone := contract.milestones[milestoneId] + + if milestone.status == MS_COMPLETED { + panic("milestone is completed") + } + + contracts[contractId].milestones[milestoneId].status = newStatus +} + +func RequestConflictResolution(contractId uint64, message string) { + caller := std.PrevRealm().Addr() + if int(contractId) >= len(contracts) { + panic("invalid contract id") + } + + contract := contracts[contractId] + if contract.funder != caller && contract.contractor != caller { + panic("only contract participants can request conflict resolution") + } + + if contract.status != ACCEPTED { + panic("conflict resolution can only be requested at ACCEPTED status") + } + + contracts[contractId].status = CONFLICT + + contracts[contractId].conflicts = append(contract.conflicts, Conflict{ + initiator: caller, + createdAt: time.Now(), + initiatorMessage: message, + }) +} + +func RespondToConflict(contractId uint64, message string) { + caller := std.PrevRealm().Addr() + if int(contractId) >= len(contracts) { + panic("invalid contract id") + } + + contract := contracts[contractId] + if contract.status != CONFLICT { + panic("conflict can only be responded at CONFLICT status") + } + + if len(contract.conflicts) == 0 { + panic("no conflict exists, this should not happen") + } + + conflictId := len(contract.conflicts) - 1 + conflict := contract.conflicts[conflictId] + + if conflict.initiator == contract.funder { + if contract.contractor != caller { + panic("only contract funder can respond to this conflict") + } + } else if conflict.initiator == contract.contractor { + if contract.funder != caller { + panic("only contract contractor can respond to this conflict") + } + } else { + panic("conflict initiator is not valid") + } + + contracts[contractId].conflicts[conflictId].responseMessage = &message + now := time.Now() + contracts[contractId].conflicts[conflictId].respondedAt = &now +} + +func ResolveConflict(contractId uint64, outcome ConflictOutcome, resolutionMessage string) { + caller := std.PrevRealm().Addr() + if int(contractId) >= len(contracts) { + panic("invalid contract id") + } + + contract := contracts[contractId] + if contract.conflictHandler != caller.String() { + panic("only conflictHandler is allowed for this operation") + } + + if contract.status != CONFLICT { + panic("conflict can only be resolved at CONFLICT status") + } + + if len(contract.conflicts) == 0 { + panic("no conflict exists") + } + + conflictId := len(contract.conflicts) - 1 + + switch outcome { + case RESUME_CONTRACT: + contracts[contractId].status = ACCEPTED + case REFUND_FUNDER: + totalPaid := int64(0) + for _, milestone := range contract.milestones { + totalPaid += milestone.paid + } + banker := std.GetBanker(std.BankerTypeRealmSend) + banker.SendCoins( + std.CurrentRealm().Addr(), + contract.funder, + std.Coins{std.Coin{contract.paymentDenom, contract.budget - totalPaid}}) + contracts[contractId].status = ABORTED_IN_FAVOR_OF_FUNDER + case PAY_CONTRACTOR: + totalPaid := int64(0) + for _, milestone := range contract.milestones { + totalPaid += milestone.paid + } + banker := std.GetBanker(std.BankerTypeRealmSend) + banker.SendCoins( + std.CurrentRealm().Addr(), + contract.contractor, + std.Coins{std.Coin{contract.paymentDenom, contract.budget - totalPaid}}) + contracts[contractId].status = ABORTED_IN_FAVOR_OF_CONTRACTOR + default: + panic("invalid outcome") + } + + contracts[contractId].conflicts[conflictId].resolutionMessage = &resolutionMessage + contracts[contractId].conflicts[conflictId].outcome = &outcome + now := time.Now() + contracts[contractId].conflicts[conflictId].resolvedAt = &now +} + +func GetContractorCandidatesJSON(contractId uint64) string { + if int(contractId) >= len(contracts) { + panic("invalid contract id") + } + + candidates := contracts[contractId].contractorCandidates + candidatesJSON := make([]*json.Node, len(candidates)) + for i, candidate := range candidates { + candidatesJSON[i] = json.StringNode("", candidate.String()) + } + + ret, err := json.Marshal(json.ArrayNode("", candidatesJSON)) + if err != nil { + panic(err) + } + return string(ret) +} + +func GetContracts(offset, limit int, filter Filter) []*Contract { + if offset < 0 { + offset = 0 + } + + if limit <= 0 || offset >= len(contracts) { + return nil + } + + if filter == nil { + end := offset + limit + if end > len(contracts) { + end = len(contracts) + } + return contracts[offset:end] + } + + var tree interface{} + switch f := filter.(type) { + case *FilterByCandidatesForFunder: + tree, _ = contractsWithCandidates.Get(f.Funder.String()) + case *FilterByContractorAndFunder: + tree, _ = contractsByFunderAndContractor.Get(f.Funder.String() + f.Contractor.String()) + case *FilterByContractor: + tree, _ = contractsByContractor.Get(f.Contractor.String()) + case *FilterByFunder: + tree, _ = contractsByFunder.Get(f.Funder.String()) + default: + panic("unknown filter") + } + + if tree == nil { + return nil + } + + var results []*Contract + tree.(*avl.Tree).IterateByOffset(offset, limit, func(key string, value interface{}) bool { + results = append(results, value.(*Contract)) + return false + }) + + return results +} + +func RenderContractJSON(contractId uint64) string { + if int(contractId) >= len(contracts) { + panic("invalid contract id") + } + + c := contracts[contractId] + ret, err := json.Marshal(c.ToJSON()) + if err != nil { + panic(err) + } + + return string(ret) +} + +func RenderContractsJSON(offset, limit int, filterJSON string) string { + filter := FilterFromJSON(json.Must(json.Unmarshal([]byte(filterJSON)))) + contractsRes := GetContracts(offset, limit, filter) + return renderContractsJSON(contractsRes) +} + +func renderContractsJSON(contractsRes []*Contract) string { + contractsJSON := make([]*json.Node, len(contractsRes)) + for i, c := range contractsRes { + contractsJSON[i] = c.ToJSON() + } + + ret, err := json.Marshal(json.ArrayNode("", contractsJSON)) + if err != nil { + panic(err) + } + return string(ret) +} + +func Render(path string) string { + b := strings.Builder{} + b.WriteString("# Projects Manager\n") + b.WriteString("## Overview\n") + b.WriteString("This contract is a simple project manager that allows users to create projects and manage them.\n") + b.WriteString(ufmt.Sprintf("Contracts managed: %d\n", len(contracts))) + b.WriteString("## Latest projects\n") + numContracts := 3 + if len(contracts) < 3 { + numContracts = len(contracts) + } + for i := 0; i < numContracts; i++ { + b.WriteString("```json\n") + b.WriteString(RenderContractJSON(uint64(len(contracts) - (i + 1)))) + b.WriteRune('\n') + b.WriteString("```\n") + } + return b.String() +} diff --git a/gno/r/projects_manager/projects_manager_test.gno b/gno/r/projects_manager/projects_manager_test.gno new file mode 100644 index 0000000000..f9c5d7d9dc --- /dev/null +++ b/gno/r/projects_manager/projects_manager_test.gno @@ -0,0 +1,74 @@ +package projects_manager + +import ( + "std" + "testing" + "time" + + "gno.land/p/demo/json" +) + +func TestJSONRender(t *testing.T) { + createdAt := time.Date(2021, time.August, 1, 0, 0, 0, 0, time.UTC) + duration := time.Hour * 24 * 30 + expireAt := createdAt.Add(duration) + + // golden contract + contract := Contract{ + id: 1, + sender: std.Address("sender"), + contractor: std.Address("contractor2"), + contractorCandidates: []std.Address{"contractor1", "contractor2"}, + funder: "funder", + paymentDenom: "denom", + metadata: "metadata", + status: CREATED, + expireAt: expireAt, + funderFeedback: "funderFeedback", + contractorFeedback: "contractorFeedback", + milestones: []Milestone{ + { + id: 1, + title: "title", + desc: "desc", + amount: 100, + paid: 0, + duration: duration, + link: "link", + funded: false, + priority: MS_PRIORITY_HIGH, + status: MS_OPEN, + }, + }, + pausedBy: "pausedBy", + conflictHandler: "conflictHandler", + handlerCandidate: "handlerCandidate", + handlerSuggestor: "handlerSuggestor", + createdAt: createdAt, + budget: 1000, + funded: false, + rejectReason: "rejectReason", + conflicts: []Conflict{ + { + initiator: "initiator", + createdAt: createdAt, + respondedAt: nil, + resolvedAt: nil, + initiatorMessage: "initiatorMessage", + responseMessage: nil, + resolutionMessage: nil, + outcome: nil, + }, + }, + } + + output, err := json.Marshal(contract.ToJSON()) + if err != nil { + t.Fatalf("Error marshalling contract to JSON: %s", err) + } + + expected := `{"id":"1","sender":"sender","contractor":"contractor2","contractorCandidates":["contractor1","contractor2"],"funder":"funder","paymentDenom":"denom","metadata":"metadata","status":"CREATED","expireAt":"2021-08-31T00:00:00Z","funderFeedback":"funderFeedback","contractorFeedback":"contractorFeedback","milestones":[{"id":"1","title":"title","desc":"desc","amount":"100","paid":"0","duration":2592000,"link":"link","funded":false,"priority":"MS_PRIORITY_HIGH","status":"MS_OPEN"}],"pausedBy":"pausedBy","conflictHandler":"conflictHandler","handlerCandidate":"handlerCandidate","handlerSuggestor":"handlerSuggestor","createdAt":"2021-08-01T00:00:00Z","budget":"1000","funded":false,"rejectReason":"rejectReason","conflicts":[{"initiator":"initiator","createdAt":"2021-08-01T00:00:00Z","initiatorMessage":"initiatorMessage"}]}` + if string(output) != expected { + t.Errorf("Expected output to be `%s`, got:\n`%s`", expected, string(output)) + } +} diff --git a/gno/r/social_feeds/gno.mod b/gno/r/social_feeds/gno.mod index 29da62ea3d..4da5feb0eb 100644 --- a/gno/r/social_feeds/gno.mod +++ b/gno/r/social_feeds/gno.mod @@ -2,9 +2,9 @@ module gno.land/r/teritori/social_feeds require ( gno.land/p/demo/avl v0.0.0-latest + gno.land/p/demo/testutils v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest gno.land/p/teritori/dao_interfaces v0.0.0-latest gno.land/p/teritori/flags_index v0.0.0-latest gno.land/p/teritori/ujson v0.0.0-latest - gno.land/p/demo/testutils v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest ) diff --git a/go/pkg/networks/features.gen.go b/go/pkg/networks/features.gen.go index 06b1db6db7..176738c009 100644 --- a/go/pkg/networks/features.gen.go +++ b/go/pkg/networks/features.gen.go @@ -18,6 +18,7 @@ const ( FeatureTypeRiotP2E = FeatureType("RiotP2E") FeatureTypeNFTBridge = FeatureType("NFTBridge") FeatureTypeCosmWasmPremiumFeed = FeatureType("CosmWasmPremiumFeed") + FeatureTypeGnoProjectManager = FeatureType("GnoProjectManager") FeatureTypeNFTMarketplaceLeaderboard = FeatureType("NFTMarketplaceLeaderboard") FeatureTypeCosmWasmNFTsBurner = FeatureType("CosmWasmNFTsBurner") ) @@ -61,6 +62,26 @@ func (nb *NetworkBase) GetFeatureCosmWasmNFTsBurner() (*FeatureCosmWasmNFTsBurne return feature.(*FeatureCosmWasmNFTsBurner), nil } +type FeatureGnoProjectManager struct { + *FeatureBase + ProjectsManagerPkgPath string `json:"projectsManagerPkgPath"` + PaymentsDenom string `json:"paymentsDenom"` +} + +var _ Feature = &FeatureGnoProjectManager{} + +func (f FeatureGnoProjectManager) Type() FeatureType { + return FeatureTypeGnoProjectManager +} + +func (nb *NetworkBase) GetFeatureGnoProjectManager() (*FeatureGnoProjectManager, error) { + feature, err := nb.GetFeature(FeatureTypeGnoProjectManager) + if err != nil { + return nil, err + } + return feature.(*FeatureGnoProjectManager), nil +} + func UnmarshalFeature(b []byte) (Feature, error) { var base FeatureBase if err := json.Unmarshal(b, &base); err != nil { @@ -79,6 +100,12 @@ func UnmarshalFeature(b []byte) (Feature, error) { return nil, errors.Wrap(err, "failed to unmarshal feature CosmWasmNFTsBurner") } return &f, nil + case FeatureTypeGnoProjectManager: + var f FeatureGnoProjectManager + if err := json.Unmarshal(b, &f); err != nil { + return nil, errors.Wrap(err, "failed to unmarshal feature GnoProjectManager") + } + return &f, nil } return nil, errors.Errorf("unknown feature type %s", base.Type) } diff --git a/networks.json b/networks.json index e001ce5d81..12a222e74e 100644 --- a/networks.json +++ b/networks.json @@ -10,6 +10,7 @@ "kind": "native", "denom": "uebl", "decimals": 6, + "variant": "cosmos", "displayName": "EBL", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/8ball/images/8ball.svg", @@ -48,6 +49,7 @@ "kind": "native", "denom": "aacre", "decimals": 18, + "variant": "cosmos", "displayName": "ACRE", "coingeckoId": "arable-protocol", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/acrechain/images/acre.svg", @@ -57,6 +59,7 @@ "kind": "native", "denom": "erc20/0x2Cbea61fdfDFA520Ee99700F104D5b75ADf50B0c", "decimals": 18, + "variant": "cosmos", "displayName": "arUSD", "coingeckoId": "arable-usd", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/acrechain/images/arusd.svg", @@ -66,6 +69,7 @@ "kind": "native", "denom": "erc20/0xAE6D3334989a22A65228732446731438672418F2", "decimals": 18, + "variant": "cosmos", "displayName": "CNTO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/acrechain/images/cnto.svg", @@ -104,6 +108,7 @@ "kind": "native", "denom": "ubld", "decimals": 6, + "variant": "cosmos", "displayName": "BLD", "coingeckoId": "agoric", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/agoric/images/bld.svg", @@ -113,6 +118,7 @@ "kind": "native", "denom": "uist", "decimals": 6, + "variant": "cosmos", "displayName": "IST", "coingeckoId": "inter-stable-token", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/agoric/images/ist.svg", @@ -151,6 +157,7 @@ "kind": "native", "denom": "attoaioz", "decimals": 18, + "variant": "cosmos", "displayName": "AIOZ", "coingeckoId": "aioz-network", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/aioz/images/aioz.svg", @@ -189,6 +196,7 @@ "kind": "native", "denom": "uakt", "decimals": 6, + "variant": "cosmos", "displayName": "AKT", "coingeckoId": "akash-network", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/akash/images/akt.svg", @@ -227,6 +235,7 @@ "kind": "native", "denom": "uandr", "decimals": 6, + "variant": "cosmos", "displayName": "ANDR", "coingeckoId": "andromeda-2", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/andromeda/images/andromeda-logo.png", @@ -265,6 +274,7 @@ "kind": "native", "denom": "utia", "decimals": 6, + "variant": "cosmos", "displayName": "TIA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/celestiatestnet2/images/celestia.svg", @@ -302,6 +312,7 @@ "kind": "native", "denom": "aarch", "decimals": 18, + "variant": "cosmos", "displayName": "ARCH", "coingeckoId": "archway", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/archway/images/archway.svg", @@ -311,6 +322,7 @@ "kind": "native", "denom": "cw20:archway1fwurjg7ah4v7hhs6xsc3wutqpvmahrfhns285s0lt34tgfdhplxq6m8xg5", "decimals": 6, + "variant": "cosmos", "displayName": "ampARCH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/archway/images/amparch.png", @@ -349,6 +361,7 @@ "kind": "native", "denom": "aconst", "decimals": 18, + "variant": "cosmos", "displayName": "CONST", "coingeckoId": "not-found", "icon": "not-found", @@ -387,6 +400,7 @@ "kind": "native", "denom": "uarkeo", "decimals": 6, + "variant": "cosmos", "displayName": "ARKEO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/arkeonetworktestnet/images/arkeo.png", @@ -424,6 +438,7 @@ "kind": "native", "denom": "arkh", "decimals": 6, + "variant": "cosmos", "displayName": "ARKH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/arkh/images/arkh.svg", @@ -462,6 +477,7 @@ "kind": "native", "denom": "uart", "decimals": 18, + "variant": "cosmos", "displayName": "ART", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/artelatestnet/images/artela.png", @@ -499,6 +515,7 @@ "kind": "native", "denom": "umntl", "decimals": 6, + "variant": "cosmos", "displayName": "MNTL", "coingeckoId": "assetmantle", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/assetmantle/images/mntl.svg", @@ -537,6 +554,7 @@ "kind": "native", "denom": "ueaura", "decimals": 6, + "variant": "cosmos", "displayName": "EAURA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/aura/images/Aura-logo-2.2.svg", @@ -575,6 +593,7 @@ "kind": "native", "denom": "uaura", "decimals": 6, + "variant": "cosmos", "displayName": "AURA", "coingeckoId": "aura-network", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/aura/images/Aura-logo-2.2.svg", @@ -613,6 +632,7 @@ "kind": "native", "denom": "uaxl", "decimals": 6, + "variant": "cosmos", "displayName": "AXL", "coingeckoId": "axelar", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/axelar/images/axl.svg", @@ -622,6 +642,7 @@ "kind": "native", "denom": "uusdc", "decimals": 6, + "variant": "cosmos", "displayName": "USDC", "coingeckoId": "axlusdc", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/axelar/images/usdc.svg", @@ -631,6 +652,7 @@ "kind": "native", "denom": "frax-wei", "decimals": 18, + "variant": "cosmos", "displayName": "FRAX", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/frax.svg", @@ -640,6 +662,7 @@ "kind": "native", "denom": "dai-wei", "decimals": 18, + "variant": "cosmos", "displayName": "DAI", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/axelar/images/dai.svg", @@ -649,6 +672,7 @@ "kind": "native", "denom": "uusdt", "decimals": 6, + "variant": "cosmos", "displayName": "USDT", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/axelar/images/usdt.svg", @@ -658,6 +682,7 @@ "kind": "native", "denom": "weth-wei", "decimals": 18, + "variant": "cosmos", "displayName": "WETH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/axelar/images/weth.png", @@ -667,6 +692,7 @@ "kind": "native", "denom": "wbtc-satoshi", "decimals": 8, + "variant": "cosmos", "displayName": "WBTC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/axelar/images/wbtc.png", @@ -676,6 +702,7 @@ "kind": "native", "denom": "aave-wei", "decimals": 18, + "variant": "cosmos", "displayName": "AAVE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/aave.svg", @@ -685,6 +712,7 @@ "kind": "native", "denom": "ape-wei", "decimals": 18, + "variant": "cosmos", "displayName": "APE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/ape.svg", @@ -694,6 +722,7 @@ "kind": "native", "denom": "axs-wei", "decimals": 18, + "variant": "cosmos", "displayName": "AXS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/axs.svg", @@ -703,6 +732,7 @@ "kind": "native", "denom": "link-wei", "decimals": 18, + "variant": "cosmos", "displayName": "LINK", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/link.svg", @@ -712,6 +742,7 @@ "kind": "native", "denom": "mkr-wei", "decimals": 18, + "variant": "cosmos", "displayName": "MKR", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/mkr.svg", @@ -721,6 +752,7 @@ "kind": "native", "denom": "rai-wei", "decimals": 18, + "variant": "cosmos", "displayName": "RAI", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/rai.svg", @@ -730,6 +762,7 @@ "kind": "native", "denom": "shib-wei", "decimals": 18, + "variant": "cosmos", "displayName": "SHIB", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/shib.svg", @@ -739,6 +772,7 @@ "kind": "native", "denom": "steth-wei", "decimals": 18, + "variant": "cosmos", "displayName": "stETH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/steth.svg", @@ -748,6 +782,7 @@ "kind": "native", "denom": "uni-wei", "decimals": 18, + "variant": "cosmos", "displayName": "UNI", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/uni.svg", @@ -757,6 +792,7 @@ "kind": "native", "denom": "xcn-wei", "decimals": 18, + "variant": "cosmos", "displayName": "XCN", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/xcn.svg", @@ -766,6 +802,7 @@ "kind": "native", "denom": "dot-planck", "decimals": 10, + "variant": "cosmos", "displayName": "DOT", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/polkadot/images/dot.svg", @@ -775,6 +812,7 @@ "kind": "native", "denom": "wglmr-wei", "decimals": 18, + "variant": "cosmos", "displayName": "WGLMR", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/moonbeam/images/glmr.svg", @@ -784,6 +822,7 @@ "kind": "native", "denom": "wmatic-wei", "decimals": 18, + "variant": "cosmos", "displayName": "WMATIC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/polygon/images/wmatic.svg", @@ -793,6 +832,7 @@ "kind": "native", "denom": "wbnb-wei", "decimals": 18, + "variant": "cosmos", "displayName": "WBNB", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/binancesmartchain/images/wbnb.svg", @@ -802,6 +842,7 @@ "kind": "native", "denom": "busd-wei", "decimals": 18, + "variant": "cosmos", "displayName": "BUSD", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/busd.png", @@ -811,6 +852,7 @@ "kind": "native", "denom": "wavax-wei", "decimals": 18, + "variant": "cosmos", "displayName": "WAVAX", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/avalanche/images/wavax.svg", @@ -820,6 +862,7 @@ "kind": "native", "denom": "wftm-wei", "decimals": 18, + "variant": "cosmos", "displayName": "WFTM", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/fantom/images/ftm.png", @@ -829,6 +872,7 @@ "kind": "native", "denom": "polygon-uusdc", "decimals": 6, + "variant": "cosmos", "displayName": "USDC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/axelar/images/usdc.svg", @@ -838,6 +882,7 @@ "kind": "native", "denom": "avalanche-uusdc", "decimals": 6, + "variant": "cosmos", "displayName": "USDC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/axelar/images/usdc.svg", @@ -847,6 +892,7 @@ "kind": "native", "denom": "wfil-wei", "decimals": 18, + "variant": "cosmos", "displayName": "axlFIL", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/filecoin/images/wfil.svg", @@ -856,6 +902,7 @@ "kind": "native", "denom": "arb-wei", "decimals": 18, + "variant": "cosmos", "displayName": "ARB", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/arbitrum/images/arb.svg", @@ -865,6 +912,7 @@ "kind": "native", "denom": "pepe-wei", "decimals": 18, + "variant": "cosmos", "displayName": "PEPE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/pepe.svg", @@ -874,6 +922,7 @@ "kind": "native", "denom": "cbeth-wei", "decimals": 18, + "variant": "cosmos", "displayName": "cbETH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/cbeth.png", @@ -883,6 +932,7 @@ "kind": "native", "denom": "reth-wei", "decimals": 18, + "variant": "cosmos", "displayName": "rETH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/reth.png", @@ -892,6 +942,7 @@ "kind": "native", "denom": "sfrxeth-wei", "decimals": 18, + "variant": "cosmos", "displayName": "sfrxETH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/sfrxeth.svg", @@ -901,6 +952,7 @@ "kind": "native", "denom": "wsteth-wei", "decimals": 18, + "variant": "cosmos", "displayName": "wstETH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/wsteth.svg", @@ -910,6 +962,7 @@ "kind": "native", "denom": "yieldeth-wei", "decimals": 18, + "variant": "cosmos", "displayName": "YieldETH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/yieldeth.svg", @@ -948,6 +1001,7 @@ "kind": "native", "denom": "uaxl", "decimals": 6, + "variant": "cosmos", "displayName": "AXL", "coingeckoId": "axelar", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/axelar/images/axl.svg", @@ -957,6 +1011,7 @@ "kind": "native", "denom": "uausdc", "decimals": 6, + "variant": "cosmos", "displayName": "aUSDC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/usdc.svg", @@ -966,6 +1021,7 @@ "kind": "native", "denom": "eth-wei", "decimals": 18, + "variant": "cosmos", "displayName": "axlWETH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/weth.svg", @@ -975,6 +1031,7 @@ "kind": "native", "denom": "wglmr-wei", "decimals": 18, + "variant": "cosmos", "displayName": "WDEV", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/moonbeam/images/glmr.svg", @@ -984,6 +1041,7 @@ "kind": "native", "denom": "wmatic-wei", "decimals": 18, + "variant": "cosmos", "displayName": "WMATIC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/polygon/images/wmatic.svg", @@ -993,6 +1051,7 @@ "kind": "native", "denom": "wbnb-wei", "decimals": 18, + "variant": "cosmos", "displayName": "WBNB", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/binancesmartchain/images/wbnb.svg", @@ -1002,6 +1061,7 @@ "kind": "native", "denom": "wavax-wei", "decimals": 18, + "variant": "cosmos", "displayName": "WAVAX", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/avalanche/images/wavax.svg", @@ -1011,6 +1071,7 @@ "kind": "native", "denom": "wftm-wei", "decimals": 18, + "variant": "cosmos", "displayName": "WFTM", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/fantom/images/ftm.png", @@ -1048,6 +1109,7 @@ "kind": "native", "denom": "uatom", "decimals": 6, + "variant": "cosmos", "displayName": "BBN", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/babylon/images/logo.svg", @@ -1086,6 +1148,7 @@ "kind": "native", "denom": "uband", "decimals": 6, + "variant": "cosmos", "displayName": "BAND", "coingeckoId": "band-protocol", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/bandchain/images/band.svg", @@ -1124,6 +1187,7 @@ "kind": "native", "denom": "ubze", "decimals": 6, + "variant": "cosmos", "displayName": "BZE", "coingeckoId": "bzedge", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/beezee/images/bze.svg", @@ -1162,6 +1226,7 @@ "kind": "native", "denom": "ubcna", "decimals": 6, + "variant": "cosmos", "displayName": "BCNA", "coingeckoId": "bitcanna", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/bitcanna/images/bcna.svg", @@ -1200,6 +1265,7 @@ "kind": "native", "denom": "ubcna", "decimals": 6, + "variant": "cosmos", "displayName": "BCNA", "coingeckoId": "bitcanna", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/bitcannadevnet/images/bcna.svg", @@ -1237,6 +1303,7 @@ "kind": "native", "denom": "ubcna", "decimals": 6, + "variant": "cosmos", "displayName": "BCNA", "coingeckoId": "bitcanna", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/bitcannadevnet2/images/bcna.svg", @@ -1274,6 +1341,7 @@ "kind": "native", "denom": "ubtsg", "decimals": 6, + "variant": "cosmos", "displayName": "BTSG", "coingeckoId": "bitsong", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/bitsong/images/btsg.svg", @@ -1283,6 +1351,7 @@ "kind": "native", "denom": "ft2D8E7041556CE93E1EFD66C07C45D551A6AAAE09", "decimals": 6, + "variant": "cosmos", "displayName": "CLAY", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/bitsong/images/ft2D8E7041556CE93E1EFD66C07C45D551A6AAAE09.png", @@ -1292,6 +1361,7 @@ "kind": "native", "denom": "ft25B30C386CDDEBD1413D5AE1180956AE9EB3B9F7", "decimals": 6, + "variant": "cosmos", "displayName": "FASANO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/bitsong/images/ft25B30C386CDDEBD1413D5AE1180956AE9EB3B9F7.png", @@ -1301,6 +1371,7 @@ "kind": "native", "denom": "ft575B10B0CEE2C164D9ED6A96313496F164A9607C", "decimals": 6, + "variant": "cosmos", "displayName": "D9X", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/bitsong/images/ft575B10B0CEE2C164D9ED6A96313496F164A9607C.png", @@ -1310,6 +1381,7 @@ "kind": "native", "denom": "ft56664FC98A2CF5F4FBAC3566D1A11D891AD88305", "decimals": 6, + "variant": "cosmos", "displayName": "FONTI", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/bitsong/images/ft56664FC98A2CF5F4FBAC3566D1A11D891AD88305.png", @@ -1319,6 +1391,7 @@ "kind": "native", "denom": "ft52EEB0EE509AC546ED92EAC8591F731F213DDD16", "decimals": 6, + "variant": "cosmos", "displayName": "BJKS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/bitsong/images/ft52EEB0EE509AC546ED92EAC8591F731F213DDD16.png", @@ -1328,6 +1401,7 @@ "kind": "native", "denom": "ftE4903ECC861CA45F2C2BC7EAB8255D2E6E87A33A", "decimals": 6, + "variant": "cosmos", "displayName": "RWNE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/bitsong/images/ftE4903ECC861CA45F2C2BC7EAB8255D2E6E87A33A.png", @@ -1337,6 +1411,7 @@ "kind": "native", "denom": "ft85AE1716C5E39EA6D64BBD7898C3899A7B500626", "decimals": 6, + "variant": "cosmos", "displayName": "ENMODA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/bitsong/images/ft85AE1716C5E39EA6D64BBD7898C3899A7B500626.png", @@ -1346,6 +1421,7 @@ "kind": "native", "denom": "ft99091610CCC66F4277C66D14AF2BC4C5EE52E27A", "decimals": 6, + "variant": "cosmos", "displayName": "404DR", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/bitsong/images/ft99091610CCC66F4277C66D14AF2BC4C5EE52E27A.png", @@ -1355,6 +1431,7 @@ "kind": "native", "denom": "ft387C1C279D962ED80C09C1D592A92C4275FD7C5D", "decimals": 6, + "variant": "cosmos", "displayName": "N43", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/bitsong/images/ft387C1C279D962ED80C09C1D592A92C4275FD7C5D.png", @@ -1364,6 +1441,7 @@ "kind": "native", "denom": "ft24C9FA4F10B0F235F4A815B15FC774E046A2B2EB", "decimals": 6, + "variant": "cosmos", "displayName": "LOBO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/bitsong/images/ft24C9FA4F10B0F235F4A815B15FC774E046A2B2EB.png", @@ -1373,6 +1451,7 @@ "kind": "native", "denom": "ft7020C2A8E984EEBCBB383E91CD6FBB067BB2272B", "decimals": 6, + "variant": "cosmos", "displayName": "VIBRA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/bitsong/images/ft7020C2A8E984EEBCBB383E91CD6FBB067BB2272B.png", @@ -1382,6 +1461,7 @@ "kind": "native", "denom": "ft2DD67F5D99E9A141142B48474FA7B6B3FF00A3FE", "decimals": 6, + "variant": "cosmos", "displayName": "KARINA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/bitsong/images/ft2DD67F5D99E9A141142B48474FA7B6B3FF00A3FE.png", @@ -1391,6 +1471,7 @@ "kind": "native", "denom": "ft4B030260D99E3ABE2B604EA2B33BAF3C085CDA12", "decimals": 6, + "variant": "cosmos", "displayName": "TESTA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/bitsong/images/ft4B030260D99E3ABE2B604EA2B33BAF3C085CDA12.png", @@ -1400,6 +1481,7 @@ "kind": "native", "denom": "ftD4B6290EDEE1EC7B97AB5A1DC6C177EFD08ADCC3", "decimals": 6, + "variant": "cosmos", "displayName": "CMQZ", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/bitsong/images/ftD4B6290EDEE1EC7B97AB5A1DC6C177EFD08ADCC3.png", @@ -1409,6 +1491,7 @@ "kind": "native", "denom": "ft347B1612A2B7659913679CF6CD45B8B130C50A00", "decimals": 6, + "variant": "cosmos", "displayName": "LDON", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/bitsong/images/ft347B1612A2B7659913679CF6CD45B8B130C50A00.png", @@ -1447,6 +1530,7 @@ "kind": "native", "denom": "utia", "decimals": 6, + "variant": "cosmos", "displayName": "TIA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/celestiatestnet/images/celestia.svg", @@ -1484,6 +1568,7 @@ "kind": "native", "denom": "ubnt", "decimals": 6, + "variant": "cosmos", "displayName": "BLZ", "coingeckoId": "bluzelle", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/bluzelle/images/bluzelle.svg", @@ -1493,6 +1578,7 @@ "kind": "native", "denom": "uelt", "decimals": 6, + "variant": "cosmos", "displayName": "ELT", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/bluzelle/images/elt.png", @@ -1502,6 +1588,7 @@ "kind": "native", "denom": "ug4", "decimals": 6, + "variant": "cosmos", "displayName": "G4", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/bluzelle/images/g4.png", @@ -1540,6 +1627,7 @@ "kind": "native", "denom": "boot", "decimals": 6, + "variant": "cosmos", "displayName": "BOOT", "coingeckoId": "bostrom", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/bostrom/images/boot.svg", @@ -1549,6 +1637,7 @@ "kind": "native", "denom": "hydrogen", "decimals": 6, + "variant": "cosmos", "displayName": "HYDROGEN", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/bostrom/images/hydrogen.svg", @@ -1558,6 +1647,7 @@ "kind": "native", "denom": "milliampere", "decimals": 3, + "variant": "cosmos", "displayName": "A", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/bostrom/images/ampere.svg", @@ -1567,6 +1657,7 @@ "kind": "native", "denom": "millivolt", "decimals": 3, + "variant": "cosmos", "displayName": "V", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/bostrom/images/volt.svg", @@ -1576,6 +1667,7 @@ "kind": "native", "denom": "tocyb", "decimals": 6, + "variant": "cosmos", "displayName": "TOCYB", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/bostrom/images/tocyb.svg", @@ -1614,6 +1706,7 @@ "kind": "native", "denom": "acanto", "decimals": 18, + "variant": "cosmos", "displayName": "CANTO", "coingeckoId": "canto", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/canto/images/canto.svg", @@ -1652,6 +1745,7 @@ "kind": "native", "denom": "swth", "decimals": 8, + "variant": "cosmos", "displayName": "SWTH", "coingeckoId": "switcheo", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/carbon/images/swth.svg", @@ -1661,6 +1755,7 @@ "kind": "native", "denom": "usc", "decimals": 8, + "variant": "cosmos", "displayName": "USC", "coingeckoId": "carbon-usd", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/carbon/images/usc.svg", @@ -1670,6 +1765,7 @@ "kind": "native", "denom": "bnb.1.6.773edb", "decimals": 18, + "variant": "cosmos", "displayName": "BNB", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/binancesmartchain/images/bnb.svg", @@ -1679,6 +1775,7 @@ "kind": "native", "denom": "bneo.1.14.e2e5f6", "decimals": 8, + "variant": "cosmos", "displayName": "bNEO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/carbon/images/bneo.svg", @@ -1688,6 +1785,7 @@ "kind": "native", "denom": "busd.1.6.754a80", "decimals": 18, + "variant": "cosmos", "displayName": "BUSD", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/busd.png", @@ -1697,6 +1795,7 @@ "kind": "native", "denom": "cglp.1.19.1698d3", "decimals": 18, + "variant": "cosmos", "displayName": "CGLP", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/carbon/images/cglp.svg", @@ -1706,6 +1805,7 @@ "kind": "native", "denom": "cgt/1", "decimals": 18, + "variant": "cosmos", "displayName": "USD", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/carbon/images/carbon-grouped-usd.svg", @@ -1715,6 +1815,7 @@ "kind": "native", "denom": "eth.1.19.c3b805", "decimals": 18, + "variant": "cosmos", "displayName": "ETH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/eth.svg", @@ -1724,6 +1825,7 @@ "kind": "native", "denom": "eth.1.2.942d87", "decimals": 18, + "variant": "cosmos", "displayName": "ETH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/eth.svg", @@ -1733,6 +1835,7 @@ "kind": "native", "denom": "usdc.1.2.343151", "decimals": 6, + "variant": "cosmos", "displayName": "USDC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/usdc.svg", @@ -1742,6 +1845,7 @@ "kind": "native", "denom": "usdc.1.6.53ff75", "decimals": 18, + "variant": "cosmos", "displayName": "USDC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/usdc.svg", @@ -1751,6 +1855,7 @@ "kind": "native", "denom": "zil.1.18.1a4a06", "decimals": 12, + "variant": "cosmos", "displayName": "ZIL", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/carbon/images/zil.svg", @@ -1789,6 +1894,7 @@ "kind": "native", "denom": "aCC", "decimals": 18, + "variant": "cosmos", "displayName": "TCC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/cascadiatestnet/images/cascadia.png", @@ -1827,6 +1933,7 @@ "kind": "native", "denom": "utia", "decimals": 6, + "variant": "cosmos", "displayName": "TIA", "coingeckoId": "celestia", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/celestia/images/celestia.svg", @@ -1865,6 +1972,7 @@ "kind": "native", "denom": "ucrbrus", "decimals": 6, + "variant": "cosmos", "displayName": "CRBRUS", "coingeckoId": "cerberus-2", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/cerberus/images/crbrus.svg", @@ -1903,6 +2011,7 @@ "kind": "native", "denom": "uc4e", "decimals": 6, + "variant": "cosmos", "displayName": "C4E", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/chain4energy/images/c4e.png", @@ -1941,6 +2050,7 @@ "kind": "native", "denom": "uc4e", "decimals": 6, + "variant": "cosmos", "displayName": "C4E", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/chain4energytestnet/images/c4e.png", @@ -1979,6 +2089,7 @@ "kind": "native", "denom": "ncheq", "decimals": 9, + "variant": "cosmos", "displayName": "CHEQ", "coingeckoId": "cheqd-network", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/cheqd/images/cheq.svg", @@ -2017,6 +2128,7 @@ "kind": "native", "denom": "ncheq", "decimals": 9, + "variant": "cosmos", "displayName": "CHEQ", "coingeckoId": "cheqd-network", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/cheqdtestnet/images/cheq.svg", @@ -2055,6 +2167,7 @@ "kind": "native", "denom": "uhuahua", "decimals": 6, + "variant": "cosmos", "displayName": "HUAHUA", "coingeckoId": "chihuahua-token", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/chihuahua/images/huahua.svg", @@ -2064,6 +2177,7 @@ "kind": "native", "denom": "cw20:chihuahua1yl8z39ugle8s02fpwkhh293509q5xcpalmdzc4amvchz8nkexrmsy95gef", "decimals": 6, + "variant": "cosmos", "displayName": "PUPPY", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/chihuahua/images/puppyhuahua_logo.png", @@ -2073,6 +2187,7 @@ "kind": "native", "denom": "factory/chihuahua1x4q2vkrz4dfgd9hcw0p5m2f2nuv2uqmt9xr8k2/achihuahuawifhat", "decimals": 6, + "variant": "cosmos", "displayName": "BADDOG", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/chihuahua/images/baddog.png", @@ -2082,6 +2197,7 @@ "kind": "native", "denom": "factory/chihuahua13jawsn574rf3f0u5rhu7e8n6sayx5gkw3eddhp/uwoof", "decimals": 6, + "variant": "cosmos", "displayName": "WOOF", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/chihuahua/images/woof.png", @@ -2091,6 +2207,7 @@ "kind": "native", "denom": "factory/chihuahua13jawsn574rf3f0u5rhu7e8n6sayx5gkw3eddhp/utacos", "decimals": 6, + "variant": "cosmos", "displayName": "TACOS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/chihuahua/images/tacos.png", @@ -2100,6 +2217,7 @@ "kind": "native", "denom": "factory/chihuahua13jawsn574rf3f0u5rhu7e8n6sayx5gkw3eddhp/uweed", "decimals": 6, + "variant": "cosmos", "displayName": "WEED", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/chihuahua/images/weed.png", @@ -2109,6 +2227,7 @@ "kind": "native", "denom": "factory/chihuahua13jawsn574rf3f0u5rhu7e8n6sayx5gkw3eddhp/ubdog", "decimals": 6, + "variant": "cosmos", "displayName": "BDOG", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/chihuahua/images/bdog.png", @@ -2118,6 +2237,7 @@ "kind": "native", "denom": "factory/chihuahua13jawsn574rf3f0u5rhu7e8n6sayx5gkw3eddhp/ucorso", "decimals": 6, + "variant": "cosmos", "displayName": "CORSO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/chihuahua/images/corso.png", @@ -2156,6 +2276,7 @@ "kind": "native", "denom": "ucmba", "decimals": 6, + "variant": "cosmos", "displayName": "CMBA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/chimba/images/chimba-blue.svg", @@ -2194,6 +2315,7 @@ "kind": "native", "denom": "ucmba", "decimals": 6, + "variant": "cosmos", "displayName": "CMBA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/chimba/images/chimba-blue.svg", @@ -2231,6 +2353,7 @@ "kind": "native", "denom": "ucht", "decimals": 6, + "variant": "cosmos", "displayName": "CHT", "coingeckoId": "cht", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/chronicnetwork/images/cht.png", @@ -2240,6 +2363,7 @@ "kind": "native", "denom": "ucgas", "decimals": 6, + "variant": "cosmos", "displayName": "CGAS", "coingeckoId": "cgas", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/chronicnetwork/images/cgas.png", @@ -2277,6 +2401,7 @@ "kind": "native", "denom": "ucmdx", "decimals": 6, + "variant": "cosmos", "displayName": "CMDX", "coingeckoId": "comdex", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/comdex/images/cmdx.svg", @@ -2286,6 +2411,7 @@ "kind": "native", "denom": "uharbor", "decimals": 6, + "variant": "cosmos", "displayName": "HARBOR", "coingeckoId": "harbor-2", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/comdex/images/harbor.svg", @@ -2295,6 +2421,7 @@ "kind": "native", "denom": "ucmst", "decimals": 6, + "variant": "cosmos", "displayName": "CMST", "coingeckoId": "composite", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/comdex/images/cmst.svg", @@ -2333,6 +2460,7 @@ "kind": "native", "denom": "ucommercio", "decimals": 6, + "variant": "cosmos", "displayName": "COM", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/commercionetwork/images/com.svg", @@ -2342,6 +2470,7 @@ "kind": "native", "denom": "uccc", "decimals": 6, + "variant": "cosmos", "displayName": "CCC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/commercionetwork/images/ccc.svg", @@ -2380,6 +2509,7 @@ "kind": "native", "denom": "ppica", "decimals": 12, + "variant": "cosmos", "displayName": "PICA", "coingeckoId": "picasso", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/composable/images/pica.svg", @@ -2418,6 +2548,7 @@ "kind": "native", "denom": "ppica", "decimals": 12, + "variant": "cosmos", "displayName": "PICA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/composable/images/composable.svg", @@ -2455,6 +2586,7 @@ "kind": "native", "denom": "acvnt", "decimals": 18, + "variant": "cosmos", "displayName": "CVN", "coingeckoId": "consciousdao", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/conscious/images/cvn.svg", @@ -2493,6 +2625,7 @@ "kind": "native", "denom": "uccat", "decimals": 6, + "variant": "cosmos", "displayName": "CCAT", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/coolcattestnet/images/coolcat.svg", @@ -2530,6 +2663,7 @@ "kind": "native", "denom": "utestcore", "decimals": 6, + "variant": "cosmos", "displayName": "TESTCORE", "coingeckoId": "coreum", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/coreum/images/coreum.svg", @@ -2569,6 +2703,7 @@ "denom": "uatom", "displayName": "ATOM", "decimals": 6, + "variant": "cosmos", "coingeckoId": "cosmos", "icon": "cosmos-hub-circle.svg", "kind": "native", @@ -2614,6 +2749,7 @@ "denom": "uatom", "displayName": "ATOM", "decimals": 6, + "variant": "cosmos", "coingeckoId": "cosmos", "icon": "cosmos-hub-circle.svg", "kind": "native", @@ -2654,6 +2790,7 @@ "kind": "native", "denom": "umlg", "decimals": 6, + "variant": "cosmos", "displayName": "MLG", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/cosmwasmtestnet/images/cosmwasm.svg", @@ -2663,6 +2800,7 @@ "kind": "native", "denom": "uand", "decimals": 6, + "variant": "cosmos", "displayName": "AND", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/cosmwasmtestnet/images/cosmwasm.svg", @@ -2700,6 +2838,7 @@ "kind": "native", "denom": "ucgas", "decimals": 6, + "variant": "cosmos", "displayName": "CGAS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/coss/images/cgas.svg", @@ -2709,6 +2848,7 @@ "kind": "native", "denom": "ucoss", "decimals": 6, + "variant": "cosmos", "displayName": "COSS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/coss/images/coss.svg", @@ -2747,6 +2887,7 @@ "kind": "native", "denom": "ucgas", "decimals": 6, + "variant": "cosmos", "displayName": "cgas", "coingeckoId": "not-found", "icon": "not-found", @@ -2784,6 +2925,7 @@ "kind": "native", "denom": "ucre", "decimals": 6, + "variant": "cosmos", "displayName": "CRE", "coingeckoId": "crescent-network", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/crescent/images/cre.svg", @@ -2793,6 +2935,7 @@ "kind": "native", "denom": "ubcre", "decimals": 6, + "variant": "cosmos", "displayName": "bCRE", "coingeckoId": "liquid-staking-crescent", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/crescent/images/bcre.svg", @@ -2831,6 +2974,7 @@ "kind": "native", "denom": "basecro", "decimals": 18, + "variant": "cosmos", "displayName": "CRO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/cronos/images/cro.svg", @@ -2869,6 +3013,7 @@ "kind": "native", "denom": "basecro", "decimals": 8, + "variant": "cosmos", "displayName": "CRO", "coingeckoId": "crypto-com-chain", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/cronos/images/cro.svg", @@ -2907,6 +3052,7 @@ "kind": "native", "denom": "acudos", "decimals": 18, + "variant": "cosmos", "displayName": "CUDOS", "coingeckoId": "cudos", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/cudos/images/cudos.svg", @@ -2945,6 +3091,7 @@ "kind": "native", "denom": "acudos", "decimals": 18, + "variant": "cosmos", "displayName": "CUDOS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/cudostestnet/images/cudos.svg", @@ -2982,6 +3129,7 @@ "kind": "native", "denom": "udear", "decimals": 6, + "variant": "cosmos", "displayName": "DEAR", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/deardogetestnet/images/deardoge.png", @@ -3019,6 +3167,7 @@ "kind": "native", "denom": "udec", "decimals": 6, + "variant": "cosmos", "displayName": "DEC", "coingeckoId": "decentr", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/decentr/images/dec.svg", @@ -3057,6 +3206,7 @@ "kind": "native", "denom": "udsm", "decimals": 6, + "variant": "cosmos", "displayName": "DSM", "coingeckoId": "desmos", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/desmos/images/dsm.svg", @@ -3095,6 +3245,7 @@ "kind": "native", "denom": "udaric", "decimals": 6, + "variant": "cosmos", "displayName": "DARIC", "coingeckoId": "desmos", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/desmos/images/dsm.svg", @@ -3133,6 +3284,7 @@ "kind": "native", "denom": "uself", "decimals": 6, + "variant": "cosmos", "displayName": "SELF", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/selfchaindevnet/images/selfchain.png", @@ -3170,6 +3322,7 @@ "kind": "native", "denom": "udig", "decimals": 6, + "variant": "cosmos", "displayName": "DIG", "coingeckoId": "dig-chain", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/dig/images/dig.png", @@ -3208,6 +3361,7 @@ "kind": "native", "denom": "peaka", "decimals": 18, + "variant": "cosmos", "displayName": "DORA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/doravota/images/dora.svg", @@ -3245,6 +3399,7 @@ "kind": "native", "denom": "peaka", "decimals": 18, + "variant": "cosmos", "displayName": "DORA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/doravotatestnet/images/doravota.png", @@ -3282,6 +3437,7 @@ "kind": "native", "denom": "peaka", "decimals": 18, + "variant": "cosmos", "displayName": "DORA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/doravotatestnet/images/doravota.png", @@ -3319,6 +3475,7 @@ "kind": "native", "denom": "adydx", "decimals": 18, + "variant": "cosmos", "displayName": "DYDX", "coingeckoId": "dydx", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/dydx/images/dydx.svg", @@ -3357,6 +3514,7 @@ "kind": "native", "denom": "adydx", "decimals": 18, + "variant": "cosmos", "displayName": "DYDX", "coingeckoId": "dydx", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/dydx/images/dydx.svg", @@ -3395,6 +3553,7 @@ "kind": "native", "denom": "dys", "decimals": 6, + "variant": "cosmos", "displayName": "DYS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/dyson/images/dys.svg", @@ -3433,6 +3592,7 @@ "kind": "native", "denom": "ungm", "decimals": 6, + "variant": "cosmos", "displayName": "NGM", "coingeckoId": "e-money", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/emoney/images/ngm.svg", @@ -3442,6 +3602,7 @@ "kind": "native", "denom": "eeur", "decimals": 6, + "variant": "cosmos", "displayName": "EEUR", "coingeckoId": "e-money-eur", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/emoney/images/eeur.svg", @@ -3451,6 +3612,7 @@ "kind": "native", "denom": "echf", "decimals": 6, + "variant": "cosmos", "displayName": "ECHF", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/emoney/images/echf.svg", @@ -3460,6 +3622,7 @@ "kind": "native", "denom": "enok", "decimals": 6, + "variant": "cosmos", "displayName": "ENOK", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/emoney/images/enok.svg", @@ -3469,6 +3632,7 @@ "kind": "native", "denom": "edkk", "decimals": 6, + "variant": "cosmos", "displayName": "EDKK", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/emoney/images/edkk.svg", @@ -3478,6 +3642,7 @@ "kind": "native", "denom": "esek", "decimals": 6, + "variant": "cosmos", "displayName": "ESEK", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/emoney/images/esek.svg", @@ -3516,6 +3681,7 @@ "kind": "native", "denom": "aechelon", "decimals": 18, + "variant": "cosmos", "displayName": "ECH", "coingeckoId": "echelon", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/echelon/images/ech.svg", @@ -3554,6 +3720,7 @@ "kind": "native", "denom": "uelys", "decimals": 6, + "variant": "cosmos", "displayName": "ELYS", "coingeckoId": "elys", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/elystestnet/images/elys.png", @@ -3563,6 +3730,7 @@ "kind": "native", "denom": "ueden", "decimals": 6, + "variant": "cosmos", "displayName": "EDEN", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/elystestnet/images/eden.png", @@ -3600,6 +3768,7 @@ "kind": "native", "denom": "umpwr", "decimals": 6, + "variant": "cosmos", "displayName": "MPWR", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/empowertestnet/images/mpwr.png", @@ -3637,6 +3806,7 @@ "kind": "native", "denom": "umpwr", "decimals": 6, + "variant": "cosmos", "displayName": "MPWR", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/empowerchain/images/mpwr.svg", @@ -3674,6 +3844,7 @@ "kind": "native", "denom": "uentry", "decimals": 6, + "variant": "cosmos", "displayName": "ENTRY", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/entrypointtestnet/images/entry.svg", @@ -3717,6 +3888,7 @@ "denom": "0x0000000000000000000000000000000000000000", "displayName": "ETH", "decimals": 18, + "variant": "ethereum", "coingeckoId": "ethereum", "icon": "ethereum-circle.svg", "kind": "native", @@ -3762,6 +3934,7 @@ "denom": "0x0000000000000000000000000000000000000000", "displayName": "GoerliETH", "decimals": 18, + "variant": "ethereum", "coingeckoId": "ethereum", "icon": "ethereum-circle.svg", "kind": "native", @@ -3802,6 +3975,7 @@ "kind": "native", "denom": "aRYT", "decimals": 18, + "variant": "cosmos", "displayName": "RYT", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/ethos/images/ethos.svg", @@ -3840,6 +4014,7 @@ "kind": "native", "denom": "aevmos", "decimals": 18, + "variant": "cosmos", "displayName": "EVMOS", "coingeckoId": "evmos", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/evmos/images/evmos.svg", @@ -3849,6 +4024,7 @@ "kind": "native", "denom": "erc20/0x655ecB57432CC1370f65e5dc2309588b71b473A9", "decimals": 18, + "variant": "cosmos", "displayName": "NEOK", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/evmos/images/neok.svg", @@ -3887,6 +4063,7 @@ "kind": "native", "denom": "atevmos", "decimals": 18, + "variant": "cosmos", "displayName": "TEVMOS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/evmostestnet/images/evmos.svg", @@ -3924,6 +4101,7 @@ "kind": "native", "denom": "FX", "decimals": 18, + "variant": "cosmos", "displayName": "FX", "coingeckoId": "fx-coin", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/fxcore/images/fx.svg", @@ -3933,6 +4111,7 @@ "kind": "native", "denom": "eth0x0FD10b9899882a6f2fcb5c371E17e70FdEe00C38", "decimals": 18, + "variant": "cosmos", "displayName": "PUNDIX", "coingeckoId": "pundi-x-2", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/pundix/images/pundi-x-token-logo.svg", @@ -3970,6 +4149,7 @@ "kind": "native", "denom": "afet", "decimals": 18, + "variant": "cosmos", "displayName": "FET", "coingeckoId": "fetch-ai", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/fetchhub/images/fet.svg", @@ -3979,6 +4159,7 @@ "kind": "native", "denom": "nanomobx", "decimals": 9, + "variant": "cosmos", "displayName": "MOBX", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/fetchhub/images/mobx.svg", @@ -4017,6 +4198,7 @@ "kind": "native", "denom": "atestfet", "decimals": 6, + "variant": "cosmos", "displayName": "FET", "coingeckoId": "fetch-ai", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/fetchhub/images/fet.svg", @@ -4054,6 +4236,7 @@ "kind": "native", "denom": "ufct", "decimals": 6, + "variant": "cosmos", "displayName": "FCT", "coingeckoId": "firmachain", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/firmachain/images/fct.svg", @@ -4092,6 +4275,7 @@ "kind": "native", "denom": "ufury", "decimals": 6, + "variant": "cosmos", "displayName": "FURY", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/furya/images/ufury.svg", @@ -4130,6 +4314,7 @@ "kind": "native", "denom": "uglx", "decimals": 6, + "variant": "cosmos", "displayName": "GLX", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/galaxy/images/glx.svg", @@ -4168,6 +4353,7 @@ "kind": "native", "denom": "el1", "decimals": 18, + "variant": "cosmos", "displayName": "L1", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/genesisl1/images/l1.svg", @@ -4206,6 +4392,7 @@ "kind": "native", "denom": "ulore", "decimals": 6, + "variant": "cosmos", "displayName": "LORE", "coingeckoId": "gitopia", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/gitopia/images/lore.svg", @@ -4244,6 +4431,7 @@ "kind": "native", "denom": "utlore", "decimals": 6, + "variant": "cosmos", "displayName": "TLORE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/gitopiatestnet/images/gitopia.png", @@ -4278,13 +4466,32 @@ "features": [ "Organizations", "SocialFeed", - "UPP" + "UPP", + "GnoProjectManager" + ], + "featureObjects": [ + { + "type": "GnoProjectManager", + "projectsManagerPkgPath": "gno.land/r/teritori/projects_manager", + "paymentsDenom": "ugnot" + } ], "currencies": [ { "denom": "ugnot", "displayName": "GNOT", "decimals": 6, + "variant": "gno", + "coingeckoId": "gno", + "icon": "gno.svg", + "kind": "native", + "color": "#232800" + }, + { + "denom": "gno.land/r/demo/tori20", + "displayName": "TORI", + "decimals": 6, + "variant": "grc20", "coingeckoId": "gno", "icon": "gno.svg", "kind": "native", @@ -4294,23 +4501,23 @@ "stakeCurrency": "ugnot", "idPrefix": "gnodev", "chainId": "dev", - "endpoint": "http://127.0.0.1:36657/http://127.0.0.1:26657", + "endpoint": "http://127.0.0.1:26657", "txExplorer": "https://gnoscan.io/transactions/details?txhash=$hash", "accountExplorer": "https://gnoscan.io/accounts/$address", "contractExplorer": "https://gnoscan.io/realms/details?path=$address", "testnet": true, - "backendEndpoint": "http://localhost:9090", + "backendEndpoint": "https://dapp-backend.testnet.teritori.com", "vaultContractAddress": "", - "daoRegistryPkgPath": "gno.land/r/demo/teritori/dao_registry", - "socialFeedsPkgPath": "gno.land/r/demo/teritori/social_feeds", - "socialFeedsDAOPkgPath": "gno.land/r/demo/teritori/social_feeds_dao", + "daoRegistryPkgPath": "gno.land/r/teritori/dao_registry", + "socialFeedsPkgPath": "gno.land/r/teritori/social_feeds", + "socialFeedsDAOPkgPath": "gno.land/r/teritori/social_feeds_dao", "nameServiceContractAddress": "gno.land/r/demo/users", - "modboardsPkgPath": "gno.land/r/demo/teritori/modboards", - "groupsPkgPath": "gno.land/r/demo/teritori/groups", - "votingGroupPkgPath": "gno.land/p/demo/teritori/dao_voting_group", - "daoProposalSinglePkgPath": "gno.land/p/demo/teritori/dao_proposal_single", - "daoInterfacesPkgPath": "gno.land/p/demo/teritori/dao_interfaces", - "daoCorePkgPath": "gno.land/p/demo/teritori/dao_core", + "modboardsPkgPath": "gno.land/r/teritori/modboards", + "groupsPkgPath": "gno.land/r/teritori/groups", + "votingGroupPkgPath": "gno.land/p/teritori/dao_voting_group", + "daoProposalSinglePkgPath": "gno.land/p/teritori/dao_proposal_single", + "daoInterfacesPkgPath": "gno.land/p/teritori/dao_interfaces", + "daoCorePkgPath": "gno.land/p/teritori/dao_core", "nameServiceDefaultImage": "ipfs://bafkreignptjimiu7wuux6mk6uh4hb4odb6ff62ny4bvdokrhes7g67huse", "gnowebURL": "http://127.0.0.1:8888" }, @@ -4332,7 +4539,8 @@ "coingeckoId": "gno", "icon": "gno.svg", "kind": "native", - "color": "#232800" + "color": "#232800", + "variant": "gno" } ], "stakeCurrency": "ugnot", @@ -4348,14 +4556,14 @@ "vaultContractAddress": "", "nameServiceContractAddress": "gno.land/r/demo/users", "nameServiceDefaultImage": "ipfs://bafkreignptjimiu7wuux6mk6uh4hb4odb6ff62ny4bvdokrhes7g67huse", - "daoRegistryPkgPath": "gno.land/r/demo/teritori/dao_registry", - "socialFeedsPkgPath": "gno.land/r/demo/teritori/social_feeds", - "socialFeedsDAOPkgPath": "gno.land/r/demo/teritori/social_feeds_dao", - "groupsPkgPath": "gno.land/r/demo/teritori/groups", - "votingGroupPkgPath": "gno.land/p/demo/teritori/dao_voting_group", - "daoProposalSinglePkgPath": "gno.land/p/demo/teritori/dao_proposal_single", - "daoInterfacesPkgPath": "gno.land/p/demo/teritori/dao_interfaces", - "daoCorePkgPath": "gno.land/p/demo/teritori/dao_core" + "daoRegistryPkgPath": "gno.land/r/teritori/dao_registry", + "socialFeedsPkgPath": "gno.land/r/teritori/social_feeds", + "socialFeedsDAOPkgPath": "gno.land/r/teritori/social_feeds_dao", + "groupsPkgPath": "gno.land/r/teritori/groups", + "votingGroupPkgPath": "gno.land/p/teritori/dao_voting_group", + "daoProposalSinglePkgPath": "gno.land/p/teritori/dao_proposal_single", + "daoInterfacesPkgPath": "gno.land/p/teritori/dao_interfaces", + "daoCorePkgPath": "gno.land/p/teritori/dao_core" }, { "id": "gno-teritori", @@ -4365,13 +4573,22 @@ "features": [ "Organizations", "SocialFeed", - "UPP" + "UPP", + "GnoProjectManager" + ], + "featureObjects": [ + { + "type": "GnoProjectManager", + "projectsManagerPkgPath": "gno.land/r/teritori/escrow", + "paymentsDenom": "ugnot" + } ], "currencies": [ { "denom": "ugnot", "displayName": "GNOT", "decimals": 6, + "variant": "gno", "coingeckoId": "gno", "icon": "gno.svg", "kind": "native", @@ -4390,15 +4607,15 @@ "vaultContractAddress": "", "nameServiceContractAddress": "gno.land/r/demo/users", "nameServiceDefaultImage": "ipfs://bafkreignptjimiu7wuux6mk6uh4hb4odb6ff62ny4bvdokrhes7g67huse", - "daoRegistryPkgPath": "gno.land/r/demo/teritori/dao_registry_v4", - "socialFeedsPkgPath": "gno.land/r/demo/teritori/social_feeds_v4", - "socialFeedsDAOPkgPath": "gno.land/r/demo/teritori/social_feeds_dao_v2", - "modboardsPkgPath": "gno.land/r/demo/teritori/modboards_v4", - "groupsPkgPath": "gno.land/r/demo/teritori/groups_v4", - "votingGroupPkgPath": "gno.land/p/demo/teritori/dao_voting_group_v2", - "daoProposalSinglePkgPath": "gno.land/p/demo/teritori/dao_proposal_single_v4", - "daoInterfacesPkgPath": "gno.land/p/demo/teritori/dao_interfaces_v5", - "daoCorePkgPath": "gno.land/p/demo/teritori/dao_core_v4", + "daoRegistryPkgPath": "gno.land/r/teritori/dao_registry_v4", + "socialFeedsPkgPath": "gno.land/r/teritori/social_feeds_v4", + "socialFeedsDAOPkgPath": "gno.land/r/teritori/social_feeds_dao_v2", + "modboardsPkgPath": "gno.land/r/teritori/modboards_v4", + "groupsPkgPath": "gno.land/r/teritori/groups_v4", + "votingGroupPkgPath": "gno.land/p/teritori/dao_voting_group_v2", + "daoProposalSinglePkgPath": "gno.land/p/teritori/dao_proposal_single_v4", + "daoInterfacesPkgPath": "gno.land/p/teritori/dao_interfaces_v5", + "daoCorePkgPath": "gno.land/p/teritori/dao_core_v4", "gnowebURL": "https://testnet.gno.teritori.com", "faucetURL": "https://testnet.gno.teritori.com:5050/?toaddr=$addr" }, @@ -4413,6 +4630,7 @@ "denom": "ugnot", "displayName": "GNOT", "decimals": 6, + "variant": "gno", "coingeckoId": "gno", "icon": "gno.svg", "kind": "native", @@ -4450,7 +4668,8 @@ "coingeckoId": "gno", "icon": "gno.svg", "kind": "native", - "color": "#232800" + "color": "#232800", + "variant": "gno" } ], "stakeCurrency": "ugnot", @@ -4481,6 +4700,7 @@ "kind": "native", "denom": "ugraviton", "decimals": 6, + "variant": "cosmos", "displayName": "GRAV", "coingeckoId": "graviton", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/gravitybridge/images/grav.svg", @@ -4490,6 +4710,7 @@ "kind": "native", "denom": "gravity0xfB5c6815cA3AC72Ce9F5006869AE67f18bF77006", "decimals": 18, + "variant": "cosmos", "displayName": "PSTAKE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/persistence/images/pstake.svg", @@ -4499,6 +4720,7 @@ "kind": "native", "denom": "gravity0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "decimals": 18, + "variant": "cosmos", "displayName": "WETH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/weth.svg", @@ -4508,6 +4730,7 @@ "kind": "native", "denom": "gravity0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "decimals": 6, + "variant": "cosmos", "displayName": "USDC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/usdc.svg", @@ -4517,6 +4740,7 @@ "kind": "native", "denom": "gravity0xdAC17F958D2ee523a2206206994597C13D831ec7", "decimals": 6, + "variant": "cosmos", "displayName": "USDT", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/usdt.svg", @@ -4526,6 +4750,7 @@ "kind": "native", "denom": "gravity0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", "decimals": 8, + "variant": "cosmos", "displayName": "WBTC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/wbtc.svg", @@ -4535,6 +4760,7 @@ "kind": "native", "denom": "gravity0x6B175474E89094C44Da98b954EedeAC495271d0F", "decimals": 18, + "variant": "cosmos", "displayName": "DAI", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/dai.svg", @@ -4544,6 +4770,7 @@ "kind": "native", "denom": "gravity0x83F20F44975D03b1b09e64809B757c47f942BEeA", "decimals": 18, + "variant": "cosmos", "displayName": "sDAI", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/sdai.svg", @@ -4553,6 +4780,7 @@ "kind": "native", "denom": "gravity0x2F109021aFe75B949429fe30523Ee7C0D5B27207", "decimals": 18, + "variant": "cosmos", "displayName": "OCC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/occamfi.png", @@ -4562,6 +4790,7 @@ "kind": "native", "denom": "gravity0x60e683C6514Edd5F758A55b6f393BeBBAfaA8d5e", "decimals": 8, + "variant": "cosmos", "displayName": "PAGE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/page.svg", @@ -4600,6 +4829,7 @@ "kind": "native", "denom": "aISLM", "decimals": 18, + "variant": "cosmos", "displayName": "ISLM", "coingeckoId": "islamic-coin", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/haqq/images/islm.svg", @@ -4638,6 +4868,7 @@ "kind": "native", "denom": "ufury", "decimals": 6, + "variant": "cosmos", "displayName": "FURY", "coingeckoId": "fanfury", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/highbury/images/fury.svg", @@ -4647,6 +4878,7 @@ "kind": "native", "denom": "jinx", "decimals": 6, + "variant": "cosmos", "displayName": "JINX", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/highbury/images/jinx.svg", @@ -4656,6 +4888,7 @@ "kind": "native", "denom": "jinxy", "decimals": 6, + "variant": "cosmos", "displayName": "JINXy", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/highbury/images/jinxy.svg", @@ -4694,6 +4927,7 @@ "kind": "native", "denom": "uheart", "decimals": 6, + "variant": "cosmos", "displayName": "HEART", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/humanstestnet/images/humans.png", @@ -4731,6 +4965,7 @@ "kind": "native", "denom": "aheart", "decimals": 18, + "variant": "cosmos", "displayName": "HEART", "coingeckoId": "humans-ai", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/humans/images/humans_small_light.svg", @@ -4769,6 +5004,7 @@ "kind": "native", "denom": "uhid", "decimals": 6, + "variant": "cosmos", "displayName": "HID", "coingeckoId": "hypersign-identity-token", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/hypersigntestnet/images/hypersign.png", @@ -4806,6 +5042,7 @@ "kind": "native", "denom": "idep", "decimals": 6, + "variant": "cosmos", "displayName": "IDEP", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/idep/images/idep.svg", @@ -4844,6 +5081,7 @@ "kind": "native", "denom": "aimv", "decimals": 18, + "variant": "cosmos", "displayName": "IMV", "coingeckoId": "imv", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/imversed/images/imversed.svg", @@ -4882,6 +5120,7 @@ "kind": "native", "denom": "nimv", "decimals": 6, + "variant": "cosmos", "displayName": "IMV", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/imversedtestnet/images/imversed.svg", @@ -4919,6 +5158,7 @@ "kind": "native", "denom": "inj", "decimals": 18, + "variant": "cosmos", "displayName": "INJ", "coingeckoId": "injective-protocol", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/injective/images/inj.svg", @@ -4928,6 +5168,7 @@ "kind": "native", "denom": "factory/inj1cdwt8g7nxgtg2k4fn8sj363mh9ahkw2qt0vrnc/ampINJ", "decimals": 6, + "variant": "cosmos", "displayName": "ampINJ", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/injective/images/ampinj.png", @@ -4937,6 +5178,7 @@ "kind": "native", "denom": "factory/inj14lf8xm6fcvlggpa7guxzjqwjmtr24gnvf56hvz/autism", "decimals": 6, + "variant": "cosmos", "displayName": "AUTISM", "coingeckoId": "autism", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/injective/images/autism.png", @@ -4946,6 +5188,7 @@ "kind": "native", "denom": "factory/inj1xtel2knkt8hmc9dnzpjz6kdmacgcfmlv5f308w/ninja", "decimals": 6, + "variant": "cosmos", "displayName": "NINJA", "coingeckoId": "dog-wif-nuchucks", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/injective/images/ninja.png", @@ -4955,6 +5198,7 @@ "kind": "native", "denom": "factory/inj1rmjzj9fn47kdmfk4f3z39qr6czexxe0yjyc546/WGMI", "decimals": 6, + "variant": "cosmos", "displayName": "WGMI", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/injective/images/wgmi.png", @@ -4993,6 +5237,7 @@ "kind": "native", "denom": "inj", "decimals": 18, + "variant": "cosmos", "displayName": "INJ", "coingeckoId": "injective-protocol", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/injective/images/inj.svg", @@ -5030,6 +5275,7 @@ "kind": "native", "denom": "uiris", "decimals": 6, + "variant": "cosmos", "displayName": "IRIS", "coingeckoId": "iris-network", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/irisnet/images/iris.svg", @@ -5068,6 +5314,7 @@ "kind": "native", "denom": "uixo", "decimals": 6, + "variant": "cosmos", "displayName": "IXO", "coingeckoId": "ixo", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/impacthub/images/ixo.svg", @@ -5106,6 +5353,7 @@ "kind": "native", "denom": "uixo", "decimals": 6, + "variant": "cosmos", "displayName": "IXO", "coingeckoId": "ixo", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/impacthubdevnet/images/ixo.svg", @@ -5143,6 +5391,7 @@ "kind": "native", "denom": "uixo", "decimals": 6, + "variant": "cosmos", "displayName": "IXO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/impacthub/images/ixo.svg", @@ -5181,6 +5430,7 @@ "kind": "native", "denom": "ujkl", "decimals": 6, + "variant": "cosmos", "displayName": "JKL", "coingeckoId": "jackal-protocol", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/jackal/images/jkl.svg", @@ -5219,6 +5469,7 @@ "kind": "native", "denom": "ujkl", "decimals": 6, + "variant": "cosmos", "displayName": "JKL", "coingeckoId": "jackal", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/jackaltestnet/images/jkl.svg", @@ -5256,6 +5507,7 @@ "kind": "native", "denom": "ujuno", "decimals": 6, + "variant": "cosmos", "displayName": "JUNO", "coingeckoId": "juno-network", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/juno.svg", @@ -5265,6 +5517,7 @@ "kind": "native", "denom": "cw20:juno168ctmpyppk90d34p3jjy658zf5a5l3w8wk35wht6ccqj4mr0yv8s4j5awr", "decimals": 6, + "variant": "cosmos", "displayName": "NETA", "coingeckoId": "neta", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/neta.svg", @@ -5274,6 +5527,7 @@ "kind": "native", "denom": "cw20:juno1g2g7ucurum66d42g8k5twk34yegdq8c82858gz0tq2fc75zy7khssgnhjl", "decimals": 3, + "variant": "cosmos", "displayName": "MARBLE", "coingeckoId": "marble", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/marble.svg", @@ -5283,6 +5537,7 @@ "kind": "native", "denom": "cw20:juno1re3x67ppxap48ygndmrc7har2cnc7tcxtm9nplcas4v0gc3wnmvs3s807z", "decimals": 6, + "variant": "cosmos", "displayName": "HOPE", "coingeckoId": "hope-galaxy", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/hope.svg", @@ -5292,6 +5547,7 @@ "kind": "native", "denom": "cw20:juno1r4pzw8f9z0sypct5l9j906d47z998ulwvhvqe5xdwgy8wf84583sxwh0pa", "decimals": 6, + "variant": "cosmos", "displayName": "RAC", "coingeckoId": "racoon", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/rac.svg", @@ -5301,6 +5557,7 @@ "kind": "native", "denom": "cw20:juno1y9rf7ql6ffwkv02hsgd4yruz23pn4w97p75e2slsnkm0mnamhzysvqnxaq", "decimals": 6, + "variant": "cosmos", "displayName": "BLOCK", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/block.svg", @@ -5310,6 +5567,7 @@ "kind": "native", "denom": "cw20:juno1tdjwrqmnztn2j3sj2ln9xnyps5hs48q3ddwjrz7jpv6mskappjys5czd49", "decimals": 6, + "variant": "cosmos", "displayName": "DHK", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/dhk.svg", @@ -5319,6 +5577,7 @@ "kind": "native", "denom": "cw20:juno15u3dt79t6sxxa3x3kpkhzsy56edaa5a66wvt3kxmukqjz2sx0hes5sn38g", "decimals": 6, + "variant": "cosmos", "displayName": "RAW", "coingeckoId": "junoswap-raw-dao", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/raw.svg", @@ -5328,6 +5587,7 @@ "kind": "native", "denom": "cw20:juno17wzaxtfdw5em7lc94yed4ylgjme63eh73lm3lutp2rhcxttyvpwsypjm4w", "decimals": 6, + "variant": "cosmos", "displayName": "ASVT", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/asvt.png", @@ -5337,6 +5597,7 @@ "kind": "native", "denom": "cw20:juno1ur4jx0sxchdevahep7fwq28yk4tqsrhshdtylz46yka3uf6kky5qllqp4k", "decimals": 6, + "variant": "cosmos", "displayName": "HNS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/hns.svg", @@ -5346,6 +5607,7 @@ "kind": "native", "denom": "cw20:juno1n7n7d5088qlzlj37e9mgmkhx6dfgtvt02hqxq66lcap4dxnzdhwqfmgng3", "decimals": 6, + "variant": "cosmos", "displayName": "JOE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/joe.png", @@ -5355,6 +5617,7 @@ "kind": "native", "denom": "cw20:juno1sfwye65qxcfsc837gu5qcprcz7w49gkv3wnat04764ld76hy3arqs779tr", "decimals": 6, + "variant": "cosmos", "displayName": "DLA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/dla.svg", @@ -5364,6 +5627,7 @@ "kind": "native", "denom": "cw20:juno1j0a9ymgngasfn3l5me8qpd53l5zlm9wurfdk7r65s5mg6tkxal3qpgf5se", "decimals": 6, + "variant": "cosmos", "displayName": "GLTO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/glto.svg", @@ -5373,6 +5637,7 @@ "kind": "native", "denom": "cw20:juno1gz8cf86zr4vw9cjcyyv432vgdaecvr9n254d3uwwkx9rermekddsxzageh", "decimals": 6, + "variant": "cosmos", "displayName": "GKEY", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/gkey.svg", @@ -5382,6 +5647,7 @@ "kind": "native", "denom": "cw20:juno1t46z6hg8vvsena7sue0vg6w85ljar3cundplkre9sz0skeqkap9sxyyy6m", "decimals": 6, + "variant": "cosmos", "displayName": "HOLE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/hole.svg", @@ -5391,6 +5657,7 @@ "kind": "native", "denom": "cw20:juno1dd0k0um5rqncfueza62w9sentdfh3ec4nw4aq4lk5hkjl63vljqscth9gv", "decimals": 6, + "variant": "cosmos", "displayName": "SEJUNO", "coingeckoId": "stakeeasy-juno-derivative", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/sejuno.svg", @@ -5400,6 +5667,7 @@ "kind": "native", "denom": "cw20:juno1wwnhkagvcd3tjz6f8vsdsw5plqnw8qy2aj3rrhqr2axvktzv9q2qz8jxn3", "decimals": 6, + "variant": "cosmos", "displayName": "BJUNO", "coingeckoId": "stakeeasy-bjuno", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/bjuno.svg", @@ -5409,6 +5677,7 @@ "kind": "native", "denom": "cw20:juno159q8t5g02744lxq8lfmcn6f78qqulq9wn3y9w7lxjgkz4e0a6kvsfvapse", "decimals": 6, + "variant": "cosmos", "displayName": "SOLAR", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/solar.svg", @@ -5418,6 +5687,7 @@ "kind": "native", "denom": "cw20:juno19rqljkh95gh40s7qdx40ksx3zq5tm4qsmsrdz9smw668x9zdr3lqtg33mf", "decimals": 6, + "variant": "cosmos", "displayName": "SEASY", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/seasy.svg", @@ -5427,6 +5697,7 @@ "kind": "native", "denom": "cw20:juno1p8x807f6h222ur0vssqy3qk6mcpa40gw2pchquz5atl935t7kvyq894ne3", "decimals": 6, + "variant": "cosmos", "displayName": "MUSE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/muse.png", @@ -5436,6 +5707,7 @@ "kind": "native", "denom": "cw20:juno1qsrercqegvs4ye0yqg93knv73ye5dc3prqwd6jcdcuj8ggp6w0us66deup", "decimals": 6, + "variant": "cosmos", "displayName": "LOOP", "coingeckoId": "loop", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/loop.png", @@ -5445,6 +5717,7 @@ "kind": "native", "denom": "cw20:juno1cltgm8v842gu54srmejewghnd6uqa26lzkpa635wzra9m9xuudkqa2gtcz", "decimals": 6, + "variant": "cosmos", "displayName": "FURY", "coingeckoId": "fanfury", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/fanfury.png", @@ -5454,6 +5727,7 @@ "kind": "native", "denom": "cw20:juno1rws84uz7969aaa7pej303udhlkt3j9ca0l3egpcae98jwak9quzq8szn2l", "decimals": 6, + "variant": "cosmos", "displayName": "PHMN", "coingeckoId": "posthuman", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/phmn.svg", @@ -5463,6 +5737,7 @@ "kind": "native", "denom": "cw20:juno1u45shlp0q4gcckvsj06ss4xuvsu0z24a0d0vr9ce6r24pht4e5xq7q995n", "decimals": 6, + "variant": "cosmos", "displayName": "HOPERS", "coingeckoId": "hopers-io ", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/hopers.svg", @@ -5472,6 +5747,7 @@ "kind": "native", "denom": "cw20:juno1g647t78y2ulqlm3lss8rs3d0spzd0teuwhdvnqn92tr79yltk9dq2h24za", "decimals": 6, + "variant": "cosmos", "displayName": "RED", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/red.png", @@ -5481,6 +5757,7 @@ "kind": "native", "denom": "cw20:juno14q8kk464fafql2fwmlsgvgcdl6h2csqpzv4hr025fmcvgjahpess32k0j7", "decimals": 6, + "variant": "cosmos", "displayName": "BLUE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/blue.png", @@ -5490,6 +5767,7 @@ "kind": "native", "denom": "cw20:juno1mkw83sv6c7sjdvsaplrzc8yaes9l42p4mhy0ssuxjnyzl87c9eps7ce3m9", "decimals": 6, + "variant": "cosmos", "displayName": "WYND", "coingeckoId": "wynd", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/wynd.svg", @@ -5499,6 +5777,7 @@ "kind": "native", "denom": "juno1s2dp05rspeuzzpzyzdchk262szehrtfpz847uvf98cnwh53ulx4qg20qwj", "decimals": 6, + "variant": "cosmos", "displayName": "BANANA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/banana.png", @@ -5508,6 +5787,7 @@ "kind": "native", "denom": "cw20:juno1qmlchtmjpvu0cr7u0tad2pq8838h6farrrjzp39eqa9xswg7teussrswlq", "decimals": 6, + "variant": "cosmos", "displayName": "NRIDE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/nride.svg", @@ -5517,6 +5797,7 @@ "kind": "native", "denom": "cw20:juno14lycavan8gvpjn97aapzvwmsj8kyrvf644p05r0hu79namyj3ens87650k", "decimals": 6, + "variant": "cosmos", "displayName": "SGNL", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/sgnl.png", @@ -5526,6 +5807,7 @@ "kind": "native", "denom": "cw20:juno1zkwveux7y6fmsr88atf3cyffx96p0c96qr8tgcsj7vfnhx7sal3s3zu3ps", "decimals": 6, + "variant": "cosmos", "displayName": "JAPE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/jape.png", @@ -5535,6 +5817,7 @@ "kind": "native", "denom": "cw20:juno12wxyvtqe76x2a5jj6ckp2hfq8v32m6rvyyxwwufl2tksqvkt7whqczv6pa", "decimals": 6, + "variant": "cosmos", "displayName": "CATOM", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/catom.png", @@ -5544,6 +5827,7 @@ "kind": "native", "denom": "cw20:juno1g0wuyu2f49ncf94r65278puxzclf5arse9f3kvffxyv4se4vgdmsk4dvqz", "decimals": 6, + "variant": "cosmos", "displayName": "HOWL", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/howl.png", @@ -5553,6 +5837,7 @@ "kind": "native", "denom": "cw20:juno1u8cr3hcjvfkzxcaacv9q75uw9hwjmn8pucc93pmy6yvkzz79kh3qncca8x", "decimals": 6, + "variant": "cosmos", "displayName": "FOX", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/fox.png", @@ -5562,6 +5847,7 @@ "kind": "native", "denom": "cw20:juno1xekkh27punj0uxruv3gvuydyt856fax0nu750xns99t2qcxp7xmsqwhfma", "decimals": 6, + "variant": "cosmos", "displayName": "GRDN", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/guardian.png", @@ -5571,6 +5857,7 @@ "kind": "native", "denom": "cw20:juno166heaxlyntd33a5euh4rrz26svhean4klzw594esmd02l4atan6sazy2my", "decimals": 6, + "variant": "cosmos", "displayName": "MNPU", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/mnpu.svg", @@ -5580,6 +5867,7 @@ "kind": "native", "denom": "cw20:juno10gthz5ufgrpuk5cscve2f0hjp56wgp90psqxcrqlg4m9mcu9dh8q4864xy", "decimals": 6, + "variant": "cosmos", "displayName": "KLEO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/kleomedes.png", @@ -5589,6 +5877,7 @@ "kind": "native", "denom": "cw20:juno1qqwf3lkfjhp77yja7gmg3y95pda0e5xctqrdhf3wvwdd79flagvqfgrgxp", "decimals": 6, + "variant": "cosmos", "displayName": "SKOJ", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/sikoba.svg", @@ -5598,6 +5887,7 @@ "kind": "native", "denom": "cw20:juno1x5qt47rw84c4k6xvvywtrd40p8gxjt8wnmlahlqg07qevah3f8lqwxfs7z", "decimals": 6, + "variant": "cosmos", "displayName": "SHIBAC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/shibacosmos.png", @@ -5607,6 +5897,7 @@ "kind": "native", "denom": "cw20:juno1ngww7zxak55fql42wmyqrr4rhzpne24hhs4p3w4cwhcdgqgr3hxsmzl9zg", "decimals": 6, + "variant": "cosmos", "displayName": "CLST", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/celestims.png", @@ -5616,6 +5907,7 @@ "kind": "native", "denom": "cw20:juno1m4h8q4p305wgy7vkux0w6e5ylhqll3s6pmadhxkhqtuwd5wlxhxs8xklsw", "decimals": 6, + "variant": "cosmos", "displayName": "WATR", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/watr.png", @@ -5625,6 +5917,7 @@ "kind": "native", "denom": "cw20:juno1ju8k8sqwsqu5k6umrypmtyqu2wqcpnrkf4w4mntvl0javt4nma7s8lzgss", "decimals": 6, + "variant": "cosmos", "displayName": "CASA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/casa.png", @@ -5634,6 +5927,7 @@ "kind": "native", "denom": "cw20:juno1j4ux0f6gt7e82z7jdpm25v4g2gts880ap64rdwa49989wzhd0dfqed6vqm", "decimals": 6, + "variant": "cosmos", "displayName": "SUMMIT", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/summit.png", @@ -5643,6 +5937,7 @@ "kind": "native", "denom": "cw20:juno13ca2g36ng6etcfhr9qxx352uw2n5e92np54thfkm3w3nzlhsgvwsjaqlyq", "decimals": 6, + "variant": "cosmos", "displayName": "MANNA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/manna.png", @@ -5652,6 +5947,7 @@ "kind": "native", "denom": "cw20:juno12etxwkxvms0uy9ak8g3pyq6a53myukufdnx82pakzmjmpm77a0ksr9gs5v", "decimals": 6, + "variant": "cosmos", "displayName": "EMPWR", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/empwr.png", @@ -5661,6 +5957,7 @@ "kind": "native", "denom": "cw20:juno1525fuspletvzykpgr2atxpymu9le4mghd7qq4a4u23uwqzc2f3fq7fmafd", "decimals": 6, + "variant": "cosmos", "displayName": "MIDDLE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/middle.png", @@ -5670,6 +5967,7 @@ "kind": "native", "denom": "cw20:juno17703kcxtsg37hryxnestejyyycuv5yyvnghp2e7w0kqvafnnyetsgzq62w", "decimals": 6, + "variant": "cosmos", "displayName": "SUNSET", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/sunset.png", @@ -5679,6 +5977,7 @@ "kind": "native", "denom": "cw20:juno1uu3rxu7w7fpfj4sl4xpxppgymk57mzdzn6kg7492jdxh5dwk7d2qq9429e", "decimals": 6, + "variant": "cosmos", "displayName": "TREE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/livingtree.png", @@ -5688,6 +5987,7 @@ "kind": "native", "denom": "cw20:juno1jwdy7v4egw36pd84aeks3ww6n8k7zhsumd4ac8q5lts83ppxueus4626e8", "decimals": 6, + "variant": "cosmos", "displayName": "INVDRS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/invdrs.png", @@ -5697,6 +5997,7 @@ "kind": "native", "denom": "cw20:juno1jrr0tuuzxrrwcg6hgeqhw5wqpck2y55734e7zcrp745aardlp0qqg8jz06", "decimals": 6, + "variant": "cosmos", "displayName": "APEMOS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/apemos.png", @@ -5706,6 +6007,7 @@ "kind": "native", "denom": "cw20:juno1ytymtllllsp3hfmndvcp802p2xmy5s8m59ufel8xv9ahyxyfs4hs4kd4je", "decimals": 6, + "variant": "cosmos", "displayName": "OSDOGE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/osdoge.png", @@ -5715,6 +6017,7 @@ "kind": "native", "denom": "cw20:juno1k2ruzzvvwwtwny6gq6kcwyfhkzahaunp685wmz4hafplduekj98q9hgs6d", "decimals": 6, + "variant": "cosmos", "displayName": "DOGA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/doga.png", @@ -5724,6 +6027,7 @@ "kind": "native", "denom": "cw20:juno1zqrj3ta4u7ylv0wqzd8t8q3jrr9rdmn43zuzp9zemeunecnhy8fss778g7", "decimals": 6, + "variant": "cosmos", "displayName": "PEPE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/pepe.png", @@ -5733,6 +6037,7 @@ "kind": "native", "denom": "cw20:juno1f5datjdse3mdgrapwuzs3prl7pvxxht48ns6calnn0t77v2s9l8s0qu488", "decimals": 6, + "variant": "cosmos", "displayName": "CATMOS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/catmos.png", @@ -5742,6 +6047,7 @@ "kind": "native", "denom": "cw20:juno1dyyf7pxeassxvftf570krv7fdf5r8e4r04mp99h0mllsqzp3rs4q7y8yqg", "decimals": 6, + "variant": "cosmos", "displayName": "SPACER", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/spacer.png", @@ -5751,6 +6057,7 @@ "kind": "native", "denom": "cw20:juno1dpany8c0lj526lsa02sldv7shzvnw5dt5ues72rk35hd69rrydxqeraz8l", "decimals": 9, + "variant": "cosmos", "displayName": "LIGHT", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/light.png", @@ -5760,6 +6067,7 @@ "kind": "native", "denom": "cw20:juno1llg7q2d5dqlrqzh5dxv8c7kzzjszld34s5vktqmlmaaxqjssz43sxyhq0d", "decimals": 6, + "variant": "cosmos", "displayName": "MILE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/mille.png", @@ -5769,6 +6077,7 @@ "kind": "native", "denom": "cw20:juno1lpvx3mv2a6ddzfjc7zzz2v2cm5gqgqf0hx67hc5p5qwn7hz4cdjsnznhu8", "decimals": 6, + "variant": "cosmos", "displayName": "VOID", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/void.png", @@ -5778,6 +6087,7 @@ "kind": "native", "denom": "cw20:juno10vgf2u03ufcf25tspgn05l7j3tfg0j63ljgpffy98t697m5r5hmqaw95ux", "decimals": 6, + "variant": "cosmos", "displayName": "SLCA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/silica.png", @@ -5787,6 +6097,7 @@ "kind": "native", "denom": "cw20:juno1epxnvge53c4hkcmqzlxryw5fp7eae2utyk6ehjcfpwajwp48km3sgxsh9k", "decimals": 6, + "variant": "cosmos", "displayName": "PEPEC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/pepec.png", @@ -5796,6 +6107,7 @@ "kind": "native", "denom": "cw20:juno15au4k2jgwd0jnchy0fkg3lm00fpt7jt0j2duuzradn2q7sega2dszyn5pp", "decimals": 6, + "variant": "cosmos", "displayName": "PLTN", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/pltn.png", @@ -5805,6 +6117,7 @@ "kind": "native", "denom": "cw20:juno12mcwmd6wqhledkjsurlfqtc8j0pedvxlcxw3gs4kh2qf808ehehsen8nmw", "decimals": 6, + "variant": "cosmos", "displayName": "YFD", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/yfd.svg", @@ -5814,6 +6127,7 @@ "kind": "native", "denom": "factory/juno1qly4zcmzr2gyxtze5yt9chv2srczwwunppxjfh/NEXX", "decimals": 6, + "variant": "cosmos", "displayName": "NEXX", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/nexx.png", @@ -5823,6 +6137,7 @@ "kind": "native", "denom": "factory/juno1u805lv20qc6jy7c3ttre7nct6uyl20pfky5r7e/DGL", "decimals": 6, + "variant": "cosmos", "displayName": "DGL", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/dgl.png", @@ -5832,6 +6147,7 @@ "kind": "native", "denom": "cw20:juno1a0khag6cfzu5lrwazmyndjgvlsuk7g4vn9jd8ceym8f4jf6v2l9q6d348a", "decimals": 6, + "variant": "cosmos", "displayName": "ampJUNO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/ampjuno.svg", @@ -5841,6 +6157,7 @@ "kind": "native", "denom": "cw20:juno14fz92ehqt37e096xr95kmy8nc0kz803uezxtg4fwx7agjjma86sqm8mg3h", "decimals": 8, + "variant": "cosmos", "displayName": "BITS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/bits.png", @@ -5850,6 +6167,7 @@ "kind": "native", "denom": "cw20:juno13epyeat7ef0k7q6kllmyvc8zpfd9xm7cqjrgtk0qkgrk7n5mjfmq8979jw", "decimals": 6, + "variant": "cosmos", "displayName": "POIL", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/poil.png", @@ -5859,6 +6177,7 @@ "kind": "native", "denom": "factory/juno195asgku87kxgu48s447z0ryhsyn5rl3yzvfw0d/uhava", "decimals": 6, + "variant": "cosmos", "displayName": "HAVA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/juno/images/hava.png", @@ -5897,6 +6216,7 @@ "kind": "native", "denom": "ujunox", "decimals": 6, + "variant": "cosmos", "displayName": "JUNOX", "coingeckoId": "juno-network", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/junotestnet/images/juno.svg", @@ -5906,6 +6226,7 @@ "kind": "native", "denom": "factory/juno12klaltyqvg2j6v034jwdxrk5n4242ttse4sdpt/NEXX", "decimals": 6, + "variant": "cosmos", "displayName": "NEXX", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/junotestnet/images/nexx.png", @@ -5943,6 +6264,7 @@ "kind": "native", "denom": "ukava", "decimals": 6, + "variant": "cosmos", "displayName": "KAVA", "coingeckoId": "kava", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kava/images/kava.svg", @@ -5952,6 +6274,7 @@ "kind": "native", "denom": "hard", "decimals": 6, + "variant": "cosmos", "displayName": "HARD", "coingeckoId": "kava-lend", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kava/images/hard.svg", @@ -5961,6 +6284,7 @@ "kind": "native", "denom": "swp", "decimals": 6, + "variant": "cosmos", "displayName": "SWP", "coingeckoId": "kava-swap", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kava/images/swp.svg", @@ -5970,6 +6294,7 @@ "kind": "native", "denom": "usdx", "decimals": 6, + "variant": "cosmos", "displayName": "USDX", "coingeckoId": "usdx", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kava/images/usdx.svg", @@ -5979,6 +6304,7 @@ "kind": "native", "denom": "erc20/tether/usdt", "decimals": 6, + "variant": "cosmos", "displayName": "USDT", "coingeckoId": "tether", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/usdt.svg", @@ -6017,6 +6343,7 @@ "kind": "native", "denom": "uxki", "decimals": 6, + "variant": "cosmos", "displayName": "XKI", "coingeckoId": "ki", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kichain/images/xki.svg", @@ -6026,6 +6353,7 @@ "kind": "native", "denom": "cw20:ki1dt3lk455ed360pna38fkhqn0p8y44qndsr77qu73ghyaz2zv4whq83mwdy", "decimals": 6, + "variant": "cosmos", "displayName": "LVN", "coingeckoId": "lvn", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kichain/images/lvn.png", @@ -6064,6 +6392,7 @@ "kind": "native", "denom": "utki", "decimals": 6, + "variant": "cosmos", "displayName": "TKI", "coingeckoId": "ki", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kichain/images/xki.svg", @@ -6101,6 +6430,7 @@ "kind": "native", "denom": "udarc", "decimals": 6, + "variant": "cosmos", "displayName": "DARC", "coingeckoId": "darcmatter-coin", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/konstellation/images/darc.svg", @@ -6139,6 +6469,7 @@ "kind": "native", "denom": "ukuji", "decimals": 6, + "variant": "cosmos", "displayName": "KUJI", "coingeckoId": "kujira", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kujira/images/kuji.svg", @@ -6148,6 +6479,7 @@ "kind": "native", "denom": "factory/kujira1qk00h5atutpsv900x202pxx42npjr9thg58dnqpa72f2p7m2luase444a7/uusk", "decimals": 6, + "variant": "cosmos", "displayName": "USK", "coingeckoId": "usk", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kujira/images/usk.svg", @@ -6157,6 +6489,7 @@ "kind": "native", "denom": "factory/kujira1m96ucsfpt2yy72w09z2rxjdj38y5qd8lqx5jtggnejmdua2ynpnsxyvjex/urcpt", "decimals": 6, + "variant": "cosmos", "displayName": "qcKUJI", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kujira/images/qckuji.svg", @@ -6166,6 +6499,7 @@ "kind": "native", "denom": "factory/kujira1n3fr5f56r2ce0s37wdvwrk98yhhq3unnxgcqus8nzsfxvllk0yxquurqty/ampKUJI", "decimals": 6, + "variant": "cosmos", "displayName": "ampKUJI", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kujira/images/ampkuji.svg", @@ -6175,6 +6509,7 @@ "kind": "native", "denom": "factory/kujira1643jxg8wasy5cfcn7xm8rd742yeazcksqlg4d7/umnta", "decimals": 6, + "variant": "cosmos", "displayName": "MNTA", "coingeckoId": "mantadao", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kujira/images/mnta.svg", @@ -6184,6 +6519,7 @@ "kind": "native", "denom": "factory/kujira1qzu3up50auxhqyzfq56znuj8n38q2ra7daaf9ef7vg8gu66jh4fqd2wd2y/urcpt", "decimals": 6, + "variant": "cosmos", "displayName": "qcMNTA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kujira/images/qcmnta.svg", @@ -6193,6 +6529,7 @@ "kind": "native", "denom": "factory/kujira175yatpvkpgw07w0chhzuks3zrrae9z9g2y6r7u5pzqesyau4x9eqqyv0rr/ampMNTA", "decimals": 6, + "variant": "cosmos", "displayName": "ampMNTA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kujira/images/ampmnta.png", @@ -6202,6 +6539,7 @@ "kind": "native", "denom": "factory/kujira12cjjeytrqcj25uv349thltcygnp9k0kukpct0e/uwink", "decimals": 6, + "variant": "cosmos", "displayName": "WINK", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kujira/images/wink.svg", @@ -6211,6 +6549,7 @@ "kind": "native", "denom": "factory/kujira1slueerjz7mx9jp45u3y0rjwtvhcf8a68wf2mjt/ublend", "decimals": 6, + "variant": "cosmos", "displayName": "BLEND", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kujira/images/blend.svg", @@ -6220,6 +6559,7 @@ "kind": "native", "denom": "factory/kujira1sc6a0347cc5q3k890jj0pf3ylx2s38rh4sza4t/ufuzn", "decimals": 6, + "variant": "cosmos", "displayName": "FUZN", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kujira/images/fuzion.svg", @@ -6229,6 +6569,7 @@ "kind": "native", "denom": "factory/kujira1sc6a0347cc5q3k890jj0pf3ylx2s38rh4sza4t/urfuzn", "decimals": 6, + "variant": "cosmos", "displayName": "rFUZN", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kujira/images/fuzionr.png", @@ -6238,6 +6579,7 @@ "kind": "native", "denom": "factory/kujira1sc6a0347cc5q3k890jj0pf3ylx2s38rh4sza4t/uyfuzn", "decimals": 6, + "variant": "cosmos", "displayName": "yFUZN", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kujira/images/fuziony.svg", @@ -6247,6 +6589,7 @@ "kind": "native", "denom": "factory/kujira1l04ged98c7a7s9tllu62ld09ztylwf442qgm4thfgmadrvngeumsz4zrh2/urcpt", "decimals": 6, + "variant": "cosmos", "displayName": "qcFUZN", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kujira/images/qcfuzn.svg", @@ -6256,6 +6599,7 @@ "kind": "native", "denom": "factory/kujira1aaudpfr9y23lt9d45hrmskphpdfaq9ajxd3ukh/unstk", "decimals": 6, + "variant": "cosmos", "displayName": "NSTK", "coingeckoId": "unstake-fi", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kujira/images/nstk.svg", @@ -6265,6 +6609,7 @@ "kind": "native", "denom": "factory/kujira1swkuyt08z74n5jl7zr6hx0ru5sa2yev5v896p6/local", "decimals": 6, + "variant": "cosmos", "displayName": "LOCAL", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kujira/images/local.png", @@ -6274,6 +6619,7 @@ "kind": "native", "denom": "factory/kujira166ysf07ze5suazfzj0r05tv8amk2yn8zvsfuu7/uplnk", "decimals": 6, + "variant": "cosmos", "displayName": "PLNK", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kujira/images/PLNK_drk.png", @@ -6312,6 +6658,7 @@ "kind": "native", "denom": "ukuji", "decimals": 6, + "variant": "cosmos", "displayName": "KUJI", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/kujiratestnet/images/kuji.png", @@ -6321,6 +6668,7 @@ "kind": "native", "denom": "factory/kujira16qpvzhmawvsm8mcj4hdvtz25dadatdhhgw79xa/FUZN", "decimals": 6, + "variant": "cosmos", "displayName": "FUZN", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/kujiratestnet/images/fuzn.png", @@ -6358,6 +6706,7 @@ "kind": "native", "denom": "ukyve", "decimals": 6, + "variant": "cosmos", "displayName": "KYVE", "coingeckoId": "kyve-network", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kyve/images/kyve-token.svg", @@ -6396,6 +6745,7 @@ "kind": "native", "denom": "tkyve", "decimals": 6, + "variant": "cosmos", "displayName": "KYVE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/kyvetestnet/images/kyve.svg", @@ -6433,6 +6783,7 @@ "kind": "native", "denom": "tkyve", "decimals": 9, + "variant": "cosmos", "displayName": "KYVE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/kyvedevnet/images/kyve.svg", @@ -6470,6 +6821,7 @@ "kind": "native", "denom": "ulamb", "decimals": 18, + "variant": "cosmos", "displayName": "LAMB", "coingeckoId": "lambda", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/lambda/images/lambda.svg", @@ -6508,6 +6860,7 @@ "kind": "native", "denom": "ulava", "decimals": 6, + "variant": "cosmos", "displayName": "LAVA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/lavatestnet/images/lava-icon.svg", @@ -6546,6 +6899,7 @@ "kind": "native", "denom": "nanolike", "decimals": 9, + "variant": "cosmos", "displayName": "LIKE", "coingeckoId": "likecoin", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/likecoin/images/like.svg", @@ -6584,6 +6938,7 @@ "kind": "native", "denom": "nanoekil", "decimals": 9, + "variant": "cosmos", "displayName": "EKIL", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/likecoin/images/like.svg", @@ -6622,6 +6977,7 @@ "kind": "native", "denom": "aLYT", "decimals": 18, + "variant": "cosmos", "displayName": "LYT", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/logos/images/logos.svg", @@ -6660,6 +7016,7 @@ "kind": "native", "denom": "ulyl", "decimals": 6, + "variant": "cosmos", "displayName": "LYL", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/loyal/images/lyl.svg", @@ -6698,6 +7055,7 @@ "kind": "native", "denom": "ulum", "decimals": 6, + "variant": "cosmos", "displayName": "LUM", "coingeckoId": "lum-network", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/lumnetwork/images/lum.svg", @@ -6736,6 +7094,7 @@ "kind": "native", "denom": "ulumen", "decimals": 6, + "variant": "cosmos", "displayName": "LUMEN", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/lumenx/images/lumen.svg", @@ -6774,6 +7133,7 @@ "kind": "native", "denom": "ulumen", "decimals": 6, + "variant": "cosmos", "displayName": "LUMEN", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/lumenxtestnet/images/lumen.svg", @@ -6811,6 +7171,7 @@ "kind": "native", "denom": "umars", "decimals": 6, + "variant": "cosmos", "displayName": "MARS", "coingeckoId": "mars-protocol-a7fcbcfb-fd61-4017-92f0-7ee9f9cc6da3", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/mars/images/mars-token.svg", @@ -6849,6 +7210,7 @@ "kind": "native", "denom": "umars", "decimals": 6, + "variant": "cosmos", "displayName": "MARS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/mars/images/mars-token.svg", @@ -6887,6 +7249,7 @@ "kind": "native", "denom": "cacao", "decimals": 10, + "variant": "cosmos", "displayName": "CACAO", "coingeckoId": "cacao", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/mayachain/images/cacao.svg", @@ -6896,6 +7259,7 @@ "kind": "native", "denom": "maya", "decimals": 4, + "variant": "cosmos", "displayName": "MAYA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/mayachain/images/maya.svg", @@ -6933,6 +7297,7 @@ "kind": "native", "denom": "umedas", "decimals": 6, + "variant": "cosmos", "displayName": "MEDAS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/medasdigital/images/medas.svg", @@ -6971,6 +7336,7 @@ "kind": "native", "denom": "umed", "decimals": 6, + "variant": "cosmos", "displayName": "MED", "coingeckoId": "medibloc", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/panacea/images/med.svg", @@ -7009,6 +7375,7 @@ "kind": "native", "denom": "umeme", "decimals": 6, + "variant": "cosmos", "displayName": "MEME", "coingeckoId": "meme-network", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/meme/images/meme.svg", @@ -7047,6 +7414,7 @@ "kind": "native", "denom": "utick", "decimals": 6, + "variant": "cosmos", "displayName": "TICK", "coingeckoId": "microtick", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/microtick/images/tick.svg", @@ -7085,6 +7453,7 @@ "kind": "native", "denom": "uwhale", "decimals": 6, + "variant": "cosmos", "displayName": "WHALE", "coingeckoId": "white-whale", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/migaloo/images/white-whale.svg", @@ -7094,6 +7463,7 @@ "kind": "native", "denom": "factory/migaloo1436kxs0w2es6xlqpp9rd35e3d0cjnw4sv8j3a7483sgks29jqwgshqdky4/ampWHALE", "decimals": 6, + "variant": "cosmos", "displayName": "ampWHALE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/migaloo/images/ampwhale.svg", @@ -7103,6 +7473,7 @@ "kind": "native", "denom": "factory/migaloo1mf6ptkssddfmxvhdx0ech0k03ktp6kf9yk59renau2gvht3nq2gqdhts4u/boneWhale", "decimals": 6, + "variant": "cosmos", "displayName": "bWHALE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/migaloo/images/bWHALE.svg", @@ -7112,6 +7483,7 @@ "kind": "native", "denom": "factory/migaloo18a9m9stu3dyvewwcq9qmp85euxqcvln5mefync/fable", "decimals": 6, + "variant": "cosmos", "displayName": "FABLE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/migaloo/images/fable.svg", @@ -7121,6 +7493,7 @@ "kind": "native", "denom": "factory/migaloo1eqntnl6tzcj9h86psg4y4h6hh05g2h9nj8e09l/urac", "decimals": 6, + "variant": "cosmos", "displayName": "RAC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/migaloo/images/rac.svg", @@ -7130,6 +7503,7 @@ "kind": "native", "denom": "factory/migaloo1erul6xyq0gk6ws98ncj7lnq9l4jn4gnnu9we73gdz78yyl2lr7qqrvcgup/ash", "decimals": 6, + "variant": "cosmos", "displayName": "ASH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/migaloo/images/ash.svg", @@ -7139,6 +7513,7 @@ "kind": "native", "denom": "cw20:migaloo10nucfm2zqgzqmy7y7ls398t58pjt9cwjsvpy88y2nvamtl34rgmqt5em2v", "decimals": 6, + "variant": "cosmos", "displayName": "mUSDC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/migaloo/images/mUSDC.svg", @@ -7148,6 +7523,7 @@ "kind": "native", "denom": "factory/migaloo1etlu2h30tjvv8rfa4fwdc43c92f6ul5w9acxzk/uguppy", "decimals": 6, + "variant": "cosmos", "displayName": "GUPPY", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/migaloo/images/guppy.png", @@ -7157,6 +7533,7 @@ "kind": "native", "denom": "factory/migaloo1t862qdu9mj5hr3j727247acypym3ej47axu22rrapm4tqlcpuseqltxwq5/ophir", "decimals": 6, + "variant": "cosmos", "displayName": "OPHIR", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/migaloo/images/ophir.png", @@ -7195,6 +7572,7 @@ "kind": "native", "denom": "uwhale", "decimals": 6, + "variant": "cosmos", "displayName": "WHALE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/migaloo/images/white-whale.svg", @@ -7233,6 +7611,7 @@ "kind": "native", "denom": "umis", "decimals": 6, + "variant": "cosmos", "displayName": "MIS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/mises/images/mises.png", @@ -7271,6 +7650,7 @@ "kind": "native", "denom": "utia", "decimals": 6, + "variant": "cosmos", "displayName": "TIA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/celestiatestnet3/images/celestia.svg", @@ -7308,6 +7688,7 @@ "kind": "native", "denom": "umun", "decimals": 6, + "variant": "cosmos", "displayName": "MUN", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/mun/images/mun.svg", @@ -7346,6 +7727,7 @@ "kind": "native", "denom": "aMYT", "decimals": 18, + "variant": "cosmos", "displayName": "MYT", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/mythos/images/mythos.svg", @@ -7384,6 +7766,7 @@ "kind": "native", "denom": "untrn", "decimals": 6, + "variant": "cosmos", "displayName": "NTRN", "coingeckoId": "neutron-3", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/neutron/images/ntrn.svg", @@ -7393,6 +7776,7 @@ "kind": "native", "denom": "factory/neutron14henrqx9y328fjrdvz6l6d92r0t7g5hk86q5nd/uastropepe", "decimals": 6, + "variant": "cosmos", "displayName": "ASTROPEPE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/neutron/images/astropepe.png", @@ -7402,6 +7786,7 @@ "kind": "native", "denom": "factory/neutron1ug740qrkquxzrk2hh29qrlx3sktkfml3je7juusc2te7xmvsscns0n2wry/wstETH", "decimals": 18, + "variant": "cosmos", "displayName": "wstETH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/wsteth.svg", @@ -7411,6 +7796,7 @@ "kind": "native", "denom": "factory/neutron1p8d89wvxyjcnawmgw72klknr3lg9gwwl6ypxda/newt", "decimals": 6, + "variant": "cosmos", "displayName": "NEWT", "coingeckoId": "newt", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/neutron/images/newt.png", @@ -7420,6 +7806,7 @@ "kind": "native", "denom": "factory/neutron1tklm6cvr2wxg8k65t8gh5ewslnzdfd5fsk0w3f/corgi", "decimals": 6, + "variant": "cosmos", "displayName": "CORGI", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/neutron/images/babycorgi.png", @@ -7429,6 +7816,7 @@ "kind": "native", "denom": "factory/neutron170v88vrtnedesyfytuku257cggxc79rd7lwt7q/ucircus", "decimals": 6, + "variant": "cosmos", "displayName": "CIRCUS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/neutron/images/circus.png", @@ -7438,6 +7826,7 @@ "kind": "native", "denom": "factory/neutron108x7vp9zv22d6wxrs9as8dshd3pd5vsga463yd/JIMMY", "decimals": 6, + "variant": "cosmos", "displayName": "JIMMY", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/neutron/images/jimmy.png", @@ -7447,6 +7836,7 @@ "kind": "native", "denom": "factory/neutron143wp6g8paqasnuuey6zyapucknwy9rhnld8hkr/bad", "decimals": 6, + "variant": "cosmos", "displayName": "BAD", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/neutron/images/bad.png", @@ -7456,6 +7846,7 @@ "kind": "native", "denom": "neutron1fjzg7fmv770hsvahqm0nwnu6grs3rjnd2wa6fvm9unv6vedkzekqpw44qj", "decimals": 6, + "variant": "cosmos", "displayName": "BTC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/neutron/images/bitcosmos.png", @@ -7465,6 +7856,7 @@ "kind": "native", "denom": "neutron12h09p8hq5y4xpsmcuxxzsn9juef4f6jvekp8yefc6xnlwm6uumnsdk29wf", "decimals": 6, + "variant": "cosmos", "displayName": "WTF", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/neutron/images/WTF.png", @@ -7474,6 +7866,7 @@ "kind": "native", "denom": "factory/neutron1t5qrjtyryh8gzt800qr5vylhh2f8cmx4wmz9mc/ugoddard", "decimals": 6, + "variant": "cosmos", "displayName": "GODRD", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/neutron/images/goddardntrn.png", @@ -7483,6 +7876,7 @@ "kind": "native", "denom": "factory/neutron154gg0wtm2v4h9ur8xg32ep64e8ef0g5twlsgvfeajqwghdryvyqsqhgk8e/APOLLO", "decimals": 6, + "variant": "cosmos", "displayName": "APOLLO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/neutron/images/apollo.svg", @@ -7492,6 +7886,7 @@ "kind": "native", "denom": "factory/neutron1ume2n42r5j0660gegrr28fzdze7aqf7r5cd9y6/newtroll", "decimals": 6, + "variant": "cosmos", "displayName": "NTRL", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/neutron/images/newtroll.svg", @@ -7501,6 +7896,7 @@ "kind": "native", "denom": "factory/neutron1t24nc7whl77relnu3taxyg3p66pjyuk82png2y/uretro", "decimals": 6, + "variant": "cosmos", "displayName": "RETRO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/neutron/images/retro.svg", @@ -7539,6 +7935,7 @@ "kind": "native", "denom": "untrn", "decimals": 6, + "variant": "cosmos", "displayName": "NTRN", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/neutrontestnet/images/neutron.svg", @@ -7577,6 +7974,7 @@ "kind": "native", "denom": "unibi", "decimals": 6, + "variant": "cosmos", "displayName": "NIBI", "coingeckoId": "nibi", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/nibiru/images/nibiru.svg", @@ -7615,6 +8013,7 @@ "kind": "native", "denom": "ustake", "decimals": 6, + "variant": "cosmos", "displayName": "STAKE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/noble/images/stake.svg", @@ -7624,6 +8023,7 @@ "kind": "native", "denom": "ufrienzies", "decimals": 6, + "variant": "cosmos", "displayName": "FRNZ", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/noble/images/frnz.svg", @@ -7633,6 +8033,7 @@ "kind": "native", "denom": "uusdc", "decimals": 6, + "variant": "cosmos", "displayName": "USDC", "coingeckoId": "usd-coin", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/noble/images/USDCoin.svg", @@ -7671,6 +8072,7 @@ "kind": "native", "denom": "ustake", "decimals": 6, + "variant": "cosmos", "displayName": "STAKE", "coingeckoId": "not-found", "icon": "not-found", @@ -7680,6 +8082,7 @@ "kind": "native", "denom": "ulove", "decimals": 6, + "variant": "cosmos", "displayName": "LOVE", "coingeckoId": "not-found", "icon": "not-found", @@ -7689,6 +8092,7 @@ "kind": "native", "denom": "uusdc", "decimals": 6, + "variant": "cosmos", "displayName": "USDC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/usdc.svg", @@ -7698,6 +8102,7 @@ "kind": "native", "denom": "uusdlr", "decimals": 6, + "variant": "cosmos", "displayName": "USDLR", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/nobletestnet/images/usdlr.svg", @@ -7735,6 +8140,7 @@ "kind": "native", "denom": "unois", "decimals": 6, + "variant": "cosmos", "displayName": "NOIS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/nois/images/nois.svg", @@ -7773,6 +8179,7 @@ "kind": "native", "denom": "unois", "decimals": 6, + "variant": "cosmos", "displayName": "NOIS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/nois/images/nois.svg", @@ -7811,6 +8218,7 @@ "kind": "native", "denom": "unls", "decimals": 6, + "variant": "cosmos", "displayName": "NLS", "coingeckoId": "nolus", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/nolus/images/nolus.svg", @@ -7849,6 +8257,7 @@ "kind": "native", "denom": "unls", "decimals": 6, + "variant": "cosmos", "displayName": "NLS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/nolustestnet/images/nolus.svg", @@ -7887,6 +8296,7 @@ "kind": "native", "denom": "unom", "decimals": 6, + "variant": "cosmos", "displayName": "NOM", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/nomic/images/nom.svg", @@ -7896,6 +8306,7 @@ "kind": "native", "denom": "usat", "decimals": 14, + "variant": "cosmos", "displayName": "nBTC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/nomic/images/nbtc.svg", @@ -7934,6 +8345,7 @@ "kind": "native", "denom": "unyx", "decimals": 6, + "variant": "cosmos", "displayName": "NYX", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/nyx/images/nyx.png", @@ -7943,6 +8355,7 @@ "kind": "native", "denom": "unym", "decimals": 6, + "variant": "cosmos", "displayName": "NYM", "coingeckoId": "nym", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/nyx/images/nym.png", @@ -7981,6 +8394,7 @@ "kind": "native", "denom": "uocta", "decimals": 6, + "variant": "cosmos", "displayName": "OCTA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/octa/images/octa.svg", @@ -8019,6 +8433,7 @@ "kind": "native", "denom": "loki", "decimals": 6, + "variant": "cosmos", "displayName": "ODIN", "coingeckoId": "odin-protocol", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/odin/images/odin.svg", @@ -8028,6 +8443,7 @@ "kind": "native", "denom": "mGeo", "decimals": 6, + "variant": "cosmos", "displayName": "GEO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/odin/images/geo.svg", @@ -8037,6 +8453,7 @@ "kind": "native", "denom": "mO9W", "decimals": 6, + "variant": "cosmos", "displayName": "O9W", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/odin/images/o9w.svg", @@ -8075,6 +8492,7 @@ "kind": "native", "denom": "wei", "decimals": 18, + "variant": "cosmos", "displayName": "OKT", "coingeckoId": "oec-token", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/okexchain/images/okc.png", @@ -8113,6 +8531,7 @@ "kind": "native", "denom": "uknow", "decimals": 6, + "variant": "cosmos", "displayName": "KNOW", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/okp4testnet/images/okp4.png", @@ -8151,6 +8570,7 @@ "kind": "native", "denom": "uflix", "decimals": 6, + "variant": "cosmos", "displayName": "FLIX", "coingeckoId": "omniflix-network", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/omniflixhub/images/flix.svg", @@ -8189,6 +8609,7 @@ "kind": "native", "denom": "anom", "decimals": 18, + "variant": "cosmos", "displayName": "NOM", "coingeckoId": "onomy-protocol", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/onomy/images/nom.svg", @@ -8227,6 +8648,7 @@ "kind": "native", "denom": "orai", "decimals": 6, + "variant": "cosmos", "displayName": "ORAI", "coingeckoId": "oraichain-token", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/oraichain/images/orai-white.svg", @@ -8270,6 +8692,7 @@ "denom": "uosmo", "displayName": "OSMO", "decimals": 6, + "variant": "cosmos", "coingeckoId": "osmosis", "icon": "osmosis-circle.svg", "kind": "native", @@ -8346,6 +8769,7 @@ "denom": "uosmo", "displayName": "OSMO", "decimals": 6, + "variant": "cosmos", "coingeckoId": "osmosis", "icon": "osmosis-circle.svg", "kind": "native", @@ -8406,6 +8830,7 @@ "kind": "native", "denom": "uosmo", "decimals": 6, + "variant": "cosmos", "displayName": "OSMO", "coingeckoId": "osmosis", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/osmosis/images/osmo.svg", @@ -8415,6 +8840,7 @@ "kind": "native", "denom": "uion", "decimals": 6, + "variant": "cosmos", "displayName": "ION", "coingeckoId": "ion", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/osmosis/images/ion.svg", @@ -8453,6 +8879,7 @@ "kind": "native", "denom": "upasg", "decimals": 6, + "variant": "cosmos", "displayName": "PASG", "coingeckoId": "passage", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/passage/images/pasg.png", @@ -8491,6 +8918,7 @@ "kind": "native", "denom": "upasg", "decimals": 6, + "variant": "cosmos", "displayName": "PASG", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/passage/images/pasg.png", @@ -8529,6 +8957,7 @@ "kind": "native", "denom": "uxprt", "decimals": 6, + "variant": "cosmos", "displayName": "XPRT", "coingeckoId": "persistence", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/persistence/images/xprt.svg", @@ -8538,6 +8967,7 @@ "kind": "native", "denom": "stk/uatom", "decimals": 6, + "variant": "cosmos", "displayName": "stkATOM", "coingeckoId": "stkatom", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/persistence/images/stkatom.svg", @@ -8547,6 +8977,7 @@ "kind": "native", "denom": "stk/uosmo", "decimals": 6, + "variant": "cosmos", "displayName": "stkOSMO", "coingeckoId": "pstake-staked-osmo", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/persistence/images/stkosmo.svg", @@ -8585,6 +9016,7 @@ "kind": "native", "denom": "uxprt", "decimals": 6, + "variant": "cosmos", "displayName": "XPRT", "coingeckoId": "persistence", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/persistence/images/xprt.svg", @@ -8594,6 +9026,7 @@ "kind": "native", "denom": "stk/uatom", "decimals": 6, + "variant": "cosmos", "displayName": "stkATOM", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/persistence/images/stkatom.svg", @@ -8631,6 +9064,7 @@ "kind": "native", "denom": "uxprt", "decimals": 6, + "variant": "cosmos", "displayName": "XPRT", "coingeckoId": "persistence", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/persistence/images/xprt.svg", @@ -8640,6 +9074,7 @@ "kind": "native", "denom": "stk/uatom", "decimals": 6, + "variant": "cosmos", "displayName": "stkATOM", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/persistence/images/stkatom.svg", @@ -8649,6 +9084,7 @@ "kind": "native", "denom": "stk/uosmo", "decimals": 6, + "variant": "cosmos", "displayName": "stkOSMO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/persistence/images/stkosmo.svg", @@ -8658,6 +9094,7 @@ "kind": "native", "denom": "stk/adv4tnt", "decimals": 18, + "variant": "cosmos", "displayName": "stkDV4TNT", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/persistence/images/stkdv4tnt.svg", @@ -8695,6 +9132,7 @@ "kind": "native", "denom": "aplanq", "decimals": 18, + "variant": "cosmos", "displayName": "PLQ", "coingeckoId": "planq", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/planq/images/planq.svg", @@ -8733,6 +9171,7 @@ "kind": "native", "denom": "apoint", "decimals": 18, + "variant": "cosmos", "displayName": "POINT", "coingeckoId": "point-network", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/point/images/point-logo.svg", @@ -8773,6 +9212,7 @@ "denom": "0x0000000000000000000000000000000000000000", "displayName": "MATIC", "decimals": 18, + "variant": "ethereum", "coingeckoId": "matic", "icon": "polygon.svg", "kind": "native", @@ -8815,6 +9255,7 @@ "denom": "0x0000000000000000000000000000000000000000", "displayName": "MATIC", "decimals": 18, + "variant": "ethereum", "coingeckoId": "matic", "icon": "polygon.svg", "kind": "native", @@ -8853,6 +9294,7 @@ "kind": "native", "denom": "nhash", "decimals": 9, + "variant": "cosmos", "displayName": "HASH", "coingeckoId": "provenance-blockchain", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/provenance/images/prov.svg", @@ -8891,6 +9333,7 @@ "kind": "native", "denom": "upryzm", "decimals": 6, + "variant": "cosmos", "displayName": "PRYZM", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/pryzmtestnet/images/pryzm.svg", @@ -8929,6 +9372,7 @@ "kind": "native", "denom": "bsc0x29a63F4B209C29B4DC47f06FFA896F32667DAD2C", "decimals": 18, + "variant": "cosmos", "displayName": "PURSE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/pundix/images/purse-token-logo.svg", @@ -8967,6 +9411,7 @@ "kind": "native", "denom": "uqsr", "decimals": 6, + "variant": "cosmos", "displayName": "QSR", "coingeckoId": "quasar-2", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/quasar/images/quasar.png", @@ -9005,6 +9450,7 @@ "kind": "native", "denom": "uqsr", "decimals": 6, + "variant": "cosmos", "displayName": "QSR", "coingeckoId": "not-found", "icon": "not-found", @@ -9014,6 +9460,7 @@ "kind": "native", "denom": "uay", "decimals": 6, + "variant": "cosmos", "displayName": "AYY", "coingeckoId": "not-found", "icon": "not-found", @@ -9023,6 +9470,7 @@ "kind": "native", "denom": "oro", "decimals": 6, + "variant": "cosmos", "displayName": "ORO", "coingeckoId": "not-found", "icon": "not-found", @@ -9061,6 +9509,7 @@ "kind": "native", "denom": "uqck", "decimals": 6, + "variant": "cosmos", "displayName": "QCK", "coingeckoId": "quicksilver", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/quicksilver/images/qck.png", @@ -9070,6 +9519,7 @@ "kind": "native", "denom": "uqstars", "decimals": 6, + "variant": "cosmos", "displayName": "qSTARS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/quicksilver/images/qstars.svg", @@ -9079,6 +9529,7 @@ "kind": "native", "denom": "uqatom", "decimals": 6, + "variant": "cosmos", "displayName": "qATOM", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/quicksilver/images/qatom.svg", @@ -9088,6 +9539,7 @@ "kind": "native", "denom": "uqregen", "decimals": 6, + "variant": "cosmos", "displayName": "qREGEN", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/quicksilver/images/qregen.svg", @@ -9097,6 +9549,7 @@ "kind": "native", "denom": "uqosmo", "decimals": 6, + "variant": "cosmos", "displayName": "qOSMO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/quicksilver/images/qosmo.svg", @@ -9106,6 +9559,7 @@ "kind": "native", "denom": "uqsomm", "decimals": 6, + "variant": "cosmos", "displayName": "qSOMM", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/quicksilver/images/qsomm.svg", @@ -9144,6 +9598,7 @@ "kind": "native", "denom": "uqck", "decimals": 6, + "variant": "cosmos", "displayName": "QCK", "coingeckoId": "quicksilver", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/quicksilver/images/qck.png", @@ -9182,6 +9637,7 @@ "kind": "native", "denom": "uqwoyn", "decimals": 6, + "variant": "cosmos", "displayName": "QWOYN", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/qwoyn/images/qwoyn.png", @@ -9220,6 +9676,7 @@ "kind": "native", "denom": "uqwoyn", "decimals": 6, + "variant": "cosmos", "displayName": "QWOYN", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/qwoyntestnet/images/qwoyn.png", @@ -9258,6 +9715,7 @@ "kind": "native", "denom": "ario", "decimals": 18, + "variant": "cosmos", "displayName": "RIO", "coingeckoId": "realio-network", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/realio/images/rio.svg", @@ -9267,6 +9725,7 @@ "kind": "native", "denom": "arst", "decimals": 18, + "variant": "cosmos", "displayName": "RST", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/realio/images/rst.png", @@ -9305,6 +9764,7 @@ "kind": "native", "denom": "arebus", "decimals": 18, + "variant": "cosmos", "displayName": "REBUS", "coingeckoId": "rebus", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/rebus/images/rebus.svg", @@ -9343,6 +9803,7 @@ "kind": "native", "denom": "uregen", "decimals": 6, + "variant": "cosmos", "displayName": "REGEN", "coingeckoId": "regen", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/regen/images/regen.svg", @@ -9352,6 +9813,7 @@ "kind": "native", "denom": "eco.uC.NCT", "decimals": 6, + "variant": "cosmos", "displayName": "NCT", "coingeckoId": "toucan-protocol-nature-carbon-tonne", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/regen/images/nct.svg", @@ -9390,6 +9852,7 @@ "kind": "native", "denom": "uatom", "decimals": 6, + "variant": "cosmos", "displayName": "ATOM", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/cosmoshub/images/atom.svg", @@ -9427,6 +9890,7 @@ "kind": "native", "denom": "uatolo", "decimals": 6, + "variant": "cosmos", "displayName": "ATOLO", "coingeckoId": "rizon", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/rizon/images/atolo.svg", @@ -9469,7 +9933,8 @@ "displayName": "SAGA", "coingeckoId": "saga-2", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/saga/images/saga.svg", - "color": "TODO" + "color": "TODO", + "variant": "cosmos" } ], "features": [], @@ -9504,6 +9969,7 @@ "kind": "native", "denom": "utsaga", "decimals": 6, + "variant": "cosmos", "displayName": "TSAGA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/saga/images/saga.svg", @@ -9545,7 +10011,8 @@ "displayName": "TSAGA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/saga/images/saga.svg", - "color": "TODO" + "color": "TODO", + "variant": "cosmos" } ], "features": [], @@ -9580,6 +10047,7 @@ "kind": "native", "denom": "uakt", "decimals": 6, + "variant": "cosmos", "displayName": "AKT", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/akash/images/akt.svg", @@ -9618,6 +10086,7 @@ "kind": "native", "denom": "uscrt", "decimals": 6, + "variant": "cosmos", "displayName": "SCRT", "coingeckoId": "secret", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/secretnetwork/images/scrt.svg", @@ -9627,6 +10096,7 @@ "kind": "native", "denom": "cw20:secret1rgm2m5t530tdzyd99775n6vzumxa5luxcllml4", "decimals": 18, + "variant": "cosmos", "displayName": "SIENNA", "coingeckoId": "sienna", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/secretnetwork/images/sienna.svg", @@ -9636,6 +10106,7 @@ "kind": "native", "denom": "cw20:secret1qfql357amn448duf5gvp9gr48sxx9tsnhupu3d", "decimals": 8, + "variant": "cosmos", "displayName": "SHD(old)", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/secretnetwork/images/shdold.svg", @@ -9645,6 +10116,7 @@ "kind": "native", "denom": "cw20:secret153wu605vvp934xhd4k9dtd640zsep5jkesstdm", "decimals": 8, + "variant": "cosmos", "displayName": "SHD", "coingeckoId": "shade-protocol", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/secretnetwork/images/shd.svg", @@ -9654,6 +10126,7 @@ "kind": "native", "denom": "cw20:secret1fl449muk5yq8dlad7a22nje4p5d2pnsgymhjfd", "decimals": 6, + "variant": "cosmos", "displayName": "SILK", "coingeckoId": "silk-bcec1136-561c-4706-a42c-8b67d0d7f7d2", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/secretnetwork/images/silk.svg", @@ -9663,6 +10136,7 @@ "kind": "native", "denom": "cw20:secret1k6u0cy4feepm6pehnz804zmwakuwdapm69tuc4", "decimals": 6, + "variant": "cosmos", "displayName": "stkd-SCRT", "coingeckoId": "stkd-scrt", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/secretnetwork/images/stkd-scrt.svg", @@ -9672,6 +10146,7 @@ "kind": "native", "denom": "cw20:secret1yxcexylwyxlq58umhgsjgstgcg2a0ytfy4d9lt", "decimals": 6, + "variant": "cosmos", "displayName": "BUTT", "coingeckoId": "buttcoin-2", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/secretnetwork/images/butt.svg", @@ -9681,6 +10156,7 @@ "kind": "native", "denom": "cw20:secret12rcvz0umvk875kd6a803txhtlu7y0pnd73kcej", "decimals": 6, + "variant": "cosmos", "displayName": "ALTER", "coingeckoId": "alter", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/secretnetwork/images/alter.svg", @@ -9690,6 +10166,7 @@ "kind": "native", "denom": "cw20:secret1s09x2xvfd2lp2skgzm29w2xtena7s8fq98v852", "decimals": 6, + "variant": "cosmos", "displayName": "AMBER", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/secretnetwork/images/amber.svg", @@ -9699,6 +10176,7 @@ "kind": "native", "denom": "cw20:secret197dvnt9yjxwn8sjdlx05f7zuk27lsdxtfnwxse", "decimals": 6, + "variant": "cosmos", "displayName": "SHILL", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/secretnetwork/images/shill.svg", @@ -9737,6 +10215,7 @@ "kind": "native", "denom": "uscrt", "decimals": 6, + "variant": "cosmos", "displayName": "SCRT", "coingeckoId": "secret", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/secretnetwork/images/scrt.svg", @@ -9774,6 +10253,7 @@ "kind": "native", "denom": "uscrt", "decimals": 6, + "variant": "cosmos", "displayName": "SCRT", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/secretnetwork/images/scrt.svg", @@ -9811,6 +10291,7 @@ "kind": "native", "denom": "usei", "decimals": 6, + "variant": "cosmos", "displayName": "SEI", "coingeckoId": "sei-network", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/sei/images/sei.svg", @@ -9820,6 +10301,7 @@ "kind": "native", "denom": "factory/sei1thgp6wamxwqt7rthfkeehktmq0ujh5kspluw6w/OIN", "decimals": 6, + "variant": "cosmos", "displayName": "OIN", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/sei/images/oin.png", @@ -9829,6 +10311,7 @@ "kind": "native", "denom": "factory/sei1x2fgaaqecvk8kwuqkjqcj27clw5p5g99uawdzy9sc4rku8avumcq3cky4k/ampSEI", "decimals": 6, + "variant": "cosmos", "displayName": "ampSEI", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/sei/images/ampsei.svg", @@ -9838,6 +10321,7 @@ "kind": "native", "denom": "factory/sei1fl8pg59wfsgw2wp4aruk38zqccfnc2g8ptrm24/popeye", "decimals": 6, + "variant": "cosmos", "displayName": "POPEYE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/sei/images/popeye.png", @@ -9847,6 +10331,7 @@ "kind": "native", "denom": "factory/sei1ta5rkr6y2qlkj7px8w2cvear7m2822q4f4ea0m/sensei", "decimals": 6, + "variant": "cosmos", "displayName": "SENSEI", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/sei/images/SenseiDog.png", @@ -9885,6 +10370,7 @@ "kind": "native", "denom": "usei", "decimals": 6, + "variant": "cosmos", "displayName": "SEI", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/seitestnet/images/sei.png", @@ -9923,6 +10409,7 @@ "kind": "native", "denom": "usei", "decimals": 6, + "variant": "cosmos", "displayName": "SEI", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/seidevnet3/images/sei.png", @@ -9960,6 +10447,7 @@ "kind": "native", "denom": "udvpn", "decimals": 6, + "variant": "cosmos", "displayName": "DVPN", "coingeckoId": "sentinel", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/sentinel/images/dvpn.svg", @@ -9998,6 +10486,7 @@ "kind": "native", "denom": "usge", "decimals": 6, + "variant": "cosmos", "displayName": "SGE", "coingeckoId": "six-sigma", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/sge/images/sge.svg", @@ -10036,6 +10525,7 @@ "kind": "native", "denom": "usge", "decimals": 6, + "variant": "cosmos", "displayName": "SGE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/sgetestnet/images/sge.png", @@ -10074,6 +10564,7 @@ "kind": "native", "denom": "nshr", "decimals": 9, + "variant": "cosmos", "displayName": "SHR", "coingeckoId": "shareledger", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/shareledger/images/token.svg", @@ -10112,6 +10603,7 @@ "kind": "native", "denom": "uctk", "decimals": 6, + "variant": "cosmos", "displayName": "CTK", "coingeckoId": "certik", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/shentu/images/ctk.svg", @@ -10150,6 +10642,7 @@ "kind": "native", "denom": "rowan", "decimals": 18, + "variant": "cosmos", "displayName": "ROWAN", "coingeckoId": "sifchain", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/sifchain/images/rowan.svg", @@ -10188,6 +10681,7 @@ "kind": "native", "denom": "usix", "decimals": 6, + "variant": "cosmos", "displayName": "six", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/sixtestnet/images/six.png", @@ -10225,6 +10719,7 @@ "kind": "native", "denom": "usix", "decimals": 6, + "variant": "cosmos", "displayName": "SIX", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/six/images/six.png", @@ -10262,6 +10757,7 @@ "kind": "native", "denom": "usomm", "decimals": 6, + "variant": "cosmos", "displayName": "SOMM", "coingeckoId": "sommelier", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/sommelier/images/somm.svg", @@ -10300,6 +10796,7 @@ "kind": "native", "denom": "usource", "decimals": 6, + "variant": "cosmos", "displayName": "SOURCE", "coingeckoId": "source", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/source/images/source.svg", @@ -10338,6 +10835,7 @@ "kind": "native", "denom": "usource", "decimals": 6, + "variant": "cosmos", "displayName": "SOURCE", "coingeckoId": "source-protocol", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/sourcetestnet/images/source.svg", @@ -10375,6 +10873,7 @@ "kind": "native", "denom": "ufis", "decimals": 6, + "variant": "cosmos", "displayName": "FIS", "coingeckoId": "stafi", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stafihub/images/fis.svg", @@ -10384,6 +10883,7 @@ "kind": "native", "denom": "uratom", "decimals": 6, + "variant": "cosmos", "displayName": "rATOM", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stafihub/images/ratom.svg", @@ -10393,6 +10893,7 @@ "kind": "native", "denom": "uriris", "decimals": 6, + "variant": "cosmos", "displayName": "rIRIS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stafihub/images/riris.svg", @@ -10402,6 +10903,7 @@ "kind": "native", "denom": "urhuahua", "decimals": 6, + "variant": "cosmos", "displayName": "rHUAHUA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stafihub/images/rhuahua.svg", @@ -10411,6 +10913,7 @@ "kind": "native", "denom": "urswth", "decimals": 8, + "variant": "cosmos", "displayName": "rSWTH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stafihub/images/rswth.svg", @@ -10449,6 +10952,7 @@ "kind": "native", "denom": "ustars", "decimals": 6, + "variant": "cosmos", "displayName": "STARS", "coingeckoId": "stargaze", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stargaze/images/stars.svg", @@ -10458,6 +10962,7 @@ "kind": "native", "denom": "factory/stars16da2uus9zrsy83h23ur42v3lglg5rmyrpqnju4/dust", "decimals": 6, + "variant": "cosmos", "displayName": "STRDST", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stargaze/images/dust.svg", @@ -10467,6 +10972,7 @@ "kind": "native", "denom": "factory/stars16da2uus9zrsy83h23ur42v3lglg5rmyrpqnju4/mGAZE", "decimals": 6, + "variant": "cosmos", "displayName": "GAZE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stargaze/images/gaze.svg", @@ -10476,6 +10982,7 @@ "kind": "native", "denom": "factory/stars16da2uus9zrsy83h23ur42v3lglg5rmyrpqnju4/uBRNCH", "decimals": 6, + "variant": "cosmos", "displayName": "BRNCH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stargaze/images/brnch.svg", @@ -10485,6 +10992,7 @@ "kind": "native", "denom": "factory/stars16da2uus9zrsy83h23ur42v3lglg5rmyrpqnju4/uOHH", "decimals": 6, + "variant": "cosmos", "displayName": "OHH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stargaze/images/ohh.svg", @@ -10494,6 +11002,7 @@ "kind": "native", "denom": "factory/stars1xx5976njvxpl9n4v8huvff6cudhx7yuu8e7rt4/usneaky", "decimals": 6, + "variant": "cosmos", "displayName": "SNEAKY", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stargaze/images/sneaky.svg", @@ -10532,6 +11041,7 @@ "kind": "native", "denom": "ustars", "decimals": 6, + "variant": "cosmos", "displayName": "STARS", "coingeckoId": "stargaze", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stargaze/images/stars.png", @@ -10569,6 +11079,7 @@ "kind": "native", "denom": "uiov", "decimals": 6, + "variant": "cosmos", "displayName": "IOV", "coingeckoId": "starname", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/starname/images/iov.svg", @@ -10607,6 +11118,7 @@ "kind": "native", "denom": "ustate", "decimals": 6, + "variant": "cosmos", "displayName": "STATE", "coingeckoId": "not-found", "icon": "not-found", @@ -10644,6 +11156,7 @@ "kind": "native", "denom": "wei", "decimals": 18, + "variant": "cosmos", "displayName": "STOS", "coingeckoId": "stratos", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stratos/images/stratos.svg", @@ -10682,6 +11195,7 @@ "kind": "native", "denom": "ustrd", "decimals": 6, + "variant": "cosmos", "displayName": "STRD", "coingeckoId": "stride", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stride/images/strd.svg", @@ -10691,6 +11205,7 @@ "kind": "native", "denom": "stuatom", "decimals": 6, + "variant": "cosmos", "displayName": "stATOM", "coingeckoId": "stride-staked-atom", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stride/images/statom.svg", @@ -10700,6 +11215,7 @@ "kind": "native", "denom": "stustars", "decimals": 6, + "variant": "cosmos", "displayName": "stSTARS", "coingeckoId": "stride-staked-stars", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stride/images/ststars.svg", @@ -10709,6 +11225,7 @@ "kind": "native", "denom": "stuosmo", "decimals": 6, + "variant": "cosmos", "displayName": "stOSMO", "coingeckoId": "stride-staked-osmo", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stride/images/stosmo.svg", @@ -10718,6 +11235,7 @@ "kind": "native", "denom": "stujuno", "decimals": 6, + "variant": "cosmos", "displayName": "stJUNO", "coingeckoId": "stride-staked-juno", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stride/images/stjuno.svg", @@ -10727,6 +11245,7 @@ "kind": "native", "denom": "stuluna", "decimals": 6, + "variant": "cosmos", "displayName": "stLUNA", "coingeckoId": "stride-staked-luna", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stride/images/stluna.svg", @@ -10736,6 +11255,7 @@ "kind": "native", "denom": "stinj", "decimals": 18, + "variant": "cosmos", "displayName": "stINJ", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stride/images/stinj.svg", @@ -10745,6 +11265,7 @@ "kind": "native", "denom": "staevmos", "decimals": 18, + "variant": "cosmos", "displayName": "stEVMOS", "coingeckoId": "stride-staked-evmos", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stride/images/stevmos.svg", @@ -10754,6 +11275,7 @@ "kind": "native", "denom": "stuumee", "decimals": 6, + "variant": "cosmos", "displayName": "stUMEE", "coingeckoId": "stride-staked-umee", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stride/images/stumee.svg", @@ -10763,6 +11285,7 @@ "kind": "native", "denom": "stucmdx", "decimals": 6, + "variant": "cosmos", "displayName": "stCMDX", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stride/images/stcmdx.svg", @@ -10772,6 +11295,7 @@ "kind": "native", "denom": "stusomm", "decimals": 6, + "variant": "cosmos", "displayName": "stSOMM", "coingeckoId": "stride-staked-sommelier", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stride/images/stsomm.svg", @@ -10810,6 +11334,7 @@ "kind": "native", "denom": "ustrd", "decimals": 6, + "variant": "cosmos", "displayName": "STRD", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stride/images/strd.svg", @@ -10847,6 +11372,7 @@ "kind": "native", "denom": "utprl", "decimals": 6, + "variant": "cosmos", "displayName": "TPRL", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/temporaltestnet/images/temporal.png", @@ -10884,6 +11410,7 @@ "kind": "native", "denom": "atenet", "decimals": 18, + "variant": "cosmos", "displayName": "TENET", "coingeckoId": "tenet-1b000f7b-59cb-4e06-89ce-d62b32d362b9", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/tenet/images/tenet.svg", @@ -10942,6 +11469,7 @@ { "denom": "utori", "displayName": "TORI", + "variant": "cosmos", "decimals": 6, "coingeckoId": "teritori", "icon": "teritori-circle.svg", @@ -11030,6 +11558,7 @@ { "denom": "utori", "displayName": "TORI", + "variant": "cosmos", "decimals": 6, "coingeckoId": "teritori", "icon": "icons/networks/teritori-circle.svg", @@ -11120,6 +11649,7 @@ { "denom": "utori", "displayName": "TORI", + "variant": "cosmos", "decimals": 6, "coingeckoId": "teritori", "icon": "teritori-circle.svg", @@ -11198,6 +11728,7 @@ "kind": "native", "denom": "uterpx", "decimals": 6, + "variant": "cosmos", "displayName": "TERPX", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terpnetwork/images/terp.png", @@ -11207,6 +11738,7 @@ "kind": "native", "denom": "uthiolx", "decimals": 6, + "variant": "cosmos", "displayName": "THIOLX", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terpnetwork/images/thiol.png", @@ -11244,6 +11776,7 @@ "kind": "native", "denom": "uluna", "decimals": 6, + "variant": "cosmos", "displayName": "LUNA", "coingeckoId": "terra-luna-2", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/luna.svg", @@ -11253,6 +11786,7 @@ "kind": "native", "denom": "cw20:terra1nsuqsk6kh58ulczatwev87ttq2z6r3pusulg9r24mfj2fvtzd4uq3exn26", "decimals": 6, + "variant": "cosmos", "displayName": "ASTRO", "coingeckoId": "astroport-fi", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/astro.png", @@ -11262,6 +11796,7 @@ "kind": "native", "denom": "cw20:terra1spkm49wd9dqkranhrks4cupecl3rtgeqqljq3qrvrrts2ev2gw6sy5vz3k", "decimals": 6, + "variant": "cosmos", "displayName": "DINHEIROS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/Dinheiros.png", @@ -11271,6 +11806,7 @@ "kind": "native", "denom": "cw20:terra1sdglum2dt4f3fmq7jrt2phf2tegmnudc7qqqqujkpqcm9ujuxxkqakv5u8", "decimals": 6, + "variant": "cosmos", "displayName": "REIS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/Reis.png", @@ -11280,6 +11816,7 @@ "kind": "native", "denom": "cw20:terra1qj5hs3e86qn4vm9dvtgtlkdp550r0rayk9wpay44mfw3gn3tr8nq5jw3dg", "decimals": 6, + "variant": "cosmos", "displayName": "ESCUDOS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/Escudos.png", @@ -11289,6 +11826,7 @@ "kind": "native", "denom": "cw20:terra1cmf8ytutcwrjrv08zskj9phuh46a3w3nkjax7en4hxezsrdr58lqvzy05q", "decimals": 6, + "variant": "cosmos", "displayName": "ALEM", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/Alem.png", @@ -11298,6 +11836,7 @@ "kind": "native", "denom": "cw20:terra1ecgazyd0waaj3g7l9cmy5gulhxkps2gmxu9ghducvuypjq68mq2s5lvsct", "decimals": 6, + "variant": "cosmos", "displayName": "ampLUNA", "coingeckoId": "eris-amplified-luna", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/ampluna.svg", @@ -11307,6 +11846,7 @@ "kind": "native", "denom": "cw20:terra1lxx40s29qvkrcj8fsa3yzyehy7w50umdvvnls2r830rys6lu2zns63eelv", "decimals": 6, + "variant": "cosmos", "displayName": "ROAR", "coingeckoId": "lion-dao", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/roar.png", @@ -11316,6 +11856,7 @@ "kind": "native", "denom": "cw20:terra1ynvsz80w9xmhdxucv96gkwpxlwvjgsq75xh2f3pf825c4wfmkfxskq6pqv", "decimals": 6, + "variant": "cosmos", "displayName": "GEM", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/gem.png", @@ -11325,6 +11866,7 @@ "kind": "native", "denom": "cw20:terra1lalvk0r6nhruel7fvzdppk3tup3mh5j4d4eadrqzfhle4zrf52as58hh9t", "decimals": 6, + "variant": "cosmos", "displayName": "CUB", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/cub.png", @@ -11334,6 +11876,7 @@ "kind": "native", "denom": "cw20:terra1gwrz9xzhqsygyr5asrgyq3pu0ewpn00mv2zenu86yvx2nlwpe8lqppv584", "decimals": 6, + "variant": "cosmos", "displayName": "BLUE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/blue.png", @@ -11343,6 +11886,7 @@ "kind": "native", "denom": "cw20:terra10se906awphtccf4vd83m0ulpmpt9v4msuakmpy0pwvmtxmup3kdq25rayn", "decimals": 10, + "variant": "cosmos", "displayName": "xxx", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/xxx3.png", @@ -11352,6 +11896,7 @@ "kind": "native", "denom": "cw20:terra17aj4ty4sz4yhgm08na8drc0v03v2jwr3waxcqrwhajj729zhl7zqnpc0ml", "decimals": 6, + "variant": "cosmos", "displayName": "bLUNA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/boneluna.png", @@ -11361,6 +11906,7 @@ "kind": "native", "denom": "cw20:terra1xp9hrhthzddnl7j5du83gqqr4wmdjm5t0guzg9jp6jwrtpukwfjsjgy4f3", "decimals": 6, + "variant": "cosmos", "displayName": "SAYVE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/sayve.svg", @@ -11370,6 +11916,7 @@ "kind": "native", "denom": "factory/terra1j35ta0llaxcf55auv2cjqau5a7aee6g8fz7md7my7005cvh23jfsaw83dy/ampWHALEt", "decimals": 6, + "variant": "cosmos", "displayName": "ampWHALEt", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/ampwhalet.svg", @@ -11379,6 +11926,7 @@ "kind": "native", "denom": "factory/terra10j3zrymfrkta2pxe0gklc79gu06tqyuy8c3kh6tqdsrrprsjqkrqzfl4df/boneWHALEt", "decimals": 6, + "variant": "cosmos", "displayName": "boneWHALEt", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/bonewhalet.svg", @@ -11388,6 +11936,7 @@ "kind": "native", "denom": "factory/terra1vklefn7n6cchn0u962w3gaszr4vf52wjvd4y95t2sydwpmpdtszsqvk9wy/ampROAR", "decimals": 6, + "variant": "cosmos", "displayName": "ampROAR", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/amproar.png", @@ -11397,6 +11946,7 @@ "kind": "native", "denom": "cw20:terra1e0efrrrj8d55pflme3dmtyuj7klzcef5cfmz6r2jyqz77kk2jz3qa6drg3", "decimals": 18, + "variant": "cosmos", "displayName": "NICO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/nicodao.png", @@ -11406,6 +11956,7 @@ "kind": "native", "denom": "cw20:terra1rc6ssp5rym7a0hg29xpj4cc9e67tl56kg5jyzgl9qrhfxxc2ugvsnrkala", "decimals": 6, + "variant": "cosmos", "displayName": "SEAS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/SEAS.png", @@ -11415,6 +11966,7 @@ "kind": "native", "denom": "cw20:terra18vp5s0r7keezm35hdxsgw8zgfnyn8wejdkk893ag2kqncgpqxhjqwjpc0v", "decimals": 6, + "variant": "cosmos", "displayName": "BITZ", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/BITZ.png", @@ -11424,6 +11976,7 @@ "kind": "native", "denom": "cw20:terra13s5pxw5j2p4ssvzwvxd8l7h30vke8vjgtng75vqgv6p9vddfk3hskfka0l", "decimals": 6, + "variant": "cosmos", "displayName": "SEUL", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/seul.png", @@ -11433,6 +11986,7 @@ "kind": "native", "denom": "cw20:terra1q328gl40az3cf9x67cgudn8e8w2az9vsmhtkwsgdu7a43rhy5caqc82yr5", "decimals": 6, + "variant": "cosmos", "displayName": "xSEUL", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/xseul.png", @@ -11442,6 +11996,7 @@ "kind": "native", "denom": "cw20:terra1c77xqv746m7ghxayrge79dxr4kcezev8g6cnrfled4f3n4ufj0vs5gz28s", "decimals": 6, + "variant": "cosmos", "displayName": "ITO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/I.png", @@ -11451,6 +12006,7 @@ "kind": "native", "denom": "cw20:terra1aa7stl3fytvave9xtcexgv0kne4k7ks068dcljkrfj37hy8q270sjadav8", "decimals": 6, + "variant": "cosmos", "displayName": "ARMANI", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/armani.png", @@ -11460,6 +12016,7 @@ "kind": "native", "denom": "cw20:terra1cl273523kmr2uwjhhznq54je69mted2u3ljffm8kp2ap4z3drdksftwqun", "decimals": 6, + "variant": "cosmos", "displayName": "DROGO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/drogo.png", @@ -11469,6 +12026,7 @@ "kind": "native", "denom": "cw20:terra1w8xk6rtu40st6lvl3yv7ynw5urm2n686u9cchvrzltmnktzwdesqcwy0nu", "decimals": 6, + "variant": "cosmos", "displayName": "ADO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/ADO.png", @@ -11507,6 +12065,7 @@ "kind": "native", "denom": "uluna", "decimals": 6, + "variant": "cosmos", "displayName": "LUNA", "coingeckoId": "terra-luna-2", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/luna.svg", @@ -11544,6 +12103,7 @@ "kind": "native", "denom": "uluna", "decimals": 6, + "variant": "cosmos", "displayName": "LUNC", "coingeckoId": "terra-luna", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/luna.svg", @@ -11553,6 +12113,7 @@ "kind": "native", "denom": "uusd", "decimals": 6, + "variant": "cosmos", "displayName": "USTC", "coingeckoId": "terrausd", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/ust.svg", @@ -11562,6 +12123,7 @@ "kind": "native", "denom": "ukrw", "decimals": 6, + "variant": "cosmos", "displayName": "KRTC", "coingeckoId": "terrakrw", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/krt.svg", @@ -11571,6 +12133,7 @@ "kind": "native", "denom": "cw20:terra1php5m8a6qd68z02t3zpw4jv2pj4vgw4wz0t8mz", "decimals": 6, + "variant": "cosmos", "displayName": "WHALE", "coingeckoId": "white-whale", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/whale.png", @@ -11580,6 +12143,7 @@ "kind": "native", "denom": "cw20:terra1kc87mu460fwkqte29rquh4hc20m54fxwtsx7gp", "decimals": 6, + "variant": "cosmos", "displayName": "bLuna", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/bluna.png", @@ -11589,6 +12153,7 @@ "kind": "native", "denom": "cw20:terra1dzhzukyezv0etz22ud940z7adyv7xgcjkahuun", "decimals": 6, + "variant": "cosmos", "displayName": "bETH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/beth.png", @@ -11598,6 +12163,7 @@ "kind": "native", "denom": "cw20:terra1hzh9vpxhsk8253se0vv5jj6etdvxu3nv8z07zu", "decimals": 6, + "variant": "cosmos", "displayName": "aUST", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/aust.png", @@ -11607,6 +12173,7 @@ "kind": "native", "denom": "cw20:terra14z56l0fp2lsf86zy3hty2z47ezkhnthtr9yq76", "decimals": 6, + "variant": "cosmos", "displayName": "ANC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/anc.png", @@ -11616,6 +12183,7 @@ "kind": "native", "denom": "cw20:terra15gwkyepfc6xgca5t5zefzwy42uts8l2m4g40k6", "decimals": 6, + "variant": "cosmos", "displayName": "MIR", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mir.png", @@ -11625,6 +12193,7 @@ "kind": "native", "denom": "cw20:terra1vxtwu4ehgzz77mnfwrntyrmgl64qjs75mpwqaz", "decimals": 6, + "variant": "cosmos", "displayName": "mAAPL", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/maapl.png", @@ -11634,6 +12203,7 @@ "kind": "native", "denom": "cw20:terra1g4x2pzmkc9z3mseewxf758rllg08z3797xly0n", "decimals": 6, + "variant": "cosmos", "displayName": "mABNB", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mabnb.png", @@ -11643,6 +12213,7 @@ "kind": "native", "denom": "cw20:terra1qelfthdanju7wavc5tq0k5r0rhsyzyyrsn09qy", "decimals": 6, + "variant": "cosmos", "displayName": "mAMC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mamc.png", @@ -11652,6 +12223,7 @@ "kind": "native", "denom": "cw20:terra18ej5nsuu867fkx4tuy2aglpvqjrkcrjjslap3z", "decimals": 6, + "variant": "cosmos", "displayName": "mAMD", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mamd.png", @@ -11661,6 +12233,7 @@ "kind": "native", "denom": "cw20:terra165nd2qmrtszehcfrntlplzern7zl4ahtlhd5t2", "decimals": 6, + "variant": "cosmos", "displayName": "mAMZN", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mamzn.png", @@ -11670,6 +12243,7 @@ "kind": "native", "denom": "cw20:terra1qqfx5jph0rsmkur2zgzyqnfucra45rtjae5vh6", "decimals": 6, + "variant": "cosmos", "displayName": "mARKK", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/markk.png", @@ -11679,6 +12253,7 @@ "kind": "native", "denom": "cw20:terra1w7zgkcyt7y4zpct9dw8mw362ywvdlydnum2awa", "decimals": 6, + "variant": "cosmos", "displayName": "mBABA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mbaba.png", @@ -11688,6 +12263,7 @@ "kind": "native", "denom": "cw20:terra1rhhvx8nzfrx5fufkuft06q5marfkucdqwq5sjw", "decimals": 6, + "variant": "cosmos", "displayName": "mBTC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mbtc.png", @@ -11697,6 +12273,7 @@ "kind": "native", "denom": "cw20:terra18wayjpyq28gd970qzgjfmsjj7dmgdk039duhph", "decimals": 6, + "variant": "cosmos", "displayName": "mCOIN", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mcoin.png", @@ -11706,6 +12283,7 @@ "kind": "native", "denom": "cw20:terra149755r3y0rve30e209awkhn5cxgkn5c8ju9pm5", "decimals": 6, + "variant": "cosmos", "displayName": "mDIS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mdis.png", @@ -11715,6 +12293,7 @@ "kind": "native", "denom": "cw20:terra19ya4jpvjvvtggepvmmj6ftmwly3p7way0tt08r", "decimals": 6, + "variant": "cosmos", "displayName": "mDOT", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mdot.png", @@ -11724,6 +12303,7 @@ "kind": "native", "denom": "cw20:terra1dk3g53js3034x4v5c3vavhj2738une880yu6kx", "decimals": 6, + "variant": "cosmos", "displayName": "mETH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/meth.png", @@ -11733,6 +12313,7 @@ "kind": "native", "denom": "cw20:terra1mqsjugsugfprn3cvgxsrr8akkvdxv2pzc74us7", "decimals": 6, + "variant": "cosmos", "displayName": "mFB", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mfb.png", @@ -11742,6 +12323,7 @@ "kind": "native", "denom": "cw20:terra1l5lrxtwd98ylfy09fn866au6dp76gu8ywnudls", "decimals": 6, + "variant": "cosmos", "displayName": "mGLXY", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mglxy.png", @@ -11751,6 +12333,7 @@ "kind": "native", "denom": "cw20:terra1m6j6j9gw728n82k78s0j9kq8l5p6ne0xcc820p", "decimals": 6, + "variant": "cosmos", "displayName": "mGME", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mgme.png", @@ -11760,6 +12343,7 @@ "kind": "native", "denom": "cw20:terra1h8arz2k547uvmpxctuwush3jzc8fun4s96qgwt", "decimals": 6, + "variant": "cosmos", "displayName": "mGOOGL", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mgoogl.png", @@ -11769,6 +12353,7 @@ "kind": "native", "denom": "cw20:terra137drsu8gce5thf6jr5mxlfghw36rpljt3zj73v", "decimals": 6, + "variant": "cosmos", "displayName": "mGS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mgs.png", @@ -11778,6 +12363,7 @@ "kind": "native", "denom": "cw20:terra18yqdfzfhnguerz9du5mnvxsh5kxlknqhcxzjfr", "decimals": 6, + "variant": "cosmos", "displayName": "mHOOD", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mhood.png", @@ -11787,6 +12373,7 @@ "kind": "native", "denom": "cw20:terra10h7ry7apm55h4ez502dqdv9gr53juu85nkd4aq", "decimals": 6, + "variant": "cosmos", "displayName": "mIAU", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/miau.png", @@ -11796,6 +12383,7 @@ "kind": "native", "denom": "cw20:terra15hp9pr8y4qsvqvxf3m4xeptlk7l8h60634gqec", "decimals": 6, + "variant": "cosmos", "displayName": "mIAU", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/miau.png", @@ -11805,6 +12393,7 @@ "kind": "native", "denom": "cw20:terra1ptdxmj3xmmljzx02nr4auwfuelmj0cnkh8egs2", "decimals": 6, + "variant": "cosmos", "displayName": "mJNJ", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mjnj.png", @@ -11814,6 +12403,7 @@ "kind": "native", "denom": "cw20:terra1qsnj5gvq8rgs7yws8x5u02gwd5wvtu4tks0hjm", "decimals": 6, + "variant": "cosmos", "displayName": "mKO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mko.png", @@ -11823,6 +12413,7 @@ "kind": "native", "denom": "cw20:terra1227ppwxxj3jxz8cfgq00jgnxqcny7ryenvkwj6", "decimals": 6, + "variant": "cosmos", "displayName": "mMSFT", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mmsft.png", @@ -11832,6 +12423,7 @@ "kind": "native", "denom": "cw20:terra1jsxngqasf2zynj5kyh0tgq9mj3zksa5gk35j4k", "decimals": 6, + "variant": "cosmos", "displayName": "mNFLX", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mnflx.png", @@ -11841,6 +12433,7 @@ "kind": "native", "denom": "cw20:terra1dj2cj02zak0nvwy3uj9r9dhhxhdwxnw6psse6p", "decimals": 6, + "variant": "cosmos", "displayName": "mNIO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mnio.png", @@ -11850,6 +12443,7 @@ "kind": "native", "denom": "cw20:terra17ana8hvzea0q7w367dm0dw48sxwql39qekpt7g", "decimals": 6, + "variant": "cosmos", "displayName": "mNKE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mnke.png", @@ -11859,6 +12453,7 @@ "kind": "native", "denom": "cw20:terra1drsjzvzej4h4qlehcfwclxg4w5l3h5tuvd3jd8", "decimals": 6, + "variant": "cosmos", "displayName": "mNVDA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mnvda.png", @@ -11868,6 +12463,7 @@ "kind": "native", "denom": "cw20:terra1rh2907984nudl7vh56qjdtvv7947z4dujj92sx", "decimals": 6, + "variant": "cosmos", "displayName": "mPYPL", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mpypl.png", @@ -11877,6 +12473,7 @@ "kind": "native", "denom": "cw20:terra1csk6tc7pdmpr782w527hwhez6gfv632tyf72cp", "decimals": 6, + "variant": "cosmos", "displayName": "mQQQ", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mqqq.png", @@ -11886,6 +12483,7 @@ "kind": "native", "denom": "cw20:terra1246zy658dfgtausf0c4a6ly8sc2e285q4kxqga", "decimals": 6, + "variant": "cosmos", "displayName": "mSBUX", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/msbux.png", @@ -11895,6 +12493,7 @@ "kind": "native", "denom": "cw20:terra1kscs6uhrqwy6rx5kuw5lwpuqvm3t6j2d6uf2lp", "decimals": 6, + "variant": "cosmos", "displayName": "mSLV", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mslv.png", @@ -11904,6 +12503,7 @@ "kind": "native", "denom": "cw20:terra1aa00lpfexyycedfg5k2p60l9djcmw0ue5l8fhc", "decimals": 6, + "variant": "cosmos", "displayName": "mSPY", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mspy.png", @@ -11913,6 +12513,7 @@ "kind": "native", "denom": "cw20:terra1u43zu5amjlsgty5j64445fr9yglhm53m576ugh", "decimals": 6, + "variant": "cosmos", "displayName": "mSQ", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/msq.png", @@ -11922,6 +12523,7 @@ "kind": "native", "denom": "cw20:terra14y5affaarufk3uscy2vr6pe6w6zqf2wpjzn5sh", "decimals": 6, + "variant": "cosmos", "displayName": "mTSLA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mtsla.png", @@ -11931,6 +12533,7 @@ "kind": "native", "denom": "cw20:terra1cc3enj9qgchlrj34cnzhwuclc4vl2z3jl7tkqg", "decimals": 6, + "variant": "cosmos", "displayName": "mTWTR", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mtwtr.png", @@ -11940,6 +12543,7 @@ "kind": "native", "denom": "cw20:terra1lvmx8fsagy70tv0fhmfzdw9h6s3sy4prz38ugf", "decimals": 6, + "variant": "cosmos", "displayName": "mUSO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/muso.png", @@ -11949,6 +12553,7 @@ "kind": "native", "denom": "cw20:terra19cmt6vzvhnnnfsmccaaxzy2uaj06zjktu6yzjx", "decimals": 6, + "variant": "cosmos", "displayName": "mVIXY", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mvixy.png", @@ -11958,6 +12563,7 @@ "kind": "native", "denom": "cw20:terra1zp3a6q6q4953cz376906g5qfmxnlg77hx3te45", "decimals": 6, + "variant": "cosmos", "displayName": "mVIXY", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mvixy.png", @@ -11967,6 +12573,7 @@ "kind": "native", "denom": "cw20:terra1ez46kxtulsdv07538fh5ra5xj8l68mu8eg24vr", "decimals": 6, + "variant": "cosmos", "displayName": "LOTA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/lota.png", @@ -11976,6 +12583,7 @@ "kind": "native", "denom": "cw20:terra17jnhankdfl8vyzj6vejt7ag8uz0cjc9crkl2h7", "decimals": 6, + "variant": "cosmos", "displayName": "DPH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/dph.png", @@ -11985,6 +12593,7 @@ "kind": "native", "denom": "cw20:terra1kcthelkax4j9x8d3ny6sdag0qmxxynl3qtcrpy", "decimals": 6, + "variant": "cosmos", "displayName": "MINE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mine.png", @@ -11994,6 +12603,7 @@ "kind": "native", "denom": "cw20:terra1zsaswh926ey8qa5x4vj93kzzlfnef0pstuca0y", "decimals": 6, + "variant": "cosmos", "displayName": "bPsiDP-24m", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/bpsidp-24m.png", @@ -12003,6 +12613,7 @@ "kind": "native", "denom": "cw20:terra1s5eczhe0h0jutf46re52x5z4r03c8hupacxmdr", "decimals": 6, + "variant": "cosmos", "displayName": "SPEC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/spec.png", @@ -12012,6 +12623,7 @@ "kind": "native", "denom": "cw20:terra1nef5jf6c7js9x6gkntlehgywvjlpytm7pcgkn4", "decimals": 6, + "variant": "cosmos", "displayName": "LOOP", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/loop.png", @@ -12021,6 +12633,7 @@ "kind": "native", "denom": "cw20:terra1jx4lmmke2srcvpjeereetc9hgegp4g5j0p9r2q", "decimals": 6, + "variant": "cosmos", "displayName": "LOOPR", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/loopr.png", @@ -12030,6 +12643,7 @@ "kind": "native", "denom": "cw20:terra13xujxcrc9dqft4p9a8ls0w3j0xnzm6y2uvve8n", "decimals": 6, + "variant": "cosmos", "displayName": "STT", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/stt.png", @@ -12039,6 +12653,7 @@ "kind": "native", "denom": "cw20:terra19djkaepjjswucys4npd5ltaxgsntl7jf0xz7w6", "decimals": 6, + "variant": "cosmos", "displayName": "TWD", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/twd.png", @@ -12048,6 +12663,7 @@ "kind": "native", "denom": "cw20:terra1kvjscdgwuvwc6uzm4rqfjl6nlmuhj28tequlnc", "decimals": 6, + "variant": "cosmos", "displayName": "XTRA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/xtra.png", @@ -12057,6 +12673,7 @@ "kind": "native", "denom": "cw20:terra1vtr50tw0pgqpes34zqu60n554p9x4950wk8f63", "decimals": 6, + "variant": "cosmos", "displayName": "MIAW", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/miaw.png", @@ -12066,6 +12683,7 @@ "kind": "native", "denom": "cw20:terra12897djskt9rge8dtmm86w654g7kzckkd698608", "decimals": 6, + "variant": "cosmos", "displayName": "Psi", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/psi.png", @@ -12075,6 +12693,7 @@ "kind": "native", "denom": "cw20:terra10f2mt82kjnkxqj2gepgwl637u2w4ue2z5nhz5j", "decimals": 6, + "variant": "cosmos", "displayName": "nLuna", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/nluna.svg", @@ -12084,6 +12703,7 @@ "kind": "native", "denom": "cw20:terra178v546c407pdnx5rer3hu8s2c0fc924k74ymnn", "decimals": 6, + "variant": "cosmos", "displayName": "nETH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/neth.svg", @@ -12093,6 +12713,7 @@ "kind": "native", "denom": "cw20:terra1u553zk43jd4rwzc53qrdrq4jc2p8rextyq09dj", "decimals": 6, + "variant": "cosmos", "displayName": "cnLuna", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/cnluna.svg", @@ -12102,6 +12723,7 @@ "kind": "native", "denom": "cw20:terra1nagqpmyw55yjphea4rhntlfv87ugmeaj8ym756", "decimals": 6, + "variant": "cosmos", "displayName": "cnETH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/cneth.svg", @@ -12111,6 +12733,7 @@ "kind": "native", "denom": "cw20:terra13k62n0285wj8ug0ngcgpf7dgnkzqeu279tz636", "decimals": 6, + "variant": "cosmos", "displayName": "nAVAX", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/navax.svg", @@ -12120,6 +12743,7 @@ "kind": "native", "denom": "cw20:terra1jtdc6zpf95tvh9peuaxwp3v0yqszcnwl8j5ade", "decimals": 6, + "variant": "cosmos", "displayName": "nATOM", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/natom.svg", @@ -12129,6 +12753,7 @@ "kind": "native", "denom": "cw20:terra1dy9kmlm4anr92e42mrkjwzyvfqwz66un00rwr5", "decimals": 6, + "variant": "cosmos", "displayName": "VKR", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/vkr.png", @@ -12138,6 +12763,7 @@ "kind": "native", "denom": "cw20:terra1mddcdx0ujx89f38gu7zspk2r2ffdl5enyz2u03", "decimals": 8, + "variant": "cosmos", "displayName": "ORION", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/orion.png", @@ -12147,6 +12773,7 @@ "kind": "native", "denom": "cw20:terra1r5506ckw5tfr3z52jwlek8vg9sn3yflrqrzfsc", "decimals": 6, + "variant": "cosmos", "displayName": "TLAND", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/tland.png", @@ -12156,6 +12783,7 @@ "kind": "native", "denom": "cw20:terra1w0p5zre38ecdy3ez8efd5h9fvgum5s206xknrg", "decimals": 6, + "variant": "cosmos", "displayName": "vUST", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/vust.png", @@ -12165,6 +12793,7 @@ "kind": "native", "denom": "cw20:terra14tl83xcwqjy0ken9peu4pjjuu755lrry2uy25r", "decimals": 8, + "variant": "cosmos", "displayName": "ETH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/eth.png", @@ -12174,6 +12803,7 @@ "kind": "native", "denom": "cw20:terra1aa7upykmmqqc63l924l5qfap8mrmx5rfdm0v55", "decimals": 8, + "variant": "cosmos", "displayName": "WBTC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/wbtc.png", @@ -12183,6 +12813,7 @@ "kind": "native", "denom": "cw20:terra190tqwgqx7s8qrknz6kckct7v607cu068gfujpk", "decimals": 8, + "variant": "cosmos", "displayName": "SOL", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/sol.png", @@ -12192,6 +12823,7 @@ "kind": "native", "denom": "cw20:terra1dfasranqm4uyaz72r960umxy0w8t6zewqlnkuq", "decimals": 8, + "variant": "cosmos", "displayName": "MATICet", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/maticet.png", @@ -12201,6 +12833,7 @@ "kind": "native", "denom": "cw20:terra1cetg5wruw2wsdjp7j46rj44xdel00z006e9yg8", "decimals": 8, + "variant": "cosmos", "displayName": "BNB", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/bnb.png", @@ -12210,6 +12843,7 @@ "kind": "native", "denom": "cw20:terra1xvqlpjl2dxyel9qrp6qvtrg04xe3jh9cyxc6av", "decimals": 8, + "variant": "cosmos", "displayName": "CAKE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/cake.png", @@ -12219,6 +12853,7 @@ "kind": "native", "denom": "cw20:terra12dfv3f0e6m22z6cnhfn3nxk2en3z3zeqy6ctym", "decimals": 8, + "variant": "cosmos", "displayName": "LINK", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/link.png", @@ -12228,6 +12863,7 @@ "kind": "native", "denom": "cw20:terra1csvuzlf92nyemu6tv25h0l79etpe8hz3h5vn4a", "decimals": 8, + "variant": "cosmos", "displayName": "SUSHI", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/sushi.png", @@ -12237,6 +12873,7 @@ "kind": "native", "denom": "cw20:terra1wyxkuy5jq545fn7xfn3enpvs5zg9f9dghf6gxf", "decimals": 8, + "variant": "cosmos", "displayName": "UNI", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/uni.png", @@ -12246,6 +12883,7 @@ "kind": "native", "denom": "cw20:terra1ce06wkrdm4vl6t0hvc0g86rsy27pu8yadg3dva", "decimals": 6, + "variant": "cosmos", "displayName": "USDTet", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/usdtet.png", @@ -12255,6 +12893,7 @@ "kind": "native", "denom": "cw20:terra1pepwcav40nvj3kh60qqgrk8k07ydmc00xyat06", "decimals": 6, + "variant": "cosmos", "displayName": "USDCet", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/usdcet.png", @@ -12264,6 +12903,7 @@ "kind": "native", "denom": "cw20:terra1xfsdgcemqwxp4hhnyk4rle6wr22sseq7j07dnn", "decimals": 6, + "variant": "cosmos", "displayName": "KUJI", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/kuji.png", @@ -12273,6 +12913,7 @@ "kind": "native", "denom": "cw20:terra188w26t95tf4dz77raftme8p75rggatxjxfeknw", "decimals": 6, + "variant": "cosmos", "displayName": "sKUJI", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/skuji.png", @@ -12282,6 +12923,7 @@ "kind": "native", "denom": "cw20:terra133chr09wu8sakfte5v7vd8qzq9vghtkv4tn0ur", "decimals": 8, + "variant": "cosmos", "displayName": "wstETH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/wsteth.png", @@ -12291,6 +12933,7 @@ "kind": "native", "denom": "cw20:terra1t9ul45l7m6jw6sxgvnp8e5hj8xzkjsg82g84ap", "decimals": 8, + "variant": "cosmos", "displayName": "wstSOL", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/wstsol.png", @@ -12300,6 +12943,7 @@ "kind": "native", "denom": "cw20:terra1c3xd5s2j3ejx2d94tvcjfkrdeu6rmz48ghzznj", "decimals": 8, + "variant": "cosmos", "displayName": "wsbSOL", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/wsbsol.svg", @@ -12309,6 +12953,7 @@ "kind": "native", "denom": "cw20:terra1jxypgnfa07j6w92wazzyskhreq2ey2a5crgt6z", "decimals": 8, + "variant": "cosmos", "displayName": "LDO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/ldo.png", @@ -12318,6 +12963,7 @@ "kind": "native", "denom": "cw20:terra1u5szg038ur9kzuular3cae8hq6q5rk5u27tuvz", "decimals": 8, + "variant": "cosmos", "displayName": "webETH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/webeth.svg", @@ -12327,6 +12973,7 @@ "kind": "native", "denom": "cw20:terra1yg3j2s986nyp5z7r2lvt0hx3r0lnd7kwvwwtsc", "decimals": 6, + "variant": "cosmos", "displayName": "stLuna", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/stluna.png", @@ -12336,6 +12983,7 @@ "kind": "native", "denom": "cw20:terra169edevav3pdrtjcx35j6pvzuv54aevewar4nlh", "decimals": 8, + "variant": "cosmos", "displayName": "XDEFI", "coingeckoId": "not-found", "icon": "not-found", @@ -12345,6 +12993,7 @@ "kind": "native", "denom": "cw20:terra193c42lfwmlkasvcw22l9qqzc5q2dx208tkd7wl", "decimals": 6, + "variant": "cosmos", "displayName": "BTL", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/btl.png", @@ -12354,6 +13003,7 @@ "kind": "native", "denom": "cw20:terra17y9qkl8dfkeg4py7n0g5407emqnemc3yqk5rup", "decimals": 6, + "variant": "cosmos", "displayName": "LunaX", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/lunax.png", @@ -12363,6 +13013,7 @@ "kind": "native", "denom": "cw20:terra1m3tdguf59xq3pa2twk5fjte5g6szj5y9x5npy7", "decimals": 6, + "variant": "cosmos", "displayName": "LUNI", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/luni.png", @@ -12372,6 +13023,7 @@ "kind": "native", "denom": "cw20:terra13awdgcx40tz5uygkgm79dytez3x87rpg4uhnvu", "decimals": 6, + "variant": "cosmos", "displayName": "PLY", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/ply.png", @@ -12381,6 +13033,7 @@ "kind": "native", "denom": "cw20:terra1u2k0nkenw0p25ljsr4ksh7rxm65y466vkdewwj", "decimals": 6, + "variant": "cosmos", "displayName": "TFLOKI", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/tfloki.png", @@ -12390,6 +13043,7 @@ "kind": "native", "denom": "cw20:terra1a8k3jyv3wf6k3zngza5h6srrxcckdf7zv90p6u", "decimals": 6, + "variant": "cosmos", "displayName": "TFTIC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/tftic.png", @@ -12399,6 +13053,7 @@ "kind": "native", "denom": "cw20:terra1xt9fgu7965kgvunnjts9zkprd8986kcc444q86", "decimals": 6, + "variant": "cosmos", "displayName": "TFTICII", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/tfticii.png", @@ -12408,6 +13063,7 @@ "kind": "native", "denom": "cw20:terra1vte2xv7dr8sfnrnwdf9arcyprqgr0hty5ads28", "decimals": 6, + "variant": "cosmos", "displayName": "TFTICIII", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/tfticiii.png", @@ -12417,6 +13073,7 @@ "kind": "native", "denom": "cw20:terra1hmxxq0y8h79f3228vs0czc4uz5jdgjt0appp26", "decimals": 6, + "variant": "cosmos", "displayName": "MOON", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/moon.png", @@ -12426,6 +13083,7 @@ "kind": "native", "denom": "cw20:terra1xj49zyqrwpv5k928jwfpfy2ha668nwdgkwlrg3", "decimals": 6, + "variant": "cosmos", "displayName": "ASTRO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/astro.png", @@ -12435,6 +13093,7 @@ "kind": "native", "denom": "cw20:terra14lpnyzc9z4g3ugr4lhm8s4nle0tq8vcltkhzh7", "decimals": 6, + "variant": "cosmos", "displayName": "xASTRO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/xastro.png", @@ -12444,6 +13103,7 @@ "kind": "native", "denom": "cw20:terra1w8kvd6cqpsthupsk4l0clwnmek4l3zr7c84kwq", "decimals": 6, + "variant": "cosmos", "displayName": "HALO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/halo.png", @@ -12453,6 +13113,7 @@ "kind": "native", "denom": "cw20:terra1kdfsdm3c4reun9j3m4mk3nmyw4a4ns7mj24q3j", "decimals": 6, + "variant": "cosmos", "displayName": "PUG", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/pug.png", @@ -12462,6 +13123,7 @@ "kind": "native", "denom": "cw20:terra1hnezwjqlhzawcrfysczcxs6xqxu2jawn729kkf", "decimals": 6, + "variant": "cosmos", "displayName": "ORNE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/orne.png", @@ -12471,6 +13133,7 @@ "kind": "native", "denom": "cw20:terra14vz4v8adanzph278xyeggll4tfww7teh0xtw2y", "decimals": 6, + "variant": "cosmos", "displayName": "TNS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/tns.png", @@ -12480,6 +13143,7 @@ "kind": "native", "denom": "cw20:terra1td743l5k5cmfy7tqq202g7vkmdvq35q48u2jfm", "decimals": 6, + "variant": "cosmos", "displayName": "XRUNE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/xrune.png", @@ -12489,6 +13153,7 @@ "kind": "native", "denom": "cw20:terra1366wmr8t8rrkh6mag8fagqxntmf2qe4kyte784", "decimals": 6, + "variant": "cosmos", "displayName": "aLOT", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/alot.png", @@ -12498,6 +13163,7 @@ "kind": "native", "denom": "cw20:terra1z09gnzufuflz6ckd9k0u456l9dnpgsynu0yyhe", "decimals": 6, + "variant": "cosmos", "displayName": "SITY", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/sity.svg", @@ -12507,6 +13173,7 @@ "kind": "native", "denom": "cw20:terra13zx49nk8wjavedjzu8xkk95r3t0ta43c9ptul7", "decimals": 6, + "variant": "cosmos", "displayName": "GLOW", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/glow.png", @@ -12516,6 +13183,7 @@ "kind": "native", "denom": "cw20:terra100yeqvww74h4yaejj6h733thgcafdaukjtw397", "decimals": 6, + "variant": "cosmos", "displayName": "APOLLO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/apollo.png", @@ -12525,6 +13193,7 @@ "kind": "native", "denom": "cw20:terra1a7ye2splpfzyenu0yrdu8t83uzgusx2malkc7u", "decimals": 6, + "variant": "cosmos", "displayName": "ABR", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/abr.svg", @@ -12534,6 +13203,7 @@ "kind": "native", "denom": "cw20:terra1y3d5qexmyac0fg53pfglh2pjk0664ymfvcq9mc", "decimals": 8, + "variant": "cosmos", "displayName": "whGTPS", "coingeckoId": "not-found", "icon": "not-found", @@ -12543,6 +13213,7 @@ "kind": "native", "denom": "cw20:terra1dh9478k2qvqhqeajhn75a2a7dsnf74y5ukregw", "decimals": 6, + "variant": "cosmos", "displayName": "PRISM", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/prism.png", @@ -12552,6 +13223,7 @@ "kind": "native", "denom": "cw20:terra1l0y8yg0s86x299nqw0p6fhh7ngex3r4phtjeuq", "decimals": 2, + "variant": "cosmos", "displayName": "SDOLLAR", "coingeckoId": "not-found", "icon": "not-found", @@ -12561,6 +13233,7 @@ "kind": "native", "denom": "cw20:terra1ku5e0dhutxhuxudsmsn5647wwcz6ndr3rsh90k", "decimals": 6, + "variant": "cosmos", "displayName": "whSAIL", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/whsail.png", @@ -12570,6 +13243,7 @@ "kind": "native", "denom": "cw20:terra1rl0cpwgtwl4utnaynugevdje37fnmsea7rv4uu", "decimals": 8, + "variant": "cosmos", "displayName": "whgSAIL", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/whgsail.png", @@ -12579,6 +13253,7 @@ "kind": "native", "denom": "cw20:terra1042wzrwg2uk6jqxjm34ysqquyr9esdgm5qyswz", "decimals": 6, + "variant": "cosmos", "displayName": "xPRISM", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/xprism.png", @@ -12588,6 +13263,7 @@ "kind": "native", "denom": "cw20:terra13fs83g5atgjwuh7c5ydzh6n7gecel6xyhhy2t5", "decimals": 9, + "variant": "cosmos", "displayName": "CDE", "coingeckoId": "not-found", "icon": "not-found", @@ -12597,6 +13273,7 @@ "kind": "native", "denom": "cw20:terra1rl20t79ffsrqfa29rke48tj05gj9jxumm92vg8", "decimals": 6, + "variant": "cosmos", "displayName": "CTX", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/ctx.png", @@ -12606,6 +13283,7 @@ "kind": "native", "denom": "cw20:terra13zaagrrrxj47qjwczsczujlvnnntde7fdt0mau", "decimals": 6, + "variant": "cosmos", "displayName": "cLuna", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/cluna.png", @@ -12615,6 +13293,7 @@ "kind": "native", "denom": "cw20:terra1tlgelulz9pdkhls6uglfn5lmxarx7f2gxtdzh2", "decimals": 6, + "variant": "cosmos", "displayName": "pLuna", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/pluna.png", @@ -12624,6 +13303,7 @@ "kind": "native", "denom": "cw20:terra17wkadg0tah554r35x6wvff0y5s7ve8npcjfuhz", "decimals": 6, + "variant": "cosmos", "displayName": "yLuna", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/yluna.png", @@ -12633,6 +13313,7 @@ "kind": "native", "denom": "cw20:terra1cl7whtrqmz5ldr553q69qahck8xvk80fm33qjx", "decimals": 6, + "variant": "cosmos", "displayName": "ATLO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/atlo.png", @@ -12642,6 +13323,7 @@ "kind": "native", "denom": "cw20:terra1vchw83qt25j89zqwdpmdzj722sqxthnckqzxxp", "decimals": 6, + "variant": "cosmos", "displayName": "LOCAL", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/local.png", @@ -12651,6 +13333,7 @@ "kind": "native", "denom": "cw20:terra15k5r9r8dl8r7xlr29pry8a9w7sghehcnv5mgp6", "decimals": 6, + "variant": "cosmos", "displayName": "LUV", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/luv.png", @@ -12660,6 +13343,7 @@ "kind": "native", "denom": "cw20:terra1f62tqesptvmhtzr8sudru00gsdtdz24srgm7wp", "decimals": 6, + "variant": "cosmos", "displayName": "ROBO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/robo.png", @@ -12669,6 +13353,7 @@ "kind": "native", "denom": "cw20:terra1vwz7t30q76s7xx6qgtxdqnu6vpr3ak3vw62ygk", "decimals": 6, + "variant": "cosmos", "displayName": "LUART", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/luart.png", @@ -12678,6 +13363,7 @@ "kind": "native", "denom": "cw20:terra12hgwnpupflfpuual532wgrxu2gjp0tcagzgx4n", "decimals": 6, + "variant": "cosmos", "displayName": "MARS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mars.svg", @@ -12687,6 +13373,7 @@ "kind": "native", "denom": "cw20:terra1a04v570f9cxp49mk06vjsm8axsswndpwwt67k4", "decimals": 6, + "variant": "cosmos", "displayName": "XMARS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/xmars.svg", @@ -12696,6 +13383,7 @@ "kind": "native", "denom": "cw20:terra1vpws4hmpmpsqwnz3gljn8zj42rv7rkpc5atgt4", "decimals": 8, + "variant": "cosmos", "displayName": "DFIAT", "coingeckoId": "not-found", "icon": "not-found", @@ -12705,6 +13393,7 @@ "kind": "native", "denom": "cw20:terra1hppnw4jppmrzzga4yvd8s87y3dwkhe27xwwl5d", "decimals": 6, + "variant": "cosmos", "displayName": "CERES", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/ceres.svg", @@ -12714,6 +13403,7 @@ "kind": "native", "denom": "cw20:terra1z3e2e4jpk4n0xzzwlkgcfvc95pc5ldq0xcny58", "decimals": 8, + "variant": "cosmos", "displayName": "wasAVAX", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/wasavax.svg", @@ -12723,6 +13413,7 @@ "kind": "native", "denom": "cw20:terra1zd6let0zg0xjn2sestagxv4ax24a4ml6j40qdr", "decimals": 6, + "variant": "cosmos", "displayName": "MINT", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mint.svg", @@ -12732,6 +13423,7 @@ "kind": "native", "denom": "cw20:terra1ustvnmngueq0p4jd7gfnutgvdc6ujpsjhsjd02", "decimals": 8, + "variant": "cosmos", "displayName": "SD", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/sd.png", @@ -12741,6 +13433,7 @@ "kind": "native", "denom": "cw20:terra1ln2z938phz0nc2wepxpzfkwp6ezn9yrz9zv9ep", "decimals": 8, + "variant": "cosmos", "displayName": "xSD", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/xsd.png", @@ -12750,6 +13443,7 @@ "kind": "native", "denom": "cw20:terra1uux6gwd6pzr0gfzrru5kne55cxex9d0700c72r", "decimals": 8, + "variant": "cosmos", "displayName": "PAXG", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/paxg.png", @@ -12759,6 +13453,7 @@ "kind": "native", "denom": "cw20:terra1efjugpjc50d8sha7lr8s48cr7wmsthz94eevcl", "decimals": 8, + "variant": "cosmos", "displayName": "whDAO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/whdao.png", @@ -12768,6 +13463,7 @@ "kind": "native", "denom": "cw20:terra1su6g4t4vwx7y0uh3ksancyaurj4l6w9pfs40qt", "decimals": 18, + "variant": "cosmos", "displayName": "LINK", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/link.png", @@ -12777,6 +13473,7 @@ "kind": "native", "denom": "cw20:terra14v9wrjs55qsn9lkvylsqela3w2ytwxzkycqzcr", "decimals": 6, + "variant": "cosmos", "displayName": "SAYVE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/sayve.png", @@ -12786,6 +13483,7 @@ "kind": "native", "denom": "cw20:terra1z55rhw0ut70jxdmpvge98mvj0rkwcz74q77z0u", "decimals": 6, + "variant": "cosmos", "displayName": "GUIDES", "coingeckoId": "not-found", "icon": "not-found", @@ -12795,6 +13493,7 @@ "kind": "native", "denom": "cw20:terra1mt2ytlrxhvd5c4d4fshxxs3zcus3fkdmuv4mk2", "decimals": 6, + "variant": "cosmos", "displayName": "BRO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/bro.svg", @@ -12804,6 +13503,7 @@ "kind": "native", "denom": "cw20:terra1qryq5wreecx2wd3cdtzz94syr4z0a92l60asds", "decimals": 6, + "variant": "cosmos", "displayName": "bBRO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/bbro.svg", @@ -12813,6 +13513,7 @@ "kind": "native", "denom": "cw20:terra15zvyhmv6gwddht7kt4q6w5nasn4tcpgzcdfmgr", "decimals": 18, + "variant": "cosmos", "displayName": "GTPS", "coingeckoId": "not-found", "icon": "not-found", @@ -12822,6 +13523,7 @@ "kind": "native", "denom": "cw20:terra15pkdjxv2ewjzn9x665y26pfz2h6ymak4d4e8se", "decimals": 18, + "variant": "cosmos", "displayName": "GFI", "coingeckoId": "not-found", "icon": "not-found", @@ -12831,6 +13533,7 @@ "kind": "native", "denom": "cw20:terra1fyjsxx73jrufw8ufgtuswa773dvdkny92k70wa", "decimals": 18, + "variant": "cosmos", "displayName": "ULC", "coingeckoId": "not-found", "icon": "not-found", @@ -12840,6 +13543,7 @@ "kind": "native", "denom": "cw20:terra1689ys6p6gfu0q6xrjqkzfn80sdyhurjqn0jfdl", "decimals": 6, + "variant": "cosmos", "displayName": "SST", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/sst.png", @@ -12849,6 +13553,7 @@ "kind": "native", "denom": "cw20:terra1rg8f993m9834afwazersesgx7jjxv4p87q9wvc", "decimals": 8, + "variant": "cosmos", "displayName": "ATLAS", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/atlas.png", @@ -12858,6 +13563,7 @@ "kind": "native", "denom": "cw20:terra1nc6flp57m5hsr6y5y8aexzszy43ksr0drdr8rp", "decimals": 8, + "variant": "cosmos", "displayName": "AUDIO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/audio.png", @@ -12867,6 +13573,7 @@ "kind": "native", "denom": "cw20:terra1hj8de24c3yqvcsv9r8chr03fzwsak3hgd8gv3m", "decimals": 8, + "variant": "cosmos", "displayName": "AVAX", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/avax.png", @@ -12876,6 +13583,7 @@ "kind": "native", "denom": "cw20:terra1apxgj5agkkfdm2tprwvykug0qtahxvfmugnhx2", "decimals": 8, + "variant": "cosmos", "displayName": "BAT", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/bat.png", @@ -12885,6 +13593,7 @@ "kind": "native", "denom": "cw20:terra1skjr69exm6v8zellgjpaa2emhwutrk5a6dz7dd", "decimals": 8, + "variant": "cosmos", "displayName": "BUSDbs", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/busdbs.png", @@ -12894,6 +13603,7 @@ "kind": "native", "denom": "cw20:terra1zmclyfepfmqvfqflu8r3lv6f75trmg05z7xq95", "decimals": 8, + "variant": "cosmos", "displayName": "DAI", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/dai.png", @@ -12903,6 +13613,7 @@ "kind": "native", "denom": "cw20:terra1dtqlfecglk47yplfrtwjzyagkgcqqngd5lgjp8", "decimals": 8, + "variant": "cosmos", "displayName": "MATICpo", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/maticpo.png", @@ -12912,6 +13623,7 @@ "kind": "native", "denom": "cw20:terra15a9dr3a2a2lj5fclrw35xxg9yuxg0d908wpf2y", "decimals": 8, + "variant": "cosmos", "displayName": "MIMet", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mimet.png", @@ -12921,6 +13633,7 @@ "kind": "native", "denom": "cw20:terra1ht5sepn28z999jx33sdduuxm9acthad507jg9q", "decimals": 6, + "variant": "cosmos", "displayName": "RAY", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/ray.png", @@ -12930,6 +13643,7 @@ "kind": "native", "denom": "cw20:terra17h82zsq6q8x5tsgm5ugcx4gytw3axguvzt4pkc", "decimals": 6, + "variant": "cosmos", "displayName": "SBR", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/sbr.png", @@ -12939,6 +13653,7 @@ "kind": "native", "denom": "cw20:terra1huku2lecfjhq9d00k5a8dh73gw7dwe6vvuf2dd", "decimals": 8, + "variant": "cosmos", "displayName": "SHIB", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/shib.png", @@ -12948,6 +13663,7 @@ "kind": "native", "denom": "cw20:terra1dkam9wd5yvaswv4yq3n2aqd4wm5j8n82qc0c7c", "decimals": 6, + "variant": "cosmos", "displayName": "SRMso", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/srmso.png", @@ -12957,6 +13673,7 @@ "kind": "native", "denom": "cw20:terra1pvel56a2hs93yd429pzv9zp5aptcjg5ulhkz7w", "decimals": 6, + "variant": "cosmos", "displayName": "USDCav", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/usdcav.png", @@ -12966,6 +13683,7 @@ "kind": "native", "denom": "cw20:terra1yljlrxvkar0c6ujpvf8g57m5rpcwl7r032zyvu", "decimals": 8, + "variant": "cosmos", "displayName": "USDCbs", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/usdcbs.png", @@ -12975,6 +13693,7 @@ "kind": "native", "denom": "cw20:terra1kkyyh7vganlpkj0gkc2rfmhy858ma4rtwywe3x", "decimals": 6, + "variant": "cosmos", "displayName": "USDCpo", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/usdcpo.png", @@ -12984,6 +13703,7 @@ "kind": "native", "denom": "cw20:terra1e6mq63y64zcxz8xyu5van4tgkhemj3r86yvgu4", "decimals": 6, + "variant": "cosmos", "displayName": "USDCso", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/usdcso.png", @@ -12993,6 +13713,7 @@ "kind": "native", "denom": "cw20:terra1eqvq3thjhye7anv6f6mhxpjhyvww8zjvqcdgjx", "decimals": 6, + "variant": "cosmos", "displayName": "USDTav", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/usdtav.png", @@ -13002,6 +13723,7 @@ "kind": "native", "denom": "cw20:terra1vlqeghv5mt5udh96kt5zxlh2wkh8q4kewkr0dd", "decimals": 8, + "variant": "cosmos", "displayName": "USDTbs", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/usdtbs.png", @@ -13011,6 +13733,7 @@ "kind": "native", "denom": "cw20:terra1hd9n65snaluvf7en0p4hqzse9eqecejz2k8rl5", "decimals": 6, + "variant": "cosmos", "displayName": "USDTso", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/usdtso.png", @@ -13020,6 +13743,7 @@ "kind": "native", "denom": "cw20:terra1fpfn2kkr8mv390wx4dtpfk3vkjx9ch3thvykl3", "decimals": 8, + "variant": "cosmos", "displayName": "gOHM", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/gohm.png", @@ -13029,6 +13753,7 @@ "kind": "native", "denom": "cw20:terra1qvlpf2v0zmru3gtex40sqq02wxp39x3cjh359y", "decimals": 8, + "variant": "cosmos", "displayName": "mSOL", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/msol.png", @@ -13038,6 +13763,7 @@ "kind": "native", "denom": "cw20:terra1w7ywr6waxtjuvn5svk5wqydqpjj0q9ps7qct4d", "decimals": 8, + "variant": "cosmos", "displayName": "stETH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/steth.png", @@ -13047,6 +13773,7 @@ "kind": "native", "denom": "cw20:terra1srp2u95kxps35nvan88gn96nfqhukqya2d0ffc", "decimals": 6, + "variant": "cosmos", "displayName": "LCT", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/lct.png", @@ -13056,6 +13783,7 @@ "kind": "native", "denom": "cw20:terra18zqcnl83z98tf6lly37gghm7238k7lh79u4z9a", "decimals": 6, + "variant": "cosmos", "displayName": "bATOM", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/batom.svg", @@ -13065,6 +13793,7 @@ "kind": "native", "denom": "cw20:terra128pe5jpempxu0nws5lw28se9zknhsr78626cpn", "decimals": 6, + "variant": "cosmos", "displayName": "webATOM", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/webatom.svg", @@ -13074,6 +13803,7 @@ "kind": "native", "denom": "cw20:terra1laczhlpxlgmrwr9un9ds74qxd2fj4754nf82dn", "decimals": 6, + "variant": "cosmos", "displayName": "WCOIN", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/wcoin.svg", @@ -13083,6 +13813,7 @@ "kind": "native", "denom": "cw20:terra1thhm2u93m2stytzynhsxh5h3jrtg540x4punqy", "decimals": 6, + "variant": "cosmos", "displayName": "LCTfancard", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/lctfancard.png", @@ -13092,6 +13823,7 @@ "kind": "native", "denom": "cw20:terra1yeyr6taynkwdl85ppaggr3zr8txhf66cny2ang", "decimals": 6, + "variant": "cosmos", "displayName": "KNTC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/kntc.svg", @@ -13101,6 +13833,7 @@ "kind": "native", "denom": "cw20:terra1g53pyke8jtmt4lwvk4yl0xaqc4u0qlsl8dz3ex", "decimals": 6, + "variant": "cosmos", "displayName": "kUST", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/kust.svg", @@ -13110,6 +13843,7 @@ "kind": "native", "denom": "cw20:terra1rl4zyexjphwgx6v3ytyljkkc4mrje2pyznaclv", "decimals": 6, + "variant": "cosmos", "displayName": "STEAK", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/steak.svg", @@ -13119,6 +13853,7 @@ "kind": "native", "denom": "cw20:terra1jkkt5638cd5pur0u5jnr2juw0v6hz5d6z8xu8m", "decimals": 6, + "variant": "cosmos", "displayName": "CST", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/cst.png", @@ -13128,6 +13863,7 @@ "kind": "native", "denom": "cw20:terra1kz7qszu7p4dg9lts7m9m7lpuarsnan47jh3fam", "decimals": 6, + "variant": "cosmos", "displayName": "CSTfancard", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/cstfancard.png", @@ -13137,6 +13873,7 @@ "kind": "native", "denom": "cw20:terra1amz5c45l34n7w8m5a3z7rd7u0k037x4nnsemwj", "decimals": 9, + "variant": "cosmos", "displayName": "NWLD", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/nwld.png", @@ -13146,6 +13883,7 @@ "kind": "native", "denom": "cw20:terra1cdc6nlsx0l6jmt3nnx7gxjggf902wge3n2z76k", "decimals": 6, + "variant": "cosmos", "displayName": "FURY", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/fury.png", @@ -13155,6 +13893,7 @@ "kind": "native", "denom": "cw20:terra17n223dxpkypc5c48la7aqjvverczg82ga3cr93", "decimals": 6, + "variant": "cosmos", "displayName": "RCT", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/rct.svg", @@ -13164,6 +13903,7 @@ "kind": "native", "denom": "cw20:terra14vw4sfqwe7jw8ppcc7u44vq7hy9qa2nlstnxmu", "decimals": 6, + "variant": "cosmos", "displayName": "VITC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/vitc.png", @@ -13173,6 +13913,7 @@ "kind": "native", "denom": "cw20:terra1948uvsah8aw40dhsa9mhl3htq8lraj0smlh77g", "decimals": 6, + "variant": "cosmos", "displayName": "SB", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/sb.png", @@ -13182,6 +13923,7 @@ "kind": "native", "denom": "cw20:terra1rz964297kvt86rteajhtp4hsffhcum0ye8eljh", "decimals": 6, + "variant": "cosmos", "displayName": "TOAD", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/toad.svg", @@ -13191,6 +13933,7 @@ "kind": "native", "denom": "cw20:terra1yhlhrea3rgyx2xdnsswsfakn28qa8z7yp5gmhd", "decimals": 6, + "variant": "cosmos", "displayName": "orionASTRO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/orionastro.png", @@ -13200,6 +13943,7 @@ "kind": "native", "denom": "cw20:terra1j4hwavavmtsafa6zr0npalfz3tk9gf3p4787mp", "decimals": 6, + "variant": "cosmos", "displayName": "RETRO", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/retro.png", @@ -13209,6 +13953,7 @@ "kind": "native", "denom": "cw20:terra16wggm67a34msdxasg2vergm2pt289y7930wv7d", "decimals": 6, + "variant": "cosmos", "displayName": "TND", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/tnd.png", @@ -13218,6 +13963,7 @@ "kind": "native", "denom": "cw20:terra1n9k2he20h5vpyn4mgv7pg4pzvw2n3wc4a86v3g", "decimals": 6, + "variant": "cosmos", "displayName": "sTND", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/stnd.svg", @@ -13227,6 +13973,7 @@ "kind": "native", "denom": "cw20:terra1ezz5xply2v3xdyv32gy5tcd7zq4k235q4xtzwe", "decimals": 9, + "variant": "cosmos", "displayName": "NWT", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/nwt.png", @@ -13236,6 +13983,7 @@ "kind": "native", "denom": "uaud", "decimals": 6, + "variant": "cosmos", "displayName": "AUTC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/aut.svg", @@ -13245,6 +13993,7 @@ "kind": "native", "denom": "ucad", "decimals": 6, + "variant": "cosmos", "displayName": "CATC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/cat.svg", @@ -13254,6 +14003,7 @@ "kind": "native", "denom": "uchf", "decimals": 6, + "variant": "cosmos", "displayName": "CHTC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/cht.svg", @@ -13263,6 +14013,7 @@ "kind": "native", "denom": "ucny", "decimals": 6, + "variant": "cosmos", "displayName": "CNTC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/cnt.svg", @@ -13272,6 +14023,7 @@ "kind": "native", "denom": "udkk", "decimals": 6, + "variant": "cosmos", "displayName": "DKTC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/dkt.svg", @@ -13281,6 +14033,7 @@ "kind": "native", "denom": "ueur", "decimals": 6, + "variant": "cosmos", "displayName": "EUTC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/eut.svg", @@ -13290,6 +14043,7 @@ "kind": "native", "denom": "ugbp", "decimals": 6, + "variant": "cosmos", "displayName": "GBTC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/gbt.svg", @@ -13299,6 +14053,7 @@ "kind": "native", "denom": "uhkd", "decimals": 6, + "variant": "cosmos", "displayName": "HKTC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/hkt.svg", @@ -13308,6 +14063,7 @@ "kind": "native", "denom": "uidr", "decimals": 6, + "variant": "cosmos", "displayName": "IDTC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/idt.svg", @@ -13317,6 +14073,7 @@ "kind": "native", "denom": "uinr", "decimals": 6, + "variant": "cosmos", "displayName": "INTC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/int.svg", @@ -13326,6 +14083,7 @@ "kind": "native", "denom": "ujpy", "decimals": 6, + "variant": "cosmos", "displayName": "JPTC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/jpt.svg", @@ -13335,6 +14093,7 @@ "kind": "native", "denom": "umnt", "decimals": 6, + "variant": "cosmos", "displayName": "MNTC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/mnt.svg", @@ -13344,6 +14103,7 @@ "kind": "native", "denom": "umyr", "decimals": 6, + "variant": "cosmos", "displayName": "MYTC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/myt.svg", @@ -13353,6 +14113,7 @@ "kind": "native", "denom": "unok", "decimals": 6, + "variant": "cosmos", "displayName": "NOTC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/not.svg", @@ -13362,6 +14123,7 @@ "kind": "native", "denom": "uphp", "decimals": 6, + "variant": "cosmos", "displayName": "PHTC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/pht.svg", @@ -13371,6 +14133,7 @@ "kind": "native", "denom": "usdr", "decimals": 6, + "variant": "cosmos", "displayName": "SDTC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/sdt.svg", @@ -13380,6 +14143,7 @@ "kind": "native", "denom": "usek", "decimals": 6, + "variant": "cosmos", "displayName": "SETC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/set.svg", @@ -13389,6 +14153,7 @@ "kind": "native", "denom": "usgd", "decimals": 6, + "variant": "cosmos", "displayName": "SGTC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/sgt.svg", @@ -13398,6 +14163,7 @@ "kind": "native", "denom": "uthb", "decimals": 6, + "variant": "cosmos", "displayName": "THTC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/tht.svg", @@ -13407,6 +14173,7 @@ "kind": "native", "denom": "utwd", "decimals": 6, + "variant": "cosmos", "displayName": "TWTC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/twt.svg", @@ -13416,6 +14183,7 @@ "kind": "native", "denom": "cw20:terra1mpq5zkkm39nmjrjg9raknpfrfmcfwv0nh0whvn", "decimals": 6, + "variant": "cosmos", "displayName": "NEB", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/neb.png", @@ -13425,6 +14193,7 @@ "kind": "native", "denom": "cw20:terra1g6fm3yu79gv0rc8067n2nnfpf0vks6n0wpzaf4u7w48tdrmj98zsy7uu00", "decimals": 6, + "variant": "cosmos", "displayName": "TRIT", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/trit.png", @@ -13463,6 +14232,7 @@ "kind": "native", "denom": "utgd", "decimals": 6, + "variant": "cosmos", "displayName": "TGD", "coingeckoId": "tgrade", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/tgrade/images/tgrade-symbol-gradient.svg", @@ -13528,6 +14298,7 @@ "kind": "native", "denom": "uulas", "decimals": 6, + "variant": "cosmos", "displayName": "ULAS", "coingeckoId": "ulas", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/ulastestnet/images/logo.png", @@ -13565,6 +14336,7 @@ "kind": "native", "denom": "uumee", "decimals": 6, + "variant": "cosmos", "displayName": "UMEE", "coingeckoId": "umee", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/umee/images/umee.svg", @@ -13603,6 +14375,7 @@ "kind": "native", "denom": "nund", "decimals": 9, + "variant": "cosmos", "displayName": "FUND", "coingeckoId": "unification", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/unification/images/fund.svg", @@ -13641,6 +14414,7 @@ "kind": "native", "denom": "muno", "decimals": 6, + "variant": "cosmos", "displayName": "UNION", "coingeckoId": "unionlabs", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/union/images/union.png", @@ -13679,6 +14453,7 @@ "kind": "native", "denom": "uguu", "decimals": 6, + "variant": "cosmos", "displayName": "GUU", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/ununifi/images/ununifi.svg", @@ -13717,6 +14492,7 @@ "kind": "native", "denom": "auptick", "decimals": 18, + "variant": "cosmos", "displayName": "UPTICK", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/uptick/images/uptick.svg", @@ -13755,6 +14531,7 @@ "kind": "native", "denom": "auptick", "decimals": 18, + "variant": "cosmos", "displayName": "UPTICK", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/upticktestnet/images/uptick.png", @@ -13792,6 +14569,7 @@ "kind": "native", "denom": "uvdl", "decimals": 6, + "variant": "cosmos", "displayName": "VDL", "coingeckoId": "vidulum", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/vidulum/images/vdl.svg", @@ -13830,6 +14608,7 @@ "kind": "native", "denom": "avce", "decimals": 18, + "variant": "cosmos", "displayName": "VCE", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/vincechaintestnet/images/vince.png", @@ -13868,6 +14647,7 @@ "kind": "native", "denom": "utest", "decimals": 6, + "variant": "cosmos", "displayName": "TEST", "coingeckoId": "not-found", "icon": "not-found", @@ -13877,6 +14657,7 @@ "kind": "native", "denom": "uworm", "decimals": 6, + "variant": "cosmos", "displayName": "WORM", "coingeckoId": "not-found", "icon": "not-found", @@ -13886,6 +14667,7 @@ "kind": "native", "denom": "factory/wormhole14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les00fpjx/46YEtoSN1AcwgGSRoWruoS6bnVh8XpMp5aQTpKohCJYh", "decimals": 8, + "variant": "cosmos", "displayName": "SUI", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/sui/images/sui.svg", @@ -13895,6 +14677,7 @@ "kind": "native", "denom": "factory/wormhole14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les00fpjx/5BWqpR48Lubd55szM5i62zK7TFkddckhbT48yy6mNbDp", "decimals": 8, + "variant": "cosmos", "displayName": "WETH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/eth-white.svg", @@ -13904,6 +14687,7 @@ "kind": "native", "denom": "factory/wormhole14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les00fpjx/5TSQTEhJ5Q6r1YqCmCxTRSPiV2pGx5rZUQf6g2XH4e1b", "decimals": 8, + "variant": "cosmos", "displayName": "wstETH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/wsteth.svg", @@ -13913,6 +14697,7 @@ "kind": "native", "denom": "factory/wormhole14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les00fpjx/5wS2fGojbL9RhGEAeQBdkHPUAciYDxjDTMYvdf9aDn2r", "decimals": 8, + "variant": "cosmos", "displayName": "APT", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/aptos/images/aptos.svg", @@ -13922,6 +14707,7 @@ "kind": "native", "denom": "factory/wormhole14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les00fpjx/8iuAc6DSeLvi2JDUtwJxLytsZT8R19itXebZsNReLLNi", "decimals": 6, + "variant": "cosmos", "displayName": "USDT", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/usdt.svg", @@ -13931,6 +14717,7 @@ "kind": "native", "denom": "factory/wormhole14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les00fpjx/8sYgCzLRJC3J7qPn2bNbx6PiGcarhyx8rBhVaNnfvHCA", "decimals": 8, + "variant": "cosmos", "displayName": "SOL", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/solana/images/sol.svg", @@ -13940,6 +14727,7 @@ "kind": "native", "denom": "factory/wormhole14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les00fpjx/95mnwzvJZJ3fKz77xfGN2nR5to9pZmH8YNvaxgLgw5AR", "decimals": 5, + "variant": "cosmos", "displayName": "Bonk", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/solana/images/bonk.png", @@ -13949,6 +14737,7 @@ "kind": "native", "denom": "factory/wormhole14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les00fpjx/BGkuAcga2WArUghF8L6kt6uCAhAzrxmn1QcbQqi5r5bd", "decimals": 8, + "variant": "cosmos", "displayName": "WBTC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/wbtc.svg", @@ -13958,6 +14747,7 @@ "kind": "native", "denom": "factory/wormhole14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les00fpjx/BhqTYfQogyt7jX7cx7x8uHEQP1x9fdtdBZtK4Swghgpw", "decimals": 8, + "variant": "cosmos", "displayName": "tBTC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/tbtc.svg", @@ -13967,6 +14757,7 @@ "kind": "native", "denom": "factory/wormhole14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les00fpjx/EKiMEqDnPKokFGcSXDvGMk6Gt1BJ6BC7BDZzTmEpWLH1", "decimals": 8, + "variant": "cosmos", "displayName": "DAI", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/dai.svg", @@ -13976,6 +14767,7 @@ "kind": "native", "denom": "factory/wormhole14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les00fpjx/GGh9Ufn1SeDGrhzEkMyRKt5568VbbxZK2yvWNsd6PbXt", "decimals": 6, + "variant": "cosmos", "displayName": "USDC", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/usdc.svg", @@ -13985,6 +14777,7 @@ "kind": "native", "denom": "factory/wormhole14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les00fpjx/5ZLmAZpcbaP4EGyihSmpfwryzDr84h51tboV392BCjW4", "decimals": 6, + "variant": "cosmos", "displayName": "avalanche.USDC.wh", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/usdc.svg", @@ -13994,6 +14787,7 @@ "kind": "native", "denom": "factory/wormhole14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les00fpjx/B8ohBnfisop27exk2gtNABJyYjLwQA7ogrp5uNzvZCoy", "decimals": 6, + "variant": "cosmos", "displayName": "PYTH", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/solana/images/pyth.svg", @@ -14032,6 +14826,7 @@ "kind": "native", "denom": "uxion", "decimals": 6, + "variant": "cosmos", "displayName": "XION", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/xion/images/burnt-round.png", @@ -14070,6 +14865,7 @@ "kind": "native", "denom": "axpla", "decimals": 18, + "variant": "cosmos", "displayName": "XPLA", "coingeckoId": "xpla", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/xpla/images/xpla.svg", @@ -14108,6 +14904,7 @@ "kind": "native", "denom": "azeta", "decimals": 18, + "variant": "cosmos", "displayName": "tZETA", "coingeckoId": "not-found", "icon": "https://raw.githubusercontent.com/cosmos/chain-registry/master/testnets/zetachaintestnet/images/zetachaintestnet.svg", diff --git a/package.json b/package.json index e12cfd01ea..602ff8f505 100644 --- a/package.json +++ b/package.json @@ -11,9 +11,10 @@ "build:web": "expo export -p web", "lint": "npx tsx packages/scripts/paralint", "lint-fix": "eslint --cache --ext .js,.jsx,.ts,.tsx . --fix", - "unused-exports": "ts-unused-exports ./tsconfig.json --excludePathsFromReport=\"packages/api;packages/contracts-clients;packages/evm-contracts-clients;packages/screens/RiotGame/RiotGameBridgeScreen.tsx;packages/components/socialFeed/RichText/inline-toolbar;app.config.js;weshd;./App.tsx;packages/modules/FileSystem/index.ts;.*\\.web|.electron|.native|.d.ts\"", + "unused-exports": "ts-unused-exports ./tsconfig.json --excludePathsFromReport=\"packages/api;packages/contracts-clients;packages/evm-contracts-clients;packages/screens/RiotGame/RiotGameBridgeScreen.tsx;packages/components/socialFeed/RichText/inline-toolbar;app.config.js;weshd;./App.tsx;./cypress.config.ts;packages/modules/FileSystem/index.ts;.*\\.web|.electron|.native|.d.ts\"", "validate-networks": "tsx packages/scripts/validateNetworks.ts", - "postinstall": "patch-package" + "postinstall": "patch-package", + "install-gno": "tsx packages/scripts/install-gno" }, "engines": { "node": "v18.1.0" @@ -25,11 +26,12 @@ "@chain-registry/utils": "1.18.0", "@cosmjs/amino": "0.32.2", "@cosmjs/cosmwasm-stargate": "0.32.2", - "@cosmjs/encoding": "^0.32.2", - "@cosmjs/math": "^0.32.2", + "@cosmjs/crypto": "0.32.2", + "@cosmjs/encoding": "0.32.2", + "@cosmjs/math": "0.32.2", "@cosmjs/proto-signing": "0.32.2", "@cosmjs/stargate": "0.32.2", - "@cosmjs/tendermint-rpc": "^0.32.2", + "@cosmjs/tendermint-rpc": "0.32.2", "@cosmology/core": "2.0.1", "@dotlottie/react-player": "^1.6.5", "@draft-js-plugins/anchor": "^4.2.0", @@ -44,6 +46,8 @@ "@expo-google-fonts/exo": "^0.2.2", "@expo/metro-runtime": "~3.1.3", "@gnolang/gno-js-client": "^1.3.0", + "@gnolang/tm2-js-client": "^1.2.1", + "@hookform/resolvers": "^3.6.0", "@improbable-eng/grpc-web": "^0.15.0", "@improbable-eng/grpc-web-node-http-transport": "^0.15.0", "@improbable-eng/grpc-web-react-native-transport": "^0.15.0", @@ -59,6 +63,7 @@ "@react-native-clipboard/clipboard": "^1.13.2", "@react-native-community/slider": "4.4.2", "@react-native-masked-view/masked-view": "0.3.0", + "@react-native-picker/picker": "2.6.1", "@react-navigation/bottom-tabs": "^6.5.11", "@react-navigation/drawer": "^6.6.6", "@react-navigation/native": "^6.0.11", @@ -128,6 +133,7 @@ "react-native-gesture-handler": "~2.14.0", "react-native-get-random-values": "~1.8.0", "react-native-heroicons": "^3.2.0", + "react-native-hoverable": "^0.2.0", "react-native-image-picker": "^7.1.0", "react-native-keyboard-aware-scrollview": "^2.1.0", "react-native-leaflet-view": "^0.1.2", @@ -139,6 +145,7 @@ "react-native-qrcode-svg": "^6.2.0", "react-native-reanimated": "^3.6.2", "react-native-reanimated-carousel": "4.0.0-alpha.9", + "react-native-reanimated-table": "^0.0.2", "react-native-redash": "^18.0.0", "react-native-safe-area-context": "4.8.2", "react-native-screens": "~3.29.0", @@ -162,7 +169,8 @@ "victory-native": "^36.6.8", "waveform-data": "^4.3.0", "yaml": "^2.3.4", - "zod": "^3.22.4" + "zod": "^3.22.4", + "zustand": "^4.4.7" }, "devDependencies": { "@axelar-network/axelarjs-types": "^0.33.0", @@ -175,6 +183,7 @@ "@babel/plugin-transform-shorthand-properties": "^7.23.3", "@babel/plugin-transform-template-literals": "^7.23.3", "@cosmwasm/ts-codegen": "^0.35.7", + "@faker-js/faker": "^8.4.1", "@types/draft-convert": "^2.1.4", "@types/draft-js": "^0.11.9", "@types/html-to-draftjs": "^1.4.0", @@ -187,6 +196,7 @@ "babel-plugin-react-inline-svg-unique-id": "^1.3.1", "cors-anywhere": "^0.4.4", "cross-env": "^7.0.3", + "cypress": "^13.9.0", "depcheck": "^1.4.7", "dotenv": "^16.3.1", "electron": "^27.1.2", diff --git a/packages/components/FlexRow.tsx b/packages/components/FlexRow.tsx index 9fb0adfcfd..1891c6612c 100644 --- a/packages/components/FlexRow.tsx +++ b/packages/components/FlexRow.tsx @@ -16,7 +16,7 @@ type Direction = | "column-reverse" | undefined; -const FlexRow: React.FC = ({ +export const FlexRow: React.FC = ({ breakpoint, width = "100%", alignItems = "center", diff --git a/packages/components/ProgressLine.tsx b/packages/components/ProgressLine.tsx index 87f2d77027..6bad62b582 100644 --- a/packages/components/ProgressLine.tsx +++ b/packages/components/ProgressLine.tsx @@ -1,22 +1,23 @@ import { LinearGradient } from "expo-linear-gradient"; -import React from "react"; -import { View, ViewStyle } from "react-native"; +import { FC, memo } from "react"; +import { StyleProp, View, ViewStyle } from "react-native"; import { neutral33 } from "../utils/style/colors"; -const DEFAULT_WIDTH = 200; - -interface ProgressLineProps { - percent: number; - width?: number; - style?: ViewStyle; -} - -export const ProgressLine: React.FC = ({ - percent, - width = DEFAULT_WIDTH, - style, -}) => { +/** + * @param gain - The gain of the progress line. Must be between 0 and 1 inclusive. + * @param style - The style of the container View. + */ +export const ProgressLine: FC<{ + gain: number; + style?: StyleProp; +}> = memo(({ gain, style }) => { + if (gain < 0) { + gain = 0; + } + if (gain > 1) { + gain = 1; + } return ( = ({ height: 4, borderRadius: 4, backgroundColor: neutral33, - width, + flexGrow: 1, position: "relative", }, style, @@ -36,7 +37,7 @@ export const ProgressLine: React.FC = ({ locations={[0, 0.5, 1]} colors={["#5433FF", "#20BDFF", "#A5FECB"]} style={{ - width: (percent / 100) * width, + width: `${gain * 100}%`, height: 4, position: "absolute", top: 0, @@ -46,4 +47,4 @@ export const ProgressLine: React.FC = ({ /> ); -}; +}); diff --git a/packages/components/Search/SearchBarInput.tsx b/packages/components/Search/SearchBarInput.tsx index f49f613ea8..d6d1d8f465 100644 --- a/packages/components/Search/SearchBarInput.tsx +++ b/packages/components/Search/SearchBarInput.tsx @@ -1,5 +1,5 @@ import React, { useRef } from "react"; -import { StyleProp, TextInput, StyleSheet } from "react-native"; +import { StyleProp, TextInput, StyleSheet, ViewStyle } from "react-native"; import { useSelector } from "react-redux"; import searchSVG from "../../../assets/icons/search.svg"; @@ -32,8 +32,19 @@ export const SearchBarInput: React.FC<{ text: string; onChangeText: (text: string) => void; onInteraction?: () => void; + placeholder?: string; style?: StyleProp; -}> = ({ onInteraction, text, onChangeText, style }) => { + inputStyle?: StyleProp; + noBrokenCorners?: boolean; +}> = ({ + onInteraction, + text, + onChangeText, + style, + placeholder, + inputStyle, + noBrokenCorners = false, +}) => { const ref = useRef(null); const fullWidth = StyleSheet.flatten(style)?.width === "100%"; return ( @@ -52,6 +63,7 @@ export const SearchBarInput: React.FC<{ > { ); }; -const SearchResultsSection: React.FC<{ +export const SearchResultsSection: React.FC<{ title: string; style: StyleProp; isFirstSection?: boolean; diff --git a/packages/components/TopMenu/TopMenuAccount.tsx b/packages/components/TopMenu/TopMenuAccount.tsx index bf0398a5fa..0ddf6f9d1c 100644 --- a/packages/components/TopMenu/TopMenuAccount.tsx +++ b/packages/components/TopMenu/TopMenuAccount.tsx @@ -1,4 +1,4 @@ -import { TextStyle, ViewStyle } from "react-native"; +import { TextStyle, View, ViewStyle } from "react-native"; import chevronRightSVG from "../../../assets/icons/chevron-right.svg"; import useSelectedWallet from "../../hooks/useSelectedWallet"; @@ -10,17 +10,16 @@ import FlexCol from "../FlexCol"; import FlexRow from "../FlexRow"; import { OmniLink } from "../OmniLink"; import { SVG } from "../SVG"; -import { UserNameInline } from "../UserNameInline"; +import { UsernameWithAvatar } from "../user/UsernameWithAvatar"; export const TopMenuAccount: React.FC = () => { const selectedWallet = useSelectedWallet(); return ( - + + + diff --git a/packages/components/TopMenu/WalletView.tsx b/packages/components/TopMenu/WalletView.tsx index e3af59400b..bef60539a3 100644 --- a/packages/components/TopMenu/WalletView.tsx +++ b/packages/components/TopMenu/WalletView.tsx @@ -22,6 +22,7 @@ export const WalletView: React.FC<{ {tinyAddress(userInfo?.metadata?.tokenId || wallet?.address || "", 16)} diff --git a/packages/components/UserNameInline.tsx b/packages/components/UserNameInline.tsx deleted file mode 100644 index 7b8888cdd2..0000000000 --- a/packages/components/UserNameInline.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import React from "react"; -import { StyleProp, TextStyle } from "react-native"; - -import { BrandText } from "./BrandText"; -import FlexRow from "./FlexRow"; -import { OmniLink } from "./OmniLink"; -import { UserAvatarWithFrame } from "./images/AvatarWithFrame"; -import { useNSUserInfo } from "../hooks/useNSUserInfo"; -import { parseUserId } from "../networks"; -import { fontSemibold14 } from "../utils/style/fonts"; -import { layout } from "../utils/style/layout"; -import { tinyAddress } from "../utils/text"; - -type PlayerNameProps = { - userId: string | undefined; - multisignWalletAddres?: string | null; - style?: StyleProp; -}; - -export const UserNameInline: React.FC = ({ - userId, - style, -}) => { - const [, userAddress] = parseUserId(userId); - const userInfo = useNSUserInfo(userId); - const name = - userInfo?.metadata?.tokenId || tinyAddress(userAddress, 30) || ""; - - return ( - - - - - {name} - - - - ); -}; diff --git a/packages/components/WalletProviderIcon.tsx b/packages/components/WalletProviderIcon.tsx index 69899e06a3..b48dba7a7f 100644 --- a/packages/components/WalletProviderIcon.tsx +++ b/packages/components/WalletProviderIcon.tsx @@ -6,6 +6,7 @@ import adenaSVG from "../../assets/icons/adena.svg"; import keplrSVG from "../../assets/icons/keplr.svg"; import leapSVG from "../../assets/icons/leap-cosmos-logo.svg"; import metamaskSVG from "../../assets/icons/metamask.svg"; +import warningSVG from "../../assets/icons/warning.svg"; import { WalletProvider } from "../utils/walletProvider"; export const WalletProviderIcon: React.FC<{ @@ -21,6 +22,8 @@ export const WalletProviderIcon: React.FC<{ return ; case WalletProvider.Adena: return ; + case WalletProvider.Gnotest: + return ; default: return ; } diff --git a/packages/components/buttons/IconButton.tsx b/packages/components/buttons/IconButton.tsx index e900b86c77..84c1b232d4 100644 --- a/packages/components/buttons/IconButton.tsx +++ b/packages/components/buttons/IconButton.tsx @@ -55,6 +55,7 @@ export const IconButton: React.FC<{ borderRadius: borderRadiusButton(size), backgroundColor, paddingHorizontal: 20, + alignItems: "center", }, ]} > diff --git a/packages/components/buttons/PrimaryButton.tsx b/packages/components/buttons/PrimaryButton.tsx index 276751b903..a3132cb882 100644 --- a/packages/components/buttons/PrimaryButton.tsx +++ b/packages/components/buttons/PrimaryButton.tsx @@ -35,6 +35,7 @@ export const PrimaryButton: React.FC<{ RightComponent?: React.FC; color?: string; isLoading?: boolean; + testID?: string; }> = ({ // If no width, the buttons will fit the content including paddingHorizontal 20 width, @@ -51,6 +52,7 @@ export const PrimaryButton: React.FC<{ iconColor, color = primaryColor, isLoading: isLoadingProp, + testID, }) => { const [isLocalLoading, setIsLocalLoading] = useState(false); const [hovered, setHovered] = useState(false); @@ -89,6 +91,7 @@ export const PrimaryButton: React.FC<{ onHoverOut={() => { setHovered(false); }} + testID={testID} > ; + style?: StyleProp; loading?: boolean; disabled?: boolean; iconSVG?: React.FC; outline?: boolean; + testID?: string | undefined; } export const SimpleButton: React.FC = ({ @@ -38,27 +39,33 @@ export const SimpleButton: React.FC = ({ style, iconSVG = null, outline = false, + testID, }) => { let padH: number; let padV: number; + let radius: number; switch (size) { case "XL": padH = layout.spacing_x3; padV = layout.spacing_x2_5; + radius = layout.spacing_x1_5; break; case "SM": padH = layout.spacing_x2; padV = layout.spacing_x1_5; + radius = layout.spacing_x0_75; break; case "XS": padH = layout.spacing_x1_5; padV = layout.spacing_x0_5; + radius = layout.spacing_x0_5; break; case "M": default: padH = layout.spacing_x2_5; padV = layout.spacing_x2; + radius = layout.spacing_x1; break; } @@ -67,15 +74,20 @@ export const SimpleButton: React.FC = ({ disabled={disabled} style={[containerStyle, (loading || disabled) && { opacity: 0.6 }]} onPress={() => !loading && onPress?.()} + testID={testID} > = ({ ); }; - -// FIXME: remove StyleSheet.create -// eslint-disable-next-line no-restricted-syntax -const styles = StyleSheet.create({ - btnStyle: { - alignSelf: "center", - borderRadius: layout.spacing_x1_5, - ...(fontSemibold14 as object), - }, -}); diff --git a/packages/components/buttons/SocialButton.tsx b/packages/components/buttons/SocialButton.tsx index 4e0931729a..23ca47e682 100644 --- a/packages/components/buttons/SocialButton.tsx +++ b/packages/components/buttons/SocialButton.tsx @@ -1,12 +1,18 @@ import React from "react"; -import { ViewStyle, StyleProp, TouchableOpacity } from "react-native"; +import { + ViewStyle, + StyleProp, + TouchableOpacity, + View, + Pressable, + ColorValue, +} from "react-native"; import { SvgProps } from "react-native-svg"; -import { BrandText } from "../BrandText"; -import { SVG } from "../SVG"; -import { Box } from "../boxes/Box"; - -import { neutral22, neutral33, withAlpha } from "@/utils/style/colors"; +import { BrandText } from "@/components/BrandText"; +import { SVG } from "@/components/SVG"; +import { Box } from "@/components/boxes/Box"; +import { withAlpha, neutral22, neutral33 } from "@/utils/style/colors"; import { fontMedium14 } from "@/utils/style/fonts"; export const iconSize = 32; @@ -14,12 +20,78 @@ export const iconPadding = 12; export const outerPadding = 6; export const innerGap = 8; +const IconWithText: React.FC<{ + text?: string; + iconSvg: React.FC; + textColor?: ColorValue; + iconColor?: ColorValue; +}> = ({ text, iconSvg, textColor, iconColor }) => { + return ( + + + + + {!!text && ( + + {text} + + )} + + ); +}; + +export const IconWithTextButton: React.FC<{ + text?: string; + iconSvg: React.FC; + textColor?: ColorValue; + onPress?: () => void; + style?: StyleProp; +}> = ({ text, iconSvg, style, onPress, textColor }) => { + const [hovered, setHovered] = React.useState(false); + return ( + setHovered(true)} + onHoverOut={() => setHovered(false)} + > + + + ); +}; + export const SocialButton: React.FC<{ text?: string; iconSvg: React.FC; + textColor?: ColorValue; + iconColor?: ColorValue; onPress?: () => void; style?: StyleProp; -}> = ({ text, onPress, iconSvg, style }) => { +}> = ({ text, onPress, iconSvg, style, textColor, iconColor }) => { return ( - - - - {!!text && ( - - {text} - - )} + ); diff --git a/packages/components/connectWallet/ConnectAdenaButton.tsx b/packages/components/connectWallet/ConnectAdenaButton.tsx index 153ad7f12c..d02ff246c8 100644 --- a/packages/components/connectWallet/ConnectAdenaButton.tsx +++ b/packages/components/connectWallet/ConnectAdenaButton.tsx @@ -31,6 +31,7 @@ export const ConnectAdenaButton: React.FC<{ const address = account.data.address; const chainId = account.data.chainId; const network = getGnoNetworkFromChainId(chainId); + if (!network) { throw new Error(`Unsupported chainId ${chainId}`); } diff --git a/packages/components/hub/AssetRatioByChain.tsx b/packages/components/hub/AssetRatioByChain.tsx index 8b353ec18d..d64033a46e 100644 --- a/packages/components/hub/AssetRatioByChain.tsx +++ b/packages/components/hub/AssetRatioByChain.tsx @@ -43,8 +43,10 @@ const ListItem: React.FC = ({ title, icon, percent }) => { {title} { description="Get funds to develop, contribute and build new feature for Communities" info="Apply here" iconSVG={labsSVG} - onPress={() => Linking.openURL("https://teritori.com/grants")} + onPress={() => Linking.openURL("https://teritori.com/projects")} /> diff --git a/packages/components/images/RoundedGradientImage.tsx b/packages/components/images/RoundedGradientImage.tsx index 25ff66fe1b..1c55d0d964 100644 --- a/packages/components/images/RoundedGradientImage.tsx +++ b/packages/components/images/RoundedGradientImage.tsx @@ -4,12 +4,16 @@ import { View, ViewStyle, StyleProp } from "react-native"; import { OptimizedImage } from "../OptimizedImage"; -type RoundedGradientImageSize = "M" | "XS" | "XXS"; +type RoundedGradientImageSize = "L" | "M" | "S" | "XS" | "XXS"; const dimension = (size: RoundedGradientImageSize) => { switch (size) { + case "L": + return 236; case "M": return 140; + case "S": + return 56; case "XS": return 32; case "XXS": @@ -18,8 +22,12 @@ const dimension = (size: RoundedGradientImageSize) => { }; const imageDimension = (size: RoundedGradientImageSize) => { switch (size) { + case "L": + return dimension(size) - 4; case "M": return dimension(size) - 4; + case "S": + return dimension(size) - 2; case "XS": return dimension(size) - 2; case "XXS": @@ -32,7 +40,8 @@ export const RoundedGradientImage: React.FC<{ fallbackURI?: string | null | undefined; size?: RoundedGradientImageSize; style?: StyleProp; -}> = ({ sourceURI, fallbackURI, size = "M", style }) => { + square?: boolean; +}> = ({ sourceURI, fallbackURI, size = "M", style, square = false }) => { return ( @@ -75,7 +88,7 @@ export const RoundedGradientImage: React.FC<{ position: "absolute", width: dimension(size), height: dimension(size), - borderRadius: 999, + borderRadius: square ? 12 : 999, }} colors={["#01B7C5", "#782C96"]} /> diff --git a/packages/components/inputs/SelectInput.tsx b/packages/components/inputs/SelectInput.tsx index 3644d7039f..0c5c374577 100644 --- a/packages/components/inputs/SelectInput.tsx +++ b/packages/components/inputs/SelectInput.tsx @@ -52,6 +52,7 @@ type Props = { allowSearchValue?: boolean; name?: string; isLoading?: boolean; + testID?: string; renderItem?: ({ onPressItem, item, @@ -75,6 +76,7 @@ export const SelectInput: React.FC = ({ name, isLoading, renderItem, + testID, }) => { const [openMenu, setOpenMenu] = useState(false); const [hovered, setHovered] = useState(false); @@ -131,6 +133,7 @@ export const SelectInput: React.FC = ({ if (!disabled || selectableData.length) setOpenMenu((value) => !value); }} disabled={disabled || !selectableData.length} + testID={testID} > {label && ( <> diff --git a/packages/components/inputs/TextInputCustom.tsx b/packages/components/inputs/TextInputCustom.tsx index ef95e3184e..6c8f29a1e6 100644 --- a/packages/components/inputs/TextInputCustom.tsx +++ b/packages/components/inputs/TextInputCustom.tsx @@ -264,6 +264,8 @@ export const TextInputCustom = ({ boxMainContainerStyle, noBrokenCorners && styles.noCropBorderBg, hovered && { borderColor: secondaryColor }, + height !== undefined && + height <= styles.mainContainer.minHeight && { minHeight: height }, ]} width={width} fullWidth={!width} diff --git a/packages/components/layout/GridList.tsx b/packages/components/layout/GridList.tsx index 4c4d2cda4d..61257e6715 100644 --- a/packages/components/layout/GridList.tsx +++ b/packages/components/layout/GridList.tsx @@ -16,6 +16,12 @@ type GridListType = React.FC<{ gap?: number; noFixedHeight?: boolean; onEndReached?: ComponentProps>["onEndReached"]; + ListHeaderComponent?: ComponentProps< + typeof FlatList + >["ListHeaderComponent"]; + ListFooterComponent?: ComponentProps< + typeof FlatList + >["ListFooterComponent"]; }>; type ItemWrapper = @@ -36,6 +42,8 @@ export function GridList({ noFixedHeight, keyExtractor, renderItem, + ListHeaderComponent, + ListFooterComponent, }: ComponentProps>): ReturnType> { const { height } = useMaxResolution({ isLarge: true }); const [containerWidth, setContainerWidth] = useState(0); @@ -90,6 +98,7 @@ export function GridList({ > onLayout={(e) => setContainerWidth(e.nativeEvent.layout.width)} contentContainerStyle={!noFixedHeight && { height }} + ListHeaderComponent={ListHeaderComponent} columnWrapperStyle={ elemsPerRow < 2 ? undefined @@ -109,6 +118,7 @@ export function GridList({ size={Math.min(height, containerWidth) / 3} /> } + ListFooterComponent={ListFooterComponent} renderItem={renderItemWithFixedWidth} /> ); diff --git a/packages/components/loaders/AnimatedLoader.tsx b/packages/components/loaders/AnimatedLoader.tsx index 452d91599b..545fc9ddb5 100644 --- a/packages/components/loaders/AnimatedLoader.tsx +++ b/packages/components/loaders/AnimatedLoader.tsx @@ -5,7 +5,8 @@ import { StyleProp, View, ViewStyle } from "react-native"; export const AnimatedLoader: React.FC<{ size?: number; style?: StyleProp; -}> = memo(({ size: sizeProp, style }) => { + testID?: string | undefined; +}> = memo(({ size: sizeProp, style, testID }) => { const size = sizeProp || 80; return ( diff --git a/packages/components/loaders/LoaderFullScreen.tsx b/packages/components/loaders/LoaderFullScreen.tsx index 2c1df5f34b..4cf5dc51bb 100644 --- a/packages/components/loaders/LoaderFullScreen.tsx +++ b/packages/components/loaders/LoaderFullScreen.tsx @@ -17,7 +17,7 @@ export const LoaderFullScreen: React.FC<{ visible: boolean }> = ({ zIndex: 10, }} > - + ); diff --git a/packages/components/modals/ConnectWalletModal.tsx b/packages/components/modals/ConnectWalletModal.tsx index fd48cc2721..c32cde9703 100644 --- a/packages/components/modals/ConnectWalletModal.tsx +++ b/packages/components/modals/ConnectWalletModal.tsx @@ -19,6 +19,8 @@ import { ConnectWalletButton } from "../connectWallet/components/ConnectWalletBu import { SeparatorGradient } from "../separators/SeparatorGradient"; import { SpacerColumn } from "../spacer"; +import { ConnectGnotestButton } from "@/context/WalletsProvider/gnotest"; + export const ConnectWalletModal: FC<{ forceNetworkFeature?: NetworkFeature; label?: string; @@ -109,6 +111,7 @@ export const ConnectWalletModal: FC<{ visible={isDisclaimerVisible} onClose={toggleDisclaimer} /> + ); }; diff --git a/packages/components/navigation/getNormalModeScreens.tsx b/packages/components/navigation/getNormalModeScreens.tsx index 20bcff6e4d..5b134f0389 100644 --- a/packages/components/navigation/getNormalModeScreens.tsx +++ b/packages/components/navigation/getNormalModeScreens.tsx @@ -39,6 +39,13 @@ import { MultisigWalletDashboardScreen } from "@/screens/Multisig/MultisigWallet import { MyCollectionScreen } from "@/screens/MyCollection/MyCollectionScreen"; import { OrganizationDeployerScreen } from "@/screens/Organizations/OrganizationDeployerScreen"; import { OrganizationsScreen } from "@/screens/Organizations/OrganizationsScreen"; +import { ProjectsCompleteMilestoneScreen } from "@/screens/Projects/CompleteMilestoneScreen"; +import { ProjectsConflictSolvingScreen } from "@/screens/Projects/ProjectsConflictSolvingScreen"; +import { ProjectsDetailScreen } from "@/screens/Projects/ProjectsDetailScreen"; +import { ProjectsMakeRequestScreen } from "@/screens/Projects/ProjectsMakeRequestScreen"; +import { ProjectsManagerScreen } from "@/screens/Projects/ProjectsManagerScreen"; +import { ProjectsPaymentScreen } from "@/screens/Projects/ProjectsPaymentScreen"; +import { ProjectsScreen } from "@/screens/Projects/ProjectsScreen"; import { ReadyLaunchpadApplicationsScreen } from "@/screens/ReadyLaunchpadApplications/ReadyLaunchpadApplicationsScreen"; import { RiotGameBreedingScreen } from "@/screens/RiotGame/RiotGameBreedingScreen"; import { RiotGameEnrollScreen } from "@/screens/RiotGame/RiotGameEnrollScreen"; @@ -318,6 +325,67 @@ export const getNormalModeScreens = ({ appMode }: { appMode: AppMode }) => { }} /> + {/* ==== Projects program */} + null, title: screenTitle("Projects Program") }} + /> + + null, + title: screenTitle("Projects Program Detail"), + }} + /> + + null, + title: screenTitle("Projects Program Manager"), + }} + /> + + null, + title: screenTitle("Projects Program Payment"), + }} + /> + + null, + title: screenTitle("Projects Milestone"), + }} + /> + + null, + title: screenTitle("Projects Program Make Request"), + }} + /> + + null, + title: screenTitle("Project Conflict Solving"), + }} + /> + {/* ==== Teritori Name Service*/} = ({ userId, addrLen = 30 }) => { + const [, userAddress] = parseUserId(userId); + const userInfo = useNSUserInfo(userId); + + if (!userId) { + return ( + + None + + ); + } + + const name = + userInfo?.metadata?.tokenId || tinyAddress(userAddress, addrLen) || ""; + + return ( + + + + {name} + + + ); +}; diff --git a/packages/context/SidebarProvider.tsx b/packages/context/SidebarProvider.tsx index 72e56176c6..5f99f59074 100644 --- a/packages/context/SidebarProvider.tsx +++ b/packages/context/SidebarProvider.tsx @@ -15,12 +15,14 @@ import { import { useAppDispatch } from "../store/store"; import { SIDEBAR_LIST } from "../utils/sidebar"; +import { useDeveloperMode } from "@/hooks/useDeveloperMode"; import { getValuesFromId, SEPARATOR } from "@/utils/dapp-store"; export const useSidebar = () => { const isSidebarExpanded = useSelector(selectSidebarExpanded); const selectedApps = useSelector(selectCheckedApps); const availableApps = useSelector(selectAvailableApps); + const [developerMode] = useDeveloperMode(); const dispatch = useAppDispatch(); // on mobile sidebar is not expanded on load const isMobile = useIsMobile(); @@ -51,31 +53,46 @@ export const useSidebar = () => { [key: string]: any; }; - selectedApps.map((element) => { - const { appId, groupKey } = getValuesFromId(element); - if (!availableApps[groupKey]) { - return; - } - const option = availableApps[groupKey].options[appId]; - if (option === undefined) { - return; - } + selectedApps + .filter((element) => { + const { appId, groupKey } = getValuesFromId(element); + if (!availableApps[groupKey]) { + return false; + } + const option = availableApps[groupKey].options[appId]; + if (option === undefined) { + return false; + } + if (option.devOnly && !developerMode) { + return false; + } + return true; + }) + .map((element) => { + const { appId, groupKey } = getValuesFromId(element); + if (!availableApps[groupKey]) { + return; + } + const option = availableApps[groupKey].options[appId]; + if (option === undefined) { + return; + } - dynamicAppsSelection[element] = SIDEBAR_LIST[option.id] - ? SIDEBAR_LIST[option.id] - : { - id: option.id, - title: option.title, - route: option.route, - url: option.url, - icon: option.icon, - }; - }); + dynamicAppsSelection[element] = SIDEBAR_LIST[option.id] + ? SIDEBAR_LIST[option.id] + : { + id: option.id, + title: option.title, + route: option.route, + url: option.url, + icon: option.icon, + }; + }); dynamicAppsSelection["dappstore"] = SIDEBAR_LIST["DAppsStore"]; return dynamicAppsSelection; - }, [availableApps, selectedApps]); + }, [availableApps, selectedApps, developerMode]); const toggleSidebar = () => { dispatch(setSidebarExpanded(!isSidebarExpanded)); diff --git a/packages/context/WalletsProvider/WalletsProvider.tsx b/packages/context/WalletsProvider/WalletsProvider.tsx index 119e7e3833..5ad2410978 100644 --- a/packages/context/WalletsProvider/WalletsProvider.tsx +++ b/packages/context/WalletsProvider/WalletsProvider.tsx @@ -1,6 +1,7 @@ import React, { createContext, ReactNode, useContext, useMemo } from "react"; import { useAdena } from "./adena"; +import { useGnotest } from "./gnotest"; import { useKeplr } from "./keplr"; import { useLeap } from "./leap"; import { useMetamask } from "./metamask"; @@ -33,6 +34,7 @@ export const WalletsProvider: React.FC<{ children: ReactNode }> = React.memo( const [hasLeap, leapIsReady, leapWallets] = useLeap(); const [hasMetamask, metamaskIsReady, metamaskWallets] = useMetamask(); const [hasAdena, adenaIsReady, adenaWallets] = useAdena(); + const [hasGnotest, , gnotestWallets] = useGnotest(); const selectedNativeWallet = useSelectedNativeWallet(); const hasNative = !!selectedNativeWallet; @@ -137,25 +139,34 @@ export const WalletsProvider: React.FC<{ children: ReactNode }> = React.memo( } } + if (hasGnotest) { + walletProviders.push(WalletProvider.Gnotest); + if (gnotestWallets?.[0]?.connected) { + wallets.push(gnotestWallets[0]); + } + } + return { wallets, walletProviders, ready: keplrIsReady && metamaskIsReady && adenaIsReady && leapIsReady, }; }, [ + adenaIsReady, + adenaWallets, + gnotestWallets, + hasAdena, + hasGnotest, hasKeplr, hasLeap, hasMetamask, - hasAdena, hasNative, keplrIsReady, - metamaskIsReady, - adenaIsReady, - leapIsReady, keplrWallets, + leapIsReady, leapWallets, + metamaskIsReady, metamaskWallets, - adenaWallets, selectedNativeWallet, ]); diff --git a/packages/context/WalletsProvider/gnotest/index.tsx b/packages/context/WalletsProvider/gnotest/index.tsx new file mode 100644 index 0000000000..c09e82dec7 --- /dev/null +++ b/packages/context/WalletsProvider/gnotest/index.tsx @@ -0,0 +1,309 @@ +import { + GnoJSONRPCProvider, + GnoWallet, + MsgSend, + decodeTxMessages, +} from "@gnolang/gno-js-client"; +import { TxFee, TransactionEndpoint, Tx } from "@gnolang/tm2-js-client"; +import Long from "long"; +import React from "react"; +import { Pressable } from "react-native"; +import { create } from "zustand"; + +import { Wallet } from "../wallet"; + +import { getUserId } from "@/networks"; +import { gnoDevNetwork } from "@/networks/gno-dev"; +import { setSelectedWalletId } from "@/store/slices/settings"; +import { useAppDispatch } from "@/store/store"; +import { RequestDocontractMessage } from "@/utils/gno"; +import { WalletProvider } from "@/utils/walletProvider"; + +type UseGnotestResult = [true, boolean, Wallet[]] | [false, boolean, undefined]; + +interface GnotestState { + connected: boolean; + wallet: GnoWallet | null; + address: string | null; + accounts: Account[]; + connect: () => void; +} + +interface Account { + wallet: GnoWallet; + address: string; +} + +const network = gnoDevNetwork; + +interface UserMetadata { + imageURI: string; + displayName: string; + bio: string; +} + +interface TestUser { + name: string; + mnemonic: string; + nsName: string; + extra: UserMetadata; +} + +const faucetMnemo = + "chimney entire define lesson scale embark copy bird rough govern surprise soda sand evidence decline crisp clinic merry slice balance typical creek lumber hollow"; + +const testUsers: TestUser[] = [ + { + name: "alice", + nsName: "alicetests", + mnemonic: + "clog eager dumb mango sibling crime soldier climb switch either lock festival raven please badge weasel misery host grant make half assume strategy buzz", + extra: { + imageURI: + "ipfs://bafybeignxvdw76wqsokthgyp4d3jrvbdiikqwo4vbff6rwb5ivj7fb3aoi", + displayName: "Alice", + bio: "Seasoned marketing strategist with a knack for digital campaigns and brand building. With a background in content creation and SEO, has helped numerous startups grow their online presence and engage with their target audience effectively. Outside of work, is an avid reader, enjoys playing guitar, and is a dedicated coffee enthusiast. Reach out for insights on marketing trends and effective brand strategies.", + }, + }, + { + name: "bob", + nsName: "bobtests", + mnemonic: + "vault garment mosquito legend merit level flavor width correct amazing window skill title dwarf another journey cube junior chat ivory toilet area pool brick", + extra: { + imageURI: + "ipfs://bafkreifvzfnitqu6yq2t4dp37oeaqvitepuutrox332kcs5jncl7uxo6sy", + displayName: "Bob", + bio: "Passionate software developer with over 10 years of experience in web and mobile application development. Specializes in JavaScript, React, and Node.js, and loves creating seamless user experiences. When not coding, enjoys hiking, photography, and volunteering at local animal shelters. Connect to discuss innovative tech solutions and collaborative projects.", + }, + }, + { + name: "dredd", + nsName: "dreddtests", + mnemonic: + "nice daughter demise elevator gate manage observe real outer awkward profit sheriff total boat collect voice speed board pilot rifle nephew grid permit frozen", + extra: { + imageURI: + "ipfs://bafkreiahgkmcppkvxhkus7baqnflrcrff2pkjboi4t4eebt3dq6ui66foi", + displayName: "Dredd", + bio: "Cybersecurity expert with a focus on network security and ethical hacking. With over 15 years in the field, has a proven track record of safeguarding organizations from cyber threats and vulnerabilities. Also a frequent speaker at industry conferences and enjoys writing articles on the latest in cybersecurity. In free time, practices martial arts and enjoys building custom PCs. Connect for advice on protecting digital assets and staying ahead of cyber threats.", + }, + }, +]; + +const useGnotestStore = create((set, get) => ({ + connected: false, + accounts: [], + wallet: null, + address: null, + connect: async () => { + const state = get(); + if (state.connected) { + return; + } + + const provider = new GnoJSONRPCProvider(network.endpoint); + + const faucetWallet = await GnoWallet.fromMnemonic(faucetMnemo); + faucetWallet.connect(provider); + const faucerAddr = await faucetWallet.getAddress(); + + // fund users + const msgs = await Promise.all( + testUsers.map(async (testUser) => { + const wallet = await GnoWallet.fromMnemonic(testUser.mnemonic); + wallet.connect(provider); + // fund user + const msg: MsgSend = { + from_address: faucerAddr, + to_address: await wallet.getAddress(), + amount: "200000000000ugnot", + }; + return msg; + }), + ); + const tx: Tx = { + messages: msgs.map((msg) => ({ + typeUrl: "/bank.MsgSend", + value: MsgSend.encode(msg).finish(), + })), + fee: { + gasFee: "1ugnot", + gasWanted: Long.fromNumber(1000000), + }, + memo: "", + signatures: [], + }; + const signed = await faucetWallet.signTransaction(tx, decodeTxMessages); + await faucetWallet.sendTransaction( + signed, + TransactionEndpoint.BROADCAST_TX_COMMIT, + ); + + const accounts = await Promise.all( + testUsers.map(async (testUser) => { + const wallet = await GnoWallet.fromMnemonic(testUser.mnemonic); + wallet.connect(provider); + const addr = await wallet.getAddress(); + + // try register user + try { + const nsRealm = network.nameServiceContractAddress; + const send = new Map(); + send.set("ugnot", 200000000); + wallet.callMethod( + nsRealm, + "Register", + ["", testUser.nsName, JSON.stringify(testUser.extra)], + TransactionEndpoint.BROADCAST_TX_COMMIT, + send, + { + gasWanted: Long.fromNumber(10000000), + gasFee: "1ugnot", + }, + ); + } catch (e) { + console.warn("Failed to register user", testUser, e); + } + + return { + wallet, + address: addr, + }; + }), + ); + set((state) => ({ + ...state, + connected: true, + accounts, + wallet: accounts[0].wallet, + address: accounts[0].address, + })); + }, +})); + +const setupAdenaMock = () => { + (window as any).adena = { + SetTestUser: async (name: string) => { + const testUser = testUsers.find((u) => u.name === name); + if (!testUser) { + throw new Error("Test user not found: " + name); + } + const newAddr = await ( + await GnoWallet.fromMnemonic(testUser.mnemonic) + ).getAddress(); + const state = useGnotestStore.getState(); + const account = state.accounts.find((a) => a.address === newAddr); + if (!account) { + throw new Error("Account not found: " + newAddr); + } + useGnotestStore.setState({ + wallet: account.wallet, + address: account.address, + }); + return getUserId(network.id, account.address); + }, + GetAccount: async () => { + const state = useGnotestStore.getState(); + return { + data: { + address: state.address, + chainId: network.chainId, + }, + }; + }, + DoContract: async (req: RequestDocontractMessage) => { + try { + const state = useGnotestStore.getState(); + if (!state.wallet) { + throw new Error("Wallet not connected"); + } + const msg = req.messages[0]; + if (msg.type !== "/vm.m_call") { + throw new Error("Unsupported message type: " + msg.type); + } + const txFee: TxFee = { + gasWanted: Long.fromNumber(req.gasWanted), + gasFee: req.gasFee.toString() + "ugnot", + }; + let sendMap; + if (msg.value.send) { + sendMap = new Map(); + const end = msg.value.send.length - "ugnot".length; + const sendAmount = (msg.value.send as string).substring(0, end); + console.log("docontract sendAmount", sendAmount); + sendMap.set("ugnot", +sendAmount); + } + const res = await state.wallet.callMethod( + msg.value.pkg_path, + msg.value.func, + msg.value.args, + TransactionEndpoint.BROADCAST_TX_COMMIT, + sendMap, + txFee, + ); + return { + status: "success", + data: { + hash: res.hash, + height: res.height, + }, + }; + } catch (e) { + console.error("docontract error", e); + const errMsg = e instanceof Error ? e.message : `${e}`; + return { + status: "failure", + message: errMsg, + data: { + error: e, + }, + }; + } + }, + }; +}; + +export const useGnotest: () => UseGnotestResult = () => { + const { wallet, address } = useGnotestStore(); + const wallets: Wallet[] = []; + if (wallet && address) { + wallets.push({ + address, + provider: WalletProvider.Gnotest, + networkKind: network.kind, + networkId: network.id, + userId: getUserId(network.id, address), + connected: true, + id: `gnotest`, + }); + } + return [true, true, wallets]; +}; + +export const ConnectGnotestButton: React.FC<{ + onDone?: () => void; +}> = ({ onDone }) => { + const { connect } = useGnotestStore(); + const dispatch = useAppDispatch(); + return ( + { + setupAdenaMock(); + connect(); + dispatch(setSelectedWalletId("gnotest")); + onDone?.(); + }} + testID="connect-gnotest-wallet" + /> + ); +}; + +const TestHiddenButton: React.FC<{ + testID: string | undefined; + onPress: () => void; +}> = ({ testID, onPress }) => { + return ( + + ); +}; diff --git a/packages/hooks/useNSNameInfo.ts b/packages/hooks/useNSNameInfo.ts index 8b5c1ec0ae..4e53905d07 100644 --- a/packages/hooks/useNSNameInfo.ts +++ b/packages/hooks/useNSNameInfo.ts @@ -64,6 +64,7 @@ export const useNSNameInfo = ( if (!address) { return null; } + // TODO: use profile realm const res: NftInfoResponse = { extension: {}, }; @@ -111,7 +112,7 @@ const gnoGetAddressByUsername = async ( try { const res = await provider.evaluateExpression( network.nameServiceContractAddress, - `GetUserByName(${JSON.stringify(name)}).address`, + `GetUserByName(${JSON.stringify(name)}).Address`, ); const address = extractGnoString(res); return address; diff --git a/packages/networks/cosmos-hub-theta/currencies.ts b/packages/networks/cosmos-hub-theta/currencies.ts index 44f9c60612..c16f288398 100644 --- a/packages/networks/cosmos-hub-theta/currencies.ts +++ b/packages/networks/cosmos-hub-theta/currencies.ts @@ -6,6 +6,7 @@ export const cosmosHubThetaCurrencies: CurrencyInfo[] = [ denom: "uatom", displayName: "ATOM", decimals: 6, + variant: "cosmos", coingeckoId: "cosmos", icon: "cosmos-hub-circle.svg", kind: "native", diff --git a/packages/networks/cosmos-hub/currencies.ts b/packages/networks/cosmos-hub/currencies.ts index 592f1d04ed..9fc336ed21 100644 --- a/packages/networks/cosmos-hub/currencies.ts +++ b/packages/networks/cosmos-hub/currencies.ts @@ -6,6 +6,7 @@ export const cosmosHubCurrencies: CurrencyInfo[] = [ denom: "uatom", displayName: "ATOM", decimals: 6, + variant: "cosmos", coingeckoId: "cosmos", icon: "cosmos-hub-circle.svg", kind: "native", diff --git a/packages/networks/cosmos-registry.ts b/packages/networks/cosmos-registry.ts index 918dc84e99..63180bdf09 100644 --- a/packages/networks/cosmos-registry.ts +++ b/packages/networks/cosmos-registry.ts @@ -54,6 +54,7 @@ export const networksFromCosmosRegistry = (): CosmosNetworkInfo[] => { decimals: asset.denom_units.find((du) => du.denom === asset.display) ?.exponent || 6, + variant: "cosmos", displayName: asset.symbol, coingeckoId: asset.coingecko_id || "not-found", icon: diff --git a/packages/networks/ethereum-goerli/currencies.ts b/packages/networks/ethereum-goerli/currencies.ts index 2f1072d9d6..4f3c6b3636 100644 --- a/packages/networks/ethereum-goerli/currencies.ts +++ b/packages/networks/ethereum-goerli/currencies.ts @@ -6,6 +6,7 @@ export const ethereumGoerliCurrencies: CurrencyInfo[] = [ denom: "0x0000000000000000000000000000000000000000", // native currency: wei displayName: "GoerliETH", decimals: 18, + variant: "ethereum", coingeckoId: "ethereum", icon: "ethereum-circle.svg", kind: "native", diff --git a/packages/networks/ethereum/currencies.ts b/packages/networks/ethereum/currencies.ts index 46989a1966..be77c1116f 100644 --- a/packages/networks/ethereum/currencies.ts +++ b/packages/networks/ethereum/currencies.ts @@ -6,6 +6,7 @@ export const ethereumCurrencies: CurrencyInfo[] = [ denom: "0x0000000000000000000000000000000000000000", // native currency: wei displayName: "ETH", decimals: 18, + variant: "ethereum", coingeckoId: "ethereum", icon: "ethereum-circle.svg", kind: "native", diff --git a/packages/networks/features.ts b/packages/networks/features.ts index 7e718ba128..5be05ca8d0 100644 --- a/packages/networks/features.ts +++ b/packages/networks/features.ts @@ -13,6 +13,7 @@ export enum NetworkFeature { RiotP2E = "RiotP2E", NFTBridge = "NFTBridge", CosmWasmPremiumFeed = "CosmWasmPremiumFeed", + GnoProjectManager = "GnoProjectManager", NFTMarketplaceLeaderboard = "NFTMarketplaceLeaderboard", CosmWasmNFTsBurner = "CosmWasmNFTsBurner", } @@ -43,12 +44,26 @@ type CosmWasmSocialFeed = { feedContractAddress: string; }; +// Gno Project Manager + +const zodGnoProjectManager = z.object({ + type: z.literal(NetworkFeature.GnoProjectManager), + projectsManagerPkgPath: z.string(), + paymentsDenom: z.string(), +}); + +type GnoProjectManager = z.infer; + +// Registry + export const allFeatureObjects = [ zodCosmWasmPremiumFeed, zodCosmWasmNFTsBurner, + zodGnoProjectManager, ]; export type NetworkFeatureObject = | CosmWasmPremiumFeed | CosmWasmSocialFeed - | CosmWasmNFTsBurner; + | CosmWasmNFTsBurner + | GnoProjectManager; diff --git a/packages/networks/gno-dev/currencies.ts b/packages/networks/gno-dev/currencies.ts index baa0c8ce2e..1f1fb4bf11 100644 --- a/packages/networks/gno-dev/currencies.ts +++ b/packages/networks/gno-dev/currencies.ts @@ -6,6 +6,17 @@ export const gnoCurrencies: CurrencyInfo[] = [ denom: "ugnot", displayName: "GNOT", decimals: 6, + variant: "gno", + coingeckoId: "gno", + icon: "gno.svg", + kind: "native", + color: currencyGNOcolor, + }, + { + denom: "gno.land/r/demo/tori20", + displayName: "TORI", + decimals: 6, + variant: "grc20", coingeckoId: "gno", icon: "gno.svg", kind: "native", diff --git a/packages/networks/gno-dev/index.ts b/packages/networks/gno-dev/index.ts index 0f1b3dd3f0..3af1938c6e 100644 --- a/packages/networks/gno-dev/index.ts +++ b/packages/networks/gno-dev/index.ts @@ -10,28 +10,38 @@ export const gnoDevNetwork: GnoNetworkInfo = { NetworkFeature.Organizations, NetworkFeature.SocialFeed, NetworkFeature.UPP, + NetworkFeature.GnoProjectManager, + ], + featureObjects: [ + { + type: NetworkFeature.GnoProjectManager, + projectsManagerPkgPath: "gno.land/r/teritori/projects_manager", + paymentsDenom: "ugnot", + }, ], currencies: gnoCurrencies, stakeCurrency: "ugnot", idPrefix: "gnodev", chainId: "dev", - endpoint: "http://127.0.0.1:36657/http://127.0.0.1:26657", + endpoint: "http://127.0.0.1:26657", txExplorer: "https://gnoscan.io/transactions/details?txhash=$hash", accountExplorer: "https://gnoscan.io/accounts/$address", contractExplorer: "https://gnoscan.io/realms/details?path=$address", testnet: true, - backendEndpoint: "http://localhost:9090", + // backendEndpoint: "http://localhost:9090", + backendEndpoint: "https://dapp-backend.testnet.teritori.com", vaultContractAddress: "", - daoRegistryPkgPath: "gno.land/r/demo/teritori/dao_registry", - socialFeedsPkgPath: "gno.land/r/demo/teritori/social_feeds", - socialFeedsDAOPkgPath: "gno.land/r/demo/teritori/social_feeds_dao", + daoRegistryPkgPath: "gno.land/r/teritori/dao_registry", + socialFeedsPkgPath: "gno.land/r/teritori/social_feeds", + socialFeedsDAOPkgPath: "gno.land/r/teritori/social_feeds_dao", nameServiceContractAddress: "gno.land/r/demo/users", - modboardsPkgPath: "gno.land/r/demo/teritori/modboards", - groupsPkgPath: "gno.land/r/demo/teritori/groups", - votingGroupPkgPath: "gno.land/p/demo/teritori/dao_voting_group", - daoProposalSinglePkgPath: "gno.land/p/demo/teritori/dao_proposal_single", - daoInterfacesPkgPath: "gno.land/p/demo/teritori/dao_interfaces", - daoCorePkgPath: "gno.land/p/demo/teritori/dao_core", + modboardsPkgPath: "gno.land/r/teritori/modboards", + groupsPkgPath: "gno.land/r/teritori/groups", + votingGroupPkgPath: "gno.land/p/teritori/dao_voting_group", + daoProposalSinglePkgPath: "gno.land/p/teritori/dao_proposal_single", + + daoInterfacesPkgPath: "gno.land/p/teritori/dao_interfaces", + daoCorePkgPath: "gno.land/p/teritori/dao_core", nameServiceDefaultImage: "ipfs://bafkreignptjimiu7wuux6mk6uh4hb4odb6ff62ny4bvdokrhes7g67huse", gnowebURL: "http://127.0.0.1:8888", diff --git a/packages/networks/gno-portal/currencies.ts b/packages/networks/gno-portal/currencies.ts index baa0c8ce2e..b1beeaf715 100644 --- a/packages/networks/gno-portal/currencies.ts +++ b/packages/networks/gno-portal/currencies.ts @@ -10,5 +10,6 @@ export const gnoCurrencies: CurrencyInfo[] = [ icon: "gno.svg", kind: "native", color: currencyGNOcolor, + variant: "gno", }, ]; diff --git a/packages/networks/gno-portal/index.ts b/packages/networks/gno-portal/index.ts index bacdd1158e..ac76c7d796 100644 --- a/packages/networks/gno-portal/index.ts +++ b/packages/networks/gno-portal/index.ts @@ -26,13 +26,13 @@ export const gnoPortalNetwork: GnoNetworkInfo = { nameServiceContractAddress: "gno.land/r/demo/users", nameServiceDefaultImage: "ipfs://bafkreignptjimiu7wuux6mk6uh4hb4odb6ff62ny4bvdokrhes7g67huse", - daoRegistryPkgPath: "gno.land/r/demo/teritori/dao_registry", - socialFeedsPkgPath: "gno.land/r/demo/teritori/social_feeds", - socialFeedsDAOPkgPath: "gno.land/r/demo/teritori/social_feeds_dao", - // modboardsPkgPath: "gno.land/r/demo/teritori/modboards_v4", - groupsPkgPath: "gno.land/r/demo/teritori/groups", - votingGroupPkgPath: "gno.land/p/demo/teritori/dao_voting_group", - daoProposalSinglePkgPath: "gno.land/p/demo/teritori/dao_proposal_single", - daoInterfacesPkgPath: "gno.land/p/demo/teritori/dao_interfaces", - daoCorePkgPath: "gno.land/p/demo/teritori/dao_core", + daoRegistryPkgPath: "gno.land/r/teritori/dao_registry", + socialFeedsPkgPath: "gno.land/r/teritori/social_feeds", + socialFeedsDAOPkgPath: "gno.land/r/teritori/social_feeds_dao", + // modboardsPkgPath: "gno.land/r/teritori/modboards_v4", + groupsPkgPath: "gno.land/r/teritori/groups", + votingGroupPkgPath: "gno.land/p/teritori/dao_voting_group", + daoProposalSinglePkgPath: "gno.land/p/teritori/dao_proposal_single", + daoInterfacesPkgPath: "gno.land/p/teritori/dao_interfaces", + daoCorePkgPath: "gno.land/p/teritori/dao_core", }; diff --git a/packages/networks/gno-teritori/currencies.ts b/packages/networks/gno-teritori/currencies.ts index baa0c8ce2e..cb3c09b8b1 100644 --- a/packages/networks/gno-teritori/currencies.ts +++ b/packages/networks/gno-teritori/currencies.ts @@ -6,6 +6,7 @@ export const gnoCurrencies: CurrencyInfo[] = [ denom: "ugnot", displayName: "GNOT", decimals: 6, + variant: "gno", coingeckoId: "gno", icon: "gno.svg", kind: "native", diff --git a/packages/networks/gno-teritori/index.ts b/packages/networks/gno-teritori/index.ts index 52a0639099..65ce09d447 100644 --- a/packages/networks/gno-teritori/index.ts +++ b/packages/networks/gno-teritori/index.ts @@ -10,6 +10,14 @@ export const gnoTeritoriNetwork: GnoNetworkInfo = { NetworkFeature.Organizations, NetworkFeature.SocialFeed, NetworkFeature.UPP, + NetworkFeature.GnoProjectManager, + ], + featureObjects: [ + { + type: NetworkFeature.GnoProjectManager, + projectsManagerPkgPath: "gno.land/r/teritori/escrow", + paymentsDenom: "ugnot", + }, ], currencies: gnoCurrencies, stakeCurrency: "ugnot", @@ -25,15 +33,15 @@ export const gnoTeritoriNetwork: GnoNetworkInfo = { nameServiceContractAddress: "gno.land/r/demo/users", nameServiceDefaultImage: "ipfs://bafkreignptjimiu7wuux6mk6uh4hb4odb6ff62ny4bvdokrhes7g67huse", - daoRegistryPkgPath: "gno.land/r/demo/teritori/dao_registry_v4", - socialFeedsPkgPath: "gno.land/r/demo/teritori/social_feeds_v4", - socialFeedsDAOPkgPath: "gno.land/r/demo/teritori/social_feeds_dao_v2", - modboardsPkgPath: "gno.land/r/demo/teritori/modboards_v4", - groupsPkgPath: "gno.land/r/demo/teritori/groups_v4", - votingGroupPkgPath: "gno.land/p/demo/teritori/dao_voting_group_v2", - daoProposalSinglePkgPath: "gno.land/p/demo/teritori/dao_proposal_single_v4", - daoInterfacesPkgPath: "gno.land/p/demo/teritori/dao_interfaces_v5", - daoCorePkgPath: "gno.land/p/demo/teritori/dao_core_v4", + daoRegistryPkgPath: "gno.land/r/teritori/dao_registry_v4", + socialFeedsPkgPath: "gno.land/r/teritori/social_feeds_v4", + socialFeedsDAOPkgPath: "gno.land/r/teritori/social_feeds_dao_v2", + modboardsPkgPath: "gno.land/r/teritori/modboards_v4", + groupsPkgPath: "gno.land/r/teritori/groups_v4", + votingGroupPkgPath: "gno.land/p/teritori/dao_voting_group_v2", + daoProposalSinglePkgPath: "gno.land/p/teritori/dao_proposal_single_v4", + daoInterfacesPkgPath: "gno.land/p/teritori/dao_interfaces_v5", + daoCorePkgPath: "gno.land/p/teritori/dao_core_v4", gnowebURL: "https://testnet.gno.teritori.com", faucetURL: "https://testnet.gno.teritori.com:5050/?toaddr=$addr", }; diff --git a/packages/networks/gno-test3/currencies.ts b/packages/networks/gno-test3/currencies.ts index baa0c8ce2e..cb3c09b8b1 100644 --- a/packages/networks/gno-test3/currencies.ts +++ b/packages/networks/gno-test3/currencies.ts @@ -6,6 +6,7 @@ export const gnoCurrencies: CurrencyInfo[] = [ denom: "ugnot", displayName: "GNOT", decimals: 6, + variant: "gno", coingeckoId: "gno", icon: "gno.svg", kind: "native", diff --git a/packages/networks/gno-test4/currencies.ts b/packages/networks/gno-test4/currencies.ts index baa0c8ce2e..b1beeaf715 100644 --- a/packages/networks/gno-test4/currencies.ts +++ b/packages/networks/gno-test4/currencies.ts @@ -10,5 +10,6 @@ export const gnoCurrencies: CurrencyInfo[] = [ icon: "gno.svg", kind: "native", color: currencyGNOcolor, + variant: "gno", }, ]; diff --git a/packages/networks/osmosis-testnet/currencies.ts b/packages/networks/osmosis-testnet/currencies.ts index a303be43a1..1e42e542e6 100644 --- a/packages/networks/osmosis-testnet/currencies.ts +++ b/packages/networks/osmosis-testnet/currencies.ts @@ -6,6 +6,7 @@ export const osmosisTestnetCurrencies: CurrencyInfo[] = [ denom: "uosmo", displayName: "OSMO", decimals: 6, + variant: "cosmos", coingeckoId: "osmosis", icon: "osmosis-circle.svg", kind: "native", diff --git a/packages/networks/osmosis/currencies.ts b/packages/networks/osmosis/currencies.ts index fb7be4d49c..531b6297fa 100644 --- a/packages/networks/osmosis/currencies.ts +++ b/packages/networks/osmosis/currencies.ts @@ -6,6 +6,7 @@ export const osmosisCurrencies: CurrencyInfo[] = [ denom: "uosmo", displayName: "OSMO", decimals: 6, + variant: "cosmos", coingeckoId: "osmosis", icon: "osmosis-circle.svg", kind: "native", diff --git a/packages/networks/polygon-mumbai/currencies.ts b/packages/networks/polygon-mumbai/currencies.ts index 7fa475c69f..61eaa967e9 100644 --- a/packages/networks/polygon-mumbai/currencies.ts +++ b/packages/networks/polygon-mumbai/currencies.ts @@ -6,6 +6,7 @@ export const polygonMumbaiCurrencies: CurrencyInfo[] = [ denom: "0x0000000000000000000000000000000000000000", // native currency: wei displayName: "MATIC", decimals: 18, + variant: "ethereum", coingeckoId: "matic", icon: "polygon.svg", kind: "native", diff --git a/packages/networks/polygon/currencies.ts b/packages/networks/polygon/currencies.ts index 41e99fb676..7743389439 100644 --- a/packages/networks/polygon/currencies.ts +++ b/packages/networks/polygon/currencies.ts @@ -6,6 +6,7 @@ export const polygonCurrencies: CurrencyInfo[] = [ denom: "0x0000000000000000000000000000000000000000", // native currency: wei displayName: "MATIC", decimals: 18, + variant: "ethereum", coingeckoId: "matic", icon: "polygon.svg", kind: "native", diff --git a/packages/networks/saga-test2/index.ts b/packages/networks/saga-test2/index.ts index f3cdaf397a..3b25595f0a 100644 --- a/packages/networks/saga-test2/index.ts +++ b/packages/networks/saga-test2/index.ts @@ -15,6 +15,7 @@ export const sagaTest2: CosmosNetworkInfo = { coingeckoId: "not-found", icon: "https://raw.githubusercontent.com/cosmos/chain-registry/master/saga/images/saga.svg", color: "TODO", + variant: "cosmos", }, ], features: [], diff --git a/packages/networks/saga/index.ts b/packages/networks/saga/index.ts index 94583d3411..d17d226655 100644 --- a/packages/networks/saga/index.ts +++ b/packages/networks/saga/index.ts @@ -16,6 +16,7 @@ export const sagaNetwork: CosmosNetworkInfo = { coingeckoId: "saga-2", icon: "https://raw.githubusercontent.com/cosmos/chain-registry/master/saga/images/saga.svg", color: "TODO", + variant: "cosmos", }, ], features: [], diff --git a/packages/networks/teritori-localnet/currencies.ts b/packages/networks/teritori-localnet/currencies.ts index 3eddd9280c..ef6dba4cf0 100644 --- a/packages/networks/teritori-localnet/currencies.ts +++ b/packages/networks/teritori-localnet/currencies.ts @@ -5,6 +5,7 @@ export const teritoriLocalnetCurrencies: CurrencyInfo[] = [ { denom: "utori", displayName: "TORI", + variant: "cosmos", decimals: 6, coingeckoId: "teritori", icon: "icons/networks/teritori-circle.svg", diff --git a/packages/networks/teritori-testnet/currencies.ts b/packages/networks/teritori-testnet/currencies.ts index 3dd718088a..493fb08133 100644 --- a/packages/networks/teritori-testnet/currencies.ts +++ b/packages/networks/teritori-testnet/currencies.ts @@ -5,6 +5,7 @@ export const teritoriTestnetCurrencies: CurrencyInfo[] = [ { denom: "utori", displayName: "TORI", + variant: "cosmos", decimals: 6, coingeckoId: "teritori", icon: "teritori-circle.svg", diff --git a/packages/networks/teritori/currencies.ts b/packages/networks/teritori/currencies.ts index ce384c1635..5c1bfc44f0 100644 --- a/packages/networks/teritori/currencies.ts +++ b/packages/networks/teritori/currencies.ts @@ -5,6 +5,7 @@ export const teritoriCurrencies: CurrencyInfo[] = [ { denom: "utori", displayName: "TORI", + variant: "cosmos", decimals: 6, coingeckoId: "teritori", icon: "teritori-circle.svg", diff --git a/packages/networks/types.ts b/packages/networks/types.ts index 1481d490aa..626a7357df 100644 --- a/packages/networks/types.ts +++ b/packages/networks/types.ts @@ -127,6 +127,7 @@ export type NetworkInfo = export type NativeCurrencyInfo = { kind: "native"; + variant: "cosmos" | "ethereum" | "gno" | "grc20"; denom: string; displayName: string; decimals: number; diff --git a/packages/screens/DAppStore/components/RightRail.tsx b/packages/screens/DAppStore/components/RightRail.tsx index 0592795d34..70172fde50 100644 --- a/packages/screens/DAppStore/components/RightRail.tsx +++ b/packages/screens/DAppStore/components/RightRail.tsx @@ -7,6 +7,7 @@ import { DAppBox } from "./DAppBox"; import { BrandText } from "@/components/BrandText"; import { SVGorImageIcon } from "@/components/SVG/SVGorImageIcon"; import { GridList } from "@/components/layout/GridList"; +import { useDeveloperMode } from "@/hooks/useDeveloperMode"; import { selectAvailableApps } from "@/store/slices/dapps-store"; import { layout } from "@/utils/style/layout"; import { dAppType } from "@/utils/types/dapp-store"; @@ -14,6 +15,7 @@ import { dAppType } from "@/utils/types/dapp-store"; export const RightRail = ({ searchInput }: { searchInput: string }) => { const availableApps = useSelector(selectAvailableApps); const { width } = useWindowDimensions(); + const [developerMode] = useDeveloperMode(); const isMobile = width < 760; return ( { noFixedHeight keyExtractor={(item) => item.id} data={Object.values(element.options).filter( - (option: dAppType) => - option.title + (option: dAppType) => { + if (option.devOnly && !developerMode) { + return false; + } + return option.title .toLowerCase() - .includes(searchInput.toLowerCase()), + .includes(searchInput.toLowerCase()); + }, )} minElemWidth={300} renderItem={({ item: option }, elemWidth) => { diff --git a/packages/screens/DAppStore/query/getFromFile.ts b/packages/screens/DAppStore/query/getFromFile.ts index 7b1636137d..4896bf26cb 100644 --- a/packages/screens/DAppStore/query/getFromFile.ts +++ b/packages/screens/DAppStore/query/getFromFile.ts @@ -14,6 +14,7 @@ import multisig from "@/assets/icons/multisig.svg"; import osmosisSVG from "@/assets/icons/networks/osmosis.svg"; import teritoriSVG from "@/assets/icons/networks/teritori.svg"; import pathwar from "@/assets/icons/pathwar.svg"; +import projectsProgramSVG from "@/assets/icons/projects-program.svg"; import otherAppsIcon from "@/assets/icons/random-goods-icon.svg"; import riot from "@/assets/icons/rioters-game.svg"; import staking from "@/assets/icons/staking.svg"; @@ -192,6 +193,17 @@ export function getAvailableApps(): dAppGroup { selectedByDefault: true, alwaysOn: true, }, + projects: { + id: "projects", + title: "Projects Program", + icon: projectsProgramSVG, + description: "Projects Program", + route: "Projects", + groupKey: "top-apps", + selectedByDefault: false, + alwaysOn: false, + devOnly: true, + }, toripunks: { id: "toripunks", title: "Toripunks dApp", diff --git a/packages/screens/MarketplaceLeaderboardScreen/component/MarketplaceLeaderboardTable.tsx b/packages/screens/MarketplaceLeaderboardScreen/component/MarketplaceLeaderboardTable.tsx index 39be10ff22..5361050e1e 100644 --- a/packages/screens/MarketplaceLeaderboardScreen/component/MarketplaceLeaderboardTable.tsx +++ b/packages/screens/MarketplaceLeaderboardScreen/component/MarketplaceLeaderboardTable.tsx @@ -5,7 +5,6 @@ import { FlatList, View } from "react-native"; import { screenContentMaxWidthLarge } from "../../../utils/style/layout"; import { LeaderboardEntry } from "@/api/marketplace/v1/marketplace"; -import { UserNameInline } from "@/components/UserNameInline"; import { SpacerColumn } from "@/components/spacer"; import { TableCell } from "@/components/table/TableCell"; import { TableHeader } from "@/components/table/TableHeader"; @@ -13,6 +12,7 @@ import { TableRow } from "@/components/table/TableRow"; import { TableTextCell } from "@/components/table/TableTextCell"; import { TableWrapper } from "@/components/table/TableWrapper"; import { TableColumns } from "@/components/table/utils"; +import { UsernameWithAvatar } from "@/components/user/UsernameWithAvatar"; import { getMarketplaceClient } from "@/utils/backend"; const columns: TableColumns = { @@ -125,7 +125,7 @@ const MarketplaceLeaderboardTableRow: React.FC<{ flex: columns.userId.flex, }} > - + { { label: ( - + ninja.tori diff --git a/packages/screens/Projects/CompleteMilestoneScreen.tsx b/packages/screens/Projects/CompleteMilestoneScreen.tsx new file mode 100644 index 0000000000..fa0259fda9 --- /dev/null +++ b/packages/screens/Projects/CompleteMilestoneScreen.tsx @@ -0,0 +1,263 @@ +import React, { useState } from "react"; +import { View } from "react-native"; +import { SvgProps } from "react-native-svg"; + +import { HeaderBackButton } from "./components/HeaderBackButton"; +import { MilestoneStatusTag } from "./components/MilestoneStatusTag"; +import { useProject } from "./hooks/useProjects"; +import { Project, ProjectMilestone } from "./types"; +import githubSVG from "../../../assets/icons/github.svg"; +import FlexRow from "../../components/FlexRow"; +import useSelectedWallet from "../../hooks/useSelectedWallet"; + +import { BrandText } from "@/components/BrandText"; +import { ScreenContainer } from "@/components/ScreenContainer"; +import { TertiaryBox } from "@/components/boxes/TertiaryBox"; +import { PrimaryButton } from "@/components/buttons/PrimaryButton"; +import { PrimaryButtonOutline } from "@/components/buttons/PrimaryButtonOutline"; +import { SocialButton } from "@/components/buttons/SocialButton"; +import { RoundedGradientImage } from "@/components/images/RoundedGradientImage"; +import { TextInputCustom } from "@/components/inputs/TextInputCustom"; +import { Separator } from "@/components/separators/Separator"; +import { SpacerColumn, SpacerRow } from "@/components/spacer"; +import { useSelectedNetworkId } from "@/hooks/useSelectedNetwork"; +import { useEscrowContract } from "@/screens/Projects/hooks/useEscrowContract"; +import { prettyPrice } from "@/utils/coins"; +import { ScreenFC, useAppNavigation } from "@/utils/navigation"; +import { + neutral17, + neutral77, + neutralA3, + neutralFF, + primaryColor, + redDefault, +} from "@/utils/style/colors"; +import { + fontSemibold13, + fontSemibold14, + fontSemibold16, + fontSemibold20, + fontSemibold28, +} from "@/utils/style/fonts"; +import { layout } from "@/utils/style/layout"; + +const CustomSocialButton: React.FC<{ + text: string; + iconSvg: React.FC; +}> = ({ text, iconSvg }) => { + return ( + + ); +}; + +export const ProjectsCompleteMilestoneScreen: ScreenFC< + "ProjectsCompleteMilestone" +> = ({ route: { params } }) => { + const navigation = useAppNavigation(); + + const networkId = useSelectedNetworkId(); + const { projectId, milestoneId } = params; + const [isProcessing, setIsProcessing] = useState(false); + const selectedWallet = useSelectedWallet(); + + const { data: project } = useProject(projectId); + const milestone = (project?.milestones || []).find( + (_, idx) => idx === +milestoneId, + ); + + const [report, setReport] = useState(""); + + const { execEscrowMethod } = useEscrowContract( + networkId, + selectedWallet?.address, + ); + + const completeMilestone = async ( + project: Project, + milestone: ProjectMilestone, + ) => { + setIsProcessing(true); + + const isOk = await execEscrowMethod("CompleteMilestoneAndPay", [ + project?.id?.toString(), + milestone.id.toString(), + ]); + + setIsProcessing(true); + + if (isOk) { + navigation.navigate("ProjectsDetail", { id: projectId }); + } + }; + + if (!milestone || !project) return null; + + return ( + }> + + + + + + + Project + + + + {project.metadata?.shortDescData?.name} + + + + + + + + {/* Left Col ==========================================================*/} + + + + + Milestone: {milestone.title} + + + + + + {milestone.desc} + + + + + + + + Report input: + + + + + setReport(text)} + label="" + name="name" + placeholder="Enter details here..." + hideLabel + multiline + noBrokenCorners + containerStyle={{ width: "100%" }} + textInputStyle={{ height: 80 }} + /> + + + + + + + + + + {/* Right Col =========================================================*/} + + + + Budget + + + {prettyPrice(networkId, milestone.amount, project.paymentDenom)} + + + + + + + Status + + + + + + + + + Contractor: + + + + @{project?.contractor} + + + + + + + + + + + + + completeMilestone(project, milestone)} + fullWidth + disabled={isProcessing} + text="Complete the Milestone" + /> + + + + + + ); +}; diff --git a/packages/screens/Projects/ProjectsConflictSolvingScreen/NewConflictSection.tsx b/packages/screens/Projects/ProjectsConflictSolvingScreen/NewConflictSection.tsx new file mode 100644 index 0000000000..a886671863 --- /dev/null +++ b/packages/screens/Projects/ProjectsConflictSolvingScreen/NewConflictSection.tsx @@ -0,0 +1,82 @@ +import React, { FC, useState } from "react"; + +import { BrandText } from "@/components/BrandText"; +import { TertiaryBox } from "@/components/boxes/TertiaryBox"; +import { PrimaryButtonOutline } from "@/components/buttons/PrimaryButtonOutline"; +import { TextInputCustom } from "@/components/inputs/TextInputCustom"; +import { SpacerColumn } from "@/components/spacer"; +import { parseUserId } from "@/networks"; +import { useEscrowContract } from "@/screens/Projects/hooks/useEscrowContract"; +import { neutral17, neutralFF, redDefault } from "@/utils/style/colors"; +import { fontSemibold28 } from "@/utils/style/fonts"; +import { layout } from "@/utils/style/layout"; + +export const NewConflictSection: FC<{ + projectId: string | undefined; + userId: string | undefined; +}> = ({ projectId, userId }) => { + const [initialMessage, setInitialMessage] = useState(""); + const [network, userAddress] = parseUserId(userId); + + const { execEscrowMethod } = useEscrowContract(network?.id, userAddress); + + return ( + <> + + New conflict + + + + Initial message + + + + + setInitialMessage(text)} + label="" + name="initialMessage" + placeholder="Enter details here..." + hideLabel + multiline + noBrokenCorners + containerStyle={{ width: "100%" }} + textInputStyle={{ height: 80 }} + /> + + + + { + const [network, userAddress] = parseUserId(userId); + if (!network || !userAddress) { + throw new Error("Invalid user id"); + } + if (!projectId) { + throw new Error("Invalid project id"); + } + + await execEscrowMethod("RequestConflictResolution", [ + projectId, + initialMessage, + ]); + }} + /> + + + ); +}; diff --git a/packages/screens/Projects/ProjectsConflictSolvingScreen/OngoingConflictSection.tsx b/packages/screens/Projects/ProjectsConflictSolvingScreen/OngoingConflictSection.tsx new file mode 100644 index 0000000000..f2df44a926 --- /dev/null +++ b/packages/screens/Projects/ProjectsConflictSolvingScreen/OngoingConflictSection.tsx @@ -0,0 +1,298 @@ +import { Picker } from "@react-native-picker/picker"; +import moment from "moment/moment"; +import React, { FC, useState } from "react"; +import { View } from "react-native"; + +import { BrandText } from "@/components/BrandText"; +import { TertiaryBox } from "@/components/boxes/TertiaryBox"; +import { PrimaryButtonOutline } from "@/components/buttons/PrimaryButtonOutline"; +import { TextInputCustom } from "@/components/inputs/TextInputCustom"; +import { SpacerColumn } from "@/components/spacer"; +import { UsernameWithAvatar } from "@/components/user/UsernameWithAvatar"; +import { getUserId, parseUserId } from "@/networks"; +import { + PartyRole, + UserRole, +} from "@/screens/Projects/ProjectsConflictSolvingScreen/types"; +import { useEscrowContract } from "@/screens/Projects/hooks/useEscrowContract"; +import { useProject } from "@/screens/Projects/hooks/useProjects"; +import { + errorColor, + neutral17, + redDefault, + yellowDefault, +} from "@/utils/style/colors"; +import { fontSemibold28 } from "@/utils/style/fonts"; +import { layout } from "@/utils/style/layout"; + +export const OngoingConflictSection: FC<{ + userId: string | undefined; + projectId: string | undefined; +}> = ({ userId, projectId }) => { + const [network, userAddress] = parseUserId(userId); + const [outcome, setOutcome] = useState(1); + const [responseMessage, setResponseMessage] = useState(""); + const [resolutionMessage, setResolutionMessage] = useState(""); + const { data: project } = useProject(projectId); + const conflicts = project?.conflicts; + const lastConflict = conflicts?.length + ? conflicts[conflicts.length - 1] + : null; + + const { execEscrowMethod } = useEscrowContract(network?.id, userAddress); + + let responderAddress; + if (lastConflict?.initiator === project?.contractor) { + responderAddress = project?.funder; + } else { + responderAddress = project?.contractor; + } + + let userRole: UserRole; + if (lastConflict?.initiator === userAddress) { + userRole = "initiator"; + } else if (responderAddress === userAddress) { + userRole = "responder"; + } else if (project?.conflictHandler === userAddress) { + userRole = "resolver"; + } else { + userRole = "observer"; + } + + let initiatorRole: PartyRole; + if (lastConflict?.initiator === project?.contractor) { + initiatorRole = "contractor"; + } else { + initiatorRole = "funder"; + } + let responderRole: PartyRole; + if (responderAddress === project?.contractor) { + responderRole = "contractor"; + } else { + responderRole = "funder"; + } + + return ( + + + Ongoing conflict + + + + + Initial message by {initiatorRole} on{" "} + {moment(lastConflict?.createdAt).format("MMM D, YYYY")} + + + + + + + {(userRole === "responder" || !!lastConflict?.respondedAt) && ( + <> + + + + Response by {responderRole} on{" "} + {moment(lastConflict?.respondedAt).format("MMM D, YYYY")} + + + + + + {userRole === "responder" && !lastConflict?.respondedAt && ( + <> + + { + if (!projectId) { + throw new Error("Invalid project id"); + } + if (!network || !userAddress) { + throw new Error("Invalid user id"); + } + + await execEscrowMethod("RespondToConflict", [ + projectId, + responseMessage, + ]); + }} + /> + + )} + + )} + + {(!!lastConflict?.resolvedAt || userRole === "resolver") && + !lastConflict?.respondedAt && ( + <> + + + + No response from {responderRole} after{" "} + {moment(lastConflict?.createdAt).fromNow(true)} + + + + + )} + + {userRole !== "resolver" && !lastConflict?.resolvedAt && ( + <> + + + Waiting for{!lastConflict?.respondedAt ? " response or " : " "} + resolution for {moment(lastConflict?.createdAt).fromNow(true)}... + + + )} + + {(userRole === "resolver" || !!lastConflict?.resolvedAt) && ( + <> + + + Verdict + + + + + {userRole === "resolver" && !lastConflict?.resolvedAt && ( + <> + + + + { + if (!projectId) { + throw new Error("Invalid project id"); + } + if (!network || !userAddress) { + throw new Error("Invalid user id"); + } + + await execEscrowMethod("ResolveConflict", [ + projectId, + outcome.toString(), + resolutionMessage, + ]); + }} + /> + + )} + + )} + + + ); +}; + +const OutcomeSelect: FC<{ + value: number; + onChange: (value: number) => void; +}> = ({ value, onChange }) => { + return ( + selectedValue={value} onValueChange={onChange}> + + + + + ); +}; diff --git a/packages/screens/Projects/ProjectsConflictSolvingScreen/SettledConflictsSection.tsx b/packages/screens/Projects/ProjectsConflictSolvingScreen/SettledConflictsSection.tsx new file mode 100644 index 0000000000..9970e8939c --- /dev/null +++ b/packages/screens/Projects/ProjectsConflictSolvingScreen/SettledConflictsSection.tsx @@ -0,0 +1,204 @@ +import moment from "moment/moment"; +import React, { FC } from "react"; +import { View } from "react-native"; + +import { BrandText } from "@/components/BrandText"; +import { TertiaryBox } from "@/components/boxes/TertiaryBox"; +import { TextInputCustom } from "@/components/inputs/TextInputCustom"; +import { SpacerColumn } from "@/components/spacer"; +import { UsernameWithAvatar } from "@/components/user/UsernameWithAvatar"; +import { getUserId, parseNetworkObjectId } from "@/networks"; +import { PartyRole } from "@/screens/Projects/ProjectsConflictSolvingScreen/types"; +import { useProject } from "@/screens/Projects/hooks/useProjects"; +import { errorColor, neutral17 } from "@/utils/style/colors"; +import { fontSemibold28 } from "@/utils/style/fonts"; +import { layout } from "@/utils/style/layout"; + +export const SettledConflictsSection: FC<{ + projectId: string | undefined; +}> = ({ projectId }) => { + const [network] = parseNetworkObjectId(projectId); + const networkId = network?.id; + const { data: project } = useProject(projectId); + return ( + <> + Settled conflicts + {[...(project?.conflicts || [])] + .reverse() + .filter((c) => !!c.outcome) + .map((conflict, index) => { + let responderAddress; + if (conflict.initiator === project?.contractor) { + responderAddress = project?.funder; + } else { + responderAddress = project?.contractor; + } + + let initiatorRole: PartyRole; + if (conflict.initiator === project?.contractor) { + initiatorRole = "contractor"; + } else { + initiatorRole = "funder"; + } + let responderRole: PartyRole; + if (responderAddress === project?.contractor) { + responderRole = "contractor"; + } else { + responderRole = "funder"; + } + + let outcomeColor, outcomeText; + switch (conflict.outcome) { + case "RESUME_CONTRACT": + outcomeColor = "white"; + outcomeText = "Project resumed"; + break; + case "REFUND_FUNDER": + outcomeColor = errorColor; + outcomeText = "Funder reimbursed"; + break; + case "PAY_CONTRACTOR": + outcomeColor = errorColor; + outcomeText = "Contractor paid"; + break; + default: + outcomeColor = errorColor; + outcomeText = "Unknown outcome"; + break; + } + + return ( + <> + + + + + Initial message by {initiatorRole} on{" "} + {moment(conflict.createdAt).format("MMM D, YYYY")} + + + + + + + + + {conflict.respondedAt ? ( + <> + + + Response by {responderRole} on{" "} + {moment(conflict.respondedAt).format("MMM D, YYYY")} + + + + + + + ) : ( + <> + + + No response from {responderRole} after{" "} + {moment(conflict.createdAt).fromNow(true)} + + + + + )} + + + + + Verdict on{" "} + {moment(conflict.resolvedAt).format("MMM D, YYYY")} + + + + + + + + {outcomeText} + + + + ); + })} + + ); +}; diff --git a/packages/screens/Projects/ProjectsConflictSolvingScreen/index.tsx b/packages/screens/Projects/ProjectsConflictSolvingScreen/index.tsx new file mode 100644 index 0000000000..a66158d4e7 --- /dev/null +++ b/packages/screens/Projects/ProjectsConflictSolvingScreen/index.tsx @@ -0,0 +1,45 @@ +import React from "react"; + +import { useProject } from "../hooks/useProjects"; + +import { ScreenContainer } from "@/components/ScreenContainer"; +import { SpacerColumn } from "@/components/spacer"; +import useSelectedWallet from "@/hooks/useSelectedWallet"; +import { NewConflictSection } from "@/screens/Projects/ProjectsConflictSolvingScreen/NewConflictSection"; +import { OngoingConflictSection } from "@/screens/Projects/ProjectsConflictSolvingScreen/OngoingConflictSection"; +import { SettledConflictsSection } from "@/screens/Projects/ProjectsConflictSolvingScreen/SettledConflictsSection"; +import { ScreenFC } from "@/utils/navigation"; + +export const ProjectsConflictSolvingScreen: ScreenFC< + "ProjectsConflictSolving" +> = ({ route }) => { + const projectId = route.params.projectId; + const selectedWallet = useSelectedWallet(); + const userId = selectedWallet?.userId; + const userAddress = selectedWallet?.address; + const { data: project } = useProject(projectId); + const userIsParty = + !!project && + !!userAddress && + (userAddress === project?.contractor || userAddress === project?.funder); + return ( + + + {project?.status === "ACCEPTED" && userIsParty && ( + + )} + + {project?.status === "CONFLICT" && ( + + )} + + {(project?.conflicts?.length || 0) > 0 && + !( + project?.conflicts?.length === 1 && project.status === "CONFLICT" + ) && } + + ); +}; diff --git a/packages/screens/Projects/ProjectsConflictSolvingScreen/types.ts b/packages/screens/Projects/ProjectsConflictSolvingScreen/types.ts new file mode 100644 index 0000000000..01443b2a37 --- /dev/null +++ b/packages/screens/Projects/ProjectsConflictSolvingScreen/types.ts @@ -0,0 +1,2 @@ +export type UserRole = "initiator" | "responder" | "resolver" | "observer"; +export type PartyRole = "contractor" | "funder"; diff --git a/packages/screens/Projects/ProjectsDetailScreen/MilestoneDetail.tsx b/packages/screens/Projects/ProjectsDetailScreen/MilestoneDetail.tsx new file mode 100644 index 0000000000..ee076dca20 --- /dev/null +++ b/packages/screens/Projects/ProjectsDetailScreen/MilestoneDetail.tsx @@ -0,0 +1,222 @@ +import { Link } from "@react-navigation/native"; +import { useQueryClient } from "@tanstack/react-query"; +import React, { useState } from "react"; +import { TouchableOpacity, View } from "react-native"; + +import chevronRightSVG from "@/assets/icons/chevron-right.svg"; +import closeSVG from "@/assets/icons/close.svg"; +import githubSVG from "@/assets/icons/github.svg"; +import { BrandText } from "@/components/BrandText"; +import FlexRow from "@/components/FlexRow"; +import { SVG } from "@/components/SVG"; +import { TertiaryBox } from "@/components/boxes/TertiaryBox"; +import { PrimaryButton } from "@/components/buttons/PrimaryButton"; +import { SelectInput, SelectInputItem } from "@/components/inputs/SelectInput"; +import { Separator } from "@/components/separators/Separator"; +import { SpacerColumn } from "@/components/spacer"; +import { useSelectedNetworkId } from "@/hooks/useSelectedNetwork"; +import useSelectedWallet from "@/hooks/useSelectedWallet"; +import { getNetworkObjectId } from "@/networks"; +import { MilestonePriorityTag } from "@/screens/Projects/components/MilestonePriorityTag"; +import { MilestoneStatusTag } from "@/screens/Projects/components/MilestoneStatusTag"; +import { useEscrowContract } from "@/screens/Projects/hooks/useEscrowContract"; +import { + MilestoneStatus, + Project, + ProjectMilestone, + zodMilestoneStatus, +} from "@/screens/Projects/types"; +import { + neutral00, + neutral22, + neutral33, + neutralA3, +} from "@/utils/style/colors"; +import { + fontSemibold13, + fontSemibold14, + fontSemibold20, +} from "@/utils/style/fonts"; +import { layout } from "@/utils/style/layout"; +import { objectKeys } from "@/utils/typescript"; + +const STATUSES: SelectInputItem[] = [ + { label: "Open", value: "MS_OPEN" }, + { label: "In Progress", value: "MS_PROGRESS" }, + { label: "Review", value: "MS_REVIEW" }, + { label: "Completed", value: "MS_COMPLETED" }, +]; + +export const MilestoneDetail: React.FC<{ + project: Project; + milestone: ProjectMilestone; + editable?: boolean; + onClose?: (milestone: ProjectMilestone) => void; +}> = ({ project, editable, milestone, onClose }) => { + const [newStatus, setNewStatus] = useState(milestone.status); + const networkId = useSelectedNetworkId(); + const selectedWallet = useSelectedWallet(); + + const { execEscrowMethod } = useEscrowContract( + networkId, + selectedWallet?.address, + ); + const [isProcessing, setIsProcessing] = useState(false); + const queryClient = useQueryClient(); + + const changeMilestoneStatus = async ( + project: Project, + milestone: ProjectMilestone, + ) => { + setIsProcessing(true); + try { + // Convert milestone status => status id + let statusId = 1; + for (const msStatus of objectKeys(zodMilestoneStatus.enum)) { + if (msStatus === newStatus) { + break; + } + statusId++; + } + + const refetch = () => + Promise.all([ + queryClient.invalidateQueries(["projects", networkId]), + queryClient.invalidateQueries([ + "project", + getNetworkObjectId(networkId, project.id), + ]), + ]); + + if (newStatus === "MS_COMPLETED") { + await execEscrowMethod("CompleteMilestoneAndPay", [ + project.id.toString(), + milestone.id.toString(), + ]); + await refetch(); + return; + } + + await execEscrowMethod("ChangeMilestoneStatus", [ + project.id.toString(), + milestone.id.toString(), + statusId.toString(), + ]); + await refetch(); + } finally { + setIsProcessing(false); + } + }; + + return ( + + onClose?.(milestone)}> + + + + {milestone.title} + + + + + + Status + + + + + + + + + + Priority + + + + + + + + Description + + + + + {milestone.desc} + + + + + + + + + Github link + + + + + + + {editable && ( + + + Change status + + + s.value === newStatus) || STATUSES[0] + } + selectItem={(item) => setNewStatus(item.value as MilestoneStatus)} + boxStyle={{ height: 32 }} + testID="milestone-select-new-status" + /> + + + + changeMilestoneStatus(project, milestone)} + fullWidth + size="SM" + /> + + )} + + ); +}; diff --git a/packages/screens/Projects/ProjectsDetailScreen/index.tsx b/packages/screens/Projects/ProjectsDetailScreen/index.tsx new file mode 100644 index 0000000000..715accdfb2 --- /dev/null +++ b/packages/screens/Projects/ProjectsDetailScreen/index.tsx @@ -0,0 +1,74 @@ +import React, { useState } from "react"; +import { View } from "react-native"; + +import { HeaderBackButton } from "../components/HeaderBackButton"; +import { ProjectInfo } from "../components/ProjectInfo"; +import { ProjectMilestones } from "../components/ProjectMilestones"; +import { useProject } from "../hooks/useProjects"; + +import { ScreenContainer } from "@/components/ScreenContainer"; +import useSelectedWallet from "@/hooks/useSelectedWallet"; +import { MilestoneDetail } from "@/screens/Projects/ProjectsDetailScreen/MilestoneDetail"; +import { ScreenFC } from "@/utils/navigation"; + +export const ProjectsDetailScreen: ScreenFC<"ProjectsDetail"> = ({ + route: { params }, +}) => { + const selectedWallet = useSelectedWallet(); + + const [selectedMilestoneId, setSelectedMilestoneId] = useState( + null, + ); + + const { data: project } = useProject(params.id); + + const selectedMilestone = project?.milestones.find( + (m) => m.id === selectedMilestoneId, + ); + + const onSelectMilestone = (id: string) => { + setSelectedMilestoneId(id); + }; + + if (!project) + return ( + } + /> + ); + + return ( + } + footerChildren={<>} + > + + + + + + + {/* Detail view ======================================================= */} + {selectedMilestone !== undefined && ( + setSelectedMilestoneId(null)} + editable={ + (project.contractor === selectedWallet?.address && + selectedMilestone.status === "MS_OPEN") || + (project.funder === selectedWallet?.address && + selectedMilestone.status === "MS_REVIEW") + } + /> + )} + + ); +}; diff --git a/packages/screens/Projects/ProjectsMakeRequestScreen/ConfirmAndSign.tsx b/packages/screens/Projects/ProjectsMakeRequestScreen/ConfirmAndSign.tsx new file mode 100644 index 0000000000..103be207f9 --- /dev/null +++ b/packages/screens/Projects/ProjectsMakeRequestScreen/ConfirmAndSign.tsx @@ -0,0 +1,338 @@ +import { useQueryClient } from "@tanstack/react-query"; +import React, { useMemo, useState } from "react"; +import { Image, View } from "react-native"; + +import gnoSVG from "../../../../assets/icons/networks/gno.svg"; +import projectSuccessPaymentPNG from "../../../../assets/project-success-payment.png"; +import ModalBase from "../../../components/modals/ModalBase"; +import useSelectedWallet from "../../../hooks/useSelectedWallet"; +import { Tag } from "../components/Milestone"; +import { useMakeRequestState } from "../hooks/useMakeRequestHook"; +import { + MilestoneRequest, + ProjectShortDescData, + ProjectTeamAndLinkData, +} from "../types"; + +import { BrandText } from "@/components/BrandText"; +import FlexRow from "@/components/FlexRow"; +import { SVG } from "@/components/SVG"; +import { TertiaryBox } from "@/components/boxes/TertiaryBox"; +import { PrimaryButton } from "@/components/buttons/PrimaryButton"; +import { SecondaryButton } from "@/components/buttons/SecondaryButton"; +import { SecondaryButtonOutline } from "@/components/buttons/SecondaryButtonOutline"; +import { SpacerColumn, SpacerRow } from "@/components/spacer"; +import { useFeedbacks } from "@/context/FeedbacksProvider"; +import { useBalances } from "@/hooks/useBalances"; +import { + useSelectedNetworkId, + useSelectedNetworkInfo, +} from "@/hooks/useSelectedNetwork"; +import { NetworkFeature, getNetworkFeature } from "@/networks"; +import { useEscrowContract } from "@/screens/Projects/hooks/useEscrowContract"; +import { prettyPrice } from "@/utils/coins"; +import { useAppNavigation } from "@/utils/navigation"; +import { + neutral00, + neutral17, + neutral33, + neutral77, + neutralFF, +} from "@/utils/style/colors"; +import { + fontSemibold12, + fontSemibold13, + fontSemibold14, + fontSemibold16, +} from "@/utils/style/fonts"; +import { layout } from "@/utils/style/layout"; +import { tinyAddress } from "@/utils/text"; + +export const ConfirmAndSign: React.FC = () => { + const [isShowModal, setIsShowModal] = useState(false); + const [isShowConfirmModal, setIsShowConfirmModal] = useState(true); + const [isProcessing, setIsProcessing] = useState(false); + + const navigation = useAppNavigation(); + const { + projectFormData, + milestones, + teamAndLinkData: teamAndLinkFormData, + } = useMakeRequestState(); + const networkId = useSelectedNetworkId(); + + const pmFeature = getNetworkFeature( + networkId, + NetworkFeature.GnoProjectManager, + ); + + const selectedWallet = useSelectedWallet(); + const selectedNetwork = useSelectedNetworkInfo(); + const { balances } = useBalances( + selectedNetwork?.id, + selectedWallet?.address, + ); + const bal = balances?.find((b) => b.denom === pmFeature?.paymentsDenom); + + const { setToast } = useFeedbacks(); + + const { execEscrowMethod } = useEscrowContract( + networkId, + selectedWallet?.address, + ); + + const queryClient = useQueryClient(); + + const cancel = async () => { + setIsShowConfirmModal(false); + navigation.replace("Projects", { network: networkId }); + }; + + const confirmAndSign = async () => { + try { + setIsProcessing(true); + + if (!projectFormData.coverImg) { + setIsShowConfirmModal(false); + throw Error("Cover image file is required"); + } + + if (!pmFeature) { + throw Error("Project manager feature not found"); + } + + const coverImg = projectFormData.coverImg; + + // other party can't accept contract after duration expired + const expiryDuration = 24 * 60 * 60; // 1 day in seconds + + const shortDescData: ProjectShortDescData = { + name: projectFormData.name, + desc: projectFormData.description, + coverImg, + tags: projectFormData.tags || "", + }; + + const teamAndLinkData: ProjectTeamAndLinkData = { + websiteLink: teamAndLinkFormData.websiteLink, + twitterProfile: teamAndLinkFormData.twitterProfile, + discordLink: teamAndLinkFormData.discordLink, + githubLink: teamAndLinkFormData.githubLink, + teamDesc: teamAndLinkFormData.teamDesc, + }; + + const metadata = JSON.stringify({ + shortDescData, + teamAndLinkData, + }); + + const conflictHandler = projectFormData.arbitratorAddress; + + let send = ""; + // If creator = funder then we need to send all needed fund + if (projectFormData.creatorKind === "funder") { + send = totalFunding + pmFeature.paymentsDenom; + } + + const contractor = + projectFormData.creatorKind === "contractor" + ? projectFormData.creatorAddress + : ""; + const funder = + projectFormData.creatorKind === "funder" + ? projectFormData.creatorAddress + : ""; + + const args = [ + contractor, + funder, + pmFeature.paymentsDenom, + metadata, + expiryDuration.toString(), + JSON.stringify( + milestones.map((ms) => { + const req: MilestoneRequest = { + title: ms.title, + desc: ms.desc, + duration: ms.duration.toString(), + amount: ms.amount.toString(), + link: ms.link || "", + priority: ms.priority, + }; + return req; + }), + ), + conflictHandler, + ]; + console.log("executing contract creation", args); + + await execEscrowMethod("CreateContractJSON", args, send, 10_000_000); + + await queryClient.invalidateQueries(["projects"]); + + setIsShowConfirmModal(false); + setIsShowModal(true); + } catch (e) { + let msg = ""; + if (e instanceof Error) { + msg = e.message; + } else { + msg = `${e}`; + } + setIsShowConfirmModal(false); + setToast({ + title: "Error", + message: msg, + type: "error", + mode: "normal", + }); + throw e; + } finally { + setIsProcessing(false); + } + }; + + const totalFunding = useMemo(() => { + return milestones.reduce((total, m) => total + +m.amount, 0).toString(); + }, [milestones]); + + return ( + + + + You’re making the signature to validate a transaction + + + + + + + + + + + + {selectedNetwork?.displayName} + + + + {tinyAddress(selectedWallet?.address, 16)} + + + + {selectedWallet?.address && } + + + + + + + Funding + + + + {prettyPrice(networkId, totalFunding, pmFeature?.paymentsDenom)} + + + + + + Balance + + + + {prettyPrice(networkId, bal?.amount, pmFeature?.paymentsDenom)} + + + + + + + + + + + + + + + setIsShowModal(false)} + label="Successful payment" + visible={isShowModal} + width={480} + > + + + + + You have successfully created Project: {projectFormData?.name} + + + + { + setIsShowModal(false); + navigation.navigate("Projects", { network: networkId }); + }} + /> + + + + + + ); +}; diff --git a/packages/screens/Projects/ProjectsMakeRequestScreen/Footer.tsx b/packages/screens/Projects/ProjectsMakeRequestScreen/Footer.tsx new file mode 100644 index 0000000000..da53e6ceed --- /dev/null +++ b/packages/screens/Projects/ProjectsMakeRequestScreen/Footer.tsx @@ -0,0 +1,49 @@ +import React from "react"; +import { View } from "react-native"; + +import FlexRow from "../../../components/FlexRow"; +import { PrimaryButton } from "../../../components/buttons/PrimaryButton"; +import { SecondaryButton } from "../../../components/buttons/SecondaryButton"; +import { Separator } from "../../../components/separators/Separator"; +import { layout } from "../../../utils/style/layout"; +import { useMakeRequestState } from "../hooks/useMakeRequestHook"; + +const DEFAULT_WIDTH = 120; + +export const MakeRequestFooter: React.FC<{ + onSubmit: () => void; + disableNext: boolean; + nextText?: string; + backText?: string; + width?: number; +}> = (props) => { + const { + actions: { goPrevStep }, + } = useMakeRequestState(); + + return ( + + + + + + + + + ); +}; diff --git a/packages/screens/Projects/ProjectsMakeRequestScreen/Milestones.tsx b/packages/screens/Projects/ProjectsMakeRequestScreen/Milestones.tsx new file mode 100644 index 0000000000..abfb82a4de --- /dev/null +++ b/packages/screens/Projects/ProjectsMakeRequestScreen/Milestones.tsx @@ -0,0 +1,42 @@ +import React from "react"; +import { View } from "react-native"; + +import { MakeRequestFooter } from "./Footer"; +import { neutral17 } from "../../../utils/style/colors"; +import { layout } from "../../../utils/style/layout"; +import { MilestoneBoard } from "../components/MilestoneBoard"; +import { useMakeRequestState } from "../hooks/useMakeRequestHook"; +import { previewMilestoneForm } from "../types"; + +export const Milestones: React.FC = () => { + const { + milestones, + projectFormData: shortDescData, + actions: { goNextStep, setShortDesc }, + } = useMakeRequestState(); + + const goToReview = () => { + setShortDesc(shortDescData); + + goNextStep(); + }; + + return ( + + + + + + ); +}; diff --git a/packages/screens/Projects/ProjectsMakeRequestScreen/Preview.tsx b/packages/screens/Projects/ProjectsMakeRequestScreen/Preview.tsx new file mode 100644 index 0000000000..5d42837f47 --- /dev/null +++ b/packages/screens/Projects/ProjectsMakeRequestScreen/Preview.tsx @@ -0,0 +1,68 @@ +import React from "react"; +import { View } from "react-native"; + +import { MakeRequestFooter } from "./Footer"; +import { ProjectInfo } from "../components/ProjectInfo"; +import { ProjectMilestones } from "../components/ProjectMilestones"; +import { useMakeRequestState } from "../hooks/useMakeRequestHook"; +import { Project, previewMilestoneForm } from "../types"; + +import useSelectedWallet from "@/hooks/useSelectedWallet"; + +export const Preview: React.FC = () => { + const { + projectFormData, + milestones, + teamAndLinkData, + actions: { goNextStep }, + } = useMakeRequestState(); + + const selectedWallet = useSelectedWallet(); + + // Create project object just like when it returned from server + const project: Project = { + sender: selectedWallet?.address || "", + metadata: { + shortDescData: { + ...projectFormData, + coverImg: projectFormData.coverImg, + tags: projectFormData.tags || "", + }, + teamAndLinkData, + }, + budget: "", + funder: selectedWallet?.address || "", + contractor: "", + status: "CREATED", + id: "", + funded: false, + milestones: milestones.map(previewMilestoneForm), + contractorCandidates: [], + paymentDenom: "", + expireAt: new Date(), + funderFeedback: "", + contractorFeedback: "", + pausedBy: "", + conflictHandler: "", + handlerCandidate: "", + handlerSuggestor: "", + createdAt: new Date(), + rejectReason: "", + conflicts: [], + }; + + return ( + + + + + + + + ); +}; diff --git a/packages/screens/Projects/ProjectsMakeRequestScreen/ShortPresentation.tsx b/packages/screens/Projects/ProjectsMakeRequestScreen/ShortPresentation.tsx new file mode 100644 index 0000000000..ca8bdc18a6 --- /dev/null +++ b/packages/screens/Projects/ProjectsMakeRequestScreen/ShortPresentation.tsx @@ -0,0 +1,248 @@ +import { zodResolver } from "@hookform/resolvers/zod"; +import React, { useEffect, useState } from "react"; +import { useForm } from "react-hook-form"; +import { View } from "react-native"; + +import { MakeRequestFooter } from "./Footer"; +import addSVG from "../../../../assets/icons/add.svg"; +import { BrandText } from "../../../components/BrandText"; +import { PrimaryButtonOutline } from "../../../components/buttons/PrimaryButtonOutline"; +import { FileUploader } from "../../../components/fileUploader"; +import { RoundedGradientImage } from "../../../components/images/RoundedGradientImage"; +import { TextInputCustom } from "../../../components/inputs/TextInputCustom"; +import { SpacerColumn } from "../../../components/spacer"; +import { useNameSearch } from "../../../hooks/search/useNameSearch"; +import { useSelectedNetworkId } from "../../../hooks/useSelectedNetwork"; +import useSelectedWallet from "../../../hooks/useSelectedWallet"; +import { IMAGE_MIME_TYPES } from "../../../utils/mime"; +import { errorColor, neutral77, neutralA3 } from "../../../utils/style/colors"; +import { fontSemibold14, fontSemibold20 } from "../../../utils/style/fonts"; +import { TNSResult } from "../components/TNSResult"; +import { + useMakeRequestState, + zodProjectFormData, +} from "../hooks/useMakeRequestHook"; + +import { LoaderFullScreen } from "@/components/loaders/LoaderFullScreen"; +import { useIpfs } from "@/hooks/useIpfs"; +import { ButtonsGroup } from "@/screens/Projects/components/ButtonsGroup"; + +export const ShortPresentation: React.FC = () => { + const { + actions: { goNextStep, setShortDesc }, + projectFormData: shortDescData, + } = useMakeRequestState(); + const selectedWallet = useSelectedWallet(); + const caller = selectedWallet?.address; + const selectedNetworkId = useSelectedNetworkId(); + const [searchTNSText, setSearchTNSText] = useState(""); + const [isTNSVisible, setIsTNSVisible] = useState(false); + const { handleSubmit, formState, setValue, watch, setError } = useForm({ + resolver: zodResolver(zodProjectFormData), + defaultValues: shortDescData, + }); + const { errors } = formState; + const values = watch(); + const { uploadToIPFS } = useIpfs(); + const [isUploadingCover, setIsUploadingCover] = useState(false); + useEffect(() => { + if (!caller) { + // TODO: would be better to not allow this corner case, aka do something smarter when no wallet is connected + return; + } + setValue("creatorAddress", caller); + }, [setValue, caller]); + + const { names } = useNameSearch({ + networkId: selectedNetworkId, + input: searchTNSText, + limit: 12, + }); + + if (!caller) { + return null; + } + + return ( + + + + Grant details + + + + + Information about your Grant + + + + + + + I'm * + + + + + { + if (selectedId === 0) { + setValue("creatorKind", "contractor"); + } else { + setValue("creatorKind", "funder"); + } + }} + /> + + + + + + { + setSearchTNSText(text); + setIsTNSVisible(true); + setValue("targetAddress", text); + }} + value={values.targetAddress} + error={errors.targetAddress?.message} + /> + + 0} + networkId={selectedNetworkId} + names={names} + onSelected={(name) => { + setIsTNSVisible(false); + setValue("targetAddress", name); + }} + /> + + + + + setValue("name", val)} + value={values.name} + error={errors.name?.message} + /> + + + + setValue("description", val)} + value={values.description} + error={errors.description?.message} + /> + + + + setValue("arbitratorAddress", val)} + value={values.arbitratorAddress} + /> + + + + + Cover Image * + + + + + { + setIsUploadingCover(true); + try { + if (files[0].fileType !== "image") { + setError("coverImg", { message: "file is not an image" }); + return; + } + const web3URI = await uploadToIPFS(selectedWallet.userId, files[0]); + setValue("coverImg", web3URI); + } finally { + setIsUploadingCover(false); + } + }} + mimeTypes={IMAGE_MIME_TYPES} + > + {({ onPress }) => ( + + )} + + + + + {!!errors.coverImg && ( + + {errors.coverImg.message} + + )} + + + {!!values.coverImg && ( + + )} + + + + + setValue("tags", val)} + value={values.tags || ""} + error={errors.tags?.message} + /> + + { + setShortDesc(submitValues); + goNextStep(); + })} + /> + + ); +}; diff --git a/packages/screens/Projects/ProjectsMakeRequestScreen/TeamAndLinks.tsx b/packages/screens/Projects/ProjectsMakeRequestScreen/TeamAndLinks.tsx new file mode 100644 index 0000000000..70813838fe --- /dev/null +++ b/packages/screens/Projects/ProjectsMakeRequestScreen/TeamAndLinks.tsx @@ -0,0 +1,159 @@ +import { zodResolver } from "@hookform/resolvers/zod"; +import React from "react"; +import { useForm } from "react-hook-form"; +import { View } from "react-native"; + +import { MakeRequestFooter } from "./Footer"; +import { BrandText } from "../../../components/BrandText"; +import { TextInputCustom } from "../../../components/inputs/TextInputCustom"; +import { Separator } from "../../../components/separators/Separator"; +import { SpacerColumn } from "../../../components/spacer"; +import { neutral55, neutral77, neutralA3 } from "../../../utils/style/colors"; +import { + fontSemibold13, + fontSemibold14, + fontSemibold20, +} from "../../../utils/style/fonts"; +import { layout } from "../../../utils/style/layout"; +import { + useMakeRequestState, + zodProjectTeamAndLinkFormData, +} from "../hooks/useMakeRequestHook"; + +export const TeamAndLinks: React.FC = () => { + const { + actions: { goNextStep, setTeamAndLink }, + teamAndLinkData, + } = useMakeRequestState(); + + const { handleSubmit, formState, setValue, watch } = useForm({ + resolver: zodResolver(zodProjectTeamAndLinkFormData), + defaultValues: teamAndLinkData, + }); + + const { errors } = formState; + const values = watch(); + + const submit = handleSubmit((values) => { + setTeamAndLink(values); + goNextStep(); + }); + + return ( + + Links + + + + + Your Grant useful links + + + + + setValue("websiteLink", val)} + value={values.websiteLink} + error={errors.websiteLink?.message} + /> + + + + setValue("twitterProfile", val)} + value={values.twitterProfile} + error={errors.twitterProfile?.message} + /> + + + + setValue("discordLink", val)} + value={values.discordLink} + error={errors.discordLink?.message} + /> + + + + setValue("githubLink", val)} + value={values.githubLink} + error={errors.githubLink?.message} + /> + + + + Links + + + + + Your Grant useful links + + + + + + Describe your team: * + + + + 1. How many core members are you? ( Working on the project daily ) + + + 2. Past accomplishments or projects? + + + 3. Please add all relevant links for all your members. + + + + + setValue("teamDesc", val)} + value={values.teamDesc} + error={errors.teamDesc?.message} + /> + + + + + Team links and attachments + + + + + ); +}; diff --git a/packages/screens/Projects/ProjectsMakeRequestScreen/index.tsx b/packages/screens/Projects/ProjectsMakeRequestScreen/index.tsx new file mode 100644 index 0000000000..9df7b905c8 --- /dev/null +++ b/packages/screens/Projects/ProjectsMakeRequestScreen/index.tsx @@ -0,0 +1,45 @@ +import React from "react"; +import { View } from "react-native"; + +import { ConfirmAndSign } from "./ConfirmAndSign"; +import { Milestones } from "./Milestones"; +import { Preview } from "./Preview"; +import { ShortPresentation } from "./ShortPresentation"; +import { TeamAndLinks } from "./TeamAndLinks"; +import { ScreenContainer } from "../../../components/ScreenContainer"; +import { SpacerColumn } from "../../../components/spacer"; +import { NetworkKind } from "../../../networks"; +import { ScreenFC } from "../../../utils/navigation"; +import { Breadcrumb } from "../components/Breadcrumb"; +import { HeaderBackButton } from "../components/HeaderBackButton"; +import { useMakeRequestState } from "../hooks/useMakeRequestHook"; + +const renderStep = (stepIndice: number) => { + if (stepIndice === 1) return ; + if (stepIndice === 2) return ; + if (stepIndice === 3) return ; + if (stepIndice === 4) return ; + if (stepIndice === 5) return ; +}; + +export const ProjectsMakeRequestScreen: ScreenFC< + "ProjectsMakeRequest" +> = () => { + const { stepIndice } = useMakeRequestState(); + + return ( + } + > + + + + + {/* Main view============================================================ */} + {renderStep(stepIndice)} + + ); +}; diff --git a/packages/screens/Projects/ProjectsManagerScreen/ContractorCandidates.tsx b/packages/screens/Projects/ProjectsManagerScreen/ContractorCandidates.tsx new file mode 100644 index 0000000000..9bdbea2edc --- /dev/null +++ b/packages/screens/Projects/ProjectsManagerScreen/ContractorCandidates.tsx @@ -0,0 +1,177 @@ +import { useQueryClient } from "@tanstack/react-query"; +import React, { useState } from "react"; +import { TouchableOpacity, View } from "react-native"; + +import FlexRow from "../../../components/FlexRow"; +import useSelectedWallet from "../../../hooks/useSelectedWallet"; +import { ProjectStatusTag } from "../components/ProjectStatusTag"; +import { useProjects } from "../hooks/useProjects"; +import { Project } from "../types"; + +import { BrandText } from "@/components/BrandText"; +import { PrimaryButton } from "@/components/buttons/PrimaryButton"; +import { RoundedGradientImage } from "@/components/images/RoundedGradientImage"; +import { TableCell } from "@/components/table/TableCell"; +import { TableHeader } from "@/components/table/TableHeader"; +import { UsernameWithAvatar } from "@/components/user/UsernameWithAvatar"; +import { + getNetworkObjectId, + getUserId, + parseNetworkObjectId, +} from "@/networks"; +import { useEscrowContract } from "@/screens/Projects/hooks/useEscrowContract"; +import { useAppNavigation } from "@/utils/navigation"; +import { neutral33, neutralFF } from "@/utils/style/colors"; +import { fontSemibold13 } from "@/utils/style/fonts"; +import { layout } from "@/utils/style/layout"; + +export const ContractorCandidates: React.FC<{ networkId: string }> = ({ + networkId, +}) => { + const selectedWallet = useSelectedWallet(); + + const { projects } = useProjects(networkId, { + byCandidatesForFunder: { funder: selectedWallet?.address || "" }, + }); + + return ( + + + {projects.map((project) => ( + + ))} + + ); +}; + +const TABLE_COLS = { + name: { + label: "Project name", + flex: 3, + }, + status: { + label: "Status", + flex: 1, + }, + candidates: { + label: "Candidates", + flex: 3, + }, +}; + +const ProjectRow: React.FC<{ networkId: string; project: Project }> = ({ + networkId, + project, +}) => { + const navigation = useAppNavigation(); + + if (!project.contractorCandidates.length) return null; + + return ( + + {/* === Name === */} + + + + { + if (!project.id) { + return; + } + navigation.navigate("ProjectsDetail", { id: project.id }); + }} + > + + {project.metadata?.shortDescData?.name} + + + + + {/* === Status === */} + + + + + + + {[ + project.contractorCandidates, + // project.contractorCandidates, + // project.contractorCandidates, + ] + .flatMap((c) => c) + .map((c, idx) => ( + + ))} + + + + ); +}; + +type CandidateProps = { + projectId: string; + candidate: string; +}; + +const Candidate: React.FC = ({ projectId, candidate }) => { + const [network, localProjectId] = parseNetworkObjectId(projectId); + const networkId = network?.id; + + const selectedWallet = useSelectedWallet(); + + const [isProcessing, setIsProcessing] = useState(false); + + const queryClient = useQueryClient(); + + const { execEscrowMethod } = useEscrowContract( + networkId, + selectedWallet?.address, + ); + + const acceptCandidate = async () => { + setIsProcessing(true); + await execEscrowMethod("AcceptContractor", [localProjectId, candidate]); + await Promise.all([ + queryClient.invalidateQueries(["project", projectId]), + queryClient.invalidateQueries(["projects", networkId]), + ]); + setIsProcessing(false); + }; + + return ( + + + acceptCandidate()} + /> + + ); +}; diff --git a/packages/screens/Projects/ProjectsManagerScreen/MilestonesUpdateManager.tsx b/packages/screens/Projects/ProjectsManagerScreen/MilestonesUpdateManager.tsx new file mode 100644 index 0000000000..1e3cc1d9c7 --- /dev/null +++ b/packages/screens/Projects/ProjectsManagerScreen/MilestonesUpdateManager.tsx @@ -0,0 +1,181 @@ +import React from "react"; +import { View } from "react-native"; +import { TouchableOpacity } from "react-native-gesture-handler"; + +import githubSVG from "../../../../assets/icons/github.svg"; +import FlexRow from "../../../components/FlexRow"; +import useSelectedWallet from "../../../hooks/useSelectedWallet"; +import { MilestonePriorityTag } from "../components/MilestonePriorityTag"; +import { MilestoneStatusTag } from "../components/MilestoneStatusTag"; +import { useProjects } from "../hooks/useProjects"; +import { ProjectMilestone } from "../types"; + +import { BrandText } from "@/components/BrandText"; +import { Link } from "@/components/Link"; +import { TertiaryBox } from "@/components/boxes/TertiaryBox"; +import { SocialButton } from "@/components/buttons/SocialButton"; +import { Separator } from "@/components/separators/Separator"; +import { useSelectedNetworkId } from "@/hooks/useSelectedNetwork"; +import { getNetworkObjectId } from "@/networks"; +import { useAppNavigation } from "@/utils/navigation"; +import { + neutral00, + neutral17, + neutral77, + neutralA3, + neutralFF, +} from "@/utils/style/colors"; +import { + fontSemibold13, + fontSemibold14, + fontSemibold16, +} from "@/utils/style/fonts"; +import { layout } from "@/utils/style/layout"; + +export const MilestonesUpdateManager: React.FC = () => { + const navigation = useAppNavigation(); + const networkId = useSelectedNetworkId(); + const selectedWallet = useSelectedWallet(); + + // TODO: Support to default limit projects for now, make this more dynamic latter + const { projects, isLoading } = useProjects(networkId, { + byFunder: { funder: selectedWallet?.address || "" }, + }); + + if (isLoading || !selectedWallet?.address) return null; + + return ( + <> + {projects.map((project) => + (project.milestones || []) + .filter((m) => m.status === "MS_REVIEW") + .map((milestone: ProjectMilestone, milestoneIdx: number) => { + return ( + <> + + Project: {project.metadata?.shortDescData?.name} + + + + + + {project.metadata?.shortDescData?.name} + + + + {milestone.title} + + + + + + + + Builder: @{project.contractor} + + + + Funder: @{project.funder} + + + + + + + + Status + + + + + + + + + + Priority + + + + + + + + + + + + { + if (!project.id) return; + navigation.navigate("ProjectsCompleteMilestone", { + projectId: getNetworkObjectId(networkId, project.id), + milestoneId: milestone.id, + }); + }} + > + + Approve + + + + + + ); + }), + )} + + ); +}; diff --git a/packages/screens/Projects/ProjectsManagerScreen/MyProjectsManager.tsx b/packages/screens/Projects/ProjectsManagerScreen/MyProjectsManager.tsx new file mode 100644 index 0000000000..512c1a0eb3 --- /dev/null +++ b/packages/screens/Projects/ProjectsManagerScreen/MyProjectsManager.tsx @@ -0,0 +1,190 @@ +import moment from "moment"; +import React, { useMemo, useState } from "react"; +import { TouchableOpacity, View } from "react-native"; + +import useSelectedWallet from "../../../hooks/useSelectedWallet"; +import { ProjectStatusTag } from "../components/ProjectStatusTag"; +import { ProjectsStatusFilterButtons } from "../components/ProjectsStatusFilterButtons"; +import { ProjectFilter, useProjects } from "../hooks/useProjects"; +import { ContractStatusFilter, Project } from "../types"; +import { getProjectStats } from "../utils"; + +import { BrandText } from "@/components/BrandText"; +import { ProgressLine } from "@/components/ProgressLine"; +import { RoundedGradientImage } from "@/components/images/RoundedGradientImage"; +import { SpacerColumn } from "@/components/spacer"; +import { TableCell } from "@/components/table/TableCell"; +import { TableHeader } from "@/components/table/TableHeader"; +import { TableRow } from "@/components/table/TableRow"; +import { UsernameWithAvatar } from "@/components/user/UsernameWithAvatar"; +import { useSelectedNetworkId } from "@/hooks/useSelectedNetwork"; +import { getNetworkObjectId, getUserId } from "@/networks"; +import { prettyPrice } from "@/utils/coins"; +import { useAppNavigation } from "@/utils/navigation"; +import { neutralFF } from "@/utils/style/colors"; +import { fontSemibold13 } from "@/utils/style/fonts"; +import { layout } from "@/utils/style/layout"; + +export const MyProjectsManager: React.FC<{ + type: ProjectType; +}> = ({ type }) => { + const networkId = useSelectedNetworkId(); + const selectedWallet = useSelectedWallet(); + + let filter: ProjectFilter; + switch (type) { + case "myInvestments": { + filter = { byFunder: { funder: selectedWallet?.address || "" } }; + break; + } + case "myProjects": { + filter = { byContractor: { contractor: selectedWallet?.address || "" } }; + } + } + const { projects } = useProjects(networkId, filter); + + const [statusFilter, setStatusFilter] = useState("ALL"); + + const filteredProjects = useMemo(() => { + if (!selectedWallet?.address) return []; + + return projects.filter( + (p) => statusFilter === "ALL" || p.status === statusFilter, + ); + }, [projects, statusFilter, selectedWallet?.address]); + + return ( + + + + + + + {filteredProjects.map((project) => ( + + ))} + + ); +}; + +const getTableCols = (projectType: ProjectType) => { + return { + name: { + label: "Project name", + flex: 2.5, + }, + status: { + label: "Status", + flex: 1, + }, + manager: { + label: projectType === "myProjects" ? "Funder" : "Contractor", + flex: 2.5, + }, + milestones: { + label: "Milestones", + flex: 2, + }, + grant: { + label: "Grant", + flex: 2, + }, + creationDate: { + label: "Creation date", + flex: 1, + }, + }; +}; + +const defaultCols = getTableCols("myProjects"); + +type ProjectType = "myInvestments" | "myProjects"; + +const ProjectRow: React.FC<{ project: Project; projectType: ProjectType }> = ({ + project, + projectType, +}) => { + const stats = getProjectStats(project); + const navigation = useAppNavigation(); + const networkId = useSelectedNetworkId(); + + return ( + + {/* === Name === */} + + + + { + if (!project.id) { + return; + } + navigation.navigate("ProjectsDetail", { + id: getNetworkObjectId(networkId, project.id), + }); + }} + > + + {project.metadata?.shortDescData?.name} + + + + + {/* === Status === */} + + + + + {/* === Manager === */} + + {projectType === "myProjects" && ( + + )} + {projectType === "myInvestments" && ( + + )} + + + {/* === Milestones === */} + + + {stats.completed}/{stats.total} + + + + + {/* === Grant === */} + + + {prettyPrice(networkId, project.budget, project.paymentDenom)} + + + + {/* === Creation date === */} + + + {moment(project.createdAt).format("L")} + + + + ); +}; diff --git a/packages/screens/Projects/ProjectsManagerScreen/Requests.tsx b/packages/screens/Projects/ProjectsManagerScreen/Requests.tsx new file mode 100644 index 0000000000..4ad1cdb183 --- /dev/null +++ b/packages/screens/Projects/ProjectsManagerScreen/Requests.tsx @@ -0,0 +1,342 @@ +import { Link } from "@react-navigation/native"; +import React, { useState } from "react"; +import { View } from "react-native"; + +import githubSVG from "../../../../assets/icons/github.svg"; +import FlexRow from "../../../components/FlexRow"; +import ModalBase from "../../../components/modals/ModalBase"; +import useSelectedWallet from "../../../hooks/useSelectedWallet"; +import { ProjectStatusTag } from "../components/ProjectStatusTag"; +import { ProjectFilter, useProjects } from "../hooks/useProjects"; +import { Project } from "../types"; + +import { BrandText } from "@/components/BrandText"; +import { TertiaryBox } from "@/components/boxes/TertiaryBox"; +import { PrimaryButton } from "@/components/buttons/PrimaryButton"; +import { PrimaryButtonOutline } from "@/components/buttons/PrimaryButtonOutline"; +import { SocialButton } from "@/components/buttons/SocialButton"; +import { TextInputCustom } from "@/components/inputs/TextInputCustom"; +import { Separator } from "@/components/separators/Separator"; +import { UsernameWithAvatar } from "@/components/user/UsernameWithAvatar"; +import { useSelectedNetworkId } from "@/hooks/useSelectedNetwork"; +import { getUserId } from "@/networks"; +import { useEscrowContract } from "@/screens/Projects/hooks/useEscrowContract"; +import { useUtils } from "@/screens/Projects/hooks/useUtils"; +import { prettyPrice } from "@/utils/coins"; +import { useAppNavigation } from "@/utils/navigation"; +import { + neutral17, + neutralA3, + primaryColor, + redDefault, +} from "@/utils/style/colors"; +import { fontSemibold13, fontSemibold14 } from "@/utils/style/fonts"; +import { layout } from "@/utils/style/layout"; + +type RequestType = "requestsByBuilders" | "requestsByInvestors"; + +const Spacing = () => { + return ( + + ); +}; + +const RequestItem: React.FC<{ + project: Project & { contractorCandidate?: string }; + networkId: string; + walletAddress: string; + requestType: RequestType; +}> = ({ project, networkId, walletAddress, requestType }) => { + const navigation = useAppNavigation(); + + const [isProcessing, setIsProcessing] = useState(false); + const [isShowModal, setIsShowModal] = useState(false); + const [rejectReason, setRejectReason] = useState(""); + const { mustGetValue } = useUtils(); + + const { execEscrowMethod } = useEscrowContract(networkId, walletAddress); + + const githubLink = project.metadata?.teamAndLinkData?.githubLink; + + const gotoProjectDetail = (project: Project) => { + if (!project.id) { + return; + } + navigation.navigate("ProjectsDetail", { id: project.id }); + }; + + const acceptContractor = async () => { + setIsProcessing(true); + + const candidate = mustGetValue( + project.contractorCandidate, + "contractor candidate", + ); + + await execEscrowMethod("AcceptContractor", [ + project?.id?.toString(), + candidate, + ]); + + setIsProcessing(false); + }; + + const acceptContract = async (project: Project) => { + setIsProcessing(true); + await execEscrowMethod("AcceptContract", [project?.id?.toString()]); + setIsProcessing(false); + }; + + const rejectContract = async (project: Project, rejectReason: string) => { + setIsProcessing(true); + await execEscrowMethod("RejectContract", [ + project?.id?.toString(), + rejectReason, + ]); + setIsProcessing(false); + }; + + return ( + <> + + + + gotoProjectDetail(project)} + style={fontSemibold14} + > + {project.metadata?.shortDescData?.name} + + + gotoProjectDetail(project)} + style={[fontSemibold14, { color: neutralA3 }]} + > + {project.metadata?.shortDescData?.desc} + + + + + + + + Grant + + + + {prettyPrice(networkId, project.budget, project.paymentDenom)} + + + + + + + {requestType === "requestsByBuilders" && ( + + )} + {requestType === "requestsByInvestors" && ( + + Investor{" "} + + )} + + + {requestType === "requestsByBuilders" && project.contractor} + {requestType === "requestsByInvestors" && project.funder} + + + + + + + + Milestones + + + + {project.milestones.length} + + + + + + + + + + {githubLink && ( + <> + + + + + + + + + )} + + + {project.status === "CREATED" && ( + <> + setIsShowModal(true)} + /> + + acceptContract(project) + } + /> + + )} + + {project.status === "REJECTED" && ( + + {project.rejectReason} + + )} + + + + + setIsShowModal(false)} + label="Reason for rejection" + visible={isShowModal} + width={480} + > + + + rejectContract(project, rejectReason)} + /> + + + ); +}; + +export const Requests: React.FC<{ + type: RequestType; +}> = ({ type }) => { + const networkId = useSelectedNetworkId(); + const selectedWallet = useSelectedWallet(); + + // FIXME: add new filters + + let filter: ProjectFilter; + switch (type) { + case "requestsByBuilders": { + filter = { byFunder: { funder: selectedWallet?.address || "" } }; + break; + } + case "requestsByInvestors": { + filter = { byContractor: { contractor: selectedWallet?.address || "" } }; + } + } + + const { projects } = useProjects(networkId, filter); + + if (!selectedWallet?.address) { + return null; + } + + let adjustedProjects: (Project & { contractorCandidate?: string })[] = + type === "requestsByBuilders" + ? projects.filter((p) => p.sender === p.funder) + : projects.filter((p) => p.sender === p.contractor); + + if (type === "requestsByBuilders") { + // expand by contractor + adjustedProjects = adjustedProjects.reduce( + (acc, p) => { + if (!p.contractorCandidates) { + return acc; + } + const newProjects = p.contractorCandidates.map((c) => ({ + ...p, + contractorCandidate: c, + })); + return [...acc, ...newProjects]; + }, + [] as (Project & { contractorCandidate?: string })[], + ); + } + + return ( + <> + {adjustedProjects.map((project) => { + return ( + + ); + })} + + ); +}; diff --git a/packages/screens/Projects/ProjectsManagerScreen/index.tsx b/packages/screens/Projects/ProjectsManagerScreen/index.tsx new file mode 100644 index 0000000000..7b85067699 --- /dev/null +++ b/packages/screens/Projects/ProjectsManagerScreen/index.tsx @@ -0,0 +1,99 @@ +import React, { useMemo } from "react"; +import { View } from "react-native"; + +import { MilestonesUpdateManager } from "./MilestonesUpdateManager"; +import { MyProjectsManager } from "./MyProjectsManager"; +import { Requests } from "./Requests"; +import { TabOption, ViewKey } from "./types"; +import { HeaderBackButton } from "../components/HeaderBackButton"; + +import { BrandText } from "@/components/BrandText"; +import { FlexRow } from "@/components/FlexRow"; +import { ScreenContainer } from "@/components/ScreenContainer"; +import { Tabs } from "@/components/tabs/Tabs"; +import { useSelectedNetworkId } from "@/hooks/useSelectedNetwork"; +import { NetworkKind } from "@/networks"; +import { ContractorCandidates } from "@/screens/Projects/ProjectsManagerScreen/ContractorCandidates"; +import { ScreenFC, useAppNavigation } from "@/utils/navigation"; +import { neutral33 } from "@/utils/style/colors"; +import { fontSemibold14, fontSemibold28 } from "@/utils/style/fonts"; +import { layout } from "@/utils/style/layout"; +import { arrayIncludes, objectKeys } from "@/utils/typescript"; + +export const ProjectsManagerScreen: ScreenFC<"ProjectsManager"> = ({ + route: { params }, +}) => { + const networkId = useSelectedNetworkId(); + const navigation = useAppNavigation(); + const viewFromParams = params.view; + + const { tabOptions, managerTypes } = useMemo(() => { + const tabOptions: TabOption = { + myInvestments: { + name: "My investments", + component: , + }, + myProjects: { + name: "My projects", + component: , + }, + milestonesUpdates: { + name: "Reviews", + component: , + }, + requestsByBuilders: { + name: "Contractor candidates", + component: , + }, + requestsByInvestors: { + name: "Requests by investors", + component: , + }, + }; + return { tabOptions, managerTypes: objectKeys(tabOptions) }; + }, [networkId]); + + const view: ViewKey = useMemo(() => { + return arrayIncludes(managerTypes, viewFromParams) + ? viewFromParams + : "myInvestments"; + }, [managerTypes, viewFromParams]); + + return ( + } + > + + {tabOptions[view].name} + + + navigation.navigate("ProjectsManager", { view: tab }) + } + tabTextStyle={fontSemibold14} + /> + + + + {tabOptions[view].component} + + + ); +}; diff --git a/packages/screens/Projects/ProjectsManagerScreen/types.ts b/packages/screens/Projects/ProjectsManagerScreen/types.ts new file mode 100644 index 0000000000..07496ffb40 --- /dev/null +++ b/packages/screens/Projects/ProjectsManagerScreen/types.ts @@ -0,0 +1,17 @@ +import React from "react"; + +export type ViewKey = + | "myInvestments" + | "myProjects" + | "milestonesUpdates" + | "requestsByBuilders" + | "requestsByInvestors"; + +type ViewData = { + name: string; + component: React.ReactNode; +}; + +export type TabOption = { + [key in ViewKey]: ViewData; +}; diff --git a/packages/screens/Projects/ProjectsPaymentScreen.tsx b/packages/screens/Projects/ProjectsPaymentScreen.tsx new file mode 100644 index 0000000000..6d73bffff8 --- /dev/null +++ b/packages/screens/Projects/ProjectsPaymentScreen.tsx @@ -0,0 +1,248 @@ +import moment from "moment"; +import React, { useState } from "react"; +import { View } from "react-native"; +import { SvgProps } from "react-native-svg"; + +import { HeaderBackButton } from "./components/HeaderBackButton"; +import { Tag } from "./components/Milestone"; +import { useProject } from "./hooks/useProjects"; +import discordSVG from "../../../assets/icons/discord.svg"; +import githubSVG from "../../../assets/icons/github.svg"; +import twitterSVG from "../../../assets/icons/twitter.svg"; +import websiteSVG from "../../../assets/icons/website.svg"; +import { BrandText } from "../../components/BrandText"; +import FlexRow from "../../components/FlexRow"; +import { ScreenContainer } from "../../components/ScreenContainer"; +import { TertiaryBox } from "../../components/boxes/TertiaryBox"; +import { PrimaryButton } from "../../components/buttons/PrimaryButton"; +import { PrimaryButtonOutline } from "../../components/buttons/PrimaryButtonOutline"; +import { SocialButton } from "../../components/buttons/SocialButton"; +import { RoundedGradientImage } from "../../components/images/RoundedGradientImage"; +import { TextInputCustom } from "../../components/inputs/TextInputCustom"; +import { Separator } from "../../components/separators/Separator"; +import { SpacerColumn, SpacerRow } from "../../components/spacer"; +import { ScreenFC } from "../../utils/navigation"; +import { + neutral17, + neutral77, + neutralA3, + neutralFF, + primaryColor, + redDefault, +} from "../../utils/style/colors"; +import { + fontSemibold13, + fontSemibold14, + fontSemibold20, + fontSemibold28, +} from "../../utils/style/fonts"; +import { layout } from "../../utils/style/layout"; + +const CustomSocialButton: React.FC<{ + text: string; + iconSvg: React.FC; +}> = ({ text, iconSvg }) => { + return ( + + ); +}; + +export const ProjectsPaymentScreen: ScreenFC<"ProjectsPayment"> = ({ + route: { params }, +}) => { + const { projectId, milestoneId } = params; + + const { data: project } = useProject(projectId); + const milestone = (project?.milestones || []).find( + (_, idx) => idx === +milestoneId, + ); + + const [report, setReport] = useState(""); + + if (!milestone) return null; + + return ( + }> + + + + {milestone.title} + + + + + + {/* Left Col ==========================================================*/} + + + + {milestone.title} + + + + + + {project?.metadata?.shortDescData?.desc} + + + + + + + + + Tags: + + + {project?.metadata?.shortDescData?.tags?.split(",").map((tag) => { + return ( + + ); + })} + + + + + + + + + + + + Report input: + + + + + setReport(text)} + label="" + name="name" + placeholder="Enter details here..." + hideLabel + multiline + noBrokenCorners + containerStyle={{ width: "100%" }} + textInputStyle={{ height: 80 }} + /> + + + + + + + + + + {/* Right Col =========================================================*/} + + + + Grant + + + $50K + + + + + + + Status + + + + + + + + + Created by: + + + + @0x17dfsdvgsd98fsbsd9b8sd + + + + + + + + + + + + + + + + + + + + + + + ); +}; diff --git a/packages/screens/Projects/ProjectsScreen.tsx b/packages/screens/Projects/ProjectsScreen.tsx new file mode 100644 index 0000000000..a7ee5af32b --- /dev/null +++ b/packages/screens/Projects/ProjectsScreen.tsx @@ -0,0 +1,104 @@ +import React, { useState } from "react"; +import { View } from "react-native"; + +import { ProjectBox } from "./components/ProjectBox"; +import { ProjectsStatusFilterButtons } from "./components/ProjectsStatusFilterButtons"; +import { useProjects } from "./hooks/useProjects"; +import { ContractStatusFilter } from "./types"; +import { BrandText } from "../../components/BrandText"; +import { FlexRow } from "../../components/FlexRow"; +import { ScreenContainer } from "../../components/ScreenContainer"; +import { SimpleButton } from "../../components/buttons/SimpleButton"; +import { Separator } from "../../components/separators/Separator"; +import { SpacerColumn, SpacerRow } from "../../components/spacer"; +import { useSelectedNetworkId } from "../../hooks/useSelectedNetwork"; +import { NetworkKind, getNetwork } from "../../networks"; +import { ScreenFC, useAppNavigation } from "../../utils/navigation"; +import { primaryColor, secondaryColor } from "../../utils/style/colors"; +import { fontSemibold20, fontSemibold28 } from "../../utils/style/fonts"; +import { layout } from "../../utils/style/layout"; + +import { GridList } from "@/components/layout/GridList"; +import { useForceNetworkSelection } from "@/hooks/useForceNetworkSelection"; +import { joinElements } from "@/utils/react"; + +export const ProjectsScreen: ScreenFC<"Projects"> = ({ route: { params } }) => { + const network = params?.network; + useForceNetworkSelection(network); + const networkId = useSelectedNetworkId(); + const inputNetwork = getNetwork(network); + const { projects, fetchNextPage } = useProjects(networkId); + + const navigation = useAppNavigation(); + + const gotoProjectsManager = () => { + navigation.navigate("ProjectsManager", { view: "myInvestments" }); + }; + + const gotoCreateGrant = () => { + navigation.navigate("ProjectsMakeRequest", { step: 1 }); + }; + + const [statusFilter, setStatusFilter] = useState("ALL"); + + const topRightElems = [ + , + , + ]; + + return ( + } + headerChildren={Projects} + > + + + + Projects + + {joinElements(topRightElems, )} + + + + + + + } + ListFooterComponent={} + data={projects} + keyExtractor={(project) => project.id} + minElemWidth={400} + onEndReached={() => fetchNextPage()} + renderItem={({ item: project }, elemWidth) => { + return ( + + ); + }} + /> + + ); +}; diff --git a/packages/screens/Projects/components/Breadcrumb.tsx b/packages/screens/Projects/components/Breadcrumb.tsx new file mode 100644 index 0000000000..bb6e7ec02b --- /dev/null +++ b/packages/screens/Projects/components/Breadcrumb.tsx @@ -0,0 +1,132 @@ +import React, { Fragment } from "react"; +import { StyleProp, ViewStyle } from "react-native"; + +import { BrandText } from "../../../components/BrandText"; +import FlexRow from "../../../components/FlexRow"; +import { TertiaryBox } from "../../../components/boxes/TertiaryBox"; +import { + neutral00, + neutral17, + neutral22, + neutral77, + neutralFF, + primaryColor, +} from "../../../utils/style/colors"; +import { fontSemibold14, fontSemibold16 } from "../../../utils/style/fonts"; +import { layout } from "../../../utils/style/layout"; +import { useMakeRequestState } from "../hooks/useMakeRequestHook"; + +const Step: React.FC<{ + indice: number; + text: string; + active?: boolean; + disabled?: boolean; + onPress: (step: number) => void; +}> = ({ indice, text, active, disabled, onPress }) => { + return ( + + onPress(indice)} + style={[ + fontSemibold14, + { + color: disabled ? neutral77 : neutral00, + backgroundColor: active + ? primaryColor + : disabled + ? neutral22 + : neutralFF, + borderRadius: 100, + width: 32, + height: 32, + justifyContent: "center", + alignItems: "center", + display: "flex", + marginRight: layout.spacing_x2, + }, + ]} + > + {indice} + + + onPress(indice)} + numberOfLines={1} + style={[ + fontSemibold14, + { + color: active ? primaryColor : disabled ? neutral77 : neutralFF, + }, + ]} + > + {text} + + + ); +}; + +const Seperator = () => { + return ( + + {">"} + + ); +}; + +const STEPS = [ + "Short presentation", + "Team and links", + "Milestones", + "Preview", + "Confirm and Sign", +]; + +export const Breadcrumb: React.FC<{ + stepIndice?: number; + containerStyle?: StyleProp; +}> = ({ stepIndice = 1, containerStyle }) => { + const { + stepIndice: currentStepIndice, + actions: { gotoStep }, + } = useMakeRequestState(); + + // We can only goto passed steps + const gotoValidStep = (targetStepIndice: number) => { + if (targetStepIndice <= currentStepIndice) { + gotoStep(targetStepIndice); + } + }; + + return ( + + + {STEPS.map((step, idx) => { + return ( + + + {idx + 1 < STEPS.length && } + + ); + })} + + + ); +}; diff --git a/packages/screens/Projects/components/ButtonsGroup.tsx b/packages/screens/Projects/components/ButtonsGroup.tsx new file mode 100644 index 0000000000..2e5243f040 --- /dev/null +++ b/packages/screens/Projects/components/ButtonsGroup.tsx @@ -0,0 +1,58 @@ +import React from "react"; +import { View } from "react-native"; + +import { SimpleButton } from "@/components/buttons/SimpleButton"; +import { + neutral00, + neutral33, + primaryColor, + secondaryColor, +} from "@/utils/style/colors"; +import { layout } from "@/utils/style/layout"; + +type ButtonsGroupType = { + texts: string[]; + selectedId: number; + onChange?: (selectedId: number) => void; + size?: "XS" | "SM" | "M" | "XL"; +}; + +export const ButtonsGroup: React.FC = ({ + texts, + selectedId, + onChange, + size = "M", +}) => { + return ( + + {texts.map((text, btnId) => { + return ( + onChange?.(btnId)} + /> + ); + })} + + ); +}; diff --git a/packages/screens/Projects/components/FundProjectModal.tsx b/packages/screens/Projects/components/FundProjectModal.tsx new file mode 100644 index 0000000000..b83eddfd28 --- /dev/null +++ b/packages/screens/Projects/components/FundProjectModal.tsx @@ -0,0 +1,184 @@ +import { useQueryClient } from "@tanstack/react-query"; +import React, { useMemo, useState } from "react"; +import { View } from "react-native"; + +import gnoSVG from "@/assets/icons/networks/gno.svg"; +import { BrandText } from "@/components/BrandText"; +import FlexRow from "@/components/FlexRow"; +import { SVG } from "@/components/SVG"; +import { TertiaryBox } from "@/components/boxes/TertiaryBox"; +import { PrimaryButton } from "@/components/buttons/PrimaryButton"; +import { SecondaryButton } from "@/components/buttons/SecondaryButton"; +import ModalBase from "@/components/modals/ModalBase"; +import { SpacerColumn, SpacerRow } from "@/components/spacer"; +import { useBalances } from "@/hooks/useBalances"; +import { + useSelectedNetworkId, + useSelectedNetworkInfo, +} from "@/hooks/useSelectedNetwork"; +import useSelectedWallet from "@/hooks/useSelectedWallet"; +import { + NetworkFeature, + getNetworkFeature, + getNetworkObjectId, +} from "@/networks"; +import { Tag } from "@/screens/Projects/components/Milestone"; +import { useEscrowContract } from "@/screens/Projects/hooks/useEscrowContract"; +import { Project } from "@/screens/Projects/types"; +import { prettyPrice } from "@/utils/coins"; +import { neutral17, neutral77 } from "@/utils/style/colors"; +import { + fontSemibold12, + fontSemibold13, + fontSemibold14, +} from "@/utils/style/fonts"; +import { layout } from "@/utils/style/layout"; +import { tinyAddress } from "@/utils/text"; + +type FundProjectModalProps = { + isVisible: boolean; + onClose: () => void; + project: Project; +}; + +export const FundProjectModal: React.FC = ({ + isVisible, + onClose, + project, +}) => { + const networkId = useSelectedNetworkId(); + const selectedWallet = useSelectedWallet(); + const selectedNetwork = useSelectedNetworkInfo(); + + const pmFeature = getNetworkFeature( + networkId, + NetworkFeature.GnoProjectManager, + ); + + const { balances } = useBalances( + selectedNetwork?.id, + selectedWallet?.address, + ); + const bal = balances?.find((b) => b.denom === pmFeature?.paymentsDenom); + + const [isSubmitting, setIsSubmitting] = useState(false); + + const { execEscrowMethod } = useEscrowContract( + networkId, + selectedWallet?.address, + ); + + const queryClient = useQueryClient(); + + const submitFunder = async () => { + setIsSubmitting(true); + try { + await execEscrowMethod( + "SubmitFunder", + [project.id?.toString()], + `${project.budget}${project.paymentDenom}`, + ); + await Promise.all([ + queryClient.invalidateQueries([ + "project", + getNetworkObjectId(networkId, project.id), + ]), + queryClient.invalidateQueries(["projects", networkId]), + ]); + } finally { + onClose(); + setIsSubmitting(false); + } + }; + + const fundingAmount = useMemo(() => { + return project.milestones + .map((m) => m.amount) + .reduce((total, amount) => total + BigInt(amount), BigInt(0)) + .toString(); + }, [project]); + + return ( + + + You’re making the signature to validate a transaction + + + + + + + + + + + + {selectedNetwork?.displayName} + + + + {tinyAddress(selectedWallet?.address, 16)} + + + + {selectedWallet?.address && } + + + + + + + Funding amount + + + + {prettyPrice(networkId, fundingAmount, pmFeature?.paymentsDenom)} + + + + + + Balance + + + + {prettyPrice(networkId, bal?.amount, pmFeature?.paymentsDenom)} + + + + + + submitFunder()} + /> + + + + + + + + ); +}; diff --git a/packages/screens/Projects/components/HeaderBackButton.tsx b/packages/screens/Projects/components/HeaderBackButton.tsx new file mode 100644 index 0000000000..e93c778f19 --- /dev/null +++ b/packages/screens/Projects/components/HeaderBackButton.tsx @@ -0,0 +1,24 @@ +import React from "react"; +import { TouchableOpacity } from "react-native"; + +import chevronLeftSVG from "../../../../assets/icons/chevron-left.svg"; +import { BrandText } from "../../../components/BrandText"; +import FlexRow from "../../../components/FlexRow"; +import { SVG } from "../../../components/SVG"; +import { SpacerRow } from "../../../components/spacer"; +import { useAppNavigation } from "../../../utils/navigation"; +import { fontSemibold20 } from "../../../utils/style/fonts"; + +export const HeaderBackButton: React.FC = () => { + const navigation = useAppNavigation(); + + return ( + navigation.navigate("Projects")}> + + + + Projects Program + + + ); +}; diff --git a/packages/screens/Projects/components/Milestone.tsx b/packages/screens/Projects/components/Milestone.tsx new file mode 100644 index 0000000000..a6f84d0ea7 --- /dev/null +++ b/packages/screens/Projects/components/Milestone.tsx @@ -0,0 +1,40 @@ +import React from "react"; +import { StyleProp, ViewStyle } from "react-native"; + +import { SimpleButton } from "../../../components/buttons/SimpleButton"; +import { neutral00, neutral33, neutral77 } from "../../../utils/style/colors"; +import { fontSemibold13 } from "../../../utils/style/fonts"; + +export const Tag: React.FC<{ + text: string; + color?: string; + bgColor?: string; + size?: "XS" | "SM" | "M" | "XL"; + borderColor?: string; + containerStyle?: StyleProp; +}> = ({ text, bgColor, color, borderColor, size, containerStyle }) => { + if (text === "") return null; + + return ( + + ); +}; diff --git a/packages/screens/Projects/components/MilestoneBoard.tsx b/packages/screens/Projects/components/MilestoneBoard.tsx new file mode 100644 index 0000000000..0112a4e0df --- /dev/null +++ b/packages/screens/Projects/components/MilestoneBoard.tsx @@ -0,0 +1,181 @@ +import React, { useState } from "react"; +import { StyleProp, ViewStyle } from "react-native"; +import Hoverable from "react-native-hoverable"; +import { SvgProps } from "react-native-svg"; + +import { MilestoneForm } from "./MilestoneForm"; +import { MilestoneItem } from "./MilestoneItem"; +import { MilestoneList } from "./MilestoneList"; +import addCircleSVG from "../../../../assets/icons/add-circle.svg"; +import noMilestonesSVG from "../../../../assets/icons/no-tasks.svg"; +import projectsCompletedSVG from "../../../../assets/icons/projects-completed.svg"; +import projectsInProgressSVG from "../../../../assets/icons/projects-inProgress.svg"; +import projectsOpenSVG from "../../../../assets/icons/projects-open.svg"; +import projectsReviewSVG from "../../../../assets/icons/projects-review.svg"; +import { BrandText } from "../../../components/BrandText"; +import FlexRow from "../../../components/FlexRow"; +import { SVG } from "../../../components/SVG"; +import { SimpleButton } from "../../../components/buttons/SimpleButton"; +import { SpacerColumn, SpacerRow } from "../../../components/spacer"; +import { + neutral00, + neutral33, + neutral77, + neutralFF, +} from "../../../utils/style/colors"; +import { fontSemibold13 } from "../../../utils/style/fonts"; +import { layout } from "../../../utils/style/layout"; +import { useMakeRequestState } from "../hooks/useMakeRequestHook"; +import { + ProjectMilestone, + MilestoneStatus, + MilestoneFormValues, +} from "../types"; + +export type Step = { + status: MilestoneStatus; + text: string; + iconSVG: React.FC; +}; + +const STEPS: Step[] = [ + { + status: "MS_OPEN", + text: "Open (Backlog)", + iconSVG: projectsOpenSVG, + }, + { + status: "MS_PROGRESS", + text: "In Progress", + iconSVG: projectsInProgressSVG, + }, + { + status: "MS_REVIEW", + text: "Review", + iconSVG: projectsReviewSVG, + }, + { + status: "MS_COMPLETED", + text: "Completed", + iconSVG: projectsCompletedSVG, + }, +]; + +export const MilestoneBoard: React.FC<{ + milestones: ProjectMilestone[]; + containerStyle?: StyleProp; + onSelectMilestone?: (id: string) => void; + editable?: boolean; +}> = ({ onSelectMilestone, containerStyle, editable, milestones }) => { + const [hoveredMilestone, setHoveredMilestone] = useState(); + const [isShowMilestoneForm, showMilestoneForm] = useState(false); + + const { + actions: { addMilestone, removeMilestone }, + } = useMakeRequestState(); + + const removeHoveredMilestone = (id: string) => { + setHoveredMilestone(undefined); + removeMilestone(id); + }; + + const addNewMilestone = (milestone: MilestoneFormValues) => { + showMilestoneForm(false); + console.log("adding milestone", milestone); + addMilestone(milestone); + }; + + return ( + + {STEPS.map((step, idx) => { + const listItems = (milestones || []).filter( + (milestone) => milestone.status === step.status, + ); + const isBacklogItem = idx === 0; + + return ( + + {listItems.map((milestone) => { + const isHovered = hoveredMilestone?.id === milestone.id; + return ( + + isBacklogItem && editable && setHoveredMilestone(milestone) + } + onMouseLeave={() => + isBacklogItem && editable && setHoveredMilestone(undefined) + } + > + + + + ); + })} + + {listItems.length === 0 && ( + + + + + {editable ? "No milestones" : "Empty"} + + + )} + + {isBacklogItem && isShowMilestoneForm && ( + showMilestoneForm(false)} + onSubmit={addNewMilestone} + /> + )} + + {isBacklogItem && editable && !isShowMilestoneForm && ( + showMilestoneForm(true)} + text="Add" + size="XS" + iconSVG={addCircleSVG} + color={neutralFF} + bgColor={neutral33} + style={{ + width: "100%", + justifyContent: "center", + alignItems: "center", + }} + /> + )} + + + + ); + })} + + ); +}; diff --git a/packages/screens/Projects/components/MilestoneForm.tsx b/packages/screens/Projects/components/MilestoneForm.tsx new file mode 100644 index 0000000000..728e60aa11 --- /dev/null +++ b/packages/screens/Projects/components/MilestoneForm.tsx @@ -0,0 +1,248 @@ +import { Decimal } from "@cosmjs/math"; +import { zodResolver } from "@hookform/resolvers/zod"; +import React, { useState } from "react"; +import { useForm } from "react-hook-form"; +import { TouchableOpacity, View } from "react-native"; + +import closeSVG from "../../../../assets/icons/close.svg"; +import { BrandText } from "../../../components/BrandText"; +import FlexRow from "../../../components/FlexRow"; +import { SVG } from "../../../components/SVG"; +import { TertiaryBox } from "../../../components/boxes/TertiaryBox"; +import { SimpleButton } from "../../../components/buttons/SimpleButton"; +import { + SelectInput, + SelectInputItem, +} from "../../../components/inputs/SelectInput"; +import { TextInputCustom } from "../../../components/inputs/TextInputCustom"; +import { SpacerColumn } from "../../../components/spacer"; +import { + neutral22, + neutral33, + neutral44, + neutral77, + neutralFF, + primaryColor, + redDefault, +} from "../../../utils/style/colors"; +import { fontSemibold12 } from "../../../utils/style/fonts"; +import { layout } from "../../../utils/style/layout"; +import { + MilestoneFormValues, + MilestonePriority, + zodMilestoneFormValues, +} from "../types"; + +import { useSelectedNetworkId } from "@/hooks/useSelectedNetwork"; +import { + NetworkFeature, + getNativeCurrency, + getNetworkFeature, +} from "@/networks"; + +const PRIORITIES: SelectInputItem[] = [ + { label: "High", value: "MS_PRIORITY_HIGH".toString() }, + { label: "Medium", value: "MS_PRIORITY_MEDIUM".toString() }, +]; + +const initialValues: MilestoneFormValues = { + title: "", + desc: "", + priority: "MS_PRIORITY_MEDIUM", + amount: 0, + duration: 0, +}; + +export const MilestoneForm: React.FC<{ + onSubmit: (milestone: MilestoneFormValues) => void; + onClose: () => void; +}> = ({ onSubmit, onClose }) => { + const [priority, setPriority] = + useState("MS_PRIORITY_MEDIUM"); + + const networkId = useSelectedNetworkId(); + + const pmFeature = getNetworkFeature( + networkId, + NetworkFeature.GnoProjectManager, + ); + const currency = getNativeCurrency(networkId, pmFeature?.paymentsDenom); + const decimals = currency?.decimals || 0; + + const { handleSubmit, watch, formState, setValue } = useForm({ + resolver: zodResolver(zodMilestoneFormValues), + defaultValues: initialValues, + }); + const values = watch(); + const { errors } = formState; + + return ( + + + setValue("title", val)} + name="milestoneName" + label="" + placeHolder="⚡️ Type name here..." + hideLabel + fullWidth + noBrokenCorners + containerStyle={{ width: "100%" }} + height={32} + value={values.title} + error={errors.title?.message} + /> + + + + setValue("desc", val)} + value={values.desc} + error={errors.desc?.message} + /> + + + + + + Priority + + p.value === priority.toString()) || + PRIORITIES[0] + } + selectItem={(item) => setPriority(item.value as any)} + boxStyle={{ height: 32 }} + /> + + + + + + + Budget + + setValue("amount", +val)} + name="milestoneBudget" + label="" + placeHolder="Type here..." + hideLabel + fullWidth + noBrokenCorners + containerStyle={{ flex: 1 }} + height={32} + value={"" + values.amount} + error={errors.amount?.message} + testID="milestone-budget" + /> + + + + + + + Duration + + setValue("duration", +val)} + name="milestoneDuration" + label="" + placeHolder="Type here..." + hideLabel + fullWidth + noBrokenCorners + containerStyle={{ flex: 1 }} + height={32} + value={"" + values.duration} + error={errors.duration?.message} + testID="milestone-duration" + /> + + + + + + + Github link + + setValue("link", val)} + name="milestoneGithubLink" + label="" + placeHolder="Github link..." + hideLabel + fullWidth + noBrokenCorners + containerStyle={{ flex: 1 }} + height={32} + value={values.link} + error={errors.link?.message} + /> + + + + + { + console.log("adding milestone: handle sumbit", values); + values.priority = priority; + // FIXME: loss of precision + values.amount = +Decimal.fromUserInput( + values.amount.toString(), + decimals, + ).atomics; + onSubmit(values); + }, + (state) => { + console.error("adding milestone: invalid", state); + }, + )} + text="Confirm" + size="XS" + color={neutralFF} + bgColor={primaryColor} + testID="milestone-confirm" + style={{ + width: "100%", + justifyContent: "center", + alignItems: "center", + }} + /> + + + onClose?.()} + style={{ + position: "absolute", + right: -44, + top: "30%", + padding: layout.spacing_x1, + backgroundColor: neutral33, + borderWidth: 1, + borderColor: neutral44, + borderRadius: 100, + }} + > + + + + ); +}; diff --git a/packages/screens/Projects/components/MilestoneItem.tsx b/packages/screens/Projects/components/MilestoneItem.tsx new file mode 100644 index 0000000000..6b28798d5d --- /dev/null +++ b/packages/screens/Projects/components/MilestoneItem.tsx @@ -0,0 +1,162 @@ +import moment from "moment"; +import React from "react"; +import { TouchableOpacity, View } from "react-native"; + +import { Tag } from "./Milestone"; +import githubSVG from "../../../../assets/icons/github.svg"; +import trashSVG from "../../../../assets/icons/trash.svg"; +import { BrandText } from "../../../components/BrandText"; +import FlexRow from "../../../components/FlexRow"; +import { SVG } from "../../../components/SVG"; +import { TertiaryBox } from "../../../components/boxes/TertiaryBox"; +import { SocialButton } from "../../../components/buttons/SocialButton"; +import { SpacerColumn } from "../../../components/spacer"; +import { + neutral00, + neutral22, + neutral33, + neutral44, + neutral77, + neutralA3, + redDefault, +} from "../../../utils/style/colors"; +import { fontSemibold13 } from "../../../utils/style/fonts"; +import { layout } from "../../../utils/style/layout"; +import { ProjectMilestone } from "../types"; + +import { useSelectedNetworkId } from "@/hooks/useSelectedNetwork"; +import { NetworkFeature, getNetworkFeature } from "@/networks"; +import { prettyPrice } from "@/utils/coins"; + +export const MilestoneItem: React.FC<{ + milestone: ProjectMilestone; + isHovered?: boolean; + onPress?: (id: string) => void; + onDelete?: (id: string) => void; +}> = ({ milestone, onPress, isHovered, onDelete }) => { + const networkId = useSelectedNetworkId(); + + const pmFeature = getNetworkFeature( + networkId, + NetworkFeature.GnoProjectManager, + ); + + return ( + + onPress?.(milestone.id)}> + + + 🔎 {milestone.title} + + + + + + {milestone.desc} + + + + + + Duration:{" "} + {moment.duration(milestone.duration, "seconds").humanize()} + + + + + {milestone.priority === "MS_PRIORITY_HIGH" && ( + + )} + + {milestone.priority === "MS_PRIORITY_MEDIUM" && ( + + )} + + {milestone.priority === "MS_PRIORITY_LOW" && ( + + )} + + + + + + + + + + {isHovered && ( + + onDelete?.(milestone.id)} + style={{ + position: "absolute", + padding: layout.spacing_x1, + backgroundColor: neutral33, + borderWidth: 1, + borderColor: neutral44, + borderRadius: 100, + }} + > + + + + )} + + ); +}; diff --git a/packages/screens/Projects/components/MilestoneList.tsx b/packages/screens/Projects/components/MilestoneList.tsx new file mode 100644 index 0000000000..dab18ae6ed --- /dev/null +++ b/packages/screens/Projects/components/MilestoneList.tsx @@ -0,0 +1,41 @@ +import React from "react"; +import { View } from "react-native"; +import { SvgProps } from "react-native-svg"; + +import { BrandText } from "../../../components/BrandText"; +import FlexRow from "../../../components/FlexRow"; +import { SVG } from "../../../components/SVG"; +import { neutral00 } from "../../../utils/style/colors"; +import { fontSemibold13 } from "../../../utils/style/fonts"; +import { layout } from "../../../utils/style/layout"; + +export const MilestoneList: React.FC<{ + iconSVG: React.FC; + text: string; + count: number; + children: React.ReactNode; +}> = ({ iconSVG, text, count, children }) => { + return ( + + + + + {text} + + + {count} + + + {children} + + ); +}; diff --git a/packages/screens/Projects/components/MilestonePriorityTag.tsx b/packages/screens/Projects/components/MilestonePriorityTag.tsx new file mode 100644 index 0000000000..658371f0ab --- /dev/null +++ b/packages/screens/Projects/components/MilestonePriorityTag.tsx @@ -0,0 +1,20 @@ +import React from "react"; + +import { Tag } from "./Milestone"; +import { neutral33, neutralFF } from "../../../utils/style/colors"; +import { MilestonePriority } from "../types"; + +export const MilestonePriorityTag: React.FC<{ + priority: MilestonePriority; +}> = ({ priority }) => { + switch (priority) { + case "MS_PRIORITY_HIGH": + return ; + case "MS_PRIORITY_MEDIUM": + return ; + case "MS_PRIORITY_LOW": + return ; + default: + return ; + } +}; diff --git a/packages/screens/Projects/components/MilestoneStatusTag.tsx b/packages/screens/Projects/components/MilestoneStatusTag.tsx new file mode 100644 index 0000000000..33f07bf667 --- /dev/null +++ b/packages/screens/Projects/components/MilestoneStatusTag.tsx @@ -0,0 +1,22 @@ +import React from "react"; + +import { Tag } from "./Milestone"; +import { neutralFF } from "../../../utils/style/colors"; +import { MilestoneStatus } from "../types"; + +export const MilestoneStatusTag: React.FC<{ + status: MilestoneStatus; +}> = ({ status }) => { + switch (status) { + case "MS_OPEN": + return ; + case "MS_PROGRESS": + return ; + case "MS_REVIEW": + return ; + case "MS_COMPLETED": + return ; + default: + return ; + } +}; diff --git a/packages/screens/Projects/components/ProjectBox.tsx b/packages/screens/Projects/components/ProjectBox.tsx new file mode 100644 index 0000000000..343cbd9e4d --- /dev/null +++ b/packages/screens/Projects/components/ProjectBox.tsx @@ -0,0 +1,249 @@ +import { Link, useLinkBuilder } from "@react-navigation/native"; +import React, { memo, useMemo } from "react"; +import { ScrollView, TouchableOpacity, View } from "react-native"; + +import { Tag } from "./Milestone"; +import { ProjectStatusTag } from "./ProjectStatusTag"; +import { Project } from "../types"; + +import discordSVG from "@/assets/icons/discord.svg"; +import githubSVG from "@/assets/icons/github.svg"; +import shareSVG from "@/assets/icons/share.svg"; +import twitterSVG from "@/assets/icons/twitter.svg"; +import websiteSVG from "@/assets/icons/website.svg"; +import { BrandText } from "@/components/BrandText"; +import FlexRow from "@/components/FlexRow"; +import { ProgressLine } from "@/components/ProgressLine"; +import { TertiaryBox } from "@/components/boxes/TertiaryBox"; +import { SocialButton } from "@/components/buttons/SocialButton"; +import { RoundedGradientImage } from "@/components/images/RoundedGradientImage"; +import { Separator } from "@/components/separators/Separator"; +import { SpacerColumn, SpacerRow } from "@/components/spacer"; +import { UsernameWithAvatar } from "@/components/user/UsernameWithAvatar"; +import { useFeedbacks } from "@/context/FeedbacksProvider"; +import { useSelectedNetworkId } from "@/hooks/useSelectedNetwork"; +import Clipboard from "@/modules/Clipboard"; +import { getNetworkObjectId, getUserId } from "@/networks"; +import { prettyPrice } from "@/utils/coins"; +import { useAppNavigation } from "@/utils/navigation"; +import { joinElements } from "@/utils/react"; +import { + neutral17, + neutral77, + neutralA3, + secondaryColor, +} from "@/utils/style/colors"; +import { + fontSemibold10, + fontSemibold13, + fontSemibold20, +} from "@/utils/style/fonts"; +import { layout } from "@/utils/style/layout"; +import { normalizeTwitterId } from "@/utils/twitter"; + +export const ProjectBox: React.FC<{ + project: Project; + width: number; +}> = memo(({ project, width }) => { + const stats = useMemo(() => { + if (!project.milestones) + return { completed: 0, total: 0, percentCompleted: 0 }; + const completed = project.milestones.filter( + (ms) => ms.status === "MS_COMPLETED", + ).length; + const total = project.milestones.length; + const percentCompleted = Math.floor((completed / total) * 100); + return { completed, total, percentCompleted }; + }, [project.milestones]); + const { setToast } = useFeedbacks(); + const buildLink = useLinkBuilder(); + + const networkId = useSelectedNetworkId(); + + const navigation = useAppNavigation(); + + const gotoProjectsDetail = (localId: string | undefined) => { + if (!localId) { + return; + } + navigation.navigate("ProjectsDetail", { + id: getNetworkObjectId(networkId, localId), + }); + }; + + const onPress = () => gotoProjectsDetail(project.id); + + const bottomElems = [ + { + const pathname = buildLink("ProjectsDetail", { + id: getNetworkObjectId(networkId, project.id), + }); + if (!pathname) return; + + const link = new URL(window.location.href); + link.pathname = pathname; + await Clipboard.setStringAsync(link.href); + + setToast({ + title: "Copied permanent link", + message: "", + type: "success", + mode: "normal", + }); + }} + />, + ]; + if (project.metadata?.teamAndLinkData?.discordLink) { + bottomElems.push( + + + , + ); + } + if (project.metadata?.teamAndLinkData?.websiteLink) { + bottomElems.push( + + + , + ); + } + if (project.metadata?.teamAndLinkData?.githubLink) { + bottomElems.push( + + + , + ); + } + if (project.metadata?.teamAndLinkData?.twitterProfile) { + bottomElems.push( + + + , + ); + } + + return ( + + {/* Body ============================================================== */} + + + + + + + + + + {project.metadata?.shortDescData?.name} + + + + + {project.metadata?.shortDescData?.tags + ?.split(",") + .map((tag, idx) => ( + + ))} + + + + + + + {project.metadata?.shortDescData?.desc} + + + + + + + + Milestones + + + {stats.completed}/{stats.total} + + + + + + + + {/* Footer ============================================================== */} + + + + + + + Grant:{" "} + + + {prettyPrice( + networkId, + project.budget || "0", + project.paymentDenom, + )} + + + + + + + + + {joinElements(bottomElems, )} + + + + + + + ); +}); diff --git a/packages/screens/Projects/components/ProjectInfo/LeftBlock.tsx b/packages/screens/Projects/components/ProjectInfo/LeftBlock.tsx new file mode 100644 index 0000000000..94427f1023 --- /dev/null +++ b/packages/screens/Projects/components/ProjectInfo/LeftBlock.tsx @@ -0,0 +1,207 @@ +import React, { useState } from "react"; +import { View } from "react-native"; + +import { Project } from "../../types"; +import { FundProjectModal } from "../FundProjectModal"; +import { Tag } from "../Milestone"; +import { ProjectStatusTag } from "../ProjectStatusTag"; +import { ResolveConflictButton } from "../ResolveConflictButton"; +import { SubmitContractorCandidateModal } from "../SubmitContractorCandidateModal"; + +import { BrandText } from "@/components/BrandText"; +import FlexRow from "@/components/FlexRow"; +import { PrimaryButton } from "@/components/buttons/PrimaryButton"; +import { RoundedGradientImage } from "@/components/images/RoundedGradientImage"; +import { SpacerColumn, SpacerRow } from "@/components/spacer"; +import { UsernameWithAvatar } from "@/components/user/UsernameWithAvatar"; +import { useAppNavigation } from "@/hooks/navigation/useAppNavigation"; +import useSelectedWallet from "@/hooks/useSelectedWallet"; +import { getNetworkObjectId, getUserId } from "@/networks"; +import { + errorColor, + neutral00, + neutral33, + neutral77, + neutralA3, +} from "@/utils/style/colors"; +import { + fontSemibold13, + fontSemibold14, + fontSemibold20, +} from "@/utils/style/fonts"; +import { layout } from "@/utils/style/layout"; + +type LeftBlockProps = { + networkId: string; + project: Project; +}; + +export const LeftBlock: React.FC = ({ networkId, project }) => { + const navigation = useAppNavigation(); + const [isFundModalVisible, setIsFundModalVisible] = useState(false); + + const projectId = getNetworkObjectId(networkId, project.id); + + const selectedWallet = useSelectedWallet(); + const walletAddress = selectedWallet?.address || ""; + + const projectStatus = project.status; + const shortDescData = project.metadata?.shortDescData; + + const authorId = project + ? getUserId(networkId, project.sender) + : selectedWallet?.userId; + + return ( + + {shortDescData?.name} + + + + Project creator:{" "} + + + + + + + + {projectStatus && } + + + + {shortDescData?.tags?.split(",").map((tag, idx) => { + return ( + + ); + })} + + + + {/* Image */} + + + {/* Name and Description */} + + + + {shortDescData?.desc} + + + + + + + {project && + (walletAddress === project.funder || + walletAddress === project?.contractor) && + project.status === "ACCEPTED" && ( + <> + { + project.id !== undefined && + navigation.navigate("ProjectsConflictSolving", { + projectId, + }); + }} + size="SM" + width={280} + /> + + + )} + + {project.id !== undefined && + project.status === "CONFLICT" && + (walletAddress === project.conflictHandler || + walletAddress === project.contractor || + walletAddress === project.funder) && ( + <> + + + + )} + + {/* Actions */} + {/* If current user is not contractor, not creator of project and the project has not funder yet then user can become funder */} + {walletAddress !== project.sender && + walletAddress !== project.contractor && + !project.funded && + project.status === "CREATED" && ( + setIsFundModalVisible(true)} + size="SM" + width={200} + /> + )} + + + + + + + + {project?.id && ( + setIsFundModalVisible(false)} + /> + )} + + ); +}; + +export const SubmitCandidacyButton: React.FC<{ + project: Project; +}> = ({ project }) => { + const [isSubmitContractorModalVisible, setIsSubmitContractorModalVisible] = + useState(false); + return ( + <> + setIsSubmitContractorModalVisible(false)} + project={project} + /> + setIsSubmitContractorModalVisible(true)} + size="SM" + /> + + ); +}; diff --git a/packages/screens/Projects/components/ProjectInfo/RelatedUsers.tsx b/packages/screens/Projects/components/ProjectInfo/RelatedUsers.tsx new file mode 100644 index 0000000000..39dcf666c9 --- /dev/null +++ b/packages/screens/Projects/components/ProjectInfo/RelatedUsers.tsx @@ -0,0 +1,83 @@ +import { Link } from "@react-navigation/native"; +import React from "react"; +import { Table, Row, Cell, TableWrapper } from "react-native-reanimated-table"; + +import { SubmitCandidacyButton } from "./LeftBlock"; + +import { BrandText } from "@/components/BrandText"; +import { TertiaryBox } from "@/components/boxes/TertiaryBox"; +import { SpacerColumn } from "@/components/spacer"; +import { UsernameWithAvatar } from "@/components/user/UsernameWithAvatar"; +import useSelectedWallet from "@/hooks/useSelectedWallet"; +import { getUserId } from "@/networks"; +import { Project } from "@/screens/Projects/types"; +import { neutral22, neutralA3 } from "@/utils/style/colors"; +import { fontSemibold14 } from "@/utils/style/fonts"; +import { layout } from "@/utils/style/layout"; + +type RelatedUsersProps = { + networkId: string; + project: Project; +}; + +export const RelatedUsers: React.FC = ({ + networkId, + project, +}) => { + const wallet = useSelectedWallet(); + const walletAddress = wallet?.address; + + const showCandidacyButton = + !!walletAddress && + !!project && + walletAddress !== project.sender && + walletAddress !== project.funder && + !project.contractor && + project.status === "CREATED" && + !project.contractorCandidates?.includes(walletAddress); + + return ( + + + + + + {[project?.funder, project?.contractor, project?.conflictHandler].map( + (cellData, cellIndex) => { + let content; + if (cellIndex === 1 && !cellData) { + if (showCandidacyButton) { + content = ; + } else { + content = ( + + + {project.contractorCandidates.length} candidates + + + ); + } + } else { + content = ( + + ); + } + return ; + }, + )} + +
+
+ ); +}; diff --git a/packages/screens/Projects/components/ProjectInfo/RightBlock.tsx b/packages/screens/Projects/components/ProjectInfo/RightBlock.tsx new file mode 100644 index 0000000000..518b5cb0bc --- /dev/null +++ b/packages/screens/Projects/components/ProjectInfo/RightBlock.tsx @@ -0,0 +1,176 @@ +import { Link } from "@react-navigation/native"; +import moment from "moment/moment"; +import React from "react"; +import { View } from "react-native"; + +import copySVG from "@/assets/icons/copy.svg"; +import discordSVG from "@/assets/icons/discord.svg"; +import githubSVG from "@/assets/icons/github.svg"; +import twitterSVG from "@/assets/icons/twitter.svg"; +import websiteSVG from "@/assets/icons/website.svg"; +import { BrandText } from "@/components/BrandText"; +import FlexRow from "@/components/FlexRow"; +import { TertiaryBox } from "@/components/boxes/TertiaryBox"; +import { IconWithTextButton } from "@/components/buttons/SocialButton"; +import { SpacerColumn, SpacerRow } from "@/components/spacer"; +import { useFeedbacks } from "@/context/FeedbacksProvider"; +import Clipboard from "@/modules/Clipboard"; +import { Project } from "@/screens/Projects/types"; +import { prettyPrice } from "@/utils/coins"; +import { joinElements } from "@/utils/react"; +import { + neutral22, + neutral77, + neutralA3, + primaryColor, + yellowDefault, +} from "@/utils/style/colors"; +import { fontSemibold20 } from "@/utils/style/fonts"; +import { layout } from "@/utils/style/layout"; +import { normalizeTwitterId } from "@/utils/twitter"; + +type RightBlockProps = { + project: Project; + networkId: string; +}; + +export const RightBlock: React.FC = ({ + networkId, + project, +}) => { + const { setToast } = useFeedbacks(); + + const isFunded = project.funded; + const teamAndLinkData = project.metadata?.teamAndLinkData; + + const actions = [ + { + await Clipboard.setStringAsync(window.location.href); + setToast({ + title: "Copied permanent link", + message: "", + type: "success", + mode: "normal", + }); + }} + />, + ]; + + if (teamAndLinkData?.websiteLink) { + actions.push( + + + , + ); + } + + if (teamAndLinkData?.discordLink) { + actions.push( + + + , + ); + } + + if (teamAndLinkData?.githubLink) { + actions.push( + + + , + ); + } + + if (teamAndLinkData?.twitterProfile) { + actions.push( + + + , + ); + } + + return ( + + + + + {isFunded ? "Deposited:" : "Budget:"} + + + + {prettyPrice(networkId, project.budget, project.paymentDenom)} + + + + + + + + + + Expires on: + + + + {/* FIXME */} + {moment(/*project.duration ||*/ 0 * 1000 + Date.now()).format( + "L", + )}{" "} + + + + + + + + {joinElements(actions, )} + + + ); +}; diff --git a/packages/screens/Projects/components/ProjectInfo/index.tsx b/packages/screens/Projects/components/ProjectInfo/index.tsx new file mode 100644 index 0000000000..9d8e7ba6f5 --- /dev/null +++ b/packages/screens/Projects/components/ProjectInfo/index.tsx @@ -0,0 +1,41 @@ +import React from "react"; +import { View } from "react-native"; + +import { Project } from "../../types"; + +import FlexRow from "@/components/FlexRow"; +import { useSelectedNetworkId } from "@/hooks/useSelectedNetwork"; +import { LeftBlock } from "@/screens/Projects/components/ProjectInfo/LeftBlock"; +import { RelatedUsers } from "@/screens/Projects/components/ProjectInfo/RelatedUsers"; +import { RightBlock } from "@/screens/Projects/components/ProjectInfo/RightBlock"; +import { layout } from "@/utils/style/layout"; + +export const ProjectInfo: React.FC<{ + project: Project; +}> = ({ project }) => { + const networkId = useSelectedNetworkId(); + + return ( + + + {/* Left block ======================================================= */} + + + + + {/* Right block ======================================================= */} + + + + + + + + ); +}; diff --git a/packages/screens/Projects/components/ProjectMilestones.tsx b/packages/screens/Projects/components/ProjectMilestones.tsx new file mode 100644 index 0000000000..6545875f4c --- /dev/null +++ b/packages/screens/Projects/components/ProjectMilestones.tsx @@ -0,0 +1,78 @@ +import React, { useMemo, useState } from "react"; +import { View } from "react-native"; + +import { MilestoneBoard } from "./MilestoneBoard"; +import { BrandText } from "../../../components/BrandText"; +import FlexRow from "../../../components/FlexRow"; +import { SearchBarInput } from "../../../components/Search/SearchBarInput"; +import { Separator } from "../../../components/separators/Separator"; +import { SpacerRow } from "../../../components/spacer"; +import { + neutral77, + neutral33, + neutral00, + neutral17, +} from "../../../utils/style/colors"; +import { fontSemibold20 } from "../../../utils/style/fonts"; +import { layout } from "../../../utils/style/layout"; +import { ProjectMilestone } from "../types"; + +export const ProjectMilestones: React.FC<{ + milestones: ProjectMilestone[]; + onSelectMilestone?: (id: string) => void; +}> = ({ milestones, onSelectMilestone }) => { + const [searchText, setSearchText] = useState(""); + const [isHideInfo, setIsHideInfo] = useState(false); + + const filteredMilestones = useMemo(() => { + return milestones.filter( + (m) => m.title.includes(searchText) || m.desc.includes(searchText), + ); + }, [milestones, searchText]); + + return ( + + + setIsHideInfo(!isHideInfo)} + style={fontSemibold20} + > + All Milestones: + + + + {filteredMilestones.length} + + + + + + + + + + ); +}; diff --git a/packages/screens/Projects/components/ProjectStatusTag.tsx b/packages/screens/Projects/components/ProjectStatusTag.tsx new file mode 100644 index 0000000000..e09c710cfe --- /dev/null +++ b/packages/screens/Projects/components/ProjectStatusTag.tsx @@ -0,0 +1,92 @@ +import React from "react"; + +import { SimpleButton } from "../../../components/buttons/SimpleButton"; +import { + neutral00, + neutral22, + primaryColor, + redDefault, + secondaryColor, +} from "../../../utils/style/colors"; +import { ContractStatusFilter } from "../types"; + +export const ProjectStatusTag: React.FC<{ + status: ContractStatusFilter | undefined; + onPress?: () => void; + active?: boolean; + size?: "XS" | "SM" | "M" | "XL"; +}> = ({ status, onPress, active, size }) => { + let color, bgColor, borderColor, text; + + switch (status) { + case "ALL": + text = "All"; + color = secondaryColor; + bgColor = neutral00; + borderColor = neutral22; + break; + case "CREATED": + text = "Open"; + color = "#C8FFAE"; + bgColor = "#C8FFAE1A"; + borderColor = "#C8FFAE1A"; + break; + case "ACCEPTED": + text = "In Progress"; + color = "#EAA54B"; + bgColor = "#EAA54B1A"; + borderColor = "#EAA54B1A"; + break; + case "COMPLETED": + text = "Completed"; + color = primaryColor; + bgColor = neutral00; + borderColor = neutral22; + break; + case "CANCELED": + text = "Canceled"; + color = redDefault; + bgColor = neutral00; + borderColor = neutral22; + break; + case "REJECTED": + text = "Rejected"; + color = redDefault; + bgColor = neutral00; + borderColor = neutral22; + break; + case "CONFLICT": + text = "Conflict"; + color = redDefault; + bgColor = neutral00; + borderColor = neutral22; + break; + case "ABORTED_IN_FAVOR_OF_CONTRACTOR": + case "ABORTED_IN_FAVOR_OF_FUNDER": + text = "Aborted"; + color = redDefault; + bgColor = neutral00; + borderColor = neutral22; + break; + default: + color = secondaryColor; + bgColor = neutral00; + borderColor = neutral00; + text = "unknown"; + break; + } + + return ( + onPress?.()} + text={text} + size={size} + bgColor={bgColor} + color={color} + style={{ + borderColor: active ? secondaryColor : borderColor, + }} + testID={`project-status-${status || "UNKNOWN"}`} + /> + ); +}; diff --git a/packages/screens/Projects/components/ProjectsStatusFilterButtons.tsx b/packages/screens/Projects/components/ProjectsStatusFilterButtons.tsx new file mode 100644 index 0000000000..6fcd01bf44 --- /dev/null +++ b/packages/screens/Projects/components/ProjectsStatusFilterButtons.tsx @@ -0,0 +1,63 @@ +import React from "react"; + +import { ProjectStatusTag } from "./ProjectStatusTag"; +import FlexRow from "../../../components/FlexRow"; +import { SpacerRow } from "../../../components/spacer"; +import { ContractStatusFilter } from "../types"; + +export const ProjectsStatusFilterButtons: React.FC<{ + status: ContractStatusFilter; + onChange: (newFilter: ContractStatusFilter) => void; +}> = ({ status, onChange }) => { + return ( + + onChange("ALL")} + /> + + + + onChange("CREATED")} + /> + + + + onChange("ACCEPTED")} + /> + + + + onChange("REJECTED")} + /> + + + + onChange("COMPLETED")} + /> + + ); +}; diff --git a/packages/screens/Projects/components/ResolveConflictButton.tsx b/packages/screens/Projects/components/ResolveConflictButton.tsx new file mode 100644 index 0000000000..40994e1bbd --- /dev/null +++ b/packages/screens/Projects/components/ResolveConflictButton.tsx @@ -0,0 +1,28 @@ +import React, { FC } from "react"; + +import { PrimaryButton } from "@/components/buttons/PrimaryButton"; +import { useAppNavigation } from "@/utils/navigation"; + +export const ResolveConflictButton: FC<{ + projectId: string | undefined; +}> = ({ projectId }) => { + const navigation = useAppNavigation(); + return ( + <> + { + if (!projectId) { + return; + } + navigation.navigate("ProjectsConflictSolving", { + projectId, + }); + }} + size="SM" + width={280} + /> + + ); +}; diff --git a/packages/screens/Projects/components/SubmitContractorCandidateModal.tsx b/packages/screens/Projects/components/SubmitContractorCandidateModal.tsx new file mode 100644 index 0000000000..4a685de891 --- /dev/null +++ b/packages/screens/Projects/components/SubmitContractorCandidateModal.tsx @@ -0,0 +1,128 @@ +import { useQueryClient } from "@tanstack/react-query"; +import React, { useState } from "react"; +import { View } from "react-native"; + +import gnoSVG from "@/assets/icons/networks/gno.svg"; +import { BrandText } from "@/components/BrandText"; +import { SVG } from "@/components/SVG"; +import { TertiaryBox } from "@/components/boxes/TertiaryBox"; +import { PrimaryButton } from "@/components/buttons/PrimaryButton"; +import { SecondaryButton } from "@/components/buttons/SecondaryButton"; +import ModalBase from "@/components/modals/ModalBase"; +import { SpacerColumn, SpacerRow } from "@/components/spacer"; +import { + useSelectedNetworkId, + useSelectedNetworkInfo, +} from "@/hooks/useSelectedNetwork"; +import useSelectedWallet from "@/hooks/useSelectedWallet"; +import { getNetworkObjectId } from "@/networks"; +import { Tag } from "@/screens/Projects/components/Milestone"; +import { useEscrowContract } from "@/screens/Projects/hooks/useEscrowContract"; +import { Project } from "@/screens/Projects/types"; +import { neutral17, neutral77 } from "@/utils/style/colors"; +import { + fontSemibold12, + fontSemibold13, + fontSemibold14, +} from "@/utils/style/fonts"; +import { layout } from "@/utils/style/layout"; +import { tinyAddress } from "@/utils/text"; + +type SubmitContractorCandidateModalProps = { + isVisible: boolean; + onClose: () => void; + project: Project; +}; + +export const SubmitContractorCandidateModal: React.FC< + SubmitContractorCandidateModalProps +> = ({ isVisible, onClose, project }) => { + const networkId = useSelectedNetworkId(); + const selectedWallet = useSelectedWallet(); + const selectedNetwork = useSelectedNetworkInfo(); + const queryClient = useQueryClient(); + + const [isSubmitting, setIsSubmitting] = useState(false); + + const { execEscrowMethod } = useEscrowContract( + networkId, + selectedWallet?.address, + ); + + const submitContractorCandidate = async () => { + setIsSubmitting(true); + + const localIdentifier = project?.id?.toString(); + + await execEscrowMethod("SubmitContractorCandidate", [localIdentifier]); + + const projectId = getNetworkObjectId(networkId, localIdentifier); + + await queryClient.invalidateQueries(["project", projectId]); + + onClose(); + setIsSubmitting(false); + }; + + return ( + + + You’re making the signature to validate a transaction + + + + + + + + + + + + {selectedNetwork?.displayName} + + + + {tinyAddress(selectedWallet?.address, 16)} + + + + {selectedWallet?.address && } + + + + + submitContractorCandidate()} + testID="confirm-and-sign" + /> + + + + + + + + ); +}; diff --git a/packages/screens/Projects/components/TNSResult.tsx b/packages/screens/Projects/components/TNSResult.tsx new file mode 100644 index 0000000000..d133045551 --- /dev/null +++ b/packages/screens/Projects/components/TNSResult.tsx @@ -0,0 +1,49 @@ +import React from "react"; +import { View } from "react-native"; + +import { SearchResultsSection } from "../../../components/Search/SearchBarResults"; +import { AvatarWithName } from "../../../components/user/AvatarWithName"; +import { neutral00, neutral33 } from "../../../utils/style/colors"; +import { layout } from "../../../utils/style/layout"; + +const SEARCH_RESULTS_NAMES_MARGIN = layout.spacing_x1; + +export const TNSResult: React.FC<{ + names: string[]; + visible: boolean; + networkId: string; + onSelected: (name: string) => void; +}> = ({ names, networkId, onSelected, visible }) => { + if (!visible) return null; + return ( + + + {names.map((n) => ( + onSelected(n)} + /> + ))} + + + ); +}; diff --git a/packages/screens/Projects/defaultValues.ts b/packages/screens/Projects/defaultValues.ts new file mode 100644 index 0000000000..07f282d5f8 --- /dev/null +++ b/packages/screens/Projects/defaultValues.ts @@ -0,0 +1,32 @@ +import { + ProjectFormData, + ProjectTeamAndLinkFormData, +} from "./hooks/useMakeRequestHook"; + +/* +const emptyTeamAndLink: ProjectTeamAndLinkFormData = { + websiteLink: "", + twitterProfile: "", + discordLink: "", + githubLink: "", + teamDesc: "", +}; +*/ + +export const emptyProjectFormData: ProjectFormData = { + creatorAddress: "", + name: "", + description: "", + arbitratorAddress: "", + coverImg: "", + creatorKind: "contractor", + tags: "", +}; + +export const fakeTeamAndLink: ProjectTeamAndLinkFormData = { + websiteLink: "https://website.com", + twitterProfile: "https://twitter.com", + discordLink: "https://discord.com", + githubLink: "https://github.com", + teamDesc: "This is long team description", +}; diff --git a/packages/screens/Projects/hooks/useEscrowContract.ts b/packages/screens/Projects/hooks/useEscrowContract.ts new file mode 100644 index 0000000000..bd1a391a80 --- /dev/null +++ b/packages/screens/Projects/hooks/useEscrowContract.ts @@ -0,0 +1,98 @@ +import { GnoJSONRPCProvider } from "@gnolang/gno-js-client"; + +import { useFeedbacks } from "@/context/FeedbacksProvider"; +import { + getNetworkFeature, + mustGetGnoNetwork, + NetworkFeature, +} from "@/networks"; +import { useUtils } from "@/screens/Projects/hooks/useUtils"; +import { adenaVMCall, extractGnoString } from "@/utils/gno"; + +export const useEscrowContract = ( + networkId: string | undefined, + walletAddress: string | undefined, +) => { + const { mustGetValue } = useUtils(); + const { setToastError } = useFeedbacks(); + + const _getEscrowInfo = (networkId: string) => { + const pmFeature = getNetworkFeature( + networkId, + NetworkFeature.GnoProjectManager, + ); + + if (!pmFeature) { + throw Error("Project Manager is not supported on this network"); + } + + const gnoNetwork = mustGetGnoNetwork(networkId); + const escrowPkgPath = mustGetValue( + pmFeature?.projectsManagerPkgPath, + "escrow pkg path", + ); + + return { gnoNetworkEndpoint: gnoNetwork.endpoint, escrowPkgPath }; + }; + + // This will call contract method and get the data + const queryEscrow = async (methodName: string, args: any[]) => { + if (!networkId) { + setToastError({ title: "Error", message: "networkId not given" }); + return; + } + + const { gnoNetworkEndpoint, escrowPkgPath } = _getEscrowInfo(networkId); + + const client = new GnoJSONRPCProvider(gnoNetworkEndpoint); + const argsStr = args + .map((arg) => (typeof arg === "number" ? arg : `"${arg}"`)) + .join(","); + + const res = await client.evaluateExpression( + escrowPkgPath, + `${methodName}(${argsStr})`, + ); + + return extractGnoString(res); + }; + + // This will execute the method and does not return result + // only through error in case of problem + const execEscrowMethod = async ( + func: string, + args: string[], + send: string = "", + gasWanted: number = 2_000_000, + ) => { + try { + if (!networkId) { + setToastError({ title: "Error", message: "networkId not given" }); + return false; + } + + const { escrowPkgPath } = _getEscrowInfo(networkId); + + const caller = mustGetValue(walletAddress, "caller"); + + await adenaVMCall( + networkId, + { + caller, + send, + pkg_path: escrowPkgPath, + func, + args, + }, + { gasWanted }, + ); + + return true; + } catch (e: any) { + setToastError({ title: "Error", message: e.message }); + return false; + } + }; + + return { execEscrowMethod, queryEscrow }; +}; diff --git a/packages/screens/Projects/hooks/useMakeRequestHook.tsx b/packages/screens/Projects/hooks/useMakeRequestHook.tsx new file mode 100644 index 0000000000..909527e07e --- /dev/null +++ b/packages/screens/Projects/hooks/useMakeRequestHook.tsx @@ -0,0 +1,125 @@ +import { useRoute } from "@react-navigation/native"; +import { useMemo } from "react"; +import { z } from "zod"; +import { create } from "zustand"; + +import { useAppNavigation } from "../../../utils/navigation"; +import { emptyProjectFormData, fakeTeamAndLink } from "../defaultValues"; +import { MilestoneFormValues } from "../types"; + +export const zodProjectTeamAndLinkFormData = z.object({ + websiteLink: z.string().url(), + twitterProfile: z.string().url(), + discordLink: z.string().url(), + githubLink: z.string().url(), + teamDesc: z.string(), +}); + +export type ProjectTeamAndLinkFormData = z.infer< + typeof zodProjectTeamAndLinkFormData +>; + +export const zodProjectFormData = z.object({ + name: z.string().min(3), + description: z.string().min(10), + creatorKind: z.enum(["funder", "contractor"]), + creatorAddress: z.string().min(1), + targetAddress: z.string().min(1).optional(), + arbitratorAddress: z.string().min(1), + tags: z.string(), + coverImg: z.string().min(1), // web3 uri +}); + +export type ProjectFormData = z.infer; + +type MakeRequestState = { + stepIndice: number; + projectFormData: ProjectFormData; + teamAndLinkData: ProjectTeamAndLinkFormData; + milestones: MilestoneFormValues[]; + actions: { + setShortDesc: (shortDescData: ProjectFormData) => void; + setTeamAndLink: (teamAndLinkData: ProjectTeamAndLinkFormData) => void; + + addMilestone: (milestone: MilestoneFormValues) => void; + removeMilestone: (id: string) => void; + }; +}; + +const TOTAL_STEPS = 5; + +const useMakeRequestStore = create((set, get) => ({ + stepIndice: 1, + projectFormData: emptyProjectFormData, + teamAndLinkData: fakeTeamAndLink, + milestones: [], + actions: { + setShortDesc: (shortDescData) => set({ projectFormData: shortDescData }), + setTeamAndLink: (teamAndLinkData) => { + set({ teamAndLinkData }); + }, + addMilestone: (milestone) => { + const updatedMilestones = [...get().milestones, milestone].map( + (t, idx) => { + t.id = idx.toString(); + return t; + }, + ); + + set({ milestones: updatedMilestones }); + }, + removeMilestone: (id) => { + const updatedMilestones = get() + .milestones.filter((t) => t.id !== id) + .map((t, idx) => { + t.id = idx.toString(); + return t; + }); + + set({ milestones: updatedMilestones }); + }, + }, +})); + +export const useMakeRequestState = () => { + const navigation = useAppNavigation(); + const store = useMakeRequestStore(); + const route = useRoute(); + const step = !route.params ? 1 : (route.params as any).step; + + const stepIndex = useMemo(() => { + try { + let res = step ? parseInt(step, 10) : 1; + res = Number.isInteger(res) ? res : 1; + res = res > 5 || res < 0 ? 1 : res; + return res; + } catch { + return 1; + } + }, [step]); + + const gotoStep = (stepIndex: number) => { + navigation.navigate("ProjectsMakeRequest", { step: stepIndex }); + }; + + const goNextStep = () => { + const nextStep = Math.min(stepIndex + 1, TOTAL_STEPS); + gotoStep(nextStep); + }; + + const goPrevStep = () => { + const prevStep = Math.max(stepIndex - 1, 1); + gotoStep(prevStep); + }; + + return { + ...store, + stepIndice: stepIndex, + actions: { + ...store.actions, + goNextStep, + goPrevStep, + gotoStep, + }, + }; +}; diff --git a/packages/screens/Projects/hooks/useProjects.ts b/packages/screens/Projects/hooks/useProjects.ts new file mode 100644 index 0000000000..66092791c3 --- /dev/null +++ b/packages/screens/Projects/hooks/useProjects.ts @@ -0,0 +1,114 @@ +import { GnoJSONRPCProvider } from "@gnolang/gno-js-client"; +import { useInfiniteQuery, useQuery } from "@tanstack/react-query"; +import { useMemo } from "react"; +import { z } from "zod"; + +import { + NetworkFeature, + getGnoNetwork, + getNetworkFeature, + parseNetworkObjectId, +} from "../../../networks"; +import { Project, zodProject } from "../types"; + +import { extractGnoJSONString } from "@/utils/gno"; + +export const useProject = (projectId: string | undefined) => { + return useQuery( + ["project", projectId], + async () => { + const [network, localIdentifierStr] = parseNetworkObjectId(projectId); + if (!network || !localIdentifierStr) { + return null; + } + + const gnoNetwork = getGnoNetwork(network.id); + if (!gnoNetwork) { + return null; + } + + const pmFeature = getNetworkFeature( + network.id, + NetworkFeature.GnoProjectManager, + ); + + if (!pmFeature) { + return null; + } + + const client = new GnoJSONRPCProvider(gnoNetwork.endpoint); + const query = `RenderContractJSON(${parseInt(localIdentifierStr, 10)})`; + const contractData = await client.evaluateExpression( + pmFeature.projectsManagerPkgPath, + query, + ); + + const j = extractGnoJSONString(contractData); + + return zodProject.parse(j); + }, + { staleTime: Infinity }, + ); +}; + +export type ProjectFilter = + | { byCandidatesForFunder: { funder: string } } + | { byFunder: { funder: string } } + | { byContractor: { contractor: string } } + | { byContractorAndFunder: { contractor: string; funder: string } } + | null; + +export const useProjects = ( + networkId: string, + filter: ProjectFilter = null, +) => { + const { data, ...other } = useInfiniteQuery<{ + projects: Project[]; + nextOffset: number; + }>( + ["projects", networkId, filter], + async ({ pageParam = 0 }) => { + const gnoNetwork = getGnoNetwork(networkId); + if (!gnoNetwork) { + return { projects: [], nextOffset: 0 }; + } + + const pmFeature = getNetworkFeature( + networkId, + NetworkFeature.GnoProjectManager, + ); + if (!pmFeature) { + return { projects: [], nextOffset: 0 }; + } + + const client = new GnoJSONRPCProvider(gnoNetwork.endpoint); + + const limit = 12; + + const pkgPath = pmFeature.projectsManagerPkgPath; + const expr = `RenderContractsJSON(${pageParam},${limit},${JSON.stringify(JSON.stringify(filter))})`; + + const contractsData = await client.evaluateExpression(pkgPath, expr); + + const j = extractGnoJSONString(contractsData); + + const projects = z.array(zodProject).parse(j); + + return { + projects, + nextOffset: pageParam + projects.length, + }; + }, + { + staleTime: Infinity, + getNextPageParam: ({ nextOffset }) => nextOffset, + }, + ); + + const projects = useMemo(() => { + if (!data) return []; + return data.pages.flatMap((page) => page.projects); + }, [data]); + + return { projects, ...other }; +}; diff --git a/packages/screens/Projects/hooks/useUtils.ts b/packages/screens/Projects/hooks/useUtils.ts new file mode 100644 index 0000000000..33951febea --- /dev/null +++ b/packages/screens/Projects/hooks/useUtils.ts @@ -0,0 +1,20 @@ +import { useFeedbacks } from "../../../context/FeedbacksProvider"; + +export const useUtils = () => { + const { setToast } = useFeedbacks(); + + const mustGetValue = (value?: string, name?: string) => { + if (!value) { + setToast({ + title: "Error", + type: "error", + mode: "normal", + message: `failed to get ${name || "value"}`, + }); + throw Error(`failed to get ${name || "value"}`); + } + return value; + }; + + return { mustGetValue }; +}; diff --git a/packages/screens/Projects/types.ts b/packages/screens/Projects/types.ts new file mode 100644 index 0000000000..dd3bf39376 --- /dev/null +++ b/packages/screens/Projects/types.ts @@ -0,0 +1,160 @@ +import * as zod from "zod"; +import { z } from "zod"; + +import { zodTryParseJSON } from "@/utils/sanitize"; + +const zodMilestonePriority = z.enum([ + "MS_PRIORITY_HIGH", + "MS_PRIORITY_MEDIUM", + "MS_PRIORITY_LOW", +]); + +export type MilestonePriority = z.infer; + +export const zodMilestoneFormValues = zod.object({ + id: zod.string().optional(), + title: zod + .string() + .min(3) + .regex(/^[^,]*$/, "Should not contain ,"), + desc: zod + .string() + .min(10) + .regex(/^[^,]*$/, "Should not contain ,"), + amount: zod.number().positive().int(), + priority: zodMilestonePriority, + link: zod.string().url().optional(), + duration: zod.number().min(1), +}); + +export type MilestoneFormValues = zod.infer; + +export interface MilestoneRequest { + title: string; + desc: string; + amount: string; + duration: string; + link: string; + priority: string; +} + +export const zodMilestoneStatus = z.enum([ + "MS_OPEN", + "MS_PROGRESS", + "MS_REVIEW", + "MS_COMPLETED", +]); + +export type MilestoneStatus = z.infer; + +const zodProjectMilestone = z.object({ + id: z.string(), + title: z.string(), + desc: z.string(), + amount: z.string(), + paid: z.string(), + duration: z.number(), // seconds + link: z.string(), + funded: z.boolean(), + priority: zodMilestonePriority, + status: zodMilestoneStatus, +}); + +export type ProjectMilestone = z.infer; + +export const previewMilestoneForm = (fm: MilestoneFormValues) => { + const m: ProjectMilestone = { + ...fm, + id: fm.id || "", + status: "MS_OPEN", + paid: "0", + amount: fm.amount.toString(), + link: fm.link || "", + funded: false, + }; + return m; +}; + +const zodContractStatus = z.enum([ + "CREATED", + "ACCEPTED", + "CANCELED", + "COMPLETED", + "REJECTED", + "CONFLICT", + "ABORTED_IN_FAVOR_OF_CONTRACTOR", + "ABORTED_IN_FAVOR_OF_FUNDER", +]); + +type ContractStatus = z.infer; + +export type ContractStatusFilter = ContractStatus | "ALL"; + +const zodConflictOutcome = z.enum([ + "RESUME_CONTRACT", + "REFUND_FUNDER", + "PAY_CONTRACTOR", +]); + +const zodConflict = z.object({ + initiator: z.string(), + createdAt: z.coerce.date(), + respondedAt: z.coerce.date().optional(), + resolvedAt: z.coerce.date().optional(), + initiatorMessage: z.string(), + responseMessage: z.string().optional(), + resolutionMessage: z.string().optional(), + outcome: zodConflictOutcome.optional(), +}); + +const zodProjectShortDescData = z.object({ + name: z.string().optional(), + desc: z.string().optional(), + coverImg: z.string().optional(), + tags: z.string().optional(), +}); + +export type ProjectShortDescData = z.infer; + +const zodProjectTeamAndLinkData = z.object({ + websiteLink: z.string().optional(), + twitterProfile: z.string().optional(), + discordLink: z.string().optional(), + githubLink: z.string().optional(), + teamDesc: z.string().optional(), +}); + +export type ProjectTeamAndLinkData = z.infer; + +const zodProjectMetadata = z.object({ + shortDescData: zodProjectShortDescData.optional(), + teamAndLinkData: zodProjectTeamAndLinkData.optional(), +}); + +export const zodProject = z.object({ + id: z.string(), + sender: z.string(), + contractor: z.string(), + contractorCandidates: z.array(z.string()), + funder: z.string(), + paymentDenom: z.string(), + metadata: z + .string() + .transform((data) => zodTryParseJSON(zodProjectMetadata, data)), + status: zodContractStatus, + expireAt: z.coerce.date(), + funderFeedback: z.string(), + contractorFeedback: z.string(), + milestones: z.array(zodProjectMilestone), + pausedBy: z.string(), + conflictHandler: z.string(), + handlerCandidate: z.string(), + handlerSuggestor: z.string(), + createdAt: z.coerce.date(), + budget: z.string(), + funded: z.boolean(), + rejectReason: z.string(), + conflicts: z.array(zodConflict), +}); + +export type Project = z.infer; diff --git a/packages/screens/Projects/utils.ts b/packages/screens/Projects/utils.ts new file mode 100644 index 0000000000..0dead50bc6 --- /dev/null +++ b/packages/screens/Projects/utils.ts @@ -0,0 +1,12 @@ +import { Project } from "./types"; + +export const getProjectStats = (project: Project) => { + if (!project.milestones) + return { completed: 0, total: 0, percentCompleted: 0 }; + const completed = project.milestones.filter( + (ms) => ms.status === "MS_COMPLETED", + ).length; + const total = project.milestones.length; + const percentCompleted = Math.floor((completed / total) * 100); + return { completed, total, percentCompleted }; +}; diff --git a/packages/screens/RiotGame/RiotGameEnrollScreen.tsx b/packages/screens/RiotGame/RiotGameEnrollScreen.tsx index 25d44550db..f10c954cca 100644 --- a/packages/screens/RiotGame/RiotGameEnrollScreen.tsx +++ b/packages/screens/RiotGame/RiotGameEnrollScreen.tsx @@ -9,7 +9,6 @@ import { useSelector } from "react-redux"; import { EnrollSlot } from "./component/EnrollSlot"; import { GameContentView } from "./component/GameContentView"; import { RipperSelectorModal } from "./component/RipperGridSelectorModal"; -import { SimpleButton } from "./component/SimpleButton"; import controllerSVG from "../../../assets/game/controller-yellow.svg"; import closeSVG from "../../../assets/icons/close.svg"; import useSelectedWallet from "../../hooks/useSelectedWallet"; @@ -18,6 +17,7 @@ import { NFT } from "@/api/marketplace/v1/marketplace"; import { BrandText } from "@/components/BrandText"; import { SVG } from "@/components/SVG"; import { LegacyTertiaryBox } from "@/components/boxes/LegacyTertiaryBox"; +import { SimpleButton } from "@/components/buttons/SimpleButton"; import { TertiaryButton } from "@/components/buttons/TertiaryButton"; import { useFeedbacks } from "@/context/FeedbacksProvider"; import { useAppNavigation } from "@/hooks/navigation/useAppNavigation"; diff --git a/packages/screens/RiotGame/component/FightSectionHeader.tsx b/packages/screens/RiotGame/component/FightSectionHeader.tsx index ca09a341f7..e3ae5e4e8b 100644 --- a/packages/screens/RiotGame/component/FightSectionHeader.tsx +++ b/packages/screens/RiotGame/component/FightSectionHeader.tsx @@ -1,11 +1,11 @@ import React from "react"; import { StyleSheet, View } from "react-native"; -import { SimpleButton } from "./SimpleButton"; import addCircleSVG from "../../../../assets/icons/add-circle.svg"; import FlexRow from "../../../components/FlexRow"; import { BrandText } from "@/components/BrandText"; +import { SimpleButton } from "@/components/buttons/SimpleButton"; import { useAppNavigation } from "@/hooks/navigation/useAppNavigation"; import { neutral17, yellowDefault } from "@/utils/style/colors"; import { fontMedium48, fontSemibold28 } from "@/utils/style/fonts"; diff --git a/packages/screens/RiotGame/component/RipperGridSelectorModal.tsx b/packages/screens/RiotGame/component/RipperGridSelectorModal.tsx index 486977a8c4..87c9b9b7b0 100644 --- a/packages/screens/RiotGame/component/RipperGridSelectorModal.tsx +++ b/packages/screens/RiotGame/component/RipperGridSelectorModal.tsx @@ -13,7 +13,6 @@ import { TouchableOpacity } from "react-native-gesture-handler"; import { RipperAvatar } from "./RipperAvatar"; import { RipperStatsSection } from "./RipperStatsSection"; -import { SimpleButton } from "./SimpleButton"; import controllerSVG from "../../../../assets/game/controller.svg"; import dashedBorderPNG from "../../../../assets/game/dashed-border.png"; import closeSVG from "../../../../assets/icons/close.svg"; @@ -23,6 +22,7 @@ import { NFT } from "@/api/marketplace/v1/marketplace"; import { BrandText } from "@/components/BrandText"; import { SVG } from "@/components/SVG"; import { LegacyTertiaryBox } from "@/components/boxes/LegacyTertiaryBox"; +import { SimpleButton } from "@/components/buttons/SimpleButton"; import { SpacerRow } from "@/components/spacer"; import { useIsMobile } from "@/hooks/useIsMobile"; import { getRipperRarity, isNFTStaked } from "@/utils/game"; diff --git a/packages/screens/RiotGame/component/RipperSelectorModal.tsx b/packages/screens/RiotGame/component/RipperSelectorModal.tsx index de66b52f93..6c3208e2d8 100644 --- a/packages/screens/RiotGame/component/RipperSelectorModal.tsx +++ b/packages/screens/RiotGame/component/RipperSelectorModal.tsx @@ -2,7 +2,7 @@ import { useEffect, useState } from "react"; import { Modal, ModalProps, - StyleSheet, + ViewStyle, View, ImageBackground, ScrollView, @@ -12,7 +12,6 @@ import { import { AvailableRippersGrid } from "./AvailableRippersGrid"; import { RipperAvatar } from "./RipperAvatar"; import { RipperStatsSection } from "./RipperStatsSection"; -import { SimpleButton } from "./SimpleButton"; import controllerSVG from "../../../../assets/game/controller.svg"; import dashedBorderPNG from "../../../../assets/game/dashed-border.png"; import closeSVG from "../../../../assets/icons/close.svg"; @@ -21,6 +20,7 @@ import FlexRow from "../../../components/FlexRow"; import { NFT } from "@/api/marketplace/v1/marketplace"; import { BrandText } from "@/components/BrandText"; import { SVG } from "@/components/SVG"; +import { SimpleButton } from "@/components/buttons/SimpleButton"; import { SpacerRow } from "@/components/spacer"; import { useBreeding } from "@/hooks/riotGame/useBreeding"; import { useIsMobile } from "@/hooks/useIsMobile"; @@ -89,8 +89,8 @@ export const RipperSelectorModal: React.FC = ({ visible={visible} {...props} > - - + + @@ -120,7 +120,7 @@ export const RipperSelectorModal: React.FC = ({ /> - + = ({ @@ -172,38 +172,38 @@ export const RipperSelectorModal: React.FC = ({ ); }; -// FIXME: remove StyleSheet.create -// eslint-disable-next-line no-restricted-syntax -const styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: withAlpha(neutral00, 0.95), - paddingTop: headerHeight, - borderWidth: 1, - }, - dashedBorder: { - width: RIPPER_IMAGE_SIZE, - height: RIPPER_IMAGE_SIZE, - marginTop: layout.spacing_x2_5, - }, - roundedContainer: { - width: RIPPER_IMAGE_SIZE - 4, - height: RIPPER_IMAGE_SIZE - 4, - position: "absolute", - left: 2, - top: 2, - borderRadius: 999, - overflow: "hidden", - }, - btnGroup: { - marginTop: layout.spacing_x2_5, - flexDirection: "row", - alignSelf: "center", - }, - closeIcon: { - position: "absolute", - right: 10, - top: 10, - zIndex: 1, - }, -}); +const styleContainer: ViewStyle = { + flex: 1, + backgroundColor: withAlpha(neutral00, 0.95), + paddingTop: headerHeight, + borderWidth: 1, +}; + +const styleDashedBorder: ViewStyle = { + width: RIPPER_IMAGE_SIZE, + height: RIPPER_IMAGE_SIZE, + marginTop: layout.spacing_x2_5, +}; + +const styleRoundedContainer: ViewStyle = { + width: RIPPER_IMAGE_SIZE - 4, + height: RIPPER_IMAGE_SIZE - 4, + position: "absolute", + left: 2, + top: 2, + borderRadius: 999, + overflow: "hidden", +}; + +const styleBtnGroup: ViewStyle = { + marginTop: layout.spacing_x2_5, + flexDirection: "row", + alignSelf: "center", +}; + +const styleCloseIcon: ViewStyle = { + position: "absolute", + right: 10, + top: 10, + zIndex: 1, +}; diff --git a/packages/screens/Settings/SettingsScreen.tsx b/packages/screens/Settings/SettingsScreen.tsx index bdcf8e0eb8..5deec15b2e 100644 --- a/packages/screens/Settings/SettingsScreen.tsx +++ b/packages/screens/Settings/SettingsScreen.tsx @@ -96,6 +96,7 @@ export const SettingsScreen: ScreenFC<"Settings"> = () => { description: "", state: testnetEnabled, }} + testID="testnet-switch" /> diff --git a/packages/screens/Settings/components/SettingItem.tsx b/packages/screens/Settings/components/SettingItem.tsx index 86f442b701..279f0d4884 100644 --- a/packages/screens/Settings/components/SettingItem.tsx +++ b/packages/screens/Settings/components/SettingItem.tsx @@ -12,11 +12,16 @@ export const SettingItem: React.FC<{ item: SettingItemType; onPress: (item: SettingItemType) => void; disabled?: boolean; -}> = ({ item, onPress, disabled }) => { + testID?: string; +}> = ({ item, onPress, disabled, testID }) => { const commonStyles = useCommonStyles(); return ( - onPress(item)} disabled={disabled}> + onPress(item)} + disabled={disabled} + testID={testID} + > {item.title} diff --git a/packages/scripts/addrFromMnemo.ts b/packages/scripts/addrFromMnemo.ts new file mode 100644 index 0000000000..bea781710f --- /dev/null +++ b/packages/scripts/addrFromMnemo.ts @@ -0,0 +1,27 @@ +import { GnoWallet } from "@gnolang/gno-js-client"; +import { program } from "commander"; + +import { NetworkKind, getNetwork } from "@/networks"; + +const main = async () => { + program.option("-n, --network ", "network"); + program.option("-m, --mnemonic ", "mnemonic"); + program.parse(); + const { network: networkId, mnemonic } = program.opts() as { + network: string; + mnemonic: string; + }; + const network = getNetwork(networkId); + if (!network) { + console.error(`Network "${networkId}" not found`); + return; + } + if (network.kind !== NetworkKind.Gno) { + console.error(`Only Gno networks are supported for now`); + } + const wallet = await GnoWallet.fromMnemonic(mnemonic); + const address = await wallet.getAddress(); + console.log(address); +}; + +main(); diff --git a/packages/scripts/gnoQuery.ts b/packages/scripts/gnoQuery.ts index 8a6f26f31c..779611a8b2 100644 --- a/packages/scripts/gnoQuery.ts +++ b/packages/scripts/gnoQuery.ts @@ -1,22 +1,34 @@ -import { GnoJSONRPCProvider } from "@gnolang/gno-js-client"; +import child_process from "child_process"; import { program } from "commander"; -import { gnoTeritoriNetwork } from "../networks/gno-teritori"; +import sqh from "./sqh"; + +import { getGnoNetwork } from "@/networks"; const main = async () => { + program.argument("network-id", "network id"); program.argument("realm", "realm pkg path"); program.argument("query", "eval query"); program.parse(); - const [realm, query] = program.args as [string, string]; - - const network = gnoTeritoriNetwork; - const provider = new GnoJSONRPCProvider(network.endpoint); - try { - const rawRes = await provider.evaluateExpression(realm, query); - console.log(rawRes); - } catch (e) { - console.error(JSON.stringify(e)); + const [networkId, realm, query] = program.args as [string, string, string]; + + const network = getGnoNetwork(networkId); + if (!network) { + console.error(`Network "${networkId}" not found`); + return; + } + + if (!realm) { + console.log("missing realm argument"); } + + if (!query) { + console.log("missing query argument"); + } + + const cmd = `gnokey query vm/qeval -remote ${sqh(network.endpoint)} -data ${sqh(`${realm}.${query}`)}`; + console.log("> " + cmd); + child_process.execSync(cmd, { stdio: "inherit" }); }; main(); diff --git a/packages/scripts/inject-projects.ts b/packages/scripts/inject-projects.ts new file mode 100644 index 0000000000..457682acbd --- /dev/null +++ b/packages/scripts/inject-projects.ts @@ -0,0 +1,113 @@ +import { faker } from "@faker-js/faker"; +import * as child_process from "child_process"; +import { program } from "commander"; +import { capitalize, range } from "lodash"; + +import sqh from "./sqh"; + +import { NetworkFeature, getGnoNetwork, getNetworkFeature } from "@/networks"; + +const main = async () => { + program + .option("-n, --network ", "Network ID") + .option("-w, --wallet ", "Wallet name") + .option("-c, --count ", "Number of projects to create") + .parse(); + + const opts = program.opts() as { + network: string; + wallet: string; + count: string; + }; + + const count = parseInt(opts.count, 10); + if (isNaN(count) || count <= 0) { + throw new Error("Invalid count"); + } + + const network = getGnoNetwork(opts.network); + if (!network) { + throw new Error("Network not found"); + } + const pmFeature = getNetworkFeature( + network.id, + NetworkFeature.GnoProjectManager, + ); + if (!pmFeature) { + throw new Error("Project manager feature not found"); + } + + console.log( + `Creating ${count} projects on ${network.displayName} with ${opts.wallet} wallet`, + ); + + for (let i = 0; i < count; i++) { + const teamAndLinkData: Record = {}; + + if (faker.helpers.maybe(() => true)) { + teamAndLinkData.websiteLink = faker.internet.url(); + } + if (faker.helpers.maybe(() => true)) { + teamAndLinkData.twitterProfile = + "@" + faker.person.firstName().toLowerCase(); + } + if (faker.helpers.maybe(() => true)) { + teamAndLinkData.discordLink = "https://discord.com"; + } + if (faker.helpers.maybe(() => true)) { + teamAndLinkData.githubLink = + "https://github.com/" + faker.person.firstName().toLowerCase(); + } + if (faker.helpers.maybe(() => true)) { + teamAndLinkData.teamDesc = faker.lorem.paragraph(); + } + + const metadata = { + shortDescData: { + name: faker.lorem.sentence(3).slice(0, -1), + desc: + capitalize(faker.hacker.phrase()) + + "\n\n" + + faker.lorem.paragraphs(10), + tags: [ + ...new Set( + range(0, faker.number.int({ min: 3, max: 10 })).map(() => + faker.hacker.noun(), + ), + ), + ].join(","), + coverImg: faker.image.urlPicsumPhotos(), + }, + teamAndLinkData, + }; + + const milestones = []; + for (let j = 0; j < faker.number.int({ min: 3, max: 6 }); j++) { + milestones.push({ + title: faker.lorem.sentence(3).slice(0, -1), + desc: faker.lorem.paragraphs(3), + priority: faker.helpers.arrayElement([ + "MS_PRIORITY_HIGH", + "MS_PRIORITY_MEDIUM", + "MS_PRIORITY_LOW", + ]), + amount: faker.number + .bigInt({ min: "420000", max: "4200000" }) + .toString(), + duration: faker.number.bigInt({ min: "3600", max: "36000" }).toString(), + link: faker.internet.url(), + }); + } + + const totalPrice = milestones.reduce( + (acc, m) => acc + BigInt(m.amount), + BigInt(0), + ); + + const cmd = `gnokey maketx call -insecure-password-stdin -pkgpath ${sqh(pmFeature.projectsManagerPkgPath)} -func "CreateContractJSON" -gas-fee 1000000ugnot -gas-wanted 10000000 -send "${totalPrice}ugnot" -broadcast -chainid ${sqh(network.chainId)} -args "" -args "g1xfjfdfyka23agew9g6qst030pr85q0ggac7vuj" -args ${sqh(pmFeature.paymentsDenom)} -args ${sqh(JSON.stringify(metadata))} -args "200000" -args ${sqh(JSON.stringify(milestones))} -args "g108cszmcvs4r3k67k7h5zuhm4el3qhlrxzhshtv" -remote ${sqh(network.endpoint)} ${sqh(opts.wallet)}`; + console.log(">", cmd); + child_process.execSync(cmd, { input: "\n" }); + } +}; + +main(); diff --git a/packages/scripts/install-gno.ts b/packages/scripts/install-gno.ts new file mode 100644 index 0000000000..66db6555c3 --- /dev/null +++ b/packages/scripts/install-gno.ts @@ -0,0 +1,18 @@ +import child_process from "child_process"; +import fs from "fs/promises"; +import os from "os"; +import path from "path"; + +import sqh from "./sqh"; + +const ref = "fec2d18f630b44ccc2121472aa2284cd9c8caf6f"; +const remote = "https://github.com/gnolang/gno.git"; + +const main = async () => { + const buildDir = await fs.mkdtemp(path.join(os.tmpdir(), "gno-build-")); + const cmd = `git clone ${sqh(remote)} ${sqh(buildDir)} && cd ${sqh(buildDir)} && git checkout ${sqh(ref)} && make install`; + console.log(">", cmd); + child_process.execSync(cmd, { stdio: "inherit" }); +}; + +main(); diff --git a/packages/scripts/validateNetworks.ts b/packages/scripts/validateNetworks.ts index 13d81ed592..37fae66237 100644 --- a/packages/scripts/validateNetworks.ts +++ b/packages/scripts/validateNetworks.ts @@ -1,5 +1,7 @@ import { allNetworks, getNativeCurrency, NetworkKind } from "../networks"; +import { allFeatureObjects } from "@/networks/features"; + const ids: { [key: string]: boolean } = {}; const idPrefixes: { [key: string]: boolean } = {}; const cosmosChainIds: { [key: string]: boolean } = {}; @@ -94,6 +96,22 @@ for (const net of allNetworks) { `feature object '${feature.type}' of network '${net.id}' does not have a corresponding feature declaration`, ); } + const zodFeatureObj = allFeatureObjects.find( + (zo) => zo.shape.type.value === feature.type, + ); + if (!zodFeatureObj) { + throw new Error( + `feature object '${feature.type}' of network '${net.id}' does not have a corresponding zod declaration`, + ); + } + try { + zodFeatureObj.parse(feature); + } catch (e) { + const msg = e instanceof Error ? e.message : JSON.stringify(e, null, 2); + throw new Error( + `feature object '${feature.type}' of network '${net.id}' does not match the zod declaration: ${msg}`, + ); + } featureObjects[feature.type] = true; } } diff --git a/packages/utils/gno.ts b/packages/utils/gno.ts index 99612d9f86..ca966e119d 100644 --- a/packages/utils/gno.ts +++ b/packages/utils/gno.ts @@ -7,7 +7,7 @@ interface AdenaDoContractMessage { value: { [key in string]: any }; } -interface RequestDocontractMessage { +export interface RequestDocontractMessage { messages: AdenaDoContractMessage[]; gasFee: number; gasWanted: number; diff --git a/packages/utils/navigation.ts b/packages/utils/navigation.ts index 5b410d972f..b8309a3a87 100644 --- a/packages/utils/navigation.ts +++ b/packages/utils/navigation.ts @@ -82,6 +82,14 @@ export type RootStackParamList = { Settings: undefined; + Projects?: { network?: string }; + ProjectsManager: { view?: string }; + ProjectsPayment: { projectId: string; milestoneId: string }; + ProjectsCompleteMilestone: { projectId: string; milestoneId: string }; + ProjectsMakeRequest: { step?: number }; + ProjectsDetail: { id: string }; + ProjectsConflictSolving: { projectId: string }; + OrganizationDeployer: undefined; Organizations?: { network?: string }; CoreDAO: undefined; @@ -230,6 +238,15 @@ const navConfig: { Organizations: "orgs", CoreDAO: "core-dao", + // === Projects Program + Projects: "projects", + ProjectsPayment: "projects/payment", + ProjectsCompleteMilestone: + "projects/completeMilestone/:projectId/:milestoneId", + ProjectsManager: "projects/manager/:view", + ProjectsMakeRequest: "projects/make-request", + ProjectsDetail: "projects/:id", + ProjectsConflictSolving: "projects/:projectId/conflicts", // === Organization OrganizationGetStarted: "organization-get-started", diff --git a/packages/utils/sidebar.ts b/packages/utils/sidebar.ts index 05b2227334..ecd93d68d5 100644 --- a/packages/utils/sidebar.ts +++ b/packages/utils/sidebar.ts @@ -12,6 +12,7 @@ import messagesSVG from "../../assets/icons/messages.svg"; import multisigSVG from "../../assets/icons/multisig.svg"; import osmosisCircleSVG from "../../assets/icons/networks/osmosis-circle.svg"; import pathwarSVG from "../../assets/icons/pathwar.svg"; +import projectsProgramSVG from "../../assets/icons/projects-program.svg"; import riotersGameSVG from "../../assets/icons/rioters-game.svg"; import stakingSVG from "../../assets/icons/staking.svg"; import tnsServiceSVG from "../../assets/icons/tns-service.svg"; @@ -123,6 +124,12 @@ export const SIDEBAR_LIST: SidebarRecordType = { route: "RiotGame", icon: riotersGameSVG, }, + projectsProgram: { + title: "Projects Program", + id: "Projects Program", + route: "Projects", + icon: projectsProgramSVG, + }, riotersFooter: { title: "Rioters Footer", id: "Rioters Footer", diff --git a/packages/utils/style/colors.ts b/packages/utils/style/colors.ts index e88e9fb716..da6c983192 100644 --- a/packages/utils/style/colors.ts +++ b/packages/utils/style/colors.ts @@ -42,6 +42,7 @@ export const neutral77 = "#777777"; export const neutral88 = "#888888"; export const neutral99 = "#999999"; export const neutralA3 = "#A3A3A3"; +export const neutralFF = "#FFFFFF"; export const transparentColor = "transparent"; export const additionalRed = "#FFAEAE"; diff --git a/packages/utils/types/dapp-store.ts b/packages/utils/types/dapp-store.ts index 4dc08b1fe9..c58082f197 100644 --- a/packages/utils/types/dapp-store.ts +++ b/packages/utils/types/dapp-store.ts @@ -13,6 +13,7 @@ export interface dAppType { selectedByDefault: boolean; alwaysOn: boolean; order?: number; + devOnly?: boolean; } export interface dAppGroup { diff --git a/packages/utils/wallet/getNativeWallet.ts b/packages/utils/wallet/getNativeWallet.ts index aac55fe3ae..2480aa6a93 100644 --- a/packages/utils/wallet/getNativeWallet.ts +++ b/packages/utils/wallet/getNativeWallet.ts @@ -1,5 +1,5 @@ import { Secp256k1HdWallet } from "@cosmjs/amino"; -import { stringToPath } from "@cosmjs/amino/node_modules/@cosmjs/crypto/build/slip10"; +import { stringToPath } from "@cosmjs/crypto"; import { getValueFor, remove, save } from "./secure-store"; diff --git a/packages/utils/walletProvider.ts b/packages/utils/walletProvider.ts index 2fa980676c..e9554fb221 100644 --- a/packages/utils/walletProvider.ts +++ b/packages/utils/walletProvider.ts @@ -6,4 +6,5 @@ export enum WalletProvider { Adena = "Adena", Store = "Store", Native = "Native", + Gnotest = "Gnotest", } diff --git a/paralint.json b/paralint.json index 83e70cc65b..c979d64a46 100644 --- a/paralint.json +++ b/paralint.json @@ -1,6 +1,6 @@ { "eslint": "eslint --cache --ext .js,.jsx,.ts,.tsx .", - "tsc": "tsc", + "tsc": "tsc --pretty", "depcheck": "depcheck", "unused-exports": "yarn unused-exports", "validate-networks": "yarn validate-networks", diff --git a/tsconfig.json b/tsconfig.json index f37d0c7b51..c838cfa151 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,6 @@ { "extends": "expo/tsconfig.base", - "target": "ES5", + "target": "ES6", "compilerOptions": { "useDefineForClassFields": false, // this is needed by cosmwasm-ts-codegen clients "strict": true, diff --git a/yarn.lock b/yarn.lock index 299fa27f09..fd2b420606 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2170,6 +2170,13 @@ __metadata: languageName: node linkType: hard +"@colors/colors@npm:1.5.0": + version: 1.5.0 + resolution: "@colors/colors@npm:1.5.0" + checksum: d64d5260bed1d5012ae3fc617d38d1afc0329fec05342f4e6b838f46998855ba56e0a73833f4a80fa8378c84810da254f76a8a19c39d038260dc06dc4e007425 + languageName: node + linkType: hard + "@confio/ics23@npm:^0.6.8": version: 0.6.8 resolution: "@confio/ics23@npm:0.6.8" @@ -2288,6 +2295,21 @@ __metadata: languageName: node linkType: hard +"@cosmjs/crypto@npm:0.32.2, @cosmjs/crypto@npm:^0.32.2": + version: 0.32.2 + resolution: "@cosmjs/crypto@npm:0.32.2" + dependencies: + "@cosmjs/encoding": ^0.32.2 + "@cosmjs/math": ^0.32.2 + "@cosmjs/utils": ^0.32.2 + "@noble/hashes": ^1 + bn.js: ^5.2.0 + elliptic: ^6.5.4 + libsodium-wrappers-sumo: ^0.7.11 + checksum: 7600bd48f718b8c352038bf96af325b9597310ccf51d2885bba4603a567b52d59446d193288f519ddf354a8668bd0ffba899c518642b3c9bb039bf24a7261faa + languageName: node + linkType: hard + "@cosmjs/crypto@npm:^0.29.3, @cosmjs/crypto@npm:^0.29.5": version: 0.29.5 resolution: "@cosmjs/crypto@npm:0.29.5" @@ -2318,21 +2340,6 @@ __metadata: languageName: node linkType: hard -"@cosmjs/crypto@npm:^0.32.2": - version: 0.32.2 - resolution: "@cosmjs/crypto@npm:0.32.2" - dependencies: - "@cosmjs/encoding": ^0.32.2 - "@cosmjs/math": ^0.32.2 - "@cosmjs/utils": ^0.32.2 - "@noble/hashes": ^1 - bn.js: ^5.2.0 - elliptic: ^6.5.4 - libsodium-wrappers-sumo: ^0.7.11 - checksum: 7600bd48f718b8c352038bf96af325b9597310ccf51d2885bba4603a567b52d59446d193288f519ddf354a8668bd0ffba899c518642b3c9bb039bf24a7261faa - languageName: node - linkType: hard - "@cosmjs/crypto@npm:^0.32.4": version: 0.32.4 resolution: "@cosmjs/crypto@npm:0.32.4" @@ -2359,6 +2366,17 @@ __metadata: languageName: node linkType: hard +"@cosmjs/encoding@npm:0.32.2, @cosmjs/encoding@npm:^0.32.2": + version: 0.32.2 + resolution: "@cosmjs/encoding@npm:0.32.2" + dependencies: + base64-js: ^1.3.0 + bech32: ^1.1.4 + readonly-date: ^1.0.0 + checksum: a9ee00b730aa7f422cf3946097cb96a0c9d5d7a9f6b3aa31d8e96e4f815220928226ae2133b76e835c781df0231e9691c8ebf1c98f68468e2f936a1d431e4c30 + languageName: node + linkType: hard + "@cosmjs/encoding@npm:^0.20.0": version: 0.20.1 resolution: "@cosmjs/encoding@npm:0.20.1" @@ -2392,17 +2410,6 @@ __metadata: languageName: node linkType: hard -"@cosmjs/encoding@npm:^0.32.2": - version: 0.32.2 - resolution: "@cosmjs/encoding@npm:0.32.2" - dependencies: - base64-js: ^1.3.0 - bech32: ^1.1.4 - readonly-date: ^1.0.0 - checksum: a9ee00b730aa7f422cf3946097cb96a0c9d5d7a9f6b3aa31d8e96e4f815220928226ae2133b76e835c781df0231e9691c8ebf1c98f68468e2f936a1d431e4c30 - languageName: node - linkType: hard - "@cosmjs/encoding@npm:^0.32.4": version: 0.32.4 resolution: "@cosmjs/encoding@npm:0.32.4" @@ -2493,6 +2500,15 @@ __metadata: languageName: node linkType: hard +"@cosmjs/math@npm:0.32.2, @cosmjs/math@npm:^0.32.2": + version: 0.32.2 + resolution: "@cosmjs/math@npm:0.32.2" + dependencies: + bn.js: ^5.2.0 + checksum: 3ea9c811d1b53b61f24c10ae4e3707fb7f926194202e5c57ea5aa1a41996ffc872ce5599967f74cc6f289d30e064d372b7ff30c1128d682847b865ca597aca59 + languageName: node + linkType: hard + "@cosmjs/math@npm:^0.20.0": version: 0.20.1 resolution: "@cosmjs/math@npm:0.20.1" @@ -2520,15 +2536,6 @@ __metadata: languageName: node linkType: hard -"@cosmjs/math@npm:^0.32.2": - version: 0.32.2 - resolution: "@cosmjs/math@npm:0.32.2" - dependencies: - bn.js: ^5.2.0 - checksum: 3ea9c811d1b53b61f24c10ae4e3707fb7f926194202e5c57ea5aa1a41996ffc872ce5599967f74cc6f289d30e064d372b7ff30c1128d682847b865ca597aca59 - languageName: node - linkType: hard - "@cosmjs/math@npm:^0.32.4": version: 0.32.4 resolution: "@cosmjs/math@npm:0.32.4" @@ -2915,6 +2922,42 @@ __metadata: languageName: node linkType: hard +"@cypress/request@npm:^3.0.0": + version: 3.0.1 + resolution: "@cypress/request@npm:3.0.1" + dependencies: + aws-sign2: ~0.7.0 + aws4: ^1.8.0 + caseless: ~0.12.0 + combined-stream: ~1.0.6 + extend: ~3.0.2 + forever-agent: ~0.6.1 + form-data: ~2.3.2 + http-signature: ~1.3.6 + is-typedarray: ~1.0.0 + isstream: ~0.1.2 + json-stringify-safe: ~5.0.1 + mime-types: ~2.1.19 + performance-now: ^2.1.0 + qs: 6.10.4 + safe-buffer: ^5.1.2 + tough-cookie: ^4.1.3 + tunnel-agent: ^0.6.0 + uuid: ^8.3.2 + checksum: 7175522ebdbe30e3c37973e204c437c23ce659e58d5939466615bddcd58d778f3a8ea40f087b965ae8b8138ea8d102b729c6eb18c6324f121f3778f4a2e8e727 + languageName: node + linkType: hard + +"@cypress/xvfb@npm:^1.2.4": + version: 1.2.4 + resolution: "@cypress/xvfb@npm:1.2.4" + dependencies: + debug: ^3.1.0 + lodash.once: ^4.1.1 + checksum: 7bdcdaeb1bb692ec9d9bf8ec52538aa0bead6764753f4a067a171a511807a43fab016f7285a56bef6a606c2467ff3f1365e1ad2d2d583b81beed849ee1573fd1 + languageName: node + linkType: hard + "@dotlottie/common@npm:0.7.9": version: 0.7.9 resolution: "@dotlottie/common@npm:0.7.9" @@ -4213,6 +4256,13 @@ __metadata: languageName: node linkType: hard +"@faker-js/faker@npm:^8.4.1": + version: 8.4.1 + resolution: "@faker-js/faker@npm:8.4.1" + checksum: d802d531f8929562715adc279cfec763c9a4bc596ec67b0ce43fd0ae61b285d2b0eec6f1f4aa852452a63721a842fe7e81926dce7bd92acca94b01e2a1f55f5a + languageName: node + linkType: hard + "@gar/promisify@npm:^1.0.1": version: 1.1.3 resolution: "@gar/promisify@npm:1.1.3" @@ -4291,6 +4341,15 @@ __metadata: languageName: node linkType: hard +"@hookform/resolvers@npm:^3.6.0": + version: 3.6.0 + resolution: "@hookform/resolvers@npm:3.6.0" + peerDependencies: + react-hook-form: ^7.0.0 + checksum: a230fd2d0b571ddb8795f587284211e17f942de6b75ba235f613f54d3c17561e3a6483deee48c7dd5a6f52131769c5e59e4ed04823447084c28b6191d7e2d9dd + languageName: node + linkType: hard + "@humanwhocodes/config-array@npm:^0.11.13": version: 0.11.14 resolution: "@humanwhocodes/config-array@npm:0.11.14" @@ -5673,6 +5732,16 @@ __metadata: languageName: node linkType: hard +"@react-native-picker/picker@npm:2.6.1": + version: 2.6.1 + resolution: "@react-native-picker/picker@npm:2.6.1" + peerDependencies: + react: ">=16" + react-native: ">=0.57" + checksum: a8c58d5d945350b70fd8b5d66dfe97dd04641277db7c702912d8c41ae4da94cfef8b0b73bfa493adfdee8f089af6e0316872c3ee61a4efc18528e6e25a5452bc + languageName: node + linkType: hard + "@react-native/assets-registry@npm:0.73.1, @react-native/assets-registry@npm:~0.73.1": version: 0.73.1 resolution: "@react-native/assets-registry@npm:0.73.1" @@ -6825,6 +6894,20 @@ __metadata: languageName: node linkType: hard +"@types/sinonjs__fake-timers@npm:8.1.1": + version: 8.1.1 + resolution: "@types/sinonjs__fake-timers@npm:8.1.1" + checksum: ca09d54d47091d87020824a73f026300fa06b17cd9f2f9b9387f28b549364b141ef194ee28db762f6588de71d8febcd17f753163cb7ea116b8387c18e80ebd5c + languageName: node + linkType: hard + +"@types/sizzle@npm:^2.3.2": + version: 2.3.8 + resolution: "@types/sizzle@npm:2.3.8" + checksum: 2ac62443dc917f5f903cbd9afc51c7d6cc1c6569b4e1a15faf04aea5b13b486e7f208650014c3dc4fed34653eded3e00fe5abffe0e6300cbf0e8a01beebf11a6 + languageName: node + linkType: hard + "@types/stack-utils@npm:^2.0.0": version: 2.0.3 resolution: "@types/stack-utils@npm:2.0.3" @@ -7339,6 +7422,13 @@ __metadata: languageName: node linkType: hard +"ansi-colors@npm:^4.1.1": + version: 4.1.3 + resolution: "ansi-colors@npm:4.1.3" + checksum: a9c2ec842038a1fabc7db9ece7d3177e2fe1c5dc6f0c51ecfbf5f39911427b89c00b5dc6b8bd95f82a26e9b16aaae2e83d45f060e98070ce4d1333038edceb0e + languageName: node + linkType: hard + "ansi-escapes@npm:^2.0.0": version: 2.0.0 resolution: "ansi-escapes@npm:2.0.0" @@ -7353,7 +7443,7 @@ __metadata: languageName: node linkType: hard -"ansi-escapes@npm:^4.2.1, ansi-escapes@npm:^4.3.2": +"ansi-escapes@npm:^4.2.1, ansi-escapes@npm:^4.3.0, ansi-escapes@npm:^4.3.2": version: 4.3.2 resolution: "ansi-escapes@npm:4.3.2" dependencies: @@ -7487,6 +7577,13 @@ __metadata: languageName: node linkType: hard +"arch@npm:^2.2.0": + version: 2.2.0 + resolution: "arch@npm:2.2.0" + checksum: e21b7635029fe8e9cdd5a026f9a6c659103e63fff423834323cdf836a1bb240a72d0c39ca8c470f84643385cf581bd8eda2cad8bf493e27e54bd9783abe9101f + languageName: node + linkType: hard + "arg@npm:5.0.2": version: 5.0.2 resolution: "arg@npm:5.0.2" @@ -7638,6 +7735,22 @@ __metadata: languageName: node linkType: hard +"asn1@npm:~0.2.3": + version: 0.2.6 + resolution: "asn1@npm:0.2.6" + dependencies: + safer-buffer: ~2.1.0 + checksum: 39f2ae343b03c15ad4f238ba561e626602a3de8d94ae536c46a4a93e69578826305366dc09fbb9b56aec39b4982a463682f259c38e59f6fa380cd72cd61e493d + languageName: node + linkType: hard + +"assert-plus@npm:1.0.0, assert-plus@npm:^1.0.0": + version: 1.0.0 + resolution: "assert-plus@npm:1.0.0" + checksum: 19b4340cb8f0e6a981c07225eacac0e9d52c2644c080198765d63398f0075f83bbc0c8e95474d54224e297555ad0d631c1dcd058adb1ddc2437b41a6b424ac64 + languageName: node + linkType: hard + "assert@npm:^2.1.0": version: 2.1.0 resolution: "assert@npm:2.1.0" @@ -7676,6 +7789,13 @@ __metadata: languageName: node linkType: hard +"astral-regex@npm:^2.0.0": + version: 2.0.0 + resolution: "astral-regex@npm:2.0.0" + checksum: 876231688c66400473ba505731df37ea436e574dd524520294cc3bbc54ea40334865e01fa0d074d74d036ee874ee7e62f486ea38bc421ee8e6a871c06f011766 + languageName: node + linkType: hard + "async-limiter@npm:~1.0.0": version: 1.0.1 resolution: "async-limiter@npm:1.0.1" @@ -7683,6 +7803,13 @@ __metadata: languageName: node linkType: hard +"async@npm:^3.2.0": + version: 3.2.5 + resolution: "async@npm:3.2.5" + checksum: 5ec77f1312301dee02d62140a6b1f7ee0edd2a0f983b6fd2b0849b969f245225b990b47b8243e7b9ad16451a53e7f68e753700385b706198ced888beedba3af4 + languageName: node + linkType: hard + "asynciterator.prototype@npm:^1.0.0": version: 1.0.0 resolution: "asynciterator.prototype@npm:1.0.0" @@ -7720,6 +7847,20 @@ __metadata: languageName: node linkType: hard +"aws-sign2@npm:~0.7.0": + version: 0.7.0 + resolution: "aws-sign2@npm:0.7.0" + checksum: b148b0bb0778098ad8cf7e5fc619768bcb51236707ca1d3e5b49e41b171166d8be9fdc2ea2ae43d7decf02989d0aaa3a9c4caa6f320af95d684de9b548a71525 + languageName: node + linkType: hard + +"aws4@npm:^1.8.0": + version: 1.12.0 + resolution: "aws4@npm:1.12.0" + checksum: 68f79708ac7c335992730bf638286a3ee0a645cf12575d557860100767c500c08b30e24726b9f03265d74116417f628af78509e1333575e9f8d52a80edfe8cbc + languageName: node + linkType: hard + "axios@npm:0.21.1": version: 0.21.1 resolution: "axios@npm:0.21.1" @@ -8014,6 +8155,15 @@ __metadata: languageName: node linkType: hard +"bcrypt-pbkdf@npm:^1.0.0": + version: 1.0.2 + resolution: "bcrypt-pbkdf@npm:1.0.2" + dependencies: + tweetnacl: ^0.14.3 + checksum: 4edfc9fe7d07019609ccf797a2af28351736e9d012c8402a07120c4453a3b789a15f2ee1530dc49eee8f7eb9379331a8dd4b3766042b9e502f74a68e7f662291 + languageName: node + linkType: hard + "bech32@npm:1.1.4, bech32@npm:^1.1.3, bech32@npm:^1.1.4": version: 1.1.4 resolution: "bech32@npm:1.1.4" @@ -8097,6 +8247,20 @@ __metadata: languageName: node linkType: hard +"blob-util@npm:^2.0.2": + version: 2.0.2 + resolution: "blob-util@npm:2.0.2" + checksum: d543e6b92e4ca715ca33c78e89a07a2290d43e5b2bc897d7ec588c5c7bbf59df93e45225ac0c9258aa6ce4320358990f99c9288f1c48280f8ec5d7a2e088d19b + languageName: node + linkType: hard + +"bluebird@npm:^3.7.2": + version: 3.7.2 + resolution: "bluebird@npm:3.7.2" + checksum: 869417503c722e7dc54ca46715f70e15f4d9c602a423a02c825570862d12935be59ed9c7ba34a9b31f186c017c23cac6b54e35446f8353059c101da73eac22ef + languageName: node + linkType: hard + "blueimp-md5@npm:^2.10.0": version: 2.19.0 resolution: "blueimp-md5@npm:2.19.0" @@ -8365,7 +8529,7 @@ __metadata: languageName: node linkType: hard -"buffer@npm:^5.4.3, buffer@npm:^5.5.0, buffer@npm:^5.6.0": +"buffer@npm:^5.4.3, buffer@npm:^5.5.0, buffer@npm:^5.6.0, buffer@npm:^5.7.1": version: 5.7.1 resolution: "buffer@npm:5.7.1" dependencies: @@ -8477,6 +8641,13 @@ __metadata: languageName: node linkType: hard +"cachedir@npm:^2.3.0": + version: 2.4.0 + resolution: "cachedir@npm:2.4.0" + checksum: 43198514eaa61f65b5535ed29ad651f22836fba3868ed58a6a87731f05462f317d39098fa3ac778801c25455483c9b7f32a2fcad1f690a978947431f12a0f4d0 + languageName: node + linkType: hard + "call-bind@npm:^1.0.0, call-bind@npm:^1.0.2, call-bind@npm:^1.0.4, call-bind@npm:^1.0.5": version: 1.0.5 resolution: "call-bind@npm:1.0.5" @@ -8569,6 +8740,13 @@ __metadata: languageName: node linkType: hard +"caseless@npm:~0.12.0": + version: 0.12.0 + resolution: "caseless@npm:0.12.0" + checksum: b43bd4c440aa1e8ee6baefee8063b4850fd0d7b378f6aabc796c9ec8cb26d27fb30b46885350777d9bd079c5256c0e1329ad0dc7c2817e0bb466810ebb353751 + languageName: node + linkType: hard + "chain-registry@npm:1.10.0": version: 1.10.0 resolution: "chain-registry@npm:1.10.0" @@ -8644,6 +8822,13 @@ __metadata: languageName: node linkType: hard +"check-more-types@npm:^2.24.0": + version: 2.24.0 + resolution: "check-more-types@npm:2.24.0" + checksum: b09080ec3404d20a4b0ead828994b2e5913236ef44ed3033a27062af0004cf7d2091fbde4b396bf13b7ce02fb018bc9960b48305e6ab2304cd82d73ed7a51ef4 + languageName: node + linkType: hard + "chownr@npm:^2.0.0": version: 2.0.0 resolution: "chownr@npm:2.0.0" @@ -8797,6 +8982,29 @@ __metadata: languageName: node linkType: hard +"cli-table3@npm:~0.6.1": + version: 0.6.5 + resolution: "cli-table3@npm:0.6.5" + dependencies: + "@colors/colors": 1.5.0 + string-width: ^4.2.0 + dependenciesMeta: + "@colors/colors": + optional: true + checksum: ab7afbf4f8597f1c631f3ee6bb3481d0bfeac8a3b81cffb5a578f145df5c88003b6cfff46046a7acae86596fdd03db382bfa67f20973b6b57425505abc47e42c + languageName: node + linkType: hard + +"cli-truncate@npm:^2.1.0": + version: 2.1.0 + resolution: "cli-truncate@npm:2.1.0" + dependencies: + slice-ansi: ^3.0.0 + string-width: ^4.2.0 + checksum: bf1e4e6195392dc718bf9cd71f317b6300dc4a9191d052f31046b8773230ece4fa09458813bf0e3455a5e68c0690d2ea2c197d14a8b85a7b5e01c97f4b5feb5d + languageName: node + linkType: hard + "cli-truncate@npm:^4.0.0": version: 4.0.0 resolution: "cli-truncate@npm:4.0.0" @@ -8964,7 +9172,7 @@ __metadata: languageName: node linkType: hard -"colorette@npm:^2.0.20": +"colorette@npm:^2.0.16, colorette@npm:^2.0.20": version: 2.0.20 resolution: "colorette@npm:2.0.20" checksum: 0c016fea2b91b733eb9f4bcdb580018f52c0bc0979443dad930e5037a968237ac53d9beb98e218d2e9235834f8eebce7f8e080422d6194e957454255bde71d3d @@ -8978,7 +9186,7 @@ __metadata: languageName: node linkType: hard -"combined-stream@npm:^1.0.6, combined-stream@npm:^1.0.8": +"combined-stream@npm:^1.0.6, combined-stream@npm:^1.0.8, combined-stream@npm:~1.0.6": version: 1.0.8 resolution: "combined-stream@npm:1.0.8" dependencies: @@ -9015,6 +9223,13 @@ __metadata: languageName: node linkType: hard +"commander@npm:^6.2.1": + version: 6.2.1 + resolution: "commander@npm:6.2.1" + checksum: d7090410c0de6bc5c67d3ca41c41760d6d268f3c799e530aafb73b7437d1826bbf0d2a3edac33f8b57cc9887b4a986dce307fa5557e109be40eadb7c43b21742 + languageName: node + linkType: hard + "commander@npm:^7.2.0": version: 7.2.0 resolution: "commander@npm:7.2.0" @@ -9029,6 +9244,13 @@ __metadata: languageName: node linkType: hard +"common-tags@npm:^1.8.0": + version: 1.8.2 + resolution: "common-tags@npm:1.8.2" + checksum: 767a6255a84bbc47df49a60ab583053bb29a7d9687066a18500a516188a062c4e4cd52de341f22de0b07062e699b1b8fe3cfa1cb55b241cb9301aeb4f45b4dff + languageName: node + linkType: hard + "commondir@npm:^1.0.1": version: 1.0.1 resolution: "commondir@npm:1.0.1" @@ -9134,6 +9356,13 @@ __metadata: languageName: node linkType: hard +"core-util-is@npm:1.0.2": + version: 1.0.2 + resolution: "core-util-is@npm:1.0.2" + checksum: 7a4c925b497a2c91421e25bf76d6d8190f0b2359a9200dbeed136e63b2931d6294d3b1893eda378883ed363cd950f44a12a401384c609839ea616befb7927dab + languageName: node + linkType: hard + "core-util-is@npm:~1.0.0": version: 1.0.3 resolution: "core-util-is@npm:1.0.3" @@ -9440,6 +9669,58 @@ __metadata: languageName: node linkType: hard +"cypress@npm:^13.9.0": + version: 13.9.0 + resolution: "cypress@npm:13.9.0" + dependencies: + "@cypress/request": ^3.0.0 + "@cypress/xvfb": ^1.2.4 + "@types/sinonjs__fake-timers": 8.1.1 + "@types/sizzle": ^2.3.2 + arch: ^2.2.0 + blob-util: ^2.0.2 + bluebird: ^3.7.2 + buffer: ^5.7.1 + cachedir: ^2.3.0 + chalk: ^4.1.0 + check-more-types: ^2.24.0 + cli-cursor: ^3.1.0 + cli-table3: ~0.6.1 + commander: ^6.2.1 + common-tags: ^1.8.0 + dayjs: ^1.10.4 + debug: ^4.3.4 + enquirer: ^2.3.6 + eventemitter2: 6.4.7 + execa: 4.1.0 + executable: ^4.1.1 + extract-zip: 2.0.1 + figures: ^3.2.0 + fs-extra: ^9.1.0 + getos: ^3.2.1 + is-ci: ^3.0.1 + is-installed-globally: ~0.4.0 + lazy-ass: ^1.6.0 + listr2: ^3.8.3 + lodash: ^4.17.21 + log-symbols: ^4.0.0 + minimist: ^1.2.8 + ospath: ^1.2.2 + pretty-bytes: ^5.6.0 + process: ^0.11.10 + proxy-from-env: 1.0.0 + request-progress: ^3.0.0 + semver: ^7.5.3 + supports-color: ^8.1.1 + tmp: ~0.2.1 + untildify: ^4.0.0 + yauzl: ^2.10.0 + bin: + cypress: bin/cypress + checksum: ec2e0237d2a38d53d4e5c05fe1c37f7fe0bb13de798045ba091b6a5cf0edd7b3a282f4d8f4c063e3988ee048d06dcf4fef91d83d63a56cee9f9ff68685f3946d + languageName: node + linkType: hard + "d3-array@npm:2 - 3, d3-array@npm:2.10.0 - 3, d3-array@npm:^3.1.6": version: 3.2.4 resolution: "d3-array@npm:3.2.4" @@ -9564,6 +9845,22 @@ __metadata: languageName: node linkType: hard +"dashdash@npm:^1.12.0": + version: 1.14.1 + resolution: "dashdash@npm:1.14.1" + dependencies: + assert-plus: ^1.0.0 + checksum: 3634c249570f7f34e3d34f866c93f866c5b417f0dd616275decae08147dcdf8fccfaa5947380ccfb0473998ea3a8057c0b4cd90c875740ee685d0624b2983598 + languageName: node + linkType: hard + +"dayjs@npm:^1.10.4": + version: 1.11.11 + resolution: "dayjs@npm:1.11.11" + checksum: 84788275aad8a87fee4f1ce4be08861df29687aae6b7b43dd65350118a37dda56772a3902f802cb2dc651dfed447a5a8df62d88f0fb900dba8333e411190a5d5 + languageName: node + linkType: hard + "dayjs@npm:^1.8.15": version: 1.11.10 resolution: "dayjs@npm:1.11.10" @@ -10092,6 +10389,16 @@ __metadata: languageName: node linkType: hard +"ecc-jsbn@npm:~0.1.1": + version: 0.1.2 + resolution: "ecc-jsbn@npm:0.1.2" + dependencies: + jsbn: ~0.1.0 + safer-buffer: ^2.1.0 + checksum: 22fef4b6203e5f31d425f5b711eb389e4c6c2723402e389af394f8411b76a488fa414d309d866e2b577ce3e8462d344205545c88a8143cc21752a5172818888a + languageName: node + linkType: hard + "ee-first@npm:1.1.1": version: 1.1.1 resolution: "ee-first@npm:1.1.1" @@ -10224,6 +10531,16 @@ __metadata: languageName: node linkType: hard +"enquirer@npm:^2.3.6": + version: 2.4.1 + resolution: "enquirer@npm:2.4.1" + dependencies: + ansi-colors: ^4.1.1 + strip-ansi: ^6.0.1 + checksum: f080f11a74209647dbf347a7c6a83c8a47ae1ebf1e75073a808bc1088eb780aa54075bfecd1bcdb3e3c724520edb8e6ee05da031529436b421b71066fcc48cb5 + languageName: node + linkType: hard + "entities@npm:^4.2.0, entities@npm:^4.4.0, entities@npm:^4.5.0": version: 4.5.0 resolution: "entities@npm:4.5.0" @@ -10947,6 +11264,13 @@ __metadata: languageName: node linkType: hard +"eventemitter2@npm:6.4.7": + version: 6.4.7 + resolution: "eventemitter2@npm:6.4.7" + checksum: 1b36a77e139d6965ebf3a36c01fa00c089ae6b80faa1911e52888f40b3a7057b36a2cc45dcd1ad87cda3798fe7b97a0aabcbb8175a8b96092a23bb7d0f039e66 + languageName: node + linkType: hard + "eventemitter3@npm:1.x.x": version: 1.2.0 resolution: "eventemitter3@npm:1.2.0" @@ -10993,6 +11317,23 @@ __metadata: languageName: node linkType: hard +"execa@npm:4.1.0": + version: 4.1.0 + resolution: "execa@npm:4.1.0" + dependencies: + cross-spawn: ^7.0.0 + get-stream: ^5.0.0 + human-signals: ^1.1.1 + is-stream: ^2.0.0 + merge-stream: ^2.0.0 + npm-run-path: ^4.0.0 + onetime: ^5.1.0 + signal-exit: ^3.0.2 + strip-final-newline: ^2.0.0 + checksum: e30d298934d9c52f90f3847704fd8224e849a081ab2b517bbc02f5f7732c24e56a21f14cb96a08256deffeb2d12b2b7cb7e2b014a12fb36f8d3357e06417ed55 + languageName: node + linkType: hard + "execa@npm:^1.0.0": version: 1.0.0 resolution: "execa@npm:1.0.0" @@ -11025,6 +11366,15 @@ __metadata: languageName: node linkType: hard +"executable@npm:^4.1.1": + version: 4.1.1 + resolution: "executable@npm:4.1.1" + dependencies: + pify: ^2.2.0 + checksum: f01927ce59bccec804e171bf859a26e362c1f50aa9ebc69f7cafdcce3859d29d4b6267fd47237c18b0a1830614bd3f0ee14b7380d9bad18a4e7af9b5f0b6984f + languageName: node + linkType: hard + "expand-tilde@npm:^2.0.0, expand-tilde@npm:^2.0.2": version: 2.0.2 resolution: "expand-tilde@npm:2.0.2" @@ -11361,7 +11711,7 @@ __metadata: languageName: node linkType: hard -"extend@npm:^3.0.0": +"extend@npm:^3.0.0, extend@npm:~3.0.2": version: 3.0.2 resolution: "extend@npm:3.0.2" checksum: a50a8309ca65ea5d426382ff09f33586527882cf532931cb08ca786ea3146c0553310bda688710ff61d7668eba9f96b923fe1420cdf56a2c3eaf30fcab87b515 @@ -11397,7 +11747,7 @@ __metadata: languageName: node linkType: hard -"extract-zip@npm:^2.0.1": +"extract-zip@npm:2.0.1, extract-zip@npm:^2.0.1": version: 2.0.1 resolution: "extract-zip@npm:2.0.1" dependencies: @@ -11414,6 +11764,20 @@ __metadata: languageName: node linkType: hard +"extsprintf@npm:1.3.0": + version: 1.3.0 + resolution: "extsprintf@npm:1.3.0" + checksum: cee7a4a1e34cffeeec18559109de92c27517e5641991ec6bab849aa64e3081022903dd53084f2080d0d2530803aa5ee84f1e9de642c365452f9e67be8f958ce2 + languageName: node + linkType: hard + +"extsprintf@npm:^1.2.0": + version: 1.4.1 + resolution: "extsprintf@npm:1.4.1" + checksum: a2f29b241914a8d2bad64363de684821b6b1609d06ae68d5b539e4de6b28659715b5bea94a7265201603713b7027d35399d10b0548f09071c5513e65e8323d33 + languageName: node + linkType: hard + "eyes@npm:^0.1.8": version: 0.1.8 resolution: "eyes@npm:0.1.8" @@ -11598,6 +11962,15 @@ __metadata: languageName: node linkType: hard +"figures@npm:^3.2.0": + version: 3.2.0 + resolution: "figures@npm:3.2.0" + dependencies: + escape-string-regexp: ^1.0.5 + checksum: 85a6ad29e9aca80b49b817e7c89ecc4716ff14e3779d9835af554db91bac41c0f289c418923519392a1e582b4d10482ad282021330cd045bb7b80c84152f2a2b + languageName: node + linkType: hard + "file-entry-cache@npm:^6.0.1": version: 6.0.1 resolution: "file-entry-cache@npm:6.0.1" @@ -11792,6 +12165,13 @@ __metadata: languageName: node linkType: hard +"forever-agent@npm:~0.6.1": + version: 0.6.1 + resolution: "forever-agent@npm:0.6.1" + checksum: 766ae6e220f5fe23676bb4c6a99387cec5b7b62ceb99e10923376e27bfea72f3c3aeec2ba5f45f3f7ba65d6616965aa7c20b15002b6860833bb6e394dea546a8 + languageName: node + linkType: hard + "form-data@npm:^2.3.3": version: 2.5.1 resolution: "form-data@npm:2.5.1" @@ -11825,6 +12205,17 @@ __metadata: languageName: node linkType: hard +"form-data@npm:~2.3.2": + version: 2.3.3 + resolution: "form-data@npm:2.3.3" + dependencies: + asynckit: ^0.4.0 + combined-stream: ^1.0.6 + mime-types: ^2.1.12 + checksum: 10c1780fa13dbe1ff3100114c2ce1f9307f8be10b14bf16e103815356ff567b6be39d70fc4a40f8990b9660012dc24b0f5e1dde1b6426166eb23a445ba068ca3 + languageName: node + linkType: hard + "freeport-async@npm:2.0.0": version: 2.0.0 resolution: "freeport-async@npm:2.0.0" @@ -12014,7 +12405,7 @@ __metadata: languageName: node linkType: hard -"get-stream@npm:^5.1.0": +"get-stream@npm:^5.0.0, get-stream@npm:^5.1.0": version: 5.2.0 resolution: "get-stream@npm:5.2.0" dependencies: @@ -12056,6 +12447,24 @@ __metadata: languageName: node linkType: hard +"getos@npm:^3.2.1": + version: 3.2.1 + resolution: "getos@npm:3.2.1" + dependencies: + async: ^3.2.0 + checksum: 42fd78a66d47cebd3e09de5566cc0044e034b08f4a000a310dbd89a77b02c65d8f4002554bfa495ea5bdc4fa9d515f5ac785a7cc474ba45383cc697f865eeaf1 + languageName: node + linkType: hard + +"getpass@npm:^0.1.1": + version: 0.1.7 + resolution: "getpass@npm:0.1.7" + dependencies: + assert-plus: ^1.0.0 + checksum: ab18d55661db264e3eac6012c2d3daeafaab7a501c035ae0ccb193c3c23e9849c6e29b6ac762b9c2adae460266f925d55a3a2a3a3c8b94be2f222df94d70c046 + languageName: node + linkType: hard + "glob-parent@npm:^5.1.2": version: 5.1.2 resolution: "glob-parent@npm:5.1.2" @@ -12168,6 +12577,15 @@ __metadata: languageName: node linkType: hard +"global-dirs@npm:^3.0.0": + version: 3.0.1 + resolution: "global-dirs@npm:3.0.1" + dependencies: + ini: 2.0.0 + checksum: 70147b80261601fd40ac02a104581432325c1c47329706acd773f3a6ce99bb36d1d996038c85ccacd482ad22258ec233c586b6a91535b1a116b89663d49d6438 + languageName: node + linkType: hard + "global-modules@npm:^1.0.0": version: 1.0.0 resolution: "global-modules@npm:1.0.0" @@ -12568,6 +12986,17 @@ __metadata: languageName: node linkType: hard +"http-signature@npm:~1.3.6": + version: 1.3.6 + resolution: "http-signature@npm:1.3.6" + dependencies: + assert-plus: ^1.0.0 + jsprim: ^2.0.2 + sshpk: ^1.14.1 + checksum: 10be2af4764e71fee0281392937050201ee576ac755c543f570d6d87134ce5e858663fe999a7adb3e4e368e1e356d0d7fec6b9542295b875726ff615188e7a0c + languageName: node + linkType: hard + "http2-wrapper@npm:^1.0.0-beta.5.2": version: 1.0.3 resolution: "http2-wrapper@npm:1.0.3" @@ -12598,6 +13027,13 @@ __metadata: languageName: node linkType: hard +"human-signals@npm:^1.1.1": + version: 1.1.1 + resolution: "human-signals@npm:1.1.1" + checksum: d587647c9e8ec24e02821b6be7de5a0fc37f591f6c4e319b3054b43fd4c35a70a94c46fc74d8c1a43c47fde157d23acd7421f375e1c1365b09a16835b8300205 + languageName: node + linkType: hard + "human-signals@npm:^2.1.0": version: 2.1.0 resolution: "human-signals@npm:2.1.0" @@ -12750,6 +13186,13 @@ __metadata: languageName: node linkType: hard +"ini@npm:2.0.0": + version: 2.0.0 + resolution: "ini@npm:2.0.0" + checksum: e7aadc5fb2e4aefc666d74ee2160c073995a4061556b1b5b4241ecb19ad609243b9cceafe91bae49c219519394bbd31512516cb22a3b1ca6e66d869e0447e84e + languageName: node + linkType: hard + "ini@npm:^1.3.4, ini@npm:~1.3.0": version: 1.3.8 resolution: "ini@npm:1.3.8" @@ -12999,6 +13442,17 @@ __metadata: languageName: node linkType: hard +"is-ci@npm:^3.0.1": + version: 3.0.1 + resolution: "is-ci@npm:3.0.1" + dependencies: + ci-info: ^3.2.0 + bin: + is-ci: bin.js + checksum: 192c66dc7826d58f803ecae624860dccf1899fc1f3ac5505284c0a5cf5f889046ffeb958fa651e5725d5705c5bcb14f055b79150ea5fcad7456a9569de60260e + languageName: node + linkType: hard + "is-core-module@npm:^2.12.0, is-core-module@npm:^2.13.0, is-core-module@npm:^2.13.1": version: 2.13.1 resolution: "is-core-module@npm:2.13.1" @@ -13113,6 +13567,16 @@ __metadata: languageName: node linkType: hard +"is-installed-globally@npm:~0.4.0": + version: 0.4.0 + resolution: "is-installed-globally@npm:0.4.0" + dependencies: + global-dirs: ^3.0.0 + is-path-inside: ^3.0.2 + checksum: 3359840d5982d22e9b350034237b2cda2a12bac1b48a721912e1ab8e0631dd07d45a2797a120b7b87552759a65ba03e819f1bd63f2d7ab8657ec0b44ee0bf399 + languageName: node + linkType: hard + "is-interactive@npm:^1.0.0": version: 1.0.0 resolution: "is-interactive@npm:1.0.0" @@ -13324,6 +13788,13 @@ __metadata: languageName: node linkType: hard +"is-typedarray@npm:~1.0.0": + version: 1.0.0 + resolution: "is-typedarray@npm:1.0.0" + checksum: 3508c6cd0a9ee2e0df2fa2e9baabcdc89e911c7bd5cf64604586697212feec525aa21050e48affb5ffc3df20f0f5d2e2cf79b08caa64e1ccc9578e251763aef7 + languageName: node + linkType: hard + "is-unicode-supported@npm:^0.1.0": version: 0.1.0 resolution: "is-unicode-supported@npm:0.1.0" @@ -13440,6 +13911,13 @@ __metadata: languageName: node linkType: hard +"isstream@npm:~0.1.2": + version: 0.1.2 + resolution: "isstream@npm:0.1.2" + checksum: 1eb2fe63a729f7bdd8a559ab552c69055f4f48eb5c2f03724430587c6f450783c8f1cd936c1c952d0a927925180fcc892ebd5b174236cf1065d4bd5bdb37e963 + languageName: node + linkType: hard + "istanbul-lib-coverage@npm:^3.2.0": version: 3.2.2 resolution: "istanbul-lib-coverage@npm:3.2.2" @@ -13774,6 +14252,13 @@ __metadata: languageName: node linkType: hard +"jsbn@npm:~0.1.0": + version: 0.1.1 + resolution: "jsbn@npm:0.1.1" + checksum: e5ff29c1b8d965017ef3f9c219dacd6e40ad355c664e277d31246c90545a02e6047018c16c60a00f36d561b3647215c41894f5d869ada6908a2e0ce4200c88f2 + languageName: node + linkType: hard + "jsc-android@npm:^250231.0.0": version: 250231.0.0 resolution: "jsc-android@npm:250231.0.0" @@ -13895,6 +14380,13 @@ __metadata: languageName: node linkType: hard +"json-schema@npm:0.4.0": + version: 0.4.0 + resolution: "json-schema@npm:0.4.0" + checksum: 66389434c3469e698da0df2e7ac5a3281bcff75e797a5c127db7c5b56270e01ae13d9afa3c03344f76e32e81678337a8c912bdbb75101c62e487dc3778461d72 + languageName: node + linkType: hard + "json-stable-stringify-without-jsonify@npm:^1.0.1": version: 1.0.1 resolution: "json-stable-stringify-without-jsonify@npm:1.0.1" @@ -13902,7 +14394,7 @@ __metadata: languageName: node linkType: hard -"json-stringify-safe@npm:^5.0.1": +"json-stringify-safe@npm:^5.0.1, json-stringify-safe@npm:~5.0.1": version: 5.0.1 resolution: "json-stringify-safe@npm:5.0.1" checksum: 48ec0adad5280b8a96bb93f4563aa1667fd7a36334f79149abd42446d0989f2ddc58274b479f4819f1f00617957e6344c886c55d05a4e15ebb4ab931e4a6a8ee @@ -13961,6 +14453,18 @@ __metadata: languageName: node linkType: hard +"jsprim@npm:^2.0.2": + version: 2.0.2 + resolution: "jsprim@npm:2.0.2" + dependencies: + assert-plus: 1.0.0 + extsprintf: 1.3.0 + json-schema: 0.4.0 + verror: 1.10.0 + checksum: d175f6b1991e160cb0aa39bc857da780e035611986b5492f32395411879fdaf4e513d98677f08f7352dac93a16b66b8361c674b86a3fa406e2e7af6b26321838 + languageName: node + linkType: hard + "jsx-ast-utils@npm:^2.4.1 || ^3.0.0": version: 3.3.5 resolution: "jsx-ast-utils@npm:3.3.5" @@ -14017,6 +14521,13 @@ __metadata: languageName: node linkType: hard +"lazy-ass@npm:^1.6.0": + version: 1.6.0 + resolution: "lazy-ass@npm:1.6.0" + checksum: 5a3ebb17915b03452320804466345382a6c25ac782ec4874fecdb2385793896cd459be2f187dc7def8899180c32ee0ab9a1aa7fe52193ac3ff3fe29bb0591729 + languageName: node + linkType: hard + "leaflet.markercluster@npm:^1.5.3": version: 1.5.3 resolution: "leaflet.markercluster@npm:1.5.3" @@ -14210,6 +14721,27 @@ __metadata: languageName: node linkType: hard +"listr2@npm:^3.8.3": + version: 3.14.0 + resolution: "listr2@npm:3.14.0" + dependencies: + cli-truncate: ^2.1.0 + colorette: ^2.0.16 + log-update: ^4.0.0 + p-map: ^4.0.0 + rfdc: ^1.3.0 + rxjs: ^7.5.1 + through: ^2.3.8 + wrap-ansi: ^7.0.0 + peerDependencies: + enquirer: ">= 2.3.0 < 3" + peerDependenciesMeta: + enquirer: + optional: true + checksum: fdb8b2d6bdf5df9371ebd5082bee46c6d0ca3d1e5f2b11fbb5a127839855d5f3da9d4968fce94f0a5ec67cac2459766abbb1faeef621065ebb1829b11ef9476d + languageName: node + linkType: hard + "listr2@npm:^8.0.1": version: 8.0.1 resolution: "listr2@npm:8.0.1" @@ -14284,6 +14816,13 @@ __metadata: languageName: node linkType: hard +"lodash.once@npm:^4.1.1": + version: 4.1.1 + resolution: "lodash.once@npm:4.1.1" + checksum: d768fa9f9b4e1dc6453be99b753906f58990e0c45e7b2ca5a3b40a33111e5d17f6edf2f768786e2716af90a8e78f8f91431ab8435f761fef00f9b0c256f6d245 + languageName: node + linkType: hard + "lodash.throttle@npm:^4.1.1": version: 4.1.1 resolution: "lodash.throttle@npm:4.1.1" @@ -14307,7 +14846,7 @@ __metadata: languageName: node linkType: hard -"log-symbols@npm:^4.1.0": +"log-symbols@npm:^4.0.0, log-symbols@npm:^4.1.0": version: 4.1.0 resolution: "log-symbols@npm:4.1.0" dependencies: @@ -14317,6 +14856,18 @@ __metadata: languageName: node linkType: hard +"log-update@npm:^4.0.0": + version: 4.0.0 + resolution: "log-update@npm:4.0.0" + dependencies: + ansi-escapes: ^4.3.0 + cli-cursor: ^3.1.0 + slice-ansi: ^4.0.0 + wrap-ansi: ^6.2.0 + checksum: ae2f85bbabc1906034154fb7d4c4477c79b3e703d22d78adee8b3862fa913942772e7fa11713e3d96fb46de4e3cabefbf5d0a544344f03b58d3c4bff52aa9eb2 + languageName: node + linkType: hard + "log-update@npm:^6.0.0": version: 6.0.0 resolution: "log-update@npm:6.0.0" @@ -14942,7 +15493,7 @@ __metadata: languageName: node linkType: hard -"mime-types@npm:^2.1.12, mime-types@npm:^2.1.27, mime-types@npm:~2.1.34": +"mime-types@npm:^2.1.12, mime-types@npm:^2.1.27, mime-types@npm:~2.1.19, mime-types@npm:~2.1.34": version: 2.1.35 resolution: "mime-types@npm:2.1.35" dependencies: @@ -15061,7 +15612,7 @@ __metadata: languageName: node linkType: hard -"minimist@npm:^1.2.0, minimist@npm:^1.2.6": +"minimist@npm:^1.2.0, minimist@npm:^1.2.6, minimist@npm:^1.2.8": version: 1.2.8 resolution: "minimist@npm:1.2.8" checksum: 75a6d645fb122dad29c06a7597bddea977258957ed88d7a6df59b5cd3fe4a527e253e9bbf2e783e4b73657f9098b96a5fe96ab8a113655d4109108577ecf85b0 @@ -15593,7 +16144,7 @@ __metadata: languageName: node linkType: hard -"npm-run-path@npm:^4.0.1": +"npm-run-path@npm:^4.0.0, npm-run-path@npm:^4.0.1": version: 4.0.1 resolution: "npm-run-path@npm:4.0.1" dependencies: @@ -15903,6 +16454,13 @@ __metadata: languageName: node linkType: hard +"ospath@npm:^1.2.2": + version: 1.2.2 + resolution: "ospath@npm:1.2.2" + checksum: 505f48a4f4f1c557d6c656ec985707726e3714721680139be037613e903aa8c8fa4ddd8d1342006f9b2dc0065e6e20f8b7bea2ee05354f31257044790367b347 + languageName: node + linkType: hard + "p-cancelable@npm:^2.0.0": version: 2.1.1 resolution: "p-cancelable@npm:2.1.1" @@ -16217,6 +16775,13 @@ __metadata: languageName: node linkType: hard +"performance-now@npm:^2.1.0": + version: 2.1.0 + resolution: "performance-now@npm:2.1.0" + checksum: 534e641aa8f7cba160f0afec0599b6cecefbb516a2e837b512be0adbe6c1da5550e89c78059c7fabc5c9ffdf6627edabe23eb7c518c4500067a898fa65c2b550 + languageName: node + linkType: hard + "picocolors@npm:^1.0.0": version: 1.0.0 resolution: "picocolors@npm:1.0.0" @@ -16238,6 +16803,13 @@ __metadata: languageName: node linkType: hard +"pify@npm:^2.2.0": + version: 2.3.0 + resolution: "pify@npm:2.3.0" + checksum: 9503aaeaf4577acc58642ad1d25c45c6d90288596238fb68f82811c08104c800e5a7870398e9f015d82b44ecbcbef3dc3d4251a1cbb582f6e5959fe09884b2ba + languageName: node + linkType: hard + "pify@npm:^4.0.1": version: 4.0.1 resolution: "pify@npm:4.0.1" @@ -16421,7 +16993,7 @@ __metadata: languageName: node linkType: hard -"pretty-bytes@npm:5.6.0": +"pretty-bytes@npm:5.6.0, pretty-bytes@npm:^5.6.0": version: 5.6.0 resolution: "pretty-bytes@npm:5.6.0" checksum: 9c082500d1e93434b5b291bd651662936b8bd6204ec9fa17d563116a192d6d86b98f6d328526b4e8d783c07d5499e2614a807520249692da9ec81564b2f439cd @@ -16465,7 +17037,7 @@ __metadata: languageName: node linkType: hard -"process@npm:^0.11.1": +"process@npm:^0.11.1, process@npm:^0.11.10": version: 0.11.10 resolution: "process@npm:0.11.10" checksum: bfcce49814f7d172a6e6a14d5fa3ac92cc3d0c3b9feb1279774708a719e19acd673995226351a082a9ae99978254e320ccda4240ddc474ba31a76c79491ca7c3 @@ -16610,6 +17182,13 @@ __metadata: languageName: node linkType: hard +"proxy-from-env@npm:1.0.0": + version: 1.0.0 + resolution: "proxy-from-env@npm:1.0.0" + checksum: 292e28d1de0c315958d71d8315eb546dd3cd8c8cbc2dab7c54eeb9f5c17f421771964ad0b5e1f77011bab2305bdae42e1757ce33bdb1ccc3e87732322a8efcf1 + languageName: node + linkType: hard + "proxy-from-env@npm:^1.1.0": version: 1.1.0 resolution: "proxy-from-env@npm:1.1.0" @@ -16617,6 +17196,13 @@ __metadata: languageName: node linkType: hard +"psl@npm:^1.1.33": + version: 1.9.0 + resolution: "psl@npm:1.9.0" + checksum: 20c4277f640c93d393130673f392618e9a8044c6c7bf61c53917a0fddb4952790f5f362c6c730a9c32b124813e173733f9895add8d26f566ed0ea0654b2e711d + languageName: node + linkType: hard + "public-encrypt@npm:^4.0.0": version: 4.0.3 resolution: "public-encrypt@npm:4.0.3" @@ -16678,6 +17264,15 @@ __metadata: languageName: node linkType: hard +"qs@npm:6.10.4": + version: 6.10.4 + resolution: "qs@npm:6.10.4" + dependencies: + side-channel: ^1.0.4 + checksum: 31e4fedd759d01eae52dde6692abab175f9af3e639993c5caaa513a2a3607b34d8058d3ae52ceeccf37c3025f22ed5e90e9ddd6c2537e19c0562ddd10dc5b1eb + languageName: node + linkType: hard + "query-string@npm:^7.1.3": version: 7.1.3 resolution: "query-string@npm:7.1.3" @@ -16690,6 +17285,13 @@ __metadata: languageName: node linkType: hard +"querystringify@npm:^2.1.1": + version: 2.2.0 + resolution: "querystringify@npm:2.2.0" + checksum: 5641ea231bad7ef6d64d9998faca95611ed4b11c2591a8cae741e178a974f6a8e0ebde008475259abe1621cb15e692404e6b6626e927f7b849d5c09392604b15 + languageName: node + linkType: hard + "queue-microtask@npm:^1.2.2": version: 1.2.3 resolution: "queue-microtask@npm:1.2.3" @@ -16968,6 +17570,16 @@ __metadata: languageName: node linkType: hard +"react-native-hoverable@npm:^0.2.0": + version: 0.2.0 + resolution: "react-native-hoverable@npm:0.2.0" + peerDependencies: + react: "*" + react-native: "*" + checksum: 9ca468d07c660ea30013da3921e09fdb42b479ce9f69e867e60bd56dbb49cb407998e07d3aa2ab6662e55f7b1cec9bc806ba9517ca9fd31839c1ebcbd4a7d26f + languageName: node + linkType: hard + "react-native-image-picker@npm:^7.1.0": version: 7.1.0 resolution: "react-native-image-picker@npm:7.1.0" @@ -17095,6 +17707,16 @@ __metadata: languageName: node linkType: hard +"react-native-reanimated-table@npm:^0.0.2": + version: 0.0.2 + resolution: "react-native-reanimated-table@npm:0.0.2" + peerDependencies: + react: ">=16.8.0" + react-native: ">=0.6.0" + checksum: ab1a326d9880bc49febbb1ab325ede544c86b4ca2faf713904e8aa64d05478e36f6d545a819bc82a7d234c23ea6cf9e4fcbc2dc804a7e7f9240d5f21eb28e76c + languageName: node + linkType: hard + "react-native-reanimated@npm:^3.6.2": version: 3.6.2 resolution: "react-native-reanimated@npm:3.6.2" @@ -17642,6 +18264,15 @@ __metadata: languageName: node linkType: hard +"request-progress@npm:^3.0.0": + version: 3.0.0 + resolution: "request-progress@npm:3.0.0" + dependencies: + throttleit: ^1.0.0 + checksum: 6ea1761dcc8a8b7b5894afd478c0286aa31bd69438d7050294bd4fd0d0b3e09b5cde417d38deef9c49809039c337d8744e4bb49d8632b0c3e4ffa5e8a687e0fd + languageName: node + linkType: hard + "require-directory@npm:^2.1.1": version: 2.1.1 resolution: "require-directory@npm:2.1.1" @@ -17688,6 +18319,13 @@ __metadata: languageName: node linkType: hard +"requires-port@npm:^1.0.0": + version: 1.0.0 + resolution: "requires-port@npm:1.0.0" + checksum: eee0e303adffb69be55d1a214e415cf42b7441ae858c76dfc5353148644f6fd6e698926fc4643f510d5c126d12a705e7c8ed7e38061113bdf37547ab356797ff + languageName: node + linkType: hard + "reselect@npm:^4.1.8": version: 4.1.8 resolution: "reselect@npm:4.1.8" @@ -18030,7 +18668,7 @@ __metadata: languageName: node linkType: hard -"rxjs@npm:^7.8.1": +"rxjs@npm:^7.5.1, rxjs@npm:^7.8.1": version: 7.8.1 resolution: "rxjs@npm:7.8.1" dependencies: @@ -18083,7 +18721,7 @@ __metadata: languageName: node linkType: hard -"safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0, safer-buffer@npm:^2.1.0": +"safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0, safer-buffer@npm:^2.0.2, safer-buffer@npm:^2.1.0, safer-buffer@npm:~2.1.0": version: 2.1.2 resolution: "safer-buffer@npm:2.1.2" checksum: cab8f25ae6f1434abee8d80023d7e72b598cf1327164ddab31003c51215526801e40b66c5e65d658a0af1e9d6478cadcb4c745f4bd6751f97d8644786c0978b0 @@ -18562,6 +19200,28 @@ __metadata: languageName: node linkType: hard +"slice-ansi@npm:^3.0.0": + version: 3.0.0 + resolution: "slice-ansi@npm:3.0.0" + dependencies: + ansi-styles: ^4.0.0 + astral-regex: ^2.0.0 + is-fullwidth-code-point: ^3.0.0 + checksum: 5ec6d022d12e016347e9e3e98a7eb2a592213a43a65f1b61b74d2c78288da0aded781f665807a9f3876b9daa9ad94f64f77d7633a0458876c3a4fdc4eb223f24 + languageName: node + linkType: hard + +"slice-ansi@npm:^4.0.0": + version: 4.0.0 + resolution: "slice-ansi@npm:4.0.0" + dependencies: + ansi-styles: ^4.0.0 + astral-regex: ^2.0.0 + is-fullwidth-code-point: ^3.0.0 + checksum: 4a82d7f085b0e1b070e004941ada3c40d3818563ac44766cca4ceadd2080427d337554f9f99a13aaeb3b4a94d9964d9466c807b3d7b7541d1ec37ee32d308756 + languageName: node + linkType: hard + "slice-ansi@npm:^5.0.0": version: 5.0.0 resolution: "slice-ansi@npm:5.0.0" @@ -18733,6 +19393,27 @@ __metadata: languageName: node linkType: hard +"sshpk@npm:^1.14.1": + version: 1.18.0 + resolution: "sshpk@npm:1.18.0" + dependencies: + asn1: ~0.2.3 + assert-plus: ^1.0.0 + bcrypt-pbkdf: ^1.0.0 + dashdash: ^1.12.0 + ecc-jsbn: ~0.1.1 + getpass: ^0.1.1 + jsbn: ~0.1.0 + safer-buffer: ^2.0.2 + tweetnacl: ~0.14.0 + bin: + sshpk-conv: bin/sshpk-conv + sshpk-sign: bin/sshpk-sign + sshpk-verify: bin/sshpk-verify + checksum: 01d43374eee3a7e37b3b82fdbecd5518cbb2e47ccbed27d2ae30f9753f22bd6ffad31225cb8ef013bc3fb7785e686cea619203ee1439a228f965558c367c3cfa + languageName: node + linkType: hard + "ssri@npm:^10.0.0": version: 10.0.5 resolution: "ssri@npm:10.0.5" @@ -19159,7 +19840,7 @@ __metadata: languageName: node linkType: hard -"supports-color@npm:^8.0.0": +"supports-color@npm:^8.0.0, supports-color@npm:^8.1.1": version: 8.1.1 resolution: "supports-color@npm:8.1.1" dependencies: @@ -19312,11 +19993,12 @@ __metadata: "@chain-registry/utils": 1.18.0 "@cosmjs/amino": 0.32.2 "@cosmjs/cosmwasm-stargate": 0.32.2 - "@cosmjs/encoding": ^0.32.2 - "@cosmjs/math": ^0.32.2 + "@cosmjs/crypto": 0.32.2 + "@cosmjs/encoding": 0.32.2 + "@cosmjs/math": 0.32.2 "@cosmjs/proto-signing": 0.32.2 "@cosmjs/stargate": 0.32.2 - "@cosmjs/tendermint-rpc": ^0.32.2 + "@cosmjs/tendermint-rpc": 0.32.2 "@cosmology/core": 2.0.1 "@cosmwasm/ts-codegen": ^0.35.7 "@dotlottie/react-player": ^1.6.5 @@ -19331,7 +20013,10 @@ __metadata: "@ethersproject/providers": ^5.7.2 "@expo-google-fonts/exo": ^0.2.2 "@expo/metro-runtime": ~3.1.3 + "@faker-js/faker": ^8.4.1 "@gnolang/gno-js-client": ^1.3.0 + "@gnolang/tm2-js-client": ^1.2.1 + "@hookform/resolvers": ^3.6.0 "@improbable-eng/grpc-web": ^0.15.0 "@improbable-eng/grpc-web-node-http-transport": ^0.15.0 "@improbable-eng/grpc-web-react-native-transport": ^0.15.0 @@ -19347,6 +20032,7 @@ __metadata: "@react-native-clipboard/clipboard": ^1.13.2 "@react-native-community/slider": 4.4.2 "@react-native-masked-view/masked-view": 0.3.0 + "@react-native-picker/picker": 2.6.1 "@react-navigation/bottom-tabs": ^6.5.11 "@react-navigation/drawer": ^6.6.6 "@react-navigation/native": ^6.0.11 @@ -19377,6 +20063,7 @@ __metadata: cosmos-endpoints-scorer: ^0.1.0 cross-env: ^7.0.3 crypto-browserify: ^3.12.0 + cypress: ^13.9.0 depcheck: ^1.4.7 dotenv: ^16.3.1 draft-convert: ^2.1.13 @@ -19438,6 +20125,7 @@ __metadata: react-native-gesture-handler: ~2.14.0 react-native-get-random-values: ~1.8.0 react-native-heroicons: ^3.2.0 + react-native-hoverable: ^0.2.0 react-native-image-picker: ^7.1.0 react-native-keyboard-aware-scrollview: ^2.1.0 react-native-leaflet-view: ^0.1.2 @@ -19449,6 +20137,7 @@ __metadata: react-native-qrcode-svg: ^6.2.0 react-native-reanimated: ^3.6.2 react-native-reanimated-carousel: 4.0.0-alpha.9 + react-native-reanimated-table: ^0.0.2 react-native-redash: ^18.0.0 react-native-safe-area-context: 4.8.2 react-native-screens: ~3.29.0 @@ -19478,6 +20167,7 @@ __metadata: waveform-data: ^4.3.0 yaml: ^2.3.4 zod: ^3.22.4 + zustand: ^4.4.7 languageName: unknown linkType: soft @@ -19562,6 +20252,13 @@ __metadata: languageName: node linkType: hard +"throttleit@npm:^1.0.0": + version: 1.0.1 + resolution: "throttleit@npm:1.0.1" + checksum: 32e0b12ca5810cd34dfce0408c7cb658dfd039848a073466eaac667ce6e846cafa53ac518e4b01dc6f34e6652b66fd29a5c6b666718ec5086ef328a9d029dc75 + languageName: node + linkType: hard + "through2@npm:^2.0.1": version: 2.0.5 resolution: "through2@npm:2.0.5" @@ -19572,7 +20269,7 @@ __metadata: languageName: node linkType: hard -"through@npm:2, through@npm:>=2.2.7 <3, through@npm:^2.3.6": +"through@npm:2, through@npm:>=2.2.7 <3, through@npm:^2.3.6, through@npm:^2.3.8": version: 2.3.8 resolution: "through@npm:2.3.8" checksum: a38c3e059853c494af95d50c072b83f8b676a9ba2818dcc5b108ef252230735c54e0185437618596c790bbba8fcdaef5b290405981ffa09dce67b1f1bf190cbd @@ -19607,6 +20304,13 @@ __metadata: languageName: node linkType: hard +"tmp@npm:~0.2.1": + version: 0.2.3 + resolution: "tmp@npm:0.2.3" + checksum: 73b5c96b6e52da7e104d9d44afb5d106bb1e16d9fa7d00dbeb9e6522e61b571fbdb165c756c62164be9a3bbe192b9b268c236d370a2a0955c7689cd2ae377b95 + languageName: node + linkType: hard + "tmpl@npm:1.0.5": version: 1.0.5 resolution: "tmpl@npm:1.0.5" @@ -19637,6 +20341,18 @@ __metadata: languageName: node linkType: hard +"tough-cookie@npm:^4.1.3": + version: 4.1.4 + resolution: "tough-cookie@npm:4.1.4" + dependencies: + psl: ^1.1.33 + punycode: ^2.1.1 + universalify: ^0.2.0 + url-parse: ^1.5.3 + checksum: 5815059f014c31179a303c673f753f7899a6fce94ac93712c88ea5f3c26e0c042b5f0c7a599a00f8e0feeca4615dba75c3dffc54f3c1a489978aa8205e09307c + languageName: node + linkType: hard + "tr46@npm:~0.0.3": version: 0.0.3 resolution: "tr46@npm:0.0.3" @@ -19766,6 +20482,22 @@ __metadata: languageName: node linkType: hard +"tunnel-agent@npm:^0.6.0": + version: 0.6.0 + resolution: "tunnel-agent@npm:0.6.0" + dependencies: + safe-buffer: ^5.0.1 + checksum: 05f6510358f8afc62a057b8b692f05d70c1782b70db86d6a1e0d5e28a32389e52fa6e7707b6c5ecccacc031462e4bc35af85ecfe4bbc341767917b7cf6965711 + languageName: node + linkType: hard + +"tweetnacl@npm:^0.14.3, tweetnacl@npm:~0.14.0": + version: 0.14.5 + resolution: "tweetnacl@npm:0.14.5" + checksum: 6061daba1724f59473d99a7bb82e13f211cdf6e31315510ae9656fefd4779851cb927adad90f3b488c8ed77c106adc0421ea8055f6f976ff21b27c5c4e918487 + languageName: node + linkType: hard + "type-check@npm:^0.4.0, type-check@npm:~0.4.0": version: 0.4.0 resolution: "type-check@npm:0.4.0" @@ -20164,6 +20896,13 @@ __metadata: languageName: node linkType: hard +"universalify@npm:^0.2.0": + version: 0.2.0 + resolution: "universalify@npm:0.2.0" + checksum: e86134cb12919d177c2353196a4cc09981524ee87abf621f7bc8d249dbbbebaec5e7d1314b96061497981350df786e4c5128dbf442eba104d6e765bc260678b5 + languageName: node + linkType: hard + "universalify@npm:^1.0.0": version: 1.0.0 resolution: "universalify@npm:1.0.0" @@ -20192,6 +20931,13 @@ __metadata: languageName: node linkType: hard +"untildify@npm:^4.0.0": + version: 4.0.0 + resolution: "untildify@npm:4.0.0" + checksum: 39ced9c418a74f73f0a56e1ba4634b4d959422dff61f4c72a8e39f60b99380c1b45ed776fbaa0a4101b157e4310d873ad7d114e8534ca02609b4916bb4187fb9 + languageName: node + linkType: hard + "update-browserslist-db@npm:^1.0.13": version: 1.0.13 resolution: "update-browserslist-db@npm:1.0.13" @@ -20222,6 +20968,16 @@ __metadata: languageName: node linkType: hard +"url-parse@npm:^1.5.3": + version: 1.5.10 + resolution: "url-parse@npm:1.5.10" + dependencies: + querystringify: ^2.1.1 + requires-port: ^1.0.0 + checksum: fbdba6b1d83336aca2216bbdc38ba658d9cfb8fc7f665eb8b17852de638ff7d1a162c198a8e4ed66001ddbf6c9888d41e4798912c62b4fd777a31657989f7bdf + languageName: node + linkType: hard + "use-latest-callback@npm:^0.1.7": version: 0.1.9 resolution: "use-latest-callback@npm:0.1.9" @@ -20231,7 +20987,7 @@ __metadata: languageName: node linkType: hard -"use-sync-external-store@npm:^1.0.0, use-sync-external-store@npm:^1.2.0": +"use-sync-external-store@npm:1.2.0, use-sync-external-store@npm:^1.0.0, use-sync-external-store@npm:^1.2.0": version: 1.2.0 resolution: "use-sync-external-store@npm:1.2.0" peerDependencies: @@ -20364,6 +21120,17 @@ __metadata: languageName: node linkType: hard +"verror@npm:1.10.0": + version: 1.10.0 + resolution: "verror@npm:1.10.0" + dependencies: + assert-plus: ^1.0.0 + core-util-is: 1.0.2 + extsprintf: ^1.2.0 + checksum: c431df0bedf2088b227a4e051e0ff4ca54df2c114096b0c01e1cbaadb021c30a04d7dd5b41ab277bcd51246ca135bf931d4c4c796ecae7a4fef6d744ecef36ea + languageName: node + linkType: hard + "vfile-message@npm:^3.0.0": version: 3.1.4 resolution: "vfile-message@npm:3.1.4" @@ -21449,3 +22216,23 @@ __metadata: checksum: 80bfd7f8039b24fddeb0718a2ec7c02aa9856e4838d6aa4864335a047b6b37a3273b191ef335bf0b2002e5c514ef261ffcda5a589fb084a48c336ffc4cdbab7f languageName: node linkType: hard + +"zustand@npm:^4.4.7": + version: 4.5.0 + resolution: "zustand@npm:4.5.0" + dependencies: + use-sync-external-store: 1.2.0 + peerDependencies: + "@types/react": ">=16.8" + immer: ">=9.0.6" + react: ">=16.8" + peerDependenciesMeta: + "@types/react": + optional: true + immer: + optional: true + react: + optional: true + checksum: 91685492ab33bb656b98e07d8fff2be1794d8e68ac5dc546ec457f4ae3d709f0c19de9e93045b9ee5d6b704f64503d9e085ffe1f600f6ade0459e572d1cf5c0d + languageName: node + linkType: hard