@flipflop-sdk/node
Version:
FlipFlop Node.js SDK for programmatic token operations
227 lines • 8.23 kB
JavaScript
;
/**
* Update name, symbol and image to irys to get metadata uri
* This module handles the complete metadata upload process:
* 1. Validate image file type and size
* 2. Upload image to Irys network
* 3. Create metadata JSON with image URL and token info
* 4. Upload metadata JSON to Irys network
* 5. Return final metadata URL
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateMetadataUri = exports.getMimeType = exports.createAndUploadMetadata = exports.uploadToStorage = exports.validateImageFile = void 0;
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const axios_1 = __importDefault(require("axios"));
const form_data_1 = __importDefault(require("form-data"));
const config_1 = require("./config");
// Constants based on frontend configuration
const VALID_IMAGE_TYPES = [
"image/jpeg",
"image/jpg",
"image/png",
"image/gif",
"image/webp",
"image/avif",
];
const MAX_AVATAR_FILE_SIZE = 0.25 * 1024 * 1024; // 250KB
/**
* Validates image file type and size based on frontend validation logic
* @param imagePath Path to the image file
* @returns Object with validation result and error message if any
*/
const validateImageFile = (imagePath) => {
try {
// Check if file exists
if (!fs_1.default.existsSync(imagePath)) {
return { valid: false, error: "Image file does not exist" };
}
// Get file stats
const stats = fs_1.default.statSync(imagePath);
// Check file size (250KB limit)
if (stats.size > MAX_AVATAR_FILE_SIZE) {
return {
valid: false,
error: `Image size ${(stats.size / 1024 / 1024).toFixed(2)}MB exceeds limit of ${MAX_AVATAR_FILE_SIZE / 1024 / 1024}MB`,
};
}
// Check file type using extension and mime type detection
const extension = path_1.default.extname(imagePath).toLowerCase();
const mimeTypeMap = {
".jpg": "image/jpeg",
".jpeg": "image/jpeg",
".png": "image/png",
".gif": "image/gif",
".webp": "image/webp",
".avif": "image/avif",
};
const mimeType = mimeTypeMap[extension];
if (!mimeType || !VALID_IMAGE_TYPES.includes(mimeType)) {
return {
valid: false,
error: `Invalid image format. Supported formats: ${VALID_IMAGE_TYPES.join(", ")}`,
};
}
return { valid: true };
}
catch (error) {
return {
valid: false,
error: `Error validating image: ${error instanceof Error ? error.message : "Unknown error"}`,
};
}
};
exports.validateImageFile = validateImageFile;
/**
* Uploads file to Irys network
* @param filePath Path to the file to upload
* @param action Type of upload (avatar, banner, metadata)
* @returns Promise resolving to the uploaded file URL
*/
const uploadToStorage = async (config, filePath, action = "avatar") => {
const uploadApiUrl = `${config.apiBaseUrl}/api/irys/upload`;
try {
const formData = new form_data_1.default();
// Read file as buffer
const fileBuffer = fs_1.default.readFileSync(filePath);
const fileName = path_1.default.basename(filePath);
const mimeType = getMimeType(filePath);
formData.append("file", fileBuffer, {
filename: fileName,
contentType: mimeType,
});
formData.append("action", action);
const response = await axios_1.default.post(uploadApiUrl, formData, {
headers: {
...formData.getHeaders(),
},
});
if (response.data.status === "success") {
const itemId = response.data.fileInfo.itemId;
return `${config.irysGatewayUrl}/${itemId}`;
}
else {
throw new Error(`Upload failed: ${JSON.stringify(response.data)}`);
}
}
catch (error) {
console.error("Error uploading to storage:", error);
throw error;
}
};
exports.uploadToStorage = uploadToStorage;
/**
* Determines MIME type based on file extension
* @param filePath Path to the file
* @returns MIME type string
*/
const getMimeType = (filePath) => {
const extension = path_1.default.extname(filePath).toLowerCase();
const mimeTypeMap = {
".jpg": "image/jpeg",
".jpeg": "image/jpeg",
".png": "image/png",
".gif": "image/gif",
".webp": "image/webp",
".avif": "image/avif",
".json": "application/json",
};
return mimeTypeMap[extension] || "application/octet-stream";
};
exports.getMimeType = getMimeType;
/**
* Creates metadata JSON object and uploads it to Irys
* @param params Metadata parameters
* @param imageUrl URL of the uploaded image
* @returns Promise resolving to the metadata URL
*/
const createAndUploadMetadata = async (config, params, imageUrl) => {
const metadata = {
name: params.name,
symbol: params.symbol,
description: params.description === undefined ? "" : params.description,
image: imageUrl,
extensions: {
website: "",
twitter: "",
discord: "",
telegram: "",
github: "",
medium: "",
},
};
// Create temporary metadata file
const tempDir = path_1.default.join(process.cwd(), "temp");
if (!fs_1.default.existsSync(tempDir)) {
fs_1.default.mkdirSync(tempDir, { recursive: true });
}
const metadataPath = path_1.default.join(tempDir, "metadata.json");
fs_1.default.writeFileSync(metadataPath, JSON.stringify(metadata, null, 2));
try {
const metadataUrl = await uploadToStorage(config, metadataPath, "metadata");
// Clean up temporary file
fs_1.default.unlinkSync(metadataPath);
return metadataUrl;
}
catch (error) {
// Clean up on error
if (fs_1.default.existsSync(metadataPath)) {
fs_1.default.unlinkSync(metadataPath);
}
throw error;
}
};
exports.createAndUploadMetadata = createAndUploadMetadata;
/**
* Main function to generate metadata URI from command line parameters
* @param name Token name
* @param symbol Token symbol
* @param description Token description
* @param imagePath Path to the image file
* @returns Promise resolving to metadata upload result
*/
const generateMetadataUri = async (options) => {
try {
const config = config_1.CONFIGS[(0, config_1.getNetworkType)(options.rpc)];
// Step 1: Validate image file
// console.log('Step 1: Validating image file...');
const validation = validateImageFile(options.imagePath);
if (!validation.valid) {
return {
success: false,
message: validation.error,
};
}
// Step 2: Upload image to Irys
// console.log('Step 2: Uploading image to Irys network...');
const imageUrl = await uploadToStorage(config, options.imagePath, "avatar");
// console.log(`Image uploaded successfully: ${imageUrl}`);
// Step 3: Create and upload metadata
// console.log('Step 3: Creating and uploading metadata...');
const metadataUrl = await createAndUploadMetadata(config, {
name: options.name,
symbol: options.symbol,
description: options.description,
}, imageUrl);
// console.log(`Metadata uploaded successfully: ${metadataUrl}`);
return {
success: true,
data: {
imageUrl,
metadataUrl,
},
};
}
catch (error) {
console.error("Error generating metadata URI:", error);
return {
success: false,
message: error instanceof Error ? error.message : "Unknown error occurred",
};
}
};
exports.generateMetadataUri = generateMetadataUri;
//# sourceMappingURL=metadata.js.map