Cuatro instrucciones devuelven fondos sin liquidar: Reclaim, Cancel y Reject mientras la operación está abierta, y Recover para un depósito que llega después de que se haya cerrado. Ninguna comprueba la expiración. Un escrow congelado o un mint modificado todavía puede retener un tramo, como describen las notas del final.
| Instrucción | Firmante | Alcance | Operación después |
|---|---|---|---|
ReclaimDvp | user_a o user_b | El tramo del propio firmante | Sigue abierta |
CancelDvp | Autoridad de liquidación | Ambos tramos | Cerrada |
RejectDvp | user_a o user_b | Ambos tramos | Cerrada |
RecoverDvp | user_a o user_b | El tramo del firmante, tras el cierre | Ya cerrada |
En cada caso, el escrow se vacía hacia la parte del tramo con todo lo que contenga:
el escrow A a la token account de user_a para mint_a, y el escrow B a la de
user_b para mint_b, sin importar quién lo fondeó. El program account de memo se
proporciona para las cuentas de reembolso que requieren un memo.
Esta página continúa desde los pasos anteriores: el cliente y los firmantes de
crear una operación, userAAtaA y
userBAtaB de fondear los tramos, y
MEMO_PROGRAM_ID y authority de
liquidar la operación se mantienen.
Reclamar un tramo
Reclaim devuelve el tramo del firmante y deja la operación abierta, de modo que el tramo pueda fondearse de nuevo. Úsalo cuando el problema esté en el tramo de la contraparte; Cancel y Reject cierran toda la operación.
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]);
Cancelar o rechazar
Cancel lo firma la autoridad de liquidación y Reject, cualquiera de las partes. Ambas instrucciones reembolsan lo que contenga cada escrow a la parte del tramo y cierran el registro y ambos escrows, y el rent de las cuentas cerradas va al firmante. Las dos instrucciones toman las mismas cuentas; solo cambia el firmante.
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,});
Las cuentas de reembolso (userAAtaA, userBAtaB) deben existir para cualquier tramo
que tenga saldo; una cuenta de reembolso sin inicializar hace que falle la transferencia
de tokens y revierte la instrucción. Un tramo que nunca se fondeó no necesita
transferencia y tolera una cuenta ausente.
Recuperar un depósito tardío
Settle, Cancel y Reject cierran ambas token accounts de escrow, por lo que una transferencia simple a un escrow cerrado falla. Un depósito solo llega después del cierre si algo recrea antes el escrow, por ejemplo una transacción de fondeo que incluya una instrucción de associated token account con creación idempotente antes de la transferencia y que estuviera en tránsito cuando la contraparte envió Reject. Entonces los tokens quedan en un escrow cuya operación ya no existe: el registro ya no está, por lo que Reclaim no puede encontrarlo, y el tombstone del nonce impide que se cree una nueva operación en la misma dirección y capture el depósito.
Para usar RecoverDvp, la parte del tramo proporciona los seed originales
(autoridad de liquidación, ambas partes, ambos mints, nonce). El programa vuelve a derivar
la dirección del registro, exige su tombstone como prueba de que la operación existió,
vacía el escrow hacia la token account del propio firmante y lo cierra, devolviendo el
rent del escrow al firmante. El tramo del firmante se elige según quién firma:
mint_a para user_a, mint_b para 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 recuperación depende de que la parte conserve los parámetros de creación. Un sistema que fondea operaciones almacena los seed de cada orden hasta que la operación se haya cerrado y se haya confirmado que los saldos de los escrows están vacíos.
Notas
- Tramos congelados. En un mint con restricciones, un escrow congelado bloquea la transferencia de tokens que realizan estas instrucciones hasta que la autoridad de congelación lo descongele. Consulta la descripción general.
- Cambios en el mint tras la creación. Las rutas de reversión omiten las comprobaciones de extensiones y de autoridad del mint para que las propias comprobaciones del programa no bloqueen una recuperación. Las reglas propias del Token Program siguen aplicándose. Un mint solo puede cerrarse con suministro cero, por lo que no puede cambiar mientras haya un saldo en el escrow, pero un mint cerrado y recreado como NonTransferable o con una comisión de transferencia antes de que llegue un depósito tardío puede hacer que ese depósito sea inmovible o esté sujeto a comisión. Esa es la dependencia de la autoridad del mint indicada en tokens compatibles.
Siguientes pasos
- Programa DvP: la descripción general, los tokens compatibles y las restricciones de configuración del mint
- Entrega contra pago (DvP) mediante delegación: el mismo intercambio mediante autoridad delegada, sin un programa
Is this page helpful?