Guthaben abheben

Ü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 RPC
const 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 destination angegeben 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:

  1. indexer-private-channel fragt den Kanal jede Sekunde nach Burn-Ereignissen ab und schreibt einen ausstehenden Auszahlungsdatensatz, wenn Ihrer erkannt wird
  2. operator-private-channel fragt die Datenbank jede Sekunde nach ausstehenden Datensätzen ab und sendet ReleaseFunds an 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 entsprechen
  • user: Empfänger-Wallet im Devnet
  • new_withdrawal_root: aktualisierte SMT-Root nach dieser Auszahlung
  • transaction_nonce: eindeutige Nonce für dieses Blatt
  • sibling_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 gateway
const 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.

Is this page helpful?

Inhaltsverzeichnis

Seite bearbeiten
© 2026 Solana Foundation. Alle Rechte vorbehalten.