PHP WebShell

Текущая директория: /var/www/bitcardoApp/cron

Просмотр файла: tron_broadcast.js

// cron/tron_broadcast.js
'use strict';

const TronWebPkg = require('tronweb');
const TronWeb =
  (TronWebPkg && TronWebPkg.TronWeb) ? TronWebPkg.TronWeb :
  (TronWebPkg && TronWebPkg.default) ? TronWebPkg.default :
  TronWebPkg;

function out(obj) {
  process.stdout.write(JSON.stringify(obj));
}

function readStdin() {
  return new Promise((resolve) => {
    let data = '';
    process.stdin.setEncoding('utf8');
    process.stdin.on('data', (chunk) => data += chunk);
    process.stdin.on('end', () => resolve(data));
  });
}

function canonCoin(c) {
  c = String(c || '').trim().toUpperCase();
  if (c === 'USDT-TRC20' || c === 'USDT_TRC20' || c === 'USDTTRC20') return 'USDT';
  return c;
}

(async () => {
  try {
    const raw = await readStdin();
    let input = {};
    try { input = JSON.parse(raw || '{}'); }
    catch (e) { return out({ ok:false, error:'Input JSON parse failed', detail:String(e?.message||e) }); }

    const network = String(input.network || '').trim();
    const apiKey  = String(input.api_key || '').trim();
    const usdtContract = String(input.usdt_contract || '').trim();
    const pk = String(input.private_key || '').trim().replace(/^0x/i, '');
    const to = String(input.to || '').trim();
    const coin = canonCoin(input.coin || '');
    const amountStr = String(input.amount_coin || '').trim();
    const feeLimitSun = Number.isFinite(Number(input.fee_limit_sun))
      ? parseInt(String(input.fee_limit_sun), 10)
      : 15000000;

    if (!network) return out({ ok:false, error:'Missing network' });
    if (!pk) return out({ ok:false, error:'Missing private_key' });
    if (!to) return out({ ok:false, error:'Missing to' });
    if (!amountStr) return out({ ok:false, error:'Missing amount_coin' });

    const amountNum = Number(amountStr);
    if (!Number.isFinite(amountNum) || amountNum <= 0) {
      return out({ ok:false, error:'Invalid amount_coin', amount_coin: amountStr });
    }

    const headers = {};
    if (apiKey) headers['TRON-PRO-API-KEY'] = apiKey;

    const tronWeb = new TronWeb({ fullHost: network, privateKey: pk, headers });

    if (!tronWeb.isAddress(to)) {
      return out({ ok:false, error:'Invalid recipient address', to });
    }

    if (coin === 'TRX') {
      const sun = Math.floor(amountNum * 1e6);
      if (!(sun > 0)) return out({ ok:false, error:'TRX amount too small after conversion', sun });

      const tx = await tronWeb.transactionBuilder.sendTrx(to, sun);
      const signed = await tronWeb.trx.sign(tx);
      const receipt = await tronWeb.trx.sendRawTransaction(signed);

      if (!receipt || receipt.result !== true) {
        return out({ ok:false, error:'TRX broadcast failed', receipt });
      }
      return out({ ok:true, coin:'TRX', txid: receipt.txid, receipt });
    }

    if (coin === 'USDT') {
      if (!usdtContract) return out({ ok:false, error:'Missing usdt_contract' });

      const amountInt = Math.floor(amountNum * 1e6); // USDT 6 decimals
      if (!(amountInt > 0)) return out({ ok:false, error:'USDT amount too small after conversion', amountInt });

      const ctr = await tronWeb.contract().at(usdtContract);

      const txid = await ctr.transfer(to, amountInt).send({
        feeLimit: feeLimitSun,
        shouldPollResponse: false
      });

      if (!txid || typeof txid !== 'string') {
        return out({ ok:false, error:'USDT broadcast failed', txid });
      }
      return out({ ok:true, coin:'USDT', txid, feeLimitSun });
    }

    return out({ ok:false, error:'Unsupported coin', coin });

  } catch (e) {
    return out({ ok:false, error:'Exception', detail:String(e?.message||e) });
  }
})();

Выполнить команду


Для локальной разработки. Не используйте в интернете!