@enbox/browser 0.3.48 → 0.3.51
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.
- package/dist/browser.mjs +58 -46
- package/dist/browser.mjs.map +3 -3
- package/dist/esm/browser-connect-handler.js +10 -0
- package/dist/esm/browser-connect-handler.js.map +1 -1
- package/dist/esm/dweb-connect-client.js +64 -9
- package/dist/esm/dweb-connect-client.js.map +1 -1
- package/dist/esm/dweb-connect-messages.js +7 -1
- package/dist/esm/dweb-connect-messages.js.map +1 -1
- package/dist/esm/dweb-connect-wallet.js +48 -2
- package/dist/esm/dweb-connect-wallet.js.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/relay-connect-runner.js +35 -2
- package/dist/esm/relay-connect-runner.js.map +1 -1
- package/dist/esm/ui/connect-modal.js +220 -101
- package/dist/esm/ui/connect-modal.js.map +1 -1
- package/dist/types/browser-connect-handler.d.ts.map +1 -1
- package/dist/types/dweb-connect-client.d.ts +9 -0
- package/dist/types/dweb-connect-client.d.ts.map +1 -1
- package/dist/types/dweb-connect-messages.d.ts +14 -1
- package/dist/types/dweb-connect-messages.d.ts.map +1 -1
- package/dist/types/dweb-connect-wallet.d.ts +23 -1
- package/dist/types/dweb-connect-wallet.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/relay-connect-runner.d.ts +11 -1
- package/dist/types/relay-connect-runner.d.ts.map +1 -1
- package/dist/types/ui/connect-modal.d.ts +11 -10
- package/dist/types/ui/connect-modal.d.ts.map +1 -1
- package/package.json +6 -6
- package/src/browser-connect-handler.ts +10 -0
- package/src/dweb-connect-client.ts +61 -7
- package/src/dweb-connect-messages.ts +16 -1
- package/src/dweb-connect-wallet.ts +50 -1
- package/src/index.ts +2 -0
- package/src/relay-connect-runner.ts +42 -2
- package/src/ui/connect-modal.ts +246 -110
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
* value-checks the `apv` origin binding against this wallet's origin.
|
|
13
13
|
* 3. After the consent ceremony, the wallet posts the sealed response JWE via
|
|
14
14
|
* `sendResponse()` — or the deny token via `deny()` — back to the opener,
|
|
15
|
-
* again with a pinned `targetOrigin`.
|
|
15
|
+
* again with a pinned `targetOrigin`. `sendResponseAwaitingAck()` does the
|
|
16
|
+
* same but stays alive briefly for the dapp's completion ack, so the
|
|
17
|
+
* wallet can show a confirmed "connected" state before closing itself.
|
|
16
18
|
*
|
|
17
19
|
* The dapp origin is never assumed: it is taken from an explicit option or
|
|
18
20
|
* derived from `document.referrer`, and `create()` fails when neither is
|
|
@@ -28,6 +30,7 @@ import { X25519 } from '@enbox/crypto';
|
|
|
28
30
|
import { CONNECT_DENIED_TOKEN, ConnectProvider } from '@enbox/connect';
|
|
29
31
|
|
|
30
32
|
import {
|
|
33
|
+
DWEB_CONNECT_ACK_MESSAGE_TYPE,
|
|
31
34
|
DWEB_CONNECT_LOADED_MESSAGE_TYPE,
|
|
32
35
|
DWEB_CONNECT_REQUEST_MESSAGE_TYPE,
|
|
33
36
|
DWEB_CONNECT_RESPONSE_MESSAGE_TYPE,
|
|
@@ -37,6 +40,9 @@ import {
|
|
|
37
40
|
/** Default budget for awaiting the dapp's sealed request. */
|
|
38
41
|
const DEFAULT_REQUEST_TIMEOUT_MS = 300_000;
|
|
39
42
|
|
|
43
|
+
/** Default budget for awaiting the dapp's completion ack after a response. */
|
|
44
|
+
const DEFAULT_ACK_TIMEOUT_MS = 5_000;
|
|
45
|
+
|
|
40
46
|
/** Options for creating a {@link WalletPostMessageTransport}. */
|
|
41
47
|
export type WalletPostMessageTransportOptions = {
|
|
42
48
|
/**
|
|
@@ -79,6 +85,7 @@ export class WalletPostMessageTransport {
|
|
|
79
85
|
private _requestReceived = false;
|
|
80
86
|
private _timeoutId?: ReturnType<typeof setTimeout>;
|
|
81
87
|
private _messageListener?: (event: MessageEvent) => void;
|
|
88
|
+
private _resolveAck?: (acked: boolean) => void;
|
|
82
89
|
|
|
83
90
|
private readonly _requestPromise: Promise<ConnectRequest>;
|
|
84
91
|
private _resolveRequest?: (request: ConnectRequest) => void;
|
|
@@ -177,6 +184,43 @@ export class WalletPostMessageTransport {
|
|
|
177
184
|
this.close();
|
|
178
185
|
}
|
|
179
186
|
|
|
187
|
+
/**
|
|
188
|
+
* Posts the sealed response JWE back to the dapp like
|
|
189
|
+
* {@link sendResponse}, then keeps the channel open briefly for the dapp's
|
|
190
|
+
* completion ack — the signal that it opened the response successfully —
|
|
191
|
+
* before closing the transport.
|
|
192
|
+
*
|
|
193
|
+
* Lets the wallet's connect page show a confirmed "connected" state (and
|
|
194
|
+
* close itself with confidence) instead of asking the user to dismiss the
|
|
195
|
+
* screen blind. Dapps predating the ack simply never send one, so the
|
|
196
|
+
* wallet should keep a manual dismiss affordance for the `false` case.
|
|
197
|
+
*
|
|
198
|
+
* @param idToken - The sealed response JWE.
|
|
199
|
+
* @param options - The awaiting options.
|
|
200
|
+
* @param options.timeoutMs - Ack budget in milliseconds; defaults to 5 s.
|
|
201
|
+
* @returns Whether the dapp acknowledged completion within the budget.
|
|
202
|
+
*/
|
|
203
|
+
public async sendResponseAwaitingAck(idToken: string, options: { timeoutMs?: number } = {}): Promise<boolean> {
|
|
204
|
+
const ackPromise = new Promise<boolean>((resolve): void => {
|
|
205
|
+
this._resolveAck = resolve;
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
this._dappWindow.postMessage({
|
|
209
|
+
type : DWEB_CONNECT_RESPONSE_MESSAGE_TYPE,
|
|
210
|
+
payload : idToken,
|
|
211
|
+
}, this._dappOrigin);
|
|
212
|
+
|
|
213
|
+
const ackTimeoutId = setTimeout((): void => {
|
|
214
|
+
this._resolveAck?.(false);
|
|
215
|
+
}, options.timeoutMs ?? DEFAULT_ACK_TIMEOUT_MS);
|
|
216
|
+
|
|
217
|
+
const acked = await ackPromise;
|
|
218
|
+
clearTimeout(ackTimeoutId);
|
|
219
|
+
this._resolveAck = undefined;
|
|
220
|
+
this.close();
|
|
221
|
+
return acked;
|
|
222
|
+
}
|
|
223
|
+
|
|
180
224
|
/** Posts the deny token back to the dapp — the user rejected the request. */
|
|
181
225
|
public deny(): void {
|
|
182
226
|
this.sendResponse(CONNECT_DENIED_TOKEN);
|
|
@@ -195,6 +239,11 @@ export class WalletPostMessageTransport {
|
|
|
195
239
|
const message = getTrustedMessage(event, this._dappOrigin, this._dappWindow);
|
|
196
240
|
if (message === undefined) { return; }
|
|
197
241
|
|
|
242
|
+
if (message.type === DWEB_CONNECT_ACK_MESSAGE_TYPE) {
|
|
243
|
+
this._resolveAck?.(true);
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
|
|
198
247
|
if (message.type !== DWEB_CONNECT_REQUEST_MESSAGE_TYPE || this._requestReceived) { return; }
|
|
199
248
|
this._requestReceived = true;
|
|
200
249
|
|
package/src/index.ts
CHANGED
|
@@ -94,12 +94,14 @@ export type { PopupClientTransportOptions, PopupConnectOptions } from './dweb-co
|
|
|
94
94
|
export { WalletPostMessageTransport } from './dweb-connect-wallet.js';
|
|
95
95
|
export type { WalletPostMessageTransportOptions } from './dweb-connect-wallet.js';
|
|
96
96
|
export {
|
|
97
|
+
DWEB_CONNECT_ACK_MESSAGE_TYPE,
|
|
97
98
|
DWEB_CONNECT_LOADED_MESSAGE_TYPE,
|
|
98
99
|
DWEB_CONNECT_PATH,
|
|
99
100
|
DWEB_CONNECT_REQUEST_MESSAGE_TYPE,
|
|
100
101
|
DWEB_CONNECT_RESPONSE_MESSAGE_TYPE,
|
|
101
102
|
} from './dweb-connect-messages.js';
|
|
102
103
|
export type {
|
|
104
|
+
DWebConnectAckMessage,
|
|
103
105
|
DWebConnectLoadedMessage,
|
|
104
106
|
DWebConnectRequestMessage,
|
|
105
107
|
DWebConnectResponseMessage,
|
|
@@ -107,7 +107,39 @@ export interface RelayConnectOptions {
|
|
|
107
107
|
timeoutMs?: number;
|
|
108
108
|
pollIntervalMs?: number;
|
|
109
109
|
onClaimed?: () => void;
|
|
110
|
-
}) => Pick<RelayClientTransport, 'requestProfile' | 'deliverRequest' | 'awaitResponse' | 'requiresPin'
|
|
110
|
+
}) => Pick<RelayClientTransport, 'requestProfile' | 'deliverRequest' | 'awaitResponse' | 'requiresPin'>
|
|
111
|
+
& Partial<Pick<RelayClientTransport, 'confirmComplete'>>;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Sleep used between relay polls that ends early when the page returns to
|
|
116
|
+
* the foreground. Browsers throttle — and mobile browsers freeze — timers in
|
|
117
|
+
* background tabs, so a plain interval sleep can leave the user staring at a
|
|
118
|
+
* stale stage after approving in the wallet tab; cutting the sleep short on
|
|
119
|
+
* `visibilitychange` makes the next poll (and with it the pairing-code
|
|
120
|
+
* prompt) land the moment they switch back. Falls back to a plain sleep
|
|
121
|
+
* outside DOM environments.
|
|
122
|
+
*/
|
|
123
|
+
export function visibilityAwareSleep(ms: number): Promise<void> {
|
|
124
|
+
return new Promise((resolve) => {
|
|
125
|
+
if (typeof document === 'undefined') {
|
|
126
|
+
setTimeout(resolve, ms);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const finish = (): void => {
|
|
131
|
+
clearTimeout(timer);
|
|
132
|
+
document.removeEventListener('visibilitychange', onVisibilityChange);
|
|
133
|
+
resolve();
|
|
134
|
+
};
|
|
135
|
+
const onVisibilityChange = (): void => {
|
|
136
|
+
if (document.visibilityState === 'visible') {
|
|
137
|
+
finish();
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
const timer = setTimeout(finish, ms);
|
|
141
|
+
document.addEventListener('visibilitychange', onVisibilityChange);
|
|
142
|
+
});
|
|
111
143
|
}
|
|
112
144
|
|
|
113
145
|
/**
|
|
@@ -116,7 +148,10 @@ export interface RelayConnectOptions {
|
|
|
116
148
|
*/
|
|
117
149
|
export async function runRelayConnect(options: RelayConnectOptions): Promise<ConnectResult | undefined> {
|
|
118
150
|
const createTransport = options.createTransport
|
|
119
|
-
?? ((transportOptions): RelayClientTransport => new RelayClientTransport(
|
|
151
|
+
?? ((transportOptions): RelayClientTransport => new RelayClientTransport({
|
|
152
|
+
...transportOptions,
|
|
153
|
+
sleep: visibilityAwareSleep,
|
|
154
|
+
}));
|
|
120
155
|
|
|
121
156
|
const transport = createTransport({
|
|
122
157
|
connectServerUrl : options.connectServerUrl,
|
|
@@ -189,6 +224,11 @@ export async function runRelayConnect(options: RelayConnectOptions): Promise<Con
|
|
|
189
224
|
throw new Error('Connect: wallet response omitted `delegatePortableDid`.');
|
|
190
225
|
}
|
|
191
226
|
|
|
227
|
+
// Best-effort completion signal so the wallet can flip its pairing
|
|
228
|
+
// screen to a confirmed "connected" state instead of leaving the user
|
|
229
|
+
// to dismiss it blind. Fire-and-forget — mirrors the kernel client.
|
|
230
|
+
void transport.confirmComplete?.().catch((): undefined => undefined);
|
|
231
|
+
|
|
192
232
|
return {
|
|
193
233
|
delegatePortableDid : response.delegatePortableDid,
|
|
194
234
|
delegateGrants : response.delegateGrants,
|