Edit me

English / 中文

Ontology Java SDK User Guide

Version 0.7.0

数字资产

数据结构说明

address 是base58编码的账户地址。 label 是账户的名称。 isDefault表明账户是否是默认的账户。默认值为false。 lock 表明账户是否是被用户锁住的。客户端不能消费掉被锁的账户中的资金。 algorithm 是加密算法名称。 parameters 是加密算法所需参数。 curve 是椭圆曲线的名称。 key 是NEP-2格式的私钥。该字段可以为null(对于只读地址或非标准地址)。 extra 是客户端存储额外信息的字段。该字段可以为null。

public class Account {
    public String label = "";
    public String address = "";
    public boolean isDefault = false;
    public boolean lock = false;
    public String algorithm = "";
    public Map parameters = new HashMap() ;
    public String key = "";
    public Object extra = null;
}

数字资产账户管理

  • 创建数字资产账号
String url = "http://127.0.0.1:20386";
OntSdk ontSdk = OntSdk.getInstance();
ontSdk.setRpcConnection(url);
ontSdk.openWalletFile("wallet.json");
Account acct = ontSdk.getWalletMgr().createAccount("password");
//创建的账号或身份只在内存中,如果要写入钱包文件,需调用写入接口
ontSdk.getWalletMgr().writeWallet();
  • 移除数字资产账号
ontSdk.getWalletMgr().getWallet().removeAccount(address);
//写入钱包 
ontSdk.getWalletMgr().writeWallet();
  • 设置默认数字资产账号
ontSdk.getWalletMgr().getWallet().setDefaultAccount(index);
ontSdk.getWalletMgr().getWallet().setDefaultAccount("address");

Note: index表示设置第index个account为默认账户,address表示设置该address对应的account为默认账户

原生数字资产

  • 使用SDK方法

我们建议您使用SDK封装的方法操作原生数字资产,比如 ONT Token等。

//step1:获得ontSdk实例
OntSdk wm = OntSdk.getInstance();
wm.setRpcConnection(url);
wm.openWalletFile("OntAssetDemo.json");
//step2:获得ontAssetTx实例
ontAssetTx = ontSdk.getOntAssetTx()
//step3:调用转账方法
ontAssetTx.sendTransfer(from,to,value)
ontSdk.getOntAssetTx().sendTransferToMany("ont",info1.address,"passwordtest",new String[]{info2.address,info3.address},new long[]{100L,200L});
ontSdk.getOntAssetTx().sendTransferFromMany("ont", new String[]{info1.address, info2.address}, new String[]{"passwordtest", "passwordtest"}, info3.address, new long[]{1L, 2L});
ontSdk.getOntAssetTx().sendOngTransferFrom(info1.address,"passwordtest",info2.address,100);
  • 使用智能合约

您也可以使用智能合约操作原生数字资产。

ontology资产智能合约abi文件,abi文件是对智能合约函数接口的描述,通过abi文件可以清楚如何传参:

{
    "hash":"0xceab719b8baa2310f232ee0d277c061704541cfb",
    "entrypoint":"Main",
    "functions":
    [
        {
            "name":"Main",
            "parameters":
            [
                {
                    "name":"operation",
                    "type":"String"
                },
                {
                    "name":"args",
                    "type":"Array"
                }
            ],
            "returntype":"Any"
        },
        {
            "name":"Transfer",
            "parameters":
            [
                {
                    "name":"from",
                    "type":"ByteArray"
                },
                {
                    "name":"to",
                    "type":"ByteArray"
                },
                {
                    "name":"value",
                    "type":"Integer"
                }
            ],
            "returntype":"Boolean"
        },
        {
            "name":"BalanceOf",
            "parameters":
            [
                {
                    "name":"address",
                    "type":"ByteArray"
                }
            ],
            "returntype":"Integer"
        }
    ],
    "events":
    [
    ]
}

通过调用ontology资产智能合约进行转账操作

//step1:读取智能合约abi文件
InputStream is = new FileInputStream("C:\\NeoContract1.abi.json");
byte[] bys = new byte[is.available()];
is.read(bys);
is.close();
String abi = new String(bys);

//step2:解析abi文件
AbiInfo abiinfo = JSON.parseObject(abi, AbiInfo.class);

//step3:设置智能合约codeaddress
ontSdk.setCodeAddress(abiinfo.getHash());

//step4:选择函数,设置函数参数
AbiFunction func = abiinfo.getFunction("Transfer");
System.out.println(func.getParameters());
func.setParamsValue(from.getBytes(),to.getBytes(),value.getBytes());

//setp5:调用合约
String hash = ontSdk.getSmartcodeTx().sendInvokeSmartCodeWithSign("passwordtest",addr,func);

AbiInfo结构是怎样的?

public class AbiInfo {
    public String hash;
    public String entrypoint;
    public List<AbiFunction> functions;
    public List<AbiEvent> events;
}
public class AbiFunction {
    public String name;
    public String returntype;
    public List<Parameter> parameters;
}
public class Parameter {
    public String name;
    public String type;
    public String value;
}

nep-5智能合约数字资产

nep-5文档:

https://github.com/neo-project/proposals/blob/master/nep-5.mediawiki

nep-5智能合约模板:

using Neo.SmartContract.Framework;
using Neo.SmartContract.Framework.Services.Neo;
using Neo.SmartContract.Framework.Services.System;
using System;
using System.ComponentModel;
using System.Numerics;

namespace Nep5Template
{
    public class Nep5Template : SmartContract
    {
        //Token Settings
        public static string Name() => "Nep5Template Token";
        public static string Symbol() => "TMP";
        public static readonly byte[] community = "AXK2KtCfcJnSMyRzSwTuwTKgNrtx5aXfFX".ToScriptHash();
        public static byte Decimals() => 8;
        private const ulong factor = 100000000; //decided by Decimals()

        //ICO Settings
        private const ulong totalAmount = 1000000000 * factor;
        private const ulong communityCap = 1000000000 * factor;

        [DisplayName("transfer")]
        public static event Action<byte[], byte[], BigInteger> Transferred;

        public static Object Main(string operation, params object[] args)
        {
            if (Runtime.Trigger == TriggerType.Application)
            {
                if (operation == "init") return Init();
                if (operation == "totalSupply") return TotalSupply();
                if (operation == "name") return Name();
                if (operation == "symbol") return Symbol();
                if (operation == "transfer")
                {
                    if (args.Length != 3) return false;
                    byte[] from = (byte[])args[0];
                    byte[] to = (byte[])args[1];
                    BigInteger value = (BigInteger)args[2];
                    return Transfer(from, to, value);
                }
                if (operation == "balanceOf")
                {
                    if (args.Length != 1) return 0;
                    byte[] account = (byte[])args[0];
                    return BalanceOf(account);
                }
                if (operation == "decimals") return Decimals();
            }
            return false;
        }

        // 初始化参数
        public static bool Init()
        {
            byte[] total_supply = Storage.Get(Storage.CurrentContext, "totalSupply");
            if (total_supply.Length != 0) return false;

            Storage.Put(Storage.CurrentContext, community, communityCap);
            Transferred(null, community, communityCap);

            Storage.Put(Storage.CurrentContext, "totalSupply", totalAmount);
            return true;
        }

        // get the total token supply
        // 获取已发行token总量
        public static BigInteger TotalSupply()
        {
            Runtime.CheckSig(new byte[1]{ 1 },  new byte[]{2},new byte[]{ 3});
            return Storage.Get(Storage.CurrentContext, "totalSupply").AsBigInteger();
        }

        // function that is always called when someone wants to transfer tokens.
        // 流转token调用
        public static bool Transfer(byte[] from, byte[] to, BigInteger value)
        {
            if (value <= 0) return false;
            if (!Runtime.CheckWitness(from)) return false;
            if (from == to) return true;
            BigInteger from_value = Storage.Get(Storage.CurrentContext, from).AsBigInteger();
            if (from_value < value) return false;
            if (from_value == value)
                Storage.Delete(Storage.CurrentContext, from);
            else
                Storage.Put(Storage.CurrentContext, from, from_value - value);
            BigInteger to_value = Storage.Get(Storage.CurrentContext, to).AsBigInteger();
            Storage.Put(Storage.CurrentContext, to, to_value + value);
            Transferred(from, to, value);
            return true;
        }

        // get the account balance of another account with address
        // 根据地址获取token的余额
        public static BigInteger BalanceOf(byte[] address)
        {
            return Storage.Get(Storage.CurrentContext, address).AsBigInteger();
        }
    }
}

部署合约:

  InputStream is = new FileInputStream("C:\\smartcontract.avm");//
  byte[] bys = new byte[is.available()];
  is.read(bys);
  is.close();
  String code = Helper.toHexString(bys);
  System.out.println("Code:" + Helper.toHexString(bys));
  System.out.println("CodeAddress:" + Helper.getCodeAddress(code, VmType.NEOVM.value()));

  ontSdk.setCodeAddress(Helper.getCodeAddress(code, VmType.NEOVM.value()));
  Transaction tx = ontSdk.getSmartcodeTx().makeDeployCodeTransaction(code, true, "name", "v1.0", "author", "email", "desc", VmType.NEOVM.value());

调用合约:

  AbiInfo abiinfo = JSON.parseObject(nep5abi, AbiInfo.class);
  //选个智能合约方法
  AbiFunction func = abiinfo.getFunction("Transfer");
  func.name = func.name.toLowerCase();
  //设置方法的参数
  func.setParamsValue(Address.decodeBase58(sendAddr).toArray(),Address.decodeBase58(recvAddr).toArray(),amount);
  Transaction tx = sdk.getSmartcodeTx().invokeTransaction(sendAddr,password,func,VmType.NEOVM.value());
  //签名
  sdk.signTx(tx, sendAddr, password);
  boolean b = sdk.getConnectMgr().sendRawTransaction(tx.toHexString());

说明

  • codeAddress是什么?
是智能合约的唯一标识。在这里代表资产合约的codeAddress。
  • invoke时为什么要传入账号和密码?
调用智能合约时需要用户签名,钱包中保存的是加密后的用户私钥,需要密码才能解密获取私钥。
  • 查询资产操作时,智能合约预执行是怎么回事,如何使用?
如智能合约get相关操作,从智能合约存储空间里读取数据,无需走节点共识,只在该节点执行即可返回结果。
发送交易时调用预执行接口
String result = (String) sdk.getConnectMgr().sendRawTransactionPreExec(txHex);
  • 想查看转账时的推送结果?

请查看智能合约采用websocket连接调用合约方法,详见smartcontract