@enbox/browser 0.3.70 → 0.3.72

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +30 -7
  2. package/dist/browser.mjs +14 -14
  3. package/dist/browser.mjs.map +4 -4
  4. package/dist/esm/blob-url-pool.js +36 -0
  5. package/dist/esm/blob-url-pool.js.map +1 -0
  6. package/dist/esm/browser-connect-handler.js +3 -1
  7. package/dist/esm/browser-connect-handler.js.map +1 -1
  8. package/dist/esm/file-envelope-url-store.js +203 -0
  9. package/dist/esm/file-envelope-url-store.js.map +1 -0
  10. package/dist/esm/index.js +12 -12
  11. package/dist/esm/index.js.map +1 -1
  12. package/dist/esm/object-url-reference.js +68 -0
  13. package/dist/esm/object-url-reference.js.map +1 -0
  14. package/dist/esm/relay-connect-runner.js +9 -1
  15. package/dist/esm/relay-connect-runner.js.map +1 -1
  16. package/dist/esm/ui/connect-modal.js +134 -16
  17. package/dist/esm/ui/connect-modal.js.map +1 -1
  18. package/dist/types/blob-url-pool.d.ts +16 -0
  19. package/dist/types/blob-url-pool.d.ts.map +1 -0
  20. package/dist/types/browser-connect-handler.d.ts +8 -2
  21. package/dist/types/browser-connect-handler.d.ts.map +1 -1
  22. package/dist/types/file-envelope-url-store.d.ts +30 -0
  23. package/dist/types/file-envelope-url-store.d.ts.map +1 -0
  24. package/dist/types/index.d.ts +16 -14
  25. package/dist/types/index.d.ts.map +1 -1
  26. package/dist/types/object-url-reference.d.ts +20 -0
  27. package/dist/types/object-url-reference.d.ts.map +1 -0
  28. package/dist/types/relay-connect-runner.d.ts +4 -0
  29. package/dist/types/relay-connect-runner.d.ts.map +1 -1
  30. package/dist/types/ui/connect-modal.d.ts +24 -11
  31. package/dist/types/ui/connect-modal.d.ts.map +1 -1
  32. package/package.json +7 -7
  33. package/src/blob-url-pool.ts +55 -0
  34. package/src/browser-connect-handler.ts +13 -2
  35. package/src/file-envelope-url-store.ts +260 -0
  36. package/src/index.ts +23 -159
  37. package/src/object-url-reference.ts +82 -0
  38. package/src/relay-connect-runner.ts +17 -2
  39. package/src/ui/connect-modal.ts +187 -28
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAMH,cAAc,YAAY,CAAC;AAM3B,cAAc,qBAAqB,CAAC;AAOpC,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACvE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAMtE,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACtF,YAAY,EAAE,4BAA4B,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC/F,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AACzG,YAAY,EAAE,2BAA2B,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACjG,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,YAAY,EAAE,iCAAiC,EAAE,MAAM,0BAA0B,CAAC;AAClF,OAAO,EACL,6BAA6B,EAC7B,gCAAgC,EAChC,iBAAiB,EACjB,iCAAiC,EACjC,kCAAkC,GACnC,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACV,qBAAqB,EACrB,wBAAwB,EACxB,yBAAyB,EACzB,0BAA0B,GAC3B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAC/G,YAAY,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACzE,OAAO,EAAE,8BAA8B,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxF,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1I,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC1G,YAAY,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC/C,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,YAAY,EACV,oBAAoB,EACpB,oBAAoB,EACpB,2BAA2B,GAC5B,MAAM,8BAA8B,CAAC;AActC,OAAO,EAAE,mBAAmB,EAAE,4BAA4B,EAAE,MAAM,kBAAkB,CAAC;AACrF,YAAY,EACV,kBAAkB,EAClB,oBAAoB,EACpB,kBAAkB,EAClB,aAAa,EACb,aAAa,EACb,oBAAoB,EACpB,uBAAuB,EACvB,oBAAoB,EACpB,2BAA2B,EAC3B,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,EACf,oBAAoB,EACpB,aAAa,GACd,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAK5C,YAAY,EACV,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,qBAAqB,EACrB,UAAU,EACV,SAAS,EACT,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,cAAc,CAAC;AAItB,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAC9E,YAAY,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,20 @@
1
+ export type ObjectUrlLease = Readonly<{
2
+ url: string;
3
+ /** Release immediately, cancelling any deferred release. Idempotent. */
4
+ release(): void;
5
+ /** Release after a grace period. The first deferred release wins. */
6
+ releaseAfter(delayMs: number): void;
7
+ }>;
8
+ /** Private reference-counted ownership for one object URL. */
9
+ export declare class ObjectUrlReference {
10
+ private readonly _onEmpty;
11
+ readonly url: string;
12
+ private _isRevoked;
13
+ private _references;
14
+ private readonly _releaseTimers;
15
+ constructor(blob: Blob, _onEmpty: (reference: ObjectUrlReference) => void);
16
+ get references(): number;
17
+ acquire(): ObjectUrlLease;
18
+ revoke(): void;
19
+ }
20
+ //# sourceMappingURL=object-url-reference.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"object-url-reference.d.ts","sourceRoot":"","sources":["../../src/object-url-reference.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,wEAAwE;IACxE,OAAO,IAAI,IAAI,CAAC;IAChB,qEAAqE;IACrE,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC,CAAC,CAAC;AAUH,8DAA8D;AAC9D,qBAAa,kBAAkB;IAME,OAAO,CAAC,QAAQ,CAAC,QAAQ;IALxD,SAAgB,GAAG,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA4C;gBAExD,IAAI,EAAE,IAAI,EAAmB,QAAQ,EAAE,CAAC,SAAS,EAAE,kBAAkB,KAAK,IAAI;IAIjG,IAAW,UAAU,IAAI,MAAM,CAE9B;IAEM,OAAO,IAAI,cAAc;IAuCzB,MAAM,IAAI,IAAI;CAWtB"}
@@ -37,6 +37,8 @@ export interface RelayConnectOptions {
37
37
  appName: string;
38
38
  /** Optional icon URL for the app, shown in the wallet consent UI. */
39
39
  appIcon?: string;
40
+ /** Stable application identifier hint available to the wallet during approval. */
41
+ applicationId?: string;
40
42
  /** Optional client/environment metadata for wallet session display. */
41
43
  clientMetadata?: ConnectClientMetadata;
42
44
  /** DWN protocols and permission scopes being requested. */
@@ -45,6 +47,8 @@ export interface RelayConnectOptions {
45
47
  delegatePortableDid?: PortableDid;
46
48
  /** User-facing request purpose. Absent means a normal connect. */
47
49
  requestType?: ConnectRequestType;
50
+ /** Wallet profile DID that a refresh must renew. */
51
+ expectedProviderDid?: string;
48
52
  /** Total milliseconds to poll the relay for a wallet response. */
49
53
  timeoutMs?: number;
50
54
  /** Milliseconds between relay polling attempts. */
@@ -1 +1 @@
1
- {"version":3,"file":"relay-connect-runner.d.ts","sourceRoot":"","sources":["../../src/relay-connect-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EACV,qBAAqB,EACrB,wBAAwB,EAExB,kBAAkB,EAClB,aAAa,EACb,gBAAgB,EACjB,MAAM,gBAAgB,CAAC;AAIxB,OAAO,EAIL,oBAAoB,EAGrB,MAAM,gBAAgB,CAAC;AAExB,mEAAmE;AACnE,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAElC,uEAAuE;AACvE,qBAAa,0BAA2B,SAAQ,KAAK;;CAKpD;AAED,2CAA2C;AAC3C,MAAM,WAAW,mBAAmB;IAClC,wDAAwD;IACxD,gBAAgB,EAAE,MAAM,CAAC;IAEzB,6EAA6E;IAC7E,SAAS,EAAE,MAAM,CAAC;IAElB,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAC;IAEhB,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,uEAAuE;IACvE,cAAc,CAAC,EAAE,qBAAqB,CAAC;IAEvC,2DAA2D;IAC3D,kBAAkB,EAAE,wBAAwB,EAAE,CAAC;IAE/C,iEAAiE;IACjE,mBAAmB,CAAC,EAAE,WAAW,CAAC;IAElC,kEAAkE;IAClE,WAAW,CAAC,EAAE,kBAAkB,CAAC;IAEjC,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,mDAAmD;IACnD,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,gBAAgB,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAEtD;;;;OAIG;IACH,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,KAAK,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAExE;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAE3B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IAEvB,0CAA0C;IAC1C,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE;QAC1B,gBAAgB,EAAE,MAAM,CAAC;QACzB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;QACvB,MAAM,CAAC,EAAE,WAAW,CAAC;KACtB,KAAK,IAAI,CAAC,oBAAoB,EAAE,gBAAgB,GAAG,gBAAgB,GAAG,eAAe,GAAG,aAAa,CAAC,GACnG,OAAO,CAAC,IAAI,CAAC,oBAAoB,EAAE,iBAAiB,CAAC,CAAC,CAAC;CAC5D;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoB9D;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAiGtG"}
1
+ {"version":3,"file":"relay-connect-runner.d.ts","sourceRoot":"","sources":["../../src/relay-connect-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EACV,qBAAqB,EACrB,wBAAwB,EAExB,kBAAkB,EAClB,aAAa,EACb,gBAAgB,EACjB,MAAM,gBAAgB,CAAC;AAIxB,OAAO,EAIL,oBAAoB,EAGrB,MAAM,gBAAgB,CAAC;AAExB,mEAAmE;AACnE,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAElC,uEAAuE;AACvE,qBAAa,0BAA2B,SAAQ,KAAK;;CAKpD;AAED,2CAA2C;AAC3C,MAAM,WAAW,mBAAmB;IAClC,wDAAwD;IACxD,gBAAgB,EAAE,MAAM,CAAC;IAEzB,6EAA6E;IAC7E,SAAS,EAAE,MAAM,CAAC;IAElB,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAC;IAEhB,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,kFAAkF;IAClF,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,uEAAuE;IACvE,cAAc,CAAC,EAAE,qBAAqB,CAAC;IAEvC,2DAA2D;IAC3D,kBAAkB,EAAE,wBAAwB,EAAE,CAAC;IAE/C,iEAAiE;IACjE,mBAAmB,CAAC,EAAE,WAAW,CAAC;IAElC,kEAAkE;IAClE,WAAW,CAAC,EAAE,kBAAkB,CAAC;IAEjC,oDAAoD;IACpD,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,mDAAmD;IACnD,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,gBAAgB,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAEtD;;;;OAIG;IACH,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,KAAK,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAExE;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAE3B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IAEvB,0CAA0C;IAC1C,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE;QAC1B,gBAAgB,EAAE,MAAM,CAAC;QACzB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;QACvB,MAAM,CAAC,EAAE,WAAW,CAAC;KACtB,KAAK,IAAI,CAAC,oBAAoB,EAAE,gBAAgB,GAAG,gBAAgB,GAAG,eAAe,GAAG,aAAa,CAAC,GACnG,OAAO,CAAC,IAAI,CAAC,oBAAoB,EAAE,iBAAiB,CAAC,CAAC,CAAC;CAC5D;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoB9D;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAoGtG"}
@@ -96,8 +96,9 @@ export interface ConnectModalOptions {
96
96
  /** Preferred method on open; overrides the remembered choice. */
97
97
  preferredMethod?: ConnectMethod;
98
98
  /**
99
- * Remember the successful method + wallet in localStorage and pre-shape
100
- * the next session accordingly.
99
+ * Remember the successful method + wallet in localStorage. Refreshes reuse
100
+ * the route saved for their delegate DID; new connections use the latest
101
+ * successful route as a convenience.
101
102
  * @default true
102
103
  */
103
104
  rememberChoice?: boolean;
@@ -105,6 +106,13 @@ export interface ConnectModalOptions {
105
106
  appName?: string;
106
107
  /** Icon URL of the requesting application. */
107
108
  appIcon?: string;
109
+ /**
110
+ * Stable application identifier hint available to the wallet during approval.
111
+ * Defaults to the browser's canonical origin.
112
+ */
113
+ applicationId?: string;
114
+ /** Wallet profile DID that a refresh must renew. */
115
+ expectedProviderDid?: string;
108
116
  /**
109
117
  * Relay base URL override for the phone path. When omitted, each wallet's
110
118
  * `connectServerUrl` is discovered from its `/.well-known/enbox-connect`
@@ -134,15 +142,7 @@ export interface ConnectModalDeps {
134
142
  /** Runs one relay handshake (phone path). */
135
143
  runRelay: typeof runRelayConnect;
136
144
  /** Runs one popup handshake (browser path); must open the popup synchronously. */
137
- runPopup: (options: {
138
- walletUrl: string;
139
- permissionRequests: ConnectPermissionRequest[];
140
- appName: string;
141
- appIcon?: string;
142
- timeoutMs?: number;
143
- delegatePortableDid?: PortableDid;
144
- requestType?: ConnectRequestType;
145
- }) => Promise<ConnectResult | undefined>;
145
+ runPopup: typeof runPopupConnect;
146
146
  /** Resolves a wallet origin to its relay `connectServerUrl` (or undefined). */
147
147
  discoverConnectServerUrl: (walletOrigin: string) => Promise<string | undefined>;
148
148
  /** Validates a pasted custom wallet URL. */
@@ -158,6 +158,18 @@ export interface ConnectModalDeps {
158
158
  * same machinery the wallet selector uses for custom-URL validation).
159
159
  */
160
160
  export declare function discoverWalletConnectServerUrl(walletOrigin: string): Promise<string | undefined>;
161
+ /** Runs one popup handshake without collapsing early-close into a denial. */
162
+ declare function runPopupConnect(options: {
163
+ walletUrl: string;
164
+ permissionRequests: ConnectPermissionRequest[];
165
+ appName: string;
166
+ appIcon?: string;
167
+ applicationId?: string;
168
+ timeoutMs?: number;
169
+ delegatePortableDid?: PortableDid;
170
+ requestType?: ConnectRequestType;
171
+ expectedProviderDid?: string;
172
+ }): Promise<ConnectResult | undefined>;
161
173
  /**
162
174
  * Opens the connect modal and resolves when the session ends.
163
175
  *
@@ -167,4 +179,5 @@ export declare function discoverWalletConnectServerUrl(walletOrigin: string): Pr
167
179
  * user dismisses the error.
168
180
  */
169
181
  export declare function runConnectModal(options: ConnectModalOptions): Promise<ConnectResult | undefined>;
182
+ export {};
170
183
  //# sourceMappingURL=connect-modal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"connect-modal.d.ts","sourceRoot":"","sources":["../../../src/ui/connect-modal.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"connect-modal.d.ts","sourceRoot":"","sources":["../../../src/ui/connect-modal.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enbox/browser",
3
- "version": "0.3.70",
3
+ "version": "0.3.72",
4
4
  "description": "Enbox tools and features to use in the browser",
5
5
  "type": "module",
6
6
  "main": "./dist/esm/index.js",
@@ -66,15 +66,15 @@
66
66
  "access": "public"
67
67
  },
68
68
  "dependencies": {
69
- "@enbox/agent": "0.8.39",
70
- "@enbox/api": "0.6.78",
71
- "@enbox/auth": "0.6.85",
69
+ "@enbox/agent": "0.8.41",
70
+ "@enbox/api": "0.6.80",
71
+ "@enbox/auth": "0.6.87",
72
72
  "@enbox/common": "0.1.6",
73
- "@enbox/connect": "0.1.19",
73
+ "@enbox/connect": "0.1.21",
74
74
  "@enbox/crypto": "0.1.9",
75
75
  "@enbox/dids": "0.1.10",
76
- "@enbox/dwn-sdk-js": "0.4.23",
77
- "@enbox/protocols": "0.2.105"
76
+ "@enbox/dwn-sdk-js": "0.4.25",
77
+ "@enbox/protocols": "0.2.107"
78
78
  },
79
79
  "devDependencies": {
80
80
  "@types/qrcode": "^1.5.6",
@@ -0,0 +1,55 @@
1
+ import type { ObjectUrlLease } from './object-url-reference.js';
2
+
3
+ import { ObjectUrlReference } from './object-url-reference.js';
4
+
5
+ /**
6
+ * A reference-counted lease for a browser object URL.
7
+ *
8
+ * When replacing a URL already rendered by the DOM, `releaseAfter()` provides
9
+ * a grace period without passing the lease through the component tree.
10
+ */
11
+ export type BlobUrlLease = ObjectUrlLease;
12
+
13
+ /** Owns object URLs for Blob identities until their last lease is released. */
14
+ export interface BlobUrlPool {
15
+ acquire(blob: Blob): BlobUrlLease;
16
+ dispose(): void;
17
+ }
18
+
19
+ class DefaultBlobUrlPool implements BlobUrlPool {
20
+ private readonly _references = new Map<Blob, ObjectUrlReference>();
21
+ private _isDisposed = false;
22
+
23
+ public acquire(blob: Blob): BlobUrlLease {
24
+ if (this._isDisposed) {
25
+ throw new Error('BlobUrlPool is disposed.');
26
+ }
27
+
28
+ let reference = this._references.get(blob);
29
+ if (reference === undefined) {
30
+ reference = new ObjectUrlReference(blob, (released): void => {
31
+ this._references.delete(blob);
32
+ released.revoke();
33
+ });
34
+ this._references.set(blob, reference);
35
+ }
36
+ return reference.acquire();
37
+ }
38
+
39
+ public dispose(): void {
40
+ if (this._isDisposed) {
41
+ return;
42
+ }
43
+
44
+ this._isDisposed = true;
45
+ for (const reference of this._references.values()) {
46
+ reference.revoke();
47
+ }
48
+ this._references.clear();
49
+ }
50
+ }
51
+
52
+ /** Create a terminally disposable, reference-counted object URL pool. */
53
+ export function createBlobUrlPool(): BlobUrlPool {
54
+ return new DefaultBlobUrlPool();
55
+ }
@@ -107,6 +107,12 @@ export interface BrowserConnectHandlerOptions {
107
107
  */
108
108
  appIcon?: string;
109
109
 
110
+ /**
111
+ * Stable application identifier hint available to the wallet during approval.
112
+ * Defaults to the browser's canonical origin.
113
+ */
114
+ applicationId?: string;
115
+
110
116
  /**
111
117
  * Preferred connect method on open: `'phone'` (QR / deep link via the
112
118
  * relay) or `'browser'` (wallet popup on this device). Overrides the
@@ -116,8 +122,9 @@ export interface BrowserConnectHandlerOptions {
116
122
  preferredMethod?: ConnectMethod;
117
123
 
118
124
  /**
119
- * Remember the successful method + wallet in localStorage and pre-shape
120
- * the next connect session accordingly.
125
+ * Remember the successful method + wallet in localStorage. Refreshes reuse
126
+ * the route saved for their delegate DID; new connections use the latest
127
+ * successful route as a convenience.
121
128
  * @default true
122
129
  */
123
130
  rememberChoice?: boolean;
@@ -176,6 +183,7 @@ export function BrowserConnectHandler(
176
183
  timeout,
177
184
  appName,
178
185
  appIcon,
186
+ applicationId,
179
187
  preferredMethod,
180
188
  rememberChoice,
181
189
  connectServerUrl,
@@ -188,6 +196,7 @@ export function BrowserConnectHandler(
188
196
  permissionRequests: ConnectPermissionRequest[];
189
197
  delegatePortableDid?: PortableDid;
190
198
  requestType?: ConnectRequestType;
199
+ expectedProviderDid?: string;
191
200
  }): Promise<ConnectResult | undefined> {
192
201
  return runConnectModal({
193
202
  wallets,
@@ -196,12 +205,14 @@ export function BrowserConnectHandler(
196
205
  rememberChoice,
197
206
  appName,
198
207
  appIcon : appIcon ?? `${window.location.origin}/favicon.ico`,
208
+ applicationId,
199
209
  connectServerUrl,
200
210
  relayWalletPath,
201
211
  timeout,
202
212
  theme,
203
213
  mode : params.requestType,
204
214
  delegatePortableDid : params.delegatePortableDid,
215
+ expectedProviderDid : params.expectedProviderDid,
205
216
  permissionRequests : params.permissionRequests,
206
217
  });
207
218
  },
@@ -0,0 +1,260 @@
1
+ import type { FileEnvelopeData } from '@enbox/api';
2
+
3
+ import type { BlobUrlLease } from './blob-url-pool.js';
4
+
5
+ import { ObjectUrlReference } from './object-url-reference.js';
6
+
7
+ const DEFAULT_MAX_BYTES = 128 * 1024 * 1024;
8
+ const DEFAULT_MAX_ENTRIES = 50;
9
+
10
+ type CacheEntry = {
11
+ bytes: number;
12
+ filename: string;
13
+ key: string;
14
+ mimeType: string;
15
+ url: ObjectUrlReference;
16
+ };
17
+
18
+ type PendingRead = {
19
+ controller: AbortController;
20
+ generation: number;
21
+ promise: Promise<CacheEntry | undefined>;
22
+ };
23
+
24
+ /** A cached file envelope represented by a leased browser object URL. */
25
+ export type FileEnvelopeUrlLease = BlobUrlLease & Readonly<{
26
+ filename: string;
27
+ mimeType: string;
28
+ }>;
29
+
30
+ export type FileEnvelopeUrlStoreOptions<Request> = Readonly<{
31
+ /** Select the stable cache key for a read request. */
32
+ key(request: Request): string;
33
+ /** Read and decode the file. The signal aborts invalidated work. */
34
+ read(request: Request, signal: AbortSignal): Promise<FileEnvelopeData | undefined>;
35
+ /** Choose the Blob exposed by the URL, retaining MIME/render policy in the caller. */
36
+ blobForUrl(value: FileEnvelopeData): Blob;
37
+ /** Maximum cached entries (default 50). Soft while every eviction candidate is leased. */
38
+ maxEntries?: number;
39
+ /** Maximum cached Blob bytes (default 128 MiB). Soft while every eviction candidate is leased. */
40
+ maxBytes?: number;
41
+ }>;
42
+
43
+ /** A keyed, bounded object URL cache for decoded file envelopes. */
44
+ export interface FileEnvelopeUrlStore<Request> {
45
+ acquire(request: Request): Promise<FileEnvelopeUrlLease | undefined>;
46
+ acquireCached(request: Request): FileEnvelopeUrlLease | undefined;
47
+ clear(): void;
48
+ dispose(): void;
49
+ invalidate(request: Request): void;
50
+ }
51
+
52
+ function assertLimit(value: number, name: string): void {
53
+ if (value !== Infinity && (!Number.isSafeInteger(value) || value < 0)) {
54
+ throw new TypeError(`${name} must be a non-negative safe integer or Infinity.`);
55
+ }
56
+ }
57
+
58
+ function throwAborted(controller: AbortController): never {
59
+ controller.abort();
60
+ throw controller.signal.reason;
61
+ }
62
+
63
+ class DefaultFileEnvelopeUrlStore<Request> implements FileEnvelopeUrlStore<Request> {
64
+ private readonly _cache = new Map<string, CacheEntry>();
65
+ private readonly _entries = new Set<CacheEntry>();
66
+ private readonly _maxBytes: number;
67
+ private readonly _maxEntries: number;
68
+ private readonly _pending = new Map<string, PendingRead>();
69
+ private _bytes = 0;
70
+ private _generation = 0;
71
+ private _isDisposed = false;
72
+
73
+ public constructor(private readonly _options: FileEnvelopeUrlStoreOptions<Request>) {
74
+ this._maxBytes = _options.maxBytes ?? DEFAULT_MAX_BYTES;
75
+ this._maxEntries = _options.maxEntries ?? DEFAULT_MAX_ENTRIES;
76
+ assertLimit(this._maxBytes, 'maxBytes');
77
+ assertLimit(this._maxEntries, 'maxEntries');
78
+ }
79
+
80
+ public async acquire(request: Request): Promise<FileEnvelopeUrlLease | undefined> {
81
+ this._assertActive();
82
+ const key = this._options.key(request);
83
+ const cached = this._cache.get(key);
84
+ if (cached !== undefined) {
85
+ return this._acquire(cached);
86
+ }
87
+
88
+ const pending = this._pending.get(key) ?? this._startRead(request, key);
89
+ const entry = await pending.promise;
90
+ if (this._isDisposed || pending.generation !== this._generation) {
91
+ return throwAborted(pending.controller);
92
+ }
93
+ if (entry === undefined) {
94
+ return undefined;
95
+ }
96
+ if (this._cache.get(key) !== entry) {
97
+ return throwAborted(pending.controller);
98
+ }
99
+ return this._acquire(entry);
100
+ }
101
+
102
+ public acquireCached(request: Request): FileEnvelopeUrlLease | undefined {
103
+ this._assertActive();
104
+ const entry = this._cache.get(this._options.key(request));
105
+ return entry === undefined ? undefined : this._acquire(entry);
106
+ }
107
+
108
+ public invalidate(request: Request): void {
109
+ this._assertActive();
110
+ const key = this._options.key(request);
111
+ const pending = this._pending.get(key);
112
+ pending?.controller.abort();
113
+ this._pending.delete(key);
114
+ const entry = this._cache.get(key);
115
+ if (entry !== undefined) {
116
+ this._remove(entry);
117
+ }
118
+ }
119
+
120
+ public clear(): void {
121
+ this._assertActive();
122
+ this._reset(false);
123
+ }
124
+
125
+ public dispose(): void {
126
+ if (this._isDisposed) {
127
+ return;
128
+ }
129
+
130
+ this._isDisposed = true;
131
+ this._reset(true);
132
+ }
133
+
134
+ private _abortReads(): void {
135
+ for (const pending of this._pending.values()) {
136
+ pending.controller.abort();
137
+ }
138
+ this._pending.clear();
139
+ }
140
+
141
+ private _acquire(entry: CacheEntry): FileEnvelopeUrlLease {
142
+ this._cache.delete(entry.key);
143
+ this._cache.set(entry.key, entry);
144
+ const lease = entry.url.acquire();
145
+ this._evict();
146
+ return Object.freeze({
147
+ filename : entry.filename,
148
+ mimeType : entry.mimeType,
149
+ release : lease.release,
150
+ releaseAfter : lease.releaseAfter,
151
+ url : lease.url,
152
+ });
153
+ }
154
+
155
+ private _assertActive(): void {
156
+ if (this._isDisposed) {
157
+ throw new Error('FileEnvelopeUrlStore is disposed.');
158
+ }
159
+ }
160
+
161
+ private _assertCurrent(key: string, controller: AbortController, generation: number): void {
162
+ if (
163
+ this._isDisposed
164
+ || controller.signal.aborted
165
+ || this._generation !== generation
166
+ || this._pending.get(key)?.controller !== controller
167
+ ) {
168
+ throwAborted(controller);
169
+ }
170
+ }
171
+
172
+ private _evict(): void {
173
+ while (this._cache.size > this._maxEntries || this._bytes > this._maxBytes) {
174
+ const entry = [...this._cache.values()].find((candidate): boolean => candidate.url.references === 0);
175
+ if (entry === undefined) {
176
+ return;
177
+ }
178
+ this._remove(entry);
179
+ }
180
+ }
181
+
182
+ private async _load(request: Request, key: string, controller: AbortController, generation: number): Promise<CacheEntry | undefined> {
183
+ const value = await this._options.read(request, controller.signal);
184
+ this._assertCurrent(key, controller, generation);
185
+ if (value === undefined) {
186
+ return undefined;
187
+ }
188
+
189
+ const blob = this._options.blobForUrl(value);
190
+ this._assertCurrent(key, controller, generation);
191
+ const url = new ObjectUrlReference(blob, (): void => this._released(entry));
192
+ const entry: CacheEntry = {
193
+ bytes : blob.size,
194
+ filename : value.filename,
195
+ key,
196
+ mimeType : value.mimeType,
197
+ url,
198
+ };
199
+ this._cache.set(key, entry);
200
+ this._bytes += entry.bytes;
201
+ this._entries.add(entry);
202
+ return entry;
203
+ }
204
+
205
+ private _released(entry: CacheEntry): void {
206
+ if (this._cache.get(entry.key) !== entry) {
207
+ this._revoke(entry);
208
+ } else {
209
+ this._evict();
210
+ }
211
+ }
212
+
213
+ private _remove(entry: CacheEntry): void {
214
+ if (this._cache.get(entry.key) !== entry) {
215
+ return;
216
+ }
217
+ this._cache.delete(entry.key);
218
+ this._bytes -= entry.bytes;
219
+ if (entry.url.references === 0) {
220
+ this._revoke(entry);
221
+ }
222
+ }
223
+
224
+ private _reset(revokeActive: boolean): void {
225
+ this._generation += 1;
226
+ this._abortReads();
227
+ this._cache.clear();
228
+ this._bytes = 0;
229
+ for (const entry of this._entries) {
230
+ if (revokeActive || entry.url.references === 0) {
231
+ this._revoke(entry);
232
+ }
233
+ }
234
+ }
235
+
236
+ private _revoke(entry: CacheEntry): void {
237
+ entry.url.revoke();
238
+ this._entries.delete(entry);
239
+ }
240
+
241
+ private _startRead(request: Request, key: string): PendingRead {
242
+ const controller = new AbortController();
243
+ const generation = this._generation;
244
+ const promise = this._load(request, key, controller, generation).finally((): void => {
245
+ if (this._pending.get(key)?.controller === controller) {
246
+ this._pending.delete(key);
247
+ }
248
+ });
249
+ const pending = { controller, generation, promise };
250
+ this._pending.set(key, pending);
251
+ return pending;
252
+ }
253
+ }
254
+
255
+ /** Create a bounded file-envelope URL store with deduplicated reads. */
256
+ export function createFileEnvelopeUrlStore<Request>(
257
+ options: FileEnvelopeUrlStoreOptions<Request>,
258
+ ): FileEnvelopeUrlStore<Request> {
259
+ return new DefaultFileEnvelopeUrlStore(options);
260
+ }