代币就是数字货币,比特币、以太币就是一个代币。利用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
    如下:
    Cypherium Java 智能合约编程指南

如果使用的是其他浏览器,直接打开会有跨域请求问题,所以需要使用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合约部署到区块链中。并会弹出合约地址信息。

Cypherium Java 智能合约编程指南
Cypherium Java 智能合约编程指南
点击Get contract info按钮获取区块链中的合约信息。
Cypherium Java 智能合约编程指南
在文本框中输入转账金额,并点击Transfer按钮,付款方就会向收款方转账。
Cypherium Java 智能合约编程指南
点击From’s Balance按钮查看付款账户的余额。
Cypherium Java 智能合约编程指南
点击To’s Balance按钮查看收款账户的余额。
Cypherium Java 智能合约编程指南

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。

相关文章:

  • 2022-01-08
  • 2022-12-23
  • 2021-11-07
  • 2021-08-08
  • 2021-12-03
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2021-06-12
  • 2021-06-17
  • 2022-01-28
  • 2021-07-17
  • 2021-04-24
  • 2021-04-07
相关资源
相似解决方案