SettleDvp, trade kaydında adı geçen takas yetkilisi tarafından imzalanır. Tek
bir işlemde, varlık bacağının amount_a miktarını nakit bacağı tarafının
hedefine, nakit bacağının amount_b miktarını ise varlık bacağı tarafının
hedefine aktarır; her iki escrow'daki fazla tutarı ilgili bacağın tarafına iade
eder ve kaydı ile her iki escrow'u kapatır. Bu transferlerden herhangi biri
tamamlanamazsa talimat başarısız olur ve hiçbir şey hareket etmez.
Bu sayfa, trade oluşturma
ve bacakları fonlama sayfalarının devamıdır; client, imzalayanlar,
trade ve tarafların token account'ları aynen devralınır.
İmzalamadan önce yeniden doğrulayın
Takas yetkilisi her iki bacağı hareket ettiren işlemi imzaladığı için, imzalamadan önce her bir tarafla aynı okumayı yapar: sahip, boyut, taraflar, mint'ler, miktarlar, son kullanma zamanı ve her iki hedef (bkz. bacakları fonlama). Program ayrıca takas sırasında her mint'in hâlâ oluşturma anında kaydedilen token program'a ait olduğunu, engellenmiş bir extension taşımadığını ve trade oluşturulduğundaki mint authority'ye sahip olduğunu yeniden kontrol eder; dolayısıyla engellenmiş bir extension ile, farklı bir token program ile veya farklı bir mint authority ile yeniden oluşturulan bir mint takas edilemez.
Alıcı token account'larını oluşturun
Settle, program tarafından oluşturulmayan 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 fazla tutar | user_a |
userBAtaB | Nakit bacağındaki fazla tutar | user_b |
Fazla tutar hesapları yalnızca bir escrow kabul edilen miktardan fazlasını tuttuğunda kullanılır; ancak mint'e sahip olan herkes escrow'a birkaç temel birim göndererek fazla tutar oluşturabilir. İade hesabı yoksa Settle işleminin tamamı başarısız olur, bu yüzden dördünü de aynı işlemde idempotent biçimde 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 listenin ardından eklenen hesaplardan kaçının varlık
bacağının transfer hook'una ait olduğunu programa bildirir; geri kalanlar nakit
bacağınındır. 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ınkiler; legAExtrasCount ilk gruptaki sayıya ayarlanmalıdır.
TypeScript'te çözümlenen meta'ları talimatın accounts dizisine spread edin;
Rust'ta builder üzerinde add_remaining_accounts kullanın. Üst sınır, hook
programı ve doğrulama hesabı dahil olmak üzere bacak başına 32 hesaptır; her iki
bacak da hook taşıdığında işlem hesap sınırı önce devreye girebilir. Program,
iletilen her hesaptan signer bayrağını kaldırır; dolayısıyla bir hook bu yol
üzerinden takas yetkilisinin imzasını elde edemez.
Sonucu kaydedin
Settle işlemi finalized durumuna ulaştığında trade'i takas edilmiş sayın.
Takastan sonra kayıt ve her iki escrow artık mevcut olmadığından, koşullara
sonradan ihtiyaç duyan bir sistem bunları takas öncesi okumadan veya oluşturan
işlemden saklar. Kapatılan hesapların rent'i takas yetkilisine geçmiştir.
Settle hataları
LegNotFunded, bir escrow'un kabul edilen miktardan azını tuttuğu anlamına
gelir; DvpExpired ve SettlementTooEarly zaman aralığının kaçırıldığını
gösterir; 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'in yetkililerine bağlı olarak işlemi geri alabilir (bkz.
trade'i geri alma).
Sonraki adımlar
- Trade'i geri alma: bir trade takas edilmediğinde fonlanmış bacakları geri kazanma
Is this page helpful?