Cypherium Java 智能合约编程指南

代币就是数字货币,比特币、以太币就是一个代币。利用Cypherium的java智能合约可以轻松编写出属于自己的代币。这些代币是建立在区块链之上,代表你拥有并可转让给其他人的数字资产。现在我们就来看看怎样创建一个这样的代币。

准备工作:

  1. 下载示例代码。https://github.com/cypherium/ContractExample
    目录结构介绍:
├── client              //客户端
│   ├── cypher          //可执行文件cypher
│   ├── jdk             //Java Development Kit
│   ├── genesis.json    //初始化创世区块所需文件
│   ├── db              //自定义数据库目录
│   └── executable_file //可执行文件
│       ├── Linux 
│       │    └── cypher
│       ├── Mac 
│       │    └── cypher
│       └── Windows 
│            └── cypher
├── file2str            //class文件生成二进制字符串工具
│   ├── file2str.go     //go源码
│   ├── Linux  
│   │   └── file2str
│   ├── Mac  
│   │   └── file2str
│   └── Windows     
│       └── file2str.exe
└── src
    ├── HelloWorld.java //Java智能合约
    ├── index.html      //合约部署页面
    └── web3.js

接下来的操作步骤,默认在ContractExample/client目录执行。
请根据操作系统,把合适的可执行文件cypher,复制到client下,如:

cp executable_file/Mac/cypher ./
  1. 初始化节点的创世区块。datadir为自行指定的数据库目录,如db。
./cypher --datadir db init genesis.json
  1. 启动节点。
./build/bin/cypher --datadir db --networkid 123666 --port 7000 --rpcport 8000  --rpc --rpccorsdomain "*" --rpcaddr 0.0.0.0
  1. 启动节点的js交互窗口(用上一步成的ipc文件):
./cypher attach db/cypher.ipc
  1. 创建账户。
personal.newAccount("your password")
  1. 请联系我们,给您的测试账户中,转入一些可供测试的代币。邮箱地址:xxx
  2. 查看您的账户余额。
cph.getBalance("your account address")
  1. 您可以通过以下方法,把您账户中的资金转给其他账户。
cph.sendTransaction(from,to,value,gas,gasPrice,data,nonce,Function)
  • from: String - 指定的发送者的地址。
  • to: String - (可选)交易消息的目标地址,如果是合约创建,则不填。
  • value: Number|String|BigNumber - (可选)交易携带的货币量,以wei为单位。如果合约创建交易,则为初始的基金。
  • gas: Number|String|BigNumber - (可选)默认是自动,交易可使用的gas,未使用的gas会退回。
  • gasPrice: Number|String|BigNumber - (可选)默认是自动确定,交易的gas价格,默认是网络gas价格的平均值 。
  • data: String - (可选)或者包含相关数据的字节字符串,如果是合约创建,则是初始化要用到的代码。
  • nonce: Number - (可选)整数,使用此值,可以允许你覆盖你自己的相同nonce的,正在pending中的交易。
  • Function - 回调函数,用于支持异步的方式执行。
  1. 通过以下命令查看现在共识到第几个区块了。
cph.txBlockNumber

API

ERC20是以太坊定义的一个代币标准。要求我们在实现代币的时候必须要遵守的协议,如指定代币名称、总量、实现代币交易函数等,只有支持了协议才能被以太坊钱包支持。
Cypherium的代币标准接口如下:

package javax.cypher;

public final class Cypnet {
    /**
     * 设置代币信息。
     * @param symbol 代币符号
     * @param name 代币名称
     * @param totalSupply 发行代币总量
     * @param _owner 合约拥有者账户地址,传""空时,代表默认为创建者账户地址
     * @return
     */
    public static native boolean setTokenInfo(String symbol, String name, long totalSupply, String _owner);

    /**
     * 获取合约创建者的账户地址。
     * @param addressType can be "caller","self","owner" and other filter
     * @return
     */
    public static native String getAddress(String addressType); 

    /**
     * 查看对应账号的代币余额。
     * @param _address
     * @return
     */
    public static native long balanceOf(String _address);

    /**
     * 修改指定账户余额。
     * @param _from
     * @param _value
     * @return
     */
    public static native boolean changeBalance(String _from, long _value);

    /**
     * 实现代币交易
     * @param _from
     * @param _to
     * @param _value
     * @return
     */
    public static native boolean transfer(String _from, String _to, long _value);

    /**
     * 设置键值对。
     * @param _key
     * @param _value
     * @return
     */
    public static native boolean setState(String _key, String _value);

    /**
     * 通过键获取值。
     * @param _key
     * @return
     */
    public static native String getState(String _key);

    static {
    }
}

Create contract

现在我们来开始编写第一个Java智能合约,代码如下:

import javax.cypher.Cypnet;

public class HelloWorld {
    public static void main(String[] args) {
        long totalSupply = 10000;
        //我们创建一个 符号为Hello,名称为Hello world,发行总量为10000的代币。
        Cypnet.setTokenInfo("Hello", "Hello world", totalSupply, "");
        //把发行的代币全都给合约创建者
        Cypnet.changeBalance("caller", totalSupply);
        System.out.println("Hello");
    }

    public static String transfer(String _to, long _value) {
        long n = Cypnet.balanceOf("caller");
        if (n < _value) {
            //throw new Exception("Insufficient balance");
            return "Insufficient balance";
        }
        Cypnet.transfer("caller", _to, _value);
        return null;
    }

    public static String getValue(String skey) {
        String s = Cypnet.getState(skey);
        return s;
    }

    public static String setValue(String skey, String sValue) {
        Cypnet.setState(skey, sValue);
        return "ok";
    }
}

简单解释下,我们定义了一个名为HelloWorld的合约,main方法是Java应用程序的入口方法,导入Cypnet类。

Compile contract

  1. 我们来把HelloWorld.java编译成字节码文件HelloWorld.class。编译命令如下:
javac -cp jdk/classes ../src/HelloWorld.java
  1. file2str赋上权限。
chmod -R 777 ../file2str

3.根据操作系统,选择合适的file2str,将 HelloWorld.class文件转成16进制字符串的命令 file2str HelloWorld.class,如Mac版为:

../file2str/Mac/file2str ../src/HelloWorld.class

会看到生成的二进制字符串:

0xcafebabe00000036005a0a001a002d05000000000000271008002e08002f0800300a003100320800330a003100340800350800360a00310037090038003908003a0a003b003c0a0031003d0a0031003e08003f0a003100400800410800420a003b00430800440800450700460700470100063c696e69743e010003282956010004436f646501000f4c696e654e756d6265725461626c650100046d61696e010016285b4c6a6176612f6c616e672f537472696e673b29560100087472616e73666572010027284c6a6176612f6c616e672f537472696e673b4a294c6a6176612f6c616e672f537472696e673b01000d537461636b4d61705461626c6501000867657456616c7565010026284c6a6176612f6c616e672f537472696e673b294c6a6176612f6c616e672f537472696e673b01000873657456616c7565010038284c6a6176612f6c616e672f537472696e673b4c6a6176612f6c616e672f537472696e673b294c6a6176612f6c616e672f537472696e673b01000967657456616c75653101001428294c6a6176612f6c616e672f537472696e673b01000967657456616c75653201000a536f7572636546696c6501000f48656c6c6f576f726c642e6a6176610c001b001c01000548656c6c6f01000b48656c6c6f20776f726c640100000700480c0049004a01000663616c6c65720c004b004c0100047465737401001048656c6c6f20776f726c6420746573740c004d004e07004f0c0050005101001448656c6c6f20776f726c6420436f6e74726163740700520c005300540c005500250c00560057010014496e73756666696369656e742062616c616e63650c00210058010004414141410100026f6b0c0053005901000973647364736473646401000331303001000a48656c6c6f576f726c640100106a6176612f6c616e672f4f626a6563740100136a617661782f6379706865722f4379706e657401000c736574546f6b656e496e666f01003a284c6a6176612f6c616e672f537472696e673b4c6a6176612f6c616e672f537472696e673b4a4c6a6176612f6c616e672f537472696e673b295a01000d6368616e676542616c616e6365010016284c6a6176612f6c616e672f537472696e673b4a295a0100087365745374617465010027284c6a6176612f6c616e672f537472696e673b4c6a6176612f6c616e672f537472696e673b295a0100106a6176612f6c616e672f53797374656d0100036f75740100154c6a6176612f696f2f5072696e7453747265616d3b0100136a6176612f696f2f5072696e7453747265616d0100077072696e746c6e010015284c6a6176612f6c616e672f537472696e673b2956010008676574537461746501000962616c616e63654f66010015284c6a6176612f6c616e672f537472696e673b294a010028284c6a6176612f6c616e672f537472696e673b4c6a6176612f6c616e672f537472696e673b4a295a0100042849295600210019001a0000000000070001001b001c0001001d0000001d00010001000000052ab70001b100000001001e000000060001000000030009001f00200001001d00000068000500040000003414000240120412051f1206b800075712081fb8000957120a120bb8000c57b2000d120eb6000f120ab800104eb2000d2db6000fb100000001001e0000002200080000000500040008000f00090016000b001e000c0026000e002c000f003300100009002100220001001d0000007a00040006000000351208b80011370416041f949c00061212b012082a1fb8001357120ab800104eb2000d2db6000f1214b800104eb2000d2db6000f01b000000002001e0000002600090000001400070015000e0017001100190019001b001f001c0026001e002c001f003300210023000000070001fd001100040009002400250001001d0000002300010002000000072ab800104c2bb000000001001e0000000a000200000025000500260009002600270001001d0000002500020002000000092a2bb8000c571215b000000001001e0000000a0002000000290006002a0009002800290001001d0000004e0002000100000019033b1a112710a20010b2000d1ab60016840001a7ffef1217b000000002001e0000001600050000003e000200400009004100100042001600440023000000070002fc000201130009002a00290001001d0000001b00010000000000031218b000000001001e000000060001000000470001002b00000002002c
  1. 部署合约
    我们需要用Chrome浏览器打开部署调用页面ContractExample/src/index.html
    如下:

如果使用的是其他浏览器,直接打开会有跨域请求问题,所以需要使用http-server来部署该页面,需要自行先安装node和npm,再安装http-server,请依次执行以下命令:

npm install http-server -g 

pm i http-server

yarn -g http-server

进入到CypherTestNet/web3-cypher.js目录下,执行

http-server

用浏览器访问http://127.0.0.1:8080 把刚生成的二进制字符串粘到Java contract bytecode文本框。
在From Account账户有余额的情况下,点击Deploy按钮后,会把您的java合约部署到区块链中。并会弹出合约地址信息。



点击Get contract info按钮获取区块链中的合约信息。

在文本框中输入转账金额,并点击Transfer按钮,付款方就会向收款方转账。

点击From’s Balance按钮查看付款账户的余额。

点击To’s Balance按钮查看收款账户的余额。

View deploy contract page

接下来,我们来看看部署调用页面的流程。

  1. web3如何调用java方法
    ABI全称Application Binary Interface, 是调用智能合约函数以及合约之间函数调用的消息编码格式定义,也可以理解为智能合约函数调用的接口说明. 类似Webservice里的SOAP协议一样;也就是定义操作函数签名,参数编码,返回结果编码等。使用ABI协议时必须要求在编译时知道类型,即强类型相关.

如果想调用HelloWorld.java中的函数,需要把该函数追加到abi变量中,按照现有格式即可。比如说,我们想要调用HelloWorld.java中的getValue方法,就要把以下内容追加到abi变量中。

var abi=
...
,
{
        "constant":false,        //方法修饰符,false表示函数内可以修改状态变量
        "inputs":[               //方法入参,数组里的每个对象都是一个参数说明
            {
                "name":"skey",   //第一个参数的名字
                "type":"bytes32" //第一个参数的类型
            }
        ],
        "outputs":[              //方法返回值,数组里的每个对象都是一个参数说明
            {
                "name":"value",  //第一个参数的名字
                "type":"bytes32" //第一个参数的类型
            }
        ],
        "name":"getValue",       //方法名
        "payable":false,
        "stateMutability":"nonpayable",
        "type":"function"        //方法类型:function,constructor,fallback,event
    }
]

uint:M为integer类型代表M bits,0 < M <= 256, M % 8 == 0,如uint32,uint8,uint256。
int:同上。同为从8到256位的无符号整数。
uint和int:整型,分别是uint256和int256的别名。这也是上面的例子中函数参数类型是uint,转sha3码时要变成uint256的原因。
address:地址,20个字节,160bits,一个Ethereum地址,地址的类型也可以有成员作为所有合约的base。
bool:布尔类型,1个字节,true:1,false:0。
bytes:固定大小的字节数组,0<M<=32,byte都是bytes1的别名。
bytes:动态分配大小字节数组。不是一个值类型。
String:动态大小UTF8编码的字符串,不是一个值类型。
尽量少用string。
2. 如何发布合约
web3.js对合约的操作进行了封装。发布合约时,可以使用web3.cph.contract的new方法。
部署过程中需要主要的是,new方法的回调会执行两次,第一次是合约的交易创建完成,第二次是在某个地址上完成部署。需要注意的是只有在部署完成后,才能进行方法该用,否则会报错TypeError: javaContract.add is not a function。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值