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

[staking-amount-duration-exponential] 2 new strategies needed for our project #1608

Merged
merged 10 commits into from
Oct 14, 2024
6 changes: 5 additions & 1 deletion src/strategies/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,8 @@ import * as superboring from './superboring';
import * as erableGovernanceV1 from './erable-governance-v1';
import * as worldLibertyFinancial from './world-liberty-financial-erc20-balance-of-votes';
import * as snxMultichain from './snx-multichain';
import * as stakingAmountDurationLinear from './staking-amount-duration-linear';
import * as stakingAmountDurationExponential from './staking-amount-duration-exponential';

const strategies = {
'delegatexyz-erc721-balance-of': delegatexyzErc721BalanceOf,
Expand Down Expand Up @@ -924,7 +926,9 @@ const strategies = {
superboring,
'erable-governance-v1': erableGovernanceV1,
'world-liberty-financial-erc20-balance-of-votes': worldLibertyFinancial,
'snx-multichain': snxMultichain
'snx-multichain': snxMultichain,
'staking-amount-duration-linear': stakingAmountDurationLinear,
'staking-amount-duration-exponential': stakingAmountDurationExponential
};

Object.keys(strategies).forEach(function (strategyName) {
Expand Down
16 changes: 16 additions & 0 deletions src/strategies/staking-amount-duration-exponential/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# staking-amount-duration-exponential

This is a strategy for calculating voting power with this formula

Voting Power = Stake Amount × (1 + r) ^ Stake Duration

Here is an example of parameters:

```json
{
"address": "0x6b175474e89094c44da98b954eedeac495271d0f",
"symbol": "DAI",
"decimals": 18,
"rate": 0.1
}
```
21 changes: 21 additions & 0 deletions src/strategies/staking-amount-duration-exponential/examples.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[
{
"name": "Example query",
"strategy": {
"name": "staking-amount-duration-exponential",
"params": {
"address": "0x520BDBFCe65CECa0813e51D724804BC7Fd6107dd",
"symbol": "STAKE",
"decimals": 18,
"rate": 0.1
}
},
"network": "11155111",
"addresses": [
"0x57bABaf9E18587C2C1E97244729847604789fC81",
"0xc62BD6B53f46883038b5f018aE74155f07b0e6Db",
"0x6CcE789f04A3f0c291E97042765E07bccC6D73B3"
],
"snapshot": 6856587
}
]
58 changes: 58 additions & 0 deletions src/strategies/staking-amount-duration-exponential/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { formatUnits } from '@ethersproject/units';
import { Multicaller } from '../../utils';

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

const abi = [
'function getUserStakes(address user) view returns (tuple(uint256 amount, uint256 claimed, uint48 stakeTime, uint8 planId, bool unstaked)[])'
];
const secondsInAMonth = 30.44 * 24 * 60 * 60;

interface Stake {
amount: bigint;
claimed: bigint;
stakeTime: bigint;
planId: bigint;
unstaked: boolean;
}

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

const snapshotBlock = await provider.getBlock(blockTag);

const multi = new Multicaller(network, provider, abi, { blockTag });
addresses.forEach((address) =>
multi.call(address, options.address, 'getUserStakes', [address])
);
const result: Record<string, Stake[]> = await multi.execute();

return Object.fromEntries(
Object.entries(result).map(([address, stakes]) => {
let power = 0;
stakes.forEach((stake) => {
if (!stake.unstaked) {
if (snapshotBlock.timestamp > stake.stakeTime) {
const duration =
Number(snapshotBlock.timestamp - stake.stakeTime) /
secondsInAMonth;
const durationRateCalculated = Math.pow(1 + options.rate, duration);
power +=
parseFloat(formatUnits(stake.amount, options.decimals)) *
durationRateCalculated;
}
}
});

return [address, power];
})
);
}
40 changes: 40 additions & 0 deletions src/strategies/staking-amount-duration-exponential/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$ref": "#/definitions/Strategy",
"definitions": {
"Strategy": {
"title": "Strategy",
"type": "object",
"properties": {
"symbol": {
"type": "string",
"title": "Symbol",
"examples": ["e.g. UNI"],
"maxLength": 16
},
"address": {
"type": "string",
"title": "Contract address",
"examples": ["e.g. 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"],
"pattern": "^0x[a-fA-F0-9]{40}$",
"minLength": 42,
"maxLength": 42
},
"decimals": {
"type": "number",
"title": "Decimals",
"examples": ["e.g. 18"],
"minimum": 0
},
"rate": {
"type": "number",
"title": "Rate (Voting Power = Stake Amount × (1 + rate) ^ Stake Duration)",
"examples": ["e.g. 0.1"],
"minimum": 0
}
},
"required": ["address", "decimals"],
"additionalProperties": false
}
}
}
15 changes: 15 additions & 0 deletions src/strategies/staking-amount-duration-linear/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# staking-amount-duration-linear

This is a strategy for calculating voting power with this formula

Voting Power = Stake Amount × Stake Duration (in time units)

Here is an example of parameters:

```json
{
"address": "0x6b175474e89094c44da98b954eedeac495271d0f",
"symbol": "DAI",
"decimals": 18
}
```
20 changes: 20 additions & 0 deletions src/strategies/staking-amount-duration-linear/examples.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[
{
"name": "Example query",
"strategy": {
"name": "staking-amount-duration-linear",
"params": {
"address": "0x520BDBFCe65CECa0813e51D724804BC7Fd6107dd",
"symbol": "STAKE",
"decimals": 18
}
},
"network": "11155111",
"addresses": [
"0x57bABaf9E18587C2C1E97244729847604789fC81",
"0xc62BD6B53f46883038b5f018aE74155f07b0e6Db",
"0x6CcE789f04A3f0c291E97042765E07bccC6D73B3"
],
"snapshot": 6856587
}
]
57 changes: 57 additions & 0 deletions src/strategies/staking-amount-duration-linear/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { formatUnits } from '@ethersproject/units';
import { Multicaller } from '../../utils';

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

const abi = [
'function getUserStakes(address user) view returns (tuple(uint256 amount, uint256 claimed, uint48 stakeTime, uint8 planId, bool unstaked)[])'
];
const secondsInAMonth = 30.44 * 24 * 60 * 60;

interface Stake {
amount: bigint;
claimed: bigint;
stakeTime: bigint;
planId: bigint;
unstaked: boolean;
}

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

const snapshotBlock = await provider.getBlock(blockTag);

const multi = new Multicaller(network, provider, abi, { blockTag });
addresses.forEach((address) =>
multi.call(address, options.address, 'getUserStakes', [address])
);
const result: Record<string, Stake[]> = await multi.execute();

return Object.fromEntries(
Object.entries(result).map(([address, stakes]) => {
let power = 0;
stakes.forEach((stake) => {
if (!stake.unstaked) {
if (snapshotBlock.timestamp > stake.stakeTime) {
const duration =
Number(snapshotBlock.timestamp - stake.stakeTime) /
secondsInAMonth;
power +=
parseFloat(formatUnits(stake.amount, options.decimals)) *
duration;
}
}
});

return [address, power];
})
);
}
34 changes: 34 additions & 0 deletions src/strategies/staking-amount-duration-linear/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$ref": "#/definitions/Strategy",
"definitions": {
"Strategy": {
"title": "Strategy",
"type": "object",
"properties": {
"symbol": {
"type": "string",
"title": "Symbol",
"examples": ["e.g. UNI"],
"maxLength": 16
},
"address": {
"type": "string",
"title": "Contract address",
"examples": ["e.g. 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"],
"pattern": "^0x[a-fA-F0-9]{40}$",
"minLength": 42,
"maxLength": 42
},
"decimals": {
"type": "number",
"title": "Decimals",
"examples": ["e.g. 18"],
"minimum": 0
}
},
"required": ["address", "decimals"],
"additionalProperties": false
}
}
}
Loading