• 0 Голоса
    1 Сообщения
    6 Просмотры

    Я пытался повторно использовать кошелек, удаленный с помощью флага DESTROY_ACCOUNT_IF_ZERO (32). Способ, которым я осуществляю перевод:

    Представьте, что у нас есть 2 кошелька: A и B.

    Мы переводим N1 тонну из "A" в "B". Например, с помощью веб-кошелька, скрипта, не имеет значения. 2. B неинициализирован - его еще нет в блокчейне. Имея это в виду, мы хотели бы отправить все деньги из B обратно в A. Для этого мы собираемся использовать прилагаемый скрипт. 3. Теперь мы идем дальше и переносим N2 ТОННЫ из A в B ** снова **. Не имеет значения, сколько.

    Ожидаемое поведение: мы получаем транзакции: A->B (N1), B->A (все), A->B (N2); в конечном итоге в кошельке B содержится N2 тонн.

    Фактическое поведение: мы получаем транзакции A->B (N1), B->A (все), A->B (N2), B->A (все); в кошельке B в итоге 0 тонн.

    Сценарий для передачи B->A (all), который вызывает такое поведение:

    import TonWeb from 'tonweb'; import tonwebMnemonic from 'tonweb-mnemonic'; const apiKey = "" || undefined; // WALLET B const mnemonic = "..."; const walletVersion = "v4R2"; // WALLET A const toAddress = "..."; const SendMode = { CARRY_ALL_REMAINING_BALANCE: 128, CARRY_ALL_REMAINING_INCOMING_VALUE: 64, DESTROY_ACCOUNT_IF_ZERO: 32, PAY_GAS_SEPARATELY: 1, IGNORE_ERRORS: 2, NONE: 0 } const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); (async () => { const provider = new TonWeb.HttpProvider('https://toncenter.com/api/v2/jsonRPC', {apiKey}); const WalletClass = TonWeb.Wallets.all[walletVersion]; const mnemonicArray = mnemonic.split(" "); let { publicKey, secretKey } = await tonwebMnemonic.mnemonicToKeyPair(mnemonicArray); publicKey = Buffer.from(publicKey); secretKey = Buffer.from(secretKey); console.log(`PUBLIC KEY: ${publicKey.toString('hex')}`); const wallet = new WalletClass(provider, { publicKey }); const seqno = await wallet.methods.seqno().call() || 0; console.log(`SEQNO: ${seqno}`); await sleep(2000); const transferParams = { secretKey, toAddress, amount: 0, seqno, sendMode: SendMode.CARRY_ALL_REMAINING_BALANCE | SendMode.IGNORE_ERRORS | SendMode.DESTROY_ACCOUNT_IF_ZERO, payload: "test bug" }; console.log(JSON.stringify({...transferParams, secretKey: transferParams.secretKey.toString('hex')}, null, 2)); const response = await wallet.methods.transfer(transferParams).send(); console.log(`transfer sent to blockchain: ${JSON.stringify(response, null, 2)}`); })();

    Странная вещь: если вы отправите A->B (N) снова, он автоматически создаст новую передачу B->A (all) снова и снова. Иногда она останавливается на 2 повторениях, иногда на 4.

    Я использую недоступный адрес: UQAPqRlewultl8xHCKGsrenb4PZaQ0QDfPYoK1fwVUODdZRd.

    Я также попробовал отправить TON с кошелька "C (C->B). И деньги ДЕЙСТВИТЕЛЬНО остались на B`. НО как только я снова сделал перевод "A->B", все деньги, включая тонны, отправленные с "C", автоматически перешли на "A"!

    Пример проявления этой ошибки (это ошибка??) находится здесь:

    https://tonviewer.com/EQAySjlsHUY2EEedO5GTenzFvAnR5E-4ptwfeox6OZYnNvGF

    Это кошелек B. Скрипт отправил только первое сообщение с текстом "тестовая ошибка". Остальные сообщения отправлялись автоматически при любом входящем переводе с A.

    В этом взаимодействии:

    A is UQAPqRlewultl8xHCKGsrenb4PZaQ0QDfPYoK1fwVUODdZRd * B is EQAySjlsHUY2EEedO5GTenzFvAnR5E-4ptwfeox6OZYnNvGF * C is UQBwpXsIVrij8UQ2OpPK2EyeVBrlN6mnOkmThb3k6K-UHZyL

    Я хочу понять, почему это происходит. Это задумано разработчиками блокчейна TON? Это не ошибка? Как обойти это и повторно использовать удаленные кошельки?

    Оригинал вопроса

  • 0 Голоса
    1 Сообщения
    19 Просмотры

    Эй, я пытаюсь передать Jettons с помощью функции firebase. Однако я действительно страдаю от завершения функции. Я не уверен, чего мне не хватает, может быть, каких-то адресов? Я также не уверен, как мне прочитать эту ошибку.

    Вот несколько адресов (я использую openmask, а мнемоника - начальная фраза main_wallet) main_wallet_address: 0QBdd6N85lIBz193LTHESG8m9XVlH0owI6nn4hdXGy6S2u7N (с jettons) jetton_wallet: EQBh5qTitSdsZmHuHutn5_cqdwaPVHzYgSc3dRoRzAwR4dTr jetton_minter: EQAtwEufBNdM_YkCaz6fEA4AkddgcEouTrEwZJB4NNUyz3Te (символ: ТЕСТ)

    Прямо сейчас я получаю:

    {"severity":"INFO","message":"my address 0:5d77a37ce65201cf5f772d31c4486f26f575651f4a3023a9e7e217571b2e92da"} > SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON > at JSON.parse (<anonymous>) > at parseJSONFromBytes (node:internal/deps/undici/undici:5418:19) > at successSteps (node:internal/deps/undici/undici:5389:27) > at fullyReadBody (node:internal/deps/undici/undici:1500:9) > at process.processTicksAndRejections (node:internal/process/task_queues:95:5) > at async specConsumeBody (node:internal/deps/undici/undici:5398:7) > at async HttpProvider.call2 (C:\Users\style\Desktop\tonstars\functions\node_modules\tonweb\src\providers\index.js:149:24) > at async JettonMinter.getJettonData (C:\Users\style\Desktop\tonstars\functions\node_modules\tonweb\src\contract\token\ft\JettonMinter.js:87:24) > at async SendTokens (C:\Users\style\Desktop\tonstars\functions\lib\index.js:76:16) > at async C:\Users\style\Desktop\tonstars\functions\lib\index.js:53:15 > {"severity":"ERROR","message":"SyntaxError: Unexpected token '<', \"<!DOCTYPE \"... is not valid JSON\n at JSON.parse (<anonymous>)\n at parseJSONFromBytes (node:internal/deps/undici/undici:5418:19)\n at successSteps (node:internal/deps/undici/undici:5389:27)\n at fullyReadBody (node:internal/deps/undici/undici:1500:9)\n at process.processTicksAndRejections (nodt async HttpProvider.call2 (C:\\Users\\style\\Desktop\\tonsumeBody (node:internal/deps/undici/undici:5398:7)\n at async HttpProvider.call2 (C:\\Users\\style\\Desktop\\tonstars\\functions\\nstars\\functions\\node_modules\\tonweb\\src\\providers\\ at async JettonMinter.getJettonData (C:\\Users\\style\\Desktop\\tonstars\\functions\\node_modules\\tonweb\\src\\contract\\token\\ftindex.js:149:24)\n at async JettonMinter.getJettonDataers\\style\\Desktop\\tonstars\\functions\\lib\\index.js:76:16)\n at async C:\\Users\\style\\Desktop\\tonstars\\functions\\lib\\inde (C:\\Users\\style\\Desktop\\tonstars\\functions\\node_modules\\tonweb\\src\\contract\\token\\ft\\JettonMinter.js:rror: Unexpected token '<', \"<!DOCTYPE \"... is not valid JSON\n at JSON.parse (<anonymous>)\n at parseJSONFromBytes (node:inte87:24)\n at async SendTokens (C:\\Users\\style\\Desktode:internal/deps/undici/undici:5389:27)\n at fullyReadBody (node:internal/deps/undici/undici:1500:9)\n at process.processTicksAnp\\tonstars\\functions\\lib\\index.js:76:16)\n at asyn at async specConsumeBody (node:internal/deps/undici/undici:5398:7)\n at async HttpProvider.call2 (C:\\Users\\style\\Desktop\\tonstc C:\\Users\\style\\Desktop\\tonstars\\functions\\lib\\inex.js:149:24)\n at async JettonMinter.getJettonData (C:\\Users\\style\\Desktop\\tonstars\\functions\\node_modules\\tonweb\\src\\condex.js:53:15"}

    и вот код

    import TonWeb from "tonweb"; import { mnemonicToKeyPair, KeyPair } from "tonweb-mnemonic"; import { onCall } from "firebase-functions/v2/https"; import * as logger from "firebase-functions/logger"; import { defineString } from "firebase-functions/params"; import {mnemonicToWalletKey} from "@ton/crypto"; import admin from "firebase-admin"; import { WalletV3ContractR2 } from "tonweb/dist/types/contract/wallet/v3/wallet-v3-contract-r2"; const app = admin.initializeApp() const db = admin.firestore(app); const walletMnemonic = defineString("WALLET_MNEMONIC"); // main wallet mnemonic const walletPassword = defineString("WALLET_PASSWORD"); // main wallet password const apiKey = defineString("API_KEY"); // api key type WithdrawJettonsRequest = { boc: string; } type TransactionData = { amount: number; nanoAmount: number; jettonsAmount: number; jettonsNanoAmount: number; toAddress: string; status: "pending" | "success" | "failed"; timestamp: number; }; exports.withdrawJettons = onCall(async (request) => { const data = request.data as WithdrawJettonsRequest; const transactionRef = db.collection("transactions").doc(data.boc); const transactionSnapshot = await transactionRef.get(); if (!transactionSnapshot.exists) { throw new Error(`Transaction ${data.boc} not found`); } const transactionData = transactionSnapshot.data() as TransactionData; if (transactionData.status !== "pending") { throw new Error(`Transaction ${data.boc} is not pending`); } const tonweb = new TonWeb(new TonWeb.HttpProvider("https://testnet.toncenter.com/api/v2/jsonRPC", { apiKey: apiKey.value() })); const r = await SendTokens(transactionData, tonweb); await transactionRef.update({ status: "success", }) logger.info("Transaction updated") return r }); export const SendTokens = async (transactionData: TransactionData, tonweb: TonWeb) => { console.log(walletMnemonic.value()) const keyPair = await mnemonicToWalletKey(walletMnemonic.value().split(" ")); const WalletClass = tonweb.wallet.all.v3R2; const wallet = new WalletClass(tonweb.provider, { publicKey: keyPair.publicKey }); const address = await wallet.getAddress(); logger.info("my address", address.toString()); const jettonMinter = new TonWeb.token.jetton.JettonMinter(tonweb.provider, { adminAddress: address, jettonContentUri: "", jettonWalletCodeHex: "TEST", address: "0:2dc04b9f04d74cfd89026b3e9f100e0091d760704a2e4eb13064907834d532cf" }); let data; try { data = await jettonMinter.getJettonData(); } catch (e) { console.log(e) logger.error(e); throw e; } logger.info('Total supply:', data.totalSupply.toString()); logger.info('URI to off-chain metadata:', data.jettonContentUri); // logger.info('Owner address:', data.adminAddress(true, true, true)); const jettonWalletAddress = await jettonMinter.getJettonWalletAddress(address); logger.info("jetton wallet address", jettonWalletAddress.toString()) const jettonWallet = new TonWeb.token.jetton.JettonWallet(tonweb.provider, { address: jettonWalletAddress }); const jettonData = await jettonWallet.getData(); logger.info("minter address", jettonData.jettonMinterAddress.toString()); logger.info('Jetton wallet address:', address.toString(true, true, true)); const seqno = (await wallet.methods.seqno().call()) || 0; logger.info('Secno:', seqno); const comment = new Uint8Array([... new Uint8Array(4), ... new TextEncoder().encode('TS pre-sale')]); await wallet.methods.transfer({ secretKey: keyPair.secretKey, toAddress: jettonWalletAddress, // address of Jetton wallet of Jetton sender amount: TonWeb.utils.toNano('0.05'), // total amount of TONs attached to the transfer message seqno: seqno, payload: await jettonWallet.createTransferBody({ queryId: seqno, jettonAmount: transactionData.jettonsNanoAmount, // Jetton amount (in basic indivisible units) toAddress: new TonWeb.utils.Address(transactionData.toAddress), // recepient user's wallet address (not Jetton wallet) forwardAmount: TonWeb.utils.toNano('0.01'), // some amount of TONs to invoke Transfer notification message forwardPayload: comment, // text comment for Transfer notification message responseAddress: address // return the TONs after deducting commissions back to the sender's wallet address }), sendMode: 3, }).send() } ```

    Оригинал вопроса

  • Жетоны с нулевой суммой в транзакции

    TON Overflow на русском
    0 Голоса
    3 Сообщения
    27 Просмотры

    Как нам следует написать код, если мы хотим перевести Jetton с кошелька, уже подключенного к tonconnect-ui?

  • 1 Голоса
    2 Сообщения
    12 Просмотры

    Я полагаю, что на этот вопрос Владимир Плотвинов более или менее ответил в другом вопросе. Вы можете просмотреть его здесь:

    https://tonpie.io/topic/23274

    Для наглядности я перепечатаю его ответ:

    Вы получаете код выхода "-13". API вызвал lite-сервер и получил некоторый результат, вот почему вы получили 200 OK. -13 код выхода, я бы сказал, что это означает, что method_id не найден в smartcontract (но я не могу найти это замечание в документации).

  • 0 Голоса
    2 Сообщения
    6 Просмотры

    Решено

    Чтобы подключить "MyLocalTon" с помощью TonWeb, вам необходимо выполнить следующие действия:

    Установите свой собственный экземпляр TonCenter, следуя инструкциям в репозитории TonCenter GitHub: https://github.com/toncenter/ton-http-api#building-and-running

    Настройте свой экземпляр TonCenter на использование вашей локальной конфигурации сети TON, чтобы он мог подключаться к вашему LiteServer (LS). Инструкции по настройке вы можете найти здесь: https://github.com/toncenter/ton-http-api#Configuration

    Наконец, настройте TonWeb для подключения к вашему локальному экземпляру TonCenter. Как только это будет сделано, вы сможете использовать TonWeb для развертывания контрактов и взаимодействия с вашей локальной сетью TON.

    Установив и конфигурируя TonCenter и TonWeb, вы сможете установить соединение между MyLocalTon и TonWeb, что позволит вам развертывать контракты и управлять ими в вашей локальной сетевой среде TON.

  • 0 Голоса
    2 Сообщения
    5 Просмотры

    Решено

    Вы можете использовать компонент tonweb-contract пакета TonWeb.

    Сначала создайте свой класс contract:

    import {Contract} from 'web3-eth-contract'; export class MyContract extends Contract { constructor(provider, options) { // insert the bytes of your code here options.code = hexToBytes('abcd..'); super(provider, options); // add definitions of the functions of the contract this.method.myMethod = ... } // @override createDataCell() { } // @override createSigningMessage(options) { } }

    Позже вы сможете выполнить развертывание с экземпляром контракта:

    const contract = new MyContract(provider, options) const deployMethod = contract.deploy(keyPair.secretKey); await deployMethod.send();
  • 0 Голоса
    2 Сообщения
    8 Просмотры

    Один из способов, который может быть полезен, - это использование индексатора: https://github.com/tonindexer/anton

    Вы могли бы получить информацию, выполнив запрос к индексатору, подобный этому, который получает информацию для адреса EQDYo6otRICNYyM2SAcS1mzTUvm1dsN5LCteE7DjeYfKgA4C:

    https://anton.tools/api/v0/accounts?latest=true&interface=nft_item&owner_address=EQDYo6otRICNYyM2SAcS1mzTUvm1dsN5LCteE7DjeYfKgA4C&minter_address=EQAOQdwdw8kGftJCSFgOErM1mBjYPe4DBPq8-AhF6vr9si5N&order=DESC&limit=10
  • 0 Голоса
    2 Сообщения
    3 Просмотры

    Решено

    Использование метода **'getTransactions' ** было бы рекомендуемым подходом для проверки того, было ли получено конкретное сообщение по определенному адресу.

    Репозиторий примеров TON JS на Github предлагает полезные ресурсы, включая фрагмент кода JavaScript, который можно использовать для получения списка транзакций по определенному адресу.

    Пример кода можно найти по адресу https://github.com/toncenter/examples https://gist.github.com/slavafomin/1bcb401b5dc336bb4f9a2005b1660cbd.

  • 0 Голоса
    2 Сообщения
    78 Просмотры

    Решено

    По моему личному опыту, я бы использовал подобный код для отслеживания результата транзакции:

    === Your Code Parameters === ..... console.log("============================"); console.log("Interacting with Collection Contract: \n" + contract_address); let seqno: number = await wallet_address.getSeqno(); let transfer = await wallet_address.sendTransfer({ seqno: seqno, secretKey: keyPair.secretKey, messages: [ internal({ value: toNano("0.75"), to: contract_address, init: { code: init.code, data: init.data }, bounce: true, body: packed, }), ], }); console.log("Transaction sent. Waiting for confirmation..."); let intervalId = setInterval(async () => { let seqno2 = await wallet_address.getSeqno(); if (seqno2 > seqno) { console.log("✅ Transaction confirmed!\n"); clearInterval(intervalId); } }, 1000);

    Чтобы дождаться возврата "seqno", вы можете подтвердить, что транзакция была обработана валидатором. Я надеюсь, что это будет полезно."

  • 0 Голоса
    2 Сообщения
    5 Просмотры

    Сообщение об ошибке, которое вы получаете, предполагает, что переменная serializedBoc, которую вы передаете методу oneFromBoc, не является строкой. Метод slice может быть вызван только для строки, поэтому, если serializedBoc не является строкой, метод выдаст ошибку.

    В частности, возможно, что переменная jettonWalletCodeHex, которую вы передаете методу new TonWeb.token.ft.JettonMinter(), является не строкой, а проанализированным boc. Убедитесь, что jettonWalletCodeHex является строкой, прежде чем передавать ее методу.

  • 0 Голоса
    2 Сообщения
    7 Просмотры

    Порядковые номера используются для обеспечения того, чтобы блокчейн-транзакции обрабатывались в правильном порядке и не выполнялись дубликаты. При оформлении транзакции Tonweb важно включить порядковый номер получателя в данные, чтобы предотвратить ошибки или задержки в обработке.

    Правильно управляя порядковыми номерами и включая порядковый номер получателя в данные транзакции, вы можете помочь обеспечить точное и бесперебойное выполнение ваших транзакций.

  • 0 Голоса
    2 Сообщения
    8 Просмотры

    С TON и TVM вы не можете получить хэш немедленно. Хэш и значение "lt" (логическое время) будут доступны только после того, как транзакция будет добавлена в блок валидаторами.

    Существует ** два способа ** проверить, была ли транзакция успешно отправлена:

    Проверьте порядковый номер (seqno) кошелька. Если он увеличился, то, скорее всего, транзакция была отправлена.

    Проверьте адрес для совершения транзакции. Это подтвердит, была ли транзакция записана в блокчейне.

  • Как мне расшифровать ответ от getTransactions в TonWeb SDK?

    TON Overflow на русском
    0 Голоса
    2 Сообщения
    6 Просмотры

    Это интерфейс для getTransactions в typescript. Вы можете использовать его для получения дополнительной информации о том, как разобрать ответ - [ссылка на github](https://github.com/ton - сообщество/ton/blob/master/src/клиент/api/HttpApi.ts#L85)

    Возврат Tonweb содержит те же данные. То есть оба клиента используют один и тот же API

  • 0 Голоса
    2 Сообщения
    5 Просмотры

    Вы можете использовать [toncenter.com ](https://toncenter.com /) API-интерфейсы:

    Mainnet: https://toncenter.com/api/v2/jsonRPC Testnet: https://testnet.toncenter.com/api/v2/jsonRPC

  • 0 Голоса
    2 Сообщения
    12 Просмотры

    Решено

    Вы можете сохранить хэш транзакции перед ее отправкой, а затем запросить метод API Toncenter getTransactionByInMessageHash, чтобы проверить, была ли подтверждена транзакция с таким хэшем или нет

    Пример:

    // Sleep function: const sleep = ms => new Promise(r => setTimeout(r, ms)) // `msg` is a Cell containing your external message // Convert message Cell to BOC String const boc = await msg.toBoc(false) // Calculate it's hash const hash = tonweb.utils.bytesToBase64(await msg.hash()) // Send message and run a loop until transaction with that hash confirms await tonweb.sendBoc(boc) var txs = [] while (txs.length == 0) { await sleep(1200) // some delay between API calls const resp = await fetch('https://toncenter.com/api/index/getTransactionByInMessageHash?&include_msg_body=false&msg_hash=' + encodeURIComponent(hash)) txs = await resp.json() } console.log('Done!')