Skip to content

Vault operations: collateral balance queries, deposits, withdrawals, and allowance signature workflows.

Reached as sdk.vault on a constructed AnvilSDK instance, which creates its own modules — consumers never call new VaultModule(...). The class is exported type-only so its methods appear in the API reference and so integrators can name the type without reaching into package internals.

Methods

buildDepositAuthorization()

buildDepositAuthorization(params): Promise<VaultDepositAuthorizationDefinition>;

Builds the exact EIP-712 CollateralizableDepositApproval definition without signing it.

Three parties are involved. The account holder signs: the wallet whose tokens will move. The collateralizable contract named in collateralizableAddress submits: it passes the signature to the vault’s depositFromAccount, and no other caller can use it because the vault binds msg.sender into the digest. The vault verifies: it accepts an EOA signature or an ERC-1271 contract signer, consumes the signer’s next deposit-approval nonce, pulls exactly depositAmount of the token from the signer’s wallet, and raises the collateralizable’s vault allowance to cover it. The signer still needs an ERC-20 approval to the vault for that transfer.

The signature carries no deadline. It stays usable until the vault consumes its nonce or the signer invalidates it with VaultModule.buildInvalidateNoncesWorkflow.

Any contract the vault has approved as a collateralizable can be named; nothing here is specific to letters of credit.

Parameters

ParameterTypeDescription
paramsBuildVaultDepositAuthorizationParamsThe collateralizable, token, and exact amount to bind.

Returns

Promise<VaultDepositAuthorizationDefinition>

The inspectable definition: chain, vault, signer, nonce, payload, and wallet-ready typed data.

Throws

InvalidArgumentError If an address is zero or malformed, or an amount or nonce does not fit its EIP-712 integer width.


buildDepositAuthorizationWorkflow()

buildDepositAuthorizationWorkflow(params): Promise<WalletOperationWorkflow>;

Builds a one-step workflow that signs a vault deposit authorization.

The connected account signs; the collateralizable contract submits the resulting bytes to the vault’s depositFromAccount, where the vault verifies them. See VaultModule.buildDepositAuthorization for what the signature permits and how long it stays usable.

Parameters

ParameterTypeDescription
paramsBuildVaultDepositAuthorizationParamsThe collateralizable, token, and exact amount to bind.

Returns

Promise<WalletOperationWorkflow>

A workflow whose single operation yields the signature.

Example

// The account holder signs. The collateralizable contract submits the
// bytes to `depositFromAccount`, and the vault verifies them there.
const workflow = await sdk.vault.buildDepositAuthorizationWorkflow({
collateralizableAddress: collateralizable,
tokenAddress: USDC,
depositAmount: 5_000_000_000n, // exact: the vault rejects any other
});
// Chain, vault, signer, nonce, and typed data, before the wallet prompt.
console.log(workflow.operations[0]?.authorization);
const execution = await workflow.execute();
if (execution.status !== 'executed') {
throw new Error(`deposit preflight ended as ${execution.status}`);
}
const [op] = execution.operations;
if (
op?.status !== WalletOperationStatus.Signed ||
op.signature === undefined
) {
throw new Error('signature not obtained');
}
return op.signature; // -> the collateralizable's deposit entry point

Throws

WorkflowSignerChangedError If the SDK’s configured accountAddress and the connected wallet’s account disagree, or if the signer observed while executing differs from the one observed while building. Rebuild the workflow for the currently connected signer; re-executing the same workflow succeeds only if the original signer reconnects.


buildDepositWorkflow()

buildDepositWorkflow(params): Promise<WalletOperationWorkflow>;

Builds the workflow that deposits tokens into the CollateralVault.

The workflow is assembled from current chain state: one ERC-20 approve step per token whose existing approval is short, followed by a single deposit step covering every token. A fully approved single-token deposit is therefore one operation, and nothing about the shape is fixed — inspect workflow.operations to show the user what they are about to sign, then call workflow.execute().

Call VaultModule.validateDeposit for early form feedback. Building does not imply validity; execute() repeats full validation against fresh state before its first prompt.

Parameters

ParameterTypeDescription
paramsDepositToVaultParamsThe token and amount to deposit.

Returns

Promise<WalletOperationWorkflow>

The workflow to present and execute.

Throws

WorkflowSignerChangedError If the SDK’s configured accountAddress and the connected wallet’s account disagree, or if the signer observed while executing differs from the one observed while building. Rebuild the workflow for the currently connected signer; re-executing the same workflow succeeds only if the original signer reconnects.


buildInvalidateNoncesWorkflow()

buildInvalidateNoncesWorkflow(params): Promise<WalletOperationWorkflow>;

Builds the transaction workflow that revokes exposed vault signatures.

Parameters

ParameterType
paramsInvalidateVaultNoncesParams

Returns

Promise<WalletOperationWorkflow>

Throws

WorkflowSignerChangedError If the SDK’s configured accountAddress and the connected wallet’s account disagree, or if the signer observed while executing differs from the one observed while building. Rebuild the workflow for the currently connected signer; re-executing the same workflow succeeds only if the original signer reconnects.


buildModifyAllowanceAuthorization()

buildModifyAllowanceAuthorization(params): Promise<ModifyVaultAllowanceAuthorizationDefinition>;

Builds the exact EIP-712 vault allowance definition without signing.

Parameters

ParameterType
paramsBuildModifyVaultAllowanceAuthorizationParams

Returns

Promise<ModifyVaultAllowanceAuthorizationDefinition>


buildModifyAllowanceAuthorizationWorkflow()

buildModifyAllowanceAuthorizationWorkflow(params): Promise<WalletOperationWorkflow>;

Builds a one-step workflow that signs a vault allowance authorization.

The definition captures the chain, vault address, signer, and nonce when this method is called. If the workflow is held while the wallet changes chain or signer, execution refuses to sign. If another authorization uses the captured nonce first, rebuild the workflow to resolve the next nonce.

Parameters

ParameterType
paramsBuildModifyVaultAllowanceAuthorizationParams

Returns

Promise<WalletOperationWorkflow>

Throws

WorkflowSignerChangedError If the SDK’s configured accountAddress and the connected wallet’s account disagree, or if the signer observed while executing differs from the one observed while building. Rebuild the workflow for the currently connected signer; re-executing the same workflow succeeds only if the original signer reconnects.


buildModifyAllowanceSignatureWorkflow()

buildModifyAllowanceSignatureWorkflow(params): Promise<WalletOperationWorkflow>;

Builds a workflow that collects an EIP-712 signature adjusting how much a collateralizable contract may reserve from the account’s vault balance. modifyAmount is signed — a negative value revokes.

This costs a signature, not a transaction. The resulting signature can be handed to LOC creation as locAllowanceSignature, which is how a create flow avoids prompting the user twice.

Parameters

ParameterTypeDescription
paramsModifyVaultAllowanceSignatureParamsThe contract, token, and signed amount to apply.

Returns

Promise<WalletOperationWorkflow>

A workflow whose single operation yields the signature.

Example

// Pre-authorize the LOC contract to reserve 5,000 vault-held USDC, then
// reuse the signature on LOC creation so the user is not prompted again.
const vault = sdk.vault;
const allowedContract = await sdk.getContractAddress(
AnvilContract.LetterOfCredit
);
const workflow = await vault.buildModifyAllowanceAuthorizationWorkflow({
allowedContract,
tokenAddress: USDC,
modifyAmount: 5_000_000_000n, // signed: a negative value revokes
});
// Available before execution for consent UI or audit logging.
console.log(workflow.operations[0]?.authorization?.typedData);
const execution = await workflow.execute();
if (execution.status !== 'executed') {
throw new Error(`allowance preflight ended as ${execution.status}`);
}
const [op] = execution.operations;
if (
op?.status !== WalletOperationStatus.Signed ||
op.signature === undefined
) {
throw new Error('signature not obtained');
}
return op.signature; // -> CreateStaticLOCParams.locAllowanceSignature

Throws

WorkflowSignerChangedError If the SDK’s configured accountAddress and the connected wallet’s account disagree, or if the signer observed while executing differs from the one observed while building. Rebuild the workflow for the currently connected signer; re-executing the same workflow succeeds only if the original signer reconnects.

Deprecated

Use VaultModule.buildModifyAllowanceAuthorizationWorkflow.


buildWithdrawWorkflow()

buildWithdrawWorkflow(params): Promise<WalletOperationWorkflow>;

Builds the workflow that withdraws tokens from the CollateralVault back to the account’s wallet.

Only available collateral can be withdrawn; anything reserved against an open LOC has to be freed first by redeeming or cancelling that LOC. The vault’s withdrawal fee (VaultModule.getWithdrawalFeeBasisPoints) is deducted from the amount.

Parameters

ParameterTypeDescription
paramsWithdrawFromVaultParamsThe token and amount to withdraw.

Returns

Promise<WalletOperationWorkflow>

The workflow to present and execute.

Throws

WorkflowSignerChangedError If the SDK’s configured accountAddress and the connected wallet’s account disagree, or if the signer observed while executing differs from the one observed while building. Rebuild the workflow for the currently connected signer; re-executing the same workflow succeeds only if the original signer reconnects.


getCollateralBalance()

getCollateralBalance(params): Promise<CollateralBalance>;

Returns the account’s CollateralBalance for one token in the CollateralVault, split into available and reserved.

reserved is collateral committed to reserving contracts and cannot be withdrawn; available is what a new LOC or a withdrawal can draw on. Read straight from the vault contract, so it reflects chain state rather than the subgraph’s indexed view.

Parameters

ParameterTypeDescription
paramsGetVaultCollateralBalanceParamsThe token, and the account whose balance to read.

Returns

Promise<CollateralBalance>

The available and reserved amounts for that token.

Example

const balance = await sdk.vault.getCollateralBalance({
tokenAddress: WETH,
});
// `reserved` is locked by reserving contracts; only `available` can be
// withdrawn
// or back a new LOC. Withdrawals pay the vault fee, so the wallet
// receives:
const feeBasisPoints = await sdk.vault.getWithdrawalFeeBasisPoints();
const fee = (balance.available * BigInt(feeBasisPoints)) / 10_000n;
const received = balance.available - fee;

Throws

InvalidArgumentError If params.tokenAddress is missing.

Throws

WalletNotConnectedError If params.accountAddress is omitted and no signer is configured to resolve a default.


getCollateralBalances()

getCollateralBalances(params, options?): Promise<CollectionPage<TokenCollateralBalance>>;

Returns every token the account holds collateral in, as a paged CollectionPage.

This one reads the subgraph rather than the vault contract, so the SDK must have been configured with a subgraph URL — it throws otherwise. For a single token, or when you need chain-truth rather than indexed data, use VaultModule.getCollateralBalance.

Parameters

ParameterTypeDescription
paramsGetVaultCollateralBalancesParamsPaging and filter options for the collection.
optionsReadExecutionOptionsCancellation controls for this page read.

Returns

Promise<CollectionPage<TokenCollateralBalance>>

One entry per token the account holds collateral in.

Example

// Every token this account holds in the vault, across all pages.
const balances: TokenCollateralBalance[] = [];
let cursor: string | undefined;
do {
const page = await sdk.vault.getCollateralBalances({ cursor });
balances.push(...page.items);
cursor = page.nextCursor ?? undefined;
} while (cursor);

Throws

ConfigError If neither subgraphUrl nor the configured profile supplies a subgraph endpoint.

Throws

WalletNotConnectedError If params.accountAddress is omitted and no signer is configured to resolve a default.

Throws

ContactSupportError COLLATERAL_BALANCE_TOKEN_NOT_FOUND when an indexed balance names a token that does not resolve on chain.


getCollateralizableAllowance()

getCollateralizableAllowance(params): Promise<bigint>;

Returns how much of one token a collateralizable contract — normally the LetterOfCredit contract — is currently allowed to reserve from the account’s vault balance.

This is the vault-side allowance, distinct from an ERC-20 approval: ERC-20 approval governs moving tokens into the vault, this governs what a contract may reserve once they are there. Raise it with VaultModule.buildModifyAllowanceAuthorizationWorkflow.

Parameters

ParameterTypeDescription
paramsGetVaultCollateralizableAllowanceParamsThe collateralizable contract, token, and account.

Returns

Promise<bigint>

The allowance in the token’s smallest units.


getCollateralReservation()

getCollateralReservation(params): Promise<CollateralReservation | undefined>;

Reads current generic reservation storage from its chain and vault reference. Deleted or unknown reservations return undefined; no product classification or token metadata is inferred.

Parameters

ParameterTypeDescription
paramsGetCollateralReservationParamsFull reservation identity, including an explicitly selected historical vault.

Returns

Promise<CollateralReservation | undefined>

Current reservation facts, or undefined for erased storage.

Example

const reference = loc.origin.originatingCollateralReservation;
if (reference === null) {
// Some legacy origins cannot recover a reservation identity.
console.log('Reservation identity unavailable');
return;
}
const reservation = await sdk.vault.getCollateralReservation({
reference,
});
// The explicit reference selects the original vault. Undefined means
// its current storage is absent, even though indexed history remains.
console.log(reservation);

getCollateralReservations()

getCollateralReservations(params?, options?): Promise<CollateralReservationPage>;

Lists indexed generic reservations in one vault, including inactive identities when no activity filter is given. Continuations retain the original index deployment and block. The current profile vault is the default namespace.

Parameters

ParameterTypeDescription
paramsGetCollateralReservationsParamsVault, account, reserving contract, token, activity and page filters.
optionsReadExecutionOptionsCancellation controls for the whole page.

Returns

Promise<CollateralReservationPage>

One complete page with index provenance.

Example

const filters = {
accountAddress,
collateralContractAddress,
active: true,
};
let page = await sdk.vault.getCollateralReservations(filters);
const reservations: CollateralReservation[] = [...page.items];
while (page.nextCursor !== null) {
page = await sdk.vault.getCollateralReservations({
...filters,
cursor: page.nextCursor,
});
reservations.push(...page.items);
}
// Group by chain, vault, account, token and reserving contract.
// A reserving contract's address does not by itself identify its
// product.
const allocations = deriveCollateralAllocations(reservations);
console.log(page.indexedAt, allocations);

getWithdrawalFeeBasisPoints()

getWithdrawalFeeBasisPoints(params?): Promise<number>;

Returns the CollateralVault’s current withdrawal fee, in basis points (200 means 2%).

The fee is taken out of the amount withdrawn, so a withdrawal returns less than it asks for. Quote it to the user before they sign.

Parameters

ParameterTypeDescription
paramsGetVaultWithdrawalFeeBasisPointsParamsOptional owning vault; defaults to the profile’s current vault.

Returns

Promise<number>

The withdrawal fee in basis points.


validateAllowance()

validateAllowance(params, signal?): Promise<ValidationIssue[]>;

Validates that the vault’s collateralizable allowance already covers a required token amount.

Unlike the other validate* methods this one does not gate a matching build*Workflow call. It is the allowance-sufficiency check that vault and LOC workflows compose internally, exposed here so a headless caller can run it standalone — for example to decide whether a create flow will need an allowance signature before it starts.

Parameters

ParameterTypeDescription
paramsPartial<VaultAllowanceValidationParams>The contract, token, and amount that must be covered.
signal?AbortSignal-

Returns

Promise<ValidationIssue[]>

The issues found: empty means checked and valid — a rule whose own required field is absent reports FieldRequired rather than being silently skipped, so empty never means “nothing could run.” Non-empty means domain-invalid. Never partial — an infrastructure failure rejects instead of resolving.

Throws

The same failure modes as runValidation: an existing typed SDK error propagates unchanged, a recognizable provider failure becomes ProviderConnectionError, an unclassifiable failure becomes ContactSupportError, and caller abort rejects with the signal’s exact reason.


validateDeposit()

validateDeposit(params, signal?): Promise<ValidationIssue[]>;

Validates deposit parameters without touching the wallet: token address and amount format, and that the wallet holds the total being deposited.

ERC-20 approval is deliberately not checked. The workflow builder adds an approve step when one is needed, so failing validation on it would block a submission that would have succeeded.

Parameters

ParameterTypeDescription
paramsPartial<DepositToVaultParams>The partial deposit parameters to check.
signal?AbortSignal-

Returns

Promise<ValidationIssue[]>

The issues found: empty means checked and valid — a rule whose own required field is absent reports FieldRequired rather than being silently skipped, so empty never means “nothing could run.” Non-empty means domain-invalid. Never partial — an infrastructure failure rejects instead of resolving.

Throws

The same failure modes as runValidation: an existing typed SDK error propagates unchanged, a recognizable provider failure becomes ProviderConnectionError, an unclassifiable failure becomes ContactSupportError, and caller abort rejects with the signal’s exact reason.


validateDepositAuthorization()

validateDepositAuthorization(params, signal?): Promise<ValidationIssue[]>;

Validates a deposit authorization before resolving its nonce.

Parameters

ParameterType
paramsPartial<BuildVaultDepositAuthorizationParams>
signal?AbortSignal

Returns

Promise<ValidationIssue[]>

The issues found: empty means checked and valid — a rule whose own required field is absent reports FieldRequired rather than being silently skipped, so empty never means “nothing could run.” Non-empty means domain-invalid. Never partial — an infrastructure failure rejects instead of resolving.

Throws

The same failure modes as runValidation: an existing typed SDK error propagates unchanged, a recognizable provider failure becomes ProviderConnectionError, an unclassifiable failure becomes ContactSupportError, and caller abort rejects with the signal’s exact reason.


validateInvalidateNonces()

validateInvalidateNonces(params, signal?): Promise<ValidationIssue[]>;

Validates the monotonic and bounded vault nonce-invalidation target.

Parameters

ParameterType
paramsPartial<InvalidateVaultNoncesParams>
signal?AbortSignal

Returns

Promise<ValidationIssue[]>

The issues found: empty means checked and valid — a rule whose own required field is absent reports FieldRequired rather than being silently skipped, so empty never means “nothing could run.” Non-empty means domain-invalid. Never partial — an infrastructure failure rejects instead of resolving.

Throws

The same failure modes as runValidation: an existing typed SDK error propagates unchanged, a recognizable provider failure becomes ProviderConnectionError, an unclassifiable failure becomes ContactSupportError, and caller abort rejects with the signal’s exact reason.


validateModifyAllowanceAuthorization()

validateModifyAllowanceAuthorization(params, signal?): Promise<ValidationIssue[]>;

Validates an allowance authorization before resolving its nonce.

Parameters

ParameterType
paramsPartial<BuildModifyVaultAllowanceAuthorizationParams>
signal?AbortSignal

Returns

Promise<ValidationIssue[]>

The issues found: empty means checked and valid — a rule whose own required field is absent reports FieldRequired rather than being silently skipped, so empty never means “nothing could run.” Non-empty means domain-invalid. Never partial — an infrastructure failure rejects instead of resolving.

Throws

The same failure modes as runValidation: an existing typed SDK error propagates unchanged, a recognizable provider failure becomes ProviderConnectionError, an unclassifiable failure becomes ContactSupportError, and caller abort rejects with the signal’s exact reason.


validateModifyAllowanceSignature()

validateModifyAllowanceSignature(params, signal?): Promise<ValidationIssue[]>;

Validates the parameters of an allowance-signature request before prompting the user to sign. collateralContractAddress selects the vault that owns both the nonce and EIP-712 domain; omission selects the profile vault. Pass the original vault explicitly when validating a historical vault authorization after the profile has moved.

Parameters

ParameterTypeDescription
paramsPartial<VaultAllowanceSignatureValidationParams>The partial signature parameters to check.
signal?AbortSignal-

Returns

Promise<ValidationIssue[]>

The issues found: empty means checked and valid — a rule whose own required field is absent reports FieldRequired rather than being silently skipped, so empty never means “nothing could run.” Non-empty means domain-invalid. Never partial — an infrastructure failure rejects instead of resolving.

Throws

The same failure modes as runValidation: an existing typed SDK error propagates unchanged, a recognizable provider failure becomes ProviderConnectionError, an unclassifiable failure becomes ContactSupportError, and caller abort rejects with the signal’s exact reason.


validateWithdraw()

validateWithdraw(params, signal?): Promise<ValidationIssue[]>;

Validates withdrawal parameters without touching the wallet: token address format, a non-negative amount when one is given, and destination address format when one is given. Zero is not rejected — it is a well-formed request for a withdrawal of nothing.

It does not check that the amount is actually available rather than held by a reserving contract — compare against VaultModule.getCollateralBalance yourself before submitting.

Parameters

ParameterTypeDescription
paramsPartial<WithdrawFromVaultParams>The partial withdrawal parameters to check.
signal?AbortSignal-

Returns

Promise<ValidationIssue[]>

The issues found: empty means checked and valid — a rule whose own required field is absent reports FieldRequired rather than being silently skipped, so empty never means “nothing could run.” Non-empty means domain-invalid. Never partial — an infrastructure failure rejects instead of resolving.

Throws

The same failure modes as runValidation: an existing typed SDK error propagates unchanged, a recognizable provider failure becomes ProviderConnectionError, an unclassifiable failure becomes ContactSupportError, and caller abort rejects with the signal’s exact reason.