Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
76.92% covered (warning)
76.92%
10 / 13
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
Bitstamp_API
76.92% covered (warning)
76.92%
10 / 13
50.00% covered (danger)
50.00%
1 / 2
5.31
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get_exchange_rate
75.00% covered (warning)
75.00%
9 / 12
0.00% covered (danger)
0.00%
0 / 1
4.25
1<?php
2/**
3 * Bitstamp exchange rate API client.
4 *
5 * @see https://www.bitstamp.net/api/
6 *
7 * Rate limit is "8000 requests per 10 minutes".
8 *
9 * @package    brianhenryie/bh-wp-bitcoin-gateway
10 */
11
12namespace BrianHenryIE\WP_Bitcoin_Gateway\API\Clients\Exchange_Rate;
13
14use BrianHenryIE\WP_Bitcoin_Gateway\API\Clients\Exchange_Rate_API_Interface;
15use BrianHenryIE\WP_Bitcoin_Gateway\API\Model\Exceptions\BH_WP_Bitcoin_Gateway_Exception;
16use BrianHenryIE\WP_Bitcoin_Gateway\Brick\Money\Currency;
17use BrianHenryIE\WP_Bitcoin_Gateway\Brick\Money\Money;
18use Psr\Log\LoggerAwareTrait;
19use Psr\Log\LoggerInterface;
20
21/**
22 * Queries API and returns Money object where 1 BTC = value of requested currency.
23 */
24class Bitstamp_API implements Exchange_Rate_API_Interface {
25    use LoggerAwareTrait;
26
27    /**
28     * Constructor.
29     *
30     * @param LoggerInterface $logger Logger instance for logging API calls.
31     */
32    public function __construct( LoggerInterface $logger ) {
33        $this->setLogger( $logger );
34    }
35
36    /**
37     * Fetch the current exchange from a remote API.
38     *
39     * @param Currency $currency The currency to get the Bitcoin exchange rate for.
40     * @return Money The exchange rate.
41     * @throws BH_WP_Bitcoin_Gateway_Exception When the currency is not supported (only USD, EUR, GBP are supported) or when the API request fails.
42     */
43    public function get_exchange_rate( Currency $currency ): Money {
44
45        $between = strtolower( "btc{$currency}" );
46
47        $valid_exchanges = array( 'btcusd', 'btceur', 'btcgbp' );
48
49        if ( ! in_array( $between, $valid_exchanges, true ) ) {
50            throw new BH_WP_Bitcoin_Gateway_Exception( 'Bitstamp only supports USD, EUR and GBP.' );
51        }
52
53        $url = "https://www.bitstamp.net/api/v2/ticker/{$between}/";
54
55        $request_response = wp_remote_get( $url );
56
57        if ( is_wp_error( $request_response ) ) {
58            throw new BH_WP_Bitcoin_Gateway_Exception();
59        }
60
61        if ( 200 !== $request_response['response']['code'] ) {
62            throw new BH_WP_Bitcoin_Gateway_Exception();
63        }
64
65        /**
66         * Response array.
67         *
68         * `last`      Last BTC price.
69         * `high`      Last 24 hours price high.
70         * `low`       Last 24 hours price low.
71         * `vwap`      Last 24 hours volume weighted average price.
72         * `volume`    Last 24 hours volume.
73         * `bid`       Highest buy order.
74         * `ask`       Lowest sell order.
75         * `timestamp` Unix timestamp date and time.
76         * `open`      First price of the day.
77         *
78         * // TODO: is `last` or `vwap` the correct value to use?
79         *
80         * @var array{timestamp:string, open:string, high:string, low:string, last:string, volume:string, vwap:string, bid:string, ask:string, side:string, open_24:string, percent_change_24:string, market_type:string} $response
81         */
82        $response = json_decode( (string) $request_response['body'], true, 512, JSON_THROW_ON_ERROR );
83
84        return Money::of( $response['last'], $currency );
85    }
86}