Main coves client
1/// Example usage of the atProto identity resolution layer.
2///
3/// This demonstrates the critical functionality for decentralization:
4/// resolving handles and DIDs to find where user data is actually stored.
5
6import 'package:atproto_oauth_flutter/src/identity/identity.dart';
7
8Future<void> main() async {
9 print('=== atProto Identity Resolution Examples ===\n');
10
11 // Create an identity resolver
12 // The handleResolverUrl should point to an XRPC service that implements
13 // com.atproto.identity.resolveHandle (typically bsky.social for public resolution)
14 final resolver = AtprotoIdentityResolver.withDefaults(
15 handleResolverUrl: 'https://bsky.social',
16 );
17
18 print('Example 1: Resolve a Bluesky handle to find their PDS');
19 print('--------------------------------------------------');
20 try {
21 // This is the most common use case: find where a user's data lives
22 final pdsUrl = await resolver.resolveToPds('pfrazee.com');
23 print('Handle: pfrazee.com');
24 print('PDS URL: $pdsUrl');
25 print('✓ This user hosts their data on: $pdsUrl\n');
26 } catch (e) {
27 print('Error: $e\n');
28 }
29
30 print('Example 2: Get full identity information');
31 print('--------------------------------------------------');
32 try {
33 final info = await resolver.resolve('pfrazee.com');
34 print('Handle: ${info.handle}');
35 print('DID: ${info.did}');
36 print('PDS URL: ${info.pdsUrl}');
37 print('Has valid handle: ${info.hasValidHandle}');
38 print('Also known as: ${info.didDoc.alsoKnownAs}');
39 print('✓ Complete identity information retrieved\n');
40 } catch (e) {
41 print('Error: $e\n');
42 }
43
44 print('Example 3: Resolve from a DID');
45 print('--------------------------------------------------');
46 try {
47 // You can also start from a DID
48 final info = await resolver.resolveFromDid(
49 'did:plc:ragtjsm2j2vknwkz3zp4oxrd',
50 );
51 print('DID: ${info.did}');
52 print('Handle: ${info.handle}');
53 print('PDS URL: ${info.pdsUrl}');
54 print('✓ Resolved DID to handle and PDS\n');
55 } catch (e) {
56 print('Error: $e\n');
57 }
58
59 print('Example 4: Custom domain handle (CRITICAL for decentralization)');
60 print('--------------------------------------------------');
61 try {
62 // This demonstrates why this code is essential:
63 // Users can use their own domains and host on their own PDS
64 final info = await resolver.resolve('jay.bsky.team');
65 print('Handle: ${info.handle}');
66 print('DID: ${info.did}');
67 print('PDS URL: ${info.pdsUrl}');
68 print('✓ Custom domain resolves to custom PDS (not hardcoded!)\n');
69 } catch (e) {
70 print('Error: $e\n');
71 }
72
73 print('Example 5: Validation - Invalid handle');
74 print('--------------------------------------------------');
75 try {
76 await resolver.resolve('not-a-valid-handle');
77 } catch (e) {
78 print('✓ Correctly rejected invalid handle: $e\n');
79 }
80
81 print('=== Why This Matters ===');
82 print('''
83This identity resolution layer is THE CRITICAL PIECE for atProto decentralization:
84
851. **No Hardcoded Servers**: Unlike broken implementations that hardcode bsky.social,
86 this correctly resolves each user's actual PDS location.
87
882. **Custom Domains**: Users can use their own domains (e.g., alice.example.com)
89 and host on any PDS they choose.
90
913. **Portability**: Users can change their PDS without losing their DID or identity.
92 The DID document always points to the current PDS location.
93
944. **Bi-directional Validation**: We verify that:
95 - Handle → DID resolution works
96 - DID document contains the handle
97 - Both directions match (security!)
98
995. **Caching**: Built-in caching prevents redundant lookups while respecting TTLs.
100
101Without this layer, apps are locked to centralized servers. With it, atProto
102achieves true decentralization where users control their data location.
103''');
104}