Tezos/DMV domain logic for the SpruceId wallet-binding feature. Per OID4VP
presentation a self-signed TezosWalletBindingCredential is minted — a
jwt_vc_json verifiable credential (compact JWS) that proves the holder
controls an independent Tezos key.
The wire format is defined by the wallet-binding contract
(dev/wallet-binding/CONTRACT.md); the verifier counterpart lives in vdc-portal
(src/verifier/wallet_binding.rs). This repo mints exactly what that verifier
consumes.
This is a Cargo workspace of three crates:
| Crate | Role | SDK-coupled? |
|---|---|---|
crates/tezos-address |
Derive Tezos implicit addresses (tz1/tz2/tz3) from public keys | no (blake2, bs58) |
crates/tezos-wallet-binding |
Core schema + mint_binding_jws + binding_query_match |
no (signer-agnostic) |
crates/tezos-wallet-binding-provider |
SDK DynamicCredentialProvider over the core |
yes (mobile-sdk-rs) |
The split keeps the mint/wire logic (tezos-wallet-binding) free of any
mobile-sdk-rs dependency: it is unit-testable on its own and re-exports the
tezos-address derivation. Only tezos-wallet-binding-provider pulls the SDK.
// Pure, signer-agnostic mint. Returns the compact JWS.
pub fn mint_binding_jws<E, F>(
public_jwk_json: &str,
nonce: &str,
client_id: &str,
sign: F,
) -> Result<String, MintError>
where
E: std::fmt::Display,
F: FnOnce(&[u8]) -> Result<Vec<u8>, E>;
// Returns Some(credential_query_id) iff a DCQL credential query targets the
// TezosWalletBindingCredential type (format jwt_vc_json + meta.type_values).
pub fn binding_query_match(query_json: &str) -> Option<String>;
// Schema constants: VC_CONTEXT, VC_TYPE, BINDING_CREDENTIAL_TYPE,
// BINDING_METHOD, BINDING_FORMAT, OFFER_ID, OFFER_TITLE.
// Error type: MintError.
// Re-exports: `pub use tezos_address;` plus tz1_from_ed25519,
// tz3_from_p256_coords, tz3_from_p256_compressed, tz2_from_secp256k1_compressed.ES256 signatures are normalized to RFC 7515 raw 64-byte r||s with p256
directly (parse Signature::from_slice or from_der, re-emit to_bytes()) —
this replaces the previous mobile_sdk_rs::crypto::CryptoCurveUtils call and is
byte-identical to it. EdDSA signatures are already raw 64-byte and pass through.
// SDK DynamicCredentialProvider over an app-supplied Tezos SigningKey.
pub struct TezosWalletBindingProvider { /* private */ }
impl TezosWalletBindingProvider {
pub fn new(signing_key: Arc<dyn mobile_sdk_rs::crypto::SigningKey>) -> Self;
}
impl mobile_sdk_rs::oid4vp::dynamic_credential::DynamicCredentialProvider
for TezosWalletBindingProvider { /* offers + mint */ }| JWK | alg | tz address |
|---|---|---|
| OKP / Ed25519 | EdDSA |
tz1... |
| EC / P-256 | ES256 |
tz3... |
tezos-address and tezos-wallet-binding are path deps within the workspace.
The provider depends on mobile-sdk-rs via a git pin:
spruceid/sprucekit-mobile branch feat/dynamic-credential-provider (PR #314).