diff --git a/cli/src/lib/website/filesInit.ts b/cli/src/lib/website/filesInit.ts index 779e998..81498cd 100644 --- a/cli/src/lib/website/filesInit.ts +++ b/cli/src/lib/website/filesInit.ts @@ -10,23 +10,26 @@ import { strToBytes, U32, } from '@massalabs/massa-web3' + +import { + CallManager, + CallStatus, + CallUpdate, + FunctionCall, +} from '../utils/callManager' import { storageCostForEntry } from '../utils/storage' +import { maxBigInt } from '../utils/utils' +import { FileDelete } from './models/FileDelete' + import { FileInit } from './models/FileInit' import { Metadata } from './models/Metadata' + import { FILE_TAG, fileChunkCountKey, fileLocationKey, globalMetadataKey, } from './storageKeys' -import { FileDelete } from './models/FileDelete' -import { maxBigInt } from '../utils/utils' -import { - FunctionCall, - CallManager, - CallUpdate, - CallStatus, -} from '../utils/callManager' const functionName = 'filesInit' export const batchSize = 32 @@ -154,13 +157,19 @@ export async function sendFilesInits( // TODO: Improve estimation // - If a file is already stored, we don't need to send coins for its hash storage -export async function filesInitCost( +export async function prepareCost( _: SmartContract, files: FileInit[], filesToDelete: FileDelete[], metadatas: Metadata[], metadatasToDelete: Metadata[] -): Promise { +): Promise<{ + filePathListCost: bigint + storageCost: bigint + filesToDeleteCost: bigint + metadatasCost: bigint + metadatasToDeleteCost: bigint +}> { const filePathListCost = files.reduce((acc, chunk) => { return ( acc + @@ -211,6 +220,30 @@ export async function filesInitCost( ) }, 0n) + return { + filePathListCost, + storageCost, + filesToDeleteCost, + metadatasCost, + metadatasToDeleteCost, + } +} + +export async function filesInitCost( + _sc: SmartContract, + files: FileInit[], + filesToDelete: FileDelete[], + metadatas: Metadata[], + metadatasToDelete: Metadata[] +): Promise { + const { + filePathListCost, + storageCost, + filesToDeleteCost, + metadatasCost, + metadatasToDeleteCost, + } = await prepareCost(_sc, files, filesToDelete, metadatas, metadatasToDelete) + return BigInt( filePathListCost + storageCost + diff --git a/cli/src/tasks/prepareUpload.ts b/cli/src/tasks/prepareUpload.ts index bbe28a6..88c0b8f 100644 --- a/cli/src/tasks/prepareUpload.ts +++ b/cli/src/tasks/prepareUpload.ts @@ -5,6 +5,7 @@ import { ListrTask } from 'listr2' import { batchSize, filesInitCost, + prepareCost, sendFilesInits, } from '../lib/website/filesInit' import { LAST_UPDATE_KEY } from '../lib/website/metadata' @@ -20,8 +21,13 @@ export function prepareUploadTask(): ListrTask { return { title: 'Prepare upload', task: (ctx: UploadCtx, task) => { - if (ctx.fileInits.length === 0 && ctx.filesToDelete.length === 0) { - task.skip('All files are ready for upload') + if ( + ctx.fileInits.length === 0 && + ctx.filesToDelete.length === 0 && + ctx.metadatas.length === 0 && + ctx.metadatasToDelete.length === 0 + ) { + task.skip('All files are ready for upload, and no metadata changes') return } @@ -34,6 +40,19 @@ export function prepareUploadTask(): ListrTask { { title: 'Confirm SC preparation', task: async (ctx, subTask) => { + if ( + ctx.fileInits.length !== 0 || + ctx.filesToDelete.length !== 0 + ) { + subTask.output = 'Files changes detected' + } + if ( + ctx.metadatas.length !== 0 || + ctx.metadatasToDelete.length !== 0 + ) { + subTask.output = 'Metadata changes detected' + } + const totalChanges = ctx.fileInits.length + ctx.filesToDelete.length + @@ -41,15 +60,34 @@ export function prepareUploadTask(): ListrTask { ctx.metadatasToDelete.length const estimatedOperations = Math.ceil(totalChanges / batchSize) const minimalFees = ctx.minimalFees * BigInt(estimatedOperations) - const cost = - (await filesInitCost( - ctx.sc, - ctx.fileInits, - ctx.filesToDelete, - ctx.metadatas, - ctx.metadatasToDelete - )) + minimalFees - subTask.output = `SC preparation costs ${formatMas(cost)} MAS (including ${formatMas(minimalFees)} MAS of minimal fees)` + const { + filePathListCost, + storageCost, + filesToDeleteCost, + metadatasCost, + metadatasToDeleteCost, + } = await prepareCost( + ctx.sc, + ctx.fileInits, + ctx.filesToDelete, + ctx.metadatas, + ctx.metadatasToDelete + ) + + const totalCost = + filePathListCost + + storageCost - + filesToDeleteCost + + metadatasCost - + metadatasToDeleteCost + + subTask.output = `Estimated cost of SC preparation:` + subTask.output = ` + Files init: ${formatMas(filePathListCost)} MAS` + subTask.output = ` + Storage: ${formatMas(storageCost)} MAS` + subTask.output = ` - Files to delete: ${formatMas(filesToDeleteCost)} MAS` + subTask.output = ` + Metadatas: ${formatMas(metadatasCost)} MAS` + subTask.output = ` - Metadatas to delete: ${formatMas(metadatasToDeleteCost)} MAS` + subTask.output = `SC preparation costs ${formatMas(totalCost + minimalFees)} MAS (including ${formatMas(minimalFees)} MAS of minimal fees)` if (!ctx.skipConfirm) { const answer = await subTask