XvP settlement flows
Create, approve, execute, and monitor XvP settlement flows through DALP APIs, SDKs, CLI commands, and polling.
XvP settlement flows
XvP settlements coordinate multiple value-transfer legs between participants. Use this flow to create a settlement, collect approvals, execute the local DALP-managed leg, reconcile external legs, or recover funds.
An XvP settlement is an atomic same-chain swap. The settlement contract and every leg it settles live on one chain, so all legs either complete together or none do. To coordinate value on another chain, model it as an external flow that your integration verifies separately, not as a cross-chain settlement DALP executes.
DALP exposes XvP through the Platform API, the SDK, and the CLI. The API and SDK share the same settlement model. Integrations can create settlements programmatically and reconcile them through the platform UI or CLI.
For external-flow settlements, DALP does not operate a bridge, relay messages, or move assets on another chain. It does not prove that another chain executed. DALP records the external-chain leg, requires a secret or hashlock, and exposes fields your integration can compare with evidence from the external EVM chain.
When to use this flow
Use an XvP settlement when your system has the XvP settlement add-on factory available.
A valid XvP settlement has at least one local on-chain flow managed by the active DALP system. Use this page when participants need to approve the settlement before execution, or when your integration must track approval, cancellation, execution, withdrawal, or secret-reveal state.
Do not use XvP documentation as a substitute for the API Reference. Use the API Reference for exact request and response fields, and the CLI Command Reference for command syntax.
Create a settlement
Create a settlement with the XvP add-on factory address, a name, a future cutoff date, and an array of flows. Each flow specifies an asset address, a sender, a recipient, and a transfer amount.
DALP supports two flow types:
| Flow type | What it represents | Extra fields |
|---|---|---|
local | A transfer leg on the active DALP-managed chain. | No extra fields beyond the core transfer fields. |
external | A reference to a transfer leg that your integration verifies outside the active DALP-managed chain. | External chain ID and external asset decimals. |
Every settlement must include at least one local flow. The factory address must belong to an XvP settlement add-on registered for the active system. If any flow is external, provide either a raw secret or a precomputed hashlock. Local-only settlements do not require a secret or hashlock.
An external flow is a reconciliation reference. Set externalChainId to a different EVM chain from the active DALP chain. The asset address, party addresses, amount, and decimal precision must match the evidence your integration checks on that external chain. DALP stores those fields and gates local execution with the hashlock. DALP does not submit, guarantee, or roll back the external-chain transaction.
For systems using the current XvP settlement factory identity model, include the ISO 3166-1 numeric country code required by the factory.
const created = await client.addons.xvp.create({
body: {
factoryAddress: "0xFACTORY",
name: "Primary sale settlement",
autoExecute: false,
cutoffDate: new Date("2026-06-30T17:00:00Z"),
country: 756,
flows: [
{
type: "local",
assetId: "0xASSET",
from: "0xSENDER",
to: "0xRECIPIENT",
amount: "1000000",
},
],
walletVerification,
},
});
if (!("data" in created)) {
throw new Error(`Settlement creation is still processing: ${created.statusUrl}`);
}
const settlementAddress = created.data.settlementId;The create response returns the queued transaction hash and the settlement contract address after DALP resolves the created settlement. When you provide a raw secret, DALP stores the encrypted secret so authorized decrypt flows can retrieve it later; when you provide only a hashlock, your integration keeps the matching secret.
Approve and execute a settlement
After creation, participants can list settlements and submit approvals from their own wallet context. The list operation applies participant visibility. The read operation fetches a known settlement by address within the active system and chain; it is not restricted to the caller's participant membership, so do not treat read as a participant-visibility check.
const settlements = await client.addons.xvp.list({
query: { page: { limit: 10, offset: 0 } },
});
const approval = await client.addons.xvp.approve({
body: { settlementAddress, walletVerification },
});Settlement approval may chain token allowance transactions before the settlement approval itself. The API runs the whole chain as one operation. By default the approve request returns 202 Accepted with a statusUrl that covers every transaction in the chain. Poll it until the operation reaches a terminal state. Sending Prefer: wait=N (RFC 7240) waits for the whole chain synchronously instead; when the wait budget elapses first, the response degrades to the same 202 handle. The SDK sends Prefer: wait=99 by default, so SDK calls like the example above complete synchronously in most cases.
Allowances that are already in place are skipped. Repeating an approve request while a previous one is still processing attaches to the running operation instead of starting a new one. Read the settlement after the approval flow completes.
const settlement = await client.addons.xvp.read({
params: { settlementAddress },
});
console.log(settlements.meta.total, settlement.data.userApproved);The read response exposes:
- approval status for the current user,
- each recorded approval account and timestamp,
- terminal state flags (executed, cancelled, withdrawn, secret-revealed),
- caller-visible stored-secret presence for external-flow settlements,
- flow details and their local or external status.
When the settlement is ready, execute it:
await client.addons.xvp.execute({
body: { settlementAddress, walletVerification },
});A participant who needs to back out before execution revokes their approval. A participant who wants to halt the settlement entirely submits a cancellation. Use revokeApproval to withdraw an individual approval:
await client.addons.xvp.revokeApproval({
body: { settlementAddress, walletVerification },
});Use cancel when the settlement should not proceed:
await client.addons.xvp.cancel({
body: { settlementAddress, walletVerification },
});Use withdraw-cancel to withdraw a cancellation proposal before the final cancellation state. Use withdraw-expired for expired settlement recovery.
Verify an external-flow settlement
An external-flow settlement combines at least one DALP-managed local leg with one or more external references. DALP records each external leg's chain, asset reference, and party addresses, along with the amount, hashlock, and secret-reveal state. Your integration uses that record to reconcile the local settlement against matching external-chain evidence.
This boundary is important: DALP does not submit, relay, or guarantee the external transfer. A revealed secret only shows that the hashlock gate for the DALP-managed settlement was satisfied. Your system must still verify the matching external execution with the venue, chain, or workflow that handles that leg.
Treat the external leg as evidence to verify, not as a DALP-managed execution path. The external route may be an HTLC, bridge, exchange, custody workflow, or another controlled settlement process chosen outside DALP. The DALP read response shows the local record and local hashlock secret state. The response does not prove that the external route is safe or that a third-party venue completed its side correctly. Check that evidence before approval, reveal, execution, or recovery.
Read the settlement, then inspect its flow fields against the external chain:
const settlement = await client.addons.xvp.read({
params: { settlementAddress },
});
for (const flow of settlement.data.flows) {
if (flow.isExternal) {
console.log(flow.externalChainId, flow.asset?.id, flow.from.id, flow.to.id, flow.amountExact);
}
}
console.log(
settlement.data.hashlock,
settlement.data.hasStoredSecret,
settlement.data.secretRevealed,
settlement.data.secretRevealTx
);Match each external flow against evidence on the external EVM chain:
| Response field | How to use it |
|---|---|
flow.isExternal | Marks a leg that DALP tracks as an external-chain leg. |
flow.externalChainId | Names the external EVM chain for your verification check. |
flow.asset?.id | Holds the asset address recorded for the leg. |
flow.from.id and flow.to.id | Specify the sender and recipient addresses that your external-chain evidence must confirm. |
flow.amountExact | Contains the base-unit amount your external-chain evidence must confirm. |
hashlock | Holds the settlement hashlock that your external-chain evidence or HTLC path must satisfy. |
hasStoredSecret | Shows caller-scoped stored-secret presence for external-flow settlements. The flag is visible to the creator and leg participants. |
secretRevealed and secretRevealTx | Show whether the hashlock secret has been revealed on the DALP-managed chain; they do not prove the external leg executed. |
Proceed only when the local approvals are complete and the matching external-chain settlement or evidence agrees with the recorded external flow. If the matching side cannot be verified before the cutoff date, use cancellation or expired-settlement recovery instead of forcing execution.
Secret and hashlock handling
External-flow settlements require either a raw secret or a hashlock when they are created.
- If you provide a raw secret, DALP derives the hashlock and stores the encrypted secret for later retrieval.
- If you provide a hashlock, your integration is responsible for managing the matching secret.
- Treat
hasStoredSecretas a caller-scoped visibility flag for external-flow reads, not as decrypt authorisation or as a universal test for whether decrypt can succeed. - A creator can use decrypt to retrieve a stored secret through the API. Other participants may see that a secret exists, but they should obtain the secret through the agreed counterparty channel or after it is revealed on-chain.
- Use the reveal-secret operation to publish the secret for hashlock-based settlement completion when that path applies.
Local-only settlements do not use hashlock enforcement. When a local-only settlement was created with a raw secret, the creator may still use decrypt to retrieve the stored secret through the API.
Monitor settlement state
XvP integrations reconcile settlement state through the list and read endpoints. The list endpoint is the polling surface for settlement collections.
Use collection pagination, global search, and filters for name, cutoffDate, participant, systemAddon, and createdAt. Use the read endpoint when you already know the settlement address and need its current approval records, flow details, and terminal flags.
const page = await client.addons.xvp.list({
query: {
limit: 25,
offset: 0,
sortBy: "createdAt",
sortDirection: "desc",
filters: [
{ id: "participant", operator: "eq", value: "0xPARTICIPANT" },
{ id: "systemAddon", operator: "eq", value: "0xXVPADDON" },
],
},
});
for (const item of page.data) {
const detail = await client.addons.xvp.read({
params: { settlementAddress: item.id },
});
if (detail.data.executed || detail.data.cancelled || detail.data.withdrawn) {
continue;
}
// Continue approval, reveal, execution, cancellation, or expiry handling.
}Treat the indexed payload as your checkpoint. The indexer records these XvP events before the API exposes them:
- creation,
- approval and approval revocation,
- execution,
- cancellation and cancel votes,
- expiry withdrawal,
- secret reveal.
A transaction can be final on-chain before the latest indexed state appears in the list response. Poll the list or read endpoint until the expected flag, approval row, or secret-reveal metadata appears.
Do not wait for a webhook when your integration needs the current XvP state. Use collection filtering and read polling as the stable reconciliation path. Webhook endpoints are available for selected DALP event delivery.
CLI coverage
The DALP CLI covers XvP settlement creation, reads, and the full lifecycle under dalp xvp-settlements:
dalp xvp-settlements list
dalp xvp-settlements read 0xSETTLEMENT
dalp xvp-settlements create --factory-address 0xFACTORY --name "Primary sale settlement" --cutoff-date 2026-06-30T17:00:00Z --flows '[{"type":"local","assetId":"0xASSET","from":"0xSENDER","to":"0xRECIPIENT","amount":"1000000"}]'
dalp xvp-settlements approve 0xSETTLEMENT
dalp xvp-settlements revoke-approval 0xSETTLEMENT
dalp xvp-settlements execute 0xSETTLEMENT
dalp xvp-settlements cancel 0xSETTLEMENT
dalp xvp-settlements withdraw-cancel 0xSETTLEMENT
dalp xvp-settlements withdraw-expired 0xSETTLEMENT
dalp xvp-settlements decrypt 0xSETTLEMENT
dalp xvp-settlements reveal-secret --address 0xSETTLEMENT --secret "shared-secret-value-at-least-32-chars"The CLI create command accepts the factory address, name, cutoff date, and flows JSON. Use the API or SDK for creation scenarios that require a V3 country code, a raw secret, or a precomputed hashlock.
Error codes
XvP operations return a stable DALP-NNNN identifier when a request cannot proceed. Map the code your integration receives to the fix below before retrying, so a settlement client recovers from the right step instead of re-sending the same request. For the full catalog with HTTP status and retryability per code, see the Platform API error reference.
Creation rejects a request before it queues any transaction. The table below lists the codes returned when the flows or factory are not ready to settle.
| Error code | When it happens | What to do |
|---|---|---|
DALP-0062 | The settlement includes an external flow, so a secret or precomputed hashlock is required to coordinate it. | Provide a settlement secret or a valid hashlock in the create request. |
DALP-0061 | The hashlock supplied for a cross-chain settlement is not a 0x-prefixed hex string. | Send a 0x-prefixed hashlock, or provide the secret so the API derives the hashlock. |
DALP-0064 | The selected XvP factory version requires an ISO 3166-1 numeric country code. | Include a valid country code in the create request. |
DALP-0063 | The factory address is missing from the active system's index of XvP settlement add-ons. | Use an installed XvP factory address, or retry after add-on indexing catches up. |
DALP-0431 | The creation transaction was confirmed on-chain, but the indexer did not produce the settlement row in time. | Poll the settlement list or read endpoint with the settlement address after a short delay. If you must retry the create request, reuse the original Idempotency-Key so the queue deduplicates the request instead of enqueueing a second factory create. |
Approval and signing apply the recorded settlement roles. A request from the wrong wallet or session fails before submission:
| Error code | When it happens | What to do |
|---|---|---|
DALP-0069 | The caller is not the local sender recorded for the settlement flow. | Approve from the wallet that is the local sender for this settlement. |
DALP-0072 | The authenticated user has no wallet id available for signing the settlement message. | Complete wallet onboarding, refresh the session, then retry. |
DALP-0071 | The submitted signature payload is not a 0x-prefixed hex value. | Sign the settlement message again and submit the hex-encoded signature. |
DALP-0070 | The caller has not approved the settlement yet, or the approval is still indexing. | Approve the settlement first, or retry after indexing catches up. |
DALP-0073 | The wallet signing service failed while signing the settlement message. | Retry after a short backoff. If signing keeps failing, contact support with the request id. |
Read, list, and secret handling return a code when the settlement, wallet filter, or stored secret cannot be resolved for the caller, or when a secret operation does not apply to the target settlement:
| Error code | When it happens | What to do |
|---|---|---|
DALP-0068 | The settlement address is missing from the active system's index. | Verify the settlement address, or retry after indexing catches up. |
DALP-0065 | A list request ran against a system that has no indexed XvP settlement add-on. | Install the XvP settlement add-on, or retry after add-on indexing catches up. |
DALP-0067 | A list request needs a participant wallet filter and the session has no wallet to use as the default. | Provide a participant wallet filter, or complete wallet onboarding. |
DALP-0066 | A systemAddon filter referenced an add-on address that is not part of the active system. | Filter on an XvP add-on address that belongs to the active system. |
DALP-9078 | A participant other than the settlement creator tried to store the settlement secret. | Ask the participant who created the settlement to store the secret. |
DALP-0615 | A reveal-secret request targeted a local-only settlement, which never uses hashlock reveal. | Skip the reveal call for local-only settlements, or target an external-flow settlement instead. |
DALP-0059 | The settlement exists but its encrypted secret payload is missing from secret storage. | Confirm the secret was created for this settlement before requesting decryption. |
DALP-0060 | The stored secret was encrypted with a method this Platform API version does not support. | Recreate the settlement secret with the supported encryption method. |
DALP-0007 | The encrypted secret could not be decrypted with the caller's current wallet signature. | Decrypt with the original wallet credentials used when the secret was created. |
An XvP settlement is an atomic same-chain swap: the settlement contract and every leg it settles must live on one chain. Operating an existing settlement returns a code when its legs do not resolve to the chain you submit the request from:
| Error code | When it happens | What to do |
|---|---|---|
DALP-9165 | An existing settlement resolves on the request chain, but none of its legs do, so it cannot settle as one atomic swap. | Recreate the settlement with every leg and the settlement contract on the same chain, then submit it from that chain. |
This code applies to operations on an existing settlement: read, approve, execute, cancel, revoke approval, store or reveal secret, withdraw a cancellation, and withdraw an expired settlement. Creation never returns it, because each create deploys the settlement and all its legs together on one chain. The same-chain rule is independent of external flows: an external-flow settlement still keeps its local leg and settlement contract on the active DALP-managed chain and references the other leg with externalChainId for your integration to verify.
Most XvP codes are client-correctable: fix the request and resend. The DALP-0061 to DALP-0064, DALP-0066, DALP-0067 to DALP-0072, DALP-0615, and DALP-9078 codes all flag a request that needs a change before it can succeed.
A few codes clear on a later attempt instead. DALP-0063, DALP-0065, and DALP-0068 resolve on their own once add-on or settlement indexing catches up, so a short retry after a recent on-chain change is safe. DALP-0431 and DALP-0073 signal a transient dependency failure: the indexer has not yet resolved a confirmed settlement, or the signing service failed mid-request. Wait for a short backoff, send the request again, and contact support with the request id if it keeps failing.
Related references
Token sale offering API and CLI flow
Create, configure, activate, buy, finalize, and settle a token sale offering through DALP APIs, SDK methods, and CLI commands.
Trading Venue API flow
Read venue markets, calendars, and market data, place signed orders and quoting batches, manage watchlists, stream live depth, and administer markets, bands, participants, busts, and desk limits through the DALP v2 API.