diff --git a/Project.toml b/Project.toml index 59c659c0..b27733ee 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "CryptoExchangeAPIs" uuid = "5e3d4798-c815-4641-85e1-deed530626d3" -version = "0.33.0" +version = "0.33.1" [deps] Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" diff --git a/docs/src/pages/Bithumb.md b/docs/src/pages/Bithumb.md index 5b5918e8..8208b39f 100644 --- a/docs/src/pages/Bithumb.md +++ b/docs/src/pages/Bithumb.md @@ -19,4 +19,5 @@ CryptoExchangeAPIs.Bithumb.Spot.market CryptoExchangeAPIs.Bithumb.Spot.order_book CryptoExchangeAPIs.Bithumb.Spot.ticker CryptoExchangeAPIs.Bithumb.Spot.user_transactions +CryptoExchangeAPIs.Bithumb.Spot.withdraw_info ``` diff --git a/examples/Bithumb/Spot.jl b/examples/Bithumb/Spot.jl index 30204b8a..34ff525b 100644 --- a/examples/Bithumb/Spot.jl +++ b/examples/Bithumb/Spot.jl @@ -46,3 +46,9 @@ Bithumb.Spot.user_transactions_log( count = 50, searchGb = Bithumb.Spot.UserTransactionsLog.ALL, ) + +Bithumb.Spot.withdraw_info( + bithumb_client; + currency = "ETH", + net_type = "ETH", +) diff --git a/src/Bithumb/Bithumb.jl b/src/Bithumb/Bithumb.jl index f005c243..582e744c 100644 --- a/src/Bithumb/Bithumb.jl +++ b/src/Bithumb/Bithumb.jl @@ -10,6 +10,7 @@ export BithumbCommonQuery, using Serde using Dates, NanoDates, TimeZones, Base64, Nettle +using UUIDs, JSONWebTokens using ..CryptoExchangeAPIs import ..CryptoExchangeAPIs: Maybe, AbstractAPIsError, AbstractAPIsData, AbstractAPIsQuery, AbstractAPIsClient @@ -93,12 +94,22 @@ function CryptoExchangeAPIs.request_sign!(::BithumbClient, query::Q, ::String):: end function CryptoExchangeAPIs.request_sign!(client::BithumbClient, query::Q, endpoint::String)::Q where {Q<:BithumbPrivateQuery} - query.nonce = Dates.now(UTC) - query.endpoint = Serde.SerQuery.escape_query("/" * endpoint) query.signature = nothing - body = Serde.to_query(query) - salt = string("/", endpoint, Char(0), body, Char(0), round(Int64, 1000 * datetime2unix(query.nonce))) - query.signature = Base64.base64encode(hexdigest("sha512", client.secret_key, salt)) + body = Dict{String,Any}( + "access_key" => client.public_key, + "nonce" => string(UUIDs.uuid4()), + "timestamp" => string(round(Int64, 1000 * datetime2unix(now(UTC)))), + ) + if !isempty(Serde.to_query(query)) + qstr = Serde.to_query(query) + merge!(body, Dict{String,Any}( + "query_hash" => hexdigest("sha512", qstr), + "query_hash_alg" => "SHA512", + )) + end + hs512 = JSONWebTokens.HS512(client.secret_key) + token = JSONWebTokens.encode(hs512, body) + query.signature = "Bearer $token" return query end @@ -122,9 +133,7 @@ end function CryptoExchangeAPIs.request_headers(client::BithumbClient, query::BithumbPrivateQuery)::Vector{Pair{String,String}} return Pair{String,String}[ - "Api-Key" => client.public_key, - "Api-Sign" => query.signature, - "Api-Nonce" => string(round(Int64, 1000 * datetime2unix(query.nonce))), + "Authorization" => query.signature, ] end diff --git a/src/Bithumb/Spot/API/WithdrawInfo.jl b/src/Bithumb/Spot/API/WithdrawInfo.jl new file mode 100644 index 00000000..d336415b --- /dev/null +++ b/src/Bithumb/Spot/API/WithdrawInfo.jl @@ -0,0 +1,157 @@ +module WithdrawInfo + +export WithdrawInfoQuery, + WithdrawInfoData, + withdraw_info + +using Serde +using Dates, NanoDates, TimeZones + +using CryptoExchangeAPIs.Bithumb +using CryptoExchangeAPIs.Bithumb: Data +using CryptoExchangeAPIs: Maybe, APIsRequest + +Base.@kwdef mutable struct WithdrawInfoQuery <: BithumbPrivateQuery + currency::String + net_type::String + + signature::Maybe{String} = nothing +end + +struct MemberLevel <: BithumbData + security_level::Maybe{Int64} + fee_level::Maybe{Int64} + email_verified::Maybe{Bool} + identity_auth_verified::Maybe{Bool} + bank_account_verified::Maybe{Bool} + two_factor_auth_verified::Maybe{Bool} + locked::Maybe{Bool} + wallet_locked::Maybe{Bool} +end + +struct Currency <: BithumbData + code::String + withdraw_fee::Float64 + is_coin::Bool + wallet_state::String + wallet_support::Vector{String} +end + +struct Account <: BithumbData + currency::String + balance::Float64 + locked::Float64 + avg_buy_price::Float64 + avg_buy_price_modified::Bool + unit_currency::String +end + +struct WithdrawLimit <: BithumbData + currency::String + minimum::Float64 + onetime::Float64 + daily::Float64 + remaining_daily::Float64 + fixed::Int64 + can_withdraw::Bool + remaining_daily_krw::Maybe{Float64} +end + +struct WithdrawInfoData <: BithumbData + member_level::MemberLevel + currency::Currency + account::Account + withdraw_limit::WithdrawLimit +end + +""" + withdraw_info(client::BithumbClient, query::WithdrawInfoQuery) + withdraw_info(client::BithumbClient; kw...) + +Retrieves detailed information about the withdrawal capabilities for a specific currency on the Bithumb exchange. + +[`GET /v1/withdraws/chance`](https://apidocs.bithumb.com/reference/%EC%B6%9C%EA%B8%88-%EA%B0%80%EB%8A%A5-%EC%A0%95%EB%B3%B4) + +## Parameters: +| Parameter | Type | Required | Description | +|-------------|-----------|----------|--------------------------------------| +| currency | String | true | The currency code (e.g., "BTC"). | +| net_type | String | true | The network type (e.g., "BTC"). | + +## Code samples: +```julia +using Serde +using CryptoExchangeAPIs.Bithumb + +bithumb_client = Bithumb.Client(; + base_url = "https://api.bithumb.com", + public_key = ENV["BITHUMB_PUBLIC_KEY"], + secret_key = ENV["BITHUMB_SECRET_KEY"], +) + +result = Bithumb.Spot.withdraw_info( + bithumb_client; + currency = "BTC", + net_type = "BTC", +) + +to_pretty_json(result.result) +``` + +## Result: + +```json +{ + "member_level": { + "security_level": null, + "fee_level": null, + "email_verified": null, + "identity_auth_verified": null, + "bank_account_verified": null, + "two_factor_auth_verified": null, + "locked": null, + "wallet_locked": null + }, + "currency": { + "code": "BTC", + "withdraw_fee": "0.000108", + "is_coin": true, + "wallet_state": "working", + "wallet_support": [ + "deposit", + "withdraw" + ] + }, + "account": { + "currency": "BTC", + "balance": "124.45282908", + "locked": "0", + "avg_buy_price": "36341011", + "avg_buy_price_modified": false, + "unit_currency": "KRW" + }, + "withdraw_limit": { + "currency": "BTC", + "onetime": "6.01", + "daily": "160", + "remaining_daily": "160.00000000", + "remaining_daily_fiat": null, + "fiat_currency": null, + "minimum": "0.0001", + "fixed": 8, + "withdraw_delayed_fiat": null, + "can_withdraw": true, + "remaining_daily_krw": null + } +} +``` +""" +function withdraw_info(client::BithumbClient, query::WithdrawInfoQuery) + return APIsRequest{WithdrawInfoData}("GET", "v1/withdraws/chance", query)(client) +end + +function withdraw_info(client::BithumbClient; kw...) + return withdraw_info(client, WithdrawInfoQuery(; kw...)) +end + +end diff --git a/src/Bithumb/Spot/Spot.jl b/src/Bithumb/Spot/Spot.jl index 013cb1e4..368b899d 100644 --- a/src/Bithumb/Spot/Spot.jl +++ b/src/Bithumb/Spot/Spot.jl @@ -26,4 +26,7 @@ using .Ticker include("API/UserTransactions.jl") using .UserTransactions +include("API/WithdrawInfo.jl") +using .WithdrawInfo + end