OptionalexistingWalletId?: stringOptionallabel?: stringLabel for a newly-created vault wallet; ignored when existingWalletId is
given (that wallet already has a name we cannot change — Utila has no
rename). Defaults to the entity's display name.
This is the label only: CUSTODIAL_WALLET_NAME_PREFIX is always applied on top, so an operator cannot mint a wallet that reads as a sweep wallet in a shared vault.
Operator-supplied because an entity being given a replacement wallet cannot reuse the retired one's name while that wallet still exists, and only the operator knows what distinguishes this generation.
Soft-delete or restore a custodial wallet, mirroring the transition onto the Utila wallet by archiving / un-archiving it.
The DB write comes first, deliberately. Archiving first and then failing the update would leave a wallet archived in the vault but still live in CFX. In this order the worst case is the benign one — hidden in CFX, still un-archived in the vault — which a retry fixes.
The Utila call is best-effort. It runs after a committed DB write, so
there is nothing to roll back, and a vault outage must not stop an operator
retiring a wallet. Reported as archiveFailed rather than swallowed, so the
caller can say "hidden, but not yet archived" instead of a clean success.
ProtectedentityThe wallet owner's display name — the identity's full name for a person,
the organization's name for a business. Built here rather than inlined
because it is needed twice: once in the projection and once in the q
predicate (Postgres can't reference a select alias from WHERE).
Asset balances for one custodial wallet, or — with walletId omitted — for
every wallet in the custody vault in a single call.
The vault-wide form is what makes balances affordable on the list page:
each returned row carries its own walletId, so one request covers a whole
page of wallets instead of one request per row.
Returns a functional error rather than throwing, because a custody-vault
outage must degrade the balance column to "unavailable" without taking down
a page whose other columns are pure DB reads. An unconfigured stage fails
inside token signing rather than at the API, so everything is caught, not
just UtilaError.
Balances are NOT paginated through here: the vault-wide query can span many
wallets, so the caller gets hasMore and decides. Rendering a partial set
silently would be a wrong number presented as a right one.
Optionalargs: { pageSize?: number; walletId?: string }
OptionalpageSize?: numberOptionalwalletId?: stringOmit to query every wallet in the vault.
OptionalcreatedAt?: DbTimestampCriteriaOptionalcustomerIds?: string[]OptionalentityIds?: string[]OptionalentityTypes?: ("PERSON" | "BUSINESS")[]Narrow to wallets owned by people (identity_id) or by businesses
(organization_id). Distinct from entityIds, which names specific
entities — this is the "all people" / "all businesses" cut.
Optionalids?: string[]OptionalincludeDeleted?: booleanInclude soft-deleted wallets. Off by default so every caller that forgets it gets the live set. Admin-only: the consumer service has no such flag, because a deleted wallet is precisely one a customer must not see.
OptionalorderBy?: DbOrderByCriterion<Optionalpage?: numberDefaults to 1
OptionalpageSize?: numberDefaults to 10
Optionalq?: stringCase-insensitive substring over the Utila wallet id, the owning customer's name, the entity's name, and the derived addresses — an operator most often arrives holding an address off a block explorer and needs the wallet it belongs to.
OptionalupdatedAt?: DbTimestampCriteriaHow many chains a fully-derived custodial wallet has addresses on — the denominator for "3 chains" on a list row, which is otherwise unjudgeable.
Comes from the client's supported-chain set, a pure function of the vault env (22 chains on prod, 7 on dev) needing no credentials and no network.
How many of a customer's custodial wallets are live, and how many are hidden.
One scan with FILTER aggregates rather than two
searchcalls: the deleted count is only meaningful next to the live one — "2, 1 deleted" is a single fact about the customer, so it should cost a single round trip. Exact, unlike counting a capped page.