@vultisig/core-chain 2.28.0 → 2.29.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.
Files changed (78) hide show
  1. package/CHANGELOG.md +138 -0
  2. package/dist/chains/cosmos/cosmosGasLimitRecord.js +3 -3
  3. package/dist/chains/cosmos/cosmosGasLimitRecord.js.map +1 -1
  4. package/dist/chains/cosmos/gas.d.ts +28 -1
  5. package/dist/chains/cosmos/gas.d.ts.map +1 -1
  6. package/dist/chains/cosmos/gas.js +37 -5
  7. package/dist/chains/cosmos/gas.js.map +1 -1
  8. package/dist/chains/cosmos/resolveCosmosGasLimit.d.ts +82 -0
  9. package/dist/chains/cosmos/resolveCosmosGasLimit.d.ts.map +1 -0
  10. package/dist/chains/cosmos/resolveCosmosGasLimit.js +71 -0
  11. package/dist/chains/cosmos/resolveCosmosGasLimit.js.map +1 -0
  12. package/dist/chains/cosmos/terraClassicTax.d.ts +68 -0
  13. package/dist/chains/cosmos/terraClassicTax.d.ts.map +1 -1
  14. package/dist/chains/cosmos/terraClassicTax.js +85 -0
  15. package/dist/chains/cosmos/terraClassicTax.js.map +1 -1
  16. package/dist/chains/sui/client.d.ts +11 -2
  17. package/dist/chains/sui/client.d.ts.map +1 -1
  18. package/dist/chains/sui/client.js +5 -4
  19. package/dist/chains/sui/client.js.map +1 -1
  20. package/dist/chains/sui/config.d.ts +28 -0
  21. package/dist/chains/sui/config.d.ts.map +1 -1
  22. package/dist/chains/sui/config.js +27 -0
  23. package/dist/chains/sui/config.js.map +1 -1
  24. package/dist/chains/sui/listAllCoins.d.ts +44 -0
  25. package/dist/chains/sui/listAllCoins.d.ts.map +1 -0
  26. package/dist/chains/sui/listAllCoins.js +43 -0
  27. package/dist/chains/sui/listAllCoins.js.map +1 -0
  28. package/dist/chains/sui/transactionResult.d.ts +59 -0
  29. package/dist/chains/sui/transactionResult.d.ts.map +1 -0
  30. package/dist/chains/sui/transactionResult.js +43 -0
  31. package/dist/chains/sui/transactionResult.js.map +1 -0
  32. package/dist/coin/balance/resolvers/sui.d.ts.map +1 -1
  33. package/dist/coin/balance/resolvers/sui.js +6 -3
  34. package/dist/coin/balance/resolvers/sui.js.map +1 -1
  35. package/dist/coin/token/metadata/chains.d.ts +1 -1
  36. package/dist/coin/token/metadata/chains.d.ts.map +1 -1
  37. package/dist/coin/token/metadata/chains.js +1 -0
  38. package/dist/coin/token/metadata/chains.js.map +1 -1
  39. package/dist/coin/token/metadata/index.d.ts.map +1 -1
  40. package/dist/coin/token/metadata/index.js +2 -0
  41. package/dist/coin/token/metadata/index.js.map +1 -1
  42. package/dist/coin/token/metadata/resolvers/ripple.d.ts +17 -0
  43. package/dist/coin/token/metadata/resolvers/ripple.d.ts.map +1 -0
  44. package/dist/coin/token/metadata/resolvers/ripple.js +44 -0
  45. package/dist/coin/token/metadata/resolvers/ripple.js.map +1 -0
  46. package/dist/coin/token/metadata/resolvers/sui.d.ts +1 -1
  47. package/dist/coin/token/metadata/resolvers/sui.d.ts.map +1 -1
  48. package/dist/coin/token/metadata/resolvers/sui.js +6 -3
  49. package/dist/coin/token/metadata/resolvers/sui.js.map +1 -1
  50. package/dist/swap/general/jupiter/api/getJupiterSwapQuote.d.ts.map +1 -1
  51. package/dist/swap/general/jupiter/api/getJupiterSwapQuote.js +2 -1
  52. package/dist/swap/general/jupiter/api/getJupiterSwapQuote.js.map +1 -1
  53. package/dist/swap/native/limitSwapMemo.d.ts +35 -5
  54. package/dist/swap/native/limitSwapMemo.d.ts.map +1 -1
  55. package/dist/swap/native/limitSwapMemo.js +32 -7
  56. package/dist/swap/native/limitSwapMemo.js.map +1 -1
  57. package/dist/tx/broadcast/resolvers/sui.d.ts +2 -8
  58. package/dist/tx/broadcast/resolvers/sui.d.ts.map +1 -1
  59. package/dist/tx/broadcast/resolvers/sui.js +18 -17
  60. package/dist/tx/broadcast/resolvers/sui.js.map +1 -1
  61. package/dist/tx/broadcast/transientRetry.d.ts.map +1 -1
  62. package/dist/tx/broadcast/transientRetry.js +30 -2
  63. package/dist/tx/broadcast/transientRetry.js.map +1 -1
  64. package/dist/tx/hash/resolvers/sui.d.ts.map +1 -1
  65. package/dist/tx/hash/resolvers/sui.js +13 -3
  66. package/dist/tx/hash/resolvers/sui.js.map +1 -1
  67. package/dist/tx/status/resolvers/sui.d.ts.map +1 -1
  68. package/dist/tx/status/resolvers/sui.js +15 -6
  69. package/dist/tx/status/resolvers/sui.js.map +1 -1
  70. package/dist/utils/isValidTokenId.d.ts +11 -0
  71. package/dist/utils/isValidTokenId.d.ts.map +1 -1
  72. package/dist/utils/isValidTokenId.js +31 -2
  73. package/dist/utils/isValidTokenId.js.map +1 -1
  74. package/package.json +22 -7
  75. package/dist/chains/cosmos/resolveCosmosGasFee.d.ts +0 -49
  76. package/dist/chains/cosmos/resolveCosmosGasFee.d.ts.map +0 -1
  77. package/dist/chains/cosmos/resolveCosmosGasFee.js +0 -35
  78. package/dist/chains/cosmos/resolveCosmosGasFee.js.map +0 -1
@@ -25,6 +25,7 @@
25
25
  * `getTerraClassicTaxCaps(denom)` calls are safe to memoize — the rate
26
26
  * does not change mid-tx.
27
27
  */
28
+ import { attempt } from '@vultisig/lib-utils/attempt';
28
29
  import { Chain } from '../../Chain.js';
29
30
  import { cosmosRpcUrl } from './cosmosRpcUrl.js';
30
31
  // ---------------------------------------------------------------------------
@@ -39,6 +40,23 @@ import { cosmosRpcUrl } from './cosmosRpcUrl.js';
39
40
  * Reference: terra-money/classic-core, x/treasury REST routes.
40
41
  */
41
42
  export const getTerraClassicTaxRateUrl = () => `${cosmosRpcUrl[Chain.TerraClassic]}/terra/treasury/v1beta1/tax_rate`;
43
+ /**
44
+ * The `x/tax` module params, which carry `burn_tax_rate` — a DIFFERENT tax
45
+ * from the `x/treasury` `tax_rate` above, and the one that is actually live.
46
+ *
47
+ * | module | field | live value | exempts uluna? |
48
+ * |--------------|-----------------|------------|----------------|
49
+ * | `x/treasury` | `tax_rate` | 0 | yes |
50
+ * | `x/tax` | `burn_tax_rate` | 0.005 | NO |
51
+ *
52
+ * The treasury stability tax has been paused by governance since the UST
53
+ * collapse; the burn tax replaced it and applies to `uluna` transfers too —
54
+ * burning LUNC is its entire purpose. Reading the treasury endpoint for a
55
+ * LUNC send therefore always yields 0 and undercharges the fee.
56
+ *
57
+ * Same endpoint iOS (`CosmosAPI.terraClassicTaxParams`) and Android read.
58
+ */
59
+ export const getTerraClassicBurnTaxParamsUrl = () => `${cosmosRpcUrl[Chain.TerraClassic]}/terra/tax/v1beta1/params`;
42
60
  export const getTerraClassicTaxCapsUrl = (denom) =>
43
61
  // URL-encode the denom: `ibc/<HASH>` and `factory/<addr>/<subdenom>` carry
44
62
  // forward-slashes that would otherwise become extra path segments and the
@@ -55,6 +73,24 @@ export const getTerraClassicTaxCapsUrl = (denom) =>
55
73
  * tax in base units of the same denom.
56
74
  */
57
75
  export const TERRA_CLASSIC_TAX_DEC_SCALE = 10n ** 18n;
76
+ /**
77
+ * Conservative fallback burn-tax rate (0.5%) used when the live `x/tax`
78
+ * params can't be fetched or parsed. Failing CLOSED (taxing) rather than open
79
+ * (0%) avoids signing a tx the chain then rejects at broadcast — an overpaid
80
+ * fee is recoverable, a rejected transfer wastes the gas and moves nothing.
81
+ *
82
+ * Mirrors iOS / Android `TerraClassicTax.fallbackBurnTaxRate`.
83
+ */
84
+ export const TERRA_CLASSIC_FALLBACK_BURN_TAX_RATE = 5000000000000000n; // 0.005
85
+ /**
86
+ * Sanity ceiling (10%) for a parsed burn-tax rate. The rate is
87
+ * governance-controlled and has historically been ≤ 1.2%, so anything above
88
+ * this is treated as garbage — a malformed `"5"` meaning 500% would otherwise
89
+ * be applied literally and drain the account into the fee. Keeps the fail-safe
90
+ * symmetric with the lower bound, so a bad endpoint can neither under- nor
91
+ * massively over-charge. Mirrors iOS / Android `maxBurnTaxRate`.
92
+ */
93
+ export const TERRA_CLASSIC_MAX_BURN_TAX_RATE = 100000000000000000n; // 0.1
58
94
  async function lcdGetJson(url, opts) {
59
95
  const f = opts.fetchImpl ?? fetch;
60
96
  const res = await f(url, { signal: opts.signal });
@@ -116,6 +152,55 @@ export async function getTerraClassicTaxRate(opts = {}) {
116
152
  }
117
153
  return parseDecToFixed18(raw.tax_rate);
118
154
  }
155
+ /**
156
+ * Parses an `x/tax` `burn_tax_rate` Dec string into an 18-decimal fixed-point
157
+ * bigint, falling back to {@link TERRA_CLASSIC_FALLBACK_BURN_TAX_RATE} on a
158
+ * missing, malformed, negative, or implausibly large value.
159
+ *
160
+ * Never throws. Unlike the treasury `tax_rate` — where a missing field means
161
+ * "the LCD is broken, refuse to guess" — a missing burn rate has a known-safe
162
+ * answer (the current governance rate), and the initiator is the only device
163
+ * that computes this. Mirrors iOS / Android `TerraClassicTax.parseRate`.
164
+ */
165
+ export const parseTerraClassicBurnTaxRate = (raw) => {
166
+ if (raw === null || raw === undefined)
167
+ return TERRA_CLASSIC_FALLBACK_BURN_TAX_RATE;
168
+ const parsed = attempt(() => parseDecToFixed18(raw));
169
+ if ('error' in parsed)
170
+ return TERRA_CLASSIC_FALLBACK_BURN_TAX_RATE;
171
+ return parsed.data > TERRA_CLASSIC_MAX_BURN_TAX_RATE ? TERRA_CLASSIC_FALLBACK_BURN_TAX_RATE : parsed.data;
172
+ };
173
+ /**
174
+ * Fetches the live `x/tax` burn-tax rate as an 18-decimal fixed-point bigint
175
+ * (`5_000_000_000_000_000n` for the current 0.5%).
176
+ *
177
+ * Fails closed to {@link TERRA_CLASSIC_FALLBACK_BURN_TAX_RATE} on any LCD
178
+ * error, so a network blip produces a slightly overpaid fee rather than a tx
179
+ * the ante handler rejects.
180
+ */
181
+ export async function getTerraClassicBurnTaxRate(opts = {}) {
182
+ const result = await attempt(() => lcdGetJson(getTerraClassicBurnTaxParamsUrl(), opts));
183
+ if ('error' in result)
184
+ return TERRA_CLASSIC_FALLBACK_BURN_TAX_RATE;
185
+ return parseTerraClassicBurnTaxRate(result.data.params?.burn_tax_rate);
186
+ }
187
+ /**
188
+ * Burn tax on a `amount` of the send denom, at an 18-decimal fixed-point
189
+ * `rate`, rounded UP so the signed fee never lands a base unit below the
190
+ * chain's check.
191
+ *
192
+ * Deliberately NOT {@link applyTerraClassicTax}: that models the treasury
193
+ * stability tax, which exempts `uluna` and applies per-denom caps. The burn
194
+ * tax exempts nothing and is uncapped — feeding a LUNC send through the
195
+ * treasury helper silently returns `0n`.
196
+ *
197
+ * Mirrors iOS / Android `TerraClassicTax.burnTax` (both round up).
198
+ */
199
+ export const applyTerraClassicBurnTax = (amount, rate) => {
200
+ if (amount <= 0n || rate <= 0n)
201
+ return 0n;
202
+ return (amount * rate + TERRA_CLASSIC_TAX_DEC_SCALE - 1n) / TERRA_CLASSIC_TAX_DEC_SCALE;
203
+ };
119
204
  /**
120
205
  * Fetches the per-denom tax cap as a base-unit bigint (e.g.
121
206
  * `60_000_000_000_000_000n` for `uluna`). The cap is the maximum tax that
@@ -1 +1 @@
1
- {"version":3,"file":"terraClassicTax.js","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/cosmos/terraClassicTax.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"terraClassicTax.js","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/cosmos/terraClassicTax.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,12 @@
1
- import { SuiJsonRpcClient } from '@mysten/sui/jsonRpc';
2
- export declare const getSuiClient: () => SuiJsonRpcClient;
1
+ import { SuiGrpcClient } from '@mysten/sui/grpc';
2
+ /**
3
+ * The Sui client every callsite programs against.
4
+ *
5
+ * `SuiGrpcClient` and `SuiGraphQLClient` both implement
6
+ * `SuiClientTypes.TransportMethods`, so the React Native override
7
+ * (`platforms/react-native/overrides/suiClient.ts`) can swap in the GraphQL
8
+ * client without touching a single caller.
9
+ */
10
+ export type SuiClient = SuiGrpcClient;
11
+ export declare const getSuiClient: () => SuiClient;
3
12
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/sui/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAGtD,eAAO,MAAM,YAAY,wBAMxB,CAAA"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/sui/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAKhD;;;;;;;GAOG;AACH,MAAM,MAAM,SAAS,GAAG,aAAa,CAAA;AAErC,eAAO,MAAM,YAAY,QACnB,SAKL,CAAA"}
@@ -1,7 +1,8 @@
1
- import { SuiJsonRpcClient } from '@mysten/sui/jsonRpc';
1
+ import { SuiGrpcClient } from '@mysten/sui/grpc';
2
2
  import { memoize } from '@vultisig/lib-utils/memoize';
3
- export const getSuiClient = memoize(() => new SuiJsonRpcClient({
4
- url: 'https://sui-rpc.publicnode.com',
5
- network: 'mainnet',
3
+ import { suiGrpcUrl, suiNetwork } from './config.js';
4
+ export const getSuiClient = memoize(() => new SuiGrpcClient({
5
+ network: suiNetwork,
6
+ baseUrl: suiGrpcUrl,
6
7
  }));
7
8
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/sui/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAA;AAErD,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CACjC,GAAG,EAAE,CACH,IAAI,gBAAgB,CAAC;IACnB,GAAG,EAAE,gCAAgC;IACrC,OAAO,EAAE,SAAS;CACnB,CAAC,CACL,CAAA"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/sui/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAA;AAErD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAYjD,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CACjC,GAAc,EAAE,CACd,IAAI,aAAa,CAAC;IAChB,OAAO,EAAE,UAAU;IACnB,OAAO,EAAE,UAAU;CACpB,CAAC,CACL,CAAA"}
@@ -1,3 +1,31 @@
1
+ import type { SuiClientTypes } from '@mysten/sui/client';
1
2
  export declare const suiGasBudget = 3000000n;
2
3
  export declare const suiMinGasBudget = 2000n;
4
+ export declare const suiNetwork: SuiClientTypes.Network;
5
+ /**
6
+ * Sui full node gRPC endpoint (grpc-web over HTTPS).
7
+ *
8
+ * Sui is retiring JSON-RPC: shutdown on Foundation mainnet full nodes began the
9
+ * week of 2026-07-27 and full decommission (code removal) lands mid-October
10
+ * 2026, after which no provider can serve it. gRPC and GraphQL RPC are the
11
+ * supported replacements, so every Sui read/simulate/execute in this repo goes
12
+ * through one of them. (JSON-RPC still answered on 2026-07-27 — this is a
13
+ * migration ahead of the deadline, not a response to a live outage.)
14
+ *
15
+ * The previously-used `sui-rpc.publicnode.com` is JSON-RPC only — it answers
16
+ * nothing over gRPC — so the endpoint moves to the Foundation full node.
17
+ */
18
+ export declare const suiGrpcUrl = "https://fullnode.mainnet.sui.io:443";
19
+ /**
20
+ * Sui GraphQL RPC endpoint.
21
+ *
22
+ * Used on React Native: `@mysten/sui`'s gRPC client speaks grpc-web through
23
+ * `GrpcWebFetchTransport`, which reads `Response.body` as a `ReadableStream`.
24
+ * Hermes' XHR-backed `fetch` exposes no `Response.body`, so grpc-web throws
25
+ * "missing response body" there. GraphQL RPC is a plain JSON POST and exposes
26
+ * the exact same unified client surface (`SuiClientTypes.TransportMethods`),
27
+ * so RN keeps identical call sites. See
28
+ * `packages/sdk/src/platforms/react-native/overrides/suiClient.ts`.
29
+ */
30
+ export declare const suiGraphqlUrl = "https://graphql.mainnet.sui.io/graphql";
3
31
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/sui/config.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,WAAY,CAAA;AACrC,eAAO,MAAM,eAAe,QAAQ,CAAA"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/sui/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAExD,eAAO,MAAM,YAAY,WAAY,CAAA;AACrC,eAAO,MAAM,eAAe,QAAQ,CAAA;AAEpC,eAAO,MAAM,UAAU,EAAE,cAAc,CAAC,OAAmB,CAAA;AAE3D;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,UAAU,wCAAwC,CAAA;AAE/D;;;;;;;;;;GAUG;AACH,eAAO,MAAM,aAAa,2CAA2C,CAAA"}
@@ -1,3 +1,30 @@
1
1
  export const suiGasBudget = 3000000n;
2
2
  export const suiMinGasBudget = 2000n;
3
+ export const suiNetwork = 'mainnet';
4
+ /**
5
+ * Sui full node gRPC endpoint (grpc-web over HTTPS).
6
+ *
7
+ * Sui is retiring JSON-RPC: shutdown on Foundation mainnet full nodes began the
8
+ * week of 2026-07-27 and full decommission (code removal) lands mid-October
9
+ * 2026, after which no provider can serve it. gRPC and GraphQL RPC are the
10
+ * supported replacements, so every Sui read/simulate/execute in this repo goes
11
+ * through one of them. (JSON-RPC still answered on 2026-07-27 — this is a
12
+ * migration ahead of the deadline, not a response to a live outage.)
13
+ *
14
+ * The previously-used `sui-rpc.publicnode.com` is JSON-RPC only — it answers
15
+ * nothing over gRPC — so the endpoint moves to the Foundation full node.
16
+ */
17
+ export const suiGrpcUrl = 'https://fullnode.mainnet.sui.io:443';
18
+ /**
19
+ * Sui GraphQL RPC endpoint.
20
+ *
21
+ * Used on React Native: `@mysten/sui`'s gRPC client speaks grpc-web through
22
+ * `GrpcWebFetchTransport`, which reads `Response.body` as a `ReadableStream`.
23
+ * Hermes' XHR-backed `fetch` exposes no `Response.body`, so grpc-web throws
24
+ * "missing response body" there. GraphQL RPC is a plain JSON POST and exposes
25
+ * the exact same unified client surface (`SuiClientTypes.TransportMethods`),
26
+ * so RN keeps identical call sites. See
27
+ * `packages/sdk/src/platforms/react-native/overrides/suiClient.ts`.
28
+ */
29
+ export const suiGraphqlUrl = 'https://graphql.mainnet.sui.io/graphql';
3
30
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/sui/config.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,YAAY,GAAG,QAAS,CAAA;AACrC,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAA"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/sui/config.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,YAAY,GAAG,QAAS,CAAA;AACrC,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAA;AAEpC,MAAM,CAAC,MAAM,UAAU,GAA2B,SAAS,CAAA;AAE3D;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,qCAAqC,CAAA;AAE/D;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,wCAAwC,CAAA"}
@@ -0,0 +1,44 @@
1
+ import type { SuiClient } from './client.js';
2
+ /**
3
+ * A coin object flattened into the shape the keysign payload stores.
4
+ *
5
+ * The unified client returns coin objects whose `type` is the full wrapper
6
+ * (`0x2::coin::Coin<0x2::sui::SUI>`) and whose id field is `objectId`; the
7
+ * retired JSON-RPC `CoinStruct` exposed the inner `coinType` and
8
+ * `coinObjectId` directly. Normalizing here keeps coin selection, the
9
+ * `SuiCoin` protobuf and every downstream comparison unchanged.
10
+ */
11
+ export type SuiCoinObject = {
12
+ coinType: string;
13
+ coinObjectId: string;
14
+ version: string;
15
+ digest: string;
16
+ balance: string;
17
+ };
18
+ /**
19
+ * A misbehaving endpoint that keeps returning `hasNextPage: true` with a
20
+ * non-advancing cursor would otherwise spin forever. 200 pages is far beyond
21
+ * any real wallet, so hitting the cap means the cursor is stuck: fail CLOSED
22
+ * rather than hang or silently truncate the coin set and under-fund a send.
23
+ */
24
+ export declare const maxSuiCoinPages = 200;
25
+ /** `0x2::coin::Coin<0x2::sui::SUI>` -> `0x2::sui::SUI`. */
26
+ export declare const unwrapSuiCoinType: (objectType: string | undefined, fallback: string) => string;
27
+ type ListAllSuiCoinsInput = {
28
+ client: Pick<SuiClient, 'listCoins'>;
29
+ owner: string;
30
+ coinType: string;
31
+ };
32
+ /**
33
+ * Every coin object of one coin type owned by `owner`.
34
+ *
35
+ * `listCoins` is paginated (~50 objects/page). Sui's object-per-coin model
36
+ * makes >50 coin objects realistic for an active wallet (dust, partial fills,
37
+ * repeated small transfers, staking rewards), so reading only the first page
38
+ * silently truncates the coin set and produces a broken send ("insufficient
39
+ * balance" despite adequate holdings) even though the balance-based display
40
+ * path shows the correct aggregate total. Follow the cursor to completion.
41
+ */
42
+ export declare const listAllSuiCoins: ({ client, owner, coinType }: ListAllSuiCoinsInput) => Promise<SuiCoinObject[]>;
43
+ export {};
44
+ //# sourceMappingURL=listAllCoins.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listAllCoins.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/sui/listAllCoins.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAEzC;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,eAAe,MAAM,CAAA;AAIlC,2DAA2D;AAC3D,eAAO,MAAM,iBAAiB,GAAI,YAAY,MAAM,GAAG,SAAS,EAAE,UAAU,MAAM,KAAG,MAChC,CAAA;AAErD,KAAK,oBAAoB,GAAG;IAC1B,MAAM,EAAE,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAA;IACpC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,GAAU,6BAA6B,oBAAoB,KAAG,OAAO,CAAC,aAAa,EAAE,CA4BhH,CAAA"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * A misbehaving endpoint that keeps returning `hasNextPage: true` with a
3
+ * non-advancing cursor would otherwise spin forever. 200 pages is far beyond
4
+ * any real wallet, so hitting the cap means the cursor is stuck: fail CLOSED
5
+ * rather than hang or silently truncate the coin set and under-fund a send.
6
+ */
7
+ export const maxSuiCoinPages = 200;
8
+ const coinWrapperType = /::coin::Coin<(.+)>$/;
9
+ /** `0x2::coin::Coin<0x2::sui::SUI>` -> `0x2::sui::SUI`. */
10
+ export const unwrapSuiCoinType = (objectType, fallback) => objectType?.match(coinWrapperType)?.[1] ?? fallback;
11
+ /**
12
+ * Every coin object of one coin type owned by `owner`.
13
+ *
14
+ * `listCoins` is paginated (~50 objects/page). Sui's object-per-coin model
15
+ * makes >50 coin objects realistic for an active wallet (dust, partial fills,
16
+ * repeated small transfers, staking rewards), so reading only the first page
17
+ * silently truncates the coin set and produces a broken send ("insufficient
18
+ * balance" despite adequate holdings) even though the balance-based display
19
+ * path shows the correct aggregate total. Follow the cursor to completion.
20
+ */
21
+ export const listAllSuiCoins = async ({ client, owner, coinType }) => {
22
+ const coins = [];
23
+ let cursor = undefined;
24
+ let pages = 0;
25
+ do {
26
+ const page = await client.listCoins({ owner, coinType, cursor });
27
+ for (const object of page.objects) {
28
+ coins.push({
29
+ coinType: unwrapSuiCoinType(object.type, coinType),
30
+ coinObjectId: object.objectId,
31
+ version: object.version,
32
+ digest: object.digest,
33
+ balance: object.balance,
34
+ });
35
+ }
36
+ cursor = page.hasNextPage ? page.cursor : null;
37
+ if (++pages >= maxSuiCoinPages && cursor) {
38
+ throw new Error(`listAllSuiCoins: exceeded ${maxSuiCoinPages} pages for ${owner} (${coinType}) — refusing to build a send from a possibly-truncated or looping coin set`);
39
+ }
40
+ } while (cursor);
41
+ return coins;
42
+ };
43
+ //# sourceMappingURL=listAllCoins.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listAllCoins.js","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/sui/listAllCoins.ts"],"names":[],"mappings":"AAmBA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAA;AAElC,MAAM,eAAe,GAAG,qBAAqB,CAAA;AAE7C,2DAA2D;AAC3D,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,UAA8B,EAAE,QAAgB,EAAU,EAAE,CAC5F,UAAU,EAAE,KAAK,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAA;AAQrD;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAwB,EAA4B,EAAE;IACnH,MAAM,KAAK,GAAoB,EAAE,CAAA;IACjC,IAAI,MAAM,GAA8B,SAAS,CAAA;IACjD,IAAI,KAAK,GAAG,CAAC,CAAA;IAEb,GAAG,CAAC;QACF,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAA;QAEhE,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,KAAK,CAAC,IAAI,CAAC;gBACT,QAAQ,EAAE,iBAAiB,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC;gBAClD,YAAY,EAAE,MAAM,CAAC,QAAQ;gBAC7B,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,OAAO,EAAE,MAAM,CAAC,OAAO;aACxB,CAAC,CAAA;QACJ,CAAC;QAED,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAA;QAE9C,IAAI,EAAE,KAAK,IAAI,eAAe,IAAI,MAAM,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CACb,6BAA6B,eAAe,cAAc,KAAK,KAAK,QAAQ,4EAA4E,CACzJ,CAAA;QACH,CAAC;IACH,CAAC,QAAQ,MAAM,EAAC;IAEhB,OAAO,KAAK,CAAA;AACd,CAAC,CAAA"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Shared readers for the unified Sui client's transaction result shape.
3
+ *
4
+ * Sui's gRPC / GraphQL clients return a discriminated union rather than the
5
+ * JSON-RPC `{ effects: { status: { status: 'success' | 'failure' } } }` object:
6
+ *
7
+ * { $kind: 'Transaction', Transaction: { status, effects, ... } }
8
+ * { $kind: 'FailedTransaction', FailedTransaction: { status, effects, ... } }
9
+ *
10
+ * and execution status is `{ success: true, error: null }` /
11
+ * `{ success: false, error: { message, ... } }`.
12
+ *
13
+ * The types below are structural on purpose: `SuiGrpcClient` and
14
+ * `SuiGraphQLClient` produce the same shape but through different generic
15
+ * instantiations, and every resolver here only ever reads status + effects.
16
+ */
17
+ export type SuiExecutionStatusLike = {
18
+ success?: boolean;
19
+ error?: {
20
+ message?: string;
21
+ } | null;
22
+ };
23
+ export type SuiGasCostSummaryLike = {
24
+ computationCost?: string;
25
+ storageCost?: string;
26
+ storageRebate?: string;
27
+ };
28
+ export type SuiTransactionEffectsLike = {
29
+ transactionDigest?: string;
30
+ gasUsed?: SuiGasCostSummaryLike;
31
+ };
32
+ export type SuiTransactionLike = {
33
+ digest?: string;
34
+ status?: SuiExecutionStatusLike;
35
+ effects?: SuiTransactionEffectsLike;
36
+ };
37
+ export type SuiTransactionResultLike = {
38
+ $kind?: 'Transaction' | 'FailedTransaction';
39
+ Transaction?: SuiTransactionLike;
40
+ FailedTransaction?: SuiTransactionLike;
41
+ };
42
+ /**
43
+ * The transaction payload of a result, regardless of which arm of the union it
44
+ * arrived on. A failed transaction still carries effects (gas used, digest),
45
+ * which broadcast verification and gas refinement both need.
46
+ */
47
+ export declare const getSuiResultTransaction: (result: SuiTransactionResultLike | null | undefined) => SuiTransactionLike | undefined;
48
+ /**
49
+ * Execution success — NOT transport success.
50
+ *
51
+ * Fails closed: only an explicit `$kind: 'Transaction'` carrying
52
+ * `status.success === true` counts. A `FailedTransaction`, a `success: false`
53
+ * status, or a result with no status at all (malformed / unexpected response)
54
+ * is not proven success and must not be treated as one (sdk#1398).
55
+ */
56
+ export declare const isSuiExecutionSuccess: (result: SuiTransactionResultLike | null | undefined) => boolean;
57
+ /** Human-readable reason a transaction did not execute successfully. */
58
+ export declare const describeSuiExecutionFailure: (result: SuiTransactionResultLike | null | undefined) => string;
59
+ //# sourceMappingURL=transactionResult.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transactionResult.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/sui/transactionResult.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;CACpC,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,OAAO,CAAC,EAAE,qBAAqB,CAAA;CAChC,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,sBAAsB,CAAA;IAC/B,OAAO,CAAC,EAAE,yBAAyB,CAAA;CACpC,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC,KAAK,CAAC,EAAE,aAAa,GAAG,mBAAmB,CAAA;IAC3C,WAAW,CAAC,EAAE,kBAAkB,CAAA;IAChC,iBAAiB,CAAC,EAAE,kBAAkB,CAAA;CACvC,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,GAClC,QAAQ,wBAAwB,GAAG,IAAI,GAAG,SAAS,KAClD,kBAAkB,GAAG,SAA6D,CAAA;AAErF;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,GAAI,QAAQ,wBAAwB,GAAG,IAAI,GAAG,SAAS,KAAG,OACE,CAAA;AAE9F,wEAAwE;AACxE,eAAO,MAAM,2BAA2B,GAAI,QAAQ,wBAAwB,GAAG,IAAI,GAAG,SAAS,KAAG,MAQjG,CAAA"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Shared readers for the unified Sui client's transaction result shape.
3
+ *
4
+ * Sui's gRPC / GraphQL clients return a discriminated union rather than the
5
+ * JSON-RPC `{ effects: { status: { status: 'success' | 'failure' } } }` object:
6
+ *
7
+ * { $kind: 'Transaction', Transaction: { status, effects, ... } }
8
+ * { $kind: 'FailedTransaction', FailedTransaction: { status, effects, ... } }
9
+ *
10
+ * and execution status is `{ success: true, error: null }` /
11
+ * `{ success: false, error: { message, ... } }`.
12
+ *
13
+ * The types below are structural on purpose: `SuiGrpcClient` and
14
+ * `SuiGraphQLClient` produce the same shape but through different generic
15
+ * instantiations, and every resolver here only ever reads status + effects.
16
+ */
17
+ /**
18
+ * The transaction payload of a result, regardless of which arm of the union it
19
+ * arrived on. A failed transaction still carries effects (gas used, digest),
20
+ * which broadcast verification and gas refinement both need.
21
+ */
22
+ export const getSuiResultTransaction = (result) => result?.Transaction ?? result?.FailedTransaction;
23
+ /**
24
+ * Execution success — NOT transport success.
25
+ *
26
+ * Fails closed: only an explicit `$kind: 'Transaction'` carrying
27
+ * `status.success === true` counts. A `FailedTransaction`, a `success: false`
28
+ * status, or a result with no status at all (malformed / unexpected response)
29
+ * is not proven success and must not be treated as one (sdk#1398).
30
+ */
31
+ export const isSuiExecutionSuccess = (result) => result?.$kind === 'Transaction' && getSuiResultTransaction(result)?.status?.success === true;
32
+ /** Human-readable reason a transaction did not execute successfully. */
33
+ export const describeSuiExecutionFailure = (result) => {
34
+ const status = getSuiResultTransaction(result)?.status;
35
+ if (status?.error?.message)
36
+ return status.error.message;
37
+ if (status?.success === false)
38
+ return 'execution failed';
39
+ if (result?.$kind === 'FailedTransaction')
40
+ return 'transaction did not execute';
41
+ return 'no execution status returned';
42
+ };
43
+ //# sourceMappingURL=transactionResult.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transactionResult.js","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/sui/transactionResult.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AA8BH;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,MAAmD,EACnB,EAAE,CAAC,MAAM,EAAE,WAAW,IAAI,MAAM,EAAE,iBAAiB,CAAA;AAErF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,MAAmD,EAAW,EAAE,CACpG,MAAM,EAAE,KAAK,KAAK,aAAa,IAAI,uBAAuB,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAA;AAE9F,wEAAwE;AACxE,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,MAAmD,EAAU,EAAE;IACzG,MAAM,MAAM,GAAG,uBAAuB,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IAEtD,IAAI,MAAM,EAAE,KAAK,EAAE,OAAO;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,OAAO,CAAA;IACvD,IAAI,MAAM,EAAE,OAAO,KAAK,KAAK;QAAE,OAAO,kBAAkB,CAAA;IACxD,IAAI,MAAM,EAAE,KAAK,KAAK,mBAAmB;QAAE,OAAO,6BAA6B,CAAA;IAE/E,OAAO,8BAA8B,CAAA;AACvC,CAAC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"sui.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/coin/balance/resolvers/sui.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEjD,eAAO,MAAM,iBAAiB,EAAE,mBAS/B,CAAA"}
1
+ {"version":3,"file":"sui.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/coin/balance/resolvers/sui.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEjD,eAAO,MAAM,iBAAiB,EAAE,mBAY/B,CAAA"}
@@ -1,10 +1,13 @@
1
1
  import { getSuiClient } from '@vultisig/core-chain/chains/sui/client';
2
2
  export const getSuiCoinBalance = async (input) => {
3
- const rpcClient = getSuiClient();
4
- const { totalBalance } = await rpcClient.getBalance({
3
+ const client = getSuiClient();
4
+ // The unified client nests the balance: `{ balance: { balance, coinType, ... } }`.
5
+ // `balance.balance` is the total (the retired JSON-RPC `totalBalance`), NOT
6
+ // the `coinBalance` / `addressBalance` split.
7
+ const { balance } = await client.getBalance({
5
8
  owner: input.address,
6
9
  ...(input.id ? { coinType: input.id } : {}),
7
10
  });
8
- return BigInt(totalBalance);
11
+ return BigInt(balance.balance);
9
12
  };
10
13
  //# sourceMappingURL=sui.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sui.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/coin/balance/resolvers/sui.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAA;AAIrE,MAAM,CAAC,MAAM,iBAAiB,GAAwB,KAAK,EAAC,KAAK,EAAC,EAAE;IAClE,MAAM,SAAS,GAAG,YAAY,EAAE,CAAA;IAEhC,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,SAAS,CAAC,UAAU,CAAC;QAClD,KAAK,EAAE,KAAK,CAAC,OAAO;QACpB,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC5C,CAAC,CAAA;IAEF,OAAO,MAAM,CAAC,YAAY,CAAC,CAAA;AAC7B,CAAC,CAAA"}
1
+ {"version":3,"file":"sui.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/coin/balance/resolvers/sui.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAA;AAIrE,MAAM,CAAC,MAAM,iBAAiB,GAAwB,KAAK,EAAC,KAAK,EAAC,EAAE;IAClE,MAAM,MAAM,GAAG,YAAY,EAAE,CAAA;IAE7B,mFAAmF;IACnF,4EAA4E;IAC5E,8CAA8C;IAC9C,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC;QAC1C,KAAK,EAAE,KAAK,CAAC,OAAO;QACpB,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC5C,CAAC,CAAA;IAEF,OAAO,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;AAChC,CAAC,CAAA"}
@@ -1,6 +1,6 @@
1
1
  import { DeriveChainKind } from '@vultisig/core-chain/ChainKind';
2
2
  import { OtherChain } from '../../../Chain.js';
3
- export declare const chainsWithTokenMetadataDiscovery: readonly ("Arbitrum" | "Base" | "Blast" | "Optimism" | "Zksync" | "Mantle" | "Avalanche" | "CronosChain" | "BSC" | "Ethereum" | "Polygon" | "Hyperliquid" | "Sei" | "Cosmos" | "Osmosis" | "Dydx" | "Kujira" | "Terra" | "TerraClassic" | "Noble" | "Akash" | "THORChain" | "MayaChain" | OtherChain.Sui | OtherChain.Solana | OtherChain.Ton | OtherChain.Tron | OtherChain.Cardano)[];
3
+ export declare const chainsWithTokenMetadataDiscovery: readonly ("Arbitrum" | "Base" | "Blast" | "Optimism" | "Zksync" | "Mantle" | "Avalanche" | "CronosChain" | "BSC" | "Ethereum" | "Polygon" | "Hyperliquid" | "Sei" | "Cosmos" | "Osmosis" | "Dydx" | "Kujira" | "Terra" | "TerraClassic" | "Noble" | "Akash" | "THORChain" | "MayaChain" | OtherChain.Sui | OtherChain.Solana | OtherChain.Ton | OtherChain.Ripple | OtherChain.Tron | OtherChain.Cardano)[];
4
4
  export type ChainWithTokenMetadataDiscovery = (typeof chainsWithTokenMetadataDiscovery)[number];
5
5
  export type ChainKindWithTokenMetadataDiscovery = DeriveChainKind<ChainWithTokenMetadataDiscovery>;
6
6
  //# sourceMappingURL=chains.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chains.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/coin/token/metadata/chains.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAA;AAEhE,OAAO,EAAyB,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAElE,eAAO,MAAM,gCAAgC,yXAQnC,CAAA;AAEV,MAAM,MAAM,+BAA+B,GAAG,CAAC,OAAO,gCAAgC,CAAC,CAAC,MAAM,CAAC,CAAA;AAE/F,MAAM,MAAM,mCAAmC,GAAG,eAAe,CAAC,+BAA+B,CAAC,CAAA"}
1
+ {"version":3,"file":"chains.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/coin/token/metadata/chains.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAA;AAEhE,OAAO,EAAyB,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAElE,eAAO,MAAM,gCAAgC,6YASnC,CAAA;AAEV,MAAM,MAAM,+BAA+B,GAAG,CAAC,OAAO,gCAAgC,CAAC,CAAC,MAAM,CAAC,CAAA;AAE/F,MAAM,MAAM,mCAAmC,GAAG,eAAe,CAAC,+BAA+B,CAAC,CAAA"}
@@ -6,6 +6,7 @@ export const chainsWithTokenMetadataDiscovery = [
6
6
  OtherChain.Tron,
7
7
  OtherChain.Cardano,
8
8
  OtherChain.Sui,
9
+ OtherChain.Ripple,
9
10
  ...Object.values(CosmosChain),
10
11
  ];
11
12
  //# sourceMappingURL=chains.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chains.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/coin/token/metadata/chains.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAElE,MAAM,CAAC,MAAM,gCAAgC,GAAG;IAC9C,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC;IAC1B,UAAU,CAAC,MAAM;IACjB,UAAU,CAAC,GAAG;IACd,UAAU,CAAC,IAAI;IACf,UAAU,CAAC,OAAO;IAClB,UAAU,CAAC,GAAG;IACd,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC;CACrB,CAAA"}
1
+ {"version":3,"file":"chains.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/coin/token/metadata/chains.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAElE,MAAM,CAAC,MAAM,gCAAgC,GAAG;IAC9C,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC;IAC1B,UAAU,CAAC,MAAM;IACjB,UAAU,CAAC,GAAG;IACd,UAAU,CAAC,IAAI;IACf,UAAU,CAAC,OAAO;IAClB,UAAU,CAAC,GAAG;IACd,UAAU,CAAC,MAAM;IACjB,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC;CACrB,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/coin/token/metadata/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAmBlD,eAAO,MAAM,gBAAgB,EAAE,qBAM9B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/coin/token/metadata/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAqBlD,eAAO,MAAM,gBAAgB,EAAE,qBAM9B,CAAA"}
@@ -2,6 +2,7 @@ import { getChainKind } from '@vultisig/core-chain/ChainKind';
2
2
  import { getCardanoTokenMetadata } from './resolvers/cardano.js';
3
3
  import { getCosmosTokenMetadata } from './resolvers/cosmos.js';
4
4
  import { getEvmTokenMetadata } from './resolvers/evm.js';
5
+ import { getRippleTokenMetadata } from './resolvers/ripple.js';
5
6
  import { getSolanaTokenMetadata } from './resolvers/solana.js';
6
7
  import { getSuiTokenMetadata } from './resolvers/sui.js';
7
8
  import { getTonTokenMetadata } from './resolvers/ton.js';
@@ -14,6 +15,7 @@ const resolvers = {
14
15
  tron: getTronTokenMetadata,
15
16
  cardano: getCardanoTokenMetadata,
16
17
  sui: getSuiTokenMetadata,
18
+ ripple: getRippleTokenMetadata,
17
19
  };
18
20
  export const getTokenMetadata = async (input) => {
19
21
  const chainKind = getChainKind(input.chain);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/coin/token/metadata/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAA;AAI7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AACrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAEvD,MAAM,SAAS,GAA4E;IACzF,GAAG,EAAE,mBAAmB;IACxB,MAAM,EAAE,sBAAsB;IAC9B,MAAM,EAAE,sBAAsB;IAC9B,GAAG,EAAE,mBAAmB;IACxB,IAAI,EAAE,oBAAoB;IAC1B,OAAO,EAAE,uBAAuB;IAChC,GAAG,EAAE,mBAAmB;CACzB,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAA0B,KAAK,EAAC,KAAK,EAAC,EAAE;IACnE,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IAE3C,MAAM,QAAQ,GAAG,SAAS,CAAC,SAAS,CAAC,CAAA;IAErC,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAA;AACxB,CAAC,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/coin/token/metadata/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAA;AAI7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AACrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAEvD,MAAM,SAAS,GAA4E;IACzF,GAAG,EAAE,mBAAmB;IACxB,MAAM,EAAE,sBAAsB;IAC9B,MAAM,EAAE,sBAAsB;IAC9B,GAAG,EAAE,mBAAmB;IACxB,IAAI,EAAE,oBAAoB;IAC1B,OAAO,EAAE,uBAAuB;IAChC,GAAG,EAAE,mBAAmB;IACxB,MAAM,EAAE,sBAAsB;CAC/B,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAA0B,KAAK,EAAC,KAAK,EAAC,EAAE;IACnE,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IAE3C,MAAM,QAAQ,GAAG,SAAS,CAAC,SAAS,CAAC,CAAA;IAErC,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAA;AACxB,CAAC,CAAA"}
@@ -0,0 +1,17 @@
1
+ import { OtherChain } from '@vultisig/core-chain/Chain';
2
+ import { TokenMetadataResolver } from '../resolver.js';
3
+ /**
4
+ * Metadata for a custom XRPL issued currency identified by a `currency.issuer`
5
+ * token id.
6
+ *
7
+ * Unlike EVM/Tron tokens, XRPL issued currencies expose no on-ledger metadata
8
+ * call: issued amounts carry no fixed on-chain decimal count (we model them at
9
+ * {@link rippleIssuedCurrencyDecimals}) and the ticker is derived from the
10
+ * currency code itself, so nothing is fetched. When the token is one we curate,
11
+ * its logo and price provider are merged in; an arbitrary token gets neither, so
12
+ * it renders with a generic icon and no price rather than borrowing a known
13
+ * token's identity — two different issuers can share a ticker on XRPL, so the
14
+ * issuer (encoded in the id) is what actually distinguishes them.
15
+ */
16
+ export declare const getRippleTokenMetadata: TokenMetadataResolver<OtherChain.Ripple>;
17
+ //# sourceMappingURL=ripple.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ripple.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/coin/token/metadata/resolvers/ripple.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AASvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAiBnD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,sBAAsB,EAAE,qBAAqB,CAAC,UAAU,CAAC,MAAM,CAqB3E,CAAA"}
@@ -0,0 +1,44 @@
1
+ import { parseRippleTokenId, rippleIssuedCurrencyDecimals, rippleKnownIssuedTokens, rippleTokenId, } from '@vultisig/core-chain/chains/ripple/issuedCurrency';
2
+ import { areEqualCoins } from '@vultisig/core-chain/coin/Coin';
3
+ /**
4
+ * Human-readable ticker for an XRPL issued currency. Standard 3-character codes
5
+ * (`USD`) are already tickers; the 160-bit hex form encodes ASCII right-padded
6
+ * with zeros, so decoding it recovers the ticker a user recognises (e.g. `RLUSD`).
7
+ */
8
+ const toIssuedCurrencyTicker = (currency) => {
9
+ if (currency.length !== 40) {
10
+ return currency;
11
+ }
12
+ const ascii = Buffer.from(currency, 'hex').toString('ascii').replace(/\0+$/, '');
13
+ return /^[\x20-\x7e]+$/.test(ascii) ? ascii : currency;
14
+ };
15
+ /**
16
+ * Metadata for a custom XRPL issued currency identified by a `currency.issuer`
17
+ * token id.
18
+ *
19
+ * Unlike EVM/Tron tokens, XRPL issued currencies expose no on-ledger metadata
20
+ * call: issued amounts carry no fixed on-chain decimal count (we model them at
21
+ * {@link rippleIssuedCurrencyDecimals}) and the ticker is derived from the
22
+ * currency code itself, so nothing is fetched. When the token is one we curate,
23
+ * its logo and price provider are merged in; an arbitrary token gets neither, so
24
+ * it renders with a generic icon and no price rather than borrowing a known
25
+ * token's identity — two different issuers can share a ticker on XRPL, so the
26
+ * issuer (encoded in the id) is what actually distinguishes them.
27
+ */
28
+ export const getRippleTokenMetadata = async ({ id, chain }) => {
29
+ const { currency, issuer } = parseRippleTokenId(id);
30
+ const metadata = {
31
+ ticker: toIssuedCurrencyTicker(currency),
32
+ decimals: rippleIssuedCurrencyDecimals,
33
+ };
34
+ const knownToken = rippleKnownIssuedTokens.find(token => areEqualCoins(token, { chain, id: rippleTokenId({ currency, issuer }) }));
35
+ if (!knownToken) {
36
+ return metadata;
37
+ }
38
+ return {
39
+ ...metadata,
40
+ logo: knownToken.logo,
41
+ priceProviderId: knownToken.priceProviderId,
42
+ };
43
+ };
44
+ //# sourceMappingURL=ripple.js.map