BVM
  • About bvm
    • Development infrastructure for Bitcoin
    • Follow our progress
  • getting started
    • Build a Bitcoin L2 with BVM Studio
    • Level up with Bitcoin dapps
    • Deploy your own Bitcoin dapp
  • L1 Scaling solutions
    • What are Bitcoin Shards? [WIP]
    • Compute sharding [WIP]
    • Data sharding [WIP]
    • Case studies [WIP]
      • SHARD_BVM
        • Bitcoin Virtual Machine #0
      • SHARD_DA [WIP]
      • SHARD_AI [WIP]
  • L2 Scaling solutions
    • What are Bitcoin rollups?
    • Optimistic rollups
    • ZK rollups
  • l3 scaling solutions
    • What are Bitcoin appchains?
    • Rollups from appchains to L2s
  • Bitcoin decentralized bridges
    • Bitcoin <> BVM bridge
    • Bitcoin <> Ethereum bridge [WIP]
    • Bitcoin <> Solana bridge [WIP]
  • bvm studio
    • Overview
    • Build a Bitcoin L2
    • Monitor a Bitcoin L2
    • Scale a Bitcoin L2
    • Building blocks
  • bitcoin heartbeats
    • Overview
    • Chain heartbeats
      • Key metrics
      • Bitcoin's 5 levels of scalability
    • Wallet heartbeats [WIP]
    • Dapp heartbeats [WIP]
  • bitcoin api
    • RaaS API
    • Chain API [WIP]
  • bitcoin dapps
    • Overview
    • EVM code tutorials
      • Build a Bitcoin Name System
      • Build an Ordinals alternative
      • BFS: Build an IPFS alternative
      • Decentralized AI
      • Auction
      • Decentralized Discord
      • Fully onchain Tic-Tac-Toe
      • BRC-721: NFTs
      • Operate your project using a DAO
      • Raise funds through a Crowdsale
      • Issue your own governance token
    • SVM code tutorials [WIP]
Powered by GitBook
On this page
  • Write the Trustless Discord smart contract
  • Clone the smart contract examples
  • Compile the contracts
  • Deploy the contracts
  • Interact with the contracts
  1. bitcoin dapps
  2. EVM code tutorials

Decentralized Discord

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: MIT
pragma solidity ^0.8.17;

contract Discord {

    struct Server {        
        address creator;
        string serverName;
    }
    
    struct Channel {        
        address creator;
        string serverName;
        string channelName;
    }
    
    struct Message {        
        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;

    function createServer(string memory _sname) public {
        require(keccak256(abi.encodePacked(servers[_sname].serverName)) == keccak256(abi.encodePacked("")), "The server name is existed already");
        servers[_sname] = Server(            
            msg.sender,
            _sname
        );
    }

    function joinServer(string memory _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;
    }

    function createChannel(string memory _sname, string memory _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
        );
    }

    function postMessage(string memory _sname, string memory _cname, string memory _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);        
    }

    function getMessages(string memory _sname, string memory _cname) public view returns (string memory, string memory, 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.

git clone https://github.com/trustlesscomputer/smart-contract-examples.git

Compile the contracts

To compile your contracts, use the built-in hardhat compile task.

cd smart-contract-examples
npm install
npx hardhat compile

Deploy the contracts

Review config file hardhat.config.ts. The network configs should look like this.

We'll deploy Trustless Discord on Layer 2, because it needs low latency.

  networks: {
    mynw: {
      url: "https://nos-testnet.trustless.computer/",
      accounts: {
        mnemonic: "<your mnemonic with funds>"
      },
      timeout: 100_000,
    },
    blockscoutVerify: {
      blockscoutURL: "https://explorer.nos-testnet.trustless.computer",
      ...
    }
  }

Run the deploy scripts using hardhat-deploy.

npx hardhat deploy --tags Discord

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 server
npx hardhat createServer --contract <your-contract-address> --sname server1

# join an existing server
npx hardhat joinServer --contract <your-contract-address> --sname server1

# create a new channel on an existing server
npx hardhat createChannel --contract <your-contract-address> --sname server1 --cname channel1

# post a message to a created channel
npx hardhat postMessage --contract <your-contract-address> --sname server1 --cname channel1 --message "The new Bitcoin city"

# get all messages from a channel
npx hardhat getMessages --contract <your-contract-address> --sname server1 --cname channel1
PreviousAuctionNextFully onchain Tic-Tac-Toe

Last updated 10 months ago