Two decisions that are each defensible alone and interact badly.
docs/wallet-implementer.md:37 instructs implementers that "uuid should be stable across product versions and page loads", and the example uses a reverse-DNS string. The Wallet follows this — src/inpage.js:10 announces the hardcoded constant "wallet.dusk.extension".
DuskWallet._registerDiscoveredProvider (src/wallet.ts:398-404) then treats uuid as an exclusive ownership key, first claim wins:
const current = this._providers.get(info.uuid);
const sameProvider = current?.provider === detail.provider;
if (current && !sameProvider) return false; // later announcement rejected
So whoever announces a given uuid first owns it for the page, and every later announcement under it — the genuine wallet's included — is silently discarded. The identifier that confers that ownership is a documented public constant.
This is the inverse of the EIP-6963 arrangement, where uuid is a per-session UUIDv4 and rdns carries stable identity, specifically so that a stable identifier is never an ownership token.
Why this does not bite today
An extension content script injects at document_start and registers its listener before any page script runs, so the genuine wallet normally wins the race.
That is a real mitigation. It is also an undocumented timing assumption rather than an enforced property, and it is currently doing more work than anything that is written down.
Proposal
Make the mechanism explicit rather than relying on injection order:
- a per-session random
uuid,
- stable identity carried in
rdns,
- collision handling that surfaces the conflict rather than silently dropping one side.
Scope
The decision applies in three places and should be made once:
src/wallet.ts — registration and conflict resolution,
docs/wallet-implementer.md:37 — currently instructs implementers to do the thing under discussion,
dusk-network/wallet, src/inpage.js:10 — announces the hardcoded constant.
Duplicate-identifier handling in requestDuskProviders (src/discovery.ts:133) resolves last-wins while DuskWallet resolves first-wins, and both are publicly exported. That mismatch is worth fixing in the same pass, since whatever is decided here determines what both should do.
Two decisions that are each defensible alone and interact badly.
docs/wallet-implementer.md:37instructs implementers that "uuidshould be stable across product versions and page loads", and the example uses a reverse-DNS string. The Wallet follows this —src/inpage.js:10announces the hardcoded constant"wallet.dusk.extension".DuskWallet._registerDiscoveredProvider(src/wallet.ts:398-404) then treatsuuidas an exclusive ownership key, first claim wins:So whoever announces a given
uuidfirst owns it for the page, and every later announcement under it — the genuine wallet's included — is silently discarded. The identifier that confers that ownership is a documented public constant.This is the inverse of the EIP-6963 arrangement, where
uuidis a per-session UUIDv4 andrdnscarries stable identity, specifically so that a stable identifier is never an ownership token.Why this does not bite today
An extension content script injects at
document_startand registers its listener before any page script runs, so the genuine wallet normally wins the race.That is a real mitigation. It is also an undocumented timing assumption rather than an enforced property, and it is currently doing more work than anything that is written down.
Proposal
Make the mechanism explicit rather than relying on injection order:
uuid,rdns,Scope
The decision applies in three places and should be made once:
src/wallet.ts— registration and conflict resolution,docs/wallet-implementer.md:37— currently instructs implementers to do the thing under discussion,dusk-network/wallet,src/inpage.js:10— announces the hardcoded constant.Duplicate-identifier handling in
requestDuskProviders(src/discovery.ts:133) resolves last-wins whileDuskWalletresolves first-wins, and both are publicly exported. That mismatch is worth fixing in the same pass, since whatever is decided here determines what both should do.