@vultisig/core-chain 5.0.0 → 5.1.0

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 (50) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/chains/ripple/issuedCurrency.d.ts.map +1 -1
  3. package/dist/chains/ripple/issuedCurrency.js +15 -4
  4. package/dist/chains/ripple/issuedCurrency.js.map +1 -1
  5. package/dist/chains/ripple/trustLine.d.ts +22 -0
  6. package/dist/chains/ripple/trustLine.d.ts.map +1 -0
  7. package/dist/chains/ripple/trustLine.js +14 -0
  8. package/dist/chains/ripple/trustLine.js.map +1 -0
  9. package/dist/chains/ton/address.d.ts +18 -0
  10. package/dist/chains/ton/address.d.ts.map +1 -1
  11. package/dist/chains/ton/address.js +30 -0
  12. package/dist/chains/ton/address.js.map +1 -1
  13. package/dist/chains/ton/api.d.ts +49 -0
  14. package/dist/chains/ton/api.d.ts.map +1 -1
  15. package/dist/chains/ton/api.js +131 -24
  16. package/dist/chains/ton/api.js.map +1 -1
  17. package/dist/chains/ton/jetton/symbol.d.ts +9 -0
  18. package/dist/chains/ton/jetton/symbol.d.ts.map +1 -0
  19. package/dist/chains/ton/jetton/symbol.js +61 -0
  20. package/dist/chains/ton/jetton/symbol.js.map +1 -0
  21. package/dist/chains/ton/jetton/verification.d.ts +35 -0
  22. package/dist/chains/ton/jetton/verification.d.ts.map +1 -0
  23. package/dist/chains/ton/jetton/verification.js +45 -0
  24. package/dist/chains/ton/jetton/verification.js.map +1 -0
  25. package/dist/chains/ton/jetton/verifiedRegistry.d.ts +43 -0
  26. package/dist/chains/ton/jetton/verifiedRegistry.d.ts.map +1 -0
  27. package/dist/chains/ton/jetton/verifiedRegistry.js +94 -0
  28. package/dist/chains/ton/jetton/verifiedRegistry.js.map +1 -0
  29. package/dist/coin/balance/resolvers/ripple.d.ts.map +1 -1
  30. package/dist/coin/balance/resolvers/ripple.js +3 -2
  31. package/dist/coin/balance/resolvers/ripple.js.map +1 -1
  32. package/dist/coin/find/CoinFinderChainKind.d.ts +1 -1
  33. package/dist/coin/find/CoinFinderChainKind.d.ts.map +1 -1
  34. package/dist/coin/find/CoinFinderChainKind.js +1 -1
  35. package/dist/coin/find/CoinFinderChainKind.js.map +1 -1
  36. package/dist/coin/find/index.d.ts.map +1 -1
  37. package/dist/coin/find/index.js +2 -0
  38. package/dist/coin/find/index.js.map +1 -1
  39. package/dist/coin/find/resolvers/ton.d.ts +15 -0
  40. package/dist/coin/find/resolvers/ton.d.ts.map +1 -0
  41. package/dist/coin/find/resolvers/ton.js +61 -0
  42. package/dist/coin/find/resolvers/ton.js.map +1 -0
  43. package/dist/coin/tokenVerification.d.ts +13 -0
  44. package/dist/coin/tokenVerification.d.ts.map +1 -0
  45. package/dist/coin/tokenVerification.js +12 -0
  46. package/dist/coin/tokenVerification.js.map +1 -0
  47. package/dist/swap/general/swapkit/api/getSwapKitQuote.d.ts.map +1 -1
  48. package/dist/swap/general/swapkit/api/getSwapKitQuote.js +89 -5
  49. package/dist/swap/general/swapkit/api/getSwapKitQuote.js.map +1 -1
  50. package/package.json +31 -1
@@ -0,0 +1,35 @@
1
+ import { TokenVerification } from '@vultisig/core-chain/coin/tokenVerification';
2
+ import { TonVerifiedJettonRegistry } from './verifiedRegistry.js';
3
+ type ResolveTonJettonVerificationInput = {
4
+ /** Jetton master address, raw or user-friendly. */
5
+ address: string;
6
+ symbol?: string;
7
+ name?: string;
8
+ /** Toncenter's own scam flag for the master, when known. */
9
+ isFlaggedScam?: boolean;
10
+ registry: TonVerifiedJettonRegistry;
11
+ };
12
+ /**
13
+ * Classifies a jetton against the verified registry. A listed address is
14
+ * `verified` whatever it calls itself. An unlisted jetton is `scam` when the
15
+ * indexer flags it or when its symbol or name collapses (see
16
+ * `normalizeJettonSymbol`) onto a verified jetton's symbol or name — the
17
+ * fake-USDT pattern, where the counterfeit is only distinguishable by address.
18
+ * Anything else is `unverified`.
19
+ */
20
+ export declare const resolveTonJettonVerification: ({ address, symbol, name, isFlaggedScam, registry, }: ResolveTonJettonVerificationInput) => TokenVerification;
21
+ type GetTonJettonVerificationInput = {
22
+ /** Jetton master address, raw or user-friendly. */
23
+ id: string;
24
+ /** Ticker already known locally, used when Toncenter has no symbol for the master. */
25
+ ticker?: string;
26
+ };
27
+ /**
28
+ * Verification tier for one jetton, for token rows and approval cards. Reads the
29
+ * master's on-chain symbol and name from Toncenter so a counterfeit is judged by
30
+ * what it actually claims to be, not by the ticker stored locally; falls back to
31
+ * that ticker when the lookup fails, so the label still renders offline.
32
+ */
33
+ export declare const getTonJettonVerification: ({ id, ticker, }: GetTonJettonVerificationInput) => Promise<TokenVerification>;
34
+ export {};
35
+ //# sourceMappingURL=verification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verification.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/ton/jetton/verification.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,6CAA6C,CAAA;AAI/E,OAAO,EAAgC,yBAAyB,EAAE,MAAM,oBAAoB,CAAA;AAE5F,KAAK,iCAAiC,GAAG;IACvC,mDAAmD;IACnD,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,4DAA4D;IAC5D,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,QAAQ,EAAE,yBAAyB,CAAA;CACpC,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,4BAA4B,GAAI,qDAM1C,iCAAiC,KAAG,iBAYtC,CAAA;AAED,KAAK,6BAA6B,GAAG;IACnC,mDAAmD;IACnD,EAAE,EAAE,MAAM,CAAA;IACV,sFAAsF;IACtF,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,GAAU,iBAG5C,6BAA6B,KAAG,OAAO,CAAC,iBAAiB,CAe3D,CAAA"}
@@ -0,0 +1,45 @@
1
+ import { tonAddressToRawKey } from '@vultisig/core-chain/chains/ton/address';
2
+ import { getJettonMastersMetadata } from '@vultisig/core-chain/chains/ton/api';
3
+ import { attempt } from '@vultisig/lib-utils/attempt';
4
+ import { normalizeJettonSymbol } from './symbol.js';
5
+ import { getTonVerifiedJettonRegistry } from './verifiedRegistry.js';
6
+ /**
7
+ * Classifies a jetton against the verified registry. A listed address is
8
+ * `verified` whatever it calls itself. An unlisted jetton is `scam` when the
9
+ * indexer flags it or when its symbol or name collapses (see
10
+ * `normalizeJettonSymbol`) onto a verified jetton's symbol or name — the
11
+ * fake-USDT pattern, where the counterfeit is only distinguishable by address.
12
+ * Anything else is `unverified`.
13
+ */
14
+ export const resolveTonJettonVerification = ({ address, symbol, name, isFlaggedScam, registry, }) => {
15
+ if (registry.byAddress[tonAddressToRawKey(address)])
16
+ return 'verified';
17
+ if (isFlaggedScam)
18
+ return 'scam';
19
+ const impersonates = [symbol, name].some(label => {
20
+ const skeleton = label ? normalizeJettonSymbol(label) : '';
21
+ return !!skeleton && (registry.symbols.has(skeleton) || registry.names.has(skeleton));
22
+ });
23
+ return impersonates ? 'scam' : 'unverified';
24
+ };
25
+ /**
26
+ * Verification tier for one jetton, for token rows and approval cards. Reads the
27
+ * master's on-chain symbol and name from Toncenter so a counterfeit is judged by
28
+ * what it actually claims to be, not by the ticker stored locally; falls back to
29
+ * that ticker when the lookup fails, so the label still renders offline.
30
+ */
31
+ export const getTonJettonVerification = async ({ id, ticker, }) => {
32
+ const [registry, metadata] = await Promise.all([
33
+ getTonVerifiedJettonRegistry(),
34
+ attempt(getJettonMastersMetadata([id])),
35
+ ]);
36
+ const master = 'data' in metadata ? metadata.data?.[tonAddressToRawKey(id)] : undefined;
37
+ return resolveTonJettonVerification({
38
+ address: id,
39
+ symbol: master?.symbol ?? ticker,
40
+ name: master?.name,
41
+ isFlaggedScam: master?.isFlaggedScam,
42
+ registry,
43
+ });
44
+ };
45
+ //# sourceMappingURL=verification.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verification.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/ton/jetton/verification.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAA;AAC5E,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAA;AAE9E,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAA;AAErD,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAA;AAChD,OAAO,EAAE,4BAA4B,EAA6B,MAAM,oBAAoB,CAAA;AAY5F;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,EAC3C,OAAO,EACP,MAAM,EACN,IAAI,EACJ,aAAa,EACb,QAAQ,GAC0B,EAAqB,EAAE;IACzD,IAAI,QAAQ,CAAC,SAAS,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;QAAE,OAAO,UAAU,CAAA;IAEtE,IAAI,aAAa;QAAE,OAAO,MAAM,CAAA;IAEhC,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;QAC/C,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QAE1D,OAAO,CAAC,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAA;IACvF,CAAC,CAAC,CAAA;IAEF,OAAO,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAA;AAC7C,CAAC,CAAA;AASD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,EAAE,EAC7C,EAAE,EACF,MAAM,GACwB,EAA8B,EAAE;IAC9D,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC7C,4BAA4B,EAAE;QAC9B,OAAO,CAAC,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;KACxC,CAAC,CAAA;IAEF,MAAM,MAAM,GAAG,MAAM,IAAI,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IAEvF,OAAO,4BAA4B,CAAC;QAClC,OAAO,EAAE,EAAE;QACX,MAAM,EAAE,MAAM,EAAE,MAAM,IAAI,MAAM;QAChC,IAAI,EAAE,MAAM,EAAE,IAAI;QAClB,aAAa,EAAE,MAAM,EAAE,aAAa;QACpC,QAAQ;KACT,CAAC,CAAA;AACJ,CAAC,CAAA"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Tonkeeper's community-reviewed jetton whitelist, the list every major TON
3
+ * wallet uses as its "verified" tier. Compiled from the repo's YAML sources on
4
+ * every merge; served with `Access-Control-Allow-Origin: *`.
5
+ */
6
+ export declare const tonAssetsJettonsUrl = "https://raw.githubusercontent.com/tonkeeper/ton-assets/main/jettons.json";
7
+ /** A jetton we treat as legitimate, keyed by its lower-cased raw master address. */
8
+ export type VerifiedJetton = {
9
+ address: string;
10
+ symbol: string;
11
+ name?: string;
12
+ decimals?: number;
13
+ logo?: string;
14
+ priceProviderId?: string;
15
+ };
16
+ /**
17
+ * Verified jettons indexed for the two questions verification asks: "is this
18
+ * address listed?" and "does this symbol or name belong to a listed jetton?".
19
+ * `symbols` and `names` hold `normalizeJettonSymbol` skeletons.
20
+ */
21
+ export type TonVerifiedJettonRegistry = {
22
+ byAddress: Record<string, VerifiedJetton>;
23
+ symbols: Set<string>;
24
+ names: Set<string>;
25
+ };
26
+ /**
27
+ * Builds a registry from a list of verified jettons. On an address collision the
28
+ * earlier entry's metadata is kept in `byAddress`, but every entry's symbol and
29
+ * name are indexed: two entries for one address describe the same verified
30
+ * contract, and a counterfeit may copy either spelling. Our curated USDT carries
31
+ * the ticker `USDT` and no name; only the ton-assets duplicate contributes
32
+ * `USD₮` and `Tether USD`, so dropping it would let a "Tether USD" impostor
33
+ * through as merely unverified.
34
+ */
35
+ export declare const makeTonVerifiedJettonRegistry: (jettons: VerifiedJetton[]) => TonVerifiedJettonRegistry;
36
+ /**
37
+ * The jettons we consider verified: our own curated TON tokens (which win, so
38
+ * their tickers and price ids are kept) merged with the ton-assets whitelist.
39
+ * Degrades to the curated list alone when the whitelist cannot be fetched, so
40
+ * discovery and labels keep working offline — with fewer jettons recognised.
41
+ */
42
+ export declare const getTonVerifiedJettonRegistry: () => Promise<TonVerifiedJettonRegistry>;
43
+ //# sourceMappingURL=verifiedRegistry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifiedRegistry.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/ton/jetton/verifiedRegistry.ts"],"names":[],"mappings":"AAUA;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,6EAA6E,CAAA;AAW7G,oFAAoF;AACpF,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACtC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;IACzC,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACpB,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CACnB,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,6BAA6B,GAAI,SAAS,cAAc,EAAE,KAAG,yBAezE,CAAA;AA4DD;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,QAAa,OAAO,CAAC,yBAAyB,CAOtF,CAAA"}
@@ -0,0 +1,94 @@
1
+ import { Chain } from '@vultisig/core-chain/Chain';
2
+ import { tonAddressToRawKey } from '@vultisig/core-chain/chains/ton/address';
3
+ import { knownTokens } from '@vultisig/core-chain/coin/knownTokens';
4
+ import { attempt } from '@vultisig/lib-utils/attempt';
5
+ import { memoizeAsync } from '@vultisig/lib-utils/memoizeAsync';
6
+ import { queryUrl } from '@vultisig/lib-utils/query/queryUrl';
7
+ import { convertDuration } from '@vultisig/lib-utils/time/convertDuration';
8
+ import { normalizeJettonSymbol } from './symbol.js';
9
+ /**
10
+ * Tonkeeper's community-reviewed jetton whitelist, the list every major TON
11
+ * wallet uses as its "verified" tier. Compiled from the repo's YAML sources on
12
+ * every merge; served with `Access-Control-Allow-Origin: *`.
13
+ */
14
+ export const tonAssetsJettonsUrl = 'https://raw.githubusercontent.com/tonkeeper/ton-assets/main/jettons.json';
15
+ /**
16
+ * Builds a registry from a list of verified jettons. On an address collision the
17
+ * earlier entry's metadata is kept in `byAddress`, but every entry's symbol and
18
+ * name are indexed: two entries for one address describe the same verified
19
+ * contract, and a counterfeit may copy either spelling. Our curated USDT carries
20
+ * the ticker `USDT` and no name; only the ton-assets duplicate contributes
21
+ * `USD₮` and `Tether USD`, so dropping it would let a "Tether USD" impostor
22
+ * through as merely unverified.
23
+ */
24
+ export const makeTonVerifiedJettonRegistry = (jettons) => {
25
+ const registry = { byAddress: {}, symbols: new Set(), names: new Set() };
26
+ for (const jetton of jettons) {
27
+ const address = tonAddressToRawKey(jetton.address);
28
+ registry.byAddress[address] ??= { ...jetton, address };
29
+ const symbol = normalizeJettonSymbol(jetton.symbol);
30
+ if (symbol)
31
+ registry.symbols.add(symbol);
32
+ const name = jetton.name ? normalizeJettonSymbol(jetton.name) : '';
33
+ if (name)
34
+ registry.names.add(name);
35
+ }
36
+ return registry;
37
+ };
38
+ const getCuratedJettons = () => knownTokens[Chain.Ton].flatMap(({ id, ticker, decimals, logo, priceProviderId }) => id
39
+ ? [
40
+ {
41
+ address: tonAddressToRawKey(id),
42
+ symbol: ticker,
43
+ decimals,
44
+ logo,
45
+ ...(priceProviderId === undefined ? {} : { priceProviderId }),
46
+ },
47
+ ]
48
+ : []);
49
+ const isTonAssetsJetton = (value) => typeof value === 'object' && value !== null && typeof value.address === 'string';
50
+ const fetchTonAssetsJettons = async () => {
51
+ const response = await queryUrl(tonAssetsJettonsUrl);
52
+ if (!Array.isArray(response)) {
53
+ throw new Error('ton-assets jettons.json is not a list');
54
+ }
55
+ return response.filter(isTonAssetsJetton).flatMap(({ address, name, symbol, decimals, image, coingecko }) => {
56
+ const ticker = symbol?.trim();
57
+ if (!ticker)
58
+ return [];
59
+ return [
60
+ {
61
+ address: tonAddressToRawKey(address),
62
+ symbol: ticker,
63
+ ...(name ? { name } : {}),
64
+ ...(typeof decimals === 'number' ? { decimals } : {}),
65
+ ...(image ? { logo: image } : {}),
66
+ ...(coingecko ? { priceProviderId: coingecko } : {}),
67
+ },
68
+ ];
69
+ });
70
+ };
71
+ // Only a successful fetch is cached: a rejected promise is never stored, so an
72
+ // outage is retried on the next call instead of pinning the degraded registry.
73
+ const getFullRegistry = memoizeAsync(async () => makeTonVerifiedJettonRegistry([...getCuratedJettons(), ...(await fetchTonAssetsJettons())]), { cacheTime: convertDuration(1, 'h', 'ms') });
74
+ let curatedRegistry;
75
+ const getCuratedRegistry = () => {
76
+ if (!curatedRegistry) {
77
+ curatedRegistry = makeTonVerifiedJettonRegistry(getCuratedJettons());
78
+ }
79
+ return curatedRegistry;
80
+ };
81
+ /**
82
+ * The jettons we consider verified: our own curated TON tokens (which win, so
83
+ * their tickers and price ids are kept) merged with the ton-assets whitelist.
84
+ * Degrades to the curated list alone when the whitelist cannot be fetched, so
85
+ * discovery and labels keep working offline — with fewer jettons recognised.
86
+ */
87
+ export const getTonVerifiedJettonRegistry = async () => {
88
+ const result = await attempt(getFullRegistry());
89
+ if ('data' in result && result.data)
90
+ return result.data;
91
+ console.warn('[ton] verified jetton list unavailable; using the curated list only', result.error);
92
+ return getCuratedRegistry();
93
+ };
94
+ //# sourceMappingURL=verifiedRegistry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifiedRegistry.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/ton/jetton/verifiedRegistry.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ripple.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/coin/balance/resolvers/ripple.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAsCjD;;;;;;GAMG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACtC,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,eAAO,MAAM,4BAA4B,GAAU,SAAS,MAAM,KAAG,OAAO,CAAC,yBAAyB,CAsCrG,CAAA;AAQD,eAAO,MAAM,oBAAoB,EAAE,mBAM3B,CAAA"}
1
+ {"version":3,"file":"ripple.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/coin/balance/resolvers/ripple.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAmCjD;;;;;;GAMG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACtC,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,eAAO,MAAM,4BAA4B,GAAU,SAAS,MAAM,KAAG,OAAO,CAAC,yBAAyB,CAsCrG,CAAA;AAQD,eAAO,MAAM,oBAAoB,EAAE,mBAM3B,CAAA"}
@@ -1,7 +1,8 @@
1
1
  import { getRippleAccountInfo } from '@vultisig/core-chain/chains/ripple/account/info';
2
2
  import { getRippleAccountLines } from '@vultisig/core-chain/chains/ripple/account/lines';
3
- import { parseIssuedCurrencyValue, parseRippleTokenId, toXrplCurrencyCode, } from '@vultisig/core-chain/chains/ripple/issuedCurrency';
3
+ import { parseIssuedCurrencyValue, parseRippleTokenId } from '@vultisig/core-chain/chains/ripple/issuedCurrency';
4
4
  import { getRippleNetworkInfo } from '@vultisig/core-chain/chains/ripple/network/info';
5
+ import { findRippleTrustLine } from '@vultisig/core-chain/chains/ripple/trustLine';
5
6
  import { isFeeCoin } from '@vultisig/core-chain/coin/utils/isFeeCoin';
6
7
  import { shouldBePresent } from '@vultisig/lib-utils/assert/shouldBePresent';
7
8
  import { attempt } from '@vultisig/lib-utils/attempt';
@@ -24,7 +25,7 @@ const getRippleIssuedCurrencyBalance = async ({ address, id }) => {
24
25
  }
25
26
  throw linesResult.error;
26
27
  }
27
- const line = linesResult.data.find(({ account, currency: lineCurrency }) => account === issuer && toXrplCurrencyCode(lineCurrency) === toXrplCurrencyCode(currency));
28
+ const line = findRippleTrustLine({ lines: linesResult.data, currency, issuer });
28
29
  if (!line) {
29
30
  return BigInt(0);
30
31
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ripple.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/coin/balance/resolvers/ripple.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ripple.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/coin/balance/resolvers/ripple.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- export declare const coinFinderChainKinds: readonly ["evm", "cosmos", "solana", "cardano", "ripple"];
1
+ export declare const coinFinderChainKinds: readonly ["evm", "cosmos", "solana", "cardano", "ripple", "ton"];
2
2
  export type CoinFinderChainKind = (typeof coinFinderChainKinds)[number];
3
3
  //# sourceMappingURL=CoinFinderChainKind.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CoinFinderChainKind.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/chain/coin/find/CoinFinderChainKind.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,2DAA4D,CAAA;AAC7F,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAA"}
1
+ {"version":3,"file":"CoinFinderChainKind.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/chain/coin/find/CoinFinderChainKind.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,kEAAmE,CAAA;AACpG,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAA"}
@@ -1,2 +1,2 @@
1
- export const coinFinderChainKinds = ['evm', 'cosmos', 'solana', 'cardano', 'ripple'];
1
+ export const coinFinderChainKinds = ['evm', 'cosmos', 'solana', 'cardano', 'ripple', 'ton'];
2
2
  //# sourceMappingURL=CoinFinderChainKind.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CoinFinderChainKind.js","sourceRoot":"","sources":["../../../../../../packages/core/chain/coin/find/CoinFinderChainKind.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAU,CAAA"}
1
+ {"version":3,"file":"CoinFinderChainKind.js","sourceRoot":"","sources":["../../../../../../packages/core/chain/coin/find/CoinFinderChainKind.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,CAAU,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/chain/coin/find/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAA;AAKlD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAe9C,eAAO,MAAM,SAAS,EAAE,iBAAiB,CAAC,KAAK,CAW9C,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/chain/coin/find/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAA;AAKlD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAiB9C,eAAO,MAAM,SAAS,EAAE,iBAAiB,CAAC,KAAK,CAW9C,CAAA"}
@@ -6,12 +6,14 @@ import { findCosmosCoins } from './resolvers/cosmos.js';
6
6
  import { findEvmCoins } from './resolvers/evm/index.js';
7
7
  import { findRippleCoins } from './resolvers/ripple.js';
8
8
  import { findSolanaCoins } from './resolvers/solana/index.js';
9
+ import { findTonCoins } from './resolvers/ton.js';
9
10
  const resolvers = {
10
11
  cosmos: findCosmosCoins,
11
12
  evm: findEvmCoins,
12
13
  solana: findSolanaCoins,
13
14
  cardano: findCardanoCoins,
14
15
  ripple: findRippleCoins,
16
+ ton: findTonCoins,
15
17
  };
16
18
  export const findCoins = async (input) => {
17
19
  const chainKind = getChainKind(input.chain);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../packages/core/chain/coin/find/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAA;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,mCAAmC,CAAA;AAE3D,OAAO,EAAuB,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AAEjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAEpD,MAAM,SAAS,GAAwD;IACrE,MAAM,EAAE,eAAe;IACvB,GAAG,EAAE,YAAY;IACjB,MAAM,EAAE,eAAe;IACvB,OAAO,EAAE,gBAAgB;IACzB,MAAM,EAAE,eAAe;CACxB,CAAA;AAED,MAAM,CAAC,MAAM,SAAS,GAA6B,KAAK,EAAC,KAAK,EAAC,EAAE;IAC/D,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IAC3C,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,oBAAoB,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CACb,sCAAsC,SAAS,sBAAsB,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACvG,CAAA;IACH,CAAC;IAED,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/find/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAA;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,mCAAmC,CAAA;AAE3D,OAAO,EAAuB,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AAEjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAE9C,MAAM,SAAS,GAAwD;IACrE,MAAM,EAAE,eAAe;IACvB,GAAG,EAAE,YAAY;IACjB,MAAM,EAAE,eAAe;IACvB,OAAO,EAAE,gBAAgB;IACzB,MAAM,EAAE,eAAe;IACvB,GAAG,EAAE,YAAY;CAClB,CAAA;AAED,MAAM,CAAC,MAAM,SAAS,GAA6B,KAAK,EAAC,KAAK,EAAC,EAAE;IAC/D,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IAC3C,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,oBAAoB,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CACb,sCAAsC,SAAS,sBAAsB,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACvG,CAAA;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,SAAS,CAAC,SAAS,CAAC,CAAA;IAErC,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAA;AACxB,CAAC,CAAA"}
@@ -0,0 +1,15 @@
1
+ import { OtherChain } from '@vultisig/core-chain/Chain';
2
+ import { FindCoinsResolver } from '@vultisig/core-chain/coin/find/resolver';
3
+ /**
4
+ * Discovers the jettons held at `address` that pass verification.
5
+ *
6
+ * Only `verified` jettons are returned. TON wallets are carpet-bombed with
7
+ * airdropped counterfeits (fake USDT above all) and spam, and auto-adding those
8
+ * to a vault would put a "USDT" balance on the home screen that the user never
9
+ * received. Unverified and scam jettons can still be added by hand, where the
10
+ * UI labels them. Toncenter's indexer metadata rides along in the wallet
11
+ * listing, so no per-jetton call is needed; curated metadata wins for jettons
12
+ * we ship ourselves.
13
+ */
14
+ export declare const findTonCoins: FindCoinsResolver<OtherChain.Ton>;
15
+ //# sourceMappingURL=ton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ton.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/coin/find/resolvers/ton.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAMvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAA;AAM3E;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,EAAE,iBAAiB,CAAC,UAAU,CAAC,GAAG,CA8C1D,CAAA"}
@@ -0,0 +1,61 @@
1
+ import { tonAddressToBounceable } from '@vultisig/core-chain/chains/ton/address';
2
+ import { getOwnerJettonWallets } from '@vultisig/core-chain/chains/ton/api';
3
+ import { resolveTonJettonVerification } from '@vultisig/core-chain/chains/ton/jetton/verification';
4
+ import { getTonVerifiedJettonRegistry } from '@vultisig/core-chain/chains/ton/jetton/verifiedRegistry';
5
+ import { knownTokensIndex } from '@vultisig/core-chain/coin/knownTokens';
6
+ import { without } from '@vultisig/lib-utils/array/without';
7
+ const defaultJettonDecimals = 9;
8
+ /**
9
+ * Discovers the jettons held at `address` that pass verification.
10
+ *
11
+ * Only `verified` jettons are returned. TON wallets are carpet-bombed with
12
+ * airdropped counterfeits (fake USDT above all) and spam, and auto-adding those
13
+ * to a vault would put a "USDT" balance on the home screen that the user never
14
+ * received. Unverified and scam jettons can still be added by hand, where the
15
+ * UI labels them. Toncenter's indexer metadata rides along in the wallet
16
+ * listing, so no per-jetton call is needed; curated metadata wins for jettons
17
+ * we ship ourselves.
18
+ */
19
+ export const findTonCoins = async ({ address, chain }) => {
20
+ const [{ wallets, masters, userFriendlyAddresses }, registry] = await Promise.all([
21
+ getOwnerJettonWallets(address),
22
+ getTonVerifiedJettonRegistry(),
23
+ ]);
24
+ const coins = wallets.map(({ jettonMasterAddress, balance }) => {
25
+ if (balance <= 0n)
26
+ return;
27
+ const master = masters[jettonMasterAddress];
28
+ const verification = resolveTonJettonVerification({
29
+ address: jettonMasterAddress,
30
+ symbol: master?.symbol,
31
+ name: master?.name,
32
+ isFlaggedScam: master?.isFlaggedScam,
33
+ registry,
34
+ });
35
+ if (verification !== 'verified')
36
+ return;
37
+ const id = tonAddressToBounceable(userFriendlyAddresses[jettonMasterAddress] ?? jettonMasterAddress);
38
+ const known = knownTokensIndex[chain][id.toLowerCase()];
39
+ if (known) {
40
+ return { ...known, chain, id, address };
41
+ }
42
+ const verified = registry.byAddress[jettonMasterAddress];
43
+ if (!verified)
44
+ return;
45
+ const ticker = master?.symbol ?? verified.symbol;
46
+ if (!ticker)
47
+ return;
48
+ const priceProviderId = verified.priceProviderId;
49
+ return {
50
+ chain,
51
+ id,
52
+ address,
53
+ ticker,
54
+ decimals: master?.decimals ?? verified.decimals ?? defaultJettonDecimals,
55
+ logo: master?.logo ?? verified.logo,
56
+ ...(priceProviderId === undefined ? {} : { priceProviderId }),
57
+ };
58
+ });
59
+ return without(coins, undefined);
60
+ };
61
+ //# sourceMappingURL=ton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ton.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/coin/find/resolvers/ton.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAA;AAChF,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAA;AAC3E,OAAO,EAAE,4BAA4B,EAAE,MAAM,qDAAqD,CAAA;AAClG,OAAO,EAAE,4BAA4B,EAAE,MAAM,yDAAyD,CAAA;AAGtG,OAAO,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAA;AACxE,OAAO,EAAE,OAAO,EAAE,MAAM,mCAAmC,CAAA;AAE3D,MAAM,qBAAqB,GAAG,CAAC,CAAA;AAE/B;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,YAAY,GAAsC,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE;IAC1F,MAAM,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,qBAAqB,EAAE,EAAE,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAChF,qBAAqB,CAAC,OAAO,CAAC;QAC9B,4BAA4B,EAAE;KAC/B,CAAC,CAAA;IAEF,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,mBAAmB,EAAE,OAAO,EAAE,EAA2C,EAAE;QACtG,IAAI,OAAO,IAAI,EAAE;YAAE,OAAM;QAEzB,MAAM,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAA;QAC3C,MAAM,YAAY,GAAG,4BAA4B,CAAC;YAChD,OAAO,EAAE,mBAAmB;YAC5B,MAAM,EAAE,MAAM,EAAE,MAAM;YACtB,IAAI,EAAE,MAAM,EAAE,IAAI;YAClB,aAAa,EAAE,MAAM,EAAE,aAAa;YACpC,QAAQ;SACT,CAAC,CAAA;QACF,IAAI,YAAY,KAAK,UAAU;YAAE,OAAM;QAEvC,MAAM,EAAE,GAAG,sBAAsB,CAAC,qBAAqB,CAAC,mBAAmB,CAAC,IAAI,mBAAmB,CAAC,CAAA;QAEpG,MAAM,KAAK,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,CAAA;QACvD,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,CAAA;QACzC,CAAC;QAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAA;QACxD,IAAI,CAAC,QAAQ;YAAE,OAAM;QAErB,MAAM,MAAM,GAAG,MAAM,EAAE,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAA;QAChD,IAAI,CAAC,MAAM;YAAE,OAAM;QAEnB,MAAM,eAAe,GAAG,QAAQ,CAAC,eAAe,CAAA;QAEhD,OAAO;YACL,KAAK;YACL,EAAE;YACF,OAAO;YACP,MAAM;YACN,QAAQ,EAAE,MAAM,EAAE,QAAQ,IAAI,QAAQ,CAAC,QAAQ,IAAI,qBAAqB;YACxE,IAAI,EAAE,MAAM,EAAE,IAAI,IAAI,QAAQ,CAAC,IAAI;YACnC,GAAG,CAAC,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC;SAC9D,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,OAAO,OAAO,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;AAClC,CAAC,CAAA"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Trust tier a wallet can attach to a discovered or user-added token.
3
+ *
4
+ * - `verified`: listed in a curated registry we trust (our own known-token list
5
+ * or a chain ecosystem whitelist).
6
+ * - `scam`: positively identified as malicious, typically because it
7
+ * impersonates a verified token's symbol or name while living at a different
8
+ * contract address, or because the indexer flagged it.
9
+ * - `unverified`: neither — a real holding we know nothing about.
10
+ */
11
+ export declare const tokenVerifications: readonly ["verified", "unverified", "scam"];
12
+ export type TokenVerification = (typeof tokenVerifications)[number];
13
+ //# sourceMappingURL=tokenVerification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenVerification.d.ts","sourceRoot":"","sources":["../../../../../packages/core/chain/coin/tokenVerification.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,6CAA8C,CAAA;AAE7E,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAA"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Trust tier a wallet can attach to a discovered or user-added token.
3
+ *
4
+ * - `verified`: listed in a curated registry we trust (our own known-token list
5
+ * or a chain ecosystem whitelist).
6
+ * - `scam`: positively identified as malicious, typically because it
7
+ * impersonates a verified token's symbol or name while living at a different
8
+ * contract address, or because the indexer flagged it.
9
+ * - `unverified`: neither — a real holding we know nothing about.
10
+ */
11
+ export const tokenVerifications = ['verified', 'unverified', 'scam'];
12
+ //# sourceMappingURL=tokenVerification.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenVerification.js","sourceRoot":"","sources":["../../../../../packages/core/chain/coin/tokenVerification.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,UAAU,EAAE,YAAY,EAAE,MAAM,CAAU,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"getSwapKitQuote.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/swap/general/swapkit/api/getSwapKitQuote.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAA;AAGnE,OAAO,EAAE,gBAAgB,EAAiB,MAAM,oDAAoD,CAAA;AA2BpG,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAGzE,KAAK,KAAK,GAAG,MAAM,CAAC,iBAAiB,EAAE,WAAW,CAAC,GAAG;IACpD,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAo4BD,eAAO,MAAM,eAAe,GAAU,+CAMnC,KAAK,KAAG,OAAO,CAAC,gBAAgB,CAwElC,CAAA"}
1
+ {"version":3,"file":"getSwapKitQuote.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/swap/general/swapkit/api/getSwapKitQuote.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAA;AAGnE,OAAO,EAAE,gBAAgB,EAAiB,MAAM,oDAAoD,CAAA;AA4BpG,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAGzE,KAAK,KAAK,GAAG,MAAM,CAAC,iBAAiB,EAAE,WAAW,CAAC,GAAG;IACpD,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AA++BD,eAAO,MAAM,eAAe,GAAU,+CAMnC,KAAK,KAAG,OAAO,CAAC,gBAAgB,CAwElC,CAAA"}
@@ -1,6 +1,7 @@
1
1
  import { base64Decode } from '@bufbuild/protobuf/wire';
2
2
  import { toChainAmount } from '@vultisig/core-chain/amount/toChainAmount';
3
3
  import { Chain } from '@vultisig/core-chain/Chain';
4
+ import { areEqualTonAddresses, tonAddressToBounceable } from '@vultisig/core-chain/chains/ton/address';
4
5
  import { chainFeeCoin } from '@vultisig/core-chain/coin/chainFeeCoin';
5
6
  import { usdc } from '@vultisig/core-chain/coin/knownTokens';
6
7
  import { assertSwapKitAddressReputation, assertSwapKitDestinationMatchesTarget, } from '@vultisig/core-chain/swap/general/knownAggregatorRouters';
@@ -9,6 +10,7 @@ import { isSwapKitSourceChain, } from '@vultisig/core-chain/swap/general/swapkit
9
10
  import { SwapKitAmountBelowMinimumError, SwapKitFeeShapeError, SwapKitNoEligibleRoutesError, } from '@vultisig/core-chain/swap/general/swapkit/SwapKitErrors';
10
11
  import { isSwapKitPairSupported, normalizeSwapKitProvider, resolveSwapKitChainMetadata, swapKitAllowedProviders, swapKitExcludedProviders, } from '@vultisig/core-chain/swap/general/swapkit/SwapKitProviders';
11
12
  import { isOneOf } from '@vultisig/lib-utils/array/isOneOf';
13
+ import { attempt } from '@vultisig/lib-utils/attempt';
12
14
  import { withoutUndefinedFields } from '@vultisig/lib-utils/record/withoutUndefinedFields';
13
15
  import { address as btcAddress, networks, Psbt } from 'bitcoinjs-lib';
14
16
  const swapKitProviderQuoteAttempts = [
@@ -332,17 +334,97 @@ const toTransferAmount = (value, decimals) => {
332
334
  }
333
335
  return value.includes('.') ? toChainAmount(value, decimals) : BigInt(value);
334
336
  };
337
+ const isTransferAmountValue = (value) => typeof value === 'string' || typeof value === 'number' || typeof value === 'bigint';
335
338
  const getTransferAmount = ({ depositAmount, tx }, amount, decimals) => {
336
339
  if (depositAmount) {
337
340
  return toChainAmount(depositAmount, decimals);
338
341
  }
339
- if (Array.isArray(tx) &&
340
- isRecord(tx[0]) &&
341
- (typeof tx[0].amount === 'string' || typeof tx[0].amount === 'number' || typeof tx[0].amount === 'bigint')) {
342
+ if (Array.isArray(tx) && isRecord(tx[0]) && isTransferAmountValue(tx[0].amount)) {
342
343
  return toTransferAmount(tx[0].amount, decimals);
343
344
  }
344
345
  return amount;
345
346
  };
347
+ /**
348
+ * The single transfer SwapKit describes in its `tx[]` array, or `undefined`
349
+ * when `tx` is any other shape — an EVM object, an opaque PSBT / PTB string, or
350
+ * absent because `disableBuildTx` was sent.
351
+ *
352
+ * More than one entry is rejected rather than ignored: only `tx[0]` is ever
353
+ * built, so a multi-transfer route would be signed as a partial deposit that
354
+ * under-funds the swap. The count is checked before the entry shape so a
355
+ * malformed trailing entry cannot slip a multi-transfer array past this guard.
356
+ */
357
+ const getTransferTxEntry = (tx) => {
358
+ if (!Array.isArray(tx) || tx.length === 0) {
359
+ return undefined;
360
+ }
361
+ if (tx.length > 1) {
362
+ throw new Error(`SwapKit transfer route returned ${tx.length} transfers; only the first would be signed, so the swap would be under-funded.`);
363
+ }
364
+ return isRecord(tx[0]) ? tx[0] : undefined;
365
+ };
366
+ /**
367
+ * The agreed TON deposit destination in its bounceable (`EQ…`) form.
368
+ *
369
+ * `assertTransferAgreement` compares TON spellings by account, so a route whose
370
+ * fields spell one account as `UQ…`, raw `0:hex` and `EQ…` passes — and the
371
+ * spelling that wins the precedence order is what the signer would otherwise
372
+ * read the bounce flag from. A deposit that goes out non-bounceable to a
373
+ * rejecting contract is absorbed instead of refunded, so the agreed account is
374
+ * re-spelled bounceable here, whichever field it came from. A string that is
375
+ * not a TON address at all cannot be a deposit destination and is refused.
376
+ */
377
+ const toCanonicalTonDeposit = (destination) => {
378
+ const canonical = attempt(() => tonAddressToBounceable(destination));
379
+ if ('error' in canonical) {
380
+ throw new Error(`SwapKit transfer route returned an invalid TON deposit address: ${destination}`);
381
+ }
382
+ return canonical.data;
383
+ };
384
+ const areEqualTransferAddresses = (left, right, chain) => chain === Chain.Ton ? areEqualTonAddresses(left, right) : left === right;
385
+ /**
386
+ * Fail closed when the `/v3/swap` response disagrees with itself about where
387
+ * the deposit goes or how large it is.
388
+ *
389
+ * `targetAddress`, `depositAddress` and `tx[]` are independent fields carrying
390
+ * the same fact, and the resolvers above take the first one that is present and
391
+ * never look at the rest. So a response whose halves diverge — a provider bug,
392
+ * an API change, a tampered payload — signs whichever field happens to win the
393
+ * precedence order while the others name a different recipient or size, and
394
+ * nothing downstream can tell. Neither field is authoritative enough to pick a
395
+ * winner from, so a divergence is refused instead of resolved.
396
+ *
397
+ * Addresses are compared per chain because TON spells one account as `EQ…`,
398
+ * `UQ…` or raw `workchain:hex` — comparing those as strings would reject
399
+ * healthy routes.
400
+ */
401
+ const assertTransferAgreement = (response, chain, decimals) => {
402
+ const entry = getTransferTxEntry(response.tx);
403
+ const destinations = [
404
+ { field: 'targetAddress', value: response.targetAddress },
405
+ { field: 'depositAddress', value: response.depositAddress },
406
+ { field: 'tx[0].address', value: typeof entry?.address === 'string' ? entry.address : undefined },
407
+ ].flatMap(({ field, value }) => (value?.trim() ? [{ field, value: value.trim() }] : []));
408
+ const [primaryDestination, ...otherDestinations] = destinations;
409
+ if (primaryDestination) {
410
+ const divergent = otherDestinations.find(({ value }) => !areEqualTransferAddresses(value, primaryDestination.value, chain));
411
+ if (divergent) {
412
+ throw new Error(`SwapKit transfer route disagrees with itself about the destination: ` +
413
+ `${primaryDestination.field} is ${primaryDestination.value} but ${divergent.field} is ${divergent.value}.`);
414
+ }
415
+ }
416
+ const txAmountValue = entry && isTransferAmountValue(entry.amount) ? entry.amount : undefined;
417
+ if (txAmountValue === undefined || !response.depositAmount) {
418
+ return;
419
+ }
420
+ const txAmount = toTransferAmount(txAmountValue, decimals);
421
+ const depositAmount = toChainAmount(response.depositAmount, decimals);
422
+ if (txAmount !== depositAmount) {
423
+ throw new Error(`SwapKit transfer route disagrees with itself about the amount: ` +
424
+ `depositAmount is ${response.depositAmount} (${depositAmount} base units) ` +
425
+ `but tx[0].amount is ${txAmountValue} (${txAmount} base units).`);
426
+ }
427
+ };
346
428
  const shouldUseTransferTx = (chain) => isOneOf(chain, swapKitTransferSourceChains);
347
429
  // Transfer-arm chains that still need SwapKit to BUILD the transaction, so
348
430
  // `/v3/swap` must not be sent `disableBuildTx`. Bitcoin gets a PSBT and Sui a
@@ -397,10 +479,12 @@ const getBitcoinPsbtDestinationAmount = ({ txPayload, senderAddress, targetAddre
397
479
  }
398
480
  };
399
481
  const buildTransferTx = (response, from, amount) => {
400
- const to = getTransferTargetAddress(response);
401
- if (!to) {
482
+ assertTransferAgreement(response, from.chain, from.decimals);
483
+ const agreedDestination = getTransferTargetAddress(response);
484
+ if (!agreedDestination) {
402
485
  throw new Error('SwapKit transfer route did not return a target address.');
403
486
  }
487
+ const to = from.chain === Chain.Ton ? toCanonicalTonDeposit(agreedDestination) : agreedDestination;
404
488
  // SwapKit renames base64 tx types on the wire without versioning — `SOLANA`
405
489
  // became `SERIALIZED_BASE64` and `CARDANO` became `CBOR` mid-flight (iOS
406
490
  // accepts both spellings in `SwapKitSwapResponse.decodeTx`). A Sui route's