Let's build Trustless Discord, a decentralized, unstoppable, and open messaging application.
create a new server
join an existing server
create a channel on an existing server
post a message to the created channel
get all messages posted to a channel
Write the Trustless Discord smart contract
It turns out that writing the Trustless Discord smart contract is very simple. Here is a basic contract to provide a decentralized social application.
// SPDX-License-Identifier: MITpragmasolidity ^0.8.17;contract Discord {structServer { address creator;string serverName; }structChannel { address creator;string serverName;string channelName; }structMessage { address sender;string message; }mapping(string=> Server) public servers;mapping(address=>mapping(string=>uint8)) public joinInfo;mapping(string=> Channel) public channels;mapping(string=>mapping(string=> Message[])) public messages;functioncreateServer(stringmemory_sname) public {require(keccak256(abi.encodePacked(servers[_sname].serverName)) ==keccak256(abi.encodePacked("")),"The server name is existed already"); servers[_sname] =Server( msg.sender, _sname ); }functionjoinServer(stringmemory_sname) public {require(keccak256(abi.encodePacked(_sname)) !=keccak256(abi.encodePacked("")),"Server name must be not empty");require(keccak256(abi.encodePacked(servers[_sname].serverName)) !=keccak256(abi.encodePacked("")),"The server name is not existed yet");require(joinInfo[msg.sender][_sname] ==0,"You have joined the server already"); joinInfo[msg.sender][_sname] =1; }functioncreateChannel(stringmemory_sname,stringmemory_cname) public {require(keccak256(abi.encodePacked(_sname)) !=keccak256(abi.encodePacked("")),"Server name must be not empty");require(keccak256(abi.encodePacked(_cname)) !=keccak256(abi.encodePacked("")),"Channel name must be not empty");require(keccak256(abi.encodePacked(servers[_sname].serverName)) !=keccak256(abi.encodePacked("")),"The server name is not existed yet"); channels[_cname] =Channel( msg.sender, servers[_sname].serverName, _cname ); }functionpostMessage(stringmemory_sname,stringmemory_cname,stringmemory_message) public {require(joinInfo[msg.sender][_sname] !=0,"You have not joined the server");require(keccak256(abi.encodePacked(channels[_cname].channelName)) !=keccak256(abi.encodePacked("")),"The channel is not existed yet"); Message memory newMsg =Message( msg.sender, _message ); messages[_sname][_cname].push(newMsg); }functiongetMessages(stringmemory_sname,stringmemory_cname) publicviewreturns (stringmemory,stringmemory,Message[] memory) {return (_sname, _cname, messages[_sname][_cname]); }}
Clone the smart contract examples
We've prepared a few different examples for you to get started. The Messenger example is located at smart-contract-examples/contracts/Discord.sol.
Make sure the accounts in hardhat.config.ts have some $BVM.
Interact with the contracts
Once the contracts are deployed, you can interact with them. We've prepared a few hardhat tasks to make it easy for you to interact with the contracts.
# create a new Discord servernpxhardhatcreateServer--contract<your-contract-address>--snameserver1# join an existing servernpxhardhatjoinServer--contract<your-contract-address>--snameserver1# create a new channel on an existing servernpxhardhatcreateChannel--contract<your-contract-address>--snameserver1--cnamechannel1# post a message to a created channelnpxhardhatpostMessage--contract<your-contract-address>--snameserver1--cnamechannel1--message"The new Bitcoin city"# get all messages from a channelnpxhardhatgetMessages--contract<your-contract-address>--snameserver1--cnamechannel1