Compile and deploy

Now we will create a test that compiles, signs and deploys the counter app on a locally running essential-server.

Start by adding the imports you will need.

#![allow(unused)]
fn main() {
use essential_app_utils::{compile::compile_pint_project, local_server::setup_server};
use counter_app::App;
use essential_types::{PredicateAddress, Word};
}

Add a tokio test because we are using async code.

#![allow(unused)]
fn main() {
#[tokio::test]
async fn test_counter() {

}
}

Run a local essential-server in the background.

Note that this requires that the essential-server binary be your $PATH. See the installation section for more details.

#![allow(unused)]
fn main() {
#[tokio::test]
async fn test_counter() {
    let (addr, _server) = setup_server().await.unwrap();
}
}

Compile

Compile the pint project.

Note that this requires that the pint binary be your $PATH. See the installation section for more details.

#![allow(unused)]
fn main() {
#[tokio::test]
async fn test_counter() {
    // ...

    let counter = compile_pint_project(
        concat!(env!("CARGO_MANIFEST_DIR"), "/../contract").into(),
    )
    .await
    .unwrap();
}
}

Create the PredicateAddress. This is the ContentAddress of the overall contract and the ContentAddress if the predicate.

#![allow(unused)]
fn main() {
#[tokio::test]
async fn test_counter() {
    // ...

    let contract_address = essential_hash::contract_addr::from_contract(&counter);
    let predicate_address = essential_hash::content_addr(&counter.predicates[0]);
    let predicate_address = PredicateAddress {
        contract: contract_address,
        predicate: predicate_address,
    };
}
}

Our contract only has a single predicate but other contracts can have multiple predicates and therefor multiple PredicateAddresss.

Sign and deploy

Using the essential-wallet create a temporary wallet and a new key for alice using the Secp256k1 scheme.
This is the key that you will use to sign the contract before deploying it.

#![allow(unused)]
fn main() {
#[tokio::test]
async fn test_counter() {
    // ...

    let mut wallet = essential_wallet::Wallet::temp().unwrap();
    wallet
        .new_key_pair("alice", essential_wallet::Scheme::Secp256k1)
        .unwrap();
}
}

Note that the essential-wallet has not been audited and is only for testing purposes. In this test we create a temporary key that is deleted at the end of the test.
To interact with the hosted essential-server you will want to create a key pair that's stored locally using essential-wallet.
Our wallet is just a convenience for testing.

Sign and deploy the contract using alice's key.

#![allow(unused)]
fn main() {
#[tokio::test]
async fn test_counter() {
    // ...

    essential_deploy_contract::sign_and_deploy(addr.clone(), "alice", &mut wallet, counter)
        .await
        .unwrap();
}
}

Now we are done getting everything setup and deployed.
In the next section we will interact with the deployed contract.

Check your `tests/counter.rs` matches this.
#![allow(unused)]
fn main() {
use essential_app_utils::{compile::compile_pint_project, local_server::setup_server};
use counter_app::App;
use essential_types::{PredicateAddress, Word};

#[tokio::test]
async fn test_counter() {
    let (addr, _server) = setup_server().await.unwrap();

    let counter = compile_pint_project(
        concat!(env!("CARGO_MANIFEST_DIR"), "/../contract").into(),
    )
    .await
    .unwrap();

    let contract_address = essential_hash::contract_addr::from_contract(&counter);
    let predicate_address = essential_hash::content_addr(&counter.predicates[0]);
    let predicate_address = PredicateAddress {
        contract: contract_address,
        predicate: predicate_address,
    };

    let mut wallet = essential_wallet::Wallet::temp().unwrap();
    wallet
        .new_key_pair("alice", essential_wallet::Scheme::Secp256k1)
        .unwrap();

    essential_deploy_contract::sign_and_deploy(addr.clone(), "alice", &mut wallet, counter)
        .await
        .unwrap();
}
}