7个版本 (4个破坏性版本)
0.4.1 | 2024年7月31日 |
---|---|
0.4.0 | 2024年7月29日 |
0.3.0 | 2024年7月20日 |
0.2.0 | 2024年7月1日 |
0.0.1 | 2024年3月19日 |
#988 in 神奇豆子
每月401次下载
350KB
8K SLoC
Kraken-Async-Rs
对Kraken Pro交易API(v1和v2 WebSocket)的完整[^3]封装,使用异步Rust编写。
在未查阅Kraken API和WebSocket文档的情况下,无法使用Kraken-Async-Rs。接下来,应参考新的API文档:Kraken REST API、Kraken Websockets V1和Kraken Websockets V2。
由于这些细节和相互依赖[^1]不在本库的控制范围内,且可能会发生变化,因此并未在库中记录或强制执行。
示例:调用公开端点
公开端点调用非常简单,只需创建一个客户端对象并等待请求。由于不需要API密钥,使用StaticSecretsProvider
提供了一个空的、静态的集合,其值为空的&str
。有关导入的完整示例,请参阅完整示例。
#[tokio::main]
async fn main() {
// credentials aren't needed for public endpoints
let secrets_provider: Arc<Mutex<Box<dyn SecretsProvider>>> = Box::new(Arc::new(Mutex::new(StaticSecretsProvider::new("", ""))));
let nonce_provider: Arc<Mutex<Box<dyn NonceProvider>>> =
Arc::new(Mutex::new(Box::new(IncreasingNonceProvider::new())));
let mut client = CoreKrakenClient::new(secrets_provider, nonce_provider);
let request = TradableAssetPairsRequest::builder()
.pair(Pairs::new(vec!["BTCUSD".to_string()]))
.build();
let open_orders_response = client.get_tradable_asset_pairs(&request).await;
// Note that Kraken will return assets in their own naming scheme, e.g. a request for
// "BTCUSD" will return as "XXBTZUSD"
// For a reasonable understanding of their mappings, see: https://gist.github.com/brendano257/975a395d73a6d7bb53e53d292534d6af
if let Ok(ResultErrorResponse {
result: Some(tradable_assets),
..
}) = open_orders_response
{
for (asset, details) in tradable_assets {
println!("{asset}: {details:?}")
}
}
}
示例:调用私有端点
私有端点调用需要有效的凭证,凭证可以通过任何方式静态提供,或者通过一个 EnvSecretsProvider
提供,它会自动加载项目目录中的 .env
文件,并从本地环境中检索指定的键。有关导入的完整示例,请参阅 此处。
#[tokio::main]
async fn main() {
// note that this will fail if you don't have your key and secret set to these env vars
// eg `export KRAKEN_KEY="YOUR-API-KEY"`, ...
let secrets_provider: Arc<Mutex<Box<dyn SecretsProvider>>> = Box::new(Arc::new(Mutex::new(StaticSecretsProvider::new("", ""))));
let nonce_provider: Arc<Mutex<Box<dyn NonceProvider>>> =
Arc::new(Mutex::new(Box::new(IncreasingNonceProvider::new())));
let mut client = CoreKrakenClient::new(secrets_provider, nonce_provider);
let request = OpenOrdersRequest::builder().build();
let open_orders_response = client.get_open_orders(&request).await;
if let Ok(ResultErrorResponse {
result: Some(open_orders),
..
}) = open_orders_response
{
for (order_id, order) in open_orders.open {
println!("{order_id}: {order:?}")
}
}
}
示例:监听 Websockets(V2)
公共 Websockets 不需要认证,因此只需创建一个 v2::KrakenWSSClient
,连接,并发送任何订阅方法,然后等待返回的 KrakenMessageStream
的 .next()
方法。
您还可以访问带有日志和导入的 完整示例。
#[tokio::main]
async fn main() {
let mut client = KrakenWSSClient::new();
let mut kraken_stream = client.connect::<WssMessage>().await.unwrap();
let ohlc_params = OhlcSubscription::new(vec!["ETH/USD".into()], 60);
let subscription = Message::new_subscription(ohlc_params, 0);
let result = kraken_stream.send(&subscription).await;
assert!(result.is_ok());
while let Ok(Some(message)) = timeout(Duration::from_secs(10), kraken_stream.next()).await {
if let Ok(response) = message {
println!("{:?}", response);
} else {
println!("Message failed: {:?}", message);
}
}
}
示例:监听 Websockets(V1 - 已弃用)
Kraken 发布了具有简化数据类型、新功能以及更多标准化文档的 V2 版本 API。如果可能,应使用 V2 API,因为 V1 端点将得到维护但不会得到改进。
公共 Websockets 不需要认证,因此只需创建一个 KrakenWSSClient
,连接,并发送任何订阅方法,然后等待返回的 KrakenMessageStream
的 .next()
方法。
您还可以访问带有日志和导入的 完整示例。
#[tokio::main]
async fn main() {
let subscriptions = [
// many of these have additional options that could be set
Subscription::new_trades_subscription(),
Subscription::new_book_subscription(Some(10)), // use a depth of 10 for simplicity
Subscription::new_ticker_subscription(),
Subscription::new_ohlc_subscription(None),
Subscription::new_spread_subscription(),
];
let mut client = KrakenWSSClient::new();
let mut kraken_stream: KrakenMessageStream<PublicMessage> = client.connect().await.unwrap();
for subscription in subscriptions {
// for more valid pairs for WSS requests, consult the `ws_name` field of `get_tradable_asset_pairs`
let subscribe_message =
SubscribeMessage::new(0, Some(vec!["XBT/USD".into()]), subscription);
kraken_stream.subscribe(&subscribe_message).await.expect("failed to subscribe");
}
while let Some(message) = kraken_stream.next().await {
println!("{:?}", message.unwrap());
}
}
请求详情
具有超过 1 或 2 个参数的请求通常会给一个结构体,而不是有多个参数的方法。通过使用标记字段为必填的 simple-builder 包,builder
实现强制执行必填参数,确保它们必须在 .builder()
调用中提供。任何可选参数都可以使用流畅的 API 添加。
例如,深度(订单簿)端点需要一个对,但可以可选地接受一个 count
参数,用于返回每侧的出价/要价数量。然后构建器表现得如下
let request = OrderbookRequest::builder("ETHUSD".to_string())
.count(500)
.build();
响应详情
尽可能遵守 Kraken 的响应格式,除非某些情况会对可用性造成严重限制。反序列化使用 serde
,并保留大多数数据类型不变,除了将字符串解析为 rust_decimal::Decimal
,以及使用许多值有明确文档的枚举。大多数 i64
String
/RFC3339 和 f64
时间戳保持不变。目标是提供一个优秀的基库,供他人构建,而不会通过解析所有内容来限制下游使用并降低整体性能。如果您正在开发通用交易算法,您应该编写一个可以在这种解析之上进行操作的通用抽象。
如果您不同意或对解析、格式化或任何其他问题或受阻用例有意见,请提供您的问题的清晰示例!
安全
- 使用
secrecy
包防止在请求和响应对象中意外记录 WebSocket 令牌。 - 默认情况下,功能
debug-inbound
和debug-outbound
是关闭的,当启用时 将记录令牌,因为它们将传入和传出消息作为字符串记录,这些字符串不容易被删除。
其他细节
- 参数和响应值通常从 Kraken API 字段重命名为符合 Rust 的命名约定或提高可读性[^2]
贡献
这是一个独立开发的大型项目,尽管我尽了最大努力,但无疑还是遗漏了一些东西。请提供任何错误、可用性问题或改进建议的清晰示例!
[^1]:例如,AddOrder 端点需要 "Good-'til-Date" 订单同时指定 endtm
值。类似的情况有很多,并且 不 由这个库强制执行。
[^2]:例如,包括 refid
-> ref_id
,endtm
-> end_time
,ofs
-> order_flags
(或 offset
...),vol_exec
-> executed_volume
,qty
-> quantity
等等。
[^3]:在完成本库初始版本的后期,添加了一些关于 NFT 交易的 20+ 个端点。我正在考虑添加它,但没有实际用途。如果你有用途或想要贡献,请告知。
依赖项
~11–23MB
~366K SLoC