Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
83.33% covered (warning)
83.33%
10 / 12
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
Bitfinex_API
83.33% covered (warning)
83.33%
10 / 12
50.00% covered (danger)
50.00%
1 / 2
4.07
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
81.82% covered (warning)
81.82%
9 / 11
0.00% covered (danger)
0.00%
0 / 1
3.05
1<?php
2/**
3 * Bitfinex exchange rate API client.
4 *
5 * Use the {@see https://bitfinex.com} API for currency conversion.
6 *
7 * TODO: surface the ToS to the admin UI.
8 *
9 * @see https://www.bitfinex.com/legal/general/api-terms/
10 *
11 * @see https://docs.bitfinex.com/docs/rest-public
12 * @see https://docs.bitfinex.com/v2/reference#rest-public-ticker
13 *
14 * @see https://api-pub.bitfinex.com/v2/conf/pub:list:pair:exchange
15 *
16 * Obviously, this should be spun into its own Composer package and use JsonMapper.
17 *
18 * @package    brianhenryie/bh-wp-bitcoin-gateway
19 */
20
21namespace BrianHenryIE\WP_Bitcoin_Gateway\API\Clients\Exchange_Rate;
22
23use BrianHenryIE\WP_Bitcoin_Gateway\API\Clients\Exchange_Rate_API_Interface;
24use BrianHenryIE\WP_Bitcoin_Gateway\API\Model\Exceptions\BH_WP_Bitcoin_Gateway_Exception;
25use BrianHenryIE\WP_Bitcoin_Gateway\Brick\Money\Currency;
26use BrianHenryIE\WP_Bitcoin_Gateway\Brick\Money\Exception\UnknownCurrencyException;
27use BrianHenryIE\WP_Bitcoin_Gateway\Brick\Money\Money;
28use JsonException;
29use Psr\Log\LoggerAwareTrait;
30use Psr\Log\LoggerInterface;
31
32/**
33 * Queries API and returns Money object where 1 BTC = value of requested currency.
34 */
35class Bitfinex_API implements Exchange_Rate_API_Interface {
36    use LoggerAwareTrait;
37
38    /**
39     * Constructor.
40     *
41     * @param LoggerInterface $logger Debug logging API calls; error logging failures.
42     */
43    public function __construct(
44        LoggerInterface $logger
45    ) {
46        $this->setLogger( $logger );
47    }
48
49    /**
50     * Fetch the current exchange from a remote API.
51     *
52     * @param Currency $currency The currency to get the Bitcoin exchange rate for.
53     * @return Money The exchange rate.
54     * @throws BH_WP_Bitcoin_Gateway_Exception When the request fails.
55     * @throws UnknownCurrencyException Almost impossible – unless the Money library cannot use a Currency object it created.
56     * @throws JsonException If the API returns unexpected/invalid data.
57     */
58    public function get_exchange_rate( Currency $currency ): Money {
59
60        $trading_pair = 'tBTC' . strtoupper( $currency );
61
62        $url = "https://api-pub.bitfinex.com/v2/tickers?symbols={$trading_pair}";
63
64        $request_response = wp_remote_get( $url );
65
66        if ( is_wp_error( $request_response ) ) {
67            throw new BH_WP_Bitcoin_Gateway_Exception( $request_response->get_error_message() );
68        }
69
70        if ( 200 !== $request_response['response']['code'] ) {
71            throw new BH_WP_Bitcoin_Gateway_Exception();
72        }
73
74        /**
75         * @var array{0:array{0:string,1:int,2:float,3:int,4:float,5:int,6:float,7:int,8:float,9:int,10:int}} $response_body
76         */
77        $response_body = json_decode( (string) $request_response['body'], true, 512, JSON_THROW_ON_ERROR );
78
79        // Multiple rates can be queried at the same time.
80
81        /**
82         * SYMBOL                string The symbol of the requested ticker data,
83         * BID                   float  Price of last highest bid,
84         * BID_SIZE              float  Sum of the 25 highest bid sizes,
85         * ASK                   float  Price of last lowest ask,
86         * ASK_SIZE              float  Sum of the 25 lowest ask sizes,
87         * DAILY_CHANGE          float  Amount that the last price has changed since yesterday,
88         * DAILY_CHANGE_RELATIVE float  Relative price change since yesterday (*100 for percentage change),
89         * LAST_PRICE            float  Price of the last trade,
90         * VOLUME                float  Daily volume,
91         * HIGH                  float  Daily high,
92         * LOW                   float  Daily low
93         */
94        $trading_pair_response = $response_body[0];
95
96        $exchange_rate = $trading_pair_response[7];
97
98        return Money::of( $exchange_rate, $currency );
99    }
100}