Build a SolidJS Web App with Wallet Integration
This tutorial will teach you how to create a web application client using the SolidJS reactive user interface framework and the Solid Algo Wallets library to provide integration with an array of wallets for signing Algorand transactions.
The solid-algo-wallets Javascript package was developed to provide developers with an easy way to add multi-wallet integration to their apps and support web developers who prefer not to build user interface logic with React. SolidJS is a lightweight, performant framework which provides reactive signals that can be read throughout the app.
By the end of the tutorial you will have a simple web app to which people can connect one of several wallets–a great jumping-off point to build your own Algorand-based app idea!
This work has been performed with support from the Algorand Foundation xGov Grants Program.
Requirements
To complete this tutorial, you should have the following:
- Understanding of HTML + Javascript-based web application development
- Familiarity with the SolidJS framework for reactive signals
- Experience with one or more self-custody cryptocurrency wallets that support Algorand
- Access to VSCode or a similar integrated developer environment (IDE) for Javascript development
Background
The solid-algo-wallets library provides a simple, unified interface for integrating Algorand wallets into a web application client built with SolidJS.
Importing solid-algo-wallet into your app client provides convenient functions to:
- Access multiple wallet interfaces
- Get icons and images for the wallets for use in your app’s interface
- Connect to a user’s wallet and get selected Algorand accounts
- Select an account to use in the app to fetch data and prepare transactions
- Provide the selected account as a reactive signal for use throughout the SolidJS app
- Sign transactions with the connected wallet account and return them to the app
- Automatically reconnect to the wallet on page reload for smoother user experience
The code of an example app using this library can be explored at https://github.com/SilentRhetoric/solid-algo-wallets-example. A live demo is available at https://solid-algo-wallets-example.netlify.app .
Steps
1. Set up your development environment
From your terminal in the directory where you want to create your project, clone the example application repository from GitHub:
git clone https://github.com/SilentRhetoric/solid-algo-wallets-example.git
Navigate to the cloned directory and launch the project in VSCode:
cd solid-algo-wallets-example && code .
Now that you have the project open, install the project’s dependencies:
npm install
or yarn install
or pnpm install
Next, set up your .env file using the .env.template example file.
Then, to start a local development server run npm run dev
and open http://localhost:3000 to view it in the browser. Vite’s hot module replacement will reload the page if you make edits to the site code as you develop.
You should now see the example application in your browser!
2. Explore the wallet interfaces
Solid Algo Wallets exposes a standard interface for a SolidJS web app to connect to a user’s wallet, providing several different options for a user to connect. To try out the wallet workflow, select the Algorand network on which you want to send a test transaction and click on one of the buttons for a wallet you have.
There are a few different types of wallets out there, and the workflow to interact with them is somewhat different. Below is an brief introduction to the different types of wallets.
Mobile Wallets, including Pera and Defly
For these mobile wallets, clicking the app button will launch a modal with a QR code that can be scanned with the user’s mobile wallet via the camera. This will establish a connection over WalletConnect–either the old v1 or the current v2 protocol–to enable accounts and transactions to be sent back and forth. Although the generic WalletConnect interface works for many wallets, wallet-specific modals may or may not work for wallets other than the one who provided the modal because they may route the connection to a proprietary relay server. These wallets generally work on multiple networks including MainNet and TestNet but not all networks.
Web-Based Wallets, including Pera and MyAlgo
Pera also provides a web-based wallet that is accessible in the browser and uses the browser’s storage to manage wallet keys. MyAlgo is another example of a web-based wallet. They both are accessed through another browser window, either as a pop-up window or in another tab. Clicking the button for one of these wallets will prompt the user to unlock the wallet, after which accounts and transactions can be passed. These wallets can be configured to work on multiple networks but not all.
WalletConnect
The WalletConnect interface can be used to connect a app to many other wallets which support WalletConnect, so long as the wallet supports Algorand. Clicking the WalletConnect button will open a modal with a QR code that can be scanned with the user’s mobile wallet via the camera. This will communicate back and forth over a relay server owned by WalletConnect and enable accounts to be passed from the wallet to the app and transactions to be sent from the app to the wallet for signing. WalletConnect’s v2 protocol for Algorand works for MainNet, TestNet, and BetaNet networks provided the wallet supports that network.
Browser Extension Wallets, including Exodus and MetaMask
Exodus and MetaMask are examples of wallets which can be installed as Chrome browser extensions. Clicking the button for these wallets will launch the extension within Chrome as long as the extension has been enabled, either generally for all sites or specifically for the app’s domain. After unlocking the wallet, the app will be able to get accounts from the wallet and subsequently pass transactions to it to be signed. Note that these wallets may only work on certain networks; Exodus, for example, only works on MainNet. MetaMask support is very experimental as the “Snap” for Algorand is not yet available on the production version of MetaMask’s browser extension but can be used with MetaMask Flask.
Ledger Hardware Wallet via USB
The Ledger interface can be used in Chrome through its USB device interface to connect directly to a Ledger hardware wallet that is plugged into the user’s computer directly via a USB cable. The device needs to be unlocked, and then connecting to it will yield a number of accounts. Sending transactions to the Ledger for signing will make them appear on the screen of the device for approval in series, one transaction after another. When all transactions have been signed, the workflow is complete and the app can send the transactions to the network. The Ledger should be able to sign transactions on any network.
AlgoKit LocalNet KMD for Sandbox Development
When working locally to develop your app, you will probably be using AlgoKit’s LocalNet sandbox network to quickly iterate and test your code. A way to connect to the Key Management Daemon (KMD) within a LocalNet network is included in the library. Clicking this button will immediately communicate with the KMD via http://localhost. Upon connecting, KMD will tell the app what wallets & accounts it has available. Upon signing a transaction, KMD will sign the transactions straight away on behalf of whatever account is provided; there is no user interface involved. Note that this wallet only works on LocalNet, and the example app automatically switches itself to Localnet when this wallet is selected.
3. Expand on the example to build an app
This example app demonstrates a minimal example of how to send an Algorand transaction to a wallet to be signed. The creation of the transaction, instantiation of an AtomicTransactionComposer (ATC), and the execution of that ATC are encapsulated in a single simple function to get you started.
The UseSolidAlgoWallets hook makes it easy to create an algokit-utils TransactionSignerAccount
object by providing the address from the connected wallet along with a signer function that can sign transactions for that address via the wallet interface.
const {
address, // A reactive SolidJS signal that returns the wallet address
transactionSigner, // A function to sign with the connected wallet
} = UseSolidAlgoWallets
const transactionSignerAccount = createMemo<TransactionSignerAccount>(() => ({
addr: address(),
signer: transactionSigner,
}))
async function sendTxn() {
setConfirmedTxn("")
const suggestedParams = await algodClient().getTransactionParams().do()
const payTxn = makePaymentTxnWithSuggestedParamsFromObject({
from: address(),
to: address(),
amount: 0,
suggestedParams,
})
const txn = await algokit.getTransactionWithSigner(payTxn, transactionSignerAccount())
const atc = new AtomicTransactionComposer()
atc.addTransaction(txn)
const result = await atc.execute(algodClient(), 4)
console.log("Txn confirmed: ", result)
setConfirmedTxn(result.txIDs[0])
}
You can scaffold from here to create whatever transactions your app requires. The Atomic Transaction Composer is a powerful tool that allows you to define multiple transactions and add them to a group in sequence to build more complex groups of transactions that will be submitted and approved together.
To see the full code of the example app and get started with developing your own, visit https://github.com/SilentRhetoric/solid-algo-wallets-example.
Learn more about how the Solid Algo Wallets library works visit https://github.com/SilentRhetoric/solid-algo-wallets
4. Thank you!
I appreciate the support of Algorand xGovernors who voted in xGov Period 1 to support the development of this code library, example app, and tutorial.
Thanks to the Algorand Foundation for their stewardship of the grants program, the developer community, and this resource portal.
Special thanks to Doug from TxnLab for your inspiration, help, and encouragement along the way of building this multi-wallet integration library.