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 agreedconst expectedExpiry = 1_798_761_600n; // as agreed, unix secondsif (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_timestampsonrası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
- İşlemi uzlaştırın: uzlaştırma yetkilisi her iki bacağı tek bir işlemde takas eder
- Bir işlemi geri alın: işlem uzlaşmadığında fonlanmış bir bacağı kurtarma
Is this page helpful?