From c9b4b5257953d683ea0f8331015ea68792fe0f2b Mon Sep 17 00:00:00 2001 From: Alexander Surkov Date: Fri, 1 May 2026 12:49:53 -0400 Subject: [PATCH 1/2] feat(spec/ext) specify getWallet/onPayment --- .../extensions-api/section/events.html | 76 ++++++++++----- .../extensions-api/section/interfaces.html | 30 +++++- .../extensions-api/section/types.html | 92 +++++++++++++++++-- specification/flows/section/storage.html | 12 +++ 4 files changed, 175 insertions(+), 35 deletions(-) diff --git a/specification/extensions-api/section/events.html b/specification/extensions-api/section/events.html index abfb69a8..a0ded360 100644 --- a/specification/extensions-api/section/events.html +++ b/specification/extensions-api/section/events.html @@ -2,9 +2,10 @@

Events

- Events in this namespace are scoped to a {{ Document }}, - identified by its tab and frame. Each event callback receives a - {{MonetizationInfo}} dictionary describing the affected document. + Events in this namespace are scoped to a [[WebMonetization]] + session. Each event callback receives a + {{monetization/Session}} dictionary identifying the affected + session and the document it belongs to.

@@ -15,9 +16,7 @@

onStarted

)

- Fired when the first [[WebMonetization]] session becomes active - in a document. Subsequent sessions starting in the same document - do not re-fire this event. + Fired when a [[WebMonetization]] session starts in a document.

Parameters

@@ -25,11 +24,11 @@

Parameters

callback

The callback parameter looks like:

-
(info: {{MonetizationInfo}}) => void
+
(session: {{monetization/Session}}) => void
-
info
-
The {{MonetizationInfo}} for the document where - monetization started.
+
session
+
The {{monetization/Session}} for the session that + started.
@@ -38,14 +37,14 @@

Parameters

onStopped

-
browser.monetization.onStopped.addListener(
+    
browser.monetization.onStopped.addListener(
   callback: function,
 )

- Fired when the last [[WebMonetization]] session in a document - has ended. This occurs when the tab is closed, the document - navigates away, or all sessions are explicitly stopped. + Fired when a [[WebMonetization]] session ends. This occurs when + the tab is closed, the document navigates away, or the session + is explicitly stopped.

Parameters

@@ -53,11 +52,11 @@

Parameters

callback

The callback parameter looks like:

-
(info: {{MonetizationInfo}}) => void
+
(session: {{monetization/Session}}) => void
-
info
-
The {{MonetizationInfo}} for the document where - monetization stopped.
+
session
+
The {{monetization/Session}} for the session that + stopped.
@@ -67,13 +66,40 @@

Parameters

Event ordering

- For a given document, an {{monetization/onStarted}} event is always - delivered before any corresponding {{monetization/onStopped}} event. - If a document has multiple concurrent sessions, intermediate - session starts and stops do not produce additional events. - Only the transition from zero to one active session - ({{monetization/onStarted}}) and from one to zero active sessions - ({{monetization/onStopped}}) fire events. + For a given session, an {{monetization/onStarted}} event is + always delivered before the corresponding + {{monetization/onStopped}} event. A document with multiple + concurrent sessions receives a separate + {{monetization/onStarted}} and {{monetization/onStopped}} pair + for each session.

+ +
+

onPayment

+ +
browser.monetization.onPayment.addListener(
+  callback: function,
+)
+ +

+ Fired when a payment is sent for a monetization session. The + updated budget balance can be retrieved via + {{monetization/getWallet()}}. +

+ +

Parameters

+
+
callback
+
+

The callback parameter looks like:

+
(session: {{monetization/Session}}) => void
+
+
session
+
The {{monetization/Session}} for the session that + triggered the payment.
+
+
+
+
diff --git a/specification/extensions-api/section/interfaces.html b/specification/extensions-api/section/interfaces.html index 6d18c56b..d2692b83 100644 --- a/specification/extensions-api/section/interfaces.html +++ b/specification/extensions-api/section/interfaces.html @@ -3,16 +3,40 @@

The monetization namespace

The monetization namespace is the entry point for the - Web Monetization Extensions API. It exposes events that allow - extensions to observe monetization session state changes within - documents. + Web Monetization Extensions API. It exposes methods for querying + wallet state and budget balance, and events that allow extensions + to observe monetization session lifecycle and payment activity. +

+ +

+ The full chrome.monetization API includes additional + methods for wallet connection management and session history that + are available only to the browser's built-in WebUI. This + specification covers the subset exposed to privileged browser + extensions.

     [Exposed=Window]
     namespace monetization {
+      Promise<Wallet?> getWallet();
+
       readonly attribute EventHandler onStarted;
       readonly attribute EventHandler onStopped;
+      readonly attribute EventHandler onPayment;
     };
   
+ +
+

Methods

+ +
+

getWallet()

+

+ Returns the connected user wallet, including its current + budget balance. Resolves with null if no wallet + is connected. +

+
+
diff --git a/specification/extensions-api/section/types.html b/specification/extensions-api/section/types.html index 15b46056..b11e9321 100644 --- a/specification/extensions-api/section/types.html +++ b/specification/extensions-api/section/types.html @@ -1,18 +1,91 @@

Types

-
-

MonetizationInfo

+

+ Type names defined here are scoped under the + monetization namespace. Implementations expose them as + namespace-scoped dictionaries on chrome.monetization + (for example, {{monetization/Wallet}} corresponds to + chrome.monetization.Wallet). +

+ +
+

Wallet

- Describes the document where a monetization state change occurred. + Describes the connected user wallet, including its current + budget balance. Currency amounts follow + {{CurrencyAmount}} conventions defined in [[WebMonetization]].

-      dictionary MonetizationInfo {
+      dictionary Wallet {
+        required DOMString address;
+        required DOMString name;
+        required DOMString currency;
+        required DOMString initial;
+        required DOMString remaining;
+        DOMString? renewDate;
+        required boolean needsReconnect;
+      };
+    
+ +

Properties

+
+
address
+
+ The wallet address URL. +
+ +
name
+
+ A human-readable name for the wallet. +
+ +
currency
+
+ An ISO 4217 currency code (e.g. "USD"). +
+ +
initial
+
+ A decimal string representing the total budget for the current + billing period (e.g. "10.00"). +
+ +
remaining
+
+ A decimal string representing the remaining budget for the + current billing period (e.g. "7.50"). +
+ +
renewDate
+
+ An ISO 8601 date string indicating when the budget next renews. + Absent when the budget does not renew monthly. +
+ +
needsReconnect
+
+ true when the stored access token is invalid and the + wallet must be reconnected. +
+
+
+ +
+

Session

+ +

+ Identifies a monetization session and the document it belongs to. +

+ +
+      dictionary Session {
         required long tabId;
         required long frameId;
-        required DOMString url;
+        required long sessionId;
+        required DOMString walletAddress;
       };
     
@@ -29,9 +102,14 @@

Properties

0 denotes the top-level (main) frame. -
url
+
sessionId
+
+ The identifier of the monetization session. +
+ +
walletAddress
- The URL of the monetized document. + The wallet address being paid by this session.
diff --git a/specification/flows/section/storage.html b/specification/flows/section/storage.html index 10286f82..a3413815 100644 --- a/specification/flows/section/storage.html +++ b/specification/flows/section/storage.html @@ -95,6 +95,12 @@

Storage operations

  • Set |storage|'s {{Storage/wallet}} to |walletAddressDetails|.
  • [=Persist storage=] with |storage|.
  • +

    + Each invocation of this algorithm establishes a new wallet connection. Implementations + that track per-connection payment history SHOULD associate sessions and payments with + the credential record created during this connection, so that balance computations are + scoped to the active connection only. +

    @@ -166,6 +172,12 @@

    Storage operations

  • [=Persist storage=] with |storage|.
  • Removes all wallet-related state (grant tokens, authentication keys, wallet address details). Budget limits MAY be retained; implementations can also clear {{Storage/maxRateOfPay}} if the user requests a full reset.

    +

    + Implementations that track payment history SHOULD treat each wallet connection as an + independent scope. When a user disconnects and later reconnects (even to the same wallet address), + the new connection starts with a fresh spending balance. Previous connection data MAY be + retained for historical display but MUST NOT affect the active connection's balance computation. +

    From 686a26654e3eedbfe2af1999710ef52f12bbd7d3 Mon Sep 17 00:00:00 2001 From: Alexander Surkov Date: Fri, 8 May 2026 11:12:40 -0400 Subject: [PATCH 2/2] address comments --- .../extensions-api/section/types.html | 62 +++++++++++++------ 1 file changed, 43 insertions(+), 19 deletions(-) diff --git a/specification/extensions-api/section/types.html b/specification/extensions-api/section/types.html index b11e9321..263baef6 100644 --- a/specification/extensions-api/section/types.html +++ b/specification/extensions-api/section/types.html @@ -4,9 +4,9 @@

    Types

    Type names defined here are scoped under the monetization namespace. Implementations expose them as - namespace-scoped dictionaries on chrome.monetization + namespace-scoped dictionaries on `chrome.monetization` (for example, {{monetization/Wallet}} corresponds to - chrome.monetization.Wallet). + `chrome.monetization.Wallet`).

    @@ -14,19 +14,22 @@

    Wallet

    Describes the connected user wallet, including its current - budget balance. Currency amounts follow - {{CurrencyAmount}} conventions defined in [[WebMonetization]]. + budget balance.

    +      enum ReconnectReason {
    +        "unauthorized"
    +      };
    +
           dictionary Wallet {
             required DOMString address;
             required DOMString name;
             required DOMString currency;
    -        required DOMString initial;
    -        required DOMString remaining;
    +        required DOMString initialBalance;
    +        required DOMString remainingBalance;
             DOMString? renewDate;
    -        required boolean needsReconnect;
    +        ReconnectReason? reconnectReason;
           };
         
    @@ -34,7 +37,12 @@

    Properties

    address
    - The wallet address URL. + The canonical wallet address URL, as returned in the `id` + field of the Open Payments wallet address resource. This is + the resolved address (e.g. + `"https://ilp.example.com/123456/usd"`), which may differ + from the URL the user originally entered (such as a + `.well-known/pay` shortcut).
    name
    @@ -44,19 +52,19 @@

    Properties

    currency
    - An ISO 4217 currency code (e.g. "USD"). + An ISO 4217 currency code (e.g. `"USD"`).
    -
    initial
    +
    initialBalance
    - A decimal string representing the total budget for the current - billing period (e.g. "10.00"). + A decimal string representing the total budget allocated for + the current billing period (e.g. `"10.00"`).
    -
    remaining
    +
    remainingBalance
    - A decimal string representing the remaining budget for the - current billing period (e.g. "7.50"). + A decimal string representing the budget remaining for the + current billing period (e.g. `"7.50"`).
    renewDate
    @@ -65,12 +73,28 @@

    Properties

    Absent when the budget does not renew monthly. -
    needsReconnect
    +
    reconnectReason
    - true when the stored access token is invalid and the - wallet must be reconnected. + When present, indicates that the wallet must be reconnected + before it can be used, and conveys the reason. When absent, + the wallet is usable. Possible values: +
    +
    `"unauthorized"`
    +
    + The stored access token is no longer valid (for example, + it has expired or been revoked). +
    +
    + +

    + The {{Wallet/currency}}, {{Wallet/initialBalance}}, and + {{Wallet/remainingBalance}} members use the same conventions as the + `currency` and `value` members of the {{PaymentCurrencyAmount}} + dictionary defined in [[payment-request]] (and the + `MonetizationCurrencyAmount` interface in [[WebMonetization]]). +

    @@ -99,7 +123,7 @@

    Properties

    frameId
    The identifier of the frame within the tab. - 0 denotes the top-level (main) frame. + `0` denotes the top-level (main) frame.
    sessionId