@vultisig/core-chain 5.0.0 → 5.2.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 (81) hide show
  1. package/CHANGELOG.md +64 -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/failure.d.ts +70 -0
  18. package/dist/chains/ton/failure.d.ts.map +1 -0
  19. package/dist/chains/ton/failure.js +170 -0
  20. package/dist/chains/ton/failure.js.map +1 -0
  21. package/dist/chains/ton/jetton/symbol.d.ts +9 -0
  22. package/dist/chains/ton/jetton/symbol.d.ts.map +1 -0
  23. package/dist/chains/ton/jetton/symbol.js +61 -0
  24. package/dist/chains/ton/jetton/symbol.js.map +1 -0
  25. package/dist/chains/ton/jetton/verification.d.ts +35 -0
  26. package/dist/chains/ton/jetton/verification.d.ts.map +1 -0
  27. package/dist/chains/ton/jetton/verification.js +45 -0
  28. package/dist/chains/ton/jetton/verification.js.map +1 -0
  29. package/dist/chains/ton/jetton/verifiedRegistry.d.ts +43 -0
  30. package/dist/chains/ton/jetton/verifiedRegistry.d.ts.map +1 -0
  31. package/dist/chains/ton/jetton/verifiedRegistry.js +94 -0
  32. package/dist/chains/ton/jetton/verifiedRegistry.js.map +1 -0
  33. package/dist/chains/ton/wallet.d.ts +50 -0
  34. package/dist/chains/ton/wallet.d.ts.map +1 -0
  35. package/dist/chains/ton/wallet.js +54 -0
  36. package/dist/chains/ton/wallet.js.map +1 -0
  37. package/dist/chains/ton/walletV5R1.d.ts +27 -0
  38. package/dist/chains/ton/walletV5R1.d.ts.map +1 -0
  39. package/dist/chains/ton/walletV5R1.js +53 -0
  40. package/dist/chains/ton/walletV5R1.js.map +1 -0
  41. package/dist/coin/balance/resolvers/ripple.d.ts.map +1 -1
  42. package/dist/coin/balance/resolvers/ripple.js +3 -2
  43. package/dist/coin/balance/resolvers/ripple.js.map +1 -1
  44. package/dist/coin/find/CoinFinderChainKind.d.ts +1 -1
  45. package/dist/coin/find/CoinFinderChainKind.d.ts.map +1 -1
  46. package/dist/coin/find/CoinFinderChainKind.js +1 -1
  47. package/dist/coin/find/CoinFinderChainKind.js.map +1 -1
  48. package/dist/coin/find/index.d.ts.map +1 -1
  49. package/dist/coin/find/index.js +2 -0
  50. package/dist/coin/find/index.js.map +1 -1
  51. package/dist/coin/find/resolvers/ton.d.ts +15 -0
  52. package/dist/coin/find/resolvers/ton.d.ts.map +1 -0
  53. package/dist/coin/find/resolvers/ton.js +61 -0
  54. package/dist/coin/find/resolvers/ton.js.map +1 -0
  55. package/dist/coin/tokenVerification.d.ts +13 -0
  56. package/dist/coin/tokenVerification.d.ts.map +1 -0
  57. package/dist/coin/tokenVerification.js +12 -0
  58. package/dist/coin/tokenVerification.js.map +1 -0
  59. package/dist/publicKey/address/deriveAddress.d.ts +8 -1
  60. package/dist/publicKey/address/deriveAddress.d.ts.map +1 -1
  61. package/dist/publicKey/address/deriveAddress.js +5 -1
  62. package/dist/publicKey/address/deriveAddress.js.map +1 -1
  63. package/dist/publicKey/address/getChainAddress.d.ts +4 -1
  64. package/dist/publicKey/address/getChainAddress.d.ts.map +1 -1
  65. package/dist/publicKey/address/getChainAddress.js +2 -2
  66. package/dist/publicKey/address/getChainAddress.js.map +1 -1
  67. package/dist/swap/general/swapkit/api/getSwapKitQuote.d.ts.map +1 -1
  68. package/dist/swap/general/swapkit/api/getSwapKitQuote.js +89 -5
  69. package/dist/swap/general/swapkit/api/getSwapKitQuote.js.map +1 -1
  70. package/dist/tx/broadcast/resolvers/ton.d.ts.map +1 -1
  71. package/dist/tx/broadcast/resolvers/ton.js +8 -0
  72. package/dist/tx/broadcast/resolvers/ton.js.map +1 -1
  73. package/dist/tx/status/index.d.ts +2 -2
  74. package/dist/tx/status/index.d.ts.map +1 -1
  75. package/dist/tx/status/resolver.d.ts +15 -0
  76. package/dist/tx/status/resolver.d.ts.map +1 -1
  77. package/dist/tx/status/resolvers/ton.d.ts +5 -1
  78. package/dist/tx/status/resolvers/ton.d.ts.map +1 -1
  79. package/dist/tx/status/resolvers/ton.js +8 -29
  80. package/dist/tx/status/resolvers/ton.js.map +1 -1
  81. package/package.json +46 -1
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Why a TON transaction did not move funds, in terms a user can act on. The
3
+ * wallet contract's own checks (`seqno-mismatch`, `expired`, `invalid-signature`,
4
+ * `wallet-id-mismatch`) fire in the compute phase of the sender's wallet; the
5
+ * money-related ones fire when the wallet tries to emit the transfer (action
6
+ * phase) or in the jetton wallet's compute phase.
7
+ */
8
+ export declare const tonTxFailureReasons: readonly ["seqno-mismatch", "expired", "invalid-signature", "wallet-id-mismatch", "insufficient-funds", "out-of-gas", "invalid-destination", "not-enough-jettons", "jetton-unauthorized", "action-failed", "action-partially-failed", "aborted", "contract-rejected"];
9
+ export type TonTxFailureReason = (typeof tonTxFailureReasons)[number];
10
+ /** Which phase of the TON transaction produced the code: TVM execution or emitting the outgoing messages. */
11
+ export type TonTxPhase = 'compute' | 'action';
12
+ export type TonTxFailure = {
13
+ reason: TonTxFailureReason;
14
+ phase: TonTxPhase;
15
+ exitCode?: number;
16
+ /** Plain-language explanation with the remedy, in English. */
17
+ message: string;
18
+ };
19
+ /** Classifies a compute-phase exit code (0 and 1 are success and yield `undefined`). */
20
+ export declare const getTonComputeFailure: (exitCode: number | undefined) => TonTxFailure | undefined;
21
+ type TonActionPhaseOutcome = {
22
+ success?: boolean;
23
+ no_funds?: boolean;
24
+ result_code?: number;
25
+ skipped_actions?: number;
26
+ /** Outgoing messages the phase actually produced, when the node reports it. */
27
+ msgs_created?: number;
28
+ };
29
+ /**
30
+ * Classifies a failed action phase. A result code the table names wins; an
31
+ * unnamed one is read as a funding failure only when `no_funds` backs it, and
32
+ * otherwise stays generic with the code attached. `no_funds` without any code
33
+ * still means the transfer could not be paid for, and a skipped or unsuccessful
34
+ * action with neither is generic — worded by `genericActionReason`, which will not
35
+ * claim nothing was sent unless the node says so.
36
+ */
37
+ export declare const getTonActionFailure: (action: TonActionPhaseOutcome | undefined) => TonTxFailure | undefined;
38
+ type TonTransactionOutcome = {
39
+ aborted?: boolean;
40
+ compute_ph?: {
41
+ exit_code?: number;
42
+ };
43
+ action?: TonActionPhaseOutcome;
44
+ };
45
+ /**
46
+ * Explains why an indexed TON transaction failed, or `undefined` when it did
47
+ * not. The compute phase is consulted first because it carries the specific
48
+ * exit code; an aborted transaction with no readable phase is reported as such.
49
+ */
50
+ export declare const getTonTxFailure: (description: TonTransactionOutcome) => TonTxFailure | undefined;
51
+ /**
52
+ * Reads the wallet contract's exit code out of a toncenter `sendBoc` rejection
53
+ * ("… inbound external message rejected by transaction …: exitcode=133, steps=49,
54
+ * gas_used=0 …"). The message never reached the chain, so the code is always the
55
+ * sender's wallet refusing it in its compute phase. Returns `undefined` for
56
+ * transport errors and any other rejection shape.
57
+ */
58
+ export declare const parseTonBroadcastRejection: (error: unknown) => TonTxFailure | undefined;
59
+ /**
60
+ * A TON broadcast the sender's wallet contract refused, with the refusal
61
+ * classified. `message` is the human-readable explanation so any consumer that
62
+ * only prints `error.message` already shows the right remedy; the original
63
+ * toncenter error stays in `cause`.
64
+ */
65
+ export declare class TonBroadcastRejectedError extends Error {
66
+ readonly failure: TonTxFailure;
67
+ constructor(failure: TonTxFailure, cause: unknown);
68
+ }
69
+ export {};
70
+ //# sourceMappingURL=failure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"failure.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/ton/failure.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,uQActB,CAAA;AAEV,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAA;AAErE,6GAA6G;AAC7G,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAA;AAE7C,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,kBAAkB,CAAA;IAC1B,KAAK,EAAE,UAAU,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,8DAA8D;IAC9D,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAsFD,wFAAwF;AACxF,eAAO,MAAM,oBAAoB,GAAI,UAAU,MAAM,GAAG,SAAS,KAAG,YAAY,GAAG,SAIlF,CAAA;AAED,KAAK,qBAAqB,GAAG;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAeD;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,GAAI,QAAQ,qBAAqB,GAAG,SAAS,KAAG,YAAY,GAAG,SAkB9F,CAAA;AAED,KAAK,qBAAqB,GAAG;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,UAAU,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACnC,MAAM,CAAC,EAAE,qBAAqB,CAAA;CAC/B,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAAI,aAAa,qBAAqB,KAAG,YAAY,GAAG,SAGJ,CAAA;AAIhF;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,GAAI,OAAO,OAAO,KAAG,YAAY,GAAG,SAK1E,CAAA;AAED;;;;;GAKG;AACH,qBAAa,yBAA0B,SAAQ,KAAK;aAEhC,OAAO,EAAE,YAAY;gBAArB,OAAO,EAAE,YAAY,EACrC,KAAK,EAAE,OAAO;CAKjB"}
@@ -0,0 +1,170 @@
1
+ import { extractErrorMsg } from '@vultisig/lib-utils/error/extractErrorMsg';
2
+ /**
3
+ * Why a TON transaction did not move funds, in terms a user can act on. The
4
+ * wallet contract's own checks (`seqno-mismatch`, `expired`, `invalid-signature`,
5
+ * `wallet-id-mismatch`) fire in the compute phase of the sender's wallet; the
6
+ * money-related ones fire when the wallet tries to emit the transfer (action
7
+ * phase) or in the jetton wallet's compute phase.
8
+ */
9
+ export const tonTxFailureReasons = [
10
+ 'seqno-mismatch',
11
+ 'expired',
12
+ 'invalid-signature',
13
+ 'wallet-id-mismatch',
14
+ 'insufficient-funds',
15
+ 'out-of-gas',
16
+ 'invalid-destination',
17
+ 'not-enough-jettons',
18
+ 'jetton-unauthorized',
19
+ 'action-failed',
20
+ 'action-partially-failed',
21
+ 'aborted',
22
+ 'contract-rejected',
23
+ ];
24
+ /**
25
+ * Compute-phase exit codes. The sender's wallet contract throws the first block
26
+ * from `recv_external`: wallet v3/v4 use 33–36, W5 uses 133–136 for the same
27
+ * checks. 13 / -14 are the TVM's out-of-gas codes. 705 and 706 come from the
28
+ * standard jetton wallet (TEP-74) and mean the same thing on a transfer and on
29
+ * a burn; its 707 and 709 are deliberately absent because the reference
30
+ * contract reuses each for two unrelated checks (707: unauthorized incoming
31
+ * transfer, or too little TON on a burn; 709: too little TON on a transfer, or
32
+ * an unexpected bounced op), and the code alone cannot tell which. Everything
33
+ * else is a contract-specific revert we can only report by number.
34
+ */
35
+ const computeExitCodeReasons = {
36
+ 33: 'seqno-mismatch',
37
+ 133: 'seqno-mismatch',
38
+ 34: 'wallet-id-mismatch',
39
+ 134: 'wallet-id-mismatch',
40
+ 35: 'invalid-signature',
41
+ 135: 'invalid-signature',
42
+ 36: 'expired',
43
+ 136: 'expired',
44
+ 13: 'out-of-gas',
45
+ [-14]: 'out-of-gas',
46
+ 705: 'jetton-unauthorized',
47
+ 706: 'not-enough-jettons',
48
+ };
49
+ /**
50
+ * Action-phase result codes that mean one thing. 36 here is an invalid destination,
51
+ * not the wallet's `expired` (36), which can only come from the compute phase. 37 is
52
+ * "Not enough GRAMs" and says so on its own.
53
+ *
54
+ * 40 is deliberately absent. It reads "Cannot process a message — not enough funds,
55
+ * the message is too large, or its Merkle depth is too big", so naming it a funding
56
+ * failure would send a user to top up their balance when the payload is what has to
57
+ * change. Codes like it fall through to `no_funds` below, the only authoritative
58
+ * funding signal in the phase.
59
+ */
60
+ const actionResultCodeReasons = {
61
+ 36: 'invalid-destination',
62
+ 37: 'insufficient-funds',
63
+ };
64
+ /**
65
+ * Human-readable explanations. Each says what happened and what to do; the
66
+ * remedy matters more than the code, because the two failures that dominate
67
+ * TON support — a replayed seqno and an expired `valid_until` — both look like
68
+ * "the network rejected it" and have opposite fixes.
69
+ */
70
+ const failureMessages = {
71
+ 'seqno-mismatch': 'Another transaction from this wallet was processed first, so the network rejected this one as out of order. Check your history: if this transfer is not there, send it again.',
72
+ expired: "The transaction's time window closed before the network processed it. Make sure your device's date and time are set automatically, then send it again.",
73
+ 'invalid-signature': 'The wallet contract rejected the signature. Sign the transaction again; if it keeps failing, the wallet contract at this address does not match this vault.',
74
+ 'wallet-id-mismatch': 'The transaction was built for a different wallet contract version than the one deployed at this address.',
75
+ 'insufficient-funds': 'Not enough TON to cover the amount plus network fees. Keep about 0.05 TON spare for fees and try again.',
76
+ 'out-of-gas': 'The transaction ran out of gas before it could finish. Attach more TON to the transfer and try again.',
77
+ 'invalid-destination': 'The destination address is not valid on TON. Check the address and try again.',
78
+ 'not-enough-jettons': 'This wallet does not hold enough of the token to send that amount.',
79
+ 'jetton-unauthorized': 'The token contract refused the transfer because this wallet is not allowed to move these tokens.',
80
+ 'action-failed': 'The wallet accepted the transaction but could not carry out the transfer, so nothing was sent. The network fee was still charged. Check the transaction and try again.',
81
+ 'action-partially-failed': 'The wallet could not carry out at least one transfer in this transaction, and others in it may have gone through. The network fee was still charged. Check your transaction history before sending again.',
82
+ aborted: 'The network aborted this transaction before it could carry out the transfer.',
83
+ 'contract-rejected': 'The contract rejected the transaction.',
84
+ };
85
+ const describe = (reason, exitCode) => reason === 'contract-rejected' && exitCode !== undefined
86
+ ? `The contract rejected the transaction (exit code ${exitCode}).`
87
+ : failureMessages[reason];
88
+ const makeFailure = (reason, phase, exitCode) => ({
89
+ reason,
90
+ phase,
91
+ ...(exitCode === undefined ? {} : { exitCode }),
92
+ message: describe(reason, exitCode),
93
+ });
94
+ /** Classifies a compute-phase exit code (0 and 1 are success and yield `undefined`). */
95
+ export const getTonComputeFailure = (exitCode) => {
96
+ if (exitCode === undefined || exitCode === 0 || exitCode === 1)
97
+ return undefined;
98
+ return makeFailure(computeExitCodeReasons[exitCode] ?? 'contract-rejected', 'compute', exitCode);
99
+ };
100
+ /**
101
+ * Which generic explanation a failed action phase gets.
102
+ *
103
+ * Under `IGNORE_ERRORS` — the mode every Vultisig TON send uses — a failing action
104
+ * is skipped and the remaining ones still go out, so a batch can lose one transfer
105
+ * and deliver the rest. Telling that user nothing was sent and to try again is how a
106
+ * duplicate transfer happens, so only the node's own `msgs_created: 0` earns the
107
+ * "nothing was sent" wording. A node that reports nothing proves nothing either way
108
+ * and gets the neutral explanation, which reads correctly for both outcomes.
109
+ */
110
+ const genericActionReason = ({ msgs_created }) => msgs_created === 0 ? 'action-failed' : 'action-partially-failed';
111
+ /**
112
+ * Classifies a failed action phase. A result code the table names wins; an
113
+ * unnamed one is read as a funding failure only when `no_funds` backs it, and
114
+ * otherwise stays generic with the code attached. `no_funds` without any code
115
+ * still means the transfer could not be paid for, and a skipped or unsuccessful
116
+ * action with neither is generic — worded by `genericActionReason`, which will not
117
+ * claim nothing was sent unless the node says so.
118
+ */
119
+ export const getTonActionFailure = (action) => {
120
+ if (!action)
121
+ return undefined;
122
+ const { success, no_funds, result_code, skipped_actions } = action;
123
+ if (result_code !== undefined && result_code !== 0) {
124
+ // A code the table does not name is a funding failure only when the node says so.
125
+ const reason = actionResultCodeReasons[result_code] ?? (no_funds === true ? 'insufficient-funds' : genericActionReason(action));
126
+ return makeFailure(reason, 'action', result_code);
127
+ }
128
+ if (no_funds === true)
129
+ return makeFailure('insufficient-funds', 'action');
130
+ if (success === false || (skipped_actions ?? 0) > 0)
131
+ return makeFailure(genericActionReason(action), 'action');
132
+ return undefined;
133
+ };
134
+ /**
135
+ * Explains why an indexed TON transaction failed, or `undefined` when it did
136
+ * not. The compute phase is consulted first because it carries the specific
137
+ * exit code; an aborted transaction with no readable phase is reported as such.
138
+ */
139
+ export const getTonTxFailure = (description) => getTonComputeFailure(description.compute_ph?.exit_code) ??
140
+ getTonActionFailure(description.action) ??
141
+ (description.aborted === true ? makeFailure('aborted', 'compute') : undefined);
142
+ const rejectionExitCodePattern = /exitcode=(-?\d+)/i;
143
+ /**
144
+ * Reads the wallet contract's exit code out of a toncenter `sendBoc` rejection
145
+ * ("… inbound external message rejected by transaction …: exitcode=133, steps=49,
146
+ * gas_used=0 …"). The message never reached the chain, so the code is always the
147
+ * sender's wallet refusing it in its compute phase. Returns `undefined` for
148
+ * transport errors and any other rejection shape.
149
+ */
150
+ export const parseTonBroadcastRejection = (error) => {
151
+ const match = rejectionExitCodePattern.exec(String(extractErrorMsg(error)));
152
+ if (!match)
153
+ return undefined;
154
+ return getTonComputeFailure(Number(match[1]));
155
+ };
156
+ /**
157
+ * A TON broadcast the sender's wallet contract refused, with the refusal
158
+ * classified. `message` is the human-readable explanation so any consumer that
159
+ * only prints `error.message` already shows the right remedy; the original
160
+ * toncenter error stays in `cause`.
161
+ */
162
+ export class TonBroadcastRejectedError extends Error {
163
+ failure;
164
+ constructor(failure, cause) {
165
+ super(failure.message, { cause });
166
+ this.failure = failure;
167
+ this.name = 'TonBroadcastRejectedError';
168
+ }
169
+ }
170
+ //# sourceMappingURL=failure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"failure.js","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/ton/failure.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Collapses a jetton symbol or name to the Latin skeleton a user perceives, so
3
+ * `USD₮`, `UЅDT` (Cyrillic Ѕ), `$USĐ₮` and `usdt` all compare equal to `USDT`.
4
+ * Compatibility decomposition folds full-width and mathematical letter forms,
5
+ * diacritics are dropped, known homoglyphs are mapped, and everything that is
6
+ * not `A–Z`/`0–9` is removed. Returns an empty string when nothing survives.
7
+ */
8
+ export declare const normalizeJettonSymbol: (value: string) => string;
9
+ //# sourceMappingURL=symbol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"symbol.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/ton/jetton/symbol.ts"],"names":[],"mappings":"AAmDA;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,GAAI,OAAO,MAAM,KAAG,MAIxB,CAAA"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Homoglyphs scammers substitute into a jetton symbol so it *reads* like a
3
+ * verified one while differing byte-for-byte: Cyrillic/Greek capitals that look
4
+ * like Latin ones, the tugrik sign standing in for `T`, and stroked `D`s. Keys
5
+ * are already upper-cased because the map is applied after `toUpperCase()`.
6
+ */
7
+ const confusables = {
8
+ // Cyrillic
9
+ А: 'A',
10
+ В: 'B',
11
+ Е: 'E',
12
+ Ё: 'E',
13
+ Ѕ: 'S',
14
+ І: 'I',
15
+ Ј: 'J',
16
+ К: 'K',
17
+ М: 'M',
18
+ Н: 'H',
19
+ О: 'O',
20
+ Р: 'P',
21
+ С: 'C',
22
+ Т: 'T',
23
+ У: 'Y',
24
+ Х: 'X',
25
+ Ԛ: 'Q',
26
+ Ԝ: 'W',
27
+ // Greek
28
+ Α: 'A',
29
+ Β: 'B',
30
+ Ε: 'E',
31
+ Ζ: 'Z',
32
+ Η: 'H',
33
+ Ι: 'I',
34
+ Κ: 'K',
35
+ Μ: 'M',
36
+ Ν: 'N',
37
+ Ο: 'O',
38
+ Ρ: 'P',
39
+ Τ: 'T',
40
+ Υ: 'Y',
41
+ Χ: 'X',
42
+ // Currency and stroked letters
43
+ '₮': 'T',
44
+ Đ: 'D',
45
+ Ð: 'D',
46
+ Ɖ: 'D',
47
+ Ŧ: 'T',
48
+ };
49
+ const combiningMarks = /[̀-ͯ]/g;
50
+ /**
51
+ * Collapses a jetton symbol or name to the Latin skeleton a user perceives, so
52
+ * `USD₮`, `UЅDT` (Cyrillic Ѕ), `$USĐ₮` and `usdt` all compare equal to `USDT`.
53
+ * Compatibility decomposition folds full-width and mathematical letter forms,
54
+ * diacritics are dropped, known homoglyphs are mapped, and everything that is
55
+ * not `A–Z`/`0–9` is removed. Returns an empty string when nothing survives.
56
+ */
57
+ export const normalizeJettonSymbol = (value) => Array.from(value.normalize('NFKD').replace(combiningMarks, '').toUpperCase())
58
+ .map(char => confusables[char] ?? char)
59
+ .join('')
60
+ .replace(/[^A-Z0-9]/g, '');
61
+ //# sourceMappingURL=symbol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"symbol.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/ton/jetton/symbol.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,GAA2B;IAC1C,WAAW;IACX,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,QAAQ;IACR,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,+BAA+B;IAC/B,GAAG,EAAE,GAAG;IACR,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;CACP,CAAA;AAED,MAAM,cAAc,GAAG,QAAQ,CAAA;AAE/B;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,KAAa,EAAU,EAAE,CAC7D,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;KAC1E,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;KACtC,IAAI,CAAC,EAAE,CAAC;KACR,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAA"}
@@ -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":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAA;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAA;AAC5E,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAA;AACnE,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAA;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAA;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,0CAA0C,CAAA;AAE1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAA;AAEhD;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,0EAA0E,CAAA;AAgC7G;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,OAAyB,EAA6B,EAAE;IACpG,MAAM,QAAQ,GAA8B,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,GAAG,EAAE,EAAE,CAAA;IAEnG,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,kBAAkB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QAClD,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,CAAA;QAEtD,MAAM,MAAM,GAAG,qBAAqB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;QACnD,IAAI,MAAM;YAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;QAExC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,qBAAqB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QAClE,IAAI,IAAI;YAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IACpC,CAAC;IAED,OAAO,QAAQ,CAAA;AACjB,CAAC,CAAA;AAED,MAAM,iBAAiB,GAAG,GAAqB,EAAE,CAC/C,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,eAAe,EAAE,EAAE,EAAE,CACjF,EAAE;IACA,CAAC,CAAC;QACE;YACE,OAAO,EAAE,kBAAkB,CAAC,EAAE,CAAC;YAC/B,MAAM,EAAE,MAAM;YACd,QAAQ;YACR,IAAI;YACJ,GAAG,CAAC,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC;SAC9D;KACF;IACH,CAAC,CAAC,EAAE,CACP,CAAA;AAEH,MAAM,iBAAiB,GAAG,CAAC,KAAc,EAA4B,EAAE,CACrE,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,OAAQ,KAA+B,CAAC,OAAO,KAAK,QAAQ,CAAA;AAE7G,MAAM,qBAAqB,GAAG,KAAK,IAA+B,EAAE;IAClE,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAU,mBAAmB,CAAC,CAAA;IAC7D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAA;IAC1D,CAAC;IAED,OAAO,QAAQ,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE;QAC1G,MAAM,MAAM,GAAG,MAAM,EAAE,IAAI,EAAE,CAAA;QAC7B,IAAI,CAAC,MAAM;YAAE,OAAO,EAAE,CAAA;QAEtB,OAAO;YACL;gBACE,OAAO,EAAE,kBAAkB,CAAC,OAAO,CAAC;gBACpC,MAAM,EAAE,MAAM;gBACd,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACzB,GAAG,CAAC,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACrD,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACjC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACrD;SACF,CAAA;IACH,CAAC,CAAC,CAAA;AACJ,CAAC,CAAA;AAED,+EAA+E;AAC/E,+EAA+E;AAC/E,MAAM,eAAe,GAAG,YAAY,CAClC,KAAK,IAAI,EAAE,CAAC,6BAA6B,CAAC,CAAC,GAAG,iBAAiB,EAAE,EAAE,GAAG,CAAC,MAAM,qBAAqB,EAAE,CAAC,CAAC,CAAC,EACvG,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,CAC7C,CAAA;AAED,IAAI,eAAsD,CAAA;AAE1D,MAAM,kBAAkB,GAAG,GAA8B,EAAE;IACzD,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,eAAe,GAAG,6BAA6B,CAAC,iBAAiB,EAAE,CAAC,CAAA;IACtE,CAAC;IAED,OAAO,eAAe,CAAA;AACxB,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,KAAK,IAAwC,EAAE;IACzF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,eAAe,EAAE,CAAC,CAAA;IAC/C,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,CAAC,IAAI;QAAE,OAAO,MAAM,CAAC,IAAI,CAAA;IAEvD,OAAO,CAAC,IAAI,CAAC,qEAAqE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;IAEjG,OAAO,kBAAkB,EAAE,CAAA;AAC7B,CAAC,CAAA"}
@@ -0,0 +1,50 @@
1
+ import { PublicKey, WalletCore } from '@trustwallet/wallet-core/dist/src/wallet-core';
2
+ import { tonV5R1WalletId } from '@vultisig/core-chain/chains/ton/walletV5R1';
3
+ /**
4
+ * The wallet contracts a Vultisig TON account can live in. The same Ed25519
5
+ * key yields a different address under each, so they are different accounts.
6
+ */
7
+ export declare const tonWalletVersions: readonly ["v4r2", "v5r1"];
8
+ export type TonWalletVersion = (typeof tonWalletVersions)[number];
9
+ /**
10
+ * The contract every Vultisig TON address has been derived from so far. W5 is
11
+ * an explicit opt-in: switching a key's default would silently move the user
12
+ * to an empty account.
13
+ */
14
+ export declare const defaultTonWalletVersion: TonWalletVersion;
15
+ export { tonV5R1WalletId };
16
+ /**
17
+ * How many outgoing messages one external request may carry. V4 is limited by
18
+ * the wallet code; W5 by the 255-entry action list.
19
+ */
20
+ export declare const tonMaxMessagesPerRequest: Record<TonWalletVersion, number>;
21
+ type DeriveTonAddressInput = {
22
+ publicKey: PublicKey;
23
+ walletCore: WalletCore;
24
+ version: TonWalletVersion;
25
+ };
26
+ /**
27
+ * The user-friendly, non-bounceable (`UQ…`) address of this key's wallet
28
+ * under the given contract. V4R2 is WalletCore's own TON derivation; W5 is the
29
+ * hash of the StateInit the contract is deployed from, built with `@ton/core`
30
+ * from the key bytes alone — no WalletCore feature beyond the public key, so it
31
+ * also works on React Native, whose native bridge exposes no `TONWallet`.
32
+ */
33
+ export declare const deriveTonAddress: ({ publicKey, walletCore, version }: DeriveTonAddressInput) => string;
34
+ type ResolveTonWalletVersionInput = {
35
+ address: string;
36
+ publicKey: PublicKey;
37
+ walletCore: WalletCore;
38
+ };
39
+ /**
40
+ * Which wallet contract an address is, for this key.
41
+ *
42
+ * The keysign payload carries no wallet-version field, so the sender address
43
+ * is the contract's identity: every co-signer derives both candidate addresses
44
+ * from the shared vault key and matches. An address that is neither is refused
45
+ * rather than assumed V4R2 — signing a V4R2 request for a wallet that is not
46
+ * one would either be rejected on chain or, worse, accepted by a contract we
47
+ * never meant to drive.
48
+ */
49
+ export declare const resolveTonWalletVersion: ({ address, publicKey, walletCore }: ResolveTonWalletVersionInput) => "v4r2" | "v5r1";
50
+ //# sourceMappingURL=wallet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wallet.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/ton/wallet.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,+CAA+C,CAAA;AACrF,OAAO,EAAqB,eAAe,EAAE,MAAM,4CAA4C,CAAA;AAG/F;;;GAGG;AACH,eAAO,MAAM,iBAAiB,2BAA4B,CAAA;AAE1D,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAA;AAEjE;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,EAAE,gBAAyB,CAAA;AAE/D,OAAO,EAAE,eAAe,EAAE,CAAA;AAE1B;;;GAGG;AACH,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAA0B,CAAA;AAEhG,KAAK,qBAAqB,GAAG;IAC3B,SAAS,EAAE,SAAS,CAAA;IACpB,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,GAAI,oCAAoC,qBAAqB,KAAG,MASzF,CAAA;AAEJ,KAAK,4BAA4B,GAAG;IAClC,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,SAAS,CAAA;IACpB,UAAU,EAAE,UAAU,CAAA;CACvB,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,uBAAuB,GAAI,oCAAoC,4BAA4B,oBAcvG,CAAA"}