CreateDvp, bir işlemin koşullarını kaydeder ve tarafların fonlayacağı iki escrow hesabını oluşturur. Hiçbir token taşımaz. Herkes gönderebilir; dolayısıyla kayıt bir karşı taraftan, takas yetkilisinin operatöründen ya da üçüncü bir taraftan gelebilir ve diğer tüm katılımcılar, saklanan koşullara dayanarak harekete geçmeden önce bunları doğrular (bkz. leg'leri fonlama).
Kod parçacıkları, ilgili hesapların ve imzalayanların görünür olması için üretilmiş istemciyi doğrudan ve yer tutucu adreslerle kullanır. Programın mainnet-beta ile aynı adreste dağıtıldığı devnet'i hedefler.
Kurulum
2 Ekim 2026 itibarıyla DvP istemcileri için yayımlanmış bir paket yoktur. İkisi de depodaki programın IDL'inden üretilir ve kaynaktan kullanılır.
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
Bu sayfalar df9919e commit'ine göre yazılmıştır; TypeScript'te @solana/kit 8, Rust'ta solana-* 2.x crate'leri kullanılmıştır.
Her adım sayfasındaki kod parçacıkları birbirinin devamıdır: her sayfa, önceki sayfalarda tanımlanan istemciyi, imzalayanları ve adresleri kullanır. payerSigner, userASigner, userBSigner ve authoritySigner, sırasıyla rent ödeyicisi, iki taraf ve takas yetkilisi için TransactionSigner'lardır; örneğin createKeyPairSignerFromBytes ile elde edilebilirler. Rust kod parçacıkları talimatları oluşturur, imzalama ve göndermeyi çağıran tarafa bırakır.
Adresleri türetme
İşlem kaydı; takas yetkilisi, iki taraf, iki mint ve bir nonce üzerinden türetilen bir Program Derived Address'tir. Her escrow, kaydın mint'lerden birine ait associated token account'udur. Her iki türetme için de ağ erişimi gerekmez.
Her işlem için rastgele 64 bitlik bir nonce kullanın. Oluşturma izin gerektirmediğinden, tahmin edilebilir bir nonce üçüncü bir tarafın bir işlemin kullanacağı adresi işgal etmesine olanak tanır. TypeScript'te nonce'u ve tutarları bigint olarak geçirin; üretilmiş istemci number değerini reddeder.
Çalıştırmadan önce her ..._HERE yer tutucusunu gerçek bir adresle değiştirin. address() base58'i doğrular ve yer tutucuda hata fırlatır; pubkey! ise derlenmez.
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,});
Koşulları kaydetme
CreateDvp, temel birimlerle iki tutarı, bir son kullanma zamanını (expiry), nonce'u ve dört isteğe bağlı alanı alır: en fazla 64 baytlık opak bir referans, her taraf için bir takas varış adresi ve en erken takas zamanı (bkz. Notlar). Varış adresi, o tarafın gelirlerinin takas sırasında ulaştığı yerdir; örneğin bir saklama kuruluşunun yatırma cüzdanı. Varsayılan olarak tarafın kendi adresidir ve kayıt oluşturulduktan sonra sabitlenir. İadeler ve geri almalar, escrow'u kim fonlamış olursa olsun, hiçbir zaman varış adresine değil, her zaman tarafın o leg'in mint'ine ait kendi token account'una gider.
Ödeyen taraf; kayıt, nonce tombstone'u ve iki escrow için rent'i karşılar. Kapatma sırasında bu rent, ödeyene geri dönmez; kapatma talimatını imzalayana gider. Tombstone hiçbir zaman kapatılmaz, bu yüzden her işlem küçük bir kalıcı bakiye bırakır. Ödeyenin SOL bütçesini planlarken rent tutarlarını sabit kodlamak yerine getMinimumBalanceForRentExemption RPC yöntemiyle türetin.
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);
TypeScript kod parçacığı için kapsamda @solana/kit içinden getProgramDerivedAddress ve getAddressEncoder, istemciden ise DVP_SWAP_PROGRAM_PROGRAM_ADDRESS bulunmalıdır. Rust builder'ı, System Program ve Associated Token Program'ı varsayılan değerlerinde bırakır.
Notlar
- Son kullanma zamanı. Expiry'yi yalnızca Settle denetler. Reclaim, Cancel ve Reject bu zamandan sonra da çalışır ve expiry'den sonra yatırılan bir mevduat, ilgili leg'in tarafı tarafından geri alınabilir. Expiry, oluşturmadan en fazla bir yıl sonrası olabilir.
- Zaman, ağ zamanıdır. Program, duvar saatinden bazen onlarca saniye farklı olabilen ve ileri sıçrayabilen onchain saati okur. Expiry ile hedeflenen takas zamanı arasında pay bırakın, bu sınırların ikisine de yakın bir zamanda fonlama veya takas yapmaktan kaçının ve saniyesi saniyesine bir son tarihi uygulatmak için expiry'ye güvenmeyin. Program README'si yaklaşık bir dakikalık sapmanın bütçelenmesini önerir.
- En erken takas. İsteğe bağlıdır. Ayarlanırsa Settle bu zamandan önce reddedilir ve bu zaman expiry'den sonra olmamalıdır.
- Oluşturma anı denetimleri. Create; bir taraf System Program'a ait bir hesap değilse (bu, SPL Token multisig'i dışarıda bırakır)
PartyNotSignerCapableile, ayrıcaSettlementDestinationIsSwapDvp,SelfDvp,SameMint,ZeroAmount,SettlementAuthorityIsPartyveyaExpiryNotInFutureile başarısız olur. Tam liste hata tablosunda yer alır.
Sonraki adımlar
- Leg'leri fonlayın: her taraf kendi leg'ini işlemin escrow'una aktarır
Is this page helpful?