Quatro instruções devolvem fundos sem liquidar: Reclaim, Cancel e Reject enquanto a negociaçã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 um mint alterado ainda pode reter uma perna, como descrevem as notas no final.
| Instrução | Assinante | Escopo | Negociação depois |
|---|---|---|---|
ReclaimDvp | user_a ou user_b | A perna do próprio assinante | Continua 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 assinante, após o encerramento | Já encerrada |
Em cada caso, o escrow é esvaziado de tudo o que contém em favor da 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 das etapas anteriores: o cliente e os assinantes de
criar uma negociação, userAAtaA e
userBAtaB de financiar as pernas, e
MEMO_PROGRAM_ID e authority de
liquidar a negociação são reaproveitados.
Recuperar uma perna
Reclaim devolve a perna do assinante e deixa a negociação aberta, de modo que a perna possa ser financiada novamente. Use-o quando o problema estiver na perna da contraparte; Cancel e Reject encerram a negociação inteira.
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 é assinada pela autoridade de liquidação e Reject por qualquer uma das partes. Ambas reembolsam o que cada escrow contém à parte da perna e fecham o registro e ambos os escrows, com a rent das contas fechadas indo para o assinante. As duas instruções recebem as mesmas contas; só o assinante muda.
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 fecham ambas as token accounts de escrow, portanto uma transferência simples para um escrow fechado falha. Um depósito só chega após o encerramento se algo recriar o escrow antes, por exemplo uma transação de financiamento que inclua uma instrução de associated token account create-idempotent antes da transferência e que estava em andamento quando a contraparte enviou Reject. Os tokens ficam então em um escrow cuja negociação já não existe: o registro desapareceu, então Reclaim não consegue encontrá-lo, e o tombstone do nonce impede que uma nova negociaçã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, ambos os mints, nonce). O programa rederiva
o endereço do registro, exige o seu tombstone como prova de que a negociação existiu, esvazia
o escrow para a token account do próprio assinante e o fecha, devolvendo a
rent do escrow ao assinante. A perna do assinante é escolhida conforme a 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 negociações armazena as entradas de seed junto com cada ordem até que a negociação tenha sido encerrada e os saldos dos escrows tenham sido confirmados como vazios.
Notas
- Pernas congeladas. Em um mint com restrições, um escrow congelado bloqueia a transferência de tokens que essas instruções executam até que a freeze authority o descongele. Veja a visão geral.
- Alterações no 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 valer. Um mint só pode ser fechado com supply zero, portanto não pode mudar enquanto houver saldo no escrow, mas um mint fechado e recriado como NonTransferable ou com 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 compatíveis.
Próximos passos
- Programa DvP: a visão geral, os tokens compatíveis e as restrições de configuração do mint
- Delivery vs Payment (DvP) usando delegação: a mesma troca por meio de autoridade delegada, sem um programa
Is this page helpful?