Bacakları Fonlayın

Fonlama, bacağın escrow'una yapılan düz bir TransferChecked işlemidir; bu nedenle token transferi gönderebilen her cüzdan veya saklama sistemi bir bacağı fonlayabilir. Yalnızca fonlamadan önce işlem kaydını okumak için DvP istemcisi gerekir. Program, escrow bakiyelerini yalnızca takas anında kontrol eder; transfer gerçekleştiğinde onu hiçbir şey denetlemez, bu yüzden her taraf transfer yapmadan önce işlem kaydını okur.

Bu sayfa işlem oluşturma adımından devam eder; istemci ve imzalayanlar aynen geçerlidir.

Koşulları doğrulayın

Kayıt oluşturmak izin gerektirmez ve escrow adresleri yalnızca kayıttan ve mint'ten türetilir, koşullardan asla. Bu nedenle bir escrow'a yapılan transfer, hiç kabul etmediğiniz koşullara karşı gerçekleşebilir; karşı tarafınızın gelirlerini üçüncü bir adrese yönlendiren takas hedefleri de buna dahildir. Fonlamadan önce SwapDvp hesabını okuyun ve anlaşılan işlemle karşılaştırarak kontrol edin.

TypeScript'teki verifySwapDvp ve Rust'taki verify::decode_swap_dvp_account, hesabın DvP programına ait olduğunu, tam olarak 458 bayt olduğunu ve kendi alanlarından türetilen adreste bulunduğunu doğrular (fetchSwapDvpChecked yalnızca ilk iki kontrolü yapar). Düz fetchSwapDvp ve decodeSwapDvp okuyucuları bunların hiçbirini kontrol etmez. Taraflara, tutarlara, zamanlara ve hedeflere ilişkin kontrolleri, anlaşılan işleme göre çağıran taraf yapar.

import { unwrapOption } from "@solana/kit";
import { verifySwapDvp } from "./dvp";
const trade = await verifySwapDvp(client.rpc, swapDvp);
const t = trade.data;
const expectedAmountA = 1_000_000_000n;
const expectedAmountB = 998_500_000n;
const expectedEarliestSettlement: bigint | null = null; // as agreed
const expectedExpiry = 1_798_761_600n; // as agreed, unix seconds
if (
t.userA !== userA ||
t.userB !== userB ||
t.mintA !== mintA ||
t.mintB !== mintB ||
t.settlementAuthority !== settlementAuthority ||
t.tokenProgramA !== tokenProgramA ||
t.tokenProgramB !== tokenProgramB ||
t.amountA !== expectedAmountA ||
t.amountB !== expectedAmountB ||
unwrapOption(t.earliestSettlementTimestamp) !== expectedEarliestSettlement ||
t.expiryTimestamp !== expectedExpiry ||
t.userASettlementDestination !== userA ||
t.userBSettlementDestination !== userB
) {
throw new Error("Stored terms do not match the agreed trade; do not fund");
}
if (t.expiryTimestamp <= BigInt(Math.floor(Date.now() / 1000)) + 60n) {
throw new Error("Trade expires too soon to fund safely");
}

Kaydı karşı tarafınız veya takas yetkilisi oluşturduysa, her alanı defter dışında üzerinde anlaştığınız koşullarla karşılaştırın. Kaydı kendiniz oluşturduysanız, bu okuma kaydın gönderdiğiniz şekilde oluştuğunu doğrular.

Escrow'a transfer yapın

Bacağı tam olarak anlaşılan tutarda fonlayın. Program takası amount_x ile sınırlar ve fazlalığı bacağın tarafına iade eder; yani fazlalık kaybolmaz, ancak takas anında ikinci bir transfer ekler ve bazı transfer hook'larında başarısız olabilir (aşağıdaki notlara bakın).

Kontrolsüz bir Transfer yerine TransferChecked kullanın. Pausable gibi mint account'a bağlı uzantılara sahip Token-2022 mint'leri, bunu sağlamayan bir transferi reddeder; transfer hook'u olan bir mint ise, hook'un hesaplarının bu token'ın diğer herhangi bir transferinde olduğu gibi çözümlenip eklenmesini gerektirir.

Varlık bacağının tarafı, userASigner olarak imzalayarak escrow A'yı fonlar:

import {
findAssociatedTokenPda,
getTransferCheckedInstruction,
} from "@solana-program/token-2022";
const [userAAtaA] = await findAssociatedTokenPda({
mint: mintA,
owner: userA,
tokenProgram: tokenProgramA,
});
const [userBAtaB] = await findAssociatedTokenPda({
mint: mintB,
owner: userB,
tokenProgram: tokenProgramB,
});
const fundAssetLeg = getTransferCheckedInstruction({
source: userAAtaA,
mint: mintA,
destination: escrowA,
authority: userASigner,
amount: t.amountA,
decimals: 6,
}, { programAddress: tokenProgramA });
await client.sendTransaction([fundAssetLeg]);

Nakit bacağının tarafı, escrow B için aynısını userBAtaB, mintB, userBSigner, t.amountB ve { programAddress: tokenProgramB } ile yapar.

confirmed düzeyinde görülen bir fonlama transferi hâlâ geçersiz kılınabilir. Program, takas anında escrow bakiyesini zincir üzerinde okur; bu yüzden gerçekleşmemiş bir fonlama transferine karşı gönderilen Settle, LegNotFunded hatasıyla başarısız olur ve hiçbir şey hareket etmez; maliyet, başarısız bir Settle ve yeniden denemedir. Bir bacağı, transferi finalized olduğunda fonlanmış sayın.

Notlar

  • Wrapped SOL bacakları. Program, yerel bir escrow'un bakiyesini senkronize ettikten sonra okur; bu nedenle wrapped-SOL escrow'una sistem transferiyle gönderilen lamport'lar hesaba katılır. Başka herhangi bir mint'in escrow'una asla SOL göndermeyin: program bunu iade edemez ve hesabı kapatan kişiye gider.
  • Kısıtlı mint'ler. Default Account State değeri frozen olan bir mint'te escrow dondurulmuş olarak oluşturulur ve ihraççı dondurmayı kaldırana veya izin verene kadar transfer başarısız olur. Genel bakış sayfası Token ACL ile etkileşimi açıklar.
  • Transfer hook'ları. Hook içeren escrow'ları tam olarak anlaşılan tutarda fonlayın. Fazlalık takas anında iade gerektirirse, iade işlemi bacağın hook hesaplarını farklı bir hedef ve tutarla yeniden kullanır; bazı hook'lar bunu reddeder. Çözüm yolu şudur: Reclaim, tam tutarla yeniden fonlama ve yeniden takas.
  • Süre sonundan sonra fonlama. expiry_timestamp sonrasında yapılan bir transferi hiçbir şey engellemez. Transfer gerçekleşir, takas artık mümkün olmaz ve bacağın tarafı onu işlem açıkken Reclaim, kapandıktan sonra Recover ile geri alır. Bkz. bir işlemi geri alma.
  • Önce kim fonlar. Program iki bacağı sıralamaz. Sıra tarafların meselesidir; bir mint yetkilisi (dondurma, duraklatma veya transfer hook'u) escrow'u engellemediği sürece her iki taraf da takastan önce istediği zaman kendi bacağını geri alabilir.

Sonraki adımlar

Is this page helpful?

İçindekiler

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