jsonRPCClient.php 5.02 KB
Newer Older
beardedwarrior's avatar
beardedwarrior committed
1 2 3 4
<?php

namespace Monero;

5 6 7
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\Log;
beardedwarrior's avatar
beardedwarrior committed
8 9 10 11 12 13 14 15

/**
 * Class jsonRPCClient
 * JSON 2.0 RPC Client for cryptocurrency wallet
 */
class jsonRPCClient
{

16 17
    /** @var string */
    private $username;
beardedwarrior's avatar
beardedwarrior committed
18

19 20 21 22 23
    /** @var string */
    private $password;

    /** @var Client|null  */
    private $client;
beardedwarrior's avatar
beardedwarrior committed
24 25

    /**
26 27
     * JsonRPCClient constructor.
     * @param null $client
beardedwarrior's avatar
beardedwarrior committed
28
     */
29 30 31 32 33 34 35 36 37 38 39
    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;
    }
beardedwarrior's avatar
beardedwarrior committed
40 41

    /**
42 43 44
     * Gets the balance
     *
     * @return int the overall value after inputs unlock
beardedwarrior's avatar
beardedwarrior committed
45
     */
46 47 48 49 50
    public function balance() : int
    {
        $response = $this->request('get_balance');
        return $response['balance'];
    }
beardedwarrior's avatar
beardedwarrior committed
51 52

    /**
53 54 55
     * Gets the unlocked balance
     *
     * @return int the spendable balance
beardedwarrior's avatar
beardedwarrior committed
56
     */
57 58 59 60 61
    public function unlockedBalance() : int
    {
        $response = $this->request('get_balance');
        return $response['unlocked_balance'];
    }
beardedwarrior's avatar
beardedwarrior committed
62 63

    /**
64
     * Gets the primary address
beardedwarrior's avatar
beardedwarrior committed
65
     *
66
     * @return string wallets primary address
beardedwarrior's avatar
beardedwarrior committed
67
     */
68
    public function address() : string
beardedwarrior's avatar
beardedwarrior committed
69
    {
70 71
        $response = $this->request('get_address');
        return $response['address'];
beardedwarrior's avatar
beardedwarrior committed
72 73 74
    }

    /**
75
     * Gets the current block height
beardedwarrior's avatar
beardedwarrior committed
76
     *
77
     * @return int block height
beardedwarrior's avatar
beardedwarrior committed
78
     */
79
    public function blockHeight() : int
beardedwarrior's avatar
beardedwarrior committed
80
    {
81 82
        $response = $this->request('get_height');
        return $response['height'];
beardedwarrior's avatar
beardedwarrior committed
83 84
    }
    /**
85
     * Creates a new integrated address
beardedwarrior's avatar
beardedwarrior committed
86
     *
87
     * @return array ['integrated_address', 'payment_id']
beardedwarrior's avatar
beardedwarrior committed
88
     */
89
    public function createIntegratedAddress() : array
beardedwarrior's avatar
beardedwarrior committed
90
    {
91 92
        $response = $this->request('make_integrated_address');
        return $response;
beardedwarrior's avatar
beardedwarrior committed
93 94 95
    }

    /**
96
     * Gets any incoming transactions
beardedwarrior's avatar
beardedwarrior committed
97
     *
98
     * @return array
beardedwarrior's avatar
beardedwarrior committed
99
     */
100
    public function incomingTransfers() : array
beardedwarrior's avatar
beardedwarrior committed
101
    {
102 103 104
        $response = $this->request('get_transfers', ['pool' => true, 'in' => true]);

        return $response;
beardedwarrior's avatar
beardedwarrior committed
105 106 107
    }

    /**
108
     * Checks for any payments made to the paymentIds
beardedwarrior's avatar
beardedwarrior committed
109
     *
110 111
     * @param array     $paymentIds list of payment ids to be searched for
     * @param int       $minHeight  the lowest block the search should start with
beardedwarrior's avatar
beardedwarrior committed
112
     *
113
     * @return array    payments received since min block height with a payment id provided
beardedwarrior's avatar
beardedwarrior committed
114
     */
115
    public function payments($paymentIds, $minHeight) : array
beardedwarrior's avatar
beardedwarrior committed
116
    {
117
        $response = $this->request('get_bulk_payments', ['payment_ids' => $paymentIds, 'min_block_height' => $minHeight]);
beardedwarrior's avatar
beardedwarrior committed
118

119
        return $response;
beardedwarrior's avatar
beardedwarrior committed
120 121
    }

122 123 124 125 126 127 128 129 130 131
    /**
     * 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
beardedwarrior's avatar
beardedwarrior committed
132
    {
133
        $response = $this->request('make_uri', ['address' => $address, 'amount' => $amount, 'payment_id' => $paymentId]);
beardedwarrior's avatar
beardedwarrior committed
134

135
        return $response['uri'];
beardedwarrior's avatar
beardedwarrior committed
136 137 138
    }

    /**
139
     * Sets up the request data body
beardedwarrior's avatar
beardedwarrior committed
140
     *
141 142
     * @param string    $method name of the rpc command
     * @param array     $params associative array of variables being passed to the method
beardedwarrior's avatar
beardedwarrior committed
143
     *
144
     * @return false|string will return a json string or false
beardedwarrior's avatar
beardedwarrior committed
145
     */
146
    private function preparePayload($method, $params)
beardedwarrior's avatar
beardedwarrior committed
147 148 149
    {
        $payload = [
            'jsonrpc' => '2.0',
150 151 152
            'id' => '0',
            'method' => $method,
            'params' => $params,
beardedwarrior's avatar
beardedwarrior committed
153
        ];
154
        return json_encode($payload);
beardedwarrior's avatar
beardedwarrior committed
155 156 157 158
    }

    /**
     *
159 160 161 162
     * @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
beardedwarrior's avatar
beardedwarrior committed
163
     *
164
     * @throws \RuntimeException
beardedwarrior's avatar
beardedwarrior committed
165
     */
166
    protected function request(string $method, array $params = [])
beardedwarrior's avatar
beardedwarrior committed
167
    {
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
        $payload = $this->preparePayload($method, $params);

        try {
            $response = $this->client->request('POST', '',[
                'auth' => [$this->username, $this->password, 'digest'],
                'body' => $payload,
                'headers' => [
                    'Content-Type' => 'application/json',
                ]
            ]);

            $body = $response->getBody();
        } catch (GuzzleException $exception) {
            Log::error($exception);
            throw new \RuntimeException('Connection to node unsuccessful');
beardedwarrior's avatar
beardedwarrior committed
183
        }
184 185
        $result = json_decode((string) $body, true);
        if (isset($result['error'])) {
beardedwarrior's avatar
beardedwarrior committed
186

187
            throw new \RuntimeException($result['error']['message']);
beardedwarrior's avatar
beardedwarrior committed
188
        }
189
        return $result['result'];
beardedwarrior's avatar
beardedwarrior committed
190 191 192
    }

}