Skip to content

Commit

Permalink
SC: Delete one, Multiple or Webiste files (#123)
Browse files Browse the repository at this point in the history
* add ChunkDelete Class

* add main and internal functions

* add unit tests

* add e2e tests

* update SC test structure

* clean helpers/index.ts

* edit remove file internal function

* clean test e2e

* rework delete functions

* update e2e

* improve unit test description

* add deleteWebsite fn

* add e2e test

* add deleteWebsite cli function

* fmt

---------

Co-authored-by: BenRey <br@massa.net>
  • Loading branch information
pivilartisant and Ben-Rey authored Sep 30, 2024
1 parent f783c79 commit ab97bec
Show file tree
Hide file tree
Showing 16 changed files with 598 additions and 84 deletions.
5 changes: 5 additions & 0 deletions cli/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Upload commands
`npm run build`
`SECRET_KEY=S...y node bin/index.js upload ./dist`

`npm run dev -- upload -w ./wallet_faker1.yaml -p faker1 ./dist`
56 changes: 46 additions & 10 deletions cli/src/commands/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import { Command } from '@commander-js/extra-typings'
import { SmartContract } from '@massalabs/massa-web3'

import { makeProviderFromNodeURLAndSecret } from './utils'
import { Listr, ListrTask } from 'listr2'
import { DeleteCtx } from '../tasks/tasks'

// Minimal implementation of delete command
export const deleteCommand = new Command('delete')
.alias('d')
.description('Delete the given website from Massa blockchain')
Expand All @@ -18,18 +21,51 @@ export const deleteCommand = new Command('delete')

const provider = await makeProviderFromNodeURLAndSecret(globalOptions)

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const sc = new SmartContract(provider, address)

console.error('deleteWebsite not implemented yet in the SC')
const ctx: DeleteCtx = {
provider: provider,
sc: sc,
address: address,
}

// No deleteWebsite in the SC yet
const tasks = new Listr(deleteWebsiteTask(), {
concurrent: false,
})

// sc.call('deleteWebsite', new Uint8Array())
// .then((result) => {
// console.log(result)
// })
// .catch((error) => {
// console.error(error)
// })
try {
await tasks.run(ctx)
} catch (error) {
console.error('Error during the process:', error)
process.exit(1)
}
})

export function deleteWebsiteTask(): ListrTask {
return {
title: 'Deleting website',
task: async (ctx) => {
// No deleteWebsite in the SC yet
await deleteWebsite(ctx)
},
rendererOptions: {
outputBar: Infinity,
persistentOutput: true,
collapseSubtasks: false,
},
}
}

async function deleteWebsite(ctx: DeleteCtx) {
if (!ctx.sc) {
throw new Error('Smart contract is not deployed yet')
}
ctx.sc
.call('deleteWebsite', new Uint8Array())
.then(() => {
console.log(`Successfully deleted the website at ${ctx.address}`)
})
.catch((error) => {
console.error(error)
})
}
2 changes: 1 addition & 1 deletion cli/src/commands/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { listFiles } from '../lib/website/read'
export const listFilesCommand = new Command('list')
.alias('ls')
.description('Lists files from the given website on Massa blockchain')
.option('-a, --address <address>', 'Address of the website to edit')
.option('-a, --address <address>', 'Address of the website to list')
.action(async (options, command) => {
const globalOptions = command.parent?.opts()

Expand Down
6 changes: 6 additions & 0 deletions cli/src/tasks/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,9 @@ export interface UploadCtx {
chunkSize: number
minimalFees: bigint
}

export interface DeleteCtx {
provider: Web3Provider
sc?: SmartContract
address: string
}
45 changes: 41 additions & 4 deletions smart-contract/assembly/__tests__/FileBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import { Args, stringToBytes } from '@massalabs/as-types';
import { sha256 } from '@massalabs/massa-as-sdk';
import { PreStore, ChunkPost, ChunkGet } from '../contracts/serializable/Chunk';
import {
PreStore,
ChunkPost,
ChunkGet,
ChunkDelete,
} from '../contracts/serializable/Chunk';
import {
preStoreFileChunks,
storeFileChunks,
getFilePathList,
getChunk,
deleteFiles,
deleteWebsite,
} from '../contracts/deweb-interface';
const limitChunk = 10240;

Expand Down Expand Up @@ -127,6 +134,16 @@ class FileBuilder {
return this;
}

deleteFiles(files: ChunkDelete[]): void {
deleteFiles(
new Args().addSerializableObjectArray<ChunkDelete>(files).serialize(),
);
}

deleteWebsite(): void {
deleteWebsite(new Args().serialize());
}

hasFiles(): void {
const fileList = new Args(getFilePathList()).next<string[]>().unwrap();
for (let i = 0; i < this.files.length; i++) {
Expand All @@ -136,16 +153,29 @@ class FileBuilder {
`File ${fileInfo.fileName} should be in the file list`,
);
for (let j = 0; j < fileInfo.data.length; j++) {
const storedChunk = getChunk(
new ChunkGet(fileInfo.fileNameHash, j).serialize(),
);
const storedChunk = getChunk(chunkGetArgs(fileInfo.fileNameHash, j));
assert(
storedChunk.length == fileInfo.data[j].length,
`Chunk ${j} of ${fileInfo.fileName} should have correct length`,
);
}
}
}

hasNoFiles(): void {
const fileList = new Args(getFilePathList()).next<string[]>().unwrap();
assert(fileList.length === 0, 'FileList should be empty');
}

fileIsDeleted(filePath: string): void {
const fileList = new Args(getFilePathList()).next<string[]>().unwrap();
for (let i = 0; i < fileList.length; i++) {
assert(
!fileList.includes(filePath),
`File ${filePath} should not be in the file list`,
);
}
}
}

export function given(): FileBuilder {
Expand All @@ -155,3 +185,10 @@ export function given(): FileBuilder {
export function checkThat(fileBuilder: FileBuilder): FileBuilder {
return fileBuilder;
}

export function chunkGetArgs(
filePathHash: StaticArray<u8>,
index: u32,
): StaticArray<u8> {
return new ChunkGet(filePathHash, index).serialize();
}
Loading

0 comments on commit ab97bec

Please sign in to comment.