openchain-sdk-yxl-ts
Version:
OpenChain SDK for browser
154 lines (131 loc) • 4.56 kB
JavaScript
import JSONbig from 'json-bigint';
import { keypair } from 'openchain-encryption-nodejs-yxl-ts';
import errors from '../exception/index.js';
import CommonUtil from '../common/util.js';
import opOperations from './op.js';
import assetOperations from './asset.js';
import accountOperations from './account.js';
import logOperations from './log.js';
import contractOperations from './contract.js';
import ctp10TokenOperations from './ctp10Token.js';
class Operation extends CommonUtil {
constructor(options = {}) {
super(options);
if (!(this instanceof Operation)) {
return new Operation(options);
}
if (typeof options !== 'object' || options === null) {
throw new Error('options is required');
}
// 设置 options 到实例上,确保子模块可以访问
this.options = options;
// 初始化所有操作模块
this.initializeOperations();
}
// 初始化所有操作模块
initializeOperations() {
const operations = [
{ name: 'op', module: opOperations },
{ name: 'asset', module: assetOperations },
{ name: 'account', module: accountOperations },
{ name: 'log', module: logOperations },
{ name: 'contract', module: contractOperations },
{ name: 'ctp10Token', module: ctp10TokenOperations }
];
operations.forEach(({ name, module }) => {
this.initializeOperationModule(name, module);
});
}
// 初始化单个操作模块
/**
* 初始化操作模块,将模块中的所有方法绑定到当前实例
* @param {string} name - 模块名称
* @param {Object} module - 要初始化的模块对象
* @description 遍历模块中的所有方法,将函数类型的方法绑定到当前实例上,并保持this上下文
*/
initializeOperationModule(name, module) {
// 将模块中的所有方法绑定到当前实例
Object.entries(module).forEach(([methodName, method]) => {
if (typeof method === 'function') {
// 绑定方法到当前实例,并保持 this 上下文
// 直接使用方法,不进行额外的绑定
this[methodName] = (...args) => {
// 确保方法在正确的上下文中执行
try {
return method.apply(this, args);
} catch (err) {
console.error(`Error in ${name} module, method ${methodName}:`, err);
throw err;
}
};
}
});
}
// 验证操作参数
validateOperation(operation) {
if (!operation || typeof operation !== 'object' || operation === null) {
return {
valid: false,
error: this._responseError(errors.INVALID_ARGUMENTS)
};
}
if (!operation.type || !operation.data) {
return {
valid: false,
error: this._responseError(errors.INVALID_ARGUMENTS)
};
}
return { valid: true };
}
// 构建操作
async buildOperation(type, data) {
try {
const operation = { type, data };
const validation = this.validateOperation(operation);
if (!validation.valid) {
return validation.error;
}
return await this._buildOperation(type, data);
} catch (err) {
console.error('Error in buildOperation:', err);
return this._responseError(errors.INVALID_OPERATIONS);
}
}
// 评估操作费用
async evaluateOperationFee(operation) {
try {
const validation = this.validateOperation(operation);
if (!validation.valid) {
return validation.error;
}
const { type, data } = operation;
const operationData = await this._buildOperation(type, data);
if (!operationData || operationData.errorCode !== 0) {
return this._responseError(errors.INVALID_OPERATIONS);
}
return this._responseData({
operation: operationData,
estimated_fee: await this._estimateOperationFee(operationData)
});
} catch (err) {
console.error('Error in evaluateOperationFee:', err);
return this._responseError(errors.INVALID_OPERATIONS);
}
}
// 估算操作费用
async _estimateOperationFee(operation) {
try {
const response = await this._request('post', 'estimateOperationFee', {
operation: JSONbig.stringify(operation)
});
if (response.error_code === 0) {
return response.result;
}
throw new Error('Failed to estimate operation fee');
} catch (err) {
console.error('Error in _estimateOperationFee:', err);
throw err;
}
}
}
export default Operation;