Übersicht
Das Abheben aus Private Channels ist ein zweistufiger Prozess. Zunächst verbrennt der Nutzer sein kanalseitiges Token-Guthaben, indem er WithdrawFunds im Withdraw Program aufruft. Anschließend ruft ein Operator ReleaseFunds im Escrow Program (Devnet, in dieser Anleitung) mit einem gültigen Sparse Merkle Tree-Ausschlussbeweis auf, um die Mittel freizugeben. Der SMT-Beweis stellt sicher, dass jede Auszahlungs-Nonce nur einmal verwendet werden kann, um Doppelausgaben zu verhindern.
Schritt 1: Auszahlung im Kanal initiieren
Rufen Sie WithdrawFunds im Withdraw Program auf, um Ihr kanalseitiges Guthaben zu verbrennen.
Verwenden Sie die Async-Variante, die das tokenAccount-PDA automatisch ableitet und die
empfohlene Form für den Produktionseinsatz ist:
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);
- Withdraw Program ID:
J231K9UEpS4y4KAPwGc4gsMNCjKFRMYcQBcjVW7vBhVi - Senden Sie diese Transaktion an das Gateway (
http://localhost:8899), nicht an einen öffentlichen Solana-RPC - Wenn
destinationangegeben ist, gehen die freigegebenen Mittel an diese Wallet anstatt an die des Signer
Was zu erwarten ist
Nach dem Aufruf von WithdrawFunds sind keine weiteren Aktionen erforderlich. Die Operator-Dienste
übernehmen die Abrechnung automatisch:
indexer-private-channelfragt den Kanal jede Sekunde nach Burn-Ereignissen ab und schreibt einen ausstehenden Auszahlungsdatensatz, wenn Ihrer erkannt wirdoperator-private-channelfragt die Datenbank jede Sekunde nach ausstehenden Datensätzen ab und sendetReleaseFundsan das Escrow Program auf Solana Devnet mit dem erforderlichen SMT-Ausschlussbeweis; es fragt bis zu 5 Mal in Abständen von 400 ms nach einer Devnet-Bestätigung, bevor es erneut versucht
Mittel erscheinen unter normalen Bedingungen typischerweise innerhalb weniger Sekunden in Ihrer Devnet-Wallet.
Wie der Operator abrechnet (Referenz)
Nach dem kanalseitigen Burn muss ein bereitgestellter Operator ReleaseFunds im Escrow Program
mit einem gültigen SMT-Ausschlussbeweis aufrufen; der Operator kann die Mittel nicht freigeben,
ohne nachzuweisen, dass die Auszahlungs-Nonce zuvor nicht verwendet wurde. Dieser Schritt
wird automatisch von operator-private-channel übernommen; Sie müssen ihn nicht selbst aufrufen.
Der Operator stellt Folgendes bereit:
amount: muss dem verbrannten Betrag entsprechenuser: Empfänger-Wallet im Devnetnew_withdrawal_root: aktualisierte SMT-Root nach dieser Auszahlungtransaction_nonce: eindeutige Nonce für dieses Blattsibling_proofs: 512 Bytes (16 x 32-Byte-Geschwister-Hashes für den Baumbeweis)
Überprüfen
Nachdem der Operator-Aufruf bestätigt wurde, prüfen Sie Ihr Devnet-Token-Guthaben:
spl-token balance <MINT_ADDRESS> --owner <YOUR_WALLET>
Oder per 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);
Sie haben den Schnellstart abgeschlossen
Sie haben den vollständigen Private Channels-Zyklus im Devnet durchlaufen: SPL-Token in das Escrow eingezahlt, eine Off-Chain-Übertragung über das Gateway gesendet und Mittel zurück in Ihre Devnet-Wallet abgehoben.
Kanal-Lebenszyklus
Verstehen Sie die Teilnehmer und den vollständigen Ablauf von der Einzahlung bis zur Auszahlung im Detail.
Authentifizierung & Rollen
Fügen Sie JWT-Authentifizierung zu Ihrer Integration hinzu.
Referenz: Mittel freigeben
Vollständige ReleaseFunds- Anweisungen-Referenz für Operator-Werkzeuge.
Sparse Merkle Tree
Verstehen Sie, wie Auszahlungsbeweise Doppelausgaben verhindern.
Is this page helpful?