@pizzaton/ton 0.0.0-stage → 0.1.1
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/CONTRACTS.md +239 -0
- package/README.md +505 -2
- package/dist/airdrop/index.d.mts +18 -0
- package/dist/airdrop/index.mjs +86 -0
- package/dist/connect/errors.d.mts +4 -0
- package/dist/connect/errors.mjs +21 -0
- package/dist/connect/index.d.mts +23 -0
- package/dist/connect/index.mjs +34 -0
- package/dist/contracts/catalog/index.d.mts +361 -0
- package/dist/contracts/catalog/index.mjs +403 -0
- package/dist/contracts/client.d.mts +18 -0
- package/dist/contracts/client.mjs +31 -0
- package/dist/contracts/codecs.d.mts +14 -0
- package/dist/contracts/codecs.mjs +61 -0
- package/dist/contracts/hipo.d.mts +138 -0
- package/dist/contracts/hipo.mjs +198 -0
- package/dist/contracts/index.d.mts +23 -0
- package/dist/contracts/index.mjs +20 -0
- package/dist/contracts/metadata.d.mts +38 -0
- package/dist/contracts/metadata.mjs +50 -0
- package/dist/contracts/module-client.d.mts +20 -0
- package/dist/contracts/module-client.mjs +34 -0
- package/dist/contracts/module.d.mts +8 -0
- package/dist/contracts/module.mjs +11 -0
- package/dist/contracts/wrappers/base.d.mts +18 -0
- package/dist/contracts/wrappers/base.mjs +31 -0
- package/dist/contracts/wrappers/index.d.mts +12 -0
- package/dist/contracts/wrappers/index.mjs +12 -0
- package/dist/contracts/wrappers/jvault-protocols.d.mts +206 -0
- package/dist/contracts/wrappers/jvault-protocols.mjs +432 -0
- package/dist/contracts/wrappers/jvault-support.d.mts +135 -0
- package/dist/contracts/wrappers/jvault-support.mjs +269 -0
- package/dist/contracts/wrappers/jvault.d.mts +123 -0
- package/dist/contracts/wrappers/jvault.mjs +258 -0
- package/dist/contracts/wrappers/memeland.d.mts +253 -0
- package/dist/contracts/wrappers/memeland.mjs +396 -0
- package/dist/contracts/wrappers/multix.d.mts +92 -0
- package/dist/contracts/wrappers/multix.mjs +156 -0
- package/dist/contracts/wrappers/pizzabox.d.mts +66 -0
- package/dist/contracts/wrappers/pizzabox.mjs +105 -0
- package/dist/contracts/wrappers/ton-raffles.d.mts +215 -0
- package/dist/contracts/wrappers/ton-raffles.mjs +398 -0
- package/dist/contracts/wrappers/tonresistor.d.mts +189 -0
- package/dist/contracts/wrappers/tonresistor.mjs +276 -0
- package/dist/core/address.d.mts +31 -0
- package/dist/core/address.mjs +53 -0
- package/dist/core/amount.d.mts +8 -0
- package/dist/core/amount.mjs +34 -0
- package/dist/core/bytes.d.mts +5 -0
- package/dist/core/bytes.mjs +18 -0
- package/dist/core/constants.d.mts +14 -0
- package/dist/core/constants.mjs +15 -0
- package/dist/core/errors.d.mts +9 -0
- package/dist/core/errors.mjs +16 -0
- package/dist/core/http.mjs +39 -0
- package/dist/core/index.d.mts +8 -0
- package/dist/core/index.mjs +8 -0
- package/dist/core/metadata.d.mts +12 -0
- package/dist/core/metadata.mjs +35 -0
- package/dist/core/network.d.mts +24 -0
- package/dist/core/network.mjs +41 -0
- package/dist/emulator/index.d.mts +20 -0
- package/dist/emulator/index.mjs +24 -0
- package/dist/index.d.mts +21 -0
- package/dist/index.mjs +19 -0
- package/dist/indexer/index.d.mts +90 -0
- package/dist/indexer/index.mjs +279 -0
- package/dist/jetton/details.d.mts +27 -0
- package/dist/jetton/details.mjs +116 -0
- package/dist/jetton/index.d.mts +54 -0
- package/dist/jetton/index.mjs +92 -0
- package/dist/jetton/versions.d.mts +12 -0
- package/dist/jetton/versions.mjs +50 -0
- package/dist/nft/collection.d.mts +57 -0
- package/dist/nft/collection.mjs +148 -0
- package/dist/nft/content.d.mts +34 -0
- package/dist/nft/content.mjs +142 -0
- package/dist/nft/index.d.mts +35 -0
- package/dist/nft/index.mjs +51 -0
- package/dist/nft/versions.d.mts +11 -0
- package/dist/nft/versions.mjs +29 -0
- package/dist/proof/index.d.mts +62 -0
- package/dist/proof/index.mjs +227 -0
- package/dist/provider/index.d.mts +32 -0
- package/dist/provider/index.mjs +1 -0
- package/dist/react/index.d.mts +13 -0
- package/dist/react/index.mjs +48 -0
- package/dist/server/index.d.mts +11 -0
- package/dist/server/index.mjs +55 -0
- package/dist/simulation/index.d.mts +112 -0
- package/dist/simulation/index.mjs +310 -0
- package/dist/transactions/index.d.mts +33 -0
- package/dist/transactions/index.mjs +51 -0
- package/dist/vesting/index.d.mts +12 -0
- package/dist/vesting/index.mjs +25 -0
- package/dist/wallet/index.d.mts +23 -0
- package/dist/wallet/index.mjs +71 -0
- package/package.json +176 -5
|
@@ -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 };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/vesting/index.d.ts
|
|
2
|
+
export interface VestingSchedule {
|
|
3
|
+
readonly totalAmount: bigint;
|
|
4
|
+
readonly startTime: number;
|
|
5
|
+
readonly cliffDuration: number;
|
|
6
|
+
readonly duration: number;
|
|
7
|
+
readonly now?: number;
|
|
8
|
+
}
|
|
9
|
+
export declare function validateVestingSchedule(schedule: VestingSchedule): void;
|
|
10
|
+
export declare function unlockedAmount(schedule: VestingSchedule, at?: number): bigint;
|
|
11
|
+
export declare function claimableAmount(schedule: VestingSchedule, releasedAmount: bigint, at?: number): bigint;
|
|
12
|
+
//#endregion
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { invariant } from "../core/errors.mjs";
|
|
2
|
+
//#region src/vesting/index.ts
|
|
3
|
+
function validateVestingSchedule(schedule) {
|
|
4
|
+
invariant(schedule.totalAmount >= 0n, "INVALID_SCHEDULE", "Total vesting amount cannot be negative");
|
|
5
|
+
invariant(Number.isSafeInteger(schedule.startTime), "INVALID_SCHEDULE", "Start time must be a safe integer");
|
|
6
|
+
if (schedule.now !== void 0) invariant(Number.isSafeInteger(schedule.now), "INVALID_SCHEDULE", "Current time must be a safe integer");
|
|
7
|
+
invariant(Number.isSafeInteger(schedule.cliffDuration) && schedule.cliffDuration >= 0, "INVALID_SCHEDULE", "Cliff duration is invalid");
|
|
8
|
+
invariant(Number.isSafeInteger(schedule.duration) && schedule.duration > 0, "INVALID_SCHEDULE", "Vesting duration must be positive");
|
|
9
|
+
invariant(schedule.cliffDuration <= schedule.duration, "INVALID_SCHEDULE", "Cliff cannot exceed vesting duration");
|
|
10
|
+
invariant(Number.isSafeInteger(schedule.startTime + schedule.duration), "INVALID_SCHEDULE", "Vesting schedule end time is out of range");
|
|
11
|
+
}
|
|
12
|
+
function unlockedAmount(schedule, at = schedule.now ?? Math.floor(Date.now() / 1e3)) {
|
|
13
|
+
validateVestingSchedule(schedule);
|
|
14
|
+
invariant(Number.isSafeInteger(at), "INVALID_SCHEDULE", "Calculation time must be a safe integer");
|
|
15
|
+
if (at < schedule.startTime + schedule.cliffDuration) return 0n;
|
|
16
|
+
const elapsed = Math.min(at - schedule.startTime, schedule.duration);
|
|
17
|
+
return schedule.totalAmount * BigInt(elapsed) / BigInt(schedule.duration);
|
|
18
|
+
}
|
|
19
|
+
function claimableAmount(schedule, releasedAmount, at) {
|
|
20
|
+
invariant(releasedAmount >= 0n && releasedAmount <= schedule.totalAmount, "INVALID_SCHEDULE", "Released amount is out of range");
|
|
21
|
+
const claimable = unlockedAmount(schedule, at) - releasedAmount;
|
|
22
|
+
return claimable > 0n ? claimable : 0n;
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
export { claimableAmount, unlockedAmount, validateVestingSchedule };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Address, Contract, ContractProvider, StateInit } from "@ton/core";
|
|
2
|
+
import { WalletContractV1R1, WalletContractV1R2, WalletContractV1R3, WalletContractV2R1, WalletContractV2R2, WalletContractV3R1, WalletContractV3R2, WalletContractV4, WalletContractV5Beta, WalletContractV5R1 } from "@ton/ton";
|
|
3
|
+
//#region src/wallet/index.d.ts
|
|
4
|
+
export declare const TON_WALLET_VERSIONS: readonly ["v1r1", "v1r2", "v1r3", "v2r1", "v2r2", "v3r1", "v3r2", "v4", "v5beta", "v5r1"];
|
|
5
|
+
export type TonWalletVersion = (typeof TON_WALLET_VERSIONS)[number];
|
|
6
|
+
export declare const DEFAULT_TON_WALLET_VERSION: TonWalletVersion;
|
|
7
|
+
export interface TonWalletContract extends Contract {
|
|
8
|
+
readonly address: Address;
|
|
9
|
+
readonly init: StateInit;
|
|
10
|
+
readonly publicKey: Buffer;
|
|
11
|
+
getBalance(provider: ContractProvider): Promise<bigint>;
|
|
12
|
+
getSeqno(provider: ContractProvider): Promise<number>;
|
|
13
|
+
}
|
|
14
|
+
export interface TonWalletFactoryOptions {
|
|
15
|
+
readonly version?: TonWalletVersion;
|
|
16
|
+
readonly workchain?: number;
|
|
17
|
+
readonly publicKey: Buffer;
|
|
18
|
+
readonly walletId?: number;
|
|
19
|
+
readonly networkGlobalId?: -239 | -3;
|
|
20
|
+
}
|
|
21
|
+
export declare function createTonWalletContract(options: TonWalletFactoryOptions): TonWalletContract;
|
|
22
|
+
//#endregion
|
|
23
|
+
export { WalletContractV1R1, WalletContractV1R2, WalletContractV1R3, WalletContractV2R1, WalletContractV2R2, WalletContractV3R1, WalletContractV3R2, WalletContractV4, WalletContractV5Beta, WalletContractV5R1 };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { WalletContractV1R1, WalletContractV1R1 as WalletContractV1R1$1, WalletContractV1R2, WalletContractV1R2 as WalletContractV1R2$1, WalletContractV1R3, WalletContractV1R3 as WalletContractV1R3$1, WalletContractV2R1, WalletContractV2R1 as WalletContractV2R1$1, WalletContractV2R2, WalletContractV2R2 as WalletContractV2R2$1, WalletContractV3R1, WalletContractV3R1 as WalletContractV3R1$1, WalletContractV3R2, WalletContractV3R2 as WalletContractV3R2$1, WalletContractV4, WalletContractV4 as WalletContractV4$1, WalletContractV5Beta, WalletContractV5Beta as WalletContractV5Beta$1, WalletContractV5R1, WalletContractV5R1 as WalletContractV5R1$1 } from "@ton/ton";
|
|
2
|
+
//#region src/wallet/index.ts
|
|
3
|
+
const TON_WALLET_VERSIONS = [
|
|
4
|
+
"v1r1",
|
|
5
|
+
"v1r2",
|
|
6
|
+
"v1r3",
|
|
7
|
+
"v2r1",
|
|
8
|
+
"v2r2",
|
|
9
|
+
"v3r1",
|
|
10
|
+
"v3r2",
|
|
11
|
+
"v4",
|
|
12
|
+
"v5beta",
|
|
13
|
+
"v5r1"
|
|
14
|
+
];
|
|
15
|
+
const DEFAULT_TON_WALLET_VERSION = "v5r1";
|
|
16
|
+
function createTonWalletContract(options) {
|
|
17
|
+
const workchain = options.workchain ?? 0;
|
|
18
|
+
const publicKey = Buffer.from(options.publicKey);
|
|
19
|
+
if (publicKey.length !== 32) throw new Error("TON wallet public keys must be exactly 32 bytes");
|
|
20
|
+
switch (options.version ?? "v5r1") {
|
|
21
|
+
case "v1r1": return WalletContractV1R1$1.create({
|
|
22
|
+
workchain,
|
|
23
|
+
publicKey
|
|
24
|
+
});
|
|
25
|
+
case "v1r2": return WalletContractV1R2$1.create({
|
|
26
|
+
workchain,
|
|
27
|
+
publicKey
|
|
28
|
+
});
|
|
29
|
+
case "v1r3": return WalletContractV1R3$1.create({
|
|
30
|
+
workchain,
|
|
31
|
+
publicKey
|
|
32
|
+
});
|
|
33
|
+
case "v2r1": return WalletContractV2R1$1.create({
|
|
34
|
+
workchain,
|
|
35
|
+
publicKey
|
|
36
|
+
});
|
|
37
|
+
case "v2r2": return WalletContractV2R2$1.create({
|
|
38
|
+
workchain,
|
|
39
|
+
publicKey
|
|
40
|
+
});
|
|
41
|
+
case "v3r1": return WalletContractV3R1$1.create({
|
|
42
|
+
workchain,
|
|
43
|
+
publicKey,
|
|
44
|
+
walletId: options.walletId
|
|
45
|
+
});
|
|
46
|
+
case "v3r2": return WalletContractV3R2$1.create({
|
|
47
|
+
workchain,
|
|
48
|
+
publicKey,
|
|
49
|
+
walletId: options.walletId
|
|
50
|
+
});
|
|
51
|
+
case "v4": return WalletContractV4$1.create({
|
|
52
|
+
workchain,
|
|
53
|
+
publicKey,
|
|
54
|
+
walletId: options.walletId
|
|
55
|
+
});
|
|
56
|
+
case "v5beta": return WalletContractV5Beta$1.create({ publicKey });
|
|
57
|
+
case "v5r1": return WalletContractV5R1$1.create({
|
|
58
|
+
publicKey,
|
|
59
|
+
walletId: {
|
|
60
|
+
networkGlobalId: options.networkGlobalId ?? -239,
|
|
61
|
+
context: {
|
|
62
|
+
walletVersion: "v5r1",
|
|
63
|
+
workchain,
|
|
64
|
+
subwalletNumber: options.walletId ?? 0
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
//#endregion
|
|
71
|
+
export { DEFAULT_TON_WALLET_VERSION, TON_WALLET_VERSIONS, WalletContractV1R1, WalletContractV1R2, WalletContractV1R3, WalletContractV2R1, WalletContractV2R2, WalletContractV3R1, WalletContractV3R2, WalletContractV4, WalletContractV5Beta, WalletContractV5R1, createTonWalletContract };
|