|
| 1 | +<pre> |
| 2 | + BIP: 171 |
| 3 | + Layer: Applications |
| 4 | + Title: Currency/exchange rate information API |
| 5 | + Author: Luke Dashjr < [email protected]> |
| 6 | + Comments-Summary: No comments yet. |
| 7 | + Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0171 |
| 8 | + Status: Draft |
| 9 | + Type: Standards Track |
| 10 | + Created: 2017-03-04 |
| 11 | + License: BSD-2-Clause |
| 12 | +</pre> |
| 13 | + |
| 14 | +==Abstract== |
| 15 | + |
| 16 | +A common interface for requesting currency exchange rate information from a server. |
| 17 | + |
| 18 | +==Copyright== |
| 19 | + |
| 20 | +This BIP is licensed under the BSD 2-clause license. |
| 21 | + |
| 22 | +==Specification== |
| 23 | + |
| 24 | +Four requests are defined, which are all made by a GET request to a common URI with parameters encoded in application/x-www-form-urlencoded format. |
| 25 | +All matching parameters may be specified with multiple comma-separated values, which are to be interpreted as "any of these". |
| 26 | +Each result is always in JSON format, with a line-feed (never a carriage-return) separating multiple results. |
| 27 | + |
| 28 | +Authentication for subscription-based services MAY be supported using standard HTTP authentication. |
| 29 | +It is recommended to use TLS (HTTPS), so that MITM attackers cannot deceive the client. |
| 30 | + |
| 31 | +To be BIP 171 compatible, servers MUST support at least one currency-pair compared to XBT. |
| 32 | +All inquiries for bitcoin amounts MUST be specified in XBT, even if the presentation to the end user is in another unit. |
| 33 | +(FIXME: or should this be satoshis?) |
| 34 | + |
| 35 | +Currency-pair tokens are arbitrary Strings no longer than 255 characters, which may include any ASCII [https://tools.ietf.org/html/rfc3986#section-2.3 RFC 3986 unreserved characters] (ie, alphanumerics and the hyphen, underscore, period, and tilde symbols). |
| 36 | + |
| 37 | +Currency code(s) used herein are defined as such: |
| 38 | + |
| 39 | +* All ISO 4217 codes are valid currency codes. |
| 40 | +* XBT is defined as 100000000 satoshis (commonly known as 1 BTC). |
| 41 | +* Strings longer than 3 characters may be used for currencies without an applicable code. (If a shorter code is desired despite this, it may be padded with space(s) to the left until it is 4 characters. Software MAY strip these spaces.) |
| 42 | +
|
| 43 | +Rate is defined as the amount of quote-currency to be exchanged for one unit of the base-currency. |
| 44 | +In other words, <code>1 baseCurrency = rate quoteCurrency</code>. |
| 45 | + |
| 46 | +===Enumerating supported currency-pair tokens=== |
| 47 | + |
| 48 | +Parameters: |
| 49 | + |
| 50 | +* ''mode'' - Always "list" for this request. |
| 51 | +* ''quote'' - If provided, the server MAY limit the results to only currency-pairs describing a currency with the given currency code(s). |
| 52 | +* ''base'' - If provided, the server MAY limit the results to only currency-pairs describing currency rates compared to the given currency code(s). |
| 53 | +* ''locale'' - If provided, the server MAY limit the results to only currency-pairs supporting the given Unicode CLDR locale(s). |
| 54 | +
|
| 55 | +Each currency-pair will receive a separate result, a JSON Object, with the following information: |
| 56 | + |
| 57 | +* ''cp'' - The currency-pair token. |
| 58 | +* ''quote'' - The currency code for the quote currency. |
| 59 | +* ''base'' - The currency code for the base currency. |
| 60 | +* ''locale'' - If provided, a String with the applicable Unicode CLDR locale. |
| 61 | +* ''desc'' - Optional description. For example, it could be "Based on Florida BTM prices." or any other short String that provides information useful to the user. SHOULD be shorter than 45 characters. |
| 62 | +
|
| 63 | +Example: |
| 64 | + |
| 65 | + Request: http://api.example.tld/?mode=list"e=USD&base=XBT&locale=en_US,en_GB |
| 66 | + Result: |
| 67 | + {"cp":"XBTUSD-ver4", "quote":"USD", "base": "XBT", "locale": "en_US", "desc": "Smoothed averages"} |
| 68 | + {"cp":"2", "quote":"USD", "base": "XBT", "locale": "en_US", "desc": "Updated per-trade"} |
| 69 | + {"cp":"XBTUSD-european", "quote":"USD", "base": "XBT", "locale": "en_GB"} |
| 70 | +
|
| 71 | +===Currency-pair information=== |
| 72 | + |
| 73 | +Parameters: |
| 74 | + |
| 75 | +* ''mode'' - Always "info" for this request. |
| 76 | +* ''cp'' - Currency pair(s) for which information is requested. |
| 77 | +
|
| 78 | +Each currency-pair will receive a separate result, a JSON Object, with the following information: |
| 79 | + |
| 80 | +* ''cp'' - The currency-pair token. |
| 81 | +* ''quote'' - The currency code for the quote currency. |
| 82 | +* ''base'' - The currency code for the base currency. |
| 83 | +* ''locale'' - If provided, a String with the applicable Unicode CLDR locale. |
| 84 | +* ''desc'' - Optional description. For example, it could be "Based on Florida BTM prices." or any other short String that provides information useful to the user. SHOULD be shorter than 45 characters. |
| 85 | +* ''longdesc'' - Optional description, but may be longer and include newlines. |
| 86 | +* ''symbol'' - An Array of prefix and suffix for the quote currency. Each may be either a fixed String, an Array of two Strings (negative and positive), or null. Any positive or negative symbols must be included in this prefix/suffix; it MUST NOT be implied otherwise. |
| 87 | +* ''digits'' - The type of digits to use for the quote currency's numbers. "arabic" should be used for common 0-9 digits. |
| 88 | +* ''grouping'' - An Array alternating between Numbers representing a series of digits, and Strings used as delimiters. If terminated by a zero, the final grouping is to be repeated continually. For example, the common US locale thousands grouping would be <code>[3, ",", 0]</code> |
| 89 | +* ''fraction_sep'' - A String to be placed between whole numbers and a fractional amount. |
| 90 | +* ''fraction_digits'' - Array of absolute minimum (even for whole numbers) number of fractional digits, minimum fractional digits when a fraction exists, and maximum number of fractional digits when absolute precision is not demanded (below which is to be rounded in an implementation-dependent manner). |
| 91 | +* ''minpoll'' - A Number of seconds indicating a minimum time between polls to the server. Clients should be prudent about not polling too often, even if this number is low. |
| 92 | +* ''longpoll'' - If provided and true, indicates longpolling is supported by the server. |
| 93 | +* ''history'' - If provided, indicates the server has historical records going back no earlier than the POSIX timestamp provided as a value. |
| 94 | +* ''archive'' - If provided, indicates the server no longer has current rates, and has no historical rates more recent than the POSIX timestamp provided as a value. |
| 95 | +
|
| 96 | +Example: |
| 97 | + |
| 98 | + Request: http://api.example.tld/?mode=info&cp=XBTUSD-ver4,2 |
| 99 | + Result: |
| 100 | + {"cp":"XBTUSD-ver4", "quote":"USD", "base": "XBT", "locale": "en_US", "desc": "Smoothed averages", "longdesc": "USD price quotes as compared to Bitcoin value\n\nRecommended for casual usage", "symbol": [["-$", "$"], null], "digits": "arabic", "grouping": [3, ",", 0], "fraction_sep": ".", "fraction_digits": [0, 2, 2], "minpoll": 300, "longpoll": true, "history": 1457231416} |
| 101 | + {"cp":"2", "quote":"USD", "base": "XBT", "locale": "en_US", "desc": "Updated per-trade", "longdesc": "Maximum precision USD price quotes as compared to Bitcoin value", "symbol": [["-$", "$"], null], "digits": "arabic", "grouping": [3, ",", 0], "fraction_sep": ".", "fraction_digits": [0, 2, 2], "minpoll": 3600, "longpoll": false, "history": 1467458333.1225} |
| 102 | +
|
| 103 | +===Current exchange rate=== |
| 104 | +
|
| 105 | +Parameters: |
| 106 | +
|
| 107 | +* ''mode'' - Always "rate" for this request. |
| 108 | +* ''cp'' - Currency pair(s) for which rate is requested. |
| 109 | +* ''type'' - Type of exchange rate data being requested. May be "high", "low", "average", "typical", or any other arbitrary name. If omitted, the server may provide any rates it deems appropriate. |
| 110 | +* ''minrate'', ''maxrate'' - If specified, indicates this request is a longpoll. The server should not send a response until the rate(s) fall below or above (respectively) the provided value. |
| 111 | +
|
| 112 | +Each currency-pair receives a separate result (a JSON Object) with all requested rate types: |
| 113 | +
|
| 114 | +* ''cp'' - The currency-pair token. |
| 115 | +* ''time'' - The time (as a POSIX timestamp) the rate information is applicable to (should be approximately the request time). |
| 116 | +* ''rates'' - A JSON Object with each rate type provided as a key, and a Number as the value specifying the rate. |
| 117 | +
|
| 118 | +Example: |
| 119 | +
|
| 120 | + Request: http://api.example.tld/?mode=rate&cp=XBTUSD-ver4,2&type=typical,high |
| 121 | + Result: |
| 122 | + {"cp":"XBTUSD-ver4", "time": 1488767410.5463133, "rates": {"typical": 1349.332215, "high": 1351.2}} |
| 123 | + {"cp":"2", "time": 1488767410, "rates": {"typical": 1350.111332}} |
| 124 | +
|
| 125 | +===Historical exchange rates=== |
| 126 | +
|
| 127 | +Parameters: |
| 128 | +
|
| 129 | +* ''mode'' - Always "history" for this request. |
| 130 | +* ''cp'' - Currency pair(s) for which rate is requested. |
| 131 | +* ''type'' - Type of exchange rate data being requested. May be "high", "low", "average", "typical", or any other arbitrary name. If omitted, the server may provide any rates it deems appropriate. |
| 132 | +* ''from'' - POSIX timestamp the results should begin with. |
| 133 | +* ''to'' - POSIX timestamp the results should end with. If omitted, the present time shall be used. |
| 134 | +* ''nearest'' - If provided and true, indicates that only the nearest timestamp to "from" must be returned, and a range is not desired. ("to" should be omitted in this case.) |
| 135 | +* ''ratedelta'', ''timedelta'' - If specified, the server may omit data where the rate or time has not changed since the last provided rate and time. If both are provided, either a significant rate change OR time change should trigger a new record in the results. |
| 136 | +
|
| 137 | +A result is provided for each currency-pair and timestamp record, in the same format as the current exchange rate request. |
| 138 | +Records MUST be provided in chronological order, but only within the scope of the applicable currency-pair (ie, it is okay to send the full history for one currency-pair, and then the full history for the next; or to intermix them out of any given order). |
| 139 | +
|
| 140 | +If there is no exact record for the times specified by "from" and/or "to", a single record before "from" and/or after "to" should also be included. |
| 141 | +This is not necessary when only the nearest record is requested, or when "to" is omitted (ie, ending at the most recent record). |
| 142 | +
|
| 143 | +Example: |
| 144 | +
|
| 145 | + Request: http://api.example.tld/?mode=history&cp=XBTUSD-ver4,2&type=typical&ratedelta=0.1&timedelta=10&from=1488759998&to=1488760090 |
| 146 | + Result: |
| 147 | + {"cp":"XBTUSD-ver4", "time": 1488760000, "rates": {"typical": 1300}} |
| 148 | + {"cp":"XBTUSD-ver4", "time": 1488760010, "rates": {"typical": 1301.1}} |
| 149 | + {"cp":"XBTUSD-ver4", "time": 1488760020, "rates": {"typical": 1320}} |
| 150 | + {"cp":"XBTUSD-ver4", "time": 1488760030, "rates": {"typical": 1305}} |
| 151 | + {"cp":"2", "time": 1488760000.1, "rates": {"typical": 1300}} |
| 152 | + {"cp":"2", "time": 1488760010.2, "rates": {"typical": 1301.1}} |
| 153 | + {"cp":"2", "time": 1488760020.2, "rates": {"typical": 1320.111332}} |
| 154 | + {"cp":"2", "time": 1488760031, "rates": {"typical": 1305.222311}} |
| 155 | + {"cp":"XBTUSD-ver4", "time": 1488760040, "rates": {"typical": 1303.33}} |
| 156 | + {"cp":"2", "time": 1488760042, "rates": {"typical": 1303.33}} |
| 157 | + {"cp":"XBTUSD-ver4", "time": 1488760050, "rates": {"typical": 1305}} |
| 158 | + {"cp":"2", "time": 1488760052, "rates": {"typical": 1307}} |
| 159 | + {"cp":"XBTUSD-ver4", "time": 1488760060, "rates": {"typical": 1309}} |
| 160 | + {"cp":"XBTUSD-ver4", "time": 1488760072, "rates": {"typical": 1308}} |
| 161 | + {"cp":"2", "time": 1488760062, "rates": {"typical": 1309.55555555}} |
| 162 | + {"cp":"2", "time": 1488760072, "rates": {"typical": 1308}} |
| 163 | + {"cp":"XBTUSD-ver4", "time": 1488760082, "rates": {"typical": 1309}} |
| 164 | + {"cp":"2", "time": 1488760082, "rates": {"typical": 1309.1}} |
| 165 | +
|
| 166 | +==Motivation== |
| 167 | +
|
| 168 | +End users often desire to see fiat currency information in their Bitcoin wallet software. |
| 169 | +Due to the nature of Bitcoin, there is inherently no authoritative source for exchange rates. |
| 170 | +There are many independent providers of such information, but they all use different formats for providing it, so wallet software is currently forced to implement dedicated code for each provider. |
| 171 | +
|
| 172 | +By providing a standard interface for retrieving this information, wallets (and other software) and service providers can implement it once, and become immediately interoperable with all other compatible implementations. |
| 173 | +
|
| 174 | +==Rationale== |
| 175 | +
|
| 176 | +Why are multiple results separated by a line-feed rather than using a JSON Array? |
| 177 | +
|
| 178 | +* Clients ought to cache historical data, and using a line-feed format allows them to simply append to a cache file. |
| 179 | +* Parsing JSON typically requires the entire data parsed together as a single memory object. Using simple lines to separate results, however, allows parsing a single result at a time. |
| 180 | +
|
| 181 | +What if long descriptions require line and paragraph breaks? |
| 182 | +
|
| 183 | +* Clients should word-wrap long lines, and JSON escapes newlines as "\n" which can be used doubly ("\n\n") for paragraph breaks. |
| 184 | +
|
| 185 | +==Backwards compatibility== |
| 186 | +
|
| 187 | +While this new standard is adopted, software and providers can continue to use and provide their current formats until they are no longer needed. |
| 188 | +
|
| 189 | +==Reference implementation== |
| 190 | +
|
| 191 | +TODO |
0 commit comments