diff --git a/.gitbook/assets/Untitled Diagram-Page-1.png b/.gitbook/assets/Untitled Diagram-Page-1.png new file mode 100644 index 0000000..b56f2c9 Binary files /dev/null and b/.gitbook/assets/Untitled Diagram-Page-1.png differ diff --git a/.gitbook/assets/Untitled Diagram-preaudit.png b/.gitbook/assets/Untitled Diagram-preaudit.png new file mode 100644 index 0000000..34d6011 Binary files /dev/null and b/.gitbook/assets/Untitled Diagram-preaudit.png differ diff --git a/.gitbook/assets/image (1).png b/.gitbook/assets/image (1).png new file mode 100644 index 0000000..38f3f64 Binary files /dev/null and b/.gitbook/assets/image (1).png differ diff --git a/.gitbook/assets/image.png b/.gitbook/assets/image.png index 38f3f64..6d72050 100644 Binary files a/.gitbook/assets/image.png and b/.gitbook/assets/image.png differ diff --git a/SUMMARY.md b/SUMMARY.md index 50d4da2..2f58692 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -17,6 +17,7 @@ * [Strategies](strategies/README.md) * [What is a strategy?](strategies/what-is-a-strategy.md) * [Create a new strategy](strategies/create.md) + * [How to write a basic strategy](strategies/how-to-write-a-basic-strategy.md) * [Plugins](plugins/README.md) * [Create a plugin](plugins/create.md) * [SafeSnap](plugins/safesnap.md) @@ -34,4 +35,3 @@ * [Contribute](guides/contribute/README.md) * [🙋‍♂️ Support](guides/contribute/support.md) * [Delegation](guides/delegation.md) - diff --git a/graphql-api.md b/graphql-api.md index ae59329..9ca621b 100644 --- a/graphql-api.md +++ b/graphql-api.md @@ -8,31 +8,31 @@ description: >- ## Explorer -You can run queries on Snapshot data using a GraphQL Explorer. +You can run queries on Snapshot data using a GraphQL Explorer. -We have exposed an integrated development environment in the browser that includes docs, syntax highlighting, and validation errors. Click the link below to access the interface. +We have exposed an integrated development environment in the browser that includes docs, syntax highlighting, and validation errors. Click the link below to access the interface. {% embed url="https://hub.snapshot.org/graphql" %} -![](.gitbook/assets/image.png) +![](<.gitbook/assets/image (1).png>) ## Endpoints Production hub -```text +``` https://hub.snapshot.org/graphql ``` Demo hub -```text +``` https://testnet.snapshot.org/graphql ``` ## Queries -### Get a single space +### Get a single space #### Arguments @@ -82,16 +82,16 @@ query { Try on [GraphiQL](https://hub.snapshot.org/graphql?query=query%20%7B%0A%20%20space%28id%3A%20%22yam.eth%22%29%20%7B%0A%20%20%20%20id%0A%20%20%20%20name%0A%20%20%20%20about%0A%20%20%20%20network%0A%20%20%20%20symbol%0A%20%20%20%20members%0A%20%20%7D%0A%7D) -### Get multiple spaces +### Get multiple spaces #### Arguments -first `number` -skip `number` -where: - - id`string` - - id\_in`array` -orderBy `string` +first `number`\ +skip `number`\ +where:\ +\- id`string`\ +\- id\_in`array`\ +orderBy `string`\ orderDirection `asc` or `desc` #### Example @@ -172,9 +172,9 @@ query { Try on [GraphiQL](https://hub.snapshot.org/graphql?query=%0Aquery%20Spaces%20%7B%0A%20%20spaces%28%0A%20%20%20%20first%3A%2020%2C%0A%20%20%20%20skip%3A%200%2C%0A%20%20%20%20orderBy%3A%20%22created%22%2C%0A%20%20%20%20orderDirection%3A%20asc%0A%20%20%29%20%7B%0A%20%20%20%20id%0A%20%20%20%20name%0A%20%20%20%20about%0A%20%20%20%20network%0A%20%20%20%20symbol%0A%20%20%20%20strategies%20%7B%0A%20%20%20%20%20%20name%0A%20%20%20%20%20%20params%0A%20%20%20%20%7D%0A%20%20%20%20admins%0A%20%20%20%20members%0A%20%20%20%20filters%20%7B%0A%20%20%20%20%20%20minScore%0A%20%20%20%20%20%20onlyMembers%0A%20%20%20%20%7D%0A%20%20%20%20plugins%0A%20%20%7D%0A%7D) -### Get a single proposal +### Get a single proposal -#### Arguments +#### Arguments id `string`‌ @@ -239,25 +239,25 @@ query { {% endtab %} {% endtabs %} -Try on [GraphiQL](https://hub.snapshot.org/graphql?operationName=Proposal&query=query%20Proposal%20%7B%0A%20%20proposal%28id%3A%22QmWbpCtwdLzxuLKnMW4Vv4MPFd2pdPX71YBKPasfZxqLUS%22%29%20%7B%0A%20%20%20%20id%0A%20%20%20%20title%0A%20%20%20%20body%0A%20%20%20%20choices%0A%20%20%20%20start%0A%20%20%20%20end%0A%20%20%20%20snapshot%0A%20%20%20%20state%0A%20%20%20%20author%0A%20%20%20%20space%20%7B%0A%20%20%20%20%20%20id%0A%20%20%20%20%20%20name%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D) +Try on [GraphiQL](https://hub.snapshot.org/graphql?operationName=Proposal\&query=query%20Proposal%20%7B%0A%20%20proposal%28id%3A%22QmWbpCtwdLzxuLKnMW4Vv4MPFd2pdPX71YBKPasfZxqLUS%22%29%20%7B%0A%20%20%20%20id%0A%20%20%20%20title%0A%20%20%20%20body%0A%20%20%20%20choices%0A%20%20%20%20start%0A%20%20%20%20end%0A%20%20%20%20snapshot%0A%20%20%20%20state%0A%20%20%20%20author%0A%20%20%20%20space%20%7B%0A%20%20%20%20%20%20id%0A%20%20%20%20%20%20name%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D) -### Get proposals +### Get proposals #### Arguments -first `number` -skip `number` -where: - - id`string` - - id\_in`array` - - space:`string` - - space\_in:`array` - - author:`string` - - author\_in:`array` - - network: `string` - - network\_in: `array` - - state: `array` -orderBy `string` +first `number`\ +skip `number`\ +where:\ +\- id`string`\ +\- id\_in`array`\ +\- space:`string`\ +\- space\_in:`array`\ +\- author:`string`\ +\- author\_in:`array`\ +\- network: `string`\ +\- network\_in: `array`\ +\- state: `array`\ +orderBy `string`\ orderDirection `asc` or `desc` #### Example @@ -326,11 +326,11 @@ query { {% endtab %} {% endtabs %} -Try on [GraphiQL](https://hub.snapshot.org/graphql?operationName=Proposals&query=query%20Proposals%20%7B%0A%20%20proposals%20%28%0A%20%20%20%20first%3A%2020%2C%0A%20%20%20%20skip%3A%200%2C%0A%20%20%20%20where%3A%20%7B%0A%20%20%20%20%20%20space_in%3A%20%5B%22yam.eth%22%5D%2C%0A%20%20%20%20%20%20state%3A%20%22closed%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20orderBy%3A%20%22created%22%2C%0A%20%20%20%20orderDirection%3A%20desc%0A%20%20%29%20%7B%0A%20%20%20%20id%0A%20%20%20%20title%0A%20%20%20%20body%0A%20%20%20%20choices%0A%20%20%20%20start%0A%20%20%20%20end%0A%20%20%20%20snapshot%0A%20%20%20%20state%0A%20%20%20%20author%0A%20%20%20%20space%20%7B%0A%20%20%20%20%20%20id%0A%20%20%20%20%20%20name%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D) +Try on [GraphiQL](https://hub.snapshot.org/graphql?operationName=Proposals\&query=query%20Proposals%20%7B%0A%20%20proposals%20%28%0A%20%20%20%20first%3A%2020%2C%0A%20%20%20%20skip%3A%200%2C%0A%20%20%20%20where%3A%20%7B%0A%20%20%20%20%20%20space\_in%3A%20%5B%22yam.eth%22%5D%2C%0A%20%20%20%20%20%20state%3A%20%22closed%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20orderBy%3A%20%22created%22%2C%0A%20%20%20%20orderDirection%3A%20desc%0A%20%20%29%20%7B%0A%20%20%20%20id%0A%20%20%20%20title%0A%20%20%20%20body%0A%20%20%20%20choices%0A%20%20%20%20start%0A%20%20%20%20end%0A%20%20%20%20snapshot%0A%20%20%20%20state%0A%20%20%20%20author%0A%20%20%20%20space%20%7B%0A%20%20%20%20%20%20id%0A%20%20%20%20%20%20name%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D) -### Get a single vote +### Get a single vote -#### Arguments +#### Arguments id `string`‌ @@ -376,24 +376,24 @@ query { {% endtab %} {% endtabs %} -Try on [GraphiQL](https://hub.snapshot.org/graphql?operationName=Vote&query=query%20Vote%20%7B%0A%20%20vote%20%28%0A%20%20%20%20id%3A%20%22QmeU7ct9Y4KLrh6F6mbT1eJNMkeQKMSnSujEfMCfbRLCMp%22%0A%20%20%29%20%7B%0A%20%20%20%20id%0A%20%20%20%20voter%0A%20%20%20%20created%0A%20%20%20%20proposal%0A%20%20%20%20choice%0A%20%20%20%20space%20%7B%0A%20%20%20%20%20%20id%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D) +Try on [GraphiQL](https://hub.snapshot.org/graphql?operationName=Vote\&query=query%20Vote%20%7B%0A%20%20vote%20%28%0A%20%20%20%20id%3A%20%22QmeU7ct9Y4KLrh6F6mbT1eJNMkeQKMSnSujEfMCfbRLCMp%22%0A%20%20%29%20%7B%0A%20%20%20%20id%0A%20%20%20%20voter%0A%20%20%20%20created%0A%20%20%20%20proposal%0A%20%20%20%20choice%0A%20%20%20%20space%20%7B%0A%20%20%20%20%20%20id%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D) -### Get votes +### Get votes #### Arguments -first `number` -skip `number` -where: - - id`string` - - id\_in`array` - - space:`string` - - space\_in:`array` - - voter:`string` - - voter\_in:`array` - - proposal: `string` - - proposal\_in: `array` -orderBy `string` +first `number`\ +skip `number`\ +where:\ +\- id`string`\ +\- id\_in`array`\ +\- space:`string`\ +\- space\_in:`array`\ +\- voter:`string`\ +\- voter\_in:`array`\ +\- proposal: `string`\ +\- proposal\_in: `array`\ +orderBy `string`\ orderDirection `asc` or `desc` #### Example @@ -457,22 +457,22 @@ query { {% endtab %} {% endtabs %} -Try on [GraphiQL](https://hub.snapshot.org/graphql?operationName=Votes&query=query%20Votes%20%7B%0A%20%20votes%20%28%0A%20%20%20%20first%3A%201000%0A%20%20%20%20skip%3A%200%0A%20%20%20%20where%3A%20%7B%0A%20%20%20%20%20%20proposal%3A%20%22QmPvbwguLfcVryzBRrbY4Pb9bCtxURagdv1XjhtFLf3wHj%22%0A%20%20%20%20%7D%0A%20%20%20%20orderBy%3A%20%22created%22%2C%0A%20%20%20%20orderDirection%3A%20desc%0A%20%20%29%20%7B%0A%20%20%20%20id%0A%20%20%20%20voter%0A%20%20%20%20created%0A%20%20%20%20proposal%0A%20%20%20%20choice%0A%20%20%20%20space%20%7B%0A%20%20%20%20%20%20id%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A) +Try on [GraphiQL](https://hub.snapshot.org/graphql?operationName=Votes\&query=query%20Votes%20%7B%0A%20%20votes%20%28%0A%20%20%20%20first%3A%201000%0A%20%20%20%20skip%3A%200%0A%20%20%20%20where%3A%20%7B%0A%20%20%20%20%20%20proposal%3A%20%22QmPvbwguLfcVryzBRrbY4Pb9bCtxURagdv1XjhtFLf3wHj%22%0A%20%20%20%20%7D%0A%20%20%20%20orderBy%3A%20%22created%22%2C%0A%20%20%20%20orderDirection%3A%20desc%0A%20%20%29%20%7B%0A%20%20%20%20id%0A%20%20%20%20voter%0A%20%20%20%20created%0A%20%20%20%20proposal%0A%20%20%20%20choice%0A%20%20%20%20space%20%7B%0A%20%20%20%20%20%20id%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A) -### Get follows +### Get follows #### Arguments -first `number` -skip `number` -where: - - id`string` - - id\_in`array` - - space:`string` - - space\_in:`array` - - follower:`string` - - follower\_in:`array` -orderBy `string` +first `number`\ +skip `number`\ +where:\ +\- id`string`\ +\- id\_in`array`\ +\- space:`string`\ +\- space\_in:`array`\ +\- follower:`string`\ +\- follower\_in:`array`\ +orderBy `string`\ orderDirection `asc` or `desc` #### Example @@ -542,4 +542,3 @@ Try on [GraphiQL](https://hub.snapshot.org/graphql?query=query%20%7B%0A%20%20fol ### Aliases TBD - diff --git a/strategies/create.md b/strategies/create.md index fb831ac..5aba8bf 100644 --- a/strategies/create.md +++ b/strategies/create.md @@ -24,6 +24,8 @@ To add your own strategy on Snapshot you need to fork the **snapshot-strategies* npm run test --strategy= // replace ``` +See [How to write a basic strategy](how-to-write-a-basic-strategy.md) + ### 4. Make sure you pass the checklist Have a look here on the requirements for adding a new strategy and make sure you full fill the points in the checklist: [https://github.com/snapshot-labs/snapshot.js/issues/212](https://github.com/snapshot-labs/snapshot.js/issues/212) @@ -31,4 +33,3 @@ Have a look here on the requirements for adding a new strategy and make sure you ### 5. Create a pull request The team will then review your PR and after it's approved and merged it will be available in your space settings. - diff --git a/strategies/how-to-write-a-basic-strategy.md b/strategies/how-to-write-a-basic-strategy.md new file mode 100644 index 0000000..f84c5c4 --- /dev/null +++ b/strategies/how-to-write-a-basic-strategy.md @@ -0,0 +1,68 @@ +--- +description: Main components of a basic strategy +--- + +# How to write a basic strategy + +Every strategy is, at its core, the implementation of the `strategy(space, network, provider, addresses, options, snapshot)` function. + +A quick word on the function parameters: + +* `space`: the space (if applicable), based on the registered ENS associated with this strategy (see [Spaces](../spaces/)) +* `network`: the network id as an integer (1 for Ethereum) +* `provider`: the network provider used by the web browser +* `addresses`: the list of addresses of the voters being processed. +* `options`: a collection of options that can be passed to strategy(...) - those have no default keys and can be used to pass any useful data +* `snapshots`: the block height at which the data are queried by strategy(...) - if none is passed, 'latest' is used. + +`Strategy(...)` returns a javascript object with every addresses from the addresses array as keys and the corresponding voting power as value (expressed in number of token owned by the address for `erc20-balance-of`, as a number of rocks owned for `has-rock`, etc). + +Every strategy comes with a JSON file `examples.json`. This file is mandatory as it will be used for testing and validating the strategy before including it in Snapshot main GitHub branch. Here are the main keys: + +* `"name"`: a human-reading name for the strategy ("ERC20 balance" for instance). +* `"strategy"`: the core parameters of the strategy + * `"name"`: the strategy name ("erc20-balance-of") + * `"params"`: optional parameters passed in `options` to strategy(...). Any useful "key":"value" can be used here and retrieved inside `strategy(...)` via `options.key` + * `"address"`: the address of the token contract (the DAI contract for instance) + * `"symbol"`: the token symbol ("DAI") + * `"decimals"`: the number of decimals (18) + * `"network"`: the network id (1 for ethereum) + * `"addresses"`: an array of addresses which will be used for testing (they should therefore have some token) + * `"snapshot"`: the block height (by taking a block height in the past where the addresses\[] had a positive balance, the test will be easily repeated) + +Finally, all strategies will contain some similar steps, illustrated in [erc20-balance-of](https://github.com/snapshot-labs/snapshot-strategies/blob/f41f98249cff78486914473a3fef29ea960971e5/src/strategies/erc20-balance-of/index.ts): + +* Getting the block height ('latest' or a specific one via the `snapshot` argument). + +``` + const blockTag = typeof snapshot === 'number' ? snapshot : 'latest'; +``` + +* Initializing Multicaller: looping over the addresses\[] array is **not allowed** as the strategy complexity would increase with the array size. Instead, Snapshot provides the Multicaller utility to group blockchain queries for a series of addresses. The abi can be in ethers human-readable form ( `['function balanceOf(address account) external view returns (uint256)']` for instance) + +``` + const multi = new Multicaller(network, provider, abi, { blockTag }); +``` + +* Feeding data into the multicaller and executing the multicall: every query is queued in the multicaller via `Multicaller.call(...)`. Once they are all stored, an unique call is executed via `Multicall.execute()`. + + `option.address` is the token contract address (`strategy.params.address` in `examples.json`). + +``` + addresses.forEach((address) => + multi.call(address, options.address, 'balanceOf', [address]) + ); + + const result: Record = await multi.execute(); +``` + +* Creating an object where every address from addresses\[] is paired with its corresponding value (returned from the multicall) and returning it + +``` + return Object.fromEntries( + Object.entries(result).map(([address, balance]) => [ + address, + parseFloat(formatUnits(balance, options.decimals)) + ]) + ); +```