@getomnichain/omnichain 0.6.2 → 0.7.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 (145) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/dist/cjs/chain_ids.js +2 -2
  3. package/dist/cjs/chain_ids.js.map +1 -1
  4. package/dist/cjs/errors.js +6 -0
  5. package/dist/cjs/errors.js.map +1 -1
  6. package/dist/cjs/index.js +1 -1
  7. package/dist/cjs/index.js.map +1 -1
  8. package/dist/cjs/ton/index.js +12 -0
  9. package/dist/cjs/ton/index.js.map +1 -1
  10. package/dist/cjs/ton/ton_address.js +72 -14
  11. package/dist/cjs/ton/ton_address.js.map +1 -1
  12. package/dist/cjs/ton/ton_asset.js +21 -0
  13. package/dist/cjs/ton/ton_asset.js.map +1 -0
  14. package/dist/cjs/ton/ton_assets.js +10 -0
  15. package/dist/cjs/ton/ton_assets.js.map +1 -0
  16. package/dist/cjs/ton/ton_chain.js +483 -0
  17. package/dist/cjs/ton/ton_chain.js.map +1 -0
  18. package/dist/cjs/ton/ton_chains.js +21 -0
  19. package/dist/cjs/ton/ton_chains.js.map +1 -0
  20. package/dist/cjs/ton/ton_jetton_metadata.js +107 -0
  21. package/dist/cjs/ton/ton_jetton_metadata.js.map +1 -0
  22. package/dist/cjs/ton/ton_messages.js +174 -0
  23. package/dist/cjs/ton/ton_messages.js.map +1 -0
  24. package/dist/cjs/ton/ton_provider.js +456 -0
  25. package/dist/cjs/ton/ton_provider.js.map +1 -0
  26. package/dist/cjs/ton/ton_tonapi.js +243 -0
  27. package/dist/cjs/ton/ton_tonapi.js.map +1 -0
  28. package/dist/cjs/ton/ton_toncenter.js +252 -0
  29. package/dist/cjs/ton/ton_toncenter.js.map +1 -0
  30. package/dist/cjs/ton/ton_transaction_status.js +231 -0
  31. package/dist/cjs/ton/ton_transaction_status.js.map +1 -0
  32. package/dist/cjs/ton/ton_transactions.js +107 -0
  33. package/dist/cjs/ton/ton_transactions.js.map +1 -0
  34. package/dist/cjs/ton/ton_wallet.js +285 -0
  35. package/dist/cjs/ton/ton_wallet.js.map +1 -0
  36. package/dist/cjs/tron/index.js +1 -0
  37. package/dist/cjs/tron/index.js.map +1 -1
  38. package/dist/cjs/tron/tron_chain.js +88 -45
  39. package/dist/cjs/tron/tron_chain.js.map +1 -1
  40. package/dist/cjs/tron/tron_memo.js +17 -0
  41. package/dist/cjs/tron/tron_memo.js.map +1 -0
  42. package/dist/cjs/tron/tron_raw_data.js +213 -0
  43. package/dist/cjs/tron/tron_raw_data.js.map +1 -0
  44. package/dist/cjs/tron/tron_transaction_builder.js +34 -13
  45. package/dist/cjs/tron/tron_transaction_builder.js.map +1 -1
  46. package/dist/cjs/tron/tron_transaction_status.js +10 -7
  47. package/dist/cjs/tron/tron_transaction_status.js.map +1 -1
  48. package/dist/cjs/tron/tron_transactions.js +1 -1
  49. package/dist/cjs/tron/tron_transactions.js.map +1 -1
  50. package/dist/esm/chain_ids.js +2 -2
  51. package/dist/esm/chain_ids.js.map +1 -1
  52. package/dist/esm/errors.d.ts +3 -0
  53. package/dist/esm/errors.d.ts.map +1 -1
  54. package/dist/esm/errors.js +5 -0
  55. package/dist/esm/errors.js.map +1 -1
  56. package/dist/esm/index.d.ts +1 -1
  57. package/dist/esm/index.d.ts.map +1 -1
  58. package/dist/esm/index.js +1 -1
  59. package/dist/esm/index.js.map +1 -1
  60. package/dist/esm/ton/index.d.ts +12 -0
  61. package/dist/esm/ton/index.d.ts.map +1 -1
  62. package/dist/esm/ton/index.js +12 -0
  63. package/dist/esm/ton/index.js.map +1 -1
  64. package/dist/esm/ton/ton_address.d.ts +26 -2
  65. package/dist/esm/ton/ton_address.d.ts.map +1 -1
  66. package/dist/esm/ton/ton_address.js +70 -14
  67. package/dist/esm/ton/ton_address.js.map +1 -1
  68. package/dist/esm/ton/ton_asset.d.ts +12 -0
  69. package/dist/esm/ton/ton_asset.d.ts.map +1 -0
  70. package/dist/esm/ton/ton_asset.js +17 -0
  71. package/dist/esm/ton/ton_asset.js.map +1 -0
  72. package/dist/esm/ton/ton_assets.d.ts +6 -0
  73. package/dist/esm/ton/ton_assets.d.ts.map +1 -0
  74. package/dist/esm/ton/ton_assets.js +7 -0
  75. package/dist/esm/ton/ton_assets.js.map +1 -0
  76. package/dist/esm/ton/ton_chain.d.ts +205 -0
  77. package/dist/esm/ton/ton_chain.d.ts.map +1 -0
  78. package/dist/esm/ton/ton_chain.js +479 -0
  79. package/dist/esm/ton/ton_chain.js.map +1 -0
  80. package/dist/esm/ton/ton_chains.d.ts +11 -0
  81. package/dist/esm/ton/ton_chains.d.ts.map +1 -0
  82. package/dist/esm/ton/ton_chains.js +18 -0
  83. package/dist/esm/ton/ton_chains.js.map +1 -0
  84. package/dist/esm/ton/ton_jetton_metadata.d.ts +36 -0
  85. package/dist/esm/ton/ton_jetton_metadata.d.ts.map +1 -0
  86. package/dist/esm/ton/ton_jetton_metadata.js +103 -0
  87. package/dist/esm/ton/ton_jetton_metadata.js.map +1 -0
  88. package/dist/esm/ton/ton_messages.d.ts +133 -0
  89. package/dist/esm/ton/ton_messages.d.ts.map +1 -0
  90. package/dist/esm/ton/ton_messages.js +159 -0
  91. package/dist/esm/ton/ton_messages.js.map +1 -0
  92. package/dist/esm/ton/ton_provider.d.ts +261 -0
  93. package/dist/esm/ton/ton_provider.d.ts.map +1 -0
  94. package/dist/esm/ton/ton_provider.js +432 -0
  95. package/dist/esm/ton/ton_provider.js.map +1 -0
  96. package/dist/esm/ton/ton_tonapi.d.ts +39 -0
  97. package/dist/esm/ton/ton_tonapi.d.ts.map +1 -0
  98. package/dist/esm/ton/ton_tonapi.js +239 -0
  99. package/dist/esm/ton/ton_tonapi.js.map +1 -0
  100. package/dist/esm/ton/ton_toncenter.d.ts +25 -0
  101. package/dist/esm/ton/ton_toncenter.d.ts.map +1 -0
  102. package/dist/esm/ton/ton_toncenter.js +248 -0
  103. package/dist/esm/ton/ton_toncenter.js.map +1 -0
  104. package/dist/esm/ton/ton_transaction_status.d.ts +116 -0
  105. package/dist/esm/ton/ton_transaction_status.d.ts.map +1 -0
  106. package/dist/esm/ton/ton_transaction_status.js +226 -0
  107. package/dist/esm/ton/ton_transaction_status.js.map +1 -0
  108. package/dist/esm/ton/ton_transactions.d.ts +54 -0
  109. package/dist/esm/ton/ton_transactions.d.ts.map +1 -0
  110. package/dist/esm/ton/ton_transactions.js +100 -0
  111. package/dist/esm/ton/ton_transactions.js.map +1 -0
  112. package/dist/esm/ton/ton_wallet.d.ts +134 -0
  113. package/dist/esm/ton/ton_wallet.d.ts.map +1 -0
  114. package/dist/esm/ton/ton_wallet.js +278 -0
  115. package/dist/esm/ton/ton_wallet.js.map +1 -0
  116. package/dist/esm/tron/index.d.ts +1 -0
  117. package/dist/esm/tron/index.d.ts.map +1 -1
  118. package/dist/esm/tron/index.js +1 -0
  119. package/dist/esm/tron/index.js.map +1 -1
  120. package/dist/esm/tron/tron_chain.d.ts +13 -1
  121. package/dist/esm/tron/tron_chain.d.ts.map +1 -1
  122. package/dist/esm/tron/tron_chain.js +89 -46
  123. package/dist/esm/tron/tron_chain.js.map +1 -1
  124. package/dist/esm/tron/tron_memo.d.ts +2 -0
  125. package/dist/esm/tron/tron_memo.d.ts.map +1 -0
  126. package/dist/esm/tron/tron_memo.js +14 -0
  127. package/dist/esm/tron/tron_memo.js.map +1 -0
  128. package/dist/esm/tron/tron_raw_data.d.ts +4 -0
  129. package/dist/esm/tron/tron_raw_data.d.ts.map +1 -0
  130. package/dist/esm/tron/tron_raw_data.js +209 -0
  131. package/dist/esm/tron/tron_raw_data.js.map +1 -0
  132. package/dist/esm/tron/tron_transaction_builder.d.ts +4 -0
  133. package/dist/esm/tron/tron_transaction_builder.d.ts.map +1 -1
  134. package/dist/esm/tron/tron_transaction_builder.js +34 -13
  135. package/dist/esm/tron/tron_transaction_builder.js.map +1 -1
  136. package/dist/esm/tron/tron_transaction_status.d.ts +16 -2
  137. package/dist/esm/tron/tron_transaction_status.d.ts.map +1 -1
  138. package/dist/esm/tron/tron_transaction_status.js +10 -7
  139. package/dist/esm/tron/tron_transaction_status.js.map +1 -1
  140. package/dist/esm/tron/tron_transactions.js +1 -1
  141. package/dist/esm/tron/tron_transactions.js.map +1 -1
  142. package/docs/README.md +2 -1
  143. package/docs/ton.md +164 -0
  144. package/docs/tron.md +21 -11
  145. package/package.json +5 -1
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TON_W5_SIGNED_EXTERNAL_OP = exports.TON_W5_SIGNED_INTERNAL_OP = exports.TON_JETTON_INTERNAL_TRANSFER_OP = exports.TON_JETTON_TRANSFER_OP = exports.TON_COMMENT_OP = exports.TON_DEFAULT_SEND_MODE = exports.TON_MAX_MESSAGES_PER_REQUEST = exports.TonSignedMessage = void 0;
4
+ exports.tonMessageHash = tonMessageHash;
5
+ exports.tonOutAction = tonOutAction;
6
+ exports.tonOutActions = tonOutActions;
7
+ exports.tonCommentBody = tonCommentBody;
8
+ exports.tonJettonTransferBody = tonJettonTransferBody;
9
+ exports.tonW5RequestFields = tonW5RequestFields;
10
+ exports.tonWalletRequestFields = tonWalletRequestFields;
11
+ exports.tonInternalRequestOf = tonInternalRequestOf;
12
+ exports.tonRelayMessage = tonRelayMessage;
13
+ exports.tonNormalizedExternalHash = tonNormalizedExternalHash;
14
+ exports.parseTonAddress = parseTonAddress;
15
+ const core_1 = require("@ton/core");
16
+ const node_crypto_1 = require("node:crypto");
17
+ const errors_ts_1 = require("../errors.js");
18
+ const wallet_base_ts_1 = require("../wallet.base.js");
19
+ const TON_MESSAGE_PREFIX = 'TON Signed Message:\n';
20
+ /**
21
+ * What `signMessage` signs: SHA-256 of a fixed prefix and the message's UTF-8
22
+ * bytes, as Stellar's SEP-53 does. The same key authorizes W5 requests by
23
+ * signing a 32-byte cell hash, so signing a message's bytes directly would let
24
+ * a crafted 32-byte message stand in for a request; a prefixed digest cannot
25
+ * equal a cell hash without a SHA-256 preimage.
26
+ */
27
+ function tonMessageHash(message) {
28
+ return (0, node_crypto_1.createHash)('sha256').update(TON_MESSAGE_PREFIX, 'utf8').update(message, 'utf8').digest();
29
+ }
30
+ class TonSignedMessage extends wallet_base_ts_1.AbstractSignedMessage {
31
+ constructor(signature) {
32
+ super(signature);
33
+ }
34
+ }
35
+ exports.TonSignedMessage = TonSignedMessage;
36
+ /** W5's limit on outgoing messages per request. */
37
+ exports.TON_MAX_MESSAGES_PER_REQUEST = 255;
38
+ /** The send mode a message gets unless it names one: the wallet pays forward fees on top of `value`. */
39
+ exports.TON_DEFAULT_SEND_MODE = core_1.SendMode.PAY_GAS_SEPARATELY;
40
+ exports.TON_COMMENT_OP = 0;
41
+ exports.TON_JETTON_TRANSFER_OP = 0x0f8a7ea5;
42
+ exports.TON_JETTON_INTERNAL_TRANSFER_OP = 0x178d4519;
43
+ function tonOutAction(message) {
44
+ if (message.value < 0n) {
45
+ throw new errors_ts_1.ChainError(errors_ts_1.ChainErrorKinds.InvalidArgument, `TON message value must be >= 0, got ${message.value}`);
46
+ }
47
+ return {
48
+ type: 'sendMsg',
49
+ mode: message.mode ?? exports.TON_DEFAULT_SEND_MODE,
50
+ outMsg: (0, core_1.internal)({
51
+ to: parseTonAddress(message.to),
52
+ value: message.value,
53
+ bounce: message.bounce ?? message.body !== undefined,
54
+ body: message.body,
55
+ init: message.stateInit,
56
+ }),
57
+ };
58
+ }
59
+ function tonOutActions(messages) {
60
+ if (messages.length === 0 || messages.length > exports.TON_MAX_MESSAGES_PER_REQUEST) {
61
+ throw new errors_ts_1.ChainError(errors_ts_1.ChainErrorKinds.InvalidArgument, `A TON request carries 1 to ${exports.TON_MAX_MESSAGES_PER_REQUEST} messages, got ${messages.length}`);
62
+ }
63
+ return messages.map(tonOutAction);
64
+ }
65
+ /** A text comment body (op 0), the form wallets show as a memo. */
66
+ function tonCommentBody(text) {
67
+ return (0, core_1.beginCell)().storeUint(exports.TON_COMMENT_OP, 32).storeStringTail(text).endCell();
68
+ }
69
+ /** The TEP-74 `transfer` body, sent to the sender's own jetton wallet. */
70
+ function tonJettonTransferBody(args) {
71
+ const builder = (0, core_1.beginCell)()
72
+ .storeUint(exports.TON_JETTON_TRANSFER_OP, 32)
73
+ .storeUint(args.queryId ?? 0n, 64)
74
+ .storeCoins(args.amount)
75
+ .storeAddress(parseTonAddress(args.destination))
76
+ .storeAddress(parseTonAddress(args.responseDestination))
77
+ .storeBit(false)
78
+ .storeCoins(args.forwardTonAmount ?? 0n);
79
+ return args.forwardPayload === undefined
80
+ ? builder.storeBit(false).endCell()
81
+ : builder.storeBit(true).storeRef(args.forwardPayload).endCell();
82
+ }
83
+ exports.TON_W5_SIGNED_INTERNAL_OP = 0x73696e74;
84
+ exports.TON_W5_SIGNED_EXTERNAL_OP = 0x7369676e;
85
+ /**
86
+ * The fields of a signed W5R1 request body: op, wallet id, `valid_until` and
87
+ * seqno lead the body, the signature trails it. Throws `TransactionDecodeFailed`
88
+ * for anything that is not one.
89
+ */
90
+ function tonW5RequestFields(body) {
91
+ try {
92
+ const slice = body.beginParse();
93
+ const op = slice.loadUint(32);
94
+ if (op !== exports.TON_W5_SIGNED_EXTERNAL_OP && op !== exports.TON_W5_SIGNED_INTERNAL_OP)
95
+ throw new Error(`op 0x${op.toString(16)}`);
96
+ return {
97
+ authType: op === exports.TON_W5_SIGNED_EXTERNAL_OP ? 'external' : 'internal',
98
+ walletId: slice.loadInt(32),
99
+ validUntil: slice.loadUint(32),
100
+ seqno: slice.loadUint(32),
101
+ };
102
+ }
103
+ catch (err) {
104
+ throw new errors_ts_1.ChainError(errors_ts_1.ChainErrorKinds.TransactionDecodeFailed, `Not a signed W5 request: ${err.message}`, undefined, err);
105
+ }
106
+ }
107
+ const ED25519_SIGNATURE_BITS = 512;
108
+ /**
109
+ * The fields of any signed wallet request body the SDK builds. A v3r2 / v4r2
110
+ * body is the signature, then wallet id, valid_until and seqno, every field
111
+ * whole bytes; a W5 body leads with its op and is never byte-aligned (its
112
+ * action-list flags are two bits). Throws `TransactionDecodeFailed` for
113
+ * anything else.
114
+ */
115
+ function tonWalletRequestFields(body) {
116
+ if (body.bits.length % 8 !== 0)
117
+ return { layout: 'w5', ...tonW5RequestFields(body) };
118
+ try {
119
+ const slice = body.beginParse();
120
+ slice.skip(ED25519_SIGNATURE_BITS);
121
+ return { layout: 'legacy', walletId: slice.loadUint(32), validUntil: slice.loadUint(32), seqno: slice.loadUint(32) };
122
+ }
123
+ catch (err) {
124
+ throw new errors_ts_1.ChainError(errors_ts_1.ChainErrorKinds.TransactionDecodeFailed, `Not a signed wallet request: ${err.message}`, undefined, err);
125
+ }
126
+ }
127
+ /** A signed internal request read back from its body, e.g. one found in a trace. */
128
+ function tonInternalRequestOf(body) {
129
+ const fields = tonW5RequestFields(body);
130
+ if (fields.authType !== 'internal') {
131
+ throw new errors_ts_1.ChainError(errors_ts_1.ChainErrorKinds.TransactionDecodeFailed, 'Not a signed W5 internal request: it is an external one');
132
+ }
133
+ return { body, seqno: fields.seqno, validUntil: fields.validUntil };
134
+ }
135
+ /**
136
+ * The message a relayer sends to deliver a wallet's signed internal request.
137
+ *
138
+ * Bounceable, so a request that fails in the wallet returns the value. A
139
+ * request the wallet does not accept (a bad signature, a stale seqno) is
140
+ * dropped without a bounce and the wallet keeps the value; the transaction
141
+ * status reports that as `request_not_executed`.
142
+ */
143
+ function tonRelayMessage(args) {
144
+ if (args.wallet.version !== undefined && args.wallet.version !== 'v5r1') {
145
+ throw new errors_ts_1.ChainError(errors_ts_1.ChainErrorKinds.FeatureNotSupported, `Only W5 (v5r1) wallets take relayed requests; ${args.wallet.address} is ${args.wallet.version}`);
146
+ }
147
+ return {
148
+ to: args.wallet.address,
149
+ value: args.value,
150
+ body: args.request.body,
151
+ bounce: true,
152
+ stateInit: args.deploy ? args.wallet.stateInit : undefined,
153
+ };
154
+ }
155
+ /**
156
+ * The normalized hash of an external message (TEP-467): source, import fee and
157
+ * StateInit dropped, body stored as a reference. It is what both TON Center and
158
+ * TonAPI index the external message under, and is used as the transaction id.
159
+ */
160
+ function tonNormalizedExternalHash(destination, body) {
161
+ const normalized = (0, core_1.beginCell)()
162
+ .store((0, core_1.storeMessage)({ info: { type: 'external-in', src: null, dest: parseTonAddress(destination), importFee: 0n }, body }, { forceRef: true }))
163
+ .endCell();
164
+ return normalized.hash().toString('hex');
165
+ }
166
+ function parseTonAddress(address) {
167
+ try {
168
+ return core_1.Address.parse(address);
169
+ }
170
+ catch (err) {
171
+ throw new errors_ts_1.ChainError(errors_ts_1.ChainErrorKinds.InvalidAddress, `Invalid TON address: ${address}`, { address }, err);
172
+ }
173
+ }
174
+ //# sourceMappingURL=ton_messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ton_messages.js","sourceRoot":"","sources":["../../../ton/ton_messages.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,456 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TonFallbackProvider = exports.TonBroadcastUncertainError = exports.TonProviderError = void 0;
4
+ exports.tonHttpJson = tonHttpJson;
5
+ exports.tonBroadcastReply = tonBroadcastReply;
6
+ exports.errorMessageOf = errorMessageOf;
7
+ exports.asRecord = asRecord;
8
+ exports.asBigInt = asBigInt;
9
+ exports.asRequiredInteger = asRequiredInteger;
10
+ exports.asRequiredRecord = asRequiredRecord;
11
+ exports.stackCellOf = stackCellOf;
12
+ exports.jettonWalletDataOf = jettonWalletDataOf;
13
+ exports.asRequiredBoolean = asRequiredBoolean;
14
+ exports.tonTransactionOutcome = tonTransactionOutcome;
15
+ exports.asStatedAccountStatus = asStatedAccountStatus;
16
+ exports.asAccountStatus = asAccountStatus;
17
+ exports.tonTraceMessageOf = tonTraceMessageOf;
18
+ exports.assertTraceConsistent = assertTraceConsistent;
19
+ exports.assertTraceOf = assertTraceOf;
20
+ exports.assertTonTxHash = assertTonTxHash;
21
+ exports.definiteError = definiteError;
22
+ const core_1 = require("@ton/core");
23
+ const errors_ts_1 = require("../errors.js");
24
+ const ton_messages_ts_1 = require("./ton_messages.js");
25
+ /**
26
+ * A provider failure. `retryable` is true only for failures that say nothing
27
+ * about the answer (transport, timeout, 429, 5xx); the fallback retries those
28
+ * and nothing else.
29
+ */
30
+ class TonProviderError extends errors_ts_1.ChainError {
31
+ retryable;
32
+ constructor(kind, message, retryable, meta, cause) {
33
+ super(kind, message, meta, cause);
34
+ this.name = 'TonProviderError';
35
+ this.retryable = retryable;
36
+ }
37
+ }
38
+ exports.TonProviderError = TonProviderError;
39
+ /**
40
+ * A broadcast whose outcome is unknown: a provider failed without an answer,
41
+ * so the message may have reached the network even if another provider then
42
+ * refused it (a refusal can mean it was already accepted). Read the status of
43
+ * `meta.txHash`, or wait until the request is expired, before signing again.
44
+ */
45
+ class TonBroadcastUncertainError extends TonProviderError {
46
+ constructor(message, meta, cause) {
47
+ super(errors_ts_1.ChainErrorKinds.BroadcastUncertain, message, false, meta, cause);
48
+ this.name = 'TonBroadcastUncertainError';
49
+ }
50
+ }
51
+ exports.TonBroadcastUncertainError = TonBroadcastUncertainError;
52
+ /**
53
+ * TON Center v3 first; TonAPI only when TON Center fails without an answer.
54
+ *
55
+ * A definite answer from the primary (not found, a refused emulation, a
56
+ * refused broadcast) is final. A broadcast retried on the fallback sends the
57
+ * same BOC: the wallet's seqno makes a second landing impossible.
58
+ */
59
+ class TonFallbackProvider {
60
+ primary;
61
+ fallback;
62
+ onFallback;
63
+ name;
64
+ constructor(primary, fallback, onFallback = () => { }) {
65
+ this.primary = primary;
66
+ this.fallback = fallback;
67
+ this.onFallback = onFallback;
68
+ this.name = fallback === null ? primary.name : `${primary.name}+${fallback.name}`;
69
+ }
70
+ getAccountState(address) {
71
+ return this.call('getAccountState', (p) => p.getAccountState(address));
72
+ }
73
+ getSeqno(address) {
74
+ return this.call('getSeqno', (p) => p.getSeqno(address));
75
+ }
76
+ getJettonWalletAddress(jettonMaster, owner) {
77
+ return this.call('getJettonWalletAddress', (p) => p.getJettonWalletAddress(jettonMaster, owner));
78
+ }
79
+ getJettonBalance(jettonWallet) {
80
+ return this.call('getJettonBalance', (p) => p.getJettonBalance(jettonWallet));
81
+ }
82
+ getJettonContent(jettonMaster) {
83
+ return this.call('getJettonContent', (p) => p.getJettonContent(jettonMaster));
84
+ }
85
+ getJettonWalletData(jettonWallet) {
86
+ return this.call('getJettonWalletData', (p) => p.getJettonWalletData(jettonWallet));
87
+ }
88
+ /**
89
+ * A refusal is definite only when no provider failed before it: once one
90
+ * failed without an answer, the message may already be in flight, and a
91
+ * later refusal may be the network rejecting a duplicate.
92
+ */
93
+ async sendBoc(boc) {
94
+ try {
95
+ await this.primary.sendBoc(boc);
96
+ return;
97
+ }
98
+ catch (err) {
99
+ if (!(err instanceof TonProviderError) || !err.retryable)
100
+ throw err;
101
+ if (this.fallback === null)
102
+ throw new TonBroadcastUncertainError(`broadcast outcome unknown: ${err.message}`, undefined, err);
103
+ this.onFallback('sendBoc', err);
104
+ try {
105
+ await this.fallback.sendBoc(boc);
106
+ }
107
+ catch (fallbackErr) {
108
+ throw new TonBroadcastUncertainError(`broadcast outcome unknown: ${err.message}; then ${fallbackErr.message}`, undefined, fallbackErr);
109
+ }
110
+ }
111
+ }
112
+ getTrace(hash) {
113
+ return this.call('getTrace', (p) => p.getTrace(hash));
114
+ }
115
+ emulate(boc) {
116
+ return this.call('emulate', (p) => p.emulate(boc));
117
+ }
118
+ getMasterchainHead() {
119
+ return this.call('getMasterchainHead', (p) => p.getMasterchainHead());
120
+ }
121
+ /**
122
+ * Runs several reads on one provider throughout: the primary, or — when any
123
+ * of them fails without an answer — all of them again on the fallback. Reads
124
+ * that must see the chain at one point never mix providers that lag
125
+ * differently.
126
+ */
127
+ onOneProvider(method, run) {
128
+ return this.call(method, run);
129
+ }
130
+ async call(method, run) {
131
+ try {
132
+ return await run(this.primary);
133
+ }
134
+ catch (err) {
135
+ if (this.fallback === null || !(err instanceof TonProviderError) || !err.retryable)
136
+ throw err;
137
+ this.onFallback(method, err);
138
+ return run(this.fallback);
139
+ }
140
+ }
141
+ }
142
+ exports.TonFallbackProvider = TonFallbackProvider;
143
+ const DEFAULT_TIMEOUT_MS = 10_000;
144
+ /** Enough of an error reply to keep the lite server's exit code, which follows a long preamble. */
145
+ const ERROR_TEXT_LIMIT = 1_000;
146
+ /** One JSON request; maps every failure to a {@link TonProviderError}. Returns `null` on a 404. */
147
+ async function tonHttpJson(provider, endpoint, path, init) {
148
+ const url = `${endpoint.url.replace(/\/$/, '')}${path}`;
149
+ let response;
150
+ try {
151
+ response = await fetch(url, {
152
+ method: init.method ?? 'GET',
153
+ headers: { accept: 'application/json', ...(init.body === undefined ? {} : { 'content-type': 'application/json' }), ...init.headers },
154
+ body: init.body === undefined ? undefined : JSON.stringify(init.body),
155
+ signal: AbortSignal.timeout(endpoint.timeoutMs ?? DEFAULT_TIMEOUT_MS),
156
+ redirect: 'error',
157
+ });
158
+ }
159
+ catch (err) {
160
+ throw new TonProviderError(errors_ts_1.ChainErrorKinds.RpcError, `${provider} ${path} request failed: ${err.message}`, true, undefined, err);
161
+ }
162
+ const text = await response.text();
163
+ if (response.status === 404)
164
+ return null;
165
+ if (response.status === 429 || response.status >= 500) {
166
+ throw new TonProviderError(errors_ts_1.ChainErrorKinds.RpcError, `${provider} ${path} answered HTTP ${response.status}: ${text.slice(0, ERROR_TEXT_LIMIT)}`, true);
167
+ }
168
+ let payload;
169
+ try {
170
+ payload = text.length === 0 ? {} : JSON.parse(text);
171
+ }
172
+ catch {
173
+ throw new TonProviderError(errors_ts_1.ChainErrorKinds.RpcError, `${provider} ${path} answered non-JSON (HTTP ${response.status})`, true);
174
+ }
175
+ if (response.status >= 400) {
176
+ const message = errorMessageOf(payload) ?? text.slice(0, ERROR_TEXT_LIMIT);
177
+ throw new TonProviderError(errors_ts_1.ChainErrorKinds.RpcError, `${provider} ${path} refused (HTTP ${response.status}): ${message}`, false);
178
+ }
179
+ return payload;
180
+ }
181
+ const EXTERNAL_MESSAGE_REFUSED = /cannot apply external message/i;
182
+ const EXTERNAL_MESSAGE_DUPLICATE = /duplicate message/i;
183
+ const REFUSAL_EXIT_CODE = /exit\s*code\s*[=:]?\s*(-?\d+)/i;
184
+ /**
185
+ * The wallets' refusals of an external request, by exit code.
186
+ *
187
+ * W5R1 checks the signature, then the seqno (133), the wallet id, then
188
+ * `valid_until`: a message that already landed fails on the seqno, and only
189
+ * there — every later refusal means the seqno still matched.
190
+ *
191
+ * v3r2 and v4r2 check `valid_until` first (v3r2: 35, which is also its bad
192
+ * signature; v4r2: 36), then the seqno (33), the wallet id (34), the
193
+ * signature (35). An expiry refusal therefore says nothing about whether the
194
+ * message landed earlier.
195
+ */
196
+ const SEQNO_MOVED_EXIT_CODES = new Set([133, 33]);
197
+ /**
198
+ * The account refused to run the request at all — typically it holds nothing
199
+ * to pay for it, as a wallet that sent everything away does. No check ran, so
200
+ * this says nothing about whether the same request landed earlier.
201
+ */
202
+ const REFUSED_BEFORE_EXECUTION = /before smart-contract execution/i;
203
+ const MAYBE_LANDED_EXIT_CODES = new Set([35, 36]);
204
+ /**
205
+ * The reply to a broadcast, read for what the lite server said rather than
206
+ * the HTTP status (both answers come as HTTP 500 from TON Center, and from
207
+ * TonAPI as 500 or 406):
208
+ * - "duplicate message": the network already has this exact message, so the
209
+ * broadcast succeeded;
210
+ * - "cannot apply external message": the wallet does not accept it now. On a
211
+ * seqno check (W5 133, v3r2 / v4r2 33) this is `NonceTooLow` — this
212
+ * message or another with its seqno already landed, so read the status
213
+ * before signing again; on a v3r2 / v4r2 expiry (35, 36), or a refusal "before
214
+ * smart-contract execution" (an account that cannot pay to run it), it may
215
+ * have landed earlier, so it is `BroadcastUncertain`; any other refusal is
216
+ * a definite `BroadcastRejected`.
217
+ */
218
+ async function tonBroadcastReply(provider, reply) {
219
+ try {
220
+ return await reply;
221
+ }
222
+ catch (err) {
223
+ if (!(err instanceof TonProviderError))
224
+ throw err;
225
+ if (EXTERNAL_MESSAGE_DUPLICATE.test(err.message))
226
+ return {};
227
+ if (EXTERNAL_MESSAGE_REFUSED.test(err.message)) {
228
+ if (REFUSED_BEFORE_EXECUTION.test(err.message)) {
229
+ throw new TonBroadcastUncertainError(`${provider} refused the message before running it (the account cannot pay for it); it may be a request that landed earlier: ${err.message}`, undefined, err);
230
+ }
231
+ const exitCode = Number(REFUSAL_EXIT_CODE.exec(err.message)?.[1]);
232
+ if (MAYBE_LANDED_EXIT_CODES.has(exitCode)) {
233
+ throw new TonBroadcastUncertainError(`${provider} refused the message as expired (v3r2 / v4r2 check that first, so it may have landed earlier) or for its signature: ${err.message}`, undefined, err);
234
+ }
235
+ if (SEQNO_MOVED_EXIT_CODES.has(exitCode)) {
236
+ throw new TonProviderError(errors_ts_1.ChainErrorKinds.NonceTooLow, `${provider} refused the message: the wallet's seqno has moved past it, so it or another request with its seqno landed: ${err.message}`, false, undefined, err);
237
+ }
238
+ throw new TonProviderError(errors_ts_1.ChainErrorKinds.BroadcastRejected, `${provider} refused the message: ${err.message}`, false, undefined, err);
239
+ }
240
+ throw err;
241
+ }
242
+ }
243
+ /** The `error` field some replies carry with a 2xx status. */
244
+ function errorMessageOf(payload) {
245
+ if (payload === null || typeof payload !== 'object')
246
+ return null;
247
+ const error = payload.error;
248
+ return typeof error === 'string' && error.length > 0 ? error : null;
249
+ }
250
+ function asRecord(value, what) {
251
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) {
252
+ throw new TonProviderError(errors_ts_1.ChainErrorKinds.RpcError, `Malformed TON provider reply: ${what} is not an object`, false);
253
+ }
254
+ return value;
255
+ }
256
+ function asBigInt(value, what) {
257
+ if (typeof value === 'bigint')
258
+ return value;
259
+ if ((typeof value === 'number' && Number.isInteger(value)) || (typeof value === 'string' && /^-?(\d+|0x[0-9a-fA-F]+)$/.test(value))) {
260
+ return BigInt(value);
261
+ }
262
+ if (value === undefined || value === null)
263
+ return 0n;
264
+ throw new TonProviderError(errors_ts_1.ChainErrorKinds.RpcError, `Malformed TON provider reply: ${what} is not an integer`, false);
265
+ }
266
+ /** A required integer field; a reply without one says nothing definite, so the fallback is asked. */
267
+ function asRequiredInteger(value, what) {
268
+ const parsed = typeof value === 'number' ? value : typeof value === 'string' && /^-?\d+$/.test(value) ? Number(value) : NaN;
269
+ if (!Number.isSafeInteger(parsed)) {
270
+ throw new TonProviderError(errors_ts_1.ChainErrorKinds.RpcError, `Malformed TON provider reply: ${what} is missing or not an integer`, true);
271
+ }
272
+ return parsed;
273
+ }
274
+ function malformed(what) {
275
+ return new TonProviderError(errors_ts_1.ChainErrorKinds.RpcError, `Malformed TON provider reply: ${what}`, true);
276
+ }
277
+ /** A required object field; a reply without one says nothing definite, so the fallback is asked. */
278
+ function asRequiredRecord(value, what) {
279
+ if (value === null || typeof value !== 'object' || Array.isArray(value))
280
+ throw malformed(`${what} is missing or not an object`);
281
+ return value;
282
+ }
283
+ /** A get-method stack entry that is a cell or slice: TON Center gives base64 (`value`), TonAPI hex (`cell`). */
284
+ function stackCellOf(item, what) {
285
+ const entry = asRequiredRecord(item, what);
286
+ if (entry.type !== 'cell' && entry.type !== 'slice')
287
+ throw malformed(`${what} is not a cell`);
288
+ try {
289
+ if (typeof entry.value === 'string')
290
+ return core_1.Cell.fromBase64(entry.value);
291
+ if (typeof entry.cell === 'string')
292
+ return core_1.Cell.fromBoc(Buffer.from(entry.cell, 'hex'))[0];
293
+ }
294
+ catch {
295
+ throw malformed(`${what} is not a valid cell`);
296
+ }
297
+ throw malformed(`${what} carries no cell`);
298
+ }
299
+ /** `get_wallet_data`'s stack — balance, owner, master, code — as both providers give it. */
300
+ function jettonWalletDataOf(stack) {
301
+ if (!Array.isArray(stack) || stack.length < 3)
302
+ throw malformed('get_wallet_data returned a short stack');
303
+ const balanceEntry = asRequiredRecord(stack[0], 'jetton balance');
304
+ const balance = asBigInt(balanceEntry.value ?? balanceEntry.num, 'jetton balance');
305
+ try {
306
+ return {
307
+ balance,
308
+ owner: stackCellOf(stack[1], 'jetton wallet owner').beginParse().loadAddress().toRawString(),
309
+ jettonMaster: stackCellOf(stack[2], 'jetton master').beginParse().loadAddress().toRawString(),
310
+ };
311
+ }
312
+ catch (err) {
313
+ if (err instanceof TonProviderError)
314
+ throw err;
315
+ throw malformed('get_wallet_data returned no addresses');
316
+ }
317
+ }
318
+ /** A required boolean field; see {@link asRequiredRecord}. */
319
+ function asRequiredBoolean(value, what) {
320
+ if (typeof value !== 'boolean')
321
+ throw malformed(`${what} is missing or not a boolean`);
322
+ return value;
323
+ }
324
+ /**
325
+ * A transaction succeeds when its compute phase succeeded — or was skipped
326
+ * only because the account has no code yet — and its action phase, if any,
327
+ * succeeded without skipping a message. Phases that cannot be what the chain
328
+ * recorded (a successful compute phase without an action phase) are a
329
+ * malformed reply, never a success.
330
+ */
331
+ function tonTransactionOutcome(phases) {
332
+ const ran = phases.computeSkipped === null;
333
+ if (ran && phases.computeSuccess && phases.action === null)
334
+ throw malformed('a compute phase that succeeded has no action phase');
335
+ if ((!ran || !phases.computeSuccess) && phases.action !== null)
336
+ throw malformed('an action phase follows a compute phase that did not succeed');
337
+ const computeOk = ran ? phases.computeSuccess : phases.computeSkipped === 'no_state';
338
+ const skippedActions = phases.action?.skippedActions ?? 0;
339
+ return {
340
+ success: computeOk && (phases.action === null || (phases.action.success && skippedActions === 0)),
341
+ skippedActions,
342
+ aborted: phases.aborted,
343
+ computeExitCode: ran ? phases.computeExitCode : null,
344
+ actionResultCode: phases.action?.resultCode ?? null,
345
+ };
346
+ }
347
+ /** An account's status as the provider stated it; anything else says nothing definite. */
348
+ function asStatedAccountStatus(value) {
349
+ if (value === 'active' || value === 'frozen' || value === 'uninit' || value === 'nonexist')
350
+ return value;
351
+ throw new TonProviderError(errors_ts_1.ChainErrorKinds.RpcError, `Malformed TON provider reply: unknown account status ${String(value)}`, true);
352
+ }
353
+ function asAccountStatus(value) {
354
+ return value === 'active' || value === 'frozen' || value === 'uninit' || value === 'nonexist' ? value : 'nonexist';
355
+ }
356
+ /** A decoded message in the trace form (raw addresses, opcode from the body). */
357
+ function tonTraceMessageOf(message) {
358
+ const info = message.info;
359
+ const body = message.body.bits.length === 0 && message.body.refs.length === 0 ? null : message.body;
360
+ return {
361
+ source: info.type === 'external-in' || info.src === null ? null : info.src.toRawString(),
362
+ destination: info.type === 'external-out' ? null : info.dest.toRawString(),
363
+ value: info.type === 'internal' ? info.value.coins : 0n,
364
+ fwdFee: info.type === 'internal' ? info.forwardFee : 0n,
365
+ bounce: info.type === 'internal' && info.bounce,
366
+ bounced: info.type === 'internal' && info.bounced,
367
+ opcode: body !== null && body.bits.length >= 32 ? body.beginParse().loadUint(32) : null,
368
+ createdLt: info.type === 'external-in' ? null : info.createdLt,
369
+ body,
370
+ };
371
+ }
372
+ /**
373
+ * Checks a trace before anything is judged from it. On TON every internal
374
+ * message produces a transaction where it lands, so a provider's trace must
375
+ * hold together:
376
+ * - one root (the first transaction); every other transaction has a parent in
377
+ * the trace and an incoming message. A trace still running may lack a
378
+ * parent, the root included;
379
+ * - every internal message sent names its source and `created_lt`;
380
+ * - every incoming message is one its parent sent: same source, `created_lt`,
381
+ * destination and value;
382
+ * - in a complete trace, every internal message sent has the transaction
383
+ * that received it.
384
+ * A trace that breaks any of these is the provider's error, not the chain's:
385
+ * the error is retryable, so the fallback provider is asked instead, and no
386
+ * gap is ever read as an undelivered message.
387
+ */
388
+ function assertTraceConsistent(source, trace) {
389
+ const inconsistent = (detail) => new TonProviderError(errors_ts_1.ChainErrorKinds.RpcError, `Inconsistent trace from ${source}: ${detail}`, true);
390
+ const byHash = new Map(trace.transactions.map((tx) => [tx.hash, tx]));
391
+ const received = new Set();
392
+ trace.transactions.forEach((tx, index) => {
393
+ const unnamed = tx.outMsgs.find((m) => m.destination !== null && (m.source === null || m.createdLt === null));
394
+ if (unnamed !== undefined)
395
+ throw inconsistent(`transaction ${tx.hash} sent a message to ${unnamed.destination} with no source or created_lt`);
396
+ if (index === 0 && tx.parent === null)
397
+ return;
398
+ if (tx.parent === null)
399
+ throw inconsistent(`transaction ${tx.hash} has no parent but is not the root`);
400
+ if (tx.inMsg === null || tx.inMsg.source === null || tx.inMsg.createdLt === null) {
401
+ throw inconsistent(`transaction ${tx.hash} has no incoming internal message`);
402
+ }
403
+ const parent = byHash.get(tx.parent);
404
+ if (parent === undefined) {
405
+ if (trace.complete)
406
+ throw inconsistent(`transaction ${tx.hash} names a parent ${tx.parent} the trace does not hold`);
407
+ return;
408
+ }
409
+ const inMsg = tx.inMsg;
410
+ const sent = parent.outMsgs.find((m) => m.source === inMsg.source && m.createdLt === inMsg.createdLt);
411
+ if (sent === undefined || sent.destination !== tx.account || sent.value !== inMsg.value) {
412
+ throw inconsistent(`transaction ${tx.hash} received no message its parent ${parent.hash} sent`);
413
+ }
414
+ received.add(`${parent.hash}:${inMsg.createdLt}`);
415
+ });
416
+ if (trace.complete) {
417
+ for (const tx of trace.transactions) {
418
+ const lost = tx.outMsgs.find((m) => m.destination !== null && !received.has(`${tx.hash}:${m.createdLt}`));
419
+ if (lost !== undefined) {
420
+ throw inconsistent(`the trace is complete, but the message ${tx.hash} sent to ${lost.destination} reached no transaction`);
421
+ }
422
+ }
423
+ }
424
+ return trace;
425
+ }
426
+ /**
427
+ * The trace a provider returned for `hash` must be that message's: its root
428
+ * received an external message whose normalized hash is `hash`. A trace still
429
+ * running may not hold its root yet.
430
+ */
431
+ function assertTraceOf(source, hash, trace) {
432
+ const root = trace.transactions[0];
433
+ if (root === undefined || root.parent !== null)
434
+ return trace;
435
+ const inMsg = root.inMsg;
436
+ if (inMsg === null || inMsg.source !== null || inMsg.body === null || (0, ton_messages_ts_1.tonNormalizedExternalHash)(root.account, inMsg.body) !== hash) {
437
+ throw new TonProviderError(errors_ts_1.ChainErrorKinds.RpcError, `${source} returned the trace of another message than ${hash}`, true);
438
+ }
439
+ return trace;
440
+ }
441
+ const TX_HASH_REGEX = /^[0-9a-f]{64}$/;
442
+ /**
443
+ * Refuses anything but a transaction id as the SDK gives it — the normalized
444
+ * external-message hash, 64 lowercase hex characters. A base64 hash or a typo
445
+ * would otherwise find no trace, and "no trace" counts as "never landed".
446
+ */
447
+ function assertTonTxHash(hash) {
448
+ if (typeof hash !== 'string' || !TX_HASH_REGEX.test(hash)) {
449
+ throw new TonProviderError(errors_ts_1.ChainErrorKinds.InvalidArgument, `A TON transaction id is 64 lowercase hex characters, got ${JSON.stringify(hash)}`, false);
450
+ }
451
+ return hash;
452
+ }
453
+ function definiteError(kind, message) {
454
+ return new TonProviderError(kind, message, false);
455
+ }
456
+ //# sourceMappingURL=ton_provider.js.map