Skip to content

Commit 2ddcf03

Browse files
committed
fix(ui): surface pairing and preimage failures
1 parent 83e09fd commit 2ddcf03

10 files changed

Lines changed: 437 additions & 76 deletions

File tree

packages/protocol/src/client.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,14 @@ export function createRemoteChainProvider(
742742
void postRequest("chainSend", {
743743
connectionId,
744744
message: JSON.stringify(message),
745+
}).catch((error: unknown) => {
746+
const errResponse = buildJsonRpcError(
747+
message,
748+
serializeError(error),
749+
);
750+
if (errResponse !== null) {
751+
onMessage(errResponse);
752+
}
745753
});
746754
}
747755
remote.pendingMessages = [];

packages/ui/src/bridge.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -630,18 +630,15 @@ export function requestCoreLogin(
630630
});
631631
resolve(result.value);
632632
} else {
633+
const error = new LoginRequestError(result.value);
633634
emitDotliDebugEvent({
634635
layer: "sso",
635636
event: "login_request_failed",
636637
flowId,
637638
timestamp: Date.now(),
638639
payload: { requestId },
639640
});
640-
if (result.value.tag === "Domain") {
641-
reject(new LoginRequestError(result.value.value));
642-
} else {
643-
reject(new Error(JSON.stringify(result.value)));
644-
}
641+
reject(error);
645642
}
646643
} catch (error) {
647644
emitDotliDebugEvent({

packages/ui/src/host-callbacks/Chain.ts

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ import {
4141
const STATEMENT_SUBMIT_METHOD = "statement_submit";
4242
const STATEMENT_SUBSCRIBE_METHOD = "statement_subscribeStatement";
4343
const STATEMENT_UNSUBSCRIBE_METHOD = "statement_unsubscribeStatement";
44+
const STATEMENT_NOTIFICATION_METHOD = "statement_statement";
45+
const LOGIN_PROGRESS_EVENT = "dotli:truapi-login-progress";
4446

4547
interface StatementStoreDebugRequest {
4648
method: string;
@@ -169,9 +171,6 @@ function emitStatementStoreResponse(
169171
response: string,
170172
debugRequests: Map<string, StatementStoreDebugRequest>,
171173
): void {
172-
if (!hasDotliDebugListeners()) {
173-
return;
174-
}
175174
let parsed: unknown;
176175
try {
177176
parsed = JSON.parse(response);
@@ -182,6 +181,18 @@ function emitStatementStoreResponse(
182181
return;
183182
}
184183
const record = parsed as Record<string, unknown>;
184+
const statementPage = parseStatementStorePage(record);
185+
if (
186+
statementPage !== null &&
187+
statementPage.statementCount > 0 &&
188+
typeof window !== "undefined"
189+
) {
190+
window.dispatchEvent(new Event(LOGIN_PROGRESS_EVENT));
191+
}
192+
193+
if (!hasDotliDebugListeners()) {
194+
return;
195+
}
185196
const responseId = jsonRpcId(record.id);
186197
if (responseId !== null) {
187198
const request = debugRequests.get(responseId);
@@ -203,9 +214,42 @@ function emitStatementStoreResponse(
203214
return;
204215
}
205216

206-
if (record.method !== STATEMENT_SUBSCRIBE_METHOD) {
217+
if (statementPage === null) {
207218
return;
208219
}
220+
emitSsoStatementStoreResponse({
221+
method: statementPage.method,
222+
requestKind: "page",
223+
frameKind: statementPage.malformed ? "malformed-page" : "page",
224+
...(statementPage.remoteSubscriptionId !== undefined
225+
? { remoteSubscriptionId: statementPage.remoteSubscriptionId }
226+
: {}),
227+
...(statementPage.eventName !== undefined
228+
? { eventName: statementPage.eventName }
229+
: {}),
230+
statementCount: statementPage.statementCount,
231+
...(statementPage.remaining !== undefined
232+
? { remaining: statementPage.remaining }
233+
: {}),
234+
});
235+
}
236+
237+
function parseStatementStorePage(record: Record<string, unknown>):
238+
| {
239+
method: string;
240+
malformed: boolean;
241+
remoteSubscriptionId?: string;
242+
eventName?: string;
243+
statementCount: number;
244+
remaining?: number;
245+
}
246+
| null {
247+
if (
248+
record.method !== STATEMENT_NOTIFICATION_METHOD &&
249+
record.method !== STATEMENT_SUBSCRIBE_METHOD
250+
) {
251+
return null;
252+
}
209253
const params =
210254
typeof record.params === "object" && record.params !== null
211255
? (record.params as Record<string, unknown>)
@@ -219,19 +263,16 @@ function emitStatementStoreResponse(
219263
? (result.data as Record<string, unknown>)
220264
: null;
221265
const statements = Array.isArray(data?.statements) ? data.statements : [];
222-
emitSsoStatementStoreResponse({
223-
method: STATEMENT_SUBSCRIBE_METHOD,
224-
requestKind: "page",
225-
frameKind: result === null ? "malformed-page" : "page",
266+
return {
267+
method: record.method,
268+
malformed: result === null,
226269
...(typeof params?.subscription === "string"
227270
? { remoteSubscriptionId: params.subscription }
228271
: {}),
229272
...(typeof result?.event === "string" ? { eventName: result.event } : {}),
230273
statementCount: statements.length,
231-
...(typeof data?.remaining === "number"
232-
? { remaining: data.remaining }
233-
: {}),
234-
});
274+
...(typeof data?.remaining === "number" ? { remaining: data.remaining } : {}),
275+
};
235276
}
236277

237278
function statementRequestKind(method: string): string | null {

packages/ui/src/login-request-error.ts

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,34 @@
22
// SPDX-License-Identifier: AGPL-3.0-only
33

44
import type { VersionedHostRequestLoginError } from "@parity/truapi";
5+
import type { CallErrorValue } from "@parity/truapi/scale";
6+
7+
type LoginRequestFailure = CallErrorValue<VersionedHostRequestLoginError>;
58

69
export class LoginRequestError extends Error {
7-
readonly error: VersionedHostRequestLoginError;
10+
readonly error: LoginRequestFailure;
811

9-
constructor(error: VersionedHostRequestLoginError) {
10-
super(JSON.stringify(error));
12+
constructor(error: LoginRequestFailure) {
13+
super(formatLoginRequestError(error));
1114
this.name = "LoginRequestError";
1215
this.error = error;
1316
}
1417
}
18+
19+
export function formatLoginRequestError(error: LoginRequestFailure): string {
20+
switch (error.tag) {
21+
case "Domain":
22+
return formatDomainLoginError(error.value);
23+
case "Denied":
24+
return "Login request denied";
25+
case "Unsupported":
26+
return "Login is not supported by this host";
27+
case "MalformedFrame":
28+
case "HostFailure":
29+
return error.value.reason;
30+
}
31+
}
32+
33+
function formatDomainLoginError(error: VersionedHostRequestLoginError): string {
34+
return error.value.value.reason;
35+
}

0 commit comments

Comments
 (0)