Skip to main content
An owner can send an item to the brand’s vault. The vault keeps the physical item and confirms it has it with its own tap; the owner keeps ownership. Your page offers the vault the brand chose, the owner approves it with their Endstate wallet, and the request waits until the vault confirms. Each step needs something different:
  • Offering the vault (useCanVault()) needs only a recent tap of the item, not a wallet, so show the prompt as soon as the tap verifies, without waiting for the wallet.
  • Asking to vault (useVault()) needs the tap, which is how the owner shows they hold the item, and the owner’s wallet, which signs the approval.
  • Cancelling (useCancelVault()) needs the wallet that approved the request. A tap is optional: with one, the call also waits until useCanVault() no longer names the request.
Vaulting is enabled per environment; until it is, these calls answer not_found.resource.

The flow

  1. Offer the vault. useCanVault() reads the brand’s default vault for the tapped item and whether it can go there now. Show the prompt only when vaultable is true.
  2. Ask to vault. vault({ vaultId }) has the wallet sign the owner’s approval for that vault and opens the vault request. It reads pending until the vault confirms it has the item, and useCanVault() names it as requestId by the time vault() resolves.
  3. Cancel, if the owner changes their mind. Until the item is vaulted, cancelVault({ requestId }) withdraws the approval from the wallet. It resolves once Endstate sees the cancel, and by then useCanVault() no longer names the request, so the prompt offers the vault again.

What the owner approves

vault() takes the vault id canVault returned, never one you pick. The wallet asks Endstate for the approval to sign, and Endstate builds it from the vault the brand allows, so a page cannot send an item to a vault the brand did not choose. cancelVault() takes the id of the request vault() returns. After a reload, canVault returns the same id as requestId until the item is vaulted, so the owner can still cancel. An item with an open vault request answers vaultable: false, so the prompt does not come back on the next tap until the request is cancelled, rejected or expires.

Outcomes and the wallet

Each action hook returns { status, data, error, reset }, with status "idle" | "pending" | "success" | "error". An outcome belongs to the tap, the wallet and the sign-in it ran for: a new tap, another wallet, a sign-out or a sign-in returns the hook to "idle", and a call still in flight for the old one never lands. useCanVault() stays current through the owner’s own actions, so a page reads one answer. vault() reads eligibility again before it resolves, and cancelVault() reads it until Endstate no longer names the request, which can take a few seconds after the network includes the cancel. Without a tap session there is nothing to read, so cancelVault() resolves once the network included the cancel. If Endstate has not seen the cancel within two minutes, or the read fails, the call still resolves and useCanVault() keeps its last answer; call canVault() again later. The cancel is sent from the owner’s wallet with the cost covered by Endstate; the owner never pays for it. It resolves with { transactionHash, address, resourceId }.

Errors

403
The brand no longer allows that vault. Read canVault again and offer the vault it names.
409
The item already has an open vault request, or is vaulted. While the owner can still cancel the request, canVault names it as requestId.
409
cancelVault() found the request past the point where it can be cancelled: it was cancelled, the vault rejected it, it expired, or the item is vaulted. Nothing was sent.
404
Vaulting is not enabled for this environment.
See Errors for every vault request code.

See also

useVault

The hook that signs the approval and opens the request.

session.vaultRequests

The same calls in @endstate-sdk/core, without a wallet.