Quatro instruções devolvem fundos sem liquidar: Reclaim, Cancel e Reject enquanto a operação está aberta, e Recover para um depósito que chega depois de ela ter sido encerrada. Nenhuma delas verifica a expiração. Um escrow congelado ou uma mint alterada ainda pode reter uma perna, conforme descrito nas notas no final.
| Instrução | Signatário | Âmbito | Operação depois |
|---|---|---|---|
ReclaimDvp | user_a ou user_b | A perna do próprio signatário | Ainda aberta |
CancelDvp | Autoridade de liquidação | Ambas as pernas | Encerrada |
RejectDvp | user_a ou user_b | Ambas as pernas | Encerrada |
RecoverDvp | user_a ou user_b | A perna do signatário, após o encerramento | Já encerrada |
Em cada caso, o escrow é esvaziado, e tudo o que ele contém é enviado à parte da perna:
o escrow A para a token account de user_a para mint_a, o escrow B para a de user_b para
mint_b, independentemente de quem o financiou. A program account do memo é fornecida para contas
de reembolso que exigem um memo.
Esta página continua a partir dos passos anteriores: o cliente e os signatários de
criar uma operação, userAAtaA e
userBAtaB de financiar as pernas, e
MEMO_PROGRAM_ID e authority de
liquidar a operação são reaproveitados.
Reclamar uma perna
Reclaim devolve a perna do signatário e deixa a operação aberta, para que a perna possa ser financiada novamente. Use-o quando o problema estiver na perna da contraparte; Cancel e Reject encerram toda a operação.
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 ou rejeitar
Cancel é assinado pela autoridade de liquidação e Reject por qualquer uma das partes. Ambos reembolsam à parte da perna tudo o que cada escrow contém e encerram o registo e ambos os escrows, com o rent das contas encerradas indo para o signatário. As duas instruções recebem as mesmas contas; apenas o signatário difere.
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,});
As contas de reembolso (userAAtaA, userBAtaB) devem existir para qualquer perna que tenha
saldo; uma conta de reembolso não inicializada faz a transferência de tokens falhar e
reverte a instrução. Uma perna que nunca foi financiada não precisa de transferência e
tolera uma conta ausente.
Recuperar um depósito tardio
Settle, Cancel e Reject encerram ambas as token accounts de escrow, pelo que uma simples transferência para um escrow encerrado falha. Um depósito só chega depois do encerramento se algo recriar primeiro o escrow, por exemplo uma transação de financiamento que inclua uma instrução create-idempotent de associated token account antes da transferência e que estava em curso quando a contraparte enviou Reject. Os tokens ficam então num escrow cuja operação já não existe: o registo desapareceu, portanto Reclaim não o consegue encontrar, e o tombstone do nonce impede que uma nova operação seja criada no mesmo endereço e capture o depósito.
Para usar RecoverDvp, a parte da perna fornece as entradas de seed originais
(autoridade de liquidação, ambas as partes, ambas as mints, nonce). O programa volta a derivar
o endereço do registo, exige o respetivo tombstone como prova de que a operação existiu, esvazia
o escrow para a token account do próprio signatário e encerra-o, devolvendo o
rent do escrow ao signatário. A perna do signatário é escolhida pela parte que assina:
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]);
A recuperação depende de a parte guardar os parâmetros de criação. Um sistema que financia operações armazena as entradas de seed com cada ordem até que a operação tenha sido encerrada e os saldos dos escrows tenham sido confirmados como vazios.
Notas
- Pernas congeladas. Numa mint com restrições, um escrow congelado bloqueia a transferência de tokens que estas instruções realizam até que a freeze authority o descongele. Consulte a visão geral.
- Alterações da mint após a criação. Os caminhos de desfazimento ignoram as verificações de extensão e de mint authority, para que as verificações do próprio programa não bloqueiem uma recuperação. As regras do próprio token program continuam a aplicar-se. Uma mint só pode ser encerrada com oferta zero, por isso não pode mudar enquanto houver saldo no escrow, mas uma mint encerrada e recriada como NonTransferable ou com uma taxa de transferência antes de um depósito tardio chegar pode tornar esse depósito imovível ou sujeito a taxa. Essa é a dependência da mint authority listada em tokens suportados.
Próximos passos
- Programa DvP: a visão geral, os tokens suportados e as restrições de configuração da mint
- Delivery vs Payment (DvP) usando delegação: a mesma troca por meio de autoridade delegada, sem um programa
Is this page helpful?