【PHP-contract】Torn Transfer from 的实现

在 PHP 中实现 TRON 的 "Transfer from" 功能,需要与 TRON 区块链进行交互。一个常见的方法是使用 TRON 的官方 PHP API 或者其他第三方库。

本文是一个使用 TRONLink 的示例,TRONLink 是 TRON 的官方钱包,允许在网页上与 TRON 区块链交互。

什么是 TRONLink:

TRONLink 是 TRON 的官方钱包,允许在网页上与 TRON 区块链交互。TRONLink 有两个版本,分别是 Chrome 插件版和网页版。本文使用的是网页版。

2. 实现的基础

  1. 安装 Compoer
  2. 安装 tronlink/php-tronlink 依赖
bash 复制代码
composer require iexbase/tron-api

3. 实现的步骤

3.1. 实现 Transfer From 功能 - 简单的示例

我们设置发送方的私钥,指定接收方的地址和转账金额,并执行了转账操作, 最后打印出转账结果。

php 复制代码
<?php

require 'vendor/autoload.php';

use IEXBase\TronAPI\Tron;

// 初始化 Tron 对象
$tron = new Tron();

// 设置发送方的私钥
$tron->setPrivateKey('your-private-key-here');

// 指定接收方的地址和转账金额
$toAddress = 'TRON-receiver-address';
$amount = 100;  // 单位是 TRX 的最小单位(sun),1 TRX = 1,000,000 sun

// 执行转账操作
try {
    $transaction = $tron->getTransactionBuilder()->sendTrx($toAddress, $amount, $tron->address);
    $signedTransaction = $tron->signTransaction($transaction);
    $result = $tron->sendRawTransaction($signedTransaction);

    // 打印结果
    print_r($result);
} catch (Exception $e) {
    echo "Error: " . $e->getMessage();
}

3.2. 通过 TRON 的智能合约地址发送 TRX 或 TRC10 代币

php 复制代码
<?php

require 'vendor/autoload.php';

use IEXBase\TronAPI\Tron;

class TronTransaction
{
    private $tron;
    private $privateKey;

    public function __construct($privateKey)
    {
        $this->tron = new Tron();
        $this->privateKey = $privateKey;
        $this->tron->setPrivateKey($privateKey);
    }

    public function sendTRX($toAddress, $amount)
    {
        try {
            $transaction = $this->tron->getTransactionBuilder()->sendTrx($toAddress, $amount, $this->tron->address);
            $signedTransaction = $this->tron->signTransaction($transaction);
            $result = $this->tron->sendRawTransaction($signedTransaction);
            return $result;
        } catch (Exception $e) {
            return "Error: " . $e->getMessage();
        }
    }

    public function sendToken($contractAddress, $toAddress, $amount)
    {
        try {
            $transaction = $this->tron->getTransactionBuilder()->sendToken($toAddress, $amount, $contractAddress);
            $signedTransaction = $this->tron->signTransaction($transaction);
            $result = $this->tron->sendRawTransaction($signedTransaction);
            return $result;
        } catch (Exception $e) {
            return "Error: " . $e->getMessage();
        }
    }
}

// 创建一个新的 TronTransaction 实例
$privateKey = 'your-private-key-here'; // 替换为的私钥
$tronTransaction = new TronTransaction($privateKey);
$sendAddress = 'send-address';

// 发送 TRX 到指定地址
// 设置接收者地址和发送数量
$trxReceiverAddress = 'receiver-address-for-TRX'; // 替换 'receiver-address-for-TRX' 为实际接收 TRX 的地址
$result = $tronTransaction->sendTRX($trxReceiverAddress, 100); // 指定金额
print_r($result);

// 发送 TRC10 代币到指定地址
// 设置代币的合约地址、接收者地址和发送数量
$tokenReceiverAddress = 'receiver-address-for-Token'; // 替换 'receiver-address-for-Token' 为实际接收代币的地址
$tokenResult = $tronTransaction->sendToken($sendAddress, $tokenReceiverAddress, 100); // 指定金额
print_r($tokenResult);
  • receiver-address-for-TRX 是接收 TRX 的 TRON 地址,是 TRON 区块链网络的原生代币。
  • receiver-address-for-Token 是接收 TRC10 代币的 TRON 地址,TRC10 是 TRON 区块链上的一种代币标准,类似于 Ethereum 的 ERC20。

3.3. 通过 TRON 的智能合约地址发送 TRC20 代币

php 复制代码
/**
 * 发送 TRC20 代币
 *
 * @param string $contractAddress TRC20 代币的合约地址
 * @param string $toAddress 接收代币的 TRON 地址
 * @param int $amount 发送的代币数量(根据代币的小数位数来计算,例如:1 代币可能需要写成 1000000,如果代币有6位小数)
 * @return array 返回交易的结果
 */
public function sendTRC20($contractAddress, $toAddress, $amount)
{
    // 校验金额,确保不为负数。金额为0是允许的。
    if ($amount < 0) {
        throw new Exception("The amount should not be negative.");
    }

    // 创建一个触发智能合约的交易
    // 这里调用了 TRC20 合约的 `transfer` 方法来发送代币
    // 参数包括接收者的地址和发送的数量
    $transaction = $this->tron->getTransactionBuilder()->triggerSmartContract(
        $contractAddress,
        'transfer(address,uint256)',
        '0',
        [
            [
                'type' => 'address',
                'value' => $toAddress
            ],
            [
                'type' => 'uint256',
                'value' => $amount
            ]
        ],
        $this->tron->address
    );

    // 签名交易
    $signedTransaction = $this->tron->signTransaction($transaction['transaction']);

    // 发送已签名的交易
    $response = $this->tron->sendRawTransaction($signedTransaction);

    return $response;
}

// 创建一个新的 TronTransaction 实例
$privateKey = 'your-private-key-here'; // 用自己的私钥替换这里
$tronTransaction = new TronTransaction($privateKey);

// TRC20 合约地址、接收者地址和要发送的代币数量
$contractAddress = 'TRC20-contract-address-here'; // 用实际的 TRC20 合约地址替换这里
$toAddress = 'receiver-address-here'; // 用接收者的 TRON 地址替换这里
$amount = 100; // 要发送的代币数量(注意:数量可能需要根据代币的小数位数进行调整)

// 发送 TRC20 代币
$response = $tronTransaction->sendTRC20($contractAddress, $toAddress, $amount);

// 打印响应
print_r($response);

3.4. "代理支付"(Gas Fee Sponsorship)或 "交易委托"(Transaction Delegation)

代理支付 (Sponsored Transactions): 允许一个账户(账户 A)支付另一个账户(账户 C)执行交易的能量或 gas 费用。这使得账户 C 能够在没有 TRX 或其他原生代币的情况下执行交易。 场景: 常见于简化用户体验的场景,如 dApps,其中用户可能没有足够的 cryptocurrency 来支付交易费用,或者开发者希望吸引和保留用户,通过支付他们的交易费用来减轻他们的负担。

这种模式在不同的区块链上有不同的实现和名称。例如,在 Ethereum 上,有一种称为 "Gas Station Network"(GSN)的系统,允许用户交易时不支付 gas 费用,而是由其他人或实体支付。

php 复制代码
/**
 * TRC20 代理支付: 使用账户A的能量,让账户C给账户B转账
 *
 * @param string $accountA 私钥 - 用于签名交易和支付能量费用
 * @param string $accountC 合约地址 - 代币将从这个地址转出
 * @param string $accountB 接收地址 - 代币将转入这个地址
 * @param int $amount 转账金额
 * @return array 返回交易结果
 */
public function sendByDelegation($accountA, $accountC, $accountB, $amount)
{
    try {
        // 设置账户A的私钥
        $this->tron->setPrivateKey($accountA);

        // 创建一个触发账户C的合约转账的交易
        // 注意: 这里需要适当的合约方法和参数
        $transaction = $this->tron->getTransactionBuilder()->triggerSmartContract(
            $accountC,
            'transfer(address,address,uint256)',  // 这里需要具体的合约方法和参数格式
            '0',
            [
                ['type' => 'address', 'value' => $accountC],
                ['type' => 'address', 'value' => $accountB],
                ['type' => 'uint256', 'value' => $amount]
            ],
            $this->tron->address
        );

        // 签名交易
        $signedTransaction = $this->tron->signTransaction($transaction['transaction']);

        // 发送已签名的交易
        $result = $this->tron->sendRawTransaction($signedTransaction);

        return $result;
    } catch (Exception $e) {
        return "Error: " . $e->getMessage();
    }
}

3.5. TRC20 的 ABI

详情阅读后续的[ABI]。

在实际情况中,当需要触发一个智能合约时,需要合约的 ABI (Application Binary Interface) 信息来正确编码和解码合约的调用和响应。这可以通过使用 TRON 网络上的相关 API 或其他方式来完成。

更新下内容:

php 复制代码
    /**
     * 发送 TRC20 代币
     *
     * @param string $contractAddress TRC20 代币的合约地址
     * @param string $toAddress 接收代币的 TRON 地址
     * @param int $amount 发送的代币数量(根据代币的小数位数来计算,例如:1 代币可能需要写成 1000000,如果代币有6位小数)
     * @return array 返回交易的结果
     */
    public function sendTRC20($contractAddress, $toAddress, $amount)
    {
        // 校验金额,确保不为负数。金额为0是允许的。
        if ($amount < 0) {
            throw new Exception("The amount should not be negative.");
        }

        // 获取合约的 ABI
        $contractABI = $this->getContractABI($contractAddress);

        // 创建一个触发智能合约的交易
        // 这里调用了 TRC20 合约的 `transfer` 方法来发送代币
        // 参数包括接收者的地址和发送的数量
        $transaction = $this->tron->getTransactionBuilder()->triggerSmartContract(
            $contractAddress,
            'transfer(address,uint256)',
            '0',
            [
                [
                    'type' => 'address',
                    'value' => $toAddress
                ],
                [
                    'type' => 'uint256',
                    'value' => $amount
                ]
            ],
            $this->tron->address,
            $contractABI,   // Call ABI
        );

        // 签名交易
        $signedTransaction = $this->tron->signTransaction($transaction['transaction']);

        // 发送已签名的交易
        $response = $this->tron->sendRawTransaction($signedTransaction);

        return $response;
    }

     /**
     * TRC20 代理支付: 使用账户A的能量,让账户C给账户B转账
     *
     * @param string $accountA 私钥 - 用于签名交易和支付能量费用
     * @param string $accountC 合约地址 - 代币将从这个地址转出
     * @param string $accountB 接收地址 - 代币将转入这个地址
     * @param int $amount 转账金额
     * @return array 返回交易结果
     */
    public function sendByDelegation($accountA, $accountC, $accountB, $amount)
    {
        try {
            // 设置账户A的私钥
            $this->tron->setPrivateKey($accountA);

            // 获取合约的 ABI
            $contractABI = $this->getContractABI($accountC);

            // 创建一个触发账户C的合约转账的交易
            // 注意: 这里需要适当的合约方法和参数
            $transaction = $this->tron->getTransactionBuilder()->triggerSmartContract(
                $accountC,
                'transfer(address,address,uint256)',  // 这里需要具体的合约方法和参数格式
                '0',
                [
                    ['type' => 'address', 'value' => $accountC],
                    ['type' => 'address', 'value' => $accountB],
                    ['type' => 'uint256', 'value' => $amount]
                ],
                $this->tron->address,
                $contractABI  // 添加 ABI 信息到方法调用
            );

            // 签名交易
            $signedTransaction = $this->tron->signTransaction($transaction['transaction']);

            // 发送已签名的交易
            $result = $this->tron->sendRawTransaction($signedTransaction);

            return $result;
        } catch (Exception $e) {
            return "Error: " . $e->getMessage();
        }
    }

    /**
     * 获取合约的 ABI
     *
     * 这里是一个抽象示例,具体实现可能需要调用 TRON 网络上的某个 API endpoint
     * @param string $contractAddress 合约地址
     * @return array 返回合约的 ABI
     * @throws Exception
     * @throws \IEXBase\TronAPI\Exception\TronException
     */
    private function getContractABI($contractAddress)
    {
        // 使用 TRON 网络 API 或其他方式获取合约的 ABI
        $apiEndpoint = "https://api.trongrid.io/v1/contracts/{$contractAddress}/abi";
        $responseJson = file_get_contents($apiEndpoint);
        $responseData = json_decode($responseJson, true);

        if (!isset($responseData['data'][0]['abi'])) {
            throw new Exception('ABI not found for the given contract address');
        }

        $contractABI = $responseData['data'][0]['abi'];

        return $contractABI;
    }

这只是一个抽象示例,具体实现可能会有所不同。例如,可以使用 TRON 网络上的某个 API 来获取合约的 ABI。

ABI

ABI (Application Binary Interface) 是用于智能合约和外部应用之间交互的接口。它是一个 JSON 对象,其中包含了智能合约的方法、输入输出参数的类型、参数顺序等信息。通过 ABI,外部应用可以正确地构造交易数据,调用智能合约的特定方法,并解析合约调用的结果。

ABI 的主要作用:

  1. 方法签名映射:ABI 包含了智能合约的方法签名,帮助外部应用确定如何调用合约的特定方法。

  2. 类型和数据转换:ABI 提供了参数和返回值的类型信息,帮助外部应用进行正确的类型和数据格式转换。

  3. 事件定义:对于 Ethereum 和其他支持事件的区块链,ABI 还包含了合约事件的定义,帮助外部应用解析和处理合约事件。

一个 ABI 的简单例子:

json 复制代码
[
  {
    "constant": false,
    "inputs": [
      {
        "name": "_value",
        "type": "uint256"
      }
    ],
    "name": "setValue",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "getValue",
    "outputs": [
      {
        "name": "",
        "type": "uint256"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  }
]

在上面的 ABI 示例中,定义了两个方法 setValuegetValuesetValue 接受一个 uint256 类型的输入参数 _value,没有输出。getValue 没有输入参数,但返回一个 uint256 类型的值。

在智能合约交互中使用 ABI:

  1. 调用合约方法:外部应用可以使用 ABI 来构造调用智能合约方法的交易数据。

  2. 解析合约调用结果:当合约方法被调用后,外部应用还可以使用 ABI 来解析方法调用的结果,将其转换为可读的格式。

  3. 处理合约事件:对于支持事件的区块链,外部应用还可以使用 ABI 来解析和处理由智能合约触发的事件。

因此,无论是在 TRON 还是在 Ethereum 等其他区块链上,ABI 都是外部应用和智能合约之间交互的关键部分。在进行合约调用时,应用需要 ABI 来确定如何正确地构造交易数据,并解析合约调用的结果。

相关推荐
许强0xq1 天前
Gas优化大师目录
web3·区块链·智能合约·solidity·foundry·ethernaut·gas优化
Joy T3 天前
Solidity智能合约开发入门攻略
web3·区块链·智能合约·solidity·以太坊·共识算法
Joy T3 天前
Solidity智能合约存储与数据结构精要
数据结构·区块链·密码学·智能合约·solidity·合约function
友莘居士6 天前
Java基于Web3j调用智能智能合约案例
java·web3·智能合约
安当加密9 天前
智能合约在分布式密钥管理系统中的应用
分布式·智能合约
RainWeb315 天前
Hardhat3-node-npm-基础版安装-V1
程序员·智能合约
天涯学馆1 个月前
Solidity多重签名合约:打造超安全的区块链投票机制
智能合约·solidity
木西1 个月前
React Native DApp 开发全栈实战·从 0 到 1 系列(完结篇)
react native·web3·智能合约
木西1 个月前
React Native DApp 开发全栈实战·从 0 到 1 系列(跨链转账-合约部分)
web3·智能合约·solidity
天涯学馆1 个月前
Solidity中实现安全的代币转账
智能合约·solidity·以太坊