Facing promise error when uploading wasm file to the internet computer

in my app have rust backend and react frontend so want to be able to upload a wasm file upload the chunks and hash them to get wasm hash and upload wasm_chunks and hash dont know what i am doing wrong but in frontend getting error

index-6c91d4d2.js:62 Uncaught (in promise) Error: Invalid vec nat8 argument: {}


    at index-6c91d4d2.js:62:6456
    at index-6c91d4d2.js:52:16370
    at Array.map (<anonymous>)
    at zipWith (index-6c91d4d2.js:52:16359)
    at encode$1 (index-6c91d4d2.js:62:6397)
    at g (index-6c91d4d2.js:81:3543)
    at a.h [as create_release] (index-6c91d4d2.js:81:3954)
    at fA (index-6c91d4d2.js:81:6398)
    at Object.Nb (index-6c91d4d2.js:37:9858)
    at Tb (index-6c91d4d2.js:37:10016)

my backend code

use ic_cdk::export::candid::{CandidType, Deserialize};
use ic_cdk_macros::*;
use serde::Serialize;
use std::cell::RefCell;
use std::collections::BTreeMap;
use sha2::{Sha256, Digest};

#[derive(Clone, Debug, CandidType, Deserialize, Serialize)]
struct Release {
    id: String,
    version: String,
    features: String,
    wasm_file: Vec<u8>,
    wasm_hash: String,
}

thread_local! {
    static RELEASES: RefCell<BTreeMap<String, Release>> = RefCell::default();
}

fn hash_wasm_file(wasm_file: &[u8]) -> String {
    let mut hasher = Sha256::new();
    hasher.update(wasm_file);
    let result = hasher.finalize();
    format!("{:x}", result)
}

fn chunk_wasm_file(wasm_file: &[u8]) -> Vec<Vec<u8>> {
    let chunk_size = 1024 * 1024; // 1MiB
    let chunks = wasm_file
        .chunks(chunk_size)
        .map(|chunk| chunk.to_vec())
        .collect();
    chunks
}

#[update]
fn create_release(id: String, version: String, features: String, wasm_file: Vec<u8>) -> String {
    let chunks = chunk_wasm_file(&wasm_file); 
    let wasm_hash = hash_wasm_file(&wasm_file);
    for chunk in chunks {
    }
    let release = Release {
        id: id.clone(),
        version,
        features,
        wasm_file,
        wasm_hash,
    };
    RELEASES.with(|releases| {
        releases.borrow_mut().insert(id.clone(), release);
    });
    id
}

#[query]
fn get_release(release_id: String) -> Option<Release> {
    RELEASES.with(|releases| releases.borrow().get(&release_id).cloned())
}

#[update]
fn update_release(id: String, version: String, features: String, wasm_file: Vec<u8>) -> String {
    let chunks = chunk_wasm_file(&wasm_file); // Chunk the wasm file
    let wasm_hash = hash_wasm_file(&wasm_file); // Hash the wasm file
    for chunk in chunks {
        // Upload each chunk using the `upload_chunk` method
    }
    let release = Release {
        id: id.clone(),
        version,
        features,
        wasm_file,
        wasm_hash,
    };
    RELEASES.with(|releases| {
        releases.borrow_mut().insert(id.clone(), release);
    });
    id
}

#[update]
fn delete_release(release_id: String) -> String {
    RELEASES.with(|releases| {
        releases.borrow_mut().remove(&release_id);
    });
    "Release deleted".to_string()
}

#[query]
fn get_all_releases() -> Vec<Release> {
    RELEASES.with(|releases| releases.borrow().values().cloned().collect())
}


#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_create_and_get_release() {
        let id = "test".to_string();
        let version = "1.0.0".to_string();
        let features = "test features".to_string();
        let wasm_file = vec![1, 2, 3, 4, 5];

  
        let created_id = create_release(id.clone(), version.clone(), features.clone(), wasm_file.clone());
        assert_eq!(created_id, id);

 
        let release = get_release(id.clone()).unwrap();
        assert_eq!(release.id, id);
        assert_eq!(release.version, version);
        assert_eq!(release.features, features);
        assert_eq!(release.wasm_file, wasm_file);
    }

    #[test]
    fn test_update_release() {
        let id = "test".to_string();
        let version = "1.0.0".to_string();
        let features = "test features".to_string();
        let wasm_file = vec![1, 2, 3, 4, 5];

 
        create_release(id.clone(), version.clone(), features.clone(), wasm_file.clone());


        let updated_version = "1.0.1".to_string();
        let updated_id = update_release(id.clone(), updated_version.clone(), features.clone(), wasm_file.clone());
        assert_eq!(updated_id, id);


        let release = get_release(id.clone()).unwrap();
        assert_eq!(release.version, updated_version);
    }

    #[test]
    fn test_delete_release() {
        let id = "test".to_string();
        let version = "1.0.0".to_string();
        let features = "test features".to_string();
        let wasm_file = vec![1, 2, 3, 4, 5];

        create_release(id.clone(), version.clone(), features.clone(), wasm_file.clone());

        let message = delete_release(id.clone());
        assert_eq!(message, "Release deleted".to_string());

        let release = get_release(id.clone());
        assert!(release.is_none());
    }

    #[test]
    fn test_get_all_releases() {
        let id1 = "test1".to_string();
        let version1 = "1.0.0".to_string();
        let features1 = "test features 1".to_string();
        let wasm_file1 = vec![1, 2, 3, 4, 5];

        let id2 = "test2".to_string();
        let version2 = "1.0.0".to_string();
        let features2 = "test features 2".to_string();
        let wasm_file2 = vec![6, 7, 8, 9, 10];

        create_release(id1.clone(), version1.clone(), features1.clone(), wasm_file1.clone());
        create_release(id2.clone(), version2.clone(), features2.clone(), wasm_file2.clone());

        let releases = get_all_releases();
        assert_eq!(releases.len(), 2);
        assert!(releases.iter().any(|release| release.id == id1));
        assert!(releases.iter().any(|release| release.id == id2));
    }
}

my frontend

import { useState } from 'react';
import { addRelease_backend } from 'declarations/addRelease_backend';
import InputField from './InputField';

function App() {
    const [releaseId, setReleaseId] = useState('');
    const [version, setVersion] = useState('');
    const [features, setFeatures] = useState('');
    const [releases, setReleases] = useState([]);
    const [wasm_file, setWasm_file] = useState(null);

    function handleFileChange(file) {
        setWasm_file(file);
    }

    function handleCreate(event) {
        event.preventDefault();
        addRelease_backend.create_release(releaseId, version, features, wasm_file).then((id) => {
            setReleaseId(id);
        });
        return false;
    }





    function handleGet(event) {
        event.preventDefault();
        addRelease_backend.get_release(releaseId).then((release) => {
            setVersion(release.version);
            setFeatures(release.features);
        });
        return false;
    }

    function handleUpdate(event) {
        event.preventDefault();
        addRelease_backend.update_release(releaseId, version, features).then((id) => {
            setReleaseId(id);
        });
        return false;
    }


    function handleDelete(event) {
        event.preventDefault();
        addRelease_backend.delete_release(releaseId).then(() => {
            setReleaseId('');
            setVersion('');
            setFeatures('');
        });
        return false;
    }

    function handleGetAll(event) {
        event.preventDefault();
        addRelease_backend.get_all_releases().then((allReleases) => {
            setReleases(allReleases);
        });
        return false;
    }

    return (
        <main className="p-4">
            <img src="/logo2.svg" alt="DFINITY logo" />
            <br />
            <br />
            <form action="#" onSubmit={handleCreate} className="justify-center mx-auto flex space-y-5">
                <InputField
                    id="releaseId"
                    label="Release ID"
                    type="text"
                    onChange={(e) => setReleaseId(e.target.value)}
                />
                <InputField
                    id="version"
                    label="Release Version"
                    type="text"
                    onChange={(e) => setVersion(e.target.value)}
                />
                <InputField
                    id="features"
                    label="Features"
                    type="text"
                    onChange={(e) => setFeatures(e.target.value)}
                />
                <InputField
                    id="wasmFile"
                    label="Wasm File"
                    type="file"
                    onChange={(e) => handleFileChange(e.target.files[0])}
                />
            </form>
            <div className="flex space-x-4 justify-center mx-auto mt-10">
                <button onClick={handleCreate} className="bg-blue-500 text-white p-2 rounded hover:bg-blue-700">
                    Create Release
                </button>
                <button onClick={handleGet} className="bg-green-500 text-white p-2 rounded hover:bg-green-700">
                    Get Release
                </button>
                <button onClick={handleUpdate} className="bg-yellow-500 text-white p-2 rounded hover:bg-yellow-700">
                    Update Release
                </button>
                <button onClick={handleDelete} className="bg-red-500 text-white p-2 rounded hover:bg-red-700">
                    Delete Release
                </button>
                <button onClick={handleGetAll} className="bg-purple-500 text-white p-2 rounded hover:bg-purple-700">
                    Get All Releases
                </button>
            </div>
            <section id="releases" className="mt-4 justify-center mx-auto">
                {JSON.stringify(releases)}
            </section>
        </main>
    );
}

export default App;

What are you doing in the front end that makes you hit this error?

The error is related to a function expecting to receive an argument of type vec nat8. vec nat8 in Candid is equivalent to Vec<u8>.

The only backend function that requires an argument with type Vec<u8> is create_release. create_release requires a wasm_file which is of Vec<u8>.

Therefore, could you check that you are passing a valid wasm_file as a Vec<u8> type in create_release in the handleCreate function in the frontend?

function handleCreate(event) {
        event.preventDefault();
        addRelease_backend.create_release(releaseId, version, features, wasm_file).then((id) => {
            setReleaseId(id);
        });
        return false;
}

So in brief the app allows a user to upload a wasm file while creating a release this wasm files is chunked and the chunks are hashed to get wasm hash and the chunks are stored this is what i want to achieve

after using your handle create function getting sam error


index-fe97fb74.js:62 Uncaught (in promise) Error: Invalid vec nat8 argument: {}


    at index-fe97fb74.js:62:6456
    at index-fe97fb74.js:52:16370
    at Array.map (<anonymous>)
    at zipWith (index-fe97fb74.js:52:16359)
    at encode$1 (index-fe97fb74.js:62:6397)
    at g (index-fe97fb74.js:81:3543)
    at a.h [as create_release] (index-fe97fb74.js:81:3954)
    at fA (index-fe97fb74.js:81:6390)
    at Object.Nb (index-fe97fb74.js:37:9858)
    at Tb (index-fe97fb74.js:37:10016)

Have you confirmed the wasm file being passed of valid Vec<u8> type?