diff --git a/package.json b/package.json index 4157d65b5..c02fff4be 100755 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "@ethersproject/strings": "^5.6.1", "@ethersproject/units": "^5.6.1", "@ethersproject/wallet": "^5.6.2", - "@snapshot-labs/snapshot.js": "^0.5.8", + "@snapshot-labs/snapshot.js": "^0.6.2", "@spruceid/didkit-wasm-node": "^0.2.1", "@uniswap/sdk-core": "^3.0.1", "@uniswap/v3-sdk": "^3.9.0", diff --git a/src/strategies/aave-governance-power/examples.json b/src/strategies/aave-governance-power/examples.json index e297a3380..03c23fc1a 100644 --- a/src/strategies/aave-governance-power/examples.json +++ b/src/strategies/aave-governance-power/examples.json @@ -11,7 +11,11 @@ } }, "network": "1", - "addresses": ["0x329c54289Ff5D6B7b7daE13592C6B1EDA1543eD4", "0x57ab7ee15cE5ECacB1aB84EE42D5A9d0d8112922", "0x0ab97008cad303a8C90ea630c282760284c19e93"], + "addresses": [ + "0x329c54289Ff5D6B7b7daE13592C6B1EDA1543eD4", + "0x57ab7ee15cE5ECacB1aB84EE42D5A9d0d8112922", + "0x0ab97008cad303a8C90ea630c282760284c19e93" + ], "snapshot": 18054498 } ] diff --git a/src/strategies/index.ts b/src/strategies/index.ts index c9068b0c2..7eb9fd0c3 100644 --- a/src/strategies/index.ts +++ b/src/strategies/index.ts @@ -363,6 +363,7 @@ import * as auraBalanceOfVlauraVebal from './aura-balance-of-vlaura-vebal'; import * as auraBalanceOfSingleAsset from './aura-vault-balance-of-single-asset'; import * as rocketpoolNodeOperator from './rocketpool-node-operator'; import * as rocketpoolNodeOperatorv2 from './rocketpool-node-operator-v2'; +import * as rocketpoolNodeOperatorv3 from './rocketpool-node-operator-v3'; import * as earthfundChildDaoStakingBalance from './earthfund-child-dao-staking-balance'; import * as unipilotVaultPilotBalance from './unipilot-vault-pilot-balance'; import * as sdBoostTWAVP from './sd-boost-twavp'; @@ -626,7 +627,7 @@ const strategies = { api, 'api-post': apiPost, 'api-v2': apiV2, - 'api-v2-override': apiV2, + 'api-v2-override': { ...apiV2 }, xseen, 'moloch-all': molochAll, 'moloch-loot': molochLoot, @@ -832,6 +833,7 @@ const strategies = { 'aura-vault-balance-of-single-asset': auraBalanceOfSingleAsset, 'rocketpool-node-operator': rocketpoolNodeOperator, 'rocketpool-node-operator-v2': rocketpoolNodeOperatorv2, + 'rocketpool-node-operator-v3': rocketpoolNodeOperatorv3, 'earthfund-child-dao-staking-balance': earthfundChildDaoStakingBalance, 'sd-boost-twavp': sdBoostTWAVP, 'unipilot-vault-pilot-balance': unipilotVaultPilotBalance, @@ -930,7 +932,7 @@ const strategies = { 'erc4626-assets-of': erc4626AssetsOf, 'friend-tech': friendTech, 'sd-vote-boost-twavp-v2': sdVoteBoostTWAVPV2, - 'moonbase': moonbase + moonbase: moonbase }; Object.keys(strategies).forEach(function (strategyName) { diff --git a/src/strategies/moonbase/examples.json b/src/strategies/moonbase/examples.json index 1668c37e4..f875696bf 100644 --- a/src/strategies/moonbase/examples.json +++ b/src/strategies/moonbase/examples.json @@ -1,27 +1,27 @@ [ - { - "name": "Example query Moonbase", - "strategy": { - "name": "moonbase", - "params": { - "address": "0xc97c478Fc35d75b51549C39974053a679A5C67E1", - "masterChef": "0x830304d6C669d33738c7E4c1F2310CC1E530Df63", - "moonbaseLPs": [ - { - "address": "0x230C64C42886A1F6b91eD8C11B59a2D45865d38F", - "pid": 7 - } - ], - "symbol": "MBG", - "decimals": 18 - } - }, - "network": "84531", - "addresses": [ - "0xe32C26Be24232ba92cd89d116985F81f94Dd26a8", - "0x7DC90A11489C384dc72234120B0f84C3932d94Ce", - "0xf704872349a62ceBb40F841B635de268b2F7B9Fb" - ], - "snapshot": 9182354 - } - ] \ No newline at end of file + { + "name": "Example query Moonbase", + "strategy": { + "name": "moonbase", + "params": { + "address": "0xc97c478Fc35d75b51549C39974053a679A5C67E1", + "masterChef": "0x830304d6C669d33738c7E4c1F2310CC1E530Df63", + "moonbaseLPs": [ + { + "address": "0x230C64C42886A1F6b91eD8C11B59a2D45865d38F", + "pid": 7 + } + ], + "symbol": "MBG", + "decimals": 18 + } + }, + "network": "84531", + "addresses": [ + "0xe32C26Be24232ba92cd89d116985F81f94Dd26a8", + "0x7DC90A11489C384dc72234120B0f84C3932d94Ce", + "0xf704872349a62ceBb40F841B635de268b2F7B9Fb" + ], + "snapshot": 9182354 + } +] diff --git a/src/strategies/moonbase/index.ts b/src/strategies/moonbase/index.ts index a48a17357..98ab3d4d0 100644 --- a/src/strategies/moonbase/index.ts +++ b/src/strategies/moonbase/index.ts @@ -35,9 +35,10 @@ export async function strategy( options, snapshot ): Promise> { - if (options.moonbaseLPs.length > MAX_MOONBASE_LPS) { - throw new Error(`Too many moonbaseLPs. Maximum allowed is ${MAX_MOONBASE_LPS}.`); + throw new Error( + `Too many moonbaseLPs. Maximum allowed is ${MAX_MOONBASE_LPS}.` + ); } const blockTag = typeof snapshot === 'number' ? snapshot : 'latest'; @@ -86,4 +87,4 @@ export async function strategy( parseFloat(formatUnits(balance, options.decimals)) ]) ); -} \ No newline at end of file +} diff --git a/src/strategies/rocketpool-node-operator-v3/README.md b/src/strategies/rocketpool-node-operator-v3/README.md new file mode 100644 index 000000000..04193da89 --- /dev/null +++ b/src/strategies/rocketpool-node-operator-v3/README.md @@ -0,0 +1,13 @@ +# rocketpool-node-operator-v3 + +This is a strategy for staking node operators, it returns the half square rooted node effective stake balance given a node address. + +Here is an example of parameters: + +```json +{ + "address": "0xD33526068D116cE69F19A9ee46F0bd304F21A51f", + "symbol": "RPL", + "decimals": 18 +} +``` diff --git a/src/strategies/rocketpool-node-operator-v3/examples.json b/src/strategies/rocketpool-node-operator-v3/examples.json new file mode 100644 index 000000000..c45f377ed --- /dev/null +++ b/src/strategies/rocketpool-node-operator-v3/examples.json @@ -0,0 +1,34 @@ +[ + { + "name": "Example query", + "strategy": { + "name": "rocketpool-node-operator-v3", + "params": { + "address": "0xD33526068D116cE69F19A9ee46F0bd304F21A51f", + "symbol": "RPL", + "decimals": 18 + } + }, + "network": "1", + "addresses": [ + "0x17Fa597cEc16Ab63A7ca00Fb351eb4B29Ffa6f46", + "0xca317A4ecCbe0Dd5832dE2A7407e3c03F88b2CdD", + "0x327260c50634136551bfE4e4eB082281555AAfAE", + "0x5d8172792a9e649053c07366E3a7C24a37F0C534", + "0x701F4dcEAD1049FA01F321d49F6dca525cF4A5A5", + "0xb8ed9ea221bf33d37360A76DDD52bA7b1E66AA5C", + "0xbfaf9BFa09F26EF8104A6d5FF09afdCC9300E5bc", + "0x174E0b45C03318B0C9bc03573028605B26764931", + "0x5f4cB66c9B1Ed8A4758A059FDB10E0F72C307D8A", + "0x24609303B67051eF77735E34D671e2A13E3Da35d", + "0xE35854CdE18A3cC4706134b4850Dd861a55B9A30", + "0x53938f795AB6c57070AAd32905a70A2E5961A887", + "0xD6527Bd3d62f1Da520E6f74B89EBD8F8cD04564f", + "0xf8bFf17a1C9dfC632F6C905d12C404AfE451B16c", + "0x689C6853f3deBac91b72f32BafA83200eeC9613C", + "0xaEbb400542598E6ee58b2FDF2E7425c07E8Ba68D", + "0xa016344b2D4dfBf370766F24d196171DeC86544A" + ], + "snapshot": 17761214 + } +] diff --git a/src/strategies/rocketpool-node-operator-v3/index.ts b/src/strategies/rocketpool-node-operator-v3/index.ts new file mode 100644 index 000000000..effdabfcf --- /dev/null +++ b/src/strategies/rocketpool-node-operator-v3/index.ts @@ -0,0 +1,112 @@ +import { BigNumberish, BigNumber } from '@ethersproject/bignumber'; +import { formatUnits } from '@ethersproject/units'; +import { Multicaller } from '../../utils'; + +export const author = 'rocket-pool'; +export const version = '0.1.3'; + +const rocketNetworkPricesAddress = '0xd3f500F550F46e504A4D2153127B47e007e11166'; +const rocketNetworkPricesContractAbi = [ + 'function getRPLPrice() external view returns (uint256)' +]; +const rocketNodeStakingAddress = '0x0d8D8f8541B12A0e1194B7CC4b6D954b90AB82ec'; +const rocketNodeStakingContractAbi = [ + 'function getNodeEffectiveRPLStake(address _nodeAddress) external view returns (uint256)', + 'function getNodeRPLStake(address _nodeAddress) external view returns (uint256)', + 'function getNodeETHProvided(address _nodeAddress) external view returns (uint256)' +]; + +function minBN(a, b) { + return a.lt(b) ? a : b; +} +export async function strategy( + space, + network, + provider, + addresses, + options, + snapshot +): Promise> { + const blockTag = typeof snapshot === 'number' ? snapshot : 'latest'; + + const nodeRPLStake = new Multicaller( + network, + provider, + rocketNodeStakingContractAbi, + { blockTag } + ); + + const nodeETHProvided = new Multicaller( + network, + provider, + rocketNodeStakingContractAbi, + { blockTag } + ); + + const RPLPrice = new Multicaller( + network, + provider, + rocketNetworkPricesContractAbi, + { blockTag } + ); + + addresses.forEach((address) => { + nodeRPLStake.call(address, rocketNodeStakingAddress, 'getNodeRPLStake', [ + address + ]); + nodeETHProvided.call( + address, + rocketNodeStakingAddress, + 'getNodeETHProvided', + [address] + ); + RPLPrice.call(address, rocketNetworkPricesAddress, 'getRPLPrice'); + }); + + const nodeRPLStakeResponse: Record = + await nodeRPLStake.execute(); + + const nodeETHProvidedResponse: Record = + await nodeETHProvided.execute(); + + const RPLPriceResponse: Record = + await RPLPrice.execute(); + + const merged = addresses.map((address) => { + const nodeRPLStake = nodeRPLStakeResponse[address]; + const nodeETHProvided = nodeETHProvidedResponse[address]; + const RPLPrice = RPLPriceResponse[address]; + + return { + address: address, + nodeRPLStake: nodeRPLStake, + nodeETHProvided: nodeETHProvided, + RPLPrice: RPLPrice + }; + }); + + const data = merged.map((item) => { + const multiplier = BigNumber.from('15').mul(BigNumber.from('10').pow(17)); + const numerator = item.nodeETHProvided.mul(multiplier); + const denominator = item.RPLPrice; + const maxEffectiveStake = numerator.div(denominator); + const effectiveStake = minBN(item.nodeRPLStake, maxEffectiveStake); + + return { + address: item.address, + effectiveStake: effectiveStake + }; + }); + + const reduced: Record = data.reduce((acc, obj) => { + acc[obj.address] = obj.effectiveStake; + return acc; + }, {}); + + return Object.fromEntries( + Object.entries(reduced).map(([address, balance]) => [ + address, + Math.sqrt(parseFloat(formatUnits(balance, options.decimals))) / 2 + ]) + ); +} diff --git a/src/strategies/taraxa-delegation/index.ts b/src/strategies/taraxa-delegation/index.ts index bc0385277..be50ca99f 100644 --- a/src/strategies/taraxa-delegation/index.ts +++ b/src/strategies/taraxa-delegation/index.ts @@ -7,8 +7,6 @@ import { Multicaller } from '../../utils'; export const author = 'Taraxa-project'; export const version = '0.1.0'; -const MIN_SCORE_AMOUNT = BigNumber.from(10).mul(BigNumber.from(10).pow(18)); - const abi = [ 'function getTotalDelegation(address delegator) external view returns (uint256 total_delegation)', 'function getEthBalance(address account) public view returns (uint256 balance)' @@ -44,13 +42,9 @@ export async function strategy( BigNumber.from(resultDelegations[address] || 0) ); - if (score.lt(MIN_SCORE_AMOUNT)) { - scores[getAddress(address)] = 0; - } else { - scores[getAddress(address)] = parseFloat( - formatUnits(score, options.decimals) - ); - } + scores[getAddress(address)] = parseFloat( + formatUnits(score, options.decimals) + ); } return scores; diff --git a/yarn.lock b/yarn.lock index c4850455c..8c050a765 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1363,10 +1363,10 @@ dependencies: "@sinonjs/commons" "^2.0.0" -"@snapshot-labs/snapshot.js@^0.5.8": - version "0.5.8" - resolved "https://registry.yarnpkg.com/@snapshot-labs/snapshot.js/-/snapshot.js-0.5.8.tgz#16bf19b27e487e937be8472e53f0ed71f25e47af" - integrity sha512-bFe4VBUOD2LbKKesD52G7hqBCrmx7BS/4n8JfnzR+GZddL4UWmjRhfnxx/6YLeJvaHOWSPs7LHkr16fpJXD7pQ== +"@snapshot-labs/snapshot.js@^0.6.2": + version "0.6.2" + resolved "https://registry.yarnpkg.com/@snapshot-labs/snapshot.js/-/snapshot.js-0.6.2.tgz#0f9ddf591ec50912aeed545c807b5295365d4e2f" + integrity sha512-hQjZ0I9uLu2sUpuR05maYCq9KLi6yNJnCCkjIutDQjFFEzmeMqJ0Lru1tOdcRMsPW3g5ktdo5xi265ESEBDPdA== dependencies: "@ensdomains/eth-ens-namehash" "^2.0.15" "@ethersproject/abi" "^5.6.4"