Resolve AT Protocol DIDs, handles, and schemas with intelligent caching for Laravel
1<?php
2
3namespace SocialDept\AtpResolver\Support;
4
5class Identity
6{
7 // "***.bsky.social" "alice.test"
8 protected const HANDLE_REGEX = '/^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/';
9
10 // "did:plc:1234..." "did:web:alice.test"
11 protected const DID_REGEX = '/^did:[a-z]+:[a-zA-Z0-9._:%-]*[a-zA-Z0-9._-]$/';
12
13 /**
14 * Check if a string is a valid handle.
15 *
16 * @param string|null $handle
17 */
18 public static function isHandle(?string $handle): bool
19 {
20 return preg_match(self::HANDLE_REGEX, $handle ?? '') === 1;
21 }
22
23 /**
24 * Check if a string is a valid DID.
25 *
26 * @param string|null $did
27 */
28 public static function isDid(?string $did): bool
29 {
30 return preg_match(self::DID_REGEX, $did ?? '') === 1;
31 }
32
33 /**
34 * Extract the DID method from a DID string.
35 *
36 * @param string $did
37 * @return string|null Returns the method (e.g., "plc", "web") or null if invalid
38 */
39 public static function extractDidMethod(string $did): ?string
40 {
41 if (! self::isDid($did)) {
42 return null;
43 }
44
45 $parts = explode(':', $did);
46
47 return $parts[1] ?? null;
48 }
49
50 /**
51 * Check if a DID uses the PLC method.
52 *
53 * @param string $did
54 */
55 public static function isPlcDid(string $did): bool
56 {
57 return self::extractDidMethod($did) === 'plc';
58 }
59
60 /**
61 * Check if a DID uses the Web method.
62 *
63 * @param string $did
64 */
65 public static function isWebDid(string $did): bool
66 {
67 return self::extractDidMethod($did) === 'web';
68 }
69}