openchain-sdk-yxl-ts
Version:
OpenChain SDK for browser
245 lines (205 loc) • 7.38 kB
JavaScript
import humps from 'humps';
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';
class Ctp10Token extends CommonUtil {
constructor(options = {}) {
super(options);
if (!(this instanceof Ctp10Token)) {
return new Ctp10Token(options);
}
}
// 辅助方法:验证合约地址
async _validateContractAddress(contractAddress) {
if (!keypair.checkAddress(contractAddress)) {
return this._responseError(this.options.errors.INVALID_CONTRACTADDRESS_ERROR);
}
const isContractAddress = await this._isContractAddress(contractAddress);
if (!isContractAddress) {
return this._responseError(this.options.errors.CONTRACTADDRESS_NOT_CONTRACTACCOUNT_ERROR);
}
return { valid: true };
}
// 辅助方法:调用合约方法
async _callContractMethod(contractAddress, method, params = {}) {
try {
let data = {
optType: 2,
contractAddress,
input: JSON.stringify({
method,
params
}),
};
data = humps.decamelizeKeys(data, { separator: '_' });
data = JSONbig.stringify(data);
const info = await this._request('post', 'callContract', data);
if (info.result?.query_rets?.[0]?.result) {
return JSONbig.parse(info.result.query_rets[0].result.value);
}
return null;
} catch (err) {
console.error(`Error calling contract method ${method}:`, err);
return null;
}
}
async checkValid(contractAddress) {
try {
return await this._isAvailableToken(contractAddress);
} catch (err) {
console.error('Error in checkValid:', err);
return this._responseError(this.options.errors.INVALID_CONTRACTADDRESS_ERROR);
}
}
async getInfo(contractAddress) {
try {
const validationResult = await this._validateContractAddress(contractAddress);
if (!validationResult.valid) return validationResult;
const info = await this._callContractMethod(contractAddress, 'contractInfo');
if (!info) {
return this._responseError(this.options.errors.INVALID_CONTRACTADDRESS_ERROR);
}
const contractInfo = info.contractInfo;
return this._responseData({
ctp: contractInfo.ctp,
name: contractInfo.name,
symbol: contractInfo.symbol,
totalSupply: contractInfo.totalSupply,
decimals: contractInfo.decimals,
contractOwner: contractInfo.contractOwner,
});
} catch (err) {
console.error('Error in getInfo:', err);
return this._responseError(this.options.errors.INVALID_CONTRACTADDRESS_ERROR);
}
}
async getName(contractAddress) {
try {
const validationResult = await this._validateContractAddress(contractAddress);
if (!validationResult.valid) return validationResult;
const data = await this.getInfo(contractAddress);
if (!data.result) return this._responseData('');
return this._responseData({
name: data.result.name,
});
} catch (err) {
console.error('Error in getName:', err);
return this._responseError(this.options.errors.INVALID_CONTRACTADDRESS_ERROR);
}
}
async getSymbol(contractAddress) {
try {
const validationResult = await this._validateContractAddress(contractAddress);
if (!validationResult.valid) return validationResult;
const data = await this.getInfo(contractAddress);
if (!data.result) return this._responseData('');
return this._responseData({
symbol: data.result.symbol,
});
} catch (err) {
console.error('Error in getSymbol:', err);
return this._responseError(this.options.errors.INVALID_CONTRACTADDRESS_ERROR);
}
}
async getDecimals(contractAddress) {
try {
const validationResult = await this._validateContractAddress(contractAddress);
if (!validationResult.valid) return validationResult;
const data = await this.getInfo(contractAddress);
if (!data.result) return this._responseData('');
return this._responseData({
decimals: data.result.decimals,
});
} catch (err) {
console.error('Error in getDecimals:', err);
return this._responseError(this.options.errors.INVALID_CONTRACTADDRESS_ERROR);
}
}
async getTotalSupply(contractAddress) {
try {
const validationResult = await this._validateContractAddress(contractAddress);
if (!validationResult.valid) return validationResult;
const data = await this.getInfo(contractAddress);
if (!data.result) return this._responseData('');
return this._responseData({
totalSupply: data.result.totalSupply,
});
} catch (err) {
console.error('Error in getTotalSupply:', err);
return this._responseError(this.options.errors.INVALID_CONTRACTADDRESS_ERROR);
}
}
async getBalance(args) {
try {
if (Array.isArray(args) || typeof args !== 'object' || args === null) {
return this._responseError(this.options.errors.INVALID_ARGUMENTS);
}
const schema = {
contractAddress: {
required: true,
address: true,
},
tokenOwner: {
required: true,
address: true,
},
};
const validation = this._validate(args, schema);
if (!validation.tag) {
return this._responseError(errors[validation.msg]);
}
const validationResult = await this._validateContractAddress(args.contractAddress);
if (!validationResult.valid) return validationResult;
const info = await this._callContractMethod(args.contractAddress, 'balanceOf', {
address: args.tokenOwner,
});
if (!info) {
return this._responseError(this.options.errors.NO_SUCH_TOKEN_ERROR);
}
return this._responseData(info);
} catch (err) {
console.error('Error in getBalance:', err);
return this._responseError(this.options.errors.NO_SUCH_TOKEN_ERROR);
}
}
async allowance(args) {
try {
if (Array.isArray(args) || typeof args !== 'object' || args === null) {
return this._responseError(this.options.errors.INVALID_ARGUMENTS);
}
const schema = {
contractAddress: {
required: true,
address: true,
},
tokenOwner: {
required: true,
address: true,
},
spender: {
required: true,
address: true,
}
};
const validation = this._validate(args, schema);
if (!validation.tag) {
return this._responseError(errors[validation.msg]);
}
const validationResult = await this._validateContractAddress(args.contractAddress);
if (!validationResult.valid) return validationResult;
const info = await this._callContractMethod(args.contractAddress, 'allowance', {
owner: args.tokenOwner,
spender: args.spender,
});
if (!info) {
return this._responseError(this.options.errors.NO_SUCH_TOKEN_ERROR);
}
return this._responseData(info);
} catch (err) {
console.error('Error in allowance:', err);
return this._responseError(this.options.errors.NO_SUCH_TOKEN_ERROR);
}
}
}
export default Ctp10Token;