From 83ba6ec0508467d8cd1defb9090400f7ea3ffe7c Mon Sep 17 00:00:00 2001 From: "johnnyji.dev" Date: Wed, 6 Mar 2024 09:42:06 +0000 Subject: [PATCH 1/4] add some api(claimedReward, UsedFee). - After completing transaction, need to retrieve a final claimed reward and used fee. --- .../dapp-staking/pending-rewards/index.ts | 91 ++++++++++++++++++- packages/sdk-core/src/modules/units/index.ts | 18 ++++ 2 files changed, 108 insertions(+), 1 deletion(-) diff --git a/packages/sdk-core/src/modules/dapp-staking/pending-rewards/index.ts b/packages/sdk-core/src/modules/dapp-staking/pending-rewards/index.ts index d9b0a327..142e737a 100644 --- a/packages/sdk-core/src/modules/dapp-staking/pending-rewards/index.ts +++ b/packages/sdk-core/src/modules/dapp-staking/pending-rewards/index.ts @@ -3,7 +3,7 @@ import { Perbill } from '@polkadot/types/interfaces'; import { ApiPromise } from '@polkadot/api'; import { ethers } from 'ethers'; import { Codec } from '@polkadot/types/types'; -import { hasProperty, truncate } from '@astar-network/astar-sdk-core'; +import { commaStrToBigInt, hasProperty, truncate } from '@astar-network/astar-sdk-core'; export interface RewardDistributionConfig extends Struct { readonly baseTreasuryPercent: Perbill; @@ -251,3 +251,92 @@ export const estimatePendingRewards = async ({ api, return { stakerPendingRewards: 0 }; } }; + + + + +/** + * Memo: + * This method returns claimed reward amount by stakerAddress and blockHeight that have the reward event. + * After StkingV3, Two kinds of rewards exist. + * - Staker Reward : When "Build&Earn" comes after the "Voting", stakers can get the reward by staking on dApps. + * - Bonus Reward : During the "Voting" subperiod makes the staker eligible for bonus rewards. + */ +export const claimedReward = async ( + { + api, staker, height + } : + { + api: ApiPromise, staker: string, height: BigInt + }): Promise<{claimedRewards: number}> => { + try { + + const blockHash = await api.rpc.chain.getBlockHash(height); + const signedBlock = await api.rpc.chain.getBlock(blockHash); + const apiAt = await api.at(signedBlock.block.header.hash); + const allRecords = (await apiAt.query.system.events()).toArray(); + + let claimedReward = BigInt('0'); + const method = 'Reward'; + const section = 'dappStaking'; + + allRecords.map((e) => { + if (e.toHuman()?.event?.data?.account == staker && + e.toHuman()?.event?.method == method && + e.toHuman()?.event?.section == section) { + let tmpAmount = e.toHuman().event?.data?.amount; + let tmpAmountBigInt = commaStrToBigInt(tmpAmount); + + claimedReward += tmpAmountBigInt; + + } else { + claimedReward = claimedReward; + } + }) + + return { claimedRewards: Number(claimedReward) }; + + } catch (error) { + console.log(error); + throw error; + } +} + +/** + * Memo: + * This method returns usedfee amount by Address and blockHeight that have the actualFee. + */ +export const UsedFee = async ( + { + api, address, height + } : + { + api: ApiPromise, address: string, height: BigInt + }): Promise<{usedFee: number}> => { + try { + + const blockHash = await api.rpc.chain.getBlockHash(height); + const signedBlock = await api.rpc.chain.getBlock(blockHash); + const apiAt = await api.at(signedBlock.block.header.hash); + const allRecords = (await apiAt.query.system.events()).toArray(); + + let usedFee = BigInt('0'); + allRecords.map((e) => { + if (e.toHuman()?.event?.data?.who == address) { + let tmpUsedFee = e.toHuman().event?.data?.actualFee; + let tmpUsedFeeBigInt = commaStrToBigInt(tmpUsedFee); + + usedFee = tmpUsedFeeBigInt; + + } else { + usedFee = usedFee; + } + }) + + return { usedFee: Number(usedFee) }; + + } catch (error) { + console.log(error); + throw error; + } +} \ No newline at end of file diff --git a/packages/sdk-core/src/modules/units/index.ts b/packages/sdk-core/src/modules/units/index.ts index b798aebe..f216917b 100644 --- a/packages/sdk-core/src/modules/units/index.ts +++ b/packages/sdk-core/src/modules/units/index.ts @@ -80,3 +80,21 @@ export const formatNumber = (value: number, digits: number): string => { return item ? (value / item.value).toFixed(digits).replace(rx, '$1') + item.symbol : '0'; }; + + +export function commaStrToBigInt(_str: string) { + + let _strToStr = String(_str); + + let _noCommaStr = _strToStr.replace(/,/g, ''); + + let rlt = BigInt("0"); + + if (_noCommaStr === "undefined") { + console.log(' _noCommaStr :undefined '); + } else { + rlt = BigInt(_noCommaStr); + } + + return rlt; +} \ No newline at end of file From af8b38f04c5899766e44dd0dc0374087748ff17d Mon Sep 17 00:00:00 2001 From: "johnnyji.dev" Date: Thu, 7 Mar 2024 14:55:34 +0000 Subject: [PATCH 2/4] update claimedReward & usedFee param (address to extrinsicHash) --- .../dapp-staking/pending-rewards/index.ts | 174 +++++++++++------- 1 file changed, 104 insertions(+), 70 deletions(-) diff --git a/packages/sdk-core/src/modules/dapp-staking/pending-rewards/index.ts b/packages/sdk-core/src/modules/dapp-staking/pending-rewards/index.ts index 142e737a..978b01b0 100644 --- a/packages/sdk-core/src/modules/dapp-staking/pending-rewards/index.ts +++ b/packages/sdk-core/src/modules/dapp-staking/pending-rewards/index.ts @@ -85,10 +85,10 @@ const getClaimableEraRange = (era: number, currentEra: number): number[] => { const formatGeneralStakerInfo = ({ eraTvls, currentEra, generalStakerInfo }: { - currentEra: number; - eraTvls: EraTvl[]; - generalStakerInfo: [StorageKey, Codec][]; -}): { stakerInfo: StakerInfo[]; stakedEras: number[] } => { + currentEra: number; + eraTvls: EraTvl[]; + generalStakerInfo: [StorageKey, Codec][]; + }): { stakerInfo: StakerInfo[]; stakedEras: number[] } => { const stakerInfo: StakerInfo[] = []; const stakedEras: number[] = []; @@ -125,12 +125,12 @@ const estimateEraTokenIssuances = async ({ blockHeight, stakedEras, currentEra, blocksPerEra }: { - blockHeight: number; - api: ApiPromise; - stakedEras: number[]; - currentEra: number; - blocksPerEra: number; -}): Promise => { + blockHeight: number; + api: ApiPromise; + stakedEras: number[]; + currentEra: number; + blocksPerEra: number; + }): Promise => { const eraTokenIssuances: { era: number; eraTokenIssuance: number }[] = []; const block7EraAgo = blockHeight - blocksPerEra * 7; const [hash, currentIssuance] = await Promise.all([ @@ -169,12 +169,12 @@ const formatStakerPendingRewards = ({ stakerInfo, eraTokenIssuances, eraRewards, rewardsDistributionConfig }: { - stakerInfo: StakerInfo[]; - eraTvls: EraTvl[]; - eraTokenIssuances: EraTokenIssuances[]; - eraRewards: number; - rewardsDistributionConfig: DistributionConfig; -}) => { + stakerInfo: StakerInfo[]; + eraTvls: EraTvl[]; + eraTokenIssuances: EraTokenIssuances[]; + eraRewards: number; + rewardsDistributionConfig: DistributionConfig; + }) => { return stakerInfo.map((it) => { const totalStaked = eraTvls[it.era].tvlLocked; const { baseStakerPercent, adjustablePercent, idealDappsStakingTvl } = rewardsDistributionConfig; @@ -199,9 +199,9 @@ const formatStakerPendingRewards = ({ stakerInfo, // In other words, as the number of unclaimed eras increases, the difference increases (but it shouldn't be too far away). export const estimatePendingRewards = async ({ api, walletAddress }: { - api: ApiPromise; - walletAddress: string; -}): Promise<{ stakerPendingRewards: number }> => { + api: ApiPromise; + walletAddress: string; + }): Promise<{ stakerPendingRewards: number }> => { try { const [eraInfo, generalStakerInfo, blockHeight, blocksPerEra, rawBlockRewards, rewardsDistributionConfig] = await Promise.all([ @@ -257,86 +257,120 @@ export const estimatePendingRewards = async ({ api, /** * Memo: - * This method returns claimed reward amount by stakerAddress and blockHeight that have the reward event. + * This method returns claimed reward amount by extrinsicHash and blockHeight that have the reward event. * After StkingV3, Two kinds of rewards exist. * - Staker Reward : When "Build&Earn" comes after the "Voting", stakers can get the reward by staking on dApps. * - Bonus Reward : During the "Voting" subperiod makes the staker eligible for bonus rewards. */ export const claimedReward = async ( { - api, staker, height - } : - { - api: ApiPromise, staker: string, height: BigInt - }): Promise<{claimedRewards: number}> => { + api, extrinsicHash, height + }: + { + api: ApiPromise, extrinsicHash: string, height: number + }): Promise<{ claimedRewards: number }> => { try { - const blockHash = await api.rpc.chain.getBlockHash(height); - const signedBlock = await api.rpc.chain.getBlock(blockHash); - const apiAt = await api.at(signedBlock.block.header.hash); - const allRecords = (await apiAt.query.system.events()).toArray(); + const blockHash = await api.rpc.chain.getBlockHash(height); + const signedBlock = await api.rpc.chain.getBlock(blockHash); + const apiAt = await api.at(signedBlock.block.header.hash); + const allRecords = (await apiAt.query.system.events()).toArray(); + + // Find the extrinsic index by matching the extrinsic hash + const extrinsicIndex = signedBlock.block.extrinsics.findIndex( + (ex) => ex.hash.toString() === extrinsicHash + ); + + if (extrinsicIndex === -1) { + throw new Error('Extrinsic not found in the block'); + } + + // Get events associated with the extrinsic + const extrinsicEvents = allRecords.filter((record) => + record.phase.isApplyExtrinsic && + record.phase.asApplyExtrinsic.eq(extrinsicIndex) + ); - let claimedReward = BigInt('0'); - const method = 'Reward'; - const section = 'dappStaking'; + const method = 'Reward'; + const section = 'dappStaking'; + let claimedReward = BigInt('0'); - allRecords.map((e) => { - if (e.toHuman()?.event?.data?.account == staker && - e.toHuman()?.event?.method == method && - e.toHuman()?.event?.section == section) { - let tmpAmount = e.toHuman().event?.data?.amount; - let tmpAmountBigInt = commaStrToBigInt(tmpAmount); + extrinsicEvents.map((e) => { + if (e.toHuman()?.event?.method == method && + e.toHuman()?.event?.section == section) { + let tmpAmount = e.toHuman().event?.data?.amount; + let tmpAmountBigInt = commaStrToBigInt(tmpAmount); - claimedReward += tmpAmountBigInt; + claimedReward += tmpAmountBigInt; - } else { - claimedReward = claimedReward; - } - }) + } else { + claimedReward = claimedReward; + } + }) - return { claimedRewards: Number(claimedReward) }; + return { claimedRewards: Number(claimedReward) }; } catch (error) { - console.log(error); - throw error; + console.log(error); + throw error; } } /** * Memo: - * This method returns usedfee amount by Address and blockHeight that have the actualFee. + * This method returns usedfee amount by extrinsicHash and blockHeight that have the actualFee. */ export const UsedFee = async ( { - api, address, height - } : - { - api: ApiPromise, address: string, height: BigInt - }): Promise<{usedFee: number}> => { + api, extrinsicHash, height + }: + { + api: ApiPromise, extrinsicHash: string, height: number + }): Promise<{ usedFee: number }> => { try { - const blockHash = await api.rpc.chain.getBlockHash(height); - const signedBlock = await api.rpc.chain.getBlock(blockHash); - const apiAt = await api.at(signedBlock.block.header.hash); - const allRecords = (await apiAt.query.system.events()).toArray(); - - let usedFee = BigInt('0'); - allRecords.map((e) => { - if (e.toHuman()?.event?.data?.who == address) { - let tmpUsedFee = e.toHuman().event?.data?.actualFee; - let tmpUsedFeeBigInt = commaStrToBigInt(tmpUsedFee); - - usedFee = tmpUsedFeeBigInt; - - } else { - usedFee = usedFee; - } + const blockHash = await api.rpc.chain.getBlockHash(height); + const signedBlock = await api.rpc.chain.getBlock(blockHash); + const apiAt = await api.at(signedBlock.block.header.hash); + const allRecords = (await apiAt.query.system.events()).toArray(); + + // Find the extrinsic index by matching the extrinsic hash + const extrinsicIndex = signedBlock.block.extrinsics.findIndex( + (ex) => ex.hash.toString() === extrinsicHash + ); + + if (extrinsicIndex === -1) { + throw new Error('Extrinsic not found in the block'); + } + + // Get events associated with the extrinsic + const extrinsicEvents = allRecords.filter((record) => + record.phase.isApplyExtrinsic && + record.phase.asApplyExtrinsic.eq(extrinsicIndex) + ); + + const method = 'TransactionFeePaid'; + const section = 'transactionPayment'; + + let usedFee = BigInt('0'); + + extrinsicEvents.map((e) => { + if (e.toHuman()?.event?.method == method && + e.toHuman()?.event?.section == section) { + let tmpUsedFee = e.toHuman().event?.data?.actualFee; + let tmpUsedFeeBigInt = commaStrToBigInt(tmpUsedFee); + + usedFee = tmpUsedFeeBigInt; + + } else { + usedFee = usedFee; + } }) return { usedFee: Number(usedFee) }; } catch (error) { - console.log(error); - throw error; + console.log(error); + throw error; } } \ No newline at end of file From 77dc1cec6fb9c32a32c7820c0aacc1cecdb08e24 Mon Sep 17 00:00:00 2001 From: "johnnyji.dev" Date: Wed, 29 May 2024 00:52:00 +0000 Subject: [PATCH 3/4] update claimedReward(Claim_staker_rewards & Claim_bonus_reward) --- .../src/modules/dapp-staking/pending-rewards/index.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/sdk-core/src/modules/dapp-staking/pending-rewards/index.ts b/packages/sdk-core/src/modules/dapp-staking/pending-rewards/index.ts index 978b01b0..b313c4b2 100644 --- a/packages/sdk-core/src/modules/dapp-staking/pending-rewards/index.ts +++ b/packages/sdk-core/src/modules/dapp-staking/pending-rewards/index.ts @@ -291,12 +291,14 @@ export const claimedReward = async ( record.phase.asApplyExtrinsic.eq(extrinsicIndex) ); - const method = 'Reward'; + const methodRwd = 'Reward'; + const methodBns = 'BonusReward'; const section = 'dappStaking'; let claimedReward = BigInt('0'); - extrinsicEvents.map((e) => { - if (e.toHuman()?.event?.method == method && + extrinsicEvents.map((e, idx) => { + console.log(e.toHuman(), idx); + if ((e.toHuman()?.event?.method == methodRwd || e.toHuman()?.event?.method == methodBns) && e.toHuman()?.event?.section == section) { let tmpAmount = e.toHuman().event?.data?.amount; let tmpAmountBigInt = commaStrToBigInt(tmpAmount); From 3f0e8e5daf7c00c118a6f2211f806b7853593323 Mon Sep 17 00:00:00 2001 From: "johnnyji.dev" Date: Sun, 23 Jun 2024 07:57:51 +0000 Subject: [PATCH 4/4] fix: version change 0.2.8 => 0.3.0 on package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 05bb4c42..139436ec 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "url": "https://github.com/AstarNetwork/astar.js.git" }, "sideEffects": false, - "version": "0.2.8", + "version": "0.3.0", "workspaces": [ "packages/*", "examples/*"