Panoramica
Il prelievo da Private Channels è un processo in due fasi. Prima, l'utente brucia
il proprio saldo di token lato canale chiamando WithdrawFunds sul Withdraw
Program. Poi, un operatore chiama ReleaseFunds sull'Escrow Program (devnet,
in questa guida) con una prova di esclusione Sparse Merkle Tree valida per rilasciare
i fondi. La prova SMT garantisce che ogni nonce di prelievo possa essere utilizzato una sola volta,
prevenendo il double-spend.
Fase 1: Avvia il Prelievo sul Canale
Chiama WithdrawFunds sul Withdraw Program per bruciare il tuo saldo lato canale.
Usa la variante Async, che deriva automaticamente il PDA tokenAccount ed è la
forma consigliata per l'uso in produzione:
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 del Withdraw Program:
J231K9UEpS4y4KAPwGc4gsMNCjKFRMYcQBcjVW7vBhVi - Invia questa transazione al gateway (
http://localhost:8899), non a un RPC Solana pubblico - Se
destinationè specificato, i fondi rilasciati vengono inviati a quel wallet invece che a quello del firmatario
Cosa Aspettarsi
Non è richiesta alcuna azione aggiuntiva dopo aver chiamato WithdrawFunds. I servizi
dell'operatore gestiscono il settlement automaticamente:
indexer-private-channelinterroga il canale ogni 1 secondo per gli eventi di burn e registra un record di prelievo in sospeso quando il tuo viene rilevatooperator-private-channelinterroga il database ogni 1 secondo per i record in sospeso e inviaReleaseFundsall'Escrow Program su Solana devnet con la prova di esclusione SMT richiesta; verifica la conferma su devnet fino a 5 volte a intervalli di 400 ms prima di riprovare
I fondi appaiono in genere nel tuo wallet devnet entro pochi secondi in condizioni normali.
Come l'Operatore Esegue il Settlement (Riferimento)
Dopo il burn lato canale, un operatore abilitato deve chiamare ReleaseFunds sull'
Escrow Program con una prova di esclusione SMT valida; l'operatore non può rilasciare
i fondi senza dimostrare che il nonce di prelievo non sia già stato utilizzato in precedenza. Questo passaggio
viene gestito automaticamente da operator-private-channel; non è necessario chiamarlo
manualmente.
L'operatore fornisce:
amount: deve corrispondere all'importo bruciatouser: wallet destinatario su devnetnew_withdrawal_root: radice SMT aggiornata dopo questo prelievotransaction_nonce: nonce univoco per questa fogliasibling_proofs: 512 byte (16 hash fratello da 32 byte per la prova dell'albero)
Verifica
Dopo la conferma della chiamata dell'operatore, controlla il tuo saldo token su devnet:
spl-token balance <MINT_ADDRESS> --owner <YOUR_WALLET>
Oppure tramite 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);
Hai Completato il Quickstart
Hai eseguito l'intero ciclo di Private Channels su devnet: depositato token SPL nell' escrow, inviato un trasferimento off-chain tramite il gateway e prelevato i fondi nel tuo wallet devnet.
Ciclo di Vita del Canale
Approfondisci i partecipanti e l'intero flusso dal deposito al prelievo.
Autenticazione e Ruoli
Aggiungi l'autenticazione JWT alla tua integrazione.
Riferimento Release Funds
Riferimento completo dell'istruzione ReleaseFunds per gli strumenti dell'operatore.
Sparse Merkle Tree
Scopri come le prove di prelievo prevengono il double-spend.
Is this page helpful?