Skip to content

Commit

Permalink
Merge branch 'master' into fix-split-delegation-returned-address-not-…
Browse files Browse the repository at this point in the history
…checksummed
  • Loading branch information
wa0x6e authored Jan 20, 2025
2 parents 64624a5 + 587b7f8 commit a4b9ebe
Show file tree
Hide file tree
Showing 73 changed files with 2,375 additions and 83 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
SNAPSHOT_API_STRATEGY_SALT=12345 # Salt for the snapshot API strategy to send a key in header (optional)
PASSPORT_API_KEY= # API key for the passport API (optional for other strategies)
PASSPORT_SCORER_ID= # Scorer ID for the passport API (optional for other strategies)
MOXIE_API_KEY= # API key for the moxie APIs (optional for other strategies)
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"@ethersproject/strings": "^5.6.1",
"@ethersproject/units": "^5.6.1",
"@ethersproject/wallet": "^5.6.2",
"@snapshot-labs/snapshot.js": "^0.12.18",
"@snapshot-labs/snapshot.js": "^0.12.42",
"@spruceid/didkit-wasm-node": "^0.2.1",
"@uniswap/sdk-core": "^3.0.1",
"@uniswap/v3-sdk": "^3.9.0",
Expand Down
33 changes: 33 additions & 0 deletions src/strategies/botto-dao-base/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Botto Dao Governance strategy

It returns the BOTTO balance of the voters participating in the governance and in the liquidity mining program

Here is an example of parameters:
```json
[
{
"name": "Botto Dao Governance strategy",
"strategy": {
"name": "botto-dao",
"params": {
"token": "0x9dfad1b7102d46b1b197b90095b5c4e9f5845bba",
"stakingAddress": "0x19CD3998f106eCC40eE7668c19C47e18b491e8a6",
"miningAddress": "0xf8515Cae6915838543bCD7756F39268CE8F853Fd",
"liquidityAddress": "0x9ff68f61ca5eb0c6606dc517a9d44001e564bb66",
"symbol": "BOTTO",
"decimals": 18
}
},
"network": "1",
"addresses": [
"0xf2b10b41961f6bc3801e7946dabe5572158a78a5",
"0xea32cf979bdaf8d3bb4121d58515d4623a27f3e0",
"0x7173d417cfa1cdec794fa21f4ca8a71d181b2ca0",
"0x58787f1659b2fd8853918dab6d4a1565569e6044",
"0x7dbc5f88986db946f1d5987edfbf9c6917230fa2"
],
"snapshot": 13808330
}
]

```
24 changes: 24 additions & 0 deletions src/strategies/botto-dao-base/examples.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[
{
"name": "Botto Dao Base Governance strategy",
"strategy": {
"name": "botto-dao-base",
"params": {
"token": "0x24914cb6bd01e6a0cf2a9c0478e33c25926e6a0c",
"stakingAddress": "0x8a7a5991aAf142B43E58253Bd6791e240084F0A9",
"symbol": "BOTTO",
"decimals": 18
}
},
"network": "8453",
"addresses": [
"0x85D906C217Bb4c7b7f7CDE0D4318fAfa02f6F01d",
"0x276Dfeec6F5772156B19116d76D1E3DEB3B6F0b4",
"0x56768B032Fc12D2e911eF654B0054e26a58cef74",
"0x7173d417cfa1cdec794fa21f4ca8a71d181b2ca0",
"0x58787f1659b2fd8853918dab6d4a1565569e6044",
"0x7dbc5f88986db946f1d5987edfbf9c6917230fa2"
],
"snapshot": 23250193
}
]
45 changes: 45 additions & 0 deletions src/strategies/botto-dao-base/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { BigNumberish } from '@ethersproject/bignumber';
import { formatUnits } from '@ethersproject/units';
import { Multicaller } from '../../utils';

export const author = 'agustinjch';
export const version = '1.0.0';

const abi = ['function userStakes(address) external view returns(uint256)'];

export async function strategy(
space,
network,
provider,
addresses,
options,
snapshot
): Promise<Record<string, number>> {
const blockTag = typeof snapshot === 'number' ? snapshot : 'latest';
const _formatUnits = (value) =>
parseFloat(formatUnits(value, options.decimals));

const multiBalances = new Multicaller(network, provider, abi, {
blockTag
});

addresses.forEach((address) => {
multiBalances.call(
address + '-stakedBotto',
options.stakingAddress,
'userStakes',
[address]
);
});

const balances: Record<string, BigNumberish> = await multiBalances.execute();

const result = Object.fromEntries(
addresses.map((adr) => {
const stakedBotto = _formatUnits(balances[adr + '-stakedBotto'] || 0);
return [adr, stakedBotto];
})
);

return result;
}
2 changes: 1 addition & 1 deletion src/strategies/botto-dao/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Botto Dao Governance strategy

It returns the BOTTO balance of the voters participating in the governance and in the liquidiy mining program
It returns the BOTTO balance of the voters participating in the governance and in the liquidity mining program

Here is an example of parameters:
```json
Expand Down
2 changes: 1 addition & 1 deletion src/strategies/brightid/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ This strategy returns a score of 1 for voters verified in a BrightID user regist
- Public Registry(v5): https://github.com/BrightID/BrightID-SmartContract/blob/v5/snapshot/BrightIDSnapshot.sol
- Private Registry: https://github.com/clrfund/monorepo/tree/develop/contracts/contracts/userRegistry

Public registries are maintained by BrightID and can be used if a DAO has no interest on setting one up themselves.
Public registries are maintained by BrightID and can be used if a DAO has no interest in setting one up themselves.

Here is an example of parameters for using a public registry contract:
Note that when using a public registry, the network is always set to IDChain(74).
Expand Down
19 changes: 19 additions & 0 deletions src/strategies/cookie-staking/examples.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[
{
"name": "Example query",
"strategy": {
"name": "cookie-staking",
"params": {
"address": "0x036b6BA384656151471f348fccf5c2818b9223aE",
"decimals": 18
}
},
"network": "56",
"addresses": [
"0xaE7EF51F517380Ca0211A60BeA83596080ddF478",
"0xd0825555aA656c56e687A6412d40534ba7f0E096",
"0x7018b9aB744cd438De14e9186De43698A29A7aAA"
],
"snapshot": 43137800
}
]
78 changes: 78 additions & 0 deletions src/strategies/cookie-staking/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { Multicaller } from '../../utils';
import { formatUnits } from '@ethersproject/units';
import { BigNumber } from '@ethersproject/bignumber';

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

const abi = [
'function users(uint256,address) view returns (uint256 shares, uint256 lastDepositedTime, uint256 totalInvested, uint256 totalClaimed)'
];

interface UserData {
shares: BigNumber;
lastDepositedTime: BigNumber;
totalInvested: BigNumber;
totalClaimed: BigNumber;
}

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

const multi = new Multicaller(network, provider, abi, { blockTag });

const poolIds = 11;

// Prepare multicall
addresses.forEach((address) => {
for (let poolId = 0; poolId < poolIds; poolId++) {
multi.call(`${address}-${poolId}`, options.address, 'users', [
poolId,
address
]);
}
});

// Typecast result to Record<string, UserData>
const result = (await multi.execute()) as Record<string, UserData>;

// Initialize a mapping for user totals
const userTotals: { [address: string]: BigNumber } = {};

// Process the result
for (const [key, userData] of Object.entries(result)) {
const address = key.split('-')[0];

const totalInvested = BigNumber.from(userData.totalInvested);
const totalClaimed = BigNumber.from(userData.totalClaimed);

if (!userTotals[address]) {
userTotals[address] = BigNumber.from(0);
}

const amount = totalInvested.sub(totalClaimed);

userTotals[address] = userTotals[address].add(amount);
}

const formattedResult = Object.fromEntries(
addresses.map((address) => [
address,
parseFloat(
formatUnits(
userTotals[address] || BigNumber.from(0),
options.decimals || 18
)
)
])
);

return formattedResult;
}
23 changes: 23 additions & 0 deletions src/strategies/cookie-staking/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"type": "object",
"definitions": {
"Strategy": {
"title": "Strategy",
"type": "object",
"properties": {
"address": {
"type": "string",
"pattern": "^0x[a-fA-F0-9]{40}$",
"minLength": 42,
"maxLength": 42
},
"decimals": {
"type": "integer",
"minimum": 0
}
},
"required": ["address"],
"additionalProperties": false
}
}
}
13 changes: 7 additions & 6 deletions src/strategies/decentraland-wearable-rarity/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { EnumType } from 'json-to-graphql-query';
import { getAddress } from '@ethersproject/address';
import { subgraphRequest } from '../../utils';

Expand Down Expand Up @@ -53,16 +54,16 @@ export async function strategy(
__args: {
where: {
itemType_in: [
'wearable_v1',
'wearable_v2',
'smart_wearable_v1',
'emote_v1'
new EnumType('wearable_v1'),
new EnumType('wearable_v2'),
new EnumType('smart_wearable_v1'),
new EnumType('emote_v1')
],
owner_in: chunk.map((address) => address.toLowerCase()),
id_gt: ''
},
orderBy: 'id',
orderDirection: 'asc',
orderBy: new EnumType('id'),
orderDirection: new EnumType('asc'),
first: 1000
},
id: true,
Expand Down
3 changes: 2 additions & 1 deletion src/strategies/delegation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ In delegation strategy, the sub strategies defined in params are used to delegat
| ----------- | ----------- |
| strategies | list of sub strategies to calculate voting power based on delegation |
| delegationSpace (optional) | Get delegations of a particular space (by default it take delegations of current space) |
| delegationNetwork | Get delegation from a particular chain instead of default chain |

Here is an example of parameters:

Expand All @@ -34,4 +35,4 @@ Here is an example of parameters:
]
}

```
```
42 changes: 35 additions & 7 deletions src/strategies/delegation/examples.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,52 @@
"strategy": {
"name": "delegation",
"params": {
"symbol": "POH (delegated)",
"symbol": "APE (delegated)",
"delegationSpace": "apecoin.eth",
"strategies": [
{
"name": "erc20-balance-of",
"params": {
"address": "0x1dAD862095d40d43c2109370121cf087632874dB",
"decimals": 0
"symbol": "APE",
"address": "0x4d224452801aced8b2f0aebe155379bb5d594381",
"decimals": 18
}
}
]
}
},
"network": "1",
"addresses": [
"0x3c13f2B56AF614aC6381265EcB3B619bA26CC641",
"0x048fee7c3279a24af0790b6b002ded42be021d2b",
"0x139a9032a46c3afe3456eb5f0a35183b5f189cae"
"0x33924aFFe6BC352C246d7f384988f7b4Ad5f9cf2",
"0x56ee461fd756c416c5d2149b3976A019D3b44cc9",
"0x5c4a0fa9Ab5cfc27d198Cab40EC079210902A948"
],
"snapshot": 15705816
"snapshot": 21218777
},
{
"name": "Example query with delegationNetwork",
"strategy": {
"name": "delegation",
"params": {
"symbol": "APE (delegated)",
"delegationSpace": "apecoin.eth",
"delegationNetwork": "1",
"strategies": [
{
"name": "eth-balance",
"params": {
"symbol": "APE"
}
}
]
}
},
"network": "33139",
"addresses": [
"0x56ee461fd756c416c5d2149b3976A019D3b44cc9",
"0x68Afd61E37267Fd2898F0f965B580182e8D20e6d",
"0xCD02c8b722c8E286fbb353Fd7Bf814Bd38490C27"
],
"snapshot": 4631281
}
]
15 changes: 12 additions & 3 deletions src/strategies/delegation/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getDelegations } from '../../utils/delegation';
import { getScoresDirect } from '../../utils';
import { getScoresDirect, getSnapshots } from '../../utils';

export const author = 'bonustrack';
export const version = '0.1.0';
Expand All @@ -24,11 +24,20 @@ export async function strategy(
)
return {};
const delegationSpace = options.delegationSpace || space;
const delegationNetwork = options.delegationNetwork || network;
let delegationSnapshot = snapshot;
if (delegationNetwork !== network) {
const snapshots = await getSnapshots(network, snapshot, provider, [
delegationNetwork
]);
delegationSnapshot = snapshots[delegationNetwork];
}

const delegations = await getDelegations(
delegationSpace,
network,
delegationNetwork,
addresses,
snapshot
delegationSnapshot
);
if (Object.keys(delegations).length === 0) return {};

Expand Down
Loading

0 comments on commit a4b9ebe

Please sign in to comment.