Skip to content

Commit

Permalink
Add Neutron support (#1373)
Browse files Browse the repository at this point in the history
  • Loading branch information
NoahSaso authored Sep 8, 2023
1 parent 834efbf commit b734c63
Show file tree
Hide file tree
Showing 37 changed files with 407 additions and 167 deletions.
8 changes: 6 additions & 2 deletions apps/dapp/pages/dao/[address]/[[...slug]].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// See the "LICENSE" file in the root directory of this package for more copyright information.

import type { GetStaticPaths, NextPage } from 'next'
import React, { useEffect } from 'react'
import React, { useEffect, useRef } from 'react'
import toast from 'react-hot-toast'
import { useTranslation } from 'react-i18next'
import { constSelector, useRecoilValueLoadable } from 'recoil'
Expand Down Expand Up @@ -99,14 +99,16 @@ const InnerDaoHome = () => {
router.prefetch(addSubDaoProposalPrefillHref)
}, [addSubDaoProposalPrefillHref, router])
// Notify if parent has not yet added subDAO.
const notifiedNotAddedSubDao = useRef<string | undefined>(undefined)
useEffect(() => {
if (
daoInfo.parentDao &&
parentDaosSubDaosLoadable.state === 'hasValue' &&
parentDaosSubDaosLoadable.contents &&
!parentDaosSubDaosLoadable.contents.some(
({ addr }) => addr === daoInfo.coreAddress
)
) &&
notifiedNotAddedSubDao.current !== daoInfo.coreAddress
) {
if (isMemberOfParent && addSubDaoProposalPrefillHref) {
toast(
Expand All @@ -131,6 +133,8 @@ const InnerDaoHome = () => {
})
)
}

notifiedNotAddedSubDao.current = daoInfo.coreAddress
}
}, [
addSubDaoProposalPrefillHref,
Expand Down
83 changes: 75 additions & 8 deletions apps/dapp/pages/gov/[chain]/[[...slug]].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,35 @@ import type { GetStaticPaths, NextPage } from 'next'
import { useRouter } from 'next/router'
import { useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useSetRecoilState } from 'recoil'
import { useRecoilValueLoadable } from 'recoil'

import { walletChainIdAtom } from '@dao-dao/state'
import { DaoCoreV2Selectors } from '@dao-dao/state'
import {
ChainSwitcher,
DaoCard,
GovCommunityPoolTab,
GovInfoBar,
GovPageWrapper,
GovPageWrapperProps,
GovProposalsTab,
LinkWrapper,
ProfileDisconnectedCard,
ProfileHomeCard,
SuspenseLoader,
useLoadingDaoCardInfos,
useWallet,
} from '@dao-dao/stateful'
import { makeGetGovStaticProps } from '@dao-dao/stateful/server'
import {
DaoDappTabbedHome,
GovernanceHome,
useChain,
useDaoInfoContext,
useSupportedChainContext,
} from '@dao-dao/stateless'
import { DaoTabId, DaoTabWithComponent } from '@dao-dao/types'
import { ChainId, DaoTabId, DaoTabWithComponent } from '@dao-dao/types'
import {
NEUTRON_GOVERNANCE_DAO,
SITE_URL,
getGovPath,
getSupportedChainConfig,
Expand All @@ -42,10 +49,6 @@ const InnerGovHome = () => {
const { chainId, config } = useSupportedChainContext()
const daoInfo = useDaoInfoContext()

// Update wallet chain ID to the current chain.
const setWalletChainId = useSetRecoilState(walletChainIdAtom)
useEffect(() => setWalletChainId(chainId), [chainId, setWalletChainId])

const router = useRouter()

const tabs: DaoTabWithComponent[] = useRef([
Expand Down Expand Up @@ -128,12 +131,76 @@ const InnerGovHome = () => {
)
}

const NeutronGovHome: NextPage = () => {
const router = useRouter()
const { chain_id: chainId } = useChain()
const { isWalletConnected } = useWallet()

const neutronSubdaos = useRecoilValueLoadable(
DaoCoreV2Selectors.listAllSubDaosSelector({
chainId,
contractAddress: NEUTRON_GOVERNANCE_DAO,
})
)
const daosLoading = useLoadingDaoCardInfos(
neutronSubdaos.state !== 'hasValue'
? { loading: true }
: {
loading: false,
data: [
{
chainId,
coreAddress: NEUTRON_GOVERNANCE_DAO,
},
...neutronSubdaos.contents.map(({ addr }) => ({
chainId,
coreAddress: addr,
})),
],
}
)

const [goingToChainId, setGoingToChainId] = useState<string>()
// Pre-fetch other chains.
useEffect(() => {
getSupportedChains().forEach(({ name }) => {
router.prefetch('/' + name)
})
}, [router])

return (
<GovernanceHome
DaoCard={DaoCard}
breadcrumbsOverride={
<ChainSwitcher
loading={!!goingToChainId && goingToChainId !== chainId}
onSelect={(chainId) => {
const chainConfig = getSupportedChainConfig(chainId)
if (chainConfig) {
router.push(getGovPath(chainConfig.name))
setGoingToChainId(chainId)
}
}}
/>
}
daos={daosLoading}
rightSidebarContent={
isWalletConnected ? <ProfileHomeCard /> : <ProfileDisconnectedCard />
}
/>
)
}

const GovHomePage: NextPage<GovPageWrapperProps> = ({
children: _,
...props
}) => (
<GovPageWrapper {...props}>
<InnerGovHome />
{props.serializedInfo?.chainId === ChainId.NeutronMainnet ? (
<NeutronGovHome />
) : (
<InnerGovHome />
)}
</GovPageWrapper>
)

Expand Down
Binary file removed apps/dapp/public/daotoken.jpg
Binary file not shown.
Binary file removed apps/dapp/public/juno.png
Binary file not shown.
4 changes: 0 additions & 4 deletions apps/dapp/public/juno.svg

This file was deleted.

Binary file removed apps/dapp/public/keplr-wallet-extension.png
Binary file not shown.
Binary file removed apps/dapp/public/osmosis.png
Binary file not shown.
Binary file removed apps/sda/public/daotoken.jpg
Binary file not shown.
Binary file removed apps/sda/public/juno.png
Binary file not shown.
4 changes: 0 additions & 4 deletions apps/sda/public/juno.svg

This file was deleted.

Binary file removed apps/sda/public/keplr-wallet-extension.png
Binary file not shown.
Binary file removed apps/sda/public/osmosis.png
Binary file not shown.
1 change: 1 addition & 0 deletions packages/i18n/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -1213,6 +1213,7 @@
"github": "GitHub",
"governance": "Governance",
"governanceConfiguration": "Governance configuration",
"governanceDaos": "Governance DAOs",
"governanceToken": "Governance Token",
"header": "Header",
"hidden": "Hidden",
Expand Down
10 changes: 9 additions & 1 deletion packages/state/recoil/selectors/chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ export const nativeDenomBalanceWithTimestampSelector = selectorFamily<
},
})

// Get the SUM of native tokens delegated across all validators
// Get the sum of native tokens delegated across all validators
export const nativeDelegatedBalanceSelector = selectorFamily<
Coin,
WithChainId<{ address: string }>
Expand All @@ -334,6 +334,14 @@ export const nativeDelegatedBalanceSelector = selectorFamily<
get:
({ address, chainId }) =>
async ({ get }) => {
// Neutron does not have staking.
if (chainId === ChainId.NeutronMainnet) {
return {
amount: '0',
denom: getNativeTokenForChainId(chainId).denomOrAddress,
}
}

const client = get(stargateClientForChainSelector(chainId))

get(refreshWalletBalancesIdAtom(address))
Expand Down
82 changes: 48 additions & 34 deletions packages/state/recoil/selectors/token.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { selectorFamily, waitForAll } from 'recoil'
import { selectorFamily, waitForAllSettled } from 'recoil'

import {
AmountWithTimestampAndDenom,
Expand Down Expand Up @@ -255,45 +255,59 @@ export const genericTokenBalancesSelector = selectorFamily<
: []

// TODO: Get polytone cw20s from some item prefix in the DAO.
const cw20TokenBalances =
const cw20TokenBalances = (
!filter || filter === TokenType.Cw20
? get(
isValidContractAddress(
address,
getChainForChainId(chainId).bech32_prefix
) &&
// If is a DAO contract.
get(
isContractSelector({
contractAddress: address,
chainId,
names: [
// V1
'cw-core',
// V2
'cwd-core',
'dao-core',
],
})
)
? DaoCoreV2Selectors.allCw20TokensWithBalancesSelector({
contractAddress: address,
governanceTokenAddress: cw20GovernanceTokenAddress,
chainId,
})
: isValidWalletAddress(
address,
getChainForChainId(chainId).bech32_prefix
// Neutron's modified DAOs do not support cw20s, so this may
// error. Ignore if so.
waitForAllSettled(
isValidContractAddress(
address,
getChainForChainId(chainId).bech32_prefix
) &&
// If is a DAO contract.
get(
isContractSelector({
contractAddress: address,
chainId,
names: [
// V1
'cw-core',
// V2
'cwd-core',
'dao-core',
],
})
)
? walletCw20BalancesSelector({
walletAddress: address,
chainId,
})
: waitForAll([])
? [
DaoCoreV2Selectors.allCw20TokensWithBalancesSelector({
contractAddress: address,
governanceTokenAddress: cw20GovernanceTokenAddress,
chainId,
}),
]
: isValidWalletAddress(
address,
getChainForChainId(chainId).bech32_prefix
)
? [
walletCw20BalancesSelector({
walletAddress: address,
chainId,
}),
]
: []
)
)
: []
)[0]

return [...nativeTokenBalances, ...cw20TokenBalances]
return [
...nativeTokenBalances,
...(cw20TokenBalances?.state === 'hasValue'
? cw20TokenBalances.contents
: []),
]
},
})

Expand Down
24 changes: 16 additions & 8 deletions packages/state/recoil/selectors/treasury.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { parseCoins } from '@cosmjs/proto-signing'
import { IndexedTx } from '@cosmjs/stargate'
import { selectorFamily, waitForAll } from 'recoil'
import { selectorFamily, waitForAll, waitForAllSettled } from 'recoil'

import { AmountWithTimestamp, WithChainId } from '@dao-dao/types'
import {
Expand Down Expand Up @@ -186,6 +186,18 @@ export const daoTvlSelector = selectorFamily<
)
)

// Neutron's modified DAOs do not support cw20s, so this may error. Ignore
// if so.
const cw20BalancesLoadable = get(
waitForAllSettled([
DaoCoreV2Selectors.allCw20TokensWithBalancesSelector({
contractAddress: coreAddress,
chainId,
governanceTokenAddress: cw20GovernanceTokenAddress,
}),
])
)[0]

const allBalances = [
// Native balances.
...[
Expand Down Expand Up @@ -218,13 +230,9 @@ export const daoTvlSelector = selectorFamily<
])
.flat(),
// Cw20s on current chain.
...get(
DaoCoreV2Selectors.allCw20TokensWithBalancesSelector({
contractAddress: coreAddress,
chainId,
governanceTokenAddress: cw20GovernanceTokenAddress,
})
),
...(cw20BalancesLoadable.state === 'hasValue'
? cw20BalancesLoadable.contents
: []),
]

const prices = allBalances.map(({ token, balance }) => {
Expand Down
6 changes: 5 additions & 1 deletion packages/stateful/actions/core/chain_governance/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
ActionCategoryKey,
ActionCategoryMaker,
ActionContextType,
ChainId,
} from '@dao-dao/types'

import { makeGovernanceDepositAction } from './GovernanceDeposit'
Expand All @@ -12,9 +13,12 @@ import { makeValidatorActionsAction } from './ValidatorActions'
export const makeChainGovernanceActionCategory: ActionCategoryMaker = ({
t,
context,
chain: { chain_id: chainId },
}) =>
// Governance module cannot participate in governance.
context.type === ActionContextType.Gov
context.type === ActionContextType.Gov ||
// Neutron does not use the x/gov module.
chainId === ChainId.NeutronMainnet
? null
: {
key: ActionCategoryKey.ChainGovernance,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { constSelector, useRecoilValue } from 'recoil'
import { MsgFundCommunityPool } from '@dao-dao/protobuf/codegen/cosmos/distribution/v1beta1/tx'
import { genericTokenSelector } from '@dao-dao/state/recoil'
import { DownArrowEmoji } from '@dao-dao/stateless'
import { TokenType, UseDecodedCosmosMsg } from '@dao-dao/types'
import { ChainId, TokenType, UseDecodedCosmosMsg } from '@dao-dao/types'
import {
ActionComponent,
ActionKey,
Expand Down Expand Up @@ -72,6 +72,11 @@ export const makeCommunityPoolDepositAction: ActionMaker<
chain: { chain_id: currentChainId },
chainContext: { nativeToken },
}) => {
// Neutron does not use the x/distribution community pool.
if (currentChainId === ChainId.NeutronMainnet) {
return null
}

const useDefaults: UseDefaults<CommunityPoolDepositData> = () => ({
chainId: currentChainId,
amount: 100,
Expand Down
Loading

2 comments on commit b734c63

@vercel
Copy link

@vercel vercel bot commented on b734c63 Sep 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on b734c63 Sep 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.