Solidity的CURD

相关工具

Solidity:https://github.com/ethereum/solidity
Web3.js:https://github.com/ethereum/web3.js
Geth:https://github.com/ethereum/go-ethereum
Mist:https://github.com/ethereum/mist
Remix:https://remix.ethereum.org/

Solidity是以太坊开发智能合约的高级语言,采用面向对象的开发方式,有一套自己的语法体系,是图灵完备的。

Web3.js是基于javascript的调用智能合约的类库。之前还可以编译和部署智能合约,不过现在已经废除了,暂时还没有找到更好的替代方式,本文是采用mist客户端进行编译和部署的,然后再通过web3.js进行调用。

Geth是以太坊客户端,可以用来挖矿,也可以搭建私有的以太坊环境。

Mist是以太坊的钱包工具,可以进行转账交易和智能合约的开发。

Remix是Solidity语言的基于Web的IDE,代码编写以及错误调试非常方便,一般在Remix调试没有问题之后,在通过Mist进行发布。另外,在没有搭建私链的环境是,可以结合chrom的浏览器扩展metamask,在测试链上进行开发。

私链环境搭建

Geth搭建以太坊私链环境:http://blog.csdn.net/koastal/article/details/78737543

搭建以太坊私有链多节点环境:http://blog.csdn.net/koastal/article/details/78749211

智能合约

  1. 利用struct存储用户的属性,这里只写了姓名和年龄。
  2. 利用mapping存储uidstruct的映射关系。
  3. 利用array存储uid,也就是作为“数据库的索引”。
  4. 插入操作成功之后,用户获得一个自增的uid,也就是IdList中的最大值+1的结果。
  5. 更新和删除都是通过uid找到该用户记录,然后操作。
  6. 插入、更新和删除都属于写操作,需要调用者支付费用(Gas)。
  7. 写操作都定义了相关的事件,在操作成功之后调用事件。
pragma solidity ^0.4.6;
contract UserCurd {
    struct UserStruct {
        string name;
        uint age;
    }
    mapping(uint => UserStruct) private UserStructs;
    uint[] private IdList;
    event InsertEvent(uint uid,string name,uint age);
    event UpdateEvent(uint uid,string name,uint age);
    event DeleteEvent(uint uid);
    //插入操作
    function insertUser(string name,uint age) public returns(uint uid){
        uint length = IdList.length;
        uint id;
        if(length == 0){
            id = 1;
        }else{
            uint lastId = IdList[length-1];
            id = lastId+1;
        }
        IdList.push(id);
        uid = IdList.length;
        UserStructs[id].name = name;
        UserStructs[id].age = age;
        InsertEvent(uid,name,age);  //插入成功,触发插入事件
        return uid;
    }
    //查询操作
    function getUser(uint uid) public view returns(uint retUid,string retName, uint retAge){
        require(isExist(uid) > -1);
        return (uid,UserStructs[uid].name,UserStructs[uid].age);
    }
    function getUidList() public view returns(uint[]){
        return IdList;
    }
    function isExist(uint uid) public view returns(int){
        if(IdList.length == 0) return -1;
        for(uint i=0;i<IdList.length;i++){
            if(IdList[i] == uid) return int(i);
        }
        return -1;
    }
    //更新操作
    function updateUser(uint uid,string name,uint age) public returns(bool){
        if(isExist(uid) < 0) return false;
        UserStructs[uid].name = name;
        UserStructs[uid].age = age;
        UpdateEvent(uid,name,age);  //更新成功,触发更新事件
        return true;
    }
    //删除操作
    function deleteUser(uint uid) public returns(bool){
        int index = isExist(uid);
        if(index < 0) return false;
        delete UserStructs[uid];
        for(uint i= uint(index);i<IdList.length-1;i++){
            IdList[i] = IdList[i+1];
        }
        IdList.length--;
        DeleteEvent(uid); //删除成功,触发更新事件
        return true;
    }
}

合约部署成功之后的mist界面
这里写图片描述

web3.js调用

调用智能合约需要知道合约的地址和ABI,如果进行写入操作的话,还需要一个有充足以太币的账户为写入操作进行付费。

let Web3 = require("web3");
let fs = require("fs");
let web3 = new Web3();
web3.setProvider(new Web3.providers.HttpProvider("http://192.168.1.11:8545"));
let address = "0x61C64CE900236575F2212D7346c12BE9d1e9002d";
let abi = JSON.parse(fs.readFileSync("./solidity/UserCurd.abi").toString("utf8"));
let MyContract = web3.eth.contract(abi);
let contractInstance = MyContract.at(address);

//查询用户
function  listUser() {
    let list = contractInstance.getUidList();
    let uids = [];
    for(let obj of list){
        uids.push(obj.c[0]);
    }
    let userList = [];
    for(let uid of uids){
        let res = contractInstance.getUser(uid);
        let name = res[1].replace(/"/g,'');
        let age = res[2].c[0];
        userList.push({
            uid : uid,
            name : name,
            age : age
        });
    }
    console.log("User List:");
    console.log(userList);
}

//添加用户
function insertUser(name,age) {
    name = name || "default";
    age = age || 1;
    let coinbase = "0x8a1C505f1ff14045c03622E9ab82EB19c730cef3";
    web3.personal.unlockAccount(coinbase, "coinbase", 500);
    contractInstance.insertUser(name,age, {from: coinbase, gas: 1000000});
    let myEvent = contractInstance.InsertEvent();
    myEvent.watch(function (err,result) {
        if(err){
            console.log("Insert Error:");
            console.log(err);
        }else{
           console.log(result);
           listUser();
        }
    })
}

//删除用户
function deleteUser(uid) {
    uid = parseInt(uid);
    if(uid <= 0) return false;
    let coinbase = "0x8a1C505f1ff14045c03622E9ab82EB19c730cef3";
    web3.personal.unlockAccount(coinbase, "coinbase", 500);
    contractInstance.deleteUser(uid, {from: coinbase, gas: 1000000});
    let myEvent = contractInstance.DeleteEvent();
    myEvent.watch(function (err,result) {
        if(err){
            console.log("Delete Error:");
            console.log(err);
        }else{
            console.log(result);
            listUser();
        }
    })
}

//修改用户
function updateUser(uid,name,age) {
    uid = parseInt(uid);
    name = name || "default";
    age = age || 1;
    if(uid <= 0) return false;
    let coinbase = "0x8a1C505f1ff14045c03622E9ab82EB19c730cef3";
    web3.personal.unlockAccount(coinbase, "coinbase", 500);
    contractInstance.updateUser(uid,name,age, {from: coinbase, gas: 1000000});
    let myEvent = contractInstance.UpdateEvent();
    myEvent.watch(function (err,result) {
        if(err){
            console.log("Update Error:");
            console.log(err);
        }else{
            console.log(result);
            listUser();
        }
    })
}

读取操作

因为是刚部署的合约,用户列表是空的
读取用户列表

listUser();

写入操作

首先需要在私链中开启挖矿,因为对智能合约的写入操作,也是一笔交易,需要有矿工挖矿打包才能完成。

minner.start()

插入用户

insertUser("one",101);
insertUser("two",12);

我们插入两个用户,就发生了两笔交易,在私链挖矿节点能够看到
这里写图片描述
并且在web3.js监听的event中,也可以获取交易的具体信息

{ address: '0x61c64ce900236575f2212d7346c12be9d1e9002d',
  blockNumber: 6329,
  transactionHash: '0xe01c9434fb832863e2c2cc402eafa38822628483a1d18a29f95648479042e6d6',
  transactionIndex: 0,
  blockHash: '0xb83ef6bd21c2d07ebf0e36cfa066b9350178d3a99f964f5fdc51b781fc9238ad',
  logIndex: 0,
  removed: false,
  event: 'InsertEvent',
  args: 
   { uid: { [String: '1'] s: 1, e: 0, c: [Object] },
     name: 'one',
     age: { [String: '101'] s: 1, e: 2, c: [Object] }
   }
}

更新用户

updateUser(1,"one",11);

删除用户

deleteUser(1);

项目的github地址:

https://github.com/qianshou/Solidity-CURD/tree/master

参考资料:

https://bitbucket.org/rhitchens2/soliditycrud
http://blog.csdn.net/ddffr/article/details/73771940

猜你喜欢

转载自blog.csdn.net/koastal/article/details/78765101