Flow Dev Wallet
The Flow Dev Wallet is a mock Flow wallet that simulates the protocols used by FCL to interact with the Flow blockchain on behalf of simulated user accounts.
This project implements an FCL compatible interface, but should not be used as a reference for building a production grade wallet.
This project should only be used in aid of local development against a locally run instance of the Flow blockchain like the Flow emulator, and should never be used in conjunction with Flow Mainnet, Testnet, or any other instances of Flow.
To see a full list of Flow compatible wallets visit Wallets page
Getting Started​
Before using the dev wallet, you'll need to start the Flow emulator.
Install the flow-cli
​
The Flow emulator is bundled with the Flow CLI. Instructions for installing the CLI can be found here: flow-cli/install/
Create a flow.json
file​
Run this command to create flow.json
file (typically in your project's root directory):
_10flow init
Start the Emulator​
Start the Emulator and deploy the contracts by running the following command from the directory containing flow.json
in your project:
_10flow emulator start_10flow project deploy --network emulator
Configuring Your JavaScript Application​
The Flow Dev Wallet is designed to be used with @onflow/fcl
version 1.0.0
or higher. The FCL package can be installed with: npm install @onflow/fcl
or yarn add @onflow/fcl
.
To use the dev wallet, configure FCL to point to the address of a locally running Flow emulator and the dev wallet endpoint.
_10import * as fcl from "@onflow/fcl"_10_10fcl_10 .config()_10 // Point App at Emulator REST API_10 .put("accessNode.api", "http://localhost:8888")_10 // Point FCL at dev-wallet (default port)_10 .put("discovery.wallet", "http://localhost:8701/fcl/authn")
For a full example refer to Authenticate using FCL snippet
Test harness​
It's easy to use this FCL harness app as a barebones app to interact with the dev-wallet during development:
Navigate to http://localhost:8701/harness
Wallet Discovery​
Wallet Discovery offers a convenient modal and mechanism to authenticate users and connects to all wallets available in the Flow ecosystem.
The following code from Emerald Academy can be added to your React app to enable Wallet Discovery:
_55import { config, authenticate, unauthenticate, currentUser } from "@onflow/fcl";_55import { useEffect, useState } from "react";_55_55const fclConfigInfo = {_55 emulator: {_55 accessNode: 'http://127.0.0.1:8888',_55 discoveryWallet: 'http://localhost:8701/fcl/authn',_55 discoveryAuthInclude: []_55 },_55 testnet: {_55 accessNode: 'https://rest-testnet.onflow.org',_55 discoveryWallet: 'https://fcl-discovery.onflow.org/testnet/authn',_55 discoveryAuthnEndpoint: 'https://fcl-discovery.onflow.org/api/testnet/authn',_55 // Adds in Dapper + Ledger_55 discoveryAuthInclude: ["0x82ec283f88a62e65", "0x9d2e44203cb13051"]_55 },_55 mainnet: {_55 accessNode: 'https://rest-mainnet.onflow.org',_55 discoveryWallet: 'https://fcl-discovery.onflow.org/authn',_55 discoveryAuthnEndpoint: 'https://fcl-discovery.onflow.org/api/authn',_55 // Adds in Dapper + Ledger_55 discoveryAuthInclude: ["0xead892083b3e2c6c", "0xe5cd26afebe62781"]_55 }_55};_55_55const network = 'emulator';_55_55config({_55 "app.detail.title": "Emerald Academy", // the name of your DApp_55 "app.detail.icon": "https://academy.ecdao.org/favicon.png", // your DApps icon_55 "flow.network": network,_55 "accessNode.api": fclConfigInfo[network].accessNode,_55 "discovery.wallet": fclConfigInfo[network].discoveryWallet,_55 "discovery.authn.endpoint": fclConfigInfo[network].discoveryAuthnEndpoint,_55 // adds in opt-in wallets like Dapper and Ledger_55 "discovery.authn.include": fclConfigInfo[network].discoveryAuthInclude_55});_55_55export default function App() {_55 const [user, setUser] = useState({ loggedIn: false, addr: "" });_55_55 // So that the user stays logged in_55 // even if the page refreshes_55 useEffect(() => {_55 currentUser.subscribe(setUser);_55 }, []);_55_55 return (_55 <div className="App">_55 <button onClick={authenticate}>Log In</button>_55 <button onClick={unauthenticate}>Log Out</button>_55 <p>{user.loggedIn ? `Welcome, ${user.addr}!` : "Please log in."}</p>_55 </div>_55 );_55}
Account/Address creation​
You can create a new account by using the AuthAccount
constructor. When you do this, make sure to specify which account will pay for the creation fees by setting it as the payer.
The account you choose to pay these fees must have enough money to cover the cost. If it doesn't, the process will stop and the account won't be created.
_14transaction(publicKey: String) {_14 prepare(signer: AuthAccount) {_14 let key = PublicKey(_14 publicKey: publicKey.decodeHex(),_14 signatureAlgorithm: SignatureAlgorithm.ECDSA_P256_14 )_14 let account = AuthAccount(payer: signer)_14 account.keys.add(_14 publicKey: key,_14 hashAlgorithm: HashAlgorithm.SHA3_256,_14 weight: 1000.0_14 )_14 }_14}
To create a new Flow account refer to these resources
Get Flow Balance​
Retrieving the token balance of a specific account involves writing a script to pull data from onchain. The user may have both locked tokens as well as unlocked so to retrieve the total balance we would aggregate them together.
_31import * as fcl from "@onflow/fcl"_31import * as t from "@onflow/types"_31const CODE = `_31import "FungibleToken"_31import "FlowToken"_31import "LockedTokens"_31_31pub fun main(address: Address): UFix64 {_31 let account = getAccount(address)_31 let unlockedVault = account_31 .getCapability(/public/flowTokenBalance)!_31 .borrow<&FlowToken.Vault{FungibleToken.Balance}>()_31 ?? panic("Could not borrow Balance reference to the Vault")_31 let unlockedBalance = unlockedVault.balance_31 let lockedAccountInfoCap = account_31 .getCapability_31 <&LockedTokens.TokenHolder{LockedTokens.LockedAccountInfo}>_31 (LockedTokens.LockedAccountInfoPublicPath)_31 if lockedAccountInfoCap == nil || !(lockedAccountInfoCap!.check()) {_31 return unlockedBalance_31 }_31 let lockedAccountInfoRef = lockedAccountInfoCap!.borrow()!_31 let lockedBalance = lockedAccountInfoRef.getLockedAccountBalance()_31 return lockedBalance + unlockedBalance_31}`_31export const getTotalFlowBalance = async (address) => {_31 return await fcl.decode(await fcl.send([_31 fcl.script(CODE),_31 fcl.args([fcl.arg(address, t.Address)])_31 ]))_31}
Contributing​
Releasing a new version of Dev Wallet is as simple as tagging and creating a release, a Github Action will then build a bundle of the Dev Wallet that can be used in other tools (such as CLI). If the update of the Dev Wallet is required in the CLI, a seperate update PR on the CLI should be created. For more information, please visit the fcl-dev-wallet GitHub repository.
More​
Additionally, consider exploring these resources: