Appearance
Hierarchical deterministic (HD) wallets
Privy's Solana embedded wallets are hierarchical deterministic (HD) wallets. An HD wallet allows you to generate multiple Solana addresses and private keys from a shared source of entropy: the wallet seed (or equivalently, a BIP-39 mnemonic encoding the seed, known as a seed phrase).
In kind, Privy can be used to provision multiple Solana embedded wallets for a single user. Read more below to learn how!
Read more about how HD wallets work.
HD wallets use a shared source of entropy to derive the wallet seed; this entropy is protected by the Privy cryptosystem.
Each wallet is generated from the seed and a unique path parameter, which has the format:
m / purpose' / coin_type' / account' / change / address_index
For Privy's Solana embedded wallets, the path used for the i
-th wallet is:
m/44'/501'/i/0'
where i
is 0-indexed. An HD wallet is said to have an index of i
if it is derived from the i
-th path above. You can read more about these derivation paths here.
Creating multiple HD wallets
To create multiple Solana wallets for a user, use the create
method from the useEmbeddedSolanaWallet
hook:
tsx
import {useEmbeddedSolanaWallet} from '@privy-io/expo';
...
const {create} = useEmbeddedSolanaWallet();
As an optional parameter to create
, you may pass an object containing the following fields:
Prop | Type | Description |
---|---|---|
createAdditional | boolean | If true , will allow the user to create a Solana wallet regardless if it is their first Solana wallet or an additional Solana wallet. If false , createWallet will succeed only if the use is creating their first wallet. Defaults to false . |
Once invoked, create
will return a Promise that resolves to the provider for the wallet created for the user, if it was successful. This method will reject with an error if:
- the user is not
authenticated
- the user already has an embedded Solana wallet and
createAdditional
was not set totrue
- if there is another error during wallet creation, such as the user exiting prematurely
Creating the user's first wallet
If this is the first wallet you are creating for the user (e.g. the 0th index), you may call create
with no parameters:
tsx
// Creating the first wallet for a user
const provider = await create();
Creating additional wallets
If the user already has an embedded wallet, and you are creating an additional embedded wallet, you must call create
with createAdditional
set to true
:
tsx
// Creating additional embedded wallets for the user
// You can also create the first wallet for the user using this syntax
const provider = await create({createAdditional: true});
Using multiple HD wallets
Once a user has one or more embedded wallets, the wallets are added to the wallets
array returned by useEmbeddedSolanaWallet
:
tsx
import {useEmbeddedSolanaWallet} from '@privy-io/expo';
...
const {wallets} = useEmbeddedSolanaWallet();
Each entry in the wallets
array is an object with the following fields:
Field | Type | Description |
---|---|---|
address | string | The address (base58-encoded public key) for the wallet. |
publicKey | string | The address (base58-encoded public key) for the wallet. |
walletIndex | number | The HD index for the wallet. |
getProvider | () => Promise<PrivyEmbeddedSolanaWalletProvider> | Method to get a provider for the wallet for requesting signatures and transactions. |
Getting a specific embedded wallet
To find a specific embedded wallet for the user, search the wallets
array for a wallet with the address
that matches your desired address:
tsx
const desiredAddress = 'insert-your-desired-wallet-address';
const {wallets} = useEmbeddedSolanaWallet();
const desiredWallet = wallets.find((wallet) => wallet.address === desiredAddress);
You can alternatively search the wallets array by your desired HD index:
tsx
// Replace this with your desired HD index
const desiredHdIndex = 0;
const {wallets} = useEmbeddedSolanaWallet();
const desiredWallet = wallets.find((wallet) => wallet.walletIndex === desiredHdIndex);
Requesting signatures and transactions
To request a signature or transaction from a specific embedded wallet, first find the corresponding wallet object from the wallets
array:
tsx
const desiredAddress = 'insert-your-desired-wallet-address';
const {wallets} = useEmbeddedSolanaWallet();
const wallet = wallets.find((wallet) => wallet.address === desiredAddress);
Then, call the object's getProvider
method to get a provider for the wallet:
tsx
const provider = await wallet.getProvider();
You can then easily request signatures from the provider
using its request
method, like so:
tsx
const message = 'Hello world';
const {signature} = await provider.request({
method: 'signMessage',
params: {
message: message,
},
});