ccxt-go/coinbase.go
zhangkun9038@dingtalk.com 1a2ce7046a first add
2025-02-28 10:33:20 +08:00

6142 lines
284 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package ccxt
// PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
// https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
type coinbase struct {
Exchange
}
func NewCoinbaseCore() coinbase {
p := coinbase{}
setDefaults(&p)
return p
}
func (this *coinbase) Describe() interface{} {
return this.DeepExtend(this.Exchange.Describe(), map[string]interface{} {
"id": "coinbase",
"name": "Coinbase Advanced",
"countries": []interface{}{"US"},
"pro": true,
"certified": false,
"rateLimit": 34,
"version": "v2",
"userAgent": GetValue(this.UserAgents, "chrome"),
"headers": map[string]interface{} {
"CB-VERSION": "2018-05-30",
},
"has": map[string]interface{} {
"CORS": true,
"spot": true,
"margin": false,
"swap": false,
"future": false,
"option": false,
"addMargin": false,
"cancelOrder": true,
"cancelOrders": true,
"closeAllPositions": false,
"closePosition": true,
"createConvertTrade": true,
"createDepositAddress": true,
"createLimitBuyOrder": true,
"createLimitSellOrder": true,
"createMarketBuyOrder": true,
"createMarketBuyOrderWithCost": true,
"createMarketOrderWithCost": false,
"createMarketSellOrder": true,
"createMarketSellOrderWithCost": false,
"createOrder": true,
"createPostOnlyOrder": true,
"createReduceOnlyOrder": false,
"createStopLimitOrder": true,
"createStopMarketOrder": false,
"createStopOrder": true,
"deposit": true,
"editOrder": true,
"fetchAccounts": true,
"fetchBalance": true,
"fetchBidsAsks": true,
"fetchBorrowRateHistories": false,
"fetchBorrowRateHistory": false,
"fetchCanceledOrders": true,
"fetchClosedOrders": true,
"fetchConvertQuote": true,
"fetchConvertTrade": true,
"fetchConvertTradeHistory": false,
"fetchCrossBorrowRate": false,
"fetchCrossBorrowRates": false,
"fetchCurrencies": true,
"fetchDeposit": true,
"fetchDepositAddress": "emulated",
"fetchDepositAddresses": false,
"fetchDepositAddressesByNetwork": true,
"fetchDepositMethodId": true,
"fetchDepositMethodIds": true,
"fetchDeposits": true,
"fetchDepositsWithdrawals": true,
"fetchFundingHistory": false,
"fetchFundingRate": false,
"fetchFundingRateHistory": false,
"fetchFundingRates": false,
"fetchIndexOHLCV": false,
"fetchIsolatedBorrowRate": false,
"fetchIsolatedBorrowRates": false,
"fetchL2OrderBook": false,
"fetchLedger": true,
"fetchLeverage": false,
"fetchLeverageTiers": false,
"fetchMarginMode": false,
"fetchMarkets": true,
"fetchMarkOHLCV": false,
"fetchMyBuys": true,
"fetchMySells": true,
"fetchMyTrades": true,
"fetchOHLCV": true,
"fetchOpenInterestHistory": false,
"fetchOpenOrders": true,
"fetchOrder": true,
"fetchOrderBook": true,
"fetchOrders": true,
"fetchPosition": true,
"fetchPositionMode": false,
"fetchPositions": true,
"fetchPositionsRisk": false,
"fetchPremiumIndexOHLCV": false,
"fetchTicker": true,
"fetchTickers": true,
"fetchTime": true,
"fetchTrades": true,
"fetchTradingFee": "emulated",
"fetchTradingFees": true,
"fetchWithdrawals": true,
"reduceMargin": false,
"setLeverage": false,
"setMarginMode": false,
"setPositionMode": false,
"withdraw": true,
},
"urls": map[string]interface{} {
"logo": "https://user-images.githubusercontent.com/1294454/40811661-b6eceae2-653a-11e8-829e-10bfadb078cf.jpg",
"api": map[string]interface{} {
"rest": "https://api.coinbase.com",
},
"www": "https://www.coinbase.com",
"doc": []interface{}{"https://developers.coinbase.com/api/v2", "https://docs.cloud.coinbase.com/advanced-trade/docs/welcome"},
"fees": []interface{}{"https://support.coinbase.com/customer/portal/articles/2109597-buy-sell-bank-transfer-fees", "https://www.coinbase.com/advanced-fees"},
"referral": "https://www.coinbase.com/join/58cbe25a355148797479dbd2",
},
"requiredCredentials": map[string]interface{} {
"apiKey": true,
"secret": true,
},
"api": map[string]interface{} {
"v2": map[string]interface{} {
"public": map[string]interface{} {
"get": map[string]interface{} {
"currencies": 10.6,
"currencies/crypto": 10.6,
"time": 10.6,
"exchange-rates": 10.6,
"users/{user_id}": 10.6,
"prices/{symbol}/buy": 10.6,
"prices/{symbol}/sell": 10.6,
"prices/{symbol}/spot": 10.6,
},
},
"private": map[string]interface{} {
"get": map[string]interface{} {
"accounts": 10.6,
"accounts/{account_id}": 10.6,
"accounts/{account_id}/addresses": 10.6,
"accounts/{account_id}/addresses/{address_id}": 10.6,
"accounts/{account_id}/addresses/{address_id}/transactions": 10.6,
"accounts/{account_id}/transactions": 10.6,
"accounts/{account_id}/transactions/{transaction_id}": 10.6,
"accounts/{account_id}/buys": 10.6,
"accounts/{account_id}/buys/{buy_id}": 10.6,
"accounts/{account_id}/sells": 10.6,
"accounts/{account_id}/sells/{sell_id}": 10.6,
"accounts/{account_id}/deposits": 10.6,
"accounts/{account_id}/deposits/{deposit_id}": 10.6,
"accounts/{account_id}/withdrawals": 10.6,
"accounts/{account_id}/withdrawals/{withdrawal_id}": 10.6,
"payment-methods": 10.6,
"payment-methods/{payment_method_id}": 10.6,
"user": 10.6,
"user/auth": 10.6,
},
"post": map[string]interface{} {
"accounts": 10.6,
"accounts/{account_id}/primary": 10.6,
"accounts/{account_id}/addresses": 10.6,
"accounts/{account_id}/transactions": 10.6,
"accounts/{account_id}/transactions/{transaction_id}/complete": 10.6,
"accounts/{account_id}/transactions/{transaction_id}/resend": 10.6,
"accounts/{account_id}/buys": 10.6,
"accounts/{account_id}/buys/{buy_id}/commit": 10.6,
"accounts/{account_id}/sells": 10.6,
"accounts/{account_id}/sells/{sell_id}/commit": 10.6,
"accounts/{account_id}/deposits": 10.6,
"accounts/{account_id}/deposits/{deposit_id}/commit": 10.6,
"accounts/{account_id}/withdrawals": 10.6,
"accounts/{account_id}/withdrawals/{withdrawal_id}/commit": 10.6,
},
"put": map[string]interface{} {
"accounts/{account_id}": 10.6,
"user": 10.6,
},
"delete": map[string]interface{} {
"accounts/{id}": 10.6,
"accounts/{account_id}/transactions/{transaction_id}": 10.6,
},
},
},
"v3": map[string]interface{} {
"public": map[string]interface{} {
"get": map[string]interface{} {
"brokerage/time": 3,
"brokerage/market/product_book": 3,
"brokerage/market/products": 3,
"brokerage/market/products/{product_id}": 3,
"brokerage/market/products/{product_id}/candles": 3,
"brokerage/market/products/{product_id}/ticker": 3,
},
},
"private": map[string]interface{} {
"get": map[string]interface{} {
"brokerage/accounts": 1,
"brokerage/accounts/{account_uuid}": 1,
"brokerage/orders/historical/batch": 1,
"brokerage/orders/historical/fills": 1,
"brokerage/orders/historical/{order_id}": 1,
"brokerage/products": 3,
"brokerage/products/{product_id}": 3,
"brokerage/products/{product_id}/candles": 3,
"brokerage/products/{product_id}/ticker": 3,
"brokerage/best_bid_ask": 3,
"brokerage/product_book": 3,
"brokerage/transaction_summary": 3,
"brokerage/portfolios": 1,
"brokerage/portfolios/{portfolio_uuid}": 1,
"brokerage/convert/trade/{trade_id}": 1,
"brokerage/cfm/balance_summary": 1,
"brokerage/cfm/positions": 1,
"brokerage/cfm/positions/{product_id}": 1,
"brokerage/cfm/sweeps": 1,
"brokerage/intx/portfolio/{portfolio_uuid}": 1,
"brokerage/intx/positions/{portfolio_uuid}": 1,
"brokerage/intx/positions/{portfolio_uuid}/{symbol}": 1,
"brokerage/payment_methods": 1,
"brokerage/payment_methods/{payment_method_id}": 1,
},
"post": map[string]interface{} {
"brokerage/orders": 1,
"brokerage/orders/batch_cancel": 1,
"brokerage/orders/edit": 1,
"brokerage/orders/edit_preview": 1,
"brokerage/orders/preview": 1,
"brokerage/portfolios": 1,
"brokerage/portfolios/move_funds": 1,
"brokerage/convert/quote": 1,
"brokerage/convert/trade/{trade_id}": 1,
"brokerage/cfm/sweeps/schedule": 1,
"brokerage/intx/allocate": 1,
"brokerage/orders/close_position": 1,
},
"put": map[string]interface{} {
"brokerage/portfolios/{portfolio_uuid}": 1,
},
"delete": map[string]interface{} {
"brokerage/portfolios/{portfolio_uuid}": 1,
"brokerage/cfm/sweeps": 1,
},
},
},
},
"fees": map[string]interface{} {
"trading": map[string]interface{} {
"taker": this.ParseNumber("0.012"),
"maker": this.ParseNumber("0.006"),
"tierBased": true,
"percentage": true,
"tiers": map[string]interface{} {
"taker": []interface{}{[]interface{}{this.ParseNumber("0"), this.ParseNumber("0.006")}, []interface{}{this.ParseNumber("10000"), this.ParseNumber("0.004")}, []interface{}{this.ParseNumber("50000"), this.ParseNumber("0.0025")}, []interface{}{this.ParseNumber("100000"), this.ParseNumber("0.002")}, []interface{}{this.ParseNumber("1000000"), this.ParseNumber("0.0018")}, []interface{}{this.ParseNumber("15000000"), this.ParseNumber("0.0016")}, []interface{}{this.ParseNumber("75000000"), this.ParseNumber("0.0012")}, []interface{}{this.ParseNumber("250000000"), this.ParseNumber("0.0008")}, []interface{}{this.ParseNumber("400000000"), this.ParseNumber("0.0005")}},
"maker": []interface{}{[]interface{}{this.ParseNumber("0"), this.ParseNumber("0.004")}, []interface{}{this.ParseNumber("10000"), this.ParseNumber("0.0025")}, []interface{}{this.ParseNumber("50000"), this.ParseNumber("0.0015")}, []interface{}{this.ParseNumber("100000"), this.ParseNumber("0.001")}, []interface{}{this.ParseNumber("1000000"), this.ParseNumber("0.0008")}, []interface{}{this.ParseNumber("15000000"), this.ParseNumber("0.0006")}, []interface{}{this.ParseNumber("75000000"), this.ParseNumber("0.0003")}, []interface{}{this.ParseNumber("250000000"), this.ParseNumber("0.0")}, []interface{}{this.ParseNumber("400000000"), this.ParseNumber("0.0")}},
},
},
},
"precisionMode": TICK_SIZE,
"exceptions": map[string]interface{} {
"exact": map[string]interface{} {
"two_factor_required": AuthenticationError,
"param_required": ExchangeError,
"validation_error": ExchangeError,
"invalid_request": ExchangeError,
"personal_details_required": AuthenticationError,
"identity_verification_required": AuthenticationError,
"jumio_verification_required": AuthenticationError,
"jumio_face_match_verification_required": AuthenticationError,
"unverified_email": AuthenticationError,
"authentication_error": AuthenticationError,
"invalid_authentication_method": AuthenticationError,
"invalid_token": AuthenticationError,
"revoked_token": AuthenticationError,
"expired_token": AuthenticationError,
"invalid_scope": AuthenticationError,
"not_found": ExchangeError,
"rate_limit_exceeded": RateLimitExceeded,
"internal_server_error": ExchangeError,
"UNSUPPORTED_ORDER_CONFIGURATION": BadRequest,
"INSUFFICIENT_FUND": BadRequest,
"PERMISSION_DENIED": PermissionDenied,
"INVALID_ARGUMENT": BadRequest,
},
"broad": map[string]interface{} {
"request timestamp expired": InvalidNonce,
"order with this orderID was not found": OrderNotFound,
},
},
"timeframes": map[string]interface{} {
"1m": "ONE_MINUTE",
"5m": "FIVE_MINUTE",
"15m": "FIFTEEN_MINUTE",
"30m": "THIRTY_MINUTE",
"1h": "ONE_HOUR",
"2h": "TWO_HOUR",
"6h": "SIX_HOUR",
"1d": "ONE_DAY",
},
"commonCurrencies": map[string]interface{} {
"CGLD": "CELO",
},
"options": map[string]interface{} {
"usePrivate": false,
"brokerId": "ccxt",
"stablePairs": []interface{}{"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"},
"fetchCurrencies": map[string]interface{} {
"expires": 5000,
},
"accounts": []interface{}{"wallet", "fiat"},
"v3Accounts": []interface{}{"ACCOUNT_TYPE_CRYPTO", "ACCOUNT_TYPE_FIAT"},
"networks": map[string]interface{} {
"ERC20": "ethereum",
"XLM": "stellar",
},
"createMarketBuyOrderRequiresPrice": true,
"advanced": true,
"fetchMarkets": "fetchMarketsV3",
"timeDifference": 0,
"adjustForTimeDifference": false,
"fetchTicker": "fetchTickerV3",
"fetchTickers": "fetchTickersV3",
"fetchAccounts": "fetchAccountsV3",
"fetchBalance": "v2PrivateGetAccounts",
"fetchTime": "v2PublicGetTime",
"user_native_currency": "USD",
},
"features": map[string]interface{} {
"default": map[string]interface{} {
"sandbox": false,
"createOrder": map[string]interface{} {
"marginMode": true,
"triggerPrice": true,
"triggerPriceType": nil,
"triggerDirection": true,
"stopLossPrice": true,
"takeProfitPrice": true,
"attachedStopLossTakeProfit": nil,
"timeInForce": map[string]interface{} {
"IOC": true,
"FOK": true,
"PO": true,
"GTD": true,
},
"hedged": false,
"trailing": false,
"leverage": true,
"marketBuyByCost": true,
"marketBuyRequiresPrice": true,
"selfTradePrevention": false,
"iceberg": false,
},
"createOrders": nil,
"fetchMyTrades": map[string]interface{} {
"marginMode": false,
"limit": 3000,
"daysBack": nil,
"untilDays": 10000,
"symbolRequired": false,
},
"fetchOrder": map[string]interface{} {
"marginMode": false,
"trigger": false,
"trailing": false,
"symbolRequired": false,
},
"fetchOpenOrders": map[string]interface{} {
"marginMode": false,
"limit": nil,
"trigger": false,
"trailing": false,
"symbolRequired": false,
},
"fetchOrders": map[string]interface{} {
"marginMode": false,
"limit": nil,
"daysBack": nil,
"untilDays": 10000,
"trigger": false,
"trailing": false,
"symbolRequired": false,
},
"fetchClosedOrders": map[string]interface{} {
"marginMode": false,
"limit": nil,
"daysBack": nil,
"daysBackCanceled": nil,
"untilDays": 10000,
"trigger": false,
"trailing": false,
"symbolRequired": false,
},
"fetchOHLCV": map[string]interface{} {
"limit": 300,
},
},
"spot": map[string]interface{} {
"extends": "default",
},
"swap": map[string]interface{} {
"linear": map[string]interface{} {
"extends": "default",
},
"inverse": nil,
},
"future": map[string]interface{} {
"linear": map[string]interface{} {
"extends": "default",
},
"inverse": nil,
},
},
})
}
/**
* @method
* @name coinbase#fetchTime
* @description fetches the current integer timestamp in milliseconds from the exchange server
* @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-time#http-request
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.method] 'v2PublicGetTime' or 'v3PublicGetBrokerageTime' default is 'v2PublicGetTime'
* @returns {int} the current integer timestamp in milliseconds from the exchange server
*/
func (this *coinbase) FetchTime(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
var defaultMethod interface{} = this.SafeString(this.Options, "fetchTime", "v2PublicGetTime")
var method interface{} = this.SafeString(params, "method", defaultMethod)
params = this.Omit(params, "method")
var response interface{} = nil
if IsTrue(IsEqual(method, "v2PublicGetTime")) {
response = (<-this.V2PublicGetTime(params))
PanicOnError(response)
//
// {
// "data": {
// "epoch": 1589295679,
// "iso": "2020-05-12T15:01:19Z"
// }
// }
//
response = this.SafeDict(response, "data", map[string]interface{} {})
} else {
response = (<-this.V3PublicGetBrokerageTime(params))
PanicOnError(response)
}
ch <- this.SafeTimestamp2(response, "epoch", "epochSeconds")
return nil
}()
return ch
}
/**
* @method
* @name coinbase#fetchAccounts
* @description fetch all the accounts associated with a profile
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getaccounts
* @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-accounts#list-accounts
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
* @returns {object} a dictionary of [account structures]{@link https://docs.ccxt.com/#/?id=account-structure} indexed by the account type
*/
func (this *coinbase) FetchAccounts(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
var method interface{} = this.SafeString(this.Options, "fetchAccounts", "fetchAccountsV3")
if IsTrue(IsEqual(method, "fetchAccountsV3")) {
retRes51919 := (<-this.FetchAccountsV3(params))
PanicOnError(retRes51919)
ch <- retRes51919
return nil
}
retRes52115 := (<-this.FetchAccountsV2(params))
PanicOnError(retRes52115)
ch <- retRes52115
return nil
}()
return ch
}
func (this *coinbase) FetchAccountsV2(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
retRes5258 := (<-this.LoadMarkets())
PanicOnError(retRes5258)
var paginate interface{} = false
paginateparamsVariable := this.HandleOptionAndParams(params, "fetchAccounts", "paginate");
paginate = GetValue(paginateparamsVariable,0);
params = GetValue(paginateparamsVariable,1)
if IsTrue(paginate) {
retRes52919 := (<-this.FetchPaginatedCallCursor("fetchAccounts", nil, nil, nil, params, "next_starting_after", "starting_after", nil, 100))
PanicOnError(retRes52919)
ch <- retRes52919
return nil
}
var request interface{} = map[string]interface{} {
"limit": 100,
}
response:= (<-this.V2PrivateGetAccounts(this.Extend(request, params)))
PanicOnError(response)
//
// {
// "pagination": {
// "ending_before": null,
// "starting_after": null,
// "previous_ending_before": null,
// "next_starting_after": null,
// "limit": 244,
// "order": "desc",
// "previous_uri": null,
// "next_uri": null
// },
// "data": [
// {
// "id": "XLM",
// "name": "XLM Wallet",
// "primary": false,
// "type": "wallet",
// "currency": {
// "code": "XLM",
// "name": "Stellar Lumens",
// "color": "#000000",
// "sort_index": 127,
// "exponent": 7,
// "type": "crypto",
// "address_regex": "^G[A-Z2-7]{55}$",
// "asset_id": "13b83335-5ede-595b-821e-5bcdfa80560f",
// "destination_tag_name": "XLM Memo ID",
// "destination_tag_regex": "^[ -~]{1,28}$"
// },
// "balance": {
// "amount": "0.0000000",
// "currency": "XLM"
// },
// "created_at": null,
// "updated_at": null,
// "resource": "account",
// "resource_path": "/v2/accounts/XLM",
// "allow_deposits": true,
// "allow_withdrawals": true
// },
// ]
// }
//
var data interface{} = this.SafeList(response, "data", []interface{}{})
var pagination interface{} = this.SafeDict(response, "pagination", map[string]interface{} {})
var cursor interface{} = this.SafeString(pagination, "next_starting_after")
var accounts interface{} = this.SafeList(response, "data", []interface{}{})
var length interface{} = GetArrayLength(accounts)
var lastIndex interface{} = Subtract(length, 1)
var last interface{} = this.SafeDict(accounts, lastIndex)
if IsTrue(IsTrue((!IsEqual(cursor, nil))) && IsTrue((!IsEqual(cursor, "")))) {
AddElementToObject(last, "next_starting_after", cursor)
AddElementToObject(accounts, lastIndex, last)
}
ch <- this.ParseAccounts(data, params)
return nil
}()
return ch
}
func (this *coinbase) FetchAccountsV3(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
retRes5948 := (<-this.LoadMarkets())
PanicOnError(retRes5948)
var paginate interface{} = false
paginateparamsVariable := this.HandleOptionAndParams(params, "fetchAccounts", "paginate");
paginate = GetValue(paginateparamsVariable,0);
params = GetValue(paginateparamsVariable,1)
if IsTrue(paginate) {
retRes59819 := (<-this.FetchPaginatedCallCursor("fetchAccounts", nil, nil, nil, params, "cursor", "cursor", nil, 250))
PanicOnError(retRes59819)
ch <- retRes59819
return nil
}
var request interface{} = map[string]interface{} {
"limit": 250,
}
response:= (<-this.V3PrivateGetBrokerageAccounts(this.Extend(request, params)))
PanicOnError(response)
//
// {
// "accounts": [
// {
// "uuid": "11111111-1111-1111-1111-111111111111",
// "name": "USDC Wallet",
// "currency": "USDC",
// "available_balance": {
// "value": "0.0000000000000000",
// "currency": "USDC"
// },
// "default": true,
// "active": true,
// "created_at": "2023-01-04T06:20:06.456Z",
// "updated_at": "2023-01-04T06:20:07.181Z",
// "deleted_at": null,
// "type": "ACCOUNT_TYPE_CRYPTO",
// "ready": false,
// "hold": {
// "value": "0.0000000000000000",
// "currency": "USDC"
// }
// },
// ...
// ],
// "has_next": false,
// "cursor": "",
// "size": 9
// }
//
var accounts interface{} = this.SafeList(response, "accounts", []interface{}{})
var length interface{} = GetArrayLength(accounts)
var lastIndex interface{} = Subtract(length, 1)
var last interface{} = this.SafeDict(accounts, lastIndex)
var cursor interface{} = this.SafeString(response, "cursor")
if IsTrue(IsTrue((!IsEqual(cursor, nil))) && IsTrue((!IsEqual(cursor, "")))) {
AddElementToObject(last, "cursor", cursor)
AddElementToObject(accounts, lastIndex, last)
}
ch <- this.ParseAccounts(accounts, params)
return nil
}()
return ch
}
/**
* @method
* @name coinbase#fetchPortfolios
* @description fetch all the portfolios
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getportfolios
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a dictionary of [account structures]{@link https://docs.ccxt.com/#/?id=account-structure} indexed by the account type
*/
func (this *coinbase) FetchPortfolios(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
response:= (<-this.V3PrivateGetBrokeragePortfolios(params))
PanicOnError(response)
var portfolios interface{} = this.SafeList(response, "portfolios", []interface{}{})
var result interface{} = []interface{}{}
for i := 0; IsLessThan(i, GetArrayLength(portfolios)); i++ {
var portfolio interface{} = GetValue(portfolios, i)
AppendToArray(&result,map[string]interface{} {
"id": this.SafeString(portfolio, "uuid"),
"type": this.SafeString(portfolio, "type"),
"code": nil,
"info": portfolio,
})
}
ch <- result
return nil
}()
return ch
}
func (this *coinbase) ParseAccount(account interface{}) interface{} {
//
// fetchAccountsV2
//
// {
// "id": "XLM",
// "name": "XLM Wallet",
// "primary": false,
// "type": "wallet",
// "currency": {
// "code": "XLM",
// "name": "Stellar Lumens",
// "color": "#000000",
// "sort_index": 127,
// "exponent": 7,
// "type": "crypto",
// "address_regex": "^G[A-Z2-7]{55}$",
// "asset_id": "13b83335-5ede-595b-821e-5bcdfa80560f",
// "destination_tag_name": "XLM Memo ID",
// "destination_tag_regex": "^[ -~]{1,28}$"
// },
// "balance": {
// "amount": "0.0000000",
// "currency": "XLM"
// },
// "created_at": null,
// "updated_at": null,
// "resource": "account",
// "resource_path": "/v2/accounts/XLM",
// "allow_deposits": true,
// "allow_withdrawals": true
// }
//
// fetchAccountsV3
//
// {
// "uuid": "11111111-1111-1111-1111-111111111111",
// "name": "USDC Wallet",
// "currency": "USDC",
// "available_balance": {
// "value": "0.0000000000000000",
// "currency": "USDC"
// },
// "default": true,
// "active": true,
// "created_at": "2023-01-04T06:20:06.456Z",
// "updated_at": "2023-01-04T06:20:07.181Z",
// "deleted_at": null,
// "type": "ACCOUNT_TYPE_CRYPTO",
// "ready": false,
// "hold": {
// "value": "0.0000000000000000",
// "currency": "USDC"
// }
// }
//
var active interface{} = this.SafeBool(account, "active")
var currencyIdV3 interface{} = this.SafeString(account, "currency")
var currency interface{} = this.SafeDict(account, "currency", map[string]interface{} {})
var currencyId interface{} = this.SafeString(currency, "code", currencyIdV3)
var typeV3 interface{} = this.SafeString(account, "name")
var typeV2 interface{} = this.SafeString(account, "type")
var parts interface{} = Split(typeV3, " ")
return map[string]interface{} {
"id": this.SafeString2(account, "id", "uuid"),
"type": Ternary(IsTrue((!IsEqual(active, nil))), this.SafeStringLower(parts, 1), typeV2),
"code": this.SafeCurrencyCode(currencyId),
"info": account,
}
}
/**
* @method
* @name coinbase#createDepositAddress
* @description create a currency deposit address
* @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-addresses#create-address
* @param {string} code unified currency code of the currency for the deposit address
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} an [address structure]{@link https://docs.ccxt.com/#/?id=address-structure}
*/
func (this *coinbase) CreateDepositAddress(code interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
var accountId interface{} = this.SafeString(params, "account_id")
params = this.Omit(params, "account_id")
if IsTrue(IsEqual(accountId, nil)) {
retRes75412 := (<-this.LoadAccounts())
PanicOnError(retRes75412)
for i := 0; IsLessThan(i, GetArrayLength(this.Accounts)); i++ {
var account interface{} = GetValue(this.Accounts, i)
if IsTrue(IsTrue(IsEqual(GetValue(account, "code"), code)) && IsTrue(IsEqual(GetValue(account, "type"), "wallet"))) {
accountId = GetValue(account, "id")
break
}
}
}
if IsTrue(IsEqual(accountId, nil)) {
panic(ExchangeError(Add(Add(Add(this.Id, " createDepositAddress() could not find the account with matching currency code "), code), ", specify an `account_id` extra param to target specific wallet")))
}
var request interface{} = map[string]interface{} {
"account_id": accountId,
}
response:= (<-this.V2PrivatePostAccountsAccountIdAddresses(this.Extend(request, params)))
PanicOnError(response)
//
// {
// "data": {
// "id": "05b1ebbf-9438-5dd4-b297-2ddedc98d0e4",
// "address": "coinbasebase",
// "address_info": {
// "address": "coinbasebase",
// "destination_tag": "287594668"
// },
// "name": null,
// "created_at": "2019-07-01T14:39:29Z",
// "updated_at": "2019-07-01T14:39:29Z",
// "network": "eosio",
// "uri_scheme": "eosio",
// "resource": "address",
// "resource_path": "/v2/accounts/14cfc769-e852-52f3-b831-711c104d194c/addresses/05b1ebbf-9438-5dd4-b297-2ddedc98d0e4",
// "warnings": [
// {
// "title": "Only send EOS (EOS) to this address",
// "details": "Sending any other cryptocurrency will result in permanent loss.",
// "image_url": "https://dynamic-assets.coinbase.com/deaca3d47b10ed4a91a872e9618706eec34081127762d88f2476ac8e99ada4b48525a9565cf2206d18c04053f278f693434af4d4629ca084a9d01b7a286a7e26/asset_icons/1f8489bb280fb0a0fd643c1161312ba49655040e9aaaced5f9ad3eeaf868eadc.png"
// },
// {
// "title": "Both an address and EOS memo are required to receive EOS",
// "details": "If you send funds without an EOS memo or with an incorrect EOS memo, your funds cannot be credited to your account.",
// "image_url": "https://www.coinbase.com/assets/receive-warning-2f3269d83547a7748fb39d6e0c1c393aee26669bfea6b9f12718094a1abff155.png"
// }
// ],
// "warning_title": "Only send EOS (EOS) to this address",
// "warning_details": "Sending any other cryptocurrency will result in permanent loss.",
// "destination_tag": "287594668",
// "deposit_uri": "eosio:coinbasebase?dt=287594668",
// "callback_url": null
// }
// }
//
var data interface{} = this.SafeDict(response, "data", map[string]interface{} {})
var tag interface{} = this.SafeString(data, "destination_tag")
var address interface{} = this.SafeString(data, "address")
ch <- map[string]interface{} {
"currency": code,
"tag": tag,
"address": address,
"info": response,
}
return nil
}()
return ch
}
/**
* @method
* @name coinbase#fetchMySells
* @ignore
* @description fetch sells
* @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-sells#list-sells
* @param {string} symbol not used by coinbase fetchMySells ()
* @param {int} [since] timestamp in ms of the earliest sell, default is undefined
* @param {int} [limit] max number of sells to return, default is undefined
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [list of order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
func (this *coinbase) FetchMySells(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
// v2 did't have an endpoint for all historical trades
symbol := GetArg(optionalArgs, 0, nil)
_ = symbol
since := GetArg(optionalArgs, 1, nil)
_ = since
limit := GetArg(optionalArgs, 2, nil)
_ = limit
params := GetArg(optionalArgs, 3, map[string]interface{} {})
_ = params
var request interface{} = this.PrepareAccountRequest(limit, params)
retRes8328 := (<-this.LoadMarkets())
PanicOnError(retRes8328)
var query interface{} = this.Omit(params, []interface{}{"account_id", "accountId"})
sells:= (<-this.V2PrivateGetAccountsAccountIdSells(this.Extend(request, query)))
PanicOnError(sells)
ch <- this.ParseTrades(GetValue(sells, "data"), nil, since, limit)
return nil
}()
return ch
}
/**
* @method
* @name coinbase#fetchMyBuys
* @ignore
* @description fetch buys
* @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-buys#list-buys
* @param {string} symbol not used by coinbase fetchMyBuys ()
* @param {int} [since] timestamp in ms of the earliest buy, default is undefined
* @param {int} [limit] max number of buys to return, default is undefined
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
func (this *coinbase) FetchMyBuys(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
// v2 did't have an endpoint for all historical trades
symbol := GetArg(optionalArgs, 0, nil)
_ = symbol
since := GetArg(optionalArgs, 1, nil)
_ = since
limit := GetArg(optionalArgs, 2, nil)
_ = limit
params := GetArg(optionalArgs, 3, map[string]interface{} {})
_ = params
var request interface{} = this.PrepareAccountRequest(limit, params)
retRes8538 := (<-this.LoadMarkets())
PanicOnError(retRes8538)
var query interface{} = this.Omit(params, []interface{}{"account_id", "accountId"})
buys:= (<-this.V2PrivateGetAccountsAccountIdBuys(this.Extend(request, query)))
PanicOnError(buys)
ch <- this.ParseTrades(GetValue(buys, "data"), nil, since, limit)
return nil
}()
return ch
}
func (this *coinbase) FetchTransactionsWithMethod(method interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
code := GetArg(optionalArgs, 0, nil)
_ = code
since := GetArg(optionalArgs, 1, nil)
_ = since
limit := GetArg(optionalArgs, 2, nil)
_ = limit
params := GetArg(optionalArgs, 3, map[string]interface{} {})
_ = params
var request interface{} = nil
requestparamsVariable := (<-this.PrepareAccountRequestWithCurrencyCode(code, limit, params));
request = GetValue(requestparamsVariable,0);
params = GetValue(requestparamsVariable,1)
retRes8628 := (<-this.LoadMarkets())
PanicOnError(retRes8628)
response:= (<-this.callDynamically(method, this.Extend(request, params)))
PanicOnError(response)
ch <- this.ParseTransactions(GetValue(response, "data"), nil, since, limit)
return nil
}()
return ch
}
/**
* @method
* @name coinbase#fetchWithdrawals
* @description Fetch all withdrawals made from an account. Won't return crypto withdrawals. Use fetchLedger for those.
* @see https://docs.cdp.coinbase.com/coinbase-app/docs/api-withdrawals#list-withdrawals
* @param {string} code unified currency code
* @param {int} [since] the earliest time in ms to fetch withdrawals for
* @param {int} [limit] the maximum number of withdrawals structures to retrieve
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.currencyType] "fiat" or "crypto"
* @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
*/
func (this *coinbase) FetchWithdrawals(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
code := GetArg(optionalArgs, 0, nil)
_ = code
since := GetArg(optionalArgs, 1, nil)
_ = since
limit := GetArg(optionalArgs, 2, nil)
_ = limit
params := GetArg(optionalArgs, 3, map[string]interface{} {})
_ = params
var currencyType interface{} = nil
currencyTypeparamsVariable := this.HandleOptionAndParams(params, "fetchWithdrawals", "currencyType");
currencyType = GetValue(currencyTypeparamsVariable,0);
params = GetValue(currencyTypeparamsVariable,1)
if IsTrue(IsEqual(currencyType, "crypto")) {
results:= (<-this.FetchTransactionsWithMethod("v2PrivateGetAccountsAccountIdTransactions", code, since, limit, params))
PanicOnError(results)
ch <- this.FilterByArray(results, "type", "withdrawal", false)
return nil
}
retRes88615 := (<-this.FetchTransactionsWithMethod("v2PrivateGetAccountsAccountIdWithdrawals", code, since, limit, params))
PanicOnError(retRes88615)
ch <- retRes88615
return nil
}()
return ch
}
/**
* @method
* @name coinbase#fetchDeposits
* @description Fetch all fiat deposits made to an account. Won't return crypto deposits or staking rewards. Use fetchLedger for those.
* @see https://docs.cdp.coinbase.com/coinbase-app/docs/api-deposits#list-deposits
* @param {string} code unified currency code
* @param {int} [since] the earliest time in ms to fetch deposits for
* @param {int} [limit] the maximum number of deposits structures to retrieve
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.currencyType] "fiat" or "crypto"
* @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
*/
func (this *coinbase) FetchDeposits(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
code := GetArg(optionalArgs, 0, nil)
_ = code
since := GetArg(optionalArgs, 1, nil)
_ = since
limit := GetArg(optionalArgs, 2, nil)
_ = limit
params := GetArg(optionalArgs, 3, map[string]interface{} {})
_ = params
var currencyType interface{} = nil
currencyTypeparamsVariable := this.HandleOptionAndParams(params, "fetchWithdrawals", "currencyType");
currencyType = GetValue(currencyTypeparamsVariable,0);
params = GetValue(currencyTypeparamsVariable,1)
if IsTrue(IsEqual(currencyType, "crypto")) {
results:= (<-this.FetchTransactionsWithMethod("v2PrivateGetAccountsAccountIdTransactions", code, since, limit, params))
PanicOnError(results)
ch <- this.FilterByArray(results, "type", "deposit", false)
return nil
}
retRes90815 := (<-this.FetchTransactionsWithMethod("v2PrivateGetAccountsAccountIdDeposits", code, since, limit, params))
PanicOnError(retRes90815)
ch <- retRes90815
return nil
}()
return ch
}
/**
* @method
* @name coinbase#fetchDepositsWithdrawals
* @description fetch history of deposits and withdrawals
* @see https://docs.cdp.coinbase.com/coinbase-app/docs/api-transactions
* @param {string} [code] unified currency code for the currency of the deposit/withdrawals, default is undefined
* @param {int} [since] timestamp in ms of the earliest deposit/withdrawal, default is undefined
* @param {int} [limit] max number of deposit/withdrawals to return, default = 50, Min: 1, Max: 100
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a list of [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
*/
func (this *coinbase) FetchDepositsWithdrawals(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
code := GetArg(optionalArgs, 0, nil)
_ = code
since := GetArg(optionalArgs, 1, nil)
_ = since
limit := GetArg(optionalArgs, 2, nil)
_ = limit
params := GetArg(optionalArgs, 3, map[string]interface{} {})
_ = params
retRes9238 := (<-this.LoadMarkets())
PanicOnError(retRes9238)
results:= (<-this.FetchTransactionsWithMethod("v2PrivateGetAccountsAccountIdTransactions", code, since, limit, params))
PanicOnError(results)
ch <- this.FilterByArray(results, "type", []interface{}{"deposit", "withdrawal"}, false)
return nil
}()
return ch
}
func (this *coinbase) ParseTransactionStatus(status interface{}) interface{} {
var statuses interface{} = map[string]interface{} {
"created": "pending",
"completed": "ok",
"canceled": "canceled",
}
return this.SafeString(statuses, status, status)
}
func (this *coinbase) ParseTransaction(transaction interface{}, optionalArgs ...interface{}) interface{} {
//
// fiat deposit
//
// {
// "id": "f34c19f3-b730-5e3d-9f72",
// "status": "completed",
// "payment_method": {
// "id": "a022b31d-f9c7-5043-98f2",
// "resource": "payment_method",
// "resource_path": "/v2/payment-methods/a022b31d-f9c7-5043-98f2"
// },
// "transaction": {
// "id": "04ed4113-3732-5b0c-af86-b1d2146977d0",
// "resource": "transaction",
// "resource_path": "/v2/accounts/91cd2d36-3a91-55b6-a5d4-0124cf105483/transactions/04ed4113-3732-5b0c-af86"
// },
// "user_reference": "2VTYTH",
// "created_at": "2017-02-09T07:01:18Z",
// "updated_at": "2017-02-09T07:01:26Z",
// "resource": "deposit",
// "resource_path": "/v2/accounts/91cd2d36-3a91-55b6-a5d4-0124cf105483/deposits/f34c19f3-b730-5e3d-9f72",
// "committed": true,
// "payout_at": "2017-02-12T07:01:17Z",
// "instant": false,
// "fee": { "amount": "0.00", "currency": "EUR" },
// "amount": { "amount": "114.02", "currency": "EUR" },
// "subtotal": { "amount": "114.02", "currency": "EUR" },
// "hold_until": null,
// "hold_days": 0,
// "hold_business_days": 0,
// "next_step": null
// }
//
// fiat_withdrawal
//
// {
// "id": "cfcc3b4a-eeb6-5e8c-8058",
// "status": "completed",
// "payment_method": {
// "id": "8b94cfa4-f7fd-5a12-a76a",
// "resource": "payment_method",
// "resource_path": "/v2/payment-methods/8b94cfa4-f7fd-5a12-a76a"
// },
// "transaction": {
// "id": "fcc2550b-5104-5f83-a444",
// "resource": "transaction",
// "resource_path": "/v2/accounts/91cd2d36-3a91-55b6-a5d4-0124cf105483/transactions/fcc2550b-5104-5f83-a444"
// },
// "user_reference": "MEUGK",
// "created_at": "2018-07-26T08:55:12Z",
// "updated_at": "2018-07-26T08:58:18Z",
// "resource": "withdrawal",
// "resource_path": "/v2/accounts/91cd2d36-3a91-55b6-a5d4-0124cf105483/withdrawals/cfcc3b4a-eeb6-5e8c-8058",
// "committed": true,
// "payout_at": "2018-07-31T08:55:12Z",
// "instant": false,
// "fee": { "amount": "0.15", "currency": "EUR" },
// "amount": { "amount": "13130.69", "currency": "EUR" },
// "subtotal": { "amount": "13130.84", "currency": "EUR" },
// "idem": "e549dee5-63ed-4e79-8a96",
// "next_step": null
// }
//
// withdraw
//
// {
// "id": "a1794ecf-5693-55fa-70cf-ef731748ed82",
// "type": "send",
// "status": "pending",
// "amount": {
// "amount": "-14.008308",
// "currency": "USDC"
// },
// "native_amount": {
// "amount": "-18.74",
// "currency": "CAD"
// },
// "description": null,
// "created_at": "2024-01-12T01:27:31Z",
// "updated_at": "2024-01-12T01:27:31Z",
// "resource": "transaction",
// "resource_path": "/v2/accounts/a34bgfad-ed67-538b-bffc-730c98c10da0/transactions/a1794ecf-5693-55fa-70cf-ef731748ed82",
// "instant_exchange": false,
// "network": {
// "status": "pending",
// "status_description": "Pending (est. less than 10 minutes)",
// "transaction_fee": {
// "amount": "4.008308",
// "currency": "USDC"
// },
// "transaction_amount": {
// "amount": "10.000000",
// "currency": "USDC"
// },
// "confirmations": 0
// },
// "to": {
// "resource": "ethereum_address",
// "address": "0x9...",
// "currency": "USDC",
// "address_info": {
// "address": "0x9..."
// }
// },
// "idem": "748d8591-dg9a-7831-a45b-crd61dg78762",
// "details": {
// "title": "Sent USDC",
// "subtitle": "To USDC address on Ethereum network",
// "header": "Sent 14.008308 USDC ($18.74)",
// "health": "warning"
// },
// "hide_native_amount": false
// }
//
//
// crypto deposit & withdrawal (using `/transactions` endpoint)
// {
// "amount": {
// "amount": "0.00014200", (negative for withdrawal)
// "currency": "BTC"
// },
// "created_at": "2024-03-29T15:48:30Z",
// "id": "0031a605-241d-514d-a97b-d4b99f3225d3",
// "idem": "092a979b-017e-4403-940a-2ca57811f442", // field present only in case of withdrawal
// "native_amount": {
// "amount": "9.85", (negative for withdrawal)
// "currency": "USD"
// },
// "network": {
// "status": "pending", // if status is `off_blockchain` then no more other fields are present in this object
// "hash": "5jYuvrNsvX2DZoMnzGYzVpYxJLfYu4GSK3xetG1H5LHrSovsuFCFYdFMwNRoiht3s6fBk92MM8QLLnz65xuEFTrE",
// "network_name": "solana",
// "transaction_fee": {
// "amount": "0.000100000",
// "currency": "SOL"
// }
// },
// "resource": "transaction",
// "resource_path": "/v2/accounts/dc504b1c-248e-5b68-a3b0-b991f7fa84e6/transactions/0031a605-241d-514d-a97b-d4b99f3225d3",
// "status": "completed",
// "type": "send",
// "from": { // in some cases, field might be present for deposit
// "id": "7fd10cd7-b091-5cee-ba41-c29e49a7cccf",
// "name": "Coinbase",
// "resource": "user"
// },
// "to": { // field only present for withdrawal
// "address": "5HA12BNthAvBwNYARYf9y5MqqCpB4qhCNFCs1Qw48ACE",
// "resource": "address"
// },
// "description": "C3 - One Time BTC Credit . Reference Case # 123.", // in some cases, field might be present for deposit
// }
//
currency := GetArg(optionalArgs, 0, nil)
_ = currency
var transactionType interface{} = this.SafeString(transaction, "type")
var amountAndCurrencyObject interface{} = nil
var feeObject interface{} = nil
var network interface{} = this.SafeDict(transaction, "network", map[string]interface{} {})
if IsTrue(IsEqual(transactionType, "send")) {
amountAndCurrencyObject = this.SafeDict(network, "transaction_amount")
feeObject = this.SafeDict(network, "transaction_fee", map[string]interface{} {})
} else {
amountAndCurrencyObject = this.SafeDict(transaction, "subtotal")
feeObject = this.SafeDict(transaction, "fee", map[string]interface{} {})
}
if IsTrue(IsEqual(amountAndCurrencyObject, nil)) {
amountAndCurrencyObject = this.SafeDict(transaction, "amount")
}
var amountString interface{} = this.SafeString(amountAndCurrencyObject, "amount")
var amountStringAbs interface{} = Precise.StringAbs(amountString)
var status interface{} = this.ParseTransactionStatus(this.SafeString(transaction, "status"))
if IsTrue(IsEqual(status, nil)) {
var committed interface{} = this.SafeBool(transaction, "committed")
status = Ternary(IsTrue(committed), "ok", "pending")
}
var id interface{} = this.SafeString(transaction, "id")
var currencyId interface{} = this.SafeString(amountAndCurrencyObject, "currency")
var feeCurrencyId interface{} = this.SafeString(feeObject, "currency")
var datetime interface{} = this.SafeString(transaction, "created_at")
var resource interface{} = this.SafeString(transaction, "resource")
var typeVar interface{} = resource
if !IsTrue(this.InArray(typeVar, []interface{}{"deposit", "withdrawal"})) {
if IsTrue(Precise.StringGt(amountString, "0")) {
typeVar = "deposit"
} else if IsTrue(Precise.StringLt(amountString, "0")) {
typeVar = "withdrawal"
}
}
var toObject interface{} = this.SafeDict(transaction, "to")
var addressTo interface{} = this.SafeString(toObject, "address")
var networkId interface{} = this.SafeString(network, "network_name")
return map[string]interface{} {
"info": transaction,
"id": id,
"txid": this.SafeString(network, "hash", id),
"timestamp": this.Parse8601(datetime),
"datetime": datetime,
"network": this.NetworkIdToCode(networkId),
"address": addressTo,
"addressTo": addressTo,
"addressFrom": nil,
"tag": nil,
"tagTo": nil,
"tagFrom": nil,
"type": typeVar,
"amount": this.ParseNumber(amountStringAbs),
"currency": this.SafeCurrencyCode(currencyId, currency),
"status": status,
"updated": this.Parse8601(this.SafeString(transaction, "updated_at")),
"fee": map[string]interface{} {
"cost": this.SafeNumber(feeObject, "amount"),
"currency": this.SafeCurrencyCode(feeCurrencyId),
},
}
}
func (this *coinbase) ParseTrade(trade interface{}, optionalArgs ...interface{}) interface{} {
//
// fetchMyBuys, fetchMySells
//
// {
// "id": "67e0eaec-07d7-54c4-a72c-2e92826897df",
// "status": "completed",
// "payment_method": {
// "id": "83562370-3e5c-51db-87da-752af5ab9559",
// "resource": "payment_method",
// "resource_path": "/v2/payment-methods/83562370-3e5c-51db-87da-752af5ab9559"
// },
// "transaction": {
// "id": "441b9494-b3f0-5b98-b9b0-4d82c21c252a",
// "resource": "transaction",
// "resource_path": "/v2/accounts/2bbf394c-193b-5b2a-9155-3b4732659ede/transactions/441b9494-b3f0-5b98-b9b0-4d82c21c252a"
// },
// "amount": { "amount": "1.00000000", "currency": "BTC" },
// "total": { "amount": "10.25", "currency": "USD" },
// "subtotal": { "amount": "10.10", "currency": "USD" },
// "created_at": "2015-01-31T20:49:02Z",
// "updated_at": "2015-02-11T16:54:02-08:00",
// "resource": "buy",
// "resource_path": "/v2/accounts/2bbf394c-193b-5b2a-9155-3b4732659ede/buys/67e0eaec-07d7-54c4-a72c-2e92826897df",
// "committed": true,
// "instant": false,
// "fee": { "amount": "0.15", "currency": "USD" },
// "payout_at": "2015-02-18T16:54:00-08:00"
// }
//
// fetchTrades
//
// {
// "trade_id": "10092327",
// "product_id": "BTC-USDT",
// "price": "17488.12",
// "size": "0.0000623",
// "time": "2023-01-11T00:52:37.557001Z",
// "side": "BUY",
// "bid": "",
// "ask": ""
// }
//
// fetchMyTrades
//
// {
// "entry_id": "b88b82cc89e326a2778874795102cbafd08dd979a2a7a3c69603fc4c23c2e010",
// "trade_id": "cdc39e45-bbd3-44ec-bf02-61742dfb16a1",
// "order_id": "813a53c5-3e39-47bb-863d-2faf685d22d8",
// "trade_time": "2023-01-18T01:37:38.091377090Z",
// "trade_type": "FILL",
// "price": "21220.64",
// "size": "0.0046830664333996",
// "commission": "0.0000280983986004",
// "product_id": "BTC-USDT",
// "sequence_timestamp": "2023-01-18T01:37:38.092520Z",
// "liquidity_indicator": "UNKNOWN_LIQUIDITY_INDICATOR",
// "size_in_quote": true,
// "user_id": "1111111-1111-1111-1111-111111111111",
// "side": "BUY"
// }
//
market := GetArg(optionalArgs, 0, nil)
_ = market
var symbol interface{} = nil
var totalObject interface{} = this.SafeDict(trade, "total", map[string]interface{} {})
var amountObject interface{} = this.SafeDict(trade, "amount", map[string]interface{} {})
var subtotalObject interface{} = this.SafeDict(trade, "subtotal", map[string]interface{} {})
var feeObject interface{} = this.SafeDict(trade, "fee", map[string]interface{} {})
var marketId interface{} = this.SafeString(trade, "product_id")
market = this.SafeMarket(marketId, market, "-")
if IsTrue(!IsEqual(market, nil)) {
symbol = GetValue(market, "symbol")
} else {
var baseId interface{} = this.SafeString(amountObject, "currency")
var quoteId interface{} = this.SafeString(totalObject, "currency")
if IsTrue(IsTrue((!IsEqual(baseId, nil))) && IsTrue((!IsEqual(quoteId, nil)))) {
var base interface{} = this.SafeCurrencyCode(baseId)
var quote interface{} = this.SafeCurrencyCode(quoteId)
symbol = Add(Add(base, "/"), quote)
}
}
var sizeInQuote interface{} = this.SafeBool(trade, "size_in_quote")
var v3Price interface{} = this.SafeString(trade, "price")
var v3Cost interface{} = nil
var v3Amount interface{} = this.SafeString(trade, "size")
if IsTrue(sizeInQuote) {
// calculate base size
v3Cost = v3Amount
v3Amount = Precise.StringDiv(v3Amount, v3Price)
}
var v3FeeCost interface{} = this.SafeString(trade, "commission")
var amountString interface{} = this.SafeString(amountObject, "amount", v3Amount)
var costString interface{} = this.SafeString(subtotalObject, "amount", v3Cost)
var priceString interface{} = nil
var cost interface{} = nil
if IsTrue(IsTrue((!IsEqual(costString, nil))) && IsTrue((!IsEqual(amountString, nil)))) {
priceString = Precise.StringDiv(costString, amountString)
} else {
priceString = v3Price
}
if IsTrue(IsTrue((!IsEqual(priceString, nil))) && IsTrue((!IsEqual(amountString, nil)))) {
cost = Precise.StringMul(priceString, amountString)
} else {
cost = costString
}
var feeCurrencyId interface{} = this.SafeString(feeObject, "currency")
var feeCost interface{} = this.SafeNumber(feeObject, "amount", this.ParseNumber(v3FeeCost))
if IsTrue(IsTrue(IsTrue((IsEqual(feeCurrencyId, nil))) && IsTrue((!IsEqual(market, nil)))) && IsTrue((!IsEqual(feeCost, nil)))) {
feeCurrencyId = GetValue(market, "quote")
}
var datetime interface{} = this.SafeStringN(trade, []interface{}{"created_at", "trade_time", "time"})
var side interface{} = this.SafeStringLower2(trade, "resource", "side")
var takerOrMaker interface{} = this.SafeStringLower(trade, "liquidity_indicator")
return this.SafeTrade(map[string]interface{} {
"info": trade,
"id": this.SafeString2(trade, "id", "trade_id"),
"order": this.SafeString(trade, "order_id"),
"timestamp": this.Parse8601(datetime),
"datetime": datetime,
"symbol": symbol,
"type": nil,
"side": Ternary(IsTrue((IsEqual(side, "unknown_order_side"))), nil, side),
"takerOrMaker": Ternary(IsTrue((IsEqual(takerOrMaker, "unknown_liquidity_indicator"))), nil, takerOrMaker),
"price": priceString,
"amount": amountString,
"cost": cost,
"fee": map[string]interface{} {
"cost": feeCost,
"currency": this.SafeCurrencyCode(feeCurrencyId),
},
})
}
/**
* @method
* @name coinbase#fetchMarkets
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getpublicproducts
* @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-currencies#get-fiat-currencies
* @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-exchange-rates#get-exchange-rates
* @description retrieves data on all markets for coinbase
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {boolean} [params.usePrivate] use private endpoint for fetching markets
* @returns {object[]} an array of objects representing market data
*/
func (this *coinbase) FetchMarkets(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
if IsTrue(GetValue(this.Options, "adjustForTimeDifference")) {
retRes129812 := (<-this.LoadTimeDifference())
PanicOnError(retRes129812)
}
var method interface{} = this.SafeString(this.Options, "fetchMarkets", "fetchMarketsV3")
if IsTrue(IsEqual(method, "fetchMarketsV3")) {
retRes130219 := (<-this.FetchMarketsV3(params))
PanicOnError(retRes130219)
ch <- retRes130219
return nil
}
retRes130415 := (<-this.FetchMarketsV2(params))
PanicOnError(retRes130415)
ch <- retRes130415
return nil
}()
return ch
}
func (this *coinbase) FetchMarketsV2(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
response:= (<-this.FetchCurrenciesFromCache(params))
PanicOnError(response)
var currencies interface{} = this.SafeDict(response, "currencies", map[string]interface{} {})
var exchangeRates interface{} = this.SafeDict(response, "exchangeRates", map[string]interface{} {})
var data interface{} = this.SafeList(currencies, "data", []interface{}{})
var dataById interface{} = this.IndexBy(data, "id")
var rates interface{} = this.SafeDict(this.SafeDict(exchangeRates, "data", map[string]interface{} {}), "rates", map[string]interface{} {})
var baseIds interface{} = ObjectKeys(rates)
var result interface{} = []interface{}{}
for i := 0; IsLessThan(i, GetArrayLength(baseIds)); i++ {
var baseId interface{} = GetValue(baseIds, i)
var base interface{} = this.SafeCurrencyCode(baseId)
var typeVar interface{} = Ternary(IsTrue((InOp(dataById, baseId))), "fiat", "crypto")
// https://github.com/ccxt/ccxt/issues/6066
if IsTrue(IsEqual(typeVar, "crypto")) {
for j := 0; IsLessThan(j, GetArrayLength(data)); j++ {
var quoteCurrency interface{} = GetValue(data, j)
var quoteId interface{} = this.SafeString(quoteCurrency, "id")
var quote interface{} = this.SafeCurrencyCode(quoteId)
AppendToArray(&result,this.SafeMarketStructure(map[string]interface{} {
"id": Add(Add(baseId, "-"), quoteId),
"symbol": Add(Add(base, "/"), quote),
"base": base,
"quote": quote,
"settle": nil,
"baseId": baseId,
"quoteId": quoteId,
"settleId": nil,
"type": "spot",
"spot": true,
"margin": false,
"swap": false,
"future": false,
"option": false,
"active": nil,
"contract": false,
"linear": nil,
"inverse": nil,
"contractSize": nil,
"expiry": nil,
"expiryDatetime": nil,
"strike": nil,
"optionType": nil,
"precision": map[string]interface{} {
"amount": nil,
"price": nil,
},
"limits": map[string]interface{} {
"leverage": map[string]interface{} {
"min": nil,
"max": nil,
},
"amount": map[string]interface{} {
"min": nil,
"max": nil,
},
"price": map[string]interface{} {
"min": nil,
"max": nil,
},
"cost": map[string]interface{} {
"min": this.SafeNumber(quoteCurrency, "min_size"),
"max": nil,
},
},
"info": quoteCurrency,
}))
}
}
}
ch <- result
return nil
}()
return ch
}
func (this *coinbase) FetchMarketsV3(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
var usePrivate interface{} = false
usePrivateparamsVariable := this.HandleOptionAndParams(params, "fetchMarkets", "usePrivate", false);
usePrivate = GetValue(usePrivateparamsVariable,0);
params = GetValue(usePrivateparamsVariable,1)
var spotUnresolvedPromises interface{} = []interface{}{}
if IsTrue(usePrivate) {
AppendToArray(&spotUnresolvedPromises,this.V3PrivateGetBrokerageProducts(params))
} else {
AppendToArray(&spotUnresolvedPromises,this.V3PublicGetBrokerageMarketProducts(params))
}
//
// {
// products: [
// {
// product_id: 'BTC-USD',
// price: '67060',
// price_percentage_change_24h: '3.30054960636883',
// volume_24h: '10967.87426597',
// volume_percentage_change_24h: '141.73048325503036',
// base_increment: '0.00000001',
// quote_increment: '0.01',
// quote_min_size: '1',
// quote_max_size: '150000000',
// base_min_size: '0.00000001',
// base_max_size: '3400',
// base_name: 'Bitcoin',
// quote_name: 'US Dollar',
// watched: false,
// is_disabled: false,
// new: false,
// status: 'online',
// cancel_only: false,
// limit_only: false,
// post_only: false,
// trading_disabled: false,
// auction_mode: false,
// product_type: 'SPOT',
// quote_currency_id: 'USD',
// base_currency_id: 'BTC',
// fcm_trading_session_details: null,
// mid_market_price: '',
// alias: '',
// alias_to: [ 'BTC-USDC' ],
// base_display_symbol: 'BTC',
// quote_display_symbol: 'USD',
// view_only: false,
// price_increment: '0.01',
// display_name: 'BTC-USD',
// product_venue: 'CBE'
// },
// ...
// ],
// num_products: '646'
// }
//
if IsTrue(this.CheckRequiredCredentials(false)) {
AppendToArray(&spotUnresolvedPromises,this.V3PrivateGetBrokerageTransactionSummary(params))
}
//
// {
// total_volume: '9.995989116664404',
// total_fees: '0.07996791093331522',
// fee_tier: {
// pricing_tier: 'Advanced 1',
// usd_from: '0',
// usd_to: '1000',
// taker_fee_rate: '0.008',
// maker_fee_rate: '0.006',
// aop_from: '',
// aop_to: ''
// },
// margin_rate: null,
// goods_and_services_tax: null,
// advanced_trade_only_volume: '9.995989116664404',
// advanced_trade_only_fees: '0.07996791093331522',
// coinbase_pro_volume: '0',
// coinbase_pro_fees: '0',
// total_balance: '',
// has_promo_fee: false
// }
//
var unresolvedContractPromises interface{} = []interface{}{}
{ ret__ := func(this *coinbase) (ret_ interface{}) {
defer func() {
if e := recover(); e != nil {
if e == "break" {
return
}
ret_ = func(this *coinbase) interface{} {
// catch block:
unresolvedContractPromises = []interface{}{} // 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
return nil
}(this)
}
}()
// try block:
unresolvedContractPromises = []interface{}{this.V3PublicGetBrokerageMarketProducts(this.Extend(params, map[string]interface{} {
"product_type": "FUTURE",
})), this.V3PublicGetBrokerageMarketProducts(this.Extend(params, map[string]interface{} {
"product_type": "FUTURE",
"contract_expiry_type": "PERPETUAL",
}))}
if IsTrue(this.CheckRequiredCredentials(false)) {
AppendToArray(&unresolvedContractPromises,this.Extend(params, map[string]interface{} {
"product_type": "FUTURE",
}))
AppendToArray(&unresolvedContractPromises,this.Extend(params, map[string]interface{} {
"product_type": "FUTURE",
"contract_expiry_type": "PERPETUAL",
}))
}
return nil
}(this)
if ret__ != nil {
return ret__
}
}
promises:= (<-promiseAll(spotUnresolvedPromises))
PanicOnError(promises)
var contractPromises interface{} = nil
{ ret__ := func(this *coinbase) (ret_ interface{}) {
defer func() {
if e := recover(); e != nil {
if e == "break" {
return
}
ret_ = func(this *coinbase) interface{} {
// catch block:
contractPromises = []interface{}{}
return nil
}(this)
}
}()
// try block:
contractPromises = (<-promiseAll(unresolvedContractPromises))
PanicOnError(contractPromises) // some users don't have access to contracts
return nil
}(this)
if ret__ != nil {
return ret__
}
}
var spot interface{} = this.SafeDict(promises, 0, map[string]interface{} {})
var fees interface{} = this.SafeDict(promises, 1, map[string]interface{} {})
var expiringFutures interface{} = this.SafeDict(contractPromises, 0, map[string]interface{} {})
var perpetualFutures interface{} = this.SafeDict(contractPromises, 1, map[string]interface{} {})
var expiringFees interface{} = this.SafeDict(contractPromises, 2, map[string]interface{} {})
var perpetualFees interface{} = this.SafeDict(contractPromises, 3, map[string]interface{} {})
//
// {
// "total_volume": 0,
// "total_fees": 0,
// "fee_tier": {
// "pricing_tier": "",
// "usd_from": "0",
// "usd_to": "10000",
// "taker_fee_rate": "0.006",
// "maker_fee_rate": "0.004"
// },
// "margin_rate": null,
// "goods_and_services_tax": null,
// "advanced_trade_only_volume": 0,
// "advanced_trade_only_fees": 0,
// "coinbase_pro_volume": 0,
// "coinbase_pro_fees": 0
// }
//
var feeTier interface{} = this.SafeDict(fees, "fee_tier", map[string]interface{} {})
var expiringFeeTier interface{} = this.SafeDict(expiringFees, "fee_tier", map[string]interface{} {}) // fee tier null?
var perpetualFeeTier interface{} = this.SafeDict(perpetualFees, "fee_tier", map[string]interface{} {}) // fee tier null?
var data interface{} = this.SafeList(spot, "products", []interface{}{})
var result interface{} = []interface{}{}
for i := 0; IsLessThan(i, GetArrayLength(data)); i++ {
AppendToArray(&result,this.ParseSpotMarket(GetValue(data, i), feeTier))
}
var futureData interface{} = this.SafeList(expiringFutures, "products", []interface{}{})
for i := 0; IsLessThan(i, GetArrayLength(futureData)); i++ {
AppendToArray(&result,this.ParseContractMarket(GetValue(futureData, i), expiringFeeTier))
}
var perpetualData interface{} = this.SafeList(perpetualFutures, "products", []interface{}{})
for i := 0; IsLessThan(i, GetArrayLength(perpetualData)); i++ {
AppendToArray(&result,this.ParseContractMarket(GetValue(perpetualData, i), perpetualFeeTier))
}
ch <- result
return nil
}()
return ch
}
func (this *coinbase) ParseSpotMarket(market interface{}, feeTier interface{}) interface{} {
//
// {
// "product_id": "TONE-USD",
// "price": "0.01523",
// "price_percentage_change_24h": "1.94109772423025",
// "volume_24h": "19773129",
// "volume_percentage_change_24h": "437.0170530929949",
// "base_increment": "1",
// "quote_increment": "0.00001",
// "quote_min_size": "1",
// "quote_max_size": "10000000",
// "base_min_size": "26.7187147229469674",
// "base_max_size": "267187147.2294696735908216",
// "base_name": "TE-FOOD",
// "quote_name": "US Dollar",
// "watched": false,
// "is_disabled": false,
// "new": false,
// "status": "online",
// "cancel_only": false,
// "limit_only": false,
// "post_only": false,
// "trading_disabled": false,
// "auction_mode": false,
// "product_type": "SPOT",
// "quote_currency_id": "USD",
// "base_currency_id": "TONE",
// "fcm_trading_session_details": null,
// "mid_market_price": ""
// }
//
var id interface{} = this.SafeString(market, "product_id")
var baseId interface{} = this.SafeString(market, "base_currency_id")
var quoteId interface{} = this.SafeString(market, "quote_currency_id")
var base interface{} = this.SafeCurrencyCode(baseId)
var quote interface{} = this.SafeCurrencyCode(quoteId)
var marketType interface{} = this.SafeStringLower(market, "product_type")
var tradingDisabled interface{} = this.SafeBool(market, "trading_disabled")
var stablePairs interface{} = this.SafeList(this.Options, "stablePairs", []interface{}{})
var defaultTakerFee interface{} = this.SafeNumber(GetValue(this.Fees, "trading"), "taker")
var defaultMakerFee interface{} = this.SafeNumber(GetValue(this.Fees, "trading"), "maker")
var takerFee interface{} = Ternary(IsTrue(this.InArray(id, stablePairs)), 0.00001, this.SafeNumber(feeTier, "taker_fee_rate", defaultTakerFee))
var makerFee interface{} = Ternary(IsTrue(this.InArray(id, stablePairs)), 0, this.SafeNumber(feeTier, "maker_fee_rate", defaultMakerFee))
return this.SafeMarketStructure(map[string]interface{} {
"id": id,
"symbol": Add(Add(base, "/"), quote),
"base": base,
"quote": quote,
"settle": nil,
"baseId": baseId,
"quoteId": quoteId,
"settleId": nil,
"type": marketType,
"spot": (IsEqual(marketType, "spot")),
"margin": nil,
"swap": false,
"future": false,
"option": false,
"active": !IsTrue(tradingDisabled),
"contract": false,
"linear": nil,
"inverse": nil,
"taker": takerFee,
"maker": makerFee,
"contractSize": nil,
"expiry": nil,
"expiryDatetime": nil,
"strike": nil,
"optionType": nil,
"precision": map[string]interface{} {
"amount": this.SafeNumber(market, "base_increment"),
"price": this.SafeNumber2(market, "price_increment", "quote_increment"),
},
"limits": map[string]interface{} {
"leverage": map[string]interface{} {
"min": nil,
"max": nil,
},
"amount": map[string]interface{} {
"min": this.SafeNumber(market, "base_min_size"),
"max": this.SafeNumber(market, "base_max_size"),
},
"price": map[string]interface{} {
"min": nil,
"max": nil,
},
"cost": map[string]interface{} {
"min": this.SafeNumber(market, "quote_min_size"),
"max": this.SafeNumber(market, "quote_max_size"),
},
},
"created": nil,
"info": market,
})
}
func (this *coinbase) ParseContractMarket(market interface{}, feeTier interface{}) interface{} {
// expiring
//
// {
// "product_id":"BIT-26APR24-CDE",
// "price":"71145",
// "price_percentage_change_24h":"-2.36722931247427",
// "volume_24h":"108549",
// "volume_percentage_change_24h":"155.78255337197794",
// "base_increment":"1",
// "quote_increment":"0.01",
// "quote_min_size":"0",
// "quote_max_size":"100000000",
// "base_min_size":"1",
// "base_max_size":"100000000",
// "base_name":"",
// "quote_name":"US Dollar",
// "watched":false,
// "is_disabled":false,
// "new":false,
// "status":"",
// "cancel_only":false,
// "limit_only":false,
// "post_only":false,
// "trading_disabled":false,
// "auction_mode":false,
// "product_type":"FUTURE",
// "quote_currency_id":"USD",
// "base_currency_id":"",
// "fcm_trading_session_details":{
// "is_session_open":true,
// "open_time":"2024-04-08T22:00:00Z",
// "close_time":"2024-04-09T21:00:00Z"
// },
// "mid_market_price":"71105",
// "alias":"",
// "alias_to":[
// ],
// "base_display_symbol":"",
// "quote_display_symbol":"USD",
// "view_only":false,
// "price_increment":"5",
// "display_name":"BTC 26 APR 24",
// "product_venue":"FCM",
// "future_product_details":{
// "venue":"cde",
// "contract_code":"BIT",
// "contract_expiry":"2024-04-26T15:00:00Z",
// "contract_size":"0.01",
// "contract_root_unit":"BTC",
// "group_description":"Nano Bitcoin Futures",
// "contract_expiry_timezone":"Europe/London",
// "group_short_description":"Nano BTC",
// "risk_managed_by":"MANAGED_BY_FCM",
// "contract_expiry_type":"EXPIRING",
// "contract_display_name":"BTC 26 APR 24"
// }
// }
//
// perpetual
//
// {
// "product_id":"ETH-PERP-INTX",
// "price":"3630.98",
// "price_percentage_change_24h":"0.65142426292038",
// "volume_24h":"114020.1501",
// "volume_percentage_change_24h":"63.33650787154869",
// "base_increment":"0.0001",
// "quote_increment":"0.01",
// "quote_min_size":"10",
// "quote_max_size":"50000000",
// "base_min_size":"0.0001",
// "base_max_size":"50000",
// "base_name":"",
// "quote_name":"USDC",
// "watched":false,
// "is_disabled":false,
// "new":false,
// "status":"",
// "cancel_only":false,
// "limit_only":false,
// "post_only":false,
// "trading_disabled":false,
// "auction_mode":false,
// "product_type":"FUTURE",
// "quote_currency_id":"USDC",
// "base_currency_id":"",
// "fcm_trading_session_details":null,
// "mid_market_price":"3630.975",
// "alias":"",
// "alias_to":[],
// "base_display_symbol":"",
// "quote_display_symbol":"USDC",
// "view_only":false,
// "price_increment":"0.01",
// "display_name":"ETH PERP",
// "product_venue":"INTX",
// "future_product_details":{
// "venue":"",
// "contract_code":"ETH",
// "contract_expiry":null,
// "contract_size":"1",
// "contract_root_unit":"ETH",
// "group_description":"",
// "contract_expiry_timezone":"",
// "group_short_description":"",
// "risk_managed_by":"MANAGED_BY_VENUE",
// "contract_expiry_type":"PERPETUAL",
// "perpetual_details":{
// "open_interest":"0",
// "funding_rate":"0.000016",
// "funding_time":"2024-04-09T09:00:00.000008Z",
// "max_leverage":"10"
// },
// "contract_display_name":"ETH PERPETUAL"
// }
// }
//
var id interface{} = this.SafeString(market, "product_id")
var futureProductDetails interface{} = this.SafeDict(market, "future_product_details", map[string]interface{} {})
var contractExpiryType interface{} = this.SafeString(futureProductDetails, "contract_expiry_type")
var contractSize interface{} = this.SafeNumber(futureProductDetails, "contract_size")
var contractExpire interface{} = this.SafeString(futureProductDetails, "contract_expiry")
var expireTimestamp interface{} = this.Parse8601(contractExpire)
var expireDateTime interface{} = this.Iso8601(expireTimestamp)
var isSwap interface{} = (IsEqual(contractExpiryType, "PERPETUAL"))
var baseId interface{} = this.SafeString(futureProductDetails, "contract_root_unit")
var quoteId interface{} = this.SafeString(market, "quote_currency_id")
var base interface{} = this.SafeCurrencyCode(baseId)
var quote interface{} = this.SafeCurrencyCode(quoteId)
var tradingDisabled interface{} = this.SafeBool(market, "is_disabled")
var symbol interface{} = Add(Add(base, "/"), quote)
var typeVar interface{} = nil
if IsTrue(isSwap) {
typeVar = "swap"
symbol = Add(Add(symbol, ":"), quote)
} else {
typeVar = "future"
symbol = Add(Add(Add(Add(symbol, ":"), quote), "-"), this.Yymmdd(expireTimestamp))
}
var takerFeeRate interface{} = this.SafeNumber(feeTier, "taker_fee_rate")
var makerFeeRate interface{} = this.SafeNumber(feeTier, "maker_fee_rate")
var taker interface{} = Ternary(IsTrue(takerFeeRate), takerFeeRate, this.ParseNumber("0.06"))
var maker interface{} = Ternary(IsTrue(makerFeeRate), makerFeeRate, this.ParseNumber("0.04"))
return this.SafeMarketStructure(map[string]interface{} {
"id": id,
"symbol": symbol,
"base": base,
"quote": quote,
"settle": quote,
"baseId": baseId,
"quoteId": quoteId,
"settleId": quoteId,
"type": typeVar,
"spot": false,
"margin": false,
"swap": isSwap,
"future": !IsTrue(isSwap),
"option": false,
"active": !IsTrue(tradingDisabled),
"contract": true,
"linear": true,
"inverse": false,
"taker": taker,
"maker": maker,
"contractSize": contractSize,
"expiry": expireTimestamp,
"expiryDatetime": expireDateTime,
"strike": nil,
"optionType": nil,
"precision": map[string]interface{} {
"amount": this.SafeNumber(market, "base_increment"),
"price": this.SafeNumber2(market, "price_increment", "quote_increment"),
},
"limits": map[string]interface{} {
"leverage": map[string]interface{} {
"min": nil,
"max": nil,
},
"amount": map[string]interface{} {
"min": this.SafeNumber(market, "base_min_size"),
"max": this.SafeNumber(market, "base_max_size"),
},
"price": map[string]interface{} {
"min": nil,
"max": nil,
},
"cost": map[string]interface{} {
"min": this.SafeNumber(market, "quote_min_size"),
"max": this.SafeNumber(market, "quote_max_size"),
},
},
"created": nil,
"info": market,
})
}
func (this *coinbase) FetchCurrenciesFromCache(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
var options interface{} = this.SafeDict(this.Options, "fetchCurrencies", map[string]interface{} {})
var timestamp interface{} = this.SafeInteger(options, "timestamp")
var expires interface{} = this.SafeInteger(options, "expires", 1000)
var now interface{} = this.Milliseconds()
if IsTrue(IsTrue((IsEqual(timestamp, nil))) || IsTrue((IsGreaterThan((Subtract(now, timestamp)), expires)))) {
var promises interface{} = []interface{}{this.V2PublicGetCurrencies(params), this.V2PublicGetCurrenciesCrypto(params)}
promisesResult:= (<-promiseAll(promises))
PanicOnError(promisesResult)
var fiatResponse interface{} = this.SafeDict(promisesResult, 0, map[string]interface{} {})
//
// [
// "data": {
// id: 'IMP',
// name: 'Isle of Man Pound',
// min_size: '0.01'
// },
// ...
// ]
//
var cryptoResponse interface{} = this.SafeDict(promisesResult, 1, map[string]interface{} {})
//
// {
// asset_id: '9476e3be-b731-47fa-82be-347fabc573d9',
// code: 'AERO',
// name: 'Aerodrome Finance',
// color: '#0433FF',
// sort_index: '340',
// exponent: '8',
// type: 'crypto',
// address_regex: '^(?:0x)?[0-9a-fA-F]{40}$'
// }
//
var fiatData interface{} = this.SafeList(fiatResponse, "data", []interface{}{})
var cryptoData interface{} = this.SafeList(cryptoResponse, "data", []interface{}{})
exchangeRates:= (<-this.V2PublicGetExchangeRates(params))
PanicOnError(exchangeRates)
AddElementToObject(this.Options, "fetchCurrencies", this.Extend(options, map[string]interface{} {
"currencies": this.ArrayConcat(fiatData, cryptoData),
"exchangeRates": exchangeRates,
"timestamp": now,
}))
}
ch <- this.SafeDict(this.Options, "fetchCurrencies", map[string]interface{} {})
return nil
}()
return ch
}
/**
* @method
* @name coinbase#fetchCurrencies
* @description fetches all available currencies on an exchange
* @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-currencies#get-fiat-currencies
* @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-exchange-rates#get-exchange-rates
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} an associative dictionary of currencies
*/
func (this *coinbase) FetchCurrencies(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
response:= (<-this.FetchCurrenciesFromCache(params))
PanicOnError(response)
var currencies interface{} = this.SafeList(response, "currencies", []interface{}{})
//
// fiat
//
// {
// id: 'IMP',
// name: 'Isle of Man Pound',
// min_size: '0.01'
// },
//
// crypto
//
// {
// asset_id: '9476e3be-b731-47fa-82be-347fabc573d9',
// code: 'AERO',
// name: 'Aerodrome Finance',
// color: '#0433FF',
// sort_index: '340',
// exponent: '8',
// type: 'crypto',
// address_regex: '^(?:0x)?[0-9a-fA-F]{40}$'
// }
//
//
// {
// "data":{
// "currency":"USD",
// "rates":{
// "AED":"3.67",
// "AFN":"78.21",
// "ALL":"110.42",
// "AMD":"474.18",
// "ANG":"1.75",
// ...
// },
// }
// }
//
var result interface{} = map[string]interface{} {}
var networks interface{} = map[string]interface{} {}
var networksById interface{} = map[string]interface{} {}
for i := 0; IsLessThan(i, GetArrayLength(currencies)); i++ {
var currency interface{} = GetValue(currencies, i)
var assetId interface{} = this.SafeString(currency, "asset_id")
var id interface{} = this.SafeString2(currency, "id", "code")
var code interface{} = this.SafeCurrencyCode(id)
var name interface{} = this.SafeString(currency, "name")
AddElementToObject(GetValue(this.Options, "networks"), code, ToLower(name))
AddElementToObject(GetValue(this.Options, "networksById"), code, ToLower(name))
AddElementToObject(result, code, map[string]interface{} {
"info": currency,
"id": id,
"code": code,
"type": Ternary(IsTrue((!IsEqual(assetId, nil))), "crypto", "fiat"),
"name": this.SafeString(currency, "name"),
"active": true,
"deposit": nil,
"withdraw": nil,
"fee": nil,
"precision": nil,
"limits": map[string]interface{} {
"amount": map[string]interface{} {
"min": this.SafeNumber(currency, "min_size"),
"max": nil,
},
"withdraw": map[string]interface{} {
"min": nil,
"max": nil,
},
},
})
if IsTrue(!IsEqual(assetId, nil)) {
var lowerCaseName interface{} = ToLower(name)
AddElementToObject(networks, code, lowerCaseName)
AddElementToObject(networksById, lowerCaseName, code)
}
}
AddElementToObject(this.Options, "networks", this.Extend(networks, GetValue(this.Options, "networks")))
AddElementToObject(this.Options, "networksById", this.Extend(networksById, GetValue(this.Options, "networksById")))
ch <- result
return nil
}()
return ch
}
/**
* @method
* @name coinbase#fetchTickers
* @description fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getproducts
* @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-exchange-rates#get-exchange-rates
* @param {string[]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {boolean} [params.usePrivate] use private endpoint for fetching tickers
* @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
*/
func (this *coinbase) FetchTickers(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbols := GetArg(optionalArgs, 0, nil)
_ = symbols
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
var method interface{} = this.SafeString(this.Options, "fetchTickers", "fetchTickersV3")
if IsTrue(IsEqual(method, "fetchTickersV3")) {
retRes197219 := (<-this.FetchTickersV3(symbols, params))
PanicOnError(retRes197219)
ch <- retRes197219
return nil
}
retRes197415 := (<-this.FetchTickersV2(symbols, params))
PanicOnError(retRes197415)
ch <- retRes197415
return nil
}()
return ch
}
func (this *coinbase) FetchTickersV2(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbols := GetArg(optionalArgs, 0, nil)
_ = symbols
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
retRes19788 := (<-this.LoadMarkets())
PanicOnError(retRes19788)
symbols = this.MarketSymbols(symbols)
var request interface{} = map[string]interface{} {}
response:= (<-this.V2PublicGetExchangeRates(this.Extend(request, params)))
PanicOnError(response)
//
// {
// "data":{
// "currency":"USD",
// "rates":{
// "AED":"3.6731",
// "AFN":"103.163942",
// "ALL":"106.973038",
// }
// }
// }
//
var data interface{} = this.SafeDict(response, "data", map[string]interface{} {})
var rates interface{} = this.SafeDict(data, "rates", map[string]interface{} {})
var quoteId interface{} = this.SafeString(data, "currency")
var result interface{} = map[string]interface{} {}
var baseIds interface{} = ObjectKeys(rates)
var delimiter interface{} = "-"
for i := 0; IsLessThan(i, GetArrayLength(baseIds)); i++ {
var baseId interface{} = GetValue(baseIds, i)
var marketId interface{} = Add(Add(baseId, delimiter), quoteId)
var market interface{} = this.SafeMarket(marketId, nil, delimiter)
var symbol interface{} = GetValue(market, "symbol")
AddElementToObject(result, symbol, this.ParseTicker(GetValue(rates, baseId), market))
}
ch <- this.FilterByArrayTickers(result, "symbol", symbols)
return nil
}()
return ch
}
func (this *coinbase) FetchTickersV3(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbols := GetArg(optionalArgs, 0, nil)
_ = symbols
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
retRes20138 := (<-this.LoadMarkets())
PanicOnError(retRes20138)
symbols = this.MarketSymbols(symbols)
var request interface{} = map[string]interface{} {}
if IsTrue(!IsEqual(symbols, nil)) {
AddElementToObject(request, "product_ids", this.MarketIds(symbols))
}
var marketType interface{} = nil
marketTypeparamsVariable := this.HandleMarketTypeAndParams("fetchTickers", this.GetMarketFromSymbols(symbols), params, "default");
marketType = GetValue(marketTypeparamsVariable,0);
params = GetValue(marketTypeparamsVariable,1)
if IsTrue(IsTrue(!IsEqual(marketType, nil)) && IsTrue(!IsEqual(marketType, "default"))) {
AddElementToObject(request, "product_type", Ternary(IsTrue((IsEqual(marketType, "swap"))), "FUTURE", "SPOT"))
}
var response interface{} = nil
var usePrivate interface{} = false
usePrivateparamsVariable := this.HandleOptionAndParams(params, "fetchTickers", "usePrivate", false);
usePrivate = GetValue(usePrivateparamsVariable,0);
params = GetValue(usePrivateparamsVariable,1)
if IsTrue(usePrivate) {
response = (<-this.V3PrivateGetBrokerageProducts(this.Extend(request, params)))
PanicOnError(response)
} else {
response = (<-this.V3PublicGetBrokerageMarketProducts(this.Extend(request, params)))
PanicOnError(response)
}
//
// {
// "products": [
// {
// "product_id": "TONE-USD",
// "price": "0.01523",
// "price_percentage_change_24h": "1.94109772423025",
// "volume_24h": "19773129",
// "volume_percentage_change_24h": "437.0170530929949",
// "base_increment": "1",
// "quote_increment": "0.00001",
// "quote_min_size": "1",
// "quote_max_size": "10000000",
// "base_min_size": "26.7187147229469674",
// "base_max_size": "267187147.2294696735908216",
// "base_name": "TE-FOOD",
// "quote_name": "US Dollar",
// "watched": false,
// "is_disabled": false,
// "new": false,
// "status": "online",
// "cancel_only": false,
// "limit_only": false,
// "post_only": false,
// "trading_disabled": false,
// "auction_mode": false,
// "product_type": "SPOT",
// "quote_currency_id": "USD",
// "base_currency_id": "TONE",
// "fcm_trading_session_details": null,
// "mid_market_price": ""
// },
// ...
// ],
// "num_products": 549
// }
//
var data interface{} = this.SafeList(response, "products", []interface{}{})
var result interface{} = map[string]interface{} {}
for i := 0; IsLessThan(i, GetArrayLength(data)); i++ {
var entry interface{} = GetValue(data, i)
var marketId interface{} = this.SafeString(entry, "product_id")
var market interface{} = this.SafeMarket(marketId, nil, "-")
var symbol interface{} = GetValue(market, "symbol")
AddElementToObject(result, symbol, this.ParseTicker(entry, market))
}
ch <- this.FilterByArrayTickers(result, "symbol", symbols)
return nil
}()
return ch
}
/**
* @method
* @name coinbase#fetchTicker
* @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getmarkettrades
* @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-prices#get-spot-price
* @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-prices#get-buy-price
* @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-prices#get-sell-price
* @param {string} symbol unified symbol of the market to fetch the ticker for
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {boolean} [params.usePrivate] whether to use the private endpoint for fetching the ticker
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
*/
func (this *coinbase) FetchTicker(symbol interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
var method interface{} = this.SafeString(this.Options, "fetchTicker", "fetchTickerV3")
if IsTrue(IsEqual(method, "fetchTickerV3")) {
retRes209719 := (<-this.FetchTickerV3(symbol, params))
PanicOnError(retRes209719)
ch <- retRes209719
return nil
}
retRes209915 := (<-this.FetchTickerV2(symbol, params))
PanicOnError(retRes209915)
ch <- retRes209915
return nil
}()
return ch
}
func (this *coinbase) FetchTickerV2(symbol interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
retRes21038 := (<-this.LoadMarkets())
PanicOnError(retRes21038)
var market interface{} = this.Market(symbol)
var request interface{} = this.Extend(map[string]interface{} {
"symbol": GetValue(market, "id"),
}, params)
spot:= (<-this.V2PublicGetPricesSymbolSpot(request))
PanicOnError(spot)
//
// {"data":{"base":"BTC","currency":"USD","amount":"48691.23"}}
//
ask:= (<-this.V2PublicGetPricesSymbolBuy(request))
PanicOnError(ask)
//
// {"data":{"base":"BTC","currency":"USD","amount":"48691.23"}}
//
bid:= (<-this.V2PublicGetPricesSymbolSell(request))
PanicOnError(bid)
//
// {"data":{"base":"BTC","currency":"USD","amount":"48691.23"}}
//
var spotData interface{} = this.SafeDict(spot, "data", map[string]interface{} {})
var askData interface{} = this.SafeDict(ask, "data", map[string]interface{} {})
var bidData interface{} = this.SafeDict(bid, "data", map[string]interface{} {})
var bidAskLast interface{} = map[string]interface{} {
"bid": this.SafeNumber(bidData, "amount"),
"ask": this.SafeNumber(askData, "amount"),
"price": this.SafeNumber(spotData, "amount"),
}
ch <- this.ParseTicker(bidAskLast, market)
return nil
}()
return ch
}
func (this *coinbase) FetchTickerV3(symbol interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
retRes21328 := (<-this.LoadMarkets())
PanicOnError(retRes21328)
var market interface{} = this.Market(symbol)
var request interface{} = map[string]interface{} {
"product_id": GetValue(market, "id"),
"limit": 1,
}
var usePrivate interface{} = false
usePrivateparamsVariable := this.HandleOptionAndParams(params, "fetchTicker", "usePrivate", false);
usePrivate = GetValue(usePrivateparamsVariable,0);
params = GetValue(usePrivateparamsVariable,1)
var response interface{} = nil
if IsTrue(usePrivate) {
response = (<-this.V3PrivateGetBrokerageProductsProductIdTicker(this.Extend(request, params)))
PanicOnError(response)
} else {
response = (<-this.V3PublicGetBrokerageMarketProductsProductIdTicker(this.Extend(request, params)))
PanicOnError(response)
}
//
// {
// "trades": [
// {
// "trade_id": "518078013",
// "product_id": "BTC-USD",
// "price": "28208.1",
// "size": "0.00659179",
// "time": "2023-04-04T23:05:34.492746Z",
// "side": "BUY",
// "bid": "",
// "ask": ""
// }
// ],
// "best_bid": "28208.61",
// "best_ask": "28208.62"
// }
//
var data interface{} = this.SafeList(response, "trades", []interface{}{})
var ticker interface{} = this.ParseTicker(GetValue(data, 0), market)
AddElementToObject(ticker, "bid", this.SafeNumber(response, "best_bid"))
AddElementToObject(ticker, "ask", this.SafeNumber(response, "best_ask"))
ch <- ticker
return nil
}()
return ch
}
func (this *coinbase) ParseTicker(ticker interface{}, optionalArgs ...interface{}) interface{} {
//
// fetchTickerV2
//
// {
// "bid": 20713.37,
// "ask": 20924.65,
// "price": 20809.83
// }
//
// fetchTickerV3
//
// {
// "trade_id": "10209805",
// "product_id": "BTC-USDT",
// "price": "19381.27",
// "size": "0.1",
// "time": "2023-01-13T20:35:41.865970Z",
// "side": "BUY",
// "bid": "",
// "ask": ""
// }
//
// fetchTickersV2
//
// "48691.23"
//
// fetchTickersV3
//
// [
// {
// "product_id": "TONE-USD",
// "price": "0.01523",
// "price_percentage_change_24h": "1.94109772423025",
// "volume_24h": "19773129",
// "volume_percentage_change_24h": "437.0170530929949",
// "base_increment": "1",
// "quote_increment": "0.00001",
// "quote_min_size": "1",
// "quote_max_size": "10000000",
// "base_min_size": "26.7187147229469674",
// "base_max_size": "267187147.2294696735908216",
// "base_name": "TE-FOOD",
// "quote_name": "US Dollar",
// "watched": false,
// "is_disabled": false,
// "new": false,
// "status": "online",
// "cancel_only": false,
// "limit_only": false,
// "post_only": false,
// "trading_disabled": false,
// "auction_mode": false,
// "product_type": "SPOT",
// "quote_currency_id": "USD",
// "base_currency_id": "TONE",
// "fcm_trading_session_details": null,
// "mid_market_price": ""
// },
// ...
// ]
//
// fetchBidsAsks
//
// {
// "product_id": "TRAC-EUR",
// "bids": [
// {
// "price": "0.2384",
// "size": "386.1"
// }
// ],
// "asks": [
// {
// "price": "0.2406",
// "size": "672"
// }
// ],
// "time": "2023-06-30T07:15:24.656044Z"
// }
//
market := GetArg(optionalArgs, 0, nil)
_ = market
var bid interface{} = this.SafeNumber(ticker, "bid")
var ask interface{} = this.SafeNumber(ticker, "ask")
var bidVolume interface{} = nil
var askVolume interface{} = nil
if IsTrue((InOp(ticker, "bids"))) {
var bids interface{} = this.SafeList(ticker, "bids", []interface{}{})
var asks interface{} = this.SafeList(ticker, "asks", []interface{}{})
bid = this.SafeNumber(GetValue(bids, 0), "price")
bidVolume = this.SafeNumber(GetValue(bids, 0), "size")
ask = this.SafeNumber(GetValue(asks, 0), "price")
askVolume = this.SafeNumber(GetValue(asks, 0), "size")
}
var marketId interface{} = this.SafeString(ticker, "product_id")
var last interface{} = this.SafeNumber(ticker, "price")
var datetime interface{} = this.SafeString(ticker, "time")
return this.SafeTicker(map[string]interface{} {
"symbol": this.SafeSymbol(marketId, market),
"timestamp": this.Parse8601(datetime),
"datetime": datetime,
"bid": bid,
"ask": ask,
"last": last,
"high": nil,
"low": nil,
"bidVolume": bidVolume,
"askVolume": askVolume,
"vwap": nil,
"open": nil,
"close": last,
"previousClose": nil,
"change": nil,
"percentage": this.SafeNumber(ticker, "price_percentage_change_24h"),
"average": nil,
"baseVolume": nil,
"quoteVolume": nil,
"info": ticker,
}, market)
}
func (this *coinbase) ParseCustomBalance(response interface{}, optionalArgs ...interface{}) interface{} {
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
var balances interface{} = this.SafeList2(response, "data", "accounts", []interface{}{})
var accounts interface{} = this.SafeList(params, "type", GetValue(this.Options, "accounts"))
var v3Accounts interface{} = this.SafeList(params, "type", GetValue(this.Options, "v3Accounts"))
var result interface{} = map[string]interface{} {
"info": response,
}
for b := 0; IsLessThan(b, GetArrayLength(balances)); b++ {
var balance interface{} = GetValue(balances, b)
var typeVar interface{} = this.SafeString(balance, "type")
if IsTrue(this.InArray(typeVar, accounts)) {
var value interface{} = this.SafeDict(balance, "balance")
if IsTrue(!IsEqual(value, nil)) {
var currencyId interface{} = this.SafeString(value, "currency")
var code interface{} = this.SafeCurrencyCode(currencyId)
var total interface{} = this.SafeString(value, "amount")
var free interface{} = total
var account interface{} = this.SafeDict(result, code)
if IsTrue(IsEqual(account, nil)) {
account = this.Account()
AddElementToObject(account, "free", free)
AddElementToObject(account, "total", total)
} else {
AddElementToObject(account, "free", Precise.StringAdd(GetValue(account, "free"), total))
AddElementToObject(account, "total", Precise.StringAdd(GetValue(account, "total"), total))
}
AddElementToObject(result, code, account)
}
} else if IsTrue(this.InArray(typeVar, v3Accounts)) {
var available interface{} = this.SafeDict(balance, "available_balance")
var hold interface{} = this.SafeDict(balance, "hold")
if IsTrue(IsTrue(!IsEqual(available, nil)) && IsTrue(!IsEqual(hold, nil))) {
var currencyId interface{} = this.SafeString(available, "currency")
var code interface{} = this.SafeCurrencyCode(currencyId)
var used interface{} = this.SafeString(hold, "value")
var free interface{} = this.SafeString(available, "value")
var total interface{} = Precise.StringAdd(used, free)
var account interface{} = this.SafeDict(result, code)
if IsTrue(IsEqual(account, nil)) {
account = this.Account()
AddElementToObject(account, "free", free)
AddElementToObject(account, "used", used)
AddElementToObject(account, "total", total)
} else {
AddElementToObject(account, "free", Precise.StringAdd(GetValue(account, "free"), free))
AddElementToObject(account, "used", Precise.StringAdd(GetValue(account, "used"), used))
AddElementToObject(account, "total", Precise.StringAdd(GetValue(account, "total"), total))
}
AddElementToObject(result, code, account)
}
}
}
return this.SafeBalance(result)
}
/**
* @method
* @name coinbase#fetchBalance
* @description query for balance and get the amount of funds available for trading or funds locked in orders
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getaccounts
* @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-accounts#list-accounts
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getfcmbalancesummary
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {boolean} [params.v3] default false, set true to use v3 api endpoint
* @param {string} [params.type] "spot" (default) or "swap" or "future"
* @param {int} [params.limit] default 250, maximum number of accounts to return
* @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
*/
func (this *coinbase) FetchBalance(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
retRes23588 := (<-this.LoadMarkets())
PanicOnError(retRes23588)
var request interface{} = map[string]interface{} {}
var response interface{} = nil
var isV3 interface{} = this.SafeBool(params, "v3", false)
params = this.Omit(params, []interface{}{"v3"})
var marketType interface{} = nil
marketTypeparamsVariable := this.HandleMarketTypeAndParams("fetchBalance", nil, params);
marketType = GetValue(marketTypeparamsVariable,0);
params = GetValue(marketTypeparamsVariable,1)
var method interface{} = this.SafeString(this.Options, "fetchBalance", "v3PrivateGetBrokerageAccounts")
if IsTrue(IsEqual(marketType, "future")) {
response = (<-this.V3PrivateGetBrokerageCfmBalanceSummary(this.Extend(request, params)))
PanicOnError(response)
} else if IsTrue(IsTrue((isV3)) || IsTrue((IsEqual(method, "v3PrivateGetBrokerageAccounts")))) {
AddElementToObject(request, "limit", 250)
response = (<-this.V3PrivateGetBrokerageAccounts(this.Extend(request, params)))
PanicOnError(response)
} else {
AddElementToObject(request, "limit", 250)
response = (<-this.V2PrivateGetAccounts(this.Extend(request, params)))
PanicOnError(response)
}
//
// v2PrivateGetAccounts
// {
// "pagination":{
// "ending_before":null,
// "starting_after":null,
// "previous_ending_before":null,
// "next_starting_after":"6b17acd6-2e68-5eb0-9f45-72d67cef578b",
// "limit":100,
// "order":"desc",
// "previous_uri":null,
// "next_uri":"/v2/accounts?limit=100\u0026starting_after=6b17acd6-2e68-5eb0-9f45-72d67cef578b"
// },
// "data":[
// {
// "id":"94ad58bc-0f15-5309-b35a-a4c86d7bad60",
// "name":"MINA Wallet",
// "primary":false,
// "type":"wallet",
// "currency":{
// "code":"MINA",
// "name":"Mina",
// "color":"#EA6B48",
// "sort_index":397,
// "exponent":9,
// "type":"crypto",
// "address_regex":"^(B62)[A-Za-z0-9]{52}$",
// "asset_id":"a4ffc575-942c-5e26-b70c-cb3befdd4229",
// "slug":"mina"
// },
// "balance":{"amount":"0.000000000","currency":"MINA"},
// "created_at":"2022-03-25T00:36:16Z",
// "updated_at":"2022-03-25T00:36:16Z",
// "resource":"account",
// "resource_path":"/v2/accounts/94ad58bc-0f15-5309-b35a-a4c86d7bad60",
// "allow_deposits":true,
// "allow_withdrawals":true
// },
// ]
// }
//
// v3PrivateGetBrokerageAccounts
// {
// "accounts": [
// {
// "uuid": "11111111-1111-1111-1111-111111111111",
// "name": "USDC Wallet",
// "currency": "USDC",
// "available_balance": {
// "value": "0.0000000000000000",
// "currency": "USDC"
// },
// "default": true,
// "active": true,
// "created_at": "2023-01-04T06:20:06.456Z",
// "updated_at": "2023-01-04T06:20:07.181Z",
// "deleted_at": null,
// "type": "ACCOUNT_TYPE_CRYPTO",
// "ready": false,
// "hold": {
// "value": "0.0000000000000000",
// "currency": "USDC"
// }
// },
// ...
// ],
// "has_next": false,
// "cursor": "",
// "size": 9
// }
//
AddElementToObject(params, "type", marketType)
ch <- this.ParseCustomBalance(response, params)
return nil
}()
return ch
}
/**
* @method
* @name coinbase#fetchLedger
* @description 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.
* @see https://docs.cdp.coinbase.com/coinbase-app/docs/api-transactions#list-transactions
* @param {string} [code] unified currency code, default is undefined
* @param {int} [since] timestamp in ms of the earliest ledger entry, default is undefined
* @param {int} [limit] max number of ledger entries to return, default is undefined
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
* @returns {object} a [ledger structure]{@link https://docs.ccxt.com/#/?id=ledger}
*/
func (this *coinbase) FetchLedger(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
code := GetArg(optionalArgs, 0, nil)
_ = code
since := GetArg(optionalArgs, 1, nil)
_ = since
limit := GetArg(optionalArgs, 2, nil)
_ = limit
params := GetArg(optionalArgs, 3, map[string]interface{} {})
_ = params
retRes24638 := (<-this.LoadMarkets())
PanicOnError(retRes24638)
var paginate interface{} = false
paginateparamsVariable := this.HandleOptionAndParams(params, "fetchLedger", "paginate");
paginate = GetValue(paginateparamsVariable,0);
params = GetValue(paginateparamsVariable,1)
if IsTrue(paginate) {
retRes246719 := (<-this.FetchPaginatedCallCursor("fetchLedger", code, since, limit, params, "next_starting_after", "starting_after", nil, 100))
PanicOnError(retRes246719)
ch <- retRes246719
return nil
}
var currency interface{} = nil
if IsTrue(!IsEqual(code, nil)) {
currency = this.Currency(code)
}
var request interface{} = nil
requestparamsVariable := (<-this.PrepareAccountRequestWithCurrencyCode(code, limit, params));
request = GetValue(requestparamsVariable,0);
params = GetValue(requestparamsVariable,1)
// for pagination use parameter 'starting_after'
// the value for the next page can be obtained from the result of the previous call in the 'pagination' field
// eg: instance.last_http_response -> pagination.next_starting_after
response:= (<-this.V2PrivateGetAccountsAccountIdTransactions(this.Extend(request, params)))
PanicOnError(response)
var ledger interface{} = this.ParseLedger(GetValue(response, "data"), currency, since, limit)
var length interface{} = GetArrayLength(ledger)
if IsTrue(IsEqual(length, 0)) {
ch <- ledger
return nil
}
var lastIndex interface{} = Subtract(length, 1)
var last interface{} = this.SafeDict(ledger, lastIndex)
var pagination interface{} = this.SafeDict(response, "pagination", map[string]interface{} {})
var cursor interface{} = this.SafeString(pagination, "next_starting_after")
if IsTrue(IsTrue((!IsEqual(cursor, nil))) && IsTrue((!IsEqual(cursor, "")))) {
AddElementToObject(GetValue(last, "info"), "next_starting_after", cursor)
AddElementToObject(ledger, lastIndex, last)
}
ch <- ledger
return nil
}()
return ch
}
func (this *coinbase) ParseLedgerEntryStatus(status interface{}) interface{} {
var types interface{} = map[string]interface{} {
"completed": "ok",
}
return this.SafeString(types, status, status)
}
func (this *coinbase) ParseLedgerEntryType(typeVar interface{}) interface{} {
var types interface{} = map[string]interface{} {
"buy": "trade",
"sell": "trade",
"fiat_deposit": "transaction",
"fiat_withdrawal": "transaction",
"exchange_deposit": "transaction",
"exchange_withdrawal": "transaction",
"send": "transaction",
"pro_deposit": "transaction",
"pro_withdrawal": "transaction",
}
return this.SafeString(types, typeVar, typeVar)
}
func (this *coinbase) ParseLedgerEntry(item interface{}, optionalArgs ...interface{}) interface{} {
//
// crypto deposit transaction
//
// {
// "id": "34e4816b-4c8c-5323-a01c-35a9fa26e490",
// "type": "send",
// "status": "completed",
// "amount": { amount: "28.31976528", currency: "BCH" },
// "native_amount": { amount: "2799.65", currency: "GBP" },
// "description": null,
// "created_at": "2019-02-28T12:35:20Z",
// "updated_at": "2019-02-28T12:43:24Z",
// "resource": "transaction",
// "resource_path": "/v2/accounts/c01d7364-edd7-5f3a-bd1d-de53d4cbb25e/transactions/34e4816b-4c8c-5323-a01c-35a9fa26e490",
// "instant_exchange": false,
// "network": {
// "status": "confirmed",
// "hash": "56222d865dae83774fccb2efbd9829cf08c75c94ce135bfe4276f3fb46d49701",
// "transaction_url": "https://bch.btc.com/56222d865dae83774fccb2efbd9829cf08c75c94ce135bfe4276f3fb46d49701"
// },
// "from": { resource: "bitcoin_cash_network", currency: "BCH" },
// "details": { title: 'Received Bitcoin Cash', subtitle: "From Bitcoin Cash address" }
// }
//
// crypto withdrawal transaction
//
// {
// "id": "459aad99-2c41-5698-ac71-b6b81a05196c",
// "type": "send",
// "status": "completed",
// "amount": { amount: "-0.36775642", currency: "BTC" },
// "native_amount": { amount: "-1111.65", currency: "GBP" },
// "description": null,
// "created_at": "2019-03-20T08:37:07Z",
// "updated_at": "2019-03-20T08:49:33Z",
// "resource": "transaction",
// "resource_path": "/v2/accounts/c6afbd34-4bd0-501e-8616-4862c193cd84/transactions/459aad99-2c41-5698-ac71-b6b81a05196c",
// "instant_exchange": false,
// "network": {
// "status": "confirmed",
// "hash": "2732bbcf35c69217c47b36dce64933d103895277fe25738ffb9284092701e05b",
// "transaction_url": "https://blockchain.info/tx/2732bbcf35c69217c47b36dce64933d103895277fe25738ffb9284092701e05b",
// "transaction_fee": { amount: "0.00000000", currency: "BTC" },
// "transaction_amount": { amount: "0.36775642", currency: "BTC" },
// "confirmations": 15682
// },
// "to": {
// "resource": "bitcoin_address",
// "address": "1AHnhqbvbYx3rnZx8uC7NbFZaTe4tafFHX",
// "currency": "BTC",
// "address_info": { address: "1AHnhqbvbYx3rnZx8uC7NbFZaTe4tafFHX" }
// },
// "idem": "da0a2f14-a2af-4c5a-a37e-d4484caf582bsend",
// "application": {
// "id": "5756ab6e-836b-553b-8950-5e389451225d",
// "resource": "application",
// "resource_path": "/v2/applications/5756ab6e-836b-553b-8950-5e389451225d"
// },
// "details": { title: 'Sent Bitcoin', subtitle: "To Bitcoin address" }
// }
//
// withdrawal transaction from coinbase to coinbasepro
//
// {
// "id": "5b1b9fb8-5007-5393-b923-02903b973fdc",
// "type": "pro_deposit",
// "status": "completed",
// "amount": { amount: "-0.00001111", currency: "BCH" },
// "native_amount": { amount: "0.00", currency: "GBP" },
// "description": null,
// "created_at": "2019-02-28T13:31:58Z",
// "updated_at": "2019-02-28T13:31:58Z",
// "resource": "transaction",
// "resource_path": "/v2/accounts/c01d7364-edd7-5f3a-bd1d-de53d4cbb25e/transactions/5b1b9fb8-5007-5393-b923-02903b973fdc",
// "instant_exchange": false,
// "application": {
// "id": "5756ab6e-836b-553b-8950-5e389451225d",
// "resource": "application",
// "resource_path": "/v2/applications/5756ab6e-836b-553b-8950-5e389451225d"
// },
// "details": { title: 'Transferred Bitcoin Cash', subtitle: "To Coinbase Pro" }
// }
//
// withdrawal transaction from coinbase to gdax
//
// {
// "id": "badb7313-a9d3-5c07-abd0-00f8b44199b1",
// "type": "exchange_deposit",
// "status": "completed",
// "amount": { amount: "-0.43704149", currency: "BCH" },
// "native_amount": { amount: "-51.90", currency: "GBP" },
// "description": null,
// "created_at": "2019-03-19T10:30:40Z",
// "updated_at": "2019-03-19T10:30:40Z",
// "resource": "transaction",
// "resource_path": "/v2/accounts/c01d7364-edd7-5f3a-bd1d-de53d4cbb25e/transactions/badb7313-a9d3-5c07-abd0-00f8b44199b1",
// "instant_exchange": false,
// "details": { title: 'Transferred Bitcoin Cash', subtitle: "To GDAX" }
// }
//
// deposit transaction from gdax to coinbase
//
// {
// "id": "9c4b642c-8688-58bf-8962-13cef64097de",
// "type": "exchange_withdrawal",
// "status": "completed",
// "amount": { amount: "0.57729420", currency: "BTC" },
// "native_amount": { amount: "4418.72", currency: "GBP" },
// "description": null,
// "created_at": "2018-02-17T11:33:33Z",
// "updated_at": "2018-02-17T11:33:33Z",
// "resource": "transaction",
// "resource_path": "/v2/accounts/c6afbd34-4bd0-501e-8616-4862c193cd84/transactions/9c4b642c-8688-58bf-8962-13cef64097de",
// "instant_exchange": false,
// "details": { title: 'Transferred Bitcoin', subtitle: "From GDAX" }
// }
//
// deposit transaction from coinbasepro to coinbase
//
// {
// "id": "8d6dd0b9-3416-568a-889d-8f112fae9e81",
// "type": "pro_withdrawal",
// "status": "completed",
// "amount": { amount: "0.40555386", currency: "BTC" },
// "native_amount": { amount: "1140.27", currency: "GBP" },
// "description": null,
// "created_at": "2019-03-04T19:41:58Z",
// "updated_at": "2019-03-04T19:41:58Z",
// "resource": "transaction",
// "resource_path": "/v2/accounts/c6afbd34-4bd0-501e-8616-4862c193cd84/transactions/8d6dd0b9-3416-568a-889d-8f112fae9e81",
// "instant_exchange": false,
// "application": {
// "id": "5756ab6e-836b-553b-8950-5e389451225d",
// "resource": "application",
// "resource_path": "/v2/applications/5756ab6e-836b-553b-8950-5e389451225d"
// },
// "details": { title: 'Transferred Bitcoin', subtitle: "From Coinbase Pro" }
// }
//
// sell trade
//
// {
// "id": "a9409207-df64-585b-97ab-a50780d2149e",
// "type": "sell",
// "status": "completed",
// "amount": { amount: "-9.09922880", currency: "BTC" },
// "native_amount": { amount: "-7285.73", currency: "GBP" },
// "description": null,
// "created_at": "2017-03-27T15:38:34Z",
// "updated_at": "2017-03-27T15:38:34Z",
// "resource": "transaction",
// "resource_path": "/v2/accounts/c6afbd34-4bd0-501e-8616-4862c193cd84/transactions/a9409207-df64-585b-97ab-a50780d2149e",
// "instant_exchange": false,
// "sell": {
// "id": "e3550b4d-8ae6-5de3-95fe-1fb01ba83051",
// "resource": "sell",
// "resource_path": "/v2/accounts/c6afbd34-4bd0-501e-8616-4862c193cd84/sells/e3550b4d-8ae6-5de3-95fe-1fb01ba83051"
// },
// "details": {
// "title": "Sold Bitcoin",
// "subtitle": "Using EUR Wallet",
// "payment_method_name": "EUR Wallet"
// }
// }
//
// buy trade
//
// {
// "id": "63eeed67-9396-5912-86e9-73c4f10fe147",
// "type": "buy",
// "status": "completed",
// "amount": { amount: "2.39605772", currency: "ETH" },
// "native_amount": { amount: "98.31", currency: "GBP" },
// "description": null,
// "created_at": "2017-03-27T09:07:56Z",
// "updated_at": "2017-03-27T09:07:57Z",
// "resource": "transaction",
// "resource_path": "/v2/accounts/8902f85d-4a69-5d74-82fe-8e390201bda7/transactions/63eeed67-9396-5912-86e9-73c4f10fe147",
// "instant_exchange": false,
// "buy": {
// "id": "20b25b36-76c6-5353-aa57-b06a29a39d82",
// "resource": "buy",
// "resource_path": "/v2/accounts/8902f85d-4a69-5d74-82fe-8e390201bda7/buys/20b25b36-76c6-5353-aa57-b06a29a39d82"
// },
// "details": {
// "title": "Bought Ethereum",
// "subtitle": "Using EUR Wallet",
// "payment_method_name": "EUR Wallet"
// }
// }
//
// fiat deposit transaction
//
// {
// "id": "04ed4113-3732-5b0c-af86-b1d2146977d0",
// "type": "fiat_deposit",
// "status": "completed",
// "amount": { amount: "114.02", currency: "EUR" },
// "native_amount": { amount: "97.23", currency: "GBP" },
// "description": null,
// "created_at": "2017-02-09T07:01:21Z",
// "updated_at": "2017-02-09T07:01:22Z",
// "resource": "transaction",
// "resource_path": "/v2/accounts/91cd2d36-3a91-55b6-a5d4-0124cf105483/transactions/04ed4113-3732-5b0c-af86-b1d2146977d0",
// "instant_exchange": false,
// "fiat_deposit": {
// "id": "f34c19f3-b730-5e3d-9f72-96520448677a",
// "resource": "fiat_deposit",
// "resource_path": "/v2/accounts/91cd2d36-3a91-55b6-a5d4-0124cf105483/deposits/f34c19f3-b730-5e3d-9f72-96520448677a"
// },
// "details": {
// "title": "Deposited funds",
// "subtitle": "From SEPA Transfer (GB47 BARC 20..., reference CBADVI)",
// "payment_method_name": "SEPA Transfer (GB47 BARC 20..., reference CBADVI)"
// }
// }
//
// fiat withdrawal transaction
//
// {
// "id": "957d98e2-f80e-5e2f-a28e-02945aa93079",
// "type": "fiat_withdrawal",
// "status": "completed",
// "amount": { amount: "-11000.00", currency: "EUR" },
// "native_amount": { amount: "-9698.22", currency: "GBP" },
// "description": null,
// "created_at": "2017-12-06T13:19:19Z",
// "updated_at": "2017-12-06T13:19:19Z",
// "resource": "transaction",
// "resource_path": "/v2/accounts/91cd2d36-3a91-55b6-a5d4-0124cf105483/transactions/957d98e2-f80e-5e2f-a28e-02945aa93079",
// "instant_exchange": false,
// "fiat_withdrawal": {
// "id": "f4bf1fd9-ab3b-5de7-906d-ed3e23f7a4e7",
// "resource": "fiat_withdrawal",
// "resource_path": "/v2/accounts/91cd2d36-3a91-55b6-a5d4-0124cf105483/withdrawals/f4bf1fd9-ab3b-5de7-906d-ed3e23f7a4e7"
// },
// "details": {
// "title": "Withdrew funds",
// "subtitle": "To HSBC BANK PLC (GB74 MIDL...)",
// "payment_method_name": "HSBC BANK PLC (GB74 MIDL...)"
// }
// }
//
currency := GetArg(optionalArgs, 0, nil)
_ = currency
var amountInfo interface{} = this.SafeDict(item, "amount", map[string]interface{} {})
var amount interface{} = this.SafeString(amountInfo, "amount")
var direction interface{} = nil
if IsTrue(Precise.StringLt(amount, "0")) {
direction = "out"
amount = Precise.StringNeg(amount)
} else {
direction = "in"
}
var currencyId interface{} = this.SafeString(amountInfo, "currency")
var code interface{} = this.SafeCurrencyCode(currencyId, currency)
currency = this.SafeCurrency(currencyId, currency)
//
// the address and txid do not belong to the unified ledger structure
//
// let address = undefined;
// if (item['to']) {
// address = this.safeString (item['to'], 'address');
// }
// let txid = undefined;
//
var fee interface{} = nil
var networkInfo interface{} = this.SafeDict(item, "network", map[string]interface{} {})
// txid = network['hash']; // txid does not belong to the unified ledger structure
var feeInfo interface{} = this.SafeDict(networkInfo, "transaction_fee")
if IsTrue(!IsEqual(feeInfo, nil)) {
var feeCurrencyId interface{} = this.SafeString(feeInfo, "currency")
var feeCurrencyCode interface{} = this.SafeCurrencyCode(feeCurrencyId, currency)
var feeAmount interface{} = this.SafeNumber(feeInfo, "amount")
fee = map[string]interface{} {
"cost": feeAmount,
"currency": feeCurrencyCode,
}
}
var timestamp interface{} = this.Parse8601(this.SafeString(item, "created_at"))
var id interface{} = this.SafeString(item, "id")
var typeVar interface{} = this.ParseLedgerEntryType(this.SafeString(item, "type"))
var status interface{} = this.ParseLedgerEntryStatus(this.SafeString(item, "status"))
var path interface{} = this.SafeString(item, "resource_path")
var accountId interface{} = nil
if IsTrue(!IsEqual(path, nil)) {
var parts interface{} = Split(path, "/")
var numParts interface{} = GetArrayLength(parts)
if IsTrue(IsGreaterThan(numParts, 3)) {
accountId = GetValue(parts, 3)
}
}
return this.SafeLedgerEntry(map[string]interface{} {
"info": item,
"id": id,
"timestamp": timestamp,
"datetime": this.Iso8601(timestamp),
"direction": direction,
"account": accountId,
"referenceId": nil,
"referenceAccount": nil,
"type": typeVar,
"currency": code,
"amount": this.ParseNumber(amount),
"before": nil,
"after": nil,
"status": status,
"fee": fee,
}, currency)
}
func (this *coinbase) FindAccountId(code interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
retRes28288 := (<-this.LoadMarkets())
PanicOnError(retRes28288)
retRes28298 := (<-this.LoadAccounts(false, params))
PanicOnError(retRes28298)
for i := 0; IsLessThan(i, GetArrayLength(this.Accounts)); i++ {
var account interface{} = GetValue(this.Accounts, i)
if IsTrue(IsEqual(GetValue(account, "code"), code)) {
ch <- GetValue(account, "id")
return nil
}
}
return nil
}()
return ch
}
func (this *coinbase) PrepareAccountRequest(optionalArgs ...interface{}) interface{} {
limit := GetArg(optionalArgs, 0, nil)
_ = limit
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
var accountId interface{} = this.SafeString2(params, "account_id", "accountId")
if IsTrue(IsEqual(accountId, nil)) {
panic(ArgumentsRequired(Add(this.Id, " prepareAccountRequest() method requires an account_id (or accountId) parameter")))
}
var request interface{} = map[string]interface{} {
"account_id": accountId,
}
if IsTrue(!IsEqual(limit, nil)) {
AddElementToObject(request, "limit", limit)
}
return request
}
func (this *coinbase) PrepareAccountRequestWithCurrencyCode(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
code := GetArg(optionalArgs, 0, nil)
_ = code
limit := GetArg(optionalArgs, 1, nil)
_ = limit
params := GetArg(optionalArgs, 2, map[string]interface{} {})
_ = params
var accountId interface{} = this.SafeString2(params, "account_id", "accountId")
params = this.Omit(params, []interface{}{"account_id", "accountId"})
if IsTrue(IsEqual(accountId, nil)) {
if IsTrue(IsEqual(code, nil)) {
panic(ArgumentsRequired(Add(this.Id, " prepareAccountRequestWithCurrencyCode() method requires an account_id (or accountId) parameter OR a currency code argument")))
}
accountId = (<-this.FindAccountId(code, params))
PanicOnError(accountId)
if IsTrue(IsEqual(accountId, nil)) {
panic(ExchangeError(Add(Add(this.Id, " prepareAccountRequestWithCurrencyCode() could not find account id for "), code)))
}
}
var request interface{} = map[string]interface{} {
"account_id": accountId,
}
if IsTrue(!IsEqual(limit, nil)) {
AddElementToObject(request, "limit", limit)
}
ch <- []interface{}{request, params}
return nil
}()
return ch
}
/**
* @method
* @name coinbase#createMarketBuyOrderWithCost
* @description create a market buy order by providing the symbol and cost
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_postorder
* @param {string} symbol unified symbol of the market to create an order in
* @param {float} cost how much you want to trade in units of the quote currency
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
func (this *coinbase) CreateMarketBuyOrderWithCost(symbol interface{}, cost interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
retRes28858 := (<-this.LoadMarkets())
PanicOnError(retRes28858)
var market interface{} = this.Market(symbol)
if !IsTrue(GetValue(market, "spot")) {
panic(NotSupported(Add(this.Id, " createMarketBuyOrderWithCost() supports spot orders only")))
}
AddElementToObject(params, "createMarketBuyOrderRequiresPrice", false)
retRes289115 := (<-this.CreateOrder(symbol, "market", "buy", cost, nil, params))
PanicOnError(retRes289115)
ch <- retRes289115
return nil
}()
return ch
}
/**
* @method
* @name coinbase#createOrder
* @description create a trade order
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_postorder
* @param {string} symbol unified symbol of the market to create an order in
* @param {string} type 'market' or 'limit'
* @param {string} side 'buy' or 'sell'
* @param {float} amount how much you want to trade in units of the base currency, quote currency for 'market' 'buy' orders
* @param {float} [price] the price to fulfill the order, in units of the quote currency, ignored in market orders
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {float} [params.stopPrice] price to trigger stop orders
* @param {float} [params.triggerPrice] price to trigger stop orders
* @param {float} [params.stopLossPrice] price to trigger stop-loss orders
* @param {float} [params.takeProfitPrice] price to trigger take-profit orders
* @param {bool} [params.postOnly] true or false
* @param {string} [params.timeInForce] 'GTC', 'IOC', 'GTD' or 'PO', 'FOK'
* @param {string} [params.stop_direction] 'UNKNOWN_STOP_DIRECTION', 'STOP_DIRECTION_STOP_UP', 'STOP_DIRECTION_STOP_DOWN' the direction the stopPrice is triggered from
* @param {string} [params.end_time] '2023-05-25T17:01:05.092Z' for 'GTD' orders
* @param {float} [params.cost] *spot market buy only* the quote quantity that can be used as an alternative for the amount
* @param {boolean} [params.preview] default to false, wether to use the test/preview endpoint or not
* @param {float} [params.leverage] default to 1, the leverage to use for the order
* @param {string} [params.marginMode] 'cross' or 'isolated'
* @param {string} [params.retail_portfolio_id] portfolio uid
* @param {boolean} [params.is_max] Used in conjunction with tradable_balance to indicate the user wants to use their entire tradable balance
* @param {string} [params.tradable_balance] amount of tradable balance
* @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
func (this *coinbase) CreateOrder(symbol interface{}, typeVar interface{}, side interface{}, amount interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
price := GetArg(optionalArgs, 0, nil)
_ = price
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
retRes29238 := (<-this.LoadMarkets())
PanicOnError(retRes29238)
var market interface{} = this.Market(symbol)
var id interface{} = this.SafeString(this.Options, "brokerId", "ccxt")
var request interface{} = map[string]interface{} {
"client_order_id": Add(Add(id, "-"), this.Uuid()),
"product_id": GetValue(market, "id"),
"side": ToUpper(side),
}
var triggerPrice interface{} = this.SafeNumberN(params, []interface{}{"stopPrice", "stop_price", "triggerPrice"})
var stopLossPrice interface{} = this.SafeNumber(params, "stopLossPrice")
var takeProfitPrice interface{} = this.SafeNumber(params, "takeProfitPrice")
var isStop interface{} = !IsEqual(triggerPrice, nil)
var isStopLoss interface{} = !IsEqual(stopLossPrice, nil)
var isTakeProfit interface{} = !IsEqual(takeProfitPrice, nil)
var timeInForce interface{} = this.SafeString(params, "timeInForce")
var postOnly interface{} = Ternary(IsTrue((IsEqual(timeInForce, "PO"))), true, this.SafeBool2(params, "postOnly", "post_only", false))
var endTime interface{} = this.SafeString(params, "end_time")
var stopDirection interface{} = this.SafeString(params, "stop_direction")
if IsTrue(IsEqual(typeVar, "limit")) {
if IsTrue(isStop) {
if IsTrue(IsEqual(stopDirection, nil)) {
stopDirection = Ternary(IsTrue((IsEqual(side, "buy"))), "STOP_DIRECTION_STOP_DOWN", "STOP_DIRECTION_STOP_UP")
}
if IsTrue(IsTrue((IsEqual(timeInForce, "GTD"))) || IsTrue((!IsEqual(endTime, nil)))) {
if IsTrue(IsEqual(endTime, nil)) {
panic(ExchangeError(Add(this.Id, " createOrder() requires an end_time parameter for a GTD order")))
}
AddElementToObject(request, "order_configuration", map[string]interface{} {
"stop_limit_stop_limit_gtd": map[string]interface{} {
"base_size": this.AmountToPrecision(symbol, amount),
"limit_price": this.PriceToPrecision(symbol, price),
"stop_price": this.PriceToPrecision(symbol, triggerPrice),
"stop_direction": stopDirection,
"end_time": endTime,
},
})
} else {
AddElementToObject(request, "order_configuration", map[string]interface{} {
"stop_limit_stop_limit_gtc": map[string]interface{} {
"base_size": this.AmountToPrecision(symbol, amount),
"limit_price": this.PriceToPrecision(symbol, price),
"stop_price": this.PriceToPrecision(symbol, triggerPrice),
"stop_direction": stopDirection,
},
})
}
} else if IsTrue(IsTrue(isStopLoss) || IsTrue(isTakeProfit)) {
var tpslPrice interface{} = nil
if IsTrue(isStopLoss) {
if IsTrue(IsEqual(stopDirection, nil)) {
stopDirection = Ternary(IsTrue((IsEqual(side, "buy"))), "STOP_DIRECTION_STOP_UP", "STOP_DIRECTION_STOP_DOWN")
}
tpslPrice = this.PriceToPrecision(symbol, stopLossPrice)
} else {
if IsTrue(IsEqual(stopDirection, nil)) {
stopDirection = Ternary(IsTrue((IsEqual(side, "buy"))), "STOP_DIRECTION_STOP_DOWN", "STOP_DIRECTION_STOP_UP")
}
tpslPrice = this.PriceToPrecision(symbol, takeProfitPrice)
}
AddElementToObject(request, "order_configuration", map[string]interface{} {
"stop_limit_stop_limit_gtc": map[string]interface{} {
"base_size": this.AmountToPrecision(symbol, amount),
"limit_price": this.PriceToPrecision(symbol, price),
"stop_price": tpslPrice,
"stop_direction": stopDirection,
},
})
} else {
if IsTrue(IsTrue((IsEqual(timeInForce, "GTD"))) || IsTrue((!IsEqual(endTime, nil)))) {
if IsTrue(IsEqual(endTime, nil)) {
panic(ExchangeError(Add(this.Id, " createOrder() requires an end_time parameter for a GTD order")))
}
AddElementToObject(request, "order_configuration", map[string]interface{} {
"limit_limit_gtd": map[string]interface{} {
"base_size": this.AmountToPrecision(symbol, amount),
"limit_price": this.PriceToPrecision(symbol, price),
"end_time": endTime,
"post_only": postOnly,
},
})
} else if IsTrue(IsEqual(timeInForce, "IOC")) {
AddElementToObject(request, "order_configuration", map[string]interface{} {
"sor_limit_ioc": map[string]interface{} {
"base_size": this.AmountToPrecision(symbol, amount),
"limit_price": this.PriceToPrecision(symbol, price),
},
})
} else if IsTrue(IsEqual(timeInForce, "FOK")) {
AddElementToObject(request, "order_configuration", map[string]interface{} {
"limit_limit_fok": map[string]interface{} {
"base_size": this.AmountToPrecision(symbol, amount),
"limit_price": this.PriceToPrecision(symbol, price),
},
})
} else {
AddElementToObject(request, "order_configuration", map[string]interface{} {
"limit_limit_gtc": map[string]interface{} {
"base_size": this.AmountToPrecision(symbol, amount),
"limit_price": this.PriceToPrecision(symbol, price),
"post_only": postOnly,
},
})
}
}
} else {
if IsTrue(IsTrue(IsTrue(isStop) || IsTrue(isStopLoss)) || IsTrue(isTakeProfit)) {
panic(NotSupported(Add(this.Id, " createOrder() only stop limit orders are supported")))
}
if IsTrue(IsTrue(GetValue(market, "spot")) && IsTrue((IsEqual(side, "buy")))) {
var total interface{} = nil
var createMarketBuyOrderRequiresPrice interface{} = true
createMarketBuyOrderRequiresPriceparamsVariable := this.HandleOptionAndParams(params, "createOrder", "createMarketBuyOrderRequiresPrice", true);
createMarketBuyOrderRequiresPrice = GetValue(createMarketBuyOrderRequiresPriceparamsVariable,0);
params = GetValue(createMarketBuyOrderRequiresPriceparamsVariable,1)
var cost interface{} = this.SafeNumber(params, "cost")
params = this.Omit(params, "cost")
if IsTrue(!IsEqual(cost, nil)) {
total = this.CostToPrecision(symbol, cost)
} else if IsTrue(createMarketBuyOrderRequiresPrice) {
if IsTrue(IsEqual(price, nil)) {
panic(InvalidOrder(Add(this.Id, " createOrder() requires a price argument for market buy orders on spot markets to calculate the total amount to spend (amount * price), alternatively set the createMarketBuyOrderRequiresPrice option or param to false and pass the cost to spend in the amount argument")))
} else {
var amountString interface{} = this.NumberToString(amount)
var priceString interface{} = this.NumberToString(price)
var costRequest interface{} = Precise.StringMul(amountString, priceString)
total = this.CostToPrecision(symbol, costRequest)
}
} else {
total = this.CostToPrecision(symbol, amount)
}
AddElementToObject(request, "order_configuration", map[string]interface{} {
"market_market_ioc": map[string]interface{} {
"quote_size": total,
},
})
} else {
AddElementToObject(request, "order_configuration", map[string]interface{} {
"market_market_ioc": map[string]interface{} {
"base_size": this.AmountToPrecision(symbol, amount),
},
})
}
}
var marginMode interface{} = this.SafeString(params, "marginMode")
if IsTrue(!IsEqual(marginMode, nil)) {
if IsTrue(IsEqual(marginMode, "isolated")) {
AddElementToObject(request, "margin_type", "ISOLATED")
} else if IsTrue(IsEqual(marginMode, "cross")) {
AddElementToObject(request, "margin_type", "CROSS")
}
}
params = this.Omit(params, []interface{}{"timeInForce", "triggerPrice", "stopLossPrice", "takeProfitPrice", "stopPrice", "stop_price", "stopDirection", "stop_direction", "clientOrderId", "postOnly", "post_only", "end_time", "marginMode"})
var preview interface{} = this.SafeBool2(params, "preview", "test", false)
var response interface{} = nil
if IsTrue(preview) {
params = this.Omit(params, []interface{}{"preview", "test"})
request = this.Omit(request, "client_order_id")
response = (<-this.V3PrivatePostBrokerageOrdersPreview(this.Extend(request, params)))
PanicOnError(response)
} else {
response = (<-this.V3PrivatePostBrokerageOrders(this.Extend(request, params)))
PanicOnError(response)
}
//
// successful order
//
// {
// "success": true,
// "failure_reason": "UNKNOWN_FAILURE_REASON",
// "order_id": "52cfe5e2-0b29-4c19-a245-a6a773de5030",
// "success_response": {
// "order_id": "52cfe5e2-0b29-4c19-a245-a6a773de5030",
// "product_id": "LTC-BTC",
// "side": "SELL",
// "client_order_id": "4d760580-6fca-4094-a70b-ebcca8626288"
// },
// "order_configuration": null
// }
//
// failed order
//
// {
// "success": false,
// "failure_reason": "UNKNOWN_FAILURE_REASON",
// "order_id": "",
// "error_response": {
// "error": "UNSUPPORTED_ORDER_CONFIGURATION",
// "message": "source is not enabled for trading",
// "error_details": "",
// "new_order_failure_reason": "UNSUPPORTED_ORDER_CONFIGURATION"
// },
// "order_configuration": {
// "limit_limit_gtc": {
// "base_size": "100",
// "limit_price": "40000",
// "post_only": false
// }
// }
// }
//
var success interface{} = this.SafeBool(response, "success")
if IsTrue(!IsEqual(success, true)) {
var errorResponse interface{} = this.SafeDict(response, "error_response")
var errorTitle interface{} = this.SafeString(errorResponse, "error")
var errorMessage interface{} = this.SafeString(errorResponse, "message")
if IsTrue(!IsEqual(errorResponse, nil)) {
this.ThrowExactlyMatchedException(GetValue(this.Exceptions, "exact"), errorTitle, errorMessage)
this.ThrowBroadlyMatchedException(GetValue(this.Exceptions, "broad"), errorTitle, errorMessage)
panic(ExchangeError(errorMessage))
}
}
var data interface{} = this.SafeDict(response, "success_response", map[string]interface{} {})
ch <- this.ParseOrder(data, market)
return nil
}()
return ch
}
func (this *coinbase) ParseOrder(order interface{}, optionalArgs ...interface{}) interface{} {
//
// createOrder
//
// {
// "order_id": "52cfe5e2-0b29-4c19-a245-a6a773de5030",
// "product_id": "LTC-BTC",
// "side": "SELL",
// "client_order_id": "4d760580-6fca-4094-a70b-ebcca8626288"
// }
//
// cancelOrder, cancelOrders
//
// {
// "success": true,
// "failure_reason": "UNKNOWN_CANCEL_FAILURE_REASON",
// "order_id": "bb8851a3-4fda-4a2c-aa06-9048db0e0f0d"
// }
//
// fetchOrder, fetchOrders, fetchOpenOrders, fetchClosedOrders, fetchCanceledOrders
//
// {
// "order_id": "9bc1eb3b-5b46-4b71-9628-ae2ed0cca75b",
// "product_id": "LTC-BTC",
// "user_id": "1111111-1111-1111-1111-111111111111",
// "order_configuration": {
// "limit_limit_gtc": {
// "base_size": "0.2",
// "limit_price": "0.006",
// "post_only": false
// },
// "stop_limit_stop_limit_gtc": {
// "base_size": "48.54",
// "limit_price": "6.998",
// "stop_price": "7.0687",
// "stop_direction": "STOP_DIRECTION_STOP_DOWN"
// }
// },
// "side": "SELL",
// "client_order_id": "e5fe8482-05bb-428f-ad4d-dbc8ce39239c",
// "status": "OPEN",
// "time_in_force": "GOOD_UNTIL_CANCELLED",
// "created_time": "2023-01-16T23:37:23.947030Z",
// "completion_percentage": "0",
// "filled_size": "0",
// "average_filled_price": "0",
// "fee": "",
// "number_of_fills": "0",
// "filled_value": "0",
// "pending_cancel": false,
// "size_in_quote": false,
// "total_fees": "0",
// "size_inclusive_of_fees": false,
// "total_value_after_fees": "0",
// "trigger_status": "INVALID_ORDER_TYPE",
// "order_type": "LIMIT",
// "reject_reason": "REJECT_REASON_UNSPECIFIED",
// "settled": false,
// "product_type": "SPOT",
// "reject_message": "",
// "cancel_message": ""
// }
//
market := GetArg(optionalArgs, 0, nil)
_ = market
var marketId interface{} = this.SafeString(order, "product_id")
var symbol interface{} = this.SafeSymbol(marketId, market, "-")
if IsTrue(!IsEqual(symbol, nil)) {
market = this.SafeMarket(symbol, market)
}
var orderConfiguration interface{} = this.SafeDict(order, "order_configuration", map[string]interface{} {})
var limitGTC interface{} = this.SafeDict(orderConfiguration, "limit_limit_gtc")
var limitGTD interface{} = this.SafeDict(orderConfiguration, "limit_limit_gtd")
var limitIOC interface{} = this.SafeDict(orderConfiguration, "sor_limit_ioc")
var stopLimitGTC interface{} = this.SafeDict(orderConfiguration, "stop_limit_stop_limit_gtc")
var stopLimitGTD interface{} = this.SafeDict(orderConfiguration, "stop_limit_stop_limit_gtd")
var marketIOC interface{} = this.SafeDict(orderConfiguration, "market_market_ioc")
var isLimit interface{} = (IsTrue(IsTrue((!IsEqual(limitGTC, nil))) || IsTrue((!IsEqual(limitGTD, nil)))) || IsTrue((!IsEqual(limitIOC, nil))))
var isStop interface{} = (IsTrue((!IsEqual(stopLimitGTC, nil))) || IsTrue((!IsEqual(stopLimitGTD, nil))))
var price interface{} = nil
var amount interface{} = nil
var postOnly interface{} = nil
var triggerPrice interface{} = nil
if IsTrue(isLimit) {
var target interface{} = nil
if IsTrue(!IsEqual(limitGTC, nil)) {
target = limitGTC
} else if IsTrue(!IsEqual(limitGTD, nil)) {
target = limitGTD
} else {
target = limitIOC
}
price = this.SafeString(target, "limit_price")
amount = this.SafeString(target, "base_size")
postOnly = this.SafeBool(target, "post_only")
} else if IsTrue(isStop) {
var stopTarget interface{} = Ternary(IsTrue((!IsEqual(stopLimitGTC, nil))), stopLimitGTC, stopLimitGTD)
price = this.SafeString(stopTarget, "limit_price")
amount = this.SafeString(stopTarget, "base_size")
postOnly = this.SafeBool(stopTarget, "post_only")
triggerPrice = this.SafeString(stopTarget, "stop_price")
} else {
amount = this.SafeString(marketIOC, "base_size")
}
var datetime interface{} = this.SafeString(order, "created_time")
var totalFees interface{} = this.SafeString(order, "total_fees")
var currencyFee interface{} = nil
if IsTrue(IsTrue((!IsEqual(totalFees, nil))) && IsTrue((!IsEqual(market, nil)))) {
currencyFee = GetValue(market, "quote")
}
return this.SafeOrder(map[string]interface{} {
"info": order,
"id": this.SafeString(order, "order_id"),
"clientOrderId": this.SafeString(order, "client_order_id"),
"timestamp": this.Parse8601(datetime),
"datetime": datetime,
"lastTradeTimestamp": nil,
"symbol": symbol,
"type": this.ParseOrderType(this.SafeString(order, "order_type")),
"timeInForce": this.ParseTimeInForce(this.SafeString(order, "time_in_force")),
"postOnly": postOnly,
"side": this.SafeStringLower(order, "side"),
"price": price,
"triggerPrice": triggerPrice,
"amount": amount,
"filled": this.SafeString(order, "filled_size"),
"remaining": nil,
"cost": nil,
"average": this.SafeString(order, "average_filled_price"),
"status": this.ParseOrderStatus(this.SafeString(order, "status")),
"fee": map[string]interface{} {
"cost": this.SafeString(order, "total_fees"),
"currency": currencyFee,
},
"trades": nil,
}, market)
}
func (this *coinbase) ParseOrderStatus(status interface{}) interface{} {
var statuses interface{} = map[string]interface{} {
"OPEN": "open",
"FILLED": "closed",
"CANCELLED": "canceled",
"EXPIRED": "canceled",
"FAILED": "canceled",
"UNKNOWN_ORDER_STATUS": nil,
}
return this.SafeString(statuses, status, status)
}
func (this *coinbase) ParseOrderType(typeVar interface{}) interface{} {
if IsTrue(IsEqual(typeVar, "UNKNOWN_ORDER_TYPE")) {
return nil
}
var types interface{} = map[string]interface{} {
"MARKET": "market",
"LIMIT": "limit",
"STOP": "limit",
"STOP_LIMIT": "limit",
}
return this.SafeString(types, typeVar, typeVar)
}
func (this *coinbase) ParseTimeInForce(timeInForce interface{}) interface{} {
var timeInForces interface{} = map[string]interface{} {
"GOOD_UNTIL_CANCELLED": "GTC",
"GOOD_UNTIL_DATE_TIME": "GTD",
"IMMEDIATE_OR_CANCEL": "IOC",
"FILL_OR_KILL": "FOK",
"UNKNOWN_TIME_IN_FORCE": nil,
}
return this.SafeString(timeInForces, timeInForce, timeInForce)
}
/**
* @method
* @name coinbase#cancelOrder
* @description cancels an open order
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_cancelorders
* @param {string} id order id
* @param {string} symbol not used by coinbase cancelOrder()
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
func (this *coinbase) CancelOrder(id interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbol := GetArg(optionalArgs, 0, nil)
_ = symbol
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
retRes33178 := (<-this.LoadMarkets())
PanicOnError(retRes33178)
orders:= (<-this.CancelOrders([]interface{}{id}, symbol, params))
PanicOnError(orders)
ch <- this.SafeDict(orders, 0, map[string]interface{} {})
return nil
}()
return ch
}
/**
* @method
* @name coinbase#cancelOrders
* @description cancel multiple orders
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_cancelorders
* @param {string[]} ids order ids
* @param {string} symbol not used by coinbase cancelOrders()
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
func (this *coinbase) CancelOrders(ids interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbol := GetArg(optionalArgs, 0, nil)
_ = symbol
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
retRes33338 := (<-this.LoadMarkets())
PanicOnError(retRes33338)
var market interface{} = nil
if IsTrue(!IsEqual(symbol, nil)) {
market = this.Market(symbol)
}
var request interface{} = map[string]interface{} {
"order_ids": ids,
}
response:= (<-this.V3PrivatePostBrokerageOrdersBatchCancel(this.Extend(request, params)))
PanicOnError(response)
//
// {
// "results": [
// {
// "success": true,
// "failure_reason": "UNKNOWN_CANCEL_FAILURE_REASON",
// "order_id": "bb8851a3-4fda-4a2c-aa06-9048db0e0f0d"
// }
// ]
// }
//
var orders interface{} = this.SafeList(response, "results", []interface{}{})
for i := 0; IsLessThan(i, GetArrayLength(orders)); i++ {
var success interface{} = this.SafeBool(GetValue(orders, i), "success")
if IsTrue(!IsEqual(success, true)) {
panic(BadRequest(Add(this.Id, " cancelOrders() has failed, check your arguments and parameters")))
}
}
ch <- this.ParseOrders(orders, market)
return nil
}()
return ch
}
/**
* @method
* @name coinbase#editOrder
* @description edit a trade order
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_editorder
* @param {string} id cancel order id
* @param {string} symbol unified symbol of the market to create an order in
* @param {string} type 'market' or 'limit'
* @param {string} side 'buy' or 'sell'
* @param {float} amount how much of currency you want to trade in units of base currency
* @param {float} [price] the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {boolean} [params.preview] default to false, wether to use the test/preview endpoint or not
* @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
func (this *coinbase) EditOrder(id interface{}, symbol interface{}, typeVar interface{}, side interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
amount := GetArg(optionalArgs, 0, nil)
_ = amount
price := GetArg(optionalArgs, 1, nil)
_ = price
params := GetArg(optionalArgs, 2, map[string]interface{} {})
_ = params
retRes33798 := (<-this.LoadMarkets())
PanicOnError(retRes33798)
var market interface{} = this.Market(symbol)
var request interface{} = map[string]interface{} {
"order_id": id,
}
if IsTrue(!IsEqual(amount, nil)) {
AddElementToObject(request, "size", this.AmountToPrecision(symbol, amount))
}
if IsTrue(!IsEqual(price, nil)) {
AddElementToObject(request, "price", this.PriceToPrecision(symbol, price))
}
var preview interface{} = this.SafeBool2(params, "preview", "test", false)
var response interface{} = nil
if IsTrue(preview) {
params = this.Omit(params, []interface{}{"preview", "test"})
response = (<-this.V3PrivatePostBrokerageOrdersEditPreview(this.Extend(request, params)))
PanicOnError(response)
} else {
response = (<-this.V3PrivatePostBrokerageOrdersEdit(this.Extend(request, params)))
PanicOnError(response)
}
//
// {
// "success": true,
// "errors": {
// "edit_failure_reason": "UNKNOWN_EDIT_ORDER_FAILURE_REASON",
// "preview_failure_reason": "UNKNOWN_PREVIEW_FAILURE_REASON"
// }
// }
//
ch <- this.ParseOrder(response, market)
return nil
}()
return ch
}
/**
* @method
* @name coinbase#fetchOrder
* @description fetches information on an order made by the user
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_gethistoricalorder
* @param {string} id the order id
* @param {string} symbol unified market symbol that the order was made in
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
func (this *coinbase) FetchOrder(id interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbol := GetArg(optionalArgs, 0, nil)
_ = symbol
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
retRes34218 := (<-this.LoadMarkets())
PanicOnError(retRes34218)
var market interface{} = nil
if IsTrue(!IsEqual(symbol, nil)) {
market = this.Market(symbol)
}
var request interface{} = map[string]interface{} {
"order_id": id,
}
response:= (<-this.V3PrivateGetBrokerageOrdersHistoricalOrderId(this.Extend(request, params)))
PanicOnError(response)
//
// {
// "order": {
// "order_id": "9bc1eb3b-5b46-4b71-9628-ae2ed0cca75b",
// "product_id": "LTC-BTC",
// "user_id": "1111111-1111-1111-1111-111111111111",
// "order_configuration": {
// "limit_limit_gtc": {
// "base_size": "0.2",
// "limit_price": "0.006",
// "post_only": false
// }
// },
// "side": "SELL",
// "client_order_id": "e5fe8482-05bb-428f-ad4d-dbc8ce39239c",
// "status": "OPEN",
// "time_in_force": "GOOD_UNTIL_CANCELLED",
// "created_time": "2023-01-16T23:37:23.947030Z",
// "completion_percentage": "0",
// "filled_size": "0",
// "average_filled_price": "0",
// "fee": "",
// "number_of_fills": "0",
// "filled_value": "0",
// "pending_cancel": false,
// "size_in_quote": false,
// "total_fees": "0",
// "size_inclusive_of_fees": false,
// "total_value_after_fees": "0",
// "trigger_status": "INVALID_ORDER_TYPE",
// "order_type": "LIMIT",
// "reject_reason": "REJECT_REASON_UNSPECIFIED",
// "settled": false,
// "product_type": "SPOT",
// "reject_message": "",
// "cancel_message": ""
// }
// }
//
var order interface{} = this.SafeDict(response, "order", map[string]interface{} {})
ch <- this.ParseOrder(order, market)
return nil
}()
return ch
}
/**
* @method
* @name coinbase#fetchOrders
* @description fetches information on multiple orders made by the user
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_gethistoricalorders
* @param {string} symbol unified market symbol that the orders were made in
* @param {int} [since] the earliest time in ms to fetch orders
* @param {int} [limit] the maximum number of order structures to retrieve
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {int} [params.until] the latest time in ms to fetch trades for
* @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
* @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
func (this *coinbase) FetchOrders(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbol := GetArg(optionalArgs, 0, nil)
_ = symbol
since := GetArg(optionalArgs, 1, nil)
_ = since
limit := GetArg(optionalArgs, 2, 100)
_ = limit
params := GetArg(optionalArgs, 3, map[string]interface{} {})
_ = params
retRes34878 := (<-this.LoadMarkets())
PanicOnError(retRes34878)
var paginate interface{} = false
paginateparamsVariable := this.HandleOptionAndParams(params, "fetchOrders", "paginate");
paginate = GetValue(paginateparamsVariable,0);
params = GetValue(paginateparamsVariable,1)
if IsTrue(paginate) {
retRes349119 := (<-this.FetchPaginatedCallCursor("fetchOrders", symbol, since, limit, params, "cursor", "cursor", nil, 1000))
PanicOnError(retRes349119)
ch <- retRes349119
return nil
}
var market interface{} = nil
if IsTrue(!IsEqual(symbol, nil)) {
market = this.Market(symbol)
}
var request interface{} = map[string]interface{} {}
if IsTrue(!IsEqual(market, nil)) {
AddElementToObject(request, "product_id", GetValue(market, "id"))
}
if IsTrue(!IsEqual(limit, nil)) {
AddElementToObject(request, "limit", limit)
}
if IsTrue(!IsEqual(since, nil)) {
AddElementToObject(request, "start_date", this.Iso8601(since))
}
var until interface{} = this.SafeIntegerN(params, []interface{}{"until"})
if IsTrue(!IsEqual(until, nil)) {
params = this.Omit(params, []interface{}{"until"})
AddElementToObject(request, "end_date", this.Iso8601(until))
}
response:= (<-this.V3PrivateGetBrokerageOrdersHistoricalBatch(this.Extend(request, params)))
PanicOnError(response)
//
// {
// "orders": [
// {
// "order_id": "813a53c5-3e39-47bb-863d-2faf685d22d8",
// "product_id": "BTC-USDT",
// "user_id": "1111111-1111-1111-1111-111111111111",
// "order_configuration": {
// "market_market_ioc": {
// "quote_size": "6.36"
// }
// },
// "side": "BUY",
// "client_order_id": "18eb9947-db49-4874-8e7b-39b8fe5f4317",
// "status": "FILLED",
// "time_in_force": "IMMEDIATE_OR_CANCEL",
// "created_time": "2023-01-18T01:37:37.975552Z",
// "completion_percentage": "100",
// "filled_size": "0.000297920684505",
// "average_filled_price": "21220.6399999973697697",
// "fee": "",
// "number_of_fills": "2",
// "filled_value": "6.3220675944333996",
// "pending_cancel": false,
// "size_in_quote": true,
// "total_fees": "0.0379324055666004",
// "size_inclusive_of_fees": true,
// "total_value_after_fees": "6.36",
// "trigger_status": "INVALID_ORDER_TYPE",
// "order_type": "MARKET",
// "reject_reason": "REJECT_REASON_UNSPECIFIED",
// "settled": true,
// "product_type": "SPOT",
// "reject_message": "",
// "cancel_message": "Internal error"
// },
// ],
// "sequence": "0",
// "has_next": false,
// "cursor": ""
// }
//
var orders interface{} = this.SafeList(response, "orders", []interface{}{})
var first interface{} = this.SafeDict(orders, 0)
var cursor interface{} = this.SafeString(response, "cursor")
if IsTrue(IsTrue((!IsEqual(cursor, nil))) && IsTrue((!IsEqual(cursor, "")))) {
AddElementToObject(first, "cursor", cursor)
AddElementToObject(orders, 0, first)
}
ch <- this.ParseOrders(orders, market, since, limit)
return nil
}()
return ch
}
func (this *coinbase) FetchOrdersByStatus(status interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbol := GetArg(optionalArgs, 0, nil)
_ = symbol
since := GetArg(optionalArgs, 1, nil)
_ = since
limit := GetArg(optionalArgs, 2, nil)
_ = limit
params := GetArg(optionalArgs, 3, map[string]interface{} {})
_ = params
retRes35668 := (<-this.LoadMarkets())
PanicOnError(retRes35668)
var market interface{} = nil
if IsTrue(!IsEqual(symbol, nil)) {
market = this.Market(symbol)
}
var request interface{} = map[string]interface{} {
"order_status": status,
}
if IsTrue(!IsEqual(market, nil)) {
AddElementToObject(request, "product_id", GetValue(market, "id"))
}
if IsTrue(IsEqual(limit, nil)) {
limit = 100
}
AddElementToObject(request, "limit", limit)
if IsTrue(!IsEqual(since, nil)) {
AddElementToObject(request, "start_date", this.Iso8601(since))
}
var until interface{} = this.SafeIntegerN(params, []interface{}{"until"})
if IsTrue(!IsEqual(until, nil)) {
params = this.Omit(params, []interface{}{"until"})
AddElementToObject(request, "end_date", this.Iso8601(until))
}
response:= (<-this.V3PrivateGetBrokerageOrdersHistoricalBatch(this.Extend(request, params)))
PanicOnError(response)
//
// {
// "orders": [
// {
// "order_id": "813a53c5-3e39-47bb-863d-2faf685d22d8",
// "product_id": "BTC-USDT",
// "user_id": "1111111-1111-1111-1111-111111111111",
// "order_configuration": {
// "market_market_ioc": {
// "quote_size": "6.36"
// }
// },
// "side": "BUY",
// "client_order_id": "18eb9947-db49-4874-8e7b-39b8fe5f4317",
// "status": "FILLED",
// "time_in_force": "IMMEDIATE_OR_CANCEL",
// "created_time": "2023-01-18T01:37:37.975552Z",
// "completion_percentage": "100",
// "filled_size": "0.000297920684505",
// "average_filled_price": "21220.6399999973697697",
// "fee": "",
// "number_of_fills": "2",
// "filled_value": "6.3220675944333996",
// "pending_cancel": false,
// "size_in_quote": true,
// "total_fees": "0.0379324055666004",
// "size_inclusive_of_fees": true,
// "total_value_after_fees": "6.36",
// "trigger_status": "INVALID_ORDER_TYPE",
// "order_type": "MARKET",
// "reject_reason": "REJECT_REASON_UNSPECIFIED",
// "settled": true,
// "product_type": "SPOT",
// "reject_message": "",
// "cancel_message": "Internal error"
// },
// ],
// "sequence": "0",
// "has_next": false,
// "cursor": ""
// }
//
var orders interface{} = this.SafeList(response, "orders", []interface{}{})
var first interface{} = this.SafeDict(orders, 0)
var cursor interface{} = this.SafeString(response, "cursor")
if IsTrue(IsTrue((!IsEqual(cursor, nil))) && IsTrue((!IsEqual(cursor, "")))) {
AddElementToObject(first, "cursor", cursor)
AddElementToObject(orders, 0, first)
}
ch <- this.ParseOrders(orders, market, since, limit)
return nil
}()
return ch
}
/**
* @method
* @name coinbase#fetchOpenOrders
* @description fetches information on all currently open orders
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_gethistoricalorders
* @param {string} symbol unified market symbol of the orders
* @param {int} [since] timestamp in ms of the earliest order, default is undefined
* @param {int} [limit] the maximum number of open order structures to retrieve
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
* @param {int} [params.until] the latest time in ms to fetch trades for
* @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
func (this *coinbase) FetchOpenOrders(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbol := GetArg(optionalArgs, 0, nil)
_ = symbol
since := GetArg(optionalArgs, 1, nil)
_ = since
limit := GetArg(optionalArgs, 2, nil)
_ = limit
params := GetArg(optionalArgs, 3, map[string]interface{} {})
_ = params
retRes36568 := (<-this.LoadMarkets())
PanicOnError(retRes36568)
var paginate interface{} = false
paginateparamsVariable := this.HandleOptionAndParams(params, "fetchOpenOrders", "paginate");
paginate = GetValue(paginateparamsVariable,0);
params = GetValue(paginateparamsVariable,1)
if IsTrue(paginate) {
retRes366019 := (<-this.FetchPaginatedCallCursor("fetchOpenOrders", symbol, since, limit, params, "cursor", "cursor", nil, 100))
PanicOnError(retRes366019)
ch <- retRes366019
return nil
}
retRes366215 := (<-this.FetchOrdersByStatus("OPEN", symbol, since, limit, params))
PanicOnError(retRes366215)
ch <- retRes366215
return nil
}()
return ch
}
/**
* @method
* @name coinbase#fetchClosedOrders
* @description fetches information on multiple closed orders made by the user
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_gethistoricalorders
* @param {string} symbol unified market symbol of the orders
* @param {int} [since] timestamp in ms of the earliest order, default is undefined
* @param {int} [limit] the maximum number of closed order structures to retrieve
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
* @param {int} [params.until] the latest time in ms to fetch trades for
* @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
func (this *coinbase) FetchClosedOrders(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbol := GetArg(optionalArgs, 0, nil)
_ = symbol
since := GetArg(optionalArgs, 1, nil)
_ = since
limit := GetArg(optionalArgs, 2, nil)
_ = limit
params := GetArg(optionalArgs, 3, map[string]interface{} {})
_ = params
retRes36798 := (<-this.LoadMarkets())
PanicOnError(retRes36798)
var paginate interface{} = false
paginateparamsVariable := this.HandleOptionAndParams(params, "fetchClosedOrders", "paginate");
paginate = GetValue(paginateparamsVariable,0);
params = GetValue(paginateparamsVariable,1)
if IsTrue(paginate) {
retRes368319 := (<-this.FetchPaginatedCallCursor("fetchClosedOrders", symbol, since, limit, params, "cursor", "cursor", nil, 100))
PanicOnError(retRes368319)
ch <- retRes368319
return nil
}
retRes368515 := (<-this.FetchOrdersByStatus("FILLED", symbol, since, limit, params))
PanicOnError(retRes368515)
ch <- retRes368515
return nil
}()
return ch
}
/**
* @method
* @name coinbase#fetchCanceledOrders
* @description fetches information on multiple canceled orders made by the user
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_gethistoricalorders
* @param {string} symbol unified market symbol of the orders
* @param {int} [since] timestamp in ms of the earliest order, default is undefined
* @param {int} [limit] the maximum number of canceled order structures to retrieve
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
func (this *coinbase) FetchCanceledOrders(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbol := GetArg(optionalArgs, 0, nil)
_ = symbol
since := GetArg(optionalArgs, 1, nil)
_ = since
limit := GetArg(optionalArgs, 2, nil)
_ = limit
params := GetArg(optionalArgs, 3, map[string]interface{} {})
_ = params
retRes370015 := (<-this.FetchOrdersByStatus("CANCELLED", symbol, since, limit, params))
PanicOnError(retRes370015)
ch <- retRes370015
return nil
}()
return ch
}
/**
* @method
* @name coinbase#fetchOHLCV
* @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getpubliccandles
* @param {string} symbol unified symbol of the market to fetch OHLCV data for
* @param {string} timeframe the length of time each candle represents
* @param {int} [since] timestamp in ms of the earliest candle to fetch
* @param {int} [limit] the maximum amount of candles to fetch, not used by coinbase
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {int} [params.until] the latest time in ms to fetch trades for
* @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
* @param {boolean} [params.usePrivate] default false, when true will use the private endpoint to fetch the candles
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
*/
func (this *coinbase) FetchOHLCV(symbol interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
timeframe := GetArg(optionalArgs, 0, "1m")
_ = timeframe
since := GetArg(optionalArgs, 1, nil)
_ = since
limit := GetArg(optionalArgs, 2, nil)
_ = limit
params := GetArg(optionalArgs, 3, map[string]interface{} {})
_ = params
retRes37198 := (<-this.LoadMarkets())
PanicOnError(retRes37198)
var maxLimit interface{} = 300
limit = Ternary(IsTrue((IsEqual(limit, nil))), maxLimit, mathMin(limit, maxLimit))
var paginate interface{} = false
paginateparamsVariable := this.HandleOptionAndParams(params, "fetchOHLCV", "paginate", false);
paginate = GetValue(paginateparamsVariable,0);
params = GetValue(paginateparamsVariable,1)
if IsTrue(paginate) {
retRes372519 := (<-this.FetchPaginatedCallDeterministic("fetchOHLCV", symbol, since, limit, timeframe, params, Subtract(maxLimit, 1)))
PanicOnError(retRes372519)
ch <- retRes372519
return nil
}
var market interface{} = this.Market(symbol)
var request interface{} = map[string]interface{} {
"product_id": GetValue(market, "id"),
"granularity": this.SafeString(this.Timeframes, timeframe, timeframe),
}
var until interface{} = this.SafeIntegerN(params, []interface{}{"until", "end"})
params = this.Omit(params, []interface{}{"until"})
var duration interface{} = this.ParseTimeframe(timeframe)
var requestedDuration interface{} = Multiply(limit, duration)
var sinceString interface{} = nil
if IsTrue(!IsEqual(since, nil)) {
sinceString = this.NumberToString(this.ParseToInt(Divide(since, 1000)))
} else {
var now interface{} = ToString(this.Seconds())
sinceString = Precise.StringSub(now, ToString(requestedDuration))
}
AddElementToObject(request, "start", sinceString)
if IsTrue(!IsEqual(until, nil)) {
AddElementToObject(request, "end", this.NumberToString(this.ParseToInt(Divide(until, 1000))))
} else {
// 300 candles max
AddElementToObject(request, "end", Precise.StringAdd(sinceString, ToString(requestedDuration)))
}
var response interface{} = nil
var usePrivate interface{} = false
usePrivateparamsVariable := this.HandleOptionAndParams(params, "fetchOHLCV", "usePrivate", false);
usePrivate = GetValue(usePrivateparamsVariable,0);
params = GetValue(usePrivateparamsVariable,1)
if IsTrue(usePrivate) {
response = (<-this.V3PrivateGetBrokerageProductsProductIdCandles(this.Extend(request, params)))
PanicOnError(response)
} else {
response = (<-this.V3PublicGetBrokerageMarketProductsProductIdCandles(this.Extend(request, params)))
PanicOnError(response)
}
//
// {
// "candles": [
// {
// "start": "1673391780",
// "low": "17414.36",
// "high": "17417.99",
// "open": "17417.74",
// "close": "17417.38",
// "volume": "1.87780853"
// },
// ]
// }
//
var candles interface{} = this.SafeList(response, "candles", []interface{}{})
ch <- this.ParseOHLCVs(candles, market, timeframe, since, limit)
return nil
}()
return ch
}
func (this *coinbase) ParseOHLCV(ohlcv interface{}, optionalArgs ...interface{}) interface{} {
//
// [
// {
// "start": "1673391780",
// "low": "17414.36",
// "high": "17417.99",
// "open": "17417.74",
// "close": "17417.38",
// "volume": "1.87780853"
// },
// ]
//
market := GetArg(optionalArgs, 0, nil)
_ = market
return []interface{}{this.SafeTimestamp(ohlcv, "start"), this.SafeNumber(ohlcv, "open"), this.SafeNumber(ohlcv, "high"), this.SafeNumber(ohlcv, "low"), this.SafeNumber(ohlcv, "close"), this.SafeNumber(ohlcv, "volume")}
}
/**
* @method
* @name coinbase#fetchTrades
* @description get the list of most recent trades for a particular symbol
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getpublicmarkettrades
* @param {string} symbol unified market symbol of the trades
* @param {int} [since] not used by coinbase fetchTrades
* @param {int} [limit] the maximum number of trade structures to fetch
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {boolean} [params.usePrivate] default false, when true will use the private endpoint to fetch the trades
* @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
*/
func (this *coinbase) FetchTrades(symbol interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
since := GetArg(optionalArgs, 0, nil)
_ = since
limit := GetArg(optionalArgs, 1, nil)
_ = limit
params := GetArg(optionalArgs, 2, map[string]interface{} {})
_ = params
retRes38128 := (<-this.LoadMarkets())
PanicOnError(retRes38128)
var market interface{} = this.Market(symbol)
var request interface{} = map[string]interface{} {
"product_id": GetValue(market, "id"),
}
if IsTrue(!IsEqual(since, nil)) {
AddElementToObject(request, "start", this.NumberToString(this.ParseToInt(Divide(since, 1000))))
}
if IsTrue(!IsEqual(limit, nil)) {
AddElementToObject(request, "limit", mathMin(limit, 1000))
}
var until interface{} = nil
untilparamsVariable := this.HandleOptionAndParams(params, "fetchTrades", "until");
until = GetValue(untilparamsVariable,0);
params = GetValue(untilparamsVariable,1)
if IsTrue(!IsEqual(until, nil)) {
AddElementToObject(request, "end", this.NumberToString(this.ParseToInt(Divide(until, 1000))))
} else if IsTrue(!IsEqual(since, nil)) {
panic(ArgumentsRequired(Add(this.Id, " fetchTrades() requires a `until` parameter when you use `since` argument")))
}
var response interface{} = nil
var usePrivate interface{} = false
usePrivateparamsVariable := this.HandleOptionAndParams(params, "fetchTrades", "usePrivate", false);
usePrivate = GetValue(usePrivateparamsVariable,0);
params = GetValue(usePrivateparamsVariable,1)
if IsTrue(usePrivate) {
response = (<-this.V3PrivateGetBrokerageProductsProductIdTicker(this.Extend(request, params)))
PanicOnError(response)
} else {
response = (<-this.V3PublicGetBrokerageMarketProductsProductIdTicker(this.Extend(request, params)))
PanicOnError(response)
}
//
// {
// "trades": [
// {
// "trade_id": "10092327",
// "product_id": "BTC-USDT",
// "price": "17488.12",
// "size": "0.0000623",
// "time": "2023-01-11T00:52:37.557001Z",
// "side": "BUY",
// "bid": "",
// "ask": ""
// },
// ]
// }
//
var trades interface{} = this.SafeList(response, "trades", []interface{}{})
ch <- this.ParseTrades(trades, market, since, limit)
return nil
}()
return ch
}
/**
* @method
* @name coinbase#fetchMyTrades
* @description fetch all trades made by the user
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getfills
* @param {string} symbol unified market symbol of the trades
* @param {int} [since] timestamp in ms of the earliest order, default is undefined
* @param {int} [limit] the maximum number of trade structures to fetch
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {int} [params.until] the latest time in ms to fetch trades for
* @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
* @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
*/
func (this *coinbase) FetchMyTrades(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbol := GetArg(optionalArgs, 0, nil)
_ = symbol
since := GetArg(optionalArgs, 1, nil)
_ = since
limit := GetArg(optionalArgs, 2, nil)
_ = limit
params := GetArg(optionalArgs, 3, map[string]interface{} {})
_ = params
retRes38728 := (<-this.LoadMarkets())
PanicOnError(retRes38728)
var paginate interface{} = false
paginateparamsVariable := this.HandleOptionAndParams(params, "fetchMyTrades", "paginate");
paginate = GetValue(paginateparamsVariable,0);
params = GetValue(paginateparamsVariable,1)
if IsTrue(paginate) {
retRes387619 := (<-this.FetchPaginatedCallCursor("fetchMyTrades", symbol, since, limit, params, "cursor", "cursor", nil, 250))
PanicOnError(retRes387619)
ch <- retRes387619
return nil
}
var market interface{} = nil
if IsTrue(!IsEqual(symbol, nil)) {
market = this.Market(symbol)
}
var request interface{} = map[string]interface{} {}
if IsTrue(!IsEqual(market, nil)) {
AddElementToObject(request, "product_id", GetValue(market, "id"))
}
if IsTrue(!IsEqual(limit, nil)) {
AddElementToObject(request, "limit", limit)
}
if IsTrue(!IsEqual(since, nil)) {
AddElementToObject(request, "start_sequence_timestamp", this.Iso8601(since))
}
var until interface{} = this.SafeIntegerN(params, []interface{}{"until"})
if IsTrue(!IsEqual(until, nil)) {
params = this.Omit(params, []interface{}{"until"})
AddElementToObject(request, "end_sequence_timestamp", this.Iso8601(until))
}
response:= (<-this.V3PrivateGetBrokerageOrdersHistoricalFills(this.Extend(request, params)))
PanicOnError(response)
//
// {
// "fills": [
// {
// "entry_id": "b88b82cc89e326a2778874795102cbafd08dd979a2a7a3c69603fc4c23c2e010",
// "trade_id": "cdc39e45-bbd3-44ec-bf02-61742dfb16a1",
// "order_id": "813a53c5-3e39-47bb-863d-2faf685d22d8",
// "trade_time": "2023-01-18T01:37:38.091377090Z",
// "trade_type": "FILL",
// "price": "21220.64",
// "size": "0.0046830664333996",
// "commission": "0.0000280983986004",
// "product_id": "BTC-USDT",
// "sequence_timestamp": "2023-01-18T01:37:38.092520Z",
// "liquidity_indicator": "UNKNOWN_LIQUIDITY_INDICATOR",
// "size_in_quote": true,
// "user_id": "1111111-1111-1111-1111-111111111111",
// "side": "BUY"
// },
// ],
// "cursor": ""
// }
//
var trades interface{} = this.SafeList(response, "fills", []interface{}{})
var first interface{} = this.SafeDict(trades, 0)
var cursor interface{} = this.SafeString(response, "cursor")
if IsTrue(IsTrue((!IsEqual(cursor, nil))) && IsTrue((!IsEqual(cursor, "")))) {
AddElementToObject(first, "cursor", cursor)
AddElementToObject(trades, 0, first)
}
ch <- this.ParseTrades(trades, market, since, limit)
return nil
}()
return ch
}
/**
* @method
* @name coinbase#fetchOrderBook
* @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getpublicproductbook
* @param {string} symbol unified symbol of the market to fetch the order book for
* @param {int} [limit] the maximum amount of order book entries to return
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {boolean} [params.usePrivate] default false, when true will use the private endpoint to fetch the order book
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
*/
func (this *coinbase) FetchOrderBook(symbol interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
limit := GetArg(optionalArgs, 0, nil)
_ = limit
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
retRes39438 := (<-this.LoadMarkets())
PanicOnError(retRes39438)
var market interface{} = this.Market(symbol)
var request interface{} = map[string]interface{} {
"product_id": GetValue(market, "id"),
}
if IsTrue(!IsEqual(limit, nil)) {
AddElementToObject(request, "limit", limit)
}
var response interface{} = nil
var usePrivate interface{} = false
usePrivateparamsVariable := this.HandleOptionAndParams(params, "fetchOrderBook", "usePrivate", false);
usePrivate = GetValue(usePrivateparamsVariable,0);
params = GetValue(usePrivateparamsVariable,1)
if IsTrue(usePrivate) {
response = (<-this.V3PrivateGetBrokerageProductBook(this.Extend(request, params)))
PanicOnError(response)
} else {
response = (<-this.V3PublicGetBrokerageMarketProductBook(this.Extend(request, params)))
PanicOnError(response)
}
//
// {
// "pricebook": {
// "product_id": "BTC-USDT",
// "bids": [
// {
// "price": "30757.85",
// "size": "0.115"
// },
// ],
// "asks": [
// {
// "price": "30759.07",
// "size": "0.04877659"
// },
// ],
// "time": "2023-06-30T04:02:40.533606Z"
// }
// }
//
var data interface{} = this.SafeDict(response, "pricebook", map[string]interface{} {})
var time interface{} = this.SafeString(data, "time")
var timestamp interface{} = this.Parse8601(time)
ch <- this.ParseOrderBook(data, symbol, timestamp, "bids", "asks", "price", "size")
return nil
}()
return ch
}
/**
* @method
* @name coinbase#fetchBidsAsks
* @description fetches the bid and ask price and volume for multiple markets
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getbestbidask
* @param {string[]} [symbols] unified symbols of the markets to fetch the bids and asks for, all markets are returned if not assigned
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
*/
func (this *coinbase) FetchBidsAsks(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbols := GetArg(optionalArgs, 0, nil)
_ = symbols
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
retRes39958 := (<-this.LoadMarkets())
PanicOnError(retRes39958)
symbols = this.MarketSymbols(symbols)
var request interface{} = map[string]interface{} {}
if IsTrue(!IsEqual(symbols, nil)) {
AddElementToObject(request, "product_ids", this.MarketIds(symbols))
}
response:= (<-this.V3PrivateGetBrokerageBestBidAsk(this.Extend(request, params)))
PanicOnError(response)
//
// {
// "pricebooks": [
// {
// "product_id": "TRAC-EUR",
// "bids": [
// {
// "price": "0.2384",
// "size": "386.1"
// }
// ],
// "asks": [
// {
// "price": "0.2406",
// "size": "672"
// }
// ],
// "time": "2023-06-30T07:15:24.656044Z"
// },
// ]
// }
//
var tickers interface{} = this.SafeList(response, "pricebooks", []interface{}{})
ch <- this.ParseTickers(tickers, symbols)
return nil
}()
return ch
}
/**
* @method
* @name coinbase#withdraw
* @description make a withdrawal
* @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-transactions#send-money
* @param {string} code unified currency code
* @param {float} amount the amount to withdraw
* @param {string} address the address to withdraw to
* @param {string} [tag] an optional tag for the withdrawal
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
*/
func (this *coinbase) Withdraw(code interface{}, amount interface{}, address interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
tag := GetArg(optionalArgs, 0, nil)
_ = tag
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
tagparamsVariable := this.HandleWithdrawTagAndParams(tag, params);
tag = GetValue(tagparamsVariable,0);
params = GetValue(tagparamsVariable,1)
this.CheckAddress(address)
retRes40438 := (<-this.LoadMarkets())
PanicOnError(retRes40438)
var currency interface{} = this.Currency(code)
var accountId interface{} = this.SafeString2(params, "account_id", "accountId")
params = this.Omit(params, []interface{}{"account_id", "accountId"})
if IsTrue(IsEqual(accountId, nil)) {
if IsTrue(IsEqual(code, nil)) {
panic(ArgumentsRequired(Add(this.Id, " withdraw() requires an account_id (or accountId) parameter OR a currency code argument")))
}
accountId = (<-this.FindAccountId(code, params))
PanicOnError(accountId)
if IsTrue(IsEqual(accountId, nil)) {
panic(ExchangeError(Add(Add(this.Id, " withdraw() could not find account id for "), code)))
}
}
var request interface{} = map[string]interface{} {
"account_id": accountId,
"type": "send",
"to": address,
"amount": amount,
"currency": GetValue(currency, "id"),
}
if IsTrue(!IsEqual(tag, nil)) {
AddElementToObject(request, "destination_tag", tag)
}
response:= (<-this.V2PrivatePostAccountsAccountIdTransactions(this.Extend(request, params)))
PanicOnError(response)
//
// {
// "data": {
// "id": "a1794ecf-5693-55fa-70cf-ef731748ed82",
// "type": "send",
// "status": "pending",
// "amount": {
// "amount": "-14.008308",
// "currency": "USDC"
// },
// "native_amount": {
// "amount": "-18.74",
// "currency": "CAD"
// },
// "description": null,
// "created_at": "2024-01-12T01:27:31Z",
// "updated_at": "2024-01-12T01:27:31Z",
// "resource": "transaction",
// "resource_path": "/v2/accounts/a34bgfad-ed67-538b-bffc-730c98c10da0/transactions/a1794ecf-5693-55fa-70cf-ef731748ed82",
// "instant_exchange": false,
// "network": {
// "status": "pending",
// "status_description": "Pending (est. less than 10 minutes)",
// "transaction_fee": {
// "amount": "4.008308",
// "currency": "USDC"
// },
// "transaction_amount": {
// "amount": "10.000000",
// "currency": "USDC"
// },
// "confirmations": 0
// },
// "to": {
// "resource": "ethereum_address",
// "address": "0x9...",
// "currency": "USDC",
// "address_info": {
// "address": "0x9..."
// }
// },
// "idem": "748d8591-dg9a-7831-a45b-crd61dg78762",
// "details": {
// "title": "Sent USDC",
// "subtitle": "To USDC address on Ethereum network",
// "header": "Sent 14.008308 USDC ($18.74)",
// "health": "warning"
// },
// "hide_native_amount": false
// }
// }
//
var data interface{} = this.SafeDict(response, "data", map[string]interface{} {})
ch <- this.ParseTransaction(data, currency)
return nil
}()
return ch
}
/**
* @method
* @name coinbase#fetchDepositAddress
* @description fetch the deposit address for a currency associated with this account
* @see https://docs.cloud.coinbase.com/exchange/reference/exchangerestapi_postcoinbaseaccountaddresses
* @param {string} code unified currency code
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} an [address structure]{@link https://docs.ccxt.com/#/?id=address-structure}
*/
func (this *coinbase) FetchDepositAddressesByNetwork(code interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
retRes41338 := (<-this.LoadMarkets())
PanicOnError(retRes41338)
var currency interface{} = this.Currency(code)
var request interface{} = nil
requestparamsVariable := (<-this.PrepareAccountRequestWithCurrencyCode(GetValue(currency, "code"), nil, params));
request = GetValue(requestparamsVariable,0);
params = GetValue(requestparamsVariable,1)
response:= (<-this.V2PrivateGetAccountsAccountIdAddresses(this.Extend(request, params)))
PanicOnError(response)
//
// {
// pagination: {
// ending_before: null,
// starting_after: null,
// previous_ending_before: null,
// next_starting_after: null,
// limit: '25',
// order: 'desc',
// previous_uri: null,
// next_uri: null
// },
// data: [
// {
// id: '64ceb5f1-5fa2-5310-a4ff-9fd46271003d',
// address: '5xjPKeAXpnhA2kHyinvdVeui6RXVdEa3B2J3SCAwiKnk',
// address_info: { address: '5xjPKeAXpnhA2kHyinvdVeui6RXVdEa3B2J3SCAwiKnk' },
// name: null,
// created_at: '2023-05-29T21:12:12Z',
// updated_at: '2023-05-29T21:12:12Z',
// network: 'solana',
// uri_scheme: 'solana',
// resource: 'address',
// resource_path: '/v2/accounts/a7b3d387-bfb8-5ce7-b8da-1f507e81cf25/addresses/64ceb5f1-5fa2-5310-a4ff-9fd46271003d',
// warnings: [
// {
// type: 'correct_address_warning',
// title: 'This is an ERC20 USDC address.',
// details: 'Only send ERC20 USD Coin (USDC) to this address.',
// image_url: 'https://www.coinbase.com/assets/addresses/global-receive-warning-a3d91807e61c717e5a38d270965003dcc025ca8a3cea40ec3d7835b7c86087fa.png',
// options: [ { text: 'I understand', style: 'primary', id: 'dismiss' } ]
// }
// ],
// qr_code_image_url: 'https://static-assets.coinbase.com/p2p/l2/asset_network_combinations/v5/usdc-solana.png',
// address_label: 'USDC address (Solana)',
// default_receive: true,
// deposit_uri: 'solana:5xjPKeAXpnhA2kHyinvdVeui6RXVdEa3B2J3SCAwiKnk?spl-token=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
// callback_url: null,
// share_address_copy: {
// line1: '5xjPKeAXpnhA2kHyinvdVeui6RXVdEa3B2J3SCAwiKnk',
// line2: 'This address can only receive USDC-SPL from Solana network. Dont send USDC from other networks, other SPL tokens or NFTs, or it may result in a loss of funds.'
// },
// receive_subtitle: 'ERC-20',
// inline_warning: {
// text: 'This address can only receive USDC-SPL from Solana network. Dont send USDC from other networks, other SPL tokens or NFTs, or it may result in a loss of funds.',
// tooltip: {
// title: 'USDC (Solana)',
// subtitle: 'This address can only receive USDC-SPL from Solana network.'
// }
// }
// },
// ...
// ]
// }
//
var data interface{} = this.SafeList(response, "data", []interface{}{})
var addressStructures interface{} = this.ParseDepositAddresses(data, nil, false)
ch <- this.IndexBy(addressStructures, "network")
return nil
}()
return ch
}
func (this *coinbase) ParseDepositAddress(depositAddress interface{}, optionalArgs ...interface{}) interface{} {
//
// {
// id: '64ceb5f1-5fa2-5310-a4ff-9fd46271003d',
// address: '5xjPKeAXpnhA2kHyinvdVeui6RXVdEa3B2J3SCAwiKnk',
// address_info: {
// address: 'GCF74576I7AQ56SLMKBQAP255EGUOWCRVII3S44KEXVNJEOIFVBDMXVL',
// destination_tag: '3722061866'
// },
// name: null,
// created_at: '2023-05-29T21:12:12Z',
// updated_at: '2023-05-29T21:12:12Z',
// network: 'solana',
// uri_scheme: 'solana',
// resource: 'address',
// resource_path: '/v2/accounts/a7b3d387-bfb8-5ce7-b8da-1f507e81cf25/addresses/64ceb5f1-5fa2-5310-a4ff-9fd46271003d',
// warnings: [
// {
// type: 'correct_address_warning',
// title: 'This is an ERC20 USDC address.',
// details: 'Only send ERC20 USD Coin (USDC) to this address.',
// image_url: 'https://www.coinbase.com/assets/addresses/global-receive-warning-a3d91807e61c717e5a38d270965003dcc025ca8a3cea40ec3d7835b7c86087fa.png',
// options: [ { text: 'I understand', style: 'primary', id: 'dismiss' } ]
// }
// ],
// qr_code_image_url: 'https://static-assets.coinbase.com/p2p/l2/asset_network_combinations/v5/usdc-solana.png',
// address_label: 'USDC address (Solana)',
// default_receive: true,
// deposit_uri: 'solana:5xjPKeAXpnhA2kHyinvdVeui6RXVdEa3B2J3SCAwiKnk?spl-token=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
// callback_url: null,
// share_address_copy: {
// line1: '5xjPKeAXpnhA2kHyinvdVeui6RXVdEa3B2J3SCAwiKnk',
// line2: 'This address can only receive USDC-SPL from Solana network. Dont send USDC from other networks, other SPL tokens or NFTs, or it may result in a loss of funds.'
// },
// receive_subtitle: 'ERC-20',
// inline_warning: {
// text: 'This address can only receive USDC-SPL from Solana network. Dont send USDC from other networks, other SPL tokens or NFTs, or it may result in a loss of funds.',
// tooltip: {
// title: 'USDC (Solana)',
// subtitle: 'This address can only receive USDC-SPL from Solana network.'
// }
// }
// }
//
currency := GetArg(optionalArgs, 0, nil)
_ = currency
var address interface{} = this.SafeString(depositAddress, "address")
this.CheckAddress(address)
var networkId interface{} = this.SafeString(depositAddress, "network")
var code interface{} = this.SafeCurrencyCode(nil, currency)
var addressLabel interface{} = this.SafeString(depositAddress, "address_label")
var currencyId interface{} = nil
if IsTrue(!IsEqual(addressLabel, nil)) {
var splitAddressLabel interface{} = Split(addressLabel, " ")
currencyId = this.SafeString(splitAddressLabel, 0)
}
var addressInfo interface{} = this.SafeDict(depositAddress, "address_info")
return map[string]interface{} {
"info": depositAddress,
"currency": this.SafeCurrencyCode(currencyId, currency),
"network": this.NetworkIdToCode(networkId, code),
"address": address,
"tag": this.SafeString(addressInfo, "destination_tag"),
}
}
/**
* @method
* @name coinbase#deposit
* @description make a deposit
* @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-deposits#deposit-funds
* @param {string} code unified currency code
* @param {float} amount the amount to deposit
* @param {string} id the payment method id to be used for the deposit, can be retrieved from v2PrivateGetPaymentMethods
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.accountId] the id of the account to deposit into
* @returns {object} a [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
*/
func (this *coinbase) Deposit(code interface{}, amount interface{}, id interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
retRes42758 := (<-this.LoadMarkets())
PanicOnError(retRes42758)
var accountId interface{} = this.SafeString2(params, "account_id", "accountId")
params = this.Omit(params, []interface{}{"account_id", "accountId"})
if IsTrue(IsEqual(accountId, nil)) {
if IsTrue(IsEqual(code, nil)) {
panic(ArgumentsRequired(Add(this.Id, " deposit() requires an account_id (or accountId) parameter OR a currency code argument")))
}
accountId = (<-this.FindAccountId(code, params))
PanicOnError(accountId)
if IsTrue(IsEqual(accountId, nil)) {
panic(ExchangeError(Add(Add(this.Id, " deposit() could not find account id for "), code)))
}
}
var request interface{} = map[string]interface{} {
"account_id": accountId,
"amount": this.NumberToString(amount),
"currency": ToUpper(code),
"payment_method": id,
}
response:= (<-this.V2PrivatePostAccountsAccountIdDeposits(this.Extend(request, params)))
PanicOnError(response)
//
// {
// "data": {
// "id": "67e0eaec-07d7-54c4-a72c-2e92826897df",
// "status": "created",
// "payment_method": {
// "id": "83562370-3e5c-51db-87da-752af5ab9559",
// "resource": "payment_method",
// "resource_path": "/v2/payment-methods/83562370-3e5c-51db-87da-752af5ab9559"
// },
// "transaction": {
// "id": "441b9494-b3f0-5b98-b9b0-4d82c21c252a",
// "resource": "transaction",
// "resource_path": "/v2/accounts/2bbf394c-193b-5b2a-9155-3b4732659ede/transactions/441b9494-b3f0-5b98-b9b0-4d82c21c252a"
// },
// "amount": {
// "amount": "10.00",
// "currency": "USD"
// },
// "subtotal": {
// "amount": "10.00",
// "currency": "USD"
// },
// "created_at": "2015-01-31T20:49:02Z",
// "updated_at": "2015-02-11T16:54:02-08:00",
// "resource": "deposit",
// "resource_path": "/v2/accounts/2bbf394c-193b-5b2a-9155-3b4732659ede/deposits/67e0eaec-07d7-54c4-a72c-2e92826897df",
// "committed": true,
// "fee": {
// "amount": "0.00",
// "currency": "USD"
// },
// "payout_at": "2015-02-18T16:54:00-08:00"
// }
// }
//
var data interface{} = this.SafeDict(response, "data", map[string]interface{} {})
ch <- this.ParseTransaction(data)
return nil
}()
return ch
}
/**
* @method
* @name coinbase#fetchDeposit
* @description fetch information on a deposit, fiat only, for crypto transactions use fetchLedger
* @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-deposits#show-deposit
* @param {string} id deposit id
* @param {string} [code] unified currency code
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.accountId] the id of the account that the funds were deposited into
* @returns {object} a [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
*/
func (this *coinbase) FetchDeposit(id interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
code := GetArg(optionalArgs, 0, nil)
_ = code
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
retRes43468 := (<-this.LoadMarkets())
PanicOnError(retRes43468)
var accountId interface{} = this.SafeString2(params, "account_id", "accountId")
params = this.Omit(params, []interface{}{"account_id", "accountId"})
if IsTrue(IsEqual(accountId, nil)) {
if IsTrue(IsEqual(code, nil)) {
panic(ArgumentsRequired(Add(this.Id, " fetchDeposit() requires an account_id (or accountId) parameter OR a currency code argument")))
}
accountId = (<-this.FindAccountId(code, params))
PanicOnError(accountId)
if IsTrue(IsEqual(accountId, nil)) {
panic(ExchangeError(Add(Add(this.Id, " fetchDeposit() could not find account id for "), code)))
}
}
var request interface{} = map[string]interface{} {
"account_id": accountId,
"deposit_id": id,
}
response:= (<-this.V2PrivateGetAccountsAccountIdDepositsDepositId(this.Extend(request, params)))
PanicOnError(response)
//
// {
// "data": {
// "id": "67e0eaec-07d7-54c4-a72c-2e92826897df",
// "status": "completed",
// "payment_method": {
// "id": "83562370-3e5c-51db-87da-752af5ab9559",
// "resource": "payment_method",
// "resource_path": "/v2/payment-methods/83562370-3e5c-51db-87da-752af5ab9559"
// },
// "transaction": {
// "id": "441b9494-b3f0-5b98-b9b0-4d82c21c252a",
// "resource": "transaction",
// "resource_path": "/v2/accounts/2bbf394c-193b-5b2a-9155-3b4732659ede/transactions/441b9494-b3f0-5b98-b9b0-4d82c21c252a"
// },
// "amount": {
// "amount": "10.00",
// "currency": "USD"
// },
// "subtotal": {
// "amount": "10.00",
// "currency": "USD"
// },
// "created_at": "2015-01-31T20:49:02Z",
// "updated_at": "2015-02-11T16:54:02-08:00",
// "resource": "deposit",
// "resource_path": "/v2/accounts/2bbf394c-193b-5b2a-9155-3b4732659ede/deposits/67e0eaec-07d7-54c4-a72c-2e92826897df",
// "committed": true,
// "fee": {
// "amount": "0.00",
// "currency": "USD"
// },
// "payout_at": "2015-02-18T16:54:00-08:00"
// }
// }
//
var data interface{} = this.SafeDict(response, "data", map[string]interface{} {})
ch <- this.ParseTransaction(data)
return nil
}()
return ch
}
/**
* @method
* @name coinbase#fetchDepositMethodIds
* @description fetch the deposit id for a fiat currency associated with this account
* @see https://docs.cdp.coinbase.com/advanced-trade/reference/retailbrokerageapi_getpaymentmethods
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} an array of [deposit id structures]{@link https://docs.ccxt.com/#/?id=deposit-id-structure}
*/
func (this *coinbase) FetchDepositMethodIds(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
retRes44128 := (<-this.LoadMarkets())
PanicOnError(retRes44128)
response:= (<-this.V3PrivateGetBrokeragePaymentMethods(params))
PanicOnError(response)
//
// {
// "payment_methods": [
// {
// "id": "21b39a5d-f7b46876fb2e",
// "type": "COINBASE_FIAT_ACCOUNT",
// "name": "CAD Wallet",
// "currency": "CAD",
// "verified": true,
// "allow_buy": false,
// "allow_sell": true,
// "allow_deposit": false,
// "allow_withdraw": false,
// "created_at": "2023-06-29T19:58:46Z",
// "updated_at": "2023-10-30T20:25:01Z"
// }
// ]
// }
//
var result interface{} = this.SafeList(response, "payment_methods", []interface{}{})
ch <- this.ParseDepositMethodIds(result)
return nil
}()
return ch
}
/**
* @method
* @name coinbase#fetchDepositMethodId
* @description fetch the deposit id for a fiat currency associated with this account
* @see https://docs.cdp.coinbase.com/advanced-trade/reference/retailbrokerageapi_getpaymentmethod
* @param {string} id the deposit payment method id
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [deposit id structure]{@link https://docs.ccxt.com/#/?id=deposit-id-structure}
*/
func (this *coinbase) FetchDepositMethodId(id interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
retRes44478 := (<-this.LoadMarkets())
PanicOnError(retRes44478)
var request interface{} = map[string]interface{} {
"payment_method_id": id,
}
response:= (<-this.V3PrivateGetBrokeragePaymentMethodsPaymentMethodId(this.Extend(request, params)))
PanicOnError(response)
//
// {
// "payment_method": {
// "id": "21b39a5d-f7b46876fb2e",
// "type": "COINBASE_FIAT_ACCOUNT",
// "name": "CAD Wallet",
// "currency": "CAD",
// "verified": true,
// "allow_buy": false,
// "allow_sell": true,
// "allow_deposit": false,
// "allow_withdraw": false,
// "created_at": "2023-06-29T19:58:46Z",
// "updated_at": "2023-10-30T20:25:01Z"
// }
// }
//
var result interface{} = this.SafeDict(response, "payment_method", map[string]interface{} {})
ch <- this.ParseDepositMethodId(result)
return nil
}()
return ch
}
func (this *coinbase) ParseDepositMethodIds(ids interface{}, optionalArgs ...interface{}) interface{} {
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
var result interface{} = []interface{}{}
for i := 0; IsLessThan(i, GetArrayLength(ids)); i++ {
var id interface{} = this.Extend(this.ParseDepositMethodId(GetValue(ids, i)), params)
AppendToArray(&result,id)
}
return result
}
func (this *coinbase) ParseDepositMethodId(depositId interface{}) interface{} {
return map[string]interface{} {
"info": depositId,
"id": this.SafeString(depositId, "id"),
"currency": this.SafeString(depositId, "currency"),
"verified": this.SafeBool(depositId, "verified"),
"tag": this.SafeString(depositId, "name"),
}
}
/**
* @method
* @name coinbase#fetchConvertQuote
* @description fetch a quote for converting from one currency to another
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_createconvertquote
* @param {string} fromCode the currency that you want to sell and convert from
* @param {string} toCode the currency that you want to buy and convert into
* @param {float} [amount] how much you want to trade in units of the from currency
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {object} [params.trade_incentive_metadata] an object to fill in user incentive data
* @param {string} [params.trade_incentive_metadata.user_incentive_id] the id of the incentive
* @param {string} [params.trade_incentive_metadata.code_val] the code value of the incentive
* @returns {object} a [conversion structure]{@link https://docs.ccxt.com/#/?id=conversion-structure}
*/
func (this *coinbase) FetchConvertQuote(fromCode interface{}, toCode interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
amount := GetArg(optionalArgs, 0, nil)
_ = amount
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
retRes45078 := (<-this.LoadMarkets())
PanicOnError(retRes45078)
var request interface{} = map[string]interface{} {
"from_account": fromCode,
"to_account": toCode,
"amount": this.NumberToString(amount),
}
response:= (<-this.V3PrivatePostBrokerageConvertQuote(this.Extend(request, params)))
PanicOnError(response)
var data interface{} = this.SafeDict(response, "trade", map[string]interface{} {})
ch <- this.ParseConversion(data)
return nil
}()
return ch
}
/**
* @method
* @name coinbase#createConvertTrade
* @description convert from one currency to another
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_commitconverttrade
* @param {string} id the id of the trade that you want to make
* @param {string} fromCode the currency that you want to sell and convert from
* @param {string} toCode the currency that you want to buy and convert into
* @param {float} [amount] how much you want to trade in units of the from currency
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [conversion structure]{@link https://docs.ccxt.com/#/?id=conversion-structure}
*/
func (this *coinbase) CreateConvertTrade(id interface{}, fromCode interface{}, toCode interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
amount := GetArg(optionalArgs, 0, nil)
_ = amount
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
retRes45318 := (<-this.LoadMarkets())
PanicOnError(retRes45318)
var request interface{} = map[string]interface{} {
"trade_id": id,
"from_account": fromCode,
"to_account": toCode,
}
response:= (<-this.V3PrivatePostBrokerageConvertTradeTradeId(this.Extend(request, params)))
PanicOnError(response)
var data interface{} = this.SafeDict(response, "trade", map[string]interface{} {})
ch <- this.ParseConversion(data)
return nil
}()
return ch
}
/**
* @method
* @name coinbase#fetchConvertTrade
* @description fetch the data for a conversion trade
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getconverttrade
* @param {string} id the id of the trade that you want to commit
* @param {string} code the unified currency code that was converted from
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {strng} params.toCode the unified currency code that was converted into
* @returns {object} a [conversion structure]{@link https://docs.ccxt.com/#/?id=conversion-structure}
*/
func (this *coinbase) FetchConvertTrade(id interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
code := GetArg(optionalArgs, 0, nil)
_ = code
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
retRes45548 := (<-this.LoadMarkets())
PanicOnError(retRes45548)
if IsTrue(IsEqual(code, nil)) {
panic(ArgumentsRequired(Add(this.Id, " fetchConvertTrade() requires a code argument")))
}
var toCode interface{} = this.SafeString(params, "toCode")
if IsTrue(IsEqual(toCode, nil)) {
panic(ArgumentsRequired(Add(this.Id, " fetchConvertTrade() requires a toCode parameter")))
}
params = this.Omit(params, "toCode")
var request interface{} = map[string]interface{} {
"trade_id": id,
"from_account": code,
"to_account": toCode,
}
response:= (<-this.V3PrivateGetBrokerageConvertTradeTradeId(this.Extend(request, params)))
PanicOnError(response)
var data interface{} = this.SafeDict(response, "trade", map[string]interface{} {})
ch <- this.ParseConversion(data)
return nil
}()
return ch
}
func (this *coinbase) ParseConversion(conversion interface{}, optionalArgs ...interface{}) interface{} {
fromCurrency := GetArg(optionalArgs, 0, nil)
_ = fromCurrency
toCurrency := GetArg(optionalArgs, 1, nil)
_ = toCurrency
var fromCoin interface{} = this.SafeString(conversion, "source_currency")
var fromCode interface{} = this.SafeCurrencyCode(fromCoin, fromCurrency)
var to interface{} = this.SafeString(conversion, "target_currency")
var toCode interface{} = this.SafeCurrencyCode(to, toCurrency)
var fromAmountStructure interface{} = this.SafeDict(conversion, "user_entered_amount")
var feeStructure interface{} = this.SafeDict(conversion, "total_fee")
var feeAmountStructure interface{} = this.SafeDict(feeStructure, "amount")
return map[string]interface{} {
"info": conversion,
"timestamp": nil,
"datetime": nil,
"id": this.SafeString(conversion, "id"),
"fromCurrency": fromCode,
"fromAmount": this.SafeNumber(fromAmountStructure, "value"),
"toCurrency": toCode,
"toAmount": nil,
"price": nil,
"fee": this.SafeNumber(feeAmountStructure, "value"),
}
}
/**
* @method
* @name coinbase#closePosition
* @description *futures only* closes open positions for a market
* @see https://coinbase-api.github.io/docs/#/en-us/swapV2/trade-api.html#One-Click%20Close%20All%20Positions
* @param {string} symbol Unified CCXT market symbol
* @param {string} [side] not used by coinbase
* @param {object} [params] extra parameters specific to the coinbase api endpoint
* @param {string} params.clientOrderId *mandatory* the client order id of the position to close
* @param {float} [params.size] the size of the position to close, optional
* @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
func (this *coinbase) ClosePosition(symbol interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
side := GetArg(optionalArgs, 0, nil)
_ = side
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
retRes46088 := (<-this.LoadMarkets())
PanicOnError(retRes46088)
var market interface{} = this.Market(symbol)
if !IsTrue(GetValue(market, "future")) {
panic(NotSupported(Add(this.Id, " closePosition() only supported for futures markets")))
}
var clientOrderId interface{} = this.SafeString2(params, "client_order_id", "clientOrderId")
params = this.Omit(params, "clientOrderId")
var request interface{} = map[string]interface{} {
"product_id": GetValue(market, "id"),
}
if IsTrue(IsEqual(clientOrderId, nil)) {
panic(ArgumentsRequired(Add(this.Id, " closePosition() requires a clientOrderId parameter")))
}
AddElementToObject(request, "client_order_id", clientOrderId)
response:= (<-this.V3PrivatePostBrokerageOrdersClosePosition(this.Extend(request, params)))
PanicOnError(response)
var order interface{} = this.SafeDict(response, "success_response", map[string]interface{} {})
ch <- this.ParseOrder(order)
return nil
}()
return ch
}
/**
* @method
* @name coinbase#fetchPositions
* @description fetch all open positions
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getfcmpositions
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getintxpositions
* @param {string[]} [symbols] list of unified market symbols
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.portfolio] the portfolio UUID to fetch positions for
* @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
*/
func (this *coinbase) FetchPositions(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbols := GetArg(optionalArgs, 0, nil)
_ = symbols
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
retRes46398 := (<-this.LoadMarkets())
PanicOnError(retRes46398)
symbols = this.MarketSymbols(symbols)
var market interface{} = nil
if IsTrue(!IsEqual(symbols, nil)) {
market = this.Market(GetValue(symbols, 0))
}
var typeVar interface{} = nil
typeVarparamsVariable := this.HandleMarketTypeAndParams("fetchPositions", market, params);
typeVar = GetValue(typeVarparamsVariable,0);
params = GetValue(typeVarparamsVariable,1)
var response interface{} = nil
if IsTrue(IsEqual(typeVar, "future")) {
response = (<-this.V3PrivateGetBrokerageCfmPositions(params))
PanicOnError(response)
} else {
var portfolio interface{} = nil
portfolioparamsVariable := this.HandleOptionAndParams(params, "fetchPositions", "portfolio");
portfolio = GetValue(portfolioparamsVariable,0);
params = GetValue(portfolioparamsVariable,1)
if IsTrue(IsEqual(portfolio, nil)) {
panic(ArgumentsRequired(Add(this.Id, " fetchPositions() requires a \"portfolio\" value in params (eg: dbcb91e7-2bc9-515), or set as exchange.options[\"portfolio\"]. You can get a list of portfolios with fetchPortfolios()")))
}
var request interface{} = map[string]interface{} {
"portfolio_uuid": portfolio,
}
response = (<-this.V3PrivateGetBrokerageIntxPositionsPortfolioUuid(this.Extend(request, params)))
PanicOnError(response)
}
var positions interface{} = this.SafeList(response, "positions", []interface{}{})
ch <- this.ParsePositions(positions, symbols)
return nil
}()
return ch
}
/**
* @method
* @name coinbase#fetchPosition
* @description fetch data on a single open contract trade position
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getintxposition
* @see https://docs.cloud.coinbase.com/advanced-trade/reference/retailbrokerageapi_getfcmposition
* @param {string} symbol unified market symbol of the market the position is held in, default is undefined
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.product_id] *futures only* the product id of the position to fetch, required for futures markets only
* @param {string} [params.portfolio] *perpetual/swaps only* the portfolio UUID to fetch the position for, required for perpetual/swaps markets only
* @returns {object} a [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
*/
func (this *coinbase) FetchPosition(symbol interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
retRes46788 := (<-this.LoadMarkets())
PanicOnError(retRes46788)
var market interface{} = this.Market(symbol)
var response interface{} = nil
if IsTrue(GetValue(market, "future")) {
var productId interface{} = this.SafeString(market, "product_id")
if IsTrue(IsEqual(productId, nil)) {
panic(ArgumentsRequired(Add(this.Id, " fetchPosition() requires a \"product_id\" in params")))
}
var futureRequest interface{} = map[string]interface{} {
"product_id": productId,
}
response = (<-this.V3PrivateGetBrokerageCfmPositionsProductId(this.Extend(futureRequest, params)))
PanicOnError(response)
} else {
var portfolio interface{} = nil
portfolioparamsVariable := this.HandleOptionAndParams(params, "fetchPositions", "portfolio");
portfolio = GetValue(portfolioparamsVariable,0);
params = GetValue(portfolioparamsVariable,1)
if IsTrue(IsEqual(portfolio, nil)) {
panic(ArgumentsRequired(Add(this.Id, " fetchPosition() requires a \"portfolio\" value in params (eg: dbcb91e7-2bc9-515), or set as exchange.options[\"portfolio\"]. You can get a list of portfolios with fetchPortfolios()")))
}
var request interface{} = map[string]interface{} {
"symbol": GetValue(market, "id"),
"portfolio_uuid": portfolio,
}
response = (<-this.V3PrivateGetBrokerageIntxPositionsPortfolioUuidSymbol(this.Extend(request, params)))
PanicOnError(response)
}
var position interface{} = this.SafeDict(response, "position", map[string]interface{} {})
ch <- this.ParsePosition(position, market)
return nil
}()
return ch
}
func (this *coinbase) ParsePosition(position interface{}, optionalArgs ...interface{}) interface{} {
//
// {
// "product_id": "1r4njf84-0-0",
// "product_uuid": "cd34c18b-3665-4ed8-9305-3db277c49fc5",
// "symbol": "ADA-PERP-INTX",
// "vwap": {
// "value": "0.6171",
// "currency": "USDC"
// },
// "position_side": "POSITION_SIDE_LONG",
// "net_size": "20",
// "buy_order_size": "0",
// "sell_order_size": "0",
// "im_contribution": "0.1",
// "unrealized_pnl": {
// "value": "0.074",
// "currency": "USDC"
// },
// "mark_price": {
// "value": "0.6208",
// "currency": "USDC"
// },
// "liquidation_price": {
// "value": "0",
// "currency": "USDC"
// },
// "leverage": "1",
// "im_notional": {
// "value": "12.342",
// "currency": "USDC"
// },
// "mm_notional": {
// "value": "0.814572",
// "currency": "USDC"
// },
// "position_notional": {
// "value": "12.342",
// "currency": "USDC"
// },
// "margin_type": "MARGIN_TYPE_CROSS",
// "liquidation_buffer": "19.677828",
// "liquidation_percentage": "4689.3506",
// "portfolio_summary": {
// "portfolio_uuid": "018ebd63-1f6d-7c8e-ada9-0761c5a2235f",
// "collateral": "20.4184",
// "position_notional": "12.342",
// "open_position_notional": "12.342",
// "pending_fees": "0",
// "borrow": "0",
// "accrued_interest": "0",
// "rolling_debt": "0",
// "portfolio_initial_margin": "0.1",
// "portfolio_im_notional": {
// "value": "12.342",
// "currency": "USDC"
// },
// "portfolio_maintenance_margin": "0.066",
// "portfolio_mm_notional": {
// "value": "0.814572",
// "currency": "USDC"
// },
// "liquidation_percentage": "4689.3506",
// "liquidation_buffer": "19.677828",
// "margin_type": "MARGIN_TYPE_CROSS",
// "margin_flags": "PORTFOLIO_MARGIN_FLAGS_UNSPECIFIED",
// "liquidation_status": "PORTFOLIO_LIQUIDATION_STATUS_NOT_LIQUIDATING",
// "unrealized_pnl": {
// "value": "0.074",
// "currency": "USDC"
// },
// "buying_power": {
// "value": "8.1504",
// "currency": "USDC"
// },
// "total_balance": {
// "value": "20.4924",
// "currency": "USDC"
// },
// "max_withdrawal": {
// "value": "8.0764",
// "currency": "USDC"
// }
// },
// "entry_vwap": {
// "value": "0.6091",
// "currency": "USDC"
// }
// }
//
market := GetArg(optionalArgs, 0, nil)
_ = market
var marketId interface{} = this.SafeString(position, "symbol", "")
market = this.SafeMarket(marketId, market)
var rawMargin interface{} = this.SafeString(position, "margin_type")
var marginMode interface{} = nil
if IsTrue(!IsEqual(rawMargin, nil)) {
marginMode = Ternary(IsTrue((IsEqual(rawMargin, "MARGIN_TYPE_CROSS"))), "cross", "isolated")
}
var notionalObject interface{} = this.SafeDict(position, "position_notional", map[string]interface{} {})
var positionSide interface{} = this.SafeString(position, "position_side")
var side interface{} = Ternary(IsTrue((IsEqual(positionSide, "POSITION_SIDE_LONG"))), "long", "short")
var unrealizedPNLObject interface{} = this.SafeDict(position, "unrealized_pnl", map[string]interface{} {})
var liquidationPriceObject interface{} = this.SafeDict(position, "liquidation_price", map[string]interface{} {})
var liquidationPrice interface{} = this.SafeNumber(liquidationPriceObject, "value")
var vwapObject interface{} = this.SafeDict(position, "vwap", map[string]interface{} {})
var summaryObject interface{} = this.SafeDict(position, "portfolio_summary", map[string]interface{} {})
return this.SafePosition(map[string]interface{} {
"info": position,
"id": this.SafeString(position, "product_id"),
"symbol": this.SafeSymbol(marketId, market),
"notional": this.SafeNumber(notionalObject, "value"),
"marginMode": marginMode,
"liquidationPrice": liquidationPrice,
"entryPrice": this.SafeNumber(vwapObject, "value"),
"unrealizedPnl": this.SafeNumber(unrealizedPNLObject, "value"),
"realizedPnl": nil,
"percentage": nil,
"contracts": this.SafeNumber(position, "net_size"),
"contractSize": GetValue(market, "contractSize"),
"markPrice": nil,
"lastPrice": nil,
"side": side,
"hedged": nil,
"timestamp": nil,
"datetime": nil,
"lastUpdateTimestamp": nil,
"maintenanceMargin": nil,
"maintenanceMarginPercentage": nil,
"collateral": this.SafeNumber(summaryObject, "collateral"),
"initialMargin": nil,
"initialMarginPercentage": nil,
"leverage": this.SafeNumber(position, "leverage"),
"marginRatio": nil,
"stopLossPrice": nil,
"takeProfitPrice": nil,
})
}
/**
* @method
* @name coinbase#fetchTradingFees
* @see https://docs.cdp.coinbase.com/advanced-trade/reference/retailbrokerageapi_gettransactionsummary/
* @description fetch the trading fees for multiple markets
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.type] 'spot' or 'swap'
* @returns {object} a dictionary of [fee structures]{@link https://docs.ccxt.com/#/?id=fee-structure} indexed by market symbols
*/
func (this *coinbase) FetchTradingFees(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
retRes48538 := (<-this.LoadMarkets())
PanicOnError(retRes48538)
var typeVar interface{} = nil
typeVarparamsVariable := this.HandleMarketTypeAndParams("fetchTradingFees", nil, params);
typeVar = GetValue(typeVarparamsVariable,0);
params = GetValue(typeVarparamsVariable,1)
var isSpot interface{} = (IsEqual(typeVar, "spot"))
var productType interface{} = Ternary(IsTrue(isSpot), "SPOT", "FUTURE")
var request interface{} = map[string]interface{} {
"product_type": productType,
}
response:= (<-this.V3PrivateGetBrokerageTransactionSummary(this.Extend(request, params)))
PanicOnError(response)
//
// {
// total_volume: '0',
// total_fees: '0',
// fee_tier: {
// pricing_tier: 'Advanced 1',
// usd_from: '0',
// usd_to: '1000',
// taker_fee_rate: '0.008',
// maker_fee_rate: '0.006',
// aop_from: '',
// aop_to: ''
// },
// margin_rate: null,
// goods_and_services_tax: null,
// advanced_trade_only_volume: '0',
// advanced_trade_only_fees: '0',
// coinbase_pro_volume: '0',
// coinbase_pro_fees: '0',
// total_balance: '',
// has_promo_fee: false
// }
//
var data interface{} = this.SafeDict(response, "fee_tier", map[string]interface{} {})
var taker_fee interface{} = this.SafeNumber(data, "taker_fee_rate")
var marker_fee interface{} = this.SafeNumber(data, "maker_fee_rate")
var result interface{} = map[string]interface{} {}
for i := 0; IsLessThan(i, GetArrayLength(this.Symbols)); i++ {
var symbol interface{} = GetValue(this.Symbols, i)
var market interface{} = this.Market(symbol)
if IsTrue(IsTrue((IsTrue(isSpot) && IsTrue(GetValue(market, "spot")))) || IsTrue((!IsTrue(isSpot) && !IsTrue(GetValue(market, "spot"))))) {
AddElementToObject(result, symbol, map[string]interface{} {
"info": response,
"symbol": symbol,
"maker": taker_fee,
"taker": marker_fee,
"percentage": true,
})
}
}
ch <- result
return nil
}()
return ch
}
func (this *coinbase) CreateAuthToken(seconds interface{}, optionalArgs ...interface{}) interface{} {
// it may not work for v2
method := GetArg(optionalArgs, 0, nil)
_ = method
url := GetArg(optionalArgs, 1, nil)
_ = url
var uri interface{} = nil
if IsTrue(!IsEqual(url, nil)) {
uri = Add(Add(method, " "), Replace(url, "https://", ""))
var quesPos interface{} = GetIndexOf(uri, "?")
// Due to we use mb_strpos, quesPos could be false in php. In that case, the quesPos >= 0 is true
// Also it's not possible that the question mark is first character, only check > 0 here.
if IsTrue(IsGreaterThan(quesPos, 0)) {
uri = Slice(uri, 0, quesPos)
}
}
var nonce interface{} = this.RandomBytes(16)
var request interface{} = map[string]interface{} {
"aud": []interface{}{"retail_rest_api_proxy"},
"iss": "coinbase-cloud",
"nbf": seconds,
"exp": Add(seconds, 120),
"sub": this.ApiKey,
"iat": seconds,
}
if IsTrue(!IsEqual(uri, nil)) {
AddElementToObject(request, "uri", uri)
}
var token interface{} = Jwt(request, this.Encode(this.Secret), sha256, false, map[string]interface{} {
"kid": this.ApiKey,
"nonce": nonce,
"alg": "ES256",
})
return token
}
func (this *coinbase) Nonce() interface{} {
return Subtract(this.Milliseconds(), GetValue(this.Options, "timeDifference"))
}
func (this *coinbase) Sign(path interface{}, optionalArgs ...interface{}) interface{} {
api := GetArg(optionalArgs, 0, []interface{}{})
_ = api
method := GetArg(optionalArgs, 1, "GET")
_ = method
params := GetArg(optionalArgs, 2, map[string]interface{} {})
_ = params
headers := GetArg(optionalArgs, 3, nil)
_ = headers
body := GetArg(optionalArgs, 4, nil)
_ = body
var version interface{} = GetValue(api, 0)
var signed interface{} = IsEqual(GetValue(api, 1), "private")
var isV3 interface{} = IsEqual(version, "v3")
var pathPart interface{} = Ternary(IsTrue((isV3)), "api/v3", "v2")
var fullPath interface{} = Add(Add(Add("/", pathPart), "/"), this.ImplodeParams(path, params))
var query interface{} = this.Omit(params, this.ExtractParams(path))
var savedPath interface{} = fullPath
if IsTrue(IsEqual(method, "GET")) {
if IsTrue(GetArrayLength(ObjectKeys(query))) {
fullPath = Add(fullPath, Add("?", this.UrlencodeWithArrayRepeat(query)))
}
}
var url interface{} = Add(GetValue(GetValue(this.Urls, "api"), "rest"), fullPath)
if IsTrue(signed) {
var authorization interface{} = this.SafeString(this.Headers, "Authorization")
var authorizationString interface{} = nil
if IsTrue(!IsEqual(authorization, nil)) {
authorizationString = authorization
} else if IsTrue(IsTrue(this.Token) && !IsTrue(this.CheckRequiredCredentials(false))) {
authorizationString = Add("Bearer ", this.Token)
} else {
this.CheckRequiredCredentials()
var seconds interface{} = this.Seconds()
var payload interface{} = ""
if IsTrue(!IsEqual(method, "GET")) {
if IsTrue(GetArrayLength(ObjectKeys(query))) {
body = this.Json(query)
payload = body
}
} else {
if !IsTrue(isV3) {
if IsTrue(GetArrayLength(ObjectKeys(query))) {
payload = Add(payload, Add("?", this.Urlencode(query)))
}
}
}
// v3: 'GET' doesn't need payload in the signature. inside url is enough
// https://docs.cloud.coinbase.com/advanced-trade/docs/auth#example-request
// v2: 'GET' require payload in the signature
// https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-key-authentication
var isCloudAPiKey interface{} = IsTrue((IsGreaterThanOrEqual(GetIndexOf(this.ApiKey, "organizations/"), 0))) || IsTrue((StartsWith(this.Secret, "-----BEGIN")))
if IsTrue(isCloudAPiKey) {
if IsTrue(StartsWith(this.ApiKey, "-----BEGIN")) {
panic(ArgumentsRequired(Add(this.Id, " apiKey should contain the name (eg: organizations/3b910e93....) and not the public key")))
}
// // it may not work for v2
// let uri = method + ' ' + url.replace ('https://', '');
// const quesPos = uri.indexOf ('?');
// // Due to we use mb_strpos, quesPos could be false in php. In that case, the quesPos >= 0 is true
// // Also it's not possible that the question mark is first character, only check > 0 here.
// if (quesPos > 0) {
// uri = uri.slice (0, quesPos);
// }
// const nonce = this.randomBytes (16);
// const request: Dict = {
// 'aud': [ 'retail_rest_api_proxy' ],
// 'iss': 'coinbase-cloud',
// 'nbf': seconds,
// 'exp': seconds + 120,
// 'sub': this.apiKey,
// 'uri': uri,
// 'iat': seconds,
// };
var token interface{} = this.CreateAuthToken(seconds, method, url)
// const token = jwt (request, this.encode (this.secret), sha256, false, { 'kid': this.apiKey, 'nonce': nonce, 'alg': 'ES256' });
authorizationString = Add("Bearer ", token)
} else {
var nonce interface{} = this.Nonce()
var timestamp interface{} = this.ParseToInt(Divide(nonce, 1000))
var timestampString interface{} = ToString(timestamp)
var auth interface{} = Add(Add(Add(timestampString, method), savedPath), payload)
var signature interface{} = this.Hmac(this.Encode(auth), this.Encode(this.Secret), sha256)
headers = map[string]interface{} {
"CB-ACCESS-KEY": this.ApiKey,
"CB-ACCESS-SIGN": signature,
"CB-ACCESS-TIMESTAMP": timestampString,
"Content-Type": "application/json",
}
}
}
if IsTrue(!IsEqual(authorizationString, nil)) {
headers = map[string]interface{} {
"Authorization": authorizationString,
"Content-Type": "application/json",
}
if IsTrue(!IsEqual(method, "GET")) {
if IsTrue(GetArrayLength(ObjectKeys(query))) {
body = this.Json(query)
}
}
}
}
return map[string]interface{} {
"url": url,
"method": method,
"body": body,
"headers": headers,
}
}
func (this *coinbase) HandleErrors(code interface{}, reason interface{}, url interface{}, method interface{}, headers interface{}, body interface{}, response interface{}, requestHeaders interface{}, requestBody interface{}) interface{} {
if IsTrue(IsEqual(response, nil)) {
return nil // fallback to default error handler
}
var feedback interface{} = Add(Add(this.Id, " "), body)
//
// {"error": "invalid_request", "error_description": "The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed."}
//
// or
//
// {
// "errors": [
// {
// "id": "not_found",
// "message": "Not found"
// }
// ]
// }
// or
// {
// "error": "UNKNOWN_FAILURE_REASON",
// "message": "",
// "error_details": "",
// "preview_failure_reason": "PREVIEW_STOP_PRICE_BELOW_LAST_TRADE_PRICE"
// }
//
var errorCode interface{} = this.SafeString(response, "error")
if IsTrue(!IsEqual(errorCode, nil)) {
var errorMessage interface{} = this.SafeString2(response, "error_description", "preview_failure_reason")
this.ThrowExactlyMatchedException(GetValue(this.Exceptions, "exact"), errorCode, feedback)
this.ThrowBroadlyMatchedException(GetValue(this.Exceptions, "broad"), errorMessage, feedback)
panic(ExchangeError(feedback))
}
var errors interface{} = this.SafeList(response, "errors")
if IsTrue(!IsEqual(errors, nil)) {
if IsTrue(IsArray(errors)) {
var numErrors interface{} = GetArrayLength(errors)
if IsTrue(IsGreaterThan(numErrors, 0)) {
errorCode = this.SafeString(GetValue(errors, 0), "id")
var errorMessage interface{} = this.SafeString(GetValue(errors, 0), "message")
if IsTrue(!IsEqual(errorCode, nil)) {
this.ThrowExactlyMatchedException(GetValue(this.Exceptions, "exact"), errorCode, feedback)
this.ThrowBroadlyMatchedException(GetValue(this.Exceptions, "broad"), errorMessage, feedback)
panic(ExchangeError(feedback))
}
}
}
}
var advancedTrade interface{} = GetValue(this.Options, "advanced")
if IsTrue(!IsTrue((InOp(response, "data"))) && IsTrue((!IsTrue(advancedTrade)))) {
panic(ExchangeError(Add(Add(this.Id, " failed due to a malformed response "), this.Json(response))))
}
return nil
}
func (this *coinbase) Init(userConfig map[string]interface{}) {
this.Exchange = Exchange{}
this.Exchange.InitParent(userConfig, this.Describe().(map[string]interface{}), this)
this.Exchange.DerivedExchange = this
}