Défaire un échange

Quatre instructions restituent les fonds sans règlement : Reclaim, Cancel et Reject tant que l'échange est ouvert, et Recover pour un dépôt qui arrive après sa clôture. Aucune ne vérifie l'expiration. Un escrow gelé ou un mint modifié peut encore bloquer un volet, comme le décrivent les notes en fin de page.

InstructionSignatairePortéeÉtat de l'échange ensuite
ReclaimDvpuser_a ou user_bLe volet du signataireToujours ouvert
CancelDvpAutorité de règlementLes deux voletsClôturé
RejectDvpuser_a ou user_bLes deux voletsClôturé
RecoverDvpuser_a ou user_bLe volet du signataire, après la clôtureDéjà clôturé

Dans chaque cas, l'escrow est vidé de son contenu au profit de la partie du volet : l'escrow A vers le token account de user_a pour mint_a, l'escrow B vers celui de user_b pour mint_b, quel que soit celui qui l'a financé. Le program account memo est fourni pour les comptes de remboursement qui exigent un mémo.

Cette page fait suite aux étapes précédentes : le client et les signataires issus de la création d'un échange, userAAtaA et userBAtaB issus de l'approvisionnement des volets, ainsi que MEMO_PROGRAM_ID et authority issus du règlement de l'échange sont repris.

Réclamer un volet

Reclaim restitue le volet du signataire et laisse l'échange ouvert, de sorte que le volet puisse être financé à nouveau. Utilisez-le lorsque le problème vient du volet de la contrepartie ; Cancel et Reject clôturent l'échange entier.

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]);

Cancel ou Reject

Cancel est signé par l'autorité de règlement et Reject par l'une ou l'autre des parties. Les deux restituent le contenu de chaque escrow à la partie du volet et ferment l'enregistrement et les deux escrows, la rent des comptes fermés revenant au signataire. Les deux instructions prennent les mêmes comptes ; seul le signataire diffère.

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,
});

Les comptes de remboursement (userAAtaA, userBAtaB) doivent exister pour tout volet qui contient un solde ; un compte de remboursement non initialisé fait échouer le transfert de tokens et annule l'instruction. Un volet qui n'a jamais été financé n'exige aucun transfert et tolère un compte manquant.

Récupérer un dépôt tardif

Settle, Cancel et Reject ferment tous les deux token accounts d'escrow, si bien qu'un simple transfert vers un escrow fermé échoue. Un dépôt n'arrive après la clôture que si quelque chose recrée d'abord l'escrow, par exemple une transaction de financement qui inclut une instruction create-idempotent d'associated token account avant le transfert et qui était en cours lorsque la contrepartie a envoyé Reject. Les tokens se trouvent alors dans un escrow dont l'échange n'existe plus : l'enregistrement a disparu, donc Reclaim ne peut pas le trouver, et la pierre tombale du nonce empêche la création d'un nouvel échange à la même adresse qui capterait le dépôt.

Pour utiliser RecoverDvp, la partie du volet fournit les entrées de seed d'origine (autorité de règlement, les deux parties, les deux mints, nonce). Le programme redérive l'adresse de l'enregistrement, exige sa pierre tombale comme preuve que l'échange a existé, vide l'escrow vers le token account du signataire, puis le ferme, en restituant la rent de l'escrow au signataire. Le volet du signataire est déterminé par la partie qui signe : mint_a pour user_a, mint_b pour 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]);

La récupération dépend du fait que la partie conserve les paramètres de création. Un système qui finance des échanges stocke les entrées de seed avec chaque ordre jusqu'à la clôture de l'échange et la confirmation que les soldes des escrows sont vides.

Notes

  • Volets gelés. Sur un mint soumis à restrictions, un escrow gelé bloque le transfert de tokens qu'effectuent ces instructions jusqu'à ce que l'autorité de gel le dégèle. Voir l'aperçu.
  • Modifications du mint après la création. Les chemins d'annulation ignorent les vérifications d'extensions et d'autorité du mint afin que les vérifications propres au programme ne bloquent pas une récupération. Les règles propres au Token Program continuent de s'appliquer. Un mint ne peut être fermé qu'à offre nulle, il ne peut donc pas changer tant qu'un solde reste dans l'escrow, mais un mint fermé puis recréé en NonTransferable ou avec des frais de transfert avant l'arrivée d'un dépôt tardif peut rendre ce dépôt impossible à déplacer ou soumis à des frais. C'est la dépendance à l'autorité du mint mentionnée dans les tokens pris en charge.

Étapes suivantes

Is this page helpful?

Table des matières

Modifier la page
© 2026 Fondation Solana. Tous droits réservés.