Το SettleDvp υπογράφεται από την αρχή διακανονισμού που ορίζεται στην εγγραφή της
ανταλλαγής. Σε μία συναλλαγή μεταφέρει amount_a του σκέλους περιουσιακού στοιχείου στον
προορισμό του συμβαλλομένου του σκέλους μετρητών και amount_b του σκέλους μετρητών στον
προορισμό του συμβαλλομένου του σκέλους περιουσιακού στοιχείου, επιστρέφει οποιοδήποτε
πλεόνασμα σε οποιοδήποτε escrow στον συμβαλλόμενο του αντίστοιχου σκέλους και κλείνει την
εγγραφή και τα δύο escrow. Αν κάποια από αυτές τις μεταφορές δεν μπορεί να ολοκληρωθεί, η
εντολή αποτυγχάνει και δεν μετακινείται τίποτα.
Αυτή η σελίδα συνεχίζει από τις ενότητες δημιουργία ανταλλαγής
και χρηματοδότηση των σκελών· ο client, οι signers,
το trade και τα token accounts των συμβαλλομένων μεταφέρονται αυτούσια.
Επανεπαλήθευση πριν την υπογραφή
Η αρχή διακανονισμού υπογράφει τη συναλλαγή που μετακινεί και τα δύο σκέλη, οπότε εκτελεί την ίδια ανάγνωση με κάθε συμβαλλόμενο πριν υπογράψει: κάτοχο, μέγεθος, συμβαλλομένους, mints, ποσά, λήξη και και τους δύο προορισμούς (βλ. χρηματοδότηση των σκελών). Το ίδιο το πρόγραμμα ελέγχει ξανά κατά τον διακανονισμό ότι κάθε mint ανήκει ακόμη στο token program που καταγράφηκε κατά τη δημιουργία, δεν φέρει μπλοκαρισμένη επέκταση και έχει την ίδια mint authority με τη στιγμή που δημιουργήθηκε η ανταλλαγή. Έτσι, ένα mint που δημιουργήθηκε εκ νέου με μπλοκαρισμένη επέκταση, με διαφορετικό token program ή με διαφορετική mint authority δεν μπορεί να διακανονιστεί.
Δημιουργία των λογαριασμών παραληπτών
Το Settle γράφει σε τέσσερα token accounts που το πρόγραμμα δεν δημιουργεί:
| Λογαριασμός | Λαμβάνει | Κάτοχος |
|---|---|---|
userADestinationAtaB | Το σκέλος μετρητών (amount_b) | user_a_settlement_destination |
userBDestinationAtaA | Το σκέλος περιουσιακού στοιχείου (amount_a) | user_b_settlement_destination |
userAAtaA | Οποιοδήποτε πλεόνασμα στο σκέλος περιουσιακού στοιχείου | user_a |
userBAtaB | Οποιοδήποτε πλεόνασμα στο σκέλος μετρητών | user_b |
Οι λογαριασμοί πλεονάσματος χρησιμοποιούνται μόνο όταν ένα escrow διατηρεί περισσότερα από το συμφωνημένο ποσό, αλλά οποιοσδήποτε κατέχει το mint μπορεί να δημιουργήσει πλεόνασμα στέλνοντας μερικές βασικές μονάδες στο escrow. Αν ο λογαριασμός επιστροφής δεν υπάρχει, ολόκληρο το Settle αποτυγχάνει, γι' αυτό δημιουργήστε και τους τέσσερις με idempotent τρόπο στην ίδια συναλλαγή.
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 ενημερώνει το πρόγραμμα πόσοι από τους λογαριασμούς που προστίθενται μετά τη
σταθερή λίστα ανήκουν στο transfer hook της μεταφοράς του σκέλους περιουσιακού στοιχείου· οι υπόλοιποι ανήκουν σε αυτό του σκέλους
μετρητών. Για mints χωρίς transfer hooks, περάστε μηδέν και μην προσθέσετε τίποτα. Το memo
program account απαιτείται από την εντολή και χρησιμοποιείται μόνο για προορισμούς
που απαιτούν memo.
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 hooks
Το παραγόμενο IDL απαριθμεί μόνο τους σταθερούς λογαριασμούς, επομένως οι παραγόμενοι builders
δεν γνωρίζουν τους λογαριασμούς των hooks. Επιλύστε τα extra account metas κάθε mint με hook με τον
ίδιο τρόπο που θα το κάνατε για άμεση μεταφορά αυτού του token και στη συνέχεια προσθέστε τα στην
εντολή: πρώτα οι λογαριασμοί του σκέλους περιουσιακού στοιχείου, έπειτα του σκέλους μετρητών, με το
legAExtrasCount ίσο με τον αριθμό της πρώτης ομάδας. Στην TypeScript, κάντε spread
τα επιλυμένα metas στον πίνακα accounts της εντολής· στη Rust, χρησιμοποιήστε
το add_remaining_accounts στον builder. Το όριο είναι 32 λογαριασμοί ανά σκέλος,
συμπεριλαμβανομένων του προγράμματος του hook και του λογαριασμού επαλήθευσης· το όριο λογαριασμών της συναλλαγής
μπορεί να τεθεί πρώτο όταν και τα δύο σκέλη έχουν hooks. Το πρόγραμμα αφαιρεί τη σημαία signer
από κάθε προωθούμενο λογαριασμό, ώστε ένα hook να μην μπορεί να αποκτήσει την υπογραφή της
αρχής διακανονισμού μέσω αυτής της διαδρομής.
Καταγραφή του αποτελέσματος
Θεωρήστε την ανταλλαγή διακανονισμένη όταν η συναλλαγή Settle φτάσει στο finalized. Η
εγγραφή και τα δύο escrow δεν υπάρχουν πια μετά τον διακανονισμό, οπότε ένα σύστημα που χρειάζεται
τους όρους αργότερα τους αποθηκεύει από την ανάγνωση πριν τον διακανονισμό ή από τη συναλλαγή
δημιουργίας. Το rent των κλειστών λογαριασμών έχει περάσει στην αρχή
διακανονισμού.
Σφάλματα του Settle
Το LegNotFunded σημαίνει ότι ένα escrow διατηρεί λιγότερα από το συμφωνημένο ποσό· τα DvpExpired
και SettlementTooEarly σημαίνουν ότι χάθηκε το χρονικό παράθυρο· τα MintAuthorityChanged
και BlockedMintExtension σημαίνουν ότι ένα mint άλλαξε μετά τη δημιουργία·
το RecipientAtaMismatch σημαίνει ότι ένα token account προορισμού ή επιστροφής λείπει ή
δεν ανήκει πλέον στον αναμενόμενο κάτοχο και mint, συνήθως επειδή το παραπάνω βήμα
δημιουργίας λογαριασμών παραλείφθηκε. Σε κάθε περίπτωση δεν έχει μετακινηθεί τίποτα και οι
συμβαλλόμενοι μπορούν να αναιρέσουν την ανταλλαγή, με την επιφύλαξη των authorities του mint (βλ.
αναίρεση ανταλλαγής).
Επόμενα βήματα
- Αναίρεση ανταλλαγής: ανάκτηση των χρηματοδοτημένων σκελών όταν μια ανταλλαγή δεν διακανονίζεται
Is this page helpful?