Skip to content

Commit fa8bb4d

Browse files
Add Bithumb Spot exchange (#35)
Co-authored-by: Yuri Shadrin <53979055+yshadrin@users.noreply.github.com>
1 parent 7952cb0 commit fa8bb4d

File tree

17 files changed

+858
-3
lines changed

17 files changed

+858
-3
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "CryptoAPIs"
22
uuid = "5e3d4798-c815-4641-85e1-deed530626d3"
3-
version = "0.17.0"
3+
version = "0.18.0"
44

55
[deps]
66
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@ Then, to install CryptoAPIs, simply use the Julia package manager:
5454
<td><a href="src/Binance/CoinMFutures">CryptoAPIs.Binance.CoinMFutures</a></td>
5555
<td><a href="https://bhftbootcamp.github.io/CryptoAPIs.jl/stable/pages/Binance/#CoinMFutures">Coin-M Futures</a></td>
5656
</tr>
57+
<tr>
58+
<td><img src="docs/src/assets/bithumb.png" alt="Bithumb Logo" width="20" height="20"></td>
59+
<td><a href="https://m.bithumb.com/">Bithumb</a></td>
60+
<td><a href="https://apidocs.bithumb.com/">Spot</a></td>
61+
<td><a href="src/Bithumb/Spot">CryptoAPIs.Bithumb.Spot</a></td>
62+
<td><a href="https://bhftbootcamp.github.io/CryptoAPIs.jl/stable/pages/Bithumb/#Spot">Spot</a></td>
63+
</tr>
5764
<tr>
5865
<td><img src="docs/src/assets/bybit.png" alt="Bybit Logo" width="20" height="20"></td>
5966
<td><a href="https://www.bybit.com/en/trade/spot/BTC/USDT">Bybit</a></td>

docs/make.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ makedocs(;
1717
"Home" => "index.md",
1818
"API Reference" => "pages/api_reference.md",
1919
"pages/Binance.md",
20+
"pages/Bithumb.md",
2021
"pages/Bybit.md",
2122
"pages/Coinbase.md",
2223
"pages/Cryptocom.md",

docs/src/index.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@ Then, to install CryptoAPIs, simply use the Julia package manager:
4848
<td><a href="src/Binance/CoinMFutures">CryptoAPIs.Binance.CoinMFutures</a></td>
4949
<td><a href="https://bhftbootcamp.github.io/CryptoAPIs.jl/stable/pages/Binance/#CoinMFutures">Coin-M Futures</a></td>
5050
</tr>
51+
<tr>
52+
<td><img src="assets/bithumb.png" alt="Bithumb Logo" width="20" height="20"></td>
53+
<td><a href="https://m.bithumb.com/">Bithumb</a></td>
54+
<td><a href="https://apidocs.bithumb.com/">Spot</a></td>
55+
<td><a href="src/Bithumb/Spot">CryptoAPIs.Bithumb.Spot</a></td>
56+
<td><a href="https://bhftbootcamp.github.io/CryptoAPIs.jl/stable/pages/Bithumb/#Spot">Spot</a></td>
57+
</tr>
5158
<tr>
5259
<td><img src="assets/bybit.png" alt="Bybit Logo" width="20" height="20"></td>
5360
<td><a href="https://www.bybit.com/en/trade/spot/BTC/USDT">Bybit</a></td>

docs/src/pages/Bithumb.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Bithumb
2+
3+
```@docs
4+
CryptoAPIs.Bithumb.BithumbClient
5+
CryptoAPIs.Bithumb.BithumbAPIError
6+
CryptoAPIs.Bithumb.Data
7+
```
8+
9+
## Spot
10+
11+
```@docs
12+
CryptoAPIs.Bithumb.Spot.public_client
13+
```
14+
15+
```@docs
16+
CryptoAPIs.Bithumb.Spot.asset_status
17+
CryptoAPIs.Bithumb.Spot.candle
18+
CryptoAPIs.Bithumb.Spot.order_book
19+
CryptoAPIs.Bithumb.Spot.ticker
20+
CryptoAPIs.Bithumb.Spot.user_transactions
21+
```

examples/Bithumb/Spot.jl

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Bithumb/Spot
2+
# https://apidocs.bithumb.com/
3+
4+
using Dates
5+
using CryptoAPIs
6+
using CryptoAPIs.Bithumb
7+
8+
CryptoAPIs.Bithumb.Spot.asset_status()
9+
CryptoAPIs.Bithumb.Spot.asset_status(; currency = "ADA")
10+
11+
CryptoAPIs.Bithumb.Spot.candle(;
12+
order_currency = "BTC",
13+
payment_currency = "KRW",
14+
interval = CryptoAPIs.Bithumb.Spot.Candle.h24,
15+
)
16+
17+
CryptoAPIs.Bithumb.Spot.order_book(;
18+
order_currency = "BTC",
19+
payment_currency = "KRW",
20+
count = 5,
21+
)
22+
CryptoAPIs.Bithumb.Spot.order_book(;
23+
payment_currency = "KRW",
24+
count = 5,
25+
)
26+
27+
CryptoAPIs.Bithumb.Spot.ticker(;
28+
order_currency = "BTC",
29+
payment_currency = "KRW",
30+
)
31+
32+
CryptoAPIs.Bithumb.Spot.ticker(;
33+
payment_currency = "KRW",
34+
)
35+
36+
bithumb_client = CryptoAPIs.Bithumb.BithumbClient(;
37+
base_url = "https://api.bithumb.com",
38+
public_key = ENV["BITHUMB_PUBLIC_KEY"],
39+
secret_key = ENV["BITHUMB_SECRET_KEY"],
40+
)
41+
42+
Bithumb.Spot.user_transactions_log(
43+
bithumb_client;
44+
order_currency = "ETH",
45+
payment_currency = "BTC",
46+
count = 50,
47+
searchGb = Bithumb.Spot.UserTransactionsLog.ALL,
48+
)

src/Bithumb/Bithumb.jl

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
module Bithumb
2+
3+
export BithumbCommonQuery,
4+
BithumbPublicQuery,
5+
BithumbAccessQuery,
6+
BithumbPrivateQuery,
7+
BithumbAPIError,
8+
BithumbClient,
9+
BithumbData
10+
11+
using Serde
12+
using Dates, NanoDates, TimeZones, Base64, Nettle
13+
14+
using ..CryptoAPIs
15+
import ..CryptoAPIs: Maybe, AbstractAPIsError, AbstractAPIsData, AbstractAPIsQuery, AbstractAPIsClient
16+
17+
abstract type BithumbData <: AbstractAPIsData end
18+
abstract type BithumbCommonQuery <: AbstractAPIsQuery end
19+
abstract type BithumbPublicQuery <: BithumbCommonQuery end
20+
abstract type BithumbAccessQuery <: BithumbCommonQuery end
21+
abstract type BithumbPrivateQuery <: BithumbCommonQuery end
22+
23+
"""
24+
Data{D<:Union{A,Vector{A},Dict{String,A}} where {A<:AbstractAPIsData}} <: AbstractAPIsData
25+
26+
## Required fields
27+
- `status::String`: Request status.
28+
- `data::D`: Request result data.
29+
30+
## Optional fields
31+
- `date::NanoDate`: Current time.
32+
"""
33+
struct Data{D<:Union{A,Vector{A},Dict{String,A}} where {A<:AbstractAPIsData}} <: AbstractAPIsData
34+
status::String
35+
date::Maybe{NanoDate}
36+
data::D
37+
end
38+
39+
"""
40+
BithumbClient <: AbstractAPIsClient
41+
42+
Client info.
43+
44+
## Required fields
45+
- `base_url::String`: Base URL for the client.
46+
47+
## Optional fields
48+
- `public_key::String`: Public key for authentication.
49+
- `secret_key::String`: Secret key for authentication.
50+
- `interface::String`: Interface for the client.
51+
- `proxy::String`: Proxy information for the client.
52+
- `account_name::String`: Account name associated with the client.
53+
- `description::String`: Description of the client.
54+
"""
55+
Base.@kwdef struct BithumbClient <: AbstractAPIsClient
56+
base_url::String
57+
public_key::Maybe{String} = nothing
58+
secret_key::Maybe{String} = nothing
59+
interface::Maybe{String} = nothing
60+
proxy::Maybe{String} = nothing
61+
account_name::Maybe{String} = nothing
62+
description::Maybe{String} = nothing
63+
end
64+
65+
"""
66+
BithumbAPIError{T} <: AbstractAPIsError
67+
68+
Exception thrown when an API method fails with code `T`.
69+
70+
## Required fields
71+
- `status::Int64`: Error status code.
72+
73+
## Optional fields
74+
- `message::String`: Error message.
75+
"""
76+
struct BithumbAPIError{T} <: AbstractAPIsError
77+
status::Int64
78+
message::Maybe{String}
79+
80+
function BithumbAPIError(status::Int64, x...)
81+
return new{status}(status, x...)
82+
end
83+
end
84+
85+
function Base.show(io::IO, e::BithumbAPIError)
86+
return print(io, "status = ", "\"", e.status, "\"", ", ", "message = ", "\"", e.message, "\"")
87+
end
88+
89+
CryptoAPIs.error_type(::BithumbClient) = BithumbAPIError
90+
91+
function CryptoAPIs.request_sign!(::BithumbClient, query::Q, ::String)::Q where {Q<:BithumbPublicQuery}
92+
return query
93+
end
94+
95+
function CryptoAPIs.request_sign!(client::BithumbClient, query::Q, endpoint::String)::Q where {Q<:BithumbPrivateQuery}
96+
query.nonce = Dates.now(UTC)
97+
query.endpoint = Serde.SerQuery.escape_query("/" * endpoint)
98+
query.signature = nothing
99+
body = Serde.to_query(query)
100+
salt = string("/", endpoint, Char(0), body, Char(0), round(Int64, 1000 * datetime2unix(query.nonce)))
101+
query.signature = Base64.base64encode(hexdigest("sha512", client.secret_key, salt))
102+
return query
103+
end
104+
105+
function CryptoAPIs.request_sign!(::BithumbClient, query::Q, ::String)::Q where {Q<:BithumbAccessQuery}
106+
return query
107+
end
108+
109+
function CryptoAPIs.request_body(::Q)::String where {Q<:BithumbCommonQuery}
110+
return ""
111+
end
112+
113+
function CryptoAPIs.request_query(query::Q)::String where {Q<:BithumbCommonQuery}
114+
return Serde.to_query(query)
115+
end
116+
117+
function CryptoAPIs.request_headers(client::BithumbClient, ::BithumbPublicQuery)::Vector{Pair{String,String}}
118+
return Pair{String,String}[
119+
"Content-Type" => "application/json"
120+
]
121+
end
122+
123+
function CryptoAPIs.request_headers(client::BithumbClient, query::BithumbPrivateQuery)::Vector{Pair{String,String}}
124+
return Pair{String,String}[
125+
"Api-Key" => client.public_key,
126+
"Api-Sign" => query.signature,
127+
"Api-Nonce" => string(round(Int64, 1000 * datetime2unix(query.nonce))),
128+
]
129+
end
130+
131+
include("Utils.jl")
132+
include("Errors.jl")
133+
134+
include("Spot/Spot.jl")
135+
using .Spot
136+
137+
end

src/Bithumb/Errors.jl

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Bithumb/Errors
2+
# https://apidocs.bithumb.com/docs/api-%EC%A3%BC%EC%9A%94-%EC%97%90%EB%9F%AC-%EC%BD%94%EB%93%9C
3+
4+
import ..CryptoAPIs: APIsResult, APIsUndefError, isretriable, retry_maxcount, retry_timeout
5+
6+
# UNDEF
7+
isretriable(e::APIsResult{BithumbAPIError}) = true
8+
9+
# BAD_REQUEST
10+
isretriable(e::APIsResult{BithumbAPIError{5100}}) = false
11+
12+
# NOT_MEMBER
13+
isretriable(e::APIsResult{BithumbAPIError{5200}}) = false
14+
15+
# INVALID_APIKEY
16+
isretriable(e::APIsResult{BithumbAPIError{5300}}) = false
17+
18+
# METHOD_NOT_ALLOWED
19+
isretriable(e::APIsResult{BithumbAPIError{5302}}) = false
20+
21+
# DATABASE_FAIL
22+
isretriable(e::APIsResult{BithumbAPIError{5400}}) = false
23+
24+
# INVALID_SYMBOL
25+
isretriable(e::APIsResult{BithumbAPIError{5500}}) = false
26+
27+
# TOO_MANY_CONNECTIONS
28+
isretriable(e::APIsResult{BithumbAPIError{5600}}) = true
29+
retry_timeout(e::APIsResult{BithumbAPIError{5600}}) = 2
30+
retry_maxcount(e::APIsResult{BithumbAPIError{5600}}) = 50
31+
32+
# UNKNOWN_ERROR
33+
isretriable(e::APIsResult{BithumbAPIError{5900}}) = true
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
module AssetStatus
2+
3+
export AssetStatusQuery,
4+
AssetStatusData,
5+
asset_status
6+
7+
using Serde
8+
using Dates, NanoDates, TimeZones
9+
10+
using CryptoAPIs.Bithumb
11+
using CryptoAPIs.Bithumb: Data
12+
using CryptoAPIs: Maybe, APIsRequest
13+
14+
Base.@kwdef struct AssetStatusQuery <: BithumbPublicQuery
15+
currency::Maybe{String} = "ALL"
16+
end
17+
18+
Serde.SerQuery.ser_ignore_field(::Type{AssetStatusQuery}, ::Val{:currency}) = true
19+
20+
struct AssetStatusData <: BithumbData
21+
currency::String
22+
net_type::String
23+
deposit_status::Bool
24+
withdrawal_status::Bool
25+
end
26+
27+
"""
28+
asset_status(client::BithumbClient, query::AssetStatusQuery)
29+
asset_status(client::BithumbClient = Bithumb.Spot.public_client; kw...)
30+
31+
Provides information on the deposit/withdrawal status of virtual assets.
32+
33+
[`GET /public/assetsstatus/multichain/{currency}`](https://apidocs.bithumb.com/reference/%EC%9E%85%EC%B6%9C%EA%B8%88-%EC%A7%80%EC%9B%90-%ED%98%84%ED%99%A9)
34+
35+
## Parameters:
36+
37+
| Parameter | Type | Required | Description |
38+
|:----------|:-------------|:---------|:---------------|
39+
| currency | String | false | Default: "ALL" |
40+
41+
## Code samples:
42+
43+
```julia
44+
using Serde
45+
using CryptoAPIs.Bithumb
46+
47+
result = Bithumb.Spot.asset_status(;
48+
currency = "ADA",
49+
)
50+
51+
to_pretty_json(result.result)
52+
```
53+
54+
## Result:
55+
56+
```json
57+
{
58+
"status":"0000",
59+
"date":null,
60+
"data":[
61+
{
62+
"currency":"ADA",
63+
"net_type":"ADA",
64+
"deposit_status":true,
65+
"withdrawal_status":true
66+
}
67+
]
68+
}
69+
```
70+
"""
71+
function asset_status(client::BithumbClient, query::AssetStatusQuery)
72+
return APIsRequest{Data{Vector{AssetStatusData}}}("GET", "public/assetsstatus/multichain/$(query.currency)", query)(client)
73+
end
74+
75+
function asset_status(client::BithumbClient = Bithumb.Spot.public_client; kw...)
76+
return asset_status(client, AssetStatusQuery(; kw...))
77+
end
78+
79+
end

0 commit comments

Comments
 (0)