Connect Apps
Use the Photon provider as the user-controlled permission boundary. Your app requests access, the wallet asks the user, and only approved origins can read account state or request privileged actions.
Connect and Read Session State
async function openPhotonSession() {
const photon = window.photon;
if (!photon) throw new Error("PhotonBolt Wallet is not available");
const connectResult = await photon.connect();
const accounts = await photon.getAccounts();
const network = await photon.getNetwork();
const balance = await photon.getBalance();
return {
connectResult,
accounts,
network,
balance,
};
}
Disconnect Cleanly
If your app has a “Disconnect Wallet” action, remove your own app state after the wallet revokes the current origin.
async function disconnectPhoton() {
if (!window.photon) return;
await window.photon.disconnect();
sessionStorage.removeItem("photon-address");
sessionStorage.removeItem("photon-network");
}
React Example
import { useEffect, useState } from "react";
export function PhotonConnectButton() {
const [address, setAddress] = useState("");
const [network, setNetwork] = useState("");
const [error, setError] = useState("");
useEffect(() => {
const photon = window.photon;
if (!photon) return;
const handleAccounts = (accounts) => setAddress(accounts[0] || "");
const handleNetwork = (nextNetwork) => setNetwork(nextNetwork);
photon.on("accountsChanged", handleAccounts);
photon.on("networkChanged", handleNetwork);
return () => {
photon.removeListener("accountsChanged", handleAccounts);
photon.removeListener("networkChanged", handleNetwork);
};
}, []);
async function connect() {
try {
setError("");
const result = await window.photon.connect();
setAddress(result.address);
setNetwork(result.network);
} catch (err) {
setError(err.message);
}
}
return (
<div>
<button onClick={connect}>Connect PhotonBolt</button>
{address ? <p>{address} on {network}</p> : null}
{error ? <p>{error}</p> : null}
</div>
);
}
Origin Permission Model
Connection Scope
Permissions are origin-scoped. An approval on app.example.com does not imply approval on another subdomain.
Privileged Methods
getBalance, getAssets, getAssetBalance, importAsset, signTransaction, sendTransaction, sendBtcFunding, payRgbInvoice, and signMessage should be treated as permissioned actions.
Connected Method Surface
| Method | When to call it |
|---|---|
getAccounts() |
After connection, when you need the active wallet address. |
getNetwork() |
Before rendering any network-specific send, receive, or import flow. |
getBalance() |
When showing the BTC summary for the connected user. |
getAssets() |
When your app needs the wallet's imported asset inventory. |
getAssetBalance() |
When you need one asset balance without iterating the full asset list. |
importAsset() |
When your dApp wants to add a public regtest RGB asset directly into the wallet. |
signTransaction() |
For preview-oriented BTC flows that need signed hex only. |
sendTransaction() |
For normal approved BTC transfers. |
sendBtcFunding() |
For explicit BTC collateral or funding transfers to an app-provided address. |
payRgbInvoice() |
For regtest RGB Lightning invoice approval and payment. |
signMessage() |
For wallet ownership challenges and signed approvals. |
Do not auto-call connect() on page load. It is better UX and better security posture to request connection only after the user clicks a wallet action.