Skip to content

Post signed data to Arweave

This guide is in typescript.

Background

A transaction can upload data onto Arweave. To upload data using Liteseed Network you need to sign data into a special format called a Data-Item. These data-items are batched together into a single transaction called a bundle and posted to Arweave. Learn more about data-items & bundles here: ANS-104: Bundled Data v2.0 - Binary Serialization.

Installing the required packages

This tutorial requires some packages to make uploading data easier.

Terminal window
npm install arweave arbundles

arweave is the official js library for interacting with the Arweave library.

arbundles is the recommended library for converting data into data-item.

Uploading the Data

Uploading has 4 steps:

  1. Signing Data
  2. Posting the signed data to Liteseed
  3. Paying the upload transaction fee
  4. Notifying the network of the payment

1. Signing Data

Use an arweave wallet jwk to sign the data.

async function signData(data: Uint8Array | string, jwk: any): Promise<DataItem> {
const signer = new ArweaveSigner(jwk);
const dataItem = await createData(data, signer);
await dataItem.sign(signer);
return dataItem;
}

2. Posting the signed data to the API

The signed data is sent to the API using a post request. The request expects a header "application/octet-stream" and the size of the data-item.

type Receipt = {
id: string;
dataCaches: string[];
fastFinalityIndexes: string[];
deadlineHeight: number;
owner: string;
version: string;
}
async function postData(dataItem: DataItem, size: number): Promise<Receipt> {
const response = await fetch(`https://api.liteseed.xyz/tx`, {
method: "POST",
body: dataItem.getRaw(),
headers: {"content-length": size.toString(), "content-type": "application/octet-stream"}
});
const receipt = await response.json();
console.log("Receipt", receipt);
return receipt;
}

The response would look something like this

{
"id": "vclUklCqp6mTOoCZjkqcD2m06VRhnKtwVNSfMOPV7SM",
"dataCaches": ["api.liteseed.xyz"],
"fastFinalityIndexes": ["api.liteseed.xyz"],
"deadlineHeight": 1460374,
"owner": "...",
"version": "1.0.0"
}

Store the id in a database, so you can query your data later easily.

3. Paying the Upload Transaction Fee

Check the price of the upload and create a transaction to pay for the upload.

async function sendPayment(size: number, jwk: any) {
const arweave = Arweave.init({});
const response = await fetch(`https://api.liteseed.xyz/price/${size}`);
const {price, address} = await response.json();
console.log("Price in AR", price); // Price of upload
console.log("Address to pay", address); // The wallet to pay
const tx = await arweave.createTransaction({quantity: price, target: address}, jwk);
await arweave.transactions.sign(tx, jwk);
await arweave.transactions.post(tx);
console.log("Transaction Id", tx.id);
return tx;
}

4. Notify network of the payment

Next, you need let the network know of the payment. Once the payment is confirmed (approximately >20 blocks on Arweave are mined), the data is posted to Arweave in a bundle.

async function notifyNetwork(id: string, paymentId: string) {
const response = await fetch(`https://api.liteseed.xyz/tx/${id}/${paymentId}`, {method: "PUT"});
const payment = await response.json();
console.log("Payment", payment);
}

The Complete Example

import { ArweaveSigner, createData, type DataItem } from "arbundles/node";
import Arweave from "arweave";
import {readFileSync} from "fs";
type Receipt = {
id: string;
dataCaches: string[];
fastFinalityIndexes: string[];
deadlineHeight: number;
owner: string;
version: string;
};
async function signData(data: Uint8Array | string, jwk: any): Promise<DataItem> {
const signer = new ArweaveSigner(jwk);
const dataItem = await createData(data, signer);
await dataItem.sign(signer);
return dataItem;
}
async function postData(dataItem: DataItem): Promise<Receipt> {
const size = dataItem.getRaw().length;
const response = await fetch(`https://api.liteseed.xyz/tx`, {
method: "POST",
body: dataItem.getRaw(),
headers: {"content-length": size.toString(), "content-type": "application/octet-stream"}
});
const receipt = await response.json();
console.log("Receipt", receipt);
return receipt;
}
async function sendPayment(size: number, jwk: any) {
const arweave = Arweave.init({});
const response = await fetch(`https://api.liteseed.xyz/price/${size}`);
const {price, address} = await response.json();
console.log("Price in AR", price); // Price of upload
console.log("Address to pay", address); // The wallet to pay
const tx = await arweave.createTransaction({quantity: price, target: address}, jwk);
await arweave.transactions.sign(tx, jwk);
await arweave.transactions.post(tx);
console.log("Transaction Id", tx.id);
return tx;
}
async function notifyNetwork(id: string, paymentId: string) {
const response = await fetch(`https://api.liteseed.xyz/tx/${id}/${paymentId}`, {method: "PUT"});
const payment = await response.json();
console.log("Payment", payment);
}
async function upload() {
const file: File = readFileSync("file.jpeg");
const jwk = JSON.parse(readFileSync("jwk.json"));
const data = new Uint8Array(await file.arrayBuffer());
const dataItem = await signData(data, jwk);
const size = dataItem.getRaw().length;
const receipt = await postData(dataItem);
const paymentId: string = await sendPayment(size, jwk);
await notifyNetwork(receipt.id, paymentId);
}
upload();