@wttp/site
Version:
Web3 Transfer Protocol (WTTP) - Site Contracts and deployment tools
241 lines ⢠10.3 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.uploadToArweave = uploadToArweave;
exports.uploadToArweaveStandalone = uploadToArweaveStandalone;
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const arweave_1 = __importDefault(require("arweave"));
const generateManifest_1 = require("./generateManifest");
/**
* Upload files marked for Arweave storage to Arweave using official Arweave library
* Updates the manifest with actual Arweave transaction IDs
*
* @param manifestPath Path to the manifest file (will be updated in place)
* @param options Upload options including wallet and source path
* @returns Upload result with TXIDs
*/
async function uploadToArweave(manifestPath, options = {}) {
const { walletPath, wallet, sourcePath, uploadManifest = false } = options;
// Load manifest
if (!fs_1.default.existsSync(manifestPath)) {
throw new Error(`Manifest file not found: ${manifestPath}`);
}
const manifest = (0, generateManifest_1.loadManifest)(manifestPath);
// Determine source path
const baseSourcePath = sourcePath || path_1.default.dirname(manifestPath);
// Initialize Arweave
const arweave = arweave_1.default.init({
host: "arweave.net",
port: 443,
protocol: "https",
});
// Load wallet
let walletKey;
if (wallet) {
walletKey = wallet;
}
else if (walletPath) {
if (!fs_1.default.existsSync(walletPath)) {
throw new Error(`Arweave wallet file not found: ${walletPath}`);
}
walletKey = JSON.parse(fs_1.default.readFileSync(walletPath, "utf-8"));
}
else {
throw new Error("Either walletPath or wallet must be provided");
}
console.log(`š¦ Starting Arweave upload for manifest: ${manifestPath}`);
console.log(`š Source directory: ${baseSourcePath}`);
// Find files marked for Arweave storage
const arweaveFiles = manifest.siteData.files.filter((file) => file.externalStorage === "arweave");
if (arweaveFiles.length === 0) {
console.log(`ā¹ļø No files marked for Arweave storage in manifest`);
return {
filesUploaded: 0,
filesSkipped: 0,
txIds: new Map(),
};
}
console.log(`š Found ${arweaveFiles.length} files to upload to Arweave`);
const txIds = new Map();
let filesUploaded = 0;
let filesSkipped = 0;
// Upload each file
for (let i = 0; i < arweaveFiles.length; i++) {
const file = arweaveFiles[i];
// Check if already has a TXID (from previous upload)
const currentLocation = file.redirect?.location || "";
const existingTxId = currentLocation.replace(/^ar:\/\//, "").replace(/^arweave:\/\//, "");
if (existingTxId && existingTxId !== "[pending]" && existingTxId.length === 43) {
// Valid Arweave TXID format (43 characters base64url)
console.log(`āļø Skipping ${file.path} - already has TXID: ${existingTxId}`);
txIds.set(file.path, existingTxId);
filesSkipped++;
continue;
}
// Resolve file path
const fileRelativePath = file.path.replace(/^\.\//, "");
const fileAbsolutePath = path_1.default.join(baseSourcePath, fileRelativePath);
if (!fs_1.default.existsSync(fileAbsolutePath)) {
console.warn(`ā ļø File not found: ${fileAbsolutePath} - skipping`);
continue;
}
console.log(`\nš¤ Uploading ${i + 1}/${arweaveFiles.length}: ${file.path}`);
console.log(` Type: ${file.type}, Size: ${file.size} bytes`);
try {
// Read file data
const fileData = fs_1.default.readFileSync(fileAbsolutePath);
// Create transaction
const transaction = await arweave.createTransaction({
data: fileData,
});
// Add tags
transaction.addTag("Content-Type", file.type);
transaction.addTag("File-Path", file.path);
if (file.charset) {
transaction.addTag("Charset", file.charset);
}
// Sign transaction
await arweave.transactions.sign(transaction, walletKey);
// Post transaction
const uploader = await arweave.transactions.getUploader(transaction);
while (!uploader.isComplete) {
await uploader.uploadChunk();
console.log(` š¤ Upload progress: ${uploader.pctComplete}%`);
}
const txId = transaction.id;
console.log(` ā
Uploaded! TXID: ${txId}`);
// Update manifest
if (!file.redirect) {
file.redirect = {
code: 301,
location: `ar://${txId}`,
};
}
else {
file.redirect.location = `ar://${txId}`;
}
file.status = "uploaded";
txIds.set(file.path, txId);
filesUploaded++;
// Save manifest after each upload (in case of interruption)
(0, generateManifest_1.saveManifest)(manifest, manifestPath);
}
catch (error) {
console.error(` ā Failed to upload ${file.path}:`, error);
file.status = "error";
throw error;
}
}
// Save updated manifest
(0, generateManifest_1.saveManifest)(manifest, manifestPath);
console.log(`\nā
Arweave upload complete!`);
console.log(` Files uploaded: ${filesUploaded}`);
console.log(` Files skipped: ${filesSkipped}`);
let manifestTxId;
// Optionally upload the manifest itself
if (uploadManifest) {
console.log(`\nš¤ Uploading manifest to Arweave...`);
try {
const manifestData = JSON.stringify(manifest, null, 2);
const manifestBuffer = Buffer.from(manifestData, "utf-8");
// Create transaction for manifest
const manifestTransaction = await arweave.createTransaction({
data: manifestBuffer,
});
// Add tags
manifestTransaction.addTag("Content-Type", "application/json");
manifestTransaction.addTag("Manifest-Name", manifest.name);
manifestTransaction.addTag("Protocol", "wttp");
// Sign transaction
await arweave.transactions.sign(manifestTransaction, walletKey);
// Post transaction
const manifestUploader = await arweave.transactions.getUploader(manifestTransaction);
while (!manifestUploader.isComplete) {
await manifestUploader.uploadChunk();
console.log(` š¤ Upload progress: ${manifestUploader.pctComplete}%`);
}
manifestTxId = manifestTransaction.id;
console.log(` ā
Manifest uploaded! TXID: ${manifestTxId}`);
}
catch (error) {
console.error(` ā Failed to upload manifest:`, error);
}
}
return {
filesUploaded,
filesSkipped,
txIds,
manifestTxId,
};
}
/**
* Standalone function to upload files to Arweave (can be used outside Hardhat)
*
* @param manifestPathOrConfig Either a path to manifest file, or a ManifestConfig object
* @param sourcePath Source directory path (required if generating manifest)
* @param options Upload options
* @returns Upload result
*/
async function uploadToArweaveStandalone(manifestPathOrConfig, sourcePath, options = {}) {
const { generateManifestStandalone, saveManifest } = await Promise.resolve().then(() => __importStar(require("./generateManifest")));
let manifest;
let manifestPath;
if (typeof manifestPathOrConfig === "string") {
// Load existing manifest
manifestPath = manifestPathOrConfig;
manifest = (0, generateManifest_1.loadManifest)(manifestPath);
// Use source path from options or manifest directory
if (!options.sourcePath) {
options.sourcePath = path_1.default.dirname(manifestPath);
}
}
else {
// Generate manifest from config
if (!sourcePath) {
throw new Error("sourcePath is required when providing ManifestConfig");
}
const config = manifestPathOrConfig;
const outputPath = path_1.default.join(sourcePath, "wttp.manifest.json");
manifest = await generateManifestStandalone(sourcePath, "/", config);
manifestPath = saveManifest(manifest, outputPath);
options.sourcePath = sourcePath;
}
return uploadToArweave(manifestPath, options);
}
//# sourceMappingURL=uploadToArweave.js.map