Boundless Rust SDK
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.
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::ClientBuilder;
use alloy::signers::local::LocalSigner;
# use alloy::primitives::Address;
# use url::Url;
# async fn init_client(rpc_url: Url, market_address: Address, set_verifier_address: Address) -> anyhow::Result<()> {
let client = ClientBuilder::new()
.with_rpc_url(rpc_url)
.with_boundless_market_address(market_address)
.with_set_verifier_address(set_verifier_address)
.with_wallet(LocalSigner::random().into())
.build()
.await?;
# Ok(())
# }
2. Upload ELF and Input
let elf_url = client.upload_image(&std::fs::read("guest.elf")?).await?;
let input_url = client.upload_input(&[0x41, 0x42, 0x43]).await?;
3. Submit Proof Request
let (request_id, expires_at) = client.submit_request(&request).await?;
4. Await Fulfillment
let (journal, seal) = client
.wait_for_request_fulfillment(request_id, Duration::from_secs(10), expires_at)
.await?;
5. Fetch Proof Results
// If not using wait_for_request_fulfillment:
let (journal, seal) = 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?;
SDK Modules
client
Client
: Core struct for transactions, storage, and offchain interaction.ClientBuilder
: Configure and build the client.
contracts
BoundlessMarketService
: Onchain interactions (requests, fulfillments, deposits).SetVerifierService
: Manages aggregated proof verifications.- Structures:
ProofRequest
,Offer
,Fulfillment
.
input
InputBuilder
: Prepare inputs for RISC Zero guests.
order_stream_client
OrderStreamClient
: Submit/fetch orders offchain via WebSocket.
storage
- Providers:
S3
,Pinata
, andTempFile
for uploading ELF/input data.
selector
- Utilities for tracking/verifying proof types.
Example: Full Proof Submission
use boundless_market::{
client::ClientBuilder,
contracts::{ProofRequest, RequestId, Requirements, Predicate, Offer},
input::InputBuilder,
storage::StorageProvider,
};
use alloy::signers::local::LocalSigner;
use alloy::signers::local::PrivateKeySigner;
use alloy::primitives::{Address, U256};
use std::time::Duration;
use url::Url;
async fn proof_submission(signer: &PrivateKeySigner, rpc_url: Url, market_address: Address, set_verifier_address: Address) -> anyhow::Result<()> {
let client = ClientBuilder::new()
.with_rpc_url(rpc_url)
.with_boundless_market_address(market_address)
.with_set_verifier_address(set_verifier_address)
.with_wallet(signer.clone().into())
.build()
.await?;
let elf_url = client.upload_image(&std::fs::read("guest.elf")?).await?;
let input_url = client.upload_input(&InputBuilder::new().write(&42u32)?.build_vec()?).await?;
let request = ProofRequest::new(
RequestId::new(signer.address(), 0),
Requirements::new([0u8; 32], Predicate::prefix_match([])),
elf_url,
input_url,
Offer {
minPrice: U256::from(1_000),
maxPrice: U256::from(2_000),
biddingStart: 0,
rampUpPeriod: 60,
timeout: 3600,
lockTimeout: 1800,
lockStake: U256::from(500),
}
);
let (request_id, expires_at) = client.submit_request(&request).await?;
let (journal, seal) = client
.wait_for_request_fulfillment(request_id, Duration::from_secs(10), expires_at)
.await?;
println!("Journal: {:?}, Seal: {:?}", journal, seal);
Ok(())
}