teleton 0.7.2 → 0.7.4
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/README.md +31 -12
- package/dist/{chunk-ND2X5FWB.js → chunk-5PLZ3KSO.js} +16 -3
- package/dist/{chunk-NERLQY2H.js → chunk-BGC2IUM5.js} +73 -15
- package/dist/{chunk-FNV5FF35.js → chunk-EK7M5K26.js} +29 -13
- package/dist/chunk-JQDLW7IE.js +107 -0
- package/dist/{chunk-VSMUAU5X.js → chunk-LAQOUFOJ.js} +2419 -2132
- package/dist/chunk-QOQWUUA4.js +158 -0
- package/dist/{chunk-LRCPA7SC.js → chunk-RMLQS3X6.js} +15 -3
- package/dist/{chunk-UDD7FYOU.js → chunk-WIKM24GZ.js} +1 -18
- package/dist/{chunk-RBU6JXD3.js → chunk-XDYDA2KV.js} +1 -1
- package/dist/{chunk-JHKWHGBM.js → chunk-YFG2QHLA.js} +380 -47
- package/dist/cli/index.js +216 -272
- package/dist/{client-3VWE7NC4.js → client-RTNALK7W.js} +3 -2
- package/dist/{get-my-gifts-RI7FAXAL.js → get-my-gifts-TPVUGUWT.js} +1 -1
- package/dist/index.js +9 -10
- package/dist/{memory-5SS3Q5EA.js → memory-JQZ6MTRU.js} +2 -2
- package/dist/{migrate-M7SJMDOL.js → migrate-GS5ACQDA.js} +2 -2
- package/dist/{server-NPSODUMA.js → server-TCJOBV3D.js} +292 -11
- package/dist/{setup-server-C7ZTPHD5.js → setup-server-YHYJLAMA.js} +77 -112
- package/dist/{tool-index-MIVK3D7H.js → tool-index-6HBRVXVG.js} +1 -1
- package/dist/web/assets/index-B6M9knfJ.css +1 -0
- package/dist/web/assets/index-DAGeQfVZ.js +72 -0
- package/dist/web/assets/{index.es-D81xLR29.js → index.es-CqZHj0tz.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +2 -2
- package/dist/chunk-EHEV7FJ7.js +0 -157
- package/dist/chunk-QUAPFI2N.js +0 -42
- package/dist/endpoint-FLYNEZ2F.js +0 -7
- package/dist/format-transactions-FD74HI5N.js +0 -9
- package/dist/web/assets/index-BqwoDycr.js +0 -72
- package/dist/web/assets/index-CRDIf07k.css +0 -1
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ConfigSchema,
|
|
3
|
+
getCachedTonClient,
|
|
3
4
|
getKeyPair,
|
|
4
5
|
getTonPrice,
|
|
5
6
|
getWalletAddress,
|
|
6
7
|
getWalletBalance,
|
|
8
|
+
invalidateTonClientCache,
|
|
7
9
|
loadWallet
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import {
|
|
10
|
-
getCachedHttpEndpoint
|
|
11
|
-
} from "./chunk-QUAPFI2N.js";
|
|
10
|
+
} from "./chunk-BGC2IUM5.js";
|
|
12
11
|
import {
|
|
13
12
|
require_BigInteger
|
|
14
13
|
} from "./chunk-TSKJCWQQ.js";
|
|
@@ -17,7 +16,7 @@ import {
|
|
|
17
16
|
} from "./chunk-XBE4JB7C.js";
|
|
18
17
|
import {
|
|
19
18
|
getProviderMetadata
|
|
20
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-RMLQS3X6.js";
|
|
21
20
|
import {
|
|
22
21
|
createDbWrapper,
|
|
23
22
|
migrateFromMainDb,
|
|
@@ -92,13 +91,12 @@ Run 'teleton setup' to create one.`);
|
|
|
92
91
|
}
|
|
93
92
|
const config = result.data;
|
|
94
93
|
const provider = config.agent.provider;
|
|
95
|
-
if (provider !== "anthropic" && !raw.agent?.model) {
|
|
94
|
+
if (provider !== "anthropic" && provider !== "claude-code" && !raw.agent?.model) {
|
|
96
95
|
const meta = getProviderMetadata(provider);
|
|
97
96
|
config.agent.model = meta.defaultModel;
|
|
98
97
|
}
|
|
99
98
|
config.telegram.session_path = expandPath(config.telegram.session_path);
|
|
100
99
|
config.storage.sessions_file = expandPath(config.storage.sessions_file);
|
|
101
|
-
config.storage.pairing_file = expandPath(config.storage.pairing_file);
|
|
102
100
|
config.storage.memory_file = expandPath(config.storage.memory_file);
|
|
103
101
|
if (process.env.TELETON_API_KEY) {
|
|
104
102
|
config.agent.api_key = process.env.TELETON_API_KEY;
|
|
@@ -657,7 +655,7 @@ var PluginSDKError = class extends Error {
|
|
|
657
655
|
var SDK_VERSION = "1.0.0";
|
|
658
656
|
|
|
659
657
|
// src/ton/transfer.ts
|
|
660
|
-
import { WalletContractV5R1,
|
|
658
|
+
import { WalletContractV5R1, toNano, internal } from "@ton/ton";
|
|
661
659
|
import { Address, SendMode } from "@ton/core";
|
|
662
660
|
|
|
663
661
|
// src/ton/tx-lock.ts
|
|
@@ -699,8 +697,7 @@ async function sendTon(params) {
|
|
|
699
697
|
workchain: 0,
|
|
700
698
|
publicKey: keyPair.publicKey
|
|
701
699
|
});
|
|
702
|
-
const
|
|
703
|
-
const client = new TonClient({ endpoint });
|
|
700
|
+
const client = await getCachedTonClient();
|
|
704
701
|
const contract = client.open(wallet);
|
|
705
702
|
const seqno = await contract.getSeqno();
|
|
706
703
|
await contract.sendTransfer({
|
|
@@ -720,8 +717,11 @@ async function sendTon(params) {
|
|
|
720
717
|
log4.info(`Sent ${amount} TON to ${toAddress.slice(0, 8)}... - seqno: ${seqno}`);
|
|
721
718
|
return pseudoHash;
|
|
722
719
|
} catch (error) {
|
|
720
|
+
if (error?.status >= 500 || error?.response?.status >= 500) {
|
|
721
|
+
invalidateTonClientCache();
|
|
722
|
+
}
|
|
723
723
|
log4.error({ err: error }, "Error sending TON");
|
|
724
|
-
|
|
724
|
+
throw error;
|
|
725
725
|
}
|
|
726
726
|
});
|
|
727
727
|
}
|
|
@@ -775,11 +775,181 @@ async function withBlockchainRetry(fn, operation = "blockchain operation") {
|
|
|
775
775
|
}
|
|
776
776
|
|
|
777
777
|
// src/sdk/ton.ts
|
|
778
|
-
import {
|
|
779
|
-
|
|
778
|
+
import {
|
|
779
|
+
toNano as tonToNano,
|
|
780
|
+
fromNano as tonFromNano,
|
|
781
|
+
WalletContractV5R1 as WalletContractV5R12,
|
|
782
|
+
internal as internal2
|
|
783
|
+
} from "@ton/ton";
|
|
784
|
+
import { Address as TonAddress, beginCell, SendMode as SendMode2 } from "@ton/core";
|
|
785
|
+
|
|
786
|
+
// src/ton/format-transactions.ts
|
|
787
|
+
import { fromNano } from "@ton/ton";
|
|
788
|
+
var OP_CODES = {
|
|
789
|
+
COMMENT: 0,
|
|
790
|
+
JETTON_TRANSFER: 260734629,
|
|
791
|
+
JETTON_TRANSFER_NOTIFICATION: 1935855772,
|
|
792
|
+
JETTON_INTERNAL_TRANSFER: 395134233,
|
|
793
|
+
JETTON_BURN: 1499400124,
|
|
794
|
+
NFT_TRANSFER: 1607220500,
|
|
795
|
+
NFT_OWNERSHIP_ASSIGNED: 85167505,
|
|
796
|
+
EXCESSES: 3576854235,
|
|
797
|
+
BOUNCE: 4294967295
|
|
798
|
+
};
|
|
799
|
+
function parseMessageBody(body) {
|
|
800
|
+
if (!body) return null;
|
|
801
|
+
try {
|
|
802
|
+
const slice = body.beginParse();
|
|
803
|
+
if (slice.remainingBits < 32) return null;
|
|
804
|
+
const op = slice.loadUint(32);
|
|
805
|
+
if (op === OP_CODES.COMMENT && slice.remainingBits > 0) {
|
|
806
|
+
return { op, comment: slice.loadStringTail() };
|
|
807
|
+
}
|
|
808
|
+
if (op === OP_CODES.JETTON_TRANSFER_NOTIFICATION) {
|
|
809
|
+
const _queryId = slice.loadUint(64);
|
|
810
|
+
const amount = slice.loadCoins();
|
|
811
|
+
const _sender = slice.loadAddress();
|
|
812
|
+
return { op, jettonAmount: amount.toString() };
|
|
813
|
+
}
|
|
814
|
+
if (op === OP_CODES.JETTON_TRANSFER) {
|
|
815
|
+
const _queryId = slice.loadUint(64);
|
|
816
|
+
const amount = slice.loadCoins();
|
|
817
|
+
const _destination = slice.loadAddress();
|
|
818
|
+
return { op, jettonAmount: amount.toString() };
|
|
819
|
+
}
|
|
820
|
+
if (op === OP_CODES.NFT_OWNERSHIP_ASSIGNED) {
|
|
821
|
+
const _queryId = slice.loadUint(64);
|
|
822
|
+
const _prevOwner = slice.loadAddress();
|
|
823
|
+
return { op };
|
|
824
|
+
}
|
|
825
|
+
if (op === OP_CODES.NFT_TRANSFER) {
|
|
826
|
+
const _queryId = slice.loadUint(64);
|
|
827
|
+
const newOwner = slice.loadAddress();
|
|
828
|
+
return { op, nftAddress: newOwner?.toString() };
|
|
829
|
+
}
|
|
830
|
+
return { op };
|
|
831
|
+
} catch {
|
|
832
|
+
return null;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
function formatTransactions(transactions) {
|
|
836
|
+
return transactions.map((tx) => {
|
|
837
|
+
const inMsg = tx.inMessage;
|
|
838
|
+
const outMsgArray = [...tx.outMessages.values()];
|
|
839
|
+
const hash = tx.hash().toString("hex");
|
|
840
|
+
const explorer = `https://tonviewer.com/transaction/${hash}`;
|
|
841
|
+
const txTimeMs = tx.now * 1e3;
|
|
842
|
+
const date = new Date(txTimeMs).toISOString();
|
|
843
|
+
const secondsAgo = Math.max(0, Math.floor((Date.now() - txTimeMs) / 1e3));
|
|
844
|
+
if (inMsg?.info.type === "internal") {
|
|
845
|
+
const tonAmount = fromNano(inMsg.info.value.coins);
|
|
846
|
+
const from = inMsg.info.src?.toString() || "unknown";
|
|
847
|
+
const parsed = parseMessageBody(inMsg.body);
|
|
848
|
+
if (parsed?.op === OP_CODES.EXCESSES) {
|
|
849
|
+
return {
|
|
850
|
+
type: "gas_refund",
|
|
851
|
+
hash,
|
|
852
|
+
amount: `${tonAmount} TON`,
|
|
853
|
+
from,
|
|
854
|
+
date,
|
|
855
|
+
secondsAgo,
|
|
856
|
+
explorer
|
|
857
|
+
};
|
|
858
|
+
}
|
|
859
|
+
if (parsed?.op === OP_CODES.JETTON_TRANSFER_NOTIFICATION) {
|
|
860
|
+
return {
|
|
861
|
+
type: "jetton_received",
|
|
862
|
+
hash,
|
|
863
|
+
jettonAmount: parsed.jettonAmount,
|
|
864
|
+
jettonWallet: from,
|
|
865
|
+
date,
|
|
866
|
+
secondsAgo,
|
|
867
|
+
explorer
|
|
868
|
+
};
|
|
869
|
+
}
|
|
870
|
+
if (parsed?.op === OP_CODES.NFT_OWNERSHIP_ASSIGNED) {
|
|
871
|
+
return { type: "nft_received", hash, nftAddress: from, date, secondsAgo, explorer };
|
|
872
|
+
}
|
|
873
|
+
if (inMsg.info.bounced || parsed?.op === OP_CODES.BOUNCE) {
|
|
874
|
+
return {
|
|
875
|
+
type: "bounce",
|
|
876
|
+
hash,
|
|
877
|
+
amount: `${tonAmount} TON`,
|
|
878
|
+
from,
|
|
879
|
+
date,
|
|
880
|
+
secondsAgo,
|
|
881
|
+
explorer
|
|
882
|
+
};
|
|
883
|
+
}
|
|
884
|
+
return {
|
|
885
|
+
type: "ton_received",
|
|
886
|
+
hash,
|
|
887
|
+
amount: `${tonAmount} TON`,
|
|
888
|
+
from,
|
|
889
|
+
comment: parsed?.comment || null,
|
|
890
|
+
date,
|
|
891
|
+
secondsAgo,
|
|
892
|
+
explorer
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
if (outMsgArray.length > 0) {
|
|
896
|
+
const results = [];
|
|
897
|
+
for (const outMsg of outMsgArray) {
|
|
898
|
+
if (outMsg.info.type !== "internal") continue;
|
|
899
|
+
const info = outMsg.info;
|
|
900
|
+
const to = info.dest?.toString() || "unknown";
|
|
901
|
+
const tonAmount = fromNano(info.value.coins);
|
|
902
|
+
const parsed = parseMessageBody(outMsg.body);
|
|
903
|
+
if (parsed?.op === OP_CODES.JETTON_TRANSFER) {
|
|
904
|
+
results.push({
|
|
905
|
+
type: "jetton_sent",
|
|
906
|
+
hash,
|
|
907
|
+
jettonAmount: parsed.jettonAmount,
|
|
908
|
+
jettonWallet: to,
|
|
909
|
+
date,
|
|
910
|
+
secondsAgo,
|
|
911
|
+
explorer
|
|
912
|
+
});
|
|
913
|
+
continue;
|
|
914
|
+
}
|
|
915
|
+
if (parsed?.op === OP_CODES.NFT_TRANSFER) {
|
|
916
|
+
results.push({ type: "nft_sent", hash, nftAddress: to, date, secondsAgo, explorer });
|
|
917
|
+
continue;
|
|
918
|
+
}
|
|
919
|
+
results.push({
|
|
920
|
+
type: "ton_sent",
|
|
921
|
+
hash,
|
|
922
|
+
amount: `${tonAmount} TON`,
|
|
923
|
+
to,
|
|
924
|
+
comment: parsed?.comment || null,
|
|
925
|
+
date,
|
|
926
|
+
secondsAgo,
|
|
927
|
+
explorer
|
|
928
|
+
});
|
|
929
|
+
}
|
|
930
|
+
if (results.length === 1) return results[0];
|
|
931
|
+
if (results.length > 1) {
|
|
932
|
+
return { type: "multi_send", hash, transfers: results, date, secondsAgo, explorer };
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
return { type: "contract_call", hash, date, secondsAgo, explorer };
|
|
936
|
+
});
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
// src/sdk/ton.ts
|
|
780
940
|
var DEFAULT_MAX_AGE_MINUTES = 10;
|
|
781
941
|
var DEFAULT_TX_RETENTION_DAYS = 30;
|
|
782
942
|
var CLEANUP_PROBABILITY = 0.1;
|
|
943
|
+
function findJettonBalance(balances, jettonAddress) {
|
|
944
|
+
return balances.find((b) => {
|
|
945
|
+
if (b.jetton.address.toLowerCase() === jettonAddress.toLowerCase()) return true;
|
|
946
|
+
try {
|
|
947
|
+
return TonAddress.parse(b.jetton.address).toString() === TonAddress.parse(jettonAddress).toString();
|
|
948
|
+
} catch {
|
|
949
|
+
return false;
|
|
950
|
+
}
|
|
951
|
+
});
|
|
952
|
+
}
|
|
783
953
|
function cleanupOldTransactions(db, retentionDays, log7) {
|
|
784
954
|
if (Math.random() > CLEANUP_PROBABILITY) return;
|
|
785
955
|
try {
|
|
@@ -829,8 +999,7 @@ function createTonSDK(log7, db) {
|
|
|
829
999
|
throw new PluginSDKError("Amount must be a positive number", "OPERATION_FAILED");
|
|
830
1000
|
}
|
|
831
1001
|
try {
|
|
832
|
-
|
|
833
|
-
Address2.parse(to);
|
|
1002
|
+
TonAddress.parse(to);
|
|
834
1003
|
} catch {
|
|
835
1004
|
throw new PluginSDKError("Invalid TON address format", "INVALID_ADDRESS");
|
|
836
1005
|
}
|
|
@@ -858,13 +1027,8 @@ function createTonSDK(log7, db) {
|
|
|
858
1027
|
},
|
|
859
1028
|
async getTransactions(address, limit) {
|
|
860
1029
|
try {
|
|
861
|
-
const
|
|
862
|
-
const
|
|
863
|
-
const { getCachedHttpEndpoint: getCachedHttpEndpoint2 } = await import("./endpoint-FLYNEZ2F.js");
|
|
864
|
-
const { formatTransactions } = await import("./format-transactions-FD74HI5N.js");
|
|
865
|
-
const addressObj = Address2.parse(address);
|
|
866
|
-
const endpoint = await getCachedHttpEndpoint2();
|
|
867
|
-
const client = new TonClient2({ endpoint });
|
|
1030
|
+
const addressObj = TonAddress.parse(address);
|
|
1031
|
+
const client = await getCachedTonClient();
|
|
868
1032
|
const transactions = await withBlockchainRetry(
|
|
869
1033
|
() => client.getTransactions(addressObj, {
|
|
870
1034
|
limit: Math.min(limit ?? 10, 50)
|
|
@@ -935,7 +1099,7 @@ function createTonSDK(log7, db) {
|
|
|
935
1099
|
try {
|
|
936
1100
|
const addr = ownerAddress ?? getWalletAddress();
|
|
937
1101
|
if (!addr) return [];
|
|
938
|
-
const response = await tonapiFetch(`/accounts/${addr}/jettons`);
|
|
1102
|
+
const response = await tonapiFetch(`/accounts/${encodeURIComponent(addr)}/jettons`);
|
|
939
1103
|
if (!response.ok) {
|
|
940
1104
|
log7.error(`ton.getJettonBalances() TonAPI error: ${response.status}`);
|
|
941
1105
|
return [];
|
|
@@ -971,7 +1135,7 @@ function createTonSDK(log7, db) {
|
|
|
971
1135
|
},
|
|
972
1136
|
async getJettonInfo(jettonAddress) {
|
|
973
1137
|
try {
|
|
974
|
-
const response = await tonapiFetch(`/jettons/${jettonAddress}`);
|
|
1138
|
+
const response = await tonapiFetch(`/jettons/${encodeURIComponent(jettonAddress)}`);
|
|
975
1139
|
if (response.status === 404) return null;
|
|
976
1140
|
if (!response.ok) {
|
|
977
1141
|
log7.error(`ton.getJettonInfo() TonAPI error: ${response.status}`);
|
|
@@ -997,9 +1161,6 @@ function createTonSDK(log7, db) {
|
|
|
997
1161
|
}
|
|
998
1162
|
},
|
|
999
1163
|
async sendJetton(jettonAddress, to, amount, opts) {
|
|
1000
|
-
const { Address: Address2, beginCell, SendMode: SendMode2 } = await import("@ton/core");
|
|
1001
|
-
const { WalletContractV5R1: WalletContractV5R12, TonClient: TonClient2, toNano: toNano2, internal: internal2 } = await import("@ton/ton");
|
|
1002
|
-
const { getCachedHttpEndpoint: getCachedHttpEndpoint2 } = await import("./endpoint-FLYNEZ2F.js");
|
|
1003
1164
|
const walletData = loadWallet();
|
|
1004
1165
|
if (!walletData) {
|
|
1005
1166
|
throw new PluginSDKError("Wallet not initialized", "WALLET_NOT_INITIALIZED");
|
|
@@ -1008,12 +1169,14 @@ function createTonSDK(log7, db) {
|
|
|
1008
1169
|
throw new PluginSDKError("Amount must be a positive number", "OPERATION_FAILED");
|
|
1009
1170
|
}
|
|
1010
1171
|
try {
|
|
1011
|
-
|
|
1172
|
+
TonAddress.parse(to);
|
|
1012
1173
|
} catch {
|
|
1013
1174
|
throw new PluginSDKError("Invalid recipient address", "INVALID_ADDRESS");
|
|
1014
1175
|
}
|
|
1015
1176
|
try {
|
|
1016
|
-
const jettonsResponse = await tonapiFetch(
|
|
1177
|
+
const jettonsResponse = await tonapiFetch(
|
|
1178
|
+
`/accounts/${encodeURIComponent(walletData.address)}/jettons`
|
|
1179
|
+
);
|
|
1017
1180
|
if (!jettonsResponse.ok) {
|
|
1018
1181
|
throw new PluginSDKError(
|
|
1019
1182
|
`Failed to fetch jetton balances: ${jettonsResponse.status}`,
|
|
@@ -1021,9 +1184,7 @@ function createTonSDK(log7, db) {
|
|
|
1021
1184
|
);
|
|
1022
1185
|
}
|
|
1023
1186
|
const jettonsData = await jettonsResponse.json();
|
|
1024
|
-
const jettonBalance = jettonsData.balances
|
|
1025
|
-
(b) => b.jetton.address.toLowerCase() === jettonAddress.toLowerCase() || Address2.parse(b.jetton.address).toString() === Address2.parse(jettonAddress).toString()
|
|
1026
|
-
);
|
|
1187
|
+
const jettonBalance = findJettonBalance(jettonsData.balances ?? [], jettonAddress);
|
|
1027
1188
|
if (!jettonBalance) {
|
|
1028
1189
|
throw new PluginSDKError(
|
|
1029
1190
|
`You don't own any of this jetton: ${jettonAddress}`,
|
|
@@ -1048,7 +1209,7 @@ function createTonSDK(log7, db) {
|
|
|
1048
1209
|
forwardPayload = beginCell().storeUint(0, 32).storeStringTail(comment).endCell();
|
|
1049
1210
|
}
|
|
1050
1211
|
const JETTON_TRANSFER_OP = 260734629;
|
|
1051
|
-
const messageBody = beginCell().storeUint(JETTON_TRANSFER_OP, 32).storeUint(0, 64).storeCoins(amountInUnits).storeAddress(
|
|
1212
|
+
const messageBody = beginCell().storeUint(JETTON_TRANSFER_OP, 32).storeUint(0, 64).storeCoins(amountInUnits).storeAddress(TonAddress.parse(to)).storeAddress(TonAddress.parse(walletData.address)).storeBit(false).storeCoins(comment ? tonToNano("0.01") : BigInt(1)).storeBit(comment ? 1 : 0).storeRef(comment ? forwardPayload : beginCell().endCell()).endCell();
|
|
1052
1213
|
const keyPair = await getKeyPair();
|
|
1053
1214
|
if (!keyPair) {
|
|
1054
1215
|
throw new PluginSDKError("Wallet key derivation failed", "OPERATION_FAILED");
|
|
@@ -1058,8 +1219,7 @@ function createTonSDK(log7, db) {
|
|
|
1058
1219
|
workchain: 0,
|
|
1059
1220
|
publicKey: keyPair.publicKey
|
|
1060
1221
|
});
|
|
1061
|
-
const
|
|
1062
|
-
const client = new TonClient2({ endpoint });
|
|
1222
|
+
const client = await getCachedTonClient();
|
|
1063
1223
|
const walletContract = client.open(wallet);
|
|
1064
1224
|
const seq = await walletContract.getSeqno();
|
|
1065
1225
|
await walletContract.sendTransfer({
|
|
@@ -1068,8 +1228,8 @@ function createTonSDK(log7, db) {
|
|
|
1068
1228
|
sendMode: SendMode2.PAY_GAS_SEPARATELY,
|
|
1069
1229
|
messages: [
|
|
1070
1230
|
internal2({
|
|
1071
|
-
to:
|
|
1072
|
-
value:
|
|
1231
|
+
to: TonAddress.parse(senderJettonWallet),
|
|
1232
|
+
value: tonToNano("0.05"),
|
|
1073
1233
|
body: messageBody,
|
|
1074
1234
|
bounce: true
|
|
1075
1235
|
})
|
|
@@ -1088,16 +1248,13 @@ function createTonSDK(log7, db) {
|
|
|
1088
1248
|
},
|
|
1089
1249
|
async getJettonWalletAddress(ownerAddress, jettonAddress) {
|
|
1090
1250
|
try {
|
|
1091
|
-
const response = await tonapiFetch(`/accounts/${ownerAddress}/jettons`);
|
|
1251
|
+
const response = await tonapiFetch(`/accounts/${encodeURIComponent(ownerAddress)}/jettons`);
|
|
1092
1252
|
if (!response.ok) {
|
|
1093
1253
|
log7.error(`ton.getJettonWalletAddress() TonAPI error: ${response.status}`);
|
|
1094
1254
|
return null;
|
|
1095
1255
|
}
|
|
1096
|
-
const { Address: Address2 } = await import("@ton/core");
|
|
1097
1256
|
const data = await response.json();
|
|
1098
|
-
const match = (data.balances
|
|
1099
|
-
(b) => b.jetton.address.toLowerCase() === jettonAddress.toLowerCase() || Address2.parse(b.jetton.address).toString() === Address2.parse(jettonAddress).toString()
|
|
1100
|
-
);
|
|
1257
|
+
const match = findJettonBalance(data.balances ?? [], jettonAddress);
|
|
1101
1258
|
return match ? match.wallet_address.address : null;
|
|
1102
1259
|
} catch (err) {
|
|
1103
1260
|
log7.error("ton.getJettonWalletAddress() failed:", err);
|
|
@@ -1126,7 +1283,7 @@ function createTonSDK(log7, db) {
|
|
|
1126
1283
|
},
|
|
1127
1284
|
async getNftInfo(nftAddress) {
|
|
1128
1285
|
try {
|
|
1129
|
-
const response = await tonapiFetch(`/nfts/${nftAddress}`);
|
|
1286
|
+
const response = await tonapiFetch(`/nfts/${encodeURIComponent(nftAddress)}`);
|
|
1130
1287
|
if (response.status === 404) return null;
|
|
1131
1288
|
if (!response.ok) {
|
|
1132
1289
|
log7.error(`ton.getNftInfo() TonAPI error: ${response.status}`);
|
|
@@ -2864,11 +3021,22 @@ function numberInRange(min, max) {
|
|
|
2864
3021
|
function enumValidator(options) {
|
|
2865
3022
|
return (v) => options.includes(v) ? void 0 : `Must be one of: ${options.join(", ")}`;
|
|
2866
3023
|
}
|
|
3024
|
+
function positiveInteger(v) {
|
|
3025
|
+
const n = Number(v);
|
|
3026
|
+
if (!Number.isInteger(n) || n <= 0) return "Must be a positive integer";
|
|
3027
|
+
return void 0;
|
|
3028
|
+
}
|
|
3029
|
+
function validateUrl(v) {
|
|
3030
|
+
if (v === "") return void 0;
|
|
3031
|
+
if (v.startsWith("http://") || v.startsWith("https://")) return void 0;
|
|
3032
|
+
return "Must be empty or start with http:// or https://";
|
|
3033
|
+
}
|
|
2867
3034
|
var CONFIGURABLE_KEYS = {
|
|
2868
3035
|
// ─── API Keys ──────────────────────────────────────────────────────
|
|
2869
3036
|
"agent.api_key": {
|
|
2870
3037
|
type: "string",
|
|
2871
3038
|
category: "API Keys",
|
|
3039
|
+
label: "LLM API Key",
|
|
2872
3040
|
description: "LLM provider API key",
|
|
2873
3041
|
sensitive: true,
|
|
2874
3042
|
validate: (v) => v.length >= 10 ? void 0 : "Must be at least 10 characters",
|
|
@@ -2878,6 +3046,7 @@ var CONFIGURABLE_KEYS = {
|
|
|
2878
3046
|
tavily_api_key: {
|
|
2879
3047
|
type: "string",
|
|
2880
3048
|
category: "API Keys",
|
|
3049
|
+
label: "Tavily API Key",
|
|
2881
3050
|
description: "Tavily API key for web search",
|
|
2882
3051
|
sensitive: true,
|
|
2883
3052
|
validate: (v) => v.startsWith("tvly-") ? void 0 : "Must start with 'tvly-'",
|
|
@@ -2887,6 +3056,7 @@ var CONFIGURABLE_KEYS = {
|
|
|
2887
3056
|
tonapi_key: {
|
|
2888
3057
|
type: "string",
|
|
2889
3058
|
category: "API Keys",
|
|
3059
|
+
label: "TonAPI Key",
|
|
2890
3060
|
description: "TonAPI key for higher rate limits",
|
|
2891
3061
|
sensitive: true,
|
|
2892
3062
|
validate: (v) => v.length >= 10 ? void 0 : "Must be at least 10 characters",
|
|
@@ -2896,6 +3066,7 @@ var CONFIGURABLE_KEYS = {
|
|
|
2896
3066
|
"telegram.bot_token": {
|
|
2897
3067
|
type: "string",
|
|
2898
3068
|
category: "API Keys",
|
|
3069
|
+
label: "Bot Token",
|
|
2899
3070
|
description: "Bot token from @BotFather",
|
|
2900
3071
|
sensitive: true,
|
|
2901
3072
|
validate: (v) => v.includes(":") ? void 0 : "Must contain ':' (e.g., 123456:ABC...)",
|
|
@@ -2906,10 +3077,12 @@ var CONFIGURABLE_KEYS = {
|
|
|
2906
3077
|
"agent.provider": {
|
|
2907
3078
|
type: "enum",
|
|
2908
3079
|
category: "Agent",
|
|
3080
|
+
label: "Provider",
|
|
2909
3081
|
description: "LLM provider",
|
|
2910
3082
|
sensitive: false,
|
|
2911
3083
|
options: [
|
|
2912
3084
|
"anthropic",
|
|
3085
|
+
"claude-code",
|
|
2913
3086
|
"openai",
|
|
2914
3087
|
"google",
|
|
2915
3088
|
"xai",
|
|
@@ -2922,6 +3095,7 @@ var CONFIGURABLE_KEYS = {
|
|
|
2922
3095
|
],
|
|
2923
3096
|
validate: enumValidator([
|
|
2924
3097
|
"anthropic",
|
|
3098
|
+
"claude-code",
|
|
2925
3099
|
"openai",
|
|
2926
3100
|
"google",
|
|
2927
3101
|
"xai",
|
|
@@ -2938,6 +3112,7 @@ var CONFIGURABLE_KEYS = {
|
|
|
2938
3112
|
"agent.model": {
|
|
2939
3113
|
type: "string",
|
|
2940
3114
|
category: "Agent",
|
|
3115
|
+
label: "Model",
|
|
2941
3116
|
description: "Main LLM model ID",
|
|
2942
3117
|
sensitive: false,
|
|
2943
3118
|
validate: nonEmpty,
|
|
@@ -2947,6 +3122,7 @@ var CONFIGURABLE_KEYS = {
|
|
|
2947
3122
|
"agent.utility_model": {
|
|
2948
3123
|
type: "string",
|
|
2949
3124
|
category: "Agent",
|
|
3125
|
+
label: "Utility Model",
|
|
2950
3126
|
description: "Cheap model for summarization (auto-detected if empty)",
|
|
2951
3127
|
sensitive: false,
|
|
2952
3128
|
validate: noValidation,
|
|
@@ -2956,6 +3132,7 @@ var CONFIGURABLE_KEYS = {
|
|
|
2956
3132
|
"agent.temperature": {
|
|
2957
3133
|
type: "number",
|
|
2958
3134
|
category: "Agent",
|
|
3135
|
+
label: "Temperature",
|
|
2959
3136
|
description: "Response creativity (0.0 = deterministic, 2.0 = max)",
|
|
2960
3137
|
sensitive: false,
|
|
2961
3138
|
validate: numberInRange(0, 2),
|
|
@@ -2965,6 +3142,7 @@ var CONFIGURABLE_KEYS = {
|
|
|
2965
3142
|
"agent.max_tokens": {
|
|
2966
3143
|
type: "number",
|
|
2967
3144
|
category: "Agent",
|
|
3145
|
+
label: "Max Tokens",
|
|
2968
3146
|
description: "Maximum response length in tokens",
|
|
2969
3147
|
sensitive: false,
|
|
2970
3148
|
validate: numberInRange(256, 128e3),
|
|
@@ -2974,16 +3152,38 @@ var CONFIGURABLE_KEYS = {
|
|
|
2974
3152
|
"agent.max_agentic_iterations": {
|
|
2975
3153
|
type: "number",
|
|
2976
3154
|
category: "Agent",
|
|
3155
|
+
label: "Max Iterations",
|
|
2977
3156
|
description: "Max tool-call loop iterations per message",
|
|
2978
3157
|
sensitive: false,
|
|
2979
3158
|
validate: numberInRange(1, 20),
|
|
2980
3159
|
mask: identity,
|
|
2981
3160
|
parse: (v) => Number(v)
|
|
2982
3161
|
},
|
|
3162
|
+
"agent.base_url": {
|
|
3163
|
+
type: "string",
|
|
3164
|
+
category: "Agent",
|
|
3165
|
+
label: "API Base URL",
|
|
3166
|
+
description: "Base URL for local LLM server (requires restart)",
|
|
3167
|
+
sensitive: false,
|
|
3168
|
+
validate: validateUrl,
|
|
3169
|
+
mask: identity,
|
|
3170
|
+
parse: identity
|
|
3171
|
+
},
|
|
3172
|
+
"cocoon.port": {
|
|
3173
|
+
type: "number",
|
|
3174
|
+
category: "Agent",
|
|
3175
|
+
label: "Cocoon Port",
|
|
3176
|
+
description: "Cocoon proxy port (requires restart)",
|
|
3177
|
+
sensitive: false,
|
|
3178
|
+
validate: numberInRange(1, 65535),
|
|
3179
|
+
mask: identity,
|
|
3180
|
+
parse: (v) => Number(v)
|
|
3181
|
+
},
|
|
2983
3182
|
// ─── Session ───────────────────────────────────────────────────
|
|
2984
3183
|
"agent.session_reset_policy.daily_reset_enabled": {
|
|
2985
3184
|
type: "boolean",
|
|
2986
3185
|
category: "Session",
|
|
3186
|
+
label: "Daily Reset",
|
|
2987
3187
|
description: "Enable daily session reset at specified hour",
|
|
2988
3188
|
sensitive: false,
|
|
2989
3189
|
validate: enumValidator(["true", "false"]),
|
|
@@ -2993,6 +3193,7 @@ var CONFIGURABLE_KEYS = {
|
|
|
2993
3193
|
"agent.session_reset_policy.daily_reset_hour": {
|
|
2994
3194
|
type: "number",
|
|
2995
3195
|
category: "Session",
|
|
3196
|
+
label: "Reset Hour",
|
|
2996
3197
|
description: "Hour (0-23 UTC) for daily session reset",
|
|
2997
3198
|
sensitive: false,
|
|
2998
3199
|
validate: numberInRange(0, 23),
|
|
@@ -3002,6 +3203,7 @@ var CONFIGURABLE_KEYS = {
|
|
|
3002
3203
|
"agent.session_reset_policy.idle_expiry_enabled": {
|
|
3003
3204
|
type: "boolean",
|
|
3004
3205
|
category: "Session",
|
|
3206
|
+
label: "Idle Expiry",
|
|
3005
3207
|
description: "Enable automatic session expiry after idle period",
|
|
3006
3208
|
sensitive: false,
|
|
3007
3209
|
validate: enumValidator(["true", "false"]),
|
|
@@ -3011,6 +3213,7 @@ var CONFIGURABLE_KEYS = {
|
|
|
3011
3213
|
"agent.session_reset_policy.idle_expiry_minutes": {
|
|
3012
3214
|
type: "number",
|
|
3013
3215
|
category: "Session",
|
|
3216
|
+
label: "Idle Minutes",
|
|
3014
3217
|
description: "Idle minutes before session expires (minimum 1)",
|
|
3015
3218
|
sensitive: false,
|
|
3016
3219
|
validate: numberInRange(1, Number.MAX_SAFE_INTEGER),
|
|
@@ -3021,6 +3224,7 @@ var CONFIGURABLE_KEYS = {
|
|
|
3021
3224
|
"telegram.bot_username": {
|
|
3022
3225
|
type: "string",
|
|
3023
3226
|
category: "Telegram",
|
|
3227
|
+
label: "Bot Username",
|
|
3024
3228
|
description: "Bot username without @",
|
|
3025
3229
|
sensitive: false,
|
|
3026
3230
|
validate: (v) => v.length >= 3 ? void 0 : "Must be at least 3 characters",
|
|
@@ -3030,19 +3234,23 @@ var CONFIGURABLE_KEYS = {
|
|
|
3030
3234
|
"telegram.dm_policy": {
|
|
3031
3235
|
type: "enum",
|
|
3032
3236
|
category: "Telegram",
|
|
3033
|
-
|
|
3237
|
+
label: "DM Policy",
|
|
3238
|
+
description: "Who can message the bot in private",
|
|
3034
3239
|
sensitive: false,
|
|
3035
|
-
options: ["
|
|
3036
|
-
|
|
3240
|
+
options: ["open", "allowlist", "disabled"],
|
|
3241
|
+
optionLabels: { open: "Open", allowlist: "Allow Users", disabled: "Admin Only" },
|
|
3242
|
+
validate: enumValidator(["allowlist", "open", "disabled"]),
|
|
3037
3243
|
mask: identity,
|
|
3038
3244
|
parse: identity
|
|
3039
3245
|
},
|
|
3040
3246
|
"telegram.group_policy": {
|
|
3041
3247
|
type: "enum",
|
|
3042
3248
|
category: "Telegram",
|
|
3043
|
-
|
|
3249
|
+
label: "Group Policy",
|
|
3250
|
+
description: "Which groups the bot can respond in",
|
|
3044
3251
|
sensitive: false,
|
|
3045
3252
|
options: ["open", "allowlist", "disabled"],
|
|
3253
|
+
optionLabels: { open: "Open", allowlist: "Allow Groups", disabled: "Disabled" },
|
|
3046
3254
|
validate: enumValidator(["open", "allowlist", "disabled"]),
|
|
3047
3255
|
mask: identity,
|
|
3048
3256
|
parse: identity
|
|
@@ -3050,6 +3258,7 @@ var CONFIGURABLE_KEYS = {
|
|
|
3050
3258
|
"telegram.require_mention": {
|
|
3051
3259
|
type: "boolean",
|
|
3052
3260
|
category: "Telegram",
|
|
3261
|
+
label: "Require Mention",
|
|
3053
3262
|
description: "Require @mention in groups to respond",
|
|
3054
3263
|
sensitive: false,
|
|
3055
3264
|
validate: enumValidator(["true", "false"]),
|
|
@@ -3059,6 +3268,7 @@ var CONFIGURABLE_KEYS = {
|
|
|
3059
3268
|
"telegram.owner_name": {
|
|
3060
3269
|
type: "string",
|
|
3061
3270
|
category: "Telegram",
|
|
3271
|
+
label: "Owner Name",
|
|
3062
3272
|
description: "Owner's first name (used in system prompt)",
|
|
3063
3273
|
sensitive: false,
|
|
3064
3274
|
validate: noValidation,
|
|
@@ -3068,6 +3278,7 @@ var CONFIGURABLE_KEYS = {
|
|
|
3068
3278
|
"telegram.owner_username": {
|
|
3069
3279
|
type: "string",
|
|
3070
3280
|
category: "Telegram",
|
|
3281
|
+
label: "Owner Username",
|
|
3071
3282
|
description: "Owner's Telegram username (without @)",
|
|
3072
3283
|
sensitive: false,
|
|
3073
3284
|
validate: noValidation,
|
|
@@ -3077,6 +3288,7 @@ var CONFIGURABLE_KEYS = {
|
|
|
3077
3288
|
"telegram.debounce_ms": {
|
|
3078
3289
|
type: "number",
|
|
3079
3290
|
category: "Telegram",
|
|
3291
|
+
label: "Debounce (ms)",
|
|
3080
3292
|
description: "Group message debounce delay in ms (0 = disabled)",
|
|
3081
3293
|
sensitive: false,
|
|
3082
3294
|
validate: numberInRange(0, 1e4),
|
|
@@ -3086,6 +3298,7 @@ var CONFIGURABLE_KEYS = {
|
|
|
3086
3298
|
"telegram.agent_channel": {
|
|
3087
3299
|
type: "string",
|
|
3088
3300
|
category: "Telegram",
|
|
3301
|
+
label: "Agent Channel",
|
|
3089
3302
|
description: "Channel username for auto-publishing",
|
|
3090
3303
|
sensitive: false,
|
|
3091
3304
|
validate: noValidation,
|
|
@@ -3095,16 +3308,91 @@ var CONFIGURABLE_KEYS = {
|
|
|
3095
3308
|
"telegram.typing_simulation": {
|
|
3096
3309
|
type: "boolean",
|
|
3097
3310
|
category: "Telegram",
|
|
3311
|
+
label: "Typing Simulation",
|
|
3098
3312
|
description: "Simulate typing indicator before sending replies",
|
|
3099
3313
|
sensitive: false,
|
|
3100
3314
|
validate: enumValidator(["true", "false"]),
|
|
3101
3315
|
mask: identity,
|
|
3102
3316
|
parse: (v) => v === "true"
|
|
3103
3317
|
},
|
|
3318
|
+
"telegram.owner_id": {
|
|
3319
|
+
type: "number",
|
|
3320
|
+
category: "Telegram",
|
|
3321
|
+
label: "Admin ID",
|
|
3322
|
+
description: "Primary admin Telegram user ID (auto-added to Admin IDs)",
|
|
3323
|
+
sensitive: false,
|
|
3324
|
+
validate: positiveInteger,
|
|
3325
|
+
mask: identity,
|
|
3326
|
+
parse: (v) => Number(v)
|
|
3327
|
+
},
|
|
3328
|
+
"telegram.max_message_length": {
|
|
3329
|
+
type: "number",
|
|
3330
|
+
category: "Telegram",
|
|
3331
|
+
label: "Max Message Length",
|
|
3332
|
+
description: "Maximum message length in characters",
|
|
3333
|
+
sensitive: false,
|
|
3334
|
+
validate: numberInRange(1, 32768),
|
|
3335
|
+
mask: identity,
|
|
3336
|
+
parse: (v) => Number(v)
|
|
3337
|
+
},
|
|
3338
|
+
"telegram.rate_limit_messages_per_second": {
|
|
3339
|
+
type: "number",
|
|
3340
|
+
category: "Telegram",
|
|
3341
|
+
label: "Rate Limit \u2014 Messages/sec",
|
|
3342
|
+
description: "Rate limit: messages per second (requires restart)",
|
|
3343
|
+
sensitive: false,
|
|
3344
|
+
validate: numberInRange(0.1, 10),
|
|
3345
|
+
mask: identity,
|
|
3346
|
+
parse: (v) => Number(v)
|
|
3347
|
+
},
|
|
3348
|
+
"telegram.rate_limit_groups_per_minute": {
|
|
3349
|
+
type: "number",
|
|
3350
|
+
category: "Telegram",
|
|
3351
|
+
label: "Rate Limit \u2014 Groups/min",
|
|
3352
|
+
description: "Rate limit: groups per minute (requires restart)",
|
|
3353
|
+
sensitive: false,
|
|
3354
|
+
validate: numberInRange(1, 60),
|
|
3355
|
+
mask: identity,
|
|
3356
|
+
parse: (v) => Number(v)
|
|
3357
|
+
},
|
|
3358
|
+
"telegram.admin_ids": {
|
|
3359
|
+
type: "array",
|
|
3360
|
+
itemType: "number",
|
|
3361
|
+
category: "Telegram",
|
|
3362
|
+
label: "Admin IDs",
|
|
3363
|
+
description: "Admin user IDs with elevated access",
|
|
3364
|
+
sensitive: false,
|
|
3365
|
+
validate: positiveInteger,
|
|
3366
|
+
mask: identity,
|
|
3367
|
+
parse: (v) => Number(v)
|
|
3368
|
+
},
|
|
3369
|
+
"telegram.allow_from": {
|
|
3370
|
+
type: "array",
|
|
3371
|
+
itemType: "number",
|
|
3372
|
+
category: "Telegram",
|
|
3373
|
+
label: "Allowed Users",
|
|
3374
|
+
description: "User IDs allowed for DM access",
|
|
3375
|
+
sensitive: false,
|
|
3376
|
+
validate: positiveInteger,
|
|
3377
|
+
mask: identity,
|
|
3378
|
+
parse: (v) => Number(v)
|
|
3379
|
+
},
|
|
3380
|
+
"telegram.group_allow_from": {
|
|
3381
|
+
type: "array",
|
|
3382
|
+
itemType: "number",
|
|
3383
|
+
category: "Telegram",
|
|
3384
|
+
label: "Allowed Groups",
|
|
3385
|
+
description: "Group IDs allowed for group access",
|
|
3386
|
+
sensitive: false,
|
|
3387
|
+
validate: positiveInteger,
|
|
3388
|
+
mask: identity,
|
|
3389
|
+
parse: (v) => Number(v)
|
|
3390
|
+
},
|
|
3104
3391
|
// ─── Embedding ─────────────────────────────────────────────────────
|
|
3105
3392
|
"embedding.provider": {
|
|
3106
3393
|
type: "enum",
|
|
3107
3394
|
category: "Embedding",
|
|
3395
|
+
label: "Embedding Provider",
|
|
3108
3396
|
description: "Embedding provider for RAG",
|
|
3109
3397
|
sensitive: false,
|
|
3110
3398
|
options: ["local", "anthropic", "none"],
|
|
@@ -3112,10 +3400,21 @@ var CONFIGURABLE_KEYS = {
|
|
|
3112
3400
|
mask: identity,
|
|
3113
3401
|
parse: identity
|
|
3114
3402
|
},
|
|
3403
|
+
"embedding.model": {
|
|
3404
|
+
type: "string",
|
|
3405
|
+
category: "Embedding",
|
|
3406
|
+
label: "Embedding Model",
|
|
3407
|
+
description: "Embedding model ID (requires restart)",
|
|
3408
|
+
sensitive: false,
|
|
3409
|
+
validate: noValidation,
|
|
3410
|
+
mask: identity,
|
|
3411
|
+
parse: identity
|
|
3412
|
+
},
|
|
3115
3413
|
// ─── WebUI ─────────────────────────────────────────────────────────
|
|
3116
3414
|
"webui.port": {
|
|
3117
3415
|
type: "number",
|
|
3118
3416
|
category: "WebUI",
|
|
3417
|
+
label: "WebUI Port",
|
|
3119
3418
|
description: "HTTP server port (requires restart)",
|
|
3120
3419
|
sensitive: false,
|
|
3121
3420
|
validate: numberInRange(1024, 65535),
|
|
@@ -3125,6 +3424,7 @@ var CONFIGURABLE_KEYS = {
|
|
|
3125
3424
|
"webui.log_requests": {
|
|
3126
3425
|
type: "boolean",
|
|
3127
3426
|
category: "WebUI",
|
|
3427
|
+
label: "Log HTTP Requests",
|
|
3128
3428
|
description: "Log all HTTP requests to console",
|
|
3129
3429
|
sensitive: false,
|
|
3130
3430
|
validate: enumValidator(["true", "false"]),
|
|
@@ -3135,16 +3435,48 @@ var CONFIGURABLE_KEYS = {
|
|
|
3135
3435
|
"deals.enabled": {
|
|
3136
3436
|
type: "boolean",
|
|
3137
3437
|
category: "Deals",
|
|
3438
|
+
label: "Deals Enabled",
|
|
3138
3439
|
description: "Enable the deals/escrow module",
|
|
3139
3440
|
sensitive: false,
|
|
3140
3441
|
validate: enumValidator(["true", "false"]),
|
|
3141
3442
|
mask: identity,
|
|
3142
3443
|
parse: (v) => v === "true"
|
|
3143
3444
|
},
|
|
3445
|
+
"deals.expiry_seconds": {
|
|
3446
|
+
type: "number",
|
|
3447
|
+
category: "Deals",
|
|
3448
|
+
label: "Deal Expiry",
|
|
3449
|
+
description: "Deal expiry timeout in seconds",
|
|
3450
|
+
sensitive: false,
|
|
3451
|
+
validate: numberInRange(10, 3600),
|
|
3452
|
+
mask: identity,
|
|
3453
|
+
parse: (v) => Number(v)
|
|
3454
|
+
},
|
|
3455
|
+
"deals.buy_max_floor_percent": {
|
|
3456
|
+
type: "number",
|
|
3457
|
+
category: "Deals",
|
|
3458
|
+
label: "Buy Max Floor %",
|
|
3459
|
+
description: "Maximum floor % for buy deals",
|
|
3460
|
+
sensitive: false,
|
|
3461
|
+
validate: numberInRange(1, 100),
|
|
3462
|
+
mask: identity,
|
|
3463
|
+
parse: (v) => Number(v)
|
|
3464
|
+
},
|
|
3465
|
+
"deals.sell_min_floor_percent": {
|
|
3466
|
+
type: "number",
|
|
3467
|
+
category: "Deals",
|
|
3468
|
+
label: "Sell Min Floor %",
|
|
3469
|
+
description: "Minimum floor % for sell deals",
|
|
3470
|
+
sensitive: false,
|
|
3471
|
+
validate: numberInRange(100, 500),
|
|
3472
|
+
mask: identity,
|
|
3473
|
+
parse: (v) => Number(v)
|
|
3474
|
+
},
|
|
3144
3475
|
// ─── Developer ─────────────────────────────────────────────────────
|
|
3145
3476
|
"dev.hot_reload": {
|
|
3146
3477
|
type: "boolean",
|
|
3147
3478
|
category: "Developer",
|
|
3479
|
+
label: "Hot Reload",
|
|
3148
3480
|
description: "Watch ~/.teleton/plugins/ for live changes",
|
|
3149
3481
|
sensitive: false,
|
|
3150
3482
|
validate: enumValidator(["true", "false"]),
|
|
@@ -3240,6 +3572,7 @@ export {
|
|
|
3240
3572
|
randomLong,
|
|
3241
3573
|
withBlockchainRetry,
|
|
3242
3574
|
sendTon,
|
|
3575
|
+
formatTransactions,
|
|
3243
3576
|
adaptPlugin,
|
|
3244
3577
|
ensurePluginDeps,
|
|
3245
3578
|
loadEnhancedPlugins,
|