Getting Started
Automatic Installation
For new projects, it is recommended to set up your Laser Eyes app using the create-lasereyes
command line interface (CLI). This will create a new Laser Eyes project using TypeScript and install the required dependencies.
npx create-lasereyes
Manual Installation
To manually add LaserEyes to your project, install the required packages.
yarn add @omnisat/lasereyes
Quick Start
- Wrap your app with the
LaserEyesProvider
:
// note: component MUST NOT be rendered with SSR
import { LaserEyesProvider, MAINNET } from "@omnisat/lasereyes";
function App() {
return (
<LaserEyesProvider config={{ network: MAINNET }}>
{/* Your app components */}
</LaserEyesProvider>
);
}
- Use the
useLaserEyes
hook in your components:
import { useLaserEyes, UNISAT } from "@omnisat/lasereyes";
function WalletConnector() {
const {
connect,
connected,
address,
balance,
sign,
sendBTC,
signPsbt,
switchNetwork,
} = useLaserEyes();
const handleConnect = () => {
connect(UNISAT);
};
const handleSendBTC = async () => {
const recipient = "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq";
const amount = 1000; // 1000 sats
await sendBTC(recipient, amount);
};
const handleSignMessage = async () => {
const message = "SIGN ME, BABY";
const signature = await sign(message);
console.log(signature);
};
const handleSignPsbt = async () => {
const psbtBase64 = "..."; // Your PSBT as a base64 string
const tx = await signPsbt(psbtBase64);
console.log(tx);
};
const handleSwitchNetwork = () => {
switchNetwork("testnet");
};
return (
<div>
{!connected ? (
<button onClick={handleConnect}>Connect Wallet</button>
) : (
<div>
<p>Connected Address: {address}</p>
<p>Balance: {balance.total}</p>
<button onClick={handleSendBTC}>Send BTC</button>
<button onClick={handleSignMessage}>Sign Message</button>
<button onClick={handleSignPsbt}>Sign PSBT</button>
<button onClick={handleSwitchNetwork}>Switch Network</button>
</div>
)}
</div>
);
}
API Reference
LaserEyesProvider
The main context provider that should wrap your app. It initializes the LaserEyes context and makes the wallet connection and functionality available to all child components.
Usage
import { LaserEyesProvider, MAINNET } from "@omnisat/lasereyes";
function App() {
return (
<LaserEyesProvider config={{ network: MAINNET }}>
{/* Your app components */}
<WalletConnector />
<TransactionHistory />
</LaserEyesProvider>
);
}
Props
The LaserEyesProvider
accepts a config
prop with the following options:
network
: 'mainnet' | 'testnet' - The Bitcoin network to connect to. Default is 'mainnet'.
Notes
- The
LaserEyesProvider
should be placed at the root of your application or at least above any components that need to interact with the wallet. - All child components of
LaserEyesProvider
can access the wallet state and functions using theuseLaserEyes
hook. - The provider initializes the wallet connection state, so it's ready to use as soon as your app loads.
- If you're using server-side rendering (SSR), make sure to conditionally render the
LaserEyesProvider
only on the client-side to avoid SSR conflicts.
import { useEffect, useState } from "react";
import { LaserEyesProvider, MAINNET } from "@omnisat/lasereyes";
function App() {
const [isClient, setIsClient] = useState(false);
useEffect(() => {
setIsClient(true);
}, []);
if (!isClient) return null;
return (
<LaserEyesProvider config={{ network: MAINNET }}>
{/* Your app components */}
</LaserEyesProvider>
);
}
This setup ensures that the LaserEyesProvider
only renders on the client-side, preventing any server-side rendering issues.
useLaserEyes
A hook that provides access to all wallet functions and state. Here are the key properties and methods:
import { useLaserEyes, UNISAT } from "@omnisat/lasereyes";
function WalletInfo() {
const {
connected,
isConnecting,
address,
paymentAddress,
publicKey,
paymentPublicKey,
balance,
provider,
network,
accounts,
hasUnisat,
connect,
disconnect,
} = useLaserEyes();
useEffect(() => {
if (hasUnisat && !connected && !isConnecting) {
connect(UNISAT);
}
}, [hasUnisat, connected, isConnecting]);
if (isConnecting) return <p>Connecting to wallet...</p>;
if (!connected)
return <button onClick={() => connect(UNISAT)}>Connect</button>;
return (
<div>
<h2>Wallet Information</h2>
<p>Address: {address}</p>
<p>Payment Address: {paymentAddress}</p>
<p>Public Key: {publicKey}</p>
<p>Payment Public Key: {paymentPublicKey}</p>
<p>
Balance: {balance !== undefined ? `${balance} satoshis` : "Loading..."}
</p>
<p>Provider: {provider}</p>
<p>Network: {network}</p>
<p>Accounts: {accounts.join(", ")}</p>
<button onClick={disconnect}>Disconnect</button>
</div>
);
}
This example demonstrates how to use the useLaserEyes
hook to access and display all available wallet properties, as well as use the connect
and disconnect
methods.
Properties
connected
: Boolean - Indicates if a wallet is currently connected.
isConnecting
: Boolean - Indicates if a wallet connection is in progress.
address
: String - The current wallet address.
paymentAddress
: String - The current wallet payment address.
- may be different from
address
for some wallet types.
publicKey
: String - The current wallet public key.
paymentPublicKey
: String - The current wallet payment public key
- may be different from
publicKey
for some wallet types.
balance
: Number | undefined - The current wallet balance in satoshis.
undefined
if not yet fetched.
provider
: String | undefined - Current wallet provider (e.g., 'unisat').
undefined
if not connected.
network
: 'mainnet' | 'testnet' - Current network the wallet is connected to.
accounts
: String[] - Array of accounts associated with the connected wallet.
hasUnisat
: Boolean - Indicates if the Unisat wallet is available in the browser.
network
: 'mainnet' | 'testnet' - Current network the wallet is connected to.
accounts
: String[] - Array of accounts associated with the connected wallet.
hasUnisat
: Boolean - Indicates if the Unisat wallet is available in the browser.
Methods
connect
Connects to the specified wallet.
Input
walletName
: 'unisat'- The name of the wallet to connect to (currently only 'unisat' is supported)
Output
Promise<void>
- Resolves when the connection is successful
- Rejects with an error if the connection fails
Example
import { UNISAT } from "@omnisat/lasereyes";
try {
await connect(UNISAT);
console.log("Successfully connected to Unisat wallet");
} catch (error) {
console.error("Error connecting to wallet:", error);
}
Notes
- Currently, only the Unisat wallet ('unisat') is supported.
- This method initiates the connection process, which may involve user interaction (e.g., approving the connection in their wallet).
- After a successful connection, other wallet-related methods (like
sendBTC
,signMessage
, etc.) become available. - The connection process may fail for various reasons (user rejection, wallet not installed, etc.). Always handle potential errors.
- It's a good practice to check if the wallet is installed before attempting to connect:
if (hasUnisat) {
await connect(UNISAT);
} else {
console.log("Unisat wallet is not installed");
}
disconnect
Disconnects the currently connected wallet.
Input
None
Output
void
Example
try {
disconnect();
console.log("Wallet disconnected successfully");
} catch (error) {
console.error("Error disconnecting wallet:", error);
}
Notes
- This method doesn't return a promise, so it executes synchronously.
- After disconnecting, all wallet-related properties (like
address
,balance
, etc.) should be considered invalid. - You may want to update your UI or application state after calling this method to reflect the disconnected state.
- It's good practice to call this method when your user initiates a "logout" or "disconnect" action.
- Even though the method doesn't have a return value, it's still a good idea to wrap it in a try-catch block to handle any unexpected errors.
switchNetwork
Switches the wallet to the specified Bitcoin network.
Input
network
: 'mainnet' | 'testnet'- The network to switch to
Output
Promise<void>
- Resolves when the network switch is complete
Example
try {
await switchNetwork("testnet");
console.log("Successfully switched to testnet");
} catch (error) {
console.error("Error switching network:", error);
}
// Later in your code...
try {
await switchNetwork("mainnet");
console.log("Successfully switched back to mainnet");
} catch (error) {
console.error("Error switching network:", error);
}
Notes
- Only 'mainnet' and 'testnet' are supported as network options.
- Switching networks may affect the wallet's balance, address, and other network-specific data.
- Ensure that you update any network-dependent operations in your application after switching networks.
- The wallet may require user confirmation to switch networks.
- Handle potential errors, as the network switch may fail due to various reasons (user rejection, connection issues, etc.).
sendBTC
Sends Bitcoin to a specified address.
Input
to
: string- Recipient's Bitcoin address
amount
: number- Amount to send in satoshis
Output
Promise<string>
- Resolves with the transaction ID
Example
const recipientAddress = "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq";
const amountInSatoshis = 100000; // 0.001 BTC
try {
const txId = await sendBTC(recipientAddress, amountInSatoshis);
console.log("Transaction sent successfully. Transaction ID:", txId);
} catch (error) {
console.error("Error sending BTC:", error);
}
Notes
- The
amount
is specified in satoshis (1 BTC = 100,000,000 satoshis). - Ensure that the wallet has sufficient balance before sending.
- The transaction may take some time to be confirmed on the network.
- Always double-check the recipient's address to avoid sending to the wrong address.
- Handle potential errors, as the transaction may fail due to various reasons (insufficient funds, network issues, etc.).
signMessage
Signs a message with the connected wallet.
Input
message
: string- The message to be signed
Output
Promise<string>
- Resolves with the signature as a string
Example
const messageToSign = "Hello, Bitcoin!";
try {
const signature = await signMessage(messageToSign);
console.log("Message signed successfully. Signature:", signature);
} catch (error) {
console.error("Error signing message:", error);
}
Notes
- The resulting signature can be used to prove ownership of the address without revealing the private key.
- The signature format may vary depending on the wallet implementation.
- Always handle potential errors, as the signing process may fail or be cancelled by the user.
signPsbt
Signs a Partially Signed Bitcoin Transaction (PSBT).
Input
psbt
: string- PSBT as a hex or base64 string
finalize
: boolean (optional)- Whether to finalize the PSBT
Output
Promise<{ signedPsbtHex?: string, signedPsbtBase64?: string, txId?: string } | undefined>
Example
const psbtHex = "70736274ff01..."; // Your PSBT hex string
try {
const { signedPsbtHex, txId } = await signPsbt(psbtHex, true, false);
console.log("Signed PSBT (hex):", signedPsbtHex);
console.log("Transaction ID:", txId);
} catch (error) {
console.error("Error signing PSBT:", error);
}
Notes
- If
finalize
is true, the PSBT will be finalized after signing. - If
broadcast
is true, the transaction will be broadcast to the network after signing. - The method may return
undefined
if the signing process fails or is cancelled by the user.
pushPsbt
Pushes a signed Partially Signed Bitcoin Transaction (PSBT) to the network.
Input
tx
: string- Signed PSBT as a hex or base64 string
Output
Promise<string | undefined>
- Resolves with the transaction ID if successful
- Resolves to
undefined
if the push fails or is cancelled
Example
const signedPsbtHex = "70736274ff01..."; // Your signed PSBT hex string
try {
const txId = await pushPsbt(signedPsbtHex);
if (txId) {
console.log("Transaction successfully pushed. Transaction ID:", txId);
} else {
console.log("Transaction push failed or was cancelled.");
}
} catch (error) {
console.error("Error pushing PSBT:", error);
}
Notes
- Ensure that the PSBT is fully signed before pushing to the network.
- The method may return
undefined
if the push fails or is cancelled for any reason. - Always handle potential errors when using this method, as network operations can fail.
Supported Wallets
More wallets are coming soon... Please vote which wallet we should add next: https://demo.lasereyes.build/
Each wallet has different capabilities and methods of interaction. The package abstracts these differences to provide a unified API.
Network Handling
The package supports both mainnet and testnet. You can switch networks using the switchNetwork
function, and check the current network with the network
property.
Error Handling
Most functions in the package are asynchronous and may throw errors. It's recommended to use try-catch blocks when calling these functions:
try {
await connect("unisat");
} catch (error) {
console.error("Failed to connect:", error);
}
Advanced Usage
Custom Configuration
You can create a custom configuration using the createConfig
function:
import { createConfig } from "@omnisat/lasereyes";
const config = createConfig({
network: "testnet",
provider: "unisat",
chainId: 1,
});
Working with PSBTs
The package provides methods for signing and pushing Partially Signed Bitcoin Transactions (PSBTs):
const psbt = "..."; // Your PSBT string
const signedPsbt = await signPsbt(psbt, true, false);
const txId = await pushPsbt(signedPsbt);
Best Practices
- Always check if a wallet is connected before performing operations.
- Handle network changes gracefully, as they can affect address and balance.
- Provide clear feedback to users during wallet operations, as they may require user interaction in the wallet interface.
- Always validate user input before sending transactions or signing messages.
Contributing
Contributions are welcome! Please check out our Contributing Guide for more details.
License
This project is licensed under the MIT License - see the LICENSE file for details.