CreateDvp mencatat ketentuan sebuah trade dan membuat dua akun escrow yang
akan didanai oleh para pihak. Instruksi ini tidak memindahkan token apa pun. Siapa pun dapat mengirimnya, sehingga record
bisa berasal dari counterparty, operator otoritas penyelesaian, atau pihak ketiga,
dan setiap peserta lain memverifikasi ketentuan yang tersimpan sebelum bertindak (lihat
danai kedua sisi).
Cuplikan kode menggunakan klien yang dihasilkan secara langsung, dengan alamat placeholder, sehingga akun dan signer yang terlibat terlihat jelas. Cuplikan ini menargetkan devnet, tempat program di-deploy pada alamat yang sama dengan mainnet-beta.
Instalasi
Per 2 Oktober 2026, belum ada paket yang dipublikasikan untuk klien DvP. Keduanya dihasilkan dari IDL program di repositori dan digunakan dari source.
git clone https://github.com/solana-foundation/dvp.gitcd dvp && git checkout df9919ed02c25a93620e7f6820107c9050ce3b92pnpm install && pnpm generate-clients && pnpm build# The client is clients/typescript/src; copy or link it into your project as ./dvppnpm add @solana/kit @solana/kit-plugin-rpc @solana/kit-plugin-signer @solana-program/token-2022 @solana-program/memo
Halaman-halaman ini ditulis berdasarkan commit df9919e, dengan @solana/kit 8 di
TypeScript dan crate solana-* 2.x di Rust.
Cuplikan kode di setiap halaman langkah saling berkelanjutan: setiap halaman menggunakan klien, signer,
dan alamat yang didefinisikan di halaman sebelumnya. payerSigner, userASigner,
userBSigner, dan authoritySigner adalah TransactionSigner untuk pembayar rent,
kedua pihak, dan otoritas penyelesaian, misalnya dari
createKeyPairSignerFromBytes. Cuplikan Rust membangun instruksi dan menyerahkan
penandatanganan serta pengiriman kepada pemanggil.
Menurunkan alamat
Record trade adalah program-derived address yang diturunkan dari otoritas penyelesaian, kedua pihak, kedua mint, dan sebuah nonce. Setiap escrow adalah associated token account milik record untuk salah satu mint. Kedua penurunan ini tidak memerlukan akses jaringan.
Gunakan nonce 64-bit acak untuk setiap trade. Karena pembuatan bersifat tanpa izin (permissionless), nonce
yang dapat ditebak memungkinkan pihak ketiga menempati alamat yang akan dipakai
oleh sebuah trade. Teruskan nonce dan jumlah sebagai bigint di TypeScript; klien
yang dihasilkan menolak number.
Ganti setiap placeholder ..._HERE dengan alamat yang sebenarnya sebelum dijalankan.
address() memvalidasi base58 dan melempar error pada placeholder, sedangkan pubkey! gagal
dikompilasi.
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,});
Mencatat ketentuan
CreateDvp menerima dua jumlah dalam satuan dasar, waktu kedaluwarsa, nonce, dan empat
bidang opsional: referensi opak hingga 64 byte, tujuan penyelesaian
untuk masing-masing sisi, dan waktu penyelesaian paling awal (lihat Catatan). Tujuan tersebut adalah
tempat hasil dari pihak itu diterima saat penyelesaian, misalnya dompet
deposit milik kustodian; secara default berupa alamat pihak itu sendiri dan tidak dapat diubah setelah
record dibuat. Refund dan reclaim selalu masuk ke token account milik pihak itu sendiri
untuk mint pada sisi tersebut, tidak pernah ke tujuan penyelesaian, siapa pun yang mendanai escrow.
Payer mendanai rent untuk record, tombstone nonce, dan kedua escrow.
Saat ditutup, rent tersebut diberikan kepada siapa pun yang menandatangani instruksi penutupan, bukan dikembalikan ke
payer. Tombstone tidak pernah ditutup, sehingga setiap trade menyisakan saldo permanen
yang kecil. Saat menganggarkan SOL payer, turunkan jumlah rent dengan metode RPC
getMinimumBalanceForRentExemption alih-alih menuliskannya secara hardcode.
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 assetamountB: 998_500_000n, // 998.50 units of a 6-decimal cash tokenexpiryTimestamp: nowSeconds + 60n * 60n * 24n, // one daynonce,refString: "ORDER-2026-10-02-0001",userASettlementDestination: null, // defaults to userAuserBSettlementDestination: null, // defaults to userBearliestSettlementTimestamp: null,});const { context } = await client.sendTransaction([createInstruction]);console.log("Trade record:", swapDvp, "signature:", context.signature);
Cuplikan TypeScript memerlukan getProgramDerivedAddress dan getAddressEncoder
dari @solana/kit, serta DVP_SWAP_PROGRAM_PROGRAM_ADDRESS dari klien, tersedia dalam
scope. Builder Rust membiarkan system program dan associated token program
pada nilai defaultnya.
Catatan
- Kedaluwarsa. Hanya Settle yang memeriksa waktu kedaluwarsa. Reclaim, Cancel, dan Reject tetap berfungsi setelahnya, dan deposit yang masuk setelah kedaluwarsa dapat dipulihkan oleh pihak pemilik sisi tersebut. Waktu kedaluwarsa paling lama satu tahun setelah pembuatan.
- Waktu adalah waktu jaringan. Program membaca jam onchain, yang dapat berbeda dari waktu jam dinding, terkadang hingga puluhan detik, dan dapat melompat maju. Sisakan margin antara waktu kedaluwarsa dan waktu penyelesaian yang direncanakan, hindari pendanaan atau penyelesaian mendekati salah satu batas, dan jangan mengandalkan waktu kedaluwarsa untuk menegakkan tenggat waktu hingga hitungan detik. README program menyarankan menganggarkan sekitar satu menit untuk selisih waktu.
- Penyelesaian paling awal. Opsional. Jika diatur, Settle akan ditolak sebelum waktu tersebut, dan waktunya tidak boleh lebih lambat dari waktu kedaluwarsa.
- Pemeriksaan saat pembuatan. Create gagal dengan
PartyNotSignerCapablejika suatu pihak bukan akun milik System Program (ini menyingkirkan multisig SPL Token),SettlementDestinationIsSwapDvp,SelfDvp,SameMint,ZeroAmount,SettlementAuthorityIsParty, atauExpiryNotInFuture. Daftar lengkapnya ada di tabel error.
Langkah berikutnya
- Danai kedua sisi: setiap pihak mentransfer sisinya ke escrow trade
Is this page helpful?