Middleware

The ArbiterMiddleware is the main interface for interacting with an Environment. We implement the ethers-rs Middleware trait so that you may work with contract bindings generated by forge or arbiter bind as if you were interacting with a live network. Not all methods are implemented, but the relevant ones are.

ArbiterMiddleware owns a Connection which is the client's interface to the Environment's Socket. This Connection acts much like a WebSocket connection and is used to send Instructions and receive their outcome from the Environment as well as subscribe to events. To make this Connection and ArbiterMiddleware flexible, we also implement (for both) the JsonRpcClient and PubSubClient traits.

We also provide ArbiterMiddleware a wallet so that it can be associated to an account in the Environment's world state. The wallet: EOA field of ArbiterMiddleware is decided upon creation of the ArbiterMiddleware and, if the wallet is generated from calling ArbiterMiddleware::new(), wallet will be of EOA::Wallet(Wallet<SigningKey>) which allows for ArbiterMiddleware to sign transactions if need be. It is possible to create accounts from a forked database, in which case you would call ArbiterMiddleware::new_from_forked_eoa() and the wallet would be of EOA::Forked(Address). This type is unable to sign as it is effectively impossible to recover the signing key from an address. Fortunately, for almost every usecase of ArbiterMiddleware, you will not need to sign transactions, so this distinction does not matter.

Usage

To create a ArbiterMiddleware that is associated with an account in the Environment's world state, we can do the following:

use arbiter_core::{middleware::ArbiterMiddleware, environment::Environment};

fn main() {
    let env = Environment::builder().build();

    // Create a client for the above `Environment` with an ID
    let id = "alice";
    let alice = ArbiterMiddleware::new(&env, Some(id));

    // Create a client without an ID
    let client = ArbiterMiddleware::new(&env, None);
}

These created clients can then get access to making calls and transactions to contracts deployed into the Environment's world state. We can do the following:

use arbiter_core::{middleware::ArbiterMiddleware, environment::Environment};
use arbiter_bindings::bindings::arbiter_token::ArbiterToken;

#[tokio::main]
async fn main() {
    let env = Environment::builder().build();
    let client = ArbiterMiddleware::new(&env, None).unwrap();

    // Deploy a contract
    let contract = ArbiterToken::deploy(client, ("ARBT".to_owned(), "Arbiter Token".to_owned(), 18u8)).unwrap().send().await.unwrap();
}