Bacakları Fonlayın

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

Bu sayfa, işlem oluşturma bölümünün devamıdır; istemci ve imzacılar olduğu gibi devam eder.

Şartları doğrulayın

Kayıt oluşturmak izin gerektirmez ve escrow adresleri şartlardan değil, yalnızca kayıttan ve mint'ten türetilir. Bu nedenle bir escrow hesabına yapılan transfer, hiç kabul etmediğiniz şartlara karşı gerçekleşebilir; buna karşı tarafınızın gelirini üçüncü bir adrese yönlendiren uzlaştırma hedefleri de dahildir. Fonlamadan önce SwapDvp hesabını okuyun ve üzerinde anlaşılan işlemle karşılaştırın.

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ı bu kontrollerin hiçbirini yapmaz. Taraflara, tutarlara, zamanlara ve hedeflere ilişkin kontroller, üzerinde anlaşılan işleme karşı çağıran tarafça yapılır.

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 uzlaştırma yetkilisi oluşturduysa, her alanı defter dışında üzerinde anlaştığınız şartlarla karşılaştırın. Kaydı siz oluşturduysanız, bu okuma kaydın gönderildiği gibi işlendiğini doğrular.

Escrow hesabına transfer

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

Denetimsiz bir Transfer değil, 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, o token'ın diğer herhangi bir transferinde olduğu gibi çözümlenip eklenmesini gerektirir.

userASigner olarak imzalayan varlık bacağı tarafı, 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ğı tarafı, escrow B için userBAtaB, mintB, userBSigner, t.amountB ve { programAddress: tokenProgramB } ile aynısını yapar.

confirmed durumunda görülen bir fonlama transferi yine de geçersiz kılınabilir. Program, uzlaştırma sırasında escrow bakiyesini zincir üzerinde okur; bu nedenle gerçekleşmemiş bir fonlama transferine karşı gönderilen Settle LegNotFunded ile 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 (native) bir escrow'un bakiyesini senkronize ettikten sonra okur; bu nedenle wrapped SOL escrow'una sistem transferiyle gönderilen lamport'lar sayılır. Başka herhangi bir mint'in escrow hesabına asla SOL göndermeyin: program bunu iade edemez ve hesabı kapatan kişiye gider.
  • Kapılı (gated) mint'ler. Default Account State değeri frozen olan bir mint'te escrow dondurulmuş olarak oluşturulur ve ihraççı çözene veya izin verene kadar transfer başarısız olur. Genel bakış, Token ACL ile etkileşimi açıklar.
  • Transfer hook'ları. Hook içeren escrow hesaplarını tam olarak üzerinde anlaşılan tutarda fonlayın. Bir fazlalık uzlaştırmada 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: Reclaim, tam tutarla yeniden fonlama ve tekrar uzlaştırma.
  • Süre dolumundan sonra fonlama. expiry_timestamp sonrasında bir transferi hiçbir şey engellemez. Transfer gerçekleşir, uzlaştırma artık mümkün olmaz ve bacağın tarafı onu işlem açıkken Reclaim ile, kapandıktan sonra ise Recover ile geri alır. Bkz. bir işlemi geri alma.
  • Önce kim fonlar. Program iki bacağı sıralamaz. Sıra tarafların kendi meselesidir; bir mint yetkilisi (freeze, pause veya transfer hook) escrow hesabını engellemedikçe, her iki taraf da uzlaştırmadan ö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.