-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9 from fran0x/master
docs + websocket + RFQs
- Loading branch information
Showing
33 changed files
with
888 additions
and
227 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
name: audit | ||
|
||
on: | ||
push: | ||
paths: | ||
- "**/Cargo.toml" | ||
- "**/Cargo.lock" | ||
schedule: | ||
- cron: "0 0 * * *" | ||
|
||
jobs: | ||
audit: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v1 | ||
- run: cargo audit | ||
working-directory: rust | ||
env: | ||
CARGO_TERM_COLOR: always | ||
RUSTFLAGS: "-Dwarnings" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
name: rust | ||
|
||
on: | ||
push: | ||
branches: | ||
- master | ||
pull_request: | ||
types: [opened, synchronize, reopened] | ||
branches: | ||
- master | ||
|
||
env: | ||
CARGO_TERM_COLOR: always | ||
RUSTFLAGS: "-Dwarnings" | ||
|
||
jobs: | ||
test: | ||
name: Test | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- uses: actions/cache@v2 | ||
id: cache-dependencies | ||
with: | ||
path: | | ||
rust/.cargo/registry | ||
rust/.cargo/git | ||
rust/target | ||
key: ${{ runner.os }}-cargo-${{ hashFiles('rust/Cargo.lock') }} | ||
- uses: actions-rs/toolchain@v1 | ||
with: | ||
profile: minimal | ||
toolchain: stable | ||
override: true | ||
- run: cargo test | ||
working-directory: rust | ||
|
||
fmt: | ||
name: Rustfmt | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- uses: actions-rs/toolchain@v1 | ||
with: | ||
toolchain: stable | ||
override: true | ||
components: rustfmt | ||
- run: cargo fmt --all -- --check | ||
working-directory: rust | ||
|
||
clippy: | ||
name: Clippy | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- uses: actions-rs/toolchain@v1 | ||
with: | ||
toolchain: stable | ||
override: true | ||
components: clippy | ||
- run: cargo clippy --all-targets --all-features | ||
working-directory: rust |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,20 @@ | ||
# Backpack Exchange Api Clients | ||
# Backpack Exchange API | ||
|
||
This repository contains the Backpack Exchange API clients for various languages. | ||
<img src="img/backpack.png" width="150px" alt="Backpack" /> | ||
|
||
## Clients | ||
Access the official API documentation here: [https://docs.backpack.exchange/](https://docs.backpack.exchange/). | ||
|
||
[Rust](./rust) | ||
This repository hosts the Backpack Exchange API clients. Currently, the client is only available in [Rust](./rust). | ||
|
||
<img src="img/book_example.png" width="270px" alt="Order Book example" /> | ||
|
||
*Example of an Order Book* | ||
|
||
## Contributing | ||
|
||
We welcome contributions from the community! | ||
Feel free to open bug reports, suggest new features, or submit pull requests to improve the client and related components. | ||
|
||
## License | ||
|
||
This project is licensed under the [Apache 2.0 License](LICENSE). |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
[advisories] | ||
ignore = ["RUSTSEC-2023-0033"] # issue in rust_decimal due to borsh |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Generated by Cargo | ||
# will have compiled files and executables | ||
debug/ | ||
target/ | ||
|
||
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries | ||
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html | ||
Cargo.lock | ||
|
||
# These are backup files generated by rustfmt | ||
**/*.rs.bk | ||
|
||
# MSVC Windows builds of rustc generate these, which store debugging information | ||
*.pdb |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,26 @@ | ||
[workspace] | ||
members = ["client", "types"] | ||
members = ["client", "examples", "types"] | ||
resolver = "2" | ||
|
||
[workspace.package] | ||
keywords = ["backpack", "exchange"] | ||
repository = "https://github.com/backpack-exchange/bpx-api-client" | ||
|
||
[workspace.dependencies] | ||
anyhow = "1.0.93" | ||
base64 = "0.22.1" | ||
chrono = { version = "0.4.38", features = ["serde"] } | ||
ed25519-dalek = "2.1.1" | ||
futures-util = "0.3.31" | ||
reqwest = { version = "0.12.5", default-features = false, features = [ | ||
"json", | ||
"rustls-tls", | ||
"json", | ||
"rustls-tls", | ||
] } | ||
rust_decimal = "1.35.0" | ||
serde = { version = "1.0.208", features = ["derive"] } | ||
serde_json = "1.0.125" | ||
strum = { version = "0.26.3", features = ["derive"] } | ||
thiserror = "1.0.63" | ||
tokio = { version = "1.41.1", features = ["full"] } | ||
tokio-tungstenite = "0.24.0" | ||
tracing = "0.1.40" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,106 @@ | ||
# Backpack Exchange Rust Client | ||
[![Build Badge]][build] [![Crates Badge]][crates] [![Docs Badge]][docs] [![License Badge]][license] | ||
|
||
## Table of Contents | ||
[Build Badge]: https://github.com/backpack-exchange/bpx-api-client/actions/workflows/rust.yml/badge.svg | ||
[build]: https://github.com/backpack-exchange/bpx-api-client/actions | ||
|
||
- [Usage](#usage) | ||
- [Contributing](#contributing) | ||
[Crates Badge]: https://img.shields.io/crates/v/bpx_api_client.svg | ||
[crates]: https://crates.io/crates/bpx_api_client | ||
|
||
[Docs Badge]: https://docs.rs/bpx_api_client/badge.svg | ||
[docs]: https://docs.rs/bpx_api_client | ||
|
||
[License Badge]: https://img.shields.io/badge/License-Apache_2.0-blue.svg | ||
[license]: ../LICENSE | ||
|
||
# Backpack Exchange API Crate | ||
|
||
This crate provides both REST and WebSocket APIs for interacting with the Backpack Exchange: | ||
|
||
## Features | ||
|
||
- **REST API**: Access public and private (authenticated) endpoints. | ||
- **WebSocket API**: Subscribe to private streams for real-time updates (requires `ws` feature). | ||
|
||
The official API documentation is available at [https://docs.backpack.exchange/](https://docs.backpack.exchange/). | ||
|
||
## Installation | ||
|
||
Add this crate to your `Cargo.toml`: | ||
|
||
```toml | ||
[dependencies] | ||
bpx_api_client = "x.y.z" # Replace with the latest version | ||
``` | ||
|
||
To enable WebSocket support: | ||
|
||
```toml | ||
[dependencies] | ||
bpx_api_client = { version = "x.y.z", features = ["ws"] } | ||
``` | ||
|
||
## Usage | ||
|
||
Instructions on how to use the project. | ||
REST API example: | ||
|
||
```rust | ||
use bpx_api_client::{BpxClient, BACKPACK_API_BASE_URL}; | ||
use std::env; | ||
|
||
#[tokio::main] | ||
async fn main() { | ||
let base_url = env::var("BASE_URL").unwrap_or_else(|_| BACKPACK_API_BASE_URL.to_string()); | ||
let secret = env::var("SECRET").expect("Missing SECRET environment variable"); | ||
|
||
let client = BpxClient::init(base_url, secret, None) | ||
.expect("Failed to initialize Backpack API client"); | ||
|
||
match client.get_open_orders(Some("SOL_USDC")).await { | ||
Ok(orders) => println!("Open Orders: {:?}", orders), | ||
Err(err) => tracing::error!("Error: {:?}", err), | ||
} | ||
} | ||
``` | ||
|
||
WebSocket API example: | ||
|
||
```rust | ||
use anyhow::Result; | ||
use bpx_api_client::{BpxClient, BACKPACK_API_BASE_URL, BACKPACK_WS_URL}; | ||
use bpx_api_types::rfq::RequestForQuote; | ||
use std::env; | ||
use tokio::sync::mpsc; | ||
|
||
#[tokio::main] | ||
async fn main() -> Result<()> { | ||
let base_url = env::var("BASE_URL").unwrap_or_else(|_| BACKPACK_API_BASE_URL.to_string()); | ||
let ws_url = env::var("WS_URL").unwrap_or_else(|_| BACKPACK_WS_URL.to_string()); | ||
let secret = env::var("SECRET").expect("Missing SECRET environment variable"); | ||
|
||
let client = BpxClient::init_with_ws(base_url, ws_url, &secret, None)?; | ||
|
||
let (tx, mut rx) = mpsc::channel::<RequestForQuote>(100); | ||
tokio::spawn(async move { | ||
while let Some(rfq) = rx.recv().await { | ||
println!("Received RFQ: {:?}", rfq); | ||
} | ||
}); | ||
|
||
client.subscribe_to_rfqs(tx).await; | ||
|
||
Ok(()) | ||
} | ||
``` | ||
|
||
## Development | ||
|
||
This project uses [Just](https://github.com/casey/just) to manage various build and development tasks. | ||
|
||
To see the available commands, run: | ||
|
||
```shell | ||
just | ||
``` | ||
|
||
## Contributing | ||
## Crate Usage | ||
|
||
Guidelines on how to contribute to the project. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,26 @@ | ||
[package] | ||
name = "bpx-api-client" | ||
authors = ["Backpack <[email protected]>"] | ||
version = "0.5.0" | ||
license = "Apache-2.0" | ||
version = "0.4.0" | ||
edition = "2021" | ||
description = "Rust client for Backpack Exchange" | ||
repository = "https://github.com/backpack-exchange/bpx-api-client/tree/master/rust/client" | ||
description = "Backpack Exchange API client" | ||
repository = "https://github.com/backpack-exchange/bpx-api-client" | ||
|
||
[dependencies] | ||
base64 = { workspace = true } | ||
bpx-api-types = { version = "0.2.0", path = "../types" } | ||
bpx-api-types = { path = "../types" } | ||
ed25519-dalek = { workspace = true } | ||
reqwest = { workspace = true } | ||
serde = { workspace = true } | ||
serde_json = { workspace = true } | ||
thiserror = { workspace = true } | ||
tracing = { workspace = true } | ||
|
||
[dev-dependencies] | ||
tokio = { version = "1.39", features = ["full"] } | ||
# Dependencies for the `ws` feature | ||
tokio = { workspace = true, optional = true } | ||
tokio-tungstenite = { workspace = true, optional = true } | ||
futures-util = { workspace = true, optional = true } | ||
|
||
[features] | ||
default = [] | ||
ws = ["tokio", "tokio-tungstenite", "futures-util"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,37 +1,54 @@ | ||
//! Error handling module for the Backpack Exchange API client. | ||
//! | ||
//! Defines a custom `Error` type and a `Result` type alias to encapsulate | ||
//! various errors that can occur during API interactions. | ||
|
||
/// A type alias for `Result` using the custom `Error` type. | ||
pub type Result<T> = std::result::Result<T, Error>; | ||
|
||
/// Enum representing possible errors in the Backpack Exchange API client. | ||
#[derive(Debug, thiserror::Error)] | ||
pub enum Error { | ||
/// Error decoding a base64 string. | ||
#[error(transparent)] | ||
InvalidHeaderValue(#[from] reqwest::header::InvalidHeaderValue), | ||
Base64Decode(#[from] base64::DecodeError), | ||
|
||
/// Backpack API returned an error with status code and message. | ||
#[error("Backpack API error: {status_code}: {message}")] | ||
BpxApiError { | ||
status_code: reqwest::StatusCode, | ||
message: String, | ||
}, | ||
|
||
/// Invalid HTTP header value. | ||
#[error(transparent)] | ||
Reqwest(#[from] reqwest::Error), | ||
InvalidHeaderValue(#[from] reqwest::header::InvalidHeaderValue), | ||
|
||
#[error("Invalid URL: {0}")] | ||
UrlParseError(String), | ||
/// Represents an invalid request with a custom message. | ||
#[error("Invalid request: {0}")] | ||
InvalidRequest(String), | ||
|
||
/// General HTTP client error from `reqwest`. | ||
#[error(transparent)] | ||
SystemTime(#[from] std::time::SystemTimeError), | ||
Reqwest(#[from] reqwest::Error), | ||
|
||
/// Invalid secret key provided. | ||
#[error("Invalid secret key")] | ||
SecretKey, | ||
|
||
/// Error during JSON serialization or deserialization. | ||
#[error(transparent)] | ||
SerdeJson(#[from] serde_json::error::Error), | ||
|
||
/// Error working with system time. | ||
#[error(transparent)] | ||
Utf8(#[from] std::str::Utf8Error), | ||
SystemTime(#[from] std::time::SystemTimeError), | ||
|
||
/// UTF-8 decoding error. | ||
#[error(transparent)] | ||
Base64Decode(#[from] base64::DecodeError), | ||
|
||
#[error("Invalid secret key")] | ||
SecretKey, | ||
|
||
#[error("Invalid request: {0}")] | ||
InvalidRequest(String), | ||
Utf8(#[from] std::str::Utf8Error), | ||
|
||
#[error("Backpack API error: {status_code}: {message}")] | ||
BpxApiError { | ||
status_code: reqwest::StatusCode, | ||
message: String, | ||
}, | ||
/// Invalid URL format. | ||
#[error("Invalid URL: {0}")] | ||
UrlParseError(String), | ||
} |
Oops, something went wrong.