AnchorShieldprove it, stay private
Stellar testnet Launch console

developer quickstart

One require line.
Full check.

Add a check to any Stellar action with AnchorShield's deployed proof system. Call the live verifier to confirm the person is approved before your action, or check a fresh proof for each action yourself — you never build the ZK circuit or verifier from scratch.

two ways to integrate

Pick how much privacy you want

Both ways reuse the deployed AnchorShield proof system on testnet. Model A is the fastest path; Model B gives every action its own fresh proof that can't be traced back.

model a just read the approval

One line to check eligibility

The user proves once with identity_verifier.attest or attest_identity. Your contract calls verify_identity_for(account, policy_id) and continues only if that account still holds a live approval for your policy. Always pin the policy — a bare passport approval must not satisfy a gate that expects age or country checks.

use soroban_sdk::{contractclient, contracttype, Address, Env};

#[derive(Clone)]
#[contracttype]
pub struct Attestation {
    pub policy_id: u32,
    pub issuer_id: u32,
    pub valid_until: u64,
}

#[contractclient(name = "IdentityVerifierPeerClient")]
pub trait IdentityVerifierPeer {
    fn verify_identity_for(env: Env, account: Address, policy_id: u32);
    fn attestation_of(env: Env, account: Address) -> Option<Attestation>;
}

fn require_anchorshield_identity(
    env: &Env,
    identity_verifier: &Address,
    account: &Address,
    policy_id: u32,
    issuer_id: u32,
) {
    let identity = IdentityVerifierPeerClient::new(env, identity_verifier);
    identity.verify_identity_for(account, &policy_id);
    let attestation = identity.attestation_of(account).unwrap();
    assert!(attestation.issuer_id == issuer_id);
}

// in your action
account.require_auth();
require_anchorshield_identity(&env, &identity_verifier, &account, MY_POLICY, MY_ISSUER);
  • Work in your contractone peer call
  • Expired or missing approvalaction reverts
  • Account ↔ approval link on the blockchainuntil expiry
model b a proof per action

A fresh proof for each action

Check the proof and its public signals yourself, and tie every signal to the exact action with your own nullifier — the same shape as the canonical gate_payment.verify_and_pay.

[dependencies]
soroban-sdk = { version = "=26.1.0" }
anchorshield-shared = { path = "../shared" }
use anchorshield_shared::{
    bool_as_u32, require_signal_u128, require_signal_u32, signal, verify_proof,
    IssuerRegistryPeerClient, NullifierRegistryPeerClient, PolicyRegistryPeerClient,
    Proof, VerifierPeerClient, ACTION_ID, ACTION_TYPE, AMOUNT, CREDENTIAL_ROOT,
    EPOCH, ISSUER_ID, NULLIFIER, POLICY_ID,
};
  • Every public signal tied to the actionenforced
  • Replay via the nullifier registryrejected
  • Action ↔ identity linknone

frontend

Install the SDK

@anchorshield/sdk v0.2.0 ships helpers for building the proof, the public inputs and the wallet submission, plus a React subpath — @anchorshield/sdk/react exposes useAnchorShield and AnchorShieldGate. The Policy Composer generates a Gate.jsx wired to both.

npm
npm install @anchorshield/sdk

deployed contracts

Point at the live testnet contracts

Your integration points at these contract IDs — the same ones in apps/web/data/deployments.json. You don't redeploy any core AnchorShield contract for either way.

contract role id
identity_verifier Model A attest + verify_identity pending
verifier Groth16 verification · VK frozen pending
issuer_registry Trusted issuer roots pending
policy_registry Per-gate eligibility policy pending
nullifier_registry Replay protection pending
gate_payment Model B canonical gate · verify_and_pay pending
rwa_compliance_adapter Consumes mint authorization pending
oz_rwa_token OpenZeppelin SEP-57 asset pending
native_sac Native asset SAC used by the payment gate pending

start building

Build a policy, get a gate you can deploy

The Policy Composer writes the policy.json, the registry command, the Stellar gate contract and the React drop-in for you — all in your browser.