Skip to content

Commit

Permalink
ens wip
Browse files Browse the repository at this point in the history
  • Loading branch information
ipatka committed Aug 9, 2023
1 parent e29805e commit e4eeea5
Show file tree
Hide file tree
Showing 1,313 changed files with 75,392 additions and 32 deletions.
13 changes: 12 additions & 1 deletion Implementations/API/backend/functions/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,15 @@ export const snapshotApiConfig: { [key: string]: any } = {

export const nonusApiConfig: { [key: string]: any } = {
'1': 'https://api.thegraph.com/subgraphs/name/nounsdao/nouns-subgraph'
}
}

export const delegationsSubgraphs: { [key: string]: string } = {
"1": "https://subgrapher.snapshot.org/gateway.thegraph.com/api/0f15b42bdeff7a063a4e1757d7e2f99e/deployments/id/QmXZiV6S13ha6QXq4dmaM3TB4CHcDxBMvGexSNu9Kc28EH",
"5": "https://subgrapher.snapshot.org/api.thegraph.com/subgraphs/name/snapshot-labs/snapshot-goerli",
"10": "https://subgrapher.snapshot.org/api.thegraph.com/subgraphs/name/snapshot-labs/snapshot-optimism",
"56": "https://subgrapher.snapshot.org/api.thegraph.com/subgraphs/name/snapshot-labs/snapshot-binance-smart-chain",
"100": "https://subgrapher.snapshot.org/api.thegraph.com/subgraphs/name/snapshot-labs/snapshot-gnosis-chain",
"137": "https://subgrapher.snapshot.org/api.thegraph.com/subgraphs/name/snapshot-labs/snapshot-polygon",
"250": "https://subgrapher.snapshot.org/api.thegraph.com/subgraphs/name/snapshot-labs/snapshot-fantom",
"42161": "https://subgrapher.snapshot.org/api.thegraph.com/subgraphs/name/snapshot-labs/snapshot-arbitrum"
}
91 changes: 91 additions & 0 deletions Implementations/API/backend/functions/snapshot/getDelegations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { APIGatewayProxyHandlerV2 } from 'aws-lambda'
import { delegationsSubgraphs } from 'functions/config'
import snapshot from '@snapshot-labs/snapshot.js';
import { getAddress } from '@ethersproject/address';


const {
subgraphRequest,
} = snapshot.utils;

async function getDelegationsOutAndIn(
network: string,
space: string
): Promise<string[]> {
if (!delegationsSubgraphs[network]) return [];

const max = 1000;
let result: any = [];
let page = 0;

const members: string[] = []

const query = {
delegations: {
__args: {
first: max,
skip: 0,
where: {
space_in: [space],
}
},
delegator: true,
delegate: true,
space: true
}
};
while (true) {
query.delegations.__args.skip = page * max;
const pageResult = await subgraphRequest(delegationsSubgraphs[network], query);
const pageDelegations = pageResult.delegations || [];
result = result.concat(pageDelegations);
page++;
if (pageDelegations.length < max) break;
}

result.forEach((delegation: any) => {
const delegator = getAddress(delegation.delegator);
const delegate = getAddress(delegation.delegate);
if (delegation.space === space) {
members.push(delegator)
members.push(delegate)

}
});

return members
}

export const handler: APIGatewayProxyHandlerV2 = async (event) => {

const space = event?.pathParameters?.id
if (!space) return { statusCode: 400, message: 'Missing id' }

const template = {
'@context': {
'@vocab': 'http://daostar.org/',
},
type: 'DAO',
name: space,
}

const members = await getDelegationsOutAndIn('1', space)

console.log({ members })

const membersFormatted = members.map((m: string) => {
return { id: m, type: 'EthereumAddress' }
})

const transformed = { members: membersFormatted, ...template }

return transformed
? {
statusCode: 200,
body: JSON.stringify(transformed),
}
: {
statusCode: 404,
body: JSON.stringify({ error: true }),
}
}
10 changes: 10 additions & 0 deletions Implementations/API/backend/utils/snapshot/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import 'dotenv/config';
import strategies from './strategies';
import validations from './validations';
import utils from './utils';

export default {
strategies,
validations,
utils
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Contract call strategy

Allows to get Voting power or Proposition power from an Aave GovernanceStrategy contract.

## Strategy Parameters

| Param | Type | Description | | |
| ------------------ | ------ | -------------------------------------------------------------------------------------------------------------------------- | --- | --- |
| governanceStrategy | string | The Ethereum address of the GovernanceStrategy contract to measure voting or proposition power from an address at a block. | | |
| powerType | string | Use `vote` for Voting Power or `proposition` for Proposition Power | | |
| | | | | |
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[
{
"name": "Example of Aave Governance Power strategy",
"strategy": {
"name": "aave-governance-power",
"params": {
"governanceStrategy": "0xb7e383ef9b1e9189fc0f71fb30af8aa14377429e",
"powerType": "vote",
"symbol": "Voting Power",
"decimals": 18
}
},
"network": "1",
"addresses": ["0x5BC928BF0DAb1e4A2ddd9e347b0F22e88026D76c"],
"snapshot": 12657715
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { BigNumber } from '@ethersproject/bignumber';
import { formatUnits } from '@ethersproject/units';
import { multicall } from '../../utils';

export const author = 'kartojal';
export const version = '0.1.0';

/**
* Aave Governance strategy to measure voting or
*/

const abi = [
{
inputs: [
{ internalType: 'address', name: 'user', type: 'address' },
{ internalType: 'uint256', name: 'blockNumber', type: 'uint256' }
],
name: 'getPropositionPowerAt',
outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
stateMutability: 'view',
type: 'function'
},
{
inputs: [
{ internalType: 'address', name: 'user', type: 'address' },
{ internalType: 'uint256', name: 'blockNumber', type: 'uint256' }
],
name: 'getVotingPowerAt',
outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
stateMutability: 'view',
type: 'function'
}
];

const powerTypesToMethod = {
vote: 'getVotingPowerAt',
proposition: 'getPropositionPowerAt'
};

export async function strategy(
space,
network,
provider,
addresses,
options,
snapshot
) {
const blockTag =
typeof snapshot === 'number'
? snapshot
: await provider.getBlockNumber(snapshot);

// Early return 0 voting power if governanceStrategy or powerType is not correctly set
if (!options.governanceStrategy || !powerTypesToMethod[options.powerType]) {
return Object.fromEntries(addresses.map((address) => [address, '0']));
}

const response: BigNumber[] = await multicall(
network,
provider,
abi,
addresses.map((address: any) => [
options.governanceStrategy,
powerTypesToMethod[options.powerType],
[address.toLowerCase(), blockTag]
]),
{ blockTag }
);
return Object.fromEntries(
response.map((value, i) => [
addresses[i],
parseFloat(formatUnits(value.toString(), options.decimals))
])
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[
{
"name": "AGIP 17: Voting power for GHST value of parcels",
"strategy": {
"name": "aavegotchi-agip-17",
"params": {
"symbol": "REALM"
}
},
"network": "137",
"addresses": ["0x027Ffd3c119567e85998f4E6B9c3d83D5702660c"],
"snapshot": 22089223
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { subgraphRequest } from '../../utils';

export const author = 'candoizo';
export const version = '0.1.2';

const AAVEGOTCHI_SUBGRAPH_URL = {
137: 'https://subgraph.satsuma-prod.com/tWYl5n5y04oz/aavegotchi/aavegotchi-core-matic/api'
};

const maxResponsePerQuery = 1000;

// agip 17: Voting power of 0.5 GHST/pixel
const realmSizeVotePower = {
0: 32, // humble
1: 128, // reasonable
2: 1028, // spacious
3: 1028, // spacious
4: 2048 // partner
};

export async function strategy(
_space,
network,
provider,
addresses,
options,
snapshot
) {
const blockTag = typeof snapshot === 'number' ? snapshot : 'latest';

const args: {
where: { id_in: string[] };
first: number;
block?: { number: number };
} = {
where: {
id_in: addresses.map((addr: string) => addr.toLowerCase())
},
first: addresses.length
};
if (blockTag !== 'latest') args.block = { number: blockTag };

const batchQuery = (i) => {
return {
['parcelsOwned_' + i]: {
__aliasFor: 'parcelsOwned',
__args: {
first: maxResponsePerQuery,
skip: maxResponsePerQuery * i
},
size: true
}
};
};
let parcelsOwnedQueryParams = {
users: {
__args: args,
id: true
}
};
for (let i = 0; i < 6; i++) {
parcelsOwnedQueryParams = {
...parcelsOwnedQueryParams,
users: {
...parcelsOwnedQueryParams.users,
...batchQuery(i)
}
};
}

const result = await subgraphRequest(
AAVEGOTCHI_SUBGRAPH_URL[network],
parcelsOwnedQueryParams
);

const userToInfo = Object.fromEntries(
result.users.map((user) => {
return [user.id, user];
})
);

return Object.fromEntries(
addresses.map((addr: string) => {
let realmVotingPowerValue = 0;
const res = userToInfo[addr.toLowerCase()];
if (res) {
const parcelsOwned = Object.entries(res)
.map(([key, val]) => {
if (key.startsWith('parcelsOwned')) return val;
else return [];
})
.flat(1) as unknown as { size: number }[];
if (parcelsOwned.length > 0) {
parcelsOwned.map((r: { size: number }) => {
let votePower = realmSizeVotePower[r.size];
if (isNaN(votePower)) votePower = 0;
realmVotingPowerValue += votePower;
});
}
}
return [addr, realmVotingPowerValue];
})
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Aavegotchi AGIP 37 GLTR Staked LP Strategy

## Description

This snapshot strategy enables voting power for the following assets staked in GLTR staking pools

- GHST-FUD LP
- GHST-FOMO LP
- GHST-ALPHA LP
- GHST-KEK LP
- GHST-GLTR LP
- GHST-USDC LP
- GHST-WMATIC LP

Please note this excludes voting power from:
- Staked wapGHST and unstaked wapGHST held in a wallet (see aavegotchi-agip-37-wap-ghst)
- amGHST (see erc20-balance-of)
- Unstaked GHST-FUD, GHST-FOMO, GHST-ALPHA, GHST-KEK, GHST-GLTR LP tokens (see erc20-tokens-per-uni)

## References

Aavegotchi AGIP 37: https://snapshot.org/#/aavegotchi.eth/proposal/0x9923aab6825158ec2503d88e3ee2f9c5fbb12000581d06343ac9829aa59b66a6
Loading

0 comments on commit e4eeea5

Please sign in to comment.