# Blind relays (/p2p-capabilities/blind-relays)



## Overview

Blind relays help establish peer connections through NAT/firewalls by routing traffic through relay nodes. Use it for model downloads from [our model registry](/introduction#models) and for delegated inference scenarios where peers may be behind restrictive network configurations.

## Configuration

Configure relays via QVAC config file (`qvac.config.json`, `qvac.config.js`, or `qvac.config.ts`) in your project root:

```json
{
  "swarmRelays": ["<relay-public-key-hex>", "<relay-public-key-hex>"]
}
```

## Example

The following script shows a basic example of downloading a model via Hyperdrive with blind relays enabled:

<Tabs>
  <Tab value="js" label="JavaScript" default>
    <WrapCode>
      ```js file=<rootDir>/packages/sdk/dist/examples/download-with-blind-relays.js title="blind-relays.js" lineNumbers
      // Set config path before importing SDK - the SDK loads config during initialization
      // This example uses a config file that defines blind relay public keys for improved P2P connectivity
      // Blind relays help establish connections through NAT/firewalls by acting as intermediaries
      const configDir = import.meta.dirname ?? process.cwd();
      process.env["QVAC_CONFIG_PATH"] =
          `${configDir}/config/blind-relay/blind-relay.config.js`;
      import { downloadAsset, close, LLAMA_3_2_1B_INST_Q4_0, loadModel, getModelInfo, unloadModel, } from "@qvac/sdk";
      console.log(`▸ Download with Blind Relays Example`);
      console.log(`${"=".repeat(60)}\n`);
      try {
          // Config is loaded from examples/config/qvac.config.json (set via QVAC_CONFIG_PATH above)
          // The config contains swarmRelays - an array of Hyperswarm relay public keys
          // These relays help with NAT traversal and firewall bypassing for P2P downloads
          console.log(`▸ Starting model download from Hyperdrive...\n`);
          const modelId = await loadModel({
              modelSrc: LLAMA_3_2_1B_INST_Q4_0,
          });
          console.log(`▸ Model loaded with ID: ${modelId}`);
          const firstStatus = await getModelInfo(LLAMA_3_2_1B_INST_Q4_0);
          console.log(`▸ First status: ${JSON.stringify(firstStatus)}`);
          await unloadModel({ modelId });
          // Download model with progress tracking
          await downloadAsset({
              assetSrc: LLAMA_3_2_1B_INST_Q4_0,
              onProgress: (p) => {
                  const mb = (n) => (n / 1e6).toFixed(1);
                  const line = `▸ Downloading ${p.percentage.toFixed(0)}% (${mb(p.downloaded)}/${mb(p.total)} MB)`;
                  process.stderr.write(process.stderr.isTTY ? `\r${line}` : `${line}\n`);
                  if (p.percentage >= 100)
                      process.stderr.write("\n");
              },
          });
          console.log(`\n▸ Model downloaded successfully using blind relays!`);
          console.log(`▸ Blind relays helped establish peer connections through NAT/firewalls\n`);
          await close();
      }
      catch (error) {
          console.error("✖", error);
          console.log(`\n▸ If download failed, check the relay public keys in:`);
          console.log(`▸ examples/config/qvac.config.json`);
          console.log(`▸ (Mock keys in this example won't work in practice!)`);
          process.exit(1);
      }
      ```
    </WrapCode>
  </Tab>

  <Tab value="ts" label="TypeScript">
    <WrapCode>
      ```ts file=<rootDir>/packages/sdk/examples/download-with-blind-relays.ts title="blind-relays.ts" lineNumbers
      // Set config path before importing SDK - the SDK loads config during initialization
      // This example uses a config file that defines blind relay public keys for improved P2P connectivity
      // Blind relays help establish connections through NAT/firewalls by acting as intermediaries

      const configDir = import.meta.dirname ?? process.cwd();
      process.env["QVAC_CONFIG_PATH"] =
        `${configDir}/config/blind-relay/blind-relay.config.js`;

      import {
        downloadAsset,
        close,
        LLAMA_3_2_1B_INST_Q4_0,
        type ModelProgressUpdate,
        loadModel,
        getModelInfo,
        unloadModel,
      } from "@qvac/sdk";

      console.log(`▸ Download with Blind Relays Example`);
      console.log(`${"=".repeat(60)}\n`);

      try {
        // Config is loaded from examples/config/qvac.config.json (set via QVAC_CONFIG_PATH above)
        // The config contains swarmRelays - an array of Hyperswarm relay public keys
        // These relays help with NAT traversal and firewall bypassing for P2P downloads

        console.log(`▸ Starting model download from Hyperdrive...\n`);

        const modelId = await loadModel({
          modelSrc: LLAMA_3_2_1B_INST_Q4_0,
        });

        console.log(`▸ Model loaded with ID: ${modelId}`);

        const firstStatus = await getModelInfo(LLAMA_3_2_1B_INST_Q4_0);

        console.log(`▸ First status: ${JSON.stringify(firstStatus)}`);

        await unloadModel({ modelId });

        // Download model with progress tracking
        await downloadAsset({
          assetSrc: LLAMA_3_2_1B_INST_Q4_0,
          onProgress: (p: ModelProgressUpdate) => {
            const mb = (n: number) => (n / 1e6).toFixed(1);
            const line = `▸ Downloading ${p.percentage.toFixed(0)}% (${mb(p.downloaded)}/${mb(p.total)} MB)`;
            process.stderr.write(process.stderr.isTTY ? `\r${line}` : `${line}\n`);
            if (p.percentage >= 100) process.stderr.write("\n");
          },
        });

        console.log(`\n▸ Model downloaded successfully using blind relays!`);
        console.log(
          `▸ Blind relays helped establish peer connections through NAT/firewalls\n`,
        );

        await close();
      } catch (error) {
        console.error("✖", error);
        console.log(`\n▸ If download failed, check the relay public keys in:`);
        console.log(`▸ examples/config/qvac.config.json`);
        console.log(`▸ (Mock keys in this example won't work in practice!)`);
        process.exit(1);
      }
      ```
    </WrapCode>
  </Tab>
</Tabs>

<Callout type="success">
  **Tip:** all examples throughout this documentation are self-contained and runnable. For instructions on how to run them, see [SDK quickstart](/quickstart).
</Callout>

## Notes

The examples use mock relay keys. For real deployments, you **must** use your own relay servers or trusted public relays.

The same `swarmRelays` config also applies to delegated inference (provider/consumer). Configure it via [`qvac.config.*` file (or `QVAC_CONFIG_PATH`)](https://github.com/tetherto/qvac/blob/main/packages/qvac-sdk/schemas/translation-config.ts) and then start your provider/consumer as usual.
