Skip to content

Using Solana wallets

Getting the Solana address

Once a user has connected an external Solana wallet or created their embedded Solana wallet, to find the user's Solana address, first find the WalletWithMetadata object from the user's user.linkedAccounts array with walletClientType: 'privy' and chainType: 'solana':

tsx
const {user} = usePrivy();
const wallet = user.linkedAccounts.find(
  (account): account is WalletWithMetadata =>
    account.type === 'wallet' &&
    account.walletClientType === 'privy' &&
    account.chainType === 'solana',
);

Next, inspect the address field of the WalletWithMetadata object to get the user's address:

tsx
console.log(wallet.address);
// 4tFqt2qzaNsnZqcpjPiyqYw9LdRzxaZdX2ewPncYEWLA

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 Dashbnoard 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 {wallets} = useSolanaWallets();
const solanaWallet = wallets[0];

// Build transaction request. You should adapt this logic for the particular
// type of transaction you need.
if (!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();

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