openchain-sdk-yxl-wx-request
Version:
openchain sd YxL wx request
301 lines (257 loc) • 7.39 kB
Markdown
# 智能合约
智能合约模块提供了合约的部署、调用、查询等完整功能支持。
## 合约部署
### 创建合约
```javascript
// 创建合约操作
const createContractOperation = {
sourceAddress: sourceAddress, // 合约创建者地址
initBalance: '1000000', // 合约初始化余额
type: 0, // 合约类型,0表示JavaScript
payload: contractCode, // 合约代码
initInput: 'init-args', // 可选,合约初始化参数
metadata: 'contract info' // 可选,合约备注
};
// 提交创建合约操作
const response = yield sdk.operation.contract.create(createContractOperation);
// 获取合约地址
const contractAddress = yield sdk.contract.getAddress({
hash: response.result.hash // 合约创建交易的hash
});
```
### 合约代码示例
```javascript
// 简单的Token合约示例
'use strict';
const contractCode = `
function init(input) {
let params = JSON.parse(input);
Chain.store('totalSupply', params.totalSupply);
Chain.store('name', params.name);
Chain.store('symbol', params.symbol);
Chain.store('decimals', params.decimals);
Chain.store(Chain.thisAddress, params.totalSupply);
}
function main(input) {
let params = JSON.parse(input);
if (params.method === 'transfer') {
return transfer(params);
} else if (params.method === 'balanceOf') {
return balanceOf(params);
}
throw 'Unknown method';
}
function transfer(params) {
let from = Chain.thisAddress;
let to = params.to;
let value = params.value;
let fromBalance = Chain.load(from);
let toBalance = Chain.load(to) || '0';
if (Number(fromBalance) < Number(value)) {
throw 'Insufficient balance';
}
Chain.store(from, String(Number(fromBalance) - Number(value)));
Chain.store(to, String(Number(toBalance) + Number(value)));
return true;
}
function balanceOf(params) {
let address = params.address;
let balance = Chain.load(address) || '0';
return balance;
}
function query(input) {
let params = JSON.parse(input);
if (params.method === 'balanceOf') {
return balanceOf(params);
}
throw 'Unknown method';
}
`;
```
## 合约调用
### 通过BU调用合约
```javascript
// 使用调用合约
const invokeByOPOperation = {
sourceAddress: sourceAddress, // 调用者地址
contractAddress: contractAddr, // 合约地址
buAmount: '100', // 调用时转入的BU数量
input: JSON.stringify({ // 调用参数
method: 'transfer',
to: 'destinationAddress',
value: '100'
})
};
const buResponse = yield sdk.operation.contract.invokeByBU(invokeByOPOperation);
```
### 通过资产调用合约
```javascript
// 使用资产调用合约
const invokeByAssetOperation = {
sourceAddress: sourceAddress, // 调用者地址
contractAddress: contractAddr, // 合约地址
code: 'CNY', // 资产代码
issuer: 'issuer-address', // 资产发行方地址
assetAmount: '100', // 调用时转入的资产数量
input: JSON.stringify({ // 调用参数
method: 'transfer',
to: 'destinationAddress',
value: '100'
})
};
const assetResponse = yield sdk.operation.contract.invokeByAsset(invokeByAssetOperation);
```
## 合约查询
### 查询合约信息
```javascript
// 查询合约基本信息
const contractInfo = yield sdk.contract.getInfo(contractAddress);
// 查询合约地址
const contractAddress = yield sdk.contract.getAddress({
hash: contractCreateHash // 合约创建交易的hash
});
```
### 调用合约查询接口
```javascript
// 调用合约的查询方法
const contractCallResponse = yield sdk.contract.call({
contractAddress: contractAddress,
input: JSON.stringify({
method: 'balanceOf',
address: 'queryAddress'
})
});
```
## 合约事件
### 创建合约日志
```javascript
// 创建合约日志
const createLogOperation = {
sourceAddress: sourceAddress, // 日志创建者地址
topic: 'event-topic', // 日志主题
data: 'event-data' // 日志数据
};
const logResponse = yield sdk.operation.log.create(createLogOperation);
```
### 查询合约日志
```javascript
// 查询合约日志
const logs = yield sdk.operation.log.getEvents({
contractAddress: contractAddress,
topic: 'event-topic'
});
```
## 最佳实践
1. 合约开发规范
```javascript
// 标准合约结构
const standardContract = `
'use strict';
// 初始化函数
function init(input) {
// 验证输入参数
if (!input) throw 'Invalid input';
// 初始化存储
}
// 主函数 - 处理所有写操作
function main(input) {
// 解析输入
let params = JSON.parse(input);
// 方法路由
switch(params.method) {
case 'method1': return method1(params);
case 'method2': return method2(params);
default: throw 'Unknown method';
}
}
// 查询函数 - 处理只读操作
function query(input) {
// 解析输入
let params = JSON.parse(input);
// 查询路由
switch(params.method) {
case 'query1': return query1(params);
case 'query2': return query2(params);
default: throw 'Unknown query method';
}
}
`;
```
2. 错误处理
```javascript
// 合约中的错误处理
function safeOperation(params) {
// 参数验证
if (!params.value || params.value <= 0) {
throw 'Invalid value';
}
// 状态检查
let state = Chain.load('state');
if (state !== 'active') {
throw 'Contract not active';
}
// 余额检查
let balance = Chain.load(params.address);
if (Number(balance) < Number(params.value)) {
throw 'Insufficient balance';
}
// 执行操作
try {
// 业务逻辑
} catch (e) {
throw 'Operation failed: ' + e;
}
}
```
3. 存储优化
```javascript
// 优化存储结构
function optimizedStorage() {
// 使用前缀区分不同类型的数据
Chain.store('balance:' + address, amount);
Chain.store('allowance:' + owner + ':' + spender, amount);
// 批量数据使用JSON存储
let data = {
key1: value1,
key2: value2
};
Chain.store('batch_data', JSON.stringify(data));
}
```
4. Gas优化
```javascript
// Gas使用优化
function optimizedOperation() {
// 减少存储操作
let data = Chain.load('data');
data = JSON.parse(data);
data.value += 1;
Chain.store('data', JSON.stringify(data));
// 避免循环操作
let total = Chain.load('total');
Chain.store('total', String(Number(total) + value));
}
```
5. 安全建议
```javascript
// 安全检查示例
function secureOperation(params) {
// 权限检查
let owner = Chain.load('owner');
if (Chain.msg.sender !== owner) {
throw 'No permission';
}
// 数值检查
if (typeof params.value !== 'string' || !/^\d+$/.test(params.value)) {
throw 'Invalid number format';
}
// 地址验证
if (!Chain.isValidAddress(params.address)) {
throw 'Invalid address';
}
// 状态检查
if (Chain.load('paused') === 'true') {
throw 'Contract is paused';
}
}
```