Skip to content

Commit 496ef01

Browse files
authoredApr 30, 2023
Add unit tests for all endpoints (#14)
1 parent 5309aa1 commit 496ef01

24 files changed

+721
-307
lines changed
 

‎.github/codecov.yml

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
coverage:
2+
## Status checks in PR
3+
##
4+
status:
5+
project:
6+
default:
7+
informational: true
8+
## Target coverage is the last one
9+
##
10+
target: auto
11+
## this allows a 2% drop from the previous base commit coverage
12+
##
13+
threshold: 2%
14+
patch:
15+
default:
16+
informational: true
17+
18+
comment:
19+
layout: "reach, diff, flags, files"
20+
behavior: default
21+
require_changes: true # if false: post the comment even if coverage dont change
22+
require_base: no # [yes :: must have a base report to post]
23+
require_head: yes # [yes :: must have a head report to post]

‎.github/workflows/CI.yml

+13-1
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,19 @@ on:
77
tags: "*"
88
pull_request:
99

10+
concurrency:
11+
group: CI-${{ github.ref }}
12+
cancel-in-progress: true
13+
1014
jobs:
1115
test:
1216
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }}
1317
runs-on: ${{ matrix.os }}
1418
strategy:
19+
max-parallel: 1 # avoid API rate limit issues
1520
matrix:
1621
version: ["1.8"]
17-
os: [ubuntu-latest, macOS-latest, windows-latest]
22+
os: [ubuntu-latest] #, macOS-latest, windows-latest]
1823
arch: [x64]
1924
steps:
2025
- uses: actions/checkout@v1
@@ -23,6 +28,13 @@ jobs:
2328
version: ${{ matrix.version }}
2429
arch: ${{ matrix.arch }}
2530
- uses: julia-actions/julia-runtest@latest
31+
env:
32+
SPOT_API_KEY: ${{ secrets.SPOT_API_KEY }}
33+
SPOT_SECRET_KEY: ${{ secrets.SPOT_SECRET_KEY }}
34+
FUTURES_API_KEY: ${{ secrets.FUTURES_API_KEY }}
35+
FUTURES_SECRET_KEY: ${{ secrets.FUTURES_SECRET_KEY }}
36+
FUTURES_SANDBOX_KEY: ${{ secrets.FUTURES_SANDBOX_KEY }}
37+
FUTURES_SANDBOX_SECRET: ${{ secrets.FUTURES_SANDBOX_SECRET }}
2638
- uses: julia-actions/julia-uploadcodecov@latest
2739
env:
2840
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

‎.github/workflows/CompatHelper.yml

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
name: CompatHelper
2+
23
on:
34
schedule:
45
- cron: 0 0 * * *

‎.github/workflows/Documentation.yml

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ on:
77
tags: "*"
88
pull_request:
99

10+
concurrency:
11+
group: DOC-${{ github.ref }}
12+
cancel-in-progress: true
13+
1014
jobs:
1115
build:
1216
runs-on: ubuntu-latest

‎Makefile

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!make
2+
# -*- coding: utf-8 -*-
3+
# Copyright (C) 2023 Benjamin Thomas Schwertfeger
4+
# Github: https://github.com/btschwertfeger
5+
6+
## help Print this help message
7+
##
8+
help:
9+
@grep "^##" Makefile | sed -e "s/##//"
10+
11+
## tests Run the unit tests
12+
##
13+
tests:
14+
julia -e 'using Pkg; Pkg.activate("."); Pkg.test()'
15+
16+
## doc Build the documentation
17+
##
18+
doc:
19+
julia -e 'using Pkg; Pkg.activate("."); using Documenter; include("docs/make.jl")'
20+
21+
## clean Remove temporary files
22+
##
23+
clean:
24+
rm *.zip
25+
rm -rf docs/build

‎README.md

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
> ⚠️ This is an unofficial collection of REST and websocket clients for Spot and Futures trading on the Kraken cryptocurrency exchange using Julia. Payward Ltd. and Kraken are in no way associated with the authors of this module and documentation.
2424
25+
Documentation: [https://btschwertfeger.github.io/KrakenEx.jl/stable/](https://btschwertfeger.github.io/KrakenEx.jl/stable/)
26+
2527
This project is based on the [python-kraken-sdk](https://github.com/btschwertfeger/python-kraken-sdk).
2628

2729

@@ -46,6 +48,7 @@ General:
4648

4749
- access both public and private endpoints
4850
- responsive error handling and custom exceptions
51+
- tested using unit tests (see `test/*`)
4952
- extensive example scripts (see `/examples`)
5053

5154
---

‎examples/README.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Examples
2+
3+
The examples shown here are not regulary maintained. Please see the `test` directory which contains all unit tests and serves as working examples.
4+
5+
This does not mean, that the examples shown here do not work - but they may not work on future versions.

‎install.jl ‎notes.jl

+5-2
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,18 @@
99
## Build project
1010
## julia> using Pkg; Pkg.build()
1111

12-
## Buikd documentation
12+
## Build documentation
1313
## julia> using Documenter
1414
## julia> ]
1515
## pkg> activate .
1616
## julia> include("docs/make.jl")
1717

18+
## Test package
19+
## julia> ]
20+
## pkg> activate .
21+
## juli> using Pkg; Pkg.test()
1822

1923
# import Pkg
20-
2124
# Pkg.add("HTTP")
2225
# Pkg.add("JSON")
2326
# Pkg.add("PkgTemplates")

‎src/futures/funding.jl

+11-11
Original file line numberDiff line numberDiff line change
@@ -18,31 +18,31 @@ export initiate_withdrawal_to_spot_wallet
1818
1919
Kraken Docs: [https://docs.futures.kraken.com/#http-api-trading-v3-api-historical-funding-rates-historicalfundingrates](https://docs.futures.kraken.com/#http-api-trading-v3-api-historical-funding-rates-historicalfundingrates)
2020
21-
# Examples
21+
# Examples
2222
2323
```julia-repl
2424
julia> client = FuturesBaseRESTAPI(key="api-key", secret="api-secret")
2525
julia> println(get_historical_funding_rates(client, symbol="PI_XBTUSD"))
2626
Dict{String, Any}(
2727
"rates" => Any[
2828
Dict{String, Any}(
29-
"fundingRate" => 1.0327058177e-8,
30-
"timestamp" => "2018-08-31T16:00:00.000Z",
29+
"fundingRate" => 1.0327058177e-8,
30+
"timestamp" => "2018-08-31T16:00:00.000Z",
3131
"relativeFundingRate" => 7.182407e-5
32-
),
32+
),
3333
Dict{String, Any}(
3434
"fundingRate" => -1.2047162502e-8,
3535
"timestamp" => "2018-08-31T20:00:00.000Z",
3636
"relativeFundingRate" => -8.4873103125e-5
37-
),
37+
),
3838
Dict{String, Any}(
39-
"fundingRate" => -9.645113378e-9,
40-
"timestamp" => "2018-09-01T00:00:00.000Z",
39+
"fundingRate" => -9.645113378e-9,
40+
"timestamp" => "2018-09-01T00:00:00.000Z",
4141
"relativeFundingRate" => -6.76651e-5
42-
),
42+
),
4343
Dict{String, Any}(
44-
"fundingRate" => -8.028122964e-9,
45-
"timestamp" => "2018-09-01T04:00:00.000Z",
44+
"fundingRate" => -8.028122964e-9,
45+
"timestamp" => "2018-09-01T04:00:00.000Z",
4646
"relativeFundingRate" => -5.66897875e-5
4747
), ...
4848
]
@@ -131,7 +131,7 @@ function initiate_subccount_transfer(
131131
toUser::String
132132
)
133133
return request(client, "POST", "/derivatives/api/v3/transfer/subaccount", post_params=Dict{String,Any}(
134-
"amount" => amount,
134+
"amount" => string(amount),
135135
"fromAccount" => fromAccount,
136136
"fromUser" => fromUser,
137137
"toAccount" => toAccount,

‎src/futures/market.jl

+185-182
Large diffs are not rendered by default.

‎src/futures/trade.jl

+19-19
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export create_order
1919

2020
#======= F U N C T I O N S ========#
2121
"""
22-
get_fills(client::FuturesBaseRESTAPI; lastFillTime::Union{Int64,String,Nothing}=nothing)
22+
get_fills(client::FuturesBaseRESTAPI; lastFillTime::Union{String,Nothing}=nothing)
2323
2424
Kraken Docs: [https://docs.futures.kraken.com/#http-api-trading-v3-api-historical-data-get-your-fills](https://docs.futures.kraken.com/#http-api-trading-v3-api-historical-data-get-your-fills)
2525
@@ -48,7 +48,7 @@ Dict{String,Any}(
4848
)
4949
```
5050
"""
51-
function get_fills(client::FuturesBaseRESTAPI; lastFillTime::Union{Int64,String,Nothing}=nothing)
51+
function get_fills(client::FuturesBaseRESTAPI; lastFillTime::Union{String,Nothing}=nothing)
5252
params::Dict{String,Any} = Dict{String,Any}()
5353
isnothing(lastFillTime) ? nothing : params["lastFillTime"] = lastFillTime
5454
return request(client, "GET", "/derivatives/api/v3/fills", query_params=params, auth=true)
@@ -67,7 +67,7 @@ Authenticated `client` required
6767
```julia-repl
6868
julia> client = FuturesBaseRESTAPI(key="api-key", secret="secret-key")
6969
julia> println(create_batch_order(
70-
... client,
70+
... client,
7171
... batchorder_list=[
7272
... Dict{String,Any}(
7373
... "order" => "send",
@@ -108,7 +108,7 @@ julia> println(create_batch_order(
108108
... "cliOrdId" => "my_client_id1234"
109109
... )
110110
... ]))
111-
...
111+
...
112112
julia> # please see the linked Kraken Docs for response examples
113113
```
114114
"""
@@ -125,7 +125,7 @@ end
125125
126126
Kraken Docs: [https://docs.futures.kraken.com/#http-api-trading-v3-api-order-management-cancel-all-orders](https://docs.futures.kraken.com/#http-api-trading-v3-api-order-management-cancel-all-orders)
127127
128-
Cancels all active orders of a user.
128+
Cancels all active orders of a user.
129129
130130
Authenticated `client` required
131131
@@ -277,9 +277,9 @@ end
277277
edit_order(client::FuturesBaseRESTAPI;
278278
orderId::Union{String,Nothing}=nothing,
279279
cliOrdId::Union{String,Nothing}=nothing,
280-
limitPrice::Union{String,Float64,Int64,Nothing}=nothing,
281-
size::Union{String,Float64,Int64,Nothing}=nothing,
282-
stopPrice::Union{String,Float64,Int64,Nothing}=nothing
280+
limitPrice::Union{String,Float64,Int,Nothing}=nothing,
281+
size::Union{String,Float64,Int,Nothing}=nothing,
282+
stopPrice::Union{String,Float64,Int,Nothing}=nothing
283283
)
284284
285285
Kraken Docs: [https://docs.futures.kraken.com/#http-api-trading-v3-api-order-management-edit-order](https://docs.futures.kraken.com/#http-api-trading-v3-api-order-management-edit-order)
@@ -343,9 +343,9 @@ Dict{String,Any}(
343343
function edit_order(client::FuturesBaseRESTAPI;
344344
orderId::Union{String,Nothing}=nothing,
345345
cliOrdId::Union{String,Nothing}=nothing,
346-
limitPrice::Union{String,Float64,Int64,Nothing}=nothing,
347-
size::Union{String,Float64,Int64,Nothing}=nothing,
348-
stopPrice::Union{String,Float64,Int64,Nothing}=nothing
346+
limitPrice::Union{String,Float64,Int,Nothing}=nothing,
347+
size::Union{String,Float64,Int,Nothing}=nothing,
348+
stopPrice::Union{String,Float64,Int,Nothing}=nothing
349349
)
350350
params::Dict{String,Any} = Dict{String,Any}()
351351
if !isnothing(orderId)
@@ -369,7 +369,7 @@ end
369369
370370
Kraken Docs: [https://docs.futures.kraken.com/#http-api-trading-v3-api-order-management-get-the-current-status-for-specific-orders](https://docs.futures.kraken.com/#http-api-trading-v3-api-order-management-get-the-current-status-for-specific-orders)
371371
372-
Get information about (a) specific order(s) using `orderIds` or `cliOrdIds`.
372+
Get information about (a) specific order(s) using `orderIds` or `cliOrdIds`.
373373
374374
Authenticated `client` required
375375
@@ -427,18 +427,18 @@ end
427427
create_order(client::FuturesBaseRESTAPI;
428428
orderType::String,
429429
side::String,
430-
size::Union{Float64,Int64,String},
430+
size::Union{Float64,Int,String},
431431
symbol::String,
432432
cliOrdId::Union{String,Nothing}=nothing,
433-
limitPrice::Union{String,Float64,Int64,Nothing}=nothing,
434-
stopPrice::Union{String,Float64,Int64,Nothing}=nothing,
433+
limitPrice::Union{String,Float64,Int,Nothing}=nothing,
434+
stopPrice::Union{String,Float64,Int,Nothing}=nothing,
435435
reduceOnly::Union{Bool,Nothing}=nothing,
436436
triggerSignal::Union{String,Nothing}=nothing
437437
)
438438
439439
Kraken Docs: [https://docs.futures.kraken.com/#http-api-trading-v3-api-order-management-send-order](https://docs.futures.kraken.com/#http-api-trading-v3-api-order-management-send-order)
440440
441-
Creates/places an order.
441+
Creates/places an order.
442442
443443
Authenticated `client` required
444444
@@ -488,11 +488,11 @@ Dict{String,Any}(
488488
function create_order(client::FuturesBaseRESTAPI;
489489
orderType::String,
490490
side::String,
491-
size::Union{Float64,Int64,String},
491+
size::Union{Float64,Int,String},
492492
symbol::String,
493493
cliOrdId::Union{String,Nothing}=nothing,
494-
limitPrice::Union{String,Float64,Int64,Nothing}=nothing,
495-
stopPrice::Union{String,Float64,Int64,Nothing}=nothing,
494+
limitPrice::Union{String,Float64,Int,Nothing}=nothing,
495+
stopPrice::Union{String,Float64,Int,Nothing}=nothing,
496496
reduceOnly::Union{Bool,Nothing}=nothing,
497497
triggerSignal::Union{String,Nothing}=nothing
498498
)

‎src/spot/funding.jl

+1
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ Initiates a withdraw and returns the `refid` to track the status.
137137
138138
Authenticated `client` required
139139
140+
Note: The `key` must be the name of the withdraw wallet as defined in the Web UI of the Kraken exchange.
140141
# Examples
141142
142143
```julia-repl

‎src/spot/market.jl

+13-13
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ function get_ticker(client::SpotBaseRESTAPI; pair::Union{Vector{String},String,N
192192
end
193193

194194
"""
195-
get_ohlc(client::SpotBaseRESTAPI; pair::String, interval::Union{String,Nothing}=nothing, since::Union{Int64,Nothing}=nothing)
195+
get_ohlc(client::SpotBaseRESTAPI; pair::String, interval::Union{String,Int,Nothing}=nothing, since::Union{Int,String,Nothing}=nothing)
196196
197197
Kraken Docs: [https://docs.kraken.com/rest/#operation/getOHLCData](https://docs.kraken.com/rest/#operation/getOHLCData)
198198
@@ -217,15 +217,15 @@ Dict{String, Any}(
217217
)
218218
```
219219
"""
220-
function get_ohlc(client::SpotBaseRESTAPI; pair::String, interval::Union{String,Nothing}=nothing, since::Union{Int64,Nothing}=nothing)
220+
function get_ohlc(client::SpotBaseRESTAPI; pair::String, interval::Union{String,Int,Nothing}=nothing, since::Union{Int,String,Nothing}=nothing)
221221
params = Dict{String,String}("pair" => pair)
222-
!isnothing(interval) ? params["interval"] = interval : nothing
223-
!isnothing(since) ? params["since"] = since : nothing
222+
!isnothing(interval) ? params["interval"] = string(interval) : nothing
223+
!isnothing(since) ? params["since"] = string(since) : nothing
224224
return request(client, "GET", "/public/OHLC"; data=params, auth=false)
225225
end
226226

227227
"""
228-
get_order_book(client::SpotBaseRESTAPI; pair::String, count::Union{Int64,Nothing}=nothing)
228+
get_order_book(client::SpotBaseRESTAPI; pair::String, count::Union{Int,Nothing}=nothing)
229229
230230
Kraken Docs: [https://docs.kraken.com/rest/#operation/getOrderBook](https://docs.kraken.com/rest/#operation/getOrderBook)
231231
@@ -259,14 +259,14 @@ Dict{String, Any}(
259259
)
260260
```
261261
"""
262-
function get_order_book(client::SpotBaseRESTAPI; pair::String, count::Union{Int64,Nothing}=nothing)
262+
function get_order_book(client::SpotBaseRESTAPI; pair::String, count::Union{Int,String,Nothing}=nothing)
263263
params = Dict{String,String}("pair" => pair)
264-
!isnothing(count) ? params["count"] = count : nothing
264+
!isnothing(count) ? params["count"] = string(count) : nothing
265265
return request(client, "GET", "/public/Depth"; data=params, auth=false)
266266
end
267267

268268
"""
269-
get_recent_trades(client::SpotBaseRESTAPI; pair::String, since::Union{Int64,Nothing}=nothing)
269+
get_recent_trades(client::SpotBaseRESTAPI; pair::String, since::Union{Int,String,Nothing}=nothing)
270270
271271
Kraken Docs: [https://docs.kraken.com/rest/#operation/getRecentTrades](https://docs.kraken.com/rest/#operation/getRecentTrades)
272272
@@ -296,14 +296,14 @@ Dict{String, Any}(
296296
)
297297
```
298298
"""
299-
function get_recent_trades(client::SpotBaseRESTAPI; pair::String, since::Union{Int64,Nothing}=nothing)
299+
function get_recent_trades(client::SpotBaseRESTAPI; pair::String, since::Union{Int,String,Nothing}=nothing)
300300
params = Dict{String,String}("pair" => pair)
301-
!isnothing(since) ? params["since"] = since : nothing
301+
!isnothing(since) ? params["since"] = string(since) : nothing
302302
return request(client, "GET", "/public/Trades"; data=params, auth=false)
303303
end
304304

305305
"""
306-
get_recent_spreads(client::SpotBaseRESTAPI; pair::String, since::Union{Int64,Nothing}=nothing)
306+
get_recent_spreads(client::SpotBaseRESTAPI; pair::String, since::Union{Int,String,Nothing}=nothing)
307307
308308
Kraken Docs: [https://docs.kraken.com/rest/#operation/getRecentSpreads](https://docs.kraken.com/rest/#operation/getRecentSpreads)
309309
@@ -328,9 +328,9 @@ Dict{String, Any}(
328328
"last" => 1673363958)
329329
```
330330
"""
331-
function get_recent_spreads(client::SpotBaseRESTAPI; pair::String, since::Union{Int64,Nothing}=nothing)
331+
function get_recent_spreads(client::SpotBaseRESTAPI; pair::String, since::Union{Int,String,Nothing}=nothing)
332332
params = Dict{String,String}("pair" => pair)
333-
!isnothing(since) ? params["since"] = since : nothing
333+
!isnothing(since) ? params["since"] = string(since) : nothing
334334
return request(client, "GET", "/public/Spread"; data=params, auth=false)
335335
end
336336

‎src/spot/trade.jl

+17-17
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ export cancel_order_batch
2323
ordertype::String,
2424
side::String,
2525
pair::String,
26-
volume::Union{Float64,Int64,String},
27-
price::Union{Float64,Int64,String,Nothing}=nothing,
28-
price2::Union{Float64,Int64,String,Nothing}=nothing,
26+
volume::Union{Float64,Int,String},
27+
price::Union{Float64,Int,String,Nothing}=nothing,
28+
price2::Union{Float64,Int,String,Nothing}=nothing,
2929
trigger::Union{String,Nothing}=nothing,
30-
leverage::Union{Float64,Int64,String,Nothing}=nothing,
30+
leverage::Union{Float64,Int,String,Nothing}=nothing,
3131
stp_type::String="cancel-newest",
3232
oflags::Union{String,Vector{String},Nothing}=nothing,
3333
timeinforce::Union{String,Nothing}=nothing,
@@ -39,7 +39,7 @@ export cancel_order_batch
3939
deadline::Union{String,Nothing}=nothing,
4040
validate::Bool=false,
4141
reduce_only::Bool=false,
42-
displayvol::Union{Float64,Int64,String,Nothing}=nothing,
42+
displayvol::Union{Float64,Int,String,Nothing}=nothing,
4343
userref::Union{Int32,Nothing}=nothing
4444
)
4545
@@ -98,11 +98,11 @@ function create_order(client::SpotBaseRESTAPI;
9898
ordertype::String,
9999
side::String,
100100
pair::String,
101-
volume::Union{Float64,Int64,String},
102-
price::Union{Float64,Int64,String,Nothing}=nothing,
103-
price2::Union{Float64,Int64,String,Nothing}=nothing,
101+
volume::Union{Float64,Int,String},
102+
price::Union{Float64,Int,String,Nothing}=nothing,
103+
price2::Union{Float64,Int,String,Nothing}=nothing,
104104
trigger::Union{String,Nothing}=nothing,
105-
leverage::Union{Float64,Int64,String,Nothing}=nothing,
105+
leverage::Union{Float64,Int,String,Nothing}=nothing,
106106
stp_type::String="cancel-newest",
107107
oflags::Union{String,Vector{String},Nothing}=nothing,
108108
timeinforce::Union{String,Nothing}=nothing,
@@ -114,8 +114,8 @@ function create_order(client::SpotBaseRESTAPI;
114114
deadline::Union{String,Nothing}=nothing,
115115
validate::Bool=false,
116116
reduce_only::Bool=false,
117-
displayvol::Union{Float64,Int64,String,Nothing}=nothing,
118-
userref::Union{Int32,Nothing}=nothing
117+
displayvol::Union{Float64,Int,String,Nothing}=nothing,
118+
userref::Union{Int,Nothing}=nothing
119119
)
120120
params = Dict{String,Any}(
121121
"ordertype" => ordertype,
@@ -259,9 +259,9 @@ end
259259
edit_order(client::SpotBaseRESTAPI;
260260
txid::String,
261261
pair::String,
262-
volume::Union{String,Int64,Float64,Nothing}=nothing,
263-
price::Union{String,Int64,Float64,Nothing}=nothing,
264-
price2::Union{String,Int64,Float64,Nothing}=nothing,
262+
volume::Union{String,Int,Float64,Nothing}=nothing,
263+
price::Union{String,Int,Float64,Nothing}=nothing,
264+
price2::Union{String,Int,Float64,Nothing}=nothing,
265265
oflags::Union{String,Vector{String},Nothing}=nothing,
266266
deadline::Union{String,Nothing}=nothing,
267267
cancel_response::Bool=false,
@@ -303,9 +303,9 @@ Dict{String, Any}(
303303
function edit_order(client::SpotBaseRESTAPI;
304304
txid::String,
305305
pair::String,
306-
volume::Union{String,Int64,Float64,Nothing}=nothing,
307-
price::Union{String,Int64,Float64,Nothing}=nothing,
308-
price2::Union{String,Int64,Float64,Nothing}=nothing,
306+
volume::Union{String,Int,Float64,Nothing}=nothing,
307+
price::Union{String,Int,Float64,Nothing}=nothing,
308+
price2::Union{String,Int,Float64,Nothing}=nothing,
309309
oflags::Union{String,Vector{String},Nothing}=nothing,
310310
deadline::Union{String,Nothing}=nothing,
311311
cancel_response::Bool=false,

‎test/futures/funding.jl

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using KrakenEx: FuturesBaseRESTAPI
2+
import KrakenEx.FuturesFundingModule as FuturesFunding
3+
import KrakenEx.ExceptionsModule as exc
4+
using HTTP
5+
using Test
6+
7+
8+
client = FuturesBaseRESTAPI(key=ENV["FUTURES_SANDBOX_KEY"], secret=ENV["FUTURES_SANDBOX_SECRET"], DEMO=true)
9+
10+
@testset verbose = true "Transfers" begin
11+
@test_throws exc.KrakenInvalidAccountError FuturesFunding.initiate_wallet_transfer(client, fromAccount="Multi-Collateral", toAccount="Single-Collateral", amount=2, unit="PI_XBTUSD")
12+
@test_throws exc.KrakenInvalidArgumentsError FuturesFunding.initiate_subccount_transfer(client, fromAccount="Multi-Collateral", toAccount="Single-Collateral", amount=2, fromUser="Dummy1", toUser="Dummy2", unit="PI_XBTUSD") # broken?
13+
@test_throws HTTP.Exceptions.StatusError FuturesFunding.initiate_withdrawal_to_spot_wallet(client, amount=5, currency="USD", sourceWallet="Single-Collateral") # CASH_ACCOUNT_TYPE_NOT_FOUND
14+
end
15+
16+
@testset verbose = true "Misc" begin
17+
@test typeof(FuturesFunding.get_historical_funding_rates(client, symbol="PI_XBTUSD")) == Dict{String,Any}
18+
end

‎test/futures/market.jl

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using KrakenEx: FuturesBaseRESTAPI
2+
import KrakenEx.FuturesMarketModule as FuturesMarket
3+
using Test
4+
5+
6+
client = FuturesBaseRESTAPI()
7+
8+
@testset verbose = true "Market data" begin
9+
@test typeof(FuturesMarket.get_ohlc(client,
10+
tick_type="trade",
11+
symbol="PI_XBTUSD",
12+
resolution="1m",
13+
from=1668989233,
14+
to=1668999233
15+
)) == Dict{String,Any}
16+
@test typeof(FuturesMarket.get_trade_history(client, symbol="PI_XBTUSD", lastTime="2020-08-27T17:03:33.196Z")) == Dict{String,Any}
17+
@test typeof(FuturesMarket.get_public_execution_events(client, tradeable="PI_XBTUSD", before=1675176107, since=1675066107, sort="asc")) == Dict{String,Any}
18+
@test typeof(FuturesMarket.get_public_order_events(client, tradeable="PI_XBTUSD", before=1675176107, since=1675066107, sort="desc")) == Dict{String,Any}
19+
@test typeof(FuturesMarket.get_public_mark_price_events(client, tradeable="PI_XBTUSD", before=1675176107, since=1675066107, sort="desc")) == Dict{String,Any}
20+
@test typeof(FuturesMarket.get_orderbook(client, symbol="PI_XBTUSD")) == Dict{String,Any}
21+
end
22+
sleep(5)
23+
24+
@testset verbose = true "Parameters" begin
25+
@test typeof(FuturesMarket.get_tick_types(client)) == Vector{Any}
26+
@test typeof(FuturesMarket.get_tradeable_products(
27+
client,
28+
tick_type="mark"
29+
)) == Vector{Any}
30+
@test typeof(FuturesMarket.get_resolutions(
31+
client,
32+
tradeable="PI_XBTUSD",
33+
tick_type="spot"
34+
)) == Vector{Any}
35+
end
36+
37+
@testset verbose = true "Instruments" begin
38+
@test typeof(FuturesMarket.get_tickers(client)) == Dict{String,Any}
39+
@test typeof(FuturesMarket.get_instruments(client)) == Dict{String,Any}
40+
@test typeof(FuturesMarket.get_instruments_status(client)) == Dict{String,Any}
41+
end
42+
43+
@testset verbose = true "Misc" begin
44+
@test typeof(FuturesMarket.get_fee_schedules(client)) == Dict{String,Any}
45+
end
46+
sleep(2
47+
)

‎test/futures/trade.jl

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
using KrakenEx: FuturesBaseRESTAPI
2+
import KrakenEx.FuturesTradeModule as FuturesTrade
3+
using Test
4+
5+
6+
client = FuturesBaseRESTAPI(key=ENV["FUTURES_SANDBOX_KEY"], secret=ENV["FUTURES_SANDBOX_SECRET"], DEMO=true)
7+
8+
@testset verbose = true "Retrieve information" begin
9+
@test typeof(FuturesTrade.get_fills(client)) == Dict{String,Any}
10+
# todo: fix authenticationerror when some strange character in string
11+
# @test typeof(FuturesTrade.get_fills(client, lastFillTime="2020-07-22T13:44:24.311Z"))==Dict{String,Any}
12+
@test typeof(FuturesTrade.get_orders_status(client, orderIds=["O2JLFP-VYFIW-35ZAAE", "O523KJ-DO4M2-KAT243"])) == Dict{String,Any}
13+
end
14+
15+
@testset verbose = true "Create and modify orders" begin
16+
@test_throws exc.KrakenNotFoundError FuturesTrade.create_batch_order(client,
17+
batchorder_list=[
18+
Dict{String,Any}(
19+
"order" => "send",
20+
"order_tag" => "1",
21+
"orderType" => "lmt",
22+
"symbol" => "PI_XBTUSD",
23+
"side" => "buy",
24+
"size" => 0.00001,
25+
"limitPrice" => 1200.0,
26+
"cliOrdId" => "my-another-client-id",
27+
"validate" => string(true)
28+
),
29+
Dict{String,Any}(
30+
"order" => "send",
31+
"order_tag" => "2",
32+
"orderType" => "stp",
33+
"symbol" => "PI_XBTUSD",
34+
"side" => "buy",
35+
"size" => 0.00001,
36+
"limitPrice" => 1100.0,
37+
"stopPrice" => 1090.0,
38+
"validate" => string(true)
39+
),
40+
Dict{String,Any}(
41+
"order" => "send",
42+
"order_tag" => "3",
43+
"orderType" => "stp",
44+
"symbol" => "PI_XBTUSD",
45+
"side" => "buy",
46+
"size" => 0.0003,
47+
"limitPrice" => 1100.0,
48+
"stopPrice" => 1900.0,
49+
"validate" => string(true)
50+
),
51+
Dict{String,Any}(
52+
"order" => "cancel",
53+
"order_id" => "f35a61dd-8a30-4d5f-a574-b5593ef0c050",
54+
),
55+
Dict{String,Any}(
56+
"order" => "cancel",
57+
"cliOrdId" => "my_client_id1234"
58+
)
59+
])
60+
@test typeof(FuturesTrade.edit_order(client, orderId="O523KJ-DO4M2-KAT243", size=2, limitPrice=10)) == Dict{String,Any}
61+
@test typeof(FuturesTrade.create_order(client, orderType="lmt",
62+
side="buy",
63+
size=0.0001,
64+
limitPrice=100.0,
65+
symbol="PI_XBTUSD",
66+
)) == Dict{String,Any}
67+
end
68+
sleep(5)
69+
70+
@testset verbose = true "Cancel orders" begin
71+
@test typeof(FuturesTrade.cancel_all_orders(client, symbol="PI_XBTUSD")) == Dict{String,Any}
72+
@test typeof(FuturesTrade.dead_mans_switch(client, timeout=0)) == Dict{String,Any}
73+
@test typeof(FuturesTrade.cancel_order(client, order_id="O523KJ-DO4M2-KAT243")) == Dict{String,Any}
74+
end

‎test/futures/user.jl

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using KrakenEx: FuturesBaseRESTAPI
2+
import KrakenEx.FuturesUserModule as FuturesUser
3+
using Test
4+
5+
6+
client = FuturesBaseRESTAPI(key=ENV["FUTURES_SANDBOX_KEY"], secret=ENV["FUTURES_SANDBOX_SECRET"], DEMO=true)
7+
8+
@testset verbose = true "Wallets and accounts" begin
9+
@test typeof(FuturesUser.get_wallets(client)) == Dict{String,Any}
10+
@test typeof(FuturesUser.get_subaccounts(client)) == Dict{String,Any}
11+
@test typeof(FuturesUser.get_account_log(client, info="all", sort="desc", since="1673066107", before="1675066107", count=100)) == Dict{String,Any}
12+
@test typeof(FuturesUser.get_account_log_csv(client)) == Vector{UInt8}
13+
end
14+
15+
@testset verbose = true "Orders and positions" begin
16+
@test typeof(FuturesUser.get_open_orders(client)) == Dict{String,Any}
17+
@test typeof(FuturesUser.get_open_positions(client)) == Dict{String,Any}
18+
19+
end
20+
@testset verbose = true "Misc" begin
21+
@test typeof(FuturesUser.get_unwindqueue(client)) == Dict{String,Any}
22+
@test typeof(FuturesUser.get_notificatios(client)) == Dict{String,Any}
23+
end

‎test/runtests.jl

+29-62
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,40 @@
1-
using KrakenEx: SpotBaseRESTAPI, FuturesBaseRESTAPI
2-
import KrakenEx.SpotMarketModule as SpotMarket
3-
import KrakenEx.FuturesMarketModule as FuturesMarket
4-
using Test
5-
6-
#=
7-
Tests can only be performed on public endpoints, because
8-
valid API keys are requred for private requests.
9-
=#
10-
11-
@testset "KrakenEx Spot REST Market Endpoints" begin
12-
13-
client = SpotBaseRESTAPI()
14-
15-
@test typeof(SpotMarket.get_server_time(client)) == Int64
16-
17-
@test typeof(SpotMarket.get_assets(client)) == Dict{String,Any}
18-
19-
@test typeof(SpotMarket.get_tradable_asset_pair(client, pair=["XBTUSD"])) == Dict{String,Any}
201

21-
@test typeof(SpotMarket.get_ticker(client, pair="XBTUSD")) == Dict{String,Any}
22-
23-
@test typeof(SpotMarket.get_ohlc(client, pair="XBTUSD")) == Dict{String,Any}
24-
25-
@test typeof(SpotMarket.get_order_book(client, pair="XBTUSD")) == Dict{String,Any}
26-
27-
@test typeof(SpotMarket.get_recent_spreads(client, pair="XBTUSD")) == Dict{String,Any}
28-
29-
@test typeof(SpotMarket.get_system_status(client)) == Dict{String,Any}
2+
using Test
303

31-
# ...
4+
#==== S P O T ====#
5+
@testset verbose = true "KrakenEx Spot REST User Endpoints" begin
6+
include(joinpath(@__DIR__, "spot", "user.jl"))
327
end
338

34-
@testset "KrakenEx Futures REST Market Endpoints" begin
35-
36-
client = FuturesBaseRESTAPI()
37-
38-
@test typeof(FuturesMarket.get_ohlc(client,
39-
tick_type="trade",
40-
symbol="PI_XBTUSD",
41-
resolution="1m",
42-
from=1668989233,
43-
to=1668999233
44-
)) == Dict{String,Any}
45-
46-
@test typeof(FuturesMarket.get_tick_types(client)) == Vector{Any}
47-
48-
@test typeof(FuturesMarket.get_tradeable_products(
49-
client,
50-
tick_type="mark"
51-
)) == Vector{Any}
52-
53-
@test typeof(FuturesMarket.get_resolutions(
54-
client,
55-
tradeable="PI_XBTUSD",
56-
tick_type="spot"
57-
)) == Vector{Any}
9+
@testset verbose = true "KrakenEx Spot REST Market Endpoints" begin
10+
include(joinpath(@__DIR__, "spot", "market.jl"))
11+
end
5812

59-
@test typeof(FuturesMarket.get_fee_schedules(client)) == Dict{String,Any}
13+
@testset verbose = true "KrakenEx Spot REST Trade Endpoints" begin
14+
include(joinpath(@__DIR__, "spot", "trade.jl"))
15+
end
6016

61-
@test typeof(FuturesMarket.get_orderbook(client, symbol="PI_XBTUSD")) == Dict{String,Any}
17+
@testset verbose = true "KrakenEx Spot REST Funding Endpoints" begin
18+
include(joinpath(@__DIR__, "spot", "funding.jl"))
19+
end
6220

63-
@test typeof(FuturesMarket.get_tickers(client)) == Dict{String,Any}
21+
@testset verbose = true "KrakenEx Spot REST Staking Endpoints" begin
22+
include(joinpath(@__DIR__, "spot", "staking.jl"))
23+
end
6424

65-
@test typeof(FuturesMarket.get_instruments(client)) == Dict{String,Any}
25+
#==== F U T U R E S ====#
26+
@testset verbose = true "KrakenEx Futures REST User Endpoints" begin
27+
include(joinpath(@__DIR__, "futures", "user.jl"))
28+
end
6629

67-
@test typeof(FuturesMarket.get_instruments_status(client)) == Dict{String,Any}
30+
@testset verbose = true "KrakenEx Futures REST Market Endpoints" begin
31+
include(joinpath(@__DIR__, "futures", "market.jl"))
32+
end
6833

69-
@test typeof(FuturesMarket.get_trade_history(client, symbol="PI_XBTUSD")) == Dict{String,Any}
34+
@testset verbose = true "KrakenEx Futures REST Trade Endpoints" begin
35+
include(joinpath(@__DIR__, "futures", "trade.jl"))
36+
end
7037

71-
@test typeof(FuturesMarket.get_public_execution_events(client, tradeable="PI_XBTUSD")) == Dict{String,Any}
72-
# ...
73-
end
38+
@testset verbose = true "KrakenEx Futures REST Funding Endpoints" begin
39+
include(joinpath(@__DIR__, "futures", "funding.jl"))
40+
end

‎test/spot/funding.jl

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using KrakenEx: SpotBaseRESTAPI
2+
import KrakenEx.SpotFundingModule as SpotFunding
3+
import KrakenEx.ExceptionsModule as exc
4+
using Test
5+
6+
7+
client = SpotBaseRESTAPI(key=ENV["SPOT_API_KEY"], secret=ENV["SPOT_SECRET_KEY"])
8+
9+
10+
@testset verbose = true "Deposit methods" begin
11+
@test typeof(SpotFunding.get_deposit_methods(client, asset="DOT")) == Vector{Any}
12+
@test typeof(SpotFunding.get_deposit_address(client, asset="DOT", method="Polkadot")) == Vector{Any}
13+
@test typeof(SpotFunding.get_recent_deposits_status(client, asset="DOT", method="Polkadot")) == Vector{Any}
14+
end
15+
16+
@testset verbose = true "Withdraw methods" begin
17+
@test_throws exc.KrakenPermissionDeniedError SpotFunding.withdraw_funds(client, asset="DOT", amount="10", key="myPolkadotWallet")
18+
@test_throws exc.KrakenPermissionDeniedError SpotFunding.get_withdrawal_info(client, asset="DOT", amount="10", key="myPolkadotWallet")
19+
@test typeof(SpotFunding.get_recent_withdraw_status(client, asset="DOT", method="Polkadot")) == Vector{Any}
20+
@test_throws exc.KrakenPermissionDeniedError SpotFunding.cancel_withdraw(client, asset="DOT", refid="123456789")
21+
@test_throws exc.KrakenPermissionDeniedError SpotFunding.wallet_transfer(client, asset="DOT", from="Spot Wallet", to="Futures Wallet", amount=200)
22+
end
23+
24+
sleep(5)

‎test/spot/market.jl

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using KrakenEx: SpotBaseRESTAPI
2+
import KrakenEx.SpotMarketModule as SpotMarket
3+
using Test
4+
5+
6+
7+
client = SpotBaseRESTAPI()
8+
9+
@testset verbose = true "Asset information" begin
10+
@test typeof(SpotMarket.get_assets(client, assets="BTC", aclass="currency")) == Dict{String,Any}
11+
@test typeof(SpotMarket.get_assets(client, assets=["BTC", "DOT"], aclass="currency")) == Dict{String,Any}
12+
@test typeof(SpotMarket.get_tradable_asset_pair(client, pair=["XBTUSD"])) == Dict{String,Any}
13+
end
14+
sleep(1)
15+
16+
@testset verbose = true "Market data" begin
17+
@test typeof(SpotMarket.get_ticker(client, pair="XBTUSD")) == Dict{String,Any}
18+
@test typeof(SpotMarket.get_ohlc(client, pair="XBTUSD")) == Dict{String,Any}
19+
@test typeof(SpotMarket.get_ohlc(client, pair="XBTUSD", interval=60, since=1675066107)) == Dict{String,Any}
20+
end
21+
sleep(1)
22+
23+
@testset verbose = true "Public orderbook, trades and spreads" begin
24+
@test typeof(SpotMarket.get_order_book(client, pair="XBTUSD", count=4)) == Dict{String,Any}
25+
@test typeof(SpotMarket.get_recent_trades(client, pair="XBTUSD", since=1675066107)) == Dict{String,Any}
26+
@test typeof(SpotMarket.get_recent_spreads(client, pair="XBTUSD", since=1675066107)) == Dict{String,Any}
27+
end
28+
sleep(1)
29+
30+
@testset verbose = true "System status" begin
31+
@test typeof(SpotMarket.get_system_status(client)) == Dict{String,Any}
32+
@test typeof(SpotMarket.get_server_time(client)) == Int64
33+
end

‎test/spot/staking.jl

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using KrakenEx: SpotBaseRESTAPI
2+
import KrakenEx.SpotStakingModule as SpotStaking
3+
import KrakenEx.ExceptionsModule as exc
4+
using Test
5+
6+
7+
client = SpotBaseRESTAPI(key=ENV["SPOT_API_KEY"], secret=ENV["SPOT_SECRET_KEY"])
8+
9+
@testset verbose = true "Stake" begin
10+
@test_throws exc.KrakenPermissionDeniedError SpotStaking.stake_asset(client, asset="DOT", method="polkadot-staked", amount=200)
11+
end
12+
sleep(2)
13+
14+
@testset verbose = true "Unstake" begin
15+
@test_throws exc.KrakenPermissionDeniedError SpotStaking.unstake_asset(client, asset="DOT", amount=200)
16+
end
17+
sleep(2)
18+
19+
@testset verbose = true "Misc" begin
20+
@test_throws exc.KrakenPermissionDeniedError SpotStaking.list_stakeable_assets(client)
21+
@test typeof(SpotStaking.get_pending_staking_transactions(client)) == Vector{Any}
22+
@test typeof(SpotStaking.list_staking_transactions(client)) == Vector{Any}
23+
end
24+
sleep(2)

‎test/spot/trade.jl

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
using KrakenEx: SpotBaseRESTAPI
2+
import KrakenEx.SpotTradeModule as SpotTrade
3+
import KrakenEx.ExceptionsModule as exc
4+
using Test
5+
6+
7+
client = SpotBaseRESTAPI(key=ENV["SPOT_API_KEY"], secret=ENV["SPOT_SECRET_KEY"])
8+
9+
@testset verbose = true "Create orders" begin
10+
@test_throws exc.KrakenPermissionDeniedError SpotTrade.create_order(
11+
client,
12+
ordertype="limit",
13+
price=12000,
14+
side="buy",
15+
volume=0.001,
16+
pair="XBTUSD",
17+
validate=true,
18+
userref=123456,
19+
oflags="fcib",
20+
timeinforce="GTC",
21+
displayvol=0.0001
22+
)
23+
@test_throws exc.KrakenPermissionDeniedError SpotTrade.create_order_batch(client,
24+
orders=[
25+
Dict{String,Any}(
26+
"close" => Dict{String,Any}(
27+
"ordertype" => "stop-loss-limit",
28+
"price" => 1000,
29+
"price2" => 900
30+
),
31+
"ordertype" => "limit",
32+
"price" => 40000,
33+
"timeinforce" => "GTC",
34+
"type" => "buy",
35+
"userref" => Int32(123),
36+
"volume" => 2
37+
),
38+
Dict{String,Any}(
39+
"ordertype" => "limit",
40+
"price" => 42000,
41+
"starttm" => "1668455555",
42+
"timeinforce" => "GTC",
43+
"type" => "sell",
44+
"userref" => Int32(999),
45+
"volume" => 5
46+
),
47+
Dict{String,Any}(
48+
"ordertype" => "market",
49+
"volume" => 2,
50+
"type" => "buy"
51+
),
52+
Dict{String,Any}(
53+
"ordertype" => "limit",
54+
"price" => 43000,
55+
"starttm" => "1668455555",
56+
"timeinforce" => "GTC",
57+
"type" => "sell",
58+
"userref" => Int32(999),
59+
"volume" => 5
60+
)
61+
],
62+
pair="XBTUSD",
63+
validate=true
64+
)
65+
end
66+
sleep(2)
67+
@testset verbose = true "Modify orders" begin
68+
@test_throws exc.KrakenPermissionDeniedError SpotTrade.edit_order(client,
69+
txid="O2JLFP-VYFIW-35ZAAE",
70+
pair="XBTUSD",
71+
volume=4.2,
72+
price=17000
73+
)
74+
end
75+
sleep(2)
76+
@testset verbose = true "Cancel orders" begin
77+
@test_throws exc.KrakenPermissionDeniedError SpotTrade.cancel_order(client, txid="O2JLFP-VYFIW-35ZAAE")
78+
@test_throws exc.KrakenPermissionDeniedError SpotTrade.cancel_all_orders(client)
79+
@test_throws exc.KrakenPermissionDeniedError SpotTrade.cancel_all_orders_after_x(client, timeout=60)
80+
@test_throws exc.KrakenPermissionDeniedError SpotTrade.cancel_order_batch(client, orders=["O2JLFP-VYFIW-35ZAAE", "O523KJ-DO4M2-KAT243"])
81+
end
82+
sleep(2)

‎test/spot/user.jl

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using KrakenEx: SpotBaseRESTAPI
2+
import KrakenEx.SpotUserModule as SpotUser
3+
using Test
4+
5+
6+
client = SpotBaseRESTAPI(key=ENV["SPOT_API_KEY"], secret=ENV["SPOT_SECRET_KEY"])
7+
8+
@testset verbose = true "Account" begin
9+
@test typeof(SpotUser.get_account_balance(client)) == Dict{String,Any}
10+
@test typeof(SpotUser.get_websockets_token(client)) == Dict{String,Any}
11+
@test typeof(SpotUser.get_trade_balance(client, asset="USD")) == Dict{String,Any}
12+
@test typeof(SpotUser.get_ledgers_info(client, start=1675066107, end_=1675166107)) == Dict{String,Any}
13+
@test typeof(SpotUser.get_ledgers(client, id="LBXJQL-BRYFU-7ZIMEA", trades=true)) == Dict{String,Any}
14+
@test typeof(SpotUser.get_trade_volume(client, pair="XBTUSD")) == Dict{String,Any}
15+
end
16+
17+
@testset verbose = true "Orders and positions" begin
18+
@test typeof(SpotUser.get_trades_history(client, trades=true, start=1675066107, end_=1675166107)) == Dict{String,Any}
19+
@test typeof(SpotUser.get_open_orders(client, trades=true)) == Dict{String,Any}
20+
@test typeof(SpotUser.get_closed_orders(client, trades=true, start=1675066107, ofs="1")) == Dict{String,Any}
21+
@test typeof(SpotUser.get_orders_info(client, txid="OFRQKY-YOKNY-YLN5BM")) == Dict{String,Any}
22+
@test typeof(SpotUser.get_trades_info(client, txid="TKH2SE-M7IF5-CFI7LT")) == Dict{String,Any}
23+
@test typeof(SpotUser.get_open_positions(client, txid="TKH2SE-M7IF5-CFI7LT")) == Vector{Any}
24+
end
25+
26+
@testset verbose = true "Report export" begin
27+
28+
result = SpotUser.request_export_report(client, report="trades", description="myExport", format="CSV")
29+
@test typeof(result) == Dict{String,Any}
30+
31+
sleep(4)
32+
@test typeof(SpotUser.get_export_report_status(client, report="trades")) == Vector{Any}
33+
34+
report = SpotUser.retrieve_export(client, id=result["id"])
35+
@test typeof(report) == Vector{UInt8}
36+
37+
@test typeof(SpotUser.delete_export_report(client, id=result["id"], type="delete")) == Dict{String,Any}
38+
end
39+
40+
41+
sleep(3)
42+

0 commit comments

Comments
 (0)
Please sign in to comment.