@vultisig/core-chain 2.3.0 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/chains/cosmos/account/getCosmosAccountInfo.d.ts.map +1 -1
- package/dist/chains/cosmos/account/getCosmosAccountInfo.js +53 -4
- package/dist/chains/cosmos/account/getCosmosAccountInfo.js.map +1 -1
- package/dist/coin/balance/resolvers/cosmos.d.ts.map +1 -1
- package/dist/coin/balance/resolvers/cosmos.js +43 -2
- package/dist/coin/balance/resolvers/cosmos.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @vultisig/core-chain
|
|
2
2
|
|
|
3
|
+
## 2.3.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#579](https://github.com/vultisig/vultisig-sdk/pull/579) [`c3881e5`](https://github.com/vultisig/vultisig-sdk/commit/c3881e549e5678e8806eba5defb2d2d6eefc2cc5) Thanks [@gomesalexandre](https://github.com/gomesalexandre)! - ## Fixed
|
|
8
|
+
- Cosmos account info LCD fallback for extended account types that StargateClient cannot decode (vesting wrappers, module accounts) — prevents doomed txs with `sequence:0` that fail at broadcast with `account sequence mismatch, expected N, got 0` ([#579](https://github.com/vultisig/vultisig-sdk/issues/579))
|
|
9
|
+
- Cosmos coin balance LCD fallback when StargateClient returns `amount:"0"` on a funded address — fixes a packaging-level discrepancy in cosmjs's HTTP layer under Hermes/React Native that silently surfaced as "you have 0" on funded Terra/TerraClassic wallets ([#579](https://github.com/vultisig/vultisig-sdk/issues/579))
|
|
10
|
+
|
|
3
11
|
## 2.3.0
|
|
4
12
|
|
|
5
13
|
### Minor Changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getCosmosAccountInfo.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/cosmos/account/getCosmosAccountInfo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAA;
|
|
1
|
+
{"version":3,"file":"getCosmosAccountInfo.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/cosmos/account/getCosmosAccountInfo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAA;AAsEhE,eAAO,MAAM,oBAAoB,GAAU,oBAAoB,YAAY,CAAC,WAAW,CAAC;;;;;;EAgCvF,CAAA"}
|
|
@@ -1,8 +1,57 @@
|
|
|
1
1
|
import { getCosmosClient } from '@vultisig/core-chain/chains/cosmos/client';
|
|
2
|
+
import { cosmosRpcUrl } from '@vultisig/core-chain/chains/cosmos/cosmosRpcUrl';
|
|
3
|
+
import { queryUrl } from '@vultisig/lib-utils/query/queryUrl';
|
|
4
|
+
const parseLcdAccount = (resp) => {
|
|
5
|
+
const acc = resp.account;
|
|
6
|
+
if (!acc)
|
|
7
|
+
return null;
|
|
8
|
+
const base = acc.base_vesting_account?.base_account ?? acc.base_account ?? acc;
|
|
9
|
+
const accountNumber = Number(base.account_number ?? '0');
|
|
10
|
+
const sequence = Number(base.sequence ?? '0');
|
|
11
|
+
if (!Number.isFinite(accountNumber) || !Number.isFinite(sequence))
|
|
12
|
+
return null;
|
|
13
|
+
return { accountNumber, sequence };
|
|
14
|
+
};
|
|
15
|
+
// LCD fallback for Tendermint-RPC account lookups that return null.
|
|
16
|
+
// Native @cosmjs/stargate.getAccount() returns null in TWO indistinguishable
|
|
17
|
+
// cases: (1) account genuinely doesn't exist on-chain, (2) the RPC response
|
|
18
|
+
// couldn't be decoded (custom account type, transient infra, etc.). For a
|
|
19
|
+
// send tx, the sender account MUST exist by definition — falling through
|
|
20
|
+
// to sequence:0 ships a tx guaranteed to fail at broadcast with
|
|
21
|
+
// "account sequence mismatch, expected N, got 0".
|
|
22
|
+
//
|
|
23
|
+
// LCD uses a different infra path (REST vs Tendermint RPC), supports
|
|
24
|
+
// extended account types (vesting, module wrappers) via JSON shape parsing,
|
|
25
|
+
// and gives us a second chance before we ship a doomed tx.
|
|
26
|
+
const fetchAccountViaLcd = async (chain, address) => {
|
|
27
|
+
const base = cosmosRpcUrl[chain];
|
|
28
|
+
if (!base)
|
|
29
|
+
return null;
|
|
30
|
+
try {
|
|
31
|
+
const resp = await queryUrl(`${base}/cosmos/auth/v1beta1/accounts/${address}`);
|
|
32
|
+
return parseLcdAccount(resp);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// 404 (account not found) or transient LCD error — caller decides.
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
2
39
|
export const getCosmosAccountInfo = async ({ chain, address }) => {
|
|
3
40
|
const client = await getCosmosClient(chain);
|
|
4
|
-
const accountInfo = await client.getAccount(address);
|
|
5
|
-
|
|
41
|
+
const [accountInfo, block] = await Promise.all([client.getAccount(address), client.getBlock()]);
|
|
42
|
+
let accountNumber = accountInfo?.accountNumber;
|
|
43
|
+
let sequence = accountInfo?.sequence;
|
|
44
|
+
// RPC returned null. Try the LCD shape parser before falling back to
|
|
45
|
+
// sequence:0 — that fallback is correct only for accounts that have
|
|
46
|
+
// genuinely never been funded, but ships a doomed tx for the much more
|
|
47
|
+
// common case where RPC just couldn't decode an extended account type.
|
|
48
|
+
if (accountInfo === null) {
|
|
49
|
+
const lcd = await fetchAccountViaLcd(chain, address);
|
|
50
|
+
if (lcd) {
|
|
51
|
+
accountNumber = lcd.accountNumber;
|
|
52
|
+
sequence = lcd.sequence;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
6
55
|
const blockTimestampStr = block.header.time;
|
|
7
56
|
const blockTimestampNs = BigInt(new Date(blockTimestampStr).getTime()) * 1000000n;
|
|
8
57
|
const timeoutNs = blockTimestampNs + 600000000000n; // +10 minutes
|
|
@@ -10,8 +59,8 @@ export const getCosmosAccountInfo = async ({ chain, address }) => {
|
|
|
10
59
|
return {
|
|
11
60
|
address,
|
|
12
61
|
pubkey: accountInfo?.pubkey ?? null,
|
|
13
|
-
accountNumber:
|
|
14
|
-
sequence:
|
|
62
|
+
accountNumber: accountNumber ?? 0,
|
|
63
|
+
sequence: sequence ?? 0,
|
|
15
64
|
latestBlock,
|
|
16
65
|
};
|
|
17
66
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getCosmosAccountInfo.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/cosmos/account/getCosmosAccountInfo.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAA;
|
|
1
|
+
{"version":3,"file":"getCosmosAccountInfo.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/cosmos/account/getCosmosAccountInfo.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cosmos.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/coin/balance/resolvers/cosmos.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;
|
|
1
|
+
{"version":3,"file":"cosmos.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/coin/balance/resolvers/cosmos.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AAUxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAuCjD,eAAO,MAAM,oBAAoB,EAAE,mBAAmB,CAAC,WAAW,CAyBjE,CAAA"}
|
|
@@ -1,7 +1,38 @@
|
|
|
1
1
|
import { getCosmosClient } from '@vultisig/core-chain/chains/cosmos/client';
|
|
2
|
-
import { getCosmosWasmTokenBalanceUrl, isCosmosWasmTokenId } from '@vultisig/core-chain/chains/cosmos/cosmosRpcUrl';
|
|
2
|
+
import { cosmosRpcUrl, getCosmosWasmTokenBalanceUrl, isCosmosWasmTokenId, } from '@vultisig/core-chain/chains/cosmos/cosmosRpcUrl';
|
|
3
3
|
import { getDenom } from '@vultisig/core-chain/coin/utils/getDenom';
|
|
4
4
|
import { queryUrl } from '@vultisig/lib-utils/query/queryUrl';
|
|
5
|
+
// LCD fallback for Tendermint-RPC bank lookups that return 0n. Native
|
|
6
|
+
// @cosmjs/stargate.getBalance() can return `{denom, amount: "0"}` in two
|
|
7
|
+
// indistinguishable cases: (1) the account genuinely holds none of the
|
|
8
|
+
// queried denom, (2) the StargateClient ABCI query path failed to decode
|
|
9
|
+
// the response (Hermes/React-Native packaging discrepancies with cosmjs's
|
|
10
|
+
// internal HTTP layer have produced false-zero returns in production,
|
|
11
|
+
// see Terra/TerraClassic balance discrepancy on iOS sim 2026-05-27 where
|
|
12
|
+
// LCD returned 4_800_000_000 uluna while StargateClient returned 0n for
|
|
13
|
+
// the same address+denom).
|
|
14
|
+
//
|
|
15
|
+
// LCD uses a different infra path (REST vs Tendermint RPC) and gives us
|
|
16
|
+
// a second chance before we ship a "you have 0" UX that contradicts the
|
|
17
|
+
// on-chain reality.
|
|
18
|
+
const fetchBalanceViaLcd = async (chain, address, denom) => {
|
|
19
|
+
const base = cosmosRpcUrl[chain];
|
|
20
|
+
if (!base)
|
|
21
|
+
return null;
|
|
22
|
+
try {
|
|
23
|
+
const resp = await queryUrl(`${base}/cosmos/bank/v1beta1/balances/${address}/by_denom?denom=${encodeURIComponent(denom)}`);
|
|
24
|
+
const amount = resp.balance?.amount;
|
|
25
|
+
if (!amount)
|
|
26
|
+
return null;
|
|
27
|
+
const parsed = BigInt(amount);
|
|
28
|
+
if (parsed < 0n)
|
|
29
|
+
return null;
|
|
30
|
+
return parsed;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
5
36
|
export const getCosmosCoinBalance = async (input) => {
|
|
6
37
|
if (isCosmosWasmTokenId(input.id)) {
|
|
7
38
|
const url = getCosmosWasmTokenBalanceUrl(input);
|
|
@@ -11,6 +42,16 @@ export const getCosmosCoinBalance = async (input) => {
|
|
|
11
42
|
const client = await getCosmosClient(input.chain);
|
|
12
43
|
const denom = getDenom(input);
|
|
13
44
|
const balance = await client.getBalance(input.address, denom);
|
|
14
|
-
|
|
45
|
+
const rpcAmount = BigInt(balance.amount);
|
|
46
|
+
// RPC returned 0 — could be a genuinely empty wallet OR a silent decode
|
|
47
|
+
// failure (cosmjs in Hermes has bitten us here). Confirm via LCD before
|
|
48
|
+
// trusting the zero. If LCD also returns 0 / null, fall through.
|
|
49
|
+
if (rpcAmount === 0n) {
|
|
50
|
+
const lcdAmount = await fetchBalanceViaLcd(input.chain, input.address, denom);
|
|
51
|
+
if (lcdAmount !== null && lcdAmount > 0n) {
|
|
52
|
+
return lcdAmount;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return rpcAmount;
|
|
15
56
|
};
|
|
16
57
|
//# sourceMappingURL=cosmos.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cosmos.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/coin/balance/resolvers/cosmos.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAA;AAC3E,OAAO,
|
|
1
|
+
{"version":3,"file":"cosmos.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/coin/balance/resolvers/cosmos.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAA;AAC3E,OAAO,EACL,YAAY,EACZ,4BAA4B,EAC5B,mBAAmB,GACpB,MAAM,iDAAiD,CAAA;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,0CAA0C,CAAA;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAA;AAW7D,sEAAsE;AACtE,yEAAyE;AACzE,uEAAuE;AACvE,yEAAyE;AACzE,0EAA0E;AAC1E,sEAAsE;AACtE,yEAAyE;AACzE,wEAAwE;AACxE,2BAA2B;AAC3B,EAAE;AACF,wEAAwE;AACxE,wEAAwE;AACxE,oBAAoB;AACpB,MAAM,kBAAkB,GAAG,KAAK,EAAE,KAAkB,EAAE,OAAe,EAAE,KAAa,EAA0B,EAAE;IAC9G,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,CAAA;IAChC,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAA;IACtB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CACzB,GAAG,IAAI,iCAAiC,OAAO,mBAAmB,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAC9F,CAAA;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,MAAM,CAAA;QACnC,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAA;QACxB,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAA;QAC7B,IAAI,MAAM,GAAG,EAAE;YAAE,OAAO,IAAI,CAAA;QAC5B,OAAO,MAAM,CAAA;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAqC,KAAK,EAAC,KAAK,EAAC,EAAE;IAClF,IAAI,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;QAClC,MAAM,GAAG,GAAG,4BAA4B,CAAC,KAAK,CAAC,CAAA;QAC/C,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,QAAQ,CAAoB,GAAG,CAAC,CAAA;QACvD,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,CAAA;IAClC,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IAEjD,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAE7B,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;IAC7D,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IAExC,wEAAwE;IACxE,wEAAwE;IACxE,iEAAiE;IACjE,IAAI,SAAS,KAAK,EAAE,EAAE,CAAC;QACrB,MAAM,SAAS,GAAG,MAAM,kBAAkB,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QAC7E,IAAI,SAAS,KAAK,IAAI,IAAI,SAAS,GAAG,EAAE,EAAE,CAAC;YACzC,OAAO,SAAS,CAAA;QAClB,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAA;AAClB,CAAC,CAAA"}
|