-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added cross-chain polytone execute action.
- Loading branch information
Showing
10 changed files
with
303 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
41 changes: 41 additions & 0 deletions
41
packages/stateful/actions/core/advanced/CrossChainExecute/Component.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { useTranslation } from 'react-i18next' | ||
|
||
import { | ||
NestedActionsEditor, | ||
NestedActionsEditorOptions, | ||
NestedActionsRenderer, | ||
NestedActionsRendererProps, | ||
} from '@dao-dao/stateless' | ||
import { NestedActionsEditorFormData } from '@dao-dao/types' | ||
import { ActionComponent } from '@dao-dao/types/actions' | ||
|
||
export type CrossChainExecuteData = { | ||
chainId: string | ||
} & NestedActionsEditorFormData | ||
|
||
export type CrossChainExecuteOptions = NestedActionsEditorOptions & | ||
Omit<NestedActionsRendererProps, 'msgsFieldName'> | ||
|
||
export const CrossChainExecuteComponent: ActionComponent< | ||
CrossChainExecuteOptions | ||
> = (props) => { | ||
const { t } = useTranslation() | ||
const { fieldNamePrefix, isCreating, options } = props | ||
|
||
return ( | ||
<> | ||
<p className="title-text -mb-1 mt-1">{t('title.actions')}</p> | ||
|
||
{isCreating ? ( | ||
<NestedActionsEditor {...props} /> | ||
) : ( | ||
<div className="flex flex-col gap-2"> | ||
<NestedActionsRenderer | ||
{...options} | ||
msgsFieldName={fieldNamePrefix + 'msgs'} | ||
/> | ||
</div> | ||
)} | ||
</> | ||
) | ||
} |
29 changes: 29 additions & 0 deletions
29
packages/stateful/actions/core/advanced/CrossChainExecute/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# CrossChainExecute | ||
|
||
Execute cross-chain messages via a Polytone account. | ||
|
||
## Bulk import format | ||
|
||
This is relevant when bulk importing actions, as described in [this | ||
guide](https://github.com/DA0-DA0/dao-dao-ui/wiki/Bulk-importing-actions). | ||
|
||
### Key | ||
|
||
`crossChainExecute` | ||
|
||
### Data format | ||
|
||
```json | ||
{ | ||
"chainId": "<CHAIN ID>", | ||
"_actionData": [ | ||
// ACTIONS | ||
] | ||
} | ||
``` | ||
|
||
Each action in `_actionData` should be formatted similar to how bulk actions are | ||
formatted, with `key` and `data` fields, except `key` should be replaced with | ||
`actionKey`. Thus, each object in `_actionData` should be an object with | ||
`actionKey` and `data`, formatted the same as the `actions` array in the bulk | ||
JSON format. |
171 changes: 171 additions & 0 deletions
171
packages/stateful/actions/core/advanced/CrossChainExecute/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
import { useCallback } from 'react' | ||
import { useFormContext } from 'react-hook-form' | ||
|
||
import { | ||
ChainPickerInput, | ||
ChainProvider, | ||
TelescopeEmoji, | ||
useChain, | ||
} from '@dao-dao/stateless' | ||
import { | ||
ActionComponent, | ||
ActionContextType, | ||
ActionKey, | ||
ActionMaker, | ||
UseDecodedCosmosMsg, | ||
UseDefaults, | ||
UseTransformToCosmos, | ||
} from '@dao-dao/types' | ||
import { | ||
decodePolytoneExecuteMsg, | ||
maybeMakePolytoneExecuteMessage, | ||
} from '@dao-dao/utils' | ||
|
||
import { SuspenseLoader } from '../../../../components' | ||
import { | ||
WalletActionsProvider, | ||
useActionOptions, | ||
useActionsForMatching, | ||
useLoadedActionsAndCategories, | ||
} from '../../../react' | ||
import { | ||
CrossChainExecuteData, | ||
CrossChainExecuteComponent as StatelessCrossChainExecuteComponent, | ||
} from './Component' | ||
|
||
const InnerComponentLoading: ActionComponent = (props) => ( | ||
<StatelessCrossChainExecuteComponent | ||
{...props} | ||
options={{ | ||
categories: [], | ||
loadedActions: {}, | ||
actionsForMatching: [], | ||
SuspenseLoader, | ||
}} | ||
/> | ||
) | ||
|
||
const InnerComponent: ActionComponent = (props) => { | ||
const { categories, loadedActions } = useLoadedActionsAndCategories({ | ||
isCreating: props.isCreating, | ||
}) | ||
const actionsForMatching = useActionsForMatching() | ||
|
||
return ( | ||
<StatelessCrossChainExecuteComponent | ||
{...props} | ||
options={{ | ||
categories, | ||
loadedActions, | ||
actionsForMatching, | ||
SuspenseLoader, | ||
}} | ||
/> | ||
) | ||
} | ||
|
||
const InnerComponentWrapper: ActionComponent = (props) => { | ||
const { chain_id: chainId } = useChain() | ||
const { context } = useActionOptions() | ||
|
||
if (context.type !== ActionContextType.Dao) { | ||
return null | ||
} | ||
|
||
const address = | ||
chainId === context.info.chainId | ||
? context.info.coreAddress | ||
: context.info.polytoneProxies[chainId] || '' | ||
|
||
return address ? ( | ||
<WalletActionsProvider address={address}> | ||
<InnerComponent {...props} /> | ||
</WalletActionsProvider> | ||
) : ( | ||
<InnerComponentLoading {...props} /> | ||
) | ||
} | ||
|
||
const Component: ActionComponent = (props) => { | ||
const { | ||
context, | ||
chain: { chain_id: currentChainId }, | ||
} = useActionOptions() | ||
|
||
const { watch } = useFormContext<CrossChainExecuteData>() | ||
const chainId = watch((props.fieldNamePrefix + 'chainId') as 'chainId') | ||
|
||
return ( | ||
<> | ||
{context.type === ActionContextType.Dao && ( | ||
<ChainPickerInput | ||
className="mb-4" | ||
disabled={!props.isCreating} | ||
excludeChainIds={[currentChainId]} | ||
fieldName={props.fieldNamePrefix + 'chainId'} | ||
/> | ||
)} | ||
|
||
{chainId !== currentChainId && ( | ||
// Re-render when chain changes so hooks and state reset. | ||
<ChainProvider key={chainId} chainId={chainId}> | ||
<InnerComponentWrapper {...props} /> | ||
</ChainProvider> | ||
)} | ||
</> | ||
) | ||
} | ||
|
||
export const makeCrossChainExecuteAction: ActionMaker< | ||
CrossChainExecuteData | ||
> = ({ t, context, chain: { chain_id: currentChainId } }) => { | ||
// Only support DAO polytone. | ||
if (context.type !== ActionContextType.Dao) { | ||
return null | ||
} | ||
|
||
const useDefaults: UseDefaults<CrossChainExecuteData> = () => ({ | ||
chainId: currentChainId, | ||
msgs: [], | ||
}) | ||
|
||
const useDecodedCosmosMsg: UseDecodedCosmosMsg<CrossChainExecuteData> = ( | ||
msg: Record<string, any> | ||
) => { | ||
const decodedPolytone = decodePolytoneExecuteMsg(currentChainId, msg) | ||
|
||
return decodedPolytone.match | ||
? { | ||
match: true, | ||
data: { | ||
chainId: decodedPolytone.chainId, | ||
msgs: decodedPolytone.cosmosMsgs, | ||
}, | ||
} | ||
: { | ||
match: false, | ||
} | ||
} | ||
|
||
const useTransformToCosmos: UseTransformToCosmos< | ||
CrossChainExecuteData | ||
> = () => | ||
useCallback( | ||
({ chainId, msgs }) => | ||
currentChainId === chainId | ||
? undefined | ||
: maybeMakePolytoneExecuteMessage(currentChainId, chainId, msgs), | ||
[] | ||
) | ||
|
||
return { | ||
key: ActionKey.CrossChainExecute, | ||
Icon: TelescopeEmoji, | ||
label: t('title.crossChainExecute'), | ||
description: t('info.crossChainExecuteDescription'), | ||
Component, | ||
useDefaults, | ||
useTransformToCosmos, | ||
useDecodedCosmosMsg, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,16 @@ | ||
import { ActionCategoryKey, ActionCategoryMaker } from '@dao-dao/types' | ||
|
||
import { makeBulkImportAction } from './BulkImport' | ||
import { makeCrossChainExecuteAction } from './CrossChainExecute' | ||
import { makeCustomAction } from './Custom' | ||
|
||
export const makeAdvancedActionCategory: ActionCategoryMaker = ({ t }) => ({ | ||
key: ActionCategoryKey.Custom, | ||
label: t('actionCategory.advancedLabel'), | ||
description: t('actionCategory.advancedDescription'), | ||
actionMakers: [makeCustomAction, makeBulkImportAction], | ||
actionMakers: [ | ||
makeCustomAction, | ||
makeCrossChainExecuteAction, | ||
makeBulkImportAction, | ||
], | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.