Skip to content

Commit

Permalink
add other necessary actions to become SubDAO (updating contract admin…
Browse files Browse the repository at this point in the history
… and registering subDAO), and fixed action detection
  • Loading branch information
NoahSaso committed Jul 17, 2024
1 parent e6a7196 commit 66908dd
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 11 deletions.
2 changes: 2 additions & 0 deletions packages/i18n/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -901,6 +901,7 @@
"info": {
"abstainVote": "Abstain",
"acceptSubDaoActionDescription": "Accept a pending SubDAO's ownership transfer request. Be sure that the SubDAO-to-be has already requested to join your DAO through the \"Become SubDAO\" action.",
"acceptSubDaoActionOtherActionsAdded": "Other actions that are required to register a new SubDAO have been added to the proposal automatically.",
"acceptSubDaoDescription": "Accept a DAO's request to become a SubDAO.",
"acknowledgeServiceFee": "We acknowledge that {{fee}} will be charged from the treasury for registration to the rebalancer.",
"acknowledgeServiceFee_none": "We acknowledge that there is no fee to register for the rebalancer.",
Expand Down Expand Up @@ -952,6 +953,7 @@
"availableBalance": "Available balance",
"availableHistoryLoaded": "All available history has been loaded.",
"becomeSubDaoActionDescription": "Provide the address of a DAO to request to become its SubDAO. The DAO will then need to accept your request to complete the ownership transfer and become your parent. Once the transfer is complete, only your new parent DAO can transfer ownership in the future. Keep in mind that your parent DAO will have full authority to execute anything it wants to on behalf of this DAO.",
"becomeSubDaoActionDescription_created": "The parent DAO needs to accept this request to complete the ownership transfer and become your parent. Once the transfer is complete, only your new parent DAO can transfer ownership in the future. Keep in mind that your parent DAO will have full authority to execute anything it wants to on behalf of this DAO.",
"becomeSubDaoDescription": "Request to become a SubDAO of a DAO.",
"betterNonPfmIbcPathAvailable": "A better path exists that unwinds the IBC token properly, but it requires hops that cannot be performed in a single proposal due to the configuration of one or more of the chains involved. You may safely use the direct path above, though it likely results in an undesirable IBC token on the final chain that will eventually need to be unwound. If you wish to unwind it manually, follow the path below by creating an individual proposal for the first hop, then a second proposal once the first one is passed and executed, and so on.",
"betterPfmIbcPathAvailable_one": "A better path exists that unwinds the IBC token properly, but it requires you to have an account on {{chains}}. An account must exist on each intermediary chain in a multi-hop transaction to act as a failsafe in the event of catastrophic failure (unlikely). Either a cross-chain or ICA account works and will be automatically detected once created. You may safely use the direct path above, though it likely results in an undesirable IBC token on the final chain that will eventually need to be unwound.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import {
import { useActionOptions } from '../../../react'
import { UpdateAdminComponent as StatelessUpdateAdminComponent } from './Component'

interface UpdateAdminData {
export type UpdateAdminData = {
chainId: string
contract: string
newAdmin: string
Expand Down
142 changes: 135 additions & 7 deletions packages/stateful/actions/core/subdaos/AcceptSubDao/Component.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import { ComponentType } from 'react'
import { ComponentType, useEffect, useState } from 'react'
import { useFormContext } from 'react-hook-form'
import { useTranslation } from 'react-i18next'

import { InputErrorMessage, InputLabel } from '@dao-dao/stateless'
import { AddressInputProps } from '@dao-dao/types'
import { ActionComponent } from '@dao-dao/types/actions'
import { makeValidateAddress, validateRequired } from '@dao-dao/utils'
import { ActionComponent, ActionKey } from '@dao-dao/types/actions'
import {
isValidBech32Address,
makeValidateAddress,
validateRequired,
} from '@dao-dao/utils'

import { useActionOptions } from '../../../react'
import { DaoAdminExecData } from '../../dao_governance/DaoAdminExec/Component'
import { UpdateAdminData } from '../../smart_contracting/UpdateAdmin'
import { ManageSubDaosData } from '../ManageSubDaos/Component'

export type AcceptSubDaoData = {
address: string
Expand All @@ -20,20 +27,135 @@ type AcceptSubDaoDataOptions = {
export const AcceptSubDaoComponent: ActionComponent<
AcceptSubDaoDataOptions,
AcceptSubDaoData
> = ({ fieldNamePrefix, errors, isCreating, options: { AddressInput } }) => {
> = ({
fieldNamePrefix,
errors,
isCreating,
allActionsWithData,
index,
addAction,
options: { AddressInput },
}) => {
const { t } = useTranslation()
const {
chain: { bech32_prefix: bech32Prefix },
address: currentAddress,
chain: { chain_id: chainId, bech32_prefix: bech32Prefix },
} = useActionOptions()

const { register } = useFormContext<AcceptSubDaoData>()
const { watch, register, setValue, getValues } =
useFormContext<AcceptSubDaoData>()

const addressFieldName = (fieldNamePrefix + 'address') as 'address'

const address = watch(addressFieldName)
const isValid = !!address && isValidBech32Address(address, bech32Prefix)
const [otherActionsAdded, setOtherActionsAdded] = useState(false)
useEffect(() => {
if (!isCreating || !isValid) {
return
}

const existingUpdateAdminIndex = allActionsWithData.findIndex(
(a, i) =>
i > index &&
a.actionKey === ActionKey.DaoAdminExec &&
(a.data as DaoAdminExecData)?._actionData?.length === 1 &&
(a.data as DaoAdminExecData)._actionData![0].actionKey ===
ActionKey.UpdateAdmin &&
(a.data as DaoAdminExecData)._actionData![0].data.newAdmin ===
currentAddress
)
const existingManageSubDaosIndex = allActionsWithData.findIndex(
(a, i) => i > index && a.actionKey === ActionKey.ManageSubDaos
)

if (existingUpdateAdminIndex === -1) {
addAction(
{
actionKey: ActionKey.DaoAdminExec,
data: {
coreAddress: address,
_actionData: [
{
actionKey: ActionKey.UpdateAdmin,
data: {
chainId,
contract: address,
newAdmin: currentAddress,
} as UpdateAdminData,
},
],
} as DaoAdminExecData,
},
// After current action.
index + 1
)
} else {
// Path to the address field on the update admin sub-action of the DAO
// admin exec action.
const existingAddressFieldName = fieldNamePrefix.replace(
new RegExp(`${index}\\.data.$`),
`${existingUpdateAdminIndex}.data._actionData.0.data.contract`
)

// If the address isn't correct, update the existing one.
if (getValues(existingAddressFieldName as any) !== address) {
setValue(existingAddressFieldName as any, address)
}
}

if (existingManageSubDaosIndex === -1) {
addAction(
{
actionKey: ActionKey.ManageSubDaos,
data: {
toAdd: [
{
addr: address,
},
],
toRemove: [],
} as ManageSubDaosData,
},
// After DAO admin exec / update admin action.
index + 2
)
} else {
// Path to the address field on the manage subDAOs action.
const existingAddressFieldName = fieldNamePrefix.replace(
new RegExp(`${index}\\.data.$`),
`${existingManageSubDaosIndex}.data.toAdd.0.addr`
)

// If the address isn't correct, update the existing one.
if (getValues(existingAddressFieldName as any) !== address) {
setValue(existingAddressFieldName as any, address)
}
}

setOtherActionsAdded(true)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [
isCreating,
isValid,
address,
index,
addAction,
currentAddress,
chainId,
fieldNamePrefix,
getValues,
setValue,
])

return (
<>
<div className="space-y-3">
<p className="max-w-prose">{t('info.acceptSubDaoActionDescription')}</p>
{isCreating && (
<p className="max-w-prose">
{t('info.acceptSubDaoActionDescription')}
</p>
)}

<div className="space-y-1">
<InputLabel name={t('form.acceptSubDaoAddressInputLabel')} />
Expand All @@ -47,6 +169,12 @@ export const AcceptSubDaoComponent: ActionComponent<
/>
<InputErrorMessage error={errors?.address} />
</div>

{otherActionsAdded && (
<p className="max-w-prose">
{t('info.acceptSubDaoActionOtherActionsAdded')}
</p>
)}
</div>
</>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ export const BecomeSubDaoComponent: ActionComponent<
return (
<>
<div className="space-y-3">
<p className="max-w-prose">{t('info.becomeSubDaoActionDescription')}</p>
<p className="max-w-prose">
{t('info.becomeSubDaoActionDescription', {
context: !isCreating ? 'created' : undefined,
})}
</p>

<div className="space-y-1">
<InputLabel name={t('form.becomeSubDaoAdminInputLabel')} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const useDecodedCosmosMsg: UseDecodedCosmosMsg<BecomeSubDaoData> = (
return {
match: true,
data: {
admin: msg.wasm.execute.nominate_admin.admin,
admin: msg.wasm.execute.msg.nominate_admin.admin,
},
}
} catch {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { makeValidateAddress, validateRequired } from '@dao-dao/utils'

import { useActionOptions } from '../../../react'

export interface ManageSubDaosData {
export type ManageSubDaosData = {
toAdd: SubDao[]
toRemove: { address: string }[]
}
Expand Down

0 comments on commit 66908dd

Please sign in to comment.