2

I am trying to use the binance_async library, tokio, and futures to make concurrent orders to Binance. (See notes at the end of this question.)
The binance_async functions I'm using return a binance_async::error::Result<impl futures::future::Future<_, _>> type. I am facing the following issue, illustrated in these 2 examples:

  1. Say I'm trying to do this:
let bn = Binance::with_credential(&api_key, &secret_key);
let fut = bn.limit_sell(&symbol, qty, price);
tokio::spawn(fut.unwrap()); // ERROR
/* Error message:
  error[E0277]: `impl futures::future::Future` is not a future
  --> src/main.rs:23:5
   |
23 |     tokio::spawn(fut.unwrap());
   |     ^^^^^^^^^^^^ `impl futures::future::Future` is not a future
   |
   = help: the trait `futures::Future` is not implemented for `impl 
 futures::future::Future`
*/

This is super weird. First, I can't find futures::Future anywhere -- only futures::future::Future, which fut.unwrap() implements. Any help?

  1. Okay, forget about Tokio, let's try this:
let mut orders : Vec<Result<_>> = Vec::new();  // not std::Result
let fut = bn.limit_sell(&symbol, qty, price);
    
orders.push(fut);

let mut futures = Vec::new(); // I want to unwrap them, to use join_all()
for f in orders.iter() {
    match *f {
        Ok(x) => {
            futures.push(x);
        },
        Err(e) => {}
    }
}

futures::future::join_all(futures).await; // <--- ERROR!
/* Error message (one of 3 similar ones):
    error[E0277]: `impl futures::future::Future` is not a future
    --> src/main.rs:37:5
    |
 37 |     join_all(futures).await; // <--- ERROR!
    |     ^^^^^^^^^^^^^^^^^^^^^^^ `impl futures::future::Future` is not a future
    |
    = help: the trait `futures::Future` is not implemented for `impl 
 futures::future::Future`
    = note: required because of the requirements on the impl of `futures::Future` for 
 `JoinAll<impl futures::future::Future>`
    = note: required by `futures::Future::poll`
*/

Same error, same question.

Notes:

  1. I might be over-importing. If importing all these libraries looks like overkill or even the source of the problem, let me know!
  2. I am aware that binance_async is an under-maintained library. I am most likely going to ditch this approach altogether and go for binance crate instead. I am just really curious about this error.
  3. My supervisor says it might have to do with attribute macros, but both of us only having a few months' experience in Rust and trying to get this work fast, we can't afford to dig deeper.

Thanks much :)

leila-m
  • 97
  • 1
  • 9
  • 1
    The main issue is that `binance_async` uses `futures` crate version `0.1`. This was before std had the `Future` trait and that trait is what Tokio uses internally on recent versions. The `futures::Future` trait your error is refering to is actually [`std::futures::Future`](https://doc.rust-lang.org/std/future/trait.Future.html). Dropping Tokio, you get into the second issue that is incompatible `futures` versions in your project and `binance_async` (I'm assuming you use the latest while dependency use `0.1`). See: https://rust-lang.github.io/futures-rs/blog/2019/04/18/compatibility-layer.html – Sven Jun 11 '21 at 10:35
  • @Sven Thank you for your comment. :) But that looks like std::future::Future though, so not quite... Also, the most recent version of Tokio uses core::future::Future (an even third path for the Future trait!). – leila-m Jun 11 '21 at 10:52
  • See https://docs.rs/tokio/1.6.1/tokio/fn.spawn.html and https://doc.rust-lang.org/nightly/core/future/trait.Future.html – leila-m Jun 11 '21 at 10:53
  • They're essentially the same thing. The reason libraries use `core` instead of `std` is because they may need to compile on platforms where `std` is not available. `std` requires libc and other system libraries to compile, while `core` does not. If you click on the *src* button on [`std`](https://doc.rust-lang.org/std/future/trait.Future.html) and [`core`](https://doc.rust-lang.org/core/future/trait.Future.html) versions of the `Future` trait, you can see that they both originate from `/src/core/future/future.rs#32-100`. – Sven Jun 11 '21 at 11:07
  • 1
    See source: https://github.com/rust-lang/rust/blob/66ba81059e15b3466c71fe5b5bf2418702dd1fd1/library/std/src/lib.rs#L418-L419 – Sven Jun 11 '21 at 11:10
  • I didn't know that! Thanks for that! – leila-m Jun 11 '21 at 12:30

1 Answers1

3

binance_async uses futures 0.1, which is incompatible with the now standardized std::future::Future that tokio uses. You can convert a futures 0.1 future to a standard future by enabling the compat feature:

futures = { version = "0.3", features = ["compat"] }

And calling the .compat() method:

use futures::compat::Future01CompatExt;

tokio::spawn(fut.unwrap().compat());
use futures::compat::Future01CompatExt;

orders.push(fut.compat());
futures::future::join_all(futures).await;
Ibraheem Ahmed
  • 11,652
  • 2
  • 48
  • 54