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

[hopr-stake-and-balance-qv] Improve hopr-stake-and-balance-qv strategy #1452

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/strategies/hopr-stake-and-balance-qv/examples.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,21 @@
"params": {
"tokenAddress": "0xf5581dfefd8fb0e4aec526be659cfab1f8c781da",
"symbol": "HOPR",
"fallbackGnosisBlock": 27852687,
"fallbackGnosisBlock": 33114482,
"subgraphStudioProdQueryApiKey": null,
"subgraphStudioDevAccountId": null,
"subgraphHostedAccountName": "hoprnet",
"useSafeStake": true,
"useChannelStake": true,
"useHoprOnGnosis": true,
"useHoprOnMainnet": true,
"subgraphStudioProdSafeStakeQueryId": "DrkbaCvNGVcNH1RghepLRy6NSHFi8Dmwp4T2LN3LqcjY",
"subgraphStudioProdSafeStakeQueryId": "FEQcaX9qfh31YL2K7rxRN5a3sr9rjMWkguJnby7StNRo",
"subgraphStudioDevSafeStakeSubgraphName": "hopr-nodes-dufour",
"subgraphStudioDevSafeStakeVersion": "latest",
"subgraphStudioDevSafeStakeVersion": "version/latest",
"subgraphHostedSafeStakeSubgraphName": null,
"subgraphStudioProdChannelsQueryId": "Feg6Jero3aQzesVYuqk253NNLyNAZZppbDPKFYEGJ1Hj",
"subgraphStudioDevChannelsSubgraphName": "hopr-channels",
"subgraphStudioDevChannelsVersion": "latest",
"subgraphStudioDevChannelsVersion": "version/latest",
"subgraphHostedChannelsSubgraphName": null,
"subgraphStudioProdHoprOnGnosisQueryId": "njToE7kpetd3P9sJdYQPSq6yQjBs7w9DahQpBj6WAoD",
"subgraphStudioDevHoprOnGnosisSubgraphName": "hopr-on-gnosis",
Expand Down Expand Up @@ -48,6 +48,6 @@
"0x3e1A12a6019ee26418F22B656926fE38F5e58C5f",
"0x7A27A4D91231aCB3282b410Cc784517B417FA0DA"
],
"snapshot": 17220270
"snapshot": 19584202
}
]
32 changes: 14 additions & 18 deletions src/strategies/hopr-stake-and-balance-qv/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { formatUnits, parseUnits } from '@ethersproject/units';
import { formatUnits } from '@ethersproject/units';
import { BigNumber } from '@ethersproject/bignumber';
import { multicall } from '../../utils';
import {
Expand Down Expand Up @@ -57,7 +57,7 @@ function calculateScore(
safeStakingBalance: number,
exponent: number
) {
const total =
const total: number =
parseFloat(
formatUnits(
gnosisBalance.add(BigNumber.from(mainnetBalance.toString())),
Expand Down Expand Up @@ -110,6 +110,7 @@ export async function strategy(
block.timestamp,
options.fallbackGnosisBlock
);
// console.info(`Gnosis subgraph block number ${subgraphBlock}`);

// trim addresses to sub of "QUERY_LIMIT" addresses.
const addressSubsets: string[][] = trimArray(addresses);
Expand All @@ -125,7 +126,7 @@ export async function strategy(
// array of nodes per safe
const safeNodes = new Map<string, string[]>();
// array of all the nodes managed by the safes where its owner is a voter
const nodes: string[] = [];
let nodes: string[] = [];
// Find the list of Safes (created by HoprStakeFactory contract) where the voting account is an owner,
// as well as the total number of owners of each safe
// construct URLs for safe stake subgraph
Expand All @@ -150,8 +151,7 @@ export async function strategy(
stuidoDevSafeStakeSubgraphUrl,
studioProdSafeStakeSubgraphUrl,
subset,
subgraphBlock,
snapshot
subgraphBlock
)
)
);
Expand All @@ -160,7 +160,7 @@ export async function strategy(
resultSubset.forEach((safe) => {
// 1. safe -> nodes
safeNodes.set(safe.safeAddress, safe.nodes);
nodes.concat(safe.nodes);
nodes = nodes.concat(safe.nodes);
if (safe.owners.length == 0) {
// 2. safe -> factor
safeFactor.set(safe.safeAddress, 0);
Expand Down Expand Up @@ -202,8 +202,7 @@ export async function strategy(
stuidoDevChannelsSubgraphUrl,
studioProdChannelsSubgraphUrl,
subset,
subgraphBlock,
snapshot
subgraphBlock
)
)
);
Expand All @@ -220,10 +219,7 @@ export async function strategy(
safeStakeInChannel.set(key, BigNumber.from('0'));
} else {
const stakesInNodes = nodesManagedBySafe.reduce(
(acc, cur) =>
(acc = acc.add(
parseUnits(subgraphNodeStakeInChannels[cur] ?? '0', 18)
)),
(acc, cur) => (acc = acc.add(subgraphNodeStakeInChannels[cur])),
BigNumber.from('0')
);
safeStakeInChannel.set(key, stakesInNodes);
Expand Down Expand Up @@ -261,8 +257,7 @@ export async function strategy(
stuidoDevHoprOnGnosisSubgraphUrl,
studioProdHoprOnGnosisSubgraphUrl,
subset,
subgraphBlock,
snapshot
subgraphBlock
)
)
);
Expand All @@ -274,11 +269,12 @@ export async function strategy(

// sum of all the safes owned by the voting account
// = sum{ factor * (safe's x/wxHOPR balance + wxHOPR tokens staked in the Channels) }
const summedStakePerSafe = addresses.map((address) => {
const summedStakePerSafe: number[] = addresses.map((address) => {
const lowercasedAddr = address.toLowerCase();
// from the voting address, get all the safe addresses
const safes = ownerSafes.get(address) ?? [];
const safes = ownerSafes.get(lowercasedAddr) ?? [];
if (safes.length == 0) {
return BigNumber.from('0');
return 0;
} else {
return safes.reduce((acc, curSafe) => {
// factor * (x/wxHOPR token balance + safe stake in channels)
Expand All @@ -298,7 +294,7 @@ export async function strategy(
formatUnits(curSafeTokenBalance.add(curSafeStakeInChannels), 18)
)
);
});
}, 0);
}
});

Expand Down
62 changes: 23 additions & 39 deletions src/strategies/hopr-stake-and-balance-qv/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,18 @@ export async function getGnosisBlockNumber(
};

// query from subgraph
const data = await subgraphRequestsToVariousServices(
queryUrl,
null,
null,
query
);
return !data ? fallbackBlockNumber : Number(data.blocks[0].number);
try {
const data = await subgraphRequestsToVariousServices(
queryUrl,
null,
null,
query
);
return !data ? fallbackBlockNumber : Number(data.blocks[0].number);
} catch (error) {
// console.error(`cannot convert block number from subgraph due to ${error}`);
return fallbackBlockNumber;
}
}

/**
Expand All @@ -148,22 +153,21 @@ export async function getGnosisBlockNumber(
* @param stuidoDevSubgraphUrl url to the dev subgraph in the studio
* @param studioProdSubgraphUrl url to the production subgraph in the studio
* @param addresses address of voting accounts, which is an owner of the safe
* @param blockNumber block number of the snapshot
* @param snapshot snapshot
* @param blockNumber Gnosis chain block number for the query
* @returns a key-value object where the key is safe address the value is the total number of owners.
*/
export async function safeStakeSubgraphQuery(
hostedSubgraphUrl: string | null,
stuidoDevSubgraphUrl: string | null,
studioProdSubgraphUrl: string | null,
addresses: string[],
blockNumber: number,
snapshot: number | string
blockNumber: number
): Promise<Safe[]> {
const query = {
safes: {
__args: {
first: QUERY_LIMIT,
block: { number: blockNumber },
where: {
owners_: {
owner_in: addresses.map((adr) => adr.toLowerCase())
Expand All @@ -184,11 +188,6 @@ export async function safeStakeSubgraphQuery(
}
};

if (snapshot !== 'latest') {
// @ts-ignore
query.safes.__args.block = { number: blockNumber };
}

// query from subgraph
const data = await subgraphRequestsToVariousServices(
hostedSubgraphUrl,
Expand All @@ -198,7 +197,7 @@ export async function safeStakeSubgraphQuery(
);

// return parsed entries
if (!data || !data.safes || data.safe.length == 0) {
if (!data || !data.safes || data.safes.length == 0) {
return [];
} else {
return data.safes.map((s) => {
Expand All @@ -217,22 +216,21 @@ export async function safeStakeSubgraphQuery(
* @param stuidoDevSubgraphUrl url to the dev subgraph in the studio
* @param studioProdSubgraphUrl url to the production subgraph in the studio
* @param addresses address of wallets
* @param blockNumber block number of the snapshot
* @param snapshot snapshot
* @param blockNumber Gnosis chain block number for the query
* @returns a key-value object where the key is the address and the value is the total HOPR token balance on Gnosis chain.
*/
export async function hoprTotalOnGnosisSubgraphQuery(
hostedSubgraphUrl: string | null,
stuidoDevSubgraphUrl: string | null,
studioProdSubgraphUrl: string | null,
addresses: string[],
blockNumber: number,
snapshot: number | string
blockNumber: number
): Promise<{ [propName: string]: BigNumber }> {
const query = {
accounts: {
__args: {
first: QUERY_LIMIT,
block: { number: blockNumber },
where: {
id_in: addresses.map((adr) => adr.toLowerCase())
}
Expand All @@ -242,11 +240,6 @@ export async function hoprTotalOnGnosisSubgraphQuery(
}
};

if (snapshot !== 'latest') {
// @ts-ignore
query.accounts.__args.block = { number: blockNumber };
}

// query from subgraph
const data = await subgraphRequestsToVariousServices(
hostedSubgraphUrl,
Expand All @@ -271,22 +264,21 @@ export async function hoprTotalOnGnosisSubgraphQuery(
* @param stuidoDevSubgraphUrl url to the dev subgraph in the studio
* @param studioProdSubgraphUrl url to the production subgraph in the studio
* @param addresses node addresses
* @param blockNumber block number of the snapshot
* @param snapshot snapshot
* @param blockNumber Gnosis chain block number for the query
* @returns a key-value object where the key is the address and the value is the total HOPR token balance on Gnosis chain.
*/
export async function hoprNodeStakeOnChannelsSubgraphQuery(
hostedSubgraphUrl: string | null,
stuidoDevSubgraphUrl: string | null,
studioProdSubgraphUrl: string | null,
addresses: string[],
blockNumber: number,
snapshot: number | string
blockNumber: number
): Promise<{ [propName: string]: BigNumber }> {
const query = {
accounts: {
__args: {
first: QUERY_LIMIT,
block: { number: blockNumber },
where: {
id_in: addresses.map((adr) => adr.toLowerCase())
}
Expand All @@ -296,11 +288,6 @@ export async function hoprNodeStakeOnChannelsSubgraphQuery(
}
};

if (snapshot !== 'latest') {
// @ts-ignore
query.accounts.__args.block = { number: blockNumber };
}

// query from subgraph
const data = await subgraphRequestsToVariousServices(
hostedSubgraphUrl,
Expand All @@ -312,10 +299,7 @@ export async function hoprNodeStakeOnChannelsSubgraphQuery(
// map result (data.accounts) to addresses
const entries = !data
? addresses.map((addr) => [addr, BigNumber.from('0')])
: data.accounts.map((d) => [
d.id,
parseUnits(d.totalBalance.toString(), 18)
]);
: data.accounts.map((d) => [d.id, parseUnits(d.balance.toString(), 18)]);
return Object.fromEntries(entries);
}

Expand Down
Loading