Skip to content
Pinner.xyz

Upload Progress & Events

pinner.upload() returns a Promise<UploadOperation> that gives you real-time progress, pause/resume control, and a promise that resolves when the upload finishes.

UploadOperation

const pinner = new Pinner({ jwt: "YOUR_JWT" });
 
const operation = await pinner.upload(file);
 
// Wait for the upload to finish
const result = await operation.result;
console.log("CID:", result.cid);
console.log("Operation ID:", result.operationId);
 
// Control the upload
operation.pause();   // toggles pause state (TUS uploads only)
operation.resume();  // toggles pause state (TUS uploads only)
operation.cancel();  // aborts the upload

UploadOperation API

MemberTypeDescription
resultPromise<UploadResult>Resolves with the CID, operation ID, and upload metadata
progressReadonly<UploadProgress>Snapshot of the current progress
cancel()() => voidAbort the upload
pause()() => voidToggle pause on a TUS upload
resume()() => voidToggle resume on a paused TUS upload

Progress events

Pass an onProgress callback in UploadOptions to get notified as bytes transfer:

const pinner = new Pinner({ jwt: "YOUR_JWT" });
 
const operation = await pinner.upload(file, {
  onProgress: (progress) => {
    console.log(`Progress: ${progress.percentage.toFixed(2)}%`);
    console.log(`Uploaded: ${progress.bytesUploaded} / ${progress.bytesTotal} bytes`);
    if (progress.speed != null) {
      console.log(`Speed: ${progress.speed} bytes/sec`);
    }
    if (progress.eta != null) {
      console.log(`ETA: ${progress.eta} seconds`);
    }
  }
});
 
const result = await operation.result;
console.log("Complete:", result.cid);

UploadProgress properties

PropertyTypeDescription
percentagenumberUpload progress from 0 to 100
bytesUploadednumberBytes transferred so far
bytesTotalnumberTotal bytes to transfer
speednumber | undefinedCurrent speed in bytes per second (optional)
etanumber | undefinedEstimated seconds remaining (optional)

Build a progress bar

Wire onProgress into any UI framework. A plain-DOM example:

const bar = document.getElementById("progress-bar");
 
const operation = await pinner.upload(file, {
  onProgress: (progress) => {
    bar.style.width = `${progress.percentage}%`;
    bar.textContent = `${progress.percentage.toFixed(0)}%`;
  }
});
 
const result = await operation.result;
bar.textContent = `Done: ${result.cid}`;

In React, store progress.percentage in state and render it the same way.

Cancel an upload

Call cancel() on the operation to abort an in-flight upload:

const operation = await pinner.upload(file);
 
// Some time later: user clicked "Cancel" or a timeout fired
operation.cancel();
 
try {
  await operation.result; // rejects after cancel
} catch (error) {
  console.log("Upload was cancelled");
}

After cancel(), the result promise rejects. Catch it to clean up UI state.

waitForOperation

Uploading is only the first step; the pin must also settle on the network. waitForOperation polls until the pin reaches a settled state.

const pinner = new Pinner({ jwt: "YOUR_JWT" });
 
const operation = await pinner.upload(file);
const uploadResult = await operation.result;
 
// Wait for pinning to complete
const result = await pinner.waitForOperation(uploadResult, {
  interval: 1000,   // poll every 1s
  timeout: 60000    // give up after 60s
});
 
console.log("CID:", result.cid);
console.log("Operation ID:", result.operationId);

Input types

waitForOperation accepts either an UploadResult or a numeric operation ID:

// Recommended: pass the full UploadResult
// Uses uploadResult.operationId if present, otherwise looks up by CID
const result = await pinner.waitForOperation(uploadResult);
 
// Also works: pass just the operation ID (number)
const result = await pinner.waitForOperation(uploadResult.operationId!);

Polling options

OptionTypeDefaultDescription
intervalnumber2000Polling interval in milliseconds
timeoutnumber300000Maximum wait time in milliseconds (5 minutes)
settledStatesstring[]["completed", "failed", "error"]States that count as settled

Next: Error Handling: classify and recover from SDK errors.