window.dogesoft
Accepting payments
Two ways to get paid through a connected wallet, plus why a self-reported txid isn't proof of payment.
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 — signPsbt(), self-serve today
Build the payment transaction yourself — a plain P2PKH output to your address, or a DRC-20 transfer envelope (see the DRC-20 protocol page) — and hand it to the wallet to sign. No allow-list, no waiting on anyone: this works the moment a user connects.
// your own PSBT builder — UTXO selection, fee, output to your address
const psbt = buildPaymentPsbt({ to: merchantAddress, amountDoge: 4.2 });
const { hex } = await dogesoft.signPsbt(psbt, { finalize: true });
const { txid } = await dogesoft.pushPsbt(hex);
This is more work than Path 2 below — you own UTXO selection, fee estimation, and, for DRC-20, the
commit → reveal → move choreography described on the
send pipeline page. It's the right call when you can't
wait on an allow-list entry, or need something sendDoge() doesn't cover.
Path 2 — sendDoge(), less work, allow-list gated
sendDoge() hands the wallet a plain-language intent — recipient,
amount — and it builds and signs everything for you, the same call documented on the
sending page. On the mobile app specifically, this call
also requires a protocol string the wallet already recognizes — an
allow-list, not a public field you can set to anything. Today that list has two entries: an internal
liquidity flow, and two public DogeSoft surfaces:
"dogesoft-shop-checkout" for
shop.dogesoft.io, and
"dogesoft-launch-mint" for
launch.dogesoft.io
collection mint prices.
await dogesoft.connect();
const { txid } = await dogesoft.sendDoge({
to: merchantAddress,
amount: 4.2,
protocol: "your-allow-listed-protocol" // required on mobile — see below
});
// record `txid` against your own order, then verify it — don't trust it yet
Getting your own protocol string added isn't a public self-serve endpoint yet — same status as bonding-curve coin launches.
window.dogesoft is the same surface in the browser extension and
the mobile app's in-app browser (provider 1.1.0+). The recognized
protocol strings in the allow-list above route the dedicated
checkout / deposit flow on both; omitting protocol falls through to
a plain sendDoge().
shop.dogesoft.io integrates against this exact surface.
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.
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() with an allow-listed protocol → 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.