tangled
alpha
login
or
join now
olaren.dev
/
pdsls
forked from
pds.ls/pdsls
0
fork
atom
atmosphere explorer
0
fork
atom
overview
issues
pulls
pipelines
add handle resolution debug
handle.invalid
1 month ago
231df811
8c64c0c6
verified
This commit was signed with the committer's
known signature
.
handle.invalid
SSH Key Fingerprint:
SHA256:mBrT4x0JdzLpbVR95g1hjI1aaErfC02kmLRkPXwsYCk=
+148
-10
2 changed files
expand all
collapse all
unified
split
src
utils
api.ts
views
repo.tsx
+26
src/utils/api.ts
···
215
215
): Promise<LinksWithRecords> =>
216
216
getConstellation("/links", target, collection, path, cursor, limit || 100);
217
217
218
218
+
export interface HandleResolveResult {
219
219
+
success: boolean;
220
220
+
did?: string;
221
221
+
error?: string;
222
222
+
}
223
223
+
224
224
+
export const resolveHandleDetailed = async (handle: Handle) => {
225
225
+
const dnsResolver = new DohJsonHandleResolver({ dohUrl: "https://dns.google/resolve?" });
226
226
+
const httpResolver = new WellKnownHandleResolver();
227
227
+
228
228
+
const tryResolve = async (
229
229
+
resolver: DohJsonHandleResolver | WellKnownHandleResolver,
230
230
+
): Promise<HandleResolveResult> => {
231
231
+
try {
232
232
+
const did = await resolver.resolve(handle);
233
233
+
return { success: true, did };
234
234
+
} catch (err: any) {
235
235
+
return { success: false, error: err.message ?? String(err) };
236
236
+
}
237
237
+
};
238
238
+
239
239
+
const [dns, http] = await Promise.all([tryResolve(dnsResolver), tryResolve(httpResolver)]);
240
240
+
241
241
+
return { dns, http };
242
242
+
};
243
243
+
218
244
export {
219
245
didDocCache,
220
246
getAllBacklinks,
+122
-10
src/views/repo.tsx
···
23
23
NavMenu,
24
24
} from "../components/dropdown.jsx";
25
25
import { Favicon } from "../components/favicon.jsx";
26
26
+
import { Modal } from "../components/modal.jsx";
26
27
import {
27
28
addNotification,
28
29
removeNotification,
29
30
updateNotification,
30
31
} from "../components/notification.jsx";
31
31
-
import Tooltip from "../components/tooltip.jsx";
32
32
import { isTouchDevice } from "../layout.jsx";
33
33
import {
34
34
didDocCache,
35
35
+
type HandleResolveResult,
35
36
labelerCache,
36
37
resolveHandle,
38
38
+
resolveHandleDetailed,
37
39
resolveLexiconAuthority,
38
40
resolvePDS,
39
41
validateHandle,
···
54
56
const [filter, setFilter] = createSignal<string>();
55
57
const [validHandles, setValidHandles] = createStore<Record<string, boolean>>({});
56
58
const [rotationKeys, setRotationKeys] = createSignal<Array<string>>([]);
59
59
+
const [handleModalAlias, setHandleModalAlias] = createSignal<string | null>(null);
60
60
+
const [handleDetailedResult, setHandleDetailedResult] = createSignal<{
61
61
+
dns: HandleResolveResult;
62
62
+
http: HandleResolveResult;
63
63
+
} | null>(null);
57
64
let rpc: Client;
58
65
let pds: string;
59
66
const did = params.repo!;
···
502
509
<div class="flex items-center gap-1 text-sm text-neutral-700 dark:text-neutral-300">
503
510
<span>{alias}</span>
504
511
<Show when={alias.startsWith("at://")}>
505
505
-
<Tooltip
506
506
-
text={
507
507
-
validHandles[alias] === true ? "Valid handle"
508
508
-
: validHandles[alias] === undefined ?
509
509
-
"Validating"
510
510
-
: "Invalid handle"
511
511
-
}
512
512
+
<button
513
513
+
class="flex items-center rounded p-0.5 hover:bg-neutral-200 dark:hover:bg-neutral-700"
514
514
+
onClick={async () => {
515
515
+
setHandleDetailedResult(null);
516
516
+
setHandleModalAlias(alias);
517
517
+
const handle = alias.replace("at://", "") as Handle;
518
518
+
const result = await resolveHandleDetailed(handle);
519
519
+
if (handleModalAlias() === alias)
520
520
+
setHandleDetailedResult(result);
521
521
+
}}
512
522
>
513
523
<span
514
524
classList={{
515
515
-
"iconify lucide--check text-green-600 dark:text-green-400":
525
525
+
"iconify text-base lucide--check text-green-600 dark:text-green-400":
516
526
validHandles[alias] === true,
517
527
"iconify lucide--x text-red-500 dark:text-red-400":
518
528
validHandles[alias] === false,
···
520
530
validHandles[alias] === undefined,
521
531
}}
522
532
></span>
523
523
-
</Tooltip>
533
533
+
</button>
524
534
</Show>
525
535
</div>
526
536
)}
527
537
</For>
528
538
</div>
529
539
</Show>
540
540
+
541
541
+
{/* Handle Verification Modal */}
542
542
+
<Modal
543
543
+
open={handleModalAlias() !== null}
544
544
+
onClose={() => setHandleModalAlias(null)}
545
545
+
contentClass="dark:bg-dark-300 dark:shadow-dark-700 pointer-events-auto w-max max-w-[90vw] rounded-lg border-[0.5px] border-neutral-300 bg-white p-4 shadow-md sm:max-w-xl dark:border-neutral-700"
546
546
+
>
547
547
+
<div class="mb-2 flex items-center justify-between gap-4">
548
548
+
<p class="truncate font-semibold">
549
549
+
{handleModalAlias()?.replace("at://", "")}
550
550
+
</p>
551
551
+
<button
552
552
+
onclick={() => setHandleModalAlias(null)}
553
553
+
class="flex shrink-0 items-center rounded-md p-1.5 text-neutral-500 hover:bg-neutral-100 hover:text-neutral-700 active:bg-neutral-200 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:hover:text-neutral-200 dark:active:bg-neutral-600"
554
554
+
>
555
555
+
<span class="iconify lucide--x"></span>
556
556
+
</button>
557
557
+
</div>
558
558
+
<div class="flex flex-col gap-2">
559
559
+
<Show
560
560
+
when={handleDetailedResult()}
561
561
+
fallback={
562
562
+
<div class="flex items-center gap-2 py-2">
563
563
+
<span class="iconify lucide--loader-circle animate-spin"></span>
564
564
+
<span>Resolving handle...</span>
565
565
+
</div>
566
566
+
}
567
567
+
>
568
568
+
{(result) => {
569
569
+
const expectedDid = didDocument().id;
570
570
+
const dnsOk = () =>
571
571
+
result().dns.success && result().dns.did === expectedDid;
572
572
+
const httpOk = () =>
573
573
+
result().http.success && result().http.did === expectedDid;
574
574
+
const dnsMismatch = () =>
575
575
+
result().dns.success && result().dns.did !== expectedDid;
576
576
+
const httpMismatch = () =>
577
577
+
result().http.success && result().http.did !== expectedDid;
578
578
+
579
579
+
return (
580
580
+
<div class="grid grid-cols-[auto_1fr] items-center gap-x-1.5">
581
581
+
{/* DNS Result */}
582
582
+
<span
583
583
+
classList={{
584
584
+
"iconify lucide--check text-green-600 dark:text-green-400":
585
585
+
dnsOk(),
586
586
+
"iconify lucide--x text-red-500 dark:text-red-400": !dnsOk(),
587
587
+
}}
588
588
+
></span>
589
589
+
<span class="font-medium">DNS (TXT record)</span>
590
590
+
<span></span>
591
591
+
<div class="mb-2 text-sm wrap-anywhere text-neutral-500 dark:text-neutral-400">
592
592
+
<Show
593
593
+
when={result().dns.success}
594
594
+
fallback={
595
595
+
<div class="text-red-500 dark:text-red-400">
596
596
+
{result().dns.error}
597
597
+
</div>
598
598
+
}
599
599
+
>
600
600
+
<div>{result().dns.did}</div>
601
601
+
<Show when={dnsMismatch()}>
602
602
+
<div class="text-red-500 dark:text-red-400">
603
603
+
Expected: {expectedDid}
604
604
+
</div>
605
605
+
</Show>
606
606
+
</Show>
607
607
+
</div>
608
608
+
609
609
+
{/* HTTP Result */}
610
610
+
<span
611
611
+
classList={{
612
612
+
"iconify lucide--check text-green-600 dark:text-green-400":
613
613
+
httpOk(),
614
614
+
"iconify lucide--x text-red-500 dark:text-red-400": !httpOk(),
615
615
+
}}
616
616
+
></span>
617
617
+
<span class="font-medium">HTTP (.well-known)</span>
618
618
+
<span></span>
619
619
+
<div class="text-sm wrap-anywhere text-neutral-500 dark:text-neutral-400">
620
620
+
<Show
621
621
+
when={result().http.success}
622
622
+
fallback={
623
623
+
<div class="text-red-500 dark:text-red-400">
624
624
+
{result().http.error}
625
625
+
</div>
626
626
+
}
627
627
+
>
628
628
+
<div>{result().http.did}</div>
629
629
+
<Show when={httpMismatch()}>
630
630
+
<div class="text-red-500 dark:text-red-400">
631
631
+
Expected: {expectedDid}
632
632
+
</div>
633
633
+
</Show>
634
634
+
</Show>
635
635
+
</div>
636
636
+
</div>
637
637
+
);
638
638
+
}}
639
639
+
</Show>
640
640
+
</div>
641
641
+
</Modal>
530
642
531
643
{/* Services Section */}
532
644
<Show when={didDocument().service}>