dApp Integration
Altitude Wallet exposes a window.postMessage API that lets any web application request wallet connections and token transfers. No SDK installation or external dependency is required — the bridge is injected automatically by the browser extension's content script.
How It Works
Altitude Wallet injects a content script into every page at document_start. This script listens for window.postMessage calls from your dApp and forwards them to the extension's background service worker, which handles vault access, signing, and transaction broadcasting.
Your dApp Content Script Background Worker
│ │ │
│ window.postMessage() │ │
│ ──────────────────────> │ │
│ │ sendMessage() │
│ │ ──────────────────────> │
│ │ │
│ │ Open popup
│ │ for user approval
│ │ │
│ │ <────────────────────── │
│ <───────────────────── │ │
│ window.postMessage() │ │
│ (response) │ │
All communication is asynchronous and Promise-based. Every request includes a unique id so your dApp can match responses to requests.
Connect Wallet
Request a connection to the user's wallet. If the wallet is locked, Altitude Wallet opens a popup prompting the user to enter their password. Once unlocked, the selected account address is returned.
Request
const id = crypto.randomUUID();
window.postMessage(
{
type: 'ALTITUDE_WALLET_CONNECT',
id,
},
'*'
);
Response
The extension responds with a message of type ALTITUDE_WALLET_CONNECT_RESPONSE:
window.addEventListener('message', (event) => {
if (event.source !== window) return;
const { type, id: responseId, result, error } = event.data;
if (type === 'ALTITUDE_WALLET_CONNECT_RESPONSE' && responseId === id) {
if (error) {
console.error('Connection rejected:', error);
return;
}
console.log('Connected address:', result.address);
}
});
Result
| Field | Type | Description |
|---|---|---|
address | string | The user's selected account address |
Errors
| Error message | Cause |
|---|---|
Wallet not set up. Please create a wallet first. | No wallet exists in the extension |
No account selected. | No wallet or account is currently selected |
Selected account not found. | Account data is corrupted or missing |
Send Tokens
Request a token transfer. Altitude Wallet opens a confirmation popup where the user reviews the token, amount, recipient, and gas fee before approving or rejecting the transaction.
Request
const id = crypto.randomUUID();
window.postMessage(
{
type: 'ALTITUDE_WALLET_SEND_TO',
id,
data: {
token: {
chainId: 1,
address: '0x0000000000000000000000000000000000000000',
name: 'Ether',
symbol: 'ETH',
decimals: 18,
logoURI: 'https://assets.coingecko.com/coins/images/279/small/ethereum.png',
nativeToken: true,
},
amount: {
value: 0.001,
fiat: 2,
},
recipientAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
},
},
'*'
);
Response
window.addEventListener('message', (event) => {
if (event.source !== window) return;
const { type, id: responseId, result, error } = event.data;
if (type === 'ALTITUDE_WALLET_SEND_TO_RESPONSE' && responseId === id) {
if (error) {
console.error('Transaction failed:', error);
return;
}
console.log('Transaction hash:', result.txHash);
}
});
Result
| Field | Type | Description |
|---|---|---|
txHash | string | The on-chain transaction hash |
Errors
| Error message | Cause |
|---|---|
Missing sendTo data | The data field was omitted from the request |
Wallet not set up. Please create a wallet first. | No wallet exists in the extension |
SendTo request timeout | User did not respond within 10 minutes |
Data Types
Token
The token object describes the asset being sent.
| Field | Type | Required | Description |
|---|---|---|---|
chainId | number | Yes | EVM chain ID (e.g. 1 for Ethereum, 8453 for Base) |
address | string | Yes | Token contract address. Use the zero address for native tokens |
name | string | Yes | Human-readable token name |
symbol | string | Yes | Token ticker symbol (e.g. ETH, USDC) |
decimals | number | Yes | Token decimals (18 for most ERC-20 tokens) |
logoURI | string | Yes | URL to the token icon |
nativeToken | boolean | No | Set to true for the chain's native gas token |
Amount
| Field | Type | Required | Description |
|---|---|---|---|
value | number | Yes | Amount in human-readable units (e.g. 0.001) |
fiat | number | No | USD-equivalent value for display purposes |
Recipient
| Field | Type | Required | Description |
|---|---|---|---|
recipientAddress | string | Yes | Valid EVM address (0x...) |
Complete Example
A minimal integration that connects to the wallet and sends a transaction:
<!DOCTYPE html>
<html>
<head>
<title>dApp Example</title>
</head>
<body>
<button id="connect">Connect Wallet</button>
<button id="send" disabled>Send 0.001 ETH</button>
<script>
function sendRequest(type, data) {
const id = crypto.randomUUID();
return new Promise((resolve, reject) => {
const handler = (event) => {
if (event.source !== window) return;
const msg = event.data;
if (msg.id !== id) return;
if (msg.type === `${type}_RESPONSE`) {
window.removeEventListener('message', handler);
if (msg.error) {
reject(new Error(msg.error));
} else {
resolve(msg.result);
}
}
};
window.addEventListener('message', handler);
window.postMessage({ type, id, data }, '*');
});
}
document.getElementById('connect').addEventListener('click', async () => {
try {
const { address } = await sendRequest('ALTITUDE_WALLET_CONNECT');
console.log('Connected:', address);
document.getElementById('send').disabled = false;
} catch (err) {
console.error(err);
}
});
document.getElementById('send').addEventListener('click', async () => {
try {
const { txHash } = await sendRequest('ALTITUDE_WALLET_SEND_TO', {
token: {
chainId: 1,
address: '0x0000000000000000000000000000000000000000',
name: 'Ether',
symbol: 'ETH',
decimals: 18,
logoURI: 'https://assets.coingecko.com/coins/images/279/small/ethereum.png',
nativeToken: true,
},
amount: { value: 0.001, fiat: 2 },
recipientAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
});
console.log('Tx hash:', txHash);
} catch (err) {
console.error(err);
}
});
</script>
</body>
</html>
TypeScript Definitions
For projects using TypeScript, copy these types into your codebase:
interface DappSendToToken {
chainId: number;
address: string;
name: string;
symbol: string;
decimals: number;
logoURI: string;
nativeToken?: boolean;
}
interface DappSendToRequestData {
token: DappSendToToken;
amount: { value: number; fiat?: number };
recipientAddress: string;
}
interface ConnectResult {
address: string;
}
interface SendToResult {
txHash: string;
}
interface WindowMessage {
type: string;
id: string;
data?: DappSendToRequestData;
result?: unknown;
error?: string;
}
Message Reference
| Request | Response | Purpose |
|---|---|---|
ALTITUDE_WALLET_CONNECT | ALTITUDE_WALLET_CONNECT_RESPONSE | Connect wallet, get address |
ALTITUDE_WALLET_SEND_TO | ALTITUDE_WALLET_SEND_TO_RESPONSE | Send token transfer for approval |
All messages share the same shape:
{
type: string, // One of the request/response types above
id: string, // UUID for request-response matching
data?: object, // Request payload (sendTo only)
result?: object, // Response payload (on success)
error?: string, // Error message (on failure)
}
Security Notes
- User confirmation required — Both
connectandsendToopen a visible popup. The user must explicitly approve before any data is returned or any transaction is signed - No silent signing — There is no way to sign a transaction without a user actively confirming it in the popup
- Timeout — A
sendTorequest expires after 10 minutes if the user does not respond - Extension must be installed — The content script is injected by the browser extension. Without it,
window.postMessagecalls are simply ignored