# Build a Hello World (TypeScript)

#### Prerequisites <a href="#prerequisites" id="prerequisites"></a>

Before you begin, ensure you have the following installed:

* [Bun](https://bun.sh/)

***

#### Step 1: Create a Bun Project <a href="#step-1-create-a-bun-project" id="step-1-create-a-bun-project"></a>

First, create a new project directory and initialize it with Bun:

Copy

```
mkdir hello-world-ml
cd hello-world-ml
bun init -y
```

Next, install the required dependencies:

Copy

```
bun add nostr-tools @solana/web3.js
```

***

#### Step 2: Write the Subscriber Code <a href="#step-2-write-the-subscriber-code" id="step-2-write-the-subscriber-code"></a>

Create a file named `subscriber.ts` and add the following code. This script connects to the Nostr relay, subscribes to "Hello World" events (custom kind 1573), and logs any received messages.

Copy

```
// subscriber.ts

import { Relay } from "nostr-tools/relay";

const RELAY_URL = "wss://dev-relay.xephy.dev";

async function main() {
  const relay = await Relay.connect(RELAY_URL);
  console.log("Subscribed events on", RELAY_URL);

  relay.subscribe(
    [
      {
        kinds: [1573],
        since: Math.floor(Date.now() / 1000),
        "#s": ["hello_session"],
        "#p": ["receiver_pubkey"],
      },
    ],
    {
      onevent: async (event) => {
        console.log("Received:", event.content);
      },
    }
  );
}

main().catch(console.error);
```

***

#### Step 3: Write the Publisher Code <a href="#step-3-write-the-publisher-code" id="step-3-write-the-publisher-code"></a>

Create a file named `publisher.ts` and insert the following code. This script sends a simple "Hello World" event to the relay using a Nostr event with custom tags.

Copy

```
// publisher.ts

import { finalizeEvent, generateSecretKey } from "nostr-tools/pure";
import { Relay } from "nostr-tools/relay";

const RELAY_URL = "wss://dev-relay.xephy.dev";

async function main() {
  const relay = await Relay.connect(RELAY_URL);

  const eventTemplate = {
    kind: 1573,
    created_at: Math.floor(Date.now() / 1000),
    tags: [
        ['s', "hello_session"],
        ['p', "receiver_pubkey"],
    ],
    content: "Hello World",
  };

  const sk = generateSecretKey();

  const event = finalizeEvent(eventTemplate, sk);

  await relay.publish(event);
  console.log("Published 'Hello World' event to", RELAY_URL);
}

main().catch(console.error);
```

***

#### Step 4: Run the "Hello World" Example <a href="#step-4-run-the-hello-world-example" id="step-4-run-the-hello-world-example"></a>

Open two terminals (or tabs):

* Run the `Subscriber`:

  Copy

  ```
  bun run subscriber.ts
  ```
* Run the `Publisher` (in a new terminal):

  Copy

  ```
  bun run publisher.ts
  ```
* Expected Output:

  * `Subscriber` terminal:

  Copy

  ```
  Subscribed events on wss://dev-relay.xephy.dev
  ```

  * `Publisher` terminal:

  Copy

  ```
  Published 'Hello World' event to wss://dev-relay.xephy.dev
  ```

  * `Subscriber` terminal:

  Copy

  ```
  Received: Hello World
  ```

***

#### Next, Enhance the Functionality with Solana Airdrop <a href="#next-enhance-the-functionality-with-solana-airdrop" id="next-enhance-the-functionality-with-solana-airdrop"></a>

At this point, the basic publish and subscribe functionality is complete. Next, we will enhance this by integrating with the Solana blockchain. Specifically, when publishing a greeting like "Hello World," the publisher will include a Solana public key, and the subscriber will request a Solana airdrop.

***

#### Step 5: Update the Publisher <a href="#step-5-update-the-publisher" id="step-5-update-the-publisher"></a>

Edit `publisher.ts` to include a structured message and a Solana public key. Replace its contents with the following code:

Copy

```
// publisher.ts

import { finalizeEvent, generateSecretKey } from "nostr-tools/pure";
import { Relay } from "nostr-tools/relay";
import { Keypair } from "@solana/web3.js";

const RELAY_URL = "wss://dev-relay.xephy.dev";

interface Message {
  greeting: string;
  solana_pubkey: string;
}

async function main() {
  const relay = await Relay.connect(RELAY_URL);

  // Generate a new Solana keypair and extract its public key
  const solanaKeypair = Keypair.generate();
  const solanaPubkey = solanaKeypair.publicKey.toBase58();

  // Create a Message object
  const message: Message = {
    greeting: "Hello World",
    solana_pubkey: solanaPubkey,
  };

  const eventTemplate = {
    kind: 1573,
    created_at: Math.floor(Date.now() / 1000),
    tags: [
      ["s", "hello_session"],
      ["p", "receiver_pubkey"],
    ],
    content: JSON.stringify(message),
  };

  const sk = generateSecretKey();

  const event = finalizeEvent(eventTemplate, sk);

  await relay.publish(event);
  console.log("Published 'Hello World' event to", RELAY_URL);
  console.log("Airdrop request for", solanaPubkey.toString());
}

main().catch(console.error);
```

***

#### Step 6: Update the Subscriber <a href="#step-6-update-the-subscriber" id="step-6-update-the-subscriber"></a>

Edit `subscriber.ts` so that it parses the structured message, extracts the Solana public key, and requests a Solana airdrop. Replace its contents with the following code:

Copy

```
// subscriber.ts

import { Relay } from "nostr-tools/relay";
import { Connection, PublicKey } from "@solana/web3.js";

const RELAY_URL = "wss://dev-relay.xephy.dev";

interface Message {
  greeting: string;
  solana_pubkey: string;
}

async function main() {
  const relay = await Relay.connect(RELAY_URL);
  console.log("Subscribed events on", RELAY_URL);
  const solanaConnection = new Connection(
    "https://api.devnet.solana.com",
    "confirmed"
  );

  relay.subscribe(
    [
      {
        kinds: [1573],
        since: Math.floor(Date.now() / 1000),
        "#s": ["hello_session"],
        "#p": ["receiver_pubkey"],
      },
    ],
    {
      onevent: async (event) => {
        console.log("Received:", event.content);

        const message: Message = JSON.parse(event.content);
        if (message.solana_pubkey) {
          const pubkey = new PublicKey(message.solana_pubkey);
          // Request an airdrop of 1 SOL (1 SOL = 1_000_000_000 lamports)
          const signature = await solanaConnection.requestAirdrop(
            pubkey,
            1_000_000_000
          );
          console.log(
            `Airdrop requested for ${pubkey.toBase58()}. Signature: ${signature}`
          );
          // Confirm the transaction
          const confirmation = await solanaConnection.confirmTransaction(
            signature
          );
          if (confirmation.value.err === null) {
            console.log(`Airdrop confirmed for ${pubkey.toBase58()}`);
          } else {
            console.error(
              `Airdrop confirmation failed for ${pubkey.toBase58()}`
            );
          }
        }
      },
    }
  );
}

main().catch(console.error);
```

***

#### Step 7: Run the Enhanced Example <a href="#step-7-run-the-enhanced-example" id="step-7-run-the-enhanced-example"></a>

Open two terminals (or tabs):

* Run the `Subscriber`:

  Copy

  ```
  bun run subscriber.ts
  ```
* Run the `Publisher` (in a new terminal):

  Copy

  ```
  bun run publisher.ts
  ```
* Expected Output:

  * `Subscriber` terminal:

  Copy

  ```
  Subscribed events on wss://dev-relay.xephy.dev
  ```

  * `Publisher` terminal:

  Copy

  ```
  Published 'Hello World' event to wss://dev-relay.xephy.dev
  Airdrop request for [ ... ]
  ```

  * `Subscriber` terminal:

  Copy

  ```
  Received: {"greeting":"Hello World","solana_pubkey":"..."}
  Airdrop requested for ... Signature: ...
  Airdrop confirmed for ...
  ```

***

#### Next Steps <a href="#next-steps" id="next-steps"></a>

This example demonstrates a basic integration between the Messaging Layer and Solana using Bun and TypeScript. You can extend this further by:

* Deploying a Solana smart contract (program) to handle more complex interactions
* Using Nostr events to trigger contract calls
* Implementing payment verification or other blockchain-based logic
* Adding error handling and retry mechanisms for airdrop requests

This simple integration opens the door to building decentralized applications that combine messaging capabilities with Solana’s high-performance blockchain.

Happy coding!
