From 35a99fa44fb7dad45c6e529fbd9356baa4cb3a5f Mon Sep 17 00:00:00 2001 From: Milan Steiner Date: Wed, 13 Apr 2022 10:14:33 +0200 Subject: [PATCH 1/8] Add getter to get staked balance --- packages/stargate/src/stargateclient.spec.ts | 10 +++++ packages/stargate/src/stargateclient.ts | 41 +++++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/packages/stargate/src/stargateclient.spec.ts b/packages/stargate/src/stargateclient.spec.ts index 593a4afa..65caee1c 100644 --- a/packages/stargate/src/stargateclient.spec.ts +++ b/packages/stargate/src/stargateclient.spec.ts @@ -257,6 +257,16 @@ describe("StargateClient", () => { client.disconnect(); }); + describe("getBalanceStaked", () => { + it("works", async () => { + pendingWithoutSimapp(); + const client = await StargateClient.connect(simapp.tendermintUrl); + const response = await client.getBalanceStaked(faucet.address0); + + expect(response).toEqual({ denom: "ustake", amount: "190422" }); + }); + }); + it("returns 0 for non-existent balance", async () => { pendingWithoutSimapp(); const client = await StargateClient.connect(simapp.tendermintUrl); diff --git a/packages/stargate/src/stargateclient.ts b/packages/stargate/src/stargateclient.ts index bbbfa251..46474ed0 100644 --- a/packages/stargate/src/stargateclient.ts +++ b/packages/stargate/src/stargateclient.ts @@ -1,10 +1,13 @@ /* eslint-disable @typescript-eslint/naming-convention */ import { toHex } from "@cosmjs/encoding"; import { Uint53 } from "@cosmjs/math"; +import { Decimal } from "@cosmjs/math"; import { Tendermint34Client, toRfc3339WithNanoseconds } from "@cosmjs/tendermint-rpc"; -import { sleep } from "@cosmjs/utils"; +import { assert, sleep } from "@cosmjs/utils"; import { MsgData } from "cosmjs-types/cosmos/base/abci/v1beta1/abci"; import { Coin } from "cosmjs-types/cosmos/base/v1beta1/coin"; +import { QueryDelegatorDelegationsResponse } from "cosmjs-types/cosmos/staking/v1beta1/query"; +import { DelegationResponse } from "cosmjs-types/cosmos/staking/v1beta1/staking"; import { Account, accountFromAny, AccountParser } from "./accounts"; import { @@ -273,6 +276,31 @@ export class StargateClient { return this.forceGetQueryClient().bank.allBalances(address); } + public async getBalanceStaked(address: string): Promise { + const allDelegations = []; + let startAtKey: Uint8Array | undefined = undefined; + do { + const { delegationResponses, pagination }: QueryDelegatorDelegationsResponse = + await this.forceGetQueryClient().staking.delegatorDelegations(address, startAtKey); + + const loadedDelegations = delegationResponses || []; + allDelegations.push(...loadedDelegations); + startAtKey = pagination?.nextKey; + } while (startAtKey?.length !== 0 && startAtKey !== undefined); + + const sumValues = allDelegations.reduce( + (previousValue: Coin | null, currentValue: DelegationResponse): Coin => { + assert(currentValue.balance); + return previousValue !== null + ? this.addCoins(previousValue, currentValue.balance) + : currentValue.balance; + }, + null, + ); + + return sumValues; + } + public async getDelegation(delegatorAddress: string, validatorAddress: string): Promise { let delegatedAmount: Coin | undefined; try { @@ -417,4 +445,15 @@ export class StargateClient { }; }); } + + /** + * Function to sum up coins with type Coin + */ + private addCoins(lhs: Coin, rhs: Coin): Coin { + if (lhs.denom !== rhs.denom) throw new Error("Trying to add two coins with different demoms"); + return { + amount: Decimal.fromAtomics(lhs.amount, 0).plus(Decimal.fromAtomics(rhs.amount, 0)).atomics, + denom: lhs.denom, + }; + } } From 5d299476bab4e53eabb1af8e7498c1e62f8cdfa0 Mon Sep 17 00:00:00 2001 From: Milan Steiner <69144826+msteiner96@users.noreply.github.com> Date: Wed, 13 Apr 2022 12:43:24 +0200 Subject: [PATCH 2/8] Update packages/stargate/src/stargateclient.ts Co-authored-by: Simon Warta <2603011+webmaster128@users.noreply.github.com> --- packages/stargate/src/stargateclient.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/stargate/src/stargateclient.ts b/packages/stargate/src/stargateclient.ts index af3da369..5e4d1aee 100644 --- a/packages/stargate/src/stargateclient.ts +++ b/packages/stargate/src/stargateclient.ts @@ -1,7 +1,6 @@ /* eslint-disable @typescript-eslint/naming-convention */ import { toHex } from "@cosmjs/encoding"; -import { Uint53 } from "@cosmjs/math"; -import { Decimal } from "@cosmjs/math"; +import { Decimal, Uint53 } from "@cosmjs/math"; import { HttpEndpoint, Tendermint34Client, toRfc3339WithNanoseconds } from "@cosmjs/tendermint-rpc"; import { assert, sleep } from "@cosmjs/utils"; import { MsgData } from "cosmjs-types/cosmos/base/abci/v1beta1/abci"; From 194c9223393058ee1d29197130995ca9b03a5e52 Mon Sep 17 00:00:00 2001 From: Milan Steiner <69144826+msteiner96@users.noreply.github.com> Date: Wed, 13 Apr 2022 12:43:35 +0200 Subject: [PATCH 3/8] Update packages/stargate/src/stargateclient.ts Co-authored-by: Simon Warta <2603011+webmaster128@users.noreply.github.com> --- packages/stargate/src/stargateclient.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/stargate/src/stargateclient.ts b/packages/stargate/src/stargateclient.ts index 5e4d1aee..0f259f3c 100644 --- a/packages/stargate/src/stargateclient.ts +++ b/packages/stargate/src/stargateclient.ts @@ -285,7 +285,7 @@ export class StargateClient { const loadedDelegations = delegationResponses || []; allDelegations.push(...loadedDelegations); startAtKey = pagination?.nextKey; - } while (startAtKey?.length !== 0 && startAtKey !== undefined); + } while (startAtKey !== undefined && startAtKey.length !== 0); const sumValues = allDelegations.reduce( (previousValue: Coin | null, currentValue: DelegationResponse): Coin => { From 342210aac844c573c1f115655227bb20c66f2eaa Mon Sep 17 00:00:00 2001 From: Milan Steiner <69144826+msteiner96@users.noreply.github.com> Date: Wed, 13 Apr 2022 12:43:42 +0200 Subject: [PATCH 4/8] Update packages/stargate/src/stargateclient.ts Co-authored-by: Simon Warta <2603011+webmaster128@users.noreply.github.com> --- packages/stargate/src/stargateclient.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/stargate/src/stargateclient.ts b/packages/stargate/src/stargateclient.ts index 0f259f3c..9a1ccf12 100644 --- a/packages/stargate/src/stargateclient.ts +++ b/packages/stargate/src/stargateclient.ts @@ -289,6 +289,7 @@ export class StargateClient { const sumValues = allDelegations.reduce( (previousValue: Coin | null, currentValue: DelegationResponse): Coin => { + // Safe because field is set to non-nullable (https://github.com/cosmos/cosmos-sdk/blob/v0.45.3/proto/cosmos/staking/v1beta1/staking.proto#L295) assert(currentValue.balance); return previousValue !== null ? this.addCoins(previousValue, currentValue.balance) From daa484d03ee881429528b97ea55ac57bb924c4cf Mon Sep 17 00:00:00 2001 From: Milan Steiner Date: Wed, 13 Apr 2022 12:51:12 +0200 Subject: [PATCH 5/8] Moving addCoins() to amino/coins --- packages/amino/src/coins.ts | 14 ++++++++++++-- packages/amino/src/index.ts | 2 +- packages/stargate/src/stargateclient.ts | 18 +++--------------- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/packages/amino/src/coins.ts b/packages/amino/src/coins.ts index 21554904..702fb2af 100644 --- a/packages/amino/src/coins.ts +++ b/packages/amino/src/coins.ts @@ -1,5 +1,4 @@ -import { Uint53, Uint64 } from "@cosmjs/math"; - +import { Decimal, Uint53, Uint64 } from "@cosmjs/math"; export interface Coin { readonly denom: string; readonly amount: string; @@ -68,3 +67,14 @@ export function parseCoins(input: string): Coin[] { }; }); } + +/** + * Function to sum up coins with type Coin + */ +export function addCoins(lhs: Coin, rhs: Coin): Coin { + if (lhs.denom !== rhs.denom) throw new Error("Trying to add two coins with different demoms"); + return { + amount: Decimal.fromAtomics(lhs.amount, 0).plus(Decimal.fromAtomics(rhs.amount, 0)).atomics, + denom: lhs.denom, + }; +} diff --git a/packages/amino/src/index.ts b/packages/amino/src/index.ts index aa235722..d273be77 100644 --- a/packages/amino/src/index.ts +++ b/packages/amino/src/index.ts @@ -4,7 +4,7 @@ export { rawEd25519PubkeyToRawAddress, rawSecp256k1PubkeyToRawAddress, } from "./addresses"; -export { Coin, coin, coins, parseCoins } from "./coins"; +export { addCoins, Coin, coin, coins, parseCoins } from "./coins"; export { decodeAminoPubkey, decodeBech32Pubkey, diff --git a/packages/stargate/src/stargateclient.ts b/packages/stargate/src/stargateclient.ts index 9a1ccf12..f97fe3c3 100644 --- a/packages/stargate/src/stargateclient.ts +++ b/packages/stargate/src/stargateclient.ts @@ -1,6 +1,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ +import { addCoins } from "@cosmjs/amino"; import { toHex } from "@cosmjs/encoding"; -import { Decimal, Uint53 } from "@cosmjs/math"; +import { Uint53 } from "@cosmjs/math"; import { HttpEndpoint, Tendermint34Client, toRfc3339WithNanoseconds } from "@cosmjs/tendermint-rpc"; import { assert, sleep } from "@cosmjs/utils"; import { MsgData } from "cosmjs-types/cosmos/base/abci/v1beta1/abci"; @@ -291,9 +292,7 @@ export class StargateClient { (previousValue: Coin | null, currentValue: DelegationResponse): Coin => { // Safe because field is set to non-nullable (https://github.com/cosmos/cosmos-sdk/blob/v0.45.3/proto/cosmos/staking/v1beta1/staking.proto#L295) assert(currentValue.balance); - return previousValue !== null - ? this.addCoins(previousValue, currentValue.balance) - : currentValue.balance; + return previousValue !== null ? addCoins(previousValue, currentValue.balance) : currentValue.balance; }, null, ); @@ -445,15 +444,4 @@ export class StargateClient { }; }); } - - /** - * Function to sum up coins with type Coin - */ - private addCoins(lhs: Coin, rhs: Coin): Coin { - if (lhs.denom !== rhs.denom) throw new Error("Trying to add two coins with different demoms"); - return { - amount: Decimal.fromAtomics(lhs.amount, 0).plus(Decimal.fromAtomics(rhs.amount, 0)).atomics, - denom: lhs.denom, - }; - } } From 345bc52d0241ae1868a0fe9087b6119f9135a882 Mon Sep 17 00:00:00 2001 From: Milan Steiner Date: Wed, 13 Apr 2022 13:05:56 +0200 Subject: [PATCH 6/8] Adding some tests --- packages/amino/src/coins.spec.ts | 37 +++++++++++++++++++- packages/stargate/src/stargateclient.spec.ts | 2 +- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/packages/amino/src/coins.spec.ts b/packages/amino/src/coins.spec.ts index 133d14fc..c80a57fc 100644 --- a/packages/amino/src/coins.spec.ts +++ b/packages/amino/src/coins.spec.ts @@ -1,4 +1,4 @@ -import { coin, coins, parseCoins } from "./coins"; +import { addCoins, coin, coins, parseCoins } from "./coins"; describe("coins", () => { describe("coin", () => { @@ -138,4 +138,39 @@ describe("coins", () => { expect(() => parseCoins("ucosm")).toThrowError(/invalid coin string/i); }); }); + + describe("addCoins", () => { + it("works with same denom", () => { + const balance1 = { + amount: "10000", + denom: "utest", + }; + + const balance2 = { + amount: "20000", + denom: "utest", + }; + + const expectedBalance = { + amount: "30000", + denom: "utest", + }; + expect(addCoins(balance1, balance2)).toEqual(expectedBalance); + }); + + it("works with different denoms", () => { + const balance1 = { + amount: "10000", + denom: "utest", + }; + + const balance2 = { + amount: "20000", + denom: "ucosm", + }; + expect(() => addCoins(balance1, balance2)).toThrowError( + /Trying to add two coins with different demoms/i, + ); + }); + }); }); diff --git a/packages/stargate/src/stargateclient.spec.ts b/packages/stargate/src/stargateclient.spec.ts index 65caee1c..444c078e 100644 --- a/packages/stargate/src/stargateclient.spec.ts +++ b/packages/stargate/src/stargateclient.spec.ts @@ -263,7 +263,7 @@ describe("StargateClient", () => { const client = await StargateClient.connect(simapp.tendermintUrl); const response = await client.getBalanceStaked(faucet.address0); - expect(response).toEqual({ denom: "ustake", amount: "190422" }); + expect(response).toEqual({ denom: "ustake", amount: "63474" }); }); }); From 65c39313c174aa56d14c7ae68f4f94c3e03ca9e0 Mon Sep 17 00:00:00 2001 From: Milan Steiner Date: Wed, 13 Apr 2022 13:10:26 +0200 Subject: [PATCH 7/8] Fix typo --- packages/amino/src/coins.spec.ts | 2 +- packages/amino/src/coins.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/amino/src/coins.spec.ts b/packages/amino/src/coins.spec.ts index c80a57fc..e8f67f69 100644 --- a/packages/amino/src/coins.spec.ts +++ b/packages/amino/src/coins.spec.ts @@ -169,7 +169,7 @@ describe("coins", () => { denom: "ucosm", }; expect(() => addCoins(balance1, balance2)).toThrowError( - /Trying to add two coins with different demoms/i, + /Trying to add two coins with different denoms/i, ); }); }); diff --git a/packages/amino/src/coins.ts b/packages/amino/src/coins.ts index 702fb2af..23a6ae22 100644 --- a/packages/amino/src/coins.ts +++ b/packages/amino/src/coins.ts @@ -72,7 +72,7 @@ export function parseCoins(input: string): Coin[] { * Function to sum up coins with type Coin */ export function addCoins(lhs: Coin, rhs: Coin): Coin { - if (lhs.denom !== rhs.denom) throw new Error("Trying to add two coins with different demoms"); + if (lhs.denom !== rhs.denom) throw new Error("Trying to add two coins with different denoms"); return { amount: Decimal.fromAtomics(lhs.amount, 0).plus(Decimal.fromAtomics(rhs.amount, 0)).atomics, denom: lhs.denom, From 426c9b451abcd0c4b99083a760b411178788df2a Mon Sep 17 00:00:00 2001 From: Milan Steiner Date: Wed, 13 Apr 2022 14:28:20 +0200 Subject: [PATCH 8/8] Add changelog entry --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2bc18d85..4a72de0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to ### Added - @cosmjs/math: Add `Decimal.zero` and `Decimal.one` ([#1110]). +- @cosmjs/amino: Add `addCoins` ([#1116]) +- @cosmjs/stargate: Add `StargateClient.getBalanceStaked()` to query the sum of all staked balance. ([#1116]) ### Changed @@ -27,6 +29,7 @@ and this project adheres to [#1110]: https://github.com/cosmos/cosmjs/issues/1110 [#1120]: https://github.com/cosmos/cosmjs/pull/1120 [#1121]: https://github.com/cosmos/cosmjs/pull/1121 +[#1116]: https://github.com/cosmos/cosmjs/issues/1116 ## [0.28.3] - 2022-04-11