diff --git a/docs/multisig.md b/docs/multisig.md index c9d91ac7e..fb7c4d98e 100644 --- a/docs/multisig.md +++ b/docs/multisig.md @@ -226,7 +226,8 @@ so that the plugin is configured

* [.executeProposal(ExecuteProposalParams)](#MultisigClientMethods+executeProposal) ⇒ \* * [.canApprove(addressOrEns)](#MultisigClientMethods+canApprove) ⇒ \* * [.canExecute(addressOrEns)](#MultisigClientMethods+canExecute) ⇒ \* - * [.getPluginSettings(addressOrEns)](#MultisigClientMethods+getPluginSettings) ⇒ \* + * [.getVotingSettings(addressOrEns)](#MultisigClientMethods+getVotingSettings) ⇒ \* + * [.getMembers(addressOrEns)](#MultisigClientMethods+getMembers) ⇒ \* * [.getProposal(proposalId)](#MultisigClientMethods+getProposal) ⇒ \* * [.getProposals({)](#MultisigClientMethods+getProposals) ⇒ \* @@ -302,13 +303,25 @@ so that the plugin is configured

| --- | --- | | addressOrEns | string | - + -### multisigClientMethods.getPluginSettings(addressOrEns) ⇒ \* -

returns the plugin settings

+### multisigClientMethods.getVotingSettings(addressOrEns) ⇒ \* +

returns the voting settings

**Kind**: instance method of [MultisigClientMethods](#MultisigClientMethods) -**Returns**: \* -

{Promise}

+**Returns**: \* -

{Promise}

+ +| Param | Type | +| --- | --- | +| addressOrEns | string | + + + +### multisigClientMethods.getMembers(addressOrEns) ⇒ \* +

returns the members of the multisig

+ +**Kind**: instance method of [MultisigClientMethods](#MultisigClientMethods) +**Returns**: \* -

{Promise<string[]>}

| Param | Type | | --- | --- | diff --git a/modules/client/CHANGELOG.md b/modules/client/CHANGELOG.md index d7ac9e8cc..3a918e135 100644 --- a/modules/client/CHANGELOG.md +++ b/modules/client/CHANGELOG.md @@ -14,7 +14,8 @@ TEMPLATE: --> ## [UPCOMING] - +### Changed +- Splits `getPluginSettings` in `getVotingSettings` and `getMembers` ## [0.18.0-alpha] ### Added - Add `pinMetadata` examples diff --git a/modules/client/examples.md b/modules/client/examples.md index 0e7f350b1..f48085507 100644 --- a/modules/client/examples.md +++ b/modules/client/examples.md @@ -3080,7 +3080,7 @@ import { Context, ContextPlugin, MultisigClient, - MultisigPluginSettings, + MultisigVotingSettings, } from "@aragon/sdk-client"; import { contextParams } from "../00-client/00-context"; @@ -3093,18 +3093,11 @@ const client = new MultisigClient(contextPlugin); const daoAddressorEns = "0x12345..."; -const settings: MultisigPluginSettings = await client.methods - .getPluginSettings(daoAddressorEns); +const settings: MultisigVotingSettings = await client.methods + .getVotingSettings(daoAddressorEns); console.log(settings); /* { - members: [ - "0x1234567890123456789012345678901234567890", - "0x2345678901234567890123456789012345678901", - "0x3456789012345678901234567890123456789012", - "0x4567890123456789012345678901234567890123", - "0x5678901234567890123456789012345678901234", - ], votingSettings: { minApprovals: 4, onlyListed: true @@ -3288,3 +3281,35 @@ console.log(metadataUri); ipfs://Qm... */ ``` + +### Loading the list of members (multisig plugin) + +```ts +import { + Context, + ContextPlugin, + MultisigClient, + MultisigVotingSettings, +} from "@aragon/sdk-client"; +import { contextParams } from "../00-client/00-context"; + +// Create a simple context +const context: Context = new Context(contextParams); +// Create a plugin context from the simple context +const contextPlugin: ContextPlugin = ContextPlugin.fromContext(context); +// Create an multisig client +const client = new MultisigClient(contextPlugin); + +const daoAddressorEns = "0x12345..."; + +const settings: string[] = await client.methods + .getMembers(daoAddressorEns); +console.log(settings); +/* +[ + "0x1234567890...", + "0x2345678901...", + "0x3456789012...", +] +*/ +``` diff --git a/modules/client/examples/06-multisig-client/08-get-plugin-settings.ts b/modules/client/examples/06-multisig-client/08-get-voting-settings.ts similarity index 61% rename from modules/client/examples/06-multisig-client/08-get-plugin-settings.ts rename to modules/client/examples/06-multisig-client/08-get-voting-settings.ts index ff2460d2d..c1dae9040 100644 --- a/modules/client/examples/06-multisig-client/08-get-plugin-settings.ts +++ b/modules/client/examples/06-multisig-client/08-get-voting-settings.ts @@ -5,7 +5,7 @@ import { Context, ContextPlugin, MultisigClient, - MultisigPluginSettings, + MultisigVotingSettings, } from "@aragon/sdk-client"; import { contextParams } from "../00-client/00-context"; @@ -18,18 +18,11 @@ const client = new MultisigClient(contextPlugin); const daoAddressorEns = "0x12345..."; -const settings: MultisigPluginSettings = await client.methods - .getPluginSettings(daoAddressorEns); +const settings: MultisigVotingSettings = await client.methods + .getVotingSettings(daoAddressorEns); console.log(settings); /* { - members: [ - "0x1234567890123456789012345678901234567890", - "0x2345678901234567890123456789012345678901", - "0x3456789012345678901234567890123456789012", - "0x4567890123456789012345678901234567890123", - "0x5678901234567890123456789012345678901234", - ], votingSettings: { minApprovals: 4, onlyListed: true diff --git a/modules/client/examples/06-multisig-client/12-get-members.ts b/modules/client/examples/06-multisig-client/12-get-members.ts new file mode 100644 index 000000000..32094f548 --- /dev/null +++ b/modules/client/examples/06-multisig-client/12-get-members.ts @@ -0,0 +1,30 @@ +/* MARKDOWN +### Loading the list of members (multisig plugin) +*/ +import { + Context, + ContextPlugin, + MultisigClient, + MultisigVotingSettings, +} from "@aragon/sdk-client"; +import { contextParams } from "../00-client/00-context"; + +// Create a simple context +const context: Context = new Context(contextParams); +// Create a plugin context from the simple context +const contextPlugin: ContextPlugin = ContextPlugin.fromContext(context); +// Create an multisig client +const client = new MultisigClient(contextPlugin); + +const daoAddressorEns = "0x12345..."; + +const settings: string[] = await client.methods + .getMembers(daoAddressorEns); +console.log(settings); +/* +[ + "0x1234567890...", + "0x2345678901...", + "0x3456789012...", +] +*/ diff --git a/modules/client/package.json b/modules/client/package.json index f70288f4a..2f7170b96 100644 --- a/modules/client/package.json +++ b/modules/client/package.json @@ -1,7 +1,7 @@ { "name": "@aragon/sdk-client", "author": "Aragon Association", - "version": "0.18.0-alpha", + "version": "0.19.0-alpha", "license": "MIT", "main": "dist/index.js", "module": "dist/sdk-client.esm.js", diff --git a/modules/client/src/multisig/interfaces.ts b/modules/client/src/multisig/interfaces.ts index 8b095833c..7cf96de84 100644 --- a/modules/client/src/multisig/interfaces.ts +++ b/modules/client/src/multisig/interfaces.ts @@ -30,9 +30,12 @@ export interface IMultisigClientMethods extends IClientCore { ) => AsyncGenerator; canApprove: (params: CanApproveParams) => Promise; canExecute: (params: CanExecuteParams) => Promise; - getPluginSettings: ( + getVotingSettings: ( addressOrEns: string, - ) => Promise; + ) => Promise; + getMembers: ( + addressOrEns: string, + ) => Promise; getProposal: (propoosalId: string) => Promise; getProposals: ( params: IProposalQueryParams, @@ -162,10 +165,13 @@ export type SubgraphMultisigApproversListItem = { approver: { id: string }; }; -export type SubgraphMultisigPluginSettings = { +export type SubgraphMultisigVotingSettings = { + minApprovals: string; + onlyListed: boolean; +}; + +export type SubgraphMultisigMembers = { members: { address: string; }[]; - minApprovals: string; - onlyListed: boolean; }; diff --git a/modules/client/src/multisig/internal/client/methods.ts b/modules/client/src/multisig/internal/client/methods.ts index a682c4bf0..e9a665f3b 100644 --- a/modules/client/src/multisig/internal/client/methods.ts +++ b/modules/client/src/multisig/internal/client/methods.ts @@ -19,12 +19,13 @@ import { CreateMultisigProposalParams, ExecuteProposalParams, IMultisigClientMethods, - MultisigPluginSettings, MultisigProposal, MultisigProposalListItem, - SubgraphMultisigPluginSettings, + MultisigVotingSettings, + SubgraphMultisigMembers, SubgraphMultisigProposal, SubgraphMultisigProposalListItem, + SubgraphMultisigVotingSettings, } from "../../interfaces"; import { CanExecuteParams, @@ -53,6 +54,7 @@ import { } from "../graphql-queries"; import { toMultisigProposal, toMultisigProposalListItem } from "../utils"; import { toUtf8Bytes } from "@ethersproject/strings"; +import { QueryMultisigMembers } from "../graphql-queries/members"; /** * Methods module the SDK Address List Client @@ -280,15 +282,15 @@ export class MultisigClientMethods extends ClientCore return multisigContract.canExecute(params.proposalId); } /** - * returns the plugin settings + * returns the voting settings * * @param {string} addressOrEns - * @return {*} {Promise} + * @return {*} {Promise} * @memberof MultisigClientMethods */ - public async getPluginSettings( + public async getVotingSettings( address: string, - ): Promise { + ): Promise { // TODO // update this with yup validation if (!isAddress(address)) { @@ -298,21 +300,46 @@ export class MultisigClientMethods extends ClientCore await this.graphql.ensureOnline(); const client = this.graphql.getClient(); const { multisigPlugin }: { - multisigPlugin: SubgraphMultisigPluginSettings; + multisigPlugin: SubgraphMultisigVotingSettings; } = await client.request(QueryMultisigVotingSettings, { address, }); return { - votingSettings: { - onlyListed: multisigPlugin.onlyListed, - minApprovals: parseInt(multisigPlugin.minApprovals), - }, - members: [], + onlyListed: multisigPlugin.onlyListed, + minApprovals: parseInt(multisigPlugin.minApprovals), }; } catch { throw new GraphQLError("Multisig settings"); } } + /** + * returns the members of the multisig + * + * @param {string} addressOrEns + * @return {*} {Promise} + * @memberof MultisigClientMethods + */ + public async getMembers( + address: string, + ): Promise { + // TODO + // update this with yup validation + if (!isAddress(address)) { + throw new InvalidAddressOrEnsError(); + } + try { + await this.graphql.ensureOnline(); + const client = this.graphql.getClient(); + const { multisigPlugin }: { + multisigPlugin: SubgraphMultisigMembers; + } = await client.request(QueryMultisigMembers, { + address, + }); + return multisigPlugin.members.map((member) => member.address); + } catch { + throw new GraphQLError("Multisig members"); + } + } /** * Returns the details of the given proposal * diff --git a/modules/client/src/multisig/internal/graphql-queries/members.ts b/modules/client/src/multisig/internal/graphql-queries/members.ts new file mode 100644 index 000000000..3252c986d --- /dev/null +++ b/modules/client/src/multisig/internal/graphql-queries/members.ts @@ -0,0 +1,11 @@ +import { gql } from "graphql-request"; + +export const QueryMultisigMembers = gql` +query MultisigMembers($address: ID!) { + multisigPlugin(id: $address){ + members { + address + } + } +} +`; diff --git a/modules/client/src/multisig/internal/graphql-queries/settings.ts b/modules/client/src/multisig/internal/graphql-queries/settings.ts index e9badfce0..444e326da 100644 --- a/modules/client/src/multisig/internal/graphql-queries/settings.ts +++ b/modules/client/src/multisig/internal/graphql-queries/settings.ts @@ -3,9 +3,6 @@ import { gql } from "graphql-request"; export const QueryMultisigVotingSettings = gql` query MultisigVotingSettings($address: ID!) { multisigPlugin(id: $address){ - members { - address - } minApprovals onlyListed } diff --git a/modules/client/test/integration/multisig-client/methods.test.ts b/modules/client/test/integration/multisig-client/methods.test.ts index b34c3dbb8..586105fb7 100644 --- a/modules/client/test/integration/multisig-client/methods.test.ts +++ b/modules/client/test/integration/multisig-client/methods.test.ts @@ -217,18 +217,33 @@ describe("Client Multisig", () => { }); describe("Data retrieval", () => { - it("Should get the settings of the plugin", async () => { + it("Should get the voting settings of the plugin", async () => { const ctx = new Context(contextParams); const ctxPlugin = ContextPlugin.fromContext(ctx); const client = new MultisigClient(ctxPlugin); - const settings = await client.methods.getPluginSettings( + const settings = await client.methods.getVotingSettings( TEST_MULTISIG_PLUGIN_ADDRESS, ); expect(typeof settings).toBe("object"); - expect(typeof settings.votingSettings.minApprovals).toBe("number"); - expect(typeof settings.votingSettings.onlyListed).toBe("boolean"); + expect(typeof settings.minApprovals).toBe("number"); + expect(typeof settings.onlyListed).toBe("boolean"); }); + + it("Should get members of the multisig", async () => { + const ctx = new Context(contextParams); + const ctxPlugin = ContextPlugin.fromContext(ctx); + const client = new MultisigClient(ctxPlugin); + + const wallets = await client.methods.getMembers( + TEST_MULTISIG_PLUGIN_ADDRESS, + ); + expect(Array.isArray(wallets)).toBe(true); + expect(wallets.length).toBeGreaterThan(0); + expect(typeof wallets[0]).toBe("string"); + expect(wallets[0]).toMatch(/^0x[A-Fa-f0-9]{40}$/i); + }); + it("Should fetch the given proposal", async () => { const ctx = new Context(contextParams); const ctxPlugin = ContextPlugin.fromContext(ctx);