Διακανονισμός της συναλλαγής

Η SettleDvp υπογράφεται από την αρχή διακανονισμού που αναφέρεται στην εγγραφή της συναλλαγής. Μέσα σε μία συναλλαγή μεταφέρει το amount_a του σκέλους περιουσιακού στοιχείου στον προορισμό του μέρους του χρηματικού σκέλους και το amount_b του χρηματικού σκέλους στον προορισμό του μέρους του σκέλους περιουσιακού στοιχείου, επιστρέφει οποιοδήποτε πλεόνασμα σε οποιοδήποτε escrow στο μέρος του αντίστοιχου σκέλους και κλείνει την εγγραφή και τα δύο escrow. Αν κάποια από αυτές τις μεταφορές δεν μπορεί να ολοκληρωθεί, η εντολή αποτυγχάνει και τίποτα δεν μετακινείται.

Αυτή η σελίδα συνεχίζει από τις ενότητες δημιουργία συναλλαγής και χρηματοδότηση των σκελών· ο client, οι υπογράφοντες, η trade και τα token accounts των μερών μεταφέρονται από εκεί.

Επανεπικύρωση πριν την υπογραφή

Η αρχή διακανονισμού υπογράφει τη συναλλαγή που μετακινεί και τα δύο σκέλη, οπότε εκτελεί την ίδια ανάγνωση με κάθε μέρος πριν υπογράψει: ιδιοκτήτης, μέγεθος, μέρη, mints, ποσά, λήξη και και οι δύο προορισμοί (δείτε χρηματοδότηση των σκελών). Το ίδιο το πρόγραμμα ελέγχει ξανά κατά τον διακανονισμό ότι κάθε mint ανήκει ακόμη στο token program που καταγράφηκε κατά τη δημιουργία, δεν φέρει αποκλεισμένη επέκταση και έχει την ίδια mint authority όπως όταν δημιουργήθηκε η συναλλαγή, επομένως ένα mint που δημιουργήθηκε εκ νέου με αποκλεισμένη επέκταση, διαφορετικό token program ή διαφορετική mint authority δεν μπορεί να διακανονιστεί.

Δημιουργία των λογαριασμών παραληπτών

Ο διακανονισμός γράφει σε τέσσερα 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 userA
const destinationB = t.userBSettlementDestination; // defaults to userB
const [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,
}),
);

Διακανονισμός

Το 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. Επιλύστε τα επιπλέον account metas κάθε hook mint με τον ίδιο τρόπο που θα κάνατε για μια άμεση μεταφορά αυτού του token και στη συνέχεια προσθέστε τα στην εντολή: πρώτα οι λογαριασμοί του σκέλους περιουσιακού στοιχείου, έπειτα του χρηματικού σκέλους, με το legAExtrasCount ορισμένο στον αριθμό της πρώτης ομάδας. Στην TypeScript, κάντε spread τα επιλυμένα metas στον πίνακα accounts της εντολής· στη Rust, χρησιμοποιήστε το add_remaining_accounts στον builder. Το όριο είναι 32 λογαριασμοί ανά σκέλος, συμπεριλαμβανομένου του προγράμματος hook και του λογαριασμού επικύρωσης· το όριο λογαριασμών της συναλλαγής μπορεί να ισχύσει πρώτο όταν και τα δύο σκέλη έχουν hooks. Το πρόγραμμα αφαιρεί τη σημαία signer από κάθε προωθούμενο λογαριασμό, επομένως ένα hook δεν μπορεί να αποκτήσει την υπογραφή της αρχής διακανονισμού μέσω αυτής της διαδρομής.

Καταγραφή του αποτελέσματος

Θεωρήστε τη συναλλαγή διακανονισμένη όταν η συναλλαγή Settle φτάσει στο finalized. Η εγγραφή και τα δύο escrow δεν υπάρχουν πλέον μετά τον διακανονισμό, επομένως ένα σύστημα που χρειάζεται τους όρους αργότερα τους αποθηκεύει από την ανάγνωση πριν τον διακανονισμό ή από τη συναλλαγή δημιουργίας. Το rent των κλειστών λογαριασμών έχει μεταφερθεί στην αρχή διακανονισμού.

Σφάλματα διακανονισμού

Το LegNotFunded σημαίνει ότι ένα escrow περιέχει λιγότερα από το συμφωνημένο ποσό· τα DvpExpired και SettlementTooEarly σημαίνουν ότι χάθηκε το χρονικό περιθώριο· τα MintAuthorityChanged και BlockedMintExtension σημαίνουν ότι ένα mint άλλαξε μετά τη δημιουργία· το RecipientAtaMismatch σημαίνει ότι ένας προορισμός ή ένας token account επιστροφής λείπει ή δεν ανήκει πλέον στον αναμενόμενο ιδιοκτήτη και mint, συνήθως επειδή το βήμα δημιουργίας λογαριασμών παραπάνω παραλείφθηκε. Σε κάθε περίπτωση δεν έχει μετακινηθεί τίποτα και τα μέρη μπορούν να αναιρέσουν τη συναλλαγή, ανάλογα με τις αρχές του mint (δείτε αναίρεση συναλλαγής).

Επόμενα βήματα

Is this page helpful?

© 2026 Ίδρυμα Solana. Με επιφύλαξη παντός δικαιώματος.