Lumera Cascade
Concepts

Download Lifecycle

How files are retrieved from the Cascade Supernode network.

Overview

Downloading a file from Cascade requires the action ID returned during upload. The process involves authentication, task creation, and streaming the reconstructed file.

Step 1: Authenticate

Every download request must be authenticated with an ADR-036 signature. The SDK signs the action_id string using the connected wallet:

const signature = await signer.signArbitrary(chainId, address, actionId);

This proves that the requester holds the private key for their Lumera address. For public files, any wallet can download; for private files, only authorized wallets are accepted.

Step 2: Request Download

The SDK sends a download request to the SN-API:

POST /api/v1/actions/cascade/{action_id}/downloads
Content-Type: application/json

{
  "signature": "base64-encoded ADR-036 signature"
}

The SN-API responds with a task_id that tracks the download preparation.

The SDK retries this request up to 3 times for transient server errors (HTTP 500), as Supernodes may need time to locate and gather the required chunks.

Step 3: Monitor Progress

The SDK monitors download progress via Server-Sent Events (SSE):

GET /api/v1/downloads/cascade/{task_id}/status

data: {"status": "processing", "progress": 45}
data: {"status": "processing", "progress": 80}
data: {"status": "completed", "progress": 100}

In browser environments, this uses the native EventSource API. In Node.js, the SDK implements a custom fetch-based SSE parser.

Step 4: Stream the File

Once the task completes, the file is available as a binary stream:

GET /api/v1/downloads/cascade/{task_id}/file
→ Content-Type: application/octet-stream
→ Binary file data

The SDK returns a ReadableStream<Uint8Array> that your application can consume:

const stream = await client.Cascade.downloader.download(actionId);
 
// Read the stream
const reader = stream.getReader();
const chunks: Uint8Array[] = [];
 
while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  chunks.push(value);
}
 
// Reassemble into a single buffer
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
const result = new Uint8Array(totalLength);
let offset = 0;
for (const chunk of chunks) {
  result.set(chunk, offset);
  offset += chunk.length;
}
 
// Decode as text (if applicable)
const text = new TextDecoder().decode(result);

Download Task States

StatusMeaning
sdk:download_completedFile ready for streaming
sdk:completedGeneric success
sdk:download_failureReconstruction failed
sdk:failedGeneric failure

Convenience Methods

Basic Download

// Returns a ReadableStream
const stream = await client.Cascade.downloader.download(actionId);

Download with Options

const stream = await client.Cascade.downloader.downloadFile({
  actionId: "your-action-id",
  taskOptions: {
    pollInterval: 2000,
    timeout: 120000,
  },
});

Private Download

For private files (identical call, but the auth signature restricts access):

const stream = await client.Cascade.downloader.downloadPrivate(actionId);

SN-API Fallback

The SN-API client attempts versioned endpoints first (/api/v1/...), then falls back to legacy paths (/api/...) on 404. This ensures compatibility across SN-API versions.

Next Steps

On this page