...
 
...@@ -39,4 +39,7 @@ MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" ...@@ -39,4 +39,7 @@ MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
RPC_URL= RPC_URL=
WALLET_ADDRESS= WALLET_ADDRESS=
\ No newline at end of file
GITLAB_URL=
GITLAB_ACCESS_TOKEN=
\ No newline at end of file
<?php
namespace App\Console\Commands;
use App\Project;
use GitLab\Connection;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
class fetchMergeRequests extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'gitlab:fetch-proposals';
/**
* The console command description.
*
* @var string
*/
protected $description = 'fetch all the proposal merge requests from gitlab';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$connection = new Connection(new Client());
$projects = $connection->mergeRequests('all');
foreach ($projects as $project) {
// create requests that are still pending
$project = Project::firstOrNew([
'merge_request_id' => $project->id
],[
'title' => $project->title,
'state' => $project->state
]);
// check if there is a payment_id and an address
// check if the amount field has been supplied
$project->save();
}
// id, title, state, username,
// save merge requests
// compare to current merge requests
// if merge request is missing is it closed or merged
return;
}
/**
* Gets the ffs amount requested from a file
*
* @param string $filename
* @return int
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
public function getAmountFromText($filename = 'test-ffs.md')
{
$input = Storage::get($filename);
$lines = preg_split('/\r\n|\r|\n/', $input);
foreach($lines as $line) {
$line = str_replace(' ','', $line);
$details = explode(':', $line);
if ($details[0] === 'amount') {
return $details[1];
}
}
return 0;
}
}
...@@ -27,9 +27,16 @@ use SimpleSoftwareIO\QrCode\Facades\QrCode; ...@@ -27,9 +27,16 @@ use SimpleSoftwareIO\QrCode\Facades\QrCode;
* @method static \Illuminate\Database\Eloquent\Builder|\App\Project whereTargetAmount($value) * @method static \Illuminate\Database\Eloquent\Builder|\App\Project whereTargetAmount($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\Project whereUpdatedAt($value) * @method static \Illuminate\Database\Eloquent\Builder|\App\Project whereUpdatedAt($value)
* @mixin \Eloquent * @mixin \Eloquent
* @property string $title
* @property int|null $merge_request_id
* @property string|null $commit_sha
* @method static \Illuminate\Database\Eloquent\Builder|\App\Project whereCommitSha($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\Project whereMergeRequestId($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\Project whereTitle($value)
*/ */
class Project extends Model class Project extends Model
{ {
protected $guarded = ['id'];
/** /**
* @return \Illuminate\Database\Eloquent\Relations\HasMany * @return \Illuminate\Database\Eloquent\Relations\HasMany
*/ */
......
...@@ -6,9 +6,12 @@ ...@@ -6,9 +6,12 @@
"type": "project", "type": "project",
"require": { "require": {
"php": "^7.1.3", "php": "^7.1.3",
"ext-curl": "*",
"ext-json": "*",
"barryvdh/laravel-ide-helper": "^2.5", "barryvdh/laravel-ide-helper": "^2.5",
"doctrine/dbal": "^2.8", "doctrine/dbal": "^2.8",
"fideloper/proxy": "^4.0", "fideloper/proxy": "^4.0",
"guzzlehttp/guzzle": "^6.3",
"laravel/framework": "5.7.*", "laravel/framework": "5.7.*",
"laravel/tinker": "^1.0", "laravel/tinker": "^1.0",
"simplesoftwareio/simple-qrcode": "2.0.*" "simplesoftwareio/simple-qrcode": "2.0.*"
...@@ -28,7 +31,8 @@ ...@@ -28,7 +31,8 @@
], ],
"psr-4": { "psr-4": {
"App\\": "app/", "App\\": "app/",
"Monero\\": "monero/" "Monero\\": "monero/",
"GitLab\\": "gitlab/"
} }
}, },
"autoload-dev": { "autoload-dev": {
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "7a5d7380ba557e7bdee9c9e7a997e459", "content-hash": "37462f3e9af90094d49d90514b64ae96",
"packages": [ "packages": [
{ {
"name": "bacon/bacon-qr-code", "name": "bacon/bacon-qr-code",
...@@ -1066,6 +1066,187 @@ ...@@ -1066,6 +1066,187 @@
], ],
"time": "2018-02-07T20:20:57+00:00" "time": "2018-02-07T20:20:57+00:00"
}, },
{
"name": "guzzlehttp/guzzle",
"version": "6.3.3",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba",
"reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba",
"shasum": ""
},
"require": {
"guzzlehttp/promises": "^1.0",
"guzzlehttp/psr7": "^1.4",
"php": ">=5.5"
},
"require-dev": {
"ext-curl": "*",
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0",
"psr/log": "^1.0"
},
"suggest": {
"psr/log": "Required for using the Log middleware"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "6.3-dev"
}
},
"autoload": {
"files": [
"src/functions_include.php"
],
"psr-4": {
"GuzzleHttp\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "[email protected]",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Guzzle is a PHP HTTP client library",
"homepage": "http://guzzlephp.org/",
"keywords": [
"client",
"curl",
"framework",
"http",
"http client",
"rest",
"web service"
],
"time": "2018-04-22T15:46:56+00:00"
},
{
"name": "guzzlehttp/promises",
"version": "v1.3.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646",
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646",
"shasum": ""
},
"require": {
"php": ">=5.5.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Promise\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "[email protected]",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Guzzle promises library",
"keywords": [
"promise"
],
"time": "2016-12-20T10:07:11+00:00"
},
{
"name": "guzzlehttp/psr7",
"version": "1.4.2",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
"reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
"shasum": ""
},
"require": {
"php": ">=5.4.0",
"psr/http-message": "~1.0"
},
"provide": {
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Psr7\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "[email protected]",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Tobias Schultze",
"homepage": "https://github.com/Tobion"
}
],
"description": "PSR-7 message implementation that also provides common utility methods",
"keywords": [
"http",
"message",
"request",
"response",
"stream",
"uri",
"url"
],
"time": "2017-03-20T17:10:46+00:00"
},
{ {
"name": "jakub-onderka/php-console-color", "name": "jakub-onderka/php-console-color",
"version": "v0.2", "version": "v0.2",
...@@ -1846,6 +2027,56 @@ ...@@ -1846,6 +2027,56 @@
], ],
"time": "2017-02-14T16:28:37+00:00" "time": "2017-02-14T16:28:37+00:00"
}, },
{
"name": "psr/http-message",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
"homepage": "https://github.com/php-fig/http-message",
"keywords": [
"http",
"http-message",
"psr",
"psr-7",
"request",
"response"
],
"time": "2016-08-06T14:39:51+00:00"
},
{ {
"name": "psr/log", "name": "psr/log",
"version": "1.0.2", "version": "1.0.2",
......
...@@ -3,11 +3,14 @@ ...@@ -3,11 +3,14 @@
use Faker\Generator as Faker; use Faker\Generator as Faker;
$factory->define(\App\Project::class, function (Faker $faker) { $factory->define(\App\Project::class, function (Faker $faker) {
$status = $faker->randomElement(['opened', 'closed', 'locked', 'merged']);
return [ return [
'title' => $faker->sentence(),
'payment_id' => $faker->sha256, 'payment_id' => $faker->sha256,
'target_amount' => $faker->randomNumber(), 'target_amount' => $faker->randomFloat(2, 0, 2000),
'status' => $faker->randomElement(['new', 'open', 'funded']), 'state' => $status,
'created_at' => $faker->dateTime, 'merge_request_id' => $faker->randomNumber(6),
'updated_at' => $faker->dateTime, 'created_at' => $faker->dateTimeThisYear,
'updated_at' => $faker->dateTimeThisYear,
]; ];
}); });
...@@ -15,9 +15,12 @@ class CreateProjectsTable extends Migration ...@@ -15,9 +15,12 @@ class CreateProjectsTable extends Migration
{ {
Schema::create('projects', function (Blueprint $table) { Schema::create('projects', function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$table->string('payment_id')->unique(); $table->string('title');
$table->string('target_amount'); $table->string('payment_id')->nullable();
$table->string('status')->default('open'); $table->string('address')->nullable();
$table->string('target_amount')->nullable();
$table->string('state')->default('opened');
$table->unsignedInteger('merge_request_id')->unique();
$table->timestamps(); $table->timestamps();
}); });
} }
......
<?php
namespace GitLab;
use GuzzleHttp\Client;
class Connection
{
/** @var Client */
private $client;
public function __construct(Client $client)
{
$this->client = $client;
}
public function mergeRequests($state = 'all') {
$url = env('GITLAB_URL') . '/merge_requests?scope=all&per_page=50&state='. $state;
$response = $this->client->request('GET', $url, ['headers' => ['Private-Token' => env('GITLAB_ACCESS_TOKEN')]]);
return collect(json_decode($response->getBody()));
}
}
\ No newline at end of file
...@@ -4,6 +4,7 @@ namespace Monero; ...@@ -4,6 +4,7 @@ namespace Monero;
use App\Project; use App\Project;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Support\Collection;
class Wallet class Wallet
{ {
...@@ -38,27 +39,6 @@ class Wallet ...@@ -38,27 +39,6 @@ class Wallet
return ['address' => $integratedAddress['integrated_address'], 'paymentId' => $integratedAddress['payment_id']]; return ['address' => $integratedAddress['integrated_address'], 'paymentId' => $integratedAddress['payment_id']];
} }
/**
* Returns all balances (locked/unlocked) or exception state for site monitor
*
* @return array
*/
public function balanceSiteMonitor()
{
$result = [];
$balance = $this->client->getbalance();
if (!$balance) {
$result['unlocked_balance'] = 'DOWN';
$result['balance'] = 'DOWN';
return $result;
}
$result['unlocked_balance'] = $balance['unlocked_balance'] / 1000000000000;
$result['balance'] = $balance['balance'] / 1000000000000;
return $result;
}
/** /**
* Returns the actual available and useable balance (unlocked balance) * Returns the actual available and useable balance (unlocked balance)
* *
...@@ -66,22 +46,19 @@ class Wallet ...@@ -66,22 +46,19 @@ class Wallet
*/ */
public function balance() public function balance()
{ {
$balance = $this->client->getbalance(); return $this->client->balance();
$result = $balance['unlocked_balance'] / 1000000000000;
return $result;
} }
public function mempoolTransfers() public function mempoolTransfers()
{ {
return $this->client->mempoolTransfers(); return $this->client->incomingTransfers();
} }
public function bulkPayments($paymentIds) public function bulkPayments($paymentIds)
{ {
$blockBuffer = 10; $blockBuffer = 10;
return $this->client->bulk_payments($paymentIds, intval($this->wallet->last_scanned_block_height) - $blockBuffer); return $this->client->payments($paymentIds, intval($this->wallet->last_scanned_block_height) - $blockBuffer);
} }
/** /**
...@@ -152,12 +129,7 @@ class Wallet ...@@ -152,12 +129,7 @@ class Wallet
*/ */
public function blockHeight() public function blockHeight()
{ {
$result = $this->client->getheight(); return $this->client->blockHeight();
if ($result && isset($result['height'])) {
return $result['height'];
}
return 0;
} }
/** /**
...@@ -167,12 +139,7 @@ class Wallet ...@@ -167,12 +139,7 @@ class Wallet
*/ */
public function getAddress() public function getAddress()
{ {
$address = $this->client->getaddress(); return $this->client->address();
if ($address != null) {
return $address['address'];
}
return 'Invalid';
} }
/** /**
...@@ -182,11 +149,7 @@ class Wallet ...@@ -182,11 +149,7 @@ class Wallet
*/ */
public function createIntegratedAddress() public function createIntegratedAddress()
{ {
try { return $this->client->createIntegratedAddress();
return $this->client->make_integrated_address();
} catch (\Throwable $e) {
return false;
}
} }
/** /**
...@@ -206,12 +169,11 @@ class Wallet ...@@ -206,12 +169,11 @@ class Wallet
/** /**
* gets all the payment_ids outstanding from the address_pool, we use these to check against the latest mined blocks * gets all the payment_ids outstanding from the address_pool, we use these to check against the latest mined blocks
* *
* @return array * @return Collection
*/ */
public function getPaymentIds() public function getPaymentIds()
{ {
$paymentIds = Project::pluck('payment_id'); //stop scanning for payment_ids after 24h
return $paymentIds; return Project::pluck('payment_id'); //stop scanning for payment_ids after 24h
} }
} }
...@@ -2,8 +2,9 @@ ...@@ -2,8 +2,9 @@
namespace Monero; namespace Monero;
//json 2.0 rpc client use GuzzleHttp\Client;
use App\Exceptions\ConnectionException; use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\Log;
/** /**
* Class jsonRPCClient * Class jsonRPCClient
...@@ -11,215 +12,181 @@ use App\Exceptions\ConnectionException; ...@@ -11,215 +12,181 @@ use App\Exceptions\ConnectionException;
*/ */
class jsonRPCClient class jsonRPCClient
{ {
/**
* @var
*/
private $url;
/** /** @var string */
* @var int private $username;
*/
private $timeout;
/** /** @var string */
* @var bool private $password;
*/
private $debug; /** @var Client|null */
private $client;
/** /**
* @var * JsonRPCClient constructor.
* @param null $client
*/ */
private $username; public function __construct($client = null)
{
if (empty($client)) {
$client = new Client([
'base_uri' => env('RPC_URL'),
]);
}
$this->username = env('MONERO_USERNAME');
$this->password = env('MONERO_PASSWORD');
$this->client = $client;
}
/** /**
* @var * Gets the balance
*
* @return int the overall value after inputs unlock
*/ */
private $password; public function balance() : int
{
$response = $this->request('get_balance');
return $response['balance'];
}
/** /**
* @var array * Gets the unlocked balance
*
* @return int the spendable balance
*/ */
private $headers = [ public function unlockedBalance() : int
'Connection: close', {
'Content-Type: application/json', $response = $this->request('get_balance');
'Accept: application/json', return $response['unlocked_balance'];
]; }
/** /**
* jsonRPCClient constructor. * Gets the primary address
* *
* @param $url * @return string wallets primary address
* @param int $timeout
* @param bool|false $debug
* @param array $headers
*/ */
public function __construct($url, $timeout = 20, $debug = false, $headers = []) public function address() : string
{ {
$this->url = $url; $response = $this->request('get_address');
$this->timeout = $timeout; return $response['address'];
$this->debug = $debug;
$this->headers = array_merge($this->headers, $headers);
} }
/** /**
* Generic method executor * Gets the current block height
*
* @param $method
* @param $params
* *
* @return null * @return int block height
*/ */
public function __call($method, $params) public function blockHeight() : int
{ {
return $this->execute($method, $params); $response = $this->request('get_height');
return $response['height'];
} }
/** /**
* Set auth credentials * Creates a new integrated address
* *
* @param $username * @return array ['integrated_address', 'payment_id']
* @param $password
*/ */
public function authentication($username, $password) public function createIntegratedAddress() : array
{ {
$this->username = $username; $response = $this->request('make_integrated_address');
$this->password = $password; return $response;
} }
/** /**
* Get XMR bulk payments * Gets any incoming transactions
*
* @param $payment_ids
* @param $block_height
* *
* @return null * @return array
*/ */
public function bulk_payments($payment_ids, $block_height) public function incomingTransfers() : array
{ {
return $this->execute('get_bulk_payments', $payment_ids, $block_height); $response = $this->request('get_transfers', ['pool' => true, 'in' => true]);
return $response;
} }
/** /**
* Transfer XMR to another destination * Checks for any payments made to the paymentIds
* *
* @param $amount * @param array $paymentIds list of payment ids to be searched for
* @param $destination * @param int $minHeight the lowest block the search should start with
* @param $payment_id
* @param $mixin
* @param int $unlock_time
* *
* @return string * @return array payments received since min block height with a payment id provided
*/ */
public function transferXMR($amount, $destination, $payment_id, $mixin, $unlock_time = 0) public function payments($paymentIds, $minHeight) : array
{ {
$dest = ['amount' => intval(0 + $amount * 1000000000000), 'address' => $destination]; $response = $this->request('get_bulk_payments', ['payment_ids' => $paymentIds, 'min_block_height' => $minHeight]);
$params = [
'destinations' => [$dest],
'payment_id' => $payment_id,
'mixin' => $mixin,
'unlock_time' => $unlock_time,
];
$response = $this->execute('transfer', $params);
$tx = trim($response['tx_hash'], '<>');
return $tx; return $response;
} }
public function mempoolTransfers() /**
* creates a uri for easier wallet parsing
*
* @param string $address address comprising of primary, sub or integrated address
* @param string $paymentId payment id when not using integrated addresses
* @param int $amount atomic amount requested
*
* @return string the uri string which can be used to generate a QR code
*/
public function createUri($address, $paymentId = null, $amount = null) : string
{ {
$response = $this->execute('get_transfers', ['pool' => true]); $response = $this->request('make_uri', ['address' => $address, 'amount' => $amount, 'payment_id' => $paymentId]);
return $response; return $response['uri'];
} }
/** /**
* Prepares the payload for CURL and evaluates the result from the RPC * Sets up the request data body
*
* @param $procedure
* @param $params
* @param null $params2
* *
* @return null * @param string $method name of the rpc command
* @param array $params associative array of variables being passed to the method
* *
* @throws WalletErrorException * @return false|string will return a json string or false
*/ */
public function execute($procedure, $params, $params2 = null) private function preparePayload($method, $params)
{ {
$id = mt_rand();
$payload = [ $payload = [
'jsonrpc' => '2.0', 'jsonrpc' => '2.0',
'method' => $procedure, 'id' => '0',
'id' => $id, 'method' => $method,
'params' => $params,
]; ];
return json_encode($payload);
if (!empty($params)) {
if ($params2 != null) {
$payload['params']['payment_ids'] = $params;
$payload['params']['min_block_height'] = $params2;
} else {
if (is_array($params)) {
// no keys
//$params = array_values($params);
$payload['params'] = $params;
}
}
}
if ($this->debug) {
print_r($payload);
}
$result = $this->doRequest($payload);
if (isset($result['id']) && $result['id'] == $id && array_key_exists('result', $result)) {
if ($this->debug) {
print_r($result['result']);
}
return $result['result'];
}
if (isset($result['error'])) {
throw new ConnectionException($result['error']['message']);
}
throw new ConnectionException('no response');
} }
/** /**
* Executes the CURL request.
* *
* @param $payload * @param string $method name of the rpc command
* @param array $params associative array of variables being passed to the method
*
* @return mixed the rpc query result
* *
* @return array|mixed * @throws \RuntimeException
*/ */
public function doRequest($payload) protected function request(string $method, array $params = [])
{ {
$ch = curl_init(); $payload = $this->preparePayload($method, $params);
curl_setopt($ch, CURLOPT_URL, $this->url); try {
curl_setopt($ch, CURLOPT_HEADER, false); $response = $this->client->request('POST', '',[
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 'auth' => [$this->username, $this->password, 'digest'],
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->timeout); 'body' => $payload,
curl_setopt($ch, CURLOPT_USERAGENT, 'JSON-RPC PHP Client'); 'headers' => [
curl_setopt($ch, CURLOPT_HTTPHEADER, $this->headers); 'Content-Type' => 'application/json',
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); ]
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); ]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_VERBOSE, true); $body = $response->getBody();
if ($this->username && $this->password) { } catch (GuzzleException $exception) {
curl_setopt($ch, CURLOPT_USERPWD, $this->username.':'.$this->password); Log::error($exception);
throw new \RuntimeException('Connection to node unsuccessful');
} }
$result = json_decode((string) $body, true);
if (isset($result['error'])) {
if ($this->debug) { throw new \RuntimeException($result['error']['message']);
print_r(json_encode($payload)."\n");
print_r($ch);
} }
return $result['result'];
$result = curl_exec($ch);
$response = json_decode($result, true);
curl_close($ch);
return is_array($response) ? $response : [];
} }
} }