Appearance
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 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 {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();
// 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));