@pizzaton/ton 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/CONTRACTS.md +239 -0
  2. package/README.md +481 -2
  3. package/dist/airdrop/index.d.mts +18 -0
  4. package/dist/airdrop/index.mjs +86 -0
  5. package/dist/connect/errors.d.mts +4 -0
  6. package/dist/connect/errors.mjs +21 -0
  7. package/dist/connect/index.d.mts +23 -0
  8. package/dist/connect/index.mjs +34 -0
  9. package/dist/contracts/catalog/index.d.mts +361 -0
  10. package/dist/contracts/catalog/index.mjs +403 -0
  11. package/dist/contracts/client.d.mts +18 -0
  12. package/dist/contracts/client.mjs +31 -0
  13. package/dist/contracts/codecs.d.mts +14 -0
  14. package/dist/contracts/codecs.mjs +61 -0
  15. package/dist/contracts/hipo.d.mts +138 -0
  16. package/dist/contracts/hipo.mjs +198 -0
  17. package/dist/contracts/index.d.mts +23 -0
  18. package/dist/contracts/index.mjs +20 -0
  19. package/dist/contracts/metadata.d.mts +38 -0
  20. package/dist/contracts/metadata.mjs +50 -0
  21. package/dist/contracts/module-client.d.mts +20 -0
  22. package/dist/contracts/module-client.mjs +34 -0
  23. package/dist/contracts/module.d.mts +8 -0
  24. package/dist/contracts/module.mjs +11 -0
  25. package/dist/contracts/wrappers/base.d.mts +18 -0
  26. package/dist/contracts/wrappers/base.mjs +31 -0
  27. package/dist/contracts/wrappers/index.d.mts +12 -0
  28. package/dist/contracts/wrappers/index.mjs +12 -0
  29. package/dist/contracts/wrappers/jvault-protocols.d.mts +206 -0
  30. package/dist/contracts/wrappers/jvault-protocols.mjs +432 -0
  31. package/dist/contracts/wrappers/jvault-support.d.mts +135 -0
  32. package/dist/contracts/wrappers/jvault-support.mjs +269 -0
  33. package/dist/contracts/wrappers/jvault.d.mts +123 -0
  34. package/dist/contracts/wrappers/jvault.mjs +258 -0
  35. package/dist/contracts/wrappers/memeland.d.mts +253 -0
  36. package/dist/contracts/wrappers/memeland.mjs +396 -0
  37. package/dist/contracts/wrappers/multix.d.mts +92 -0
  38. package/dist/contracts/wrappers/multix.mjs +156 -0
  39. package/dist/contracts/wrappers/pizzabox.d.mts +66 -0
  40. package/dist/contracts/wrappers/pizzabox.mjs +105 -0
  41. package/dist/contracts/wrappers/ton-raffles.d.mts +215 -0
  42. package/dist/contracts/wrappers/ton-raffles.mjs +398 -0
  43. package/dist/contracts/wrappers/tonresistor.d.mts +189 -0
  44. package/dist/contracts/wrappers/tonresistor.mjs +276 -0
  45. package/dist/core/address.d.mts +25 -0
  46. package/dist/core/address.mjs +45 -0
  47. package/dist/core/amount.d.mts +8 -0
  48. package/dist/core/amount.mjs +34 -0
  49. package/dist/core/bytes.d.mts +5 -0
  50. package/dist/core/bytes.mjs +18 -0
  51. package/dist/core/constants.d.mts +14 -0
  52. package/dist/core/constants.mjs +15 -0
  53. package/dist/core/errors.d.mts +9 -0
  54. package/dist/core/errors.mjs +16 -0
  55. package/dist/core/http.mjs +39 -0
  56. package/dist/core/index.d.mts +8 -0
  57. package/dist/core/index.mjs +8 -0
  58. package/dist/core/metadata.d.mts +12 -0
  59. package/dist/core/metadata.mjs +35 -0
  60. package/dist/core/network.d.mts +24 -0
  61. package/dist/core/network.mjs +41 -0
  62. package/dist/emulator/index.d.mts +20 -0
  63. package/dist/emulator/index.mjs +24 -0
  64. package/dist/index.d.mts +21 -0
  65. package/dist/index.mjs +19 -0
  66. package/dist/indexer/index.d.mts +90 -0
  67. package/dist/indexer/index.mjs +279 -0
  68. package/dist/jetton/details.d.mts +27 -0
  69. package/dist/jetton/details.mjs +116 -0
  70. package/dist/jetton/index.d.mts +54 -0
  71. package/dist/jetton/index.mjs +92 -0
  72. package/dist/jetton/versions.d.mts +12 -0
  73. package/dist/jetton/versions.mjs +50 -0
  74. package/dist/nft/collection.d.mts +57 -0
  75. package/dist/nft/collection.mjs +148 -0
  76. package/dist/nft/content.d.mts +34 -0
  77. package/dist/nft/content.mjs +142 -0
  78. package/dist/nft/index.d.mts +35 -0
  79. package/dist/nft/index.mjs +51 -0
  80. package/dist/nft/versions.d.mts +11 -0
  81. package/dist/nft/versions.mjs +29 -0
  82. package/dist/provider/index.d.mts +32 -0
  83. package/dist/provider/index.mjs +1 -0
  84. package/dist/react/index.d.mts +13 -0
  85. package/dist/react/index.mjs +48 -0
  86. package/dist/server/index.d.mts +11 -0
  87. package/dist/server/index.mjs +55 -0
  88. package/dist/simulation/index.d.mts +112 -0
  89. package/dist/simulation/index.mjs +310 -0
  90. package/dist/transactions/index.d.mts +33 -0
  91. package/dist/transactions/index.mjs +51 -0
  92. package/dist/vesting/index.d.mts +12 -0
  93. package/dist/vesting/index.mjs +25 -0
  94. package/dist/wallet/index.d.mts +23 -0
  95. package/dist/wallet/index.mjs +71 -0
  96. package/package.json +169 -5
@@ -0,0 +1,32 @@
1
+ import { TonNetwork } from "../core/network.mjs";
2
+ import { Address, Contract, ContractProvider, OpenedContract, StateInit, TupleItem, TupleReader } from "@ton/core";
3
+ //#region src/provider/index.d.ts
4
+ export interface TonAccountState {
5
+ readonly status: "active" | "uninitialized" | "frozen" | "non-existing";
6
+ readonly balance: bigint;
7
+ }
8
+ export interface TonTransactionSummary {
9
+ readonly lt: bigint;
10
+ readonly hash: string;
11
+ readonly timestamp: number;
12
+ }
13
+ export interface TonGetMethodResult {
14
+ readonly gasUsed: number;
15
+ readonly stack: TupleReader;
16
+ readonly exitCode?: number;
17
+ }
18
+ export interface TonProvider {
19
+ readonly network: TonNetwork;
20
+ openContract<T extends Contract>(contract: T): OpenedContract<T>;
21
+ contractProvider(address: Address, init?: StateInit | null): ContractProvider;
22
+ getBalance(address: Address): Promise<bigint>;
23
+ getAccountState(address: Address): Promise<TonAccountState>;
24
+ runGetMethod(address: Address, method: string, args?: readonly TupleItem[]): Promise<TonGetMethodResult>;
25
+ getTransactions(address: Address, options?: {
26
+ readonly limit?: number;
27
+ readonly lt?: bigint;
28
+ readonly hash?: string;
29
+ }): Promise<readonly TonTransactionSummary[]>;
30
+ isContractDeployed(address: Address): Promise<boolean>;
31
+ }
32
+ //#endregion
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,13 @@
1
+ import { TransactionIntent } from "../transactions/index.mjs";
2
+ import { TonConnectAdapter, TonConnectWallet } from "../connect/index.mjs";
3
+ //#region src/react/index.d.ts
4
+ export declare function useTonWallet(adapter: TonConnectAdapter | null): TonConnectWallet | null;
5
+ export type TonTransactionStatus = "idle" | "sending" | "sent" | "error";
6
+ export declare function useTonTransaction(adapter: TonConnectAdapter | null): {
7
+ readonly send: (intent: TransactionIntent) => Promise<string | null>;
8
+ readonly status: TonTransactionStatus;
9
+ readonly boc: string | null;
10
+ readonly error: Error | null;
11
+ readonly reset: () => void;
12
+ };
13
+ //#endregion
@@ -0,0 +1,48 @@
1
+ import { useCallback, useEffect, useRef, useState, useSyncExternalStore } from "react";
2
+ //#region src/react/index.ts
3
+ function useTonWallet(adapter) {
4
+ return useSyncExternalStore((listener) => adapter?.subscribe(listener) ?? (() => void 0), () => adapter?.getWallet() ?? null, () => null);
5
+ }
6
+ function useTonTransaction(adapter) {
7
+ const [status, setStatus] = useState("idle");
8
+ const [boc, setBoc] = useState(null);
9
+ const [error, setError] = useState(null);
10
+ const sending = useRef(false);
11
+ const reset = useCallback(() => {
12
+ setStatus("idle");
13
+ setBoc(null);
14
+ setError(null);
15
+ }, []);
16
+ const send = useCallback(async (intent) => {
17
+ if (!adapter) throw new Error("A TON Connect adapter is required");
18
+ if (sending.current) throw new Error("A TON transaction is already being sent");
19
+ sending.current = true;
20
+ setStatus("sending");
21
+ setError(null);
22
+ try {
23
+ const result = await adapter.sendTransaction(intent);
24
+ setBoc(result);
25
+ setStatus("sent");
26
+ return result;
27
+ } catch (cause) {
28
+ const nextError = cause instanceof Error ? cause : new Error(String(cause));
29
+ setError(nextError);
30
+ setStatus("error");
31
+ return null;
32
+ } finally {
33
+ sending.current = false;
34
+ }
35
+ }, [adapter]);
36
+ useEffect(() => {
37
+ if (!adapter) reset();
38
+ }, [adapter, reset]);
39
+ return {
40
+ send,
41
+ status,
42
+ boc,
43
+ error,
44
+ reset
45
+ };
46
+ }
47
+ //#endregion
48
+ export { useTonTransaction, useTonWallet };
@@ -0,0 +1,11 @@
1
+ import { TonNetwork } from "../core/network.mjs";
2
+ import { TonProvider } from "../provider/index.mjs";
3
+ //#region src/server/index.d.ts
4
+ export interface TonHttpProviderOptions {
5
+ readonly network: TonNetwork;
6
+ readonly endpoint: string;
7
+ readonly apiKey?: string;
8
+ readonly timeoutMs?: number;
9
+ }
10
+ export declare function createTonHttpProvider(options: TonHttpProviderOptions): TonProvider;
11
+ //#endregion
@@ -0,0 +1,55 @@
1
+ import { invariant } from "../core/errors.mjs";
2
+ import { createNetworkConfig } from "../core/network.mjs";
3
+ import { TonClient } from "@ton/ton";
4
+ //#region src/server/index.ts
5
+ function createTonHttpProvider(options) {
6
+ const networkConfig = createNetworkConfig({
7
+ network: options.network,
8
+ endpoint: options.endpoint
9
+ });
10
+ const timeoutMs = options.timeoutMs ?? 1e4;
11
+ invariant(Number.isSafeInteger(timeoutMs) && timeoutMs > 0, "INVALID_NETWORK", "TON provider timeout must be a positive safe integer");
12
+ const client = new TonClient({
13
+ endpoint: networkConfig.endpoint,
14
+ ...options.apiKey === void 0 ? {} : { apiKey: options.apiKey },
15
+ timeout: timeoutMs
16
+ });
17
+ return {
18
+ network: options.network,
19
+ openContract: (contract) => client.open(contract),
20
+ contractProvider: (address, init) => client.provider(address, init),
21
+ getBalance: (address) => client.getBalance(address),
22
+ async getAccountState(address) {
23
+ const state = await client.getContractState(address);
24
+ return {
25
+ status: state.state === "active" ? "active" : state.state === "frozen" ? "frozen" : "uninitialized",
26
+ balance: state.balance
27
+ };
28
+ },
29
+ async runGetMethod(address, method, args) {
30
+ const result = await client.runMethodWithError(address, method, args ? [...args] : []);
31
+ return {
32
+ gasUsed: result.gas_used,
33
+ stack: result.stack,
34
+ exitCode: result.exit_code
35
+ };
36
+ },
37
+ async getTransactions(address, transactionOptions) {
38
+ const limit = transactionOptions?.limit ?? 20;
39
+ invariant(Number.isSafeInteger(limit) && limit >= 1 && limit <= 1e3, "INVALID_TRANSACTION", "Transaction limit must be an integer from 1 to 1000");
40
+ if (transactionOptions?.lt !== void 0) invariant(transactionOptions.lt >= 0n, "INVALID_TRANSACTION", "Transaction logical time cannot be negative");
41
+ return (await client.getTransactions(address, {
42
+ limit,
43
+ ...transactionOptions?.lt !== void 0 ? { lt: transactionOptions.lt.toString() } : {},
44
+ ...transactionOptions?.hash ? { hash: transactionOptions.hash } : {}
45
+ })).map((transaction) => ({
46
+ lt: transaction.lt,
47
+ hash: transaction.hash().toString("hex"),
48
+ timestamp: transaction.now
49
+ }));
50
+ },
51
+ isContractDeployed: (address) => client.isContractDeployed(address)
52
+ };
53
+ }
54
+ //#endregion
55
+ export { createTonHttpProvider };
@@ -0,0 +1,112 @@
1
+ import { Address, Cell, Message, StateInit } from "@ton/core";
2
+ import { AccountEvent } from "@ton-api/client";
3
+ import { Blockchain, BlockchainConfig, Event } from "@ton/sandbox";
4
+ //#region src/simulation/index.d.ts
5
+ export type TonSimulationSource = "sandbox" | "tonapi";
6
+ export interface TonSimulationInput {
7
+ /** A serialized external or internal message, or a message object for local sandbox execution. */
8
+ readonly message: Cell | Message;
9
+ /** Required for unsigned external-wallet previews. Internal messages do not need this flag. */
10
+ readonly ignoreSignatureCheck?: boolean;
11
+ /** Keep mutations in a local sandbox. Preview callers should leave this false. */
12
+ readonly persist?: boolean;
13
+ }
14
+ export interface TonSimulationMessage {
15
+ readonly type: "internal" | "external-in" | "external-out";
16
+ readonly source?: Address;
17
+ readonly destination?: Address;
18
+ readonly value?: bigint;
19
+ readonly body?: Cell;
20
+ readonly init?: StateInit;
21
+ readonly createdAt?: number;
22
+ readonly createdLt?: bigint;
23
+ }
24
+ export interface TonSimulationTransaction {
25
+ readonly hash: string;
26
+ readonly logicalTime: bigint;
27
+ /** Raw 256-bit account identifier; TON transactions do not carry the workchain in this field. */
28
+ readonly accountId: string;
29
+ readonly timestamp: number;
30
+ readonly success: boolean;
31
+ readonly oldStatus: string;
32
+ readonly endStatus: string;
33
+ readonly totalFees: bigint;
34
+ readonly storageFees: bigint;
35
+ readonly gasFees: bigint;
36
+ readonly forwardFees: bigint;
37
+ readonly actionFees: bigint;
38
+ readonly gasUsed: bigint;
39
+ readonly vmSteps: number;
40
+ readonly exitCode?: number;
41
+ readonly actionSuccess?: boolean;
42
+ readonly input?: TonSimulationMessage;
43
+ readonly outputs: readonly TonSimulationMessage[];
44
+ readonly parentHash?: string;
45
+ readonly childHashes: readonly string[];
46
+ readonly blockchainLogs: string;
47
+ readonly vmLogs: string;
48
+ readonly debugLogs: string;
49
+ readonly oldStorage?: Cell;
50
+ readonly newStorage?: Cell;
51
+ }
52
+ export interface TonSimulationCost {
53
+ readonly totalFees: bigint;
54
+ readonly storageFees: bigint;
55
+ readonly gasFees: bigint;
56
+ readonly forwardFees: bigint;
57
+ readonly actionFees: bigint;
58
+ readonly gasUsed: bigint;
59
+ readonly vmSteps: number;
60
+ }
61
+ export interface TonSimulationError {
62
+ readonly message: string;
63
+ readonly exitCode?: number;
64
+ }
65
+ export interface TonSimulationResult {
66
+ readonly source: TonSimulationSource;
67
+ readonly success: boolean;
68
+ readonly transactions: readonly TonSimulationTransaction[];
69
+ readonly cost: TonSimulationCost;
70
+ readonly rootTransactionHash?: string;
71
+ readonly events?: readonly Event[] | readonly AccountEvent[];
72
+ readonly error?: TonSimulationError;
73
+ /** Always true for remote previews because the remote chain may change before signing. */
74
+ readonly speculative: boolean;
75
+ }
76
+ export interface TonSimulationAdapter {
77
+ readonly source: TonSimulationSource;
78
+ simulate(input: TonSimulationInput): Promise<TonSimulationResult>;
79
+ }
80
+ export declare function createTonSimulationWithFallback(primary: TonSimulationAdapter, fallback: TonSimulationAdapter): TonSimulationAdapter;
81
+ export interface TonSandboxSimulation extends TonSimulationAdapter {
82
+ readonly source: "sandbox";
83
+ readonly blockchain: Blockchain;
84
+ }
85
+ export interface TonSandboxSimulationOptions {
86
+ /** Recording storage snapshots makes state diffs available but is slower. */
87
+ readonly recordStorage?: boolean;
88
+ }
89
+ export declare function messageToCell(message: Message): Cell;
90
+ export declare function createTonSandboxSimulation(blockchain: Blockchain, options?: TonSandboxSimulationOptions): TonSandboxSimulation;
91
+ export interface TonClient4SandboxSimulationOptions {
92
+ readonly endpoint: string;
93
+ readonly timeoutMs?: number;
94
+ readonly blockSeqno?: number;
95
+ readonly config?: BlockchainConfig;
96
+ readonly now?: number;
97
+ readonly recordStorage?: boolean;
98
+ }
99
+ /**
100
+ * Creates a native sandbox backed by a read-only snapshot of the live chain.
101
+ * Contract code and account state are fetched lazily from TonClient4.
102
+ */
103
+ export declare function createTonClient4SandboxSimulation(options: TonClient4SandboxSimulationOptions): Promise<TonSandboxSimulation>;
104
+ export interface TonApiSimulationFallbackOptions {
105
+ readonly baseUrl?: string;
106
+ readonly apiKey?: string;
107
+ readonly timeoutMs?: number;
108
+ readonly fetch?: typeof globalThis.fetch;
109
+ }
110
+ /** Optional fallback for clients that cannot hydrate a native sandbox snapshot. */
111
+ export declare function createTonApiSimulationFallback(options?: TonApiSimulationFallbackOptions): TonSimulationAdapter;
112
+ //#endregion
@@ -0,0 +1,310 @@
1
+ import { invariant } from "../core/errors.mjs";
2
+ import { createTimedFetch, normalizeHttpsBaseUrl, validateRequestTimeout } from "../core/http.mjs";
3
+ import { Cell, beginCell, storeMessage } from "@ton/core";
4
+ import { TonClient4 } from "@ton/ton";
5
+ import { TonApiClient } from "@ton-api/client";
6
+ import { Blockchain, RemoteBlockchainStorage, wrapTonClient4ForRemote } from "@ton/sandbox";
7
+ //#region src/simulation/index.ts
8
+ function createTonSimulationWithFallback(primary, fallback) {
9
+ return {
10
+ source: primary.source,
11
+ async simulate(input) {
12
+ try {
13
+ const result = await primary.simulate(input);
14
+ if (!result.error) return result;
15
+ } catch {}
16
+ return fallback.simulate(input);
17
+ }
18
+ };
19
+ }
20
+ function messageToCell(message) {
21
+ return beginCell().store(storeMessage(message)).endCell();
22
+ }
23
+ function createTonSandboxSimulation(blockchain, options = {}) {
24
+ blockchain.recordStorage = options.recordStorage ?? true;
25
+ return {
26
+ source: "sandbox",
27
+ blockchain,
28
+ async simulate(input) {
29
+ return withBlockchainLock(blockchain, async () => {
30
+ const snapshot = blockchain.snapshot();
31
+ try {
32
+ const result = await blockchain.sendMessage(input.message, { ignoreChksig: input.ignoreSignatureCheck ?? false });
33
+ return buildSandboxResult(result.transactions, result.events);
34
+ } catch (cause) {
35
+ return buildFailureResult("sandbox", cause, false);
36
+ } finally {
37
+ if (!input.persist) await blockchain.loadFrom(snapshot);
38
+ }
39
+ });
40
+ }
41
+ };
42
+ }
43
+ /**
44
+ * Creates a native sandbox backed by a read-only snapshot of the live chain.
45
+ * Contract code and account state are fetched lazily from TonClient4.
46
+ */
47
+ async function createTonClient4SandboxSimulation(options) {
48
+ const endpoint = normalizeHttpsBaseUrl(options.endpoint, "TON Client4 endpoint");
49
+ const timeoutMs = validateRequestTimeout(options.timeoutMs, "TON Client4");
50
+ if (options.blockSeqno !== void 0) invariant(Number.isSafeInteger(options.blockSeqno) && options.blockSeqno >= 0, "INVALID_NETWORK", "TON Client4 block sequence number must be a non-negative safe integer");
51
+ if (options.now !== void 0) invariant(Number.isSafeInteger(options.now) && options.now >= 0, "INVALID_NETWORK", "TON simulation time must be a non-negative safe integer");
52
+ const client = new TonClient4({
53
+ endpoint,
54
+ timeout: timeoutMs
55
+ });
56
+ const latest = await client.getLastBlock();
57
+ const blockSeqno = options.blockSeqno ?? latest.last.seqno;
58
+ const config = options.config ?? Cell.fromBase64((await client.getConfig(blockSeqno)).config.cell);
59
+ const blockchain = await Blockchain.create({
60
+ config,
61
+ storage: new RemoteBlockchainStorage(wrapTonClient4ForRemote(client), blockSeqno),
62
+ autoDeployLibs: true
63
+ });
64
+ blockchain.now = options.now ?? latest.now;
65
+ return createTonSandboxSimulation(blockchain, options);
66
+ }
67
+ /** Optional fallback for clients that cannot hydrate a native sandbox snapshot. */
68
+ function createTonApiSimulationFallback(options = {}) {
69
+ const baseUrl = options.baseUrl ?? "https://tonapi.io";
70
+ const normalizedBaseUrl = normalizeHttpsBaseUrl(baseUrl, "TonAPI");
71
+ const timeoutMs = validateRequestTimeout(options.timeoutMs, "TonAPI");
72
+ const client = new TonApiClient({
73
+ baseUrl: normalizedBaseUrl,
74
+ fetch: createTimedFetch(options.fetch ?? globalThis.fetch, timeoutMs, "TonAPI"),
75
+ ...options.apiKey === void 0 ? {} : { apiKey: options.apiKey }
76
+ });
77
+ return {
78
+ source: "tonapi",
79
+ async simulate(input) {
80
+ const boc = input.message instanceof Cell ? input.message : messageToCell(input.message);
81
+ try {
82
+ return buildTonApiResult(await client.emulation.emulateMessageToTrace({ boc }, { ignore_signature_check: input.ignoreSignatureCheck ?? false }));
83
+ } catch (cause) {
84
+ return buildFailureResult("tonapi", cause, true);
85
+ }
86
+ }
87
+ };
88
+ }
89
+ function buildSandboxResult(transactions, events) {
90
+ const normalized = transactions.map(normalizeSandboxTransaction);
91
+ const rootTransaction = normalized.find((transaction) => !transaction.parentHash);
92
+ const cost = normalized.reduce((total, transaction) => ({
93
+ totalFees: total.totalFees + transaction.totalFees,
94
+ storageFees: total.storageFees + transaction.storageFees,
95
+ gasFees: total.gasFees + transaction.gasFees,
96
+ forwardFees: total.forwardFees + transaction.forwardFees,
97
+ actionFees: total.actionFees + transaction.actionFees,
98
+ gasUsed: total.gasUsed + transaction.gasUsed,
99
+ vmSteps: total.vmSteps + transaction.vmSteps
100
+ }), zeroCost());
101
+ return {
102
+ source: "sandbox",
103
+ success: normalized.length > 0 && normalized.every((transaction) => transaction.success),
104
+ transactions: normalized,
105
+ cost,
106
+ events,
107
+ ...rootTransaction ? { rootTransactionHash: rootTransaction.hash } : {},
108
+ ...normalized.length === 0 ? { error: { message: "Sandbox produced no transactions" } } : {},
109
+ speculative: false
110
+ };
111
+ }
112
+ function normalizeSandboxTransaction(transaction) {
113
+ const description = transaction.description;
114
+ const compute = "computePhase" in description ? description.computePhase : void 0;
115
+ const storage = "storagePhase" in description ? description.storagePhase : void 0;
116
+ const action = "actionPhase" in description ? description.actionPhase : void 0;
117
+ const computePhase = compute ?? void 0;
118
+ const actionPhase = action ?? void 0;
119
+ const gasUsed = computePhase?.type === "vm" ? computePhase.gasUsed : 0n;
120
+ const gasFees = computePhase?.type === "vm" ? computePhase.gasFees : 0n;
121
+ const vmSteps = computePhase?.type === "vm" ? computePhase.vmSteps : 0;
122
+ const actionFees = actionPhase?.totalActionFees ?? 0n;
123
+ const forwardFees = actionPhase?.totalFwdFees ?? 0n;
124
+ const aborted = "aborted" in description ? description.aborted : false;
125
+ const computeSuccess = computePhase?.type === "vm" ? computePhase.success : true;
126
+ const actionSuccess = actionPhase?.success;
127
+ return {
128
+ hash: transaction.hash().toString("hex"),
129
+ logicalTime: transaction.lt,
130
+ accountId: transaction.address.toString(16).padStart(64, "0"),
131
+ timestamp: transaction.now,
132
+ success: !aborted && computeSuccess && actionSuccess !== false,
133
+ oldStatus: transaction.oldStatus,
134
+ endStatus: transaction.endStatus,
135
+ totalFees: transaction.totalFees.coins,
136
+ storageFees: storage?.storageFeesCollected ?? 0n,
137
+ gasFees,
138
+ forwardFees,
139
+ actionFees,
140
+ gasUsed,
141
+ vmSteps,
142
+ ...computePhase?.type === "vm" ? { exitCode: computePhase.exitCode } : {},
143
+ ...actionSuccess !== void 0 ? { actionSuccess } : {},
144
+ ...transaction.inMessage ? { input: summarizeMessage(transaction.inMessage) } : {},
145
+ outputs: transaction.outMessages.values().map(summarizeMessage),
146
+ ...transaction.parent ? { parentHash: transaction.parent.hash().toString("hex") } : {},
147
+ childHashes: transaction.children.map((child) => child.hash().toString("hex")),
148
+ blockchainLogs: transaction.blockchainLogs,
149
+ vmLogs: transaction.vmLogs,
150
+ debugLogs: transaction.debugLogs,
151
+ ...transaction.oldStorage ? { oldStorage: transaction.oldStorage } : {},
152
+ ...transaction.newStorage ? { newStorage: transaction.newStorage } : {}
153
+ };
154
+ }
155
+ function summarizeMessage(message) {
156
+ const info = message.info;
157
+ if (info.type === "internal") return {
158
+ type: "internal",
159
+ source: info.src,
160
+ destination: info.dest,
161
+ value: info.value.coins,
162
+ body: message.body,
163
+ ...message.init ? { init: message.init } : {},
164
+ createdAt: info.createdAt,
165
+ createdLt: info.createdLt
166
+ };
167
+ if (info.type === "external-in") return {
168
+ type: "external-in",
169
+ destination: info.dest,
170
+ body: message.body,
171
+ ...message.init ? { init: message.init } : {}
172
+ };
173
+ return {
174
+ type: "external-out",
175
+ source: info.src,
176
+ body: message.body,
177
+ createdAt: info.createdAt,
178
+ createdLt: info.createdLt
179
+ };
180
+ }
181
+ function buildTonApiResult(trace) {
182
+ const transactions = flattenTonApiTrace(trace).map(normalizeTonApiTransaction);
183
+ const cost = transactions.reduce((total, transaction) => ({
184
+ totalFees: total.totalFees + transaction.totalFees,
185
+ storageFees: total.storageFees + transaction.storageFees,
186
+ gasFees: total.gasFees + transaction.gasFees,
187
+ forwardFees: total.forwardFees + transaction.forwardFees,
188
+ actionFees: total.actionFees + transaction.actionFees,
189
+ gasUsed: total.gasUsed + transaction.gasUsed,
190
+ vmSteps: total.vmSteps + transaction.vmSteps
191
+ }), zeroCost());
192
+ return {
193
+ source: "tonapi",
194
+ success: transactions.length > 0 && transactions.every((transaction) => transaction.success),
195
+ transactions,
196
+ cost,
197
+ ...transactions.length === 0 ? { error: { message: "TonAPI returned no transactions" } } : {},
198
+ ...transactions[0] ? { rootTransactionHash: transactions[0].hash } : {},
199
+ speculative: true
200
+ };
201
+ }
202
+ function flattenTonApiTrace(root) {
203
+ const flattened = [];
204
+ const pending = [{ trace: root }];
205
+ const seen = /* @__PURE__ */ new Set();
206
+ while (pending.length > 0) {
207
+ const item = pending.pop();
208
+ if (!item) continue;
209
+ invariant(!seen.has(item.trace), "PROVIDER_ERROR", "TonAPI returned a recursive trace");
210
+ seen.add(item.trace);
211
+ invariant(seen.size <= 1e5, "PROVIDER_ERROR", "TonAPI trace exceeds the transaction limit");
212
+ flattened.push(item);
213
+ const children = item.trace.children ?? [];
214
+ for (let index = children.length - 1; index >= 0; index -= 1) {
215
+ const child = children[index];
216
+ if (child) pending.push({
217
+ trace: child,
218
+ parentHash: item.trace.transaction.hash
219
+ });
220
+ }
221
+ }
222
+ return flattened;
223
+ }
224
+ function normalizeTonApiTransaction(item) {
225
+ const transaction = item.trace.transaction;
226
+ const compute = transaction.computePhase;
227
+ const action = transaction.actionPhase;
228
+ const storage = transaction.storagePhase;
229
+ return {
230
+ hash: transaction.hash,
231
+ logicalTime: transaction.lt,
232
+ accountId: transaction.account.address.hash.toString("hex").padStart(64, "0"),
233
+ timestamp: transaction.utime,
234
+ success: transaction.success,
235
+ oldStatus: transaction.origStatus,
236
+ endStatus: transaction.endStatus,
237
+ totalFees: transaction.totalFees,
238
+ storageFees: storage?.feesCollected ?? 0n,
239
+ gasFees: compute?.gasFees ?? 0n,
240
+ forwardFees: action?.fwdFees ?? 0n,
241
+ actionFees: action ? action.totalFees - action.fwdFees : 0n,
242
+ gasUsed: compute?.gasUsed ?? 0n,
243
+ vmSteps: compute?.vmSteps ?? 0,
244
+ ...compute?.exitCode !== void 0 ? { exitCode: compute.exitCode } : {},
245
+ ...action ? { actionSuccess: action.success } : {},
246
+ ...transaction.inMsg ? { input: summarizeTonApiMessage(transaction.inMsg) } : {},
247
+ outputs: transaction.outMsgs.map(summarizeTonApiMessage),
248
+ ...item.parentHash ? { parentHash: item.parentHash } : {},
249
+ childHashes: (item.trace.children ?? []).map((child) => child.transaction.hash),
250
+ blockchainLogs: "",
251
+ vmLogs: "",
252
+ debugLogs: ""
253
+ };
254
+ }
255
+ function summarizeTonApiMessage(message) {
256
+ if (!message) return { type: "external-in" };
257
+ return {
258
+ type: message.msgType === "int_msg" ? "internal" : message.msgType === "ext_out_msg" ? "external-out" : "external-in",
259
+ ...message.source ? { source: message.source.address } : {},
260
+ ...message.destination ? { destination: message.destination.address } : {},
261
+ ...message.value === void 0 ? {} : { value: message.value },
262
+ ...message.rawBody ? { body: message.rawBody } : {},
263
+ ...message.createdAt === void 0 ? {} : { createdAt: message.createdAt },
264
+ ...message.createdLt === void 0 ? {} : { createdLt: message.createdLt }
265
+ };
266
+ }
267
+ function zeroCost() {
268
+ return {
269
+ totalFees: 0n,
270
+ storageFees: 0n,
271
+ gasFees: 0n,
272
+ forwardFees: 0n,
273
+ actionFees: 0n,
274
+ gasUsed: 0n,
275
+ vmSteps: 0
276
+ };
277
+ }
278
+ function buildFailureResult(source, cause, speculative) {
279
+ const error = cause instanceof Error ? cause : new Error(String(cause));
280
+ const exitCode = typeof cause === "object" && cause !== null && "exitCode" in cause && typeof cause.exitCode === "number" ? cause.exitCode : void 0;
281
+ return {
282
+ source,
283
+ success: false,
284
+ transactions: [],
285
+ cost: zeroCost(),
286
+ error: {
287
+ message: error.message,
288
+ ...exitCode !== void 0 ? { exitCode } : {}
289
+ },
290
+ speculative
291
+ };
292
+ }
293
+ const blockchainLocks = /* @__PURE__ */ new WeakMap();
294
+ async function withBlockchainLock(blockchain, operation) {
295
+ const previous = blockchainLocks.get(blockchain) ?? Promise.resolve();
296
+ let release = () => {};
297
+ const turn = new Promise((resolve) => {
298
+ release = resolve;
299
+ });
300
+ blockchainLocks.set(blockchain, turn);
301
+ await previous;
302
+ try {
303
+ return await operation();
304
+ } finally {
305
+ release();
306
+ if (blockchainLocks.get(blockchain) === turn) blockchainLocks.delete(blockchain);
307
+ }
308
+ }
309
+ //#endregion
310
+ export { createTonApiSimulationFallback, createTonClient4SandboxSimulation, createTonSandboxSimulation, createTonSimulationWithFallback, messageToCell };
@@ -0,0 +1,33 @@
1
+ import { TonNetwork } from "../core/network.mjs";
2
+ import { TonAddress } from "../core/address.mjs";
3
+ import { Address, Cell } from "@ton/core";
4
+ import { SendTransactionRequestWithMessages } from "@tonconnect/sdk";
5
+ //#region src/transactions/index.d.ts
6
+ export interface TonTransactionMessage {
7
+ readonly to: string | Address | TonAddress;
8
+ readonly value: bigint;
9
+ readonly body?: Cell;
10
+ readonly stateInit?: Cell;
11
+ readonly bounce?: boolean;
12
+ }
13
+ export interface TransactionIntent {
14
+ readonly kind: "ton-transaction";
15
+ readonly id: string;
16
+ readonly validUntil: number;
17
+ readonly messages: readonly TonTransactionMessage[];
18
+ readonly metadata?: Readonly<Record<string, string>>;
19
+ }
20
+ export type TonConnectMessage = SendTransactionRequestWithMessages["messages"][number];
21
+ export type TonConnectTransaction = Pick<SendTransactionRequestWithMessages, "validUntil" | "messages">;
22
+ export declare function createTransactionIntent(input: {
23
+ id: string;
24
+ validUntil: number;
25
+ messages: readonly TonTransactionMessage[];
26
+ metadata?: Readonly<Record<string, string>>;
27
+ }): TransactionIntent;
28
+ export declare function validateTransactionIntent(input: Pick<TransactionIntent, "id" | "validUntil" | "messages">, now?: number): void;
29
+ export declare function toTonConnectTransaction(intent: TransactionIntent, options: {
30
+ network: TonNetwork;
31
+ now?: number;
32
+ }): TonConnectTransaction;
33
+ //#endregion
@@ -0,0 +1,51 @@
1
+ import { invariant } from "../core/errors.mjs";
2
+ import { parseTonAddress, toFriendlyAddress } from "../core/address.mjs";
3
+ import { MAX_TON_COINS } from "../core/amount.mjs";
4
+ import { bytesToBase64 } from "../core/bytes.mjs";
5
+ import { Cell } from "@ton/core";
6
+ //#region src/transactions/index.ts
7
+ function createTransactionIntent(input) {
8
+ validateTransactionIntent(input);
9
+ return Object.freeze({
10
+ kind: "ton-transaction",
11
+ id: input.id,
12
+ validUntil: input.validUntil,
13
+ messages: Object.freeze(input.messages.map((message) => Object.freeze({ ...message }))),
14
+ ...input.metadata ? { metadata: Object.freeze({ ...input.metadata }) } : {}
15
+ });
16
+ }
17
+ function validateTransactionIntent(input, now = Math.floor(Date.now() / 1e3)) {
18
+ invariant(typeof input.id === "string" && input.id.trim().length > 0, "INVALID_TRANSACTION", "Transaction intent id is required");
19
+ invariant(Number.isSafeInteger(now), "INVALID_TRANSACTION", "Current time must be a safe integer");
20
+ invariant(Number.isSafeInteger(input.validUntil), "INVALID_TRANSACTION", "validUntil must be a safe integer");
21
+ invariant(input.validUntil > now, "INVALID_TRANSACTION", "Transaction intent has expired");
22
+ invariant(input.validUntil <= now + 3600, "INVALID_TRANSACTION", "Transaction intent expires too far in the future");
23
+ invariant(Array.isArray(input.messages) && input.messages.length > 0 && input.messages.length <= 4, "INVALID_TRANSACTION", "A transaction must contain between one and four messages");
24
+ for (const message of input.messages) {
25
+ invariant(typeof message === "object" && message !== null, "INVALID_TRANSACTION", "Transaction message must be an object");
26
+ invariant(typeof message.value === "bigint" && message.value >= 0n, "INVALID_TRANSACTION", "Message value must be a non-negative bigint");
27
+ invariant(message.value <= MAX_TON_COINS, "INVALID_TRANSACTION", "Message value is out of range");
28
+ parseTonAddress(message.to);
29
+ invariant(message.body === void 0 || message.body instanceof Cell, "INVALID_TRANSACTION", "Message body must be a TON Cell");
30
+ invariant(message.stateInit === void 0 || message.stateInit instanceof Cell, "INVALID_TRANSACTION", "Message state init must be a TON Cell");
31
+ invariant(message.bounce === void 0 || typeof message.bounce === "boolean", "INVALID_TRANSACTION", "Message bounce flag must be a boolean");
32
+ }
33
+ }
34
+ function toTonConnectTransaction(intent, options) {
35
+ invariant(options.network === "mainnet" || options.network === "testnet", "INVALID_NETWORK", "Unsupported TON network");
36
+ validateTransactionIntent(intent, options.now);
37
+ return {
38
+ validUntil: intent.validUntil,
39
+ messages: intent.messages.map((message) => ({
40
+ address: toFriendlyAddress(message.to, {
41
+ network: options.network,
42
+ bounceable: message.bounce ?? true
43
+ }),
44
+ amount: message.value.toString(),
45
+ ...message.body ? { payload: bytesToBase64(message.body.toBoc()) } : {},
46
+ ...message.stateInit ? { stateInit: bytesToBase64(message.stateInit.toBoc()) } : {}
47
+ }))
48
+ };
49
+ }
50
+ //#endregion
51
+ export { createTransactionIntent, toTonConnectTransaction, validateTransactionIntent };