@anywalletkit/wallet-ton 0.3.0 → 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/{chunk-BLWBC6L2.js → chunk-ZFENRKRW.js} +1 -1
- package/dist/chunk-ZFENRKRW.js.map +1 -0
- package/dist/history.cjs.map +1 -1
- package/dist/history.d.cts +2 -2
- package/dist/history.d.ts +2 -2
- package/dist/history.js +1 -1
- package/dist/index.cjs +92 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -10
- package/dist/index.d.ts +31 -10
- package/dist/index.js +89 -18
- package/dist/index.js.map +1 -1
- package/package.json +8 -7
- package/dist/chunk-BLWBC6L2.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -41,6 +41,7 @@ __export(src_exports, {
|
|
|
41
41
|
WalletAccountReadOnlyTon: () => WalletAccountReadOnlyTon,
|
|
42
42
|
WalletAccountTon: () => WalletAccountTon,
|
|
43
43
|
WalletManagerTon: () => WalletManagerTon,
|
|
44
|
+
canonicalBocCell: () => canonicalBocCell,
|
|
44
45
|
commentCell: () => commentCell,
|
|
45
46
|
createTonClient: () => createTonRpc,
|
|
46
47
|
createTonHistory: () => createTonHistory,
|
|
@@ -58,6 +59,7 @@ __export(src_exports, {
|
|
|
58
59
|
mapTonapiActions: () => mapActions,
|
|
59
60
|
mapTonapiEvent: () => mapTonapiEvent,
|
|
60
61
|
mapToncenterTransaction: () => mapToncenterTransaction,
|
|
62
|
+
messageBody: () => messageBody,
|
|
61
63
|
parseEmulation: () => parseEmulation,
|
|
62
64
|
parseTonapiConsequences: () => parseTonapiConsequences,
|
|
63
65
|
parseTonapiRisk: () => parseTonapiRisk,
|
|
@@ -623,6 +625,7 @@ function parseV5R1Body(body) {
|
|
|
623
625
|
}
|
|
624
626
|
|
|
625
627
|
// src/describe.ts
|
|
628
|
+
var import_buffer4 = require("buffer");
|
|
626
629
|
var import_core6 = require("@ton/core");
|
|
627
630
|
var JETTON_TRANSFER_OP = 260734629;
|
|
628
631
|
var LARGE_FORWARD_NANOTON = 500000000n;
|
|
@@ -682,11 +685,67 @@ function parseTo(to) {
|
|
|
682
685
|
const a = import_core6.Address.parse(to);
|
|
683
686
|
return { to: a.toRawString(), bounceable: true, workchain: a.workChain };
|
|
684
687
|
}
|
|
685
|
-
function
|
|
688
|
+
function canonicalBocCell(b64, what = "bodyBoc") {
|
|
689
|
+
if (!/^[A-Za-z0-9+/_-]+={0,2}$/.test(b64)) throw new UnsafeTransactionError("non-canonical-boc", `${what} is not a base64 string.`);
|
|
690
|
+
const bytes = import_buffer4.Buffer.from(b64, "base64");
|
|
691
|
+
const layout = plainBocLayout(bytes);
|
|
692
|
+
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.`);
|
|
693
|
+
let roots;
|
|
694
|
+
try {
|
|
695
|
+
roots = import_core6.Cell.fromBoc(bytes);
|
|
696
|
+
} catch {
|
|
697
|
+
throw new UnsafeTransactionError("non-canonical-boc", `${what} is not a valid BoC.`);
|
|
698
|
+
}
|
|
699
|
+
if (roots.length !== 1) throw new UnsafeTransactionError("non-canonical-boc", `${what} has ${roots.length} roots.`);
|
|
700
|
+
return roots[0];
|
|
701
|
+
}
|
|
702
|
+
function plainBocLayout(b) {
|
|
703
|
+
if (b.length < 6 || b[0] !== 181 || b[1] !== 238 || b[2] !== 156 || b[3] !== 114) return "not the generic BoC magic";
|
|
704
|
+
const flags = b[4];
|
|
705
|
+
const size = flags & 7;
|
|
706
|
+
const offBytes = b[5];
|
|
707
|
+
if (size < 1 || size > 4 || offBytes < 1 || offBytes > 8) return "bad size fields";
|
|
708
|
+
let i = 6;
|
|
709
|
+
const int = (n) => {
|
|
710
|
+
if (i + n > b.length) throw new RangeError("truncated");
|
|
711
|
+
let v = 0;
|
|
712
|
+
for (let k = 0; k < n; k++) v = v * 256 + b[i++];
|
|
713
|
+
return v;
|
|
714
|
+
};
|
|
715
|
+
try {
|
|
716
|
+
const cells = int(size);
|
|
717
|
+
const roots = int(size);
|
|
718
|
+
const absent = int(size);
|
|
719
|
+
int(offBytes);
|
|
720
|
+
if (roots !== 1) return `${roots} roots`;
|
|
721
|
+
if (absent !== 0) return "absent cells";
|
|
722
|
+
i += roots * size;
|
|
723
|
+
if (flags & 128) i += cells * offBytes;
|
|
724
|
+
for (let c = 0; c < cells; c++) {
|
|
725
|
+
if (i + 2 > b.length) return "truncated";
|
|
726
|
+
const d1 = b[i++];
|
|
727
|
+
const d2 = b[i++];
|
|
728
|
+
if (d1 & 16) return "a cell stores its hashes";
|
|
729
|
+
if (d1 >> 5 !== 0) return "a cell has a level mask";
|
|
730
|
+
if (d1 & 8) return "an exotic cell";
|
|
731
|
+
if ((d1 & 7) > 4) return "a cell with more than 4 refs";
|
|
732
|
+
i += Math.ceil(d2 / 2) + (d1 & 7) * size;
|
|
733
|
+
}
|
|
734
|
+
if (i + (flags & 64 ? 4 : 0) !== b.length) return "trailing or missing bytes";
|
|
735
|
+
} catch {
|
|
736
|
+
return "truncated";
|
|
737
|
+
}
|
|
738
|
+
return null;
|
|
739
|
+
}
|
|
740
|
+
function messageBody(tx) {
|
|
686
741
|
if (tx.body instanceof import_core6.Cell) return tx.body;
|
|
687
742
|
if (typeof tx.body === "string") return tx.body === "" ? void 0 : commentCell(tx.body);
|
|
688
|
-
if (tx.
|
|
689
|
-
|
|
743
|
+
if (tx.body !== void 0) throw new UnsafeTransactionError("body", "A message body must be a Cell or a string (a text comment).");
|
|
744
|
+
if (tx.bodyBoc !== void 0 && typeof tx.bodyBoc !== "string") throw new UnsafeTransactionError("body", "bodyBoc must be a base64 string.");
|
|
745
|
+
return tx.bodyBoc ? canonicalBocCell(tx.bodyBoc) : void 0;
|
|
746
|
+
}
|
|
747
|
+
function bodyOf(tx) {
|
|
748
|
+
return messageBody(tx);
|
|
690
749
|
}
|
|
691
750
|
function commentCell(text) {
|
|
692
751
|
return (0, import_core6.beginCell)().storeUint(0, 32).storeStringTail(text).endCell();
|
|
@@ -792,6 +851,8 @@ var import_ed25519 = require("@noble/curves/ed25519.js");
|
|
|
792
851
|
var import_core8 = require("@ton/core");
|
|
793
852
|
var JETTON_TRANSFER_OP2 = 260734629;
|
|
794
853
|
var DEFAULT_JETTON_ATTACHED = 50000000n;
|
|
854
|
+
var DEFAULT_MAX_JETTON_ATTACHED = 1000000000n;
|
|
855
|
+
var RAW_ADDRESS = /^-?\d+:[0-9a-fA-F]{64}$/;
|
|
795
856
|
var DEFAULT_INDEXER = "https://toncenter.com/api/v3";
|
|
796
857
|
var DEFAULT_VALID_SECONDS = 60;
|
|
797
858
|
var MAX_VALID_SECONDS = 600;
|
|
@@ -893,13 +954,15 @@ var WalletAccountReadOnlyTon = class {
|
|
|
893
954
|
let address;
|
|
894
955
|
let bounceable = true;
|
|
895
956
|
let testOnly;
|
|
896
|
-
if (import_core8.Address.isFriendly(to)) {
|
|
957
|
+
if (typeof to === "string" && import_core8.Address.isFriendly(to)) {
|
|
897
958
|
const f = import_core8.Address.parseFriendly(to);
|
|
898
959
|
address = f.address;
|
|
899
960
|
bounceable = f.isBounceable;
|
|
900
961
|
testOnly = f.isTestOnly;
|
|
901
|
-
} else {
|
|
962
|
+
} else if (typeof to === "string" && RAW_ADDRESS.test(to)) {
|
|
902
963
|
address = import_core8.Address.parse(to);
|
|
964
|
+
} else {
|
|
965
|
+
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).`);
|
|
903
966
|
}
|
|
904
967
|
if (address.workChain !== 0 && address.workChain !== -1) throw new UnsafeTransactionError("exotic-workchain", `Refusing to send to workchain ${address.workChain}.`);
|
|
905
968
|
const testnet = this._config.network === "testnet";
|
|
@@ -912,7 +975,7 @@ var WalletAccountReadOnlyTon = class {
|
|
|
912
975
|
const value = big(tx.value);
|
|
913
976
|
if (value <= 0n) throw new UnsafeTransactionError("zero-value", "TON message value must be positive.");
|
|
914
977
|
const { address, bounceable } = this.checkedAddress(tx.to);
|
|
915
|
-
const body =
|
|
978
|
+
const body = messageBody(tx);
|
|
916
979
|
const init = this.stateInitOf(tx.stateInit);
|
|
917
980
|
const message = (0, import_core8.internal)({ to: address, value, bounce: tx.bounceable ?? bounceable, ...body ? { body } : {}, ...init ? { init } : {} });
|
|
918
981
|
return { message, ...tx.sendMode !== void 0 ? { mode: tx.sendMode } : {} };
|
|
@@ -922,14 +985,22 @@ var WalletAccountReadOnlyTon = class {
|
|
|
922
985
|
if (amount <= 0n) throw new UnsafeTransactionError("zero-value", "Jetton amount must be positive.");
|
|
923
986
|
const recipient = this.checkedAddress(o.recipient).address;
|
|
924
987
|
const response = o.responseDestination ? this.checkedAddress(o.responseDestination).address : void 0;
|
|
988
|
+
if (response && !response.equals(this._address) && o.allowForeignResponseDestination !== true) {
|
|
989
|
+
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.`);
|
|
990
|
+
}
|
|
991
|
+
const forwardTon = o.forwardTonAmount !== void 0 ? big(o.forwardTonAmount) : 1n;
|
|
992
|
+
const attached = o.attachedValue !== void 0 ? big(o.attachedValue) : (this._config.jettonAttachedValue !== void 0 ? big(this._config.jettonAttachedValue) : DEFAULT_JETTON_ATTACHED) + forwardTon;
|
|
993
|
+
const maxAttached = this._config.maxJettonAttachedValue !== void 0 ? big(this._config.maxJettonAttachedValue) : DEFAULT_MAX_JETTON_ATTACHED;
|
|
994
|
+
if (attached > maxAttached || forwardTon > attached) {
|
|
995
|
+
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.`);
|
|
996
|
+
}
|
|
925
997
|
const jw = await this.getJettonWalletAddress(o.token);
|
|
926
998
|
await this.jettonWalletData(o.token, jw);
|
|
927
|
-
const forwardTonAmount =
|
|
999
|
+
const forwardTonAmount = forwardTon;
|
|
928
1000
|
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.");
|
|
929
1001
|
const payload = o.forwardPayload ?? o.memo;
|
|
930
1002
|
const forwardPayload = payload === void 0 ? null : typeof payload === "string" ? commentCell(payload) : payload;
|
|
931
1003
|
const body = (0, import_core8.beginCell)().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();
|
|
932
|
-
const attached = o.attachedValue !== void 0 ? big(o.attachedValue) : (this._config.jettonAttachedValue !== void 0 ? big(this._config.jettonAttachedValue) : DEFAULT_JETTON_ATTACHED) + forwardTonAmount;
|
|
933
1004
|
return { message: (0, import_core8.internal)({ to: jw, value: attached, bounce: true, body }) };
|
|
934
1005
|
}
|
|
935
1006
|
toMessages(tx) {
|
|
@@ -1046,12 +1117,12 @@ function randomQueryId() {
|
|
|
1046
1117
|
|
|
1047
1118
|
// src/account.ts
|
|
1048
1119
|
var import_core9 = require("@anywalletkit/core");
|
|
1049
|
-
var
|
|
1120
|
+
var import_buffer6 = require("buffer");
|
|
1050
1121
|
var import_core10 = require("@ton/core");
|
|
1051
1122
|
|
|
1052
1123
|
// src/tonconnect.ts
|
|
1053
1124
|
var import_sha2 = require("@noble/hashes/sha2.js");
|
|
1054
|
-
var
|
|
1125
|
+
var import_buffer5 = require("buffer");
|
|
1055
1126
|
var utf82 = (s) => new TextEncoder().encode(s);
|
|
1056
1127
|
var int32BE = (n) => {
|
|
1057
1128
|
const b = new Uint8Array(4);
|
|
@@ -1086,7 +1157,7 @@ function checkCommon(address, domain, timestamp) {
|
|
|
1086
1157
|
function base64Bytes(raw) {
|
|
1087
1158
|
const s = raw.replace(/[\t\n\f\r ]/g, "");
|
|
1088
1159
|
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(s) || s.replace(/=+$/, "").length % 4 === 1) throw new TypeError("signData binary payload must be base64.");
|
|
1089
|
-
return new Uint8Array(
|
|
1160
|
+
return new Uint8Array(import_buffer5.Buffer.from(s, "base64"));
|
|
1090
1161
|
}
|
|
1091
1162
|
function tonProofDigest(address, request) {
|
|
1092
1163
|
checkCommon(address, request.domain, request.timestamp);
|
|
@@ -1163,7 +1234,7 @@ var WalletAccountTon = class _WalletAccountTon extends WalletAccountReadOnlyTon
|
|
|
1163
1234
|
timestamp: request.timestamp,
|
|
1164
1235
|
domain: { lengthBytes: new TextEncoder().encode(request.domain).length, value: request.domain },
|
|
1165
1236
|
payload: request.payload,
|
|
1166
|
-
signature:
|
|
1237
|
+
signature: import_buffer6.Buffer.from(signature).toString("base64")
|
|
1167
1238
|
};
|
|
1168
1239
|
}
|
|
1169
1240
|
/** TON Connect `signData` (text / binary) for this wallet's address: the reply the dApp gets. */
|
|
@@ -1171,7 +1242,7 @@ var WalletAccountTon = class _WalletAccountTon extends WalletAccountReadOnlyTon
|
|
|
1171
1242
|
const digest = tonSignDataDigest(this._address, request);
|
|
1172
1243
|
const signature = await this.signer.sign(digest, { scheme: "ed25519", context: "ton-sign-data" });
|
|
1173
1244
|
return {
|
|
1174
|
-
signature:
|
|
1245
|
+
signature: import_buffer6.Buffer.from(signature).toString("base64"),
|
|
1175
1246
|
address: this._address.toRawString(),
|
|
1176
1247
|
timestamp: request.timestamp,
|
|
1177
1248
|
domain: request.domain,
|
|
@@ -1199,7 +1270,7 @@ var WalletAccountTon = class _WalletAccountTon extends WalletAccountReadOnlyTon
|
|
|
1199
1270
|
bodyModes(body) {
|
|
1200
1271
|
return parseV5R1Body(body)?.messages.map((m) => m.mode) ?? [];
|
|
1201
1272
|
}
|
|
1202
|
-
async signMessages(messages, limit, op) {
|
|
1273
|
+
async #signMessages(messages, limit, op) {
|
|
1203
1274
|
this.assertNoDrain(messages.map((m) => sendModeOf(m.mode)));
|
|
1204
1275
|
const want = messages.reduce((sum, m) => sum + (m.message.info.type === "internal" ? m.message.info.value.coins : 0n), 0n);
|
|
1205
1276
|
if (want > 0n) {
|
|
@@ -1236,7 +1307,7 @@ var WalletAccountTon = class _WalletAccountTon extends WalletAccountReadOnlyTon
|
|
|
1236
1307
|
await this.preflight(tx, (0, import_core9.feeLimit)(this._config.transactionMaxFee, options), "transaction");
|
|
1237
1308
|
return tx.toBoc().toString("base64");
|
|
1238
1309
|
}
|
|
1239
|
-
const { body } = await this
|
|
1310
|
+
const { body } = await this.#signMessages(this.toMessages(tx), (0, import_core9.feeLimit)(this._config.transactionMaxFee, options), "transaction");
|
|
1240
1311
|
return body.toBoc().toString("base64");
|
|
1241
1312
|
}
|
|
1242
1313
|
async broadcast(body) {
|
|
@@ -1255,14 +1326,14 @@ var WalletAccountTon = class _WalletAccountTon extends WalletAccountReadOnlyTon
|
|
|
1255
1326
|
async sendTransaction(tx, options = {}) {
|
|
1256
1327
|
this.requireRpc("send transactions");
|
|
1257
1328
|
if (tx instanceof import_core10.Cell) this.assertNoDrain(this.bodyModes(tx));
|
|
1258
|
-
const { body, fee } = tx instanceof import_core10.Cell ? { body: tx, fee: await this.preflight(tx, (0, import_core9.feeLimit)(this._config.transactionMaxFee, options), "transaction") } : await this
|
|
1329
|
+
const { body, fee } = tx instanceof import_core10.Cell ? { body: tx, fee: await this.preflight(tx, (0, import_core9.feeLimit)(this._config.transactionMaxFee, options), "transaction") } : await this.#signMessages(this.toMessages(tx), (0, import_core9.feeLimit)(this._config.transactionMaxFee, options), "transaction");
|
|
1259
1330
|
return { hash: await this.broadcast(body), fee };
|
|
1260
1331
|
}
|
|
1261
1332
|
/** TON (no `token`) or jetton transfer. */
|
|
1262
1333
|
async transfer(o, writeOptions = {}) {
|
|
1263
1334
|
this.requireRpc("transfer tokens");
|
|
1264
1335
|
const message = o.token ? await this.jettonTransferMessage(o) : this.transactionMessage({ to: o.recipient, value: o.amount, ...o.memo !== void 0 ? { body: o.memo } : {} });
|
|
1265
|
-
const { body, fee } = await this
|
|
1336
|
+
const { body, fee } = await this.#signMessages([message], (0, import_core9.feeLimit)(this._config.transferMaxFee, writeOptions), "transfer");
|
|
1266
1337
|
return { hash: await this.broadcast(body), fee };
|
|
1267
1338
|
}
|
|
1268
1339
|
/** The same wallet as a {@link WalletAccountReadOnlyTon}. */
|
|
@@ -1359,7 +1430,7 @@ var WalletManagerTon = class _WalletManagerTon extends import_core11.WalletManag
|
|
|
1359
1430
|
|
|
1360
1431
|
// src/history.ts
|
|
1361
1432
|
var import_core12 = require("@ton/core");
|
|
1362
|
-
var
|
|
1433
|
+
var import_buffer7 = require("buffer");
|
|
1363
1434
|
var HistoryUnavailableError = class extends Error {
|
|
1364
1435
|
chain;
|
|
1365
1436
|
reason;
|
|
@@ -1376,12 +1447,12 @@ var DEFAULT_LIMIT = 25;
|
|
|
1376
1447
|
var MAX_LIMIT = 100;
|
|
1377
1448
|
var DEFAULT_TIMEOUT_MS3 = 15e3;
|
|
1378
1449
|
function encodeCursor(c) {
|
|
1379
|
-
return
|
|
1450
|
+
return import_buffer7.Buffer.from(JSON.stringify(c), "utf8").toString("base64");
|
|
1380
1451
|
}
|
|
1381
1452
|
function decodeCursor(s) {
|
|
1382
1453
|
let parsed;
|
|
1383
1454
|
try {
|
|
1384
|
-
parsed = JSON.parse(
|
|
1455
|
+
parsed = JSON.parse(import_buffer7.Buffer.from(s, "base64").toString("utf8"));
|
|
1385
1456
|
} catch {
|
|
1386
1457
|
throw new Error("@anywalletkit/wallet-ton: malformed history cursor");
|
|
1387
1458
|
}
|
|
@@ -1633,7 +1704,7 @@ function mapTonapiEvent(chain, address, own, event, valueFlow) {
|
|
|
1633
1704
|
var TEXT_COMMENT_OP = "0x00000000";
|
|
1634
1705
|
function mapToncenterTransaction(chain, address, row) {
|
|
1635
1706
|
const own = row.account.toLowerCase();
|
|
1636
|
-
const hash =
|
|
1707
|
+
const hash = import_buffer7.Buffer.from(row.hash, "base64").toString("hex");
|
|
1637
1708
|
const d = row.description;
|
|
1638
1709
|
const failed = d?.aborted === true || d?.compute_ph?.skipped !== true && d?.compute_ph?.success === false || d?.action?.success === false;
|
|
1639
1710
|
const transfers = [];
|