UNPKG

openchain-sdk-yxl-ts

Version:

OpenChain SDK for browser

288 lines (256 loc) 8.43 kB
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, };