voxID

On-chain program

An Anchor program that holds credentials and gates buying. It enforces uniqueness exactly; the fuzzy part stays with the verifier.

Not deployed yet. The program ID will be published here when it is.

Accounts

AccountSeedsFields
Config["config"]admin, verifier_authority, treasury, mint, price_lamports, credentials_issued, epoch_cap, epoch, issued_in_epoch
HumanCredential["cred", wallet]wallet, person_id, issued_at, revoked
PersonLock["person", person_id]person_id, bound_wallet
UsedNonce["nonce", wallet, nonce]none; its existence marks a pass as spent

Both HumanCredential and PersonLock are created with Anchor's init, which fails if the account exists. That is the uniqueness rule: a second credential for a wallet, or a second wallet for a person ID, can't be created.

Instructions

InstructionSignerEffect
initialize_configadminCreates Config and the token mint (authority: Config).
issue_credential(wallet, person_id)verifierCreates both PDAs. Limited to epoch_cap per Solana epoch.
rebind_wallet(person_id, new_wallet)verifierCloses the old credential, opens one for the new wallet. Refused if revoked.
revoke(wallet)verifier or adminSets revoked.
buy(amount)buyerNeeds an unrevoked credential. Pays amount × price_lamports to the treasury, mints amount.
buy_with_attestation(amount, nonce, expiry)buyerSame, plus a verifier-signed pass checked through the Ed25519 precompile.

The buy pass

107 bytes, little-endian, signed by the verifier's ed25519 key:

"voicegate:attest:v1"   19 bytes
program id              32
wallet                  32
nonce                   u64
expiry                  i64, unix seconds
amount cap              u64, token base units

To use it, put two instructions in one transaction, in this order:

  1. An Ed25519 program instruction with ed25519_instruction_data from /attest as its data and no accounts. All its offsets point into its own data.
  2. buy_with_attestation(amount ≤ cap, nonce, expiry), which reads the instruction right before it through the instructions sysvar.

The program refuses the purchase if the pass is signed by another key, names another wallet or program, has expired, or was already used.

Errors

CodeName
6000Unauthorized
6001EpochCapReached
6002CredentialRevoked
6003ZeroAmount
6004MathOverflow
6005MissingAttestation
6006InvalidAttestation
6007AttestationExpired
6008AmountExceedsCap