Docs / Wallet provider / Accepting payments

window.dogesoft

Accepting payments

Two ways to get paid through a connected wallet, plus why a self-reported txid isn't proof of payment.

Live

Two ways to get paid through a connected DogeSoft wallet, in order of how fast you can ship them. Both show the user the real destination and amount before anything signs — nothing here bypasses that.

Path 1 — sendDoge(), least work

sendDoge() hands the wallet a plain intent (recipient and amount) and the wallet builds, signs and broadcasts everything after the user approves. It works the same in the extension and the mobile app's browser, with no allow-list. See the sending page.

accept-via-senddoge.js
await dogesoft.connect();
const { txid } = await dogesoft.sendDoge({
  to: merchantAddress,
  amount: 4.2        // DOGE
});
// record `txid` against your own order, then verify it — don't trust it yet

For DRC-20 payments use sendDrc20({ tick, amount, to }) and verify the coins arrived with the Explorer API.

Path 2 — signPsbt(), full control

Build the payment transaction yourself on your server (a plain P2PKH output to your address, plus your own inputs, fee and change logic) and hand it to the wallet to sign.

accept-via-psbt.js
// psbt from your backend (inputs must include nonWitnessUtxo)
const { txHex } = await dogesoft.signPsbt(psbt, { finalize: true });
// send txHex to your server, which broadcasts it via the Explorer API
// (POST /api/tx/broadcast { hex }) and records the txid
ℹ️

This is more work than Path 1: you own UTXO selection, fee estimation and change. See PSBTs.

Verify before you trust it

Either path above ends with a txid the wallet reports back to your page — that's a claim, not proof. Nothing stops a bug, a network hiccup, or a malicious client from reporting a txid that never happened or paid the wrong amount. Confirm it independently against the Explorer API before marking anything paid.

verify-payment.js (run on your server)
const res = await fetch(
  `https://explorer.dogesoft.io/api/wallet/address/${merchantAddress}/history?count=200`
);
const { items } = await res.json();

const paid = items.some((tx) =>
  tx.txid === claimedTxid &&
  tx.direction === "in" &&
  tx.counterparty_address === buyerAddress &&
  tx.amount_koinu >= expectedKoinu &&
  tx.confirmations >= 1
);
💡

Match on the buyer's own counterparty_address, not amount alone — flat pricing means two simultaneous buyers can owe the identical amount, and the buyer's address is already known from DogeSoft Connect for free. Don't trust a match with zero confirmations — a mempool-only transaction can still be dropped.

Worked example

shop.dogesoft.io runs exactly this pattern end to end: connect → sendDoge() → record the claimed txid → independently verify it against Explorer on an interval, whether or not the customer's page is still open — the same "doesn't need to stay open" property as the DRC-20 send pipeline. Its order confirmation screen distinguishes "sent" (broadcast, unconfirmed) from "confirmed" (independently verified) rather than treating a self-reported txid as final.