teleton 0.7.1 → 0.7.3

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.
@@ -1,6 +1,10 @@
1
+ import {
2
+ getClaudeCodeApiKey,
3
+ refreshClaudeCodeApiKey
4
+ } from "./chunk-JQDLW7IE.js";
1
5
  import {
2
6
  getProviderMetadata
3
- } from "./chunk-LRCPA7SC.js";
7
+ } from "./chunk-RMLQS3X6.js";
4
8
  import {
5
9
  appendToTranscript,
6
10
  readTranscript
@@ -92,12 +96,13 @@ function sanitizeToolsForGemini(tools) {
92
96
  // src/agent/client.ts
93
97
  var log = createLogger("LLM");
94
98
  function isOAuthToken(apiKey, provider) {
95
- if (provider && provider !== "anthropic") return false;
99
+ if (provider && provider !== "anthropic" && provider !== "claude-code") return false;
96
100
  return apiKey.startsWith("sk-ant-oat01-");
97
101
  }
98
102
  function getEffectiveApiKey(provider, rawKey) {
99
103
  if (provider === "local") return "local";
100
104
  if (provider === "cocoon") return "";
105
+ if (provider === "claude-code") return getClaudeCodeApiKey(rawKey);
101
106
  return rawKey;
102
107
  }
103
108
  var modelCache = /* @__PURE__ */ new Map();
@@ -307,7 +312,15 @@ async function chatWithContext(config, options) {
307
312
  const { stripCocoonPayload } = await import("./tool-adapter-Y3TCEQOC.js");
308
313
  completeOptions.onPayload = stripCocoonPayload;
309
314
  }
310
- const response = await complete(model, context, completeOptions);
315
+ let response = await complete(model, context, completeOptions);
316
+ if (provider === "claude-code" && response.stopReason === "error" && response.errorMessage && (response.errorMessage.includes("401") || response.errorMessage.toLowerCase().includes("unauthorized"))) {
317
+ log.warn("Claude Code token rejected (401), refreshing credentials and retrying...");
318
+ const refreshedKey = refreshClaudeCodeApiKey();
319
+ if (refreshedKey) {
320
+ completeOptions.apiKey = refreshedKey;
321
+ response = await complete(model, context, completeOptions);
322
+ }
323
+ }
311
324
  if (isCocoon) {
312
325
  const textBlock = response.content.find((b) => b.type === "text");
313
326
  if (textBlock?.type === "text" && textBlock.text.includes("<tool_call>")) {
@@ -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-NERLQY2H.js";
9
- import {
10
- getCachedHttpEndpoint
11
- } from "./chunk-QUAPFI2N.js";
10
+ } from "./chunk-DAMCNMYL.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-LRCPA7SC.js";
19
+ } from "./chunk-RMLQS3X6.js";
21
20
  import {
22
21
  createDbWrapper,
23
22
  migrateFromMainDb,
@@ -48,7 +47,6 @@ import {
48
47
  createLogger
49
48
  } from "./chunk-RCMD3U65.js";
50
49
  import {
51
- __require,
52
50
  __toESM
53
51
  } from "./chunk-QGM4M3NI.js";
54
52
 
@@ -93,7 +91,7 @@ Run 'teleton setup' to create one.`);
93
91
  }
94
92
  const config = result.data;
95
93
  const provider = config.agent.provider;
96
- if (provider !== "anthropic" && !raw.agent?.model) {
94
+ if (provider !== "anthropic" && provider !== "claude-code" && !raw.agent?.model) {
97
95
  const meta = getProviderMetadata(provider);
98
96
  config.agent.model = meta.defaultModel;
99
97
  }
@@ -658,56 +656,75 @@ var PluginSDKError = class extends Error {
658
656
  var SDK_VERSION = "1.0.0";
659
657
 
660
658
  // src/ton/transfer.ts
661
- import { WalletContractV5R1, TonClient, toNano, internal } from "@ton/ton";
659
+ import { WalletContractV5R1, toNano, internal } from "@ton/ton";
662
660
  import { Address, SendMode } from "@ton/core";
661
+
662
+ // src/ton/tx-lock.ts
663
+ var pending = Promise.resolve();
664
+ function withTxLock(fn) {
665
+ const execute = pending.then(fn, fn);
666
+ pending = execute.then(
667
+ () => {
668
+ },
669
+ () => {
670
+ }
671
+ );
672
+ return execute;
673
+ }
674
+
675
+ // src/ton/transfer.ts
663
676
  var log4 = createLogger("TON");
664
677
  async function sendTon(params) {
665
- try {
666
- const { toAddress, amount, comment = "", bounce = false } = params;
667
- if (!Number.isFinite(amount) || amount <= 0) {
668
- log4.error({ amount }, "Invalid transfer amount");
669
- return null;
670
- }
671
- let recipientAddress;
678
+ return withTxLock(async () => {
672
679
  try {
673
- recipientAddress = Address.parse(toAddress);
674
- } catch (e) {
675
- log4.error({ err: e }, `Invalid recipient address: ${toAddress}`);
676
- return null;
677
- }
678
- const keyPair = await getKeyPair();
679
- if (!keyPair) {
680
- log4.error("Wallet not initialized");
681
- return null;
680
+ const { toAddress, amount, comment = "", bounce = false } = params;
681
+ if (!Number.isFinite(amount) || amount <= 0) {
682
+ log4.error({ amount }, "Invalid transfer amount");
683
+ return null;
684
+ }
685
+ let recipientAddress;
686
+ try {
687
+ recipientAddress = Address.parse(toAddress);
688
+ } catch (e) {
689
+ log4.error({ err: e }, `Invalid recipient address: ${toAddress}`);
690
+ return null;
691
+ }
692
+ const keyPair = await getKeyPair();
693
+ if (!keyPair) {
694
+ log4.error("Wallet not initialized");
695
+ return null;
696
+ }
697
+ const wallet = WalletContractV5R1.create({
698
+ workchain: 0,
699
+ publicKey: keyPair.publicKey
700
+ });
701
+ const client = await getCachedTonClient();
702
+ const contract = client.open(wallet);
703
+ const seqno = await contract.getSeqno();
704
+ await contract.sendTransfer({
705
+ seqno,
706
+ secretKey: keyPair.secretKey,
707
+ sendMode: SendMode.PAY_GAS_SEPARATELY,
708
+ messages: [
709
+ internal({
710
+ to: recipientAddress,
711
+ value: toNano(amount),
712
+ body: comment,
713
+ bounce
714
+ })
715
+ ]
716
+ });
717
+ const pseudoHash = `${seqno}_${Date.now()}_${amount.toFixed(2)}`;
718
+ log4.info(`Sent ${amount} TON to ${toAddress.slice(0, 8)}... - seqno: ${seqno}`);
719
+ return pseudoHash;
720
+ } catch (error) {
721
+ if (error?.status >= 500 || error?.response?.status >= 500) {
722
+ invalidateTonClientCache();
723
+ }
724
+ log4.error({ err: error }, "Error sending TON");
725
+ throw error;
682
726
  }
683
- const wallet = WalletContractV5R1.create({
684
- workchain: 0,
685
- publicKey: keyPair.publicKey
686
- });
687
- const endpoint = await getCachedHttpEndpoint();
688
- const client = new TonClient({ endpoint });
689
- const contract = client.open(wallet);
690
- const seqno = await contract.getSeqno();
691
- await contract.sendTransfer({
692
- seqno,
693
- secretKey: keyPair.secretKey,
694
- sendMode: SendMode.PAY_GAS_SEPARATELY,
695
- messages: [
696
- internal({
697
- to: recipientAddress,
698
- value: toNano(amount),
699
- body: comment,
700
- bounce
701
- })
702
- ]
703
- });
704
- const pseudoHash = `${seqno}_${Date.now()}_${amount.toFixed(2)}`;
705
- log4.info(`Sent ${amount} TON to ${toAddress.slice(0, 8)}... - seqno: ${seqno}`);
706
- return pseudoHash;
707
- } catch (error) {
708
- log4.error({ err: error }, "Error sending TON");
709
- return null;
710
- }
727
+ });
711
728
  }
712
729
 
713
730
  // src/utils/retry.ts
@@ -758,10 +775,182 @@ async function withBlockchainRetry(fn, operation = "blockchain operation") {
758
775
  }
759
776
  }
760
777
 
778
+ // src/sdk/ton.ts
779
+ import {
780
+ toNano as tonToNano,
781
+ fromNano as tonFromNano,
782
+ WalletContractV5R1 as WalletContractV5R12,
783
+ internal as internal2
784
+ } from "@ton/ton";
785
+ import { Address as TonAddress, beginCell, SendMode as SendMode2 } from "@ton/core";
786
+
787
+ // src/ton/format-transactions.ts
788
+ import { fromNano } from "@ton/ton";
789
+ var OP_CODES = {
790
+ COMMENT: 0,
791
+ JETTON_TRANSFER: 260734629,
792
+ JETTON_TRANSFER_NOTIFICATION: 1935855772,
793
+ JETTON_INTERNAL_TRANSFER: 395134233,
794
+ JETTON_BURN: 1499400124,
795
+ NFT_TRANSFER: 1607220500,
796
+ NFT_OWNERSHIP_ASSIGNED: 85167505,
797
+ EXCESSES: 3576854235,
798
+ BOUNCE: 4294967295
799
+ };
800
+ function parseMessageBody(body) {
801
+ if (!body) return null;
802
+ try {
803
+ const slice = body.beginParse();
804
+ if (slice.remainingBits < 32) return null;
805
+ const op = slice.loadUint(32);
806
+ if (op === OP_CODES.COMMENT && slice.remainingBits > 0) {
807
+ return { op, comment: slice.loadStringTail() };
808
+ }
809
+ if (op === OP_CODES.JETTON_TRANSFER_NOTIFICATION) {
810
+ const _queryId = slice.loadUint(64);
811
+ const amount = slice.loadCoins();
812
+ const _sender = slice.loadAddress();
813
+ return { op, jettonAmount: amount.toString() };
814
+ }
815
+ if (op === OP_CODES.JETTON_TRANSFER) {
816
+ const _queryId = slice.loadUint(64);
817
+ const amount = slice.loadCoins();
818
+ const _destination = slice.loadAddress();
819
+ return { op, jettonAmount: amount.toString() };
820
+ }
821
+ if (op === OP_CODES.NFT_OWNERSHIP_ASSIGNED) {
822
+ const _queryId = slice.loadUint(64);
823
+ const _prevOwner = slice.loadAddress();
824
+ return { op };
825
+ }
826
+ if (op === OP_CODES.NFT_TRANSFER) {
827
+ const _queryId = slice.loadUint(64);
828
+ const newOwner = slice.loadAddress();
829
+ return { op, nftAddress: newOwner?.toString() };
830
+ }
831
+ return { op };
832
+ } catch {
833
+ return null;
834
+ }
835
+ }
836
+ function formatTransactions(transactions) {
837
+ return transactions.map((tx) => {
838
+ const inMsg = tx.inMessage;
839
+ const outMsgArray = [...tx.outMessages.values()];
840
+ const hash = tx.hash().toString("hex");
841
+ const explorer = `https://tonviewer.com/transaction/${hash}`;
842
+ const txTimeMs = tx.now * 1e3;
843
+ const date = new Date(txTimeMs).toISOString();
844
+ const secondsAgo = Math.max(0, Math.floor((Date.now() - txTimeMs) / 1e3));
845
+ if (inMsg?.info.type === "internal") {
846
+ const tonAmount = fromNano(inMsg.info.value.coins);
847
+ const from = inMsg.info.src?.toString() || "unknown";
848
+ const parsed = parseMessageBody(inMsg.body);
849
+ if (parsed?.op === OP_CODES.EXCESSES) {
850
+ return {
851
+ type: "gas_refund",
852
+ hash,
853
+ amount: `${tonAmount} TON`,
854
+ from,
855
+ date,
856
+ secondsAgo,
857
+ explorer
858
+ };
859
+ }
860
+ if (parsed?.op === OP_CODES.JETTON_TRANSFER_NOTIFICATION) {
861
+ return {
862
+ type: "jetton_received",
863
+ hash,
864
+ jettonAmount: parsed.jettonAmount,
865
+ jettonWallet: from,
866
+ date,
867
+ secondsAgo,
868
+ explorer
869
+ };
870
+ }
871
+ if (parsed?.op === OP_CODES.NFT_OWNERSHIP_ASSIGNED) {
872
+ return { type: "nft_received", hash, nftAddress: from, date, secondsAgo, explorer };
873
+ }
874
+ if (inMsg.info.bounced || parsed?.op === OP_CODES.BOUNCE) {
875
+ return {
876
+ type: "bounce",
877
+ hash,
878
+ amount: `${tonAmount} TON`,
879
+ from,
880
+ date,
881
+ secondsAgo,
882
+ explorer
883
+ };
884
+ }
885
+ return {
886
+ type: "ton_received",
887
+ hash,
888
+ amount: `${tonAmount} TON`,
889
+ from,
890
+ comment: parsed?.comment || null,
891
+ date,
892
+ secondsAgo,
893
+ explorer
894
+ };
895
+ }
896
+ if (outMsgArray.length > 0) {
897
+ const results = [];
898
+ for (const outMsg of outMsgArray) {
899
+ if (outMsg.info.type !== "internal") continue;
900
+ const info = outMsg.info;
901
+ const to = info.dest?.toString() || "unknown";
902
+ const tonAmount = fromNano(info.value.coins);
903
+ const parsed = parseMessageBody(outMsg.body);
904
+ if (parsed?.op === OP_CODES.JETTON_TRANSFER) {
905
+ results.push({
906
+ type: "jetton_sent",
907
+ hash,
908
+ jettonAmount: parsed.jettonAmount,
909
+ jettonWallet: to,
910
+ date,
911
+ secondsAgo,
912
+ explorer
913
+ });
914
+ continue;
915
+ }
916
+ if (parsed?.op === OP_CODES.NFT_TRANSFER) {
917
+ results.push({ type: "nft_sent", hash, nftAddress: to, date, secondsAgo, explorer });
918
+ continue;
919
+ }
920
+ results.push({
921
+ type: "ton_sent",
922
+ hash,
923
+ amount: `${tonAmount} TON`,
924
+ to,
925
+ comment: parsed?.comment || null,
926
+ date,
927
+ secondsAgo,
928
+ explorer
929
+ });
930
+ }
931
+ if (results.length === 1) return results[0];
932
+ if (results.length > 1) {
933
+ return { type: "multi_send", hash, transfers: results, date, secondsAgo, explorer };
934
+ }
935
+ }
936
+ return { type: "contract_call", hash, date, secondsAgo, explorer };
937
+ });
938
+ }
939
+
761
940
  // src/sdk/ton.ts
762
941
  var DEFAULT_MAX_AGE_MINUTES = 10;
763
942
  var DEFAULT_TX_RETENTION_DAYS = 30;
764
943
  var CLEANUP_PROBABILITY = 0.1;
944
+ function findJettonBalance(balances, jettonAddress) {
945
+ return balances.find((b) => {
946
+ if (b.jetton.address.toLowerCase() === jettonAddress.toLowerCase()) return true;
947
+ try {
948
+ return TonAddress.parse(b.jetton.address).toString() === TonAddress.parse(jettonAddress).toString();
949
+ } catch {
950
+ return false;
951
+ }
952
+ });
953
+ }
765
954
  function cleanupOldTransactions(db, retentionDays, log7) {
766
955
  if (Math.random() > CLEANUP_PROBABILITY) return;
767
956
  try {
@@ -811,8 +1000,7 @@ function createTonSDK(log7, db) {
811
1000
  throw new PluginSDKError("Amount must be a positive number", "OPERATION_FAILED");
812
1001
  }
813
1002
  try {
814
- const { Address: Address2 } = await import("@ton/core");
815
- Address2.parse(to);
1003
+ TonAddress.parse(to);
816
1004
  } catch {
817
1005
  throw new PluginSDKError("Invalid TON address format", "INVALID_ADDRESS");
818
1006
  }
@@ -840,13 +1028,8 @@ function createTonSDK(log7, db) {
840
1028
  },
841
1029
  async getTransactions(address, limit) {
842
1030
  try {
843
- const { TonClient: TonClient2 } = await import("@ton/ton");
844
- const { Address: Address2 } = await import("@ton/core");
845
- const { getCachedHttpEndpoint: getCachedHttpEndpoint2 } = await import("./endpoint-FLYNEZ2F.js");
846
- const { formatTransactions } = await import("./format-transactions-FD74HI5N.js");
847
- const addressObj = Address2.parse(address);
848
- const endpoint = await getCachedHttpEndpoint2();
849
- const client = new TonClient2({ endpoint });
1031
+ const addressObj = TonAddress.parse(address);
1032
+ const client = await getCachedTonClient();
850
1033
  const transactions = await withBlockchainRetry(
851
1034
  () => client.getTransactions(addressObj, {
852
1035
  limit: Math.min(limit ?? 10, 50)
@@ -917,7 +1100,7 @@ function createTonSDK(log7, db) {
917
1100
  try {
918
1101
  const addr = ownerAddress ?? getWalletAddress();
919
1102
  if (!addr) return [];
920
- const response = await tonapiFetch(`/accounts/${addr}/jettons`);
1103
+ const response = await tonapiFetch(`/accounts/${encodeURIComponent(addr)}/jettons`);
921
1104
  if (!response.ok) {
922
1105
  log7.error(`ton.getJettonBalances() TonAPI error: ${response.status}`);
923
1106
  return [];
@@ -953,7 +1136,7 @@ function createTonSDK(log7, db) {
953
1136
  },
954
1137
  async getJettonInfo(jettonAddress) {
955
1138
  try {
956
- const response = await tonapiFetch(`/jettons/${jettonAddress}`);
1139
+ const response = await tonapiFetch(`/jettons/${encodeURIComponent(jettonAddress)}`);
957
1140
  if (response.status === 404) return null;
958
1141
  if (!response.ok) {
959
1142
  log7.error(`ton.getJettonInfo() TonAPI error: ${response.status}`);
@@ -979,9 +1162,6 @@ function createTonSDK(log7, db) {
979
1162
  }
980
1163
  },
981
1164
  async sendJetton(jettonAddress, to, amount, opts) {
982
- const { Address: Address2, beginCell, SendMode: SendMode2 } = await import("@ton/core");
983
- const { WalletContractV5R1: WalletContractV5R12, TonClient: TonClient2, toNano: toNano2, internal: internal2 } = await import("@ton/ton");
984
- const { getCachedHttpEndpoint: getCachedHttpEndpoint2 } = await import("./endpoint-FLYNEZ2F.js");
985
1165
  const walletData = loadWallet();
986
1166
  if (!walletData) {
987
1167
  throw new PluginSDKError("Wallet not initialized", "WALLET_NOT_INITIALIZED");
@@ -990,12 +1170,14 @@ function createTonSDK(log7, db) {
990
1170
  throw new PluginSDKError("Amount must be a positive number", "OPERATION_FAILED");
991
1171
  }
992
1172
  try {
993
- Address2.parse(to);
1173
+ TonAddress.parse(to);
994
1174
  } catch {
995
1175
  throw new PluginSDKError("Invalid recipient address", "INVALID_ADDRESS");
996
1176
  }
997
1177
  try {
998
- const jettonsResponse = await tonapiFetch(`/accounts/${walletData.address}/jettons`);
1178
+ const jettonsResponse = await tonapiFetch(
1179
+ `/accounts/${encodeURIComponent(walletData.address)}/jettons`
1180
+ );
999
1181
  if (!jettonsResponse.ok) {
1000
1182
  throw new PluginSDKError(
1001
1183
  `Failed to fetch jetton balances: ${jettonsResponse.status}`,
@@ -1003,9 +1185,7 @@ function createTonSDK(log7, db) {
1003
1185
  );
1004
1186
  }
1005
1187
  const jettonsData = await jettonsResponse.json();
1006
- const jettonBalance = jettonsData.balances?.find(
1007
- (b) => b.jetton.address.toLowerCase() === jettonAddress.toLowerCase() || Address2.parse(b.jetton.address).toString() === Address2.parse(jettonAddress).toString()
1008
- );
1188
+ const jettonBalance = findJettonBalance(jettonsData.balances ?? [], jettonAddress);
1009
1189
  if (!jettonBalance) {
1010
1190
  throw new PluginSDKError(
1011
1191
  `You don't own any of this jetton: ${jettonAddress}`,
@@ -1030,31 +1210,33 @@ function createTonSDK(log7, db) {
1030
1210
  forwardPayload = beginCell().storeUint(0, 32).storeStringTail(comment).endCell();
1031
1211
  }
1032
1212
  const JETTON_TRANSFER_OP = 260734629;
1033
- const messageBody = beginCell().storeUint(JETTON_TRANSFER_OP, 32).storeUint(0, 64).storeCoins(amountInUnits).storeAddress(Address2.parse(to)).storeAddress(Address2.parse(walletData.address)).storeBit(false).storeCoins(comment ? toNano2("0.01") : BigInt(1)).storeBit(comment ? true : false).storeMaybeRef(comment ? forwardPayload : null).endCell();
1213
+ 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();
1034
1214
  const keyPair = await getKeyPair();
1035
1215
  if (!keyPair) {
1036
1216
  throw new PluginSDKError("Wallet key derivation failed", "OPERATION_FAILED");
1037
1217
  }
1038
- const wallet = WalletContractV5R12.create({
1039
- workchain: 0,
1040
- publicKey: keyPair.publicKey
1041
- });
1042
- const endpoint = await getCachedHttpEndpoint2();
1043
- const client = new TonClient2({ endpoint });
1044
- const walletContract = client.open(wallet);
1045
- const seqno = await walletContract.getSeqno();
1046
- await walletContract.sendTransfer({
1047
- seqno,
1048
- secretKey: keyPair.secretKey,
1049
- sendMode: SendMode2.PAY_GAS_SEPARATELY,
1050
- messages: [
1051
- internal2({
1052
- to: Address2.parse(senderJettonWallet),
1053
- value: toNano2("0.05"),
1054
- body: messageBody,
1055
- bounce: true
1056
- })
1057
- ]
1218
+ const seqno = await withTxLock(async () => {
1219
+ const wallet = WalletContractV5R12.create({
1220
+ workchain: 0,
1221
+ publicKey: keyPair.publicKey
1222
+ });
1223
+ const client = await getCachedTonClient();
1224
+ const walletContract = client.open(wallet);
1225
+ const seq = await walletContract.getSeqno();
1226
+ await walletContract.sendTransfer({
1227
+ seqno: seq,
1228
+ secretKey: keyPair.secretKey,
1229
+ sendMode: SendMode2.PAY_GAS_SEPARATELY,
1230
+ messages: [
1231
+ internal2({
1232
+ to: TonAddress.parse(senderJettonWallet),
1233
+ value: tonToNano("0.05"),
1234
+ body: messageBody,
1235
+ bounce: true
1236
+ })
1237
+ ]
1238
+ });
1239
+ return seq;
1058
1240
  });
1059
1241
  return { success: true, seqno };
1060
1242
  } catch (err) {
@@ -1067,16 +1249,13 @@ function createTonSDK(log7, db) {
1067
1249
  },
1068
1250
  async getJettonWalletAddress(ownerAddress, jettonAddress) {
1069
1251
  try {
1070
- const response = await tonapiFetch(`/accounts/${ownerAddress}/jettons`);
1252
+ const response = await tonapiFetch(`/accounts/${encodeURIComponent(ownerAddress)}/jettons`);
1071
1253
  if (!response.ok) {
1072
1254
  log7.error(`ton.getJettonWalletAddress() TonAPI error: ${response.status}`);
1073
1255
  return null;
1074
1256
  }
1075
- const { Address: Address2 } = await import("@ton/core");
1076
1257
  const data = await response.json();
1077
- const match = (data.balances || []).find(
1078
- (b) => b.jetton.address.toLowerCase() === jettonAddress.toLowerCase() || Address2.parse(b.jetton.address).toString() === Address2.parse(jettonAddress).toString()
1079
- );
1258
+ const match = findJettonBalance(data.balances ?? [], jettonAddress);
1080
1259
  return match ? match.wallet_address.address : null;
1081
1260
  } catch (err) {
1082
1261
  log7.error("ton.getJettonWalletAddress() failed:", err);
@@ -1105,7 +1284,7 @@ function createTonSDK(log7, db) {
1105
1284
  },
1106
1285
  async getNftInfo(nftAddress) {
1107
1286
  try {
1108
- const response = await tonapiFetch(`/nfts/${nftAddress}`);
1287
+ const response = await tonapiFetch(`/nfts/${encodeURIComponent(nftAddress)}`);
1109
1288
  if (response.status === 404) return null;
1110
1289
  if (!response.ok) {
1111
1290
  log7.error(`ton.getNftInfo() TonAPI error: ${response.status}`);
@@ -1121,8 +1300,7 @@ function createTonSDK(log7, db) {
1121
1300
  // ─── Utilities ───────────────────────────────────────────────
1122
1301
  toNano(amount) {
1123
1302
  try {
1124
- const { toNano: convert } = __require("@ton/ton");
1125
- return convert(String(amount));
1303
+ return tonToNano(String(amount));
1126
1304
  } catch (err) {
1127
1305
  throw new PluginSDKError(
1128
1306
  `toNano conversion failed: ${err instanceof Error ? err.message : String(err)}`,
@@ -1131,13 +1309,11 @@ function createTonSDK(log7, db) {
1131
1309
  }
1132
1310
  },
1133
1311
  fromNano(nano) {
1134
- const { fromNano: convert } = __require("@ton/ton");
1135
- return convert(nano);
1312
+ return tonFromNano(nano);
1136
1313
  },
1137
1314
  validateAddress(address) {
1138
1315
  try {
1139
- const { Address: Address2 } = __require("@ton/core");
1140
- Address2.parse(address);
1316
+ TonAddress.parse(address);
1141
1317
  return true;
1142
1318
  } catch {
1143
1319
  return false;
@@ -2892,6 +3068,7 @@ var CONFIGURABLE_KEYS = {
2892
3068
  sensitive: false,
2893
3069
  options: [
2894
3070
  "anthropic",
3071
+ "claude-code",
2895
3072
  "openai",
2896
3073
  "google",
2897
3074
  "xai",
@@ -2904,6 +3081,7 @@ var CONFIGURABLE_KEYS = {
2904
3081
  ],
2905
3082
  validate: enumValidator([
2906
3083
  "anthropic",
3084
+ "claude-code",
2907
3085
  "openai",
2908
3086
  "google",
2909
3087
  "xai",
@@ -3222,6 +3400,7 @@ export {
3222
3400
  randomLong,
3223
3401
  withBlockchainRetry,
3224
3402
  sendTon,
3403
+ formatTransactions,
3225
3404
  adaptPlugin,
3226
3405
  ensurePluginDeps,
3227
3406
  loadEnhancedPlugins,