Skip to content

Upload a File

This Node.js example shows how to:

  1. POST a file to Liteseed
  2. Query the Arweave storage price
  3. Pay a blockchain transaction to finalize permanent storage
  4. Download the file once it’s live on Arweave

You’ll need an Arweave wallet key (JWK) and Node.js v14+.


Terminal window
npm install arweave form-data node-fetch

Note: In Node 18+ you can skip node-fetch since fetch is built-in.


upload-file.js
import fs from 'fs';
import Arweave from 'arweave';
import FormData from 'form-data';
// ——— CONFIG ———
const API_BASE = 'https://api.liteseed.xyz';
const KEY_PATH = './keyfile.json';
const FILE_PATH = './image.jpg';
// ——— HELPERS ———
// 1️⃣ POST the file to Liteseed
async function postFile(fileBuffer) {
const form = new FormData();
form.append('file', fileBuffer, { filename: 'image.jpg' });
const res = await fetch(`${API_BASE}/data`, {
method: 'POST',
body: form
});
if (!res.ok) throw new Error(`Upload failed: ${res.status}`);
return res.json(); // { id, dataCaches, ... }
}
// 2️⃣ GET price and payment address
async function getPrice(size) {
const res = await fetch(`${API_BASE}/price/${size}`);
if (!res.ok) throw new Error(`Price lookup failed`);
return res.json(); // { price: '0.0001234', address: '...' }
}
// 3️⃣ PAY on Arweave
async function payOnArweave(price, address, jwk) {
const ar = Arweave.init({ host: 'arweave.net', protocol: 'https' });
const tx = await ar.createTransaction({ target: address, quantity: price }, jwk);
await ar.transactions.sign(tx, jwk);
const res = await ar.transactions.post(tx);
if (res.status !== 200) throw new Error(`Arweave payment failed: ${res.status}`);
return tx.id;
}
// 4️⃣ UPDATE Liteseed with paymentId
async function confirmPayment(uploadId, paymentId) {
const res = await fetch(`${API_BASE}/tx/${uploadId}/${paymentId}`, { method: 'PUT' });
if (!res.ok) throw new Error(`Confirmation failed`);
return res.json();
}
// ——— MAIN FLOW ———
(async () => {
try {
const fileBuffer = fs.readFileSync(FILE_PATH);
const jwk = JSON.parse(fs.readFileSync(KEY_PATH, 'utf-8'));
const size = fileBuffer.length;
console.log('Uploading file…');
const { id: uploadId } = await postFile(fileBuffer);
console.log(`✔️ Upload ID: ${uploadId}`);
console.log('Fetching price…');
const { price, address } = await getPrice(size);
console.log(`Price: ${price} AR to ${address}`);
console.log('Paying on Arweave…');
const paymentId = await payOnArweave(price, address, jwk);
console.log(`✔️ Payment TX ID: ${paymentId}`);
console.log('Confirming with Liteseed…');
await confirmPayment(uploadId, paymentId);
console.log('🎉 File is now permanently stored on Arweave!');
} catch (err) {
console.error(err);
}
})();

Once your bundle is live on Arweave (usually within a few blocks), fetch it directly:

Terminal window
curl https://api.liteseed.xyz/data/<UploadID> \
-H 'Mime-Type: image/jpeg' \
-o downloaded.jpg

  • POST /data Uploads your file to Liteseed’s staging layer.
  • GET /price/:size Returns how much AR you need and where to send it.
  • PUT /tx/:uploadId/:paymentId Tells Liteseed to bundle your payment and push everything on-chain.

This pattern works for any file type—just adjust the Mime-Type when you download.