Expand description
§cow-sdk-app-data
CoW Protocol app-data document generation, typed validation, CID conversion, and the IPFS read transport seam.
⚠️ Alpha —
0.1.0-alpha. Pre-release and not security-audited; the public API may change before0.1.0. It is published as a pre-release, so Cargo selects it only when you opt in (cow-sdk-app-data = "0.1.0-alpha.10"). Review it yourself before relying on it with real funds.
appData is the canonical metadata attached to every CoW Protocol order.
This crate builds deterministic app-data documents, validates them through
typed metadata construction, computes their keccak256 digest, and
converts between the 32-byte hex hash and the supported CID encoding
(CIDv1 + raw codec + keccak-256 multihash).
Registering a document is an orderbook concern: hash it locally with this
crate, then submit the full document through OrderbookApi::upload_app_data,
which stores it under its hash. The IPFS read seam is the secondary path, for
resolving a document by hash directly from a gateway when it is not available
through the orderbook.
§Install
[dependencies]
cow-sdk-app-data = "0.1.0-alpha.10"§Minimal example
Tag a document with a validated AppCode, validate its modelled metadata,
and compute the canonical content and keccak256 digest in a single call. Chain
with_* setters for environment, signer, hooks, flashloan
hints, or open-ended metadata before the terminal into_validated:
use cow_sdk_core::AppCode;
use cow_sdk_app_data::AppDataParams;
let code = AppCode::new("my-app")?;
let validated = AppDataParams::new(code)
.with_environment("production")
.into_validated()?;
// Ready to register through the orderbook:
// PUT /api/v1/app_data/{hash}
// hash = validated.info.app_data_hex (0x-prefixed keccak256 digest)
// body = validated.info.app_data_content (canonical JSON)
assert_eq!(validated.info.app_data_hex.len(), 66); // "0x" + 32-byte digest§CID conversion
Convert between the 32-byte app-data hash and its CID form. The transform is pure and offline — no network — and round-trips losslessly:
use cow_sdk_app_data::{app_data_hex_to_cid, cid_to_app_data_hex};
let hex = "0x0000000000000000000000000000000000000000000000000000000000000000";
let cid = app_data_hex_to_cid(hex)?;
assert_eq!(cid_to_app_data_hex(&cid)?, hex);§Reading a document from IPFS
The primary way to read a document you registered is the orderbook
GET /api/v1/app_data/{hash} request, served from the orderbook database with
no gateway involved. The IPFS read seam is the secondary, not-in-database
path: it derives the keccak-256 CIDv1 from an app-data hash and reads it
through a fetch transport you supply, so the SDK stays decoupled from any
specific HTTP stack.
The seam is async, so native and browser runtimes can plug in their own HTTP
client; cow-sdk-js implements it over JavaScript’s CowFetchCallback, and
browser and non-browser wasm runtimes share the same app-data contract.
Because documents are addressed by a keccak-256 CID, the gateway must be able
to resolve keccak-CID documents — a generic public gateway cannot.
use cow_sdk_app_data::{AppDataError, IpfsFetchTransport, fetch_doc_from_app_data_hex};
struct IpfsClient;
impl IpfsFetchTransport for IpfsClient {
async fn get(&self, uri: &str) -> Result<String, AppDataError> {
// Issue the GET with your HTTP client of choice and return the body.
let _ = uri;
Ok(r#"{"version":"1.4.0","metadata":{}}"#.to_owned())
}
}
let app_data_hex =
"0x337aa6e6c2a7a0d1eb79a35ebd88b08fc963d5f7a3fc953b7ffb2b7f5898a1df";
let doc = fetch_doc_from_app_data_hex(app_data_hex, client, None).await?;
assert_eq!(doc["version"], "1.4.0");Pass None to read from the default CoW gateway, or Some(uri) to target a
specific keccak-CID-capable gateway. When you already hold a CID rather than a
hash, fetch_doc_from_cid takes the same transport.
§Canonical JSON
App-data document canonicalisation routes through serde_jcs::to_string per
RFC 8785 (JSON Canonicalization Scheme). The serializer sorts object keys
by UTF-16 code unit value and emits a deterministic byte sequence for any
equivalent document shape, so the resulting CID is byte-identical to the
canonical form the upstream @cowprotocol/cow-sdk TypeScript helper would
produce for the same input. Documents whose object keys carry code points
whose UTF-16 ordering and UTF-8 byte ordering disagree are pinned by
parity/fixtures/app_data/canonical_json_utf16.json; ASCII-only documents
are byte-identical to any earlier bytewise canonicalisation.
The cow AppDataHash is a cow-owned #[repr(transparent)] newtype over
alloy_primitives::B256 per
ADR 0052;
the canonical CID conversion is the free function app_data_hex_to_cid,
which takes the hash’s to_hex_string form. The digest input fed to
alloy_primitives::keccak256 is the canonical-JSON byte stream produced
by serde_jcs.
§Feature flags
| Feature | Default | Enables |
|---|---|---|
tracing | off | Emits tracing spans and enables cow-sdk-core’s tracing. |
§Where this fits
This crate builds and validates app-data and converts hex ↔ CID. It does not
perform IPFS networking itself — you supply an IpfsFetchTransport — and it does
not sign, submit, or attach app-data to an order. Registering a document is an
orderbook concern via OrderbookApi::upload_app_data
(cow-sdk-orderbook); the digest
and content also feed
cow-sdk-trading. Only the
CIDv1 + raw + keccak-256 shape is supported; CIDv0 is rejected.
§Where to next
§License
Licensed under GPL-3.0-or-later. See the workspace
LICENSE
file for the full text.
CoW Protocol app-data generation, validation, CID conversion, and
the IPFS read transport seam.
§Quick start
Build a minimal SDK-attribution document tagged with a validated
AppCode, validate its modelled metadata, and
produce a payload ready for PUT /api/v1/app_data/{hash}:
use cow_sdk_core::AppCode;
use cow_sdk_app_data::AppDataParams;
let code = AppCode::new("my-app")?;
let validated = AppDataParams::new(code).into_validated()?;
// validated.info.app_data_content — canonical JSON for PUT /app_data
// validated.info.app_data_hex — 0x-prefixed keccak256 digestChain with_* setters before the terminal call to add environment,
signer, hooks, flashloan hints, or open-ended metadata. See
AppDataParams for the full setter surface and additional examples.
Re-exports§
pub use cid::app_data_hex_to_cid;pub use cid::cid_to_app_data_hex;pub use errors::AppDataError;pub use fetch::IpfsFetchPolicy;pub use fetch::IpfsFetchTransport;pub use fetch::fetch_doc_from_app_data_hex;pub use fetch::fetch_doc_from_app_data_hex_with_policy;pub use fetch::fetch_doc_from_cid;pub use fetch::fetch_doc_from_cid_with_policy;pub use info::APP_DATA_APPROACHING_LIMIT_RATIO;pub use info::APP_DATA_MAX_BYTES;pub use info::AppDataSource;pub use info::AppDataValidated;pub use info::AppDataValidation;pub use info::AppDataWarning;pub use info::app_data_cid;pub use info::app_data_content;pub use info::app_data_info;pub use info::app_data_info_hex;pub use info::stringify_deterministic;pub use metadata::FlashloanHints;pub use metadata::Hook;pub use metadata::HookList;pub use metadata::QuoteMetadata;pub use schema::extract_schema_version;pub use schema::generate_app_data_doc;pub use schema::validate_app_data_doc;pub use types::AppDataDoc;pub use types::AppDataInfo;pub use types::AppDataParams;pub use types::DEFAULT_APP_CODE;pub use types::DEFAULT_IPFS_READ_URI;pub use types::IpfsConfig;pub use types::LATEST_APP_DATA_VERSION;pub use types::MetadataMap;pub use types::PartnerFee;pub use types::PartnerFeePolicy;pub use types::SchemaVersion;
Modules§
- cid
- CID conversion helpers for app-data hashes and documents. CID conversion helpers for app-data documents.
- errors
- App-data crate error types.
- fetch
- IPFS fetch policies and read transport seams.
- info
- Deterministic app-data rendering and digest helpers.
- metadata
- Typed sub-metadata shapes carried inside the app-data envelope. Typed sub-metadata shapes carried inside the app-data envelope.
- schema
- Schema generation and validation helpers.
- types
- Shared app-data types, constants, and configuration structs. Shared app-data types, constants, and configuration structs.