Skip to content

Commit

Permalink
[plearn] Add plearn strategy (#1357)
Browse files Browse the repository at this point in the history
* feat: Add Plearn strategy

* fix: Change object ABI to string ABI

* docs: Update plearn strategy Readme

* fix: Add limit address arrays to max 5

* fix: Refactor multicall implementation for Limit network requests

* fix: Refactor score calculation logic

* fix: Refactor score calculation logic

* fix: Improve code and add Types

* fix: Improve code and types

* fix: Check result is undefined, null

* fix: Refactor transformResults to use  lambda function for balance processing

* fix: Remove check amount is null and undefined

* Refactor index.ts

* Update index.ts

* fix: Add import BigNumber and change let to const

---------

Co-authored-by: Tia <[email protected]>
  • Loading branch information
jeeraponnnnnnnn and tiakun authored Nov 28, 2023
1 parent cd01f3b commit 2d3a070
Show file tree
Hide file tree
Showing 4 changed files with 231 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/strategies/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,7 @@ import * as hatsProtocolHatId from './hats-protocol-hat-id';
import * as hatsProtocolHatIds from './hats-protocol-hat-ids';
import * as bubblegumKids from './bubblegum-kids';
import * as clipperStakedSail from './clipper-staked-sail';
import * as plearn from './plearn';
import * as snote from './snote';

const strategies = {
Expand Down Expand Up @@ -962,6 +963,7 @@ const strategies = {
'hats-protocol-hat-ids': hatsProtocolHatIds,
'bubblegum-kids': bubblegumKids,
'clipper-staked-sail': clipperStakedSail,
plearn,
snote
};

Expand Down
47 changes: 47 additions & 0 deletions src/strategies/plearn/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Plearn

This is the most common strategy, it returns the balances of the voters for a balances PLN token
in Plearn project(pools, token).

Here is an example of parameters:

```json
[
{
"name": "Example query",
"strategy": {
"name": "plearn",
"params": {
"lockedPoolAddresses": [
{
"address": "0xc38d542326545470a12B06Bf8e315DE55B0B6B46"
},
{
"address": "0x9b45a8eeD3eF6DA3bE222147533Da542aa384006"
}
],
"foundingInvestorPoolAddresses": [],
"pendingWithdrawalAddresses": [
{
"address": "0x7E4e06C81B41284198C0693cd98eb357257Fc3d9"
},
{
"address": "0xC26a3E07D8CCF34195e943C0bb705f206Dd57030"
}
],
"symbol": "PLN",
"address": "0xBe0D3526fc797583Dada3F30BC390013062A048B",
"decimals": 18
}
},
"network": "56",
"addresses": [
"0xE0d54117600e592E7a78C985996d11b8Fb1B69C3",
"0x3C97c372B45cC96Fe73814721ebbE6db02C9D88E",
"0xB6605F98A5562b1AC821Bc5f2B75934239e8c6D6",
"0x8900cCBdC60fD97E3B7c8529A9987F8c0f8A1125"
],
"snapshot": 33739024
}
]
```
38 changes: 38 additions & 0 deletions src/strategies/plearn/examples.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
[
{
"name": "Example query",
"strategy": {
"name": "plearn",
"params": {
"lockedPoolAddresses": [
{
"address": "0xc38d542326545470a12B06Bf8e315DE55B0B6B46"
},
{
"address": "0x9b45a8eeD3eF6DA3bE222147533Da542aa384006"
}
],
"foundingInvestorPoolAddresses": [],
"pendingWithdrawalAddresses": [
{
"address": "0x7E4e06C81B41284198C0693cd98eb357257Fc3d9"
},
{
"address": "0xC26a3E07D8CCF34195e943C0bb705f206Dd57030"
}
],
"symbol": "PLN",
"address": "0xBe0D3526fc797583Dada3F30BC390013062A048B",
"decimals": 18
}
},
"network": "56",
"addresses": [
"0xE0d54117600e592E7a78C985996d11b8Fb1B69C3",
"0x3C97c372B45cC96Fe73814721ebbE6db02C9D88E",
"0xB6605F98A5562b1AC821Bc5f2B75934239e8c6D6",
"0x8900cCBdC60fD97E3B7c8529A9987F8c0f8A1125"
],
"snapshot": 33739024
}
]
144 changes: 144 additions & 0 deletions src/strategies/plearn/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import { Provider } from '@ethersproject/providers';
import { formatUnits } from '@ethersproject/units';
import { BigNumber } from '@ethersproject/bignumber';
import { multicall } from '../../utils';
import { strategy as erc20BalanceOfStrategy } from '../erc20-balance-of';

export const author = 'plearnclub';
export const version = '0.0.1';

const lockedPoolabi = [
'function userInfo(address) view returns (uint256 amount)'
];

const foundingInvestorPoolabi = [
'function userInfo(address) view returns (uint256 initialAmount, uint256 amount)'
];

const pendingWithdrawalabi = [
'function lockedBalances(address user) view returns (uint256 total, uint256 unlockable, uint256 locked, tuple(uint256 amount, uint256 unlockTime)[] lockData)'
];

function transformResults(
res: any[],
addresses: string[],
balanceTransformer: (result: any) => number
): { [address: string]: number } {
return res.reduce((acc: { [address: string]: number }, result, index) => {
const address = addresses[index % addresses.length];
if (!acc[address]) {
acc[address] = 0;
}

const amount = balanceTransformer(result);
acc[address] += amount;
return acc;
}, {});
}

export async function strategy(
space: string,
network: string,
provider: Provider,
addresses: string[],
options: {
lockedPoolAddresses: { address: string }[];
foundingInvestorPoolAddresses: { address: string }[];
pendingWithdrawalAddresses: { address: string }[];
symbol: string;
address: string;
decimals: number;
},
snapshot: number | string
): Promise<{ [address: string]: number }> {
const blockTag = typeof snapshot === 'number' ? snapshot : 'latest';
const score = await erc20BalanceOfStrategy(
space,
network,
provider,
addresses,
options,
snapshot
);

const lockedPoolCalls = options.lockedPoolAddresses.flatMap((item) =>
addresses.map((address) => [
item.address,
'userInfo',
[address],
{ blockTag }
])
);

const foundingInvestorPoolCalls =
options.foundingInvestorPoolAddresses.flatMap((item) =>
addresses.map((address) => [
item.address,
'userInfo',
[address],
{ blockTag }
])
);

const pendingWithdrawalCalls = options.pendingWithdrawalAddresses.flatMap(
(item) =>
addresses.map((address) => [
item.address,
'lockedBalances',
[address],
{ blockTag }
])
);

const [
lockedPoolBalancesRes,
foundingInvestorPoolBalancesRes,
pendingWithdrawalBalancesRes
] = await Promise.all([
multicall(network, provider, lockedPoolabi, lockedPoolCalls, { blockTag }),
multicall(
network,
provider,
foundingInvestorPoolabi,
foundingInvestorPoolCalls,
{ blockTag }
),
multicall(network, provider, pendingWithdrawalabi, pendingWithdrawalCalls, {
blockTag
})
]);

const pf = (amount: BigNumber) =>
parseFloat(formatUnits(amount, options.decimals));

const lockedPoolScore = transformResults(
lockedPoolBalancesRes,
addresses,
(r) => pf(r.amount)
);
const foundingInvestorPoolScore = transformResults(
foundingInvestorPoolBalancesRes,
addresses,
(r) => pf(r.amount)
);
const pendingWithdrawalScore = transformResults(
pendingWithdrawalBalancesRes,
addresses,
(r) => pf(r.total)
);

const finalScore = Object.keys(score).reduce(
(acc: { [address: string]: number }, address) => {
acc[address] = Math.trunc(
score[address] +
(lockedPoolScore[address] || 0) +
(foundingInvestorPoolScore[address] || 0) +
(pendingWithdrawalScore[address] || 0)
);
return acc;
},
{}
);

return finalScore;
}

0 comments on commit 2d3a070

Please sign in to comment.