diff --git a/proto/farms.proto b/proto/farms.proto index 58be7a824..4a7e7f52e 100644 --- a/proto/farms.proto +++ b/proto/farms.proto @@ -46,4 +46,6 @@ message Farm { string optimalEnergyPerLp = 38; string boostedRewardsPerWeek = 39; Pair pair = 40; + string perSecondRewards = 41; + uint32 lastRewardTimestamp = 42; } \ No newline at end of file diff --git a/proto/staking_farms.proto b/proto/staking_farms.proto index 514998205..67cedddcc 100644 --- a/proto/staking_farms.proto +++ b/proto/staking_farms.proto @@ -22,9 +22,9 @@ message StakingFarm { string baseApr = 15; string maxBoostedApr = 16; uint32 minUnboundEpochs = 17; - string perBlockRewards = 18; - uint32 lastRewardBlockNonce = 19; - string rewardsPerBlockAPRBound = 20; + string perSecondRewards = 18; + uint32 lastRewardTimestamp = 19; + string rewardsPerSecondAPRBound = 20; bool isProducingRewards = 21; uint32 rewardsRemainingDays = 22; uint32 rewardsRemainingDaysUncapped = 23; diff --git a/src/abis/farm-staking.abi.json b/src/abis/farm-staking.abi.json index 223ad5e17..0292d6d0a 100644 --- a/src/abis/farm-staking.abi.json +++ b/src/abis/farm-staking.abi.json @@ -1,20 +1,13 @@ { "buildInfo": { - "rustc": { - "version": "1.80.0-nightly", - "commitHash": "84b40fc908c3adc7e0e470b3fbaa264df0e122b8", - "commitDate": "2024-05-27", - "channel": "Nightly", - "short": "rustc 1.80.0-nightly (84b40fc90 2024-05-27)" - }, "contractCrate": { "name": "farm-staking", "version": "0.0.0", - "gitVersion": "v1.6.0-1831-g81b6253f" + "gitVersion": "v1.6.0-2122-g457d1532" }, "framework": { "name": "multiversx-sc", - "version": "0.50.5" + "version": "0.64.1" } }, "name": "FarmStaking", @@ -129,11 +122,11 @@ "outputs": [] }, { - "name": "setPerBlockRewardAmount", + "name": "setPerSecondRewardAmount", "mutability": "mutable", "inputs": [ { - "name": "per_block_amount", + "name": "per_second_amount", "type": "BigUint" } ], @@ -227,17 +220,6 @@ } ] }, - { - "name": "setAllowExternalClaimBoostedRewards", - "mutability": "mutable", - "inputs": [ - { - "name": "allow_external_claim", - "type": "bool" - } - ], - "outputs": [] - }, { "name": "getFarmingTokenId", "mutability": "readonly", @@ -259,7 +241,7 @@ ] }, { - "name": "getPerBlockRewardAmount", + "name": "getPerSecondRewardAmount", "mutability": "readonly", "inputs": [], "outputs": [ @@ -269,7 +251,7 @@ ] }, { - "name": "getLastRewardBlockNonce", + "name": "getLastRewardTimestamp", "mutability": "readonly", "inputs": [], "outputs": [ @@ -504,6 +486,18 @@ } ] }, + { + "name": "setPermissionsHubAddress", + "onlyOwner": true, + "mutability": "mutable", + "inputs": [ + { + "name": "address", + "type": "Address" + } + ], + "outputs": [] + }, { "name": "setBurnRoleForAddress", "onlyOwner": true, @@ -680,69 +674,70 @@ ] }, { - "name": "claimBoostedRewards", + "name": "stakeFarmOnBehalf", "mutability": "mutable", + "payableInTokens": [ + "*" + ], "inputs": [ { - "name": "opt_user", - "type": "optional
", - "multi_arg": true + "name": "user", + "type": "Address" } ], "outputs": [ + { + "type": "EsdtTokenPayment" + }, { "type": "EsdtTokenPayment" } ] }, { - "name": "collectUndistributedBoostedRewards", + "name": "claimRewardsOnBehalf", "mutability": "mutable", - "inputs": [], - "outputs": [] - }, - { - "name": "getBoostedYieldsRewardsPercentage", - "mutability": "readonly", + "payableInTokens": [ + "*" + ], "inputs": [], "outputs": [ { - "type": "u64" + "type": "EsdtTokenPayment" + }, + { + "type": "EsdtTokenPayment" } ] }, { - "name": "getAccumulatedRewardsForWeek", - "mutability": "readonly", + "name": "claimBoostedRewards", + "mutability": "mutable", "inputs": [ { - "name": "week", - "type": "u32" + "name": "opt_user", + "type": "optional
", + "multi_arg": true } ], "outputs": [ { - "type": "BigUint" + "type": "EsdtTokenPayment" } ] }, { - "name": "getFarmSupplyForWeek", + "name": "getBoostedYieldsRewardsPercentage", "mutability": "readonly", - "inputs": [ - { - "name": "week", - "type": "u32" - } - ], + "inputs": [], "outputs": [ { - "type": "BigUint" + "type": "u64" } ] }, { - "name": "getRemainingBoostedRewardsToDistribute", + "name": "getAccumulatedRewardsForWeek", "mutability": "readonly", "inputs": [ { @@ -757,9 +752,14 @@ ] }, { - "name": "getUndistributedBoostedRewards", + "name": "getFarmSupplyForWeek", "mutability": "readonly", - "inputs": [], + "inputs": [ + { + "name": "week", + "type": "u32" + } + ], "outputs": [ { "type": "BigUint" @@ -803,6 +803,32 @@ } ] }, + { + "name": "collectUndistributedBoostedRewards", + "onlyOwner": true, + "mutability": "mutable", + "inputs": [], + "outputs": [ + { + "type": "BigUint" + } + ] + }, + { + "name": "getRemainingBoostedRewardsToDistribute", + "mutability": "readonly", + "inputs": [ + { + "name": "week", + "type": "u32" + } + ], + "outputs": [ + { + "type": "BigUint" + } + ] + }, { "docs": [ "Week starts from 1" diff --git a/src/abis/farms/v2/farm-with-locked-rewards.abi.json b/src/abis/farms/v2/farm-with-locked-rewards.abi.json index a60924419..6a0c77942 100644 --- a/src/abis/farms/v2/farm-with-locked-rewards.abi.json +++ b/src/abis/farms/v2/farm-with-locked-rewards.abi.json @@ -1,20 +1,13 @@ { "buildInfo": { - "rustc": { - "version": "1.80.0-nightly", - "commitHash": "84b40fc908c3adc7e0e470b3fbaa264df0e122b8", - "commitDate": "2024-05-27", - "channel": "Nightly", - "short": "rustc 1.80.0-nightly (84b40fc90 2024-05-27)" - }, "contractCrate": { "name": "farm-with-locked-rewards", "version": "0.0.0", - "gitVersion": "v1.6.0-1831-g81b6253f" + "gitVersion": "v1.6.0-2122-g457d1532" }, "framework": { "name": "multiversx-sc", - "version": "0.50.5" + "version": "0.64.1" } }, "name": "Farm", @@ -170,11 +163,11 @@ "outputs": [] }, { - "name": "setPerBlockRewardAmount", + "name": "setPerSecondRewardAmount", "mutability": "mutable", "inputs": [ { - "name": "per_block_amount", + "name": "per_second_amount", "type": "BigUint" } ], @@ -234,17 +227,6 @@ } ] }, - { - "name": "setAllowExternalClaimBoostedRewards", - "mutability": "mutable", - "inputs": [ - { - "name": "allow_external_claim", - "type": "bool" - } - ], - "outputs": [] - }, { "name": "getFarmingTokenId", "mutability": "readonly", @@ -266,7 +248,7 @@ ] }, { - "name": "getPerBlockRewardAmount", + "name": "getPerSecondRewardAmount", "mutability": "readonly", "inputs": [], "outputs": [ @@ -276,7 +258,7 @@ ] }, { - "name": "getLastRewardBlockNonce", + "name": "getLastRewardTimestamp", "mutability": "readonly", "inputs": [], "outputs": [ @@ -516,6 +498,18 @@ } ] }, + { + "name": "setPermissionsHubAddress", + "onlyOwner": true, + "mutability": "mutable", + "inputs": [ + { + "name": "address", + "type": "Address" + } + ], + "outputs": [] + }, { "name": "addSCAddressToWhitelist", "onlyOwner": true, @@ -631,38 +625,54 @@ ] }, { - "name": "collectUndistributedBoostedRewards", + "name": "enterFarmOnBehalf", "mutability": "mutable", - "inputs": [], - "outputs": [] + "payableInTokens": [ + "*" + ], + "inputs": [ + { + "name": "user", + "type": "Address" + } + ], + "outputs": [ + { + "type": "EsdtTokenPayment" + }, + { + "type": "EsdtTokenPayment" + } + ] }, { - "name": "getBoostedYieldsRewardsPercentage", - "mutability": "readonly", + "name": "claimRewardsOnBehalf", + "mutability": "mutable", + "payableInTokens": [ + "*" + ], "inputs": [], "outputs": [ { - "type": "u64" + "type": "EsdtTokenPayment" + }, + { + "type": "EsdtTokenPayment" } ] }, { - "name": "getAccumulatedRewardsForWeek", + "name": "getBoostedYieldsRewardsPercentage", "mutability": "readonly", - "inputs": [ - { - "name": "week", - "type": "u32" - } - ], + "inputs": [], "outputs": [ { - "type": "BigUint" + "type": "u64" } ] }, { - "name": "getFarmSupplyForWeek", + "name": "getAccumulatedRewardsForWeek", "mutability": "readonly", "inputs": [ { @@ -677,7 +687,7 @@ ] }, { - "name": "getRemainingBoostedRewardsToDistribute", + "name": "getFarmSupplyForWeek", "mutability": "readonly", "inputs": [ { @@ -691,16 +701,6 @@ } ] }, - { - "name": "getUndistributedBoostedRewards", - "mutability": "readonly", - "inputs": [], - "outputs": [ - { - "type": "BigUint" - } - ] - }, { "name": "setBoostedYieldsFactors", "mutability": "mutable", @@ -738,6 +738,32 @@ } ] }, + { + "name": "collectUndistributedBoostedRewards", + "onlyOwner": true, + "mutability": "mutable", + "inputs": [], + "outputs": [ + { + "type": "BigUint" + } + ] + }, + { + "name": "getRemainingBoostedRewardsToDistribute", + "mutability": "readonly", + "inputs": [ + { + "name": "week", + "type": "u32" + } + ], + "outputs": [ + { + "type": "BigUint" + } + ] + }, { "docs": [ "Week starts from 1" diff --git a/src/abis/farms/v2/farm.abi.json b/src/abis/farms/v2/farm.abi.json index 1140657b6..48e5ac77a 100644 --- a/src/abis/farms/v2/farm.abi.json +++ b/src/abis/farms/v2/farm.abi.json @@ -1,20 +1,13 @@ { "buildInfo": { - "rustc": { - "version": "1.66.0-nightly", - "commitHash": "b8c35ca26b191bb9a9ac669a4b3f4d3d52d97fb1", - "commitDate": "2022-10-15", - "channel": "Nightly", - "short": "rustc 1.66.0-nightly (b8c35ca26 2022-10-15)" - }, "contractCrate": { "name": "farm", "version": "0.0.0", - "git_version": "v1.6.0-657-g8d756848-modified" + "gitVersion": "v1.6.0-2122-g457d1532" }, "framework": { - "name": "elrond-wasm", - "version": "0.36.0" + "name": "multiversx-sc", + "version": "0.64.1" } }, "name": "Farm", @@ -48,6 +41,10 @@ ], "outputs": [] }, + "upgradeConstructor": { + "inputs": [], + "outputs": [] + }, "endpoints": [ { "name": "enterFarm", @@ -119,10 +116,6 @@ "*" ], "inputs": [ - { - "name": "exit_amount", - "type": "BigUint" - }, { "name": "opt_orig_caller", "type": "optional
", @@ -133,50 +126,39 @@ { "type": "EsdtTokenPayment" }, - { - "type": "EsdtTokenPayment" - }, { "type": "EsdtTokenPayment" } ] }, { - "name": "calculateRewardsForGivenPosition", - "mutability": "readonly", + "name": "mergeFarmTokens", + "mutability": "mutable", + "payableInTokens": [ + "*" + ], "inputs": [ { - "name": "user", - "type": "Address" - }, - { - "name": "farm_token_nonce", - "type": "u64" - }, - { - "name": "farm_token_amount", - "type": "BigUint" - }, - { - "name": "attributes", - "type": "FarmTokenAttributes" + "name": "opt_orig_caller", + "type": "optional
", + "multi_arg": true } ], "outputs": [ { - "type": "BigUint" + "type": "EsdtTokenPayment" + }, + { + "type": "EsdtTokenPayment" } ] }, { - "name": "mergeFarmTokens", + "name": "claimBoostedRewards", "mutability": "mutable", - "payableInTokens": [ - "*" - ], "inputs": [ { - "name": "opt_orig_caller", + "name": "opt_user", "type": "optional
", "multi_arg": true } @@ -200,16 +182,50 @@ "outputs": [] }, { - "name": "setPerBlockRewardAmount", + "name": "setPerSecondRewardAmount", "mutability": "mutable", "inputs": [ { - "name": "per_block_amount", + "name": "per_second_amount", "type": "BigUint" } ], "outputs": [] }, + { + "name": "setBoostedYieldsRewardsPercentage", + "mutability": "mutable", + "inputs": [ + { + "name": "percentage", + "type": "u64" + } + ], + "outputs": [] + }, + { + "name": "calculateRewardsForGivenPosition", + "mutability": "readonly", + "inputs": [ + { + "name": "user", + "type": "Address" + }, + { + "name": "farm_token_amount", + "type": "BigUint" + }, + { + "name": "attributes", + "type": "FarmTokenAttributes" + } + ], + "outputs": [ + { + "type": "BigUint" + } + ] + }, { "name": "getRewardPerShare", "mutability": "readonly", @@ -251,7 +267,7 @@ ] }, { - "name": "getPerBlockRewardAmount", + "name": "getPerSecondRewardAmount", "mutability": "readonly", "inputs": [], "outputs": [ @@ -261,7 +277,7 @@ ] }, { - "name": "getLastRewardBlockNonce", + "name": "getLastRewardTimestamp", "mutability": "readonly", "inputs": [], "outputs": [ @@ -280,6 +296,46 @@ } ] }, + { + "name": "getUserTotalFarmPosition", + "mutability": "readonly", + "inputs": [ + { + "name": "user", + "type": "Address" + } + ], + "outputs": [ + { + "type": "BigUint" + } + ] + }, + { + "name": "getAllowExternalClaim", + "mutability": "readonly", + "inputs": [ + { + "name": "user", + "type": "Address" + } + ], + "outputs": [ + { + "type": "bool" + } + ] + }, + { + "name": "getFarmPositionMigrationNonce", + "mutability": "readonly", + "inputs": [], + "outputs": [ + { + "type": "u64" + } + ] + }, { "name": "registerFarmToken", "mutability": "mutable", @@ -390,6 +446,18 @@ ], "outputs": [] }, + { + "name": "updateOwnerOrAdmin", + "onlyOwner": true, + "mutability": "mutable", + "inputs": [ + { + "name": "previous_owner", + "type": "Address" + } + ], + "outputs": [] + }, { "name": "getPermissions", "mutability": "readonly", @@ -405,6 +473,18 @@ } ] }, + { + "name": "setPermissionsHubAddress", + "onlyOwner": true, + "mutability": "mutable", + "inputs": [ + { + "name": "address", + "type": "Address" + } + ], + "outputs": [] + }, { "name": "addSCAddressToWhitelist", "onlyOwner": true, @@ -520,22 +600,88 @@ ] }, { - "name": "setBoostedYieldsRewardsPercentage", + "name": "enterFarmOnBehalf", "mutability": "mutable", + "payableInTokens": [ + "*" + ], "inputs": [ { - "name": "percentage", + "name": "user", + "type": "Address" + } + ], + "outputs": [ + { + "type": "EsdtTokenPayment" + }, + { + "type": "EsdtTokenPayment" + } + ] + }, + { + "name": "claimRewardsOnBehalf", + "mutability": "mutable", + "payableInTokens": [ + "*" + ], + "inputs": [], + "outputs": [ + { + "type": "EsdtTokenPayment" + }, + { + "type": "EsdtTokenPayment" + } + ] + }, + { + "name": "getBoostedYieldsRewardsPercentage", + "mutability": "readonly", + "inputs": [], + "outputs": [ + { "type": "u64" } + ] + }, + { + "name": "getAccumulatedRewardsForWeek", + "mutability": "readonly", + "inputs": [ + { + "name": "week", + "type": "u32" + } ], - "outputs": [] + "outputs": [ + { + "type": "BigUint" + } + ] + }, + { + "name": "getFarmSupplyForWeek", + "mutability": "readonly", + "inputs": [ + { + "name": "week", + "type": "u32" + } + ], + "outputs": [ + { + "type": "BigUint" + } + ] }, { "name": "setBoostedYieldsFactors", "mutability": "mutable", "inputs": [ { - "name": "user_rewards_base_const", + "name": "max_rewards_factor", "type": "BigUint" }, { @@ -558,18 +704,23 @@ "outputs": [] }, { - "name": "collectUndistributedBoostedRewards", - "mutability": "mutable", + "name": "getBoostedYieldsFactors", + "mutability": "readonly", "inputs": [], - "outputs": [] + "outputs": [ + { + "type": "BoostedYieldsFactors" + } + ] }, { - "name": "getBoostedYieldsRewardsPercenatage", - "mutability": "readonly", + "name": "collectUndistributedBoostedRewards", + "onlyOwner": true, + "mutability": "mutable", "inputs": [], "outputs": [ { - "type": "u64" + "type": "BigUint" } ] }, @@ -588,26 +739,6 @@ } ] }, - { - "name": "getUndistributedBoostedRewards", - "mutability": "readonly", - "inputs": [], - "outputs": [ - { - "type": "BigUint" - } - ] - }, - { - "name": "getBoostedYieldsFactors", - "mutability": "readonly", - "inputs": [], - "outputs": [ - { - "type": "BoostedYieldsFactors" - } - ] - }, { "docs": [ "Week starts from 1" @@ -632,7 +763,7 @@ ] }, { - "name": "getCurrentClaimProgress", + "name": "getLastActiveWeekForUser", "mutability": "readonly", "inputs": [ { @@ -642,7 +773,7 @@ ], "outputs": [ { - "type": "ClaimProgress" + "type": "u32" } ] }, @@ -661,22 +792,8 @@ ], "outputs": [ { - "type": "Energy" - } - ] - }, - { - "name": "getLastActiveWeekForUser", - "mutability": "readonly", - "inputs": [ - { - "name": "user", - "type": "Address" - } - ], - "outputs": [ - { - "type": "u32" + "type": "optional", + "multi_result": true } ] }, @@ -735,6 +852,32 @@ } ] }, + { + "name": "updateEnergyForUser", + "mutability": "mutable", + "inputs": [ + { + "name": "user", + "type": "Address" + } + ], + "outputs": [] + }, + { + "name": "getCurrentClaimProgress", + "mutability": "readonly", + "inputs": [ + { + "name": "user", + "type": "Address" + } + ], + "outputs": [ + { + "type": "ClaimProgress" + } + ] + }, { "name": "setEnergyFactoryAddress", "onlyOwner": true, @@ -960,30 +1103,14 @@ ] } ], + "esdtAttributes": [], "hasCallback": true, "types": { - "Energy": { - "type": "struct", - "fields": [ - { - "name": "amount", - "type": "BigInt" - }, - { - "name": "last_update_epoch", - "type": "u64" - }, - { - "name": "total_locked_tokens", - "type": "BigUint" - } - ] - }, "BoostedYieldsFactors": { "type": "struct", "fields": [ { - "name": "user_rewards_base_const", + "name": "max_rewards_factor", "type": "BigUint" }, { @@ -1091,6 +1218,23 @@ } ] }, + "Energy": { + "type": "struct", + "fields": [ + { + "name": "amount", + "type": "BigInt" + }, + { + "name": "last_update_epoch", + "type": "u64" + }, + { + "name": "total_locked_tokens", + "type": "BigUint" + } + ] + }, "EnterFarmEvent": { "type": "struct", "fields": [ @@ -1185,18 +1329,10 @@ "name": "reward_per_share", "type": "BigUint" }, - { - "name": "original_entering_epoch", - "type": "u64" - }, { "name": "entering_epoch", "type": "u64" }, - { - "name": "initial_farming_amount", - "type": "BigUint" - }, { "name": "compounded_reward", "type": "BigUint" @@ -1204,6 +1340,10 @@ { "name": "current_farm_amount", "type": "BigUint" + }, + { + "name": "original_owner", + "type": "Address" } ] }, diff --git a/src/common.app.module.ts b/src/common.app.module.ts index 35f3297f2..bef621e43 100644 --- a/src/common.app.module.ts +++ b/src/common.app.module.ts @@ -11,10 +11,32 @@ import { RedisPubSubModule } from './services/redis.pubSub.module'; const loglevel = !!process.env.LOG_LEVEL ? process.env.LOG_LEVEL : 'error'; +const errorSanitizer = winston.format((info) => { + // Sanitize splat args (extra arguments passed to logger.error) + const splat = info[Symbol.for('splat') as any]; + if (Array.isArray(splat)) { + for (let i = 0; i < splat.length; i++) { + if (splat[i] instanceof Error || splat[i]?.stack) { + splat[i] = { + message: splat[i].message, + ...(splat[i].code !== undefined && { code: splat[i].code }), + ...(splat[i].details && { details: splat[i].details }), + }; + } + } + } + // Remove stack trace from the info object itself + if (info.stack) { + delete info.stack; + } + return info; +}); + const logTransports: Transport[] = [ new winston.transports.Console({ format: winston.format.combine( winston.format.timestamp(), + errorSanitizer(), nestWinstonModuleUtilities.format.nestLike('xExchangeService', { colors: true, prettyPrint: true, diff --git a/src/config/shadowfork2.json b/src/config/bon.json similarity index 85% rename from src/config/shadowfork2.json rename to src/config/bon.json index a029755b2..e1fc05f3d 100644 --- a/src/config/shadowfork2.json +++ b/src/config/bon.json @@ -32,7 +32,7 @@ "feesCollector": "erd1qqqqqqqqqqqqqpgqjsnxqprks7qxfwkcg2m2v9hxkrchgm9akp2segrswt", "energyUpdate": "erd1qqqqqqqqqqqqqpgqg48z8qfm028ze6y3d6tamdfaw6vn774tkp2shg5dt5", "tokenUnstake": "erd1qqqqqqqqqqqqqpgqxv0y4p6vvszrknaztatycac77yvsxqrrkp2sghd86c", - "lockedTokenWrapper": "erd1qqqqqqqqqqqqqpgq97fctvqlskzu0str05muew2qyjttp8kfkp2sl9k0gx", + "lockedTokenWrapper": "erd1qqqqqqqqqqqqqpgqu64gygjs5ted4rupaewaszyhaxl9lv7m2jpsw47nzr", "escrow": "erd1qqqqqqqqqqqqqpgqeh4yv09rmyg4xgn5ma03mvm4v5gndu8w2jpsglz3cn", "positionCreator": "erd1qqqqqqqqqqqqqpgq43cyf9yjfy79ey0cax55kenxgpefhayk2jps6zt793", "lockedTokenPositionCreator": "erd1qqqqqqqqqqqqqpgqwtyu7d5qw322smp0kjq789ua0wtz5cfa2jpsu999xr", @@ -87,7 +87,7 @@ }, "v2": { "lockedRewards": [ - "erd1qqqqqqqqqqqqqpgqapxdp9gjxtg60mjwhle3n6h88zch9e7kkp2s8aqhkg", + "erd1qqqqqqqqqqqqqpgqtdc0rzjwmp9qs0h0wj9pjwxnp5vjc9hdkp2swd4dxz", "erd1qqqqqqqqqqqqqpgqv0pz5z3fkz54nml6pkzzdruuf020gqzykp2sya7kkv", "erd1qqqqqqqqqqqqqpgqenvn0s3ldc94q2mlkaqx4arj3zfnvnmakp2sxca2h9", "erd1qqqqqqqqqqqqqpgqrdq6zvepdxg36rey8pmluwur43q4hcx3kp2su4yltq", @@ -105,7 +105,15 @@ "erd1qqqqqqqqqqqqqpgqjgtun0fhl2em5ayukvahm3myltaxc5tz2jpssz8axf", "erd1qqqqqqqqqqqqqpgq4se997u3eyhjmpwaa57lvdgvmyn23yqpx9rsdzja7j", "erd1qqqqqqqqqqqqqpgqhh8lke0kfch0g20jrmskczwq86d23qhex9rs5hm4uk", - "erd1qqqqqqqqqqqqqpgqgjqu7c0mq8a4jd4d43st44gvwhduvqaxkp2s7vsq64" + "erd1qqqqqqqqqqqqqpgqgjqu7c0mq8a4jd4d43st44gvwhduvqaxkp2s7vsq64", + "erd1qqqqqqqqqqqqqpgqzfy62c66hjuu9lm2c9mr4gcver9lmnydkp2st70eq5", + "erd1qqqqqqqqqqqqqpgqgg42sl557vh7rwt600w76pe48u64qngmkp2sl8mrfx", + "erd1qqqqqqqqqqqqqpgqu288dj3qgrelujal5wynsv5zrf7u0hwlkp2se383n7", + "erd1qqqqqqqqqqqqqpgqvymupfsf40v7xgtkcgtzdnstd9x9xfgzkp2s8wnwpz", + "erd1qqqqqqqqqqqqqpgqx6qadfnrgfqkgfmq5nj92j3u2qm2yfs9kp2say42ng" + ], + "deprecated": [ + "erd1qqqqqqqqqqqqqpgqapxdp9gjxtg60mjwhle3n6h88zch9e7kkp2s8aqhkg" ] } }, @@ -117,16 +125,18 @@ "USDC_TOKEN_ID": "USDC-c76f1f", "MAINTENANCE": false, "roundedSwapEnable": { - "USDC-c76f1f": "5000000", + "USDC-c76f1f": "100000", "WEGLD-bd4d79": "100000000000000000", - "MEX-455c57": "1000000000000000000000000" - }, - "trendingScore": { - "MIN_24H_VOLUME": 10000, - "MIN_24H_TRADE_COUNT": 100, - "PRICE_WEIGHT": 0.5, - "VOLUME_WEIGHT": 0.5, - "TRADES_COUNT_WEIGHT": 0 + "MEX-455c57": "100000000000000000000000", + "USDT-f8c08c": "100000", + "WBTC-5349b3": "1000", + "WETH-b4ca29": "100000000000000", + "SEGLD-3ad2d0": "100000000000000000", + "LEGLD-d74da9": "100000000000000000", + "XEGLD-e413ed": "100000000000000000", + "WDAI-9eeb54": "100000000000000000", + "WSDAI-277fee": "100000000000000000", + "USH-111e09": "100000000000000000" } } } diff --git a/src/config/default.json b/src/config/default.json index 1af362f9f..c307dff1e 100644 --- a/src/config/default.json +++ b/src/config/default.json @@ -18,11 +18,15 @@ "MEX-27f4cd": "erd1qqqqqqqqqqqqqpgqxv39e72dt57vcjdyfz6cztw86vuq7nx20n4srlnthr", "WEGLD_USDC": "erd1qqqqqqqqqqqqqpgqq67uv84ma3cekpa55l4l68ajzhq8qm3u0n4s20ecvx", "distributionAddress": "erd1qqqqqqqqqqqqqpgq29s98mhxwyknmxcpdtdx6nm0wkvnkvwe0n4sjpdhyq", - "proxyDexAddress": ["erd1qqqqqqqqqqqqqpgqs8avffeeyx5fg3q04fu4rjstuh7m06sl0n4szj2g8z"], + "proxyDexAddress": [ + "erd1qqqqqqqqqqqqqpgqs8avffeeyx5fg3q04fu4rjstuh7m06sl0n4szj2g8z" + ], "lockedAssetAddress": "erd1qqqqqqqqqqqqqpgqup60nzrkww5ukj7rxxud9txq9fakd36l0n4sthknw2", "metabondingStakingAddress": "erd1qqqqqqqqqqqqqpgq4jvy228nzlcxnwufqzm7hugnv6wl42xj0n4sz7ra7n", "simpleLockEnergy": "erd1qqqqqqqqqqqqqpgq0agdv39w3s7cyn3cll3u93t3adektylz0n4sryxmaj", - "simpleLockAddress": ["erd1qqqqqqqqqqqqqpgq0agdv39w3s7cyn3cll3u93t3adektylz0n4sryxmaj"], + "simpleLockAddress": [ + "erd1qqqqqqqqqqqqqpgq0agdv39w3s7cyn3cll3u93t3adektylz0n4sryxmaj" + ], "wrappingAddress": { "shardID-0": "erd1qqqqqqqqqqqqqpgqd77fnev2sthnczp2lnfx0y5jdycynjfhzzgq6p3rax", "shardID-1": "erd1qqqqqqqqqqqqqpgqhjdqy6rqz3vdqsr3wydvyha9xvw5n75h0n4swc0wnt", @@ -48,8 +52,12 @@ "composableTasks": "erd1qqqqqqqqqqqqqpgq7ykazrzd905zvnlr88dpfw06677lxe9w0n4suz00uh" }, "tokenProviderUSD": "WEGLD-71e90a", - "tokensSupply": ["MEX-27f4cd"], - "cachedTokensPrice": ["MEX-27f4cd"], + "tokensSupply": [ + "MEX-27f4cd" + ], + "cachedTokensPrice": [ + "MEX-27f4cd" + ], "governance": { "oldEnergy": { "cvadratic": [ @@ -425,7 +433,7 @@ "set_minimum_farming_epochs": 20000000, "set_transfer_exec_gas_limit": 20000000, "set_burn_gas_limit": 20000000, - "setPerBlockRewardAmount": 200000000, + "setPerSecondRewardAmount": 200000000, "setMaxApr": 200000000, "setMinUnbondEpochs": 200000000, "setRewardsState": 200000000, @@ -540,7 +548,7 @@ "energyPosition": 15000000 }, "composableTasks": { - "default":10000000 + "default": 10000000 }, "lockedAssetCreate": 5000000, "wrapeGLD": 3000000, @@ -598,6 +606,9 @@ "MAX_PERCENT": 10000, "MAX_PERCENTAGE_PRICE_DISCOVERY": 10000000000000, "BLOCKS_IN_YEAR": 5256000, + "SECONDS_IN_YEAR": 31536000, + "SECONDS_IN_WEEK": 604800, + "SECONDS_IN_DAY": 86400, "SWAP_FEE_PERCENT": 300, "SWAP_FEE_PERCENT_BASE_POINTS": 100000, "FEES_COLLECTOR_CUT": 50000, @@ -637,7 +648,11 @@ ], "slippage": { "DEFAULT_SLIPPAGE": 0.01, - "SLIPPAGE_VALUES": [0.001, 0.005, 0.01], + "SLIPPAGE_VALUES": [ + 0.001, + 0.005, + 0.01 + ], "MAX_SLIPPAGE": 0.05 }, "MIN_SWAP_AMOUNT": 0, @@ -654,11 +669,11 @@ }, "COMPOUND_TRANSACTION_FEE": 0.000365144, "trendingScore": { - "MIN_24H_VOLUME": 10000, - "MIN_24H_TRADE_COUNT": 100, - "PRICE_WEIGHT": 0.5, - "VOLUME_WEIGHT": 0.25, - "TRADES_COUNT_WEIGHT": 0.25 + "MIN_24H_VOLUME": 10000, + "MIN_24H_TRADE_COUNT": 100, + "PRICE_WEIGHT": 0.5, + "VOLUME_WEIGHT": 0.25, + "TRADES_COUNT_WEIGHT": 0.25 }, "AWS_QUERY_CACHE_WARMER_DELAY": 50, "FEES_COLLECTOR_MIN_SWAP_AMOUNT_USD": 10, @@ -678,36 +693,37 @@ "name": "Silver", "minEnergy": "5040000000000000000000000000", "maxEnergy": "50400000000000000000000000000" - }, { "name": "Gold", "minEnergy": "50400000000000000000000000000", "maxEnergy": "504000000000000000000000000000" - }, { "name": "Platinum", "minEnergy": "504000000000000000000000000000", "maxEnergy": "5040000000000000000000000000000" - }, { "name": "Diamond", "minEnergy": "5040000000000000000000000000000" } ], - "cryptoRatesIdentifiers": ["WBTC-5349b3", "WETH-b4ca29", "WEGLD-bd4d79"], + "cryptoRatesIdentifiers": [ + "WBTC-5349b3", + "WETH-b4ca29", + "WEGLD-bd4d79" + ], "complexity": { - "maxComplexity": 3000, - "defaultComplexity": 1, - "collectMetrics": true, - "exposeComplexity": true, - "rejectQueries": false, - "costModifiers": { - "nested": 1.5, - "exponentialBase": 10 - } + "maxComplexity": 3000, + "defaultComplexity": 1, + "collectMetrics": true, + "exposeComplexity": true, + "rejectQueries": false, + "costModifiers": { + "nested": 1.5, + "exponentialBase": 10 + } }, "pushNotifications": { "options": { @@ -728,4 +744,4 @@ "iconUrl": "https://xexchange.com/assets/imgs/mx-logos/xexchange-logo@2x.webp" } } -} +} \ No newline at end of file diff --git a/src/microservices/dex-state/services/compute/farm.compute.service.ts b/src/microservices/dex-state/services/compute/farm.compute.service.ts index 8f16cd56d..2900dd603 100644 --- a/src/microservices/dex-state/services/compute/farm.compute.service.ts +++ b/src/microservices/dex-state/services/compute/farm.compute.service.ts @@ -41,8 +41,8 @@ export class FarmComputeService { farm.farmTokenPriceUSD, ).toFixed(); - const totalRewardsPerYear = new BigNumber(farm.perBlockRewards) - .multipliedBy(constantsConfig.BLOCKS_IN_YEAR) + const totalRewardsPerYear = new BigNumber(farm.perSecondRewards) + .multipliedBy(constantsConfig.SECONDS_IN_YEAR) .toFixed(); const totalRewardsPerYearUSD = computeValueUSD( @@ -73,10 +73,9 @@ export class FarmComputeService { } calculateBoostedRewardsPerWeek(farm: FarmModelV2): string { - const blocksInWeek = constantsConfig.BLOCKS_PER_WEEK; const totalRewardsPerWeek = new BigNumber( - farm.perBlockRewards, - ).multipliedBy(blocksInWeek); + farm.perSecondRewards, + ).multipliedBy(constantsConfig.SECONDS_IN_WEEK); return totalRewardsPerWeek .multipliedBy(farm.boostedYieldsRewardsPercenatage) diff --git a/src/microservices/dex-state/services/compute/staking.compute.service.ts b/src/microservices/dex-state/services/compute/staking.compute.service.ts index 9799f4f10..554c3cc89 100644 --- a/src/microservices/dex-state/services/compute/staking.compute.service.ts +++ b/src/microservices/dex-state/services/compute/staking.compute.service.ts @@ -13,7 +13,7 @@ import { StateStore } from '../state.store'; @Injectable() export class StakingComputeService { - constructor(private readonly stateStore: StateStore) {} + constructor(private readonly stateStore: StateStore) { } computeMissingStakingProxyFields( stakingProxy: StakingProxyModel, @@ -47,29 +47,27 @@ export class StakingComputeService { ); stakingFarm.isProducingRewards = - !stakingFarm.produceRewardsEnabled || - new BigNumber(stakingFarm.accumulatedRewards).isEqualTo( + stakingFarm.produceRewardsEnabled && + !new BigNumber(stakingFarm.accumulatedRewards).isEqualTo( stakingFarm.rewardCapacity, - ) - ? false - : true; + ); - stakingFarm.rewardsPerBlockAPRBound = - this.computeRewardsPerBlockAPRBound( + stakingFarm.rewardsPerSecondAPRBound = + this.computeRewardsPerSecondAPRBound( stakingFarm.farmTokenSupply, stakingFarm.annualPercentageRewards, ); stakingFarm.rewardsRemainingDays = this.computeRewardsRemainingDaysBase( - stakingFarm.perBlockRewards, + stakingFarm.perSecondRewards, stakingFarm.rewardCapacity, stakingFarm.accumulatedRewards, - stakingFarm.rewardsPerBlockAPRBound, + stakingFarm.rewardsPerSecondAPRBound, ); stakingFarm.rewardsRemainingDaysUncapped = this.computeRewardsRemainingDaysBase( - stakingFarm.perBlockRewards, + stakingFarm.perSecondRewards, stakingFarm.rewardCapacity, stakingFarm.accumulatedRewards, ); @@ -83,19 +81,19 @@ export class StakingComputeService { ).toFixed(); const rewardsAPRBounded = new BigNumber( - stakingFarm.rewardsPerBlockAPRBound, - ).multipliedBy(constantsConfig.BLOCKS_IN_YEAR); + stakingFarm.rewardsPerSecondAPRBound, + ).multipliedBy(constantsConfig.SECONDS_IN_YEAR); stakingFarm.apr = this.computeStakeFarmAPR( stakingFarm.isProducingRewards, - stakingFarm.perBlockRewards, + stakingFarm.perSecondRewards, stakingFarm.farmTokenSupply, stakingFarm.annualPercentageRewards, rewardsAPRBounded, ); stakingFarm.aprUncapped = this.computeStakeFarmUncappedAPR( - stakingFarm.perBlockRewards, + stakingFarm.perSecondRewards, stakingFarm.farmTokenSupply, stakingFarm.isProducingRewards, ); @@ -123,7 +121,7 @@ export class StakingComputeService { computeStakeFarmAPR( isProducingRewards: boolean, - perBlockRewardAmount: string, + perSecondRewardAmount: string, farmTokenSupply: string, annualPercentageRewards: string, rewardsAPRBounded: BigNumber, @@ -132,20 +130,20 @@ export class StakingComputeService { return '0'; } - const rewardsUnboundedBig = new BigNumber(perBlockRewardAmount).times( - constantsConfig.BLOCKS_IN_YEAR, + const rewardsUnboundedBig = new BigNumber(perSecondRewardAmount).times( + constantsConfig.SECONDS_IN_YEAR, ); const stakedValueBig = new BigNumber(farmTokenSupply); return rewardsUnboundedBig.isLessThan(rewardsAPRBounded.integerValue()) ? rewardsUnboundedBig.dividedBy(stakedValueBig).toFixed() : new BigNumber(annualPercentageRewards) - .dividedBy(constantsConfig.MAX_PERCENT) - .toFixed(); + .dividedBy(constantsConfig.MAX_PERCENT) + .toFixed(); } computeStakeFarmUncappedAPR( - perBlockRewardAmount: string, + perSecondRewardAmount: string, farmTokenSupply: string, isProducingRewards: boolean, ): string { @@ -154,8 +152,8 @@ export class StakingComputeService { } const rewardsUnboundedBig = new BigNumber( - perBlockRewardAmount, - ).multipliedBy(constantsConfig.BLOCKS_IN_YEAR); + perSecondRewardAmount, + ).multipliedBy(constantsConfig.SECONDS_IN_YEAR); return rewardsUnboundedBig.dividedBy(farmTokenSupply).toFixed(); } @@ -192,38 +190,35 @@ export class StakingComputeService { return bnRawMaxBoostedApr.toFixed(); } - computeRewardsPerBlockAPRBound( + computeRewardsPerSecondAPRBound( farmTokenSupply: string, annualPercentageRewards: string, ): string { return new BigNumber(farmTokenSupply) .multipliedBy(annualPercentageRewards) .dividedBy(constantsConfig.MAX_PERCENT) - .dividedBy(constantsConfig.BLOCKS_IN_YEAR) + .dividedBy(constantsConfig.SECONDS_IN_YEAR) .toFixed(); } computeRewardsRemainingDaysBase( - perBlockRewardAmount: string, + perSecondRewardAmount: string, rewardsCapacity: string, accumulatedRewards: string, - extraRewardsAPRBoundedPerBlock?: string, + extraRewardsAPRBoundedPerSecond?: string, ): number { - const perBlockRewards = extraRewardsAPRBoundedPerBlock + const perSecondRewards = extraRewardsAPRBoundedPerSecond ? BigNumber.min( - extraRewardsAPRBoundedPerBlock, - perBlockRewardAmount, - ) - : new BigNumber(perBlockRewardAmount); - - // 10 blocks per minute * 60 minutes per hour * 24 hours per day - const blocksInDay = 10 * 60 * 24; + extraRewardsAPRBoundedPerSecond, + perSecondRewardAmount, + ) + : new BigNumber(perSecondRewardAmount); return parseFloat( new BigNumber(rewardsCapacity) .minus(accumulatedRewards) - .dividedBy(perBlockRewards) - .dividedBy(blocksInDay) + .dividedBy(perSecondRewards) + .dividedBy(constantsConfig.SECONDS_IN_DAY) .toFixed(2), ); } diff --git a/src/microservices/dex-state/services/state.initialization.service.ts b/src/microservices/dex-state/services/state.initialization.service.ts index 7861cd4dc..ab8e50fee 100644 --- a/src/microservices/dex-state/services/state.initialization.service.ts +++ b/src/microservices/dex-state/services/state.initialization.service.ts @@ -31,6 +31,7 @@ export class StateInitializationService { ) {} initState(request: InitStateRequest): InitStateResponse { + console.log('Initialize state store in gRPC'); const { tokens, pairs, diff --git a/src/microservices/dex-state/services/state.store.ts b/src/microservices/dex-state/services/state.store.ts index c3208023e..077ff95cd 100644 --- a/src/microservices/dex-state/services/state.store.ts +++ b/src/microservices/dex-state/services/state.store.ts @@ -136,6 +136,7 @@ export class StateStore { } setInitialized(initialized: boolean): void { + console.log(`DEX STATE STORE INITIALIZED: ${initialized}`); this._initialized = initialized; } diff --git a/src/modules/analytics/services/analytics.compute.service.ts b/src/modules/analytics/services/analytics.compute.service.ts index 597ba27f9..26e7459c4 100644 --- a/src/modules/analytics/services/analytics.compute.service.ts +++ b/src/modules/analytics/services/analytics.compute.service.ts @@ -1,11 +1,8 @@ import { Injectable } from '@nestjs/common'; import { BigNumber } from 'bignumber.js'; import { constantsConfig, scAddress } from 'src/config'; -import { - FarmRewardType, - FarmVersion, -} from 'src/modules/farm/models/farm.model'; -import { farmsAddresses, farmType, farmVersion } from 'src/utils/farm.utils'; +import { FarmVersion } from 'src/modules/farm/models/farm.model'; +import { farmsAddresses } from 'src/utils/farm.utils'; import { FarmComputeFactory } from 'src/modules/farm/farm.compute.factory'; import { AnalyticsQueryService } from 'src/services/analytics/services/analytics.query.service'; import { RemoteConfigGetterService } from '../../remote-config/remote-config.getter.service'; @@ -17,7 +14,6 @@ import { RouterAbiService } from 'src/modules/router/services/router.abi.service import { StakingComputeService } from 'src/modules/staking/services/staking.compute.service'; import { GetOrSetCache } from 'src/helpers/decorators/caching.decorator'; import { Constants } from '@multiversx/sdk-nestjs-common'; -import { FarmAbiFactory } from 'src/modules/farm/farm.abi.factory'; import { TokenComputeService } from 'src/modules/tokens/services/token.compute.service'; import { TokenService } from 'src/modules/tokens/services/token.service'; import { ErrorLoggerAsync } from '@multiversx/sdk-nestjs-common'; @@ -29,12 +25,13 @@ import { SwapEvent } from '@multiversx/sdk-exchange'; import { convertEventTopicsAndDataToBase64 } from 'src/utils/elastic.search.utils'; import { ElasticSearchEventsService } from 'src/services/elastic-search/services/es.events.service'; import { determineBaseAndQuoteTokens } from 'src/utils/pair.utils'; +import { FarmAbiServiceV2 } from 'src/modules/farm/v2/services/farm.v2.abi.service'; @Injectable() export class AnalyticsComputeService { constructor( private readonly routerAbi: RouterAbiService, - private readonly farmAbi: FarmAbiFactory, + private readonly farmAbiV2: FarmAbiServiceV2, private readonly farmCompute: FarmComputeFactory, private readonly pairAbi: PairAbiService, private readonly pairCompute: PairComputeService, @@ -172,29 +169,22 @@ export class AnalyticsComputeService { } async computeTotalAggregatedRewards(days: number): Promise { - const addresses: string[] = farmsAddresses(); + const addresses: string[] = farmsAddresses([FarmVersion.V2]); const promises = addresses.map(async (farmAddress) => { - if ( - farmType(farmAddress) === FarmRewardType.CUSTOM_REWARDS || - farmVersion(farmAddress) === FarmVersion.V1_2 - ) { - return '0'; - } - return this.farmAbi - .useAbi(farmAddress) - .rewardsPerBlock(farmAddress); + return this.farmAbiV2.rewardsPerSecond(farmAddress); }); - const farmsRewardsPerBlock = await Promise.all(promises); - const blocksNumber = (days * 24 * 60 * 60) / 6; + const farmsRewardsPerSecond = await Promise.all(promises); + const seconds = days * 24 * 60 * 60; let totalAggregatedRewards = new BigNumber(0); - for (const rewardsPerBlock of farmsRewardsPerBlock) { + for (const rewardsPerSecond of farmsRewardsPerSecond) { const aggregatedRewards = new BigNumber( - rewardsPerBlock, - ).multipliedBy(blocksNumber); + rewardsPerSecond, + ).multipliedBy(seconds); totalAggregatedRewards = totalAggregatedRewards.plus(aggregatedRewards); } + return totalAggregatedRewards.toFixed(); } diff --git a/src/modules/farm/mocks/farm.constants.ts b/src/modules/farm/mocks/farm.constants.ts index e54a42958..e0b516f4f 100644 --- a/src/modules/farm/mocks/farm.constants.ts +++ b/src/modules/farm/mocks/farm.constants.ts @@ -59,6 +59,7 @@ export const farms = [ farmTotalSupply: '1000000000000000000', farmingTokenReserve: '1000000000000000000', rewardsPerBlock: '2000000000000000000', + rewardsPerSecond: '2000000000000000000', rewardPerShare: '0', }, ]; diff --git a/src/modules/farm/mocks/farm.v2.abi.service.mock.ts b/src/modules/farm/mocks/farm.v2.abi.service.mock.ts index 5796882bb..3efccaa14 100644 --- a/src/modules/farm/mocks/farm.v2.abi.service.mock.ts +++ b/src/modules/farm/mocks/farm.v2.abi.service.mock.ts @@ -1,13 +1,13 @@ import { FarmAbiServiceV2 } from '../v2/services/farm.v2.abi.service'; import { FarmAbiServiceMock } from './farm.abi.service.mock'; +import { farms } from './farm.constants'; import { IFarmAbiServiceV2 } from '../v2/services/interfaces'; import { BoostedYieldsFactors } from '../models/farm.v2.model'; import BigNumber from 'bignumber.js'; export class FarmAbiServiceMockV2 extends FarmAbiServiceMock - implements IFarmAbiServiceV2 -{ + implements IFarmAbiServiceV2 { async lastUndistributedBoostedRewardsCollectWeek( farmAddress: string, ): Promise { @@ -80,6 +80,14 @@ export class FarmAbiServiceMockV2 ): Promise { return '2'; } + + async rewardsPerSecond(farmAddress: string): Promise { + return farms.find((f) => f.address === farmAddress).rewardsPerSecond; + } + + async lastRewardTimestamp(farmAddress: string): Promise { + return 1; + } } export const FarmAbiServiceProviderV2 = { diff --git a/src/modules/farm/models/farm.v2.model.ts b/src/modules/farm/models/farm.v2.model.ts index 50b4db698..a71dcdd17 100644 --- a/src/modules/farm/models/farm.v2.model.ts +++ b/src/modules/farm/models/farm.v2.model.ts @@ -44,7 +44,7 @@ export class FarmModelV2 { @Field() produceRewardsEnabled: boolean; @Field() - perBlockRewards: string; + perSecondRewards: string; @Field() farmTokenSupply: string; @Field(() => Int) @@ -56,7 +56,7 @@ export class FarmModelV2 { @Field() rewardReserve: string; @Field(() => Int) - lastRewardBlockNonce: number; + lastRewardTimestamp: number; @Field() divisionSafetyConstant: string; @Field() diff --git a/src/modules/farm/specs/farm.service.spec.ts b/src/modules/farm/specs/farm.service.spec.ts index 9c9156825..b0aebf696 100644 --- a/src/modules/farm/specs/farm.service.spec.ts +++ b/src/modules/farm/specs/farm.service.spec.ts @@ -176,7 +176,7 @@ describe('FarmService', () => { farmTokenCollection: 'EGLDMEXFL-ghijkl', farmingTokenId: 'EGLDMEXLP-abcdef', farmTokenSupply: '1000000000000000000', - perBlockRewards: '2000000000000000000', + perSecondRewards: '2000000000000000000', rewardPerShare: '0', }, ]); diff --git a/src/modules/farm/specs/farm.v2.compute.service.spec.ts b/src/modules/farm/specs/farm.v2.compute.service.spec.ts index cf0c5c529..3b6b05fe9 100644 --- a/src/modules/farm/specs/farm.v2.compute.service.spec.ts +++ b/src/modules/farm/specs/farm.v2.compute.service.spec.ts @@ -116,7 +116,7 @@ describe('FarmServiceV2', () => { }), ]); jest.spyOn(farmAbi, 'farmTokenSupply').mockResolvedValue('2'); - jest.spyOn(farmAbi, 'rewardsPerBlock').mockResolvedValue( + jest.spyOn(farmAbi, 'rewardsPerSecond').mockResolvedValue( '1000000000000000000', ); jest.spyOn(farmAbi, 'userTotalFarmPosition').mockResolvedValue('2'); diff --git a/src/modules/farm/v2/services/farm.v2.abi.service.ts b/src/modules/farm/v2/services/farm.v2.abi.service.ts index 063f3c650..762209d18 100644 --- a/src/modules/farm/v2/services/farm.v2.abi.service.ts +++ b/src/modules/farm/v2/services/farm.v2.abi.service.ts @@ -34,8 +34,7 @@ import { CacheService } from 'src/services/caching/cache.service'; @Injectable() export class FarmAbiServiceV2 extends FarmAbiService - implements IFarmAbiServiceV2 -{ + implements IFarmAbiServiceV2 { constructor( protected readonly mxProxy: MXProxyService, protected readonly gatewayService: MXGatewayService, @@ -45,6 +44,58 @@ export class FarmAbiServiceV2 super(mxProxy, gatewayService, mxApi, cacheService); } + async rewardsPerBlock(farmAddress: string): Promise { + throw new Error( + `rewardsPerBlock() is not supported on V2 farms. Use rewardsPerSecond() instead. Farm: ${farmAddress}`, + ); + } + + async lastRewardBlockNonce(farmAddress: string): Promise { + throw new Error( + `lastRewardBlockNonce() is not supported on V2 farms. Use lastRewardTimestamp() instead. Farm: ${farmAddress}`, + ); + } + + @ErrorLoggerAsync({ + logArgs: true, + }) + @GetOrSetCache({ + baseKey: 'farm', + remoteTtl: CacheTtlInfo.ContractState.remoteTtl, + localTtl: CacheTtlInfo.ContractState.localTtl, + }) + async rewardsPerSecond(farmAddress: string): Promise { + return this.getRewardsPerSecondRaw(farmAddress); + } + + async getRewardsPerSecondRaw(farmAddress: string): Promise { + const contract = await this.mxProxy.getFarmSmartContract(farmAddress); + const interaction: Interaction = + contract.methodsExplicit.getPerSecondRewardAmount(); + const response = await this.getGenericData(interaction); + return response.firstValue.valueOf().toFixed(); + } + + @ErrorLoggerAsync({ + logArgs: true, + }) + @GetOrSetCache({ + baseKey: 'farm', + remoteTtl: CacheTtlInfo.ContractInfo.remoteTtl, + localTtl: CacheTtlInfo.ContractInfo.localTtl, + }) + async lastRewardTimestamp(farmAddress: string): Promise { + return this.getLastRewardTimestampRaw(farmAddress); + } + + async getLastRewardTimestampRaw(farmAddress: string): Promise { + const contract = await this.mxProxy.getFarmSmartContract(farmAddress); + const interaction: Interaction = + contract.methodsExplicit.getLastRewardTimestamp(); + const response = await this.getGenericData(interaction); + return response.firstValue.valueOf().toNumber(); + } + async getLastErrorMessageRaw(farmAddress: string): Promise { return undefined; } diff --git a/src/modules/farm/v2/services/farm.v2.compute.service.ts b/src/modules/farm/v2/services/farm.v2.compute.service.ts index 09a8dbd76..ffd124d69 100644 --- a/src/modules/farm/v2/services/farm.v2.compute.service.ts +++ b/src/modules/farm/v2/services/farm.v2.compute.service.ts @@ -26,8 +26,7 @@ import { EnergyType } from '@multiversx/sdk-exchange'; @Injectable() export class FarmComputeServiceV2 extends FarmComputeService - implements IFarmComputeServiceV2 -{ + implements IFarmComputeServiceV2 { constructor( protected readonly farmAbi: FarmAbiServiceV2, @Inject(forwardRef(() => FarmServiceV2)) @@ -98,13 +97,45 @@ export class FarmComputeServiceV2 .toFixed(); } + async computeAnualRewardsUSD(farmAddress: string): Promise { + const farmedToken = await this.farmService.getFarmedToken(farmAddress); + + const [farmedTokenPriceUSD, rewardsPerSecond] = await Promise.all([ + this.tokenCompute.computeTokenPriceDerivedUSD( + farmedToken.identifier, + ), + this.farmAbi.rewardsPerSecond(farmAddress), + ]); + + const totalRewardsPerYear = new BigNumber(rewardsPerSecond).multipliedBy( + constantsConfig.SECONDS_IN_YEAR, + ); + + return computeValueUSD( + totalRewardsPerYear.toFixed(), + farmedToken.decimals, + farmedTokenPriceUSD, + ).toFixed(); + } + async computeMintedRewards(farmAddress: string): Promise { - const [toBeMinted, boostedYieldsRewardsPercenatage] = await Promise.all( - [ - super.computeMintedRewards(farmAddress), + const [rewardsPerSecond, lastRewardTimestamp, produceRewardsEnabled, boostedYieldsRewardsPercenatage] = + await Promise.all([ + this.farmAbi.rewardsPerSecond(farmAddress), + this.farmAbi.lastRewardTimestamp(farmAddress), + this.farmAbi.produceRewardsEnabled(farmAddress), this.farmAbi.boostedYieldsRewardsPercenatage(farmAddress), - ], - ); + ]); + + const currentTimestamp = Math.floor(Date.now() / 1000); + const rewardsPerSecondBig = new BigNumber(rewardsPerSecond); + let toBeMinted = new BigNumber(0); + + if (currentTimestamp > lastRewardTimestamp && produceRewardsEnabled) { + toBeMinted = rewardsPerSecondBig.times( + currentTimestamp - lastRewardTimestamp, + ); + } return this.computeBaseRewards( toBeMinted, @@ -112,21 +143,21 @@ export class FarmComputeServiceV2 ); } - computeRewardsIncrease(farm: FarmModelV2, currentNonce: number): BigNumber { - const currentBlockBig = new BigNumber(currentNonce); - const lastRewardBlockNonceBig = new BigNumber( - farm.lastRewardBlockNonce, + computeRewardsIncrease(farm: FarmModelV2, currentTimestamp: number): BigNumber { + const currentTimestampBig = new BigNumber(currentTimestamp); + const lastRewardTimestampBig = new BigNumber( + farm.lastRewardTimestamp, ); - const perBlockRewardAmountBig = new BigNumber(farm.perBlockRewards); + const perSecondRewardAmountBig = new BigNumber(farm.perSecondRewards); let toBeMinted = new BigNumber(0); if ( - currentNonce > farm.lastRewardBlockNonce && + currentTimestamp > farm.lastRewardTimestamp && farm.produceRewardsEnabled ) { - toBeMinted = perBlockRewardAmountBig.times( - currentBlockBig.minus(lastRewardBlockNonceBig), + toBeMinted = perSecondRewardAmountBig.times( + currentTimestampBig.minus(lastRewardTimestampBig), ); } @@ -140,9 +171,9 @@ export class FarmComputeServiceV2 farm: FarmModelV2, positon: CalculateRewardsArgs, rewardPerShare: string, - currentNonce: number, + currentTimestamp: number, ): BigNumber { - const rewardIncrease = this.computeRewardsIncrease(farm, currentNonce); + const rewardIncrease = this.computeRewardsIncrease(farm, currentTimestamp); const amountBig = new BigNumber(positon.liquidity); const divisionSafetyConstantBig = new BigNumber( @@ -612,15 +643,14 @@ export class FarmComputeServiceV2 } async computeBoostedRewardsPerWeek(scAddress: string): Promise { - const [rewardsPerBlock, boostedYieldsRewardsPercentage] = + const [rewardsPerSecond, boostedYieldsRewardsPercentage] = await Promise.all([ - this.farmAbi.rewardsPerBlock(scAddress), + this.farmAbi.rewardsPerSecond(scAddress), this.farmAbi.boostedYieldsRewardsPercenatage(scAddress), ]); - const blocksInWeek = 14440 * 7; - const totalRewardsPerWeek = new BigNumber(rewardsPerBlock).multipliedBy( - blocksInWeek, + const totalRewardsPerWeek = new BigNumber(rewardsPerSecond).multipliedBy( + constantsConfig.SECONDS_IN_WEEK, ); return totalRewardsPerWeek diff --git a/src/modules/farm/v2/services/farm.v2.service.ts b/src/modules/farm/v2/services/farm.v2.service.ts index db146a5f1..6de91609f 100644 --- a/src/modules/farm/v2/services/farm.v2.service.ts +++ b/src/modules/farm/v2/services/farm.v2.service.ts @@ -66,7 +66,7 @@ export class FarmServiceV2 extends FarmServiceBase { boostedPositions.set(position.farmAddress, boostedPosition); }); - const [farms, currentEpoch, currentNonce] = await Promise.all([ + const [farms, currentEpoch, currentTimestamp] = await Promise.all([ this.farmsState.getFarms( positions.map((position) => position.farmAddress), [ @@ -78,8 +78,8 @@ export class FarmServiceV2 extends FarmServiceBase { 'boosterRewards', 'boostedYieldsFactors', 'boostedYieldsRewardsPercenatage', - 'lastRewardBlockNonce', - 'perBlockRewards', + 'lastRewardTimestamp', + 'perSecondRewards', 'rewardPerShare', 'produceRewardsEnabled', 'farmTokenSupply', @@ -87,7 +87,7 @@ export class FarmServiceV2 extends FarmServiceBase { ], ), this.contextGetter.getCurrentEpoch(), - this.contextGetter.getShardCurrentBlockNonce(1), + Promise.resolve(Math.floor(Date.now() / 1000)), ]); return Promise.all( @@ -95,7 +95,7 @@ export class FarmServiceV2 extends FarmServiceBase { this.computeRewardsForPosition( farms[index], currentEpoch, - currentNonce, + currentTimestamp, position, boostedPositions.get(position.farmAddress) === position, ), @@ -106,7 +106,7 @@ export class FarmServiceV2 extends FarmServiceBase { async computeRewardsForPosition( farm: FarmModelV2, currentEpoch: number, - currentNonce: number, + currentTimestamp: number, position: CalculateRewardsArgs, computeBoosted = false, ): Promise { @@ -123,7 +123,7 @@ export class FarmServiceV2 extends FarmServiceBase { farm, position, farmTokenAttributes.rewardPerShare, - currentNonce, + currentTimestamp, ); } @@ -193,7 +193,7 @@ export class FarmServiceV2 extends FarmServiceBase { const remainingFarmingEpochs = Math.max( 0, farm.minimumFarmingEpochs - - (currentEpoch - farmTokenAttributes.enteringEpoch), + (currentEpoch - farmTokenAttributes.enteringEpoch), ); return new RewardsModel({ diff --git a/src/modules/farm/v2/services/farm.v2.setter.service.ts b/src/modules/farm/v2/services/farm.v2.setter.service.ts index 5de58ff45..e5c2644cb 100644 --- a/src/modules/farm/v2/services/farm.v2.setter.service.ts +++ b/src/modules/farm/v2/services/farm.v2.setter.service.ts @@ -46,4 +46,28 @@ export class FarmSetterServiceV2 extends FarmSetterService { CacheTtlInfo.ContractInfo.localTtl, ); } + + async setRewardsPerSecond( + farmAddress: string, + value: string, + ): Promise { + return await this.setDataOrUpdateTtl( + this.getCacheKey('rewardsPerSecond', farmAddress), + value, + CacheTtlInfo.ContractState.remoteTtl, + CacheTtlInfo.ContractState.localTtl, + ); + } + + async setLastRewardTimestamp( + farmAddress: string, + value: number, + ): Promise { + return await this.setData( + this.getCacheKey('lastRewardTimestamp', farmAddress), + value, + CacheTtlInfo.ContractInfo.remoteTtl, + CacheTtlInfo.ContractInfo.localTtl, + ); + } } diff --git a/src/modules/farm/v2/services/interfaces.ts b/src/modules/farm/v2/services/interfaces.ts index 0436e3da4..e9b8f0ddb 100644 --- a/src/modules/farm/v2/services/interfaces.ts +++ b/src/modules/farm/v2/services/interfaces.ts @@ -5,6 +5,8 @@ import { import { BoostedYieldsFactors } from '../../models/farm.v2.model'; export interface IFarmAbiServiceV2 extends IFarmAbiService { + rewardsPerSecond(farmAddress: string): Promise; + lastRewardTimestamp(farmAddress: string): Promise; boostedYieldsRewardsPercenatage(farmAddress: string): Promise; lockingScAddress(farmAddress: string): Promise; lockEpochs(farmAddress: string): Promise; diff --git a/src/modules/pair/services/pair.abi.service.ts b/src/modules/pair/services/pair.abi.service.ts index 0a89f3ebe..dc118b25b 100644 --- a/src/modules/pair/services/pair.abi.service.ts +++ b/src/modules/pair/services/pair.abi.service.ts @@ -103,7 +103,9 @@ export class PairAbiService contract.methodsExplicit.getLpTokenIdentifier(); const response = await this.getGenericData(interaction); - const lpTokenID = response.firstValue.valueOf().toString(); + const lpTokenID = response.firstValue + ? response.firstValue.valueOf().toString() + : ''; return lpTokenID === mxConfig.EGLDIdentifier || lpTokenID === '' ? undefined : lpTokenID; diff --git a/src/modules/staking/mocks/staking.abi.service.mock.ts b/src/modules/staking/mocks/staking.abi.service.mock.ts index bb2ec47af..73e64bfd6 100644 --- a/src/modules/staking/mocks/staking.abi.service.mock.ts +++ b/src/modules/staking/mocks/staking.abi.service.mock.ts @@ -31,10 +31,10 @@ export class StakingAbiServiceMock implements IStakingAbiService { minUnbondEpochs(stakeAddress: string): Promise { throw new Error('Method not implemented.'); } - async perBlockRewardsAmount(stakeAddress: string): Promise { + async perSecondRewardsAmount(stakeAddress: string): Promise { return new BigNumber(500000000).toFixed(); } - async lastRewardBlockNonce(stakeAddress: string): Promise { + async lastRewardTimestamp(stakeAddress: string): Promise { return new BigNumber(100).toNumber(); } async divisionSafetyConstant(stakeAddress: string): Promise { diff --git a/src/modules/staking/models/staking.model.ts b/src/modules/staking/models/staking.model.ts index a4dad4199..d0df4032a 100644 --- a/src/modules/staking/models/staking.model.ts +++ b/src/modules/staking/models/staking.model.ts @@ -45,13 +45,13 @@ export class StakingModel { boostedApr: string; baseApr: string; maxBoostedApr: string; - rewardsPerBlockAPRBound: string; + rewardsPerSecondAPRBound: string; @Field(() => Int) minUnboundEpochs: number; @Field() - perBlockRewards: string; + perSecondRewards: string; @Field(() => Int) - lastRewardBlockNonce: number; + lastRewardTimestamp: number; @Field() rewardsRemainingDays: number; @Field() diff --git a/src/modules/staking/services/interfaces.ts b/src/modules/staking/services/interfaces.ts index 754232859..87e5fcc0c 100644 --- a/src/modules/staking/services/interfaces.ts +++ b/src/modules/staking/services/interfaces.ts @@ -12,8 +12,8 @@ export interface IStakingAbiService { annualPercentageRewards(stakeAddress: string): Promise; minUnbondEpochs(stakeAddress: string): Promise; - perBlockRewardsAmount(stakeAddress: string): Promise; - lastRewardBlockNonce(stakeAddress: string): Promise; + perSecondRewardsAmount(stakeAddress: string): Promise; + lastRewardTimestamp(stakeAddress: string): Promise; divisionSafetyConstant(stakeAddress: string): Promise; produceRewardsEnabled(stakeAddress: string): Promise; state(stakeAddress: string): Promise; diff --git a/src/modules/staking/services/staking.abi.service.ts b/src/modules/staking/services/staking.abi.service.ts index 5c24cfbd8..94f7615b7 100644 --- a/src/modules/staking/services/staking.abi.service.ts +++ b/src/modules/staking/services/staking.abi.service.ts @@ -26,8 +26,7 @@ import { getAllKeys } from 'src/utils/get.many.utils'; @Injectable() export class StakingAbiService extends GenericAbiService - implements IStakingAbiService -{ + implements IStakingAbiService { constructor( protected readonly mxProxy: MXProxyService, private readonly gatewayService: MXGatewayService, @@ -285,16 +284,16 @@ export class StakingAbiService remoteTtl: CacheTtlInfo.ContractState.remoteTtl, localTtl: CacheTtlInfo.ContractState.localTtl, }) - async perBlockRewardsAmount(stakeAddress: string): Promise { - return this.getPerBlockRewardsAmountRaw(stakeAddress); + async perSecondRewardsAmount(stakeAddress: string): Promise { + return this.getPerSecondRewardsAmountRaw(stakeAddress); } - async getPerBlockRewardsAmountRaw(stakeAddress: string): Promise { + async getPerSecondRewardsAmountRaw(stakeAddress: string): Promise { const contract = await this.mxProxy.getStakingSmartContract( stakeAddress, ); const interaction: Interaction = - contract.methodsExplicit.getPerBlockRewardAmount(); + contract.methodsExplicit.getPerSecondRewardAmount(); const response = await this.getGenericData(interaction); return response.firstValue.valueOf().toFixed(); } @@ -307,18 +306,18 @@ export class StakingAbiService remoteTtl: CacheTtlInfo.ContractState.remoteTtl, localTtl: CacheTtlInfo.ContractState.localTtl, }) - async lastRewardBlockNonce(stakeAddress: string): Promise { - return this.getLastRewardBlockNonceRaw(stakeAddress); + async lastRewardTimestamp(stakeAddress: string): Promise { + return this.getLastRewardTimestampRaw(stakeAddress); } - async getLastRewardBlockNonceRaw(stakeAddress: string): Promise { + async getLastRewardTimestampRaw(stakeAddress: string): Promise { const contract = await this.mxProxy.getStakingSmartContract( stakeAddress, ); const interaction: Interaction = - contract.methodsExplicit.getLastRewardBlockNonce(); + contract.methodsExplicit.getLastRewardTimestamp(); const response = await this.getGenericData(interaction); - return response.firstValue.valueOf().toFixed(); + return response.firstValue.valueOf().toNumber(); } @ErrorLoggerAsync({ diff --git a/src/modules/staking/services/staking.compute.service.ts b/src/modules/staking/services/staking.compute.service.ts index 257bca3f8..c7855610f 100644 --- a/src/modules/staking/services/staking.compute.service.ts +++ b/src/modules/staking/services/staking.compute.service.ts @@ -38,11 +38,11 @@ export class StakingComputeService { stakingFarm: StakingModel, liquidity: string, decodedAttributes: StakingTokenAttributesModel, - currentNonce: number, + currentTimestamp: number, ): BigNumber { const futureRewardsPerShare = this.computeFutureRewardsPerShare( stakingFarm, - currentNonce, + currentTimestamp, ); const amountBig = new BigNumber(liquidity); @@ -61,11 +61,11 @@ export class StakingComputeService { computeFutureRewardsPerShare( stakingFarm: StakingModel, - currentNonce: number, + currentTimestamp: number, ): BigNumber { let extraRewards = this.computeExtraRewardsSinceLastAllocation( stakingFarm, - currentNonce, + currentTimestamp, ); const farmRewardPerShareBig = new BigNumber(stakingFarm.rewardPerShare); @@ -97,26 +97,27 @@ export class StakingComputeService { computeExtraRewardsSinceLastAllocation( stakingFarm: StakingModel, - currentNonce: number, + currentTimestamp: number, ): BigNumber { - const currentBlockBig = new BigNumber(currentNonce); - const lastRewardBlockNonceBig = new BigNumber( - stakingFarm.lastRewardBlockNonce, + const currentTimestampBig = new BigNumber(currentTimestamp); + const lastRewardTimestampBig = new BigNumber( + stakingFarm.lastRewardTimestamp, ); - const perBlockRewardAmountBig = new BigNumber( - stakingFarm.perBlockRewards, + const perSecondRewardAmountBig = new BigNumber( + stakingFarm.perSecondRewards, ); - const blockDifferenceBig = currentBlockBig.minus( - lastRewardBlockNonceBig, + const timestampDifferenceBig = currentTimestampBig.minus( + lastRewardTimestampBig, ); if ( - currentNonce > stakingFarm.lastRewardBlockNonce && + currentTimestamp > stakingFarm.lastRewardTimestamp && stakingFarm.produceRewardsEnabled ) { - const extraRewardsUnbounded = - perBlockRewardAmountBig.times(blockDifferenceBig); - const extraRewardsBounded = blockDifferenceBig.multipliedBy( - stakingFarm.rewardsPerBlockAPRBound, + const extraRewardsUnbounded = perSecondRewardAmountBig.times( + timestampDifferenceBig, + ); + const extraRewardsBounded = timestampDifferenceBig.multipliedBy( + stakingFarm.rewardsPerSecondAPRBound, ); return extraRewardsUnbounded.isLessThan(extraRewardsBounded) @@ -129,15 +130,17 @@ export class StakingComputeService { async computeExtraRewardsBounded( stakeAddress: string, - blockDifferenceBig: BigNumber, + secondsDifferenceBig: BigNumber, ): Promise { - const extraRewardsAPRBoundedPerBlock = - await this.computeExtraRewardsAPRBoundedPerBlock(stakeAddress); + const extraRewardsAPRBoundedPerSecond = + await this.computeExtraRewardsAPRBoundedPerSecond(stakeAddress); - return extraRewardsAPRBoundedPerBlock.multipliedBy(blockDifferenceBig); + return extraRewardsAPRBoundedPerSecond.multipliedBy( + secondsDifferenceBig, + ); } - async computeExtraRewardsAPRBoundedPerBlock( + async computeExtraRewardsAPRBoundedPerSecond( stakeAddress: string, ): Promise { const [farmTokenSupply, annualPercentageRewards] = await Promise.all([ @@ -147,7 +150,7 @@ export class StakingComputeService { return new BigNumber(farmTokenSupply) .multipliedBy(annualPercentageRewards) .dividedBy(constantsConfig.MAX_PERCENT) - .dividedBy(constantsConfig.BLOCKS_IN_YEAR); + .dividedBy(constantsConfig.SECONDS_IN_YEAR); } async farmingTokenPriceUSD(stakeAddress: string): Promise { @@ -206,21 +209,21 @@ export class StakingComputeService { const [ annualPercentageRewards, - perBlockRewardAmount, + perSecondRewardAmount, rewardsAPRBoundedBig, stakedValue, ] = await Promise.all([ this.stakingAbi.annualPercentageRewards(stakeAddress), - this.stakingAbi.perBlockRewardsAmount(stakeAddress), + this.stakingAbi.perSecondRewardsAmount(stakeAddress), this.computeExtraRewardsBounded( stakeAddress, - constantsConfig.BLOCKS_IN_YEAR, + new BigNumber(constantsConfig.SECONDS_IN_YEAR), ), this.stakingAbi.farmTokenSupply(stakeAddress), ]); - const rewardsUnboundedBig = new BigNumber(perBlockRewardAmount).times( - constantsConfig.BLOCKS_IN_YEAR, + const rewardsUnboundedBig = new BigNumber(perSecondRewardAmount).times( + constantsConfig.SECONDS_IN_YEAR, ); const stakedValueBig = new BigNumber(stakedValue); @@ -252,14 +255,14 @@ export class StakingComputeService { return '0'; } - const [perBlockRewardAmount, farmTokenSupply] = await Promise.all([ - this.stakingAbi.perBlockRewardsAmount(stakeAddress), + const [perSecondRewardAmount, farmTokenSupply] = await Promise.all([ + this.stakingAbi.perSecondRewardsAmount(stakeAddress), this.stakingAbi.farmTokenSupply(stakeAddress), ]); const rewardsUnboundedBig = new BigNumber( - perBlockRewardAmount, - ).multipliedBy(constantsConfig.BLOCKS_IN_YEAR); + perSecondRewardAmount, + ).multipliedBy(constantsConfig.SECONDS_IN_YEAR); return rewardsUnboundedBig.dividedBy(farmTokenSupply).toFixed(); } @@ -334,12 +337,12 @@ export class StakingComputeService { } async computeRewardsRemainingDays(stakeAddress: string): Promise { - const extraRewardsAPRBoundedPerBlock = - await this.computeExtraRewardsAPRBoundedPerBlock(stakeAddress); + const extraRewardsAPRBoundedPerSecond = + await this.computeExtraRewardsAPRBoundedPerSecond(stakeAddress); return this.computeRewardsRemainingDaysBase( stakeAddress, - extraRewardsAPRBoundedPerBlock, + extraRewardsAPRBoundedPerSecond, ); } @@ -351,30 +354,27 @@ export class StakingComputeService { async computeRewardsRemainingDaysBase( stakeAddress: string, - extraRewardsAPRBoundedPerBlock?: BigNumber, + extraRewardsAPRBoundedPerSecond?: BigNumber, ): Promise { - const [perBlockRewardAmount, accumulatedRewards, rewardsCapacity] = + const [perSecondRewardAmount, accumulatedRewards, rewardsCapacity] = await Promise.all([ - this.stakingAbi.perBlockRewardsAmount(stakeAddress), + this.stakingAbi.perSecondRewardsAmount(stakeAddress), this.stakingAbi.accumulatedRewards(stakeAddress), this.stakingAbi.rewardCapacity(stakeAddress), ]); - const perBlockRewards = extraRewardsAPRBoundedPerBlock + const perSecondRewards = extraRewardsAPRBoundedPerSecond ? BigNumber.min( - extraRewardsAPRBoundedPerBlock, - perBlockRewardAmount, + extraRewardsAPRBoundedPerSecond, + perSecondRewardAmount, ) - : new BigNumber(perBlockRewardAmount); - - // 10 blocks per minute * 60 minutes per hour * 24 hours per day - const blocksInDay = 10 * 60 * 24; + : new BigNumber(perSecondRewardAmount); return parseFloat( new BigNumber(rewardsCapacity) .minus(accumulatedRewards) - .dividedBy(perBlockRewards) - .dividedBy(blocksInDay) + .dividedBy(perSecondRewards) + .dividedBy(constantsConfig.SECONDS_IN_DAY) .toFixed(2), ); } @@ -503,9 +503,11 @@ export class StakingComputeService { ); } const remainingRewards = await Promise.all(promises); - return remainingRewards.reduce((acc, curr) => { - return new BigNumber(acc).plus(curr); - }); + return remainingRewards.length > 0 + ? remainingRewards.reduce((acc, curr) => { + return new BigNumber(acc).plus(curr); + }) + : new BigNumber(0); } async computeUserRewardsDistributionForWeek( @@ -809,11 +811,11 @@ export class StakingComputeService { additionalUserStakeAmount = '0', ): Promise { const [ - rewardsPerBlock, + rewardsPerSecond, annualPercentageRewards, boostedYieldsRewardsPercentage, ] = await Promise.all([ - this.stakingAbi.perBlockRewardsAmount(scAddress), + this.stakingAbi.perSecondRewardsAmount(scAddress), this.stakingAbi.annualPercentageRewards(scAddress), this.stakingAbi.boostedYieldsRewardsPercenatage(scAddress), ]); @@ -823,19 +825,19 @@ export class StakingComputeService { .plus(additionalUserStakeAmount) .toFixed(); - const rewardsPerBlockAPRBound = new BigNumber(farmTokenSupply) + const rewardsPerSecondAPRBound = new BigNumber(farmTokenSupply) .multipliedBy(annualPercentageRewards) .dividedBy(constantsConfig.MAX_PERCENT) - .dividedBy(constantsConfig.BLOCKS_IN_YEAR); - - const actualRewardsPerBlock = new BigNumber(rewardsPerBlock).isLessThan( - rewardsPerBlockAPRBound, - ) - ? new BigNumber(rewardsPerBlock) - : rewardsPerBlockAPRBound; - const blocksInWeek = 14440 * 7; - const totalRewardsPerWeek = - actualRewardsPerBlock.multipliedBy(blocksInWeek); + .dividedBy(constantsConfig.SECONDS_IN_YEAR); + + const actualRewardsPerSecond = new BigNumber( + rewardsPerSecond, + ).isLessThan(rewardsPerSecondAPRBound) + ? new BigNumber(rewardsPerSecond) + : rewardsPerSecondAPRBound; + const totalRewardsPerWeek = actualRewardsPerSecond.multipliedBy( + constantsConfig.SECONDS_IN_WEEK, + ); return totalRewardsPerWeek .multipliedBy(boostedYieldsRewardsPercentage) @@ -905,34 +907,6 @@ export class StakingComputeService { .toFixed(); } - async computeBlocksInWeek( - scAddress: string, - week: number, - ): Promise { - const [startEpochForCurrentWeek, currentEpoch, shardID] = - await Promise.all([ - this.weekTimekeepingCompute.startEpochForWeek(scAddress, week), - this.contextGetter.getCurrentEpoch(), - this.stakingAbi.stakingShard(scAddress), - ]); - - const promises = []; - for ( - let epoch = startEpochForCurrentWeek; - epoch <= currentEpoch; - epoch++ - ) { - promises.push( - this.contextGetter.getBlocksCountInEpoch(epoch, shardID), - ); - } - - const blocksInEpoch = await Promise.all(promises); - return blocksInEpoch.reduce((total, current) => { - return total + current; - }); - } - @ErrorLoggerAsync({ logArgs: true, }) diff --git a/src/modules/staking/services/staking.service.ts b/src/modules/staking/services/staking.service.ts index 47220650e..46cce3ac4 100644 --- a/src/modules/staking/services/staking.service.ts +++ b/src/modules/staking/services/staking.service.ts @@ -51,7 +51,7 @@ export class StakingService { private readonly weekTimekeepingAbi: WeekTimekeepingAbiService, private readonly weeklyRewardsSplittingAbi: WeeklyRewardsSplittingAbiService, private readonly stakingState: StakingStateService, - ) {} + ) { } async getFarmsStaking( fields: (keyof StakingModel)[] = [], @@ -130,7 +130,7 @@ export class StakingService { positions: CalculateRewardsArgs[], computeBoosted = false, ): Promise { - const [stakingFarms, currentNonce] = await Promise.all([ + const [stakingFarms, currentTimestamp] = await Promise.all([ this.stakingState.getStakingFarms( positions.map((position) => position.farmAddress), [ @@ -141,13 +141,13 @@ export class StakingService { 'divisionSafetyConstant', 'accumulatedRewards', 'rewardCapacity', - 'lastRewardBlockNonce', - 'perBlockRewards', + 'lastRewardTimestamp', + 'perSecondRewards', 'produceRewardsEnabled', - 'rewardsPerBlockAPRBound', + 'rewardsPerSecondAPRBound', ], ), - this.contextGetter.getShardCurrentBlockNonce(1), + Promise.resolve(Math.floor(Date.now() / 1000)), ]); return Promise.all( @@ -155,7 +155,7 @@ export class StakingService { this.getRewardsForPosition( stakingFarms[index], position, - currentNonce, + currentTimestamp, computeBoosted, ), ), @@ -165,7 +165,7 @@ export class StakingService { async getRewardsForPosition( stakingFarm: StakingModel, position: CalculateRewardsArgs, - currentNonce: number, + currentTimestamp: number, computeBoosted = false, ): Promise { const stakeTokenAttributes = this.decodeStakingTokenAttributes({ @@ -188,7 +188,7 @@ export class StakingService { stakingFarm, position.liquidity, stakeTokenAttributes[0], - currentNonce, + currentTimestamp, ); } diff --git a/src/modules/staking/services/staking.setter.service.ts b/src/modules/staking/services/staking.setter.service.ts index 79797cd5d..c4d765b1d 100644 --- a/src/modules/staking/services/staking.setter.service.ts +++ b/src/modules/staking/services/staking.setter.service.ts @@ -134,24 +134,24 @@ export class StakingSetterService extends GenericSetterService { ); } - async setPerBlockRewardAmount( + async setPerSecondRewardAmount( stakeAddress: string, value: string, ): Promise { return await this.setData( - this.getCacheKey('perBlockRewards', stakeAddress), + this.getCacheKey('perSecondRewardsAmount', stakeAddress), value, CacheTtlInfo.ContractState.remoteTtl, CacheTtlInfo.ContractState.localTtl, ); } - async setLastRewardBlockNonce( + async setLastRewardTimestamp( stakeAddress: string, value: number, ): Promise { return await this.setData( - this.getCacheKey('lastRewardBlockNonce', stakeAddress), + this.getCacheKey('lastRewardTimestamp', stakeAddress), value, CacheTtlInfo.ContractInfo.remoteTtl, CacheTtlInfo.ContractInfo.localTtl, diff --git a/src/modules/staking/services/staking.transactions.service.ts b/src/modules/staking/services/staking.transactions.service.ts index 7e6eb1429..c29fdcbe3 100644 --- a/src/modules/staking/services/staking.transactions.service.ts +++ b/src/modules/staking/services/staking.transactions.service.ts @@ -26,7 +26,7 @@ export class StakingTransactionService { private readonly mxProxy: MXProxyService, private readonly mxApi: MXApiService, private readonly contextGetter: ContextGetterService, - ) {} + ) { } @ErrorLoggerAsync() async stakeFarm( @@ -226,7 +226,7 @@ export class StakingTransactionService { if ( nft.nonce < migrationNonce && nft.attributes.length > - constantsConfig.STAKING_UNBOND_ATTRIBUTES_LEN + constantsConfig.STAKING_UNBOND_ATTRIBUTES_LEN ) { promises.push( this.claimRewards(userAddress, stakingAddress, { @@ -361,18 +361,18 @@ export class StakingTransactionService { ); } - async setPerBlockRewardAmount( + async setPerSecondRewardAmount( sender: string, stakeAddress: string, - perBlockAmount: string, + perSecondAmount: string, ): Promise { return this.mxProxy.getStakingSmartContractTransaction( stakeAddress, new TransactionOptions({ sender: sender, - gasLimit: gasConfig.stake.admin.setPerBlockRewardAmount, - function: 'setPerBlockRewardAmount', - arguments: [new BigUIntValue(new BigNumber(perBlockAmount))], + gasLimit: gasConfig.stake.admin.setPerSecondRewardAmount, + function: 'setPerSecondRewardAmount', + arguments: [new BigUIntValue(new BigNumber(perSecondAmount))], }), ); } diff --git a/src/modules/staking/specs/staking.compute.service.spec.ts b/src/modules/staking/specs/staking.compute.service.spec.ts index 6cbd279d6..147f6806b 100644 --- a/src/modules/staking/specs/staking.compute.service.spec.ts +++ b/src/modules/staking/specs/staking.compute.service.spec.ts @@ -150,9 +150,9 @@ describe('StakingComputeService', () => { const extraRewardsBounded = await service.computeExtraRewardsBounded( Address.Zero().bech32(), - new BigNumber(100000000), + new BigNumber(600000000), ); - expect(extraRewardsBounded).toEqual( + expect(extraRewardsBounded.integerValue(BigNumber.ROUND_UP)).toEqual( new BigNumber(10000000000000000000), ); }); @@ -166,8 +166,8 @@ describe('StakingComputeService', () => { jest.spyOn(stakingAbi, 'farmTokenSupply').mockImplementation( async () => '10000000000000000000000000', ); - jest.spyOn(stakingAbi, 'perBlockRewardsAmount').mockImplementation( - async () => '4138000000000000000', + jest.spyOn(stakingAbi, 'perSecondRewardsAmount').mockImplementation( + async () => '689666666666666666', ); jest.spyOn(stakingAbi, 'annualPercentageRewards').mockImplementation( async () => '2500', @@ -185,15 +185,15 @@ describe('StakingComputeService', () => { jest.spyOn(stakingAbi, 'farmTokenSupply').mockImplementation( async () => '100000000000000000000000000', ); - jest.spyOn(stakingAbi, 'perBlockRewardsAmount').mockImplementation( - async () => '4138000000000000000', + jest.spyOn(stakingAbi, 'perSecondRewardsAmount').mockImplementation( + async () => '689666666666666666', ); jest.spyOn(stakingAbi, 'annualPercentageRewards').mockImplementation( async () => '2500', ); const apr = await service.computeStakeFarmAPR(Address.Zero().bech32()); - expect(apr).toEqual('0.21749328'); + expect(apr).toEqual('0.21749327999999999978'); }); it('should compute optimal compound frequency', async () => { @@ -250,11 +250,11 @@ describe('StakingComputeService', () => { const stakingAbi = module.get(StakingAbiService); jest.spyOn(stakingAbi, 'accumulatedRewards').mockResolvedValue('100'); jest.spyOn(stakingAbi, 'rewardCapacity').mockResolvedValue('14500'); - jest.spyOn(stakingAbi, 'perBlockRewardsAmount').mockResolvedValue('1'); + jest.spyOn(stakingAbi, 'perSecondRewardsAmount').mockResolvedValue('0.16666667'); const rewardsRemainingDays = await service.computeRewardsRemainingDays( Address.Zero().bech32(), ); - expect(rewardsRemainingDays).toEqual(1); + expect(rewardsRemainingDays).toEqual(0.99); }); }); diff --git a/src/modules/staking/specs/staking.service.spec.ts b/src/modules/staking/specs/staking.service.spec.ts index b2d048575..9716cb3d4 100644 --- a/src/modules/staking/specs/staking.service.spec.ts +++ b/src/modules/staking/specs/staking.service.spec.ts @@ -88,7 +88,7 @@ describe('StakingService', () => { stakingFarm, { farmAddress: - 'erd1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqes9lzxht', + Address.Zero().bech32(), liquidity: '1000000000000000', identifier: 'MEXFARML-772223-14', attributes: @@ -112,36 +112,4 @@ describe('StakingService', () => { rewards: '150000000000000001046423', }); }); - - it('should get batch rewards for position', async () => { - const service: StakingService = - module.get(StakingService); - const batchRewards = await service.getBatchRewardsForPosition([ - { - farmAddress: - 'erd1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqes9lzxht', - liquidity: '1000000000000000', - identifier: 'MEXFARML-772223-14', - attributes: - 'AAAAAAAAAAAAAAQUAAAAAAAABBQAAAAMBP50cQa8hndHG4AAAAAAAAAAAAwE/nRxBryGd0cbgAA=', - vmQuery: false, - user: Address.Zero().bech32(), - }, - ]); - expect(batchRewards).toEqual([ - { - decodedAttributes: { - attributes: - 'AAAAAAAAAAAAAAQUAAAAAAAABBQAAAAMBP50cQa8hndHG4AAAAAAAAAAAAwE/nRxBryGd0cbgAA=', - compoundedReward: '0', - currentFarmAmount: - '519205458813209018315265407815173060004346493743728287017479820327455628280230924139593728', - identifier: 'MEXFARML-772223-14', - rewardPerShare: '0', - type: 'stakingFarmToken', - }, - rewards: '150000000000000001046423', - }, - ]); - }); }); diff --git a/src/modules/staking/specs/staking.transactions.service.spec.ts b/src/modules/staking/specs/staking.transactions.service.spec.ts index 0a32e419d..ccb417dd1 100644 --- a/src/modules/staking/specs/staking.transactions.service.spec.ts +++ b/src/modules/staking/specs/staking.transactions.service.spec.ts @@ -558,12 +558,12 @@ describe('StakingTransactionService', () => { }); }); - it('should get set per block reward amount transaction', async () => { + it('should get set per second reward amount transaction', async () => { const service = module.get( StakingTransactionService, ); - const transaction = await service.setPerBlockRewardAmount( + const transaction = await service.setPerSecondRewardAmount( senderAddress, Address.Zero().bech32(), '100', @@ -577,8 +577,8 @@ describe('StakingTransactionService', () => { receiverUsername: undefined, senderUsername: undefined, gasPrice: 1000000000, - gasLimit: gasConfig.stake.admin.setPerBlockRewardAmount, - data: encodeTransactionData('setPerBlockRewardAmount@0100'), + gasLimit: gasConfig.stake.admin.setPerSecondRewardAmount, + data: encodeTransactionData('setPerSecondRewardAmount@0100'), chainID: 'T', version: 2, options: undefined, diff --git a/src/modules/staking/staking.resolver.ts b/src/modules/staking/staking.resolver.ts index 2c2bf34fe..814d745ff 100644 --- a/src/modules/staking/staking.resolver.ts +++ b/src/modules/staking/staking.resolver.ts @@ -41,7 +41,7 @@ import { StateDataLoader } from '../state/services/state.dataloader'; @Resolver(() => StakingBoostedRewardsModel) export class StakingBoostedRewardsResolver { - constructor(private readonly stakingCompute: StakingComputeService) {} + constructor(private readonly stakingCompute: StakingComputeService) { } @ResolveField() async estimatedWeeklyRewards( @@ -117,7 +117,7 @@ export class StakingResolver { private readonly stakingCompute: StakingComputeService, private readonly stakingTransactionService: StakingTransactionService, private readonly stateDataLoader: StateDataLoader, - ) {} + ) { } @ResolveField() async farmToken(parent: StakingModel) { @@ -331,16 +331,16 @@ export class StakingResolver { @UseGuards(JwtOrNativeAdminGuard) @Query(() => TransactionModel) - async setPerBlockRewardAmount( + async setPerSecondRewardAmount( @Args('farmStakeAddress') farmStakeAddress: string, - @Args('perBlockAmount') perBlockAmount: string, + @Args('perSecondAmount') perSecondAmount: string, @AuthUser() user: UserAuthResult, ): Promise { await this.stakingService.requireOwner(farmStakeAddress, user.address); - return this.stakingTransactionService.setPerBlockRewardAmount( + return this.stakingTransactionService.setPerSecondRewardAmount( user.address, farmStakeAddress, - perBlockAmount, + perSecondAmount, ); } diff --git a/src/modules/state/mocks/farms.state.service.mock.ts b/src/modules/state/mocks/farms.state.service.mock.ts index e2b4f8e4c..7f3464df6 100644 --- a/src/modules/state/mocks/farms.state.service.mock.ts +++ b/src/modules/state/mocks/farms.state.service.mock.ts @@ -27,7 +27,7 @@ export class FarmsStateServiceMock { farmTokenCollection: farm.farmTokenID, farmingTokenId: farm.farmingTokenID, farmTokenSupply: farm.farmTotalSupply, - perBlockRewards: farm.rewardsPerBlock, + perSecondRewards: farm.rewardsPerSecond, rewardPerShare: farm.rewardPerShare, rewardType: FarmRewardType.LOCKED_REWARDS, version: FarmVersion.V2, diff --git a/src/modules/state/mocks/staking.state.service.mock.ts b/src/modules/state/mocks/staking.state.service.mock.ts index 1ece60385..74fa970f4 100644 --- a/src/modules/state/mocks/staking.state.service.mock.ts +++ b/src/modules/state/mocks/staking.state.service.mock.ts @@ -17,10 +17,10 @@ export class StakingStateServiceMock { rewardPerShare: '150000000000000000000', accumulatedRewards: '10000000000000000000', rewardCapacity: '10000000000000000000000', - lastRewardBlockNonce: 100, - perBlockRewards: new BigNumber(500000000).toFixed(), + lastRewardTimestamp: 100, + perSecondRewards: new BigNumber(500000000).toFixed(), produceRewardsEnabled: true, - rewardsPerBlockAPRBound: '100000000000', + rewardsPerSecondAPRBound: '100000000000', time: new WeekTimekeepingModel({ currentWeek: 250, firstWeekStartEpoch: 250, @@ -41,10 +41,10 @@ export class StakingStateServiceMock { rewardPerShare: '150000000000000000000', accumulatedRewards: '10000000000000000000', rewardCapacity: '10000000000000000000000', - lastRewardBlockNonce: 100, - perBlockRewards: new BigNumber(500000000).toFixed(), + lastRewardTimestamp: 100, + perSecondRewards: new BigNumber(500000000).toFixed(), produceRewardsEnabled: true, - rewardsPerBlockAPRBound: '100000000000', + rewardsPerSecondAPRBound: '100000000000', time: new WeekTimekeepingModel({ currentWeek: 250, firstWeekStartEpoch: 250, diff --git a/src/modules/state/services/state.sync.service.ts b/src/modules/state/services/state.sync.service.ts index b96e88e4c..891e7649c 100644 --- a/src/modules/state/services/state.sync.service.ts +++ b/src/modules/state/services/state.sync.service.ts @@ -85,6 +85,7 @@ export class StateSyncService { const pairsNeedingAnalytics: string[] = []; const tokensNeedingAnalytics: string[] = []; + let count = 1; for (const pairMeta of pairsMetadata) { if ( snapshotPairs.has(pairMeta.address) && @@ -167,6 +168,11 @@ export class StateSyncService { pairsNeedingAnalytics.push(pair.address); tokensNeedingAnalytics.push(pair.firstTokenId, pair.secondTokenId); + + this.logger.info( + `Finished populating pair: ${pair.address}: ${count} / ${pairsMetadata.length}`, + ); + count += 1; } this.bulkUpdatesService.recomputeAllValues( diff --git a/src/modules/state/services/state.tasks.service.ts b/src/modules/state/services/state.tasks.service.ts index 361fdc603..219d2a9ba 100644 --- a/src/modules/state/services/state.tasks.service.ts +++ b/src/modules/state/services/state.tasks.service.ts @@ -207,7 +207,7 @@ export class StateTasksService { const response = await this.stateService.initState(request); - this.logger.debug(`Populate state task completed`, { + this.logger.info(`Populate state task completed`, { context: StateTasksService.name, response, }); diff --git a/src/modules/state/services/sync/farms.sync.service.ts b/src/modules/state/services/sync/farms.sync.service.ts index 66bf3746c..1ec3822e2 100644 --- a/src/modules/state/services/sync/farms.sync.service.ts +++ b/src/modules/state/services/sync/farms.sync.service.ts @@ -18,7 +18,7 @@ export class FarmsSyncService { private readonly apiService: MXApiService, private readonly weeklyRewardsUtils: WeeklyRewardsSyncService, @Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger, - ) {} + ) { } async populateFarm(address: string): Promise { const profiler = new PerformanceProfiler(); @@ -27,7 +27,7 @@ export class FarmsSyncService { farmingTokenId, farmedTokenId, farmTokenCollection, - perBlockRewards, + perSecondRewards, penaltyPercent, minimumFarmingEpochs, divisionSafetyConstant, @@ -44,7 +44,7 @@ export class FarmsSyncService { this.farmAbiV2.getFarmingTokenIDRaw(address), this.farmAbiV2.getFarmedTokenIDRaw(address), this.farmAbiV2.getFarmTokenIDRaw(address), - this.farmAbiV2.getRewardsPerBlockRaw(address), + this.farmAbiV2.getRewardsPerSecondRaw(address), this.farmAbiV2.getPenaltyPercentRaw(address), this.farmAbiV2.getMinimumFarmingEpochsRaw(address), this.farmAbiV2.getDivisionSafetyConstantRaw(address), @@ -71,7 +71,7 @@ export class FarmsSyncService { farmTokenCollection, farmTokenDecimals: farmTokenMetadata.decimals, pairAddress, - perBlockRewards, + perSecondRewards, penaltyPercent, minimumFarmingEpochs, divisionSafetyConstant, @@ -106,8 +106,8 @@ export class FarmsSyncService { ): Promise> { const [ farmTokenSupply, - lastRewardBlockNonce, - perBlockRewards, + lastRewardTimestamp, + perSecondRewards, rewardPerShare, rewardReserve, produceRewardsEnabled, @@ -118,8 +118,8 @@ export class FarmsSyncService { boosterRewards, ] = await Promise.all([ this.farmAbiV2.getFarmTokenSupplyRaw(address), - this.farmAbiV2.getLastRewardBlockNonceRaw(address), - this.farmAbiV2.getRewardsPerBlockRaw(address), + this.farmAbiV2.getLastRewardTimestampRaw(address), + this.farmAbiV2.getRewardsPerSecondRaw(address), this.farmAbiV2.getRewardPerShareRaw(address), this.farmAbiV2.getRewardReserveRaw(address), this.farmAbiV2.getProduceRewardsEnabledRaw(address), @@ -142,8 +142,8 @@ export class FarmsSyncService { const farm: Partial = { farmTokenSupply, - lastRewardBlockNonce, - perBlockRewards, + lastRewardTimestamp, + perSecondRewards, rewardPerShare, rewardReserve, produceRewardsEnabled, diff --git a/src/modules/state/services/sync/staking.sync.service.ts b/src/modules/state/services/sync/staking.sync.service.ts index 256d5bab4..45b6477c4 100644 --- a/src/modules/state/services/sync/staking.sync.service.ts +++ b/src/modules/state/services/sync/staking.sync.service.ts @@ -19,7 +19,7 @@ export class StakingSyncService { private readonly apiService: MXApiService, private readonly weeklyRewardsUtils: WeeklyRewardsSyncService, @Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger, - ) {} + ) { } async populateStakingFarm(address: string): Promise { const profiler = new PerformanceProfiler(); @@ -29,7 +29,7 @@ export class StakingSyncService { farmingTokenId, rewardTokenId, annualPercentageRewards, - perBlockRewards, + perSecondRewards, minUnboundEpochs, divisionSafetyConstant, lockedAssetFactoryManagedAddress, @@ -45,7 +45,7 @@ export class StakingSyncService { this.stakingAbi.getFarmingTokenIDRaw(address), this.stakingAbi.getRewardTokenIDRaw(address), this.stakingAbi.getAnnualPercentageRewardsRaw(address), - this.stakingAbi.getPerBlockRewardsAmountRaw(address), + this.stakingAbi.getPerSecondRewardsAmountRaw(address), this.stakingAbi.getMinUnbondEpochsRaw(address), this.stakingAbi.getDivisionSafetyConstantRaw(address), this.stakingAbi.getLockedAssetFactoryAddressRaw(address), @@ -71,7 +71,7 @@ export class StakingSyncService { rewardTokenId, annualPercentageRewards, minUnboundEpochs, - perBlockRewards, + perSecondRewards, divisionSafetyConstant: divisionSafetyConstant.toString(), lockedAssetFactoryManagedAddress, state, @@ -106,9 +106,9 @@ export class StakingSyncService { rewardPerShare, accumulatedRewards, rewardCapacity, - lastRewardBlockNonce, + lastRewardTimestamp, annualPercentageRewards, - perBlockRewards, + perSecondRewards, produceRewardsEnabled, farmTokenSupplyCurrentWeek, accumulatedRewardsForWeek, @@ -120,9 +120,9 @@ export class StakingSyncService { this.stakingAbi.getRewardPerShareRaw(address), this.stakingAbi.getAccumulatedRewardsRaw(address), this.stakingAbi.getRewardCapacityRaw(address), - this.stakingAbi.getLastRewardBlockNonceRaw(address), + this.stakingAbi.getLastRewardTimestampRaw(address), this.stakingAbi.getAnnualPercentageRewardsRaw(address), - this.stakingAbi.getPerBlockRewardsAmountRaw(address), + this.stakingAbi.getPerSecondRewardsAmountRaw(address), this.stakingAbi.getProduceRewardsEnabledRaw(address), this.stakingAbi.getFarmSupplyForWeekRaw(address, currentWeek), this.stakingAbi.getAccumulatedRewardsForWeekRaw( @@ -145,9 +145,9 @@ export class StakingSyncService { rewardPerShare, accumulatedRewards, rewardCapacity, - lastRewardBlockNonce, + lastRewardTimestamp, annualPercentageRewards, - perBlockRewards, + perSecondRewards, produceRewardsEnabled, farmTokenSupplyCurrentWeek, accumulatedRewardsForWeek, diff --git a/src/services/crons/farm.cache.warmer.service.ts b/src/services/crons/farm.cache.warmer.service.ts index 6de66f349..1302fce9e 100644 --- a/src/services/crons/farm.cache.warmer.service.ts +++ b/src/services/crons/farm.cache.warmer.service.ts @@ -11,6 +11,8 @@ import { FarmAbiServiceV1_2 } from 'src/modules/farm/v1.2/services/farm.v1.2.abi import { FarmComputeFactory } from 'src/modules/farm/farm.compute.factory'; import { FarmSetterFactory } from 'src/modules/farm/farm.setter.factory'; import { FarmComputeServiceV2 } from 'src/modules/farm/v2/services/farm.v2.compute.service'; +import { FarmAbiServiceV2 } from 'src/modules/farm/v2/services/farm.v2.abi.service'; +import { FarmSetterServiceV2 } from 'src/modules/farm/v2/services/farm.v2.setter.service'; import { WeekTimekeepingAbiService } from 'src/submodules/week-timekeeping/services/week-timekeeping.abi.service'; @Injectable() @@ -27,7 +29,7 @@ export class FarmCacheWarmerService { private readonly farmSetterFactory: FarmSetterFactory, private readonly weekTimekeepingAbi: WeekTimekeepingAbiService, @Inject(PUB_SUB) private pubSub: RedisPubSub, - ) {} + ) { } @Cron(CronExpression.EVERY_MINUTE) async cacheFarmsTokens(): Promise { @@ -143,10 +145,12 @@ export class FarmCacheWarmerService { @Cron(CronExpression.EVERY_MINUTE) async cacheFarmInfo(): Promise { for (const farmAddress of farmsAddresses()) { + const isV2 = farmVersion(farmAddress) === FarmVersion.V2; + const [ minimumFarmingEpochs, penaltyPercent, - rewardsPerBlock, + rewardsAmount, state, produceRewardsEnabled, ] = await Promise.all([ @@ -156,9 +160,12 @@ export class FarmCacheWarmerService { this.farmAbiFactory .useAbi(farmAddress) .getPenaltyPercentRaw(farmAddress), - this.farmAbiFactory - .useAbi(farmAddress) - .getRewardsPerBlockRaw(farmAddress), + isV2 + ? (this.farmAbiFactory.useAbi(farmAddress) as FarmAbiServiceV2) + .getRewardsPerSecondRaw(farmAddress) + : this.farmAbiFactory + .useAbi(farmAddress) + .getRewardsPerBlockRaw(farmAddress), this.farmAbiFactory .useAbi(farmAddress) .getStateRaw(farmAddress), @@ -174,9 +181,12 @@ export class FarmCacheWarmerService { this.farmSetterFactory .useSetter(farmAddress) .setPenaltyPercent(farmAddress, penaltyPercent), - this.farmSetterFactory - .useSetter(farmAddress) - .setRewardsPerBlock(farmAddress, rewardsPerBlock), + isV2 + ? (this.farmSetterFactory.useSetter(farmAddress) as FarmSetterServiceV2) + .setRewardsPerSecond(farmAddress, rewardsAmount) + : this.farmSetterFactory + .useSetter(farmAddress) + .setRewardsPerBlock(farmAddress, rewardsAmount), this.farmSetterFactory .useSetter(farmAddress) .setState(farmAddress, state), @@ -195,18 +205,23 @@ export class FarmCacheWarmerService { @Cron(CronExpression.EVERY_30_SECONDS) async cacheFarmReserves(): Promise { for (const farmAddress of farmsAddresses()) { + const isV2 = farmVersion(farmAddress) === FarmVersion.V2; + const [ farmTokenSupply, - lastRewardBlockNonce, + lastRewardPoint, farmRewardPerShare, rewardReserve, ] = await Promise.all([ this.farmAbiFactory .useAbi(farmAddress) .getFarmTokenSupplyRaw(farmAddress), - this.farmAbiFactory - .useAbi(farmAddress) - .getLastRewardBlockNonceRaw(farmAddress), + isV2 + ? (this.farmAbiFactory.useAbi(farmAddress) as FarmAbiServiceV2) + .getLastRewardTimestampRaw(farmAddress) + : this.farmAbiFactory + .useAbi(farmAddress) + .getLastRewardBlockNonceRaw(farmAddress), this.farmAbiFactory .useAbi(farmAddress) .getRewardPerShareRaw(farmAddress), @@ -218,9 +233,12 @@ export class FarmCacheWarmerService { this.farmSetterFactory .useSetter(farmAddress) .setFarmTokenSupply(farmAddress, farmTokenSupply), - this.farmSetterFactory - .useSetter(farmAddress) - .setLastRewardBlockNonce(farmAddress, lastRewardBlockNonce), + isV2 + ? (this.farmSetterFactory.useSetter(farmAddress) as FarmSetterServiceV2) + .setLastRewardTimestamp(farmAddress, lastRewardPoint) + : this.farmSetterFactory + .useSetter(farmAddress) + .setLastRewardBlockNonce(farmAddress, lastRewardPoint), this.farmSetterFactory .useSetter(farmAddress) .setRewardPerShare(farmAddress, farmRewardPerShare), diff --git a/src/services/crons/staking.cache.warmer.service.ts b/src/services/crons/staking.cache.warmer.service.ts index 0799a4903..b43f8223b 100644 --- a/src/services/crons/staking.cache.warmer.service.ts +++ b/src/services/crons/staking.cache.warmer.service.ts @@ -15,7 +15,7 @@ export class StakingCacheWarmerService { private readonly stakeCompute: StakingComputeService, private readonly remoteConfigGetterService: RemoteConfigGetterService, @Inject(PUB_SUB) private pubSub: RedisPubSub, - ) {} + ) { } @Cron(CronExpression.EVERY_HOUR) async cacheFarmsStaking(): Promise { @@ -101,15 +101,15 @@ export class StakingCacheWarmerService { rewardPerShare, accumulatedRewards, rewardCapacity, - perBlockRewards, - lastRewardBlockNonce, + perSecondRewards, + lastRewardTimestamp, ] = await Promise.all([ this.stakingAbi.getFarmTokenSupplyRaw(address), this.stakingAbi.getRewardPerShareRaw(address), this.stakingAbi.getAccumulatedRewardsRaw(address), this.stakingAbi.getRewardCapacityRaw(address), - this.stakingAbi.getPerBlockRewardsAmountRaw(address), - this.stakingAbi.getLastRewardBlockNonceRaw(address), + this.stakingAbi.getPerSecondRewardsAmountRaw(address), + this.stakingAbi.getLastRewardTimestampRaw(address), ]); const cacheKeys = await Promise.all([ @@ -129,13 +129,13 @@ export class StakingCacheWarmerService { address, rewardCapacity, ), - this.stakeSetterService.setPerBlockRewardAmount( + this.stakeSetterService.setPerSecondRewardAmount( address, - perBlockRewards, + perSecondRewards, ), - this.stakeSetterService.setLastRewardBlockNonce( + this.stakeSetterService.setLastRewardTimestamp( address, - lastRewardBlockNonce, + lastRewardTimestamp, ), ]);