Skip to content

Commit

Permalink
Merge pull request #2646 from decentdao/feature/#2533-example-proposa…
Browse files Browse the repository at this point in the history
…l-templates

`[ENG-65]` `[ENG-66]` - example proposal templates + unified UX for Sablier PB and general PB
  • Loading branch information
mudrila authored Jan 24, 2025
2 parents 395661a + 60d14be commit a1de1a2
Show file tree
Hide file tree
Showing 39 changed files with 2,377 additions and 1,621 deletions.
117 changes: 77 additions & 40 deletions src/components/ProposalBuilder/ProposalActionCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,80 @@ import { ArrowsDownUp, CheckSquare, Trash } from '@phosphor-icons/react';
import { useTranslation } from 'react-i18next';
import { formatUnits, getAddress, zeroAddress } from 'viem';
import PencilWithLineIcon from '../../assets/theme/custom/icons/PencilWithLineIcon';
import { useGetAccountName } from '../../hooks/utils/useGetAccountName';
import { useFractal } from '../../providers/App/AppProvider';
import { useProposalActionsStore } from '../../store/actions/useProposalActionsStore';
import { CreateProposalAction, ProposalActionType } from '../../types/proposalBuilder';
import { Card } from '../ui/cards/Card';
import { SendAssetsData } from '../ui/modals/SendAssetsModal';
import { SendAssetsActionCard } from '../ui/cards/SendAssetsActionCard';

export function SendAssetsAction({
index,
action,
onRemove,
}: {
index: number;
action: SendAssetsData;
onRemove: (index: number) => void;
action: CreateProposalAction;
onRemove: () => void;
}) {
const {
treasury: { assetsFungible },
} = useFractal();
const destinationAddress = action.transactions[0].parameters[0].value
? getAddress(action.transactions[0].parameters[0].value)
: zeroAddress;
const transferAmount = BigInt(action.transactions[0].parameters[1].value || '0');

if (!destinationAddress || !transferAmount) {
return null;
}

// @todo: This does not work for native asset
const actionAsset = assetsFungible.find(
asset => getAddress(asset.tokenAddress) === getAddress(action.transactions[0].targetAddress),
);

if (!actionAsset) {
return null;
}

return (
<SendAssetsActionCard
action={{
destinationAddress,
transferAmount,
asset: actionAsset,
nonceInput: undefined,
}}
onRemove={onRemove}
/>
);
}

export function AirdropAction({
action,
onRemove,
}: {
action: CreateProposalAction;
onRemove: () => void;
}) {
const { t } = useTranslation('common');
const { displayName } = useGetAccountName(action.destinationAddress);
const {
treasury: { assetsFungible },
} = useFractal();
const totalAmountString = action.transactions[1].parameters[2].value?.slice(1, -1);
const totalAmount = BigInt(
totalAmountString?.split(',').reduce((acc, curr) => acc + BigInt(curr), 0n) || '0',
);
const recipientsCount = action.transactions[1].parameters[1].value?.split(',').length || 0;

// First transaction in the airdrop proposal will be approval transaction, which is called on the token
// Thus we can find the asset by looking at the target address of the first transaction

const actionAsset = assetsFungible.find(
asset => getAddress(asset.tokenAddress) === getAddress(action.transactions[0].targetAddress),
);

if (!actionAsset) {
return null;
}
return (
<Card my="0.5rem">
<Flex justifyContent="space-between">
Expand All @@ -35,20 +90,20 @@ export function SendAssetsAction({
h="1.5rem"
color="lilac-0"
/>
<Text>{t('transfer')}</Text>
<Text>{t('airdrop')}</Text>
<Text color="lilac-0">
{formatUnits(action.transferAmount, action.asset.decimals)} {action.asset.symbol}
{formatUnits(totalAmount, actionAsset.decimals)} {actionAsset.symbol}
</Text>
<Text>{t('to').toLowerCase()}</Text>
<Text color="lilac-0">{displayName}</Text>
<Text color="lilac-0">
{recipientsCount} {t('recipients')}
</Text>
</Flex>
<Button
color="red-0"
variant="tertiary"
size="sm"
onClick={() => {
onRemove(index);
}}
onClick={onRemove}
>
<Icon as={Trash} />
</Button>
Expand All @@ -67,36 +122,18 @@ export function ProposalActionCard({
canBeDeleted: boolean;
}) {
const { removeAction } = useProposalActionsStore();
const {
treasury: { assetsFungible },
} = useFractal();
if (action.actionType === ProposalActionType.TRANSFER) {
const destinationAddress = action.transactions[0].parameters[0].value
? getAddress(action.transactions[0].parameters[0].value)
: zeroAddress;
const transferAmount = BigInt(action.transactions[0].parameters[1].value || '0');
if (!destinationAddress || !transferAmount) {
return null;
}

const actionAsset = assetsFungible.find(
asset => getAddress(asset.tokenAddress) === destinationAddress,
);

if (!actionAsset) {
return null;
}
return (
<SendAssetsAction
key={index}
index={index}
action={{
destinationAddress,
transferAmount,
asset: actionAsset,
nonceInput: undefined,
}}
onRemove={removeAction}
action={action}
onRemove={() => removeAction(index)}
/>
);
} else if (action.actionType === ProposalActionType.AIRDROP) {
return (
<AirdropAction
action={action}
onRemove={() => removeAction(index)}
/>
);
}
Expand Down
Loading

0 comments on commit a1de1a2

Please sign in to comment.