@anywalletkit/wallet-ton 0.3.1 → 0.4.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.
package/dist/index.d.cts CHANGED
@@ -67,6 +67,12 @@ interface TonConfig {
67
67
  validUntilSeconds?: number;
68
68
  /** Nanotons attached to a jetton transfer on top of `forwardTonAmount` (default 0.05 TON). */
69
69
  jettonAttachedValue?: bigint | number | string;
70
+ /**
71
+ * Most nanotons a jetton `transfer()` may attach to the jetton-wallet call, `forwardTonAmount`
72
+ * included (default 1 TON). The contract that receives them is the one the jetton master names,
73
+ * so a fake master gets all of it: the cap bounds what such a call can cost.
74
+ */
75
+ maxJettonAttachedValue?: bigint | number | string;
70
76
  /**
71
77
  * 'mainnet' (ton:-239, default) or 'testnet' (ton:-3). Sets the CAIP-2 id, the address flags and the
72
78
  * wallet_id network (-239 / -3), so a testnet wallet has its own address and its signed messages are
@@ -122,8 +128,14 @@ interface TonTransferOptions {
122
128
  memo?: string;
123
129
  /** Jetton only: custom payload cell (rarely needed; e.g. mintless jettons). */
124
130
  customPayload?: Cell;
125
- /** Jetton only: where excess TON returns (default: this wallet). */
131
+ /**
132
+ * Jetton only: where excess TON returns (default: this wallet). Another address is refused
133
+ * unless `allowForeignResponseDestination` is set: it receives TON the policies' recipient
134
+ * check never sees.
135
+ */
126
136
  responseDestination?: string;
137
+ /** Jetton only: let `responseDestination` be another address than this wallet. Off by default. */
138
+ allowForeignResponseDestination?: boolean;
127
139
  /** Jetton only: query id (default random). */
128
140
  queryId?: bigint | number;
129
141
  /** Jetton only: nanotons attached to the jetton-wallet call (default config.jettonAttachedValue + forwardTonAmount). */
@@ -469,12 +481,6 @@ interface ParsedV5R1Body {
469
481
  /** Parse a signed (or zero-signed) V5R1 external body back into its messages. Returns null for anything else. */
470
482
  declare function parseV5R1Body(body: Cell): ParsedV5R1Body | null;
471
483
 
472
- /**
473
- * "What am I signing" for TON — offline. Decodes the messages of a
474
- * {@link TonSendable} (or a prebuilt V5R1 body) into human-checkable items and
475
- * flags the classic mistakes before any key is touched.
476
- */
477
-
478
484
  /** TEP-74 `transfer` op code of a jetton wallet. */
479
485
  declare const JETTON_TRANSFER_OP = 260734629;
480
486
  /** What one outgoing message does. */
@@ -553,6 +559,21 @@ type DecodedBody = {
553
559
  };
554
560
  /** Decode a message body cell. */
555
561
  declare function decodeBody(body: Cell): DecodedBody;
562
+ /**
563
+ * A base64 BoC as its single root Cell, refused when its layout is one other readers may parse
564
+ * differently from @ton/core: a magic other than the generic one, more than one root, absent cells,
565
+ * or any cell that stores its hashes (with_hashes: @ton/core skips a hash area another reader takes
566
+ * for data), has a level mask, or is exotic. What remains is read the same by every reader, the
567
+ * kit's policy reader included, whatever order the serializer put the cells in (scan 2026-10-27
568
+ * F2, F4). Real provider BoCs order cells differently from @ton/core, so the bytes are not required
569
+ * to round-trip.
570
+ */
571
+ declare function canonicalBocCell(b64: string, what?: string): Cell;
572
+ /**
573
+ * The body a message is built with: a Cell, a text comment, or a canonical `bodyBoc`. A `body` that is
574
+ * neither a string nor a Cell is refused rather than replaced by `bodyBoc` (scan 2026-10-27 F4).
575
+ */
576
+ declare function messageBody(tx: TonTransaction): Cell | undefined;
556
577
  /** A text comment body (op 0 plus the text), as wallets show it. */
557
578
  declare function commentCell(text: string): Cell;
558
579
  /** Describe one outgoing message and push its warnings into `warnings`. */
@@ -723,6 +744,7 @@ declare function tonSignDataDigest(address: TonAddressParts, request: TonSignDat
723
744
  * once the transaction has passed.
724
745
  */
725
746
  declare class WalletAccountTon extends WalletAccountReadOnlyTon implements IWalletAccount {
747
+ #private;
726
748
  /** seqno and fees come from the network before signing. */
727
749
  readonly needsNetwork = true;
728
750
  /** Derivation path, `ton-mnemonic`, or `external`. */
@@ -766,7 +788,6 @@ declare class WalletAccountTon extends WalletAccountReadOnlyTon implements IWall
766
788
  private assertNoDrain;
767
789
  /** The send modes of a prebuilt V5R1 body; an unreadable body is left to the emulation and the node. */
768
790
  private bodyModes;
769
- private signMessages;
770
791
  private preflight;
771
792
  /** Sign without broadcasting. Returns the external-message BODY as base64 BoC (pass it back to sendTransaction as a Cell). */
772
793
  signTransaction(tx: TonSendable, options?: WriteOptions): Promise<string>;
@@ -818,4 +839,4 @@ declare class WalletManagerTon extends WalletManager<WalletAccountTon, TonConfig
818
839
  getFeeRates(): Promise<FeeRates>;
819
840
  }
820
841
 
821
- export { BroadcastUnknownError, CAIP2, DEFAULT_SEND_MODE, DEFAULT_TONAPI, type DecodedBody, type EmulateOptions, type EmulationOutcome, type EmulationSource, type EmulationVerdict, type GetMethodResult, JETTON_TRANSFER_OP, MAINNET_GLOBAL_ID, MAX_ACTIONS, MessageIsTransactionError, type ParsedV5R1Body, SEND_MODE, SimulationError, TESTNET_GLOBAL_ID, TON_BASE_PATH, TON_MNEMONIC_PATH, type TonAccountState, type TonAccountStatus, type TonAddressParts, TonCenter, type TonConfig, type TonDescribedKind, type TonDescribedMessage, type TonDescription, type TonEmulateConfig, type TonEndpoint, type TonFees, type TonJettonDetails, type TonProof, type TonProofRequest, type TonProvider, type TonReceipt, type TonRisk, type TonRpc, type TonSendable, type TonSignDataPayload, type TonSignDataRequest, type TonSignedData, type TonSimulation, type TonSimulationSource, type TonTransaction, type TonTransferOptions, type TonWarning, type TonWarningCode, UnsafeTransactionError, type V5R1Message, type V5R1SigningParams, type V5R1WalletIdParts, V5R1_CODE_HEX, V5R1_OP, WalletAccountReadOnlyTon, WalletAccountTon, WalletManagerTon, commentCell, createTonRpc as createTonClient, createTonRpc, decodeBody, WalletManagerTon as default, describeMessageRelaxed, describeTransaction, emulateExternal, emulateViaTonapi, installBufferGlobal, isAnsweredRefusal, parseEmulation, parseTonapiConsequences, parseTonapiRisk, parseTonapiTrace, parseV5R1Body, resolveEmulate, runEmulation, tonCenterEndpoint, tonProofDigest, tonSignDataDigest, v5r1Address, v5r1Code, v5r1ExternalMessage, v5r1PackSigned, v5r1PackUnsigned, v5r1SigningMessage, v5r1StateInit, v5r1WalletId };
842
+ export { BroadcastUnknownError, CAIP2, DEFAULT_SEND_MODE, DEFAULT_TONAPI, type DecodedBody, type EmulateOptions, type EmulationOutcome, type EmulationSource, type EmulationVerdict, type GetMethodResult, JETTON_TRANSFER_OP, MAINNET_GLOBAL_ID, MAX_ACTIONS, MessageIsTransactionError, type ParsedV5R1Body, SEND_MODE, SimulationError, TESTNET_GLOBAL_ID, TON_BASE_PATH, TON_MNEMONIC_PATH, type TonAccountState, type TonAccountStatus, type TonAddressParts, TonCenter, type TonConfig, type TonDescribedKind, type TonDescribedMessage, type TonDescription, type TonEmulateConfig, type TonEndpoint, type TonFees, type TonJettonDetails, type TonProof, type TonProofRequest, type TonProvider, type TonReceipt, type TonRisk, type TonRpc, type TonSendable, type TonSignDataPayload, type TonSignDataRequest, type TonSignedData, type TonSimulation, type TonSimulationSource, type TonTransaction, type TonTransferOptions, type TonWarning, type TonWarningCode, UnsafeTransactionError, type V5R1Message, type V5R1SigningParams, type V5R1WalletIdParts, V5R1_CODE_HEX, V5R1_OP, WalletAccountReadOnlyTon, WalletAccountTon, WalletManagerTon, canonicalBocCell, commentCell, createTonRpc as createTonClient, createTonRpc, decodeBody, WalletManagerTon as default, describeMessageRelaxed, describeTransaction, emulateExternal, emulateViaTonapi, installBufferGlobal, isAnsweredRefusal, messageBody, parseEmulation, parseTonapiConsequences, parseTonapiRisk, parseTonapiTrace, parseV5R1Body, resolveEmulate, runEmulation, tonCenterEndpoint, tonProofDigest, tonSignDataDigest, v5r1Address, v5r1Code, v5r1ExternalMessage, v5r1PackSigned, v5r1PackUnsigned, v5r1SigningMessage, v5r1StateInit, v5r1WalletId };
package/dist/index.d.ts CHANGED
@@ -67,6 +67,12 @@ interface TonConfig {
67
67
  validUntilSeconds?: number;
68
68
  /** Nanotons attached to a jetton transfer on top of `forwardTonAmount` (default 0.05 TON). */
69
69
  jettonAttachedValue?: bigint | number | string;
70
+ /**
71
+ * Most nanotons a jetton `transfer()` may attach to the jetton-wallet call, `forwardTonAmount`
72
+ * included (default 1 TON). The contract that receives them is the one the jetton master names,
73
+ * so a fake master gets all of it: the cap bounds what such a call can cost.
74
+ */
75
+ maxJettonAttachedValue?: bigint | number | string;
70
76
  /**
71
77
  * 'mainnet' (ton:-239, default) or 'testnet' (ton:-3). Sets the CAIP-2 id, the address flags and the
72
78
  * wallet_id network (-239 / -3), so a testnet wallet has its own address and its signed messages are
@@ -122,8 +128,14 @@ interface TonTransferOptions {
122
128
  memo?: string;
123
129
  /** Jetton only: custom payload cell (rarely needed; e.g. mintless jettons). */
124
130
  customPayload?: Cell;
125
- /** Jetton only: where excess TON returns (default: this wallet). */
131
+ /**
132
+ * Jetton only: where excess TON returns (default: this wallet). Another address is refused
133
+ * unless `allowForeignResponseDestination` is set: it receives TON the policies' recipient
134
+ * check never sees.
135
+ */
126
136
  responseDestination?: string;
137
+ /** Jetton only: let `responseDestination` be another address than this wallet. Off by default. */
138
+ allowForeignResponseDestination?: boolean;
127
139
  /** Jetton only: query id (default random). */
128
140
  queryId?: bigint | number;
129
141
  /** Jetton only: nanotons attached to the jetton-wallet call (default config.jettonAttachedValue + forwardTonAmount). */
@@ -469,12 +481,6 @@ interface ParsedV5R1Body {
469
481
  /** Parse a signed (or zero-signed) V5R1 external body back into its messages. Returns null for anything else. */
470
482
  declare function parseV5R1Body(body: Cell): ParsedV5R1Body | null;
471
483
 
472
- /**
473
- * "What am I signing" for TON — offline. Decodes the messages of a
474
- * {@link TonSendable} (or a prebuilt V5R1 body) into human-checkable items and
475
- * flags the classic mistakes before any key is touched.
476
- */
477
-
478
484
  /** TEP-74 `transfer` op code of a jetton wallet. */
479
485
  declare const JETTON_TRANSFER_OP = 260734629;
480
486
  /** What one outgoing message does. */
@@ -553,6 +559,21 @@ type DecodedBody = {
553
559
  };
554
560
  /** Decode a message body cell. */
555
561
  declare function decodeBody(body: Cell): DecodedBody;
562
+ /**
563
+ * A base64 BoC as its single root Cell, refused when its layout is one other readers may parse
564
+ * differently from @ton/core: a magic other than the generic one, more than one root, absent cells,
565
+ * or any cell that stores its hashes (with_hashes: @ton/core skips a hash area another reader takes
566
+ * for data), has a level mask, or is exotic. What remains is read the same by every reader, the
567
+ * kit's policy reader included, whatever order the serializer put the cells in (scan 2026-10-27
568
+ * F2, F4). Real provider BoCs order cells differently from @ton/core, so the bytes are not required
569
+ * to round-trip.
570
+ */
571
+ declare function canonicalBocCell(b64: string, what?: string): Cell;
572
+ /**
573
+ * The body a message is built with: a Cell, a text comment, or a canonical `bodyBoc`. A `body` that is
574
+ * neither a string nor a Cell is refused rather than replaced by `bodyBoc` (scan 2026-10-27 F4).
575
+ */
576
+ declare function messageBody(tx: TonTransaction): Cell | undefined;
556
577
  /** A text comment body (op 0 plus the text), as wallets show it. */
557
578
  declare function commentCell(text: string): Cell;
558
579
  /** Describe one outgoing message and push its warnings into `warnings`. */
@@ -723,6 +744,7 @@ declare function tonSignDataDigest(address: TonAddressParts, request: TonSignDat
723
744
  * once the transaction has passed.
724
745
  */
725
746
  declare class WalletAccountTon extends WalletAccountReadOnlyTon implements IWalletAccount {
747
+ #private;
726
748
  /** seqno and fees come from the network before signing. */
727
749
  readonly needsNetwork = true;
728
750
  /** Derivation path, `ton-mnemonic`, or `external`. */
@@ -766,7 +788,6 @@ declare class WalletAccountTon extends WalletAccountReadOnlyTon implements IWall
766
788
  private assertNoDrain;
767
789
  /** The send modes of a prebuilt V5R1 body; an unreadable body is left to the emulation and the node. */
768
790
  private bodyModes;
769
- private signMessages;
770
791
  private preflight;
771
792
  /** Sign without broadcasting. Returns the external-message BODY as base64 BoC (pass it back to sendTransaction as a Cell). */
772
793
  signTransaction(tx: TonSendable, options?: WriteOptions): Promise<string>;
@@ -818,4 +839,4 @@ declare class WalletManagerTon extends WalletManager<WalletAccountTon, TonConfig
818
839
  getFeeRates(): Promise<FeeRates>;
819
840
  }
820
841
 
821
- export { BroadcastUnknownError, CAIP2, DEFAULT_SEND_MODE, DEFAULT_TONAPI, type DecodedBody, type EmulateOptions, type EmulationOutcome, type EmulationSource, type EmulationVerdict, type GetMethodResult, JETTON_TRANSFER_OP, MAINNET_GLOBAL_ID, MAX_ACTIONS, MessageIsTransactionError, type ParsedV5R1Body, SEND_MODE, SimulationError, TESTNET_GLOBAL_ID, TON_BASE_PATH, TON_MNEMONIC_PATH, type TonAccountState, type TonAccountStatus, type TonAddressParts, TonCenter, type TonConfig, type TonDescribedKind, type TonDescribedMessage, type TonDescription, type TonEmulateConfig, type TonEndpoint, type TonFees, type TonJettonDetails, type TonProof, type TonProofRequest, type TonProvider, type TonReceipt, type TonRisk, type TonRpc, type TonSendable, type TonSignDataPayload, type TonSignDataRequest, type TonSignedData, type TonSimulation, type TonSimulationSource, type TonTransaction, type TonTransferOptions, type TonWarning, type TonWarningCode, UnsafeTransactionError, type V5R1Message, type V5R1SigningParams, type V5R1WalletIdParts, V5R1_CODE_HEX, V5R1_OP, WalletAccountReadOnlyTon, WalletAccountTon, WalletManagerTon, commentCell, createTonRpc as createTonClient, createTonRpc, decodeBody, WalletManagerTon as default, describeMessageRelaxed, describeTransaction, emulateExternal, emulateViaTonapi, installBufferGlobal, isAnsweredRefusal, parseEmulation, parseTonapiConsequences, parseTonapiRisk, parseTonapiTrace, parseV5R1Body, resolveEmulate, runEmulation, tonCenterEndpoint, tonProofDigest, tonSignDataDigest, v5r1Address, v5r1Code, v5r1ExternalMessage, v5r1PackSigned, v5r1PackUnsigned, v5r1SigningMessage, v5r1StateInit, v5r1WalletId };
842
+ export { BroadcastUnknownError, CAIP2, DEFAULT_SEND_MODE, DEFAULT_TONAPI, type DecodedBody, type EmulateOptions, type EmulationOutcome, type EmulationSource, type EmulationVerdict, type GetMethodResult, JETTON_TRANSFER_OP, MAINNET_GLOBAL_ID, MAX_ACTIONS, MessageIsTransactionError, type ParsedV5R1Body, SEND_MODE, SimulationError, TESTNET_GLOBAL_ID, TON_BASE_PATH, TON_MNEMONIC_PATH, type TonAccountState, type TonAccountStatus, type TonAddressParts, TonCenter, type TonConfig, type TonDescribedKind, type TonDescribedMessage, type TonDescription, type TonEmulateConfig, type TonEndpoint, type TonFees, type TonJettonDetails, type TonProof, type TonProofRequest, type TonProvider, type TonReceipt, type TonRisk, type TonRpc, type TonSendable, type TonSignDataPayload, type TonSignDataRequest, type TonSignedData, type TonSimulation, type TonSimulationSource, type TonTransaction, type TonTransferOptions, type TonWarning, type TonWarningCode, UnsafeTransactionError, type V5R1Message, type V5R1SigningParams, type V5R1WalletIdParts, V5R1_CODE_HEX, V5R1_OP, WalletAccountReadOnlyTon, WalletAccountTon, WalletManagerTon, canonicalBocCell, commentCell, createTonRpc as createTonClient, createTonRpc, decodeBody, WalletManagerTon as default, describeMessageRelaxed, describeTransaction, emulateExternal, emulateViaTonapi, installBufferGlobal, isAnsweredRefusal, messageBody, parseEmulation, parseTonapiConsequences, parseTonapiRisk, parseTonapiTrace, parseV5R1Body, resolveEmulate, runEmulation, tonCenterEndpoint, tonProofDigest, tonSignDataDigest, v5r1Address, v5r1Code, v5r1ExternalMessage, v5r1PackSigned, v5r1PackUnsigned, v5r1SigningMessage, v5r1StateInit, v5r1WalletId };
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  rawTonAddress,
11
11
  tonExplorerTxUrl,
12
12
  valueFlowTransfers
13
- } from "./chunk-RCL4PSJZ.js";
13
+ } from "./chunk-ZFENRKRW.js";
14
14
 
15
15
  // src/buffer-global.ts
16
16
  import { Buffer } from "buffer";
@@ -559,6 +559,7 @@ function parseV5R1Body(body) {
559
559
  }
560
560
 
561
561
  // src/describe.ts
562
+ import { Buffer as Buffer4 } from "buffer";
562
563
  import { Address as Address3, Cell as Cell3, beginCell as beginCell2 } from "@ton/core";
563
564
  var JETTON_TRANSFER_OP = 260734629;
564
565
  var LARGE_FORWARD_NANOTON = 500000000n;
@@ -618,11 +619,67 @@ function parseTo(to) {
618
619
  const a = Address3.parse(to);
619
620
  return { to: a.toRawString(), bounceable: true, workchain: a.workChain };
620
621
  }
621
- function bodyOf(tx) {
622
+ function canonicalBocCell(b64, what = "bodyBoc") {
623
+ if (!/^[A-Za-z0-9+/_-]+={0,2}$/.test(b64)) throw new UnsafeTransactionError("non-canonical-boc", `${what} is not a base64 string.`);
624
+ const bytes = Buffer4.from(b64, "base64");
625
+ const layout = plainBocLayout(bytes);
626
+ if (layout !== null) throw new UnsafeTransactionError("non-canonical-boc", `${what} is not a plain single-root BoC (${layout}), so what was reviewed may not be what is signed.`);
627
+ let roots;
628
+ try {
629
+ roots = Cell3.fromBoc(bytes);
630
+ } catch {
631
+ throw new UnsafeTransactionError("non-canonical-boc", `${what} is not a valid BoC.`);
632
+ }
633
+ if (roots.length !== 1) throw new UnsafeTransactionError("non-canonical-boc", `${what} has ${roots.length} roots.`);
634
+ return roots[0];
635
+ }
636
+ function plainBocLayout(b) {
637
+ if (b.length < 6 || b[0] !== 181 || b[1] !== 238 || b[2] !== 156 || b[3] !== 114) return "not the generic BoC magic";
638
+ const flags = b[4];
639
+ const size = flags & 7;
640
+ const offBytes = b[5];
641
+ if (size < 1 || size > 4 || offBytes < 1 || offBytes > 8) return "bad size fields";
642
+ let i = 6;
643
+ const int = (n) => {
644
+ if (i + n > b.length) throw new RangeError("truncated");
645
+ let v = 0;
646
+ for (let k = 0; k < n; k++) v = v * 256 + b[i++];
647
+ return v;
648
+ };
649
+ try {
650
+ const cells = int(size);
651
+ const roots = int(size);
652
+ const absent = int(size);
653
+ int(offBytes);
654
+ if (roots !== 1) return `${roots} roots`;
655
+ if (absent !== 0) return "absent cells";
656
+ i += roots * size;
657
+ if (flags & 128) i += cells * offBytes;
658
+ for (let c = 0; c < cells; c++) {
659
+ if (i + 2 > b.length) return "truncated";
660
+ const d1 = b[i++];
661
+ const d2 = b[i++];
662
+ if (d1 & 16) return "a cell stores its hashes";
663
+ if (d1 >> 5 !== 0) return "a cell has a level mask";
664
+ if (d1 & 8) return "an exotic cell";
665
+ if ((d1 & 7) > 4) return "a cell with more than 4 refs";
666
+ i += Math.ceil(d2 / 2) + (d1 & 7) * size;
667
+ }
668
+ if (i + (flags & 64 ? 4 : 0) !== b.length) return "trailing or missing bytes";
669
+ } catch {
670
+ return "truncated";
671
+ }
672
+ return null;
673
+ }
674
+ function messageBody(tx) {
622
675
  if (tx.body instanceof Cell3) return tx.body;
623
676
  if (typeof tx.body === "string") return tx.body === "" ? void 0 : commentCell(tx.body);
624
- if (tx.bodyBoc) return Cell3.fromBase64(tx.bodyBoc);
625
- return void 0;
677
+ if (tx.body !== void 0) throw new UnsafeTransactionError("body", "A message body must be a Cell or a string (a text comment).");
678
+ if (tx.bodyBoc !== void 0 && typeof tx.bodyBoc !== "string") throw new UnsafeTransactionError("body", "bodyBoc must be a base64 string.");
679
+ return tx.bodyBoc ? canonicalBocCell(tx.bodyBoc) : void 0;
680
+ }
681
+ function bodyOf(tx) {
682
+ return messageBody(tx);
626
683
  }
627
684
  function commentCell(text) {
628
685
  return beginCell2().storeUint(0, 32).storeStringTail(text).endCell();
@@ -728,6 +785,8 @@ import { ed25519 } from "@noble/curves/ed25519.js";
728
785
  import { Address as Address4, Cell as Cell4, beginCell as beginCell3, internal, loadStateInit } from "@ton/core";
729
786
  var JETTON_TRANSFER_OP2 = 260734629;
730
787
  var DEFAULT_JETTON_ATTACHED = 50000000n;
788
+ var DEFAULT_MAX_JETTON_ATTACHED = 1000000000n;
789
+ var RAW_ADDRESS = /^-?\d+:[0-9a-fA-F]{64}$/;
731
790
  var DEFAULT_INDEXER = "https://toncenter.com/api/v3";
732
791
  var DEFAULT_VALID_SECONDS = 60;
733
792
  var MAX_VALID_SECONDS = 600;
@@ -829,13 +888,15 @@ var WalletAccountReadOnlyTon = class {
829
888
  let address;
830
889
  let bounceable = true;
831
890
  let testOnly;
832
- if (Address4.isFriendly(to)) {
891
+ if (typeof to === "string" && Address4.isFriendly(to)) {
833
892
  const f = Address4.parseFriendly(to);
834
893
  address = f.address;
835
894
  bounceable = f.isBounceable;
836
895
  testOnly = f.isTestOnly;
837
- } else {
896
+ } else if (typeof to === "string" && RAW_ADDRESS.test(to)) {
838
897
  address = Address4.parse(to);
898
+ } else {
899
+ throw new UnsafeTransactionError("address", `${JSON.stringify(to)} is not a TON address in a strict form (raw wc:hex, or a friendly address with its checksum).`);
839
900
  }
840
901
  if (address.workChain !== 0 && address.workChain !== -1) throw new UnsafeTransactionError("exotic-workchain", `Refusing to send to workchain ${address.workChain}.`);
841
902
  const testnet = this._config.network === "testnet";
@@ -848,7 +909,7 @@ var WalletAccountReadOnlyTon = class {
848
909
  const value = big(tx.value);
849
910
  if (value <= 0n) throw new UnsafeTransactionError("zero-value", "TON message value must be positive.");
850
911
  const { address, bounceable } = this.checkedAddress(tx.to);
851
- const body = tx.body instanceof Cell4 ? tx.body : typeof tx.body === "string" ? tx.body === "" ? void 0 : commentCell(tx.body) : tx.bodyBoc ? Cell4.fromBase64(tx.bodyBoc) : void 0;
912
+ const body = messageBody(tx);
852
913
  const init = this.stateInitOf(tx.stateInit);
853
914
  const message = internal({ to: address, value, bounce: tx.bounceable ?? bounceable, ...body ? { body } : {}, ...init ? { init } : {} });
854
915
  return { message, ...tx.sendMode !== void 0 ? { mode: tx.sendMode } : {} };
@@ -858,14 +919,22 @@ var WalletAccountReadOnlyTon = class {
858
919
  if (amount <= 0n) throw new UnsafeTransactionError("zero-value", "Jetton amount must be positive.");
859
920
  const recipient = this.checkedAddress(o.recipient).address;
860
921
  const response = o.responseDestination ? this.checkedAddress(o.responseDestination).address : void 0;
922
+ if (response && !response.equals(this._address) && o.allowForeignResponseDestination !== true) {
923
+ throw new UnsafeTransactionError("foreign-response-destination", `The excess TON of this jetton transfer would go to ${response.toString()}, not to this wallet; pass allowForeignResponseDestination to allow it.`);
924
+ }
925
+ const forwardTon = o.forwardTonAmount !== void 0 ? big(o.forwardTonAmount) : 1n;
926
+ const attached = o.attachedValue !== void 0 ? big(o.attachedValue) : (this._config.jettonAttachedValue !== void 0 ? big(this._config.jettonAttachedValue) : DEFAULT_JETTON_ATTACHED) + forwardTon;
927
+ const maxAttached = this._config.maxJettonAttachedValue !== void 0 ? big(this._config.maxJettonAttachedValue) : DEFAULT_MAX_JETTON_ATTACHED;
928
+ if (attached > maxAttached || forwardTon > attached) {
929
+ throw new UnsafeTransactionError("attached-value", `A jetton transfer may attach at most ${maxAttached} nanotons, forwardTonAmount included (asked: ${attached}, forward ${forwardTon}); raise config.maxJettonAttachedValue if this is intended.`);
930
+ }
861
931
  const jw = await this.getJettonWalletAddress(o.token);
862
932
  await this.jettonWalletData(o.token, jw);
863
- const forwardTonAmount = o.forwardTonAmount !== void 0 ? big(o.forwardTonAmount) : 1n;
933
+ const forwardTonAmount = forwardTon;
864
934
  if (o.memo !== void 0 && o.forwardPayload !== void 0) throw new UnsafeTransactionError("memo-and-payload", "Pass either memo or forwardPayload, not both: a jetton transfer carries one forward payload.");
865
935
  const payload = o.forwardPayload ?? o.memo;
866
936
  const forwardPayload = payload === void 0 ? null : typeof payload === "string" ? commentCell(payload) : payload;
867
937
  const body = beginCell3().storeUint(JETTON_TRANSFER_OP2, 32).storeUint(o.queryId !== void 0 ? BigInt(o.queryId) : randomQueryId(), 64).storeCoins(amount).storeAddress(recipient).storeAddress(response ?? this._address).storeMaybeRef(o.customPayload ?? null).storeCoins(forwardTonAmount).storeMaybeRef(forwardPayload).endCell();
868
- const attached = o.attachedValue !== void 0 ? big(o.attachedValue) : (this._config.jettonAttachedValue !== void 0 ? big(this._config.jettonAttachedValue) : DEFAULT_JETTON_ATTACHED) + forwardTonAmount;
869
938
  return { message: internal({ to: jw, value: attached, bounce: true, body }) };
870
939
  }
871
940
  toMessages(tx) {
@@ -982,12 +1051,12 @@ function randomQueryId() {
982
1051
 
983
1052
  // src/account.ts
984
1053
  import { LocalSigner, feeLimit, requireCurve } from "@anywalletkit/core";
985
- import { Buffer as Buffer5 } from "buffer";
1054
+ import { Buffer as Buffer6 } from "buffer";
986
1055
  import { Cell as Cell5 } from "@ton/core";
987
1056
 
988
1057
  // src/tonconnect.ts
989
1058
  import { sha256 } from "@noble/hashes/sha2.js";
990
- import { Buffer as Buffer4 } from "buffer";
1059
+ import { Buffer as Buffer5 } from "buffer";
991
1060
  var utf82 = (s) => new TextEncoder().encode(s);
992
1061
  var int32BE = (n) => {
993
1062
  const b = new Uint8Array(4);
@@ -1022,7 +1091,7 @@ function checkCommon(address, domain, timestamp) {
1022
1091
  function base64Bytes(raw) {
1023
1092
  const s = raw.replace(/[\t\n\f\r ]/g, "");
1024
1093
  if (!/^[A-Za-z0-9+/]*={0,2}$/.test(s) || s.replace(/=+$/, "").length % 4 === 1) throw new TypeError("signData binary payload must be base64.");
1025
- return new Uint8Array(Buffer4.from(s, "base64"));
1094
+ return new Uint8Array(Buffer5.from(s, "base64"));
1026
1095
  }
1027
1096
  function tonProofDigest(address, request) {
1028
1097
  checkCommon(address, request.domain, request.timestamp);
@@ -1099,7 +1168,7 @@ var WalletAccountTon = class _WalletAccountTon extends WalletAccountReadOnlyTon
1099
1168
  timestamp: request.timestamp,
1100
1169
  domain: { lengthBytes: new TextEncoder().encode(request.domain).length, value: request.domain },
1101
1170
  payload: request.payload,
1102
- signature: Buffer5.from(signature).toString("base64")
1171
+ signature: Buffer6.from(signature).toString("base64")
1103
1172
  };
1104
1173
  }
1105
1174
  /** TON Connect `signData` (text / binary) for this wallet's address: the reply the dApp gets. */
@@ -1107,7 +1176,7 @@ var WalletAccountTon = class _WalletAccountTon extends WalletAccountReadOnlyTon
1107
1176
  const digest = tonSignDataDigest(this._address, request);
1108
1177
  const signature = await this.signer.sign(digest, { scheme: "ed25519", context: "ton-sign-data" });
1109
1178
  return {
1110
- signature: Buffer5.from(signature).toString("base64"),
1179
+ signature: Buffer6.from(signature).toString("base64"),
1111
1180
  address: this._address.toRawString(),
1112
1181
  timestamp: request.timestamp,
1113
1182
  domain: request.domain,
@@ -1135,7 +1204,7 @@ var WalletAccountTon = class _WalletAccountTon extends WalletAccountReadOnlyTon
1135
1204
  bodyModes(body) {
1136
1205
  return parseV5R1Body(body)?.messages.map((m) => m.mode) ?? [];
1137
1206
  }
1138
- async signMessages(messages, limit, op) {
1207
+ async #signMessages(messages, limit, op) {
1139
1208
  this.assertNoDrain(messages.map((m) => sendModeOf(m.mode)));
1140
1209
  const want = messages.reduce((sum, m) => sum + (m.message.info.type === "internal" ? m.message.info.value.coins : 0n), 0n);
1141
1210
  if (want > 0n) {
@@ -1172,7 +1241,7 @@ var WalletAccountTon = class _WalletAccountTon extends WalletAccountReadOnlyTon
1172
1241
  await this.preflight(tx, feeLimit(this._config.transactionMaxFee, options), "transaction");
1173
1242
  return tx.toBoc().toString("base64");
1174
1243
  }
1175
- const { body } = await this.signMessages(this.toMessages(tx), feeLimit(this._config.transactionMaxFee, options), "transaction");
1244
+ const { body } = await this.#signMessages(this.toMessages(tx), feeLimit(this._config.transactionMaxFee, options), "transaction");
1176
1245
  return body.toBoc().toString("base64");
1177
1246
  }
1178
1247
  async broadcast(body) {
@@ -1191,14 +1260,14 @@ var WalletAccountTon = class _WalletAccountTon extends WalletAccountReadOnlyTon
1191
1260
  async sendTransaction(tx, options = {}) {
1192
1261
  this.requireRpc("send transactions");
1193
1262
  if (tx instanceof Cell5) this.assertNoDrain(this.bodyModes(tx));
1194
- const { body, fee } = tx instanceof Cell5 ? { body: tx, fee: await this.preflight(tx, feeLimit(this._config.transactionMaxFee, options), "transaction") } : await this.signMessages(this.toMessages(tx), feeLimit(this._config.transactionMaxFee, options), "transaction");
1263
+ const { body, fee } = tx instanceof Cell5 ? { body: tx, fee: await this.preflight(tx, feeLimit(this._config.transactionMaxFee, options), "transaction") } : await this.#signMessages(this.toMessages(tx), feeLimit(this._config.transactionMaxFee, options), "transaction");
1195
1264
  return { hash: await this.broadcast(body), fee };
1196
1265
  }
1197
1266
  /** TON (no `token`) or jetton transfer. */
1198
1267
  async transfer(o, writeOptions = {}) {
1199
1268
  this.requireRpc("transfer tokens");
1200
1269
  const message = o.token ? await this.jettonTransferMessage(o) : this.transactionMessage({ to: o.recipient, value: o.amount, ...o.memo !== void 0 ? { body: o.memo } : {} });
1201
- const { body, fee } = await this.signMessages([message], feeLimit(this._config.transferMaxFee, writeOptions), "transfer");
1270
+ const { body, fee } = await this.#signMessages([message], feeLimit(this._config.transferMaxFee, writeOptions), "transfer");
1202
1271
  return { hash: await this.broadcast(body), fee };
1203
1272
  }
1204
1273
  /** The same wallet as a {@link WalletAccountReadOnlyTon}. */
@@ -1317,6 +1386,7 @@ export {
1317
1386
  WalletAccountReadOnlyTon,
1318
1387
  WalletAccountTon,
1319
1388
  WalletManagerTon,
1389
+ canonicalBocCell,
1320
1390
  commentCell,
1321
1391
  createTonRpc as createTonClient,
1322
1392
  createTonHistory,
@@ -1334,6 +1404,7 @@ export {
1334
1404
  mapActions as mapTonapiActions,
1335
1405
  mapTonapiEvent,
1336
1406
  mapToncenterTransaction,
1407
+ messageBody,
1337
1408
  parseEmulation,
1338
1409
  parseTonapiConsequences,
1339
1410
  parseTonapiRisk,