Takas Oluşturma

CreateDvp, bir takasın 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, yerleşim yetkilisinin operatöründen ya da üçüncü bir taraftan gelebilir ve diğer tüm katılımcılar, saklanan koşullara dayanarak işlem yapmadan önce bu koşulları doğrular (bkz. bacakları fonlayın).

Kod parçacıkları, ilgili hesapların ve imzalayanların görülebilmesi için yer tutucu adreslerle birlikte doğrudan oluşturulmuş (generated) istemciyi kullanır. Hedef ağ devnet'tir; program burada mainnet-beta ile aynı adreste dağıtılmıştır.

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.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

Bu sayfalar df9919e commit'ine göre yazılmıştır; TypeScript'te @solana/kit 8, Rust'ta ise solana-* 2.x crate'leri kullanılı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 yerleşim yetkilisi için TransactionSigner nesneleridir; ö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

Takas kaydı; yerleşim yetkilisi, iki taraf, iki mint ve bir nonce üzerinden türetilen bir program-derived address'tir. Her escrow, kaydın mint'lerden biri için kullanılan associated token account'udur. Her iki türetme de ağ erişimi gerektirmez.

Her takas için rastgele 64 bitlik bir nonce kullanın. Oluşturma işlemi izne tabi olmadığından, tahmin edilebilir bir nonce üçüncü bir tarafın takasın kullanacağı adresi işgal etmesine yol açabilir. TypeScript'te nonce'u ve tutarları bigint olarak geçirin; oluşturulmuş 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ı, nonce'u ve dört isteğe bağlı alanı alır: en fazla 64 bayttan oluşan opak bir referans, her taraf için bir yerleşim hedefi ve en erken yerleşim zamanı (bkz. Notlar). Hedef, ilgili tarafın gelirinin yerleşim anı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 değiştirilemez. İadeler ve geri alımlar, escrow'u kim fonlamış olursa olsun, her zaman tarafın o bacağın mint'i için kullanılan kendi token account'una gider; hiçbir zaman bir hedefe gitmez.

Ödeyici; kayıt, nonce tombstone'u ve iki escrow için gereken rent'i karşılar. Kapatma sırasında bu rent, ödeyiciye geri dönmez; kapatma talimatını imzalayan kişiye gider. Tombstone hiçbir zaman kapatılmaz, bu yüzden her takas geride küçük bir kalıcı bakiye bırakır. Ödeyicinin 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 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 kod parçacığı için @solana/kit içinden getProgramDerivedAddress ve getAddressEncoder, istemciden ise DVP_SWAP_PROGRAM_PROGRAM_ADDRESS kapsamda olmalıdır. Rust builder'ı, system program ve associated token program'ı varsayılan değerlerinde bırakır.

Notlar

  • Son kullanma zamanı. Son kullanma zamanını yalnızca Settle denetler. Reclaim, Cancel ve Reject bu zamandan sonra da çalışır; son kullanma zamanından sonra gelen bir mevduat, ilgili bacağın tarafı tarafından geri alınabilir. Son kullanma zamanı, oluşturmadan en fazla bir yıl sonrası olabilir.
  • Zaman, ağ zamanıdır. Program zincir üstü saati okur; bu saat duvar saatinden bazen onlarca saniye farklı olabilir ve ileri doğru sıçrayabilir. Son kullanma zamanı ile planlanan yerleşim zamanı arasında pay bırakın, bu sınırlardan birine yakın bir zamanda fonlama veya yerleşim yapmaktan kaçının ve saniyesi saniyesine bir son tarihi zorunlu kılmak için son kullanma zamanına güvenmeyin. Program README'si yaklaşık bir dakikalık sapma payı bırakılmasını önerir.
  • En erken yerleşim. İsteğe bağlıdır. Ayarlanırsa Settle bu zamandan önce reddedilir ve bu zaman son kullanma zamanından geç olamaz.
  • Oluşturma anı denetimleri. Bir taraf system program'a ait bir hesap değilse (bu, SPL Token multisig'i dışarıda bırakır) Create, PartyNotSignerCapable ile başarısız olur. Diğer hata kodları şunlardır: SettlementDestinationIsSwapDvp, SelfDvp, SameMint, ZeroAmount, SettlementAuthorityIsParty veya ExpiryNotInFuture. Tam liste hatalar tablosunda yer alır.

Sonraki adımlar

Is this page helpful?

İçindekiler

Sayfayı Düzenle
© 2026 Solana Vakfı. Tüm hakları saklıdır.