Annullare uno scambio

Quattro istruzioni restituiscono i fondi senza eseguire il regolamento: Reclaim, Cancel e Reject mentre lo scambio è aperto, e Recover per un deposito che arriva dopo la chiusura. Nessuna di esse controlla la scadenza. Un escrow congelato o un mint modificato possono comunque bloccare una leg, come descritto nelle note finali.

IstruzioneFirmatarioAmbitoStato dello scambio dopo
ReclaimDvpuser_a o user_bLa leg del firmatarioAncora aperto
CancelDvpAutorità di regolamentoEntrambe le legChiuso
RejectDvpuser_a o user_bEntrambe le legChiuso
RecoverDvpuser_a o user_bLa leg del firmatario, dopo la chiusuraGià chiuso

In ogni caso l'escrow viene svuotato di tutto ciò che contiene a favore della parte della leg: l'escrow A verso il token account di user_a per mint_a, l'escrow B verso quello di user_b per mint_b, indipendentemente da chi lo ha finanziato. Il program account memo viene fornito per gli account di rimborso che richiedono un memo.

Questa pagina prosegue dai passaggi precedenti: il client e i firmatari di crea uno scambio, userAAtaA e userBAtaB da finanzia le leg, e MEMO_PROGRAM_ID e authority da regola lo scambio restano validi.

Recuperare una leg

Reclaim restituisce la leg del firmatario e lascia aperto lo scambio, così la leg può essere finanziata di nuovo. Usalo quando il problema riguarda la leg della controparte; Cancel e Reject chiudono l'intero scambio.

import { MEMO_PROGRAM_ADDRESS } from "@solana-program/memo";
import { getReclaimDvpInstruction } from "./dvp";
// The asset-leg party takes its asset back.
const reclaimInstruction = getReclaimDvpInstruction({
signer: userASigner,
swapDvp,
mint: mintA,
dvpSourceAta: escrowA,
signerDestAta: userAAtaA,
tokenProgram: tokenProgramA,
memoProgram: MEMO_PROGRAM_ADDRESS,
});
await client.sendTransaction([reclaimInstruction]);

Annullare o rifiutare

Cancel è firmata dall'autorità di regolamento e Reject da una qualsiasi delle parti. Entrambe rimborsano alla parte della leg tutto ciò che ogni escrow contiene e chiudono il record e entrambi gli escrow, con la rent degli account chiusi che va al firmatario. Le due istruzioni usano gli stessi account; cambia solo il firmatario.

import { getCancelDvpInstruction, getRejectDvpInstruction } from "./dvp";
const unwindAccounts = {
swapDvp,
mintA,
mintB,
dvpAtaA: escrowA,
dvpAtaB: escrowB,
userAAtaA,
userBAtaB,
tokenProgramA,
tokenProgramB,
memoProgram: MEMO_PROGRAM_ADDRESS,
legAExtrasCount: 0,
};
// Signed by the settlement authority:
const cancelInstruction = getCancelDvpInstruction({
settlementAuthority: authoritySigner,
...unwindAccounts,
});
// Or signed by either party:
const rejectInstruction = getRejectDvpInstruction({
signer: userBSigner,
...unwindAccounts,
});

Gli account di rimborso (userAAtaA, userBAtaB) devono esistere per ogni leg che contiene un saldo; un account di rimborso non inizializzato fa fallire il trasferimento di token e annulla l'istruzione. Una leg mai finanziata non richiede alcun trasferimento e tollera un account mancante.

Recuperare un deposito tardivo

Settle, Cancel e Reject chiudono entrambi i token account di escrow, quindi un semplice trasferimento verso un escrow chiuso fallisce. Un deposito arriva dopo la chiusura solo se qualcosa ricrea prima l'escrow, ad esempio una transazione di finanziamento che includa un'istruzione create-idempotent associated token account prima del trasferimento e che fosse in corso quando la controparte ha inviato Reject. I token restano quindi in un escrow il cui scambio non esiste più: il record non c'è più, quindi Reclaim non può trovarlo, e il tombstone del nonce impedisce di creare un nuovo scambio allo stesso indirizzo e di intercettare il deposito.

Per usare RecoverDvp, la parte della leg fornisce gli input originali del seed (settlement authority, entrambe le parti, entrambi i mint, nonce). Il programma ricalcola l'indirizzo del record, richiede il relativo tombstone come prova che lo scambio sia esistito, svuota l'escrow nel token account del firmatario e lo chiude, restituendo la rent dell'escrow al firmatario. La leg del firmatario è determinata da quale parte firma: mint_a per user_a, mint_b per user_b.

import { getAddressEncoder, getProgramDerivedAddress } from "@solana/kit";
import { DVP_SWAP_PROGRAM_PROGRAM_ADDRESS, getRecoverDvpInstruction } from "./dvp";
const [nonceTombstone] = await getProgramDerivedAddress({
programAddress: DVP_SWAP_PROGRAM_PROGRAM_ADDRESS,
seeds: ["nonce", getAddressEncoder().encode(swapDvp)],
});
const recoverInstruction = getRecoverDvpInstruction({
signer: userASigner,
swapDvp,
nonceTombstone,
mint: mintA,
dvpEscrowAta: escrowA,
signerDestAta: userAAtaA,
tokenProgram: tokenProgramA,
memoProgram: MEMO_PROGRAM_ADDRESS,
settlementAuthority,
userA,
userB,
mintA,
mintB,
nonce,
});
await client.sendTransaction([recoverInstruction]);

Il recupero dipende dal fatto che la parte conservi i parametri di creazione. Un sistema che finanzia gli scambi memorizza gli input del seed con ogni ordine finché lo scambio non è stato chiuso e i saldi degli escrow non sono stati confermati vuoti.

Note

  • Leg congelate. Su un mint con restrizioni (gated), un escrow congelato blocca il trasferimento di token che queste istruzioni eseguono finché la freeze authority non lo sblocca. Vedi la panoramica.
  • Modifiche al mint dopo la creazione. I percorsi di annullamento saltano i controlli sulle estensioni e sulla mint authority, così i controlli del programma non bloccano un recupero. Le regole del token program continuano comunque ad applicarsi. Un mint può essere chiuso solo con supply pari a zero, quindi non può cambiare mentre un saldo si trova in escrow, ma un mint chiuso e ricreato come NonTransferable o con una commissione di trasferimento prima dell'arrivo di un deposito tardivo può rendere quel deposito immovibile o soggetto a commissione. È la dipendenza dalla mint authority elencata in token supportati.

Prossimi passi

Is this page helpful?

Indice dei contenuti

Modifica pagina
© 2026 Solana Foundation. Tutti i diritti riservati.