Introduction and Problem Statement:

File sharing and data storage have exploded in the last 20 years reaching enormous valuation and market share.

Image

As we all know the modern world cannot work without Data Storage and sharing applications nevertheless they are heavily centralized and prone to data leaks. We want to attack that problem.

Additionally messaging systems and apps such as whatsapp, telegram, wechat, facebook messenger and so many others have become ubiquitous nowadays. And not only that, but businesses and individuals have become partially dependent on these and we trust them because of the number of people that use them. With more than 3.6 billion people worldwide and over 145 billion messages being sent every day.

Chart

This has brought forth stratospheric market valuations.

WhatsApp was acquired for $19 billion in 2014, Telegram has over 500 million users and rejected an investment offer at $30 billion. Skype was sold to Microsoft for $8.5 billion in 2011. And they will continue growing at a rate of 10% per year by 2030.

But there's a huge privacy problem in regards to siloed enterprises controlling data. These are regarding several right’s violations mainly around privacy such as Data sharing violations like the fine of 266 million euros that Whattsapp received by the EU in September last year, Telegram’s constant issues with cyber theft mainly around bank accounts and quite a large number of cases of Blackmail. And private data leaks such as the one that happened through facebook in April 2021.

Graph

Nevertheless, messaging companies are still operating under practices that suggest data governance has not been solved.

Data is the most valuable resource an individual has and through blockchain technology this privacy issue can be quenched. We think that the way to launch a competitor is through the DeFi ecosystem as it is growing at an incredible rate and Serum is one of the premium platforms for that.

Our Solution:

FileD is a Decentralized chat application with document transfer capabilities and NFT services, while providing TradFi conveniences.

Diagram:

Image

Tech we Use:

How it's built:

EVMOS Network:

EVMOS

The EVMOS network was used to deploy all the contracts, both the contracts of all the NFTs and the main chat contract, in this case it was designed for its speed and low fees, making it easily scalable to carry out an effective chat.

To start the chat you must type the evmos account to start chat in Bech32 format

evmosXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

The chat contract allows us to attach any kind of text to our message, in our case we use the discord format to send the CID of the files and instructions about the messages.

Message

Hi!:file:QmdF4hz6Z7fQ9qNSQJVHRxqHDSFjEEcDdshqK8RZZgW9EN:filef::type:image/png:typef:

With this format, we can separate the message from what interests us, the text and thus display it on the display.

if (item.mess.indexOf(":req:") > -1) {
    delString1 = item.mess.substring(item.mess.indexOf
    (":req:"), item.mess.indexOf(":reqf:") + 6)
    req = parseFloat(delString1.replace(":req:", "").
    replace(":reqf:", ""))
}
if (item.mess.indexOf(":file:") > -1) {
    delString2 = item.mess.substring(item.mess.indexOf
    (":file:"), item.mess.indexOf(":filef:") + 7)
    file = IPFSgateway + delString2.replace(":file:", "").
    replace(":filef:", "")
    delString3 = item.mess.substring(item.mess.indexOf
    (":type:"), item.mess.indexOf(":typef:") + 7)
    type = delString3.replace(":type:", "").replace
    (":typef:", "")
}

Chainlink:

The prices feeds of our project are obtained with the following code and contract.

Code:

async getPriceFeed() {
    try {
        let contract = new ethers.Contract(priceFeed, abi3
        (), providerMatic);
        let priceAVAX = await contract.getLatestAVAXPrice();
        .
        .
        .
        let priceXRP = await contract.getLatestXRPPrice();

        let prices = {
        avax: parseFloat((priceAVAX).toString()) / 100000000,
        .
        .
        .
        xrp: parseFloat((priceXRP).toString()) / 100000000,
        }
        this.setState({
        prices: [
            epsilonRound(prices.avax),
            .
            .
            .
            epsilonRound(prices.xrp),
        ],
        })
    }
    catch {
        // nothing
    }
}

Contract Price Feeds: https://github.com/altaga/FileD-EVMOS/blob/main/Contract/PriceConsumerV3.sol

Filecoin and IPFS:

Filecoin-IPFS

Filecoin and IPFS are the core of our project since almost every part of it works thanks to a product made by the Filecoin community.

  • Explorer:

In the case of the explorer, the use of Chainsafe is essential, since with this we can obtain the CID of the contents that we have uploaded to chainsafe from our chat and, in turn, the files that we have uploaded from the explorer.

Explorer

However, in this case the important part is that the files received by the chat will in turn be added to our explorer, being content that we have as shared, above all we will be able to see the Shared files according to the conversation that we have active in the chat, to a larger organization.

async getSharedFiles(add1, add2) {
    let to = []
    let from = []
    try {
        to = await this.getFilesAsync(add1.toLowerCase())
    }
    catch {
        //nothing
    }
    try {
        from = await this.getFilesAsync(add2.toLowerCase
        ())
    }
    catch {
        //nothing
    }
    let tofrom = [].concat(to, from)
    let chatCID = this.state.messageHistory.map((item) => 
    htmlToCID(item.file))
    let temp = []
    for (let i = 0; i < tofrom.length; i++) {
        for (let j = 0; j < chatCID.length; j++) {
        if (tofrom[i].cid === chatCID[j]) {
            temp.push(tofrom[i])
        }
        }
    }
    this.setState({
        sharedFiles: removeDuplicates(temp)
    })
}
  • NFT Gallery:

All the gallery that we have in our project was completely made from our UI, since we already have the NFT.Storage API and the NFT Token smart contract integrated in the web page.

NFT-Gallery

In a simple way it is possible to create new NFTs on our platform, and even be able to create a complete collection from it, such as our limited edition Phanties.

async NFTstorageStore() {
    return new Promise((resolve, reject) => {
        var data = new FormData();
        data.append('meta', `{"name": "${this.state.
        nameNFT}","description":"${this.state.descNFT}"}
        `);
        data.append('image', this.state.fileNFT, this.
        state.fileNFT.name);
        var config = {
            method: 'post',
            url: 'https://api.nft.storage/store',
            headers: {
                'Authorization': 'Bearer 
                XXXXXXXXXXXXTOKENXXXXXXXXXX',
            },
            data: data
        };

        axios(config)
        .then((response) => {
            this.setState({
                cidNFT: response.data.value.url
            }, () => resolve(response.data.value.url))
        })
        .catch((error) => {
            reject(error);
        });
    })
}
  • Chat window:

Chat

Being able to send files from our chat window is possible thanks to the Chainsafe service (https://chainsafe.io/), since with its API's we can upload the files to IPFS directly, previously associating them to a folder, which in this case is the same address (this in order to save us the use of the database), and after this send the CID of the content to the recipient.

async uploadFile(address) {
    return new Promise((resolve, reject) => {
        var myData = new FormData();
        myData.append('file', this.state.file, this.state.
        file.name);
        myData.append('path', `${address}`);
        var config = {
            method: 'post',
            url: 'https://api.chainsafe.io/api/v1/bucket/
            BUCKET/upload',
            headers: {
            'Content-Type': 'multipart/form-data',
            'Accept': 'application/json',
            'Authorization': 'Bearer 
            XXXXXXXXXXXXTOKENXXXXXXXXXX'
        },
        data: myData
    };
    axios(config)
        .then((res) => resolve("Ok"))
        .catch((error) => {
        reject("Error")
        });
    })
}

In turn, we can easily obtain the list of files uploaded by this user thanks to its listing API.

getFiles(address) {
    var data = JSON.stringify({
        "path": address.toLowerCase()
    });
    var config = {
        method: 'post',
        url: 'https://api.chainsafe.io/api/v1/bucket/
        BUCKET/ls',
            headers: {
            'Content-Type': 'application/json',
            'Accept': 'application/json',
            'Authorization': 'Bearer 
            XXXXXXXXXXXXTOKENXXXXXXXXXX'
        },
        data: data
    };
    axios(config)
        .then((res) => this.setState({ files: res.data }))
        .catch((error) => { console.log(error) });
}

Valist:

Thanks to valist we have a more secure way to distribute our code in a decentralized way and at the same time be able to keep track of the versions of our code.

Valist

In this case during development we reached version 1.0.3

NOTE: The version of Valist does not support HTML tags like Image so the images in your post must be in the format that uses:

URL: https://app.valist.io/altaga-eth/file-d

Covalent:

Our application by requiring that we quickly look up the transactions of our Wallet and in turn if it has NFT's in it, we were able to find a way to do it efficiently from the Covalent API's.

Get Transactions:

async getTransactions(address) {
    return new Promise((resolve, reject) => {
        var config = {
            method: 'get',
            url: `https://api.covalenthq.com/v1/9001/
            address/${address}/transactions_v2/?key=$
            {process.env.REACT_APP_Covalent}`,
            headers: {}
        };
        axios(config)
            .then((response) => {
                resolve(response.data.data.items)
            })
            .catch((error) => {
                console.log(error);
                reject(error)
            });
    })
}

Get NFT's:

async syncNFT(address) {
    let contractsNFT = []
    let temp = await axios({
        method: 'get',
        url: `https://api.covalenthq.com/v1/80001/address/
        ${address}/balances_v2/?key=${process.env.
        REACT_APP_Covalent}&format=JSON&nft=true&
        no-nft-fetch=false`,
        headers: {
            'Accept': 'application/json'
        }
    })
    temp = temp.data.data.items.filter(item => item.type 
    === "nft");
    temp = temp.map(item => {
        return ({
            contractAddress: item.contract_address
        })
    })
    temp.forEach((item) => {
        if (item.contractAddress !== "") {
            contractsNFT.push(new ethers.Contract(item.
            contractAddress, abi2(), this.provider.
            getSigner()));
        }
    })
    let res = []
    for (let i = 0; i < contractsNFT.length; i++) {
        try {
            temp = await contractsNFT[i].tokenURI("0");
            temp = await fetch(ipfsTohtml(temp))
            temp = await temp.json()
            temp.image = ipfsTohtml2(temp.image ? temp.
            image : temp.file)
            temp.contract = contractsNFT[i]
            res.push(temp)
        }
        catch {
            // nothing
        }
    }
        if (this.state.nft.length !== res.length) {
            this.setState({
                nft: res
            })
        }
}

What's Next for FileD

Our intention was to create with Web3 tools and EVMOS a Proof of Concept of what a File sharing and chat application would look like in a decentralized way. Basically the only thing that is not on top of a Web3 tooling is actually the hosting, but that of course can be improved on. By the way everything is done on the EVMOS mainnet. For now we will try to improve on the aforementioned concepts and then we will tentatively launch it in a closed and controlled manner to keep iterating on it.

Built With

Share this project:

Updates