Hoàn tác một giao dịch

Có bốn instruction hoàn trả tiền mà không thực hiện thanh toán: Reclaim, Cancel và Reject trong khi giao dịch còn mở, và Recover cho khoản nạp đến sau khi giao dịch đã đóng. Không instruction nào kiểm tra thời hạn hết hiệu lực. Escrow bị đóng băng hoặc mint bị thay đổi vẫn có thể giữ lại một leg, như được mô tả trong phần ghi chú ở cuối trang.

InstructionNgười kýPhạm viGiao dịch sau đó
ReclaimDvpuser_a hoặc user_bLeg của chính người kýVẫn mở
CancelDvpSettlement authorityCả hai legĐã đóng
RejectDvpuser_a hoặc user_bCả hai legĐã đóng
RecoverDvpuser_a hoặc user_bLeg của người ký, sau khi đóngĐã đóng từ trước

Trong mọi trường hợp, escrow đều được rút toàn bộ số dư đang giữ về cho bên sở hữu leg đó: escrow A về token account của user_a cho mint_a, escrow B về token account của user_b cho mint_b, bất kể ai đã nạp tiền. Program account của memo được cung cấp cho các tài khoản hoàn tiền yêu cầu memo.

Trang này tiếp nối các bước trước: client và các signer từ tạo giao dịch, userAAtaA và userBAtaB từ nạp tiền cho các leg, cùng MEMO_PROGRAM_ID và authority từ thanh toán giao dịch được dùng tiếp.

Rút lại một leg

Reclaim trả lại leg của người ký và để giao dịch ở trạng thái mở, nên leg đó có thể được nạp lại. Hãy dùng khi vấn đề nằm ở leg của đối tác; Cancel và Reject sẽ đóng toàn bộ giao dịch.

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 hoặc Reject

Cancel do settlement authority ký và Reject do một trong hai bên ký. Cả hai đều hoàn trả số dư mà mỗi escrow đang giữ cho bên sở hữu leg tương ứng, đồng thời đóng bản ghi và cả hai escrow, với rent của các tài khoản được đóng chuyển về cho người ký. Hai instruction này nhận cùng các tài khoản; chỉ khác người ký.

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

Các tài khoản hoàn tiền (userAAtaA, userBAtaB) phải tồn tại đối với bất kỳ leg nào đang có số dư; tài khoản hoàn tiền chưa được khởi tạo sẽ khiến việc chuyển token thất bại và hoàn nguyên instruction. Leg chưa từng được nạp tiền không cần chuyển token nên chấp nhận việc thiếu tài khoản.

Thu hồi khoản nạp đến muộn

Settle, Cancel và Reject đều đóng cả hai token account của escrow, nên một lệnh chuyển thông thường vào escrow đã đóng sẽ thất bại. Khoản nạp chỉ có thể đến sau khi đóng nếu có thứ gì đó tạo lại escrow trước, ví dụ một giao dịch nạp tiền chứa instruction create-idempotent associated token account đặt trước lệnh chuyển và đang được xử lý thì đối tác gửi Reject. Khi đó các token nằm trong một escrow mà giao dịch của nó không còn tồn tại: bản ghi đã mất, nên Reclaim không thể tìm thấy nó, và nonce tombstone ngăn việc tạo một giao dịch mới tại cùng địa chỉ để chiếm lấy khoản nạp đó.

Để dùng RecoverDvp, bên sở hữu leg cung cấp các đầu vào seed ban đầu (settlement authority, hai bên, hai mint, nonce). Chương trình tính lại địa chỉ bản ghi, yêu cầu tombstone của nó làm bằng chứng giao dịch từng tồn tại, rút toàn bộ escrow về token account của chính người ký, rồi đóng escrow, trả rent của escrow về cho người ký. Leg của người ký được chọn theo bên nào ký: mint_a cho user_a, mint_b cho 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]);

Việc thu hồi phụ thuộc vào việc bên liên quan giữ lại các tham số tạo giao dịch. Một hệ thống nạp tiền cho các giao dịch sẽ lưu các đầu vào seed cùng với mỗi lệnh cho đến khi giao dịch đã đóng và số dư escrow đã được xác nhận là trống.

Ghi chú

  • Leg bị đóng băng. Với mint có kiểm soát (gated), escrow bị đóng băng sẽ chặn việc chuyển token mà các instruction này thực hiện cho đến khi freeze authority giải băng. Xem phần tổng quan.
  • Mint thay đổi sau khi tạo. Các luồng hoàn tác bỏ qua việc kiểm tra extension và mint authority để các kiểm tra của chính chương trình không chặn việc thu hồi. Các quy tắc của token program vẫn được áp dụng. Một mint chỉ có thể bị đóng khi nguồn cung bằng 0, nên nó không thể thay đổi khi vẫn còn số dư trong escrow, nhưng một mint được đóng rồi tạo lại dưới dạng NonTransferable hoặc có phí chuyển (transfer fee) trước khi một khoản nạp đến muộn xuất hiện có thể khiến khoản nạp đó không thể di chuyển hoặc bị tính phí. Đó là sự phụ thuộc vào mint authority được liệt kê tại các token được hỗ trợ.

Các bước tiếp theo

Is this page helpful?

Mục lục

Chỉnh sửa trang