SettleDvp wordt ondertekend door de settlement authority die in het traderecord staat. In
eén transactie verplaatst de instructie amount_a van de assetleg naar de bestemming van de partij van de cashleg en amount_b van de cashleg naar de bestemming van de partij van de assetleg,
geeft ze eventueel overschot in een van beide escrows terug aan de partij van die leg en sluit ze het record
en beide escrows. Als een van die overdrachten niet kan worden voltooid, mislukt de instructie en wordt er niets verplaatst.
Deze pagina sluit aan op een trade aanmaken
en de legs financieren; de client, signers,
trade en de token accounts van de partijen worden overgenomen.
Opnieuw valideren voor het ondertekenen
De settlement authority ondertekent de transactie die beide legs verplaatst, dus voert ze dezelfde controle uit als elke partij voordat ze ondertekent: eigenaar, grootte, partijen, mints, bedragen, vervaldatum en beide bestemmingen (zie de legs financieren). Het programma zelf controleert bij de afwikkeling opnieuw of elke mint nog steeds bij het token program hoort dat bij het aanmaken is vastgelegd, geen geblokkeerde extensie bevat en dezelfde mint authority heeft als toen de trade werd aangemaakt. Een mint die opnieuw is aangemaakt met een geblokkeerde extensie, een ander token program of een andere mint authority kan dus niet worden afgewikkeld.
De token accounts van de ontvangers aanmaken
Settle schrijft naar vier token accounts die het programma niet aanmaakt:
| Account | Ontvangt | Eigenaar |
|---|---|---|
userADestinationAtaB | De cashleg (amount_b) | user_a_settlement_destination |
userBDestinationAtaA | De assetleg (amount_a) | user_b_settlement_destination |
userAAtaA | Eventueel overschot op de assetleg | user_a |
userBAtaB | Eventueel overschot op de cashleg | user_b |
De token accounts voor het overschot worden alleen gebruikt wanneer een escrow meer bevat dan het afgesproken bedrag, maar iedereen die tokens van de mint bezit kan een overschot creëren door een paar basis- eenheden naar de escrow te sturen. Als het token account voor de terugbetaling niet bestaat, mislukt de hele Settle, dus maak alle vier idempotent aan in dezelfde transactie.
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,}),);
Afwikkelen
legAExtrasCount geeft het programma aan hoeveel van de accounts die na de
vaste lijst zijn toegevoegd bij de transfer hook van de assetleg horen; de rest is voor die van de
cashleg. Geef voor mints zonder transfer hooks nul door en voeg niets toe. Het memo
program account is vereist voor de instructie en wordt alleen gebruikt voor bestemmingen
die een memo vereisen.
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
De gegenereerde IDL vermeldt alleen de vaste accounts, dus de gegenereerde builders
kennen de hook-accounts niet. Bepaal de extra account metas van elke hook-mint op dezelfde
manier als bij een directe overdracht van dat token en voeg ze vervolgens toe aan de
instructie: eerst de accounts van de assetleg, dan die van de cashleg, waarbij
legAExtrasCount is ingesteld op het aantal in de eerste groep. Spreid in TypeScript
de bepaalde metas over de accounts-array van de instructie; gebruik in Rust
add_remaining_accounts op de builder. De limiet is 32 accounts per leg,
inclusief het hookprogramma en het validatieaccount; de accountlimiet van de transactie
kan eerder worden bereikt wanneer beide legs hooks hebben. Het programma verwijdert de signer-vlag
van elk doorgestuurd account, zodat een hook via dit pad niet de
handtekening van de settlement authority kan verkrijgen.
Het resultaat vastleggen
Beschouw de trade als afgewikkeld wanneer de Settle-transactie finalized bereikt. Het
record en beide escrows bestaan na de afwikkeling niet meer, dus een systeem dat
de voorwaarden later nodig heeft, slaat ze op vanuit de uitlezing vóór de afwikkeling of vanuit de aanmaaktransactie.
De rent van de gesloten accounts is naar de settlement
authority gegaan.
Settle-fouten
LegNotFunded betekent dat een escrow minder bevat dan het afgesproken bedrag; DvpExpired
en SettlementTooEarly betekenen dat het tijdvenster is gemist; MintAuthorityChanged
en BlockedMintExtension betekenen dat een mint na het aanmaken is gewijzigd;
RecipientAtaMismatch betekent dat een token account voor de bestemming of terugbetaling ontbreekt of
niet meer van de verwachte eigenaar en mint is, meestal omdat de
bovenstaande stap voor het aanmaken van accounts is overgeslagen. In elk geval is er niets verplaatst en kunnen de
partijen de trade terugdraaien, afhankelijk van de authorities van de mint (zie
een trade terugdraaien).
Volgende stappen
- Een trade terugdraaien: gefinancierde legs terughalen wanneer een trade niet wordt afgewikkeld
Is this page helpful?