openchain-sdk-yxl-ts
Version:
OpenChain SDK for browser
288 lines (256 loc) • 8.43 kB
JavaScript
import { keypair } from 'openchain-encryption-nodejs-yxl-ts';
import errors from '../exception/index.js';
/**
* 账户操作相关的方法集合
* 这些方法将被混入到 Operation 类中
*/
class AccountOperations {
/**
* 验证阈值参数
* @private
* @param {number} value - 要验证的值
* @param {number} [min=-1] - 最小值
* @param {number} [max=Number.MAX_SAFE_INTEGER] - 最大值
* @returns {boolean} 是否有效
*/
_isValidThreshold(value, min = -1, max = Number.MAX_SAFE_INTEGER) {
if (value === undefined) return true;
return this._isAvailableValue(value, min, max);
}
/**
* 验证签名者列表
* @private
* @param {Array} signers - 签名者列表
* @returns {Object} 验证结果
*/
_validateSigners(signers) {
if (!Array.isArray(signers)) return { valid: true };
const maxInt32 = Math.pow(2, 32) - 1;
for (const signer of signers) {
if (!keypair.checkAddress(signer.address)) {
return {
valid: false,
error: 'INVALID_SIGNER_ADDRESS_ERROR'
};
}
if (!this._isAvailableValue(signer.weight, -1, maxInt32)) {
return {
valid: false,
error: 'INVALID_SIGNER_WEIGHT_ERROR'
};
}
}
return { valid: true };
}
/**
* 验证类型阈值列表
* @private
* @param {Array} thresholds - 类型阈值列表
* @returns {Object} 验证结果
*/
_validateTypeThresholds(thresholds) {
if (!Array.isArray(thresholds)) return { valid: true };
for (const threshold of thresholds) {
if (!this._isAvailableValue(threshold.type, -1, 100)) {
return {
valid: false,
error: 'INVALID_OPERATION_TYPE_ERROR'
};
}
if (!this._isAvailableValue(threshold.threshold)) {
return {
valid: false,
error: 'INVALID_TYPE_THRESHOLD_ERROR'
};
}
}
return { valid: true };
}
/**
* 账户激活操作
* @param {Object} args - 激活参数
* @param {string} [args.sourceAddress] - 源地址
* @param {string} args.destAddress - 目标地址
* @param {string|number} args.initBalance - 初始余额
* @param {string} [args.metadata] - 元数据
* @returns {Object} 操作结果
*/
accountActivateOperation(args) {
try {
if (Array.isArray(args) || typeof args !== 'object' || args === null) {
return this._responseError(this.options.errors.INVALID_ARGUMENTS);
}
const schema = {
sourceAddress: {
required: true,
address: true,
},
destAddress: {
required: true,
address: true,
},
initBalance: {
required: true,
numeric: true,
},
metadata: {
required: false,
string: true,
}
};
if (!this._validate(args, schema).tag) {
const msg = this._validate(args, schema).msg;
return this._responseError(this.options.errors[msg]);
}
if (args.sourceAddress && args.destAddress === args.sourceAddress) {
return this._responseError(errors.SOURCEADDRESS_EQUAL_DESTADDRESS_ERROR);
}
return this._responseData({
operation: {
type: 'activateAccount',
data: this._sanitizeOperationData(args),
},
});
} catch (err) {
console.error('Error in accountActivateOperation:', err);
return this._responseError(this.options.errors.INVALID_ARGUMENTS);
}
}
/**
* 设置账户元数据操作
* @param {Object} args - 元数据参数
* @param {string} args.key - 键
* @param {string} args.value - 值
* @param {string} [args.sourceAddress] - 源地址
* @param {boolean} [args.deleteFlag] - 删除标志
* @param {string} [args.metadata] - 元数据
* @returns {Object} 操作结果
*/
accountSetMetadataOperation(args) {
try {
if (Array.isArray(args) || typeof args !== 'object' || args === null) {
return this._responseError(this.options.errors.INVALID_ARGUMENTS);
}
const schema = {
key: {
required: true,
string: true,
},
sourceAddress: {
required: false,
address: true,
},
deleteFlag: {
required: false,
boolean: true,
},
metadata: {
required: false,
string: true,
}
};
if (!this._validate(args, schema).tag) {
return this._responseError(this.options.errors.INVALID_ARGUMENTS);
}
const { value } = args;
if (typeof value !== 'string' || !value.trim() || value.length > 256000) {
return this._responseError(errors.INVALID_DATAVALUE_ERROR);
}
if (args.version && !this._isAvailableValue(args.version, -1)) {
return this._responseError(errors.INVALID_DATAVERSION_ERROR);
}
return this._responseData({
operation: {
type: 'accountSetMetadata',
data: this._sanitizeOperationData(args),
},
});
} catch (err) {
console.error('Error in accountSetMetadataOperation:', err);
return this._responseError(this.options.errors.INVALID_ARGUMENTS);
}
}
/**
* 设置账户权限操作
* @param {Object} args - 权限参数
* @param {string} [args.sourceAddress] - 源地址
* @param {number} [args.masterWeight] - 主权重
* @param {number} [args.txThreshold] - 交易阈值
* @param {Array} [args.signers] - 签名者列表
* @param {Array} [args.typeThresholds] - 类型阈值列表
* @param {string} [args.metadata] - 元数据
* @returns {Object} 操作结果
*/
accountSetPrivilegeOperation(args = {}) {
try {
if (Array.isArray(args) || typeof args !== 'object' || args === null) {
return this._responseError(this.options.errors.INVALID_ARGUMENTS);
}
const schema = {
sourceAddress: {
required: false,
address: true,
},
metadata: {
required: false,
string: true,
},
};
if (!this._validate(args, schema).tag) {
return this._responseError(this.options.errors.INVALID_ARGUMENTS);
}
const maxInt32 = Math.pow(2, 32) - 1;
// 验证主权重
if (!this._isValidThreshold(args.masterWeight, -1, maxInt32)) {
return this._responseError(errors.INVALID_MASTERWEIGHT_ERROR);
}
// 验证交易阈值
if (!this._isValidThreshold(args.txThreshold)) {
return this._responseError(errors.INVALID_TX_THRESHOLD_ERROR);
}
// 验证签名者列表
const signersValidation = this._validateSigners(args.signers);
if (!signersValidation.valid) {
return this._responseError(errors[signersValidation.error]);
}
// 验证类型阈值列表
const thresholdsValidation = this._validateTypeThresholds(args.typeThresholds);
if (!thresholdsValidation.valid) {
return this._responseError(errors[thresholdsValidation.error]);
}
return this._responseData({
operation: {
type: 'accountSetPrivilege',
data: this._sanitizeOperationData(args),
},
});
} catch (err) {
console.error('Error in accountSetPrivilegeOperation:', err);
return this._responseError(this.options.errors.INVALID_ARGUMENTS);
}
}
/**
* 清理操作数据,移除未定义的字段
* @private
* @param {Object} data - 原始数据
* @returns {Object} 清理后的数据
*/
_sanitizeOperationData(data) {
return Object.entries(data).reduce((acc, [key, value]) => {
if (value !== undefined && value !== null) {
acc[key] = value;
}
return acc;
}, {});
}
}
// 导出操作方法
export default {
accountActivateOperation: AccountOperations.prototype.accountActivateOperation,
accountSetMetadataOperation: AccountOperations.prototype.accountSetMetadataOperation,
accountSetPrivilegeOperation: AccountOperations.prototype.accountSetPrivilegeOperation,
_validateSigners: AccountOperations.prototype._validateSigners,
_validateTypeThresholds: AccountOperations.prototype._validateTypeThresholds,
_isValidThreshold: AccountOperations.prototype._isValidThreshold,
_sanitizeOperationData: AccountOperations.prototype._sanitizeOperationData,
};