Contract new method.
This commit is contained in:
parent
b87e836fc5
commit
b833dfebb7
300
src/Contract.php
Normal file
300
src/Contract.php
Normal file
@ -0,0 +1,300 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of web3.php package.
|
||||
*
|
||||
* (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
|
||||
*
|
||||
* @author Peter Lai <alk03073135@gmail.com>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace Web3;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Web3\Providers\Provider;
|
||||
use Web3\Providers\HttpProvider;
|
||||
use Web3\RequestManagers\RequestManager;
|
||||
use Web3\RequestManagers\HttpRequestManager;
|
||||
use Web3\Utils;
|
||||
use Web3\Eth;
|
||||
use Web3\Contracts\Ethabi;
|
||||
use Web3\Contracts\Types\Address;
|
||||
use Web3\Contracts\Types\Boolean;
|
||||
use Web3\Contracts\Types\Bytes;
|
||||
use Web3\Contracts\Types\Integer;
|
||||
use Web3\Contracts\Types\Str;
|
||||
use Web3\Contracts\Types\Uinteger;
|
||||
|
||||
class Contract
|
||||
{
|
||||
/**
|
||||
* provider
|
||||
*
|
||||
* @var \Web3\Providers\Provider
|
||||
*/
|
||||
protected $provider;
|
||||
|
||||
/**
|
||||
* abi
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $abi;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $constructor = [];
|
||||
|
||||
/**
|
||||
* functions
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $functions = [];
|
||||
|
||||
/**
|
||||
* events
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $events = [];
|
||||
|
||||
/**
|
||||
* toAddress
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $toAddress;
|
||||
|
||||
/**
|
||||
* eth
|
||||
*
|
||||
* @var \Web3\Eth
|
||||
*/
|
||||
protected $eth;
|
||||
|
||||
/**
|
||||
* ethabi
|
||||
*
|
||||
* @var \Web3\Contracts\Ethabi
|
||||
*/
|
||||
protected $ethabi;
|
||||
|
||||
/**
|
||||
* construct
|
||||
*
|
||||
* @param mixed string | Web3\Providers\Provider $provider
|
||||
* @param mixed string | stdClass | array $abi
|
||||
* @param string $toAddress
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($provider, $abi, $toAddress='')
|
||||
{
|
||||
if (is_string($provider) && (filter_var($provider, FILTER_VALIDATE_URL) !== false)) {
|
||||
// check the uri schema
|
||||
if (preg_match('/^https?:\/\//', $provider) === 1) {
|
||||
$requestManager = new HttpRequestManager($provider);
|
||||
|
||||
$this->provider = new HttpProvider($requestManager);
|
||||
}
|
||||
} else if ($provider instanceof Provider) {
|
||||
$this->provider = $provider;
|
||||
}
|
||||
$abi = Utils::jsonToArray($abi, 5);
|
||||
|
||||
foreach ($abi as $item) {
|
||||
if (isset($item['type'])) {
|
||||
if ($item['type'] === 'function') {
|
||||
$this->functions[$item['name']] = $item;
|
||||
} elseif ($item['type'] === 'constructor') {
|
||||
$this->constructor = $item;
|
||||
} elseif ($item['type'] === 'event') {
|
||||
$this->events[$item['name']] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->abi = $abi;
|
||||
|
||||
if (is_string($toAddress)) {
|
||||
$this->toAddress = $toAddress;
|
||||
}
|
||||
$this->eth = new Eth($this->provider);
|
||||
$this->ethabi = new Ethabi([
|
||||
'address' => new Address,
|
||||
'bool' => new Boolean,
|
||||
'bytes' => new Bytes,
|
||||
'int' => new Integer,
|
||||
'string' => new Str,
|
||||
'uint' => new Uinteger,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* call
|
||||
*
|
||||
* @param string $name
|
||||
* @param array $arguments
|
||||
* @return void
|
||||
*/
|
||||
// public function __call($name, $arguments)
|
||||
// {
|
||||
// if (empty($this->provider)) {
|
||||
// throw new \RuntimeException('Please set provider first.');
|
||||
// }
|
||||
|
||||
// $class = explode('\\', get_class());
|
||||
|
||||
// if (preg_match('/^[a-zA-Z0-9]+$/', $name) === 1) {
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* get
|
||||
*
|
||||
* @param string $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
$method = 'get' . ucfirst($name);
|
||||
|
||||
if (method_exists($this, $method)) {
|
||||
return call_user_func_array([$this, $method], []);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
{
|
||||
$method = 'set' . ucfirst($name);
|
||||
|
||||
if (method_exists($this, $method)) {
|
||||
return call_user_func_array([$this, $method], [$value]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* getProvider
|
||||
*
|
||||
* @return \Web3\Providers\Provider
|
||||
*/
|
||||
public function getProvider()
|
||||
{
|
||||
return $this->provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* setProvider
|
||||
*
|
||||
* @param $provider
|
||||
* @return bool
|
||||
*/
|
||||
public function setProvider($provider)
|
||||
{
|
||||
if ($provider instanceof Provider) {
|
||||
$this->provider = $provider;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* getFunctions
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
return $this->functions;
|
||||
}
|
||||
|
||||
/**
|
||||
* getEvents
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getEvents()
|
||||
{
|
||||
return $this->events;
|
||||
}
|
||||
|
||||
/**
|
||||
* getConstructor
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getConstructor()
|
||||
{
|
||||
return $this->constructor;
|
||||
}
|
||||
|
||||
/**
|
||||
* getAbr
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAbi()
|
||||
{
|
||||
return $this->abi;
|
||||
}
|
||||
|
||||
/**
|
||||
* getEth
|
||||
*
|
||||
* @return \Web3\Eth
|
||||
*/
|
||||
public function getEth()
|
||||
{
|
||||
return $this->eth;
|
||||
}
|
||||
|
||||
/**
|
||||
* new
|
||||
* Deploy a contruct with params.
|
||||
*
|
||||
* @param mixed
|
||||
* @return void
|
||||
*/
|
||||
public function new()
|
||||
{
|
||||
if (isset($this->constructor)) {
|
||||
$constructor = $this->constructor;
|
||||
$arguments = func_get_args();
|
||||
$callback = array_pop($arguments);
|
||||
|
||||
if (count($arguments) < count($constructor['inputs'])) {
|
||||
throw new InvalidArgumentException('Please make sure you have put all constructor params and callback.');
|
||||
}
|
||||
if (is_callable($callback) !== true) {
|
||||
throw new \InvalidArgumentException('The last param must be callback function.');
|
||||
}
|
||||
$params = array_splice($arguments, 0, count($constructor['inputs']));
|
||||
$data = $this->ethabi->encodeParameters($constructor, $params);
|
||||
$transaction = [];
|
||||
|
||||
if (count($arguments) > 0) {
|
||||
$transaction = $arguments[0];
|
||||
}
|
||||
$transaction['to'] = '';
|
||||
$transaction['data'] = $data;
|
||||
|
||||
$this->eth->sendTransaction($transaction, function ($err, $transaction) use ($callback){
|
||||
if ($err !== null) {
|
||||
return call_user_func($callback, $err, null);
|
||||
}
|
||||
return call_user_func($callback, null, $transaction);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
339
test/unit/ContractTest.php
Normal file
339
test/unit/ContractTest.php
Normal file
@ -0,0 +1,339 @@
|
||||
<?php
|
||||
|
||||
namespace Test\Unit;
|
||||
|
||||
use Test\TestCase;
|
||||
use Web3\Contract;
|
||||
|
||||
class ContractTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* contract
|
||||
*
|
||||
* @var \Web3\Contract
|
||||
*/
|
||||
protected $contract;
|
||||
|
||||
/**
|
||||
* testAbi
|
||||
* GameToken abi from https://github.com/sc0Vu/GameToken
|
||||
*
|
||||
* @var \Web3\Contract
|
||||
*/
|
||||
protected $testAbi = '[
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "name",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "approve",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "success",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "totalSupply",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transferFrom",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "success",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "decimals",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint8"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "standard",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "balanceOf",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "symbol",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transfer",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "allowance",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"name": "initialSupply",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "tokenName",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "decimalUnits",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"name": "tokenSymbol",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "constructor"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Transfer",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Approval",
|
||||
"type": "event"
|
||||
}
|
||||
]';
|
||||
|
||||
/**
|
||||
* accounts
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $accounts;
|
||||
|
||||
/**
|
||||
* setUp
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
// $this->contract = new Contract('http://localhost:8545', $this->testAbi);
|
||||
$this->contract = new Contract($this->web3->provider, $this->testAbi);
|
||||
$this->contract->eth->accounts(function ($err, $accounts) {
|
||||
if ($err === null) {
|
||||
if (isset($accounts->result)) {
|
||||
$this->accounts = $accounts->result;
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* testDeploy
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDeploy()
|
||||
{
|
||||
$contract = $this->contract;
|
||||
|
||||
// var_dump($this->contract->constructor);
|
||||
if (!isset($this->accounts[0])) {
|
||||
$account = '0x407d73d8a49eeb85d32cf465507dd71d507100c1';
|
||||
} else {
|
||||
$account = $this->accounts[0];
|
||||
}
|
||||
$contract->new(10000, 'Game Token', 1, 'GT', [
|
||||
'from' => $account
|
||||
], function ($err, $result) use ($contract) {
|
||||
if ($err !== null) {
|
||||
// infura api gg
|
||||
return $this->assertTrue($err !== null);
|
||||
}
|
||||
if ($result->result) {
|
||||
echo "\nTransaction has made:) id: " . $result->result . "\n";
|
||||
}
|
||||
$transactionId = $result->result;
|
||||
$this->assertTrue((preg_match('/^0x[a-f0-9]{64}$/', $transactionId) === 1));
|
||||
|
||||
$contract->eth->getTransactionReceipt($transactionId, function ($err, $transaction) {
|
||||
if ($err !== null) {
|
||||
return $this->fail($err);
|
||||
}
|
||||
if ($transaction->result) {
|
||||
echo "\nTransaction has mind:) block number: " . $transaction->result->blockNumber . "\n";
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user