Skip to main content

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.

IMPORTANT

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.

info

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):


_10
flow init --config-only

Start the Emulator

Start the Emulator and deploy the contracts by running the following command from the directory containing flow.json in your project:


_10
flow emulator start
_10
flow 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.


_10
import * as fcl from '@onflow/fcl';
_10
_10
fcl
_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');

info

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:


_59
import { config, authenticate, unauthenticate, currentUser } from '@onflow/fcl';
_59
import { useEffect, useState } from 'react';
_59
_59
const fclConfigInfo = {
_59
emulator: {
_59
accessNode: 'http://127.0.0.1:8888',
_59
discoveryWallet: 'http://localhost:8701/fcl/authn',
_59
discoveryAuthInclude: [],
_59
},
_59
testnet: {
_59
accessNode: 'https://rest-testnet.onflow.org',
_59
discoveryWallet: 'https://fcl-discovery.onflow.org/testnet/authn',
_59
discoveryAuthnEndpoint:
_59
'https://fcl-discovery.onflow.org/api/testnet/authn',
_59
// Adds in Dapper + Ledger
_59
discoveryAuthInclude: ['0x82ec283f88a62e65', '0x9d2e44203cb13051'],
_59
},
_59
mainnet: {
_59
accessNode: 'https://rest-mainnet.onflow.org',
_59
discoveryWallet: 'https://fcl-discovery.onflow.org/authn',
_59
discoveryAuthnEndpoint: 'https://fcl-discovery.onflow.org/api/authn',
_59
// Adds in Dapper + Ledger
_59
discoveryAuthInclude: ['0xead892083b3e2c6c', '0xe5cd26afebe62781'],
_59
},
_59
};
_59
_59
const network = 'emulator';
_59
_59
config({
_59
'walletconnect.projectId': 'YOUR_PROJECT_ID', // your WalletConnect project ID
_59
'app.detail.title': 'Emerald Academy', // the name of your DApp
_59
'app.detail.icon': 'https://academy.ecdao.org/favicon.png', // your DApps icon
_59
'app.detail.description': 'Emerald Academy is a DApp for learning Flow', // a description of your DApp
_59
'app.detail.url': 'https://academy.ecdao.org', // the URL of your DApp
_59
'flow.network': network,
_59
'accessNode.api': fclConfigInfo[network].accessNode,
_59
'discovery.wallet': fclConfigInfo[network].discoveryWallet,
_59
'discovery.authn.endpoint': fclConfigInfo[network].discoveryAuthnEndpoint,
_59
// adds in opt-in wallets like Dapper and Ledger
_59
'discovery.authn.include': fclConfigInfo[network].discoveryAuthInclude,
_59
});
_59
_59
export default function App() {
_59
const [user, setUser] = useState({ loggedIn: false, addr: '' });
_59
_59
// So that the user stays logged in
_59
// even if the page refreshes
_59
useEffect(() => {
_59
currentUser.subscribe(setUser);
_59
}, []);
_59
_59
return (
_59
<div className="App">
_59
<button onClick={authenticate}>Log In</button>
_59
<button onClick={unauthenticate}>Log Out</button>
_59
<p>{user.loggedIn ? `Welcome, ${user.addr}!` : 'Please log in.'}</p>
_59
</div>
_59
);
_59
}

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.


_14
transaction(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.


_30
import * as fcl from '@onflow/fcl';
_30
import * as t from '@onflow/types';
_30
const CODE = `
_30
import "FungibleToken"
_30
import "FlowToken"
_30
import "LockedTokens"
_30
_30
access(all) fun main(address: Address): UFix64 {
_30
let account = getAccount(address)
_30
let unlockedVault = account
_30
.getCapability(/public/flowTokenBalance)!
_30
.borrow<&FlowToken.Vault{FungibleToken.Balance}>()
_30
?? panic("Could not borrow Balance reference to the Vault")
_30
let unlockedBalance = unlockedVault.balance
_30
let lockedAccountInfoCap = account
_30
.getCapability
_30
<&LockedTokens.TokenHolder{LockedTokens.LockedAccountInfo}>
_30
(LockedTokens.LockedAccountInfoPublicPath)
_30
if lockedAccountInfoCap == nil || !(lockedAccountInfoCap!.check()) {
_30
return unlockedBalance
_30
}
_30
let lockedAccountInfoRef = lockedAccountInfoCap!.borrow()!
_30
let lockedBalance = lockedAccountInfoRef.getLockedAccountBalance()
_30
return lockedBalance + unlockedBalance
_30
}`;
_30
export const getTotalFlowBalance = async (address) => {
_30
return await fcl.decode(
_30
await fcl.send([fcl.script(CODE), fcl.args([fcl.arg(address, t.Address)])]),
_30
);
_30
};

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: