1. 背景
数字积分是指在数字化环境中由企业或组织发行的虚拟资产,它们通常代表用户的消费记录、忠诚度、参与活动等行为产生的奖励。用户可以通过购物、互动、完成任务等方式获得数字积分,并可以在特定的场景下兑换商品、服务或作为权益证明。数字积分的应用场景多样,包括但不限于电商购物返利、会员特权提升、线上线下活动参与奖励、品牌联盟积分互换等。
2. 数字积分应用场景
-
电商平台与新零售:顾客消费后获得区块链积分,积分可以在各个合 作商家之间无缝流动和兑换,实现跨品牌、跨平台的积分互通。
-
旅游出行行业:航空公司、酒店等行业发行的里程积分或住宿积分可采用区块链技术,增强积分的安全性和流动性,方便用户在全球范围内实时兑换旅行相关服务。
-
企业内部激励:利用区块链积分对员工进行绩效评价和奖励,保证评价结果真实可靠,积分可用于内部福利兑换或职业发展资源的分配。
-
公益活动:政府或非营利组织发起的社会责任项目,参与者完成公益行动后获得区块链积分,积分可作为社会贡献证明,甚至转化为实质奖励。
-
游戏产业:在线游戏中,玩家通过游戏行为获取区块链积分,积分可以作为游戏内货币流通,也可以转换成现实世界的商品或服务。
3. 区块链在数字积分中的作用
区块链技术对于数字积分系统有着显著的改进作用:
- 安全性:区块链分布式账本的特点确保积分数据不可篡改,增强了积分系统的安全性和可信度。
- 透明性:所有积分的发行、转移和消耗记录均公开透明,任何一方都无法私自增删积分,提升了公平性。
- 流动性:基于区块链的数字积分可实现跨平台、跨企业的无缝流通,打破了传统积分系统的封闭性。
- 自动化管理:智能合约可以自动执行积分的发放、转让、结算等操作,减少人工干预带来的 风险和成本。
- 有效期管理:通过智能合约编程,可以实现积分有效期的自动跟踪和过期失效,避免积分沉淀和资源浪费。
4. 准备工作
在开始开发之前,您需要准备BubiChain的接入环境(体验网络:https://seed1-node.bubi.cn)或接入自建网络。请访问BubiChain的官方文档,按照指南安装必要的软件,如BubiChain SDK和相关工具。
确保您具备以下基础知识:
- JavaScript、Java编程语言。
- 区块链和智能合约的基本原理。
5. 概要设计
本文以Java语言为例,新创建一个积分发行方(简称为“资方”)并发行10亿GLA积分,然后转给10积分接收方Alice。
Alice的区块链账户地址:adxSfphzMP1qLfDh3a4iCU1M8F3X7Z2VBfwgD。
5.1. 智能合约设计
我们的智能合约将包含以下几个关键功能:
init()
:在init方法定义积分初始化参数(见BRC20协议),初始化积分供应量。transfer()
:在用户之间转移积分。balanceOf()
:查询特定用户的积分余额。
本示例数字积分合约是基于BRC20协议所开发,源代码下载;
5.2. 业务设计
- 用户注册时获得一定数量的初始积分。
- 用户可通过特定活动或交易获得更多积分。
- 积分可以用于兑换商品或服务,或转赠给其他用户。
6. 代码实现
6.1. 业务代码开发
在开发基于区块链技术的应用过程中,有一个非常重要的步骤是在选定的区块链网络环境中部署智能合约。智能合约实质上是自动执行、自我约束的程序,它定义了应用中的关键业务规则和操作,诸如积分发行、转移等核心功能。在该开发实践中,所有与积分上链相关的业务需求和功能实现,都将围绕并依赖于这个预先部署好的智能合约来运行。请跟随以下代码实现模块,了解如何部署智能合约到区块链网络环境,从而为后续的数字积分应用开发奠定基础。
- 创建SDK实例
设置区块链网络URL(本示例以体验网为例),创建SDK实例。
String url = "https://seed1-node.bubi.cn";
SDK sdk = SDK.getInstance(url);
- 部署数字积分合约
@Test
public void deployContract() {
// 账户部署合约所用的私钥
// 注意该私钥为测试网私钥,请勿用于生产环境
// 该账户需要确保至少30个Gas,以便部署资产积分合约;
String creatorPrivateKey = ExampleData.ACCOUNT_PRIVATE_KEY;
// 部署BRC20 token的账户地址
String creatorContractAddress = ExampleData.ACCOUNT_ADDRESS;
// 合约初始化的Gas,单位UGas,1Gas = 10^8 UGas
Long initBalance = ToBaseUnit.ToUGas("0.1");
// token 名称
String name = "Global";
// token 代码
String symbol = "GLA";
// token 总供应量,包含小数位
// 发行10亿个token,小数位为8,则需要1000000000 * 10^8
String totalSupply = "1000000000";
// 积分的小数位
Integer decimals = 8;
String version = "1.0";
// 合约源代码
String payload = ExampleData.CONTRACT_BRC20_CODE;
// Init initInput
JSONObject initInput = new JSONObject();
JSONObject params = new JSONObject();
params.put("name", name);
params.put("symbol", symbol);
params.put("decimals", decimals);
params.put("version", version);
params.put("supply", totalSupply);
initInput.put("params", params);
String metadata = "deploy BRC20 contracts";
// 获取合约发行方账户的nonce
long nonce = BRC20ContractHelper.getAccountNonce(creatorContractAddress);
BaseOperation[] operations = BRC20ContractHelper.buildCreateContractOperations(creatorContractAddress, payload, initInput.toJSONString(), initBalance, metadata);
// 发行积分方账户地址
String senderAddress = ExampleData.ACCOUNT_ADDRESS;
// 设置最大花费10.1Gas,单位UGas
Long feeLimit = ToBaseUnit.ToUGas("10.1");
String transactionBlob = BRC20ContractHelper.buildTransactionBlob(senderAddress,nonce, feeLimit, operations);
Signature[] signatures = BRC20ContractHelper.signTransaction(creatorPrivateKey, transactionBlob);
System.out.println("signData: " + signatures[0].getSignData());
System.out.println("publicKey: " + signatures[0].getPublicKey());
String hash = BRC20ContractHelper.submitTransaction(transactionBlob, signatures);
// 模拟延迟
try {
Thread.sleep(3500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("hash: " + hash);
int status = BRC20ContractHelper.checkTransactionStatus(hash);
System.out.println("status: " + status);
// 获取合约地址, 需要做延迟处理,才可以获取到合约地址
System.out.println("contractAddress: " + BRC20ContractHelper.getContractAddress(hash));
}
-
核心业务
-
积分转移
积分转移功能是允许一个账户(即源账户)通过调用智能合约的方法,将其持有的部分或全部积分转移至另一个不同的账户(即目标账户)。
以下场景都需要用到积分转移功能:
场景一:用户注册时获得一定数量的初始积分。
场景二:用户可通过特定活动或交易获得更多积分。
场景三:积分可以用于兑换商品或服务,或转赠给其他用户。 -
具有积分转移功能的场景,都需要调用智能合约的transfer
方法,完成给目标账户转移积分。
首先创建一个积分接收方账户
public static AccountCreateResult createAccount() {
AccountCreateResponse response = sdk.getAccountService().create();
if (response.getErrorCode() != 0) {
return null;
}
return response.getResult();
}
// 调用后生成的账户地址作为积分接收方的区块链账户
// AccountCreateResult
// privateKey: privbUAYxPLLyaxvU3EMkSTfuEDTWxAYvyCasUcCgUxDihtNXQL4oHJx
// publicKey: b001724ed9475ca4c8893329924c7dceae66c61d8577ab2c2c3b29376e143137c20a4bbed176
// address: adxSXVGt5ujjAe4hr11VqhjWpJdKqn6QfDVUX
其次通过SDK 调用数字积分智能合约的transfer
方法,完成给目标账户转移积分。
@Test
public void transfer() {
// Init variable
// The account private key to invoke contract
String invokePrivateKey = ExampleData.ACCOUNT_PRIVATE_KEY;
// The contract address , you can get it from create contract transaction
String contractAddress = ExampleData.CONTRACT_ADDRESS;
// The account to receive the BRC20 token
String destAddress = ExampleData.RECEIVER_ADDRESS;
// 0 means that the contract is only triggered
long amount = 0L;
// The fixed write 1000L, the unit is UGas
Long gasPrice = 1000L;
// Set up the maximum cost 0.01Gas
Long feeLimit = ToBaseUnit.ToUGas("0.01");
// The amount of BRC20 token to transfer, because the decimals is 8, so the unit is UGas
long toAmount = ToBaseUnit.ToUGas(ExampleData.SEND_DIGITAL_POINTS_AMOUNT);
// Contract main function entry
JSONObject input = new JSONObject();
JSONObject params = new JSONObject();
params.put("to", destAddress);
params.put("value", toAmount+"");
input.put("params", params);
input.put("method", "transfer");
String inputMethod = input.toJSONString();
// 1. Get the account address to send this transaction
String invokerAddress = ExampleData.ACCOUNT_ADDRESS;
// Transaction initiation account's Nonce + 1
Long nonce = BRC20ContractHelper.getAccountNonce(invokerAddress);
// 2. Build sendAsset operation
BaseOperation[] operations = BRC20ContractHelper.buildInvokeContractOperations(invokerAddress, contractAddress, amount, inputMethod);
// 3. Build transaction blob
String transactionBlob = BRC20ContractHelper.buildTransactionBlob(invokerAddress,nonce, feeLimit, operations);
// 4. Sign the transaction
Signature[] signatures = BRC20ContractHelper.signTransaction(invokePrivateKey, transactionBlob);
// 5. Submit the transaction
String txHash = BRC20ContractHelper.submitTransaction(transactionBlob, signatures);
if(txHash != null) {
System.out.println("hash: " + txHash);
}
}
最后可以通过交易查询接口获取最终状态。
即完成上一步“积分转移”操作后,其实该交易仅从接入节点被广播出去,交易的最终状态需要通过交易查询接口获取最终状态。
@Test
public void getTransactionStatus() {
String hash = ExampleData.SEND_DIGITAL_POINTS_TX_HASH;
int status = BRC20ContractHelper.checkTransactionStatus(hash);
if(status == 0) {
System.out.println("Transaction status: " + status);
} else {
System.out.println("Transaction status: " + status);
}
}
// status 为0时说明积分转移成功
- 获取账户余额
业务里经常需要获取某指定账户的积分余额,可以通过一下方法进行查询
@Test
public void callContract() {
// The contract address , you can get it from create contract transaction
String contractAddress = ExampleData.CONTRACT_ADDRESS;
// The parameter to call
JSONObject input = new JSONObject();
JSONObject params = new JSONObject();
params.put("address", ExampleData.RECEIVER_ADDRESS);
input.put("params", params);
input.put("method", "balanceOf");
String result = BRC20ContractHelper.callContract(contractAddress, input.toJSONString());
JSONObject jsonObject = JSONObject.parseObject(result);
if(jsonObject.get("query_rets") != null) {
System.out.println(jsonObject.getJSONArray("query_rets").getJSONObject(0).getJSONObject("result").get("value"));
}
}
// 如果打印结果为{"balance":"1000000000"},类似结果说明成功获取账户余额;注意这个返回结果需要考虑积分精度问题;
如果你对源代码感兴趣,可以通过以下链接进行下载。示例代码
八、总结
通过上述 Demo 的开发学习,可以初步了解如何利用 BubiChain Java SDK 开发数字积分业务。该示例实现了积分的发行、转移和余额查询功能。然而,在实际的生产环境中,还需要考虑更多的业务问题。例如,增加积分有效期管理,以确保积分的有效性和合理性;积分合约与现有业务系统的集成,以实现整体业务的协同运作。在将这些知识应用到自己的业务中时,请务必综合考虑实际需求和业务场景,以确保数字积分业务的成功实施和高效运行。