Kasperia Wallet API Documentation
Integrate Kasperia Wallet by choosing one access mode first: use the injected provider inside the Kasperia App WebView or desktop extension, or use a deep-link request with callback from an external mobile browser. This guide covers connecting accounts, checking networks, reading balances, signing messages, and sending transactions.
window.kasperia for Kaspa native APIs and window.kasperia.ethereum for EVM APIs. New integrations should avoid mixed casing or fallback global names unless a third-party EVM library requires window.ethereum.Kaspa Native
Use window.kasperia to connect a Kaspa account, read network and balance, switch Kaspa network, and send KAS.
EVM
Use window.kasperia.ethereum as an EIP-1193 compatible provider for EVM accounts, chains, RPC, and transactions.
Mobile App
When the dApp is opened inside the Kasperia app, the provider is injected automatically at document start.
Integration Modes
| Mode | When to use | Provider | User confirmation |
|---|---|---|---|
| Mobile In-App Browser | User opens the dApp inside Kasperia App WebView. | window.kasperia and window.kasperia.ethereum | Connect, switch network, signing, and transaction requests are confirmed in the app. |
| External Mobile Browser | User opens the dApp from Safari, Chrome, Telegram, X, or another external app. | No injected provider until the user opens Kasperia App. | Use a deep link or universal link request payload and receive the result by callback. |
| Browser Extension | User opens the dApp in a desktop browser with the Kasperia extension installed. | window.kasperia and window.kasperia.ethereum | Handled by the extension wallet UI. |
Provider Objects
Kasperia exposes one canonical wallet object for dApps:
window.kasperia
For EVM dApps, use the EVM provider under the same namespace:
window.kasperia.ethereum
| Object | Purpose | Use this in new integrations? |
|---|---|---|
window.kasperia | Kaspa native wallet API and shared request entry. | Yes |
window.kasperia.ethereum | EVM EIP-1193 compatible provider. | Yes |
window.ethereum | Compatibility with existing EVM libraries. | Only when a third-party library requires it. |
Quick Start
Most integrations should follow this order:
- Detect the environment. If
window.kasperiaexists, use the injected provider. If it does not exist on mobile, open Kasperia through the external request flow. - Connect after a user click. Use
requestAccounts()for Kaspa oreth_requestAccountsfor EVM. - Check the current network. Read
getNetwork()oreth_chainId. If the user is on the wrong network, call the switch method and wait for confirmation. - Read state. Read the selected account, balance, and network again after connect or switch.
- Submit user actions. Sign messages or send transactions only after the user confirms the action in your UI.
eth_requestAccounts → eth_chainId → wallet_switchEthereumChain if needed → eth_sendTransaction or personal_sign.Copy-paste EVM integration
const KASPLEX_L2_TESTNET = '0x28c64'; // 167012
const KASPLEX_L2_MAINNET = '0x3173b'; // 202555
const BSC_TESTNET = '0x61'; // 97
const BSC_MAINNET = '0x38'; // 56
function getKasperiaWallet() {
return window.kasperia && window.kasperia.isKasperia ? window.kasperia : null;
}
function getKasperiaEvmProvider() {
const wallet = getKasperiaWallet();
return wallet && wallet.ethereum ? wallet.ethereum : null;
}
async function waitForKasperia(timeout = 3000) {
const wallet = getKasperiaWallet();
if (wallet) return wallet;
return new Promise((resolve, reject) => {
const timer = setTimeout(() => reject(new Error('Kasperia provider not found')), timeout);
window.addEventListener('kasperia#initialized', () => {
clearTimeout(timer);
const injected = getKasperiaWallet();
injected ? resolve(injected) : reject(new Error('Kasperia provider not found'));
}, { once: true });
});
}
async function connectEvm() {
await waitForKasperia();
const provider = getKasperiaEvmProvider();
if (!provider) throw new Error('Kasperia EVM provider is not available');
const accounts = await provider.request({ method: 'eth_requestAccounts' });
return { provider, address: accounts[0] };
}
async function ensureEvmChain(provider, targetChainId) {
const currentChainId = await provider.request({ method: 'eth_chainId' });
if (currentChainId.toLowerCase() === targetChainId.toLowerCase()) return;
await provider.request({
method: 'wallet_switchEthereumChain',
params: [{ chainId: targetChainId }]
});
}
async function connectAndPrepareEvm() {
const { provider, address } = await connectEvm();
await ensureEvmChain(provider, KASPLEX_L2_TESTNET);
const balance = await provider.request({
method: 'eth_getBalance',
params: [address, 'latest']
});
return { provider, address, balance };
}
Copy-paste Kaspa native integration
async function connectKaspa() {
const wallet = await waitForKasperia();
const accounts = await wallet.requestAccounts();
const address = accounts[0];
const network = await wallet.getNetwork();
const balance = await wallet.getBalance();
return { wallet, address, network, balance };
}
async function switchKaspaToTestnet10() {
const wallet = await waitForKasperia();
await wallet.switchNetwork('testnet-10');
return await wallet.getNetwork();
}
Demo Test Pages
Use these demo pages inside the same Kasperia web project to test provider injection, external wallet request callbacks, and QR scan links. The demo pages are stored under /demo/; the separate demo home page is intentionally not included.
In-App API Demo
Open this page inside the Kasperia App WebView to test window.kasperia and window.kasperia.ethereum.
External Request Demo
Open this page from a mobile browser to build kasperia://wallet/request or universal-link requests and receive callback results.
QR Links Demo
Generate and copy supported scan-link examples for Bridge, KAS, KRC20, EVM, and dApp URL flows.
kaspatest:qp48ut63r78w5umx6tpk4vu6s4ftv79x2uf56arar3acqs368mxd65sfdeqjl for Kaspa / KRC20 / Bridge tests, and 0x46C7956fDbC3c81b5D5aca9E20d9ACcFF59037BF for EVM tests.Mobile Overview
The Kasperia mobile app supports two mobile access paths:
- In-App Browser: the dApp page runs inside Kasperia WebView. The wallet provider is injected automatically.
- External Browser: the dApp runs outside Kasperia. Use a deep link or universal link request to open Kasperia and get a callback response.
In-App Browser
Use this mode when your dApp is opened inside the Kasperia mobile app. The app injects window.kasperia at document start. Your page should wait for the provider, then use the same APIs as the browser extension integration.
waitForKasperia() after the click, then call the account, network, balance, sign, or transaction method required by your product flow.async function initInKasperiaApp() {
const wallet = await waitForKasperia();
// Kaspa native provider
const kaspaAccounts = await wallet.requestAccounts();
// EVM provider
const evmProvider = wallet.ethereum;
const evmAccounts = evmProvider
? await evmProvider.request({ method: 'eth_requestAccounts' })
: [];
return { wallet, kaspaAccounts, evmProvider, evmAccounts };
}
After connection, always re-read the network before showing balances or enabling transaction buttons.
External Browser
Use this mode when the user opens your dApp in Safari, Chrome, Telegram, X, or another external mobile app. In this environment, the page cannot assume that window.kasperia is injected. Instead, create a wallet request, open Kasperia, and receive the result through your callback URL.
Supported request URLs:
kasperia://wallet/request?payload=<base64url-json>
https://link.kasperia.app/wallet/request?payload=<base64url-json>
kasperia://wallet/request and https://link.kasperia.app/wallet/request.External Request Payload
The payload is a JSON object encoded as base64url without padding. Each request should have a unique id. Your callback handler must decode walletResponse and verify that the response id matches the request id.
const payload = {
id: crypto.randomUUID(),
origin: window.location.origin,
method: 'eth_requestAccounts',
params: {},
callback: `${window.location.origin}/wallet-callback`
};
Encode and open the request:
function base64UrlEncodeJson(json) {
const raw = JSON.stringify(json);
const bytes = new TextEncoder().encode(raw);
let binary = '';
bytes.forEach((b) => binary += String.fromCharCode(b));
return btoa(binary)
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/g, '');
}
function openKasperiaWalletRequest(payload) {
const encoded = base64UrlEncodeJson(payload);
window.location.href = `kasperia://wallet/request?payload=${encoded}`;
}
Kasperia returns the result by appending walletResponse to your callback URL:
https://your-dapp.com/wallet-callback?walletResponse=<base64url-json>
Decoded success response:
{
id: 'request-id',
success: true,
data: ['0x46C7956fDbC3c81b5D5aca9E20d9ACcFF59037BF']
}
Decoded error response:
{
id: 'request-id',
success: false,
error: {
code: 4001,
message: 'User rejected the request'
}
}
https or your app scheme. If origin is provided, the callback host should match the origin host.Mobile Support Matrix
| Action | In-App Browser | External Request | Notes |
|---|---|---|---|
| Connect Kaspa | window.kasperia.requestAccounts() | kasperia_requestAccounts | Shows Connect Wallet confirmation if not authorized. |
| Connect EVM | window.kasperia.ethereum.request({ method: 'eth_requestAccounts' }) | eth_requestAccounts | Returns the current EVM address. |
| Get Kaspa network | window.kasperia.getNetwork() | kasperia_getNetwork | Returns current Kaspa network id. |
| Switch Kaspa network | window.kasperia.switchNetwork('mainnet') | kasperia_switchNetwork | Supports mainnet and testnet-10 aliases depending on app config. |
| Switch EVM chain | wallet_switchEthereumChain | wallet_switchEthereumChain | Shows Switch Network confirmation. |
| Get balance | getBalance / eth_getBalance | Supported | EVM token contract balance is not exposed in the current service. |
| Send KAS | sendKaspa | kasperia_sendKaspa | Amount must be in sompi. |
| Send EVM transaction | eth_sendTransaction | eth_sendTransaction | Shows transaction confirmation. |
| Sign message | personal_sign | personal_sign | Typed data v4 is not supported yet. |
Connect Wallet
Requests access to the current Kaspa account. If the site is not authorized, Kasperia shows a Connect Wallet confirmation.
async function connectKaspaWallet() {
const accounts = await window.kasperia.requestAccounts();
const address = accounts[0];
console.log('Kaspa address:', address);
return address;
}
Returns
['kaspa:...']
// or
['kaspatest:...']
Accounts
After the site is connected, use getAccounts to read the current Kaspa address without opening the connect prompt again.
const accounts = await window.kasperia.getAccounts();
const current = await window.kasperia.request({ method: 'kasperia_currentAccount' });
const publicKey = await window.kasperia.getPublicKey();
Current account response
{
id: 'account-id',
name: 'Account 1',
kaspaAddress: 'kaspa:...',
evmAddress: '0x46C7956fDbC3c81b5D5aca9E20d9ACcFF59037BF',
publicKey: '...',
isCurrent: true
}
Network
Use getNetwork for the current Kaspa network and getNetworks for all available Kaspa and EVM networks.
const currentKaspaNetwork = await window.kasperia.getNetwork();
const allNetworks = await window.kasperia.getNetworks();
Switch Kaspa network:
await window.kasperia.switchNetwork('mainnet');
await window.kasperia.switchNetwork('testnet-10');
You can also use the generic request form:
await window.kasperia.request({
method: 'kasperia_switchNetwork',
params: { type: 'kaspa', network: 'testnet-10' }
});
Balance
Read the current Kaspa account balance. The raw unit is sompi and decimals is 8.
const balance = await window.kasperia.getBalance();
console.log(balance.raw, balance.symbol, balance.decimals);
Response
{
type: 'kaspa',
network: 'mainnet',
address: 'kaspa:...',
symbol: 'KAS',
decimals: 8,
total: '100000000',
available: '100000000',
pending: '0',
raw: '100000000'
}
Send KAS
Use sendKaspa to send KAS. The amount must be passed in sompi.
async function sendKas() {
const to = 'kaspa:qp...';
const sompi = '100000000'; // 1 KAS
const txid = await window.kasperia.sendKaspa(to, sompi, {
payload: ''
});
console.log('Kaspa txid:', txid);
}
Generic request form:
const result = await window.kasperia.request({
method: 'kasperia_sendKaspa',
params: {
to: 'kaspa:qp...',
sompi: '100000000',
payload: ''
}
});
Generic Request
window.kasperia.request is the shared low-level request method. It is useful for methods without a convenience wrapper.
const version = await window.kasperia.getVersion();
const result = await window.kasperia.request({
method: 'kasperia_getNetworks',
params: {}
});
| Method | Description | Params |
|---|---|---|
kasperia_requestAccounts | Connect and return Kaspa account. | {} |
kasperia_accounts | Return connected Kaspa account. | {} |
kasperia_currentAccount | Return current account object. | {} |
kasperia_getPublicKey | Return current account public key. | {} |
kasperia_getBalance | Return Kaspa or EVM balance depending on type. | { type, address } |
kasperia_getNetwork | Return current Kaspa network id. | {} |
kasperia_getNetworks | Return available Kaspa and EVM networks. | {} |
kasperia_switchNetwork | Switch Kaspa or EVM network. | { type, network } or { type, chainId } |
kasperia_sendKaspa | Send KAS. | { to, sompi, payload } |
kasperia_disconnect | Revoke site permission. | {} |
Kaspa Events
window.kasperia.on('networkChanged', (network) => {
console.log('Kaspa network changed:', network);
});
window.kasperia.on('accountsChanged', (accounts) => {
console.log('Kaspa accounts changed:', accounts);
});
Get EVM Provider
Use window.kasperia.ethereum as the recommended EVM provider.
function getEvmProvider() {
if (window.kasperia && window.kasperia.ethereum) {
return window.kasperia.ethereum;
}
return null;
}
The provider supports request, send, sendAsync, enable, events, selectedAddress, chainId, and networkVersion.
Connect EVM Account
async function connectEvmWallet() {
const provider = window.kasperia.ethereum;
const accounts = await provider.request({ method: 'eth_requestAccounts' });
return accounts[0];
}
Read connected EVM accounts without prompting:
const accounts = await window.kasperia.ethereum.request({
method: 'eth_accounts'
});
Get / Switch Chain
Read the current EVM chain id. The result is a hex string.
const chainId = await window.kasperia.ethereum.request({
method: 'eth_chainId'
});
console.log(chainId); // example: '0x28c64' = 167012
Switch EVM chain. Kasperia will show a Switch Network confirmation sheet in the app.
await window.kasperia.ethereum.request({
method: 'wallet_switchEthereumChain',
params: [{ chainId: '0x28c64' }]
});
wallet_addEthereumChain is treated as a switch request to an already configured chain. The current app implementation does not add arbitrary new RPC networks from dApp params.
Get EVM Balance
Use eth_getBalance to read the native EVM balance. The result is a hex quantity.
const address = '0x46C7956fDbC3c81b5D5aca9E20d9ACcFF59037BF';
const balanceHex = await window.kasperia.ethereum.request({
method: 'eth_getBalance',
params: [address, 'latest']
});
You can also use the Kasperia generic request form:
const balance = await window.kasperia.request({
method: 'kasperia_getBalance',
params: {
type: 'evm',
address: '0x46C7956fDbC3c81b5D5aca9E20d9ACcFF59037BF'
}
});
Send EVM Transaction
Use eth_sendTransaction for EVM transfers or contract calls. The app will show a transaction confirmation sheet before submitting the transaction.
async function sendEvmTransaction() {
const provider = window.kasperia.ethereum;
const [from] = await provider.request({ method: 'eth_requestAccounts' });
const txHash = await provider.request({
method: 'eth_sendTransaction',
params: [{
from,
to: '0x46C7956fDbC3c81b5D5aca9E20d9ACcFF59037BF',
value: '0x0',
data: '0x'
}]
});
console.log('EVM tx hash:', txHash);
}
from address must match the current Kasperia EVM account. If it does not match, the request will fail with invalid params.For native transfers without custom gas or data, you may use the generic request form:
const result = await window.kasperia.request({
method: 'kasperia_sendTransaction',
params: {
type: 'evm',
to: '0x46C7956fDbC3c81b5D5aca9E20d9ACcFF59037BF',
amount: '0.01'
}
});
Sign Message
The current mobile implementation supports personal_sign.
const provider = window.kasperia.ethereum;
const [address] = await provider.request({ method: 'eth_requestAccounts' });
const signature = await provider.request({
method: 'personal_sign',
params: ['Hello Kasperia', address]
});
Generic request form:
const signed = await window.kasperia.request({
method: 'kasperia_signMessage',
params: {
message: 'Hello Kasperia',
address: '0x46C7956fDbC3c81b5D5aca9E20d9ACcFF59037BF'
}
});
Read-only RPC
The mobile app proxies common read-only EVM RPC calls through the current selected EVM network RPC URL.
const blockNumber = await window.kasperia.ethereum.request({
method: 'eth_blockNumber'
});
EVM Events
const provider = window.kasperia.ethereum;
provider.on('accountsChanged', (accounts) => {
console.log('EVM accounts changed:', accounts);
});
provider.on('chainChanged', (chainId) => {
console.log('EVM chain changed:', chainId);
});
provider.on('connect', ({ chainId }) => {
console.log('Connected:', chainId);
});
provider.on('disconnect', (error) => {
console.log('Disconnected:', error);
});
QR Scan Link Overview
Kasperia scans the plain-text content inside a QR code, classifies it by protocol, and opens the matching app page with parsed parameters. Scanning only prepares the target page; it does not automatically submit a transfer, mint, bridge action, or transaction. The user must still review and confirm inside the app.
Open the Send KAS page with recipient, amount, and optional payload.
Open an internal Kasperia app page, including Bridge, KRC20 token list, or Ecosystem Fund.
Open KRC20 transfer, mint, or token detail flows.
Open an EVM native-token or contract-token transfer page by chain id.
Open a dApp URL inside the Kasperia in-app browser.
General QR Link Format
Use a plain-text URL or address as the QR content. For routes with parameters, use standard query parameters: ? after the route and & between parameters. Always URL-encode user-generated text, especially payloads, token symbols, addresses inside query values, spaces, symbols, and non-English characters.
| Parameter | Used by | Description | Example |
|---|---|---|---|
to | KAS, KRC20, EVM, Bridge | Recipient address. Kaspa / KRC20 addresses are checked against the current Kaspa network. | to=kaspatest:... |
address | Bridge, Ecosystem Fund | Alternative recipient field accepted by internal app pages. | address=kaspatest:... |
amount | KAS, KRC20, EVM, Bridge, Ecosystem Fund | Optional amount used to pre-fill the target page. Use a human-readable decimal value in QR links. | amount=5 |
payload | KAS | Optional Kaspa transaction payload passed to the Send KAS page. | payload=hello |
tick | KRC20 | KRC20 ticker symbol. Required for transfer, mint, and token detail routes. | tick=JEMES |
chainId | EVM | Required EVM chain id. The app must already have a matching network config. | chainId=56 |
token | EVM | Optional ERC20 contract address. If omitted, the app opens the native-token transfer flow. | token=0x1234567890abcdef1234567890abcdef12345678 |
targetAmount | Ecosystem Fund | Optional target amount for the Ecosystem Fund page. | targetAmount=100 |
KAS Transfer QR
Kaspa transfer QR content opens the Send KAS page. The scanner supports a raw Kaspa address and a transfer-style URL. If amount or payload is included, the app pre-fills those values. The app checks that the scanned recipient address prefix matches the current Kaspa network before opening the send page.
kaspatest:qp48ut63r78w5umx6tpk4vu6s4ftv79x2uf56arar3acqs368mxd65sfdeqjl
kaspa://transfer?to=kaspatest:qp48ut63r78w5umx6tpk4vu6s4ftv79x2uf56arar3acqs368mxd65sfdeqjl&amount=5
kaspa://transfer?to=kaspatest:qp48ut63r78w5umx6tpk4vu6s4ftv79x2uf56arar3acqs368mxd65sfdeqjl&amount=5&payload=hello
function buildKasTransferQr({ to, amount, payload }) {
const params = new URLSearchParams();
params.set('to', to);
if (amount !== undefined && amount !== '') params.set('amount', String(amount));
if (payload) params.set('payload', payload);
return `kaspa://transfer?${params.toString()}`;
}
Kasperia App Pages / Bridge QR
Use the kasperia:// scheme for supported internal app pages. These links are handled by the app page scanner flow.
| QR content | Supported parameters | Result in app |
|---|---|---|
kasperia://bridge | to / address, amount | Open the Bridge page. Recipient and amount are passed as initial values when present. |
kasperia://bridge?to=kaspatest:...&amount=5 | to, amount | Open Bridge with recipient and amount pre-filled. |
kasperia://krc20_tokens | None | Open the KRC20 token list page. |
kasperia://eco_system_fund?address=kaspatest:...&amount=5&targetAmount=100 | address / to, amount, targetAmount | Open the Ecosystem Fund page with receive address, transfer amount, and target amount. |
kasperia://bridge?to=kaspatest:qp48ut63r78w5umx6tpk4vu6s4ftv79x2uf56arar3acqs368mxd65sfdeqjl&amount=5
kasperia://krc20_tokens
kasperia://eco_system_fund?address=kaspatest:qp48ut63r78w5umx6tpk4vu6s4ftv79x2uf56arar3acqs368mxd65sfdeqjl&amount=5&targetAmount=100
KRC20 Transfer / Mint QR
Use the krc20:// scheme for KRC20 actions. The app reads tick as the token identifier, checks the current account token data when needed, and opens the matching KRC20 page. For transfer and mint, if a recipient is provided, the Kaspa address prefix must match the current Kaspa network.
| Action | QR content | Required parameters | Result in app |
|---|---|---|---|
| Transfer | krc20://transfer?tick=JEMES&to=kaspatest:...&amount=5 | tick; optional to, amount | Open the KRC20 Send page for the ticker. |
| Mint | krc20://mint?tick=JEMES&to=kaspatest:...&amount=5 | tick; optional to, amount | Open the KRC20 Mint page. If to is missing, the current account Kaspa address is used. |
| Token detail | krc20://token?tick=JEMES | tick | Open the KRC20 token detail page if the token exists for the current account. |
krc20://transfer?tick=JEMES&to=kaspatest:qp48ut63r78w5umx6tpk4vu6s4ftv79x2uf56arar3acqs368mxd65sfdeqjl&amount=5
krc20://mint?tick=JEMES&to=kaspatest:qp48ut63r78w5umx6tpk4vu6s4ftv79x2uf56arar3acqs368mxd65sfdeqjl&amount=5
krc20://token?tick=JEMES
function buildKrc20TransferQr({ tick, to, amount }) {
const params = new URLSearchParams();
params.set('tick', tick);
if (to) params.set('to', to);
if (amount !== undefined && amount !== '') params.set('amount', String(amount));
return `krc20://transfer?${params.toString()}`;
}
EVM Transfer QR
Use the ethereum://transfer scheme to open the EVM Send page. chainId is required. The app looks up the network by chain id; if no configured network is found, the scanner shows an error. If token is omitted, the app opens the native-token transfer flow. If token is provided, the app treats it as a contract token address and opens the token transfer flow.
ethereum://transfer?chainId=56&to=0x46C7956fDbC3c81b5D5aca9E20d9ACcFF59037BF&amount=1.5
ethereum://transfer?chainId=56&token=0x1234567890abcdef1234567890abcdef12345678&to=0x46C7956fDbC3c81b5D5aca9E20d9ACcFF59037BF&amount=100
chainId must be a positive number and must exist in the app EVM network configuration.function buildEvmTransferQr({ chainId, to, amount, token }) {
const params = new URLSearchParams();
params.set('chainId', String(chainId));
if (to) params.set('to', to);
if (amount !== undefined && amount !== '') params.set('amount', String(amount));
if (token) params.set('token', token);
return `ethereum://transfer?${params.toString()}`;
}
Open dApp URL QR
If the scanned QR content is a normal http:// or https:// web URL, Kasperia opens it inside the app WebView. The dApp can then use window.kasperia and window.kasperia.ethereum after provider injection.
https://kas.fun/
http://example.com/dapp
https://kasbridge-tn10evm-m.kaspafoundation.org/
https://. Use http:// only for local development, testing, or trusted internal environments.Recommended dApp behavior after being opened from a QR:
async function initAfterQrOpen() {
const wallet = await waitForKasperia();
const accounts = await wallet.requestAccounts();
const network = await wallet.getNetwork();
return { accounts, network };
}
QR Builder Examples
Developers can generate QR codes with any QR library as long as the encoded content is the exact plain-text link that the scanner should receive.
import QRCode from 'qrcode';
const qrText = 'krc20://transfer?tick=JEMES&to=kaspatest:qp48ut63r78w5umx6tpk4vu6s4ftv79x2uf56arar3acqs368mxd65sfdeqjl&amount=5';
const dataUrl = await QRCode.toDataURL(qrText);
document.querySelector('#qr').src = dataUrl;
Plain JavaScript helper for building supported scan links safely:
const KAS_TEST_ADDRESS = 'kaspatest:qp48ut63r78w5umx6tpk4vu6s4ftv79x2uf56arar3acqs368mxd65sfdeqjl';
const examples = {
kasAddressOnly: KAS_TEST_ADDRESS,
kasTransfer: `kaspa://transfer?to=${encodeURIComponent(KAS_TEST_ADDRESS)}&amount=5&payload=${encodeURIComponent('hello world')}`,
bridge: `kasperia://bridge?to=${encodeURIComponent(KAS_TEST_ADDRESS)}&amount=5`,
krc20TokenList: 'kasperia://krc20_tokens',
ecosystemFund: `kasperia://eco_system_fund?address=${encodeURIComponent(KAS_TEST_ADDRESS)}&amount=5&targetAmount=100`,
krc20Transfer: `krc20://transfer?tick=JEMES&to=${encodeURIComponent(KAS_TEST_ADDRESS)}&amount=5`,
krc20Mint: `krc20://mint?tick=JEMES&to=${encodeURIComponent(KAS_TEST_ADDRESS)}&amount=5`,
krc20Token: 'krc20://token?tick=JEMES',
evmNativeTransfer: 'ethereum://transfer?chainId=56&to=0x46C7956fDbC3c81b5D5aca9E20d9ACcFF59037BF&amount=1.5',
evmTokenTransfer: 'ethereum://transfer?chainId=56&token=0x1234567890abcdef1234567890abcdef12345678&to=0x46C7956fDbC3c81b5D5aca9E20d9ACcFF59037BF&amount=100',
dappHttps: 'https://kas.fun/',
dappHttp: 'http://example.com/dapp'
};
Validation Notes
- Scanning a payment, mint, bridge, or EVM QR opens a pre-filled app page; the user must still confirm the action.
- For Kaspa and KRC20 links, the recipient address prefix must match the current Kaspa network. Use
kaspa:on mainnet andkaspatest:on testnet. - For KRC20 actions,
tickis required. If the token cannot be found for the current account, the app shows an error. - For EVM transfer links,
chainIdis required, must be greater than zero, and must exist in the app EVM network config. - For EVM contract-token transfers,
tokenmust be a valid contract address on the selected chain. - For dApp QR links,
http://andhttps://URLs are opened inside the app WebView. - Use
encodeURIComponentorURLSearchParamswhen generating QR links from JavaScript. - Unsupported or unknown protocols should be treated as invalid QR content.
Network Reference
Use window.kasperia.getNetworks() to get the exact networks configured in the current app build. A network item may include the following fields:
{
type: 'evm',
id: '167012',
name: 'Kasplex L2 Testnet',
isCurrent: true,
chainId: 167012,
rpcUrl: 'https://...',
explorerUrl: 'https://...',
symbol: 'KAS',
decimals: 18
}
getNetworks() and then switching to a chain that exists in the returned list.Error Codes
| Code | Meaning | Common reason |
|---|---|---|
4001 | User rejected | User tapped Cancel, Reject, or closed the request. |
4100 | Unauthorized | The site is not connected to Kasperia Wallet. |
4200 | Unsupported method | The method is not exposed by the current app service. |
4900 | Disconnected | The wallet provider was disconnected. |
-32602 | Invalid params | Missing address, invalid chain id, invalid transaction params, or mismatched from address. |
-32603 | Internal error | Wallet bridge, RPC, or transaction service failed. |
try {
await window.kasperia.ethereum.request({
method: 'wallet_switchEthereumChain',
params: [{ chainId: '0x28c64' }]
});
} catch (error) {
if (error.code === 4001) {
console.log('User rejected the request');
} else {
console.error(error.code, error.message, error.data);
}
}
Best Practices
- Use
window.kasperiaas the single canonical namespace in your dApp. - Use
window.kasperia.ethereumfor EVM requests instead of mixing multiple provider names. - Always call connect, switch network, signing, and transaction APIs from a user click or similar direct action.
- Disable your button while a wallet request is pending to avoid duplicate confirmation sheets.
- After switching EVM chains, re-read
eth_chainIdand update your UI from thechainChangedevent. - Pass EVM transaction
value,gas,gasPrice, andnonceas hex quantities. - Pass Kaspa transfer amounts in sompi, not decimal KAS.
- For external callback flows, generate a unique
idfor every request and verify the response id.
Unsupported Methods
| Method | Status | Recommendation |
|---|---|---|
kasperia_submitCommitReveal | Not supported in mobile WebView yet. | Do not expose KNS/KRC commit-reveal flows through the mobile dApp API until app service support is added. |
kasperia_signTransaction | Not exposed by current wallet services. | Use send transaction flows that show confirmation and submit through the app. |
eth_signTypedData_v4 | Not supported yet. | Use personal_sign only if your use case allows it. |
| ERC20 balance by contract | Not exposed by current mobile service. | Use read-only RPC calls or your own RPC/indexer for token balances. |
KASPERIA