Skip to the content
TAPEHOUSE

SDKs

Rust SDK

Read the band, margin accounts, shorts, baskets and gap cover and build their transactions with the tapehouse-sdk crate on alloy.

tapehouse-sdk gives you alloy contract instances for Tapehouse's contracts at the addresses of a chain's registry, plus typed helpers for the reads and quotes that need more than one call. A method on an instance builds a typed call or transaction, which you .call() or .send() through your own alloy provider and signer.

Read and send#

Rust
use alloy::providers::ProviderBuilder;
use tapehouse_sdk::{Deployments, Tapehouse, to_bytes32};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let deployments = Deployments::load("deployments/46630.json")?;
    let provider = ProviderBuilder::new()
        .connect_http("https://rpc.testnet.chain.robinhood.com".parse()?);
    let tapehouse = Tapehouse::new(provider, deployments);

    let quote = tapehouse.band()?.quote(to_bytes32("TSLA")?).call().await?;
    println!("{} {} {}", quote.state, quote.low, quote.high);
    Ok(())
}

To send, give the provider a wallet (ProviderBuilder::new().wallet(signer)) and send the call the instance builds:

Rust
use alloy::primitives::U256;
use tapehouse_sdk::CROSS;

let receipt = tapehouse
    .accounts()?
    .borrow(CROSS, U256::from(50_000_000u64), account, account)
    .send()
    .await?
    .get_receipt()
    .await?;

An asset is its symbol as &str, turned into a B256 with to_bytes32. A position is CROSS or an asset's B256. Amounts are U256 in raw units. A fallible method returns tapehouse_sdk::Result.

Registry#

ItemWhat it does
Deployments::load(path)Reads deployments/<chainId>.json
Deployments::parse(json)The same from a &str. An address in mixed case must carry its checksum
deployments.share_prices()Whether the chain's Chainlink feeds price the share (SHARE_PRICE_CHAINS, Arbitrum One)
token_price_feed(name), share_price_feed(name)A .chainlink feed as TokenPriceFeed or SharePriceFeed
to_bytes32(name)A symbol or feed ID as 32 bytes; an error above 32 bytes
CROSSThe cross position

Tapehouse#

Tapehouse::new(provider, deployments) takes an alloy Provider + Clone. Its accessors return alloy instances generated with sol! from the contracts' ABIs, so every function of the contract is a method on them.

MethodReturns
band()The band: quote, session, halt, price, writePrices and the rest
band_feed(asset)An asset's BandFeed: latestRoundData, latestBand, seal
accounts()The margin accounts: deposit, withdraw, borrow, repay, health, setAuthorization and the rest
shorts()The short positions: sell, cover, deposit, withdraw, liquidate
basket(key)A basket of .tapehouse.Baskets
gap_cover()The gap cover
usdg(), stock_token(asset)USDG and an asset's Stock Token
morpho_oracle(asset)An asset's Morpho oracle from .morphoOracles
token_price(feed), share_price(feed)A Chainlink aggregator, typed by what it prices
deployments()The registry

The bindings in tapehouse_sdk::bindings also cover the margin engine, the liquidator, the gap backstop, the reopening auction, the stock lending vault, the supply vault, Morpho Blue, Uniswap's QuoterV2, the sponsor paymaster, WETH and the Stock Token registry.

Helpers#

These are on Tapehouse and do what an instance cannot do in one call.

MethodArgumentsDoes
write_pricessource: &impl PackageSource, feed_ids: &[&str]The band's writePrices with the payload source returns. The crate holds no RedStone key
observeassetThe accounts' observe of an asset. Anyone may
set_mandateagent, expires_at, max_debt, max_leverageBounded authority for an agent; expires_at of 0 ends it
mandate, mandate_statusaccount, agent (and position)The mandate, and whether the agent may borrow now
recoveryassetWhen borrowing against an asset reopens
repaymentaccount, positionRepayment { debt, premium, assets }, both read at one block
collateralaccount, position, tokenWhat the position holds of a token
leverageaccount, positionGross exposure over equity in basis points
liquidation_priceaccount, position, asset, borrowingThe price at or above which the position meets its requirement once it owes borrowing more USDG
quote_sale, quote_coverasset, amount, slippage_bpsSale { proceeds, min_proceeds } and BuyBack { cost, max_cost } from Uniswap's QuoterV2; slippage is 0 to 10,000 basis points
unwrapaccount, key, sharesRedeems basket shares in the cross position
basket_components, preview_mint, preview_redeem, basket_target, pending_targetkey (and shares)A basket's reads
in_basketsaccount, positionWhat a position holds of each Stock Token through its baskets
quote_gap_coverasset, layerCoverQuote { premium, reserve }
gap_cover_pricing_gapassetThe weekend gap the cover prices at
gap_cover_salesnoneThe closure on sale, if any
gap_cover_seriesasset, closes_msA Series: open, settled with its prices, or void
oracle_priceassetAn OraclePrice: a price, or no price with NoPrice::Stale, Halted or SequencerNotSettled. Never zero
payoutlayer, reference_price, priceA free function: what a settled cover pays

Layer is { notional, deductible_bps, limit_bps }. PackageSource is a trait with one method, payload(&self, feed_ids: &[&str]), that returns the signed RedStone payload as Bytes.

Errors#

tapehouse_sdk::Error is Registry, Argument, Revert, Unexpected, Contract and Source. A call that fails inside alloy converts to Error::Revert when its revert data matches an error of the contracts. decode_revert(&alloy::contract::Error) and decode_revert_data(&[u8]) return the Revert { name, args, data }. See errors.

Rust
use tapehouse_sdk::decode_revert;

if let Some(revert) = decode_revert(&error) {
    println!("{revert}");
}

Example#

crates/sdk/examples/devnode.rs runs the crate against a local Nitro dev node: PRIVATE_KEY=0x… cargo run --example devnode -- RPC_URL DEPLOYMENTS_JSON PAYLOAD_FILE. It reads the key from the environment, never from an argument.

Next#