From 978aab01094315f2b05ee064ab93390d20e1f4dc Mon Sep 17 00:00:00 2001 From: XDCFoundation Date: Sat, 15 Jan 2022 12:49:17 +0530 Subject: [PATCH] XDC3 Base Php --- composer.json | 21 + .../Contracts/EventLogBuilderInterface.php | 12 + src/Foundation/EventLogBuilder.php | 37 ++ src/Foundation/StandardXRC20Token.php | 269 +++++++++++++ src/Foundation/StandardXRC721.php | 206 ++++++++++ .../Transaction/SignedTransaction.php | 32 ++ src/Foundation/Transaction/Transaction.php | 27 ++ .../Transaction/TransactionBuilder.php | 68 ++++ src/Foundation/XRC.php | 125 ++++++ src/Foundation/Xdc.php | 22 ++ src/Foundation/XdcBase.php | 84 ++++ src/Token20.php | 19 + src/Token721.php | 16 + src/Utils/Address.php | 10 + src/Utils/KeyPair.php | 14 + src/Utils/Number.php | 39 ++ src/resources/xrc20.abi.json | 195 ++++++++++ src/resources/xrc721.abi.json | 366 ++++++++++++++++++ 18 files changed, 1562 insertions(+) create mode 100644 composer.json create mode 100644 src/Foundation/Contracts/EventLogBuilderInterface.php create mode 100644 src/Foundation/EventLogBuilder.php create mode 100644 src/Foundation/StandardXRC20Token.php create mode 100644 src/Foundation/StandardXRC721.php create mode 100644 src/Foundation/Transaction/SignedTransaction.php create mode 100644 src/Foundation/Transaction/Transaction.php create mode 100644 src/Foundation/Transaction/TransactionBuilder.php create mode 100644 src/Foundation/XRC.php create mode 100644 src/Foundation/Xdc.php create mode 100644 src/Foundation/XdcBase.php create mode 100644 src/Token20.php create mode 100644 src/Token721.php create mode 100644 src/Utils/Address.php create mode 100644 src/Utils/KeyPair.php create mode 100644 src/Utils/Number.php create mode 100644 src/resources/xrc20.abi.json create mode 100644 src/resources/xrc721.abi.json diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..d67e38f --- /dev/null +++ b/composer.json @@ -0,0 +1,21 @@ +{ + "name": "xdc3base/php", + "description": "This library provides simple way to interact with XRC20 and XRC721 .", + "type": "library", + "authors": [{ + "name": "XDCFoundation", + "email": "XFLW@xinfin.org" + }], + "autoload": { + "psr-4": { + "XDC3BASE\\PHP\\": "src" + } + }, + "minimum-stability": "dev", + "require": { + "php": ">=7.1", + "sc0vu/web3.php": "0.1.4", + "web3p/ethereum-util": "0.1.2", + "kornrunner/ethereum-offline-raw-tx": "0.2.4" + } +} \ No newline at end of file diff --git a/src/Foundation/Contracts/EventLogBuilderInterface.php b/src/Foundation/Contracts/EventLogBuilderInterface.php new file mode 100644 index 0000000..0de1b2e --- /dev/null +++ b/src/Foundation/Contracts/EventLogBuilderInterface.php @@ -0,0 +1,12 @@ +blockHash; + $tx['blockNumber'] = hexdec($log->blockNumber); + $tx['data'] = sprintf('%u', hexdec($log->data)); + $tx['contract'] = $log->address; + $tx['from'] = $log->topics[1]; + $tx['to'] = $log->topics[2]; + $tx['transactionHash'] = $log->transactionHash; + $tx['transactionIndex'] = hexdec($log->transactionIndex); + $tx['type'] = $this->checkTopicFunction($log->topics[0]); + + return $tx; + } + + public function setContract(XRC $contract){ + $this->contract = $contract; + } + + private function checkTopicFunction($hash){ + return array_search(str_ireplace('0x', '', $hash), $this->contract->getTopics()); + } +} diff --git a/src/Foundation/StandardXRC20Token.php b/src/Foundation/StandardXRC20Token.php new file mode 100644 index 0000000..1fbf4a5 --- /dev/null +++ b/src/Foundation/StandardXRC20Token.php @@ -0,0 +1,269 @@ + 3000000, + 'transfer' => 3000000, + 'transferFrom' => 3000000, + 'default' => 3000000 + ]; + + public function __construct($ethClient, $timeout = 10){ + $abi = file_get_contents(__DIR__ . '/../resources/xrc20.abi.json'); + parent::__construct($this->contractAddress, $abi, $ethClient, $timeout); + } + + + //XRC20_READ OPERATIONS + //1// Name Method + public function name(): string{ + return $this->call('name')[0]; + } + + //2// Symbol Method + public function symbol(): string{ + return $this->call('symbol')[0]; + } + + //3// Decimal Method + public function decimals(): int{ + if ($this->decimals) + { + return $this->decimals; + } + return $this->decimals = intval($this->call('decimals')[0]->toString()); + } + + //4// Balanceof Method + /** + * @param string $address + * @return string + */ + public function balanceOf(string $address){ + return Number::scaleDown($this->call('balanceOf', [$address])['balance']->toString(), $this->decimals()); + } + + //5// TotalSupply Method + /** + * @return string + */ + public function totalSupply(): string{ + return $this->call('totalSupply')[0]; + if ($this->totalSupply) + { + return $this->totalSupply; + } + return $this->totalSupply = intval($this->call('totalSupply')[0]->toString()); + } + + + //6// Allowance Method + public function allowance(string $ownerAddress, string $spenderAddress){ + return Number::scaleDown($this->call('allowance', [$ownerAddress, $spenderAddress])[0]->toString(), $this->decimals()); + } + + + + //XRC20_WRITE OPERATIONS + //1// TransferXDC Method for Transfer XDC + /** + * @param string $from + * @param string $to + * @param float $amount + * @return Transaction\Transaction + */ + public function transferxdc($from,$to,float $amount){ + $amount = Number::scaleUp($amount, $this->decimals()); + $amount = Number::toHex($amount); + $data = $this->buildTransferData($to, $amount); + $nonce = Number::toHex($this->getEth()->getTransactionCount($from, 'pending')); + $gasLimit = $this->getGasLimit('transferxdc'); + $gasPrice = $this->getSafeGasPrice(); + return (new TransactionBuilder()) + ->setEth($this->getEth()) + ->to($to) + ->nonce($nonce) + ->gasPrice($gasPrice) + ->gasLimit($gasLimit) + ->data($data) + ->amount($amount) + ->build(); + } + + + //2// Transfer Method For TransferToken + /** + * @param string $from + * @param string $to + * @param float $amount + * @return Transaction\Transaction + */ + public function transfer(string $from, string $to, float $amount){ + $amount = Number::scaleUp($amount, $this->decimals()); + $data = $this->buildTransferData($to, $amount); + $nonce = Number::toHex($this->getEth() + ->getTransactionCount($from, 'pending')); + $gasLimit = $this->getGasLimit('transfer'); + $gasPrice = $this->getSafeGasPrice(); + + return (new TransactionBuilder()) + ->setEth($this->getEth()) + ->to($this->contractAddress) + ->nonce($nonce) + ->gasPrice($gasPrice) + ->gasLimit($gasLimit) + ->data($data) + ->amount(0) + ->build() + ; + } + public function buildTransferData(string $to, $amount){ + return $this->getContract() + ->at($this->contractAddress) + ->getData('transfer', $to, $amount) + ; + } + + + //3// Approve Method For Gave Permission To Others To Use Our Token Balance + public function approve(string $ownerAddress, string $spenderAddress, string $amount){ + $amount = Number::scaleUp($amount, $this->decimals()); + $data = $this->buildApproveData($spenderAddress, $amount); + $nonce = Number::toHex($this->getEth() + ->getTransactionCount($ownerAddress, 'pending')); + $gasLimit = $this->getGasLimit('approve'); + $gasPrice = $this->getSafeGasPrice(); + + return (new TransactionBuilder()) + ->setEth($this->getEth()) + ->to($this->contractAddress) + ->nonce($nonce) + ->gasPrice($gasPrice) + ->gasLimit($gasLimit) + ->data($data) + ->amount(0) + ->build() + ; + } + public function buildApproveData(string $to, $amount){ + return $this->getContract() + ->at($this->contractAddress) + ->getData('approve', $to, $amount) + ; + } + + //4// Increased Allowance Method To Increase Already Approved Allowance + public function increaseAllowance(string $ownerAddress, string $spenderAddress, string $amount, string $gasLimit = 'default', string $gasPrice = 'default'){ + $original_allowance = $this->allowance($ownerAddress,$spenderAddress); + $amount = Number::scaleUp($amount + $original_allowance , $this->decimals()); + $data = $this->buildApproveData($spenderAddress, $amount); + $nonce = Number::toHex($this->getEth() + ->getTransactionCount($ownerAddress, 'pending')); + if (strtolower($gasLimit) === 'default') + { + $gasLimit = $this->getGasLimit('approve'); + } + if (strtolower($gasPrice) === 'default') + { + $gasPrice = $this->getSafeGasPrice(); + } return (new TransactionBuilder()) + ->setEth($this->getEth()) + ->to($this->contractAddress) + ->nonce($nonce) + ->gasPrice($gasPrice) + ->gasLimit($gasLimit) + ->data($data) + ->amount(0) + ->build() + ; + } + + + //5// Decrease Allowance Method To Decrease Already Approved Allowance + public function decreaseAllowance(string $ownerAddress, string $spenderAddress, string $amount, string $gasLimit = 'default', string $gasPrice = 'default'){ + $original_allowance = $this->allowance($ownerAddress,$spenderAddress); + $amount = Number::scaleUp( $original_allowance - $amount, $this->decimals()); + // $am = $this->allowance($spenderAddress, $ownerAddress, $this->decimals())+ $amount; + $data = $this->buildApproveData($spenderAddress, $amount); + $nonce = Number::toHex($this->getEth() + ->getTransactionCount($ownerAddress, 'pending')); + if (strtolower($gasLimit) === 'default') + { + $gasLimit = $this->getGasLimit('approve'); + } + if (strtolower($gasPrice) === 'default') + { + $gasPrice = $this->getSafeGasPrice(); + } return (new TransactionBuilder()) + ->setEth($this->getEth()) + ->to($this->contractAddress) + ->nonce($nonce) + ->gasPrice($gasPrice) + ->gasLimit($gasLimit) + ->data($data) + ->amount(0) + ->build() + ; + } + + + //6// TransferFrom Method to Send Token Balance From One Account To Other Account By Using allowance Get By Others + /** + * @param string $spender + * @param string $from + * @param string $to + * @param float $amount + * @return Transaction\Transaction + */ + public function transferFrom(string $spender, string $from, string $to, float $amount){ + $amount = Number::scaleUp($amount, $this->decimals()); + $data = $this->buildTransferFromData($from, $to, $amount); + $nonce = Number::toHex($this->getEth() + ->getTransactionCount($spender, 'pending')); + $gasLimit = $this->getGasLimit('transferFrom'); + $gasPrice = $this->getSafeGasPrice(); + return (new TransactionBuilder()) + ->setEth($this->getEth()) + ->to($this->contractAddress) + ->nonce($nonce) + ->gasPrice($gasPrice) + ->gasLimit($gasLimit) + ->data($data) + ->amount(0) + ->build() + ; + } + public function buildTransferFromData(string $from, string $to, $amount){ + return $this->getContract() + ->at($this->contractAddress) + ->getData('transferFrom', $from, $to, $amount) + ; + } + + public function getGasLimit($action = ''){ + return isset($this->gasLimits[$action]) ? $this->gasLimits[$action] : $this->gasLimits['default']; + } + public function getSafeGasPrice(){ + $gasPrice = $this->getEth() + ->gasPrice() + ; + + $modified = floatval(Number::fromWei($gasPrice, 'gwei')) + $this->gasPriceModifier; + return Number::toWei($modified, 'gwei') + ->toString() + ; + } +} diff --git a/src/Foundation/StandardXRC721.php b/src/Foundation/StandardXRC721.php new file mode 100644 index 0000000..74cad09 --- /dev/null +++ b/src/Foundation/StandardXRC721.php @@ -0,0 +1,206 @@ + 3000000, + 'transfer' => 3000000, + 'transferFrom' => 3000000, + 'default' => 3000000 + ]; + + + public function __construct($ethClient, $timeout = 10){ + $abi = file_get_contents(__DIR__ . '/../resources/xrc721.abi.json'); + parent::__construct($this->contractAddress, $abi, $ethClient, $timeout); + } + + public function name(): string{ + return $this->call('name')[0]; + } + + public function symbol(): string{ + return $this->call('symbol')[0]; + } + + public function totalSupply(): string{ + return $this->call('totalSupply')[0]; + } + + public function ownerOf(int $tokenId) { + return $this->call('ownerOf', [$tokenId])[0]; + } + + public function balanceOf(string $ownerAddress){ + $balance = ($this->call('balanceOf', [$ownerAddress])[0]->toString()); + return $balance; + } + + public function tokenURI(int $tokenId) { + return $this->call('tokenURI', [$tokenId])[0]; + } + + public function tokenByIndex(int $index) { + return $this->call('tokenByIndex', [$index])[0]; + } + + public function tokenOfOwnerByIndex(String $ownerAddress,int $index) { + return $this->call('tokenOfOwnerByIndex', [$ownerAddress,$index])[0]; + } + + public function supportsInterface(String $interfaceId) { + $result = ($this->call('supportsInterface', [$interfaceId])[0]); + if ($result==1){ + return "True"; + }else{ + return "False"; + } + } + + public function approve721(string $to, int $tokenId){ + $data = $this->buildApproveData($to, $tokenId); + $ownerAddress = $this->ownerOf($tokenId); + $nonce = Number::toHex($this->getEth() + ->getTransactionCount( $ownerAddress, 'pending')); + $gasLimit = $this->getGasLimit('approve'); + $gasPrice = $this->getSafeGasPrice(); + return (new TransactionBuilder()) + ->setEth($this->getEth()) + ->to($this->contractAddress) + ->nonce($nonce) + ->gasPrice($gasPrice) + ->gasLimit($gasLimit) + ->data($data) + ->amount(0) + ->build(); + } + public function buildApproveData(string $to, int $tokenId){ + return $this->getContract() + ->at($this->contractAddress) + ->getData('approve', $to, $tokenId); + } + + public function getApproved(int $tokenId) { + return $this->call('getApproved', [$tokenId])[0]; + } + + public function transfer( string $from, string $to, int $tokenId){ + $data = $this->buildTTransferData($from, $to, $tokenId); + $nonce = Number::toHex($this->getEth() + ->getTransactionCount($from, 'pending')); + $gasLimit = $this->getGasLimit('transferFrom'); + $gasPrice = $this->getSafeGasPrice(); return (new TransactionBuilder()) + ->setEth($this->getEth()) + ->to($this->contractAddress) + ->nonce($nonce) + ->gasPrice($gasPrice) + ->gasLimit($gasLimit) + ->data($data) + ->amount(0) + ->build(); + } + public function buildTTransferData(string $from, string $to, int $tokenId){ + return $this->getContract() + ->at($this->contractAddress) + ->getData('transferFrom', $from, $to, $tokenId); + } + + public function transferFrom721( string $from, string $to, int $tokenId){ + $data = $this->buildTransferFromData($from, $to, $tokenId); + $ownerAddress= $this->getApproved($tokenId); + $nonce = Number::toHex($this->getEth() + ->getTransactionCount($ownerAddress, 'pending')); + $gasLimit = $this->getGasLimit('transferFrom'); + $gasPrice = $this->getSafeGasPrice(); + return (new TransactionBuilder()) + ->setEth($this->getEth()) + ->to($this->contractAddress) + ->nonce($nonce) + ->gasPrice($gasPrice) + ->gasLimit($gasLimit) + ->data($data) + ->amount(0) + ->build(); + } + public function buildTransferFromData(string $from, string $to, int $tokenId){ + return $this->getContract() + ->at($this->contractAddress) + ->getData('transferFrom', $from, $to, $tokenId); + } + + public function safeTransferFrom( string $from, string $to, int $tokenId){ + $data = $this->buildSafeTransferFromData($from, $to, $tokenId); + $ownerAddress= $this->getApproved($tokenId); + $nonce = Number::toHex($this->getEth() + ->getTransactionCount($ownerAddress, 'pending')); + $gasLimit = $this->getGasLimit('transferFrom'); + $gasPrice = $this->getSafeGasPrice(); + return (new TransactionBuilder()) + ->setEth($this->getEth()) + ->to($this->contractAddress) + ->nonce($nonce) + ->gasPrice($gasPrice) + ->gasLimit($gasLimit) + ->data($data) + ->amount(0) + ->build(); + } + public function buildSafeTransferFromData(string $from, string $to, int $tokenId){ + return $this->getContract() + ->at($this->contractAddress) + ->getData('safeTransferFrom', $from, $to, $tokenId); + } + + public function setApprovalForAll( string $to, bool $approve, $tokenId){ + $data = $this->buildsetApprovalForAllData($to, $approve); + $ownerAddress = $this->ownerOf($tokenId); + $nonce = Number::toHex($this->getEth() + ->getTransactionCount( $ownerAddress , 'pending')); + $gasLimit = $this->getGasLimit('approve'); + $gasPrice = $this->getSafeGasPrice(); + return (new TransactionBuilder()) + ->setEth($this->getEth()) + ->to($this->contractAddress) + ->nonce($nonce) + ->gasPrice($gasPrice) + ->gasLimit($gasLimit) + ->data($data) + ->amount(0) + ->build(); + } + public function buildsetApprovalForAllData(string $to, bool $approve){ + return $this->getContract() + ->at($this->contractAddress) + ->getData('setApprovalForAll', $to, $approve); + } + + public function isApprovedForAll( string $owner, string $operator) : bool{ + return $this->call('isApprovedForAll', [$owner, $operator])[0]; + } + + public function getGasLimit($action = ''){ + return isset($this->gasLimits[$action]) ? $this->gasLimits[$action] : $this->gasLimits['default']; + } + public function getSafeGasPrice(){ + $gasPrice = $this->getEth() + ->gasPrice() + ; + + $modified = floatval(Number::fromWei($gasPrice, 'gwei')) + $this->gasPriceModifier; + return Number::toWei($modified, 'gwei') + ->toString() + ; + } +} diff --git a/src/Foundation/Transaction/SignedTransaction.php b/src/Foundation/Transaction/SignedTransaction.php new file mode 100644 index 0000000..5eb946e --- /dev/null +++ b/src/Foundation/Transaction/SignedTransaction.php @@ -0,0 +1,32 @@ +hash = $hash; + $this->eth = $eth; + } + + public function getSignedHash(){ + return $this->hash; + } + + /** + * @return string + * @throws Exception + */ + public function send(){ + if (!isset($this->eth)){ + throw new Exception('XDC client not provided. Signed transaction have not be broadcasted'); + } + return $this->eth->sendRawTransaction($this->hash); + } +} diff --git a/src/Foundation/Transaction/Transaction.php b/src/Foundation/Transaction/Transaction.php new file mode 100644 index 0000000..0857ef7 --- /dev/null +++ b/src/Foundation/Transaction/Transaction.php @@ -0,0 +1,27 @@ +transaction = $transaction; + $this->eth = $eth; + } + + public function sign($privateKey){ + $privateKey = str_replace('0x', '', $privateKey); + return new SignedTransaction('0x' . $this->transaction->getRaw($privateKey), $this->eth); + } +} diff --git a/src/Foundation/Transaction/TransactionBuilder.php b/src/Foundation/Transaction/TransactionBuilder.php new file mode 100644 index 0000000..e151e1f --- /dev/null +++ b/src/Foundation/Transaction/TransactionBuilder.php @@ -0,0 +1,68 @@ +eth = $eth; + return $this; + } + + + public function nonce(string $nonce){ + $this->nonce = $nonce; + return $this; + } + + public function to(string $to){ + $this->to = $to; + return $this; + } + + public function amount(string $amount){ + $this->amount = $amount; + return $this; + } + + public function gasPrice(string $gasPrice){ + $this->gasPrice = $gasPrice; + return $this; + } + + public function gasLimit(string $gasLimit){ + $this->gasLimit = $gasLimit; + return $this; + } + + public function data(string $data){ + $this->data = $data; + return $this; + } + + public function build(){ + return new Transaction(new BaseTransaction($this->nonce, $this->gasPrice, $this->gasLimit, $this->to, $this->amount, $this->data), $this->eth); + } +} diff --git a/src/Foundation/XRC.php b/src/Foundation/XRC.php new file mode 100644 index 0000000..643e00f --- /dev/null +++ b/src/Foundation/XRC.php @@ -0,0 +1,125 @@ +web3 = $web3; + $this->abi = $abi; + $this->contractAddress = $contractAddress; + $this->contract = new Contract($web3->getProvider(), $abi); + $this->eth = new Xdc($web3); + $this->generateTopics(); + } + + /** + * @param string $method + * @param array $arguments + * @return array|null + */ + public function call(string $method, array $arguments = []) + { + $params = [$method]; + foreach ($arguments as $argument) + { + $params[] = $argument; + } + $result = null; + $params[] = function ($err, $response) use (&$result) { + if ($err) + { + throw $err; + } + $result = $response; + }; + call_user_func_array([$this->contract->at($this->contractAddress), 'call'], $params); + + return $result; + } + + /** + * @return array + */ + public function getTopics() + { + return $this->topics; + } + + /** + * @return Contract + */ + public function getContract() + { + return $this->contract; + } + + /** + * @return Eth + */ + public function getEth() + { + return $this->eth; + } + + /** + * @return Web3 + */ + public function getWeb3() + { + return $this->web3; + } + + private function generateTopics() + { + $events = $this->contract->getEvents(); + foreach ($events as $key => $event) + { + $topic = sprintf("%s(%s)", $key, implode(',', array_column($event['inputs'], 'type'))); + $this->topics[$key] = Keccak::hash($topic, 256); + } + } +} diff --git a/src/Foundation/Xdc.php b/src/Foundation/Xdc.php new file mode 100644 index 0000000..b6d489b --- /dev/null +++ b/src/Foundation/Xdc.php @@ -0,0 +1,22 @@ +call('getTransactionCount', [$address, $blockParameter]) + ->toString(); + } + + public function gasPrice(){ + return $this->call('gasPrice') + ->toString(); + } + + public function sendRawTransaction(string $hash){ + return (string)$this->call('sendRawTransaction', [$hash]); + } +} diff --git a/src/Foundation/XdcBase.php b/src/Foundation/XdcBase.php new file mode 100644 index 0000000..5709e13 --- /dev/null +++ b/src/Foundation/XdcBase.php @@ -0,0 +1,84 @@ +web3 = $web3; + $this->eth = new BaseEth($this->web3->getProvider()); + } + + /** + * @param string $method + * @param array $arguments + * @return object + */ + public function call(string $method, array $arguments = []){ + foreach ($arguments as $argument){ + $params[] = $argument; + } + $result = null; + $params[] = function ($err, $response) use (&$result) { + if ($err){ + throw $err; + } + $result = $response; + }; + call_user_func_array([$this->eth, $method], $params); + return $result; + } + + public function addCall(string $id, string $method, array $arguments = []){ + $this->batchCalls[$id] = ['method' => $method, 'params' => $arguments]; + return $this; + } + + + public function batchCall(){ + $this->eth->batch(true); + $callResultMap = []; + $counter = 0; + foreach ($this->batchCalls as $key => $call) + { + $callResultMap[$counter] = $key; + call_user_func_array([$this->eth, $call['method']], $call['params']); + $counter++; + } + + $result = null; + // $this->eth->getProvider() + // ->execute(function ($err, $responses) use (&$result, $callResultMap) { + // if ($err) + // { + // throw $err; + // } + + // foreach ($responses as $key => $response) + // { + // $result[$callResultMap[$key]] = $response; + // } + // }); + + return $result; + } + +} diff --git a/src/Token20.php b/src/Token20.php new file mode 100644 index 0000000..84673b0 --- /dev/null +++ b/src/Token20.php @@ -0,0 +1,19 @@ +contractAddress = $contractAddress; + parent::__construct($ethClient, $timeout); + } + +} diff --git a/src/Token721.php b/src/Token721.php new file mode 100644 index 0000000..0a70b29 --- /dev/null +++ b/src/Token721.php @@ -0,0 +1,16 @@ +contractAddress = $contractAddress; + parent::__construct($ethClient, $timeout); + } + +} diff --git a/src/Utils/Address.php b/src/Utils/Address.php new file mode 100644 index 0000000..726e595 --- /dev/null +++ b/src/Utils/Address.php @@ -0,0 +1,10 @@ +privateKeyToPublicKey($privateKey); + return $util->publicKeyToAddress($publicKey); + } +} diff --git a/src/Utils/Number.php b/src/Utils/Number.php new file mode 100644 index 0000000..1c26c89 --- /dev/null +++ b/src/Utils/Number.php @@ -0,0 +1,39 @@ +multiply(new BigInteger($base)); + } + return $number; + } + + public static function fromWei($number, $unit){ + list($decimal, $precious) = Utils::fromWei($number, $unit); + return $decimal->toString() . '.' . $precious->toString(); + } + + public static function toWei($number, $unit){ + return Utils::toWei($number, $unit); + } + + public static function toHex($number){ + return Utils::toHex($number); + } +} diff --git a/src/resources/xrc20.abi.json b/src/resources/xrc20.abi.json new file mode 100644 index 0000000..342b664 --- /dev/null +++ b/src/resources/xrc20.abi.json @@ -0,0 +1,195 @@ +[{ + "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": "", + "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": "", + "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": "owner", + "type": "address" + }], + "name": "balanceOf", + "outputs": [{ + "name": "balance", + "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": [{ + "name": "", + "type": "bool" + }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [{ + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [{ + "name": "", + "type": "uint256" + }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "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" + }, + { + "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" + } +] \ No newline at end of file diff --git a/src/resources/xrc721.abi.json b/src/resources/xrc721.abi.json new file mode 100644 index 0000000..2fa305f --- /dev/null +++ b/src/resources/xrc721.abi.json @@ -0,0 +1,366 @@ +[{ + "constant": true, + "inputs": [{ + "name": "interfaceId", + "type": "bytes4" + }], + "name": "supportsInterface", + "outputs": [{ + "name": "", + "type": "bool" + }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [{ + "name": "", + "type": "string" + }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [{ + "name": "tokenId", + "type": "uint256" + }], + "name": "getApproved", + "outputs": [{ + "name": "", + "type": "address" + }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [{ + "name": "to", + "type": "address" + }, + { + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "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": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [{ + "name": "owner", + "type": "address" + }, + { + "name": "index", + "type": "uint256" + } + ], + "name": "tokenOfOwnerByIndex", + "outputs": [{ + "name": "", + "type": "uint256" + }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [{ + "name": "from", + "type": "address" + }, + { + "name": "to", + "type": "address" + }, + { + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [{ + "name": "index", + "type": "uint256" + }], + "name": "tokenByIndex", + "outputs": [{ + "name": "", + "type": "uint256" + }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [{ + "name": "tokenId", + "type": "uint256" + }], + "name": "ownerOf", + "outputs": [{ + "name": "", + "type": "address" + }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [{ + "name": "owner", + "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": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [{ + "name": "from", + "type": "address" + }, + { + "name": "to", + "type": "address" + }, + { + "name": "tokenId", + "type": "uint256" + }, + { + "name": "_data", + "type": "bytes" + } + ], + "name": "safeTransferFrom1", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [{ + "name": "tokenId", + "type": "uint256" + }], + "name": "tokenURI", + "outputs": [{ + "name": "", + "type": "string" + }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [{ + "name": "_to", + "type": "address" + }, + { + "name": "_tokenId", + "type": "uint256" + }, + { + "name": "_uri", + "type": "string" + } + ], + "name": "mint", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [{ + "name": "owner", + "type": "address" + }, + { + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [{ + "name": "", + "type": "bool" + }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ + "name": "name", + "type": "string" + }, + { + "name": "symbol", + "type": "string" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [{ + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": true, + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [{ + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [{ + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + } +] \ No newline at end of file