以太坊实现简单的数据链上存储

工具:Truffle;Ganache;MetaMask

环境:Windows10

新建一个文件夹,命名为存储,在文件夹下执行如下命令:(相当于是下载一个webpack模板)

truffle unbox webpack

接着你会看到以下内容已经下载好了:

与单纯的执行Truffle初始化操作不同,在这里多了个APP文件夹,里面主要是前端代码(src中):


可以先看一下什么都不改的情况下这个模板是什么样子的:

然后发现报错了哈哈哈哈哈啊哈哈:(稍微改一下truffle-config中的内容)

 连接Ganache与Meta Mask,在migrate之后在进入App文件夹,执行:

npm run dev

接着打开浏览器,进入 http://localhost:8080/然后就会看到:

自带的合约就是铸币合约,就不演示了。


接下来尝试进行实现链上存储功能。 

首先在contracts文件夹下新建合约文件storage_.sol

内容如下:

pragma solidity >=0.4.21 <=0.9.0;

contract storage_ {
//数据结构
    struct Item {
        string what;//数据
        address who;//存数据的人(账户地址)
        uint when ;//时间
    }
//记录所有的数据
    Item[] private allWords;
//将数据存储在区块链上
    function save(string memory s, uint t) public {
        //每增加一条,就push到结构体中
        allWords.push(Item({
            what: s,
            who: msg.sender,
            when: t
        }));
    }
//查询当前数据的总条数
    function getSize() public view returns (uint){
        return allWords.length;
    }
//根据编号查询数据的具体内容
//random为编号
    function getRandom(uint random) public view returns (string memory, address, uint) {
        if(allWords.length==0){
            return ("", msg.sender, 0);
        }else{
            Item storage result = allWords[random];
            return (result.what, result.who, result.when);
        }
    }
	function () payable external {
     
    }

}

主要包括存储函数和查询函数,所有人都可见。

magrations文件夹下的2_deploy_contracts.js文件修改为:

const storage_ = artifacts.require("storage_");
module.exports = function(deployer) {
  deployer.deploy(storage_);
};

这样智能合约部分就完成了,接下来看JavaScript部分。

index.js内容更改为如下:

import Web3 from "web3";
import metaCoinArtifact from "../../build/contracts/storage_.json";

const App = {
  web3: null,
  account: null,
  coin: null,
//连接以太坊
  start: async function() {
    const { web3 } = this;

    try {
      const networkId = await web3.eth.net.getId();
      const deployedNetwork = metaCoinArtifact.networks[networkId];
      this.meta = new web3.eth.Contract(
        metaCoinArtifact.abi,
        deployedNetwork.address,
      );

      const accounts = await web3.eth.getAccounts();
      this.account = accounts[0];

      //this.loadRandomWords();
    } catch (error) {
      console.error("Could not connect to contract or chain.");
    }
  },

  loadRandomWords: async function(number) {
    const { getRandom, getSize } = this.meta.methods;//.sol文件中的两个方法
    const count  = await getSize().call()//数据总条数count
    const msgEl = document.getElementById("msg")//
    if (count == 0){
      msgEl.innerHTML = "暂时没有内容"
    }else{
   var words ="共"+count+"条数据"+"<br /> ---------------------------------------------------------------------------------------------------------------------------------------------------<br />";
      for (var i=0;i<count;i++){
          var j=i+1;
          const word  = await getRandom(parseInt(i)).call();
          words = words 
              +"第"+j+"条"+"<br /> "
              
              +"内容:  "+word[0]
             
              +"<br />  来源:  "+word[1]
             
              +"<br />  时间:  "+ formatTime(word[2])
               
              +"<br /> ---------------------------------------------------------------------------------------------------------------------------------------------------<br />"
           }
        msgEl.innerHTML =words
          }
    
  },

  saveWord: async function() {
    const msg = document.getElementById("wordArea").value;
    if (msg.length == 0){
      alert("数据不能为空")
      return
    }

    let timestamp = new Date().getTime()
    const { save } = this.meta.methods;//.sol文件中的save方法
    await save(msg, parseInt(timestamp / 1000)).send({ from: this.account });

    //this.loadRandomWords();
  },
};
function formatNumber(n) {
  n = n.toString()
  return n[1] ? n : '0' + n
}

function formatTime(timestamp) {
  let date = new Date(Number(timestamp * 1000))
  let year = date.getFullYear()
  let month = date.getMonth() + 1
  let day = date.getDate()
  let hour = date.getHours()
  let minute = date.getMinutes()
  let second = date.getSeconds()
  let fDate = [year, month, day, ].map(formatNumber)
  return fDate[0] + '年' + fDate[1] + '月' + fDate[2] + '日' + ' ' + [hour, minute, second].map(formatNumber).join(':')
}
window.App = App;

window.addEventListener("load", function() {
  if (window.ethereum) {
    // use MetaMask's provider
    App.web3 = new Web3(window.ethereum);
    window.ethereum.enable(); // get permission to access accounts
  } else {
    console.warn(
      "No web3 detected. Falling back to http://127.0.0.1:9545. You should remove this fallback when you deploy live",
    );
    // fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)
    App.web3 = new Web3(
      new Web3.providers.HttpProvider("http://127.0.0.1:9545"),
    );
  }

  App.start();
});

再来看HTML:

index.html文件更改如下:

<!DOCTYPE html>
<html>
<head>
  <title>数据上链</title>
  <link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'>
  <link href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css' rel='stylesheet' type='text/css'>
</head>
<h1 style="background-color:rgb(166, 163, 252)">
     数    据
</h1>
<body class="container">
<br/>
<br/>
<textarea rows="3"  cols="100" id="wordArea"></textarea>
<br/>
<a href="#" onclick="App.saveWord()" class="btn btn-primary">上链</a>
<br/>
<br/>
---------------------------------------------------------------------------------------------------------------------------------------------------
<br/>
<br/>
<a href="#" onclick="App.loadRandomWords()" class="btn btn-primary">显示所有链上数据</a>
<div id="msg"></div>
<br/>

</body>
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js"></script>
<script src="index.js"></script>
</html>

接着就可以运行了,如图所示:

E:\DAPP\存储>truffle migrate --reset

Compiling your contracts...
===========================
> Compiling .\contracts\Migrations.sol
> Compiling .\contracts\storage_.sol
> Artifacts written to E:\DAPP\存储\build\contracts
> Compiled successfully using:
   - solc: 0.5.16+commit.9c3226ce.Emscripten.clang


Starting migrations...
======================
> Network name:    'development'
> Network id:      5777
> Block gas limit: 6721975 (0x6691b7)


1_initial_migration.js
======================

   Replacing 'Migrations'
   ----------------------
   > transaction hash:    0x6d8f1fcf259da54a4de08f446ccf3d9388113532b075eedfa60a87d0bb8bd213
   > Blocks: 0            Seconds: 0
   > contract address:    0xF8f84d69b825720cd7450f38655B4025F9a713f3
   > block number:        120
   > block timestamp:     1653055560
   > account:             0x840E940c19E56d8D93e0Ca650D7AE7a252172939
   > balance:             115.74797984
   > gas used:            164175 (0x2814f)
   > gas price:           20 gwei
   > value sent:          0 ETH
   > total cost:          0.0032835 ETH

   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:           0.0032835 ETH


2_deploy_contracts.js
=====================

   Deploying 'storage_'
   --------------------
   > transaction hash:    0xc8c551c8480c8347b5807ad0742a3e898d1d1c519629709496311582a808f615
   > Blocks: 0            Seconds: 0
   > contract address:    0xebfb7eE1f79468cec97B07498e0239c9f9Ba560c
   > block number:        122
   > block timestamp:     1653055561
   > account:             0x840E940c19E56d8D93e0Ca650D7AE7a252172939
   > balance:             115.7405039
   > gas used:            331456 (0x50ec0)
   > gas price:           20 gwei
   > value sent:          0 ETH
   > total cost:          0.00662912 ETH

   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:          0.00662912 ETH

Summary
=======
> Total deployments:   2
> Final cost:          0.00991262 ETH

接着打开浏览器,进入 http://localhost:8080/

 (有点丑,不要介意,能说明功能就行了)

在连接MetaMask的情况下,可以输入内容,然后点击上链,结果如下所示:

参考书籍:《精通以太坊智能合约开发》熊丽兵编著.北京电子工业出版社,2018

END 

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要搭建本地以太坊私链并连接钱包实现转账,需要以下步骤: 1. 安装Geth客户端 Geth是以太坊客户端软件,可以用于连接以太坊网络。可以从https://geth.ethereum.org/downloads/下载Geth安装包并安装。 2. 创建创世块 在创建私链之前,需要先创建创世块。可以使用Puppeth工具来创建创世块,该工具可以从https://github.com/ethereum/go-ethereum/releases下载。使用Puppeth可以选择网络ID、区块时间、初始难度等选项,并生成创世块配置文件。 3. 初始化私链 使用以下命令来初始化私链: ``` geth --datadir /path/to/chaindata init /path/to/genesis.json ``` 其中,/path/to/chaindata为私链数据存储路径,/path/to/genesis.json为创世块配置文件路径。执行该命令后,私链数据存储路径下会生成相应的数据文件。 4. 启动私链 使用以下命令来启动私链: ``` geth --datadir /path/to/chaindata --networkid 1234 --rpc --rpcport "8545" --rpcaddr "127.0.0.1" --rpccorsdomain "*" --rpcapi "eth,net,web3,personal" --nodiscover console ``` 其中,/path/to/chaindata为私链数据存储路径,--networkid为私链的网络ID,--rpc为启用RPC服务,--rpcport为RPC服务端口,--rpcaddr为RPC服务IP地址,--rpccorsdomain为跨域访问配置,--rpcapi为RPC接口配置,--nodiscover为禁用节点发现。执行该命令后,会启动私链节点并进入控制台。 5. 创建钱包 在私链节点控制台中,使用以下命令来创建钱包: ``` personal.newAccount() ``` 执行该命令后,会提示输入密码,并返回钱包地址。 6. 解锁钱包 使用以下命令来解锁钱包: ``` personal.unlockAccount("钱包地址", "密码", 0) ``` 其中,"钱包地址"为钱包地址,"密码"为钱包密码,0为解锁时长,表示永久解锁。执行该命令后,会返回true表示解锁成功。 7. 转账 在私链节点控制台中,使用以下命令来转账: ``` eth.sendTransaction({from: "发送方钱包地址", to: "接收方钱包地址", value: web3.toWei(1, "ether")}) ``` 其中,"发送方钱包地址"为发送方钱包地址,"接收方钱包地址"为接收方钱包地址,web3.toWei(1, "ether")为转账金额,表示1个以太币。执行该命令后,会返回交易哈希值。 8. 查询余额 使用以下命令来查询钱包余额: ``` eth.getBalance("钱包地址") ``` 其中,"钱包地址"为钱包地址。执行该命令后,会返回钱包余额。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值