ccxt 4.2.76__py2.py3-none-any.whl → 4.4.48__py2.py3-none-any.whl
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.
- ccxt/__init__.py +36 -14
- ccxt/abstract/alpaca.py +4 -0
- ccxt/abstract/bigone.py +1 -1
- ccxt/abstract/binance.py +112 -48
- ccxt/abstract/binancecoinm.py +112 -48
- ccxt/abstract/binanceus.py +147 -83
- ccxt/abstract/binanceusdm.py +112 -48
- ccxt/abstract/bingx.py +133 -78
- ccxt/abstract/bitbank.py +5 -0
- ccxt/abstract/bitfinex.py +136 -65
- ccxt/abstract/bitfinex1.py +69 -0
- ccxt/abstract/bitflyer.py +1 -0
- ccxt/abstract/bitget.py +8 -1
- ccxt/abstract/bitmart.py +13 -1
- ccxt/abstract/bitopro.py +1 -0
- ccxt/abstract/bitpanda.py +0 -12
- ccxt/abstract/bitrue.py +3 -3
- ccxt/abstract/bitstamp.py +26 -3
- ccxt/abstract/blofin.py +24 -0
- ccxt/abstract/btcbox.py +1 -0
- ccxt/abstract/bybit.py +29 -14
- ccxt/abstract/cex.py +28 -29
- ccxt/abstract/coinbase.py +6 -0
- ccxt/abstract/coinbaseadvanced.py +94 -0
- ccxt/abstract/{coinbasepro.py → coinbaseexchange.py} +1 -0
- ccxt/abstract/coinbaseinternational.py +1 -1
- ccxt/abstract/coincatch.py +94 -0
- ccxt/abstract/coinex.py +233 -123
- ccxt/abstract/coinmetro.py +1 -0
- ccxt/abstract/cryptocom.py +14 -0
- ccxt/abstract/defx.py +69 -0
- ccxt/abstract/deribit.py +1 -0
- ccxt/abstract/digifinex.py +1 -0
- ccxt/abstract/ellipx.py +25 -0
- ccxt/abstract/gate.py +20 -0
- ccxt/abstract/gateio.py +20 -0
- ccxt/abstract/gemini.py +1 -0
- ccxt/abstract/hashkey.py +67 -0
- ccxt/abstract/hyperliquid.py +1 -1
- ccxt/abstract/independentreserve.py +6 -0
- ccxt/abstract/kraken.py +4 -3
- ccxt/abstract/krakenfutures.py +4 -0
- ccxt/abstract/kucoin.py +25 -0
- ccxt/abstract/kucoinfutures.py +35 -0
- ccxt/abstract/luno.py +2 -0
- ccxt/abstract/mexc.py +4 -0
- ccxt/abstract/myokx.py +340 -0
- ccxt/abstract/oceanex.py +5 -0
- ccxt/abstract/okx.py +30 -0
- ccxt/abstract/onetrading.py +0 -12
- ccxt/abstract/oxfun.py +34 -0
- ccxt/abstract/paradex.py +40 -0
- ccxt/abstract/phemex.py +1 -0
- ccxt/abstract/upbit.py +4 -0
- ccxt/abstract/vertex.py +19 -0
- ccxt/abstract/whitebit.py +31 -1
- ccxt/abstract/woo.py +6 -2
- ccxt/abstract/woofipro.py +119 -0
- ccxt/abstract/xt.py +153 -0
- ccxt/abstract/zonda.py +6 -0
- ccxt/ace.py +164 -60
- ccxt/alpaca.py +727 -63
- ccxt/ascendex.py +395 -249
- ccxt/async_support/__init__.py +36 -14
- ccxt/async_support/ace.py +164 -60
- ccxt/async_support/alpaca.py +727 -63
- ccxt/async_support/ascendex.py +396 -249
- ccxt/async_support/base/exchange.py +531 -155
- ccxt/async_support/base/ws/aiohttp_client.py +28 -5
- ccxt/async_support/base/ws/cache.py +3 -2
- ccxt/async_support/base/ws/client.py +26 -5
- ccxt/async_support/base/ws/fast_client.py +4 -3
- ccxt/async_support/base/ws/functions.py +1 -1
- ccxt/async_support/base/ws/future.py +40 -31
- ccxt/async_support/base/ws/order_book_side.py +3 -0
- ccxt/async_support/bequant.py +1 -1
- ccxt/async_support/bigone.py +329 -202
- ccxt/async_support/binance.py +3513 -1511
- ccxt/async_support/binancecoinm.py +2 -1
- ccxt/async_support/binanceus.py +12 -1
- ccxt/async_support/binanceusdm.py +3 -1
- ccxt/async_support/bingx.py +3105 -881
- ccxt/async_support/bit2c.py +119 -38
- ccxt/async_support/bitbank.py +215 -76
- ccxt/async_support/bitbns.py +124 -53
- ccxt/async_support/bitfinex.py +3236 -1078
- ccxt/async_support/bitfinex1.py +1711 -0
- ccxt/async_support/bitflyer.py +239 -50
- ccxt/async_support/bitget.py +1513 -563
- ccxt/async_support/bithumb.py +201 -67
- ccxt/async_support/bitmart.py +1320 -435
- ccxt/async_support/bitmex.py +308 -111
- ccxt/async_support/bitopro.py +256 -96
- ccxt/async_support/bitrue.py +365 -233
- ccxt/async_support/bitso.py +201 -89
- ccxt/async_support/bitstamp.py +438 -269
- ccxt/async_support/bitteam.py +179 -73
- ccxt/async_support/bitvavo.py +180 -70
- ccxt/async_support/bl3p.py +92 -25
- ccxt/async_support/blockchaincom.py +193 -79
- ccxt/async_support/blofin.py +403 -150
- ccxt/async_support/btcalpha.py +161 -55
- ccxt/async_support/btcbox.py +250 -34
- ccxt/async_support/btcmarkets.py +232 -85
- ccxt/async_support/btcturk.py +159 -60
- ccxt/async_support/bybit.py +2326 -1255
- ccxt/async_support/cex.py +1409 -1329
- ccxt/async_support/coinbase.py +1455 -288
- ccxt/async_support/coinbaseadvanced.py +17 -0
- ccxt/async_support/{coinbasepro.py → coinbaseexchange.py} +233 -99
- ccxt/async_support/coinbaseinternational.py +428 -88
- ccxt/async_support/coincatch.py +5152 -0
- ccxt/async_support/coincheck.py +121 -38
- ccxt/async_support/coinex.py +4020 -3339
- ccxt/async_support/coinlist.py +273 -116
- ccxt/async_support/coinmate.py +204 -97
- ccxt/async_support/coinmetro.py +203 -110
- ccxt/async_support/coinone.py +142 -68
- ccxt/async_support/coinsph.py +206 -89
- ccxt/async_support/coinspot.py +137 -62
- ccxt/async_support/cryptocom.py +515 -185
- ccxt/async_support/currencycom.py +203 -85
- ccxt/async_support/defx.py +2066 -0
- ccxt/async_support/delta.py +467 -158
- ccxt/async_support/deribit.py +558 -324
- ccxt/async_support/digifinex.py +340 -223
- ccxt/async_support/ellipx.py +1826 -0
- ccxt/async_support/exmo.py +259 -128
- ccxt/async_support/gate.py +1473 -464
- ccxt/async_support/gemini.py +206 -84
- ccxt/async_support/hashkey.py +4164 -0
- ccxt/async_support/hitbtc.py +334 -178
- ccxt/async_support/hollaex.py +134 -83
- ccxt/async_support/htx.py +1095 -563
- ccxt/async_support/huobijp.py +105 -56
- ccxt/async_support/hyperliquid.py +1634 -269
- ccxt/async_support/idex.py +148 -95
- ccxt/async_support/independentreserve.py +236 -31
- ccxt/async_support/indodax.py +165 -62
- ccxt/async_support/kraken.py +871 -354
- ccxt/async_support/krakenfutures.py +324 -100
- ccxt/async_support/kucoin.py +1050 -355
- ccxt/async_support/kucoinfutures.py +1004 -149
- ccxt/async_support/kuna.py +138 -106
- ccxt/async_support/latoken.py +135 -79
- ccxt/async_support/lbank.py +290 -113
- ccxt/async_support/luno.py +112 -62
- ccxt/async_support/lykke.py +104 -55
- ccxt/async_support/mercado.py +36 -29
- ccxt/async_support/mexc.py +995 -429
- ccxt/async_support/myokx.py +43 -0
- ccxt/async_support/ndax.py +163 -82
- ccxt/async_support/novadax.py +121 -75
- ccxt/async_support/oceanex.py +175 -59
- ccxt/async_support/okcoin.py +222 -163
- ccxt/async_support/okx.py +1777 -455
- ccxt/async_support/onetrading.py +132 -414
- ccxt/async_support/oxfun.py +2832 -0
- ccxt/async_support/p2b.py +79 -51
- ccxt/async_support/paradex.py +2017 -0
- ccxt/async_support/paymium.py +56 -32
- ccxt/async_support/phemex.py +572 -196
- ccxt/async_support/poloniex.py +218 -95
- ccxt/async_support/poloniexfutures.py +260 -92
- ccxt/async_support/probit.py +143 -110
- ccxt/async_support/timex.py +123 -70
- ccxt/async_support/tokocrypto.py +129 -93
- ccxt/async_support/tradeogre.py +39 -25
- ccxt/async_support/upbit.py +322 -113
- ccxt/async_support/vertex.py +2983 -0
- ccxt/async_support/wavesexchange.py +227 -173
- ccxt/async_support/wazirx.py +145 -65
- ccxt/async_support/whitebit.py +533 -138
- ccxt/async_support/woo.py +1155 -295
- ccxt/async_support/woofipro.py +2716 -0
- ccxt/async_support/xt.py +4628 -0
- ccxt/async_support/yobit.py +160 -92
- ccxt/async_support/zaif.py +80 -33
- ccxt/async_support/zonda.py +140 -69
- ccxt/base/errors.py +51 -20
- ccxt/base/exchange.py +1729 -482
- ccxt/base/precise.py +10 -0
- ccxt/base/types.py +223 -4
- ccxt/bequant.py +1 -1
- ccxt/bigone.py +329 -202
- ccxt/binance.py +3513 -1511
- ccxt/binancecoinm.py +2 -1
- ccxt/binanceus.py +12 -1
- ccxt/binanceusdm.py +3 -1
- ccxt/bingx.py +3105 -881
- ccxt/bit2c.py +119 -38
- ccxt/bitbank.py +215 -76
- ccxt/bitbns.py +124 -53
- ccxt/bitfinex.py +3235 -1078
- ccxt/bitfinex1.py +1710 -0
- ccxt/bitflyer.py +239 -50
- ccxt/bitget.py +1513 -563
- ccxt/bithumb.py +200 -67
- ccxt/bitmart.py +1320 -435
- ccxt/bitmex.py +308 -111
- ccxt/bitopro.py +256 -96
- ccxt/bitrue.py +365 -233
- ccxt/bitso.py +201 -89
- ccxt/bitstamp.py +438 -269
- ccxt/bitteam.py +179 -73
- ccxt/bitvavo.py +180 -70
- ccxt/bl3p.py +92 -25
- ccxt/blockchaincom.py +193 -79
- ccxt/blofin.py +403 -150
- ccxt/btcalpha.py +161 -55
- ccxt/btcbox.py +250 -34
- ccxt/btcmarkets.py +232 -85
- ccxt/btcturk.py +159 -60
- ccxt/bybit.py +2326 -1255
- ccxt/cex.py +1408 -1329
- ccxt/coinbase.py +1455 -288
- ccxt/coinbaseadvanced.py +17 -0
- ccxt/{coinbasepro.py → coinbaseexchange.py} +233 -99
- ccxt/coinbaseinternational.py +428 -88
- ccxt/coincatch.py +5152 -0
- ccxt/coincheck.py +121 -38
- ccxt/coinex.py +4020 -3339
- ccxt/coinlist.py +273 -116
- ccxt/coinmate.py +204 -97
- ccxt/coinmetro.py +203 -110
- ccxt/coinone.py +142 -68
- ccxt/coinsph.py +206 -89
- ccxt/coinspot.py +137 -62
- ccxt/cryptocom.py +515 -185
- ccxt/currencycom.py +203 -85
- ccxt/defx.py +2065 -0
- ccxt/delta.py +467 -158
- ccxt/deribit.py +558 -324
- ccxt/digifinex.py +340 -223
- ccxt/ellipx.py +1826 -0
- ccxt/exmo.py +259 -128
- ccxt/gate.py +1473 -464
- ccxt/gemini.py +206 -84
- ccxt/hashkey.py +4164 -0
- ccxt/hitbtc.py +334 -178
- ccxt/hollaex.py +134 -83
- ccxt/htx.py +1095 -563
- ccxt/huobijp.py +105 -56
- ccxt/hyperliquid.py +1633 -269
- ccxt/idex.py +148 -95
- ccxt/independentreserve.py +235 -31
- ccxt/indodax.py +165 -62
- ccxt/kraken.py +871 -354
- ccxt/krakenfutures.py +324 -100
- ccxt/kucoin.py +1050 -355
- ccxt/kucoinfutures.py +1004 -149
- ccxt/kuna.py +138 -106
- ccxt/latoken.py +135 -79
- ccxt/lbank.py +290 -113
- ccxt/luno.py +112 -62
- ccxt/lykke.py +104 -55
- ccxt/mercado.py +36 -29
- ccxt/mexc.py +994 -429
- ccxt/myokx.py +43 -0
- ccxt/ndax.py +163 -82
- ccxt/novadax.py +121 -75
- ccxt/oceanex.py +175 -59
- ccxt/okcoin.py +222 -163
- ccxt/okx.py +1777 -455
- ccxt/onetrading.py +132 -414
- ccxt/oxfun.py +2831 -0
- ccxt/p2b.py +79 -51
- ccxt/paradex.py +2017 -0
- ccxt/paymium.py +56 -32
- ccxt/phemex.py +572 -196
- ccxt/poloniex.py +218 -95
- ccxt/poloniexfutures.py +260 -92
- ccxt/pro/__init__.py +29 -5
- ccxt/pro/alpaca.py +32 -17
- ccxt/pro/ascendex.py +63 -15
- ccxt/pro/bequant.py +4 -0
- ccxt/pro/binance.py +1596 -329
- ccxt/pro/binancecoinm.py +1 -0
- ccxt/pro/binanceus.py +2 -9
- ccxt/pro/binanceusdm.py +2 -0
- ccxt/pro/bingx.py +527 -134
- ccxt/pro/bitcoincom.py +4 -1
- ccxt/pro/bitfinex.py +731 -266
- ccxt/pro/bitfinex1.py +635 -0
- ccxt/pro/bitget.py +726 -357
- ccxt/pro/bithumb.py +380 -0
- ccxt/pro/bitmart.py +138 -39
- ccxt/pro/bitmex.py +199 -40
- ccxt/pro/bitopro.py +25 -13
- ccxt/pro/bitrue.py +31 -32
- ccxt/pro/bitstamp.py +7 -6
- ccxt/pro/bitvavo.py +204 -82
- ccxt/pro/blockchaincom.py +30 -17
- ccxt/pro/blofin.py +692 -0
- ccxt/pro/bybit.py +791 -82
- ccxt/pro/cex.py +99 -51
- ccxt/pro/coinbase.py +220 -30
- ccxt/{async_support/hitbtc3.py → pro/coinbaseadvanced.py} +5 -5
- ccxt/pro/{coinbasepro.py → coinbaseexchange.py} +19 -19
- ccxt/pro/coinbaseinternational.py +193 -30
- ccxt/pro/coincatch.py +1464 -0
- ccxt/pro/coincheck.py +11 -6
- ccxt/pro/coinex.py +967 -661
- ccxt/pro/coinone.py +17 -10
- ccxt/pro/cryptocom.py +446 -66
- ccxt/pro/currencycom.py +11 -10
- ccxt/pro/defx.py +832 -0
- ccxt/pro/deribit.py +168 -32
- ccxt/pro/exmo.py +253 -21
- ccxt/pro/gate.py +729 -64
- ccxt/pro/gemini.py +44 -26
- ccxt/pro/hashkey.py +802 -0
- ccxt/pro/hitbtc.py +208 -103
- ccxt/pro/hollaex.py +25 -9
- ccxt/pro/htx.py +83 -39
- ccxt/pro/huobijp.py +17 -16
- ccxt/pro/hyperliquid.py +502 -31
- ccxt/pro/idex.py +28 -13
- ccxt/pro/independentreserve.py +21 -16
- ccxt/pro/kraken.py +298 -51
- ccxt/pro/krakenfutures.py +166 -75
- ccxt/pro/kucoin.py +395 -77
- ccxt/pro/kucoinfutures.py +400 -99
- ccxt/pro/lbank.py +52 -31
- ccxt/pro/luno.py +12 -10
- ccxt/pro/mexc.py +400 -50
- ccxt/pro/myokx.py +28 -0
- ccxt/pro/ndax.py +25 -12
- ccxt/pro/okcoin.py +28 -9
- ccxt/pro/okx.py +935 -124
- ccxt/pro/onetrading.py +41 -24
- ccxt/pro/oxfun.py +1054 -0
- ccxt/pro/p2b.py +100 -24
- ccxt/pro/paradex.py +352 -0
- ccxt/pro/phemex.py +93 -34
- ccxt/pro/poloniex.py +129 -50
- ccxt/pro/poloniexfutures.py +53 -32
- ccxt/pro/probit.py +93 -86
- ccxt/pro/upbit.py +401 -8
- ccxt/pro/vertex.py +943 -0
- ccxt/pro/wazirx.py +46 -28
- ccxt/pro/whitebit.py +65 -12
- ccxt/pro/woo.py +486 -70
- ccxt/pro/woofipro.py +1271 -0
- ccxt/pro/xt.py +1067 -0
- ccxt/probit.py +143 -110
- ccxt/static_dependencies/__init__.py +1 -1
- ccxt/static_dependencies/lark/__init__.py +38 -0
- ccxt/static_dependencies/lark/__pyinstaller/__init__.py +6 -0
- ccxt/static_dependencies/lark/__pyinstaller/hook-lark.py +14 -0
- ccxt/static_dependencies/lark/ast_utils.py +59 -0
- ccxt/static_dependencies/lark/common.py +86 -0
- ccxt/static_dependencies/lark/exceptions.py +292 -0
- ccxt/static_dependencies/lark/grammar.py +130 -0
- ccxt/static_dependencies/lark/grammars/__init__.py +0 -0
- ccxt/static_dependencies/lark/indenter.py +143 -0
- ccxt/static_dependencies/lark/lark.py +658 -0
- ccxt/static_dependencies/lark/lexer.py +678 -0
- ccxt/static_dependencies/lark/load_grammar.py +1428 -0
- ccxt/static_dependencies/lark/parse_tree_builder.py +391 -0
- ccxt/static_dependencies/lark/parser_frontends.py +257 -0
- ccxt/static_dependencies/lark/parsers/__init__.py +0 -0
- ccxt/static_dependencies/lark/parsers/cyk.py +340 -0
- ccxt/static_dependencies/lark/parsers/earley.py +314 -0
- ccxt/static_dependencies/lark/parsers/earley_common.py +42 -0
- ccxt/static_dependencies/lark/parsers/earley_forest.py +801 -0
- ccxt/static_dependencies/lark/parsers/grammar_analysis.py +203 -0
- ccxt/static_dependencies/lark/parsers/lalr_analysis.py +332 -0
- ccxt/static_dependencies/lark/parsers/lalr_interactive_parser.py +158 -0
- ccxt/static_dependencies/lark/parsers/lalr_parser.py +122 -0
- ccxt/static_dependencies/lark/parsers/lalr_parser_state.py +110 -0
- ccxt/static_dependencies/lark/parsers/xearley.py +165 -0
- ccxt/static_dependencies/lark/py.typed +0 -0
- ccxt/static_dependencies/lark/reconstruct.py +107 -0
- ccxt/static_dependencies/lark/tools/__init__.py +70 -0
- ccxt/static_dependencies/lark/tools/nearley.py +202 -0
- ccxt/static_dependencies/lark/tools/serialize.py +32 -0
- ccxt/static_dependencies/lark/tools/standalone.py +196 -0
- ccxt/static_dependencies/lark/tree.py +267 -0
- ccxt/static_dependencies/lark/tree_matcher.py +186 -0
- ccxt/static_dependencies/lark/tree_templates.py +180 -0
- ccxt/static_dependencies/lark/utils.py +343 -0
- ccxt/static_dependencies/lark/visitors.py +596 -0
- ccxt/static_dependencies/marshmallow/__init__.py +81 -0
- ccxt/static_dependencies/marshmallow/base.py +65 -0
- ccxt/static_dependencies/marshmallow/class_registry.py +94 -0
- ccxt/static_dependencies/marshmallow/decorators.py +231 -0
- ccxt/static_dependencies/marshmallow/error_store.py +60 -0
- ccxt/static_dependencies/marshmallow/exceptions.py +71 -0
- ccxt/static_dependencies/marshmallow/fields.py +2114 -0
- ccxt/static_dependencies/marshmallow/orderedset.py +89 -0
- ccxt/static_dependencies/marshmallow/py.typed +0 -0
- ccxt/static_dependencies/marshmallow/schema.py +1228 -0
- ccxt/static_dependencies/marshmallow/types.py +12 -0
- ccxt/static_dependencies/marshmallow/utils.py +378 -0
- ccxt/static_dependencies/marshmallow/validate.py +678 -0
- ccxt/static_dependencies/marshmallow/warnings.py +2 -0
- ccxt/static_dependencies/marshmallow_dataclass/__init__.py +1047 -0
- ccxt/static_dependencies/marshmallow_dataclass/collection_field.py +51 -0
- ccxt/static_dependencies/marshmallow_dataclass/lazy_class_attribute.py +45 -0
- ccxt/static_dependencies/marshmallow_dataclass/mypy.py +71 -0
- ccxt/static_dependencies/marshmallow_dataclass/py.typed +0 -0
- ccxt/static_dependencies/marshmallow_dataclass/typing.py +14 -0
- ccxt/static_dependencies/marshmallow_dataclass/union_field.py +82 -0
- ccxt/static_dependencies/marshmallow_oneofschema/__init__.py +1 -0
- ccxt/static_dependencies/marshmallow_oneofschema/one_of_schema.py +193 -0
- ccxt/static_dependencies/marshmallow_oneofschema/py.typed +0 -0
- ccxt/static_dependencies/starknet/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/data_types.py +123 -0
- ccxt/static_dependencies/starknet/cairo/deprecated_parse/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/deprecated_parse/cairo_types.py +77 -0
- ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser.py +46 -0
- ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser_transformer.py +138 -0
- ccxt/static_dependencies/starknet/cairo/felt.py +64 -0
- ccxt/static_dependencies/starknet/cairo/type_parser.py +121 -0
- ccxt/static_dependencies/starknet/cairo/v1/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/v1/type_parser.py +59 -0
- ccxt/static_dependencies/starknet/cairo/v2/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/v2/type_parser.py +77 -0
- ccxt/static_dependencies/starknet/ccxt_utils.py +7 -0
- ccxt/static_dependencies/starknet/common.py +15 -0
- ccxt/static_dependencies/starknet/constants.py +39 -0
- ccxt/static_dependencies/starknet/hash/__init__.py +0 -0
- ccxt/static_dependencies/starknet/hash/address.py +79 -0
- ccxt/static_dependencies/starknet/hash/compiled_class_hash_objects.py +111 -0
- ccxt/static_dependencies/starknet/hash/selector.py +16 -0
- ccxt/static_dependencies/starknet/hash/storage.py +12 -0
- ccxt/static_dependencies/starknet/hash/utils.py +78 -0
- ccxt/static_dependencies/starknet/models/__init__.py +0 -0
- ccxt/static_dependencies/starknet/models/typed_data.py +45 -0
- ccxt/static_dependencies/starknet/serialization/__init__.py +24 -0
- ccxt/static_dependencies/starknet/serialization/_calldata_reader.py +40 -0
- ccxt/static_dependencies/starknet/serialization/_context.py +142 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/__init__.py +10 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/_common.py +82 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/array_serializer.py +43 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/bool_serializer.py +37 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/byte_array_serializer.py +66 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/cairo_data_serializer.py +71 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/enum_serializer.py +71 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/felt_serializer.py +50 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/named_tuple_serializer.py +58 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/option_serializer.py +43 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/output_serializer.py +40 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/payload_serializer.py +72 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/struct_serializer.py +36 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/tuple_serializer.py +36 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/uint256_serializer.py +76 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/uint_serializer.py +100 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/unit_serializer.py +32 -0
- ccxt/static_dependencies/starknet/serialization/errors.py +10 -0
- ccxt/static_dependencies/starknet/serialization/factory.py +229 -0
- ccxt/static_dependencies/starknet/serialization/function_serialization_adapter.py +110 -0
- ccxt/static_dependencies/starknet/serialization/tuple_dataclass.py +59 -0
- ccxt/static_dependencies/starknet/utils/__init__.py +0 -0
- ccxt/static_dependencies/starknet/utils/constructor_args_translator.py +86 -0
- ccxt/static_dependencies/starknet/utils/iterable.py +13 -0
- ccxt/static_dependencies/starknet/utils/schema.py +13 -0
- ccxt/static_dependencies/starknet/utils/typed_data.py +182 -0
- ccxt/static_dependencies/starkware/__init__.py +0 -0
- ccxt/static_dependencies/starkware/crypto/__init__.py +0 -0
- ccxt/static_dependencies/starkware/crypto/fast_pedersen_hash.py +50 -0
- ccxt/static_dependencies/starkware/crypto/math_utils.py +78 -0
- ccxt/static_dependencies/starkware/crypto/signature.py +2344 -0
- ccxt/static_dependencies/starkware/crypto/utils.py +63 -0
- ccxt/static_dependencies/sympy/__init__.py +0 -0
- ccxt/static_dependencies/sympy/core/__init__.py +0 -0
- ccxt/static_dependencies/sympy/core/intfunc.py +35 -0
- ccxt/static_dependencies/sympy/external/__init__.py +0 -0
- ccxt/static_dependencies/sympy/external/gmpy.py +345 -0
- ccxt/static_dependencies/sympy/external/importtools.py +187 -0
- ccxt/static_dependencies/sympy/external/ntheory.py +637 -0
- ccxt/static_dependencies/sympy/external/pythonmpq.py +341 -0
- ccxt/static_dependencies/typing_inspect/__init__.py +0 -0
- ccxt/static_dependencies/typing_inspect/typing_inspect.py +851 -0
- ccxt/test/{test_async.py → tests_async.py} +465 -407
- ccxt/test/tests_helpers.py +285 -0
- ccxt/test/tests_init.py +39 -0
- ccxt/test/{test_sync.py → tests_sync.py} +465 -409
- ccxt/timex.py +123 -70
- ccxt/tokocrypto.py +129 -93
- ccxt/tradeogre.py +39 -25
- ccxt/upbit.py +322 -113
- ccxt/vertex.py +2983 -0
- ccxt/wavesexchange.py +227 -173
- ccxt/wazirx.py +145 -65
- ccxt/whitebit.py +533 -138
- ccxt/woo.py +1155 -295
- ccxt/woofipro.py +2716 -0
- ccxt/xt.py +4627 -0
- ccxt/yobit.py +159 -92
- ccxt/zaif.py +80 -33
- ccxt/zonda.py +140 -69
- ccxt-4.4.48.dist-info/LICENSE.txt +21 -0
- ccxt-4.4.48.dist-info/METADATA +646 -0
- ccxt-4.4.48.dist-info/RECORD +669 -0
- {ccxt-4.2.76.dist-info → ccxt-4.4.48.dist-info}/WHEEL +1 -1
- ccxt/abstract/bitbay.py +0 -47
- ccxt/abstract/bitfinex2.py +0 -139
- ccxt/abstract/hitbtc3.py +0 -115
- ccxt/async_support/bitbay.py +0 -17
- ccxt/async_support/bitfinex2.py +0 -3496
- ccxt/async_support/flowbtc.py +0 -34
- ccxt/bitbay.py +0 -17
- ccxt/bitfinex2.py +0 -3496
- ccxt/flowbtc.py +0 -34
- ccxt/hitbtc3.py +0 -16
- ccxt/pro/bitfinex2.py +0 -1081
- ccxt/test/base/__init__.py +0 -28
- ccxt/test/base/test_account.py +0 -26
- ccxt/test/base/test_balance.py +0 -56
- ccxt/test/base/test_borrow_interest.py +0 -35
- ccxt/test/base/test_borrow_rate.py +0 -32
- ccxt/test/base/test_calculate_fee.py +0 -51
- ccxt/test/base/test_crypto.py +0 -127
- ccxt/test/base/test_currency.py +0 -76
- ccxt/test/base/test_datetime.py +0 -103
- ccxt/test/base/test_decimal_to_precision.py +0 -392
- ccxt/test/base/test_deep_extend.py +0 -68
- ccxt/test/base/test_deposit_withdrawal.py +0 -50
- ccxt/test/base/test_exchange_datetime_functions.py +0 -76
- ccxt/test/base/test_funding_rate_history.py +0 -29
- ccxt/test/base/test_last_price.py +0 -32
- ccxt/test/base/test_ledger_entry.py +0 -45
- ccxt/test/base/test_ledger_item.py +0 -48
- ccxt/test/base/test_leverage_tier.py +0 -33
- ccxt/test/base/test_margin_mode.py +0 -24
- ccxt/test/base/test_margin_modification.py +0 -35
- ccxt/test/base/test_market.py +0 -190
- ccxt/test/base/test_number.py +0 -411
- ccxt/test/base/test_ohlcv.py +0 -32
- ccxt/test/base/test_open_interest.py +0 -32
- ccxt/test/base/test_order.py +0 -64
- ccxt/test/base/test_order_book.py +0 -63
- ccxt/test/base/test_position.py +0 -60
- ccxt/test/base/test_shared_methods.py +0 -345
- ccxt/test/base/test_status.py +0 -24
- ccxt/test/base/test_throttle.py +0 -126
- ccxt/test/base/test_ticker.py +0 -86
- ccxt/test/base/test_trade.py +0 -47
- ccxt/test/base/test_trading_fee.py +0 -26
- ccxt/test/base/test_transaction.py +0 -39
- ccxt-4.2.76.dist-info/METADATA +0 -626
- ccxt-4.2.76.dist-info/RECORD +0 -534
- {ccxt-4.2.76.dist-info → ccxt-4.4.48.dist-info}/top_level.txt +0 -0
ccxt/coinbase.py
CHANGED
@@ -6,9 +6,11 @@
|
|
6
6
|
from ccxt.base.exchange import Exchange
|
7
7
|
from ccxt.abstract.coinbase import ImplicitAPI
|
8
8
|
import hashlib
|
9
|
-
from ccxt.base.types import Account, Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
|
9
|
+
from ccxt.base.types import Account, Balances, Conversion, Currencies, Currency, DepositAddress, Int, LedgerEntry, Market, MarketInterface, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFees, Transaction
|
10
10
|
from typing import List
|
11
11
|
from ccxt.base.errors import ExchangeError
|
12
|
+
from ccxt.base.errors import AuthenticationError
|
13
|
+
from ccxt.base.errors import PermissionDenied
|
12
14
|
from ccxt.base.errors import ArgumentsRequired
|
13
15
|
from ccxt.base.errors import BadRequest
|
14
16
|
from ccxt.base.errors import InvalidOrder
|
@@ -16,7 +18,6 @@ from ccxt.base.errors import OrderNotFound
|
|
16
18
|
from ccxt.base.errors import NotSupported
|
17
19
|
from ccxt.base.errors import RateLimitExceeded
|
18
20
|
from ccxt.base.errors import InvalidNonce
|
19
|
-
from ccxt.base.errors import AuthenticationError
|
20
21
|
from ccxt.base.decimal_to_precision import TICK_SIZE
|
21
22
|
from ccxt.base.precise import Precise
|
22
23
|
|
@@ -26,11 +27,12 @@ class coinbase(Exchange, ImplicitAPI):
|
|
26
27
|
def describe(self):
|
27
28
|
return self.deep_extend(super(coinbase, self).describe(), {
|
28
29
|
'id': 'coinbase',
|
29
|
-
'name': 'Coinbase',
|
30
|
+
'name': 'Coinbase Advanced',
|
30
31
|
'countries': ['US'],
|
31
32
|
'pro': True,
|
33
|
+
'certified': True,
|
32
34
|
# rate-limits:
|
33
|
-
# ADVANCED API: https://docs.cloud.coinbase.com/advanced-trade
|
35
|
+
# ADVANCED API: https://docs.cloud.coinbase.com/advanced-trade/docs/rest-api-rate-limits
|
34
36
|
# - max 30 req/second for private data, 10 req/s for public data
|
35
37
|
# DATA API : https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/rate-limiting
|
36
38
|
# - max 10000 req/hour(to prevent userland mistakes we apply ~3 req/second RL per call
|
@@ -51,7 +53,8 @@ class coinbase(Exchange, ImplicitAPI):
|
|
51
53
|
'cancelOrder': True,
|
52
54
|
'cancelOrders': True,
|
53
55
|
'closeAllPositions': False,
|
54
|
-
'closePosition':
|
56
|
+
'closePosition': True,
|
57
|
+
'createConvertTrade': True,
|
55
58
|
'createDepositAddress': True,
|
56
59
|
'createLimitBuyOrder': True,
|
57
60
|
'createLimitSellOrder': True,
|
@@ -75,6 +78,9 @@ class coinbase(Exchange, ImplicitAPI):
|
|
75
78
|
'fetchBorrowRateHistory': False,
|
76
79
|
'fetchCanceledOrders': True,
|
77
80
|
'fetchClosedOrders': True,
|
81
|
+
'fetchConvertQuote': True,
|
82
|
+
'fetchConvertTrade': True,
|
83
|
+
'fetchConvertTradeHistory': False,
|
78
84
|
'fetchCrossBorrowRate': False,
|
79
85
|
'fetchCrossBorrowRates': False,
|
80
86
|
'fetchCurrencies': True,
|
@@ -82,7 +88,10 @@ class coinbase(Exchange, ImplicitAPI):
|
|
82
88
|
'fetchDepositAddress': 'emulated',
|
83
89
|
'fetchDepositAddresses': False,
|
84
90
|
'fetchDepositAddressesByNetwork': True,
|
91
|
+
'fetchDepositMethodId': True,
|
92
|
+
'fetchDepositMethodIds': True,
|
85
93
|
'fetchDeposits': True,
|
94
|
+
'fetchDepositsWithdrawals': True,
|
86
95
|
'fetchFundingHistory': False,
|
87
96
|
'fetchFundingRate': False,
|
88
97
|
'fetchFundingRateHistory': False,
|
@@ -106,17 +115,17 @@ class coinbase(Exchange, ImplicitAPI):
|
|
106
115
|
'fetchOrder': True,
|
107
116
|
'fetchOrderBook': True,
|
108
117
|
'fetchOrders': True,
|
109
|
-
'fetchPosition':
|
118
|
+
'fetchPosition': True,
|
110
119
|
'fetchPositionMode': False,
|
111
|
-
'fetchPositions':
|
120
|
+
'fetchPositions': True,
|
112
121
|
'fetchPositionsRisk': False,
|
113
122
|
'fetchPremiumIndexOHLCV': False,
|
114
123
|
'fetchTicker': True,
|
115
124
|
'fetchTickers': True,
|
116
125
|
'fetchTime': True,
|
117
126
|
'fetchTrades': True,
|
118
|
-
'fetchTradingFee':
|
119
|
-
'fetchTradingFees':
|
127
|
+
'fetchTradingFee': 'emulated',
|
128
|
+
'fetchTradingFees': True,
|
120
129
|
'fetchWithdrawals': True,
|
121
130
|
'reduceMargin': False,
|
122
131
|
'setLeverage': False,
|
@@ -132,7 +141,7 @@ class coinbase(Exchange, ImplicitAPI):
|
|
132
141
|
'www': 'https://www.coinbase.com',
|
133
142
|
'doc': [
|
134
143
|
'https://developers.coinbase.com/api/v2',
|
135
|
-
'https://docs.cloud.coinbase.com/advanced-trade
|
144
|
+
'https://docs.cloud.coinbase.com/advanced-trade/docs/welcome',
|
136
145
|
],
|
137
146
|
'fees': [
|
138
147
|
'https://support.coinbase.com/customer/portal/articles/2109597-buy-sell-bank-transfer-fees',
|
@@ -210,6 +219,11 @@ class coinbase(Exchange, ImplicitAPI):
|
|
210
219
|
'public': {
|
211
220
|
'get': {
|
212
221
|
'brokerage/time': 3,
|
222
|
+
'brokerage/market/product_book': 3,
|
223
|
+
'brokerage/market/products': 3,
|
224
|
+
'brokerage/market/products/{product_id}': 3,
|
225
|
+
'brokerage/market/products/{product_id}/candles': 3,
|
226
|
+
'brokerage/market/products/{product_id}/ticker': 3,
|
213
227
|
},
|
214
228
|
},
|
215
229
|
'private': {
|
@@ -251,6 +265,8 @@ class coinbase(Exchange, ImplicitAPI):
|
|
251
265
|
'brokerage/convert/trade/{trade_id}': 1,
|
252
266
|
'brokerage/cfm/sweeps/schedule': 1,
|
253
267
|
'brokerage/intx/allocate': 1,
|
268
|
+
# futures
|
269
|
+
'brokerage/orders/close_position': 1,
|
254
270
|
},
|
255
271
|
'put': {
|
256
272
|
'brokerage/portfolios/{portfolio_uuid}': 1,
|
@@ -264,8 +280,8 @@ class coinbase(Exchange, ImplicitAPI):
|
|
264
280
|
},
|
265
281
|
'fees': {
|
266
282
|
'trading': {
|
267
|
-
'taker': self.parse_number('0.
|
268
|
-
'maker': self.parse_number('0.
|
283
|
+
'taker': self.parse_number('0.012'),
|
284
|
+
'maker': self.parse_number('0.006'), # {"pricing_tier":"Advanced 1","usd_from":"0","usd_to":"1000","taker_fee_rate":"0.012","maker_fee_rate":"0.006","aop_from":"","aop_to":""}
|
269
285
|
'tierBased': True,
|
270
286
|
'percentage': True,
|
271
287
|
'tiers': {
|
@@ -317,6 +333,8 @@ class coinbase(Exchange, ImplicitAPI):
|
|
317
333
|
'internal_server_error': ExchangeError, # 500 Internal server error
|
318
334
|
'UNSUPPORTED_ORDER_CONFIGURATION': BadRequest,
|
319
335
|
'INSUFFICIENT_FUND': BadRequest,
|
336
|
+
'PERMISSION_DENIED': PermissionDenied,
|
337
|
+
'INVALID_ARGUMENT': BadRequest,
|
320
338
|
},
|
321
339
|
'broad': {
|
322
340
|
'request timestamp expired': InvalidNonce, # {"errors":[{"id":"authentication_error","message":"request timestamp expired"}]}
|
@@ -337,6 +355,8 @@ class coinbase(Exchange, ImplicitAPI):
|
|
337
355
|
'CGLD': 'CELO',
|
338
356
|
},
|
339
357
|
'options': {
|
358
|
+
'usePrivate': False,
|
359
|
+
'brokerId': 'ccxt',
|
340
360
|
'stablePairs': ['BUSD-USD', 'CBETH-ETH', 'DAI-USD', 'GUSD-USD', 'GYEN-USD', 'PAX-USD', 'PAX-USDT', 'USDC-EUR', 'USDC-GBP', 'USDT-EUR', 'USDT-GBP', 'USDT-USD', 'USDT-USDC', 'WBTC-BTC'],
|
341
361
|
'fetchCurrencies': {
|
342
362
|
'expires': 5000,
|
@@ -357,6 +377,8 @@ class coinbase(Exchange, ImplicitAPI):
|
|
357
377
|
'createMarketBuyOrderRequiresPrice': True,
|
358
378
|
'advanced': True, # set to True if using any v3 endpoints from the advanced trade API
|
359
379
|
'fetchMarkets': 'fetchMarketsV3', # 'fetchMarketsV3' or 'fetchMarketsV2'
|
380
|
+
'timeDifference': 0, # the difference between system clock and exchange server clock
|
381
|
+
'adjustForTimeDifference': False, # controls the adjustment logic upon instantiation
|
360
382
|
'fetchTicker': 'fetchTickerV3', # 'fetchTickerV3' or 'fetchTickerV2'
|
361
383
|
'fetchTickers': 'fetchTickersV3', # 'fetchTickersV3' or 'fetchTickersV2'
|
362
384
|
'fetchAccounts': 'fetchAccountsV3', # 'fetchAccountsV3' or 'fetchAccountsV2'
|
@@ -364,12 +386,94 @@ class coinbase(Exchange, ImplicitAPI):
|
|
364
386
|
'fetchTime': 'v2PublicGetTime', # 'v2PublicGetTime' or 'v3PublicGetBrokerageTime'
|
365
387
|
'user_native_currency': 'USD', # needed to get fees for v3
|
366
388
|
},
|
389
|
+
'features': {
|
390
|
+
'default': {
|
391
|
+
'sandbox': False,
|
392
|
+
'createOrder': {
|
393
|
+
'marginMode': True,
|
394
|
+
'triggerPrice': True,
|
395
|
+
'triggerPriceType': None,
|
396
|
+
'triggerDirection': True,
|
397
|
+
'stopLossPrice': True,
|
398
|
+
'takeProfitPrice': True,
|
399
|
+
'attachedStopLossTakeProfit': None,
|
400
|
+
'timeInForce': {
|
401
|
+
'IOC': True,
|
402
|
+
'FOK': True,
|
403
|
+
'PO': True,
|
404
|
+
'GTD': True,
|
405
|
+
},
|
406
|
+
'hedged': False,
|
407
|
+
'trailing': False,
|
408
|
+
'leverage': True, # todo implement
|
409
|
+
'marketBuyByCost': True,
|
410
|
+
'marketBuyRequiresPrice': True,
|
411
|
+
'selfTradePrevention': False,
|
412
|
+
'iceberg': False,
|
413
|
+
},
|
414
|
+
'createOrders': None,
|
415
|
+
'fetchMyTrades': {
|
416
|
+
'marginMode': False,
|
417
|
+
'limit': 3000,
|
418
|
+
'daysBack': None,
|
419
|
+
'untilDays': 10000,
|
420
|
+
},
|
421
|
+
'fetchOrder': {
|
422
|
+
'marginMode': False,
|
423
|
+
'trigger': False,
|
424
|
+
'trailing': False,
|
425
|
+
},
|
426
|
+
'fetchOpenOrders': {
|
427
|
+
'marginMode': False,
|
428
|
+
'limit': None,
|
429
|
+
'trigger': False,
|
430
|
+
'trailing': False,
|
431
|
+
},
|
432
|
+
'fetchOrders': {
|
433
|
+
'marginMode': False,
|
434
|
+
'limit': None,
|
435
|
+
'daysBack': None,
|
436
|
+
'untilDays': 10000,
|
437
|
+
'trigger': False,
|
438
|
+
'trailing': False,
|
439
|
+
},
|
440
|
+
'fetchClosedOrders': {
|
441
|
+
'marginMode': False,
|
442
|
+
'limit': None,
|
443
|
+
'daysBack': None,
|
444
|
+
'daysBackCanceled': None,
|
445
|
+
'untilDays': 10000,
|
446
|
+
'trigger': False,
|
447
|
+
'trailing': False,
|
448
|
+
},
|
449
|
+
'fetchOHLCV': {
|
450
|
+
'limit': 350,
|
451
|
+
},
|
452
|
+
},
|
453
|
+
'spot': {
|
454
|
+
'extends': 'default',
|
455
|
+
},
|
456
|
+
'swap': {
|
457
|
+
'linear': {
|
458
|
+
'extends': 'default',
|
459
|
+
},
|
460
|
+
'inverse': None,
|
461
|
+
},
|
462
|
+
'future': {
|
463
|
+
'linear': {
|
464
|
+
'extends': 'default',
|
465
|
+
},
|
466
|
+
'inverse': None,
|
467
|
+
},
|
468
|
+
},
|
367
469
|
})
|
368
470
|
|
369
471
|
def fetch_time(self, params={}):
|
370
472
|
"""
|
371
473
|
fetches the current integer timestamp in milliseconds from the exchange server
|
372
|
-
|
474
|
+
|
475
|
+
https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-time#http-request
|
476
|
+
|
373
477
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
374
478
|
:param str [params.method]: 'v2PublicGetTime' or 'v3PublicGetBrokerageTime' default is 'v2PublicGetTime'
|
375
479
|
:returns int: the current integer timestamp in milliseconds from the exchange server
|
@@ -403,8 +507,10 @@ class coinbase(Exchange, ImplicitAPI):
|
|
403
507
|
def fetch_accounts(self, params={}) -> List[Account]:
|
404
508
|
"""
|
405
509
|
fetch all the accounts associated with a profile
|
406
|
-
|
407
|
-
|
510
|
+
|
511
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getaccounts
|
512
|
+
https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-accounts#list-accounts
|
513
|
+
|
408
514
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
409
515
|
:param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
|
410
516
|
:returns dict: a dictionary of `account structures <https://docs.ccxt.com/#/?id=account-structure>` indexed by the account type
|
@@ -420,7 +526,7 @@ class coinbase(Exchange, ImplicitAPI):
|
|
420
526
|
paginate, params = self.handle_option_and_params(params, 'fetchAccounts', 'paginate')
|
421
527
|
if paginate:
|
422
528
|
return self.fetch_paginated_call_cursor('fetchAccounts', None, None, None, params, 'next_starting_after', 'starting_after', None, 100)
|
423
|
-
request = {
|
529
|
+
request: dict = {
|
424
530
|
'limit': 100,
|
425
531
|
}
|
426
532
|
response = self.v2PrivateGetAccounts(self.extend(request, params))
|
@@ -485,9 +591,9 @@ class coinbase(Exchange, ImplicitAPI):
|
|
485
591
|
paginate = False
|
486
592
|
paginate, params = self.handle_option_and_params(params, 'fetchAccounts', 'paginate')
|
487
593
|
if paginate:
|
488
|
-
return self.fetch_paginated_call_cursor('fetchAccounts', None, None, None, params, 'cursor', 'cursor', None,
|
489
|
-
request = {
|
490
|
-
'limit':
|
594
|
+
return self.fetch_paginated_call_cursor('fetchAccounts', None, None, None, params, 'cursor', 'cursor', None, 250)
|
595
|
+
request: dict = {
|
596
|
+
'limit': 250,
|
491
597
|
}
|
492
598
|
response = self.v3PrivateGetBrokerageAccounts(self.extend(request, params))
|
493
599
|
#
|
@@ -530,6 +636,28 @@ class coinbase(Exchange, ImplicitAPI):
|
|
530
636
|
accounts[lastIndex] = last
|
531
637
|
return self.parse_accounts(accounts, params)
|
532
638
|
|
639
|
+
def fetch_portfolios(self, params={}) -> List[Account]:
|
640
|
+
"""
|
641
|
+
fetch all the portfolios
|
642
|
+
|
643
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getportfolios
|
644
|
+
|
645
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
646
|
+
:returns dict: a dictionary of `account structures <https://docs.ccxt.com/#/?id=account-structure>` indexed by the account type
|
647
|
+
"""
|
648
|
+
response = self.v3PrivateGetBrokeragePortfolios(params)
|
649
|
+
portfolios = self.safe_list(response, 'portfolios', [])
|
650
|
+
result = []
|
651
|
+
for i in range(0, len(portfolios)):
|
652
|
+
portfolio = portfolios[i]
|
653
|
+
result.append({
|
654
|
+
'id': self.safe_string(portfolio, 'uuid'),
|
655
|
+
'type': self.safe_string(portfolio, 'type'),
|
656
|
+
'code': None,
|
657
|
+
'info': portfolio,
|
658
|
+
})
|
659
|
+
return result
|
660
|
+
|
533
661
|
def parse_account(self, account):
|
534
662
|
#
|
535
663
|
# fetchAccountsV2
|
@@ -603,7 +731,9 @@ class coinbase(Exchange, ImplicitAPI):
|
|
603
731
|
def create_deposit_address(self, code: str, params={}):
|
604
732
|
"""
|
605
733
|
create a currency deposit address
|
606
|
-
|
734
|
+
|
735
|
+
https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-addresses#create-address
|
736
|
+
|
607
737
|
:param str code: unified currency code of the currency for the deposit address
|
608
738
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
609
739
|
:returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
|
@@ -619,7 +749,7 @@ class coinbase(Exchange, ImplicitAPI):
|
|
619
749
|
break
|
620
750
|
if accountId is None:
|
621
751
|
raise ExchangeError(self.id + ' createDepositAddress() could not find the account with matching currency code, specify an `account_id` extra param')
|
622
|
-
request = {
|
752
|
+
request: dict = {
|
623
753
|
'account_id': accountId,
|
624
754
|
}
|
625
755
|
response = self.v2PrivatePostAccountsAccountIdAddresses(self.extend(request, params))
|
@@ -671,9 +801,11 @@ class coinbase(Exchange, ImplicitAPI):
|
|
671
801
|
|
672
802
|
def fetch_my_sells(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
673
803
|
"""
|
674
|
-
|
804
|
+
@ignore
|
675
805
|
fetch sells
|
676
|
-
|
806
|
+
|
807
|
+
https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-sells#list-sells
|
808
|
+
|
677
809
|
:param str symbol: not used by coinbase fetchMySells()
|
678
810
|
:param int [since]: timestamp in ms of the earliest sell, default is None
|
679
811
|
:param int [limit]: max number of sells to return, default is None
|
@@ -689,9 +821,11 @@ class coinbase(Exchange, ImplicitAPI):
|
|
689
821
|
|
690
822
|
def fetch_my_buys(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
691
823
|
"""
|
692
|
-
|
824
|
+
@ignore
|
693
825
|
fetch buys
|
694
|
-
|
826
|
+
|
827
|
+
https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-buys#list-buys
|
828
|
+
|
695
829
|
:param str symbol: not used by coinbase fetchMyBuys()
|
696
830
|
:param int [since]: timestamp in ms of the earliest buy, default is None
|
697
831
|
:param int [limit]: max number of buys to return, default is None
|
@@ -714,39 +848,69 @@ class coinbase(Exchange, ImplicitAPI):
|
|
714
848
|
|
715
849
|
def fetch_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
|
716
850
|
"""
|
717
|
-
|
718
|
-
|
851
|
+
Fetch all withdrawals made from an account. Won't return crypto withdrawals. Use fetchLedger for those.
|
852
|
+
|
853
|
+
https://docs.cdp.coinbase.com/coinbase-app/docs/api-withdrawals#list-withdrawals
|
854
|
+
|
719
855
|
:param str code: unified currency code
|
720
856
|
:param int [since]: the earliest time in ms to fetch withdrawals for
|
721
857
|
:param int [limit]: the maximum number of withdrawals structures to retrieve
|
722
858
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
859
|
+
:param str [params.currencyType]: "fiat" or "crypto"
|
723
860
|
:returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
|
724
861
|
"""
|
725
|
-
|
862
|
+
currencyType = None
|
863
|
+
currencyType, params = self.handle_option_and_params(params, 'fetchWithdrawals', 'currencyType')
|
864
|
+
if currencyType == 'crypto':
|
865
|
+
results = self.fetch_transactions_with_method('v2PrivateGetAccountsAccountIdTransactions', code, since, limit, params)
|
866
|
+
return self.filter_by_array(results, 'type', 'withdrawal', False)
|
726
867
|
return self.fetch_transactions_with_method('v2PrivateGetAccountsAccountIdWithdrawals', code, since, limit, params)
|
727
868
|
|
728
869
|
def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
|
729
870
|
"""
|
730
|
-
|
731
|
-
|
871
|
+
Fetch all fiat deposits made to an account. Won't return crypto deposits or staking rewards. Use fetchLedger for those.
|
872
|
+
|
873
|
+
https://docs.cdp.coinbase.com/coinbase-app/docs/api-deposits#list-deposits
|
874
|
+
|
732
875
|
:param str code: unified currency code
|
733
876
|
:param int [since]: the earliest time in ms to fetch deposits for
|
734
877
|
:param int [limit]: the maximum number of deposits structures to retrieve
|
735
878
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
879
|
+
:param str [params.currencyType]: "fiat" or "crypto"
|
736
880
|
:returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
|
737
881
|
"""
|
738
|
-
|
882
|
+
currencyType = None
|
883
|
+
currencyType, params = self.handle_option_and_params(params, 'fetchWithdrawals', 'currencyType')
|
884
|
+
if currencyType == 'crypto':
|
885
|
+
results = self.fetch_transactions_with_method('v2PrivateGetAccountsAccountIdTransactions', code, since, limit, params)
|
886
|
+
return self.filter_by_array(results, 'type', 'deposit', False)
|
739
887
|
return self.fetch_transactions_with_method('v2PrivateGetAccountsAccountIdDeposits', code, since, limit, params)
|
740
888
|
|
741
|
-
def
|
742
|
-
|
889
|
+
def fetch_deposits_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
|
890
|
+
"""
|
891
|
+
fetch history of deposits and withdrawals
|
892
|
+
|
893
|
+
https://docs.cdp.coinbase.com/coinbase-app/docs/api-transactions
|
894
|
+
|
895
|
+
:param str [code]: unified currency code for the currency of the deposit/withdrawals, default is None
|
896
|
+
:param int [since]: timestamp in ms of the earliest deposit/withdrawal, default is None
|
897
|
+
:param int [limit]: max number of deposit/withdrawals to return, default = 50, Min: 1, Max: 100
|
898
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
899
|
+
:returns dict: a list of `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
|
900
|
+
"""
|
901
|
+
self.load_markets()
|
902
|
+
results = self.fetch_transactions_with_method('v2PrivateGetAccountsAccountIdTransactions', code, since, limit, params)
|
903
|
+
return self.filter_by_array(results, 'type', ['deposit', 'withdrawal'], False)
|
904
|
+
|
905
|
+
def parse_transaction_status(self, status: Str):
|
906
|
+
statuses: dict = {
|
743
907
|
'created': 'pending',
|
744
908
|
'completed': 'ok',
|
745
909
|
'canceled': 'canceled',
|
746
910
|
}
|
747
911
|
return self.safe_string(statuses, status, status)
|
748
912
|
|
749
|
-
def parse_transaction(self, transaction, currency: Currency = None) -> Transaction:
|
913
|
+
def parse_transaction(self, transaction: dict, currency: Currency = None) -> Transaction:
|
750
914
|
#
|
751
915
|
# fiat deposit
|
752
916
|
#
|
@@ -861,16 +1025,59 @@ class coinbase(Exchange, ImplicitAPI):
|
|
861
1025
|
# "hide_native_amount": False
|
862
1026
|
# }
|
863
1027
|
#
|
1028
|
+
#
|
1029
|
+
# crypto deposit & withdrawal(using `/transactions` endpoint)
|
1030
|
+
# {
|
1031
|
+
# "amount": {
|
1032
|
+
# "amount": "0.00014200",(negative for withdrawal)
|
1033
|
+
# "currency": "BTC"
|
1034
|
+
# },
|
1035
|
+
# "created_at": "2024-03-29T15:48:30Z",
|
1036
|
+
# "id": "0031a605-241d-514d-a97b-d4b99f3225d3",
|
1037
|
+
# "idem": "092a979b-017e-4403-940a-2ca57811f442", # field present only in case of withdrawal
|
1038
|
+
# "native_amount": {
|
1039
|
+
# "amount": "9.85",(negative for withdrawal)
|
1040
|
+
# "currency": "USD"
|
1041
|
+
# },
|
1042
|
+
# "network": {
|
1043
|
+
# "status": "pending", # if status is `off_blockchain` then no more other fields are hasattr(self, present) object
|
1044
|
+
# "hash": "5jYuvrNsvX2DZoMnzGYzVpYxJLfYu4GSK3xetG1H5LHrSovsuFCFYdFMwNRoiht3s6fBk92MM8QLLnz65xuEFTrE",
|
1045
|
+
# "network_name": "solana",
|
1046
|
+
# "transaction_fee": {
|
1047
|
+
# "amount": "0.000100000",
|
1048
|
+
# "currency": "SOL"
|
1049
|
+
# }
|
1050
|
+
# },
|
1051
|
+
# "resource": "transaction",
|
1052
|
+
# "resource_path": "/v2/accounts/dc504b1c-248e-5b68-a3b0-b991f7fa84e6/transactions/0031a605-241d-514d-a97b-d4b99f3225d3",
|
1053
|
+
# "status": "completed",
|
1054
|
+
# "type": "send",
|
1055
|
+
# "from": { # in some cases, field might be present for deposit
|
1056
|
+
# "id": "7fd10cd7-b091-5cee-ba41-c29e49a7cccf",
|
1057
|
+
# "name": "Coinbase",
|
1058
|
+
# "resource": "user"
|
1059
|
+
# },
|
1060
|
+
# "to": { # field only present for withdrawal
|
1061
|
+
# "address": "5HA12BNthAvBwNYARYf9y5MqqCpB4qhCNFCs1Qw48ACE",
|
1062
|
+
# "resource": "address"
|
1063
|
+
# },
|
1064
|
+
# "description": "C3 - One Time BTC Credit . Reference Case # 123.", # in some cases, field might be present for deposit
|
1065
|
+
# }
|
1066
|
+
#
|
864
1067
|
transactionType = self.safe_string(transaction, 'type')
|
865
1068
|
amountAndCurrencyObject = None
|
866
1069
|
feeObject = None
|
1070
|
+
network = self.safe_dict(transaction, 'network', {})
|
867
1071
|
if transactionType == 'send':
|
868
|
-
|
869
|
-
amountAndCurrencyObject = self.safe_dict(network, 'transaction_amount', {})
|
1072
|
+
amountAndCurrencyObject = self.safe_dict(network, 'transaction_amount')
|
870
1073
|
feeObject = self.safe_dict(network, 'transaction_fee', {})
|
871
1074
|
else:
|
872
|
-
amountAndCurrencyObject = self.safe_dict(transaction, 'subtotal'
|
1075
|
+
amountAndCurrencyObject = self.safe_dict(transaction, 'subtotal')
|
873
1076
|
feeObject = self.safe_dict(transaction, 'fee', {})
|
1077
|
+
if amountAndCurrencyObject is None:
|
1078
|
+
amountAndCurrencyObject = self.safe_dict(transaction, 'amount')
|
1079
|
+
amountString = self.safe_string(amountAndCurrencyObject, 'amount')
|
1080
|
+
amountStringAbs = Precise.string_abs(amountString)
|
874
1081
|
status = self.parse_transaction_status(self.safe_string(transaction, 'status'))
|
875
1082
|
if status is None:
|
876
1083
|
committed = self.safe_bool(transaction, 'committed')
|
@@ -879,23 +1086,31 @@ class coinbase(Exchange, ImplicitAPI):
|
|
879
1086
|
currencyId = self.safe_string(amountAndCurrencyObject, 'currency')
|
880
1087
|
feeCurrencyId = self.safe_string(feeObject, 'currency')
|
881
1088
|
datetime = self.safe_string(transaction, 'created_at')
|
882
|
-
|
883
|
-
|
1089
|
+
resource = self.safe_string(transaction, 'resource')
|
1090
|
+
type = resource
|
1091
|
+
if not self.in_array(type, ['deposit', 'withdrawal']):
|
1092
|
+
if Precise.string_gt(amountString, '0'):
|
1093
|
+
type = 'deposit'
|
1094
|
+
elif Precise.string_lt(amountString, '0'):
|
1095
|
+
type = 'withdrawal'
|
1096
|
+
toObject = self.safe_dict(transaction, 'to')
|
1097
|
+
addressTo = self.safe_string(toObject, 'address')
|
1098
|
+
networkId = self.safe_string(network, 'network_name')
|
884
1099
|
return {
|
885
1100
|
'info': transaction,
|
886
1101
|
'id': id,
|
887
|
-
'txid': id,
|
1102
|
+
'txid': self.safe_string(network, 'hash', id),
|
888
1103
|
'timestamp': self.parse8601(datetime),
|
889
1104
|
'datetime': datetime,
|
890
|
-
'network':
|
891
|
-
'address':
|
892
|
-
'addressTo':
|
1105
|
+
'network': self.network_id_to_code(networkId),
|
1106
|
+
'address': addressTo,
|
1107
|
+
'addressTo': addressTo,
|
893
1108
|
'addressFrom': None,
|
894
1109
|
'tag': None,
|
895
1110
|
'tagTo': None,
|
896
1111
|
'tagFrom': None,
|
897
|
-
'type':
|
898
|
-
'amount': self.
|
1112
|
+
'type': type,
|
1113
|
+
'amount': self.parse_number(amountStringAbs),
|
899
1114
|
'currency': self.safe_currency_code(currencyId, currency),
|
900
1115
|
'status': status,
|
901
1116
|
'updated': self.parse8601(self.safe_string(transaction, 'updated_at')),
|
@@ -905,7 +1120,7 @@ class coinbase(Exchange, ImplicitAPI):
|
|
905
1120
|
},
|
906
1121
|
}
|
907
1122
|
|
908
|
-
def parse_trade(self, trade, market: Market = None) -> Trade:
|
1123
|
+
def parse_trade(self, trade: dict, market: Market = None) -> Trade:
|
909
1124
|
#
|
910
1125
|
# fetchMyBuys, fetchMySells
|
911
1126
|
#
|
@@ -1030,17 +1245,24 @@ class coinbase(Exchange, ImplicitAPI):
|
|
1030
1245
|
},
|
1031
1246
|
})
|
1032
1247
|
|
1033
|
-
def fetch_markets(self, params={}):
|
1248
|
+
def fetch_markets(self, params={}) -> List[Market]:
|
1034
1249
|
"""
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1250
|
+
|
1251
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getpublicproducts
|
1252
|
+
https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-currencies#get-fiat-currencies
|
1253
|
+
https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-exchange-rates#get-exchange-rates
|
1254
|
+
|
1038
1255
|
retrieves data on all markets for coinbase
|
1039
1256
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1257
|
+
:param boolean [params.usePrivate]: use private endpoint for fetching markets
|
1040
1258
|
:returns dict[]: an array of objects representing market data
|
1041
1259
|
"""
|
1260
|
+
if self.options['adjustForTimeDifference']:
|
1261
|
+
self.load_time_difference()
|
1042
1262
|
method = self.safe_string(self.options, 'fetchMarkets', 'fetchMarketsV3')
|
1043
|
-
|
1263
|
+
if method == 'fetchMarketsV3':
|
1264
|
+
return self.fetch_markets_v3(params)
|
1265
|
+
return self.fetch_markets_v2(params)
|
1044
1266
|
|
1045
1267
|
def fetch_markets_v2(self, params={}):
|
1046
1268
|
response = self.fetch_currencies_from_cache(params)
|
@@ -1112,9 +1334,142 @@ class coinbase(Exchange, ImplicitAPI):
|
|
1112
1334
|
return result
|
1113
1335
|
|
1114
1336
|
def fetch_markets_v3(self, params={}):
|
1115
|
-
|
1337
|
+
usePrivate = False
|
1338
|
+
usePrivate, params = self.handle_option_and_params(params, 'fetchMarkets', 'usePrivate', False)
|
1339
|
+
spotUnresolvedPromises = []
|
1340
|
+
if usePrivate:
|
1341
|
+
spotUnresolvedPromises.append(self.v3PrivateGetBrokerageProducts(params))
|
1342
|
+
else:
|
1343
|
+
spotUnresolvedPromises.append(self.v3PublicGetBrokerageMarketProducts(params))
|
1344
|
+
#
|
1345
|
+
# {
|
1346
|
+
# products: [
|
1347
|
+
# {
|
1348
|
+
# product_id: 'BTC-USD',
|
1349
|
+
# price: '67060',
|
1350
|
+
# price_percentage_change_24h: '3.30054960636883',
|
1351
|
+
# volume_24h: '10967.87426597',
|
1352
|
+
# volume_percentage_change_24h: '141.73048325503036',
|
1353
|
+
# base_increment: '0.00000001',
|
1354
|
+
# quote_increment: '0.01',
|
1355
|
+
# quote_min_size: '1',
|
1356
|
+
# quote_max_size: '150000000',
|
1357
|
+
# base_min_size: '0.00000001',
|
1358
|
+
# base_max_size: '3400',
|
1359
|
+
# base_name: 'Bitcoin',
|
1360
|
+
# quote_name: 'US Dollar',
|
1361
|
+
# watched: False,
|
1362
|
+
# is_disabled: False,
|
1363
|
+
# new: False,
|
1364
|
+
# status: 'online',
|
1365
|
+
# cancel_only: False,
|
1366
|
+
# limit_only: False,
|
1367
|
+
# post_only: False,
|
1368
|
+
# trading_disabled: False,
|
1369
|
+
# auction_mode: False,
|
1370
|
+
# product_type: 'SPOT',
|
1371
|
+
# quote_currency_id: 'USD',
|
1372
|
+
# base_currency_id: 'BTC',
|
1373
|
+
# fcm_trading_session_details: null,
|
1374
|
+
# mid_market_price: '',
|
1375
|
+
# alias: '',
|
1376
|
+
# alias_to: ['BTC-USDC'],
|
1377
|
+
# base_display_symbol: 'BTC',
|
1378
|
+
# quote_display_symbol: 'USD',
|
1379
|
+
# view_only: False,
|
1380
|
+
# price_increment: '0.01',
|
1381
|
+
# display_name: 'BTC-USD',
|
1382
|
+
# product_venue: 'CBE'
|
1383
|
+
# },
|
1384
|
+
# ...
|
1385
|
+
# ],
|
1386
|
+
# num_products: '646'
|
1387
|
+
# }
|
1388
|
+
#
|
1389
|
+
if self.check_required_credentials(False):
|
1390
|
+
spotUnresolvedPromises.append(self.v3PrivateGetBrokerageTransactionSummary(params))
|
1391
|
+
#
|
1392
|
+
# {
|
1393
|
+
# total_volume: '9.995989116664404',
|
1394
|
+
# total_fees: '0.07996791093331522',
|
1395
|
+
# fee_tier: {
|
1396
|
+
# pricing_tier: 'Advanced 1',
|
1397
|
+
# usd_from: '0',
|
1398
|
+
# usd_to: '1000',
|
1399
|
+
# taker_fee_rate: '0.008',
|
1400
|
+
# maker_fee_rate: '0.006',
|
1401
|
+
# aop_from: '',
|
1402
|
+
# aop_to: ''
|
1403
|
+
# },
|
1404
|
+
# margin_rate: null,
|
1405
|
+
# goods_and_services_tax: null,
|
1406
|
+
# advanced_trade_only_volume: '9.995989116664404',
|
1407
|
+
# advanced_trade_only_fees: '0.07996791093331522',
|
1408
|
+
# coinbase_pro_volume: '0',
|
1409
|
+
# coinbase_pro_fees: '0',
|
1410
|
+
# total_balance: '',
|
1411
|
+
# has_promo_fee: False
|
1412
|
+
# }
|
1413
|
+
#
|
1414
|
+
unresolvedContractPromises = []
|
1415
|
+
try:
|
1416
|
+
unresolvedContractPromises = [
|
1417
|
+
self.v3PublicGetBrokerageMarketProducts(self.extend(params, {'product_type': 'FUTURE'})),
|
1418
|
+
self.v3PublicGetBrokerageMarketProducts(self.extend(params, {'product_type': 'FUTURE', 'contract_expiry_type': 'PERPETUAL'})),
|
1419
|
+
]
|
1420
|
+
if self.check_required_credentials(False):
|
1421
|
+
unresolvedContractPromises.append(self.extend(params, {'product_type': 'FUTURE'}))
|
1422
|
+
unresolvedContractPromises.append(self.extend(params, {'product_type': 'FUTURE', 'contract_expiry_type': 'PERPETUAL'}))
|
1423
|
+
except Exception as e:
|
1424
|
+
unresolvedContractPromises = [] # the sync version of ccxt won't have the promise.all line so the request is made here. Some users can't access perpetual products
|
1425
|
+
promises = spotUnresolvedPromises
|
1426
|
+
contractPromises = None
|
1427
|
+
try:
|
1428
|
+
contractPromises = unresolvedContractPromises # some users don't have access to contracts
|
1429
|
+
except Exception as e:
|
1430
|
+
contractPromises = []
|
1431
|
+
spot = self.safe_dict(promises, 0, {})
|
1432
|
+
fees = self.safe_dict(promises, 1, {})
|
1433
|
+
expiringFutures = self.safe_dict(contractPromises, 0, {})
|
1434
|
+
perpetualFutures = self.safe_dict(contractPromises, 1, {})
|
1435
|
+
expiringFees = self.safe_dict(contractPromises, 2, {})
|
1436
|
+
perpetualFees = self.safe_dict(contractPromises, 3, {})
|
1437
|
+
#
|
1438
|
+
# {
|
1439
|
+
# "total_volume": 0,
|
1440
|
+
# "total_fees": 0,
|
1441
|
+
# "fee_tier": {
|
1442
|
+
# "pricing_tier": "",
|
1443
|
+
# "usd_from": "0",
|
1444
|
+
# "usd_to": "10000",
|
1445
|
+
# "taker_fee_rate": "0.006",
|
1446
|
+
# "maker_fee_rate": "0.004"
|
1447
|
+
# },
|
1448
|
+
# "margin_rate": null,
|
1449
|
+
# "goods_and_services_tax": null,
|
1450
|
+
# "advanced_trade_only_volume": 0,
|
1451
|
+
# "advanced_trade_only_fees": 0,
|
1452
|
+
# "coinbase_pro_volume": 0,
|
1453
|
+
# "coinbase_pro_fees": 0
|
1454
|
+
# }
|
1455
|
+
#
|
1456
|
+
feeTier = self.safe_dict(fees, 'fee_tier', {})
|
1457
|
+
expiringFeeTier = self.safe_dict(expiringFees, 'fee_tier', {}) # fee tier null?
|
1458
|
+
perpetualFeeTier = self.safe_dict(perpetualFees, 'fee_tier', {}) # fee tier null?
|
1459
|
+
data = self.safe_list(spot, 'products', [])
|
1460
|
+
result = []
|
1461
|
+
for i in range(0, len(data)):
|
1462
|
+
result.append(self.parse_spot_market(data[i], feeTier))
|
1463
|
+
futureData = self.safe_list(expiringFutures, 'products', [])
|
1464
|
+
for i in range(0, len(futureData)):
|
1465
|
+
result.append(self.parse_contract_market(futureData[i], expiringFeeTier))
|
1466
|
+
perpetualData = self.safe_list(perpetualFutures, 'products', [])
|
1467
|
+
for i in range(0, len(perpetualData)):
|
1468
|
+
result.append(self.parse_contract_market(perpetualData[i], perpetualFeeTier))
|
1469
|
+
return result
|
1470
|
+
|
1471
|
+
def parse_spot_market(self, market, feeTier) -> MarketInterface:
|
1116
1472
|
#
|
1117
|
-
# [
|
1118
1473
|
# {
|
1119
1474
|
# "product_id": "TONE-USD",
|
1120
1475
|
# "price": "0.01523",
|
@@ -1143,95 +1498,266 @@ class coinbase(Exchange, ImplicitAPI):
|
|
1143
1498
|
# "base_currency_id": "TONE",
|
1144
1499
|
# "fcm_trading_session_details": null,
|
1145
1500
|
# "mid_market_price": ""
|
1146
|
-
# }
|
1147
|
-
# ...
|
1148
|
-
# ]
|
1501
|
+
# }
|
1149
1502
|
#
|
1150
|
-
|
1503
|
+
id = self.safe_string(market, 'product_id')
|
1504
|
+
baseId = self.safe_string(market, 'base_currency_id')
|
1505
|
+
quoteId = self.safe_string(market, 'quote_currency_id')
|
1506
|
+
base = self.safe_currency_code(baseId)
|
1507
|
+
quote = self.safe_currency_code(quoteId)
|
1508
|
+
marketType = self.safe_string_lower(market, 'product_type')
|
1509
|
+
tradingDisabled = self.safe_bool(market, 'trading_disabled')
|
1510
|
+
stablePairs = self.safe_list(self.options, 'stablePairs', [])
|
1511
|
+
defaultTakerFee = self.safe_number(self.fees['trading'], 'taker')
|
1512
|
+
defaultMakerFee = self.safe_number(self.fees['trading'], 'maker')
|
1513
|
+
takerFee = 0.00001 if self.in_array(id, stablePairs) else self.safe_number(feeTier, 'taker_fee_rate', defaultTakerFee)
|
1514
|
+
makerFee = 0.0 if self.in_array(id, stablePairs) else self.safe_number(feeTier, 'maker_fee_rate', defaultMakerFee)
|
1515
|
+
return self.safe_market_structure({
|
1516
|
+
'id': id,
|
1517
|
+
'symbol': base + '/' + quote,
|
1518
|
+
'base': base,
|
1519
|
+
'quote': quote,
|
1520
|
+
'settle': None,
|
1521
|
+
'baseId': baseId,
|
1522
|
+
'quoteId': quoteId,
|
1523
|
+
'settleId': None,
|
1524
|
+
'type': marketType,
|
1525
|
+
'spot': (marketType == 'spot'),
|
1526
|
+
'margin': None,
|
1527
|
+
'swap': False,
|
1528
|
+
'future': False,
|
1529
|
+
'option': False,
|
1530
|
+
'active': not tradingDisabled,
|
1531
|
+
'contract': False,
|
1532
|
+
'linear': None,
|
1533
|
+
'inverse': None,
|
1534
|
+
'taker': takerFee,
|
1535
|
+
'maker': makerFee,
|
1536
|
+
'contractSize': None,
|
1537
|
+
'expiry': None,
|
1538
|
+
'expiryDatetime': None,
|
1539
|
+
'strike': None,
|
1540
|
+
'optionType': None,
|
1541
|
+
'precision': {
|
1542
|
+
'amount': self.safe_number(market, 'base_increment'),
|
1543
|
+
'price': self.safe_number_2(market, 'price_increment', 'quote_increment'),
|
1544
|
+
},
|
1545
|
+
'limits': {
|
1546
|
+
'leverage': {
|
1547
|
+
'min': None,
|
1548
|
+
'max': None,
|
1549
|
+
},
|
1550
|
+
'amount': {
|
1551
|
+
'min': self.safe_number(market, 'base_min_size'),
|
1552
|
+
'max': self.safe_number(market, 'base_max_size'),
|
1553
|
+
},
|
1554
|
+
'price': {
|
1555
|
+
'min': None,
|
1556
|
+
'max': None,
|
1557
|
+
},
|
1558
|
+
'cost': {
|
1559
|
+
'min': self.safe_number(market, 'quote_min_size'),
|
1560
|
+
'max': self.safe_number(market, 'quote_max_size'),
|
1561
|
+
},
|
1562
|
+
},
|
1563
|
+
'created': None,
|
1564
|
+
'info': market,
|
1565
|
+
})
|
1566
|
+
|
1567
|
+
def parse_contract_market(self, market, feeTier) -> MarketInterface:
|
1568
|
+
# expiring
|
1151
1569
|
#
|
1152
|
-
#
|
1153
|
-
#
|
1154
|
-
#
|
1155
|
-
#
|
1156
|
-
#
|
1157
|
-
#
|
1158
|
-
#
|
1159
|
-
#
|
1160
|
-
#
|
1161
|
-
#
|
1162
|
-
#
|
1163
|
-
#
|
1164
|
-
#
|
1165
|
-
#
|
1166
|
-
#
|
1167
|
-
#
|
1168
|
-
#
|
1570
|
+
# {
|
1571
|
+
# "product_id":"BIT-26APR24-CDE",
|
1572
|
+
# "price":"71145",
|
1573
|
+
# "price_percentage_change_24h":"-2.36722931247427",
|
1574
|
+
# "volume_24h":"108549",
|
1575
|
+
# "volume_percentage_change_24h":"155.78255337197794",
|
1576
|
+
# "base_increment":"1",
|
1577
|
+
# "quote_increment":"0.01",
|
1578
|
+
# "quote_min_size":"0",
|
1579
|
+
# "quote_max_size":"100000000",
|
1580
|
+
# "base_min_size":"1",
|
1581
|
+
# "base_max_size":"100000000",
|
1582
|
+
# "base_name":"",
|
1583
|
+
# "quote_name":"US Dollar",
|
1584
|
+
# "watched":false,
|
1585
|
+
# "is_disabled":false,
|
1586
|
+
# "new":false,
|
1587
|
+
# "status":"",
|
1588
|
+
# "cancel_only":false,
|
1589
|
+
# "limit_only":false,
|
1590
|
+
# "post_only":false,
|
1591
|
+
# "trading_disabled":false,
|
1592
|
+
# "auction_mode":false,
|
1593
|
+
# "product_type":"FUTURE",
|
1594
|
+
# "quote_currency_id":"USD",
|
1595
|
+
# "base_currency_id":"",
|
1596
|
+
# "fcm_trading_session_details":{
|
1597
|
+
# "is_session_open":true,
|
1598
|
+
# "open_time":"2024-04-08T22:00:00Z",
|
1599
|
+
# "close_time":"2024-04-09T21:00:00Z"
|
1600
|
+
# },
|
1601
|
+
# "mid_market_price":"71105",
|
1602
|
+
# "alias":"",
|
1603
|
+
# "alias_to":[
|
1604
|
+
# ],
|
1605
|
+
# "base_display_symbol":"",
|
1606
|
+
# "quote_display_symbol":"USD",
|
1607
|
+
# "view_only":false,
|
1608
|
+
# "price_increment":"5",
|
1609
|
+
# "display_name":"BTC 26 APR 24",
|
1610
|
+
# "product_venue":"FCM",
|
1611
|
+
# "future_product_details":{
|
1612
|
+
# "venue":"cde",
|
1613
|
+
# "contract_code":"BIT",
|
1614
|
+
# "contract_expiry":"2024-04-26T15:00:00Z",
|
1615
|
+
# "contract_size":"0.01",
|
1616
|
+
# "contract_root_unit":"BTC",
|
1617
|
+
# "group_description":"Nano Bitcoin Futures",
|
1618
|
+
# "contract_expiry_timezone":"Europe/London",
|
1619
|
+
# "group_short_description":"Nano BTC",
|
1620
|
+
# "risk_managed_by":"MANAGED_BY_FCM",
|
1621
|
+
# "contract_expiry_type":"EXPIRING",
|
1622
|
+
# "contract_display_name":"BTC 26 APR 24"
|
1623
|
+
# }
|
1624
|
+
# }
|
1169
1625
|
#
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
|
1179
|
-
|
1180
|
-
|
1181
|
-
|
1182
|
-
|
1183
|
-
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1199
|
-
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1626
|
+
# perpetual
|
1627
|
+
#
|
1628
|
+
# {
|
1629
|
+
# "product_id":"ETH-PERP-INTX",
|
1630
|
+
# "price":"3630.98",
|
1631
|
+
# "price_percentage_change_24h":"0.65142426292038",
|
1632
|
+
# "volume_24h":"114020.1501",
|
1633
|
+
# "volume_percentage_change_24h":"63.33650787154869",
|
1634
|
+
# "base_increment":"0.0001",
|
1635
|
+
# "quote_increment":"0.01",
|
1636
|
+
# "quote_min_size":"10",
|
1637
|
+
# "quote_max_size":"50000000",
|
1638
|
+
# "base_min_size":"0.0001",
|
1639
|
+
# "base_max_size":"50000",
|
1640
|
+
# "base_name":"",
|
1641
|
+
# "quote_name":"USDC",
|
1642
|
+
# "watched":false,
|
1643
|
+
# "is_disabled":false,
|
1644
|
+
# "new":false,
|
1645
|
+
# "status":"",
|
1646
|
+
# "cancel_only":false,
|
1647
|
+
# "limit_only":false,
|
1648
|
+
# "post_only":false,
|
1649
|
+
# "trading_disabled":false,
|
1650
|
+
# "auction_mode":false,
|
1651
|
+
# "product_type":"FUTURE",
|
1652
|
+
# "quote_currency_id":"USDC",
|
1653
|
+
# "base_currency_id":"",
|
1654
|
+
# "fcm_trading_session_details":null,
|
1655
|
+
# "mid_market_price":"3630.975",
|
1656
|
+
# "alias":"",
|
1657
|
+
# "alias_to":[],
|
1658
|
+
# "base_display_symbol":"",
|
1659
|
+
# "quote_display_symbol":"USDC",
|
1660
|
+
# "view_only":false,
|
1661
|
+
# "price_increment":"0.01",
|
1662
|
+
# "display_name":"ETH PERP",
|
1663
|
+
# "product_venue":"INTX",
|
1664
|
+
# "future_product_details":{
|
1665
|
+
# "venue":"",
|
1666
|
+
# "contract_code":"ETH",
|
1667
|
+
# "contract_expiry":null,
|
1668
|
+
# "contract_size":"1",
|
1669
|
+
# "contract_root_unit":"ETH",
|
1670
|
+
# "group_description":"",
|
1671
|
+
# "contract_expiry_timezone":"",
|
1672
|
+
# "group_short_description":"",
|
1673
|
+
# "risk_managed_by":"MANAGED_BY_VENUE",
|
1674
|
+
# "contract_expiry_type":"PERPETUAL",
|
1675
|
+
# "perpetual_details":{
|
1676
|
+
# "open_interest":"0",
|
1677
|
+
# "funding_rate":"0.000016",
|
1678
|
+
# "funding_time":"2024-04-09T09:00:00.000008Z",
|
1679
|
+
# "max_leverage":"10"
|
1680
|
+
# },
|
1681
|
+
# "contract_display_name":"ETH PERPETUAL"
|
1682
|
+
# }
|
1683
|
+
# }
|
1684
|
+
#
|
1685
|
+
id = self.safe_string(market, 'product_id')
|
1686
|
+
futureProductDetails = self.safe_dict(market, 'future_product_details', {})
|
1687
|
+
contractExpiryType = self.safe_string(futureProductDetails, 'contract_expiry_type')
|
1688
|
+
contractSize = self.safe_number(futureProductDetails, 'contract_size')
|
1689
|
+
contractExpire = self.safe_string(futureProductDetails, 'contract_expiry')
|
1690
|
+
expireTimestamp = self.parse8601(contractExpire)
|
1691
|
+
expireDateTime = self.iso8601(expireTimestamp)
|
1692
|
+
isSwap = (contractExpiryType == 'PERPETUAL')
|
1693
|
+
baseId = self.safe_string(futureProductDetails, 'contract_root_unit')
|
1694
|
+
quoteId = self.safe_string(market, 'quote_currency_id')
|
1695
|
+
base = self.safe_currency_code(baseId)
|
1696
|
+
quote = self.safe_currency_code(quoteId)
|
1697
|
+
tradingDisabled = self.safe_bool(market, 'is_disabled')
|
1698
|
+
symbol = base + '/' + quote
|
1699
|
+
type = None
|
1700
|
+
if isSwap:
|
1701
|
+
type = 'swap'
|
1702
|
+
symbol = symbol + ':' + quote
|
1703
|
+
else:
|
1704
|
+
type = 'future'
|
1705
|
+
symbol = symbol + ':' + quote + '-' + self.yymmdd(expireTimestamp)
|
1706
|
+
takerFeeRate = self.safe_number(feeTier, 'taker_fee_rate')
|
1707
|
+
makerFeeRate = self.safe_number(feeTier, 'maker_fee_rate')
|
1708
|
+
taker = takerFeeRate if takerFeeRate else self.parse_number('0.06')
|
1709
|
+
maker = makerFeeRate if makerFeeRate else self.parse_number('0.04')
|
1710
|
+
return self.safe_market_structure({
|
1711
|
+
'id': id,
|
1712
|
+
'symbol': symbol,
|
1713
|
+
'base': base,
|
1714
|
+
'quote': quote,
|
1715
|
+
'settle': quote,
|
1716
|
+
'baseId': baseId,
|
1717
|
+
'quoteId': quoteId,
|
1718
|
+
'settleId': quoteId,
|
1719
|
+
'type': type,
|
1720
|
+
'spot': False,
|
1721
|
+
'margin': False,
|
1722
|
+
'swap': isSwap,
|
1723
|
+
'future': not isSwap,
|
1724
|
+
'option': False,
|
1725
|
+
'active': not tradingDisabled,
|
1726
|
+
'contract': True,
|
1727
|
+
'linear': True,
|
1728
|
+
'inverse': False,
|
1729
|
+
'taker': taker,
|
1730
|
+
'maker': maker,
|
1731
|
+
'contractSize': contractSize,
|
1732
|
+
'expiry': expireTimestamp,
|
1733
|
+
'expiryDatetime': expireDateTime,
|
1734
|
+
'strike': None,
|
1735
|
+
'optionType': None,
|
1736
|
+
'precision': {
|
1737
|
+
'amount': self.safe_number(market, 'base_increment'),
|
1738
|
+
'price': self.safe_number_2(market, 'price_increment', 'quote_increment'),
|
1739
|
+
},
|
1740
|
+
'limits': {
|
1741
|
+
'leverage': {
|
1742
|
+
'min': None,
|
1743
|
+
'max': None,
|
1212
1744
|
},
|
1213
|
-
'
|
1214
|
-
'
|
1215
|
-
|
1216
|
-
'max': None,
|
1217
|
-
},
|
1218
|
-
'amount': {
|
1219
|
-
'min': self.safe_number(market, 'base_min_size'),
|
1220
|
-
'max': self.safe_number(market, 'base_max_size'),
|
1221
|
-
},
|
1222
|
-
'price': {
|
1223
|
-
'min': None,
|
1224
|
-
'max': None,
|
1225
|
-
},
|
1226
|
-
'cost': {
|
1227
|
-
'min': self.safe_number(market, 'quote_min_size'),
|
1228
|
-
'max': self.safe_number(market, 'quote_max_size'),
|
1229
|
-
},
|
1745
|
+
'amount': {
|
1746
|
+
'min': self.safe_number(market, 'base_min_size'),
|
1747
|
+
'max': self.safe_number(market, 'base_max_size'),
|
1230
1748
|
},
|
1231
|
-
'
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1749
|
+
'price': {
|
1750
|
+
'min': None,
|
1751
|
+
'max': None,
|
1752
|
+
},
|
1753
|
+
'cost': {
|
1754
|
+
'min': self.safe_number(market, 'quote_min_size'),
|
1755
|
+
'max': self.safe_number(market, 'quote_max_size'),
|
1756
|
+
},
|
1757
|
+
},
|
1758
|
+
'created': None,
|
1759
|
+
'info': market,
|
1760
|
+
})
|
1235
1761
|
|
1236
1762
|
def fetch_currencies_from_cache(self, params={}):
|
1237
1763
|
options = self.safe_dict(self.options, 'fetchCurrencies', {})
|
@@ -1278,11 +1804,13 @@ class coinbase(Exchange, ImplicitAPI):
|
|
1278
1804
|
})
|
1279
1805
|
return self.safe_dict(self.options, 'fetchCurrencies', {})
|
1280
1806
|
|
1281
|
-
def fetch_currencies(self, params={}):
|
1807
|
+
def fetch_currencies(self, params={}) -> Currencies:
|
1282
1808
|
"""
|
1283
1809
|
fetches all available currencies on an exchange
|
1284
|
-
|
1285
|
-
|
1810
|
+
|
1811
|
+
https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-currencies#get-fiat-currencies
|
1812
|
+
https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-exchange-rates#get-exchange-rates
|
1813
|
+
|
1286
1814
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1287
1815
|
:returns dict: an associative dictionary of currencies
|
1288
1816
|
"""
|
@@ -1325,9 +1853,9 @@ class coinbase(Exchange, ImplicitAPI):
|
|
1325
1853
|
# }
|
1326
1854
|
# }
|
1327
1855
|
#
|
1328
|
-
result = {}
|
1329
|
-
networks = {}
|
1330
|
-
networksById = {}
|
1856
|
+
result: dict = {}
|
1857
|
+
networks: dict = {}
|
1858
|
+
networksById: dict = {}
|
1331
1859
|
for i in range(0, len(currencies)):
|
1332
1860
|
currency = currencies[i]
|
1333
1861
|
assetId = self.safe_string(currency, 'asset_id')
|
@@ -1369,10 +1897,13 @@ class coinbase(Exchange, ImplicitAPI):
|
|
1369
1897
|
def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
|
1370
1898
|
"""
|
1371
1899
|
fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
|
1372
|
-
|
1373
|
-
|
1900
|
+
|
1901
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getproducts
|
1902
|
+
https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-exchange-rates#get-exchange-rates
|
1903
|
+
|
1374
1904
|
:param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
|
1375
1905
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1906
|
+
:param boolean [params.usePrivate]: use private endpoint for fetching tickers
|
1376
1907
|
:returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
|
1377
1908
|
"""
|
1378
1909
|
method = self.safe_string(self.options, 'fetchTickers', 'fetchTickersV3')
|
@@ -1383,7 +1914,7 @@ class coinbase(Exchange, ImplicitAPI):
|
|
1383
1914
|
def fetch_tickers_v2(self, symbols: Strings = None, params={}):
|
1384
1915
|
self.load_markets()
|
1385
1916
|
symbols = self.market_symbols(symbols)
|
1386
|
-
request = {
|
1917
|
+
request: dict = {
|
1387
1918
|
# 'currency': 'USD',
|
1388
1919
|
}
|
1389
1920
|
response = self.v2PublicGetExchangeRates(self.extend(request, params))
|
@@ -1402,7 +1933,7 @@ class coinbase(Exchange, ImplicitAPI):
|
|
1402
1933
|
data = self.safe_dict(response, 'data', {})
|
1403
1934
|
rates = self.safe_dict(data, 'rates', {})
|
1404
1935
|
quoteId = self.safe_string(data, 'currency')
|
1405
|
-
result = {}
|
1936
|
+
result: dict = {}
|
1406
1937
|
baseIds = list(rates.keys())
|
1407
1938
|
delimiter = '-'
|
1408
1939
|
for i in range(0, len(baseIds)):
|
@@ -1416,10 +1947,20 @@ class coinbase(Exchange, ImplicitAPI):
|
|
1416
1947
|
def fetch_tickers_v3(self, symbols: Strings = None, params={}):
|
1417
1948
|
self.load_markets()
|
1418
1949
|
symbols = self.market_symbols(symbols)
|
1419
|
-
request = {}
|
1950
|
+
request: dict = {}
|
1420
1951
|
if symbols is not None:
|
1421
1952
|
request['product_ids'] = self.market_ids(symbols)
|
1422
|
-
|
1953
|
+
marketType = None
|
1954
|
+
marketType, params = self.handle_market_type_and_params('fetchTickers', self.get_market_from_symbols(symbols), params, 'default')
|
1955
|
+
if marketType is not None and marketType != 'default':
|
1956
|
+
request['product_type'] = 'FUTURE' if (marketType == 'swap') else 'SPOT'
|
1957
|
+
response = None
|
1958
|
+
usePrivate = False
|
1959
|
+
usePrivate, params = self.handle_option_and_params(params, 'fetchTickers', 'usePrivate', False)
|
1960
|
+
if usePrivate:
|
1961
|
+
response = self.v3PrivateGetBrokerageProducts(self.extend(request, params))
|
1962
|
+
else:
|
1963
|
+
response = self.v3PublicGetBrokerageMarketProducts(self.extend(request, params))
|
1423
1964
|
#
|
1424
1965
|
# {
|
1425
1966
|
# "products": [
|
@@ -1458,7 +1999,7 @@ class coinbase(Exchange, ImplicitAPI):
|
|
1458
1999
|
# }
|
1459
2000
|
#
|
1460
2001
|
data = self.safe_list(response, 'products', [])
|
1461
|
-
result = {}
|
2002
|
+
result: dict = {}
|
1462
2003
|
for i in range(0, len(data)):
|
1463
2004
|
entry = data[i]
|
1464
2005
|
marketId = self.safe_string(entry, 'product_id')
|
@@ -1470,12 +2011,15 @@ class coinbase(Exchange, ImplicitAPI):
|
|
1470
2011
|
def fetch_ticker(self, symbol: str, params={}) -> Ticker:
|
1471
2012
|
"""
|
1472
2013
|
fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
1473
|
-
|
1474
|
-
|
1475
|
-
|
1476
|
-
|
2014
|
+
|
2015
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getmarkettrades
|
2016
|
+
https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-prices#get-spot-price
|
2017
|
+
https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-prices#get-buy-price
|
2018
|
+
https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-prices#get-sell-price
|
2019
|
+
|
1477
2020
|
:param str symbol: unified symbol of the market to fetch the ticker for
|
1478
2021
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2022
|
+
:param boolean [params.usePrivate]: whether to use the private endpoint for fetching the ticker
|
1479
2023
|
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
1480
2024
|
"""
|
1481
2025
|
method = self.safe_string(self.options, 'fetchTicker', 'fetchTickerV3')
|
@@ -1504,7 +2048,7 @@ class coinbase(Exchange, ImplicitAPI):
|
|
1504
2048
|
spotData = self.safe_dict(spot, 'data', {})
|
1505
2049
|
askData = self.safe_dict(ask, 'data', {})
|
1506
2050
|
bidData = self.safe_dict(bid, 'data', {})
|
1507
|
-
bidAskLast = {
|
2051
|
+
bidAskLast: dict = {
|
1508
2052
|
'bid': self.safe_number(bidData, 'amount'),
|
1509
2053
|
'ask': self.safe_number(askData, 'amount'),
|
1510
2054
|
'price': self.safe_number(spotData, 'amount'),
|
@@ -1514,11 +2058,17 @@ class coinbase(Exchange, ImplicitAPI):
|
|
1514
2058
|
def fetch_ticker_v3(self, symbol: str, params={}):
|
1515
2059
|
self.load_markets()
|
1516
2060
|
market = self.market(symbol)
|
1517
|
-
request = {
|
2061
|
+
request: dict = {
|
1518
2062
|
'product_id': market['id'],
|
1519
2063
|
'limit': 1,
|
1520
2064
|
}
|
1521
|
-
|
2065
|
+
usePrivate = False
|
2066
|
+
usePrivate, params = self.handle_option_and_params(params, 'fetchTicker', 'usePrivate', False)
|
2067
|
+
response = None
|
2068
|
+
if usePrivate:
|
2069
|
+
response = self.v3PrivateGetBrokerageProductsProductIdTicker(self.extend(request, params))
|
2070
|
+
else:
|
2071
|
+
response = self.v3PublicGetBrokerageMarketProductsProductIdTicker(self.extend(request, params))
|
1522
2072
|
#
|
1523
2073
|
# {
|
1524
2074
|
# "trades": [
|
@@ -1543,7 +2093,7 @@ class coinbase(Exchange, ImplicitAPI):
|
|
1543
2093
|
ticker['ask'] = self.safe_number(response, 'best_ask')
|
1544
2094
|
return ticker
|
1545
2095
|
|
1546
|
-
def parse_ticker(self, ticker, market: Market = None) -> Ticker:
|
2096
|
+
def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
|
1547
2097
|
#
|
1548
2098
|
# fetchTickerV2
|
1549
2099
|
#
|
@@ -1665,7 +2215,7 @@ class coinbase(Exchange, ImplicitAPI):
|
|
1665
2215
|
balances = self.safe_list_2(response, 'data', 'accounts', [])
|
1666
2216
|
accounts = self.safe_list(params, 'type', self.options['accounts'])
|
1667
2217
|
v3Accounts = self.safe_list(params, 'type', self.options['v3Accounts'])
|
1668
|
-
result = {'info': response}
|
2218
|
+
result: dict = {'info': response}
|
1669
2219
|
for b in range(0, len(balances)):
|
1670
2220
|
balance = balances[b]
|
1671
2221
|
type = self.safe_string(balance, 'type')
|
@@ -1710,25 +2260,32 @@ class coinbase(Exchange, ImplicitAPI):
|
|
1710
2260
|
def fetch_balance(self, params={}) -> Balances:
|
1711
2261
|
"""
|
1712
2262
|
query for balance and get the amount of funds available for trading or funds locked in orders
|
1713
|
-
|
1714
|
-
|
2263
|
+
|
2264
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getaccounts
|
2265
|
+
https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-accounts#list-accounts
|
2266
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getfcmbalancesummary
|
2267
|
+
|
1715
2268
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1716
2269
|
:param boolean [params.v3]: default False, set True to use v3 api endpoint
|
1717
|
-
:param
|
2270
|
+
:param str [params.type]: "spot"(default) or "swap" or "future"
|
2271
|
+
:param int [params.limit]: default 250, maximum number of accounts to return
|
1718
2272
|
:returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
|
1719
2273
|
"""
|
1720
2274
|
self.load_markets()
|
1721
|
-
request = {}
|
2275
|
+
request: dict = {}
|
1722
2276
|
response = None
|
1723
2277
|
isV3 = self.safe_bool(params, 'v3', False)
|
1724
|
-
|
1725
|
-
|
2278
|
+
params = self.omit(params, ['v3'])
|
2279
|
+
marketType = None
|
2280
|
+
marketType, params = self.handle_market_type_and_params('fetchBalance', None, params)
|
1726
2281
|
method = self.safe_string(self.options, 'fetchBalance', 'v3PrivateGetBrokerageAccounts')
|
1727
|
-
if
|
2282
|
+
if marketType == 'future':
|
2283
|
+
response = self.v3PrivateGetBrokerageCfmBalanceSummary(self.extend(request, params))
|
2284
|
+
elif (isV3) or (method == 'v3PrivateGetBrokerageAccounts'):
|
1728
2285
|
request['limit'] = 250
|
1729
2286
|
response = self.v3PrivateGetBrokerageAccounts(self.extend(request, params))
|
1730
2287
|
else:
|
1731
|
-
request['limit'] =
|
2288
|
+
request['limit'] = 250
|
1732
2289
|
response = self.v2PrivateGetAccounts(self.extend(request, params))
|
1733
2290
|
#
|
1734
2291
|
# v2PrivateGetAccounts
|
@@ -1801,19 +2358,21 @@ class coinbase(Exchange, ImplicitAPI):
|
|
1801
2358
|
# "size": 9
|
1802
2359
|
# }
|
1803
2360
|
#
|
1804
|
-
params['type'] =
|
2361
|
+
params['type'] = marketType
|
1805
2362
|
return self.parse_custom_balance(response, params)
|
1806
2363
|
|
1807
|
-
def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
|
2364
|
+
def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[LedgerEntry]:
|
1808
2365
|
"""
|
1809
|
-
|
1810
|
-
|
1811
|
-
|
2366
|
+
Fetch the history of changes, i.e. actions done by the user or operations that altered the balance. Will return staking rewards, and crypto deposits or withdrawals.
|
2367
|
+
|
2368
|
+
https://docs.cdp.coinbase.com/coinbase-app/docs/api-transactions#list-transactions
|
2369
|
+
|
2370
|
+
:param str [code]: unified currency code, default is None
|
1812
2371
|
:param int [since]: timestamp in ms of the earliest ledger entry, default is None
|
1813
|
-
:param int [limit]: max number of ledger
|
2372
|
+
:param int [limit]: max number of ledger entries to return, default is None
|
1814
2373
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1815
|
-
:param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [
|
1816
|
-
:returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger
|
2374
|
+
:param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
|
2375
|
+
:returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger>`
|
1817
2376
|
"""
|
1818
2377
|
self.load_markets()
|
1819
2378
|
paginate = False
|
@@ -1827,27 +2386,29 @@ class coinbase(Exchange, ImplicitAPI):
|
|
1827
2386
|
request, params = self.prepare_account_request_with_currency_code(code, limit, params)
|
1828
2387
|
# for pagination use parameter 'starting_after'
|
1829
2388
|
# the value for the next page can be obtained from the result of the previous call in the 'pagination' field
|
1830
|
-
# eg: instance.
|
2389
|
+
# eg: instance.last_http_response -> pagination.next_starting_after
|
1831
2390
|
response = self.v2PrivateGetAccountsAccountIdTransactions(self.extend(request, params))
|
1832
2391
|
ledger = self.parse_ledger(response['data'], currency, since, limit)
|
1833
2392
|
length = len(ledger)
|
2393
|
+
if length == 0:
|
2394
|
+
return ledger
|
1834
2395
|
lastIndex = length - 1
|
1835
2396
|
last = self.safe_dict(ledger, lastIndex)
|
1836
2397
|
pagination = self.safe_dict(response, 'pagination', {})
|
1837
2398
|
cursor = self.safe_string(pagination, 'next_starting_after')
|
1838
2399
|
if (cursor is not None) and (cursor != ''):
|
1839
|
-
last['next_starting_after'] = cursor
|
2400
|
+
last['info']['next_starting_after'] = cursor
|
1840
2401
|
ledger[lastIndex] = last
|
1841
2402
|
return ledger
|
1842
2403
|
|
1843
2404
|
def parse_ledger_entry_status(self, status):
|
1844
|
-
types = {
|
2405
|
+
types: dict = {
|
1845
2406
|
'completed': 'ok',
|
1846
2407
|
}
|
1847
2408
|
return self.safe_string(types, status, status)
|
1848
2409
|
|
1849
2410
|
def parse_ledger_entry_type(self, type):
|
1850
|
-
types = {
|
2411
|
+
types: dict = {
|
1851
2412
|
'buy': 'trade',
|
1852
2413
|
'sell': 'trade',
|
1853
2414
|
'fiat_deposit': 'transaction',
|
@@ -1860,7 +2421,7 @@ class coinbase(Exchange, ImplicitAPI):
|
|
1860
2421
|
}
|
1861
2422
|
return self.safe_string(types, type, type)
|
1862
2423
|
|
1863
|
-
def parse_ledger_entry(self, item, currency: Currency = None):
|
2424
|
+
def parse_ledger_entry(self, item: dict, currency: Currency = None) -> LedgerEntry:
|
1864
2425
|
#
|
1865
2426
|
# crypto deposit transaction
|
1866
2427
|
#
|
@@ -2114,6 +2675,7 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2114
2675
|
direction = 'in'
|
2115
2676
|
currencyId = self.safe_string(amountInfo, 'currency')
|
2116
2677
|
code = self.safe_currency_code(currencyId, currency)
|
2678
|
+
currency = self.safe_currency(currencyId, currency)
|
2117
2679
|
#
|
2118
2680
|
# the address and txid do not belong to the unified ledger structure
|
2119
2681
|
#
|
@@ -2146,7 +2708,7 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2146
2708
|
numParts = len(parts)
|
2147
2709
|
if numParts > 3:
|
2148
2710
|
accountId = parts[3]
|
2149
|
-
return {
|
2711
|
+
return self.safe_ledger_entry({
|
2150
2712
|
'info': item,
|
2151
2713
|
'id': id,
|
2152
2714
|
'timestamp': timestamp,
|
@@ -2162,11 +2724,11 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2162
2724
|
'after': None,
|
2163
2725
|
'status': status,
|
2164
2726
|
'fee': fee,
|
2165
|
-
}
|
2727
|
+
}, currency)
|
2166
2728
|
|
2167
|
-
def find_account_id(self, code):
|
2729
|
+
def find_account_id(self, code, params={}):
|
2168
2730
|
self.load_markets()
|
2169
|
-
self.load_accounts()
|
2731
|
+
self.load_accounts(False, params)
|
2170
2732
|
for i in range(0, len(self.accounts)):
|
2171
2733
|
account = self.accounts[i]
|
2172
2734
|
if account['code'] == code:
|
@@ -2177,7 +2739,7 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2177
2739
|
accountId = self.safe_string_2(params, 'account_id', 'accountId')
|
2178
2740
|
if accountId is None:
|
2179
2741
|
raise ArgumentsRequired(self.id + ' prepareAccountRequest() method requires an account_id(or accountId) parameter')
|
2180
|
-
request = {
|
2742
|
+
request: dict = {
|
2181
2743
|
'account_id': accountId,
|
2182
2744
|
}
|
2183
2745
|
if limit is not None:
|
@@ -2190,10 +2752,10 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2190
2752
|
if accountId is None:
|
2191
2753
|
if code is None:
|
2192
2754
|
raise ArgumentsRequired(self.id + ' prepareAccountRequestWithCurrencyCode() method requires an account_id(or accountId) parameter OR a currency code argument')
|
2193
|
-
accountId = self.find_account_id(code)
|
2755
|
+
accountId = self.find_account_id(code, params)
|
2194
2756
|
if accountId is None:
|
2195
2757
|
raise ExchangeError(self.id + ' prepareAccountRequestWithCurrencyCode() could not find account id for ' + code)
|
2196
|
-
request = {
|
2758
|
+
request: dict = {
|
2197
2759
|
'account_id': accountId,
|
2198
2760
|
}
|
2199
2761
|
if limit is not None:
|
@@ -2203,7 +2765,9 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2203
2765
|
def create_market_buy_order_with_cost(self, symbol: str, cost: float, params={}):
|
2204
2766
|
"""
|
2205
2767
|
create a market buy order by providing the symbol and cost
|
2206
|
-
|
2768
|
+
|
2769
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_postorder
|
2770
|
+
|
2207
2771
|
:param str symbol: unified symbol of the market to create an order in
|
2208
2772
|
:param float cost: how much you want to trade in units of the quote currency
|
2209
2773
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
@@ -2219,7 +2783,9 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2219
2783
|
def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
|
2220
2784
|
"""
|
2221
2785
|
create a trade order
|
2222
|
-
|
2786
|
+
|
2787
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_postorder
|
2788
|
+
|
2223
2789
|
:param str symbol: unified symbol of the market to create an order in
|
2224
2790
|
:param str type: 'market' or 'limit'
|
2225
2791
|
:param str side: 'buy' or 'sell'
|
@@ -2231,24 +2797,30 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2231
2797
|
:param float [params.stopLossPrice]: price to trigger stop-loss orders
|
2232
2798
|
:param float [params.takeProfitPrice]: price to trigger take-profit orders
|
2233
2799
|
:param bool [params.postOnly]: True or False
|
2234
|
-
:param str [params.timeInForce]: 'GTC', 'IOC', 'GTD' or 'PO'
|
2800
|
+
:param str [params.timeInForce]: 'GTC', 'IOC', 'GTD' or 'PO', 'FOK'
|
2235
2801
|
:param str [params.stop_direction]: 'UNKNOWN_STOP_DIRECTION', 'STOP_DIRECTION_STOP_UP', 'STOP_DIRECTION_STOP_DOWN' the direction the stopPrice is triggered from
|
2236
2802
|
:param str [params.end_time]: '2023-05-25T17:01:05.092Z' for 'GTD' orders
|
2237
2803
|
:param float [params.cost]: *spot market buy only* the quote quantity that can be used alternative for the amount
|
2238
2804
|
:param boolean [params.preview]: default to False, wether to use the test/preview endpoint or not
|
2805
|
+
:param float [params.leverage]: default to 1, the leverage to use for the order
|
2806
|
+
:param str [params.marginMode]: 'cross' or 'isolated'
|
2807
|
+
:param str [params.retail_portfolio_id]: portfolio uid
|
2808
|
+
:param boolean [params.is_max]: Used in conjunction with tradable_balance to indicate the user wants to use their entire tradable balance
|
2809
|
+
:param str [params.tradable_balance]: amount of tradable balance
|
2239
2810
|
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
2240
2811
|
"""
|
2241
2812
|
self.load_markets()
|
2242
2813
|
market = self.market(symbol)
|
2243
|
-
|
2244
|
-
|
2814
|
+
id = self.safe_string(self.options, 'brokerId', 'ccxt')
|
2815
|
+
request: dict = {
|
2816
|
+
'client_order_id': id + '-' + self.uuid(),
|
2245
2817
|
'product_id': market['id'],
|
2246
2818
|
'side': side.upper(),
|
2247
2819
|
}
|
2248
|
-
|
2820
|
+
triggerPrice = self.safe_number_n(params, ['stopPrice', 'stop_price', 'triggerPrice'])
|
2249
2821
|
stopLossPrice = self.safe_number(params, 'stopLossPrice')
|
2250
2822
|
takeProfitPrice = self.safe_number(params, 'takeProfitPrice')
|
2251
|
-
isStop =
|
2823
|
+
isStop = triggerPrice is not None
|
2252
2824
|
isStopLoss = stopLossPrice is not None
|
2253
2825
|
isTakeProfit = takeProfitPrice is not None
|
2254
2826
|
timeInForce = self.safe_string(params, 'timeInForce')
|
@@ -2266,7 +2838,7 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2266
2838
|
'stop_limit_stop_limit_gtd': {
|
2267
2839
|
'base_size': self.amount_to_precision(symbol, amount),
|
2268
2840
|
'limit_price': self.price_to_precision(symbol, price),
|
2269
|
-
'stop_price': self.price_to_precision(symbol,
|
2841
|
+
'stop_price': self.price_to_precision(symbol, triggerPrice),
|
2270
2842
|
'stop_direction': stopDirection,
|
2271
2843
|
'end_time': endTime,
|
2272
2844
|
},
|
@@ -2276,25 +2848,25 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2276
2848
|
'stop_limit_stop_limit_gtc': {
|
2277
2849
|
'base_size': self.amount_to_precision(symbol, amount),
|
2278
2850
|
'limit_price': self.price_to_precision(symbol, price),
|
2279
|
-
'stop_price': self.price_to_precision(symbol,
|
2851
|
+
'stop_price': self.price_to_precision(symbol, triggerPrice),
|
2280
2852
|
'stop_direction': stopDirection,
|
2281
2853
|
},
|
2282
2854
|
}
|
2283
2855
|
elif isStopLoss or isTakeProfit:
|
2284
|
-
|
2856
|
+
tpslPrice = None
|
2285
2857
|
if isStopLoss:
|
2286
2858
|
if stopDirection is None:
|
2287
2859
|
stopDirection = 'STOP_DIRECTION_STOP_UP' if (side == 'buy') else 'STOP_DIRECTION_STOP_DOWN'
|
2288
|
-
|
2860
|
+
tpslPrice = self.price_to_precision(symbol, stopLossPrice)
|
2289
2861
|
else:
|
2290
2862
|
if stopDirection is None:
|
2291
2863
|
stopDirection = 'STOP_DIRECTION_STOP_DOWN' if (side == 'buy') else 'STOP_DIRECTION_STOP_UP'
|
2292
|
-
|
2864
|
+
tpslPrice = self.price_to_precision(symbol, takeProfitPrice)
|
2293
2865
|
request['order_configuration'] = {
|
2294
2866
|
'stop_limit_stop_limit_gtc': {
|
2295
2867
|
'base_size': self.amount_to_precision(symbol, amount),
|
2296
2868
|
'limit_price': self.price_to_precision(symbol, price),
|
2297
|
-
'stop_price':
|
2869
|
+
'stop_price': tpslPrice,
|
2298
2870
|
'stop_direction': stopDirection,
|
2299
2871
|
},
|
2300
2872
|
}
|
@@ -2317,6 +2889,13 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2317
2889
|
'limit_price': self.price_to_precision(symbol, price),
|
2318
2890
|
},
|
2319
2891
|
}
|
2892
|
+
elif timeInForce == 'FOK':
|
2893
|
+
request['order_configuration'] = {
|
2894
|
+
'limit_limit_fok': {
|
2895
|
+
'base_size': self.amount_to_precision(symbol, amount),
|
2896
|
+
'limit_price': self.price_to_precision(symbol, price),
|
2897
|
+
},
|
2898
|
+
}
|
2320
2899
|
else:
|
2321
2900
|
request['order_configuration'] = {
|
2322
2901
|
'limit_limit_gtc': {
|
@@ -2328,7 +2907,7 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2328
2907
|
else:
|
2329
2908
|
if isStop or isStopLoss or isTakeProfit:
|
2330
2909
|
raise NotSupported(self.id + ' createOrder() only stop limit orders are supported')
|
2331
|
-
if side == 'buy':
|
2910
|
+
if market['spot'] and (side == 'buy'):
|
2332
2911
|
total = None
|
2333
2912
|
createMarketBuyOrderRequiresPrice = True
|
2334
2913
|
createMarketBuyOrderRequiresPrice, params = self.handle_option_and_params(params, 'createOrder', 'createMarketBuyOrderRequiresPrice', True)
|
@@ -2357,7 +2936,13 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2357
2936
|
'base_size': self.amount_to_precision(symbol, amount),
|
2358
2937
|
},
|
2359
2938
|
}
|
2360
|
-
|
2939
|
+
marginMode = self.safe_string(params, 'marginMode')
|
2940
|
+
if marginMode is not None:
|
2941
|
+
if marginMode == 'isolated':
|
2942
|
+
request['margin_type'] = 'ISOLATED'
|
2943
|
+
elif marginMode == 'cross':
|
2944
|
+
request['margin_type'] = 'CROSS'
|
2945
|
+
params = self.omit(params, ['timeInForce', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice', 'stopPrice', 'stop_price', 'stopDirection', 'stop_direction', 'clientOrderId', 'postOnly', 'post_only', 'end_time', 'marginMode'])
|
2361
2946
|
preview = self.safe_bool_2(params, 'preview', 'test', False)
|
2362
2947
|
response = None
|
2363
2948
|
if preview:
|
@@ -2415,7 +3000,7 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2415
3000
|
data = self.safe_dict(response, 'success_response', {})
|
2416
3001
|
return self.parse_order(data, market)
|
2417
3002
|
|
2418
|
-
def parse_order(self, order, market: Market = None) -> Order:
|
3003
|
+
def parse_order(self, order: dict, market: Market = None) -> Order:
|
2419
3004
|
#
|
2420
3005
|
# createOrder
|
2421
3006
|
#
|
@@ -2481,7 +3066,7 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2481
3066
|
marketId = self.safe_string(order, 'product_id')
|
2482
3067
|
symbol = self.safe_symbol(marketId, market, '-')
|
2483
3068
|
if symbol is not None:
|
2484
|
-
market = self.
|
3069
|
+
market = self.safe_market(symbol, market)
|
2485
3070
|
orderConfiguration = self.safe_dict(order, 'order_configuration', {})
|
2486
3071
|
limitGTC = self.safe_dict(orderConfiguration, 'limit_limit_gtc')
|
2487
3072
|
limitGTD = self.safe_dict(orderConfiguration, 'limit_limit_gtd')
|
@@ -2532,7 +3117,6 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2532
3117
|
'postOnly': postOnly,
|
2533
3118
|
'side': self.safe_string_lower(order, 'side'),
|
2534
3119
|
'price': price,
|
2535
|
-
'stopPrice': triggerPrice,
|
2536
3120
|
'triggerPrice': triggerPrice,
|
2537
3121
|
'amount': amount,
|
2538
3122
|
'filled': self.safe_string(order, 'filled_size'),
|
@@ -2547,8 +3131,8 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2547
3131
|
'trades': None,
|
2548
3132
|
}, market)
|
2549
3133
|
|
2550
|
-
def parse_order_status(self, status):
|
2551
|
-
statuses = {
|
3134
|
+
def parse_order_status(self, status: Str):
|
3135
|
+
statuses: dict = {
|
2552
3136
|
'OPEN': 'open',
|
2553
3137
|
'FILLED': 'closed',
|
2554
3138
|
'CANCELLED': 'canceled',
|
@@ -2558,10 +3142,10 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2558
3142
|
}
|
2559
3143
|
return self.safe_string(statuses, status, status)
|
2560
3144
|
|
2561
|
-
def parse_order_type(self, type):
|
3145
|
+
def parse_order_type(self, type: Str):
|
2562
3146
|
if type == 'UNKNOWN_ORDER_TYPE':
|
2563
3147
|
return None
|
2564
|
-
types = {
|
3148
|
+
types: dict = {
|
2565
3149
|
'MARKET': 'market',
|
2566
3150
|
'LIMIT': 'limit',
|
2567
3151
|
'STOP': 'limit',
|
@@ -2569,8 +3153,8 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2569
3153
|
}
|
2570
3154
|
return self.safe_string(types, type, type)
|
2571
3155
|
|
2572
|
-
def parse_time_in_force(self, timeInForce):
|
2573
|
-
timeInForces = {
|
3156
|
+
def parse_time_in_force(self, timeInForce: Str):
|
3157
|
+
timeInForces: dict = {
|
2574
3158
|
'GOOD_UNTIL_CANCELLED': 'GTC',
|
2575
3159
|
'GOOD_UNTIL_DATE_TIME': 'GTD',
|
2576
3160
|
'IMMEDIATE_OR_CANCEL': 'IOC',
|
@@ -2582,7 +3166,9 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2582
3166
|
def cancel_order(self, id: str, symbol: Str = None, params={}):
|
2583
3167
|
"""
|
2584
3168
|
cancels an open order
|
2585
|
-
|
3169
|
+
|
3170
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_cancelorders
|
3171
|
+
|
2586
3172
|
:param str id: order id
|
2587
3173
|
:param str symbol: not used by coinbase cancelOrder()
|
2588
3174
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
@@ -2595,7 +3181,9 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2595
3181
|
def cancel_orders(self, ids, symbol: Str = None, params={}):
|
2596
3182
|
"""
|
2597
3183
|
cancel multiple orders
|
2598
|
-
|
3184
|
+
|
3185
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_cancelorders
|
3186
|
+
|
2599
3187
|
:param str[] ids: order ids
|
2600
3188
|
:param str symbol: not used by coinbase cancelOrders()
|
2601
3189
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
@@ -2605,7 +3193,7 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2605
3193
|
market = None
|
2606
3194
|
if symbol is not None:
|
2607
3195
|
market = self.market(symbol)
|
2608
|
-
request = {
|
3196
|
+
request: dict = {
|
2609
3197
|
'order_ids': ids,
|
2610
3198
|
}
|
2611
3199
|
response = self.v3PrivatePostBrokerageOrdersBatchCancel(self.extend(request, params))
|
@@ -2630,20 +3218,22 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2630
3218
|
def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
|
2631
3219
|
"""
|
2632
3220
|
edit a trade order
|
2633
|
-
|
3221
|
+
|
3222
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_editorder
|
3223
|
+
|
2634
3224
|
:param str id: cancel order id
|
2635
3225
|
:param str symbol: unified symbol of the market to create an order in
|
2636
3226
|
:param str type: 'market' or 'limit'
|
2637
3227
|
:param str side: 'buy' or 'sell'
|
2638
3228
|
:param float amount: how much of currency you want to trade in units of base currency
|
2639
|
-
:param float [price]: the price at which the order is to be
|
3229
|
+
:param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
|
2640
3230
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2641
3231
|
:param boolean [params.preview]: default to False, wether to use the test/preview endpoint or not
|
2642
3232
|
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
2643
3233
|
"""
|
2644
3234
|
self.load_markets()
|
2645
3235
|
market = self.market(symbol)
|
2646
|
-
request = {
|
3236
|
+
request: dict = {
|
2647
3237
|
'order_id': id,
|
2648
3238
|
}
|
2649
3239
|
if amount is not None:
|
@@ -2671,7 +3261,9 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2671
3261
|
def fetch_order(self, id: str, symbol: Str = None, params={}):
|
2672
3262
|
"""
|
2673
3263
|
fetches information on an order made by the user
|
2674
|
-
|
3264
|
+
|
3265
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_gethistoricalorder
|
3266
|
+
|
2675
3267
|
:param str id: the order id
|
2676
3268
|
:param str symbol: unified market symbol that the order was made in
|
2677
3269
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
@@ -2681,7 +3273,7 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2681
3273
|
market = None
|
2682
3274
|
if symbol is not None:
|
2683
3275
|
market = self.market(symbol)
|
2684
|
-
request = {
|
3276
|
+
request: dict = {
|
2685
3277
|
'order_id': id,
|
2686
3278
|
}
|
2687
3279
|
response = self.v3PrivateGetBrokerageOrdersHistoricalOrderId(self.extend(request, params))
|
@@ -2730,7 +3322,9 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2730
3322
|
def fetch_orders(self, symbol: Str = None, since: Int = None, limit: Int = 100, params={}) -> List[Order]:
|
2731
3323
|
"""
|
2732
3324
|
fetches information on multiple orders made by the user
|
2733
|
-
|
3325
|
+
|
3326
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_gethistoricalorders
|
3327
|
+
|
2734
3328
|
:param str symbol: unified market symbol that the orders were made in
|
2735
3329
|
:param int [since]: the earliest time in ms to fetch orders
|
2736
3330
|
:param int [limit]: the maximum number of order structures to retrieve
|
@@ -2743,20 +3337,20 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2743
3337
|
paginate = False
|
2744
3338
|
paginate, params = self.handle_option_and_params(params, 'fetchOrders', 'paginate')
|
2745
3339
|
if paginate:
|
2746
|
-
return self.fetch_paginated_call_cursor('fetchOrders', symbol, since, limit, params, 'cursor', 'cursor', None,
|
3340
|
+
return self.fetch_paginated_call_cursor('fetchOrders', symbol, since, limit, params, 'cursor', 'cursor', None, 1000)
|
2747
3341
|
market = None
|
2748
3342
|
if symbol is not None:
|
2749
3343
|
market = self.market(symbol)
|
2750
|
-
request = {}
|
3344
|
+
request: dict = {}
|
2751
3345
|
if market is not None:
|
2752
3346
|
request['product_id'] = market['id']
|
2753
3347
|
if limit is not None:
|
2754
3348
|
request['limit'] = limit
|
2755
3349
|
if since is not None:
|
2756
3350
|
request['start_date'] = self.iso8601(since)
|
2757
|
-
until = self.safe_integer_n(params, ['until'
|
3351
|
+
until = self.safe_integer_n(params, ['until'])
|
2758
3352
|
if until is not None:
|
2759
|
-
params = self.omit(params, ['until'
|
3353
|
+
params = self.omit(params, ['until'])
|
2760
3354
|
request['end_date'] = self.iso8601(until)
|
2761
3355
|
response = self.v3PrivateGetBrokerageOrdersHistoricalBatch(self.extend(request, params))
|
2762
3356
|
#
|
@@ -2814,7 +3408,7 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2814
3408
|
market = None
|
2815
3409
|
if symbol is not None:
|
2816
3410
|
market = self.market(symbol)
|
2817
|
-
request = {
|
3411
|
+
request: dict = {
|
2818
3412
|
'order_status': status,
|
2819
3413
|
}
|
2820
3414
|
if market is not None:
|
@@ -2824,9 +3418,9 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2824
3418
|
request['limit'] = limit
|
2825
3419
|
if since is not None:
|
2826
3420
|
request['start_date'] = self.iso8601(since)
|
2827
|
-
until = self.safe_integer_n(params, ['until'
|
3421
|
+
until = self.safe_integer_n(params, ['until'])
|
2828
3422
|
if until is not None:
|
2829
|
-
params = self.omit(params, ['until'
|
3423
|
+
params = self.omit(params, ['until'])
|
2830
3424
|
request['end_date'] = self.iso8601(until)
|
2831
3425
|
response = self.v3PrivateGetBrokerageOrdersHistoricalBatch(self.extend(request, params))
|
2832
3426
|
#
|
@@ -2882,7 +3476,9 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2882
3476
|
def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
2883
3477
|
"""
|
2884
3478
|
fetches information on all currently open orders
|
2885
|
-
|
3479
|
+
|
3480
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_gethistoricalorders
|
3481
|
+
|
2886
3482
|
:param str symbol: unified market symbol of the orders
|
2887
3483
|
:param int [since]: timestamp in ms of the earliest order, default is None
|
2888
3484
|
:param int [limit]: the maximum number of open order structures to retrieve
|
@@ -2901,7 +3497,9 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2901
3497
|
def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
2902
3498
|
"""
|
2903
3499
|
fetches information on multiple closed orders made by the user
|
2904
|
-
|
3500
|
+
|
3501
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_gethistoricalorders
|
3502
|
+
|
2905
3503
|
:param str symbol: unified market symbol of the orders
|
2906
3504
|
:param int [since]: timestamp in ms of the earliest order, default is None
|
2907
3505
|
:param int [limit]: the maximum number of closed order structures to retrieve
|
@@ -2920,7 +3518,9 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2920
3518
|
def fetch_canceled_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
2921
3519
|
"""
|
2922
3520
|
fetches information on multiple canceled orders made by the user
|
2923
|
-
|
3521
|
+
|
3522
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_gethistoricalorders
|
3523
|
+
|
2924
3524
|
:param str symbol: unified market symbol of the orders
|
2925
3525
|
:param int [since]: timestamp in ms of the earliest order, default is None
|
2926
3526
|
:param int [limit]: the maximum number of canceled order structures to retrieve
|
@@ -2932,7 +3532,9 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2932
3532
|
def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
|
2933
3533
|
"""
|
2934
3534
|
fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
2935
|
-
|
3535
|
+
|
3536
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getpubliccandles
|
3537
|
+
|
2936
3538
|
:param str symbol: unified symbol of the market to fetch OHLCV data for
|
2937
3539
|
:param str timeframe: the length of time each candle represents
|
2938
3540
|
:param int [since]: timestamp in ms of the earliest candle to fetch
|
@@ -2940,6 +3542,7 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2940
3542
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2941
3543
|
:param int [params.until]: the latest time in ms to fetch trades for
|
2942
3544
|
:param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
|
3545
|
+
:param boolean [params.usePrivate]: default False, when True will use the private endpoint to fetch the candles
|
2943
3546
|
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
2944
3547
|
"""
|
2945
3548
|
self.load_markets()
|
@@ -2950,12 +3553,12 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2950
3553
|
if paginate:
|
2951
3554
|
return self.fetch_paginated_call_deterministic('fetchOHLCV', symbol, since, limit, timeframe, params, maxLimit - 1)
|
2952
3555
|
market = self.market(symbol)
|
2953
|
-
request = {
|
3556
|
+
request: dict = {
|
2954
3557
|
'product_id': market['id'],
|
2955
3558
|
'granularity': self.safe_string(self.timeframes, timeframe, timeframe),
|
2956
3559
|
}
|
2957
|
-
until = self.safe_integer_n(params, ['until', '
|
2958
|
-
params = self.omit(params, ['until'
|
3560
|
+
until = self.safe_integer_n(params, ['until', 'end'])
|
3561
|
+
params = self.omit(params, ['until'])
|
2959
3562
|
duration = self.parse_timeframe(timeframe)
|
2960
3563
|
requestedDuration = limit * duration
|
2961
3564
|
sinceString = None
|
@@ -2965,12 +3568,18 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2965
3568
|
now = str(self.seconds())
|
2966
3569
|
sinceString = Precise.string_sub(now, str(requestedDuration))
|
2967
3570
|
request['start'] = sinceString
|
2968
|
-
|
2969
|
-
|
3571
|
+
if until is not None:
|
3572
|
+
request['end'] = self.number_to_string(self.parse_to_int(until / 1000))
|
3573
|
+
else:
|
2970
3574
|
# 300 candles max
|
2971
|
-
|
2972
|
-
|
2973
|
-
|
3575
|
+
request['end'] = Precise.string_add(sinceString, str(requestedDuration))
|
3576
|
+
response = None
|
3577
|
+
usePrivate = False
|
3578
|
+
usePrivate, params = self.handle_option_and_params(params, 'fetchOHLCV', 'usePrivate', False)
|
3579
|
+
if usePrivate:
|
3580
|
+
response = self.v3PrivateGetBrokerageProductsProductIdCandles(self.extend(request, params))
|
3581
|
+
else:
|
3582
|
+
response = self.v3PublicGetBrokerageMarketProductsProductIdCandles(self.extend(request, params))
|
2974
3583
|
#
|
2975
3584
|
# {
|
2976
3585
|
# "candles": [
|
@@ -3013,16 +3622,19 @@ class coinbase(Exchange, ImplicitAPI):
|
|
3013
3622
|
def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
3014
3623
|
"""
|
3015
3624
|
get the list of most recent trades for a particular symbol
|
3016
|
-
|
3625
|
+
|
3626
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getpublicmarkettrades
|
3627
|
+
|
3017
3628
|
:param str symbol: unified market symbol of the trades
|
3018
3629
|
:param int [since]: not used by coinbase fetchTrades
|
3019
3630
|
:param int [limit]: the maximum number of trade structures to fetch
|
3020
3631
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
3632
|
+
:param boolean [params.usePrivate]: default False, when True will use the private endpoint to fetch the trades
|
3021
3633
|
:returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
3022
3634
|
"""
|
3023
3635
|
self.load_markets()
|
3024
3636
|
market = self.market(symbol)
|
3025
|
-
request = {
|
3637
|
+
request: dict = {
|
3026
3638
|
'product_id': market['id'],
|
3027
3639
|
}
|
3028
3640
|
if since is not None:
|
@@ -3035,7 +3647,13 @@ class coinbase(Exchange, ImplicitAPI):
|
|
3035
3647
|
request['end'] = self.number_to_string(self.parse_to_int(until / 1000))
|
3036
3648
|
elif since is not None:
|
3037
3649
|
raise ArgumentsRequired(self.id + ' fetchTrades() requires a `until` parameter when you use `since` argument')
|
3038
|
-
response =
|
3650
|
+
response = None
|
3651
|
+
usePrivate = False
|
3652
|
+
usePrivate, params = self.handle_option_and_params(params, 'fetchTrades', 'usePrivate', False)
|
3653
|
+
if usePrivate:
|
3654
|
+
response = self.v3PrivateGetBrokerageProductsProductIdTicker(self.extend(request, params))
|
3655
|
+
else:
|
3656
|
+
response = self.v3PublicGetBrokerageMarketProductsProductIdTicker(self.extend(request, params))
|
3039
3657
|
#
|
3040
3658
|
# {
|
3041
3659
|
# "trades": [
|
@@ -3058,7 +3676,9 @@ class coinbase(Exchange, ImplicitAPI):
|
|
3058
3676
|
def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
3059
3677
|
"""
|
3060
3678
|
fetch all trades made by the user
|
3061
|
-
|
3679
|
+
|
3680
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getfills
|
3681
|
+
|
3062
3682
|
:param str symbol: unified market symbol of the trades
|
3063
3683
|
:param int [since]: timestamp in ms of the earliest order, default is None
|
3064
3684
|
:param int [limit]: the maximum number of trade structures to fetch
|
@@ -3071,20 +3691,20 @@ class coinbase(Exchange, ImplicitAPI):
|
|
3071
3691
|
paginate = False
|
3072
3692
|
paginate, params = self.handle_option_and_params(params, 'fetchMyTrades', 'paginate')
|
3073
3693
|
if paginate:
|
3074
|
-
return self.fetch_paginated_call_cursor('fetchMyTrades', symbol, since, limit, params, 'cursor', 'cursor', None,
|
3694
|
+
return self.fetch_paginated_call_cursor('fetchMyTrades', symbol, since, limit, params, 'cursor', 'cursor', None, 250)
|
3075
3695
|
market = None
|
3076
3696
|
if symbol is not None:
|
3077
3697
|
market = self.market(symbol)
|
3078
|
-
request = {}
|
3698
|
+
request: dict = {}
|
3079
3699
|
if market is not None:
|
3080
3700
|
request['product_id'] = market['id']
|
3081
3701
|
if limit is not None:
|
3082
3702
|
request['limit'] = limit
|
3083
3703
|
if since is not None:
|
3084
3704
|
request['start_sequence_timestamp'] = self.iso8601(since)
|
3085
|
-
until = self.safe_integer_n(params, ['until'
|
3705
|
+
until = self.safe_integer_n(params, ['until'])
|
3086
3706
|
if until is not None:
|
3087
|
-
params = self.omit(params, ['until'
|
3707
|
+
params = self.omit(params, ['until'])
|
3088
3708
|
request['end_sequence_timestamp'] = self.iso8601(until)
|
3089
3709
|
response = self.v3PrivateGetBrokerageOrdersHistoricalFills(self.extend(request, params))
|
3090
3710
|
#
|
@@ -3121,20 +3741,29 @@ class coinbase(Exchange, ImplicitAPI):
|
|
3121
3741
|
def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
|
3122
3742
|
"""
|
3123
3743
|
fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
3124
|
-
|
3744
|
+
|
3745
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getpublicproductbook
|
3746
|
+
|
3125
3747
|
:param str symbol: unified symbol of the market to fetch the order book for
|
3126
3748
|
:param int [limit]: the maximum amount of order book entries to return
|
3127
3749
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
3750
|
+
:param boolean [params.usePrivate]: default False, when True will use the private endpoint to fetch the order book
|
3128
3751
|
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
3129
3752
|
"""
|
3130
3753
|
self.load_markets()
|
3131
3754
|
market = self.market(symbol)
|
3132
|
-
request = {
|
3755
|
+
request: dict = {
|
3133
3756
|
'product_id': market['id'],
|
3134
3757
|
}
|
3135
3758
|
if limit is not None:
|
3136
3759
|
request['limit'] = limit
|
3137
|
-
response =
|
3760
|
+
response = None
|
3761
|
+
usePrivate = False
|
3762
|
+
usePrivate, params = self.handle_option_and_params(params, 'fetchOrderBook', 'usePrivate', False)
|
3763
|
+
if usePrivate:
|
3764
|
+
response = self.v3PrivateGetBrokerageProductBook(self.extend(request, params))
|
3765
|
+
else:
|
3766
|
+
response = self.v3PublicGetBrokerageMarketProductBook(self.extend(request, params))
|
3138
3767
|
#
|
3139
3768
|
# {
|
3140
3769
|
# "pricebook": {
|
@@ -3163,14 +3792,16 @@ class coinbase(Exchange, ImplicitAPI):
|
|
3163
3792
|
def fetch_bids_asks(self, symbols: Strings = None, params={}):
|
3164
3793
|
"""
|
3165
3794
|
fetches the bid and ask price and volume for multiple markets
|
3166
|
-
|
3795
|
+
|
3796
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getbestbidask
|
3797
|
+
|
3167
3798
|
:param str[] [symbols]: unified symbols of the markets to fetch the bids and asks for, all markets are returned if not assigned
|
3168
3799
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
3169
3800
|
:returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
|
3170
3801
|
"""
|
3171
3802
|
self.load_markets()
|
3172
3803
|
symbols = self.market_symbols(symbols)
|
3173
|
-
request = {}
|
3804
|
+
request: dict = {}
|
3174
3805
|
if symbols is not None:
|
3175
3806
|
request['product_ids'] = self.market_ids(symbols)
|
3176
3807
|
response = self.v3PrivateGetBrokerageBestBidAsk(self.extend(request, params))
|
@@ -3199,10 +3830,12 @@ class coinbase(Exchange, ImplicitAPI):
|
|
3199
3830
|
tickers = self.safe_list(response, 'pricebooks', [])
|
3200
3831
|
return self.parse_tickers(tickers, symbols)
|
3201
3832
|
|
3202
|
-
def withdraw(self, code: str, amount: float, address, tag=None, params={}):
|
3833
|
+
def withdraw(self, code: str, amount: float, address: str, tag=None, params={}) -> Transaction:
|
3203
3834
|
"""
|
3204
3835
|
make a withdrawal
|
3205
|
-
|
3836
|
+
|
3837
|
+
https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-transactions#send-money
|
3838
|
+
|
3206
3839
|
:param str code: unified currency code
|
3207
3840
|
:param float amount: the amount to withdraw
|
3208
3841
|
:param str address: the address to withdraw to
|
@@ -3219,10 +3852,10 @@ class coinbase(Exchange, ImplicitAPI):
|
|
3219
3852
|
if accountId is None:
|
3220
3853
|
if code is None:
|
3221
3854
|
raise ArgumentsRequired(self.id + ' withdraw() requires an account_id(or accountId) parameter OR a currency code argument')
|
3222
|
-
accountId = self.find_account_id(code)
|
3855
|
+
accountId = self.find_account_id(code, params)
|
3223
3856
|
if accountId is None:
|
3224
3857
|
raise ExchangeError(self.id + ' withdraw() could not find account id for ' + code)
|
3225
|
-
request = {
|
3858
|
+
request: dict = {
|
3226
3859
|
'account_id': accountId,
|
3227
3860
|
'type': 'send',
|
3228
3861
|
'to': address,
|
@@ -3287,10 +3920,12 @@ class coinbase(Exchange, ImplicitAPI):
|
|
3287
3920
|
data = self.safe_dict(response, 'data', {})
|
3288
3921
|
return self.parse_transaction(data, currency)
|
3289
3922
|
|
3290
|
-
def fetch_deposit_addresses_by_network(self, code: str, params={}):
|
3923
|
+
def fetch_deposit_addresses_by_network(self, code: str, params={}) -> List[DepositAddress]:
|
3291
3924
|
"""
|
3292
3925
|
fetch the deposit address for a currency associated with self account
|
3293
|
-
|
3926
|
+
|
3927
|
+
https://docs.cloud.coinbase.com/exchange/reference/exchangerestapi_postcoinbaseaccountaddresses
|
3928
|
+
|
3294
3929
|
:param str code: unified currency code
|
3295
3930
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
3296
3931
|
:returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
|
@@ -3359,7 +3994,7 @@ class coinbase(Exchange, ImplicitAPI):
|
|
3359
3994
|
addressStructures = self.parse_deposit_addresses(data, None, False)
|
3360
3995
|
return self.index_by(addressStructures, 'network')
|
3361
3996
|
|
3362
|
-
def parse_deposit_address(self, depositAddress, currency: Currency = None):
|
3997
|
+
def parse_deposit_address(self, depositAddress, currency: Currency = None) -> DepositAddress:
|
3363
3998
|
#
|
3364
3999
|
# {
|
3365
4000
|
# id: '64ceb5f1-5fa2-5310-a4ff-9fd46271003d',
|
@@ -3414,15 +4049,17 @@ class coinbase(Exchange, ImplicitAPI):
|
|
3414
4049
|
return {
|
3415
4050
|
'info': depositAddress,
|
3416
4051
|
'currency': self.safe_currency_code(marketId, currency),
|
4052
|
+
'network': self.network_id_to_code(networkId, code),
|
3417
4053
|
'address': address,
|
3418
4054
|
'tag': self.safe_string(addressInfo, 'destination_tag'),
|
3419
|
-
'network': self.network_id_to_code(networkId, code),
|
3420
4055
|
}
|
3421
4056
|
|
3422
4057
|
def deposit(self, code: str, amount: float, id: str, params={}):
|
3423
4058
|
"""
|
3424
4059
|
make a deposit
|
3425
|
-
|
4060
|
+
|
4061
|
+
https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-deposits#deposit-funds
|
4062
|
+
|
3426
4063
|
:param str code: unified currency code
|
3427
4064
|
:param float amount: the amount to deposit
|
3428
4065
|
:param str id: the payment method id to be used for the deposit, can be retrieved from v2PrivateGetPaymentMethods
|
@@ -3436,10 +4073,10 @@ class coinbase(Exchange, ImplicitAPI):
|
|
3436
4073
|
if accountId is None:
|
3437
4074
|
if code is None:
|
3438
4075
|
raise ArgumentsRequired(self.id + ' deposit() requires an account_id(or accountId) parameter OR a currency code argument')
|
3439
|
-
accountId = self.find_account_id(code)
|
4076
|
+
accountId = self.find_account_id(code, params)
|
3440
4077
|
if accountId is None:
|
3441
4078
|
raise ExchangeError(self.id + ' deposit() could not find account id for ' + code)
|
3442
|
-
request = {
|
4079
|
+
request: dict = {
|
3443
4080
|
'account_id': accountId,
|
3444
4081
|
'amount': self.number_to_string(amount),
|
3445
4082
|
'currency': code.upper(), # need to use code in case depositing USD etc.
|
@@ -3488,7 +4125,9 @@ class coinbase(Exchange, ImplicitAPI):
|
|
3488
4125
|
def fetch_deposit(self, id: str, code: Str = None, params={}):
|
3489
4126
|
"""
|
3490
4127
|
fetch information on a deposit, fiat only, for crypto transactions use fetchLedger
|
3491
|
-
|
4128
|
+
|
4129
|
+
https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-deposits#show-deposit
|
4130
|
+
|
3492
4131
|
:param str id: deposit id
|
3493
4132
|
:param str [code]: unified currency code
|
3494
4133
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
@@ -3501,10 +4140,10 @@ class coinbase(Exchange, ImplicitAPI):
|
|
3501
4140
|
if accountId is None:
|
3502
4141
|
if code is None:
|
3503
4142
|
raise ArgumentsRequired(self.id + ' fetchDeposit() requires an account_id(or accountId) parameter OR a currency code argument')
|
3504
|
-
accountId = self.find_account_id(code)
|
4143
|
+
accountId = self.find_account_id(code, params)
|
3505
4144
|
if accountId is None:
|
3506
4145
|
raise ExchangeError(self.id + ' fetchDeposit() could not find account id for ' + code)
|
3507
|
-
request = {
|
4146
|
+
request: dict = {
|
3508
4147
|
'account_id': accountId,
|
3509
4148
|
'deposit_id': id,
|
3510
4149
|
}
|
@@ -3548,6 +4187,508 @@ class coinbase(Exchange, ImplicitAPI):
|
|
3548
4187
|
data = self.safe_dict(response, 'data', {})
|
3549
4188
|
return self.parse_transaction(data)
|
3550
4189
|
|
4190
|
+
def fetch_deposit_method_ids(self, params={}):
|
4191
|
+
"""
|
4192
|
+
fetch the deposit id for a fiat currency associated with self account
|
4193
|
+
|
4194
|
+
https://docs.cdp.coinbase.com/advanced-trade/reference/retailbrokerageapi_getpaymentmethods
|
4195
|
+
|
4196
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
4197
|
+
:returns dict: an array of `deposit id structures <https://docs.ccxt.com/#/?id=deposit-id-structure>`
|
4198
|
+
"""
|
4199
|
+
self.load_markets()
|
4200
|
+
response = self.v3PrivateGetBrokeragePaymentMethods(params)
|
4201
|
+
#
|
4202
|
+
# {
|
4203
|
+
# "payment_methods": [
|
4204
|
+
# {
|
4205
|
+
# "id": "21b39a5d-f7b46876fb2e",
|
4206
|
+
# "type": "COINBASE_FIAT_ACCOUNT",
|
4207
|
+
# "name": "CAD Wallet",
|
4208
|
+
# "currency": "CAD",
|
4209
|
+
# "verified": True,
|
4210
|
+
# "allow_buy": False,
|
4211
|
+
# "allow_sell": True,
|
4212
|
+
# "allow_deposit": False,
|
4213
|
+
# "allow_withdraw": False,
|
4214
|
+
# "created_at": "2023-06-29T19:58:46Z",
|
4215
|
+
# "updated_at": "2023-10-30T20:25:01Z"
|
4216
|
+
# }
|
4217
|
+
# ]
|
4218
|
+
# }
|
4219
|
+
#
|
4220
|
+
result = self.safe_list(response, 'payment_methods', [])
|
4221
|
+
return self.parse_deposit_method_ids(result)
|
4222
|
+
|
4223
|
+
def fetch_deposit_method_id(self, id: str, params={}):
|
4224
|
+
"""
|
4225
|
+
fetch the deposit id for a fiat currency associated with self account
|
4226
|
+
|
4227
|
+
https://docs.cdp.coinbase.com/advanced-trade/reference/retailbrokerageapi_getpaymentmethod
|
4228
|
+
|
4229
|
+
:param str id: the deposit payment method id
|
4230
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
4231
|
+
:returns dict: a `deposit id structure <https://docs.ccxt.com/#/?id=deposit-id-structure>`
|
4232
|
+
"""
|
4233
|
+
self.load_markets()
|
4234
|
+
request: dict = {
|
4235
|
+
'payment_method_id': id,
|
4236
|
+
}
|
4237
|
+
response = self.v3PrivateGetBrokeragePaymentMethodsPaymentMethodId(self.extend(request, params))
|
4238
|
+
#
|
4239
|
+
# {
|
4240
|
+
# "payment_method": {
|
4241
|
+
# "id": "21b39a5d-f7b46876fb2e",
|
4242
|
+
# "type": "COINBASE_FIAT_ACCOUNT",
|
4243
|
+
# "name": "CAD Wallet",
|
4244
|
+
# "currency": "CAD",
|
4245
|
+
# "verified": True,
|
4246
|
+
# "allow_buy": False,
|
4247
|
+
# "allow_sell": True,
|
4248
|
+
# "allow_deposit": False,
|
4249
|
+
# "allow_withdraw": False,
|
4250
|
+
# "created_at": "2023-06-29T19:58:46Z",
|
4251
|
+
# "updated_at": "2023-10-30T20:25:01Z"
|
4252
|
+
# }
|
4253
|
+
# }
|
4254
|
+
#
|
4255
|
+
result = self.safe_dict(response, 'payment_method', {})
|
4256
|
+
return self.parse_deposit_method_id(result)
|
4257
|
+
|
4258
|
+
def parse_deposit_method_ids(self, ids, params={}):
|
4259
|
+
result = []
|
4260
|
+
for i in range(0, len(ids)):
|
4261
|
+
id = self.extend(self.parse_deposit_method_id(ids[i]), params)
|
4262
|
+
result.append(id)
|
4263
|
+
return result
|
4264
|
+
|
4265
|
+
def parse_deposit_method_id(self, depositId):
|
4266
|
+
return {
|
4267
|
+
'info': depositId,
|
4268
|
+
'id': self.safe_string(depositId, 'id'),
|
4269
|
+
'currency': self.safe_string(depositId, 'currency'),
|
4270
|
+
'verified': self.safe_bool(depositId, 'verified'),
|
4271
|
+
'tag': self.safe_string(depositId, 'name'),
|
4272
|
+
}
|
4273
|
+
|
4274
|
+
def fetch_convert_quote(self, fromCode: str, toCode: str, amount: Num = None, params={}) -> Conversion:
|
4275
|
+
"""
|
4276
|
+
fetch a quote for converting from one currency to another
|
4277
|
+
|
4278
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_createconvertquote
|
4279
|
+
|
4280
|
+
:param str fromCode: the currency that you want to sell and convert from
|
4281
|
+
:param str toCode: the currency that you want to buy and convert into
|
4282
|
+
:param float [amount]: how much you want to trade in units of the from currency
|
4283
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
4284
|
+
:param dict [params.trade_incentive_metadata]: an object to fill in user incentive data
|
4285
|
+
:param str [params.trade_incentive_metadata.user_incentive_id]: the id of the incentive
|
4286
|
+
:param str [params.trade_incentive_metadata.code_val]: the code value of the incentive
|
4287
|
+
:returns dict: a `conversion structure <https://docs.ccxt.com/#/?id=conversion-structure>`
|
4288
|
+
"""
|
4289
|
+
self.load_markets()
|
4290
|
+
request: dict = {
|
4291
|
+
'from_account': fromCode,
|
4292
|
+
'to_account': toCode,
|
4293
|
+
'amount': self.number_to_string(amount),
|
4294
|
+
}
|
4295
|
+
response = self.v3PrivatePostBrokerageConvertQuote(self.extend(request, params))
|
4296
|
+
data = self.safe_dict(response, 'trade', {})
|
4297
|
+
return self.parse_conversion(data)
|
4298
|
+
|
4299
|
+
def create_convert_trade(self, id: str, fromCode: str, toCode: str, amount: Num = None, params={}) -> Conversion:
|
4300
|
+
"""
|
4301
|
+
convert from one currency to another
|
4302
|
+
|
4303
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_commitconverttrade
|
4304
|
+
|
4305
|
+
:param str id: the id of the trade that you want to make
|
4306
|
+
:param str fromCode: the currency that you want to sell and convert from
|
4307
|
+
:param str toCode: the currency that you want to buy and convert into
|
4308
|
+
:param float [amount]: how much you want to trade in units of the from currency
|
4309
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
4310
|
+
:returns dict: a `conversion structure <https://docs.ccxt.com/#/?id=conversion-structure>`
|
4311
|
+
"""
|
4312
|
+
self.load_markets()
|
4313
|
+
request: dict = {
|
4314
|
+
'trade_id': id,
|
4315
|
+
'from_account': fromCode,
|
4316
|
+
'to_account': toCode,
|
4317
|
+
}
|
4318
|
+
response = self.v3PrivatePostBrokerageConvertTradeTradeId(self.extend(request, params))
|
4319
|
+
data = self.safe_dict(response, 'trade', {})
|
4320
|
+
return self.parse_conversion(data)
|
4321
|
+
|
4322
|
+
def fetch_convert_trade(self, id: str, code: Str = None, params={}) -> Conversion:
|
4323
|
+
"""
|
4324
|
+
fetch the data for a conversion trade
|
4325
|
+
|
4326
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getconverttrade
|
4327
|
+
|
4328
|
+
:param str id: the id of the trade that you want to commit
|
4329
|
+
:param str code: the unified currency code that was converted from
|
4330
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
4331
|
+
:param strng params['toCode']: the unified currency code that was converted into
|
4332
|
+
:returns dict: a `conversion structure <https://docs.ccxt.com/#/?id=conversion-structure>`
|
4333
|
+
"""
|
4334
|
+
self.load_markets()
|
4335
|
+
if code is None:
|
4336
|
+
raise ArgumentsRequired(self.id + ' fetchConvertTrade() requires a code argument')
|
4337
|
+
toCode = self.safe_string(params, 'toCode')
|
4338
|
+
if toCode is None:
|
4339
|
+
raise ArgumentsRequired(self.id + ' fetchConvertTrade() requires a toCode parameter')
|
4340
|
+
params = self.omit(params, 'toCode')
|
4341
|
+
request: dict = {
|
4342
|
+
'trade_id': id,
|
4343
|
+
'from_account': code,
|
4344
|
+
'to_account': toCode,
|
4345
|
+
}
|
4346
|
+
response = self.v3PrivateGetBrokerageConvertTradeTradeId(self.extend(request, params))
|
4347
|
+
data = self.safe_dict(response, 'trade', {})
|
4348
|
+
return self.parse_conversion(data)
|
4349
|
+
|
4350
|
+
def parse_conversion(self, conversion: dict, fromCurrency: Currency = None, toCurrency: Currency = None) -> Conversion:
|
4351
|
+
fromCoin = self.safe_string(conversion, 'source_currency')
|
4352
|
+
fromCode = self.safe_currency_code(fromCoin, fromCurrency)
|
4353
|
+
to = self.safe_string(conversion, 'target_currency')
|
4354
|
+
toCode = self.safe_currency_code(to, toCurrency)
|
4355
|
+
fromAmountStructure = self.safe_dict(conversion, 'user_entered_amount')
|
4356
|
+
feeStructure = self.safe_dict(conversion, 'total_fee')
|
4357
|
+
feeAmountStructure = self.safe_dict(feeStructure, 'amount')
|
4358
|
+
return {
|
4359
|
+
'info': conversion,
|
4360
|
+
'timestamp': None,
|
4361
|
+
'datetime': None,
|
4362
|
+
'id': self.safe_string(conversion, 'id'),
|
4363
|
+
'fromCurrency': fromCode,
|
4364
|
+
'fromAmount': self.safe_number(fromAmountStructure, 'value'),
|
4365
|
+
'toCurrency': toCode,
|
4366
|
+
'toAmount': None,
|
4367
|
+
'price': None,
|
4368
|
+
'fee': self.safe_number(feeAmountStructure, 'value'),
|
4369
|
+
}
|
4370
|
+
|
4371
|
+
def close_position(self, symbol: str, side: OrderSide = None, params={}) -> Order:
|
4372
|
+
"""
|
4373
|
+
*futures only* closes open positions for a market
|
4374
|
+
|
4375
|
+
https://coinbase-api.github.io/docs/#/en-us/swapV2/trade-api.html#One-Click%20Close%20All%20Positions
|
4376
|
+
|
4377
|
+
:param str symbol: Unified CCXT market symbol
|
4378
|
+
:param str [side]: not used by coinbase
|
4379
|
+
:param dict [params]: extra parameters specific to the coinbase api endpoint
|
4380
|
+
@param {str} params.clientOrderId *mandatory* the client order id of the position to close
|
4381
|
+
:param float [params.size]: the size of the position to close, optional
|
4382
|
+
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
4383
|
+
"""
|
4384
|
+
self.load_markets()
|
4385
|
+
market = self.market(symbol)
|
4386
|
+
if not market['future']:
|
4387
|
+
raise NotSupported(self.id + ' closePosition() only supported for futures markets')
|
4388
|
+
clientOrderId = self.safe_string_2(params, 'client_order_id', 'clientOrderId')
|
4389
|
+
params = self.omit(params, 'clientOrderId')
|
4390
|
+
request: dict = {
|
4391
|
+
'product_id': market['id'],
|
4392
|
+
}
|
4393
|
+
if clientOrderId is None:
|
4394
|
+
raise ArgumentsRequired(self.id + ' closePosition() requires a clientOrderId parameter')
|
4395
|
+
request['client_order_id'] = clientOrderId
|
4396
|
+
response = self.v3PrivatePostBrokerageOrdersClosePosition(self.extend(request, params))
|
4397
|
+
order = self.safe_dict(response, 'success_response', {})
|
4398
|
+
return self.parse_order(order)
|
4399
|
+
|
4400
|
+
def fetch_positions(self, symbols: Strings = None, params={}):
|
4401
|
+
"""
|
4402
|
+
fetch all open positions
|
4403
|
+
|
4404
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getfcmpositions
|
4405
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getintxpositions
|
4406
|
+
|
4407
|
+
:param str[] [symbols]: list of unified market symbols
|
4408
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
4409
|
+
:param str [params.portfolio]: the portfolio UUID to fetch positions for
|
4410
|
+
:returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
|
4411
|
+
"""
|
4412
|
+
self.load_markets()
|
4413
|
+
symbols = self.market_symbols(symbols)
|
4414
|
+
market = None
|
4415
|
+
if symbols is not None:
|
4416
|
+
market = self.market(symbols[0])
|
4417
|
+
type = None
|
4418
|
+
type, params = self.handle_market_type_and_params('fetchPositions', market, params)
|
4419
|
+
response = None
|
4420
|
+
if type == 'future':
|
4421
|
+
response = self.v3PrivateGetBrokerageCfmPositions(params)
|
4422
|
+
else:
|
4423
|
+
portfolio = None
|
4424
|
+
portfolio, params = self.handle_option_and_params(params, 'fetchPositions', 'portfolio')
|
4425
|
+
if portfolio is None:
|
4426
|
+
raise ArgumentsRequired(self.id + ' fetchPositions() requires a "portfolio" value in params(eg: dbcb91e7-2bc9-515), or set.options["portfolio"]. You can get a list of portfolios with fetchPortfolios()')
|
4427
|
+
request: dict = {
|
4428
|
+
'portfolio_uuid': portfolio,
|
4429
|
+
}
|
4430
|
+
response = self.v3PrivateGetBrokerageIntxPositionsPortfolioUuid(self.extend(request, params))
|
4431
|
+
positions = self.safe_list(response, 'positions', [])
|
4432
|
+
return self.parse_positions(positions, symbols)
|
4433
|
+
|
4434
|
+
def fetch_position(self, symbol: str, params={}):
|
4435
|
+
"""
|
4436
|
+
fetch data on a single open contract trade position
|
4437
|
+
|
4438
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getintxposition
|
4439
|
+
https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getfcmposition
|
4440
|
+
|
4441
|
+
:param str symbol: unified market symbol of the market the position is held in, default is None
|
4442
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
4443
|
+
:param str [params.product_id]: *futures only* the product id of the position to fetch, required for futures markets only
|
4444
|
+
:param str [params.portfolio]: *perpetual/swaps only* the portfolio UUID to fetch the position for, required for perpetual/swaps markets only
|
4445
|
+
:returns dict: a `position structure <https://docs.ccxt.com/#/?id=position-structure>`
|
4446
|
+
"""
|
4447
|
+
self.load_markets()
|
4448
|
+
market = self.market(symbol)
|
4449
|
+
response = None
|
4450
|
+
if market['future']:
|
4451
|
+
productId = self.safe_string(market, 'product_id')
|
4452
|
+
if productId is None:
|
4453
|
+
raise ArgumentsRequired(self.id + ' fetchPosition() requires a "product_id" in params')
|
4454
|
+
futureRequest: dict = {
|
4455
|
+
'product_id': productId,
|
4456
|
+
}
|
4457
|
+
response = self.v3PrivateGetBrokerageCfmPositionsProductId(self.extend(futureRequest, params))
|
4458
|
+
else:
|
4459
|
+
portfolio = None
|
4460
|
+
portfolio, params = self.handle_option_and_params(params, 'fetchPositions', 'portfolio')
|
4461
|
+
if portfolio is None:
|
4462
|
+
raise ArgumentsRequired(self.id + ' fetchPosition() requires a "portfolio" value in params(eg: dbcb91e7-2bc9-515), or set.options["portfolio"]. You can get a list of portfolios with fetchPortfolios()')
|
4463
|
+
request: dict = {
|
4464
|
+
'symbol': market['id'],
|
4465
|
+
'portfolio_uuid': portfolio,
|
4466
|
+
}
|
4467
|
+
response = self.v3PrivateGetBrokerageIntxPositionsPortfolioUuidSymbol(self.extend(request, params))
|
4468
|
+
position = self.safe_dict(response, 'position', {})
|
4469
|
+
return self.parse_position(position, market)
|
4470
|
+
|
4471
|
+
def parse_position(self, position: dict, market: Market = None):
|
4472
|
+
#
|
4473
|
+
# {
|
4474
|
+
# "product_id": "1r4njf84-0-0",
|
4475
|
+
# "product_uuid": "cd34c18b-3665-4ed8-9305-3db277c49fc5",
|
4476
|
+
# "symbol": "ADA-PERP-INTX",
|
4477
|
+
# "vwap": {
|
4478
|
+
# "value": "0.6171",
|
4479
|
+
# "currency": "USDC"
|
4480
|
+
# },
|
4481
|
+
# "position_side": "POSITION_SIDE_LONG",
|
4482
|
+
# "net_size": "20",
|
4483
|
+
# "buy_order_size": "0",
|
4484
|
+
# "sell_order_size": "0",
|
4485
|
+
# "im_contribution": "0.1",
|
4486
|
+
# "unrealized_pnl": {
|
4487
|
+
# "value": "0.074",
|
4488
|
+
# "currency": "USDC"
|
4489
|
+
# },
|
4490
|
+
# "mark_price": {
|
4491
|
+
# "value": "0.6208",
|
4492
|
+
# "currency": "USDC"
|
4493
|
+
# },
|
4494
|
+
# "liquidation_price": {
|
4495
|
+
# "value": "0",
|
4496
|
+
# "currency": "USDC"
|
4497
|
+
# },
|
4498
|
+
# "leverage": "1",
|
4499
|
+
# "im_notional": {
|
4500
|
+
# "value": "12.342",
|
4501
|
+
# "currency": "USDC"
|
4502
|
+
# },
|
4503
|
+
# "mm_notional": {
|
4504
|
+
# "value": "0.814572",
|
4505
|
+
# "currency": "USDC"
|
4506
|
+
# },
|
4507
|
+
# "position_notional": {
|
4508
|
+
# "value": "12.342",
|
4509
|
+
# "currency": "USDC"
|
4510
|
+
# },
|
4511
|
+
# "margin_type": "MARGIN_TYPE_CROSS",
|
4512
|
+
# "liquidation_buffer": "19.677828",
|
4513
|
+
# "liquidation_percentage": "4689.3506",
|
4514
|
+
# "portfolio_summary": {
|
4515
|
+
# "portfolio_uuid": "018ebd63-1f6d-7c8e-ada9-0761c5a2235f",
|
4516
|
+
# "collateral": "20.4184",
|
4517
|
+
# "position_notional": "12.342",
|
4518
|
+
# "open_position_notional": "12.342",
|
4519
|
+
# "pending_fees": "0",
|
4520
|
+
# "borrow": "0",
|
4521
|
+
# "accrued_interest": "0",
|
4522
|
+
# "rolling_debt": "0",
|
4523
|
+
# "portfolio_initial_margin": "0.1",
|
4524
|
+
# "portfolio_im_notional": {
|
4525
|
+
# "value": "12.342",
|
4526
|
+
# "currency": "USDC"
|
4527
|
+
# },
|
4528
|
+
# "portfolio_maintenance_margin": "0.066",
|
4529
|
+
# "portfolio_mm_notional": {
|
4530
|
+
# "value": "0.814572",
|
4531
|
+
# "currency": "USDC"
|
4532
|
+
# },
|
4533
|
+
# "liquidation_percentage": "4689.3506",
|
4534
|
+
# "liquidation_buffer": "19.677828",
|
4535
|
+
# "margin_type": "MARGIN_TYPE_CROSS",
|
4536
|
+
# "margin_flags": "PORTFOLIO_MARGIN_FLAGS_UNSPECIFIED",
|
4537
|
+
# "liquidation_status": "PORTFOLIO_LIQUIDATION_STATUS_NOT_LIQUIDATING",
|
4538
|
+
# "unrealized_pnl": {
|
4539
|
+
# "value": "0.074",
|
4540
|
+
# "currency": "USDC"
|
4541
|
+
# },
|
4542
|
+
# "buying_power": {
|
4543
|
+
# "value": "8.1504",
|
4544
|
+
# "currency": "USDC"
|
4545
|
+
# },
|
4546
|
+
# "total_balance": {
|
4547
|
+
# "value": "20.4924",
|
4548
|
+
# "currency": "USDC"
|
4549
|
+
# },
|
4550
|
+
# "max_withdrawal": {
|
4551
|
+
# "value": "8.0764",
|
4552
|
+
# "currency": "USDC"
|
4553
|
+
# }
|
4554
|
+
# },
|
4555
|
+
# "entry_vwap": {
|
4556
|
+
# "value": "0.6091",
|
4557
|
+
# "currency": "USDC"
|
4558
|
+
# }
|
4559
|
+
# }
|
4560
|
+
#
|
4561
|
+
marketId = self.safe_string(position, 'symbol', '')
|
4562
|
+
market = self.safe_market(marketId, market)
|
4563
|
+
rawMargin = self.safe_string(position, 'margin_type')
|
4564
|
+
marginMode = None
|
4565
|
+
if rawMargin is not None:
|
4566
|
+
marginMode = 'cross' if (rawMargin == 'MARGIN_TYPE_CROSS') else 'isolated'
|
4567
|
+
notionalObject = self.safe_dict(position, 'position_notional', {})
|
4568
|
+
positionSide = self.safe_string(position, 'position_side')
|
4569
|
+
side = 'long' if (positionSide == 'POSITION_SIDE_LONG') else 'short'
|
4570
|
+
unrealizedPNLObject = self.safe_dict(position, 'unrealized_pnl', {})
|
4571
|
+
liquidationPriceObject = self.safe_dict(position, 'liquidation_price', {})
|
4572
|
+
liquidationPrice = self.safe_number(liquidationPriceObject, 'value')
|
4573
|
+
vwapObject = self.safe_dict(position, 'vwap', {})
|
4574
|
+
summaryObject = self.safe_dict(position, 'portfolio_summary', {})
|
4575
|
+
return self.safe_position({
|
4576
|
+
'info': position,
|
4577
|
+
'id': self.safe_string(position, 'product_id'),
|
4578
|
+
'symbol': self.safe_symbol(marketId, market),
|
4579
|
+
'notional': self.safe_number(notionalObject, 'value'),
|
4580
|
+
'marginMode': marginMode,
|
4581
|
+
'liquidationPrice': liquidationPrice,
|
4582
|
+
'entryPrice': self.safe_number(vwapObject, 'value'),
|
4583
|
+
'unrealizedPnl': self.safe_number(unrealizedPNLObject, 'value'),
|
4584
|
+
'realizedPnl': None,
|
4585
|
+
'percentage': None,
|
4586
|
+
'contracts': self.safe_number(position, 'net_size'),
|
4587
|
+
'contractSize': market['contractSize'],
|
4588
|
+
'markPrice': None,
|
4589
|
+
'lastPrice': None,
|
4590
|
+
'side': side,
|
4591
|
+
'hedged': None,
|
4592
|
+
'timestamp': None,
|
4593
|
+
'datetime': None,
|
4594
|
+
'lastUpdateTimestamp': None,
|
4595
|
+
'maintenanceMargin': None,
|
4596
|
+
'maintenanceMarginPercentage': None,
|
4597
|
+
'collateral': self.safe_number(summaryObject, 'collateral'),
|
4598
|
+
'initialMargin': None,
|
4599
|
+
'initialMarginPercentage': None,
|
4600
|
+
'leverage': self.safe_number(position, 'leverage'),
|
4601
|
+
'marginRatio': None,
|
4602
|
+
'stopLossPrice': None,
|
4603
|
+
'takeProfitPrice': None,
|
4604
|
+
})
|
4605
|
+
|
4606
|
+
def fetch_trading_fees(self, params={}) -> TradingFees:
|
4607
|
+
"""
|
4608
|
+
|
4609
|
+
https://docs.cdp.coinbase.com/advanced-trade/reference/retailbrokerageapi_gettransactionsummary/
|
4610
|
+
|
4611
|
+
fetch the trading fees for multiple markets
|
4612
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
4613
|
+
:param str [params.type]: 'spot' or 'swap'
|
4614
|
+
:returns dict: a dictionary of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>` indexed by market symbols
|
4615
|
+
"""
|
4616
|
+
self.load_markets()
|
4617
|
+
type = None
|
4618
|
+
type, params = self.handle_market_type_and_params('fetchTradingFees', None, params)
|
4619
|
+
isSpot = (type == 'spot')
|
4620
|
+
productType = 'SPOT' if isSpot else 'FUTURE'
|
4621
|
+
request: dict = {
|
4622
|
+
'product_type': productType,
|
4623
|
+
}
|
4624
|
+
response = self.v3PrivateGetBrokerageTransactionSummary(self.extend(request, params))
|
4625
|
+
#
|
4626
|
+
# {
|
4627
|
+
# total_volume: '0',
|
4628
|
+
# total_fees: '0',
|
4629
|
+
# fee_tier: {
|
4630
|
+
# pricing_tier: 'Advanced 1',
|
4631
|
+
# usd_from: '0',
|
4632
|
+
# usd_to: '1000',
|
4633
|
+
# taker_fee_rate: '0.008',
|
4634
|
+
# maker_fee_rate: '0.006',
|
4635
|
+
# aop_from: '',
|
4636
|
+
# aop_to: ''
|
4637
|
+
# },
|
4638
|
+
# margin_rate: null,
|
4639
|
+
# goods_and_services_tax: null,
|
4640
|
+
# advanced_trade_only_volume: '0',
|
4641
|
+
# advanced_trade_only_fees: '0',
|
4642
|
+
# coinbase_pro_volume: '0',
|
4643
|
+
# coinbase_pro_fees: '0',
|
4644
|
+
# total_balance: '',
|
4645
|
+
# has_promo_fee: False
|
4646
|
+
# }
|
4647
|
+
#
|
4648
|
+
data = self.safe_dict(response, 'fee_tier', {})
|
4649
|
+
taker_fee = self.safe_number(data, 'taker_fee_rate')
|
4650
|
+
marker_fee = self.safe_number(data, 'maker_fee_rate')
|
4651
|
+
result: dict = {}
|
4652
|
+
for i in range(0, len(self.symbols)):
|
4653
|
+
symbol = self.symbols[i]
|
4654
|
+
market = self.market(symbol)
|
4655
|
+
if (isSpot and market['spot']) or (not isSpot and not market['spot']):
|
4656
|
+
result[symbol] = {
|
4657
|
+
'info': response,
|
4658
|
+
'symbol': symbol,
|
4659
|
+
'maker': taker_fee,
|
4660
|
+
'taker': marker_fee,
|
4661
|
+
'percentage': True,
|
4662
|
+
}
|
4663
|
+
return result
|
4664
|
+
|
4665
|
+
def create_auth_token(self, seconds: Int, method: Str = None, url: Str = None):
|
4666
|
+
# it may not work for v2
|
4667
|
+
uri = None
|
4668
|
+
if url is not None:
|
4669
|
+
uri = method + ' ' + url.replace('https://', '')
|
4670
|
+
quesPos = uri.find('?')
|
4671
|
+
# Due to we use mb_strpos, quesPos could be False in php. In that case, the quesPos >= 0 is True
|
4672
|
+
# Also it's not possible that the question mark is first character, only check > 0 here.
|
4673
|
+
if quesPos > 0:
|
4674
|
+
uri = uri[0:quesPos]
|
4675
|
+
nonce = self.random_bytes(16)
|
4676
|
+
request: dict = {
|
4677
|
+
'aud': ['retail_rest_api_proxy'],
|
4678
|
+
'iss': 'coinbase-cloud',
|
4679
|
+
'nbf': seconds,
|
4680
|
+
'exp': seconds + 120,
|
4681
|
+
'sub': self.apiKey,
|
4682
|
+
'iat': seconds,
|
4683
|
+
}
|
4684
|
+
if uri is not None:
|
4685
|
+
request['uri'] = uri
|
4686
|
+
token = self.jwt(request, self.encode(self.secret), 'sha256', False, {'kid': self.apiKey, 'nonce': nonce, 'alg': 'ES256'})
|
4687
|
+
return token
|
4688
|
+
|
4689
|
+
def nonce(self):
|
4690
|
+
return self.milliseconds() - self.options['timeDifference']
|
4691
|
+
|
3551
4692
|
def sign(self, path, api=[], method='GET', params={}, headers=None, body=None):
|
3552
4693
|
version = api[0]
|
3553
4694
|
signed = api[1] == 'private'
|
@@ -3562,25 +4703,14 @@ class coinbase(Exchange, ImplicitAPI):
|
|
3562
4703
|
url = self.urls['api']['rest'] + fullPath
|
3563
4704
|
if signed:
|
3564
4705
|
authorization = self.safe_string(self.headers, 'Authorization')
|
4706
|
+
authorizationString = None
|
3565
4707
|
if authorization is not None:
|
3566
|
-
|
3567
|
-
'Authorization': authorization,
|
3568
|
-
'Content-Type': 'application/json',
|
3569
|
-
}
|
3570
|
-
if method != 'GET':
|
3571
|
-
if query:
|
3572
|
-
body = self.json(query)
|
4708
|
+
authorizationString = authorization
|
3573
4709
|
elif self.token and not self.check_required_credentials(False):
|
3574
|
-
|
3575
|
-
'Authorization': 'Bearer ' + self.token,
|
3576
|
-
'Content-Type': 'application/json',
|
3577
|
-
}
|
3578
|
-
if method != 'GET':
|
3579
|
-
if query:
|
3580
|
-
body = self.json(query)
|
4710
|
+
authorizationString = 'Bearer ' + self.token
|
3581
4711
|
else:
|
3582
4712
|
self.check_required_credentials()
|
3583
|
-
|
4713
|
+
seconds = self.seconds()
|
3584
4714
|
payload = ''
|
3585
4715
|
if method != 'GET':
|
3586
4716
|
if query:
|
@@ -3591,20 +4721,57 @@ class coinbase(Exchange, ImplicitAPI):
|
|
3591
4721
|
if query:
|
3592
4722
|
payload += '?' + self.urlencode(query)
|
3593
4723
|
# v3: 'GET' doesn't need payload in the signature. inside url is enough
|
3594
|
-
# https://docs.cloud.coinbase.com/advanced-trade
|
4724
|
+
# https://docs.cloud.coinbase.com/advanced-trade/docs/auth#example-request
|
3595
4725
|
# v2: 'GET' require payload in the signature
|
3596
4726
|
# https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-key-authentication
|
3597
|
-
|
3598
|
-
|
4727
|
+
isCloudAPiKey = (self.apiKey.find('organizations/') >= 0) or (self.secret.startswith('-----BEGIN'))
|
4728
|
+
if isCloudAPiKey:
|
4729
|
+
if self.apiKey.startswith('-----BEGIN'):
|
4730
|
+
raise ArgumentsRequired(self.id + ' apiKey should contain the name(eg: organizations/3b910e93....) and not the public key')
|
4731
|
+
# # it may not work for v2
|
4732
|
+
# uri = method + ' ' + url.replace('https://', '')
|
4733
|
+
# quesPos = uri.find('?')
|
4734
|
+
# # Due to we use mb_strpos, quesPos could be False in php. In that case, the quesPos >= 0 is True
|
4735
|
+
# # Also it's not possible that the question mark is first character, only check > 0 here.
|
4736
|
+
# if quesPos > 0:
|
4737
|
+
# uri = uri[0:quesPos]
|
4738
|
+
# }
|
4739
|
+
# nonce = self.random_bytes(16)
|
4740
|
+
# request: Dict = {
|
4741
|
+
# 'aud': ['retail_rest_api_proxy'],
|
4742
|
+
# 'iss': 'coinbase-cloud',
|
4743
|
+
# 'nbf': seconds,
|
4744
|
+
# 'exp': seconds + 120,
|
4745
|
+
# 'sub': self.apiKey,
|
4746
|
+
# 'uri': uri,
|
4747
|
+
# 'iat': seconds,
|
4748
|
+
# }
|
4749
|
+
token = self.create_auth_token(seconds, method, url)
|
4750
|
+
# token = self.jwt(request, self.encode(self.secret), 'sha256', False, {'kid': self.apiKey, 'nonce': nonce, 'alg': 'ES256'})
|
4751
|
+
authorizationString = 'Bearer ' + token
|
4752
|
+
else:
|
4753
|
+
nonce = self.nonce()
|
4754
|
+
timestamp = self.parse_to_int(nonce / 1000)
|
4755
|
+
timestampString = str(timestamp)
|
4756
|
+
auth = timestampString + method + savedPath + payload
|
4757
|
+
signature = self.hmac(self.encode(auth), self.encode(self.secret), hashlib.sha256)
|
4758
|
+
headers = {
|
4759
|
+
'CB-ACCESS-KEY': self.apiKey,
|
4760
|
+
'CB-ACCESS-SIGN': signature,
|
4761
|
+
'CB-ACCESS-TIMESTAMP': timestampString,
|
4762
|
+
'Content-Type': 'application/json',
|
4763
|
+
}
|
4764
|
+
if authorizationString is not None:
|
3599
4765
|
headers = {
|
3600
|
-
'
|
3601
|
-
'CB-ACCESS-SIGN': signature,
|
3602
|
-
'CB-ACCESS-TIMESTAMP': timestampString,
|
4766
|
+
'Authorization': authorizationString,
|
3603
4767
|
'Content-Type': 'application/json',
|
3604
4768
|
}
|
4769
|
+
if method != 'GET':
|
4770
|
+
if query:
|
4771
|
+
body = self.json(query)
|
3605
4772
|
return {'url': url, 'method': method, 'body': body, 'headers': headers}
|
3606
4773
|
|
3607
|
-
def handle_errors(self, code, reason, url, method, headers, body, response, requestHeaders, requestBody):
|
4774
|
+
def handle_errors(self, code: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
|
3608
4775
|
if response is None:
|
3609
4776
|
return None # fallback to default error handler
|
3610
4777
|
feedback = self.id + ' ' + body
|