Integrate your dApp with Spooky Doge wallet for Dogecoin payments and Doginal transfers
Spooky Doge wallet is available on:
window.dogecoin provider, so you can support all users with a single codebase.
// Check if Spooky Doge wallet is available
function isSpookyWalletAvailable() {
return typeof window.dogecoin !== 'undefined' && window.dogecoin.isSpookyWallet;
}
// Wait for wallet to be ready (it injects after page load)
window.addEventListener('dogecoin#initialized', () => {
console.log('Spooky Doge wallet detected!');
});
async function connectWallet() {
if (!isSpookyWalletAvailable()) {
alert('Please install Spooky Doge wallet or open in the Spooky Doge app browser');
return null;
}
try {
// Opens approval popup for user
const result = await window.dogecoin.connect();
console.log('Connected! Address:', result.address);
return result.address;
} catch (error) {
console.error('Connection rejected:', error.message);
return null;
}
}
// Get connected address
const address = await window.dogecoin.getAddress();
// Get wallet balance in koinu (1 DOGE = 100,000,000 koinu)
const balance = await window.dogecoin.getBalance();
const dogeBalance = balance / 100000000;
// Check if currently connected
const connected = window.dogecoin.isConnected();
// Get all connected accounts
const accounts = await window.dogecoin.getAccounts();
// Simple single-output transaction
async function sendPayment(recipientAddress, amountInDoge) {
try {
// Opens transaction approval popup
const result = await window.dogecoin.sendTransaction({
to: recipientAddress,
amount: amountInDoge // Amount in DOGE (not koinu)
});
console.log('Transaction sent! TXID:', result.txid);
return result.txid;
} catch (error) {
console.error('Transaction failed:', error.message);
throw error;
}
}
// Advanced: Multi-output transaction (e.g., with marketplace fee)
async function sendPaymentWithFee(recipientAddress, amount, marketplaceFeeAddress, feeAmount) {
try {
const result = await window.dogecoin.sendTransaction({
outputs: [
{ address: recipientAddress, amount: amount },
{ address: marketplaceFeeAddress, amount: feeAmount }
]
});
console.log('Transaction sent! TXID:', result.txid);
return result.txid;
} catch (error) {
console.error('Transaction failed:', error.message);
throw error;
}
}
// Example: Send 100 DOGE to seller + 5 DOGE marketplace fee
await sendPaymentWithFee('DSellerAddress...', 100, 'DMarketplaceFeeAddress...', 5);
// Get all doginals in the wallet
const doginals = await window.dogecoin.getDoginals();
doginals.forEach(d => {
console.log('Inscription:', d.inscriptionId);
console.log('Image URL:', d.imageUrl);
console.log('Content Type:', d.contentType);
});
// Transfer a single doginal
async function transferDoginal(inscriptionId, recipientAddress) {
try {
const result = await window.dogecoin.sendDoginal({
inscriptionId: inscriptionId, // Single inscription ID
to: recipientAddress
});
console.log('Doginal transferred! TXID:', result.txid);
return result.txid;
} catch (error) {
console.error('Transfer failed:', error.message);
throw error;
}
}
// Transfer MULTIPLE doginals in one transaction
async function transferMultipleDoginals(inscriptionIds, recipientAddress) {
try {
const result = await window.dogecoin.sendDoginal({
inscriptionId: inscriptionIds, // Array of inscription IDs
to: recipientAddress
});
console.log('Doginals transferred! TXID:', result.txid);
return result.txid;
} catch (error) {
console.error('Transfer failed:', error.message);
throw error;
}
}
// Example: Send 3 doginals at once
const myDoginals = ['abc123i0', 'def456i0', 'ghi789i0'];
await transferMultipleDoginals(myDoginals, 'DRecipientAddress...');
// Request a message signature (no cost, requires user approval)
async function signMessage(message) {
try {
const result = await window.dogecoin.signMessage(message);
console.log('Signature:', result.signature);
console.log('Signed by:', result.address);
return result;
} catch (error) {
console.error('Signing failed:', error.message);
throw error;
}
}
// Get DRC-20 token balances
async function getDrc20Balances() {
const balances = await window.dogecoin.request({
method: 'doge_getDrc20Balances'
});
// Returns: [{ tick: 'DOGI', available: '1000', transferable: '500', total: '1500' }, ...]
return balances;
}
// Send DRC-20 tokens
async function sendDrc20(tick, amount, recipient) {
const result = await window.dogecoin.request({
method: 'doge_sendDrc20',
params: {
tick: tick, // Token ticker (e.g., 'DOGI')
amount: amount, // Amount as string
to: recipient // Recipient address
}
});
return result.txid;
}
Fee: 0.03 DOGE per transfer (0.02 network + 0.01 wallet)
// Get Dunes token balances
async function getDunesBalances() {
const balances = await window.dogecoin.request({
method: 'doge_getDunesBalances'
});
// Returns: [{ name: 'COOL•DUNE', symbol: 'COOLDUNE', balance: '5000', divisibility: 0 }, ...]
return balances;
}
// Send Dunes tokens
async function sendDune(duneName, amount, recipient) {
const result = await window.dogecoin.request({
method: 'doge_sendDune',
params: {
duneName: duneName, // Dune name (e.g., 'COOL•DUNE')
amount: amount, // Amount as string
to: recipient // Recipient address
}
});
return result.txid;
}
Fee: Variable (0.02 DOGE for single-dune UTXO, 0.20 DOGE for multi-dune auto-split)
// Account changes (user switches address)
window.dogecoin.on('accountsChanged', (accounts) => {
if (accounts.length === 0) {
console.log('Wallet disconnected');
} else {
console.log('Active account:', accounts[0]);
}
});
// Connection events
window.dogecoin.on('connect', ({ address }) => {
console.log('Connected:', address);
});
window.dogecoin.on('disconnect', () => {
console.log('Wallet disconnected');
});
Available at window.dogecoin or window.spookyWallet
| Property | Type | Description |
|---|---|---|
isSpookyWallet |
boolean |
Always true - identifies the wallet |
isConnected() |
function |
Returns true if site is connected |
connect()Request wallet connection. Opens approval popup.
Returns: Promise<{ address: string }>
disconnect()Disconnect the dApp from the wallet.
Returns: Promise<void>
getAddress()Get the currently connected address.
Returns: Promise<string | null> - Null if not connected
getAccounts()Get all connected accounts.
Returns: Promise<string[]>
getBalance()Get wallet balance in koinu.
Returns: Promise<number> - Balance in koinu (divide by 100,000,000 for DOGE)
getDoginals()Get all doginals (inscriptions) in the wallet.
Returns: Promise<Doginal[]>
interface Doginal {
inscriptionId: string; // Unique inscription identifier
output: string; // UTXO reference (txid:vout)
contentType: string; // MIME type (e.g., 'image/png', 'text/html')
imageUrl: string; // CDN URL for the content
value?: number; // UTXO value in DOGE (optional)
}
sendTransaction(params)Request a DOGE transaction. Opens approval popup. Supports both simple single-output and advanced multi-output formats.
Parameters (Simple):
{
to: string; // Recipient Dogecoin address
amount: number; // Amount in DOGE (not koinu)
}
Parameters (Multi-Output):
{
outputs: Array<{
address: string; // Recipient Dogecoin address
amount: number; // Amount in DOGE
}>;
}
Returns: Promise<{ txid: string }>
sendDoginal(params)Request a doginal transfer. Opens approval popup. Supports both single and multiple inscription transfers.
Parameters:
{
inscriptionId: string | string[]; // Single ID or array of inscription IDs
to: string; // Recipient Dogecoin address
}
Returns: Promise<{ txid: string }>
signMessage(message)Request a message signature. Opens approval popup. Free - no DOGE cost
Parameters: message (string) - The message to sign
Returns: Promise<{ signature: string, address: string }>
The signature is in Bitcoin/Dogecoin signed message format (base64-encoded, 65 bytes), compatible with verifymessage in Dogecoin Core.
signPsbt(params)Request signing of a partially signed transaction (PSBT). Opens approval popup. Marketplace Integration
This method enables marketplaces like InuBits to request partial transaction signing for trading Doginals, DRC-20 tokens, and Dunes. The wallet signs only the specified inputs, returning the signed hex to the marketplace for finalization and broadcast.
Parameters:
{
psbtHex: string; // Raw transaction hex to sign
signInputs?: number[]; // Input indices to sign (default: all)
sighashTypes?: number[]; // Sighash types (default: [0x01] SIGHASH_ALL)
message?: string; // Optional message to display to user
}
Returns: Promise<{ signedPsbtHex: string }>
// Example: Request PSBT signing for a marketplace trade
async function signMarketplaceTrade(psbtHex, inputsToSign) {
try {
const result = await window.dogecoin.signPsbt({
psbtHex: psbtHex,
signInputs: inputsToSign,
message: 'Sign to complete your trade on MyMarketplace'
});
console.log('Signed transaction:', result.signedPsbtHex);
return result.signedPsbtHex;
} catch (error) {
console.error('PSBT signing failed:', error.message);
throw error;
}
}
request(args)EIP-1193 style request method for compatibility.
// Examples
const accounts = await window.dogecoin.request({ method: 'doge_requestAccounts' });
const balance = await window.dogecoin.request({ method: 'doge_getBalance' });
const doginals = await window.dogecoin.request({ method: 'doge_getDoginals' });
const result = await window.dogecoin.request({
method: 'doge_sendTransaction',
params: { to: 'DAddress...', amount: 10 }
});
Supported Methods:
| Method | Description |
|---|---|
doge_requestAccounts | Request wallet connection |
doge_accounts | Get connected accounts |
doge_getBalance | Get wallet balance |
doge_getDoginals | Get doginals in wallet (supports pagination) |
doge_sendTransaction | Send DOGE (single or multi-output) |
doge_sendDoginal | Transfer doginals (single or batch) |
doge_getDrc20Balances | Get DRC-20 token balances |
doge_sendDrc20 | Send DRC-20 tokens |
doge_getDunesBalances | Get Dunes token balances |
doge_sendDune | Send Dunes tokens |
doge_signMessage | Sign a message (free, no DOGE cost) |
doge_signPsbt | Sign a partially signed transaction (marketplace integration) |
doge_chainId | Get chain identifier ("dogecoin:mainnet") |
on(event, callback)Subscribe to wallet events.
Events:
connect - Fired when connected, receives { address: string }disconnect - Fired when disconnectedaccountsChanged - Fired when active address changes, receives string[]removeListener(event, callback)Unsubscribe from wallet events.
| Transaction Type | Network Fee | Dev Fee | Total |
|---|---|---|---|
| Regular DOGE send | Dynamic (based on tx size) | 0.01 DOGE | Variable |
| Doginal transfer | 0.02 DOGE | 0.01 DOGE | 0.03 DOGE |
| Multi-doginal transfer | 0.02 DOGE x count | 0.01 DOGE | Variable |
| DRC-20 transfer | 0.02 DOGE | 0.01 DOGE | 0.03 DOGE |
| Dune transfer | 0.02 DOGE | 0.01 DOGE | 0.03 DOGE |
| Multi-dune transfer | 0.20 DOGE | 0.01 DOGE | 0.21 DOGE |
| Error Message | Cause |
|---|---|
"Connection rejected by user" | User declined connection request |
"Site not connected" | dApp not connected to wallet |
"Wallet not unlocked" | User hasn't unlocked the wallet |
"Transaction rejected by user" | User declined transaction |
"Doginal transfer rejected by user" | User declined doginal transfer |
"Message signing rejected by user" | User declined signature request |
"PSBT signing rejected by user" | User declined PSBT signing request |
"Invalid PSBT params: psbtHex is required" | Missing psbtHex parameter |
"Insufficient funds" | Not enough DOGE for transaction + fees |
"Inscription not found in wallet" | Requested inscription not in wallet |
dist-extension folderif (!isSpookyWalletAvailable()) {
// Show a banner or modal
showModal({
title: 'Use Spooky Doge Wallet',
message: 'For the best experience, open this site in the Spooky Doge app browser.',
buttons: [
{ text: 'Get the App', url: 'https://spooksociety.xyz' },
{ text: 'Continue Anyway', action: 'dismiss' }
]
});
}
For integration support or questions: