Ikhtisar
Penarikan dari Private Channels adalah proses dua langkah. Pertama, pengguna membakar
saldo token sisi channel dengan memanggil WithdrawFunds pada Withdraw
Program. Kedua, operator memanggil ReleaseFunds pada Escrow Program (devnet,
dalam panduan ini) dengan bukti eksklusi Sparse Merkle Tree yang valid untuk melepaskan
dana. Bukti SMT memastikan setiap nonce penarikan hanya dapat digunakan sekali,
mencegah double-spend.
Langkah 1: Inisiasi Penarikan di Channel
Panggil WithdrawFunds pada Withdraw Program untuk membakar saldo sisi channel Anda.
Gunakan varian Async, yang secara otomatis menurunkan PDA tokenAccount dan merupakan
bentuk yang direkomendasikan untuk penggunaan produksi:
import { getWithdrawFundsInstructionAsync } from "../private-channel-withdraw-program/clients/typescript/src/generated";import {createSolanaRpc,address,pipe,createTransactionMessage,setTransactionMessageFeePayerSigner,setTransactionMessageLifetimeUsingBlockhash,appendTransactionMessageInstruction,signAndSendTransactionMessageWithSigners,assertIsTransactionMessageWithSingleSendingSigner,getBase58Decoder} from "@solana/kit";// Point to the gateway, not a public Solana RPCconst privateChannelRpc = createSolanaRpc("http://localhost:8899");const withdrawIx = await getWithdrawFundsInstructionAsync({user: userSigner,mint: address(mintAddress),amount: 1_000_000n, // 1 USDC (6 decimals)destination: null // null = release to signer's devnet wallet});const { value: latestBlockhash } = await privateChannelRpc.getLatestBlockhash({ commitment: "confirmed" }).send();// Sent to the Private Channels gateway (not Solana RPC directly), which// expects the legacy transaction format - do not switch this to version 0.const transactionMessage = pipe(createTransactionMessage({ version: "legacy" }),(m) => setTransactionMessageFeePayerSigner(userSigner, m),(m) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m),(m) => appendTransactionMessageInstruction(withdrawIx, m));assertIsTransactionMessageWithSingleSendingSigner(transactionMessage);const signatureBytes =await signAndSendTransactionMessageWithSigners(transactionMessage);const signature = getBase58Decoder().decode(signatureBytes);console.log("Withdrawal initiated:", signature);
- ID Withdraw Program:
J231K9UEpS4y4KAPwGc4gsMNCjKFRMYcQBcjVW7vBhVi - Kirimkan transaksi ini ke gateway (
http://localhost:8899), bukan ke RPC Solana publik - Jika
destinationdisediakan, dana yang dilepaskan akan dikirim ke dompet tersebut, bukan ke dompet penandatangan
Yang Dapat Diharapkan
Tidak diperlukan tindakan lebih lanjut setelah memanggil WithdrawFunds. Layanan operator
menangani penyelesaian secara otomatis:
indexer-private-channelmelakukan polling channel setiap 1 detik untuk event pembakaran dan menulis catatan penarikan yang tertunda saat penarikan Anda terdeteksioperator-private-channelmelakukan polling database setiap 1 detik untuk catatan yang tertunda dan mengirimkanReleaseFundske Escrow Program di Solana devnet dengan bukti eksklusi SMT yang diperlukan; ia melakukan polling untuk konfirmasi devnet hingga 5 kali dengan interval 400 md sebelum mencoba ulang
Dana biasanya muncul di dompet devnet Anda dalam beberapa detik dalam kondisi normal.
Cara Operator Menyelesaikan (Referensi)
Setelah pembakaran sisi channel, operator yang telah diprovisikan harus memanggil ReleaseFunds pada
Escrow Program dengan bukti eksklusi SMT yang valid; operator tidak dapat melepaskan
dana tanpa membuktikan bahwa nonce penarikan belum pernah digunakan sebelumnya. Langkah ini
ditangani secara otomatis oleh operator-private-channel; Anda tidak perlu memanggilnya
sendiri.
Operator menyediakan:
amount: harus sesuai dengan jumlah yang dibakaruser: dompet penerima di devnetnew_withdrawal_root: root SMT yang diperbarui setelah penarikan initransaction_nonce: nonce unik untuk leaf inisibling_proofs: 512 byte (16 x 32-byte sibling hash untuk bukti pohon)
Verifikasi
Setelah panggilan operator dikonfirmasi, periksa saldo token devnet Anda:
spl-token balance <MINT_ADDRESS> --owner <YOUR_WALLET>
Atau melalui RPC:
import { createSolanaRpc, address } from "@solana/kit";import { findAssociatedTokenPda } from "@solana-program/token";const TOKEN_PROGRAM_ADDRESS = address("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");// Query devnet directly; ReleaseFunds settles here, not through the gatewayconst rpc = createSolanaRpc("https://api.devnet.solana.com");const [yourDevnetAta] = await findAssociatedTokenPda({mint: address(mintAddress),owner: address(userSigner.address),tokenProgram: TOKEN_PROGRAM_ADDRESS});const balance = await rpc.getTokenAccountBalance(yourDevnetAta).send();console.log(balance.value.uiAmountString);
Anda Telah Menyelesaikan Quickstart
Anda telah menjalankan siklus Private Channels secara penuh di devnet: menyetor token SPL ke escrow, mengirimkan transfer off-chain melalui gateway, dan menarik dana kembali ke dompet devnet Anda.
Siklus Hidup Channel
Pahami peserta dan alur lengkap dari deposit hingga penarikan secara mendalam.
Autentikasi & Peran
Tambahkan autentikasi JWT ke integrasi Anda.
Referensi Release Funds
Referensi instruksi ReleaseFunds lengkap untuk tooling operator.
Sparse Merkle Tree
Pahami bagaimana bukti penarikan mencegah double-spend.
Is this page helpful?