Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Space settings to allow voting with alias #3973

Closed
wants to merge 8 commits into from
7 changes: 7 additions & 0 deletions src/components/SettingsVotingBlock.vue
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ const { form } = useFormSpaceSettings(props.context);
:label="$t('settings.hideAbstain')"
:disabled="isViewOnly"
/>

<TuneSwitch
v-model="form.voting.aliased"
:label="$t('settings.enableAliased')"
:disabled="isViewOnly"
:hint="$t('settings.enableAliasedHint')"
/>
</div>
</BaseBlock>
</template>
4 changes: 2 additions & 2 deletions src/composables/useAliasAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@ export function useAliasAction() {
try {
await checkAlias();
if (aliasWallet.value && isValidAlias.value) {
return await action();
return await action(aliasWallet.value);
}
await setAlias();
return await action();
return await action(aliasWallet.value);
} catch (e) {
console.error(e);
loading.value = false;
Expand Down
80 changes: 71 additions & 9 deletions src/composables/useClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export function useClient() {
const { web3 } = useWeb3();
Copy link
Contributor

@samuveth samuveth Jun 21, 2023

Choose a reason for hiding this comment

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

This composable has become a little hard to read. Can we try something like this?

const ACTIONS = {
  proposal: 'proposal',
  vote: 'vote',
  deleteProposal: 'delete-proposal',
  settings: 'settings',
  deleteSpace: 'delete-space'
};

export function useClient() {

  async function executeAndHandleError(func) {
    isSending.value = true;
    try {
      return await func();
    } catch (e: any) {
      errorNotification(e?.error_description || '');
      return e;
    } finally {
      isSending.value = false;
    }
  }

  function bindWithAlias(actionFn) {
    return (client, payload) => {
      return actionWithAlias(aliasWallet =>
        actionFn(client, payload, {
          provider: aliasWallet,
          address: aliasWallet.address
        })
      );
    };
  }

  async function sendEIP712(space, type, payload) {
    const client = isGnosisSafe.value ? clientGnosisSafe : clientEIP712;
    const shouldUseAlias = space.voting?.aliased && !isGnosisSafe.value;

    switch (type) {
      case ACTIONS.proposal:
        return executeAndHandleError(() => sendProposal(space, payload, client, shouldUseAlias));
      case ACTIONS.vote:
        return executeAndHandleError(() => sendVote(space, payload, client, shouldUseAlias));
      case ACTIONS.deleteProposal:
        return executeAndHandleError(() => sendDeleteProposal(space, payload, client, shouldUseAlias));
      case ACTIONS.settings:
        return executeAndHandleError(() => sendSettings(space, payload, client));
      case ACTIONS.deleteSpace:
        return executeAndHandleError(() => sendDeleteSpace(space, client));
      default:
        throw new Error(`Unknown action type: ${type}`);
    }
  }

  function sendProposal(space, payload, client, shouldUseAlias) {
    const actionFn = shouldUseAlias ? bindWithAlias(proposal) : proposal;

    let plugins = {};
    if (Object.keys(payload.metadata?.plugins).length !== 0)
      plugins = payload.metadata.plugins;

    const proposalPayload = {
      space: space.id,
      type: payload.type,
      title: payload.name,
      body: payload.body,
      discussion: payload.discussion,
      choices: payload.choices,
      start: payload.start,
      end: payload.end,
      snapshot: payload.snapshot,
      plugins: JSON.stringify(plugins),
      app: definedApp,
      from: web3.value.account
    };

    return actionFn(client, proposalPayload);
  }

  // Similarly implement sendVote, sendDeleteProposal, sendSettings, and sendDeleteSpace


}

const auth = getInstance();
const route = useRoute();
const { actionWithAlias } = useAliasAction();

const DEFINED_APP = (route?.query.app as string) || 'snapshot';

Expand All @@ -35,13 +36,57 @@ export function useClient() {
}
}

const signParams = {
get provider() {
return auth.web3;
},
get address() {
return web3.value.account;
}
};

function vote(client, votePayload, { provider, address } = signParams) {
return client.vote(provider, address, votePayload);
}

function proposal(
client,
proposalPayload,
{ provider, address } = signParams
) {
return client.proposal(provider, address, proposalPayload);
}

function deleteProposal(
client,
deleteProposalPayload,
{ provider, address } = signParams
) {
return client.cancelProposal(provider, address, deleteProposalPayload);
}

function bindWithAlias(actionFn) {
return (client, payload) => {
return actionWithAlias(aliasWallet =>
actionFn(client, payload, {
provider: aliasWallet,
address: aliasWallet.address
})
);
};
}

async function sendEIP712(space, type, payload) {
const client = isGnosisSafe.value ? clientGnosisSafe : clientEIP712;
if (type === 'proposal') {
const shouldUseAlias = space.voting?.aliased && !isGnosisSafe.value;
const proposalFn = shouldUseAlias ? bindWithAlias(proposal) : proposal;

let plugins = {};
if (Object.keys(payload.metadata?.plugins).length !== 0)
plugins = payload.metadata.plugins;
return client.proposal(auth.web3, web3.value.account, {

const proposalPayload = {
space: space.id,
type: payload.type,
title: payload.name,
Expand All @@ -52,23 +97,40 @@ export function useClient() {
end: payload.end,
snapshot: payload.snapshot,
plugins: JSON.stringify(plugins),
app: DEFINED_APP
});
app: DEFINED_APP,
from: web3.value.account
};

return proposalFn(client, proposalPayload);
} else if (type === 'vote') {
return client.vote(auth.web3, web3.value.account, {
const shouldUseAlias = space.voting?.aliased && !isGnosisSafe.value;
const voteFn = shouldUseAlias ? bindWithAlias(vote) : vote;

const votePayload = {
space: space.id,
proposal: payload.proposal.id,
type: payload.proposal.type,
choice: payload.choice,
privacy: payload.privacy,
app: DEFINED_APP,
reason: payload.reason
});
reason: payload.reason,
from: web3.value.account
};

return voteFn(client, votePayload);
} else if (type === 'delete-proposal') {
return client.cancelProposal(auth.web3, web3.value.account, {
const shouldUseAlias = space.voting?.aliased && !isGnosisSafe.value;
const deleteProposalFn = shouldUseAlias
? bindWithAlias(deleteProposal)
: deleteProposal;

const deleteProposalPayload = {
space: space.id,
proposal: payload.proposal.id
});
proposal: payload.proposal.id,
from: web3.value.account
};

return deleteProposalFn(client, deleteProposalPayload);
} else if (type === 'settings') {
return client.space(auth.web3, web3.value.account, {
space: space.id,
Expand Down
3 changes: 2 additions & 1 deletion src/composables/useFormSpaceSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ const EMPTY_SPACE_FORM = {
period: 0,
quorum: 0,
type: '',
privacy: ''
privacy: '',
aliased: false
},
validation: clone(DEFAULT_PROPOSAL_VALIDATION),
voteValidation: clone(DEFAULT_VOTE_VALIDATION),
Expand Down
1 change: 1 addition & 0 deletions src/helpers/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ export interface ExtendedSpace {
quorum: number | null;
type: string | null;
privacy: string | null;
aliased: boolean;
};
}

Expand Down
1 change: 1 addition & 0 deletions src/helpers/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,7 @@ export const SPACE_QUERY = gql`
quorum
privacy
hideAbstain
aliased
}
strategies {
name
Expand Down
2 changes: 2 additions & 0 deletions src/locales/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,8 @@
"voting": "Voting",
"votingDelay": "Voting delay",
"votingPeriod": "Voting period",
"enableAliased": "Allow actions with session keys",
"enableAliasedHint": "Voting, creating and deleting proposals will no longer require the user to manually sign each time.",
"hours": "Hours",
"days": "Days",
"quorum": {
Expand Down