Luo kauppa

CreateDvp tallentaa kaupan ehdot ja luo kaksi escrow-tiliä, jotka osapuolet rahoittavat. Se ei siirrä tokeneita. Kuka tahansa voi lähettää sen, joten tietue voi tulla vastapuolelta, selvitysvaltuutetun operaattorilta tai kolmannelta osapuolelta, ja kaikki muut osallistujat tarkistavat tallennetut ehdot ennen kuin toimivat niiden pohjalta (ks. osuuksien rahoitus).

Esimerkit käyttävät generoitua asiakasohjelmaa suoraan ja paikkamerkkiosoitteita, jotta mukana olevat tilit ja allekirjoittajat näkyvät selvästi. Ne kohdistuvat devnetiin, jossa ohjelma on otettu käyttöön samassa osoitteessa kuin mainnet-betassa.

Asennus

DvP-asiakasohjelmille ei ole julkaistu pakettia 2. lokakuuta 2026 mennessä. Molemmat generoidaan ohjelman IDL:stä repositoriossa, ja niitä käytetään lähdekoodista.

git clone https://github.com/solana-foundation/dvp.git
cd dvp && git checkout df9919ed02c25a93620e7f6820107c9050ce3b92
pnpm install && pnpm generate-clients && pnpm build
# The client is clients/typescript/src; copy or link it into your project as ./dvp
pnpm add @solana/kit @solana/kit-plugin-rpc @solana/kit-plugin-signer @solana-program/token-2022 @solana-program/memo

Nämä sivut on kirjoitettu commitia df9919e vasten, käyttäen TypeScriptissä @solana/kit 8 -kirjastoa ja Rustissa solana-* 2.x -crateja.

Jokaisen vaihesivun esimerkit jatkuvat edellisistä: kukin sivu käyttää aiemmilla sivuilla määriteltyä asiakasohjelmaa, allekirjoittajia ja osoitteita. payerSigner, userASigner, userBSigner ja authoritySigner ovat TransactionSigner-olioita rent-maksajalle, kahdelle osapuolelle ja selvitysvaltuutetulle, esimerkiksi createKeyPairSignerFromBytes-funktiolla luotuina. Rust-esimerkit rakentavat käskyt ja jättävät allekirjoittamisen ja lähettämisen kutsujalle.

Johda osoitteet

Kauppatietue on Program Derived Address, joka johdetaan selvitysvaltuutetusta, kahdesta osapuolesta, kahdesta mintistä ja nonce-arvosta. Kukin escrow on tietueen associated token account toiselle mintille. Molemmat johdot toimivat ilman verkkoyhteyttä.

Käytä jokaiselle kaupalle satunnaista 64-bittistä nonce-arvoa. Koska luonti on luvanvaraisuudesta vapaata, ennustettava nonce antaa kolmannelle osapuolelle mahdollisuuden varata osoitteen, jota kauppa aikoi käyttää. Anna nonce ja summat TypeScriptissä bigint-tyyppisinä; generoitu asiakasohjelma hylkää number-arvon.

Korvaa jokainen ..._HERE-paikkamerkki oikealla osoitteella ennen suoritusta. address() validoi base58-muodon ja heittää virheen paikkamerkistä, ja pubkey! ei käänny.

import { address, createClient } from "@solana/kit";
import { solanaRpc } from "@solana/kit-plugin-rpc";
import { signer } from "@solana/kit-plugin-signer";
import { TOKEN_2022_PROGRAM_ADDRESS } from "@solana-program/token-2022";
import { findSwapDvpEscrowAta, findSwapDvpPda } from "./dvp";
const client = createClient()
.use(signer(payerSigner))
.use(
solanaRpc({
rpcUrl: "https://api.devnet.solana.com",
rpcSubscriptionsUrl: "wss://api.devnet.solana.com",
}),
);
const settlementAuthority = address("SETTLEMENT_AUTHORITY_ADDRESS_HERE");
const userA = address("ASSET_LEG_PARTY_ADDRESS_HERE");
const userB = address("CASH_LEG_PARTY_ADDRESS_HERE");
const mintA = address("ASSET_MINT_ADDRESS_HERE");
const mintB = address("CASH_MINT_ADDRESS_HERE");
const tokenProgramA = TOKEN_2022_PROGRAM_ADDRESS;
const tokenProgramB = TOKEN_2022_PROGRAM_ADDRESS;
// A fresh random nonce per trade, as a bigint.
const nonce = new DataView(
crypto.getRandomValues(new Uint8Array(8)).buffer,
).getBigUint64(0);
const [swapDvp] = await findSwapDvpPda({
settlementAuthority,
userA,
userB,
mintA,
mintB,
nonce,
});
const [escrowA] = await findSwapDvpEscrowAta({
swapDvp,
mint: mintA,
tokenProgram: tokenProgramA,
});
const [escrowB] = await findSwapDvpEscrowAta({
swapDvp,
mint: mintB,
tokenProgram: tokenProgramB,
});

Tallenna ehdot

CreateDvp ottaa vastaan kaksi summaa perusyksiköissä, erääntymisajan, nonce-arvon ja neljä valinnaista kenttää: enintään 64 tavun mittaisen läpinäkymättömän viitteen, kummallekin osapuolelle selvityskohteen sekä aikaisimman selvitysajan (ks. Huomautukset). Selvityskohde on se paikka, johon kyseisen osapuolen tuotot päätyvät selvityksessä, esimerkiksi säilyttäjän talletuslompakko; oletuksena se on osapuolen oma osoite, ja se lukitaan, kun tietue on luotu. Hyvitykset ja takaisinvaatimukset menevät aina osapuolen omalle token accountille kyseisen osuuden mintille, ei koskaan selvityskohteeseen, riippumatta siitä, kuka escrow'n rahoitti.

Maksaja rahoittaa tietueen, nonce-tombstonen ja molempien escrow-tilien rentin. Suljettaessa tämä rent menee sulkevan käskyn allekirjoittajalle, ei takaisin maksajalle. Tombstonea ei koskaan suljeta, joten jokainen kauppa jättää jälkeensä pienen pysyvän saldon. Kun budjetoit maksajan SOL-määrää, johda rent-summat getMinimumBalanceForRentExemption RPC-metodilla sen sijaan, että kovakoodaisit ne.

import { getCreateDvpInstruction } from "./dvp";
const nowSeconds = BigInt(Math.floor(Date.now() / 1000));
const createInstruction = getCreateDvpInstruction({
payer: payerSigner,
swapDvp,
nonceTombstone: (
await getProgramDerivedAddress({
programAddress: DVP_SWAP_PROGRAM_PROGRAM_ADDRESS,
seeds: ["nonce", getAddressEncoder().encode(swapDvp)],
})
)[0],
settlementAuthority,
userA,
userB,
mintA,
mintB,
dvpAtaA: escrowA,
dvpAtaB: escrowB,
tokenProgramA,
tokenProgramB,
amountA: 1_000_000_000n, // 1,000 units of a 6-decimal asset
amountB: 998_500_000n, // 998.50 units of a 6-decimal cash token
expiryTimestamp: nowSeconds + 60n * 60n * 24n, // one day
nonce,
refString: "ORDER-2026-10-02-0001",
userASettlementDestination: null, // defaults to userA
userBSettlementDestination: null, // defaults to userB
earliestSettlementTimestamp: null,
});
const { context } = await client.sendTransaction([createInstruction]);
console.log("Trade record:", swapDvp, "signature:", context.signature);

TypeScript-esimerkki tarvitsee getProgramDerivedAddress- ja getAddressEncoder-funktiot paketista @solana/kit sekä DVP_SWAP_PROGRAM_PROGRAM_ADDRESS-vakion asiakasohjelmasta näkyvyysalueellaan. Rust-builder jättää System Programin ja Associated Token Programin oletusarvoihinsa.

Huomautukset

  • Erääntymisaika. Vain Settle tarkistaa erääntymisajan. Reclaim, Cancel ja Reject toimivat sen jälkeenkin, ja erääntymisen jälkeen tehdyn talletuksen voi periä takaisin kyseisen osuuden osapuoli. Erääntymisaika voi olla enintään vuoden luonnista.
  • Aika on verkon aikaa. Ohjelma lukee ketjun sisäistä kelloa, joka voi poiketa seinäkellon ajasta, ajoittain kymmenillä sekunneilla, ja voi hypätä eteenpäin. Jätä erääntymisajan ja aiotun selvitysajan väliin marginaali, vältä rahoittamista tai selvitystä lähellä kumpaakaan rajaa äläkä luota siihen, että erääntymisaika pakottaisi määräajan sekunnin tarkkuudella. Ohjelman README suosittelee varaamaan noin minuutin poikkeaman.
  • Aikaisin selvitys. Valinnainen. Jos asetettu, Settle hylätään ennen sitä, eikä se saa olla erääntymisaikaa myöhäisempi.
  • Luontihetken tarkistukset. Create epäonnistuu virheeseen PartyNotSignerCapable, jos osapuoli ei ole tili, jonka omistaa System Program (tämä sulkee pois SPL Token -multisigin), tai virheisiin SettlementDestinationIsSwapDvp, SelfDvp, SameMint, ZeroAmount, SettlementAuthorityIsParty tai ExpiryNotInFuture. Täydellinen luettelo on virhetaulukossa.

Seuraavat vaiheet

  • Rahoita osuudet: kumpikin osapuoli siirtää osuutensa kaupan escrow-tilille

Is this page helpful?

Sisällysluettelo

Muokkaa sivua
© 2026 Solana Foundation. Kaikki oikeudet pidätetään.