This project builds a web extension
You will need to add a backend for Freighter to connect to. You can configure
this by adding an .env file at the path extension/.env.
Inside this file, you can configure a backend by setting a value for the global
variable INDEXER_URL. For example, to connect to the production backend, in
your .env file, you can add the line
INDEXER_URL=https://freighter-backend-prd.stellar.org/api/v1.
To connect to a local instance of the backend, just swap out the value in
INDEXER_URL.
We will compile the code for the extension and then load this package into your browser.
Run
yarn build
You may also choose to enable some experimental features by alternatively running
yarn build:experimental
To install on Chrome:
-
In Chrome, navigate to
chrome://extensions/. -
Toggle
Developer modeto the ON position in the top right corner -
You will now see a button in the top left titled
Load Unpacked -
Click
Load Unpackedand it will open your file system. -
Navigate to this folder (
/extension) and click thebuildfolder. HitSelect. You should now see an icon for Freighter in Chrome.
To install on Firefox:
-
In Firefox, navigate to about:debugging#/runtime/this-firefox
-
Click
Load Temporary Add-On -
Navigate to this folder (
/extension) and open thebuildfolder and findmanifest.json. HitSelect. You should now see an icon for Freighter in Firefox
When we build for the app store, we will minify our code and enable some security guardrails. In order to do that, run
yarn build:production
Note that when you build using this setting and install locally, you will NOT be able to connect to it using a dev server (mentioned in the next stop)
Next we'll spin up a dev environment. Here, you can access the popup in your
browser, so you can make edits with the benefit of hot reloads. This dev
environment will be able to make calls to the installed version of the
extension, so it has all the capabilites of the popup inside the extension.
NOTE: This dev environment only works for the popup
Changes to background and content script will still require a production
build using yarn build, followed by reloading the extension in Chrome.
- Start a local dev server by running
yarn start
You should be able to access the Popup by going to localhost:9000/
You can also set the experimental flag to true by running
yarn start:experimental
This will enable some features hidden by the experimental feature flag that
are still under development.
WARNING: running the intergration tests will clear the apps data
Steps:
- Build the extension in experimental mode
yarn build:experimental
- Start the dev server
yarn start
- Go to the integration tests route
localhost:9000/#/integration-test
Errors, if any, will be in the console logs.
When developing or testing Blockaid security warnings, you can override the Blockaid scan results to simulate different security states. This feature is only available in development mode.
Steps:
-
Build the extension in development mode:
yarn build -
Start the dev server:
yarn start -
Navigate to the Debug page:
localhost:9000/#/debug -
In the "Blockaid Response Override" section, click one of the security level buttons:
- Safe: Simulates a safe transaction (no warnings)
- Suspicious: Simulates a suspicious transaction (warning banner)
- Malicious: Simulates a malicious transaction (error banner)
- Unable to Scan: Simulates an unable-to-scan state (warning banner)
-
The override will persist across page reloads and will affect all Blockaid scans until you click "Clear Override".
Important Notes:
- The override state is stored in local storage and only works in development builds. Production builds will ignore any override state.
- Error messages/details are only injected for "Unable to Scan" overrides. When overriding to "Malicious" or "Suspicious", the warning banners will appear, but the expanded detail view may show a blank list of rows. This is because the backend will not return actual malicious/suspicious threat data - it only returns real scan results. The override only forces the security level classification, not the detailed threat information.
The Debug page (/#/debug) includes an Analytics Debug section that shows real-time Amplitude event activity. This is useful for verifying that screen-view and interaction metrics fire correctly during development.
What it shows:
- Initialized — Whether the Amplitude SDK has been initialized.
- API Key — Whether an
AMPLITUDE_KEYis configured (does not reveal the key). - User ID — The anonymous metrics user ID stored in local storage.
- Sending to Amplitude —
Yesonly when the SDK is initialized, an API key is set, and the user has data sharing enabled. - Recent Events — A scrollable list of the last 50 events with timestamps and expandable property payloads.
How events are stored:
- Events are persisted to
localStorage, so they are shared across all extension tabs and survive page refreshes. - Events are automatically flushed after 10 minutes (TTL). Stale entries are filtered out on every read.
- Debug events are only recorded in development builds (
isDev). Production builds never write to this buffer. - Events are recorded regardless of the data-sharing preference, so you can test metrics in dev even with data sharing disabled.
Testing events:
-
Set up your
.envwith anAMPLITUDE_KEY(optional — events are logged to the debug panel even without a key):AMPLITUDE_KEY=your_key_here -
Start the dev server:
yarn start -
Navigate around the extension (e.g., open Send, Swap, Settings). Each screen transition emits a
loaded screen: *event. -
Open the Debug page at
localhost:9000/#/debugto see the captured events. -
Click Clear to reset the event list.
This app has 3 main components that are named using extension nomenclature. All
of these are located in the src/ folder:
-
The UI that appears when you click on the extension in your browser. This code also controls the fullscreen authentiction flow and any popups triggered by the extension. This is all controlled by one React app. In web extension parlance, this is called the
popupand is therefore located insrc/popup. -
The "backend" service. We want to do things like account creation and store sensitive data, like public keys, in a secure place away from the
popupand away from thecontent script. We want this service to be a standalone entity that these other 2 can make requests to and receive only what the backend sees fit. In web extension terms, this is known as thebackgroundscript and is instantiated bypublic/background. The code is located insrc/background.This script is run by the extension on browser starts and continues running, storing data and listening/responding to messages from
popupandcontent script, and only terminates on browser close (or extension uninstall/reload). It is run in a headless browser, so it has access to all Web APIs. It also has accessible dev tools, which can be reached by going tochrome://extensions/orabout:debugging#/runtime/this-firefoxand clickingservice worker -
The
content scriptthat allows external sites to send and receive messages tobackground. Using an event listener, it waits for an application to attempt to communicate using@stellar/freighter-api(under the hood,window.postMessage). Once it picks up a message and determines that this fromfreighter-api, it sends the message ontobackground.