Skip to main content

dApp Integration

Altitude Wallet exposes a standard Ethereum provider to every web page. It implements the EIP-1193 JavaScript provider API and announces itself through EIP-6963 multi-wallet discovery. A TronLink-compatible surface is also injected for TRON dApps.

No SDK installation is required — the provider is injected automatically by the extension's content script.

How It Works

Altitude Wallet injects an inpage script into every page at document_start. The inpage script registers window.ethereum, window.tronLink, and window.tronWeb, then communicates with the content script through window.postMessage. The content script opens a persistent browser.runtime.connect Port to the background service worker, which routes dApp requests, manages site permissions, and opens a confirmation popup when user approval is required.

Your dApp                Inpage Script             Content Script           Background Worker
│ │ │ │
│ window.ethereum │ │ │
│ .request(...) │ │ │
│ ──────────────────────> │ │ │
│ │ window.postMessage │ │
│ │ ──────────────────────> │ │
│ │ │ runtime.connect Port │
│ │ │ ──────────────────────> │
│ │ │ │
│ │ │ Open popup
│ │ │ for approval
│ │ │ │
│ │ │ <──────────────────────│
│ │ <──────────────────────│ │
│ <───────────────────── │ │ │
│ Promise resolves │ │ │

All provider methods return a Promise. Every internal request carries a unique id so responses are correlated correctly.

EIP-1193 Provider

The provider is available on window.ethereum.

Connect Wallet

const accounts = await window.ethereum.request({
method: 'eth_requestAccounts',
});

console.log('Connected address:', accounts[0]);

If the wallet is locked or the site has not been connected before, Altitude Wallet opens a confirmation popup where the user can unlock and approve access.

Get Chain ID

const chainId = await window.ethereum.request({
method: 'eth_chainId',
});

console.log('Current chain:', chainId); // e.g. "0x1"

Get Connected Accounts

const accounts = await window.ethereum.request({
method: 'eth_accounts',
});

Switch Chain

await window.ethereum.request({
method: 'wallet_switchEthereumChain',
params: [{ chainId: '0x1' }],
});

Only the chain currently selected inside the wallet is considered available. Switching to an unsupported chain returns EIP-1193 error 4902.

Read-Only RPC Calls

Read methods are forwarded to the configured RPC endpoint without user confirmation:

const blockNumber = await window.ethereum.request({
method: 'eth_blockNumber',
});

Examples of read-only methods: eth_blockNumber, eth_call, eth_getBalance, eth_getTransactionReceipt, eth_gasPrice, eth_estimateGas, net_version, eth_getCode, eth_getStorageAt.

Events

window.ethereum.on('accountsChanged', (accounts) => {
console.log('Accounts changed:', accounts);
});

window.ethereum.on('chainChanged', (chainId) => {
console.log('Chain changed:', chainId);
});

window.ethereum.on('connect', (info) => {
console.log('Connected:', info.chainId);
});

window.ethereum.on('disconnect', (error) => {
console.log('Disconnected:', error);
});

Errors

Errors returned by request() follow the EIP-1193 error shape:

interface ProviderError extends Error {
code: number;
data?: unknown;
}
CodeNameTypical cause
4001User Rejected RequestThe user rejected the request in the popup
4100UnauthorizedThe requested account is not authorized for this origin
4200Unsupported MethodThe method is not implemented
4900DisconnectedThe provider is disconnected from the current chain
4901Chain DisconnectedThe provider is disconnected from the requested chain
4902Chain UnavailableThe requested chain is not available in the wallet
-32602Invalid ParamsMalformed method parameters
-32603Internal ErrorUnexpected error inside the wallet

EIP-6963 Multi-Wallet Discovery

Altitude Wallet announces itself through the standard eip6963:announceProvider event.

window.addEventListener('eip6963:announceProvider', (event) => {
const { info, provider } = event.detail;

if (info.rdns === 'io.altitude.wallet') {
console.log('Altitude Wallet discovered:', info.name);
// Use provider as your EIP-1193 provider
}
});

window.dispatchEvent(new Event('eip6963:requestProvider'));

Announcements are emitted once immediately and again whenever another dApp requests providers.

TRON Provider

Altitude Wallet injects a TronLink-compatible surface on both window.tronLink and window.tronWeb. The structure mirrors the real TronLink extension, so libraries like @tronweb3/tronwallet-adapters (TronLinkAdapter) work without any special configuration.

Connect Wallet

// Request account access — returns the TRON address (base58)
const accounts = await window.tronLink.request({ method: 'tron_requestAccounts' });

console.log('Connected TRON address:', accounts[0]); // e.g. "T..."

After a successful tron_requestAccounts, the address is automatically available on tronWeb:

window.tronWeb.defaultAddress.base58; // "T..."
window.tronLink.tronWeb.defaultAddress.base58; // same — shared instance

Sign Transaction / Message

// Sign a TRON transaction
const signedTx = await window.tronWeb.trx.sign(transaction);

// Sign a message (TronLink-compatible)
const signature = await window.tronWeb.trx.signMessageV2('Hello TRON');

Signing requires user approval in the confirmation popup.

Multi-Chain Behavior

Altitude Wallet is a multi-chain wallet. The protocol used to connect determines which address is returned:

CallNetwork switched toAddress returned
eth_requestAccountsEthereum (EVM)0x... (EVM)
tron_requestAccountsTRONT... (base58)

The wallet automatically switches the active network when a connect request is received. EVM and TRON accounts are stored independently per origin, so a dApp that connects via both protocols receives the correct address for each.

Supported Methods (Feature Set 1)

The following methods are supported by the current implementation:

MethodBehavior
eth_requestAccountsOpens connect confirmation; returns authorized addresses
eth_accountsReturns previously authorized addresses for this origin
eth_chainIdReturns the chain ID selected in the wallet
wallet_switchEthereumChainReturns null if the chain is selected; otherwise 4902
Read-only eth_* / net_*Forwarded to RPC without confirmation
tron_requestAccountsTRON connect; returns TRON address (T...); auto-switches to TRON network
tron_signTransactionTRON transaction signing via tronWeb.trx.sign

Methods such as eth_sendTransaction, personal_sign, and eth_signTypedData_v4 are reserved for upcoming features.

Legacy window.postMessage API

The original Altitude Wallet dApp API based on window.postMessage messages ALTITUDE_WALLET_CONNECT and ALTITUDE_WALLET_SEND_TO remains supported for backward compatibility. New integrations should prefer the EIP-1193 provider described above.

Connect Wallet

const id = crypto.randomUUID();

window.postMessage(
{
type: 'ALTITUDE_WALLET_CONNECT',
id,
},
'*'
);

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);
}
});

Send Tokens

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',
},
},
'*'
);

Legacy Data Types

Token

FieldTypeRequiredDescription
chainIdnumberYesEVM chain ID (e.g. 1 for Ethereum, 8453 for Base)
addressstringYesToken contract address. Use the zero address for native tokens
namestringYesHuman-readable token name
symbolstringYesToken ticker symbol (e.g. ETH, USDC)
decimalsnumberYesToken decimals (18 for most ERC-20 tokens)
logoURIstringYesURL to the token icon
nativeTokenbooleanNoSet to true for the chain's native gas token

Amount

FieldTypeRequiredDescription
valuenumberYesAmount in human-readable units (e.g. 0.001)
fiatnumberNoUSD-equivalent value for display purposes

Recipient

FieldTypeRequiredDescription
recipientAddressstringYesValid EVM address (0x...)

Complete Example

A minimal integration using the standard EIP-1193 provider:

<!DOCTYPE html>
<html>
<head>
<title>dApp Example</title>
</head>
<body>
<button id="connect">Connect Wallet</button>
<button id="chainId" disabled>Get Chain ID</button>

<script>
const provider = window.ethereum;

document.getElementById('connect').addEventListener('click', async () => {
try {
const accounts = await provider.request({ method: 'eth_requestAccounts' });
console.log('Connected:', accounts[0]);
document.getElementById('chainId').disabled = false;
} catch (err) {
console.error('Connection rejected:', err);
}
});

document.getElementById('chainId').addEventListener('click', async () => {
try {
const chainId = await provider.request({ method: 'eth_chainId' });
console.log('Chain ID:', chainId);
} catch (err) {
console.error(err);
}
});

provider.on('accountsChanged', (accounts) => {
console.log('Accounts changed:', accounts);
});

provider.on('chainChanged', (chainId) => {
console.log('Chain changed:', chainId);
});
</script>
</body>
</html>

RainbowKit + wagmi Integration

RainbowKit v2 supports EIP-6963 multi-wallet discovery out of the box. Altitude Wallet will appear in the wallet selection modal automatically no requires any setup.

npm install @rainbow-me/rainbow-kit wagmi viem @tanstack/react-query
src/App.tsx
import '@rainbow-me/rainbow-kit/styles.css';
import { WagmiProvider } from 'wagmi';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { RainbowKitProvider } from '@rainbow-me/rainbow-kit';

const queryClient = new QueryClient();

function App() {
return (
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
<RainbowKitProvider>
<YourApp />
</RainbowKitProvider>
</QueryClientProvider>
</WagmiProvider>
);
}

Altitude Wallet is automatically appear in the "Connect Wallet" modal via EIP-6963 — No additional configuration is required.

wagmi Configuration

src/wagmi.ts
import { http, createConfig } from 'wagmi';
import { mainnet, sepolia, base } from 'wagmi/chains';

export const config = createConfig({
chains: [mainnet, sepolia, base],
transports: {
[mainnet.id]: http(),
[sepolia.id]: http(),
[base.id]: http(),
},
// EIP-6963 is enabled by default in wagmi v2
multiInjectedProviderDiscovery: true,
});

When multiInjectedProviderDiscovery is true (default), wagmi automatically discovers all EIP-6963 providers including Altitude Wallet. The wallet will appear in RainbowKit's selection modal alongside MetaMask and other wallets.

Web3Modal

src/web3modal.ts
import { createWeb3Modal } from '@web3modal/wagmi/react';
import { mainnet, sepolia, base } from 'wagmi/chains';

const modal = createWeb3Modal({
wagmiConfig: config,
projectId: 'YOUR_PROJECT_ID',
chains: [mainnet, sepolia, base],
// EIP-6963 wallets appear automatically
});

TypeScript Definitions

For projects using TypeScript, the following interfaces describe the provider surface:

interface Eip1193Provider {
request(args: { method: string; params?: unknown[] }): Promise<unknown>;
on(event: string, listener: (...args: unknown[]) => void): void;
removeListener(event: string, listener: (...args: unknown[]) => void): void;
}

interface ProviderError extends Error {
code: number;
data?: unknown;
}

interface Eip6963ProviderInfo {
uuid: string;
name: string;
icon: string;
rdns: string;
}

interface Eip6963AnnounceProviderEvent extends CustomEvent {
detail: {
info: Eip6963ProviderInfo;
provider: Eip1193Provider;
};
}

interface TronWebLike {
defaultAddress: { base58?: string; hex?: string };
trx: {
sign(transaction: unknown): Promise<unknown>;
signMessageV2(message: string): Promise<string>;
};
address: { toHex(base58: string): string };
}

declare global {
interface Window {
ethereum?: Eip1193Provider & { providers?: Eip1193Provider[] };
tronLink?: {
ready: boolean;
tronWeb: TronWebLike;
request(args: { method: string; params?: unknown[] }): Promise<unknown>;
};
tronWeb?: TronWebLike;
}
}

Security Notes

  • User confirmation requiredeth_requestAccounts, wallet_switchEthereumChain, TRON signing, and the legacy sendTo flow open 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 or message without a user actively confirming it in the popup.
  • Origin-scoped permissions — Connected accounts are stored per origin. A dApp can only read accounts it has been authorized to access.
  • Protocol-isolated accounts — EVM and TRON accounts are stored independently per origin. A dApp connecting via eth_requestAccounts always receives the EVM address; tron_requestAccounts always receives the TRON address.
  • Deduplicated, time-bounded connect requests — If the same origin calls eth_requestAccounts or tron_requestAccounts multiple times concurrently (e.g. an auto-reconnect effect racing with a user click), every call shares a single confirmation popup and resolves to the same result rather than opening duplicate windows. If the user never responds, the request rejects with a timeout error after 2 minutes instead of hanging indefinitely.
  • Extension must be installed — The inpage script is injected by the browser extension. Without it, window.ethereum and the legacy window.postMessage bridge are not available.