> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Laravel Nostr

> Package Laravel pour le protocole Nostr. Gestion des clés, opérations sur les événements, prise en charge des pools, NIP-05 / NIP-17 et intégration avec Laravel Notifications.

## Vue d'ensemble

[revolution/laravel-nostr](https://github.com/invokable/laravel-nostr) est un package qui permet d'utiliser le protocole Nostr depuis Laravel. Il propose la génération et la conversion de clés, la récupération et la publication d'événements, la prise en charge de pools (plusieurs relays), les profils NIP-05, les messages directs privés NIP-17, ainsi que l'intégration avec Laravel Notifications.

<Info>
  Les spécifications de Nostr évoluent encore, ce package est donc en développement continu. La fonctionnalité de notification est déjà utilisable en pratique.
</Info>

## Pilotes

Ce package propose deux pilotes.

| Pilote   | Description                                                                                                             |
| -------- | ----------------------------------------------------------------------------------------------------------------------- |
| `native` | Implémentation en PHP pur. Utilise [nostr-php](https://github.com/nostrver-se/nostr-php). Suffisant à l'heure actuelle. |
| `node`   | Implémentation dépendant d'une [WebAPI externe](https://github.com/kawax/nostr-vercel-api) (Node.js).                   |

<Tip>
  La particularité du pilote `native` est son implémentation `WebSocketHttpMixin`. Il se connecte en WebSocket via le client HTTP de Laravel, échange des données puis se déconnecte immédiatement. Il n'est pas nécessaire de faire tourner un serveur WebSocket en continu, ce qui rend cette solution accessible à tout utilisateur de Laravel.
</Tip>

<Info>
  Le pilote `native` ne prend pas en charge NIP-04.
</Info>

### Configuration du pilote par défaut

Configurez dans `config/nostr.php` ou `.env`.

```php theme={null}
// config/nostr.php

'driver' => env('NOSTR_DRIVER', 'node'),
```

```dotenv theme={null}
NOSTR_DRIVER=native
```

Si aucun pilote n'est spécifié, le pilote par défaut est utilisé.

```php theme={null}
use Revolution\Nostr\Facades\Nostr;

Nostr::event()->list();
```

Vous pouvez également spécifier explicitement le pilote.

```php theme={null}
use Revolution\Nostr\Facades\Nostr;

Nostr::driver('node')->event()->list();
Nostr::node()->event()->list();

Nostr::driver('native')->event()->list();
Nostr::native()->event()->list();
```

## Installation

<Steps>
  <Step title="Installer le package">
    ```bash theme={null}
    composer require revolution/laravel-nostr
    ```
  </Step>

  <Step title="Publier le fichier de configuration">
    ```bash theme={null}
    php artisan vendor:publish --tag=nostr-config
    ```
  </Step>
</Steps>

## Gestion des clés

### Générer une clé

```php theme={null}
use Revolution\Nostr\Facades\Nostr;
use Illuminate\Http\Client\Response;

/** @var Response $response */
$response = Nostr::key()->generate();
$keys = $response->json();
// [
//     'sk'   => 'sk...',
//     'nsec' => 'nsec...',
//     'pk'   => 'pk...',
//     'npub' => 'npub...',
// ]
```

### Convertir une clé

Conversion depuis un nsec.

```php theme={null}
use Revolution\Nostr\Facades\Nostr;

$response = Nostr::key()->fromNsec(nsec: 'nsec');
$keys = $response->json();
// ['sk' => '...', 'nsec' => '...', 'pk' => '...', 'npub' => '...']
```

Conversion depuis une secret key.

```php theme={null}
$response = Nostr::key()->fromSecretKey(sk: 'sk');
```

Conversion depuis un npub (clé publique uniquement).

```php theme={null}
$response = Nostr::key()->fromNpub(npub: 'npub');
$keys = $response->json();
// ['pk' => '...', 'npub' => '...']
```

Conversion depuis une public key.

```php theme={null}
$response = Nostr::key()->fromPublicKey(pk: 'pk');
```

## Récupération d'événements

### Récupérer plusieurs événements

```php theme={null}
use Illuminate\Http\Client\Response;
use Revolution\Nostr\Facades\Nostr;
use Revolution\Nostr\Filter;
use Revolution\Nostr\Kind;

$filter = Filter::make(
    authors: ['my pk'],
    kinds: [Kind::Text],
    limit: 10,
);

/** @var Response $response */
$response = Nostr::event()->list(filter: $filter);
$events = $response->json('events');
// [
//     ['id' => '...1', 'kind' => 1, 'content' => '...'],
//     ['id' => '...2', 'kind' => 1, 'content' => '...'],
// ]
```

### Récupérer un seul événement

```php theme={null}
use Revolution\Nostr\Facades\Nostr;
use Revolution\Nostr\Filter;
use Revolution\Nostr\Kind;

$filter = Filter::make(
    authors: ['my pk'],
    kinds: [Kind::Metadata],
);

$response = Nostr::event()->get(filter: $filter);
$event = $response->json('event');
// ['id' => '...', 'kind' => 0, 'content' => '{name: ""}']
```

## Publication d'événements

### Publier sur un seul relay

```php theme={null}
use Revolution\Nostr\Facades\Nostr;
use Revolution\Nostr\Event;
use Revolution\Nostr\Kind;

$event = Event::make(
    kind: Kind::Text,
    content: 'hello',
    created_at: now()->timestamp,
    tags: [],
);

$sk = 'my sk';

$response = Nostr::event()->publish(event: $event, sk: $sk);

if ($response->successful()) {
    $event = $response->json('event');
}
```

### Publier sur plusieurs relays (pool)

```php theme={null}
use Revolution\Nostr\Facades\Nostr;
use Revolution\Nostr\Event;
use Revolution\Nostr\Kind;

$event = Event::make(
    kind: Kind::Text,
    content: 'test',
    created_at: now()->timestamp,
    tags: [],
);

$responses = Nostr::pool()->publish(event: $event, sk: 'my sk');
// $responses est de type array<string, Response>
// ['wss://relay1' => $response, 'wss://relay2' => $response]

foreach ($responses as $relay => $response) {
    if ($response->failed()) {
        dump($relay . ' : ' . $response->body());
    }
}
```

## Configuration des serveurs relay

### Serveurs relay utilisés

Si vous utilisez uniquement `Nostr::event()`, le premier relay défini dans `config/nostr.php` est utilisé. Avec `Nostr::pool()`, tous les relays de la configuration sont ciblés.

### Modifier les relays à l'exécution

```php theme={null}
use Revolution\Nostr\Facades\Nostr;

$response = Nostr::event()->withRelay('wss://')->...;
```

```php theme={null}
use Revolution\Nostr\Facades\Nostr;

$response = Nostr::pool()->withRelays(['wss://', 'wss://'])->...;
```

## Profils NIP-05

```php theme={null}
use Revolution\Nostr\Facades\Nostr;

$profile = Nostr::nip05()->profile('user@localhost');
// [
//     'user'   => 'user@localhost',
//     'pubkey' => 'pk',
//     'relays' => [],
// ]
```

## Messages directs privés NIP-17

<Info>
  NIP-17 n'est pris en charge que par le pilote `native`.
</Info>

### Envoyer un message privé

```php theme={null}
use Revolution\Nostr\Facades\Nostr;

$response = Nostr::driver('native')
    ->nip17()
    ->sendDirectMessage(
        sk: 'sender-secret-key',
        pk: 'receiver-public-key',
        message: 'Hello, this is a private message!'
    );
```

### Déchiffrer un message privé

```php theme={null}
use Revolution\Nostr\Facades\Nostr;

$response = Nostr::driver('native')
    ->nip17()
    ->decryptDirectMessage(
        giftWrap: $receivedGiftWrap,
        sk: 'receiver-secret-key'
    );

$decryptedMessage = $response->json();
```

## Laravel Notifications

Avec `NostrChannel`, vous pouvez envoyer des messages vers Nostr depuis Laravel Notifications.

### Classe Notification

```php theme={null}
use Illuminate\Notifications\Notification;
use Revolution\Nostr\Notifications\NostrChannel;
use Revolution\Nostr\Notifications\NostrMessage;
use Revolution\Nostr\Tags\HashTag;

class TestNotification extends Notification
{
    public function via(object $notifiable): array
    {
        return [
            'mail',
            NostrChannel::class,
        ];
    }

    public function toNostr(object $notifiable): NostrMessage
    {
        return new NostrMessage(
            // Le #laravel dans le content sert à l'affichage ; le HashTag dans tags est destiné à la classification au niveau du protocole.
            content: 'hello #laravel',
            tags: [
                HashTag::make(t: 'laravel'),
            ],
        );
    }
}
```

### Notification à la demande

```php theme={null}
use Illuminate\Support\Facades\Notification;
use Revolution\Nostr\Notifications\NostrRoute;

Notification::route('nostr', NostrRoute::to(sk: 'sk'))
    ->notify(new TestNotification());
```

### Intégration au modèle User

```php theme={null}
use Illuminate\Notifications\Notifiable;
use Revolution\Nostr\Notifications\NostrRoute;

class User
{
    use Notifiable;

    public function routeNotificationForNostr($notification): NostrRoute
    {
        return NostrRoute::to(sk: $this->sk, relays: ['wss://']);
    }
}
```

```php theme={null}
$user->notify(new TestNotification());
```

### Relays utilisés pour les notifications

Par défaut, tous les relays de `config/nostr.php` sont utilisés. Vous pouvez les modifier à l'exécution en spécifiant des relays dans `NostrRoute`.

```php theme={null}
use Revolution\Nostr\Notifications\NostrRoute;

return NostrRoute::to(sk: 'sk', relays: ['wss://', 'wss://']);
```

<Info>
  Pour les dernières informations, consultez le [dépôt GitHub](https://github.com/invokable/laravel-nostr).
</Info>


## Related topics

- [Laravel Telescope](/fr/telescope.md)
- [Laravel Boost](/fr/boost.md)
- [Laravel Octane](/fr/octane.md)
- [Laravel Bluesky](/fr/packages/laravel-bluesky/index.md)
- [Laravel Pint](/fr/pint.md)
