PHPackages                             socialdept/atp-resolver - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. socialdept/atp-resolver

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

socialdept/atp-resolver
=======================

Resolve AT Protocol DIDs and handles in Laravel

v1.1.0(5mo ago)2262MITPHPPHP ^8.2CI passing

Since Nov 1Pushed 4mo agoCompare

[ Source](https://github.com/socialdept/atp-resolver)[ Packagist](https://packagist.org/packages/socialdept/atp-resolver)[ RSS](/packages/socialdept-atp-resolver/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (2)Dependencies (7)Versions (7)Used By (0)

[![Resolver Header](./header.png)](https://github.com/socialdept/atp-signals)

###  Resolve AT Protocol identities in your Laravel application.

[](#----resolve-at-protocol-identities-in-your-laravel-application)

 [![](https://camo.githubusercontent.com/ec626bf7c4ca808f9400b72bc73996a02d12725cb30fdb67d6c2ec6ef634a9f1/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f736f6369616c646570742f6174702d7265736f6c7665722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/socialdept/atp-resolver "Latest Version on Packagist") [![](https://camo.githubusercontent.com/4fd83a7c845e657abf3ebf225c2bac891f424a62c88556808d09a1354f2d0aaf/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f736f6369616c646570742f6174702d7265736f6c7665722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/socialdept/atp-resolver "Total Downloads") [![](https://camo.githubusercontent.com/a81ef84b06496cc35c7795ef6c8e70c6895c896394905ecabce6c084c7d8bdf2/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f736f6369616c646570742f6174702d7265736f6c7665722f74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/socialdept/atp-resolver/actions/workflows/tests.yml "GitHub Tests Action Status") [![](https://camo.githubusercontent.com/bc56e7fee85c00c7563ea3306f9b45f2bbef0f36ca1109023ff133fcc8aa0eaa/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f736f6369616c646570742f6174702d7265736f6c7665723f7374796c653d666c61742d737175617265)](LICENSE "Software License")

---

What is Resolver?
-----------------

[](#what-is-resolver)

**Resolver** is a Laravel package that resolves AT Protocol identities. Convert DIDs to handles, find PDS endpoints, and resolve DID documents with automatic caching and fallback support for both `did:plc` and `did:web` methods.

Think of it as a Swiss Army knife for AT Protocol identity resolution.

Why use Resolver?
-----------------

[](#why-use-resolver)

- **Simple API** - Resolve DIDs and handles with one method call
- **Automatic caching** - Smart caching with configurable TTLs
- **Multiple DID methods** - Support for `did:plc` and `did:web`
- **PDS discovery** - Find the correct PDS endpoint for any user
- **Production ready** - Battle-tested with proper error handling
- **Zero config** - Works out of the box with sensible defaults

Quick Example
-------------

[](#quick-example)

```
use SocialDept\AtpResolver\Facades\Resolver;

// Resolve a DID to its document
$document = Resolver::resolveDid('did:plc:ewvi7nxzyoun6zhxrhs64oiz');
$handle = $document->getHandle(); // "user.bsky.social"
$pds = $document->getPdsEndpoint(); // "https://bsky.social"

// Convert a handle to its DID
$did = Resolver::handleToDid('user.bsky.social');
// "did:plc:ewvi7nxzyoun6zhxrhs64oiz"

// Resolve any identity (DID or handle) to a document
$document = Resolver::resolveIdentity('alice.bsky.social');

// Find someone's PDS endpoint
$pds = Resolver::resolvePds('alice.bsky.social');
// "https://bsky.social"
```

Installation
------------

[](#installation)

```
composer require socialdept/atp-resolver
```

Resolver will auto-register with Laravel. Optionally publish the config:

```
php artisan vendor:publish --tag=resolver-config
```

Basic Usage
-----------

[](#basic-usage)

### Resolving DIDs

[](#resolving-dids)

Resolver supports both `did:plc` and `did:web` methods:

```
use SocialDept\AtpResolver\Facades\Resolver;

// PLC directory resolution
$document = Resolver::resolveDid('did:plc:ewvi7nxzyoun6zhxrhs64oiz');

// Web DID resolution
$document = Resolver::resolveDid('did:web:example.com');

// Access document data
$handle = $document->getHandle();
$pdsEndpoint = $document->getPdsEndpoint();
$services = $document->service;
```

### Resolving Handles

[](#resolving-handles)

Convert human-readable handles to DIDs or DID documents:

```
// Convert handle to DID string
$did = Resolver::handleToDid('alice.bsky.social');
// "did:plc:ewvi7nxzyoun6zhxrhs64oiz"

// Resolve handle to full DID document
$document = Resolver::resolveHandle('alice.bsky.social');
$handle = $document->getHandle();
$pds = $document->getPdsEndpoint();
```

### Resolving Identities

[](#resolving-identities)

Automatically detect and resolve either DIDs or handles:

```
// Works with DIDs
$document = Resolver::resolveIdentity('did:plc:ewvi7nxzyoun6zhxrhs64oiz');

// Works with handles
$document = Resolver::resolveIdentity('alice.bsky.social');

// Perfect for user input where type is unknown
$actor = $request->input('actor'); // Could be DID or handle
$document = Resolver::resolveIdentity($actor);
```

### Finding PDS Endpoints

[](#finding-pds-endpoints)

Automatically discover a user's Personal Data Server:

```
// From a DID
$pds = Resolver::resolvePds('did:plc:ewvi7nxzyoun6zhxrhs64oiz');

// From a handle
$pds = Resolver::resolvePds('alice.bsky.social');

// Returns: "https://bsky.social" or user's custom PDS
```

This is particularly useful when you need to make API calls to a user's PDS instead of hardcoding Bluesky's public instance.

### Cache Management

[](#cache-management)

Beacon automatically caches resolutions. Clear the cache when needed:

```
// Clear specific DID cache
Resolver::clearDidCache('did:plc:abc123');

// Clear specific handle cache
Resolver::clearHandleCache('alice.bsky.social');

// Clear specific PDS cache
Resolver::clearPdsCache('alice.bsky.social');

// Clear all cached data
Resolver::clearCache();
```

### Disable Caching

[](#disable-caching)

Pass `false` as the second parameter to bypass cache:

```
$document = Resolver::resolveDid('did:plc:abc123', useCache: false);
$did = Resolver::handleToDid('alice.bsky.social', useCache: false);
$document = Resolver::resolveIdentity('alice.bsky.social', useCache: false);
$pds = Resolver::resolvePds('alice.bsky.social', useCache: false);
```

### Identity Validation

[](#identity-validation)

Beacon includes static helper methods to validate DIDs and handles:

```
use SocialDept\AtpResolver\Support\Identity;

// Validate handles
Identity::isHandle('alice.bsky.social'); // true
Identity::isHandle('invalid');           // false

// Validate DIDs
Identity::isDid('did:plc:ewvi7nxzyoun6zhxrhs64oiz'); // true
Identity::isDid('did:web:example.com');              // true
Identity::isDid('invalid');                          // false

// Extract DID method
Identity::extractDidMethod('did:plc:abc123'); // "plc"
Identity::extractDidMethod('did:web:test');   // "web"

// Check specific DID types
Identity::isPlcDid('did:plc:abc123'); // true
Identity::isWebDid('did:web:test');   // true
```

These helpers are useful for validating user input before making resolution calls.

Configuration
-------------

[](#configuration)

Beacon works great with zero configuration, but you can customize behavior in `config/resolver.php`:

```
return [
    // PLC directory for did:plc resolution
    'plc_directory' => env('RESOLVER_PLC_DIRECTORY', 'https://plc.directory'),

    // Default PDS endpoint for handle resolution
    'pds_endpoint' => env('RESOLVER_PDS_ENDPOINT', 'https://bsky.social'),

    // HTTP request timeout
    'timeout' => env('RESOLVER_TIMEOUT', 10),

    // Cache configuration
    'cache' => [
        'enabled' => env('RESOLVER_CACHE_ENABLED', true),

        // Cache TTL for DID documents (1 hour)
        'did_ttl' => env('RESOLVER_CACHE_DID_TTL', 3600),

        // Cache TTL for handle resolutions (1 hour)
        'handle_ttl' => env('RESOLVER_CACHE_HANDLE_TTL', 3600),

        // Cache TTL for PDS endpoints (1 hour)
        'pds_ttl' => env('RESOLVER_CACHE_PDS_TTL', 3600),
    ],
];
```

API Reference
-------------

[](#api-reference)

### Available Methods

[](#available-methods)

```
// DID Resolution
Resolver::resolveDid(string $did, bool $useCache = true): DidDocument

// Handle Resolution
Resolver::handleToDid(string $handle, bool $useCache = true): string
Resolver::resolveHandle(string $handle, bool $useCache = true): DidDocument

// Identity Resolution
Resolver::resolveIdentity(string $actor, bool $useCache = true): DidDocument

// PDS Resolution
Resolver::resolvePds(string $actor, bool $useCache = true): ?string

// Cache Management
Resolver::clearDidCache(string $did): void
Resolver::clearHandleCache(string $handle): void
Resolver::clearPdsCache(string $actor): void
Resolver::clearCache(): void

// Identity Validation (static helpers)
Identity::isHandle(?string $handle): bool
Identity::isDid(?string $did): bool
Identity::extractDidMethod(string $did): ?string
Identity::isPlcDid(string $did): bool
Identity::isWebDid(string $did): bool
```

### DidDocument Object

[](#diddocument-object)

```
$document->id;                    // string - The DID
$document->alsoKnownAs;           // array - Alternative identifiers
$document->verificationMethod;    // array - Verification methods
$document->service;               // array - Service endpoints
$document->raw;                   // array - Raw DID document

// Helper methods
$document->getHandle();           // ?string - Extract handle from alsoKnownAs
$document->getPdsEndpoint();      // ?string - Extract PDS service endpoint
$document->toArray();             // array - Convert to array
```

Error Handling
--------------

[](#error-handling)

Beacon throws descriptive exceptions when resolution fails:

```
use SocialDept\AtpResolver\Exceptions\DidResolutionException;
use SocialDept\AtpResolver\Exceptions\HandleResolutionException;

try {
    $document = Resolver::resolveDid('did:invalid:format');
} catch (DidResolutionException $e) {
    // Handle DID resolution errors
    logger()->error('DID resolution failed', [
        'message' => $e->getMessage(),
    ]);
}

try {
    $did = Resolver::handleToDid('invalid-handle');
} catch (HandleResolutionException $e) {
    // Handle handle resolution errors
}
```

Use Cases
---------

[](#use-cases)

### Building an AppView

[](#building-an-appview)

```
// Resolve user identity from DID
$document = Resolver::resolveDid($event->did);
$handle = $document->getHandle();

// Make authenticated requests to their PDS
$pds = Resolver::resolvePds($event->did);
$client = new AtProtoClient($pds);
```

### Custom Feed Generators

[](#custom-feed-generators)

```
// Resolve multiple handles efficiently (caching kicks in)
$dids = collect(['alice.bsky.social', 'bob.bsky.social'])
    ->map(fn($handle) => Resolver::handleToDid($handle))
    ->all();
```

### Profile Resolution

[](#profile-resolution)

```
// Get complete identity information
$document = Resolver::resolveIdentity($username);

$profile = [
    'did' => $document->id,
    'handle' => $document->getHandle(),
    'pds' => $document->getPdsEndpoint(),
];
```

### Input Validation

[](#input-validation)

```
use SocialDept\AtpResolver\Support\Identity;
use SocialDept\AtpResolver\Facades\Resolver;

// Validate user input before resolving
$actor = request()->input('actor');

if (Identity::isHandle($actor) || Identity::isDid($actor)) {
    $document = Resolver::resolveIdentity($actor);
} else {
    abort(422, 'Invalid handle or DID');
}

// Or convert handle to DID
if (Identity::isHandle($actor)) {
    $did = Resolver::handleToDid($actor);
}
```

Requirements
------------

[](#requirements)

- PHP 8.2+
- Laravel 11+
- `ext-gmp` extension

Resources
---------

[](#resources)

- [AT Protocol Documentation](https://atproto.com/)
- [DID:PLC Specification](https://github.com/did-method-plc/did-method-plc)
- [DID:Web Specification](https://w3c-ccg.github.io/did-method-web/)
- [PLC Directory](https://plc.directory/)

Support &amp; Contributing
--------------------------

[](#support--contributing)

Found a bug or have a feature request? [Open an issue](https://github.com/socialdept/atp-resolver/issues).

Want to contribute? We'd love your help! Check out the [contribution guidelines](CONTRIBUTING.md).

Credits
-------

[](#credits)

- [Miguel Batres](https://batres.co) - founder &amp; lead maintainer
- [All contributors](https://github.com/socialdept/atp-resolver/graphs/contributors)

License
-------

[](#license)

Beacon is open-source software licensed under the [MIT license](LICENSE).

---

**Built for the Federation** • By Social Dept.

###  Health Score

40

—

FairBetter than 87% of packages

Maintenance78

Regular maintenance activity

Popularity14

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity51

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~6 days

Total

5

Last Release

164d ago

Major Versions

v0.1.2 → v1.0.02025-11-02

### Community

Maintainers

![](https://www.gravatar.com/avatar/ae252717302843968ef8adec35c3edb4a8fe70656083863691b6566b54ffeea9?d=identicon)[socialdept](/maintainers/socialdept)

---

Top Contributors

[![btrsco](https://avatars.githubusercontent.com/u/1373528?v=4)](https://github.com/btrsco "btrsco (16 commits)")

###  Code Quality

TestsPHPUnit

Code StylePHP CS Fixer

### Embed Badge

![Health badge](/badges/socialdept-atp-resolver/health.svg)

```
[![Health](https://phpackages.com/badges/socialdept-atp-resolver/health.svg)](https://phpackages.com/packages/socialdept-atp-resolver)
```

###  Alternatives

[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9682.1M97](/packages/roots-acorn)[laravel-zero/framework

The Laravel Zero Framework.

3371.4M368](/packages/laravel-zero-framework)[orchestra/canvas

Code Generators for Laravel Applications and Packages

21017.2M157](/packages/orchestra-canvas)[glhd/conveyor-belt

14797.0k](/packages/glhd-conveyor-belt)[pulkitjalan/ip-geolocation

IP Geolocation Wrapper with Laravel Support

89164.9k1](/packages/pulkitjalan-ip-geolocation)[torchlight/torchlight-laravel

A Laravel Client for Torchlight, the syntax highlighting API.

120452.8k11](/packages/torchlight-torchlight-laravel)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
