Skip to main content

Overview

The Boundless Market SDK offers high-level Rust APIs for interacting with the Boundless Market smart contracts, preparing and submitting ZK proofs, and handling relevant offchain data such as images and inputs. Crate Documentation

Installation

cargo add boundless-market
or add manually to your Cargo.toml:
[dependencies]
boundless-market = "X.X.X"
where X.X.X is the latest release specified on the Boundless GitHub Release page.

SDK Workflow Overview

Below is an example of the Boundless end-to-end programmatic workflow:

1. Initialize Client

use boundless_market::Client;
use alloy::signers::local::LocalSigner;
# use url::Url;
# async fn init_client(rpc_url: Url) -> anyhow::Result<()> {
let client = Client::builder()
    .with_rpc_url(rpc_url)
    .with_private_key(LocalSigner::random())
    .build()
    .await?;
# Ok(())
# }

2. Upload Program and Input

# use boundless_market::{Client, storage::storage_provider_from_env};
# use alloy::signers::local::LocalSigner;
# use url::Url;
# async fn upload_program_and_input(rpc_url: Url) -> anyhow::Result<()> {
# let client = Client::builder()
#    .with_rpc_url(rpc_url)
#    .with_private_key(LocalSigner::random())
#    .with_storage_provider(Some(storage_provider_from_env()?))
#    .build()
#    .await?;
let program_url = client.upload_program(&std::fs::read("guest.bin")?).await?;
let input_url = client.upload_input(&[0x41, 0x42, 0x43]).await?;
# Ok(())
# }

3. Submit Proof Request

# use boundless_market::Client;
# use boundless_market::contracts::ProofRequest;
# async fn submit_request(client: Client, request: ProofRequest) -> anyhow::Result<()>
# {
let (request_id, expires_at) = client.submit_request_onchain(&request).await?;
# Ok(())
# }

4. Await Fulfillment

# use std::time::Duration;
# use boundless_market::Client;
# use boundless_market::contracts::ProofRequest;
# async fn submit_request(client: Client, request: ProofRequest) -> anyhow::Result<()>
# {
# let (request_id, expires_at) = client.submit_request_onchain(&request).await?;
let fulfillment = client
    .wait_for_request_fulfillment(request_id, Duration::from_secs(10), expires_at)
    .await?;
# Ok(())
# }

5. Fetch Proof Results

# use alloy::primitives::U256;
# use boundless_market::Client;
# async fn fetch_results(client: Client, request_id: U256) -> anyhow::Result<()>
# {
// If not using wait_for_request_fulfillment:
let fulfillment = client.boundless_market.get_request_fulfillment(request_id).await?;

// Advanced: Set-Inclusion Receipt
let (journal, receipt) = client.fetch_set_inclusion_receipt(request_id, [0u8; 32].into()).await?;
# Ok(())
# }

SDK Modules

client

  • Client: Core struct for transactions, storage, and offchain interaction.

contracts

  • BoundlessMarketService: Onchain interactions (requests, fulfillments, deposits).
  • SetVerifierService: Manages aggregated proof verifications.
  • Structures: ProofRequest, Offer, Fulfillment.

input

  • GuestEnv: Environment for the guest, including input (e.g. stdin)

order_stream_client

  • OrderStreamClient: Submit/fetch orders offchain via WebSocket.

storage

  • Providers: S3 and Pinata for uploading program and input data.

selector

  • Utilities for tracking/verifying proof types.

Example: Full Proof Submission

use boundless_market::{
  Client,
  contracts::{FulfillmentData, RequestId, Requirements, Predicate, Offer},
  storage::storage_provider_from_env,
  request_builder::OfferParams,
};
use alloy::signers::local::PrivateKeySigner;
use alloy::primitives::U256;
use std::time::Duration;
use url::Url;

async fn proof_submission(signer: &PrivateKeySigner, rpc_url: Url) -> anyhow::Result<()> {
    let client = Client::builder()
        .with_rpc_url(rpc_url)
        .with_private_key(signer.clone())
        .with_storage_provider(Some(storage_provider_from_env()?))
        .build()
        .await?;

    // Build the request.
    let request = client.new_request()
        .with_program(std::fs::read("guest.bin")?)
        .with_stdin(42u32.to_le_bytes())
        .with_offer(OfferParams::builder()
            .ramp_up_period(30)
            .lock_timeout(150)
            .timeout(300)
        );

    // Submit the request onchain.
    let (request_id, expires_at) = client.submit_onchain(request).await?;

    let fulfillment = client
        .wait_for_request_fulfillment(request_id, Duration::from_secs(10), expires_at)
        .await?;
    println!("FulfillmentData: {:?}, Seal: {:?}", fulfillment.data()?, fulfillment.seal);

    Ok(())
}