From 87d209295f6cc9677614922b2158c4d84fe09df9 Mon Sep 17 00:00:00 2001 From: Tarik Gul <47201679+TarikGul@users.noreply.github.com> Date: Wed, 22 Nov 2023 12:21:12 -0500 Subject: [PATCH] fix(calc): remove wasm-pack from node, and add it to calc library (#1360) * fix(calc): remove wasm-pack from node, and add it to calc library * Update calc/build.sh Co-authored-by: Dominique --------- Co-authored-by: Dominique --- calc/README.md | 5 +++ calc/build.sh | 37 +++++++++++++++++-- calc/pkg/README.md | 80 ++++++++++++++++++++++++++++++++++++++++-- calc/pkg/calc.d.ts | 45 ------------------------ calc/pkg/calc.js | 45 ------------------------ calc/pkg/calc_bg.wasm | Bin 37428 -> 38592 bytes package.json | 3 +- yarn.lock | 42 ---------------------- 8 files changed, 119 insertions(+), 138 deletions(-) diff --git a/calc/README.md b/calc/README.md index cb09c8dc8..c650e43b6 100644 --- a/calc/README.md +++ b/calc/README.md @@ -31,6 +31,11 @@ Example usage for the package can be found in Sidecar's [staking payout service](https://github.com/paritytech/substrate-api-sidecar/blob/master/src/services/accounts/AccountsStakingPayoutsService.ts) and Sidecar's [block service](https://github.com/paritytech/substrate-api-sidecar/blob/master/src/services/blocks/BlocksService.ts). +## Build + +In order to build the rust source code with `wasm-pack`, please run `sh build.sh`. +This will require `wasm-pack` being installed globally. The script will install it for you, but before it does it will ask you whether you want it installed or not. + ### calc_partial_fee Tool to calculate an extrinsics' `partial_fee` (i.e. the total fee minus any tip). It uses the following formula: diff --git a/calc/build.sh b/calc/build.sh index 4dd10d83d..c0bb254b6 100755 --- a/calc/build.sh +++ b/calc/build.sh @@ -2,11 +2,44 @@ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +install_wasm_pack() { + WASM_PACK_VERSION=0.12.1 + WASM_PACK="wasm-pack" + + uname_out="$(uname -s)" + case "${uname_out}" in + Linux*) machine=Linux;; + Darwin*) machine=Darwin;; + esac + + if [ $(cargo install --list | grep -q "wasm-pack v${WASM_PACK_VERSION}"; echo $?) != 0 ]; then + echo "$WASM_PACK v${WASM_PACK_VERSION} is not installed, and is required to build calc, would you like to install it now? (Y/N)"; + read response + if [ "$response" == "y" ] || [ "$response" == "Y" ]; then + ## Check if system is linux or mac for sudo or not. + if [[ $machine = "Darwin" ]] + then + cargo install "$WASM_PACK" --vers 0.12.1; + elif [[ $machine = "Linux" ]] + then + sudo cargo install "$WASM_PACK" --vers 0.12.1; + fi + else + echo "Skipping the installation of $WASM_PACK..."; + echo "Please note that this Conky configuration will not work without the $WASM_PACK package."; + fi + else + echo "The $WASM_PACK package has already been installed."; + fi +} + +install_wasm_pack + if [ -z ${CALC_DEBUG} ]; then - yarn wasm-pack build --target nodejs --scope substrate "$SCRIPT_DIR" + wasm-pack build --target nodejs --scope substrate "$SCRIPT_DIR" else echo "Fee debugging enabled" - yarn wasm-pack build --debug --target nodejs --scope substrate "$SCRIPT_DIR" -- --features debug + wasm-pack build --debug --target nodejs --scope substrate "$SCRIPT_DIR" -- --features debug fi # append a newline to pkg/package.json if it isn't there if [ "$(tail -c1 "$SCRIPT_DIR/pkg/package.json"; echo x)" != $'\nx' ]; then diff --git a/calc/pkg/README.md b/calc/pkg/README.md index 334f9d874..cb09c8dc8 100644 --- a/calc/pkg/README.md +++ b/calc/pkg/README.md @@ -27,8 +27,84 @@ standalone through the npm registry. ## Usage -Example usage for the package can be found in Sidecar's [staking payout service](https://github.com/paritytech/substrate-api-sidecar/blob/master/src/services/accounts/AccountsStakingPayoutsService.ts) and Sidecar's [block service](https://github.com/paritytech/substrate-api-sidecar/blob/master/src/services/blocks/BlocksService.ts). +Example usage for the package can be found in Sidecar's +[staking payout service](https://github.com/paritytech/substrate-api-sidecar/blob/master/src/services/accounts/AccountsStakingPayoutsService.ts) +and Sidecar's [block service](https://github.com/paritytech/substrate-api-sidecar/blob/master/src/services/blocks/BlocksService.ts). + +### calc_partial_fee +Tool to calculate an extrinsics' `partial_fee` (i.e. the total fee minus any tip). +It uses the following formula: + +``` +partial_fee = base_fee + len_fee + ((adjusted_weight_fee/estimated_weight)*actual_weight) +``` + +Where: +- `base_fee` is a fixed base fee to include some transaction in a block. It accounts + for the work needed to verify the signature and the computing work common to any tx. + It is constant for any tx. +- `len_fee` is a fee paid based on the size (length in bytes) of the transaction. + Longer transactions require more storage, and therefore are more expensive. +- `adjusted_weight_fee` is a fee that is itself `estimated_weight * targeted_fee_adjustment`: + - `targeted_fee_adjustment` is some adjustment made based on the network load and + other circumstantial factors, and is an opaque internal value we have no access to. + - `estimated_weight` is the "pre-dispatch" weight of the transaction. It's set + based on the cost of processing the transaction on reference hardware. +- `actual_weight` is the weight that is found in the `ExtrinsicSuccess` event for + the extrinsic in a block (it's just called `weight` in the event), and it's + value is often close to `estimated_weight`, but the node has the opportunity + to change it depending on the actual computing work necessary to process the tx. + +The RPC endpoint `payment_queryFeeDetails` returns `base_fee`, `len_fee` and +`adjusted_weight_fee`. The RPC endpoint `payment_queryInfo` returns `estimated_weight` +(called `weight` in the response), and a `partialFee` value, which is our best +guess at the inclusion fee for the tx without actually submitting it and seeing +whether the node changes the weight or decides not to take a fee at all. + +To get the correct values for some extrinsic from both endpoints, provide the +extrinsic bytes, and the number of the block **before the block it is included in** +(e.g. if the extrinsic was in block 100, you'd use block 99 as an argument). This +is very important. + +Once you've called these endpoints, access the `ExtrinsicSuccess` event to find +the `actual_weight`, but also a `paysFee` value which signals whether the extrinsic +actually incurred a fee at all or not (a node has the opportunity to refund the +fee entirely). + +With all of those values at hand, the equation above calculates the correct Fee. +Why? Well, the basic way to calculate a pre-dispatch fee is: + +``` +partial_fee = base_fee + len_fee + adjusted_weight_fee +``` + +We can do this from just the RPC methods. But then once it's in a block, we need +to swap out the weight used to calculate that `adjusted_weight_fee` with the +actual weight that was used from the `ExtrinsicSuccess` event. In the end, the +calculation itself is simple, but gathering the details needed is the main difficulty. +We do this all in Rust simply to limit any precision loss. + +### calc_payout + +This is a tool to calculate the payout of a staking era, either for a validator +or a nominator. This is not a predictive estimation, instead it intakes data +from a concluded [era](https://wiki.polkadot.network/docs/kusama-parameters#periods-of-common-actions-and-attributes) +to arrive to the final amount. For this it takes the following parameters: +- `total_reward_points` are the total [era points](https://wiki.polkadot.network/docs/maintain-guides-validator-payout#era-points) + for a determined [era](https://wiki.polkadot.network/docs/kusama-parameters#periods-of-common-actions-and-attributes). +- `era_payout` is the [payout](https://wiki.polkadot.network/docs/maintain-guides-validator-payout#payout-scheme) + for a determined [era](https://wiki.polkadot.network/docs/kusama-parameters#periods-of-common-actions-and-attributes). +- `validator_reward_points` are the [era points](https://wiki.polkadot.network/docs/maintain-guides-validator-payout#era-points) + earned by the validator in a determined [era](https://wiki.polkadot.network/docs/kusama-parameters#periods-of-common-actions-and-attributes). +- `validator_commission` is the commission that the validator takes of its assigned + payout before distribituing the remainder between itself and it's nominators. +- `nominator_exposure` is the amount staked by the nominator or validator, + depending on who we are inquiring about. +- `total_exposure` the total amount staked. +- `is_validator` is a `bool` that states whether the inquired account is a validator. + ## Contributing -We welcome [contributions for documentation and code](https://github.com/paritytech/substrate-api-sidecar/pulls). If you have any questions you can reach the maintainers by [filing an issue on github.](https://github.com/paritytech/substrate-api-sidecar/issues) \ No newline at end of file +We welcome [contributions for documentation and code](https://github.com/paritytech/substrate-api-sidecar/pulls). +If you have any questions you can reach the maintainers by [filing an issue on github.](https://github.com/paritytech/substrate-api-sidecar/issues) \ No newline at end of file diff --git a/calc/pkg/calc.d.ts b/calc/pkg/calc.d.ts index c9bc477b5..a5f453d8b 100644 --- a/calc/pkg/calc.d.ts +++ b/calc/pkg/calc.d.ts @@ -1,51 +1,6 @@ /* tslint:disable */ /* eslint-disable */ /** -* Uses the following formula to calculate an extrinsics `partial_fee` (ie the total fee -* minus any tip). -* -* ``` -* partial_fee = base_fee + len_fee + ((adjusted_weight_fee/estimated_weight)*actual_weight) -* ``` -* -* Where: -* - `base_fee` is a fixed base fee to include some transaction in a block. It accounts -* for the work needed to verify the signature and such and is constant for any tx. -* - `len_fee` is a fee paid based on the size (length in bytes) of the transaction. Longer -* transactions require more storage. -* - `adjusted_weight_fee` is a fee that is itself `estimated_weight * targeted_fee_adjustment`. -* `targeted_fee_adjustment` is some adjustment made based on the network load and such, and is -* an opaque internal value we have no access to. -* - `estimated_weight` is the "pre-dispatch" weight of the transaction. It's set based on the cost -* of processing the transaction on reference hardware. -* - `actual_weight` is the weight that is found in the `ExtrinsicSuccess` event for the extrinsic in -* a block (it's just called `weight` in the event), and is often the same as `estimated_weight`, -* but the node has the opportunity to change it to whatever it likes, I think. -* -* The RPC endpoint `payment_queryFeeDetails` returns `base_fee`, `len_fee` and `adjusted_weight_fee`/ -* The RPC endpoint `payment_queryInfo` returns `estimated_weight` (called `weight` in the response), and -* a `partialFee` value, which is our best guess at the inclusion fee for the tx without actually submitting -* it and seeing whether the node changes the weight/decides not to take a fee at all. -* -* To get the correct values for some extrinsic from both endpoints, provide the extrinsic bytes, and the -* block number **one before the block it made it into** (eg if the extrinsic was in block 100, you'd use -* block 99 as an argument). This is very important. -* -* Once you've called these endpoints, access the `ExtrinsicSuccess` event to find the `actual_weight`, but -* also a `paysFee` value which signals whether the extrinsic actually incurred a fee at all or not (a node -* has the opportunity to refund the fee entirely if it likes by setting this). -* -* With all of those values to hand, the equation above calculates the correct Fee. Why? Well, the basic -* way to calculate a pre-dispatch fee is: -* -* ``` -* partial_fee = base_fee + len_fee + adjusted_weight_fee -* ``` -* -* We can do this from just the RPC methods. But then once it's in a block, we need to swap out the weight used -* to calculate that `adjusted_weight_fee` with the actual weight that was used from the `ExtrinsicSuccess` event. -* In the end, the maths is simple and gathering the details needed is the main difficulty. We do this all in -* Rust simply to limit any precision loss. * @param {string} base_fee * @param {string} len_fee * @param {string} adjusted_weight_fee diff --git a/calc/pkg/calc.js b/calc/pkg/calc.js index d509f11a8..369ab2b57 100644 --- a/calc/pkg/calc.js +++ b/calc/pkg/calc.js @@ -113,51 +113,6 @@ function takeObject(idx) { return ret; } /** -* Uses the following formula to calculate an extrinsics `partial_fee` (ie the total fee -* minus any tip). -* -* ``` -* partial_fee = base_fee + len_fee + ((adjusted_weight_fee/estimated_weight)*actual_weight) -* ``` -* -* Where: -* - `base_fee` is a fixed base fee to include some transaction in a block. It accounts -* for the work needed to verify the signature and such and is constant for any tx. -* - `len_fee` is a fee paid based on the size (length in bytes) of the transaction. Longer -* transactions require more storage. -* - `adjusted_weight_fee` is a fee that is itself `estimated_weight * targeted_fee_adjustment`. -* `targeted_fee_adjustment` is some adjustment made based on the network load and such, and is -* an opaque internal value we have no access to. -* - `estimated_weight` is the "pre-dispatch" weight of the transaction. It's set based on the cost -* of processing the transaction on reference hardware. -* - `actual_weight` is the weight that is found in the `ExtrinsicSuccess` event for the extrinsic in -* a block (it's just called `weight` in the event), and is often the same as `estimated_weight`, -* but the node has the opportunity to change it to whatever it likes, I think. -* -* The RPC endpoint `payment_queryFeeDetails` returns `base_fee`, `len_fee` and `adjusted_weight_fee`/ -* The RPC endpoint `payment_queryInfo` returns `estimated_weight` (called `weight` in the response), and -* a `partialFee` value, which is our best guess at the inclusion fee for the tx without actually submitting -* it and seeing whether the node changes the weight/decides not to take a fee at all. -* -* To get the correct values for some extrinsic from both endpoints, provide the extrinsic bytes, and the -* block number **one before the block it made it into** (eg if the extrinsic was in block 100, you'd use -* block 99 as an argument). This is very important. -* -* Once you've called these endpoints, access the `ExtrinsicSuccess` event to find the `actual_weight`, but -* also a `paysFee` value which signals whether the extrinsic actually incurred a fee at all or not (a node -* has the opportunity to refund the fee entirely if it likes by setting this). -* -* With all of those values to hand, the equation above calculates the correct Fee. Why? Well, the basic -* way to calculate a pre-dispatch fee is: -* -* ``` -* partial_fee = base_fee + len_fee + adjusted_weight_fee -* ``` -* -* We can do this from just the RPC methods. But then once it's in a block, we need to swap out the weight used -* to calculate that `adjusted_weight_fee` with the actual weight that was used from the `ExtrinsicSuccess` event. -* In the end, the maths is simple and gathering the details needed is the main difficulty. We do this all in -* Rust simply to limit any precision loss. * @param {string} base_fee * @param {string} len_fee * @param {string} adjusted_weight_fee diff --git a/calc/pkg/calc_bg.wasm b/calc/pkg/calc_bg.wasm index 56a928048ae1dcc6597b247f868f8ea93161e1a2..e267a6a396c36735f8fdf28efcdf57670245c0e2 100644 GIT binary patch delta 18128 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 Y{9dVrG}-&Izh)c^nh delta 17211 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