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.
| Instruction | Người ký | Phạm vi | Giao dịch sau đó |
|---|---|---|---|
ReclaimDvp | user_a hoặc user_b | Leg của chính người ký | Vẫn mở |
CancelDvp | Settlement authority | Cả hai leg | Đã đóng |
RejectDvp | user_a hoặc user_b | Cả hai leg | Đã đóng |
RecoverDvp | user_a hoặc user_b | Leg 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
- Chương trình DvP: phần tổng quan, các token được hỗ trợ và các ràng buộc cấu hình mint
- Delivery vs Payment (DvP) bằng ủy quyền (delegation): cùng một giao dịch trao đổi thông qua quyền được ủy quyền, không cần chương trình
Is this page helpful?