Skip to content

Commit

Permalink
feat: add option to flag offchain proposals (#1063)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sekhmet authored Dec 20, 2024
1 parent 91bdb3e commit 5ebcc3c
Show file tree
Hide file tree
Showing 10 changed files with 132 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/lucky-kangaroos-approve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@snapshot-labs/sx": patch
---

add flagProposal method to offchain EthereumSig client
20 changes: 20 additions & 0 deletions apps/ui/src/composables/useActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,25 @@ export function useActions() {
return true;
}

async function flagProposal(proposal: Proposal) {
if (!web3.value.account) {
await forceLogin();
return false;
}

const network = getNetwork(proposal.network);
if (!network.managerConnectors.includes(web3.value.type as Connector)) {
throw new Error(`${web3.value.type} is not supported for this action`);
}

await wrapPromise(
proposal.network,
network.actions.flagProposal(auth.web3, proposal)
);

return true;
}

async function cancelProposal(proposal: Proposal) {
if (!web3.value.account) {
await forceLogin();
Expand Down Expand Up @@ -634,6 +653,7 @@ export function useActions() {
vote: wrapWithErrors(vote),
propose: wrapWithErrors(propose),
updateProposal: wrapWithErrors(updateProposal),
flagProposal: wrapWithErrors(flagProposal),
cancelProposal: wrapWithErrors(cancelProposal),
finalizeProposal: wrapWithErrors(finalizeProposal),
executeTransactions: wrapWithErrors(executeTransactions),
Expand Down
3 changes: 3 additions & 0 deletions apps/ui/src/networks/evm/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,9 @@ export function createActions(
{ noWait: isContract }
);
},
flagProposal: () => {
throw new Error('Not implemented');
},
cancelProposal: async (web3: Web3Provider, proposal: Proposal) => {
await verifyNetwork(web3, chainId);

Expand Down
9 changes: 9 additions & 0 deletions apps/ui/src/networks/offchain/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,15 @@ export function createActions(

return client.updateProposal({ signer: web3.getSigner(), data });
},
flagProposal(web3: Web3Provider, proposal: Proposal) {
return client.flagProposal({
signer: web3.getSigner(),
data: {
proposal: proposal.proposal_id as string,
space: proposal.space.id
}
});
},
cancelProposal(web3: Web3Provider, proposal: Proposal) {
return client.cancel({
signer: web3.getSigner(),
Expand Down
3 changes: 3 additions & 0 deletions apps/ui/src/networks/starknet/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,9 @@ export function createActions(
data
});
},
flagProposal: () => {
throw new Error('Not implemented');
},
cancelProposal: async (web3: any, proposal: Proposal) => {
await verifyStarknetNetwork(web3, chainId);

Expand Down
1 change: 1 addition & 0 deletions apps/ui/src/networks/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ export type ReadOnlyNetworkActions = {
labels: string[],
executions: ExecutionInfo[] | null
): Promise<any>;
flagProposal(web3: Web3Provider, proposal: Proposal);
cancelProposal(web3: Web3Provider, proposal: Proposal);
vote(
web3: Web3Provider,
Expand Down
48 changes: 47 additions & 1 deletion apps/ui/src/views/Proposal/Overview.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const uiStore = useUiStore();
const proposalsStore = useProposalsStore();
const { getCurrent, getTsFromCurrent } = useMetaStore();
const { web3 } = useWeb3();
const { cancelProposal } = useActions();
const { flagProposal, cancelProposal } = useActions();
const { createDraft } = useEditor();
const {
state: aiSummaryState,
Expand All @@ -42,9 +42,24 @@ const {
const modalOpenVotes = ref(false);
const modalOpenTimeline = ref(false);
const flagging = ref(false);
const cancelling = ref(false);
const aiSummaryOpen = ref(false);
const flaggable = computed(() => {
if (!offchainNetworks.includes(props.proposal.network)) return false;
if (props.proposal.flagged) return false;
const addresses = [
props.proposal.space.admins || [],
props.proposal.space.moderators || []
].flat();
return addresses.some(address =>
compareAddresses(address, web3.value.account)
);
});
const editable = computed(() => {
// HACK: here we need to use snapshot instead of start because start is artificially
// shifted for Starknet's proposals with ERC20Votes strategies.
Expand Down Expand Up @@ -176,6 +191,22 @@ async function handleDuplicateClick() {
});
}
async function handleFlagClick() {
flagging.value = true;
try {
const result = await flagProposal(props.proposal);
if (result) {
proposalsStore.reset(props.proposal.space.id, props.proposal.network);
router.push({
name: 'space-overview'
});
}
} finally {
flagging.value = false;
}
}
async function handleCancelClick() {
cancelling.value = true;
Expand Down Expand Up @@ -357,6 +388,21 @@ onBeforeUnmount(() => destroyAudio());
Edit proposal
</button>
</UiDropdownItem>
<UiDropdownItem
v-if="flaggable"
v-slot="{ active, disabled }"
:disabled="flagging"
>
<button
type="button"
class="flex items-center gap-2"
:class="{ 'opacity-80': active, 'opacity-40': disabled }"
@click="handleFlagClick"
>
<IH-flag :width="16" />
Flag proposal
</button>
</UiDropdownItem>
<UiDropdownItem
v-if="cancellable"
v-slot="{ active, disabled }"
Expand Down
20 changes: 20 additions & 0 deletions packages/sx.js/src/clients/offchain/ethereum-sig/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
deleteSpaceTypes,
domain,
encryptedVoteTypes,
flagProposalTypes,
followSpaceTypes,
proposeTypes,
rankedChoiceVoteTypes,
Expand All @@ -29,6 +30,7 @@ import {
DeleteSpace,
EIP712CancelProposalMessage,
EIP712DeleteSpaceMessage,
EIP712FlagProposalMessage,
EIP712FollowSpaceMessage,
EIP712Message,
EIP712ProposeMessage,
Expand All @@ -40,6 +42,7 @@ import {
EIP712UpdateUserMessage,
EIP712VoteMessage,
Envelope,
FlagProposal,
FollowSpace,
Propose,
SetAlias,
Expand Down Expand Up @@ -82,6 +85,7 @@ export class EthereumSig {
| EIP712VoteMessage
| EIP712ProposeMessage
| EIP712UpdateProposal
| EIP712FlagProposalMessage
| EIP712CancelProposalMessage
| EIP712FollowSpaceMessage
| EIP712UnfollowSpaceMessage
Expand Down Expand Up @@ -116,6 +120,7 @@ export class EthereumSig {
| Vote
| Propose
| UpdateProposal
| FlagProposal
| CancelProposal
| FollowSpace
| UnfollowSpace
Expand Down Expand Up @@ -200,6 +205,21 @@ export class EthereumSig {
};
}

public async flagProposal({
signer,
data
}: {
signer: Signer & TypedDataSigner;
data: FlagProposal;
}): Promise<Envelope<FlagProposal>> {
const signatureData = await this.sign(signer, data, flagProposalTypes);

return {
signatureData,
data
};
}

public async cancel({
signer,
data
Expand Down
9 changes: 9 additions & 0 deletions packages/sx.js/src/clients/offchain/ethereum-sig/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,15 @@ export const updateProposalTypes = {
]
};

export const flagProposalTypes = {
FlagProposal: [
{ name: 'from', type: 'address' },
{ name: 'space', type: 'string' },
{ name: 'proposal', type: 'string' },
{ name: 'timestamp', type: 'uint64' }
]
};

export const cancelProposalTypes = {
CancelProposal: [
{ name: 'from', type: 'address' },
Expand Down
16 changes: 15 additions & 1 deletion packages/sx.js/src/clients/offchain/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,13 @@ export type EIP712UpdateProposal = {
from?: string;
};

export type EIP712FlagProposalMessage = {
space: string;
proposal: string;
from?: string;
timestamp?: number;
};

export type EIP712CancelProposalMessage = {
space: string;
proposal: string;
Expand Down Expand Up @@ -193,11 +200,18 @@ export type UpdateProposal = {
plugins: string;
};

export type CancelProposal = {
export type FlagProposal = {
from?: string;
space: string;
proposal: string;
timestamp?: number;
};

export type CancelProposal = {
from?: string;
space: string;
proposal: string;
timestamp?: number;
};

export type FollowSpace = {
Expand Down

0 comments on commit 5ebcc3c

Please sign in to comment.