SettleDvp, alım satım kaydında belirtilen takas yetkilisi tarafından imzalanır. Tek bir
işlemde varlık bacağının amount_a tutarını nakit bacağı tarafının
hedef hesabına, nakit bacağının amount_b tutarını ise varlık bacağı tarafının hedef hesabına taşır;
her iki escrow hesabındaki fazlalığı ilgili bacağın tarafına iade eder, ardından kaydı
ve her iki escrow hesabını kapatır. Bu transferlerden herhangi biri tamamlanamazsa talimat
başarısız olur ve hiçbir şey hareket etmez.
Bu sayfa, alım satım oluşturma
ve bacakları fonlama sayfalarının devamıdır; istemci, imzalayanlar,
trade ve tarafların token account'ları aynen devralınır.
İmzalamadan önce yeniden doğrulama
Takas yetkilisi her iki bacağı da taşıyan işlemi imzalar; bu nedenle imzalamadan önce her tarafın yaptığı okumanın aynısını yapar: sahip, boyut, taraflar, mint'ler, tutarlar, son kullanma zamanı ve her iki hedef hesap (bkz. bacakları fonlama). Programın kendisi de takas sırasında her mint'in hâlâ oluşturma anında kaydedilen token program'a ait olduğunu, engellenmiş bir uzantı taşımadığını ve alım satım oluşturulduğundaki mint yetkilisiyle aynı yetkiliye sahip olduğunu yeniden kontrol eder. Dolayısıyla engellenmiş bir uzantıyla, farklı bir token program ile veya farklı bir mint yetkilisiyle yeniden oluşturulmuş bir mint takas edilemez.
Alıcı hesaplarını oluşturma
Settle, programın oluşturmadığı dört token account'a yazar:
| Hesap | Aldığı | Sahip |
|---|---|---|
userADestinationAtaB | Nakit bacağı (amount_b) | user_a_settlement_destination |
userBDestinationAtaA | Varlık bacağı (amount_a) | user_b_settlement_destination |
userAAtaA | Varlık bacağındaki fazlalık | user_a |
userBAtaB | Nakit bacağındaki fazlalık | user_b |
Fazlalık hesapları yalnızca bir escrow hesabı kararlaştırılan tutardan fazlasını tuttuğunda kullanılır; ancak mint'e sahip herhangi biri escrow hesabına birkaç temel birim göndererek fazlalık oluşturabilir. İade hesabı mevcut değilse Settle işleminin tamamı başarısız olur; bu nedenle dördünü de aynı işlemde idempotent olarak oluşturun.
import {findAssociatedTokenPda,getCreateAssociatedTokenIdempotentInstruction,} from "@solana-program/token-2022";const destinationA = t.userASettlementDestination; // defaults to userAconst destinationB = t.userBSettlementDestination; // defaults to userBconst [userADestinationAtaB] = await findAssociatedTokenPda({mint: mintB,owner: destinationA,tokenProgram: tokenProgramB,});const [userBDestinationAtaA] = await findAssociatedTokenPda({mint: mintA,owner: destinationB,tokenProgram: tokenProgramA,});// userAAtaA and userBAtaB are from fund the legs.const createRecipientAccounts = [{ ata: userADestinationAtaB, owner: destinationA, mint: mintB, tokenProgram: tokenProgramB },{ ata: userBDestinationAtaA, owner: destinationB, mint: mintA, tokenProgram: tokenProgramA },{ ata: userAAtaA, owner: userA, mint: mintA, tokenProgram: tokenProgramA },{ ata: userBAtaB, owner: userB, mint: mintB, tokenProgram: tokenProgramB },].map(({ ata, owner, mint, tokenProgram }) =>getCreateAssociatedTokenIdempotentInstruction({payer: authoritySigner,ata,owner,mint,tokenProgram,}),);
Settle
legAExtrasCount, sabit listeden sonra eklenen hesaplardan kaçının varlık bacağının
transfer hook'una ait olduğunu programa bildirir; geri kalanı nakit bacağına aittir.
Transfer hook'u olmayan mint'ler için sıfır geçin ve hiçbir şey eklemeyin. Memo
program account'ı talimat için zorunludur ve yalnızca memo gerektiren hedefler
için kullanılır.
import { MEMO_PROGRAM_ADDRESS } from "@solana-program/memo";import { getSettleDvpInstruction } from "./dvp";const settleInstruction = getSettleDvpInstruction({settlementAuthority: authoritySigner,swapDvp,mintA,mintB,dvpAtaA: escrowA,dvpAtaB: escrowB,userADestinationAtaB,userBDestinationAtaA,userAAtaA,userBAtaB,tokenProgramA,tokenProgramB,memoProgram: MEMO_PROGRAM_ADDRESS,legAExtrasCount: 0,});const { context: settleContext } = await client.sendTransaction([...createRecipientAccounts,settleInstruction,]);const settleSignature = settleContext.signature;console.log("Submitted:", settleSignature);// sendTransaction returns at the client's commitment (confirmed by default).// Wait for finalized before recording the trade as settled.let finalized = false;for (let attempt = 0; attempt < 30 && !finalized; attempt++) {const {value: [status],} = await client.rpc.getSignatureStatuses([settleSignature]).send();if (status?.err) {throw new Error("Settle transaction failed");}finalized = status?.confirmationStatus === "finalized";if (!finalized) {await new Promise((resolve) => setTimeout(resolve, 2_000));}}if (!finalized) {// A closed record means it settled; an open one is safe to settle again.throw new Error("Settle not finalized after 60s; read the trade record");}console.log("Settled:", settleSignature);
Transfer hook'ları
Oluşturulan IDL yalnızca sabit hesapları listeler; bu nedenle oluşturulan builder'lar
hook hesaplarından haberdar değildir. Her hook mint'inin ek account meta'larını, o token'ın
doğrudan transferi için yapacağınız şekilde çözümleyin, ardından bunları talimata ekleyin:
önce varlık bacağının hesapları, sonra nakit bacağının hesapları; legAExtrasCount
ilk gruptaki sayıya ayarlanmalıdır. TypeScript'te çözümlenen meta'ları talimatın
accounts dizisine yayın (spread); Rust'ta builder üzerinde
add_remaining_accounts kullanın. Üst sınır, hook programı ve doğrulama hesabı dahil
bacak başına 32 hesaptır; her iki bacak da hook taşıyorsa işlem hesap sınırı
önce devreye girebilir. Program, iletilen her hesaptan imzalayan (signer) bayrağını kaldırır;
bu nedenle bir hook bu yol üzerinden takas yetkilisinin imzasını elde edemez.
Sonucu kaydetme
Settle işlemi finalized durumuna ulaştığında alım satımı takas edilmiş sayın.
Takastan sonra kayıt ve her iki escrow hesabı artık mevcut değildir; bu nedenle koşullara
sonradan ihtiyaç duyan bir sistem, bunları takas öncesi okumasından veya oluşturma
işleminden saklamalıdır. Kapatılan hesapların rent'i takas
yetkilisine gitmiştir.
Settle hataları
LegNotFunded, bir escrow hesabının kararlaştırılan tutardan azını tuttuğu anlamına gelir; DvpExpired
ve SettlementTooEarly zaman aralığının kaçırıldığını belirtir; MintAuthorityChanged
ve BlockedMintExtension bir mint'in oluşturulduktan sonra değiştiği anlamına gelir;
RecipientAtaMismatch ise bir hedef veya iade token account'ının eksik olduğunu ya da
artık beklenen sahip ve mint'e ait olmadığını belirtir; bu genellikle yukarıdaki
hesap oluşturma adımının atlanmasından kaynaklanır. Her durumda hiçbir şey hareket etmemiştir ve
taraflar, mint yetkililerinin izin verdiği ölçüde işlemi geri alabilir (bkz.
alım satımı geri alma).
Sonraki adımlar
- Alım satımı geri alma: bir alım satım takas edilmediğinde fonlanmış bacakları geri alma
Is this page helpful?