Please ask questions in the #developer-support channel on the Solana Discord: https://discord.com/invite/solana
After reading this FAQ, if you've found a bug or you'd like to request a feature, please open an issue.
Yes, see the react-ui-starter package.
Yes, use the useAnchorWallet() hook in the React package to easily get an Anchor-compatible Wallet interface.
Yes, see the nextjs-starter package for very basic configuration, or the example package for more complete configuration.
If you're using one of the react-ui, material-ui, or ant-design packages too, make sure to configure the WalletModalProvider or WalletDialogProvider context as shown here.
Yes, see the material-ui-starter package.
Yes, see the ant-design package.
Yes, see the vue package.
Yes, see the angular package.
Yes, but you may need to set up polyfills for certain imported modules.
For example, you may need to install buffer:
yarn add buffer
And configure webpack.config.js:
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.ProvidePlugin({
Buffer: ['buffer', 'Buffer']
})
],
resolve: {
fallback: {
crypto: false
}
}
};
Yes, but you may need to provide custom build configuration.
Most of the packages are built using the TypeScript compiler, which outputs modular ES6 with import/export statements.
If you're using Create React App, craco, or one of the React-based starter projects using them, this should be handled automatically.
If you're using Next.js, this requires configuration, which is provided in the nextjs-starter package.
If you're using something else, you may have to configure your build tool to transpile the packages similarly to how it's done in the Next.js config. Please open an issue or pull request to document your solution!
Failed to compile. [...] Module not found: Can't resolve [...]This can happen if you're cloning the project and building it from the source and you missed a step.
If this doesn't fix the problem, please open an issue.
[...] is not a function / [...] is undefined / Uncaught TypeError: Cannot destructure property / Uncaught (in promise) WalletNotConnectedErrorThis can happen if you don't wrap your dApp with the WalletContext and ConnectionContext provided by the react package.
See issues #62, #73, and #85.
This shouldn't happen if you're using one of the starter projects, since they set up the contexts for you.
[...] is not a functionThis can happen if you try to use signTransaction, signAllTransactions, or signMessage without checking if they are defined first.
sendTransaction is the primary method that all wallets support, and it signs transactions.
The other methods are optional APIs, so you have to feature-detect them before using them.
Please see issue #72.
Some wallet adapters provide a signMessage method for signing arbitrary bytes:
The signature string returned by this method can be verified using tweetnacl-js using the public key from the adapter.
This can be used to sign offline -- without sending a transaction -- and prove a user controls a given private key.
import { useWallet } from '@solana/wallet-adapter-react';
import bs58 from 'bs58';
import React, { FC, useCallback } from 'react';
import { sign } from 'tweetnacl';
export const SignMessageButton: FC = () => {
const { publicKey, signMessage } = useWallet();
const onClick = useCallback(async () => {
try {
// `publicKey` will be null if the wallet isn't connected
if (!publicKey) throw new Error('Wallet not connected!');
// `signMessage` will be undefined if the wallet doesn't support it
if (!signMessage) throw new Error('Wallet does not support message signing!');
// Encode anything as bytes
const message = new TextEncoder().encode('Hello, world!');
// Sign the bytes using the wallet
const signature = await signMessage(message);
// Verify that the bytes were signed using the private key that matches the known public key
if (!sign.detached.verify(message, signature, publicKey.toBytes())) throw new Error('Invalid signature!');
alert(`Message signature: ${bs58.encode(signature)}`);
} catch (error: any) {
alert(`Signing failed: ${error?.message}`);
}
}, [publicKey, signMessage]);
return signMessage ? (<button onClick={onClick} disabled={!publicKey}>Sign Message</button>) : null;
};