Skip to content
arkade-osPublic

About

Arkade Wallet — open-source, self-custodial wallet for Bitcoin and stablecoins. Swap, borrow and earn with your Bitcoins.

Resources

Security policy

Stars

58 stars

Watchers

6 watching

Forks

Latest commit

 

History

1,126 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

👾 Arkade Wallet

Arkade Wallet is the entry-point to the Arkade ecosystem—a self-custodial Bitcoin wallet delivered as a lightweight Progressive Web App (installable on mobile or desktop in seconds, no app-store gatekeepers). Built around the open-source ARK protocol, it speaks natively to any arkd instance, letting you create, send, and receive Virtual Transaction Outputs (VTXOs) for instant, off-chain pre-confirmations and batched, fee-efficient on-chain settlement.

Screenshots

New Wallet Home Screen

Recovering an asset mint

Minting with a new control asset requires two separate issuances. The wallet saves a local recovery record before submitting each one and imports the control asset as soon as its issuance is known. If the control asset is not yet spendable, the wait ends after 60 seconds; return to the mint screen and resume the original mint without issuing another control asset. This flow requires Web Locks support and a secure browser context.

If an issuance's outcome is unknown (for example, the browser closed while submitting it), the wallet cannot determine safely whether retrying would create a duplicate. Check wallet activity and contact support before discarding the recovery record. Discarding it or clearing browser storage can make a later mint incur another fee. Recovery records are stored in this browser, not in the Nostr backup; use the same wallet and Arkade server to resume.

Environment Variables

Variable Description Example Value
VITE_ARK_SERVER Override the default Arkade server URL VITE_ARK_SERVER=http://localhost:7070
VITE_APP_VERSION App version string shown in support diagnostics VITE_APP_VERSION=1.2.3
VITE_CHATWOOT_WEBSITE_TOKEN ChatWoot website token for customer support integration VITE_CHATWOOT_WEBSITE_TOKEN=your-token
VITE_CHATWOOT_BASE_URL ChatWoot server base URL for customer support integration VITE_CHATWOOT_BASE_URL=https://app.chatwoot.com
VITE_DELEGATOR_URL Delegator service URL for the wallet service worker VITE_DELEGATOR_URL=https://delegator.example.com
VITE_MAX_PERCENTAGE Override the max fee percentage (default 10) VITE_MAX_PERCENTAGE=5
VITE_NOSTR_RELAY_URL Override the default Nostr relay URLs for backup VITE_NOSTR_RELAY_URL=wss://relay.example.com
VITE_SENTRY_DSN Enable Sentry error tracking (only in production, not on localhost) VITE_SENTRY_DSN=your-sentry-dsn
VITE_UTXO_MAX_AMOUNT Override the server's utxoMaxAmount VITE_UTXO_MAX_AMOUNT=-1
VITE_UTXO_MIN_AMOUNT Override the server's utxoMinAmount VITE_UTXO_MIN_AMOUNT=330
VITE_VERIFIED_ASSETS_URL URL to fetch the verified assets list VITE_VERIFIED_ASSETS_URL=https://arklabshq.github.io/asset-registry/mutinynet.json
VITE_VTXO_MAX_AMOUNT Override the server's vtxoMaxAmount VITE_VTXO_MAX_AMOUNT=-1
VITE_VTXO_MIN_AMOUNT Override the server's vtxoMinAmount VITE_VTXO_MIN_AMOUNT=330
CI Set to true for Continuous Integration environments CI=true
GENERATE_SOURCEMAP Disable source map generation during build GENERATE_SOURCEMAP=false

Docker

The wallet is available as a Docker image on GitHub Container Registry.

Pull and run

docker pull ghcr.io/arkade-os/wallet:latest
docker run -p 8080:80 ghcr.io/arkade-os/wallet:latest

Open http://localhost:8080 to view the wallet.

Runtime configuration

Environment variables can be passed at runtime to configure the wallet without rebuilding the image:

docker run -p 8080:80 \
  -e VITE_ARK_SERVER=https://arkade.computer \
  ghcr.io/arkade-os/wallet:latest

See the Environment Variables table for all supported variables.

Build locally

docker build -t arkade-wallet .

# With build-time configuration
docker build \
  --build-arg VITE_ARK_SERVER=https://arkade.computer \
  -t arkade-wallet .

Content Security Policy

The policy is served by nginx (nginx-security-headers.conf) for Docker and by public/_headers for Cloudflare Pages. Both are static, so:

  • Setting VITE_CHATWOOT_BASE_URL to a host other than https://app.chatwoot.com requires adding that origin to script-src in the file your deployment uses.
  • The inline theme bootstrap in index.html is allowed by hash. pnpm csp:check (run on pre-commit and before pnpm build) verifies it; pnpm csp:fix updates it after editing that block.
  • public/_headers allows https://static.cloudflareinsights.com because Cloudflare Web Analytics injects its beacon into HTML responses at the edge, so the script is not in the build. Beware of Cloudflare features that inject inline script — Rocket Loader, Email Obfuscation — which the hash-only script-src blocks and pnpm csp:check cannot catch, since it only sees the built index.html.

Getting Started

Prerequisites

  • Node.js v24.22.1 (see .nvmrc)
  • PNPM >=8

Installation

Install dependencies

pnpm install

Development

pnpm run start

Runs the app in the development mode.
Open http://localhost:3002 to view it in the browser.

The page will reload if you make edits.
You will also see any lint errors in the console.

pnpm run build

Builds the app for production to the dist folder.
It correctly bundles React in production mode and optimizes the build for the best performance.

The build is minified and the filenames include the hashes.
Your app is ready to be deployed!

pnpm run regtest:start

Starts the regtest environment and sets up the arkd instance.
Requires Docker and Node.js v20.19+ or v22.12+. The stack is driven by the in-house arkade-regtest Node CLI (regtest/regtest.mjs) — no Nigiri required.

Use pnpm run regtest:stop to stop it and pnpm run regtest:clean to tear it down.

Funding your local wallet

To interact with Ark features, you need Regtest coins.

  1. Copy your address from the wallet's Receive screen (ensure it starts with bcrt1 for Regtest).
  2. Run the faucet command (the --confirm flag mines a block so the deposit confirms):
node regtest/regtest.mjs faucet <bcrt-address> <btc> --confirm

e2e tests

note: e2e tests require a regtest environment to be running. pnpm run regtest:start to start and setup the regtest environment.

note: e2e tests use playwright for ui testing, you may need to run pnpm exec playwright install once to download new browsers.

Run the tests with:

pnpm run test:e2e

Run the tests in interactive mode with:

pnpm run test:e2e --ui

Access the playwright code generator tool with:

pnpm run test:codegen

On CI the suite runs as four parallel jobs: two browser projects (Mobile Chrome, Google Chrome) times two file groups defined in .github/workflows/playwright.yml:

  • assets-send: asset.test.ts, send.test.ts
  • core: every other file in src/test/e2e/

The groups list files explicitly, so a new test file must be added to one of them, otherwise it will never run on CI.

App links

Another site can open the wallet with a query string. The wallet asks before it shares an address or sends funds, then returns to callback by navigating there. Build the link with URLSearchParams — a BIP21 and a callback are both URLs, and raw & / ? will be parsed as the wallet's own query.

Connect (the address a user would copy from Receive, plus the x-only public key):

https://arkade.money/?action=connect&callback=https%3A%2F%2Farkade.trade%2Fconnect

Approval opens callback?address=<ark address>&pubkey=<64 hex chars>. Decline opens callback?error=denied.

Pay (the existing send screen, prefilled — nothing is broadcast until the user signs):

https://arkade.money/?action=send&request=<percent-encoded BIP21>&callback=https%3A%2F%2Farkade.trade%2Fvault

Success opens callback?status=sent&txid=<txid> when there is a txid. sent reports that the payment was committed; for swaps, txid is the funding transaction. An onchain swap keeps the wallet open and defers this callback until its payout claim is broadcast. Backing out opens callback?error=denied. callback is optional on send.

Error codes in callback?error=<code>: denied (the user declined or backed out) and invalid (the request was malformed, such as a bad action, address, or BIP21; sent only when the request still carried a valid callback).

callback must be https, or http on localhost, 127.0.0.1, or [::1]. The whole query must stay under 6000 characters. The wallet appends its params; it does not fill a template, and it will not leave a pre-set address in place on decline.

An installed wallet on Chrome or Edge also handles the web+arkade protocol (public/manifest.json sends it to the hash). The actions are the same:

web+arkade://connect?callback=https%3A%2F%2Farkade.trade%2Fconnect
web+arkade://send?request=<percent-encoded BIP21>&callback=https%3A%2F%2Farkade.trade%2Fvault

The browser asks once before it lets the installed app own that protocol. Safari has no manifest protocol handler, so an iOS app uses the https link, which opens in the browser. That page shows Open in App: Chrome and Edge launch web+arkade:// in the installed app, and Safari explains that it cannot switch there, so the request stays on this page. Ark notes keep using web+arkade:// and are not treated as connect or send.

Troubleshooting

address already in use (Port 5000) on macOS

macOS AirPlay Receiver uses port 5000 by default, which conflicts with the regtest stack.

  • Fix: Go to System Settings > General > AirDrop & Handoff and disable AirPlay Receiver.

About

Arkade Wallet — open-source, self-custodial wallet for Bitcoin and stablecoins. Swap, borrow and earn with your Bitcoins.

Resources

Security policy

Stars

58 stars

Watchers

6 watching

Forks

Releases

Packages

Used by

Contributors

Languages