Spooky Doge Logo

dApp Integration Guide

Integrate your dApp with Spooky Doge wallet for Dogecoin payments and Doginal transfers


Platform Support

Spooky Doge wallet is available on:

Both platforms inject the same window.dogecoin provider, so you can support all users with a single codebase.

Quick Start

1. Detect the Wallet

// 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!');
});

2. Connect to the Wallet

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

3. Get Account Information

// 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();

4. Send DOGE

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

5. Work with Doginals (Inscriptions)

// 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...');

6. Sign Messages

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

7. Work with DRC-20 Tokens

// 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)

8. Work with Dunes Tokens

// 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)

9. Listen for Events

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

API Reference

Provider Object

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

Methods

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
  }>;
}
Marketplace Tip: Use multi-output to include your marketplace fee in the same transaction. Each output is shown to the user for approval, ensuring full transparency.
Fee Structure: All transactions include a 0.01 DOGE wallet fee plus network fees (~0.02 DOGE). These are shown separately in the approval dialog so users see exactly where their funds go.

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
}
Multi-Send: Pass an array of inscription IDs to transfer multiple doginals in a single transaction. Fees scale per inscription: 0.02 DOGE network fee + 0.01 DOGE wallet fee = 0.03 DOGE per inscription. The approval dialog shows each fee component separately.

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

Security Note: Users must review and explicitly approve each PSBT signing request. The approval popup displays the origin, transaction data, and any message from the marketplace.

Example: Marketplace Integration

// 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_requestAccountsRequest wallet connection
doge_accountsGet connected accounts
doge_getBalanceGet wallet balance
doge_getDoginalsGet doginals in wallet (supports pagination)
doge_sendTransactionSend DOGE (single or multi-output)
doge_sendDoginalTransfer doginals (single or batch)
doge_getDrc20BalancesGet DRC-20 token balances
doge_sendDrc20Send DRC-20 tokens
doge_getDunesBalancesGet Dunes token balances
doge_sendDuneSend Dunes tokens
doge_signMessageSign a message (free, no DOGE cost)
doge_signPsbtSign a partially signed transaction (marketplace integration)
doge_chainIdGet chain identifier ("dogecoin:mainnet")

on(event, callback)

Subscribe to wallet events.

Events:

removeListener(event, callback)

Unsubscribe from wallet events.


Fee Structure

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 Handling

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

Security Notes

  1. User Approval Required - All transactions require explicit user approval via popup
  2. Per-Site Permissions - Each website must be approved separately; users can manage connections in Settings
  3. Non-Custodial - Private keys never leave the wallet
  4. Inscription Protection - UTXOs under 0.1 DOGE are protected from regular spending
  5. Dev Fee Transparency - 0.01 DOGE dev fee included in all transactions

Platform Notes

Browser Extension

Mobile App

Suggesting Users Open in Spooky Doge

if (!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' }
    ]
  });
}

Support

For integration support or questions: