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

added strategy to give liquidity providers on the Ocean marketplace v… #113

Merged
merged 4 commits into from Feb 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/strategies/index.ts
Expand Up @@ -45,6 +45,7 @@ import { strategy as ticket } from './ticket';
import { strategy as work } from './work';
import { strategy as ticketValidity } from './ticket-validity';
import { strategy as opium } from './opium';
import { strategy as ocean } from './ocean-marketplace';
import { strategy as theGraphBalance } from './the-graph-balance';
import { strategy as theGraphDelegation } from './the-graph-delegation';
import { strategy as theGraphIndexing } from './the-graph-indexing';
Expand Down Expand Up @@ -100,6 +101,7 @@ export default {
work,
'ticket-validity': ticketValidity,
opium,
'ocean-marketplace': ocean,
'the-graph-balance': theGraphBalance,
'the-graph-delegation': theGraphDelegation,
'the-graph-indexing': theGraphIndexing,
Expand Down
67 changes: 67 additions & 0 deletions src/strategies/ocean-marketplace/README.md
@@ -0,0 +1,67 @@
# Ocean marketplace Snapshot strategy

```version 0.1```

This strategy gives score aka votes to the liquidity providers on the [Ocean marketplace](https://market.oceanprotocol.com). This means that they can vote for OceanDAO votes hosted on the Snapshot platform without the need to remove their liquidity.

## Solution description

The solution pulls the needed data from the Ocean Protocol mainnet subgraph endpoint:
```https://subgraph.mainnet.oceanprotocol.com/subgraphs/name/oceanprotocol/ocean-subgraph```

It is pulling a bit more information than currently used so the solution can also be extended. The current limitation comes from only considering liquidity providers and ignoring pure token holders. This means that the tokens added to the liquidity pool by the pure token holders are accredited to the liquidity providers. This can be fixed but is a bit more complicated as the ratio of datatokens to Ocean tokens has to be considered in a general manner. And the token holders for each pool have to be extracted from the subgraph.

So the current solution checks for active pools with participants and then attributes votes to them like this:
```
user_votes = user_pool_shares * (total_Ocean_in_the_pool / total_number_of_pool_shares)
```
This is done for all pools and the votes for the users are added up.

To extend or run this strategy please use the setup described [here](https://docs.snapshot.page/strategies).

## GraphQL queries:

### Pools

```
pools (first: 1000, orderBy: oceanReserve, orderDirection: desc) {
id,
holderCount,
oceanReserve,
active,
totalShares,
shares (first: 1000) {
id,
userAddress {
id,
tokensOwned {
id
}
},
balance
},
tokens {
balance,
denormWeight,
tokenId {
id
}
}
}
```

### Datatokens

```
{
datatokens {
id,
balances {
userAddress {
id
}
balance
}
}
}
```
22 changes: 22 additions & 0 deletions src/strategies/ocean-marketplace/examples.json
@@ -0,0 +1,22 @@
[
{
"name": "OCEAN tokens staked on the marketplace",
"strategy": {
"name": "ocean-marketplace",
"params": {
"symbol": "OCEAN",
"decimals": 18,
"tokenAddress": "0x967da4048cD07aB37855c090aAF366e4ce1b9F48"
}
},
"network": "1",
"addresses": [
"0x655eFe6Eb2021b8CEfE22794d90293aeC37bb325",
"0x12BD31628075C20919BA838b89F414241b8c4869",
"0xf88bD9c3F81f7148E4076bBB8b2e2B0951A8cE38",
"0xAAB9EaBa1AA2653c1Dda9846334700b9F5e14E44"
],
"snapshot": "11635000"
}
]

75 changes: 75 additions & 0 deletions src/strategies/ocean-marketplace/index.ts
@@ -0,0 +1,75 @@
import { getAddress } from '@ethersproject/address';
import { subgraphRequest } from '../../utils';

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

const OCEAN_SUBGRAPH_URL = {
'1': 'https://subgraph.mainnet.oceanprotocol.com/subgraphs/name/oceanprotocol/ocean-subgraph',
'42': 'https://subgraph.rinkeby.oceanprotocol.com/subgraphs/name/oceanprotocol/ocean-subgraph'
};

export async function strategy(
space,
network,
provider,
addresses,
options,
snapshot
) {
const params = {
pools: {
__args: {
first: 1000,
orderBy: 'oceanReserve',
orderDirection: 'desc'
},
active: true,
totalShares: true,
holderCount: true,
oceanReserve: true,
shares: {
__args: {
first: 1000,
orderBy: 'balance',
orderDirection: 'desc'
},
userAddress: {
id: true,
tokensOwned: true
},
balance: true
},
tokens: {
balance: true,
denormWeight: true,
tokenId: {
id: true
}
}
}
};
if (snapshot !== 'latest') {
// @ts-ignore
params.pools.__args.block = { number: +snapshot };
}

const result = await subgraphRequest(OCEAN_SUBGRAPH_URL[network], params);

const score = {};
if (result && result.pools) {
result.pools.forEach((pool) => {
if (pool.holderCount > 0 && pool.active) {
pool.shares.map((share) => {
const userAddress = getAddress(share.userAddress.id);
if (!score[userAddress]) score[userAddress] = 0;
score[userAddress] =
score[userAddress] +
(pool.oceanReserve / pool.totalShares) *
share.balance;
});
}
});
}
return score || {};
}