Sponsored Vault
A sponsored vault is a normal single-tenant ACTA vault deployed through `deploy_sponsored` on the vc-vault-factory contract. The sponsor invokes the factory and must satisfy Soroban auth (sponsor.require_auth()); the owner is the vault admin and does not sign this transaction. Use this when an organization pays fees or orchestrates onboarding while the end user only receives the vault.
For comparison, POST /contracts/vault/create prepares the owner's own factory deploy, where the owner typically signs. The sponsored flow uses POST /contracts/sponsored-vault/create; the invoke must satisfy on-chain auth for sponsor - in practice the prepared XDR is usually signed by the sponsor account (see sourcePublicKey below).
Concept
| Role | Responsibility |
|---|---|
| Sponsor | Signs the transaction. Pays network/fees like any invoke. |
| Owner | Receives the vault; address stored as vault admin; didUri stored for the vault. |
Open sponsorship, on-chain and over HTTP: on the contract, any sponsor address may call deploy_sponsored for an owner (subject to Stellar/Soroban auth and fees) - there is no sponsor allowlist and no open-to-all toggle. The ACTA API route matches that: any standard API key can sponsor, paying with its own wallet.
The factory derives the vault address deterministically from (factory, owner, userSalt), so a sponsored deploy and a self-service deploy for the same owner + salt resolve to the same vault. Calling deploy again for an owner that already has a vault at that salt fails on-chain (already deployed).
On success the factory emits a vault-deployed event with the sponsor, owner, and did_uri.
On-chain (vc-vault-factory)
The relevant factory entrypoint is:
| Function | Auth | Description |
|---|---|---|
deploy_sponsored(deployer, owner, did_uri, user_salt) | Deployer (sponsor) | Deterministically deploys the owner's vault if not already deployed at that salt. |
The API's sponsor request field maps to the contract's deployer parameter.
Public HTTP: the ACTA API documents only `POST /contracts/sponsored-vault/create` (prepare/submit for deploy_sponsored).
HTTP API
This route accepts any standard API key (X-ACTA-Key header) and is rate limited per key. Prefix paths with your network base URL (e.g. https://sandbox-api.acta.build).
You can only sponsor with your own account. sponsor must be the wallet_address linked to your API key, and sourcePublicKey, when sent, must be that same address; anything else returns 403. A key with no linked wallet also returns 403. The owner is deliberately unrestricted: paying for somebody else's vault is the whole point of the endpoint.
POST /contracts/sponsored-vault/create
Prepares or submits deploy_sponsored.
Prepare body:
{
"sponsor": "G...",
"owner": "G...",
"didUri": "did:stellar:...",
"userSalt": "00...00",
"sourcePublicKey": "G..."
}- sponsor (required): Stellar address passed to the factory as the sponsor (must satisfy
sponsor.require_auth()when the transaction is signed and submitted). - owner (required): Vault owner (
G...). - didUri (required): DID URI stored for the vault.
- userSalt (optional): 32-byte salt selecting the owner's vault; defaults to 32 zero bytes (one canonical vault per owner).
- sourcePublicKey (required): Stellar account used as the transaction source when the API prepares the XDR, which makes it the account that pays the network fee. For standard keys it must equal
sponsor, so the sponsor is always both the authorizing and the paying account.
Submit body: { "signedXdr": "AAAA..." }
Responses: Prepare returns { "xdr", "network" }; Submit returns { "tx_id" }.
Prepare / submit
This write endpoint follows the standard two-step flow:
- Prepare - JSON with operation fields (no
signedXdr) returnsxdr+networkpassphrase. - Sign - Stellar wallet signs the XDR so the sponsor's auth requirements are met.
- Submit - POST the same path with
{ "signedXdr" }returnstx_id.
Operational notes
- Avoid calling create when the owner already has a vault at the chosen
userSalt; the on-chain deploy fails if the vault already exists. Prefer an on-chain or API read of vault existence first (see vault read operations). - The vault address is deterministic, so it can be claimed first. Because
(factory, owner, userSalt)fixes the address and sponsorship is open, anyone can deploy an owner's canonical vault before the owner does, with adidUriof their choosing. This is not a takeover: the constructor stores the owner as both vault owner and vault admin, andset_vault_didrequires the owner's auth, so the owner can correct the DID. What it does mean is that an owner's own deploy can fail because the address is already taken, and that a vault's initialdidUriis only as trustworthy as whoever deployed it. Readvault_didand confirm it before treating it as the owner's. - Issuance fees are charged on-chain by the vault (via the factory's
quote_fee) and paid by the issuer at issuance time, independently of who sponsored the vault deploy.