// GENERATED CONTENT - DO NOT EDIT
// Content was automatically extracted by Reffy into reffy-reports
// (https://github.com/tidoust/reffy-reports)
// Source: Payment Handler API (https://w3c.github.io/payment-handler/)

partial interface ServiceWorkerRegistration {
  [SameObject] readonly attribute PaymentManager paymentManager;
};

[SecureContext, Exposed=(Window,Worker)]
interface PaymentManager {
  [SameObject] readonly attribute PaymentInstruments instruments;
  attribute DOMString userHint;
};

[SecureContext, Exposed=(Window,Worker)]
interface PaymentInstruments {
    Promise<boolean> delete(DOMString instrumentKey);
    Promise<any> get(DOMString instrumentKey);
    Promise<sequence<DOMString>> keys();
    Promise<boolean> has(DOMString instrumentKey);
    Promise<void> set(DOMString instrumentKey, PaymentInstrument details);
    Promise<void> clear();
};

dictionary PaymentInstrument {
  required DOMString name;
  sequence<ImageObject> icons;
  DOMString method;
  object capabilities;
};

dictionary ImageObject {
    required USVString src;
    DOMString sizes;
    DOMString type;
};

partial interface ServiceWorkerGlobalScope {
  attribute EventHandler oncanmakepayment;
};

[Constructor(DOMString type, CanMakePaymentEventInit eventInitDict), Exposed=ServiceWorker]
interface CanMakePaymentEvent : ExtendableEvent {
  readonly attribute USVString topOrigin;
  readonly attribute USVString paymentRequestOrigin;
  readonly attribute FrozenArray<PaymentMethodData> methodData;
  void respondWith(Promise<boolean> canMakePaymentResponse);
};

dictionary CanMakePaymentEventInit : ExtendableEventInit {
  USVString topOrigin;
  USVString paymentRequestOrigin;
  sequence<PaymentMethodData> methodData;
};

partial interface ServiceWorkerGlobalScope {
  attribute EventHandler onpaymentrequest;
};

dictionary PaymentMethodChangeResponse {
  DOMString error;
  PaymentCurrencyAmount total;
  FrozenArray<PaymentDetailsModifier> modifiers;
  object paymentMethodErrors;
};

[Constructor(DOMString type, PaymentRequestEventInit eventInitDict), Exposed=ServiceWorker]
interface PaymentRequestEvent : ExtendableEvent {
  readonly attribute USVString topOrigin;
  readonly attribute USVString paymentRequestOrigin;
  readonly attribute DOMString paymentRequestId;
  readonly attribute FrozenArray<PaymentMethodData> methodData;
  readonly attribute object total;
  readonly attribute FrozenArray<PaymentDetailsModifier> modifiers;
  readonly attribute DOMString instrumentKey;
  readonly attribute boolean requestBillingAddress;
  Promise<WindowClient?> openWindow(USVString url);
  Promise<PaymentMethodChangeResponse?> changePaymentMethod(DOMString methodName, optional object? methodDetails = null);
  void respondWith(Promise<PaymentHandlerResponse> handlerResponsePromise);
};

dictionary PaymentRequestEventInit : ExtendableEventInit {
  USVString topOrigin;
  USVString paymentRequestOrigin;
  DOMString paymentRequestId;
  sequence<PaymentMethodData> methodData;
  PaymentCurrencyAmount total;
  sequence<PaymentDetailsModifier> modifiers;
  DOMString instrumentKey;
};

dictionary PaymentHandlerResponse {
DOMString methodName;
object details;
};
