forked from snapshot-labs/snapshot-strategies
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding new strategy lrc-nft-search-mult[lrc-nft-search-mult] (snapsho…
…t-labs#1098) * initial commit of lrc-nft-search-mult This is an extended functionality version of a previous Loopring NFT voting strategy. This allows for queried scores to be multiplied by a value to allow vote weighting in conjunction with multiple strategies. * Update index.ts Update to add lrc-nft-search-mult strategy * Update src/strategies/lrc-nft-search-mult/index.ts Update strategy version Co-authored-by: Chaitanya <[email protected]> * Update examples.json Add additional addresses to satisfy test case conditions --------- Co-authored-by: Chaitanya <[email protected]>
- Loading branch information
Showing
4 changed files
with
181 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# lrc-nft-search-mult | ||
|
||
This is a further improvement of karamorf's lrc-l2-nft-balance of Snapshot voting strategy by raecaug(system32). | ||
|
||
This strategy is an extension of lrc-nft-dao-search, allowing space owners to apply a multiplier to counted votes. | ||
This can then be combined with additional voting strategies to allow for complex DAO setups with vote weighting of specific NFTs. | ||
Providing a multiplier is necessary; if default behavior is desired, simply specify '1'. | ||
|
||
Strategy to read account balances for NFTs (72 or 1155) from LoopringV2 subgraph. Assumes we only want tokens minted by a specific account id. | ||
|
||
Here is an example of parameters: | ||
|
||
```json | ||
{ | ||
"graph": "https://api.thegraph.com/subgraphs/name/juanmardefago/loopring36", | ||
"minter_account_id": "74447", | ||
"tokens": ["token (Collection contract address) to include"], | ||
"nft_ids": ["nftIDs, unique to every nft, even those under the same token contract"], | ||
"blacklisted_account_ids": ["38482"], | ||
"blacklisted_nft_ids": ["... nft id's to exclude ..."] | ||
"multiplier": "3" // Setting this to '1' will result in normal vote counting behavior. | ||
} | ||
``` | ||
|
||
Use explorer.loopring.io to look up addresses and find account id's. | ||
|
||
Account id `38482` maps to `0x000000000000000000000000000000000000dead` and is used for burning tokens. | ||
|
||
to note: either the `minter_account_id` or the `tokens` parameter must be provided for this query to work. You do not need to specify both, just one of them. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
[ | ||
{ | ||
"name": "lrcNFTmult", | ||
"strategy": { | ||
"name": "lrc-nft-search-mult", | ||
"params": { | ||
"graph": "https://api.thegraph.com/subgraphs/name/juanmardefago/loopring36", | ||
"minter_account_id": "157510", | ||
"tokens": ["0xb6d91e38e4ac53c9f8952c6c6b1c7aee66c8b6f0"], | ||
"nft_ids": [ | ||
"0x1e31297dd163ca44a5fad74de4ffbebf1ba11d46e1b448b0e105449d827fb264" | ||
], | ||
"blacklisted_account_ids": [""], | ||
"blacklisted_nft_ids": [""], | ||
"multiplier": "1" | ||
} | ||
}, | ||
"network": "1", | ||
"addresses": ["0xeE253D3fCC30787a1E58570E355010d0b9C33B60","0xddCCE06088517c56FA938bD99cD0820094010F8e","0x9Fd19B8ca6E49eD92142339F54026497cE913492"], | ||
"snapshot": 15677787 | ||
} | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
// Original code by Karamorf, upgraded by Raecaug(system32) | ||
// Allows querys of Loopring L2 accounts & balances by specifying a nft minter, token contract address(and optionally specifying individual ids to white/blacklist) | ||
|
||
import { subgraphRequest } from '../../utils'; | ||
export const author = 'raecaug'; | ||
export const version = '0.1.0'; | ||
|
||
const LIMIT = 1000; | ||
|
||
function makeQuery( | ||
snapshot, // This is an Ethereum block # or defaults to 'latest' | ||
minter, // This is referred to as account # or account id on the Loopring L2 block explorer | ||
tokens, // NFT collection contract addresses, also referred to as 'token address' | ||
skip, // Used to skip response lines in requests | ||
blacklisted_account_ids, // Ditto properties of 'minter' | ||
blacklisted_nft_ids, // This is the nft id, which is unique for every nft ever minted, allows distinction between nfts in a collection at the chain level | ||
nft_ids // Ditto properties of blacklisted version | ||
) { | ||
const query: any = { | ||
// Query constructor, builds request with params from snapshot space settings | ||
accountNFTSlots: { | ||
__args: { | ||
where: { | ||
nft_: { | ||
id_not_in: blacklisted_nft_ids, // Excluding blacklisted nft ids | ||
nftID_in: nft_ids // Including uniquely specified nft ids | ||
}, | ||
account_not_in: blacklisted_account_ids // Excluding blacklisted account ids | ||
}, | ||
first: LIMIT, | ||
skip: skip | ||
}, | ||
account: { address: true }, | ||
balance: true | ||
} | ||
}; | ||
|
||
if (minter && minter !== '') { | ||
//Check to ensure minter id is specified and not blank | ||
query.accountNFTSlots.__args.where.nft_.minter = minter; | ||
} | ||
|
||
if (tokens && tokens.length > 0) { | ||
//Check to ensure at least 1 token to search for is specified | ||
query.accountNFTSlots.__args.where.nft_.token_in = tokens; | ||
} | ||
|
||
if (snapshot !== 'latest') { | ||
// If the snapshot date is manually specified, overwrite the 'latest' block, strict inequality check operand used | ||
query.accountNFTSlots.__args = { | ||
...query.accountNFTSlots.__args, | ||
block: { | ||
number: snapshot | ||
} | ||
}; | ||
} | ||
|
||
return query; | ||
} | ||
|
||
export async function strategy( // *****Logical execution begins here; args passed in by Snapshot settings***** | ||
space, | ||
network, | ||
provider, | ||
addresses, | ||
options, | ||
snapshot | ||
): Promise<Record<string, number>> { | ||
let blacklisted_account_ids = options.blacklisted_account_ids; | ||
let blacklisted_nft_ids = options.blacklisted_nft_ids; | ||
|
||
let multiplier = options.multiplier; // Multiplier to be applied against returned NFT amounts | ||
|
||
let nft_ids = options.nft_ids; // Unique NFT ids, distinguishable from 1155 token contracts | ||
|
||
const balances = {}; // Initialization | ||
let skip = 0; | ||
let response_size = 0; | ||
|
||
if (!blacklisted_account_ids || blacklisted_account_ids.length === 0) { | ||
// If no blacklisted accts specified, set to empty | ||
blacklisted_account_ids = ['']; | ||
} | ||
|
||
if (!blacklisted_nft_ids || blacklisted_nft_ids.length === 0) { | ||
// If no unique nft_ids specified, set to empty | ||
blacklisted_nft_ids = ['']; | ||
} | ||
|
||
if (!nft_ids || nft_ids.length === 0) { | ||
// If no unique nft_ids specified, set to empty | ||
nft_ids = ['']; | ||
} | ||
|
||
do { | ||
// Transmit query and await results | ||
const response = await subgraphRequest( | ||
// Constructs response variable from subgraph query function | ||
options.graph, // Parameter 1, options specified | ||
makeQuery( | ||
// Query constructor(defined above) called, results are the second parameter | ||
snapshot, | ||
options.minter_account_id, | ||
options.tokens, | ||
skip, | ||
blacklisted_account_ids, | ||
blacklisted_nft_ids, | ||
nft_ids | ||
) | ||
); | ||
|
||
response.accountNFTSlots.forEach((slot) => { | ||
// Checking against each accountNFTSlot element | ||
if (!balances.hasOwnProperty(slot.account.address)) { | ||
balances[slot.account.address] = 0; // If nothing returned, set this accounts balance to 0 | ||
} | ||
balances[slot.account.address] += (multiplier * parseInt(slot.balance)); // Otherwise, a bigint is returned; parse it, apply multiplier and store in balances array | ||
}); | ||
response_size = response.accountNFTSlots.length; // Value is set to 0 on loop entry, updated here, will break loop for anything other than 1000 | ||
skip += response_size; | ||
} while (response_size == LIMIT); | ||
|
||
const scores = Object.fromEntries( | ||
addresses.map((address) => [address, balances[address.toLowerCase()]]) // Map returned addresses and balances as scores array | ||
); | ||
|
||
return scores; // Returns addresses and balances to Snapshot | ||
} |