ccxt-look 1.81.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cache/eslintcache +1 -0
- package/.dockerignore +6 -0
- package/.eslintignore +1 -0
- package/.gitattributes +5 -0
- package/.readthedocs.yaml +16 -0
- package/CONTRIBUTING.md +1049 -0
- package/LICENSE.txt +21 -0
- package/README.md +537 -0
- package/SECURITY.md +5 -0
- package/build/cleanup-old-tags.js +94 -0
- package/build/countries.js +256 -0
- package/build/export-exchanges.js +520 -0
- package/build/fs.js +51 -0
- package/build/transpile.js +1772 -0
- package/build/vss.js +78 -0
- package/ccxt.browser.js +7 -0
- package/ccxt.d.ts +692 -0
- package/ccxt.js +171 -0
- package/cleanup.sh +2 -0
- package/composer-install.sh +20 -0
- package/dist/ccxt.browser.js +208383 -0
- package/gource.sh +3 -0
- package/index.html +7 -0
- package/js/.eslintrc +87 -0
- package/js/aax.js +2686 -0
- package/js/ascendex.js +2584 -0
- package/js/base/.eslintrc.js +43 -0
- package/js/base/Exchange.js +2371 -0
- package/js/base/Precise.js +283 -0
- package/js/base/errorHierarchy.js +47 -0
- package/js/base/errors.js +55 -0
- package/js/base/functions/crypto.js +158 -0
- package/js/base/functions/encode.js +118 -0
- package/js/base/functions/generic.js +270 -0
- package/js/base/functions/misc.js +138 -0
- package/js/base/functions/number.js +329 -0
- package/js/base/functions/platform.js +38 -0
- package/js/base/functions/string.js +21 -0
- package/js/base/functions/throttle.js +79 -0
- package/js/base/functions/time.js +210 -0
- package/js/base/functions/type.js +66 -0
- package/js/base/functions.js +28 -0
- package/js/bequant.js +32 -0
- package/js/bibox.js +1407 -0
- package/js/bigone.js +1366 -0
- package/js/binance.js +5652 -0
- package/js/binancecoinm.js +46 -0
- package/js/binanceus.js +46 -0
- package/js/binanceusdm.js +49 -0
- package/js/bit2c.js +535 -0
- package/js/bitbank.js +842 -0
- package/js/bitbay.js +16 -0
- package/js/bitbns.js +1073 -0
- package/js/bitcoincom.js +15 -0
- package/js/bitfinex.js +1433 -0
- package/js/bitfinex2.js +2025 -0
- package/js/bitflyer.js +840 -0
- package/js/bitforex.js +614 -0
- package/js/bitget.js +2397 -0
- package/js/bithumb.js +980 -0
- package/js/bitmart.js +2516 -0
- package/js/bitmex.js +1809 -0
- package/js/bitopro.js +1443 -0
- package/js/bitpanda.js +1782 -0
- package/js/bitrue.js +1747 -0
- package/js/bitso.js +1062 -0
- package/js/bitstamp.js +1757 -0
- package/js/bitstamp1.js +343 -0
- package/js/bittrex.js +1876 -0
- package/js/bitvavo.js +1579 -0
- package/js/bkex.js +1233 -0
- package/js/bl3p.js +346 -0
- package/js/blockchaincom.js +969 -0
- package/js/btcalpha.js +680 -0
- package/js/btcbox.js +477 -0
- package/js/btcmarkets.js +1022 -0
- package/js/btctradeua.js +466 -0
- package/js/btcturk.js +734 -0
- package/js/buda.js +946 -0
- package/js/bw.js +1265 -0
- package/js/bybit.js +3372 -0
- package/js/bytetrade.js +1336 -0
- package/js/cdax.js +1646 -0
- package/js/cex.js +1410 -0
- package/js/coinbase.js +1342 -0
- package/js/coinbaseprime.js +31 -0
- package/js/coinbasepro.js +1466 -0
- package/js/coincheck.js +755 -0
- package/js/coinex.js +3400 -0
- package/js/coinfalcon.js +880 -0
- package/js/coinmate.js +794 -0
- package/js/coinone.js +816 -0
- package/js/coinspot.js +345 -0
- package/js/crex24.js +1636 -0
- package/js/cryptocom.js +1832 -0
- package/js/currencycom.js +1748 -0
- package/js/delta.js +1547 -0
- package/js/deribit.js +2148 -0
- package/js/digifinex.js +1585 -0
- package/js/eqonex.js +1660 -0
- package/js/exmo.js +1670 -0
- package/js/fairdesk.js +1231 -0
- package/js/flowbtc.js +35 -0
- package/js/fmfwio.js +34 -0
- package/js/ftx.js +2751 -0
- package/js/ftxus.js +38 -0
- package/js/gateio.js +4174 -0
- package/js/gemini.js +1397 -0
- package/js/hitbtc.js +1343 -0
- package/js/hitbtc3.js +2329 -0
- package/js/hollaex.js +1486 -0
- package/js/huobi.js +5706 -0
- package/js/huobijp.js +1710 -0
- package/js/huobipro.js +18 -0
- package/js/idex.js +1439 -0
- package/js/independentreserve.js +649 -0
- package/js/indodax.js +742 -0
- package/js/itbit.js +722 -0
- package/js/kraken.js +2179 -0
- package/js/kucoin.js +2571 -0
- package/js/kucoinfutures.js +1771 -0
- package/js/kuna.js +809 -0
- package/js/latoken.js +1445 -0
- package/js/lbank.js +760 -0
- package/js/liquid.js +1432 -0
- package/js/luno.js +873 -0
- package/js/lykke.js +1147 -0
- package/js/mercado.js +771 -0
- package/js/mexc.js +3151 -0
- package/js/ndax.js +2233 -0
- package/js/novadax.js +1318 -0
- package/js/oceanex.js +816 -0
- package/js/okcoin.js +3841 -0
- package/js/okex.js +16 -0
- package/js/okex5.js +16 -0
- package/js/okx.js +4795 -0
- package/js/paymium.js +498 -0
- package/js/phemex.js +2957 -0
- package/js/poloniex.js +1674 -0
- package/js/probit.js +1346 -0
- package/js/qtrade.js +1588 -0
- package/js/ripio.js +1061 -0
- package/js/static_dependencies/BN/bn.js +3526 -0
- package/js/static_dependencies/README.md +1 -0
- package/js/static_dependencies/crypto-js/crypto-js.js +5988 -0
- package/js/static_dependencies/elliptic/lib/elliptic/curve/base.js +375 -0
- package/js/static_dependencies/elliptic/lib/elliptic/curve/edwards.js +433 -0
- package/js/static_dependencies/elliptic/lib/elliptic/curve/index.js +8 -0
- package/js/static_dependencies/elliptic/lib/elliptic/curve/mont.js +180 -0
- package/js/static_dependencies/elliptic/lib/elliptic/curve/short.js +938 -0
- package/js/static_dependencies/elliptic/lib/elliptic/curves.js +204 -0
- package/js/static_dependencies/elliptic/lib/elliptic/ec/index.js +240 -0
- package/js/static_dependencies/elliptic/lib/elliptic/ec/key.js +119 -0
- package/js/static_dependencies/elliptic/lib/elliptic/ec/signature.js +24 -0
- package/js/static_dependencies/elliptic/lib/elliptic/eddsa/index.js +145 -0
- package/js/static_dependencies/elliptic/lib/elliptic/eddsa/key.js +100 -0
- package/js/static_dependencies/elliptic/lib/elliptic/eddsa/signature.js +65 -0
- package/js/static_dependencies/elliptic/lib/elliptic/precomputed/secp256k1.js +780 -0
- package/js/static_dependencies/elliptic/lib/elliptic/utils.js +214 -0
- package/js/static_dependencies/elliptic/lib/elliptic.js +22 -0
- package/js/static_dependencies/elliptic/lib/hmac-drbg/hmac-drbg.js +114 -0
- package/js/static_dependencies/fetch-ponyfill/fetch-node.js +39 -0
- package/js/static_dependencies/node-fetch/index.js +1564 -0
- package/js/static_dependencies/node-rsa/NodeRSA.js +223 -0
- package/js/static_dependencies/node-rsa/asn1/ber/errors.js +13 -0
- package/js/static_dependencies/node-rsa/asn1/ber/index.js +21 -0
- package/js/static_dependencies/node-rsa/asn1/ber/reader.js +262 -0
- package/js/static_dependencies/node-rsa/asn1/ber/types.js +36 -0
- package/js/static_dependencies/node-rsa/asn1/index.js +17 -0
- package/js/static_dependencies/node-rsa/encryptEngines/js.js +34 -0
- package/js/static_dependencies/node-rsa/formats/components.js +71 -0
- package/js/static_dependencies/node-rsa/formats/formats.js +31 -0
- package/js/static_dependencies/node-rsa/formats/pkcs1.js +148 -0
- package/js/static_dependencies/node-rsa/formats/pkcs8.js +187 -0
- package/js/static_dependencies/node-rsa/libs/jsbn.js +1252 -0
- package/js/static_dependencies/node-rsa/libs/rsa.js +147 -0
- package/js/static_dependencies/node-rsa/schemes/pkcs1.js +176 -0
- package/js/static_dependencies/node-rsa/schemes/schemes.js +21 -0
- package/js/static_dependencies/node-rsa/utils.js +98 -0
- package/js/static_dependencies/qs/formats.js +18 -0
- package/js/static_dependencies/qs/index.js +11 -0
- package/js/static_dependencies/qs/parse.js +242 -0
- package/js/static_dependencies/qs/stringify.js +269 -0
- package/js/static_dependencies/qs/utils.js +230 -0
- package/js/stex.js +1925 -0
- package/js/test/.eslintrc.js +42 -0
- package/js/test/Exchange/test.balance.js +61 -0
- package/js/test/Exchange/test.borrowRate.js +32 -0
- package/js/test/Exchange/test.currency.js +52 -0
- package/js/test/Exchange/test.fetchBalance.js +23 -0
- package/js/test/Exchange/test.fetchBorrowInterest.js +59 -0
- package/js/test/Exchange/test.fetchBorrowRate.js +32 -0
- package/js/test/Exchange/test.fetchBorrowRates.js +28 -0
- package/js/test/Exchange/test.fetchClosedOrders.js +32 -0
- package/js/test/Exchange/test.fetchCurrencies.js +35 -0
- package/js/test/Exchange/test.fetchDeposits.js +31 -0
- package/js/test/Exchange/test.fetchFundingFees.js +19 -0
- package/js/test/Exchange/test.fetchFundingRateHistory.js +40 -0
- package/js/test/Exchange/test.fetchL2OrderBook.js +23 -0
- package/js/test/Exchange/test.fetchLedger.js +42 -0
- package/js/test/Exchange/test.fetchLeverageTiers.js +33 -0
- package/js/test/Exchange/test.fetchMarketLeverageTiers.js +22 -0
- package/js/test/Exchange/test.fetchMarkets.js +33 -0
- package/js/test/Exchange/test.fetchMyTrades.js +42 -0
- package/js/test/Exchange/test.fetchOHLCV.js +46 -0
- package/js/test/Exchange/test.fetchOpenOrders.js +36 -0
- package/js/test/Exchange/test.fetchOrderBook.js +25 -0
- package/js/test/Exchange/test.fetchOrderBooks.js +35 -0
- package/js/test/Exchange/test.fetchOrders.js +41 -0
- package/js/test/Exchange/test.fetchPositions.js +47 -0
- package/js/test/Exchange/test.fetchStatus.js +35 -0
- package/js/test/Exchange/test.fetchTicker.js +38 -0
- package/js/test/Exchange/test.fetchTickers.js +49 -0
- package/js/test/Exchange/test.fetchTrades.js +39 -0
- package/js/test/Exchange/test.fetchTradingFee.js +18 -0
- package/js/test/Exchange/test.fetchTradingFees.js +22 -0
- package/js/test/Exchange/test.fetchTransactions.js +31 -0
- package/js/test/Exchange/test.fetchWithdrawals.js +31 -0
- package/js/test/Exchange/test.ledgerItem.js +46 -0
- package/js/test/Exchange/test.leverageTier.js +33 -0
- package/js/test/Exchange/test.loadMarkets.js +35 -0
- package/js/test/Exchange/test.market.js +129 -0
- package/js/test/Exchange/test.ohlcv.js +33 -0
- package/js/test/Exchange/test.order.js +62 -0
- package/js/test/Exchange/test.orderbook.js +61 -0
- package/js/test/Exchange/test.position.js +21 -0
- package/js/test/Exchange/test.throttle.js +94 -0
- package/js/test/Exchange/test.ticker.js +95 -0
- package/js/test/Exchange/test.trade.js +68 -0
- package/js/test/Exchange/test.tradingFee.js +34 -0
- package/js/test/Exchange/test.transaction.js +35 -0
- package/js/test/base/.eslintrc +38 -0
- package/js/test/base/functions/test.crypto.js +110 -0
- package/js/test/base/functions/test.datetime.js +62 -0
- package/js/test/base/functions/test.generic.js +152 -0
- package/js/test/base/functions/test.number.js +362 -0
- package/js/test/base/functions/test.time.js +56 -0
- package/js/test/base/functions/test.type.js +53 -0
- package/js/test/base/test.base.js +193 -0
- package/js/test/errors/test.InsufficientFunds.js +86 -0
- package/js/test/errors/test.InvalidNonce.js +64 -0
- package/js/test/errors/test.InvalidOrder.js +35 -0
- package/js/test/errors/test.OrderNotFound.js +39 -0
- package/js/test/test.js +426 -0
- package/js/test/test.timeout_hang.js +12 -0
- package/js/therock.js +1431 -0
- package/js/tidebit.js +632 -0
- package/js/tidex.js +939 -0
- package/js/timex.js +1283 -0
- package/js/upbit.js +1622 -0
- package/js/vcc.js +1353 -0
- package/js/wavesexchange.js +2185 -0
- package/js/wazirx.js +732 -0
- package/js/whitebit.js +1352 -0
- package/js/woo.js +1577 -0
- package/js/xena.js +1948 -0
- package/js/yobit.js +1129 -0
- package/js/zaif.js +647 -0
- package/js/zb.js +4088 -0
- package/js/zipmex.js +40 -0
- package/js/zonda.js +1497 -0
- package/multilang.sh +159 -0
- package/package.json +591 -0
- package/postinstall.js +103 -0
package/js/coinbase.js
ADDED
@@ -0,0 +1,1342 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
// ----------------------------------------------------------------------------
|
4
|
+
|
5
|
+
const Exchange = require ('./base/Exchange');
|
6
|
+
const { ExchangeError, ArgumentsRequired, AuthenticationError, RateLimitExceeded, InvalidNonce } = require ('./base/errors');
|
7
|
+
const Precise = require ('./base/Precise');
|
8
|
+
|
9
|
+
// ----------------------------------------------------------------------------
|
10
|
+
|
11
|
+
module.exports = class coinbase extends Exchange {
|
12
|
+
describe () {
|
13
|
+
return this.deepExtend (super.describe (), {
|
14
|
+
'id': 'coinbase',
|
15
|
+
'name': 'Coinbase',
|
16
|
+
'countries': [ 'US' ],
|
17
|
+
'rateLimit': 400, // 10k calls per hour
|
18
|
+
'version': 'v2',
|
19
|
+
'userAgent': this.userAgents['chrome'],
|
20
|
+
'headers': {
|
21
|
+
'CB-VERSION': '2018-05-30',
|
22
|
+
},
|
23
|
+
'has': {
|
24
|
+
'CORS': true,
|
25
|
+
'spot': true,
|
26
|
+
'margin': false,
|
27
|
+
'swap': false,
|
28
|
+
'future': false,
|
29
|
+
'option': false,
|
30
|
+
'addMargin': false,
|
31
|
+
'cancelOrder': undefined,
|
32
|
+
'createDepositAddress': true,
|
33
|
+
'createOrder': undefined,
|
34
|
+
'createReduceOnlyOrder': false,
|
35
|
+
'fetchAccounts': true,
|
36
|
+
'fetchBalance': true,
|
37
|
+
'fetchBidsAsks': undefined,
|
38
|
+
'fetchBorrowRate': false,
|
39
|
+
'fetchBorrowRateHistories': false,
|
40
|
+
'fetchBorrowRateHistory': false,
|
41
|
+
'fetchBorrowRates': false,
|
42
|
+
'fetchBorrowRatesPerSymbol': false,
|
43
|
+
'fetchClosedOrders': undefined,
|
44
|
+
'fetchCurrencies': true,
|
45
|
+
'fetchDepositAddress': undefined,
|
46
|
+
'fetchDeposits': true,
|
47
|
+
'fetchFundingHistory': false,
|
48
|
+
'fetchFundingRate': false,
|
49
|
+
'fetchFundingRateHistory': false,
|
50
|
+
'fetchFundingRates': false,
|
51
|
+
'fetchIndexOHLCV': false,
|
52
|
+
'fetchL2OrderBook': false,
|
53
|
+
'fetchLedger': true,
|
54
|
+
'fetchLeverage': false,
|
55
|
+
'fetchLeverageTiers': false,
|
56
|
+
'fetchMarkets': true,
|
57
|
+
'fetchMarkOHLCV': false,
|
58
|
+
'fetchMyBuys': true,
|
59
|
+
'fetchMySells': true,
|
60
|
+
'fetchMyTrades': undefined,
|
61
|
+
'fetchOHLCV': false,
|
62
|
+
'fetchOpenOrders': undefined,
|
63
|
+
'fetchOrder': undefined,
|
64
|
+
'fetchOrderBook': false,
|
65
|
+
'fetchOrders': undefined,
|
66
|
+
'fetchPosition': false,
|
67
|
+
'fetchPositions': false,
|
68
|
+
'fetchPositionsRisk': false,
|
69
|
+
'fetchPremiumIndexOHLCV': false,
|
70
|
+
'fetchTicker': true,
|
71
|
+
'fetchTickers': true,
|
72
|
+
'fetchTime': true,
|
73
|
+
'fetchTrades': undefined,
|
74
|
+
'fetchTradingFee': false,
|
75
|
+
'fetchTradingFees': false,
|
76
|
+
'fetchTransactions': undefined,
|
77
|
+
'fetchWithdrawals': true,
|
78
|
+
'reduceMargin': false,
|
79
|
+
'setLeverage': false,
|
80
|
+
'setMarginMode': false,
|
81
|
+
'setPositionMode': false,
|
82
|
+
'withdraw': undefined,
|
83
|
+
},
|
84
|
+
'urls': {
|
85
|
+
'logo': 'https://user-images.githubusercontent.com/1294454/40811661-b6eceae2-653a-11e8-829e-10bfadb078cf.jpg',
|
86
|
+
'api': 'https://api.coinbase.com',
|
87
|
+
'www': 'https://www.coinbase.com',
|
88
|
+
'doc': 'https://developers.coinbase.com/api/v2',
|
89
|
+
'fees': 'https://support.coinbase.com/customer/portal/articles/2109597-buy-sell-bank-transfer-fees',
|
90
|
+
'referral': 'https://www.coinbase.com/join/58cbe25a355148797479dbd2',
|
91
|
+
},
|
92
|
+
'requiredCredentials': {
|
93
|
+
'apiKey': true,
|
94
|
+
'secret': true,
|
95
|
+
},
|
96
|
+
'api': {
|
97
|
+
'public': {
|
98
|
+
'get': [
|
99
|
+
'currencies',
|
100
|
+
'time',
|
101
|
+
'exchange-rates',
|
102
|
+
'users/{user_id}',
|
103
|
+
'prices/{symbol}/buy',
|
104
|
+
'prices/{symbol}/sell',
|
105
|
+
'prices/{symbol}/spot',
|
106
|
+
],
|
107
|
+
},
|
108
|
+
'private': {
|
109
|
+
'get': [
|
110
|
+
'accounts',
|
111
|
+
'accounts/{account_id}',
|
112
|
+
'accounts/{account_id}/addresses',
|
113
|
+
'accounts/{account_id}/addresses/{address_id}',
|
114
|
+
'accounts/{account_id}/addresses/{address_id}/transactions',
|
115
|
+
'accounts/{account_id}/transactions',
|
116
|
+
'accounts/{account_id}/transactions/{transaction_id}',
|
117
|
+
'accounts/{account_id}/buys',
|
118
|
+
'accounts/{account_id}/buys/{buy_id}',
|
119
|
+
'accounts/{account_id}/sells',
|
120
|
+
'accounts/{account_id}/sells/{sell_id}',
|
121
|
+
'accounts/{account_id}/deposits',
|
122
|
+
'accounts/{account_id}/deposits/{deposit_id}',
|
123
|
+
'accounts/{account_id}/withdrawals',
|
124
|
+
'accounts/{account_id}/withdrawals/{withdrawal_id}',
|
125
|
+
'payment-methods',
|
126
|
+
'payment-methods/{payment_method_id}',
|
127
|
+
'user',
|
128
|
+
'user/auth',
|
129
|
+
],
|
130
|
+
'post': [
|
131
|
+
'accounts',
|
132
|
+
'accounts/{account_id}/primary',
|
133
|
+
'accounts/{account_id}/addresses',
|
134
|
+
'accounts/{account_id}/transactions',
|
135
|
+
'accounts/{account_id}/transactions/{transaction_id}/complete',
|
136
|
+
'accounts/{account_id}/transactions/{transaction_id}/resend',
|
137
|
+
'accounts/{account_id}/buys',
|
138
|
+
'accounts/{account_id}/buys/{buy_id}/commit',
|
139
|
+
'accounts/{account_id}/sells',
|
140
|
+
'accounts/{account_id}/sells/{sell_id}/commit',
|
141
|
+
'accounts/{account_id}/deposists',
|
142
|
+
'accounts/{account_id}/deposists/{deposit_id}/commit',
|
143
|
+
'accounts/{account_id}/withdrawals',
|
144
|
+
'accounts/{account_id}/withdrawals/{withdrawal_id}/commit',
|
145
|
+
],
|
146
|
+
'put': [
|
147
|
+
'accounts/{account_id}',
|
148
|
+
'user',
|
149
|
+
],
|
150
|
+
'delete': [
|
151
|
+
'accounts/{id}',
|
152
|
+
'accounts/{account_id}/transactions/{transaction_id}',
|
153
|
+
],
|
154
|
+
},
|
155
|
+
},
|
156
|
+
'exceptions': {
|
157
|
+
'exact': {
|
158
|
+
'two_factor_required': AuthenticationError, // 402 When sending money over 2fa limit
|
159
|
+
'param_required': ExchangeError, // 400 Missing parameter
|
160
|
+
'validation_error': ExchangeError, // 400 Unable to validate POST/PUT
|
161
|
+
'invalid_request': ExchangeError, // 400 Invalid request
|
162
|
+
'personal_details_required': AuthenticationError, // 400 User’s personal detail required to complete this request
|
163
|
+
'identity_verification_required': AuthenticationError, // 400 Identity verification is required to complete this request
|
164
|
+
'jumio_verification_required': AuthenticationError, // 400 Document verification is required to complete this request
|
165
|
+
'jumio_face_match_verification_required': AuthenticationError, // 400 Document verification including face match is required to complete this request
|
166
|
+
'unverified_email': AuthenticationError, // 400 User has not verified their email
|
167
|
+
'authentication_error': AuthenticationError, // 401 Invalid auth (generic)
|
168
|
+
'invalid_authentication_method': AuthenticationError, // 401 API access is blocked for deleted users.
|
169
|
+
'invalid_token': AuthenticationError, // 401 Invalid Oauth token
|
170
|
+
'revoked_token': AuthenticationError, // 401 Revoked Oauth token
|
171
|
+
'expired_token': AuthenticationError, // 401 Expired Oauth token
|
172
|
+
'invalid_scope': AuthenticationError, // 403 User hasn’t authenticated necessary scope
|
173
|
+
'not_found': ExchangeError, // 404 Resource not found
|
174
|
+
'rate_limit_exceeded': RateLimitExceeded, // 429 Rate limit exceeded
|
175
|
+
'internal_server_error': ExchangeError, // 500 Internal server error
|
176
|
+
},
|
177
|
+
'broad': {
|
178
|
+
'request timestamp expired': InvalidNonce, // {"errors":[{"id":"authentication_error","message":"request timestamp expired"}]}
|
179
|
+
},
|
180
|
+
},
|
181
|
+
'commonCurrencies': {
|
182
|
+
'CGLD': 'CELO',
|
183
|
+
},
|
184
|
+
'options': {
|
185
|
+
'fetchCurrencies': {
|
186
|
+
'expires': 5000,
|
187
|
+
},
|
188
|
+
'accounts': [
|
189
|
+
'wallet',
|
190
|
+
'fiat',
|
191
|
+
// 'vault',
|
192
|
+
],
|
193
|
+
},
|
194
|
+
});
|
195
|
+
}
|
196
|
+
|
197
|
+
async fetchTime (params = {}) {
|
198
|
+
const response = await this.publicGetTime (params);
|
199
|
+
//
|
200
|
+
// {
|
201
|
+
// "data": {
|
202
|
+
// "epoch": 1589295679,
|
203
|
+
// "iso": "2020-05-12T15:01:19Z"
|
204
|
+
// }
|
205
|
+
// }
|
206
|
+
//
|
207
|
+
const data = this.safeValue (response, 'data', {});
|
208
|
+
return this.safeTimestamp (data, 'epoch');
|
209
|
+
}
|
210
|
+
|
211
|
+
async fetchAccounts (params = {}) {
|
212
|
+
await this.loadMarkets ();
|
213
|
+
const request = {
|
214
|
+
'limit': 100,
|
215
|
+
};
|
216
|
+
const response = await this.privateGetAccounts (this.extend (request, params));
|
217
|
+
//
|
218
|
+
// {
|
219
|
+
// "id": "XLM",
|
220
|
+
// "name": "XLM Wallet",
|
221
|
+
// "primary": false,
|
222
|
+
// "type": "wallet",
|
223
|
+
// "currency": {
|
224
|
+
// "code": "XLM",
|
225
|
+
// "name": "Stellar Lumens",
|
226
|
+
// "color": "#000000",
|
227
|
+
// "sort_index": 127,
|
228
|
+
// "exponent": 7,
|
229
|
+
// "type": "crypto",
|
230
|
+
// "address_regex": "^G[A-Z2-7]{55}$",
|
231
|
+
// "asset_id": "13b83335-5ede-595b-821e-5bcdfa80560f",
|
232
|
+
// "destination_tag_name": "XLM Memo ID",
|
233
|
+
// "destination_tag_regex": "^[ -~]{1,28}$"
|
234
|
+
// },
|
235
|
+
// "balance": {
|
236
|
+
// "amount": "0.0000000",
|
237
|
+
// "currency": "XLM"
|
238
|
+
// },
|
239
|
+
// "created_at": null,
|
240
|
+
// "updated_at": null,
|
241
|
+
// "resource": "account",
|
242
|
+
// "resource_path": "/v2/accounts/XLM",
|
243
|
+
// "allow_deposits": true,
|
244
|
+
// "allow_withdrawals": true
|
245
|
+
// }
|
246
|
+
//
|
247
|
+
const data = this.safeValue (response, 'data', []);
|
248
|
+
const result = [];
|
249
|
+
for (let i = 0; i < data.length; i++) {
|
250
|
+
const account = data[i];
|
251
|
+
const currency = this.safeValue (account, 'currency', {});
|
252
|
+
const currencyId = this.safeString (currency, 'code');
|
253
|
+
const code = this.safeCurrencyCode (currencyId);
|
254
|
+
result.push ({
|
255
|
+
'id': this.safeString (account, 'id'),
|
256
|
+
'type': this.safeString (account, 'type'),
|
257
|
+
'code': code,
|
258
|
+
'info': account,
|
259
|
+
});
|
260
|
+
}
|
261
|
+
return result;
|
262
|
+
}
|
263
|
+
|
264
|
+
async createDepositAddress (code, params = {}) {
|
265
|
+
let accountId = this.safeString (params, 'account_id');
|
266
|
+
params = this.omit (params, 'account_id');
|
267
|
+
if (accountId === undefined) {
|
268
|
+
await this.loadAccounts ();
|
269
|
+
for (let i = 0; i < this.accounts.length; i++) {
|
270
|
+
const account = this.accounts[i];
|
271
|
+
if (account['code'] === code && account['type'] === 'wallet') {
|
272
|
+
accountId = account['id'];
|
273
|
+
break;
|
274
|
+
}
|
275
|
+
}
|
276
|
+
}
|
277
|
+
if (accountId === undefined) {
|
278
|
+
throw new ExchangeError (this.id + ' createDepositAddress() could not find the account with matching currency code, specify an `account_id` extra param');
|
279
|
+
}
|
280
|
+
const request = {
|
281
|
+
'account_id': accountId,
|
282
|
+
};
|
283
|
+
const response = await this.privatePostAccountsAccountIdAddresses (this.extend (request, params));
|
284
|
+
//
|
285
|
+
// {
|
286
|
+
// "data": {
|
287
|
+
// "id": "05b1ebbf-9438-5dd4-b297-2ddedc98d0e4",
|
288
|
+
// "address": "coinbasebase",
|
289
|
+
// "address_info": {
|
290
|
+
// "address": "coinbasebase",
|
291
|
+
// "destination_tag": "287594668"
|
292
|
+
// },
|
293
|
+
// "name": null,
|
294
|
+
// "created_at": "2019-07-01T14:39:29Z",
|
295
|
+
// "updated_at": "2019-07-01T14:39:29Z",
|
296
|
+
// "network": "eosio",
|
297
|
+
// "uri_scheme": "eosio",
|
298
|
+
// "resource": "address",
|
299
|
+
// "resource_path": "/v2/accounts/14cfc769-e852-52f3-b831-711c104d194c/addresses/05b1ebbf-9438-5dd4-b297-2ddedc98d0e4",
|
300
|
+
// "warnings": [
|
301
|
+
// {
|
302
|
+
// "title": "Only send EOS (EOS) to this address",
|
303
|
+
// "details": "Sending any other cryptocurrency will result in permanent loss.",
|
304
|
+
// "image_url": "https://dynamic-assets.coinbase.com/deaca3d47b10ed4a91a872e9618706eec34081127762d88f2476ac8e99ada4b48525a9565cf2206d18c04053f278f693434af4d4629ca084a9d01b7a286a7e26/asset_icons/1f8489bb280fb0a0fd643c1161312ba49655040e9aaaced5f9ad3eeaf868eadc.png"
|
305
|
+
// },
|
306
|
+
// {
|
307
|
+
// "title": "Both an address and EOS memo are required to receive EOS",
|
308
|
+
// "details": "If you send funds without an EOS memo or with an incorrect EOS memo, your funds cannot be credited to your account.",
|
309
|
+
// "image_url": "https://www.coinbase.com/assets/receive-warning-2f3269d83547a7748fb39d6e0c1c393aee26669bfea6b9f12718094a1abff155.png"
|
310
|
+
// }
|
311
|
+
// ],
|
312
|
+
// "warning_title": "Only send EOS (EOS) to this address",
|
313
|
+
// "warning_details": "Sending any other cryptocurrency will result in permanent loss.",
|
314
|
+
// "destination_tag": "287594668",
|
315
|
+
// "deposit_uri": "eosio:coinbasebase?dt=287594668",
|
316
|
+
// "callback_url": null
|
317
|
+
// }
|
318
|
+
// }
|
319
|
+
//
|
320
|
+
const data = this.safeValue (response, 'data', {});
|
321
|
+
const tag = this.safeString (data, 'destination_tag');
|
322
|
+
const address = this.safeString (data, 'address');
|
323
|
+
return {
|
324
|
+
'currency': code,
|
325
|
+
'tag': tag,
|
326
|
+
'address': address,
|
327
|
+
'info': response,
|
328
|
+
};
|
329
|
+
}
|
330
|
+
|
331
|
+
async fetchMySells (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
332
|
+
// they don't have an endpoint for all historical trades
|
333
|
+
const request = await this.prepareAccountRequest (limit, params);
|
334
|
+
await this.loadMarkets ();
|
335
|
+
const query = this.omit (params, [ 'account_id', 'accountId' ]);
|
336
|
+
const sells = await this.privateGetAccountsAccountIdSells (this.extend (request, query));
|
337
|
+
return this.parseTrades (sells['data'], undefined, since, limit);
|
338
|
+
}
|
339
|
+
|
340
|
+
async fetchMyBuys (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
341
|
+
// they don't have an endpoint for all historical trades
|
342
|
+
const request = await this.prepareAccountRequest (limit, params);
|
343
|
+
await this.loadMarkets ();
|
344
|
+
const query = this.omit (params, [ 'account_id', 'accountId' ]);
|
345
|
+
const buys = await this.privateGetAccountsAccountIdBuys (this.extend (request, query));
|
346
|
+
return this.parseTrades (buys['data'], undefined, since, limit);
|
347
|
+
}
|
348
|
+
|
349
|
+
async fetchTransactionsWithMethod (method, code = undefined, since = undefined, limit = undefined, params = {}) {
|
350
|
+
const request = await this.prepareAccountRequestWithCurrencyCode (code, limit, params);
|
351
|
+
await this.loadMarkets ();
|
352
|
+
const query = this.omit (params, [ 'account_id', 'accountId' ]);
|
353
|
+
const response = await this[method] (this.extend (request, query));
|
354
|
+
return this.parseTransactions (response['data'], undefined, since, limit);
|
355
|
+
}
|
356
|
+
|
357
|
+
async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
|
358
|
+
// fiat only, for crypto transactions use fetchLedger
|
359
|
+
return await this.fetchTransactionsWithMethod ('privateGetAccountsAccountIdWithdrawals', code, since, limit, params);
|
360
|
+
}
|
361
|
+
|
362
|
+
async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
|
363
|
+
// fiat only, for crypto transactions use fetchLedger
|
364
|
+
return await this.fetchTransactionsWithMethod ('privateGetAccountsAccountIdDeposits', code, since, limit, params);
|
365
|
+
}
|
366
|
+
|
367
|
+
parseTransactionStatus (status) {
|
368
|
+
const statuses = {
|
369
|
+
'created': 'pending',
|
370
|
+
'completed': 'ok',
|
371
|
+
'canceled': 'canceled',
|
372
|
+
};
|
373
|
+
return this.safeString (statuses, status, status);
|
374
|
+
}
|
375
|
+
|
376
|
+
parseTransaction (transaction, market = undefined) {
|
377
|
+
//
|
378
|
+
// fiat deposit
|
379
|
+
//
|
380
|
+
// {
|
381
|
+
// "id": "f34c19f3-b730-5e3d-9f72",
|
382
|
+
// "status": "completed",
|
383
|
+
// "payment_method": {
|
384
|
+
// "id": "a022b31d-f9c7-5043-98f2",
|
385
|
+
// "resource": "payment_method",
|
386
|
+
// "resource_path": "/v2/payment-methods/a022b31d-f9c7-5043-98f2"
|
387
|
+
// },
|
388
|
+
// "transaction": {
|
389
|
+
// "id": "04ed4113-3732-5b0c-af86-b1d2146977d0",
|
390
|
+
// "resource": "transaction",
|
391
|
+
// "resource_path": "/v2/accounts/91cd2d36-3a91-55b6-a5d4-0124cf105483/transactions/04ed4113-3732-5b0c-af86"
|
392
|
+
// },
|
393
|
+
// "user_reference": "2VTYTH",
|
394
|
+
// "created_at": "2017-02-09T07:01:18Z",
|
395
|
+
// "updated_at": "2017-02-09T07:01:26Z",
|
396
|
+
// "resource": "deposit",
|
397
|
+
// "resource_path": "/v2/accounts/91cd2d36-3a91-55b6-a5d4-0124cf105483/deposits/f34c19f3-b730-5e3d-9f72",
|
398
|
+
// "committed": true,
|
399
|
+
// "payout_at": "2017-02-12T07:01:17Z",
|
400
|
+
// "instant": false,
|
401
|
+
// "fee": { "amount": "0.00", "currency": "EUR" },
|
402
|
+
// "amount": { "amount": "114.02", "currency": "EUR" },
|
403
|
+
// "subtotal": { "amount": "114.02", "currency": "EUR" },
|
404
|
+
// "hold_until": null,
|
405
|
+
// "hold_days": 0,
|
406
|
+
// "hold_business_days": 0,
|
407
|
+
// "next_step": null
|
408
|
+
// }
|
409
|
+
//
|
410
|
+
// fiat_withdrawal
|
411
|
+
//
|
412
|
+
// {
|
413
|
+
// "id": "cfcc3b4a-eeb6-5e8c-8058",
|
414
|
+
// "status": "completed",
|
415
|
+
// "payment_method": {
|
416
|
+
// "id": "8b94cfa4-f7fd-5a12-a76a",
|
417
|
+
// "resource": "payment_method",
|
418
|
+
// "resource_path": "/v2/payment-methods/8b94cfa4-f7fd-5a12-a76a"
|
419
|
+
// },
|
420
|
+
// "transaction": {
|
421
|
+
// "id": "fcc2550b-5104-5f83-a444",
|
422
|
+
// "resource": "transaction",
|
423
|
+
// "resource_path": "/v2/accounts/91cd2d36-3a91-55b6-a5d4-0124cf105483/transactions/fcc2550b-5104-5f83-a444"
|
424
|
+
// },
|
425
|
+
// "user_reference": "MEUGK",
|
426
|
+
// "created_at": "2018-07-26T08:55:12Z",
|
427
|
+
// "updated_at": "2018-07-26T08:58:18Z",
|
428
|
+
// "resource": "withdrawal",
|
429
|
+
// "resource_path": "/v2/accounts/91cd2d36-3a91-55b6-a5d4-0124cf105483/withdrawals/cfcc3b4a-eeb6-5e8c-8058",
|
430
|
+
// "committed": true,
|
431
|
+
// "payout_at": "2018-07-31T08:55:12Z",
|
432
|
+
// "instant": false,
|
433
|
+
// "fee": { "amount": "0.15", "currency": "EUR" },
|
434
|
+
// "amount": { "amount": "13130.69", "currency": "EUR" },
|
435
|
+
// "subtotal": { "amount": "13130.84", "currency": "EUR" },
|
436
|
+
// "idem": "e549dee5-63ed-4e79-8a96",
|
437
|
+
// "next_step": null
|
438
|
+
// }
|
439
|
+
//
|
440
|
+
const subtotalObject = this.safeValue (transaction, 'subtotal', {});
|
441
|
+
const feeObject = this.safeValue (transaction, 'fee', {});
|
442
|
+
const id = this.safeString (transaction, 'id');
|
443
|
+
const timestamp = this.parse8601 (this.safeValue (transaction, 'created_at'));
|
444
|
+
const updated = this.parse8601 (this.safeValue (transaction, 'updated_at'));
|
445
|
+
const type = this.safeString (transaction, 'resource');
|
446
|
+
const amount = this.safeNumber (subtotalObject, 'amount');
|
447
|
+
const currencyId = this.safeString (subtotalObject, 'currency');
|
448
|
+
const currency = this.safeCurrencyCode (currencyId);
|
449
|
+
const feeCost = this.safeNumber (feeObject, 'amount');
|
450
|
+
const feeCurrencyId = this.safeString (feeObject, 'currency');
|
451
|
+
const feeCurrency = this.safeCurrencyCode (feeCurrencyId);
|
452
|
+
const fee = {
|
453
|
+
'cost': feeCost,
|
454
|
+
'currency': feeCurrency,
|
455
|
+
};
|
456
|
+
let status = this.parseTransactionStatus (this.safeString (transaction, 'status'));
|
457
|
+
if (status === undefined) {
|
458
|
+
const committed = this.safeValue (transaction, 'committed');
|
459
|
+
status = committed ? 'ok' : 'pending';
|
460
|
+
}
|
461
|
+
return {
|
462
|
+
'info': transaction,
|
463
|
+
'id': id,
|
464
|
+
'txid': id,
|
465
|
+
'timestamp': timestamp,
|
466
|
+
'datetime': this.iso8601 (timestamp),
|
467
|
+
'network': undefined,
|
468
|
+
'address': undefined,
|
469
|
+
'addressTo': undefined,
|
470
|
+
'addressFrom': undefined,
|
471
|
+
'tag': undefined,
|
472
|
+
'tagTo': undefined,
|
473
|
+
'tagFrom': undefined,
|
474
|
+
'type': type,
|
475
|
+
'amount': amount,
|
476
|
+
'currency': currency,
|
477
|
+
'status': status,
|
478
|
+
'updated': updated,
|
479
|
+
'fee': fee,
|
480
|
+
};
|
481
|
+
}
|
482
|
+
|
483
|
+
parseTrade (trade, market = undefined) {
|
484
|
+
//
|
485
|
+
// {
|
486
|
+
// "id": "67e0eaec-07d7-54c4-a72c-2e92826897df",
|
487
|
+
// "status": "completed",
|
488
|
+
// "payment_method": {
|
489
|
+
// "id": "83562370-3e5c-51db-87da-752af5ab9559",
|
490
|
+
// "resource": "payment_method",
|
491
|
+
// "resource_path": "/v2/payment-methods/83562370-3e5c-51db-87da-752af5ab9559"
|
492
|
+
// },
|
493
|
+
// "transaction": {
|
494
|
+
// "id": "441b9494-b3f0-5b98-b9b0-4d82c21c252a",
|
495
|
+
// "resource": "transaction",
|
496
|
+
// "resource_path": "/v2/accounts/2bbf394c-193b-5b2a-9155-3b4732659ede/transactions/441b9494-b3f0-5b98-b9b0-4d82c21c252a"
|
497
|
+
// },
|
498
|
+
// "amount": { "amount": "1.00000000", "currency": "BTC" },
|
499
|
+
// "total": { "amount": "10.25", "currency": "USD" },
|
500
|
+
// "subtotal": { "amount": "10.10", "currency": "USD" },
|
501
|
+
// "created_at": "2015-01-31T20:49:02Z",
|
502
|
+
// "updated_at": "2015-02-11T16:54:02-08:00",
|
503
|
+
// "resource": "buy",
|
504
|
+
// "resource_path": "/v2/accounts/2bbf394c-193b-5b2a-9155-3b4732659ede/buys/67e0eaec-07d7-54c4-a72c-2e92826897df",
|
505
|
+
// "committed": true,
|
506
|
+
// "instant": false,
|
507
|
+
// "fee": { "amount": "0.15", "currency": "USD" },
|
508
|
+
// "payout_at": "2015-02-18T16:54:00-08:00"
|
509
|
+
// }
|
510
|
+
//
|
511
|
+
let symbol = undefined;
|
512
|
+
const totalObject = this.safeValue (trade, 'total', {});
|
513
|
+
const amountObject = this.safeValue (trade, 'amount', {});
|
514
|
+
const subtotalObject = this.safeValue (trade, 'subtotal', {});
|
515
|
+
const feeObject = this.safeValue (trade, 'fee', {});
|
516
|
+
const id = this.safeString (trade, 'id');
|
517
|
+
const timestamp = this.parse8601 (this.safeValue (trade, 'created_at'));
|
518
|
+
if (market === undefined) {
|
519
|
+
const baseId = this.safeString (amountObject, 'currency');
|
520
|
+
const quoteId = this.safeString (totalObject, 'currency');
|
521
|
+
if ((baseId !== undefined) && (quoteId !== undefined)) {
|
522
|
+
const base = this.safeCurrencyCode (baseId);
|
523
|
+
const quote = this.safeCurrencyCode (quoteId);
|
524
|
+
symbol = base + '/' + quote;
|
525
|
+
}
|
526
|
+
}
|
527
|
+
const orderId = undefined;
|
528
|
+
const side = this.safeString (trade, 'resource');
|
529
|
+
const type = undefined;
|
530
|
+
const costString = this.safeString (subtotalObject, 'amount');
|
531
|
+
const amountString = this.safeString (amountObject, 'amount');
|
532
|
+
const cost = this.parseNumber (costString);
|
533
|
+
const amount = this.parseNumber (amountString);
|
534
|
+
const price = this.parseNumber (Precise.stringDiv (costString, amountString));
|
535
|
+
const feeCost = this.safeNumber (feeObject, 'amount');
|
536
|
+
const feeCurrencyId = this.safeString (feeObject, 'currency');
|
537
|
+
const feeCurrency = this.safeCurrencyCode (feeCurrencyId);
|
538
|
+
const fee = {
|
539
|
+
'cost': feeCost,
|
540
|
+
'currency': feeCurrency,
|
541
|
+
};
|
542
|
+
return {
|
543
|
+
'info': trade,
|
544
|
+
'id': id,
|
545
|
+
'order': orderId,
|
546
|
+
'timestamp': timestamp,
|
547
|
+
'datetime': this.iso8601 (timestamp),
|
548
|
+
'symbol': symbol,
|
549
|
+
'type': type,
|
550
|
+
'side': side,
|
551
|
+
'takerOrMaker': undefined,
|
552
|
+
'price': price,
|
553
|
+
'amount': amount,
|
554
|
+
'cost': cost,
|
555
|
+
'fee': fee,
|
556
|
+
};
|
557
|
+
}
|
558
|
+
|
559
|
+
async fetchMarkets (params = {}) {
|
560
|
+
const response = await this.fetchCurrenciesFromCache (params);
|
561
|
+
const currencies = this.safeValue (response, 'currencies', {});
|
562
|
+
const exchangeRates = this.safeValue (response, 'exchangeRates', {});
|
563
|
+
const data = this.safeValue (currencies, 'data', []);
|
564
|
+
const dataById = this.indexBy (data, 'id');
|
565
|
+
const rates = this.safeValue (this.safeValue (exchangeRates, 'data', {}), 'rates', {});
|
566
|
+
const baseIds = Object.keys (rates);
|
567
|
+
const result = [];
|
568
|
+
for (let i = 0; i < baseIds.length; i++) {
|
569
|
+
const baseId = baseIds[i];
|
570
|
+
const base = this.safeCurrencyCode (baseId);
|
571
|
+
const type = (baseId in dataById) ? 'fiat' : 'crypto';
|
572
|
+
// https://github.com/ccxt/ccxt/issues/6066
|
573
|
+
if (type === 'crypto') {
|
574
|
+
for (let j = 0; j < data.length; j++) {
|
575
|
+
const quoteCurrency = data[j];
|
576
|
+
const quoteId = this.safeString (quoteCurrency, 'id');
|
577
|
+
const quote = this.safeCurrencyCode (quoteId);
|
578
|
+
result.push ({
|
579
|
+
'id': baseId + '-' + quoteId,
|
580
|
+
'symbol': base + '/' + quote,
|
581
|
+
'base': base,
|
582
|
+
'quote': quote,
|
583
|
+
'settle': undefined,
|
584
|
+
'baseId': baseId,
|
585
|
+
'quoteId': quoteId,
|
586
|
+
'settleId': undefined,
|
587
|
+
'type': 'spot',
|
588
|
+
'spot': true,
|
589
|
+
'margin': false,
|
590
|
+
'swap': false,
|
591
|
+
'future': false,
|
592
|
+
'option': false,
|
593
|
+
'active': undefined,
|
594
|
+
'contract': false,
|
595
|
+
'linear': undefined,
|
596
|
+
'inverse': undefined,
|
597
|
+
'contractSize': undefined,
|
598
|
+
'expiry': undefined,
|
599
|
+
'expiryDatetime': undefined,
|
600
|
+
'strike': undefined,
|
601
|
+
'optionType': undefined,
|
602
|
+
'precision': {
|
603
|
+
'amount': undefined,
|
604
|
+
'price': undefined,
|
605
|
+
},
|
606
|
+
'limits': {
|
607
|
+
'leverage': {
|
608
|
+
'min': undefined,
|
609
|
+
'max': undefined,
|
610
|
+
},
|
611
|
+
'amount': {
|
612
|
+
'min': undefined,
|
613
|
+
'max': undefined,
|
614
|
+
},
|
615
|
+
'price': {
|
616
|
+
'min': undefined,
|
617
|
+
'max': undefined,
|
618
|
+
},
|
619
|
+
'cost': {
|
620
|
+
'min': this.safeNumber (quoteCurrency, 'min_size'),
|
621
|
+
'max': undefined,
|
622
|
+
},
|
623
|
+
},
|
624
|
+
'info': quoteCurrency,
|
625
|
+
});
|
626
|
+
}
|
627
|
+
}
|
628
|
+
}
|
629
|
+
return result;
|
630
|
+
}
|
631
|
+
|
632
|
+
async fetchCurrenciesFromCache (params = {}) {
|
633
|
+
const options = this.safeValue (this.options, 'fetchCurrencies', {});
|
634
|
+
const timestamp = this.safeInteger (options, 'timestamp');
|
635
|
+
const expires = this.safeInteger (options, 'expires', 1000);
|
636
|
+
const now = this.milliseconds ();
|
637
|
+
if ((timestamp === undefined) || ((now - timestamp) > expires)) {
|
638
|
+
const currencies = await this.publicGetCurrencies (params);
|
639
|
+
const exchangeRates = await this.publicGetExchangeRates (params);
|
640
|
+
this.options['fetchCurrencies'] = this.extend (options, {
|
641
|
+
'currencies': currencies,
|
642
|
+
'exchangeRates': exchangeRates,
|
643
|
+
'timestamp': now,
|
644
|
+
});
|
645
|
+
}
|
646
|
+
return this.safeValue (this.options, 'fetchCurrencies', {});
|
647
|
+
}
|
648
|
+
|
649
|
+
async fetchCurrencies (params = {}) {
|
650
|
+
const response = await this.fetchCurrenciesFromCache (params);
|
651
|
+
const currencies = this.safeValue (response, 'currencies', {});
|
652
|
+
//
|
653
|
+
// {
|
654
|
+
// "data":[
|
655
|
+
// {"id":"AED","name":"United Arab Emirates Dirham","min_size":"0.01000000"},
|
656
|
+
// {"id":"AFN","name":"Afghan Afghani","min_size":"0.01000000"},
|
657
|
+
// {"id":"ALL","name":"Albanian Lek","min_size":"0.01000000"},
|
658
|
+
// {"id":"AMD","name":"Armenian Dram","min_size":"0.01000000"},
|
659
|
+
// {"id":"ANG","name":"Netherlands Antillean Gulden","min_size":"0.01000000"},
|
660
|
+
// // ...
|
661
|
+
// ],
|
662
|
+
// }
|
663
|
+
//
|
664
|
+
const exchangeRates = this.safeValue (response, 'exchangeRates', {});
|
665
|
+
//
|
666
|
+
// {
|
667
|
+
// "data":{
|
668
|
+
// "currency":"USD",
|
669
|
+
// "rates":{
|
670
|
+
// "AED":"3.67",
|
671
|
+
// "AFN":"78.21",
|
672
|
+
// "ALL":"110.42",
|
673
|
+
// "AMD":"474.18",
|
674
|
+
// "ANG":"1.75",
|
675
|
+
// // ...
|
676
|
+
// },
|
677
|
+
// }
|
678
|
+
// }
|
679
|
+
//
|
680
|
+
const data = this.safeValue (currencies, 'data', []);
|
681
|
+
const dataById = this.indexBy (data, 'id');
|
682
|
+
const rates = this.safeValue (this.safeValue (exchangeRates, 'data', {}), 'rates', {});
|
683
|
+
const keys = Object.keys (rates);
|
684
|
+
const result = {};
|
685
|
+
for (let i = 0; i < keys.length; i++) {
|
686
|
+
const key = keys[i];
|
687
|
+
const type = (key in dataById) ? 'fiat' : 'crypto';
|
688
|
+
const currency = this.safeValue (dataById, key, {});
|
689
|
+
const id = this.safeString (currency, 'id', key);
|
690
|
+
const name = this.safeString (currency, 'name');
|
691
|
+
const code = this.safeCurrencyCode (id);
|
692
|
+
result[code] = {
|
693
|
+
'id': id,
|
694
|
+
'code': code,
|
695
|
+
'info': currency, // the original payload
|
696
|
+
'type': type,
|
697
|
+
'name': name,
|
698
|
+
'active': true,
|
699
|
+
'deposit': undefined,
|
700
|
+
'withdraw': undefined,
|
701
|
+
'fee': undefined,
|
702
|
+
'precision': undefined,
|
703
|
+
'limits': {
|
704
|
+
'amount': {
|
705
|
+
'min': this.safeNumber (currency, 'min_size'),
|
706
|
+
'max': undefined,
|
707
|
+
},
|
708
|
+
'withdraw': {
|
709
|
+
'min': undefined,
|
710
|
+
'max': undefined,
|
711
|
+
},
|
712
|
+
},
|
713
|
+
};
|
714
|
+
}
|
715
|
+
return result;
|
716
|
+
}
|
717
|
+
|
718
|
+
async fetchTickers (symbols = undefined, params = {}) {
|
719
|
+
await this.loadMarkets ();
|
720
|
+
const request = {
|
721
|
+
// 'currency': 'USD',
|
722
|
+
};
|
723
|
+
const response = await this.publicGetExchangeRates (this.extend (request, params));
|
724
|
+
//
|
725
|
+
// {
|
726
|
+
// "data":{
|
727
|
+
// "currency":"USD",
|
728
|
+
// "rates":{
|
729
|
+
// "AED":"3.6731",
|
730
|
+
// "AFN":"103.163942",
|
731
|
+
// "ALL":"106.973038",
|
732
|
+
// }
|
733
|
+
// }
|
734
|
+
// }
|
735
|
+
//
|
736
|
+
const data = this.safeValue (response, 'data', {});
|
737
|
+
const rates = this.safeValue (data, 'rates', {});
|
738
|
+
const quoteId = this.safeString (data, 'currency');
|
739
|
+
const result = {};
|
740
|
+
const baseIds = Object.keys (rates);
|
741
|
+
const delimiter = '-';
|
742
|
+
for (let i = 0; i < baseIds.length; i++) {
|
743
|
+
const baseId = baseIds[i];
|
744
|
+
const marketId = baseId + delimiter + quoteId;
|
745
|
+
const market = this.safeMarket (marketId, undefined, delimiter);
|
746
|
+
const symbol = market['symbol'];
|
747
|
+
result[symbol] = this.parseTicker (rates[baseId], market);
|
748
|
+
}
|
749
|
+
return this.filterByArray (result, 'symbol', symbols);
|
750
|
+
}
|
751
|
+
|
752
|
+
async fetchTicker (symbol, params = {}) {
|
753
|
+
await this.loadMarkets ();
|
754
|
+
const market = this.market (symbol);
|
755
|
+
const request = this.extend ({
|
756
|
+
'symbol': market['id'],
|
757
|
+
}, params);
|
758
|
+
const spot = await this.publicGetPricesSymbolSpot (request);
|
759
|
+
//
|
760
|
+
// {"data":{"base":"BTC","currency":"USD","amount":"48691.23"}}
|
761
|
+
//
|
762
|
+
const buy = await this.publicGetPricesSymbolBuy (request);
|
763
|
+
//
|
764
|
+
// {"data":{"base":"BTC","currency":"USD","amount":"48691.23"}}
|
765
|
+
//
|
766
|
+
const sell = await this.publicGetPricesSymbolSell (request);
|
767
|
+
//
|
768
|
+
// {"data":{"base":"BTC","currency":"USD","amount":"48691.23"}}
|
769
|
+
//
|
770
|
+
return this.parseTicker ([ spot, buy, sell ], market);
|
771
|
+
}
|
772
|
+
|
773
|
+
parseTicker (ticker, market = undefined) {
|
774
|
+
//
|
775
|
+
// fetchTicker
|
776
|
+
//
|
777
|
+
// [
|
778
|
+
// "48691.23", // spot
|
779
|
+
// "48691.23", // buy
|
780
|
+
// "48691.23", // sell
|
781
|
+
// ]
|
782
|
+
//
|
783
|
+
// fetchTickers
|
784
|
+
//
|
785
|
+
// "48691.23"
|
786
|
+
//
|
787
|
+
const symbol = this.safeSymbol (undefined, market);
|
788
|
+
let ask = undefined;
|
789
|
+
let bid = undefined;
|
790
|
+
let last = undefined;
|
791
|
+
const timestamp = this.milliseconds ();
|
792
|
+
if (typeof ticker !== 'string') {
|
793
|
+
const [ spot, buy, sell ] = ticker;
|
794
|
+
const spotData = this.safeValue (spot, 'data', {});
|
795
|
+
const buyData = this.safeValue (buy, 'data', {});
|
796
|
+
const sellData = this.safeValue (sell, 'data', {});
|
797
|
+
last = this.safeString (spotData, 'amount');
|
798
|
+
bid = this.safeString (buyData, 'amount');
|
799
|
+
ask = this.safeString (sellData, 'amount');
|
800
|
+
}
|
801
|
+
return this.safeTicker ({
|
802
|
+
'symbol': symbol,
|
803
|
+
'timestamp': timestamp,
|
804
|
+
'datetime': this.iso8601 (timestamp),
|
805
|
+
'bid': bid,
|
806
|
+
'ask': ask,
|
807
|
+
'last': last,
|
808
|
+
'high': undefined,
|
809
|
+
'low': undefined,
|
810
|
+
'bidVolume': undefined,
|
811
|
+
'askVolume': undefined,
|
812
|
+
'vwap': undefined,
|
813
|
+
'open': undefined,
|
814
|
+
'close': last,
|
815
|
+
'previousClose': undefined,
|
816
|
+
'change': undefined,
|
817
|
+
'percentage': undefined,
|
818
|
+
'average': undefined,
|
819
|
+
'baseVolume': undefined,
|
820
|
+
'quoteVolume': undefined,
|
821
|
+
'info': ticker,
|
822
|
+
}, market, false);
|
823
|
+
}
|
824
|
+
|
825
|
+
async fetchBalance (params = {}) {
|
826
|
+
await this.loadMarkets ();
|
827
|
+
const request = {
|
828
|
+
'limit': 100,
|
829
|
+
};
|
830
|
+
const response = await this.privateGetAccounts (this.extend (request, params));
|
831
|
+
const balances = this.safeValue (response, 'data');
|
832
|
+
const accounts = this.safeValue (params, 'type', this.options['accounts']);
|
833
|
+
const result = { 'info': response };
|
834
|
+
for (let b = 0; b < balances.length; b++) {
|
835
|
+
const balance = balances[b];
|
836
|
+
const type = this.safeString (balance, 'type');
|
837
|
+
if (this.inArray (type, accounts)) {
|
838
|
+
const value = this.safeValue (balance, 'balance');
|
839
|
+
if (value !== undefined) {
|
840
|
+
const currencyId = this.safeString (value, 'currency');
|
841
|
+
const code = this.safeCurrencyCode (currencyId);
|
842
|
+
const total = this.safeString (value, 'amount');
|
843
|
+
const free = total;
|
844
|
+
let account = this.safeValue (result, code);
|
845
|
+
if (account === undefined) {
|
846
|
+
account = this.account ();
|
847
|
+
account['free'] = free;
|
848
|
+
account['total'] = total;
|
849
|
+
} else {
|
850
|
+
account['free'] = Precise.stringAdd (account['free'], total);
|
851
|
+
account['total'] = Precise.stringAdd (account['total'], total);
|
852
|
+
}
|
853
|
+
result[code] = account;
|
854
|
+
}
|
855
|
+
}
|
856
|
+
}
|
857
|
+
return this.safeBalance (result);
|
858
|
+
}
|
859
|
+
|
860
|
+
async fetchLedger (code = undefined, since = undefined, limit = undefined, params = {}) {
|
861
|
+
await this.loadMarkets ();
|
862
|
+
let currency = undefined;
|
863
|
+
if (code !== undefined) {
|
864
|
+
currency = this.currency (code);
|
865
|
+
}
|
866
|
+
const request = await this.prepareAccountRequestWithCurrencyCode (code, limit, params);
|
867
|
+
const query = this.omit (params, [ 'account_id', 'accountId' ]);
|
868
|
+
// for pagination use parameter 'starting_after'
|
869
|
+
// the value for the next page can be obtained from the result of the previous call in the 'pagination' field
|
870
|
+
// eg: instance.last_json_response.pagination.next_starting_after
|
871
|
+
const response = await this.privateGetAccountsAccountIdTransactions (this.extend (request, query));
|
872
|
+
return this.parseLedger (response['data'], currency, since, limit);
|
873
|
+
}
|
874
|
+
|
875
|
+
parseLedgerEntryStatus (status) {
|
876
|
+
const types = {
|
877
|
+
'completed': 'ok',
|
878
|
+
};
|
879
|
+
return this.safeString (types, status, status);
|
880
|
+
}
|
881
|
+
|
882
|
+
parseLedgerEntryType (type) {
|
883
|
+
const types = {
|
884
|
+
'buy': 'trade',
|
885
|
+
'sell': 'trade',
|
886
|
+
'fiat_deposit': 'transaction',
|
887
|
+
'fiat_withdrawal': 'transaction',
|
888
|
+
'exchange_deposit': 'transaction', // fiat withdrawal (from coinbase to coinbasepro)
|
889
|
+
'exchange_withdrawal': 'transaction', // fiat deposit (to coinbase from coinbasepro)
|
890
|
+
'send': 'transaction', // crypto deposit OR withdrawal
|
891
|
+
'pro_deposit': 'transaction', // crypto withdrawal (from coinbase to coinbasepro)
|
892
|
+
'pro_withdrawal': 'transaction', // crypto deposit (to coinbase from coinbasepro)
|
893
|
+
};
|
894
|
+
return this.safeString (types, type, type);
|
895
|
+
}
|
896
|
+
|
897
|
+
parseLedgerEntry (item, currency = undefined) {
|
898
|
+
//
|
899
|
+
// crypto deposit transaction
|
900
|
+
//
|
901
|
+
// {
|
902
|
+
// id: '34e4816b-4c8c-5323-a01c-35a9fa26e490',
|
903
|
+
// type: 'send',
|
904
|
+
// status: 'completed',
|
905
|
+
// amount: { amount: '28.31976528', currency: 'BCH' },
|
906
|
+
// native_amount: { amount: '2799.65', currency: 'GBP' },
|
907
|
+
// description: null,
|
908
|
+
// created_at: '2019-02-28T12:35:20Z',
|
909
|
+
// updated_at: '2019-02-28T12:43:24Z',
|
910
|
+
// resource: 'transaction',
|
911
|
+
// resource_path: '/v2/accounts/c01d7364-edd7-5f3a-bd1d-de53d4cbb25e/transactions/34e4816b-4c8c-5323-a01c-35a9fa26e490',
|
912
|
+
// instant_exchange: false,
|
913
|
+
// network: {
|
914
|
+
// status: 'confirmed',
|
915
|
+
// hash: '56222d865dae83774fccb2efbd9829cf08c75c94ce135bfe4276f3fb46d49701',
|
916
|
+
// transaction_url: 'https://bch.btc.com/56222d865dae83774fccb2efbd9829cf08c75c94ce135bfe4276f3fb46d49701'
|
917
|
+
// },
|
918
|
+
// from: { resource: 'bitcoin_cash_network', currency: 'BCH' },
|
919
|
+
// details: { title: 'Received Bitcoin Cash', subtitle: 'From Bitcoin Cash address' }
|
920
|
+
// }
|
921
|
+
//
|
922
|
+
// crypto withdrawal transaction
|
923
|
+
//
|
924
|
+
// {
|
925
|
+
// id: '459aad99-2c41-5698-ac71-b6b81a05196c',
|
926
|
+
// type: 'send',
|
927
|
+
// status: 'completed',
|
928
|
+
// amount: { amount: '-0.36775642', currency: 'BTC' },
|
929
|
+
// native_amount: { amount: '-1111.65', currency: 'GBP' },
|
930
|
+
// description: null,
|
931
|
+
// created_at: '2019-03-20T08:37:07Z',
|
932
|
+
// updated_at: '2019-03-20T08:49:33Z',
|
933
|
+
// resource: 'transaction',
|
934
|
+
// resource_path: '/v2/accounts/c6afbd34-4bd0-501e-8616-4862c193cd84/transactions/459aad99-2c41-5698-ac71-b6b81a05196c',
|
935
|
+
// instant_exchange: false,
|
936
|
+
// network: {
|
937
|
+
// status: 'confirmed',
|
938
|
+
// hash: '2732bbcf35c69217c47b36dce64933d103895277fe25738ffb9284092701e05b',
|
939
|
+
// transaction_url: 'https://blockchain.info/tx/2732bbcf35c69217c47b36dce64933d103895277fe25738ffb9284092701e05b',
|
940
|
+
// transaction_fee: { amount: '0.00000000', currency: 'BTC' },
|
941
|
+
// transaction_amount: { amount: '0.36775642', currency: 'BTC' },
|
942
|
+
// confirmations: 15682
|
943
|
+
// },
|
944
|
+
// to: {
|
945
|
+
// resource: 'bitcoin_address',
|
946
|
+
// address: '1AHnhqbvbYx3rnZx8uC7NbFZaTe4tafFHX',
|
947
|
+
// currency: 'BTC',
|
948
|
+
// address_info: { address: '1AHnhqbvbYx3rnZx8uC7NbFZaTe4tafFHX' }
|
949
|
+
// },
|
950
|
+
// idem: 'da0a2f14-a2af-4c5a-a37e-d4484caf582bsend',
|
951
|
+
// application: {
|
952
|
+
// id: '5756ab6e-836b-553b-8950-5e389451225d',
|
953
|
+
// resource: 'application',
|
954
|
+
// resource_path: '/v2/applications/5756ab6e-836b-553b-8950-5e389451225d'
|
955
|
+
// },
|
956
|
+
// details: { title: 'Sent Bitcoin', subtitle: 'To Bitcoin address' }
|
957
|
+
// }
|
958
|
+
//
|
959
|
+
// withdrawal transaction from coinbase to coinbasepro
|
960
|
+
//
|
961
|
+
// {
|
962
|
+
// id: '5b1b9fb8-5007-5393-b923-02903b973fdc',
|
963
|
+
// type: 'pro_deposit',
|
964
|
+
// status: 'completed',
|
965
|
+
// amount: { amount: '-0.00001111', currency: 'BCH' },
|
966
|
+
// native_amount: { amount: '0.00', currency: 'GBP' },
|
967
|
+
// description: null,
|
968
|
+
// created_at: '2019-02-28T13:31:58Z',
|
969
|
+
// updated_at: '2019-02-28T13:31:58Z',
|
970
|
+
// resource: 'transaction',
|
971
|
+
// resource_path: '/v2/accounts/c01d7364-edd7-5f3a-bd1d-de53d4cbb25e/transactions/5b1b9fb8-5007-5393-b923-02903b973fdc',
|
972
|
+
// instant_exchange: false,
|
973
|
+
// application: {
|
974
|
+
// id: '5756ab6e-836b-553b-8950-5e389451225d',
|
975
|
+
// resource: 'application',
|
976
|
+
// resource_path: '/v2/applications/5756ab6e-836b-553b-8950-5e389451225d'
|
977
|
+
// },
|
978
|
+
// details: { title: 'Transferred Bitcoin Cash', subtitle: 'To Coinbase Pro' }
|
979
|
+
// }
|
980
|
+
//
|
981
|
+
// withdrawal transaction from coinbase to gdax
|
982
|
+
//
|
983
|
+
// {
|
984
|
+
// id: 'badb7313-a9d3-5c07-abd0-00f8b44199b1',
|
985
|
+
// type: 'exchange_deposit',
|
986
|
+
// status: 'completed',
|
987
|
+
// amount: { amount: '-0.43704149', currency: 'BCH' },
|
988
|
+
// native_amount: { amount: '-51.90', currency: 'GBP' },
|
989
|
+
// description: null,
|
990
|
+
// created_at: '2019-03-19T10:30:40Z',
|
991
|
+
// updated_at: '2019-03-19T10:30:40Z',
|
992
|
+
// resource: 'transaction',
|
993
|
+
// resource_path: '/v2/accounts/c01d7364-edd7-5f3a-bd1d-de53d4cbb25e/transactions/badb7313-a9d3-5c07-abd0-00f8b44199b1',
|
994
|
+
// instant_exchange: false,
|
995
|
+
// details: { title: 'Transferred Bitcoin Cash', subtitle: 'To GDAX' }
|
996
|
+
// }
|
997
|
+
//
|
998
|
+
// deposit transaction from gdax to coinbase
|
999
|
+
//
|
1000
|
+
// {
|
1001
|
+
// id: '9c4b642c-8688-58bf-8962-13cef64097de',
|
1002
|
+
// type: 'exchange_withdrawal',
|
1003
|
+
// status: 'completed',
|
1004
|
+
// amount: { amount: '0.57729420', currency: 'BTC' },
|
1005
|
+
// native_amount: { amount: '4418.72', currency: 'GBP' },
|
1006
|
+
// description: null,
|
1007
|
+
// created_at: '2018-02-17T11:33:33Z',
|
1008
|
+
// updated_at: '2018-02-17T11:33:33Z',
|
1009
|
+
// resource: 'transaction',
|
1010
|
+
// resource_path: '/v2/accounts/c6afbd34-4bd0-501e-8616-4862c193cd84/transactions/9c4b642c-8688-58bf-8962-13cef64097de',
|
1011
|
+
// instant_exchange: false,
|
1012
|
+
// details: { title: 'Transferred Bitcoin', subtitle: 'From GDAX' }
|
1013
|
+
// }
|
1014
|
+
//
|
1015
|
+
// deposit transaction from coinbasepro to coinbase
|
1016
|
+
//
|
1017
|
+
// {
|
1018
|
+
// id: '8d6dd0b9-3416-568a-889d-8f112fae9e81',
|
1019
|
+
// type: 'pro_withdrawal',
|
1020
|
+
// status: 'completed',
|
1021
|
+
// amount: { amount: '0.40555386', currency: 'BTC' },
|
1022
|
+
// native_amount: { amount: '1140.27', currency: 'GBP' },
|
1023
|
+
// description: null,
|
1024
|
+
// created_at: '2019-03-04T19:41:58Z',
|
1025
|
+
// updated_at: '2019-03-04T19:41:58Z',
|
1026
|
+
// resource: 'transaction',
|
1027
|
+
// resource_path: '/v2/accounts/c6afbd34-4bd0-501e-8616-4862c193cd84/transactions/8d6dd0b9-3416-568a-889d-8f112fae9e81',
|
1028
|
+
// instant_exchange: false,
|
1029
|
+
// application: {
|
1030
|
+
// id: '5756ab6e-836b-553b-8950-5e389451225d',
|
1031
|
+
// resource: 'application',
|
1032
|
+
// resource_path: '/v2/applications/5756ab6e-836b-553b-8950-5e389451225d'
|
1033
|
+
// },
|
1034
|
+
// details: { title: 'Transferred Bitcoin', subtitle: 'From Coinbase Pro' }
|
1035
|
+
// }
|
1036
|
+
//
|
1037
|
+
// sell trade
|
1038
|
+
//
|
1039
|
+
// {
|
1040
|
+
// id: 'a9409207-df64-585b-97ab-a50780d2149e',
|
1041
|
+
// type: 'sell',
|
1042
|
+
// status: 'completed',
|
1043
|
+
// amount: { amount: '-9.09922880', currency: 'BTC' },
|
1044
|
+
// native_amount: { amount: '-7285.73', currency: 'GBP' },
|
1045
|
+
// description: null,
|
1046
|
+
// created_at: '2017-03-27T15:38:34Z',
|
1047
|
+
// updated_at: '2017-03-27T15:38:34Z',
|
1048
|
+
// resource: 'transaction',
|
1049
|
+
// resource_path: '/v2/accounts/c6afbd34-4bd0-501e-8616-4862c193cd84/transactions/a9409207-df64-585b-97ab-a50780d2149e',
|
1050
|
+
// instant_exchange: false,
|
1051
|
+
// sell: {
|
1052
|
+
// id: 'e3550b4d-8ae6-5de3-95fe-1fb01ba83051',
|
1053
|
+
// resource: 'sell',
|
1054
|
+
// resource_path: '/v2/accounts/c6afbd34-4bd0-501e-8616-4862c193cd84/sells/e3550b4d-8ae6-5de3-95fe-1fb01ba83051'
|
1055
|
+
// },
|
1056
|
+
// details: {
|
1057
|
+
// title: 'Sold Bitcoin',
|
1058
|
+
// subtitle: 'Using EUR Wallet',
|
1059
|
+
// payment_method_name: 'EUR Wallet'
|
1060
|
+
// }
|
1061
|
+
// }
|
1062
|
+
//
|
1063
|
+
// buy trade
|
1064
|
+
//
|
1065
|
+
// {
|
1066
|
+
// id: '63eeed67-9396-5912-86e9-73c4f10fe147',
|
1067
|
+
// type: 'buy',
|
1068
|
+
// status: 'completed',
|
1069
|
+
// amount: { amount: '2.39605772', currency: 'ETH' },
|
1070
|
+
// native_amount: { amount: '98.31', currency: 'GBP' },
|
1071
|
+
// description: null,
|
1072
|
+
// created_at: '2017-03-27T09:07:56Z',
|
1073
|
+
// updated_at: '2017-03-27T09:07:57Z',
|
1074
|
+
// resource: 'transaction',
|
1075
|
+
// resource_path: '/v2/accounts/8902f85d-4a69-5d74-82fe-8e390201bda7/transactions/63eeed67-9396-5912-86e9-73c4f10fe147',
|
1076
|
+
// instant_exchange: false,
|
1077
|
+
// buy: {
|
1078
|
+
// id: '20b25b36-76c6-5353-aa57-b06a29a39d82',
|
1079
|
+
// resource: 'buy',
|
1080
|
+
// resource_path: '/v2/accounts/8902f85d-4a69-5d74-82fe-8e390201bda7/buys/20b25b36-76c6-5353-aa57-b06a29a39d82'
|
1081
|
+
// },
|
1082
|
+
// details: {
|
1083
|
+
// title: 'Bought Ethereum',
|
1084
|
+
// subtitle: 'Using EUR Wallet',
|
1085
|
+
// payment_method_name: 'EUR Wallet'
|
1086
|
+
// }
|
1087
|
+
// }
|
1088
|
+
//
|
1089
|
+
// fiat deposit transaction
|
1090
|
+
//
|
1091
|
+
// {
|
1092
|
+
// id: '04ed4113-3732-5b0c-af86-b1d2146977d0',
|
1093
|
+
// type: 'fiat_deposit',
|
1094
|
+
// status: 'completed',
|
1095
|
+
// amount: { amount: '114.02', currency: 'EUR' },
|
1096
|
+
// native_amount: { amount: '97.23', currency: 'GBP' },
|
1097
|
+
// description: null,
|
1098
|
+
// created_at: '2017-02-09T07:01:21Z',
|
1099
|
+
// updated_at: '2017-02-09T07:01:22Z',
|
1100
|
+
// resource: 'transaction',
|
1101
|
+
// resource_path: '/v2/accounts/91cd2d36-3a91-55b6-a5d4-0124cf105483/transactions/04ed4113-3732-5b0c-af86-b1d2146977d0',
|
1102
|
+
// instant_exchange: false,
|
1103
|
+
// fiat_deposit: {
|
1104
|
+
// id: 'f34c19f3-b730-5e3d-9f72-96520448677a',
|
1105
|
+
// resource: 'fiat_deposit',
|
1106
|
+
// resource_path: '/v2/accounts/91cd2d36-3a91-55b6-a5d4-0124cf105483/deposits/f34c19f3-b730-5e3d-9f72-96520448677a'
|
1107
|
+
// },
|
1108
|
+
// details: {
|
1109
|
+
// title: 'Deposited funds',
|
1110
|
+
// subtitle: 'From SEPA Transfer (GB47 BARC 20..., reference CBADVI)',
|
1111
|
+
// payment_method_name: 'SEPA Transfer (GB47 BARC 20..., reference CBADVI)'
|
1112
|
+
// }
|
1113
|
+
// }
|
1114
|
+
//
|
1115
|
+
// fiat withdrawal transaction
|
1116
|
+
//
|
1117
|
+
// {
|
1118
|
+
// id: '957d98e2-f80e-5e2f-a28e-02945aa93079',
|
1119
|
+
// type: 'fiat_withdrawal',
|
1120
|
+
// status: 'completed',
|
1121
|
+
// amount: { amount: '-11000.00', currency: 'EUR' },
|
1122
|
+
// native_amount: { amount: '-9698.22', currency: 'GBP' },
|
1123
|
+
// description: null,
|
1124
|
+
// created_at: '2017-12-06T13:19:19Z',
|
1125
|
+
// updated_at: '2017-12-06T13:19:19Z',
|
1126
|
+
// resource: 'transaction',
|
1127
|
+
// resource_path: '/v2/accounts/91cd2d36-3a91-55b6-a5d4-0124cf105483/transactions/957d98e2-f80e-5e2f-a28e-02945aa93079',
|
1128
|
+
// instant_exchange: false,
|
1129
|
+
// fiat_withdrawal: {
|
1130
|
+
// id: 'f4bf1fd9-ab3b-5de7-906d-ed3e23f7a4e7',
|
1131
|
+
// resource: 'fiat_withdrawal',
|
1132
|
+
// resource_path: '/v2/accounts/91cd2d36-3a91-55b6-a5d4-0124cf105483/withdrawals/f4bf1fd9-ab3b-5de7-906d-ed3e23f7a4e7'
|
1133
|
+
// },
|
1134
|
+
// details: {
|
1135
|
+
// title: 'Withdrew funds',
|
1136
|
+
// subtitle: 'To HSBC BANK PLC (GB74 MIDL...)',
|
1137
|
+
// payment_method_name: 'HSBC BANK PLC (GB74 MIDL...)'
|
1138
|
+
// }
|
1139
|
+
// }
|
1140
|
+
//
|
1141
|
+
const amountInfo = this.safeValue (item, 'amount', {});
|
1142
|
+
let amount = this.safeNumber (amountInfo, 'amount');
|
1143
|
+
let direction = undefined;
|
1144
|
+
if (amount < 0) {
|
1145
|
+
direction = 'out';
|
1146
|
+
amount = -amount;
|
1147
|
+
} else {
|
1148
|
+
direction = 'in';
|
1149
|
+
}
|
1150
|
+
const currencyId = this.safeString (amountInfo, 'currency');
|
1151
|
+
const code = this.safeCurrencyCode (currencyId, currency);
|
1152
|
+
//
|
1153
|
+
// the address and txid do not belong to the unified ledger structure
|
1154
|
+
//
|
1155
|
+
// let address = undefined;
|
1156
|
+
// if (item['to']) {
|
1157
|
+
// address = this.safeString (item['to'], 'address');
|
1158
|
+
// }
|
1159
|
+
// let txid = undefined;
|
1160
|
+
//
|
1161
|
+
let fee = undefined;
|
1162
|
+
const networkInfo = this.safeValue (item, 'network', {});
|
1163
|
+
// txid = network['hash']; // txid does not belong to the unified ledger structure
|
1164
|
+
const feeInfo = this.safeValue (networkInfo, 'transaction_fee');
|
1165
|
+
if (feeInfo !== undefined) {
|
1166
|
+
const feeCurrencyId = this.safeString (feeInfo, 'currency');
|
1167
|
+
const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId, currency);
|
1168
|
+
const feeAmount = this.safeNumber (feeInfo, 'amount');
|
1169
|
+
fee = {
|
1170
|
+
'cost': feeAmount,
|
1171
|
+
'currency': feeCurrencyCode,
|
1172
|
+
};
|
1173
|
+
}
|
1174
|
+
const timestamp = this.parse8601 (this.safeValue (item, 'created_at'));
|
1175
|
+
const id = this.safeString (item, 'id');
|
1176
|
+
const type = this.parseLedgerEntryType (this.safeString (item, 'type'));
|
1177
|
+
const status = this.parseLedgerEntryStatus (this.safeString (item, 'status'));
|
1178
|
+
const path = this.safeString (item, 'resource_path');
|
1179
|
+
let accountId = undefined;
|
1180
|
+
if (path !== undefined) {
|
1181
|
+
const parts = path.split ('/');
|
1182
|
+
const numParts = parts.length;
|
1183
|
+
if (numParts > 3) {
|
1184
|
+
accountId = parts[3];
|
1185
|
+
}
|
1186
|
+
}
|
1187
|
+
return {
|
1188
|
+
'info': item,
|
1189
|
+
'id': id,
|
1190
|
+
'timestamp': timestamp,
|
1191
|
+
'datetime': this.iso8601 (timestamp),
|
1192
|
+
'direction': direction,
|
1193
|
+
'account': accountId,
|
1194
|
+
'referenceId': undefined,
|
1195
|
+
'referenceAccount': undefined,
|
1196
|
+
'type': type,
|
1197
|
+
'currency': code,
|
1198
|
+
'amount': amount,
|
1199
|
+
'before': undefined,
|
1200
|
+
'after': undefined,
|
1201
|
+
'status': status,
|
1202
|
+
'fee': fee,
|
1203
|
+
};
|
1204
|
+
}
|
1205
|
+
|
1206
|
+
async findAccountId (code) {
|
1207
|
+
await this.loadMarkets ();
|
1208
|
+
await this.loadAccounts ();
|
1209
|
+
for (let i = 0; i < this.accounts.length; i++) {
|
1210
|
+
const account = this.accounts[i];
|
1211
|
+
if (account['code'] === code) {
|
1212
|
+
return account['id'];
|
1213
|
+
}
|
1214
|
+
}
|
1215
|
+
return undefined;
|
1216
|
+
}
|
1217
|
+
|
1218
|
+
prepareAccountRequest (limit = undefined, params = {}) {
|
1219
|
+
const accountId = this.safeString2 (params, 'account_id', 'accountId');
|
1220
|
+
if (accountId === undefined) {
|
1221
|
+
throw new ArgumentsRequired (this.id + ' prepareAccountRequest() method requires an account_id (or accountId) parameter');
|
1222
|
+
}
|
1223
|
+
const request = {
|
1224
|
+
'account_id': accountId,
|
1225
|
+
};
|
1226
|
+
if (limit !== undefined) {
|
1227
|
+
request['limit'] = limit;
|
1228
|
+
}
|
1229
|
+
return request;
|
1230
|
+
}
|
1231
|
+
|
1232
|
+
async prepareAccountRequestWithCurrencyCode (code = undefined, limit = undefined, params = {}) {
|
1233
|
+
let accountId = this.safeString2 (params, 'account_id', 'accountId');
|
1234
|
+
if (accountId === undefined) {
|
1235
|
+
if (code === undefined) {
|
1236
|
+
throw new ArgumentsRequired (this.id + ' prepareAccountRequestWithCurrencyCode() method requires an account_id (or accountId) parameter OR a currency code argument');
|
1237
|
+
}
|
1238
|
+
accountId = await this.findAccountId (code);
|
1239
|
+
if (accountId === undefined) {
|
1240
|
+
throw new ExchangeError (this.id + ' prepareAccountRequestWithCurrencyCode() could not find account id for ' + code);
|
1241
|
+
}
|
1242
|
+
}
|
1243
|
+
const request = {
|
1244
|
+
'account_id': accountId,
|
1245
|
+
};
|
1246
|
+
if (limit !== undefined) {
|
1247
|
+
request['limit'] = limit;
|
1248
|
+
}
|
1249
|
+
return request;
|
1250
|
+
}
|
1251
|
+
|
1252
|
+
sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
|
1253
|
+
let fullPath = '/' + this.version + '/' + this.implodeParams (path, params);
|
1254
|
+
const query = this.omit (params, this.extractParams (path));
|
1255
|
+
if (method === 'GET') {
|
1256
|
+
if (Object.keys (query).length) {
|
1257
|
+
fullPath += '?' + this.urlencode (query);
|
1258
|
+
}
|
1259
|
+
}
|
1260
|
+
const url = this.urls['api'] + fullPath;
|
1261
|
+
if (api === 'private') {
|
1262
|
+
const authorization = this.safeString (this.headers, 'Authorization');
|
1263
|
+
if (authorization !== undefined) {
|
1264
|
+
headers = {
|
1265
|
+
'Authorization': authorization,
|
1266
|
+
'Content-Type': 'application/json',
|
1267
|
+
};
|
1268
|
+
} else if (this.token) {
|
1269
|
+
headers = {
|
1270
|
+
'Authorization': 'Bearer ' + this.token,
|
1271
|
+
'Content-Type': 'application/json',
|
1272
|
+
};
|
1273
|
+
} else {
|
1274
|
+
this.checkRequiredCredentials ();
|
1275
|
+
const nonce = this.nonce ().toString ();
|
1276
|
+
let payload = '';
|
1277
|
+
if (method !== 'GET') {
|
1278
|
+
if (Object.keys (query).length) {
|
1279
|
+
body = this.json (query);
|
1280
|
+
payload = body;
|
1281
|
+
}
|
1282
|
+
}
|
1283
|
+
const auth = nonce + method + fullPath + payload;
|
1284
|
+
const signature = this.hmac (this.encode (auth), this.encode (this.secret));
|
1285
|
+
headers = {
|
1286
|
+
'CB-ACCESS-KEY': this.apiKey,
|
1287
|
+
'CB-ACCESS-SIGN': signature,
|
1288
|
+
'CB-ACCESS-TIMESTAMP': nonce,
|
1289
|
+
'Content-Type': 'application/json',
|
1290
|
+
};
|
1291
|
+
}
|
1292
|
+
}
|
1293
|
+
return { 'url': url, 'method': method, 'body': body, 'headers': headers };
|
1294
|
+
}
|
1295
|
+
|
1296
|
+
handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
|
1297
|
+
if (response === undefined) {
|
1298
|
+
return; // fallback to default error handler
|
1299
|
+
}
|
1300
|
+
const feedback = this.id + ' ' + body;
|
1301
|
+
//
|
1302
|
+
// {"error": "invalid_request", "error_description": "The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed."}
|
1303
|
+
//
|
1304
|
+
// or
|
1305
|
+
//
|
1306
|
+
// {
|
1307
|
+
// "errors": [
|
1308
|
+
// {
|
1309
|
+
// "id": "not_found",
|
1310
|
+
// "message": "Not found"
|
1311
|
+
// }
|
1312
|
+
// ]
|
1313
|
+
// }
|
1314
|
+
//
|
1315
|
+
let errorCode = this.safeString (response, 'error');
|
1316
|
+
if (errorCode !== undefined) {
|
1317
|
+
const errorMessage = this.safeString (response, 'error_description');
|
1318
|
+
this.throwExactlyMatchedException (this.exceptions['exact'], errorCode, feedback);
|
1319
|
+
this.throwBroadlyMatchedException (this.exceptions['broad'], errorMessage, feedback);
|
1320
|
+
throw new ExchangeError (feedback);
|
1321
|
+
}
|
1322
|
+
const errors = this.safeValue (response, 'errors');
|
1323
|
+
if (errors !== undefined) {
|
1324
|
+
if (Array.isArray (errors)) {
|
1325
|
+
const numErrors = errors.length;
|
1326
|
+
if (numErrors > 0) {
|
1327
|
+
errorCode = this.safeString (errors[0], 'id');
|
1328
|
+
const errorMessage = this.safeString (errors[0], 'message');
|
1329
|
+
if (errorCode !== undefined) {
|
1330
|
+
this.throwExactlyMatchedException (this.exceptions['exact'], errorCode, feedback);
|
1331
|
+
this.throwBroadlyMatchedException (this.exceptions['broad'], errorMessage, feedback);
|
1332
|
+
throw new ExchangeError (feedback);
|
1333
|
+
}
|
1334
|
+
}
|
1335
|
+
}
|
1336
|
+
}
|
1337
|
+
const data = this.safeValue (response, 'data');
|
1338
|
+
if (data === undefined) {
|
1339
|
+
throw new ExchangeError (this.id + ' failed due to a malformed response ' + this.json (response));
|
1340
|
+
}
|
1341
|
+
}
|
1342
|
+
};
|