Skip to content

Using Solana wallets

Getting wallet data

To get information about a connected wallet, first find the corresponding ConnectedWallet object from the wallets array.

Address

To get the wallet's address, use the object's address field:

tsx
const address = wallet.address;

Wallet client type

To get the wallet's wallet client type, inspect the object's walletClientType field:

tsx
const walletClientType = wallet.walletClientType;
const isEmbeddedWallet = walletClientType === 'privy';
Privy tip
The wallet client type refers to the client the user is using to interface with their wallet, such as the Solflare browser extension, the Phantom mobile app, or Privy's UIs within your app. Embedded wallets always have a walletClientType of 'privy'. External wallets' wallet client types will vary depending on the client the user is using (e.g. 'phantom', 'solflare', etc.).

Requesting a signature

To request a signature from a user's Solana wallet, you can use the signMessage function on the wallet:

tsx
// This assumes you have already created a Solana wallet for the user or they have connected one
const {wallets} = useSolanaWallets();

TIP

When signMessage is invoked for an embedded Solana wallet, Privy will open up a modal where your user can view the message being signed and confirm the signature. You can choose to disable this UI and show your own UI instead by disabling wallet UIs in the Privy Dashboard for your app.

As an example, you might request a signature from a user's Solana wallet like so:

tsx
const message = 'Hello world';
const {signature} = await wallets[0].signMessage(new TextEncoder().encode(message));

The request will then return an object containing an Ed25519 signature over the message, as a base64-encoded string. You can verify the signature as follows:

tsx
import bs58 from 'bs58';
import {Buffer} from 'buffer';
import nacl from 'tweetnacl';

// This assumes the `message` was originally a string
const result = nacl.sign.detached.verify(
  Buffer.from(message, 'base64'),
  Buffer.from(signature, 'base64'),
  bs58.decode(wallets[0].address),
);

Sending a transaction

In addition to signing messages, you can sign and send transactions on the Solana blockchain. Privy supports both legacy and v0 (versioned) transactions.

As an example, you can send a transaction on Solana with connected Solana external and embedded wallets like so:

tsx
import {PublicKey, Transaction, Connection, SystemProgram} from '@solana/web3.js';
import {useSolanaWallets} from '@privy-io/react-auth';

...

// The rest of this code must be placed within a React component
// Get Solana wallet
const {ready, wallets} = useSolanaWallets();
const solanaWallet = wallets[0];

// Build transaction request. You should adapt this logic for the particular
// type of transaction you need.
if (!ready || !solanaWallet) return;

// Configure your connection to point to the correct Solana network
let connection = new Connection(clusterApiUrl('devnet'));

// Build out the transaction object for your desired program
// https://solana-labs.github.io/solana-web3.js/classes/Transaction.html
let transaction = new Transaction();

// Send transaction
console.log(await wallet.sendTransaction!(transaction, connection));

Using custom SVMs

In addition to supporting transactions on Solana mainnet, devnet, and testnet, Privy also supports sending transactions on any blockchain that implements the Solana Virtual Machine (SVM).

You can send a transaction on a custom SVM by initializing the Connection instance for your transaction with the RPC URL for the SVM, like so:

tsx
// Initialize connection instance with custom SVM RPC URL
let connection = new Connection('insert-custom-SVM-rpc-url');

// Build out the transaction object for your desired program
// https://solana-labs.github.io/solana-web3.js/classes/Transaction.html
let transaction = new Transaction();

// Send transaction on custom SVM
console.log(await wallet.sendTransaction!(transaction, connection));