// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck
import google_protobuf_any_pb from 'google-protobuf/google/protobuf/any_pb.js';
import '../protocol/core/Tron_pb.cjs';
const { Transaction, Permission, Key } = globalThis.TronWebProto;
import '../protocol/core/contract/balance_contract_pb.cjs';
const {
TransferContract,
FreezeBalanceContract,
UnfreezeBalanceContract,
WithdrawBalanceContract,
FreezeBalanceV2Contract,
UnfreezeBalanceV2Contract,
CancelAllUnfreezeV2Contract,
WithdrawExpireUnfreezeContract,
DelegateResourceContract,
UnDelegateResourceContract,
} = globalThis.TronWebProto;
import '../protocol/core/contract/asset_issue_contract_pb.cjs';
const { TransferAssetContract, ParticipateAssetIssueContract, AssetIssueContract, UpdateAssetContract } = globalThis.TronWebProto;
import '../protocol/core/contract/smart_contract_pb.cjs';
const {
TriggerSmartContract,
ClearABIContract,
UpdateEnergyLimitContract,
UpdateSettingContract,
CreateSmartContract,
SmartContract,
} = globalThis.TronWebProto;
import '../protocol/core/contract/common_pb.cjs';
const { ResourceCode } = globalThis.TronWebProto;
import '../protocol/core/contract/witness_contract_pb.cjs';
const { WitnessCreateContract, VoteWitnessContract } = globalThis.TronWebProto;
import '../protocol/core/contract/storage_contract_pb.cjs';
const { UpdateBrokerageContract } = globalThis.TronWebProto;
import '../protocol/core/contract/account_contract_pb.cjs';
const { AccountCreateContract, AccountUpdateContract, SetAccountIdContract, AccountPermissionUpdateContract } =
globalThis.TronWebProto;
import '../protocol/core/contract/proposal_contract_pb.cjs';
const { ProposalCreateContract, ProposalDeleteContract, ProposalApproveContract } = globalThis.TronWebProto;
import '../protocol/core/contract/exchange_contract_pb.cjs';
const { ExchangeCreateContract, ExchangeInjectContract, ExchangeWithdrawContract, ExchangeTransactionContract } =
globalThis.TronWebProto;
import { byteArray2hexStr } from './bytes.js';
import { hexStr2byteArray } from './code.js';
import { sha256, keccak256 } from './ethersUtils.js';
import TronWeb from '../tronweb.js';
import { isHex } from './validations.js';
const fromHexString = (hexString: string) => {
if (!hexString || hexString.length === 0) return new Uint8Array([]);
return new Uint8Array(
TronWeb.address
.toHex(hexString)
.match(/.{1,2}/g)
.map((byte: string) => parseInt(byte, 16))
);
};
const stringToUint8Array = (hexString: string) => {
if (!hexString || hexString.length === 0) return new Uint8Array([]);
return new Uint8Array(
(isHex(hexString) ? hexString : TronWeb.toHex(hexString))
.replace(/^0x/, '')
.match(/.{1,2}/g)
.map((byte: string) => parseInt(byte, 16))
);
};
const flexToUint8Array = (str: string, visible: boolean) => {
if (!visible) return stringToUint8Array(str.replace(/^0x/, ''));
return stringToUint8Array(TronWeb.fromUtf8(str).replace(/^0x/, ''));
};
const sha3 = (string: string, prefix = true) => {
return (prefix ? '0x' : '') + keccak256(Buffer.from(string, 'utf-8')).toString().substring(2);
};
const buildCommonTransaction = (message, contractType, typeName, permissionId) => {
const anyValue = new google_protobuf_any_pb.Any();
anyValue.pack(message.serializeBinary(), 'protocol.' + typeName);
const contract = new Transaction.Contract();
contract.setType(contractType);
contract.setParameter(anyValue);
if (permissionId) {
contract.setPermissionId(permissionId);
}
const raw = new Transaction.raw();
raw.addContract(contract);
const transaction = new Transaction();
transaction.setRawData(raw);
return transaction;
};
// wallet/createtransaction for sendTrx
const buildTransferContract = (value, options) => {
const { to_address, owner_address, amount } = value;
const transferContract = new TransferContract();
transferContract.setToAddress(fromHexString(to_address));
transferContract.setOwnerAddress(fromHexString(owner_address));
transferContract.setAmount(amount);
return buildCommonTransaction(
transferContract,
Transaction.Contract.ContractType.TRANSFERCONTRACT,
'TransferContract',
options.Permission_id
);
};
// wallet/transferasset for sendToken
const buildTransferAssetContract = (value, options) => {
const { to_address, owner_address, amount, asset_name } = value;
const transferContract = new TransferAssetContract();
transferContract.setToAddress(fromHexString(to_address));
transferContract.setOwnerAddress(fromHexString(owner_address));
transferContract.setAssetName(flexToUint8Array(asset_name, options.visible));
transferContract.setAmount(amount);
return buildCommonTransaction(
transferContract,
Transaction.Contract.ContractType.TRANSFERASSETCONTRACT,
'TransferAssetContract',
options.Permission_id
);
};
// wallet/participateassetissue for purchaseToken
const buildParticipateAssetIssueContract = (value, options) => {
const pbObj = new ParticipateAssetIssueContract();
pbObj.setToAddress(fromHexString(value.to_address));
pbObj.setOwnerAddress(fromHexString(value.owner_address));
pbObj.setAssetName(flexToUint8Array(value.asset_name, options.visible));
pbObj.setAmount(value.amount);
return buildCommonTransaction(
pbObj,
Transaction.Contract.ContractType.PARTICIPATEASSETISSUECONTRACT,
'ParticipateAssetIssueContract',
options.Permission_id
);
};
const buildTriggerSmartContract = (value, options) => {
const triggerSmartContract = new TriggerSmartContract();
const {
owner_address,
contract_address,
parameter = '',
function_selector,
call_value,
call_token_value,
token_id,
data,
} = value;
triggerSmartContract.setOwnerAddress(fromHexString(owner_address));
triggerSmartContract.setContractAddress(fromHexString(contract_address));
triggerSmartContract.setCallValue(call_value);
if (data) {
triggerSmartContract.setData(stringToUint8Array(data));
} else if (function_selector) {
const contractData = sha3(function_selector).substring(2, 10) + parameter;
triggerSmartContract.setData(stringToUint8Array(contractData));
}
if (token_id) {
triggerSmartContract.setTokenId(token_id);
}
if (call_token_value) {
triggerSmartContract.setCallTokenValue(call_token_value);
}
return buildCommonTransaction(
triggerSmartContract,
Transaction.Contract.ContractType.TRIGGERSMARTCONTRACT,
'TriggerSmartContract',
options.Permission_id
);
};
const buildFreezeBalanceContract = (value, options) => {
const freezeBalanceContract = new FreezeBalanceContract();
const { owner_address, frozen_balance, frozen_duration, resource, receiver_address } = value;
freezeBalanceContract.setOwnerAddress(fromHexString(owner_address));
freezeBalanceContract.setFrozenBalance(frozen_balance);
freezeBalanceContract.setFrozenDuration(frozen_duration);
if (resource) {
freezeBalanceContract.setResource(ResourceCode[resource]);
}
if (receiver_address) {
freezeBalanceContract.setReceiverAddress(fromHexString(receiver_address));
}
return buildCommonTransaction(
freezeBalanceContract,
Transaction.Contract.ContractType.FREEZEBALANCECONTRACT,
'FreezeBalanceContract',
options.Permission_id
);
};
const buildUnfreezeBalanceContract = (value, options) => {
const unfreezeBalanceContract = new UnfreezeBalanceContract();
const { owner_address, resource, receiver_address } = value;
unfreezeBalanceContract.setOwnerAddress(fromHexString(owner_address));
if (resource) {
unfreezeBalanceContract.setResource(ResourceCode[resource]);
}
if (receiver_address) {
unfreezeBalanceContract.setReceiverAddress(fromHexString(receiver_address));
}
return buildCommonTransaction(
unfreezeBalanceContract,
Transaction.Contract.ContractType.UNFREEZEBALANCECONTRACT,
'UnfreezeBalanceContract',
options.Permission_id
);
};
const buildWithdrawBalanceContract = (value, options) => {
const withdrawbalanceContract = new WithdrawBalanceContract();
const { owner_address } = value;
withdrawbalanceContract.setOwnerAddress(fromHexString(owner_address));
return buildCommonTransaction(
withdrawbalanceContract,
Transaction.Contract.ContractType.WITHDRAWBALANCECONTRACT,
'WithdrawBalanceContract',
options.Permission_id
);
};
const buildFreezeBalanceV2Contract = (value, options) => {
const freezeBalanceV2Contract = new FreezeBalanceV2Contract();
const { owner_address, frozen_balance, resource } = value;
freezeBalanceV2Contract.setOwnerAddress(fromHexString(owner_address));
freezeBalanceV2Contract.setFrozenBalance(frozen_balance);
freezeBalanceV2Contract.setResource(ResourceCode[resource]);
return buildCommonTransaction(
freezeBalanceV2Contract,
Transaction.Contract.ContractType.FREEZEBALANCEV2CONTRACT,
'FreezeBalanceV2Contract',
options.Permission_id
);
};
const buildCancelFreezeBalanceV2Contract = (value, options) => {
const cancelAllUnfreezeV2Contract = new CancelAllUnfreezeV2Contract();
const { owner_address } = value;
cancelAllUnfreezeV2Contract.setOwnerAddress(fromHexString(owner_address));
return buildCommonTransaction(
cancelAllUnfreezeV2Contract,
Transaction.Contract.ContractType.CANCELALLUNFREEZEV2CONTRACT,
'CancelAllUnfreezeV2Contract',
options.Permission_id
);
};
const buildUnfreezeBalanceV2Contract = (value, options) => {
const unfreezeBalanceV2Contract = new UnfreezeBalanceV2Contract();
const { owner_address, unfreeze_balance, resource } = value;
unfreezeBalanceV2Contract.setOwnerAddress(fromHexString(owner_address));
unfreezeBalanceV2Contract.setUnfreezeBalance(unfreeze_balance);
unfreezeBalanceV2Contract.setResource(ResourceCode[resource]);
return buildCommonTransaction(
unfreezeBalanceV2Contract,
Transaction.Contract.ContractType.UNFREEZEBALANCEV2CONTRACT,
'UnfreezeBalanceV2Contract',
options.Permission_id
);
};
const buildDelegateResourceContract = (value, options) => {
const delegateResourceContract = new DelegateResourceContract();
const { owner_address, receiver_address, balance, resource, lock = false, lock_period } = value;
delegateResourceContract.setOwnerAddress(fromHexString(owner_address));
delegateResourceContract.setBalance(balance);
delegateResourceContract.setResource(ResourceCode[resource]);
delegateResourceContract.setLock(lock);
delegateResourceContract.setLockPeriod(lock_period);
delegateResourceContract.setReceiverAddress(fromHexString(receiver_address));
return buildCommonTransaction(
delegateResourceContract,
Transaction.Contract.ContractType.DELEGATERESOURCECONTRACT,
'DelegateResourceContract',
options.Permission_id
);
};
const buildUnDelegateResourceContract = (value, options) => {
const unDelegateResourceContract = new UnDelegateResourceContract();
const { owner_address, receiver_address, balance, resource } = value;
unDelegateResourceContract.setOwnerAddress(fromHexString(owner_address));
unDelegateResourceContract.setBalance(balance);
unDelegateResourceContract.setResource(ResourceCode[resource]);
unDelegateResourceContract.setReceiverAddress(fromHexString(receiver_address));
return buildCommonTransaction(
unDelegateResourceContract,
Transaction.Contract.ContractType.UNDELEGATERESOURCECONTRACT,
'UnDelegateResourceContract',
options.Permission_id
);
};
const buildWithdrawExpireUnfreezeContract = (value, options) => {
const withdrawExpireUnfreeze = new WithdrawExpireUnfreezeContract();
const { owner_address } = value;
withdrawExpireUnfreeze.setOwnerAddress(fromHexString(owner_address));
return buildCommonTransaction(
withdrawExpireUnfreeze,
Transaction.Contract.ContractType.WITHDRAWEXPIREUNFREEZECONTRACT,
'WithdrawExpireUnfreezeContract',
options.Permission_id
);
};
// applyForSR
const buildCreateWitness = (value, options) => {
const createWitnessContract = new WitnessCreateContract();
const { owner_address, url } = value;
createWitnessContract.setOwnerAddress(fromHexString(owner_address));
createWitnessContract.setUrl(stringToUint8Array(url.replace(/^0x/, '')));
return buildCommonTransaction(
createWitnessContract,
Transaction.Contract.ContractType.WITNESSCREATECONTRACT,
'WitnessCreateContract',
options.Permission_id
);
};
// vote
const buildVoteWitnessAccount = (value, options) => {
const voteWitnessContract = new VoteWitnessContract();
const { owner_address, votes } = value;
voteWitnessContract.setOwnerAddress(fromHexString(owner_address));
votes.forEach((voteItem) => {
const vote = new VoteWitnessContract.Vote();
const { vote_address, vote_count } = voteItem;
vote.setVoteAddress(fromHexString(vote_address));
const numberOfVotes = parseInt(vote_count);
vote.setVoteCount(numberOfVotes);
voteWitnessContract.addVotes(vote);
});
return buildCommonTransaction(
voteWitnessContract,
Transaction.Contract.ContractType.VOTEWITNESSCONTRACT,
'VoteWitnessContract',
options.Permission_id
);
};
const buildCreateSmartContract = (value, options) => {
const params = value?.new_contract
? {
...{
owner_address: value.owner_address,
call_token_value: value.call_token_value,
token_id: value.token_id,
},
...value.new_contract,
}
: value;
const {
owner_address,
consume_user_resource_percent,
origin_energy_limit,
abi,
bytecode = '',
parameter = '',
call_value,
call_token_value,
token_id,
name: contracName,
} = params;
let { origin_address } = params;
const createSmartContract = new CreateSmartContract();
createSmartContract.setOwnerAddress(fromHexString(owner_address));
if (token_id) {
createSmartContract.setTokenId(token_id);
}
if (call_token_value) {
createSmartContract.setCallTokenValue(call_token_value);
}
const smartContractBuilder = new SmartContract();
if (abi) {
let abiJson;
if (typeof abi === 'string') {
abiJson = JSON.parse(abi);
} else {
abiJson = abi?.entrys || []; // abi could be an empty object if origin abi is `[]`;
}
const abiBuilder = new SmartContract.ABI();
const buildEntryParam = (data) => {
const param = new SmartContract.ABI.Entry.Param();
const { indexed, name, type } = data;
if (indexed === true) {
param.setIndexed(true);
}
param.setName(name);
param.setType(type);
return param;
};
const entryBuilders = abiJson.map((entry) => {
const { anonymous, constant, name, inputs, outputs, type, payable, stateMutability } = entry;
const entryBuilder = new SmartContract.ABI.Entry();
entryBuilder.setAnonymous(anonymous);
entryBuilder.setConstant(constant);
entryBuilder.setName(name);
if (inputs) {
entryBuilder.setInputsList(inputs.map((input) => buildEntryParam(input)));
}
if (outputs) {
entryBuilder.setOutputsList(outputs.map((output) => buildEntryParam(output)));
}
if (type) {
entryBuilder.setType(SmartContract.ABI.Entry.EntryType[type.toUpperCase()]);
}
entryBuilder.setPayable(payable);
if (stateMutability) {
entryBuilder.setStatemutability(SmartContract.ABI.Entry.StateMutabilityType[stateMutability.toUpperCase()]);
}
return entryBuilder;
});
abiBuilder.setEntrysList(entryBuilders);
smartContractBuilder.setAbi(abiBuilder);
}
if (call_value) {
smartContractBuilder.setCallValue(call_value);
}
smartContractBuilder.setConsumeUserResourcePercent(consume_user_resource_percent);
smartContractBuilder.setOriginEnergyLimit(origin_energy_limit);
if (!origin_address) {
origin_address = owner_address;
}
smartContractBuilder.setOriginAddress(fromHexString(origin_address));
if (bytecode) {
const bytecodeParameter = bytecode.replace(/^0x/, '') + parameter.replace(/^0x/, '');
smartContractBuilder.setBytecode(stringToUint8Array(bytecodeParameter));
}
smartContractBuilder.setName(contracName);
createSmartContract.setNewContract(smartContractBuilder);
return buildCommonTransaction(
createSmartContract,
Transaction.Contract.ContractType.CREATESMARTCONTRACT,
'CreateSmartContract',
options.Permission_id
);
};
const buildClearABIContract = (value, options) => {
const { contract_address, owner_address } = value;
const clearABIContract = new ClearABIContract();
clearABIContract.setOwnerAddress(fromHexString(owner_address));
clearABIContract.setContractAddress(fromHexString(contract_address));
return buildCommonTransaction(
clearABIContract,
Transaction.Contract.ContractType.CLEARABICONTRACT,
'ClearABIContract',
options.Permission_id
);
};
// updateBrokerage
const buildUpdateBrokerageContract = (value, options) => {
const { brokerage, owner_address } = value;
const updateBrokerageContract = new UpdateBrokerageContract();
updateBrokerageContract.setOwnerAddress(fromHexString(owner_address));
updateBrokerageContract.setBrokerage(brokerage);
return buildCommonTransaction(
updateBrokerageContract,
Transaction.Contract.ContractType.UPDATEBROKERAGECONTRACT,
'UpdateBrokerageContract',
options.Permission_id
);
};
// createToken
const buildAssetIssueContract = (value, options) => {
const {
owner_address,
name,
abbr,
description,
url,
total_supply,
trx_num,
num,
start_time,
end_time,
precision,
free_asset_net_limit,
public_free_asset_net_limit,
public_free_asset_net_usage = 0,
public_latest_free_net_time = 0,
vote_score = 0,
frozen_supply,
} = value;
const assetIssueContract = new AssetIssueContract();
assetIssueContract.setOwnerAddress(fromHexString(owner_address));
if (name) {
assetIssueContract.setName(stringToUint8Array(name.replace(/^0x/, '')));
}
if (abbr) {
assetIssueContract.setAbbr(stringToUint8Array(abbr.replace(/^0x/, '')));
}
assetIssueContract.setTotalSupply(total_supply);
assetIssueContract.setNum(num);
assetIssueContract.setEndTime(end_time);
assetIssueContract.setStartTime(start_time);
assetIssueContract.setTrxNum(trx_num);
assetIssueContract.setVoteScore(vote_score);
if (precision) {
assetIssueContract.setPrecision(precision);
}
if (public_latest_free_net_time) {
assetIssueContract.setPublicLatestFreeNetTime(public_latest_free_net_time);
}
if (description) {
assetIssueContract.setDescription(stringToUint8Array(description.replace(/^0x/, '')));
}
if (url) {
assetIssueContract.setUrl(stringToUint8Array(url.replace(/^0x/, '')));
}
assetIssueContract.setPublicFreeAssetNetUsage(public_free_asset_net_usage);
assetIssueContract.setFreeAssetNetLimit(free_asset_net_limit);
assetIssueContract.setPublicFreeAssetNetLimit(public_free_asset_net_limit);
if (frozen_supply) {
const frozenSupplyContract = new AssetIssueContract.FrozenSupply();
frozenSupplyContract.setFrozenAmount(frozen_supply.length ? frozen_supply[0].frozen_amount : frozen_supply.frozen_amount);
frozenSupplyContract.setFrozenDays(frozen_supply.length ? frozen_supply[0].frozen_days : frozen_supply.frozen_days);
assetIssueContract.addFrozenSupply(frozenSupplyContract);
}
return buildCommonTransaction(
assetIssueContract,
Transaction.Contract.ContractType.ASSETISSUECONTRACT,
'AssetIssueContract',
options.Permission_id
);
};
//createAccount
const buildAccountCreateContract = (value, options) => {
const accountCreateContract = new AccountCreateContract();
const { account_address, owner_address } = value;
accountCreateContract.setOwnerAddress(fromHexString(owner_address));
accountCreateContract.setAccountAddress(fromHexString(account_address.replace(/^0x/, '')));
return buildCommonTransaction(
accountCreateContract,
Transaction.Contract.ContractType.ACCOUNTCREATECONTRACT,
'AccountCreateContract',
options.Permission_id
);
};
// updateAccount
const buildAccountUpdateContract = (value, options) => {
const accountUpdateContract = new AccountUpdateContract();
const { account_name, owner_address } = value;
accountUpdateContract.setOwnerAddress(fromHexString(owner_address));
accountUpdateContract.setAccountName(stringToUint8Array(account_name.replace(/^0x/, '')));
return buildCommonTransaction(
accountUpdateContract,
Transaction.Contract.ContractType.ACCOUNTUPDATECONTRACT,
'AccountUpdateContract',
options.Permission_id
);
};
// setAccountId
const buildSetAccountIdContract = (value, options) => {
const setAccountIdContract = new SetAccountIdContract();
const { account_id, owner_address } = value;
setAccountIdContract.setOwnerAddress(fromHexString(owner_address));
setAccountIdContract.setAccountId(stringToUint8Array(account_id.replace(/^0x/, '')));
return buildCommonTransaction(
setAccountIdContract,
Transaction.Contract.ContractType.SETACCOUNTIDCONTRACT,
'SetAccountIdContract',
options.Permission_id
);
};
const buildProposalCreateContract = (value, options) => {
const proposalCreateContract = new ProposalCreateContract();
const { owner_address, parameters } = value;
proposalCreateContract.setOwnerAddress(fromHexString(owner_address));
parameters.forEach((parameter) => {
proposalCreateContract.getParametersMap().set(parameter.key, parameter.value);
});
return buildCommonTransaction(
proposalCreateContract,
Transaction.Contract.ContractType.PROPOSALCREATECONTRACT,
'ProposalCreateContract',
options.Permission_id
);
};
const buildProposalDeleteContract = (value, options) => {
const proposalDeleteContract = new ProposalDeleteContract();
const { owner_address, proposal_id } = value;
proposalDeleteContract.setOwnerAddress(fromHexString(owner_address));
proposalDeleteContract.setProposalId(proposal_id);
return buildCommonTransaction(
proposalDeleteContract,
Transaction.Contract.ContractType.PROPOSALDELETECONTRACT,
'ProposalDeleteContract',
options.Permission_id
);
};
const buildVoteProposalContract = (value, options) => {
const proposalVoteContract = new ProposalApproveContract();
const { owner_address, proposal_id, is_add_approval } = value;
proposalVoteContract.setOwnerAddress(fromHexString(owner_address));
proposalVoteContract.setProposalId(proposal_id);
proposalVoteContract.setIsAddApproval(is_add_approval);
return buildCommonTransaction(
proposalVoteContract,
Transaction.Contract.ContractType.PROPOSALAPPROVECONTRACT,
'ProposalApproveContract',
options.Permission_id
);
};
const buildExchangeCreateContract = (value, options) => {
const exchangeCreateContract = new ExchangeCreateContract();
const { owner_address, first_token_id, first_token_balance, second_token_id, second_token_balance } = value;
exchangeCreateContract.setOwnerAddress(fromHexString(owner_address));
exchangeCreateContract.setFirstTokenId(flexToUint8Array(first_token_id, options.visible));
exchangeCreateContract.setFirstTokenBalance(first_token_balance);
exchangeCreateContract.setSecondTokenId(flexToUint8Array(second_token_id, options.visible));
exchangeCreateContract.setSecondTokenBalance(second_token_balance);
return buildCommonTransaction(
exchangeCreateContract,
Transaction.Contract.ContractType.EXCHANGECREATECONTRACT,
'ExchangeCreateContract',
options.Permission_id
);
};
const buildExchangeInjectContract = (value, options) => {
const exchangeInjectContract = new ExchangeInjectContract();
const { owner_address, exchange_id, token_id, quant } = value;
exchangeInjectContract.setOwnerAddress(fromHexString(owner_address));
exchangeInjectContract.setExchangeId(exchange_id);
exchangeInjectContract.setTokenId(flexToUint8Array(token_id, options.visible));
exchangeInjectContract.setQuant(quant);
return buildCommonTransaction(
exchangeInjectContract,
Transaction.Contract.ContractType.EXCHANGEINJECTCONTRACT,
'ExchangeInjectContract',
options.Permission_id
);
};
const buildExchangeWithdrawContract = (value, options) => {
const exchangeWithdrawContract = new ExchangeWithdrawContract();
const { owner_address, exchange_id, token_id, quant } = value;
exchangeWithdrawContract.setOwnerAddress(fromHexString(owner_address));
exchangeWithdrawContract.setExchangeId(exchange_id);
exchangeWithdrawContract.setTokenId(flexToUint8Array(token_id, options.visible));
exchangeWithdrawContract.setQuant(quant);
return buildCommonTransaction(
exchangeWithdrawContract,
Transaction.Contract.ContractType.EXCHANGEWITHDRAWCONTRACT,
'ExchangeWithdrawContract',
options.Permission_id
);
};
const buildExchangeTransactionContract = (value, options) => {
const exchangeTransactionContract = new ExchangeTransactionContract();
const { owner_address, exchange_id, token_id, quant, expected } = value;
exchangeTransactionContract.setOwnerAddress(fromHexString(owner_address));
exchangeTransactionContract.setExchangeId(exchange_id);
exchangeTransactionContract.setTokenId(flexToUint8Array(token_id, options.visible));
exchangeTransactionContract.setQuant(quant);
exchangeTransactionContract.setExpected(expected);
return buildCommonTransaction(
exchangeTransactionContract,
Transaction.Contract.ContractType.EXCHANGETRANSACTIONCONTRACT,
'ExchangeTransactionContract',
options.Permission_id
);
};
const buildUpdateSettingContract = (value, options) => {
const updateSettingContract = new UpdateSettingContract();
const { owner_address, contract_address, consume_user_resource_percent } = value;
updateSettingContract.setOwnerAddress(fromHexString(owner_address));
updateSettingContract.setContractAddress(fromHexString(contract_address));
updateSettingContract.setConsumeUserResourcePercent(consume_user_resource_percent);
return buildCommonTransaction(
updateSettingContract,
Transaction.Contract.ContractType.UPDATESETTINGCONTRACT,
'UpdateSettingContract',
options.Permission_id
);
};
const buildUpdateEnergyLimitContract = (value, options) => {
const updateEnergyLimitContract = new UpdateEnergyLimitContract();
const { owner_address, contract_address, origin_energy_limit } = value;
updateEnergyLimitContract.setOwnerAddress(fromHexString(owner_address));
updateEnergyLimitContract.setContractAddress(fromHexString(contract_address));
updateEnergyLimitContract.setOriginEnergyLimit(origin_energy_limit);
return buildCommonTransaction(
updateEnergyLimitContract,
Transaction.Contract.ContractType.UPDATEENERGYLIMITCONTRACT,
'UpdateEnergyLimitContract',
options.Permission_id
);
};
const buildAccountPermissionUpdateContract = (value, options) => {
const accountPermissionUpdateContract = new AccountPermissionUpdateContract();
const { owner_address, owner, witness, actives } = value;
accountPermissionUpdateContract.setOwnerAddress(fromHexString(owner_address));
const getType = (type) => {
// no type when permission_name is owner
if (isNaN(type)) return type === 'Active' ? 2 : type === 'Witness' ? 1 : 0;
return type;
};
const buildPermission = (data) => {
// no type when permission_name is owner
const permission = new Permission();
const { type, id, permission_name, threshold, parentId, operations, keys } = data;
permission.setType(getType(type));
permission.setId(id);
permission.setPermissionName(permission_name);
permission.setThreshold(threshold);
if (parentId) {
permission.setParentId(parentId);
}
if (operations) {
permission.setOperations(stringToUint8Array(operations));
}
if (keys) {
permission.setKeysList(
keys.map((key) => {
const keyBuilder = new Key();
keyBuilder.setAddress(fromHexString(key.address));
keyBuilder.setWeight(key.weight);
return keyBuilder;
})
);
}
return permission;
};
if (owner) {
accountPermissionUpdateContract.setOwner(buildPermission(owner));
}
if (witness) {
accountPermissionUpdateContract.setWitness(buildPermission(witness));
}
if (actives) {
if (Array.isArray(actives)) {
accountPermissionUpdateContract.setActivesList(actives.map((active) => buildPermission(active)));
} else {
accountPermissionUpdateContract.setActivesList([buildPermission(actives)]);
}
}
return buildCommonTransaction(
accountPermissionUpdateContract,
Transaction.Contract.ContractType.ACCOUNTPERMISSIONUPDATECONTRACT,
'AccountPermissionUpdateContract',
options.Permission_id
);
};
const buildUpdateAssetContract = (value, options) => {
const updateAssetContract = new UpdateAssetContract();
const { owner_address, description, url, new_limit, new_public_limit } = value;
updateAssetContract.setOwnerAddress(fromHexString(owner_address));
if (description) {
updateAssetContract.setDescription(stringToUint8Array(description.replace(/^0x/, '')));
}
if (url) {
updateAssetContract.setUrl(stringToUint8Array(url.replace(/^0x/, '')));
}
if (new_limit) {
updateAssetContract.setNewLimit(new_limit);
}
if (new_public_limit) {
updateAssetContract.setNewPublicLimit(new_public_limit);
}
return buildCommonTransaction(
updateAssetContract,
Transaction.Contract.ContractType.UPDATEASSETCONTRACT,
'UpdateAssetContract',
options.Permission_id
);
};
const contractJsonToProtobuf = (contract, value, options) => {
switch (contract.type) {
case 'TransferContract':
return buildTransferContract(value, options);
case 'TransferAssetContract':
return buildTransferAssetContract(value, options);
case 'ParticipateAssetIssueContract':
return buildParticipateAssetIssueContract(value, options);
case 'TriggerSmartContract':
return buildTriggerSmartContract(value, options);
case 'FreezeBalanceContract':
return buildFreezeBalanceContract(value, options);
case 'UnfreezeBalanceContract':
return buildUnfreezeBalanceContract(value, options);
case 'WithdrawBalanceContract':
return buildWithdrawBalanceContract(value, options);
case 'FreezeBalanceV2Contract':
return buildFreezeBalanceV2Contract(value, options);
case 'CancelAllUnfreezeV2Contract':
return buildCancelFreezeBalanceV2Contract(value, options);
case 'UnfreezeBalanceV2Contract':
return buildUnfreezeBalanceV2Contract(value, options);
case 'DelegateResourceContract':
return buildDelegateResourceContract(value, options);
case 'UnDelegateResourceContract':
return buildUnDelegateResourceContract(value, options);
case 'WithdrawExpireUnfreezeContract':
return buildWithdrawExpireUnfreezeContract(value, options);
case 'WitnessCreateContract':
return buildCreateWitness(value, options);
case 'VoteWitnessContract':
return buildVoteWitnessAccount(value, options);
case 'CreateSmartContract':
return buildCreateSmartContract(value, options);
case 'ClearABIContract':
return buildClearABIContract(value, options);
case 'UpdateBrokerageContract':
return buildUpdateBrokerageContract(value, options);
case 'AssetIssueContract':
return buildAssetIssueContract(value, options);
case 'AccountCreateContract':
return buildAccountCreateContract(value, options);
case 'AccountUpdateContract':
return buildAccountUpdateContract(value, options);
case 'SetAccountIdContract':
return buildSetAccountIdContract(value, options);
case 'ProposalCreateContract':
return buildProposalCreateContract(value, options);
case 'ProposalDeleteContract':
return buildProposalDeleteContract(value, options);
case 'ProposalApproveContract':
return buildVoteProposalContract(value, options);
case 'ExchangeCreateContract':
return buildExchangeCreateContract(value, options);
case 'ExchangeInjectContract':
return buildExchangeInjectContract(value, options);
case 'ExchangeWithdrawContract':
return buildExchangeWithdrawContract(value, options);
case 'ExchangeTransactionContract':
return buildExchangeTransactionContract(value, options);
case 'UpdateSettingContract':
return buildUpdateSettingContract(value, options);
case 'UpdateEnergyLimitContract':
return buildUpdateEnergyLimitContract(value, options);
case 'AccountPermissionUpdateContract':
return buildAccountPermissionUpdateContract(value, options);
case 'UpdateAssetContract':
return buildUpdateAssetContract(value, options);
}
};
const txJsonToPb = (transaction) => {
const rawData = transaction['raw_data'];
const contractJson = rawData.contract[0];
const data = contractJson.parameter.value;
const options = { Permission_id: contractJson.Permission_id, visible: transaction.visible };
const transactionObj = contractJsonToProtobuf(contractJson, data, options) as any;
const rawDataObj = transactionObj.getRawData();
rawDataObj.setRefBlockBytes(stringToUint8Array(rawData.ref_block_bytes));
rawDataObj.setRefBlockHash(stringToUint8Array(rawData.ref_block_hash));
if (rawData.data) {
rawDataObj.setData(stringToUint8Array(rawData.data));
}
if (rawData.fee_limit) {
rawDataObj.setFeeLimit(rawData.fee_limit);
}
if (rawData.expiration) {
rawDataObj.setExpiration(rawData.expiration);
}
if (rawData.timestamp) {
rawDataObj.setTimestamp(rawData.timestamp);
}
transactionObj.setRawData(rawDataObj);
return transactionObj;
};
const txJsonToPbWithArgs = (transaction, args: any = {}, options: any = {}) => {
const rawData = transaction['raw_data'];
const contractJson = rawData.contract[0];
const transactionObj = contractJsonToProtobuf(contractJson, args, {
Permission_id: args?.Permission_id,
}) as any;
const rawDataObj = transactionObj.getRawData();
rawDataObj.setRefBlockBytes(stringToUint8Array(rawData.ref_block_bytes));
rawDataObj.setRefBlockHash(stringToUint8Array(rawData.ref_block_hash));
// for memo
if (options.data) {
rawDataObj.setData(stringToUint8Array(options.data.replace(/^0x/, '')));
}
if (options.fee_limit || args.fee_limit) {
rawDataObj.setFeeLimit(options.fee_limit || args.fee_limit);
}
if (rawData.expiration) {
rawDataObj.setExpiration(rawData.expiration);
}
if (rawData.timestamp) {
rawDataObj.setTimestamp(rawData.timestamp);
}
transactionObj.setRawData(rawDataObj);
return transactionObj;
};
const compareTransaction = (transaction, transactionPb) => {
const rawDataBytes = transactionPb.getRawData().serializeBinary();
const rawDataHex = byteArray2hexStr(rawDataBytes);
const txID = sha256(rawDataBytes);
return (
rawDataHex.toLowerCase() === transaction.raw_data_hex.toLowerCase() &&
txID.replace(/^0x/, '').toLowerCase() === transaction.txID.replace(/^0x/, '').toLowerCase()
);
};
const txPbToRawDataHex = (pb) => {
return byteArray2hexStr(pb.getRawData().serializeBinary());
};
const txCheck = (transaction) => {
const transactionPb = txJsonToPb(transaction);
return compareTransaction(transaction, transactionPb);
};
const txCheckWithArgs = (transaction, args, options) => {
const transactionPb = txJsonToPbWithArgs(transaction, args, options);
return compareTransaction(transaction, transactionPb);
};
const txPbToTxID = (transactionPb) => {
const rawDataBytes = transactionPb.getRawData().serializeBinary();
const txID = sha256(rawDataBytes);
return txID;
};
const ContractTypeMap = {
'0': 'AccountCreateContract',
'1': 'TransferContract',
'2': 'TransferAssetContract',
'4': 'VoteWitnessContract',
'5': 'WitnessCreateContract',
'6': 'AssetIssueContract',
'9': 'ParticipateAssetIssueContract',
'10': 'AccountUpdateContract',
'11': 'FreezeBalanceContract',
'12': 'UnfreezeBalanceContract',
'13': 'WithdrawBalanceContract',
'15': 'UpdateAssetContract',
'16': 'ProposalCreateContract',
'17': 'ProposalApproveContract',
'18': 'ProposalDeleteContract',
'19': 'SetAccountIdContract',
'30': 'CreateSmartContract',
'31': 'TriggerSmartContract',
'33': 'UpdateSettingContract',
'41': 'ExchangeCreateContract',
'42': 'ExchangeInjectContract',
'43': 'ExchangeWithdrawContract',
'44': 'ExchangeTransactionContract',
'45': 'UpdateEnergyLimitContract',
'46': 'AccountPermissionUpdateContract',
'48': 'ClearABIContract',
'49': 'UpdateBrokerageContract',
'54': 'FreezeBalanceV2Contract',
'55': 'UnfreezeBalanceV2Contract',
'56': 'WithdrawExpireUnfreezeContract',
'57': 'DelegateResourceContract',
'58': 'UnDelegateResourceContract',
'59': 'CancelAllUnfreezeV2Contract',
};
const getAuthsList = (pb) => {
const authsList = pb.getAuthsList();
return authsList.map((authPb) => {
const permission_name = byteArray2hexStr(authPb.getPermissionName_asU8());
const accountPb = authPb.getAccount();
const account = {
name: byteArray2hexStr(accountPb.getName_asU8()),
address: byteArray2hexStr(accountPb.getAddress_asU8()),
};
return {
permission_name,
account,
};
});
}
const DCommonData = (type: string, rawDataHex: string) => {
const pb = Transaction.raw.deserializeBinary(hexStr2byteArray(rawDataHex));
const contract = pb.getContractList()[0];
const valuePb = contract.getParameter().getValue();
const contractType = ContractTypeMap[contract.getType()];
if (type !== contractType) {
throw new Error(`type ${type} dismatches with rawDataHex type ${contractType}`);
}
return [
{
contract: [
{
parameter: {
value: {},
type_url: contract.getParameter().getTypeUrl(),
},
type,
Permission_id: contract.getPermissionId(),
},
],
data: byteArray2hexStr(pb.getData()),
fee_limit: pb.getFeeLimit(),
ref_block_bytes: byteArray2hexStr(pb.getRefBlockBytes_asU8()),
ref_block_hash: byteArray2hexStr(pb.getRefBlockHash_asU8()),
expiration: pb.getExpiration(),
timestamp: pb.getTimestamp(),
scripts: byteArray2hexStr(pb.getScripts_asU8()),
auths: getAuthsList(pb),
},
valuePb,
];
};
const DTriggerSmartContract = (type, rawDataHex) => {
const [commonData, valuePb] = DCommonData(type, rawDataHex);
const triggerSmartContract = TriggerSmartContract.deserializeBinary(valuePb);
commonData.contract[0].parameter.value = {
owner_address: byteArray2hexStr(triggerSmartContract.getOwnerAddress_asU8()),
contract_address: byteArray2hexStr(triggerSmartContract.getContractAddress_asU8()),
call_value: triggerSmartContract.getCallValue(),
data: byteArray2hexStr(triggerSmartContract.getData_asU8()),
call_token_value: triggerSmartContract.getCallTokenValue(),
token_id: triggerSmartContract.getTokenId(),
};
return commonData;
};
const getResourceName = (type) => {
switch (type) {
case 0:
return 'BANDWIDTH';
case 1:
return 'ENERGY';
default:
return 'BANDWIDTH';
}
};
const DFreezeBalanceV2Contract = (type, rawDataHex) => {
const [commonData, valuePb] = DCommonData(type, rawDataHex);
const freezeBalanceV2Contract = FreezeBalanceV2Contract.deserializeBinary(valuePb);
commonData.contract[0].parameter.value = {
owner_address: byteArray2hexStr(freezeBalanceV2Contract.getOwnerAddress_asU8()),
frozen_balance: freezeBalanceV2Contract.getFrozenBalance(),
resource: getResourceName(freezeBalanceV2Contract.getResource()),
};
return commonData;
};
const DUnfreezeBalanceV2Contract = (type, rawDataHex) => {
const [commonData, valuePb] = DCommonData(type, rawDataHex);
const unfreezeBalanceV2Contract = UnfreezeBalanceV2Contract.deserializeBinary(valuePb);
commonData.contract[0].parameter.value = {
owner_address: byteArray2hexStr(unfreezeBalanceV2Contract.getOwnerAddress_asU8()),
unfreeze_balance: unfreezeBalanceV2Contract.getUnfreezeBalance(),
resource: getResourceName(unfreezeBalanceV2Contract.getResource()),
};
return commonData;
};
const DCancelAllUnfreezeV2Contract = (type, rawDataHex) => {
const [commonData, valuePb] = DCommonData(type, rawDataHex);
const cancelAllUnfreezeV2Contract = CancelAllUnfreezeV2Contract.deserializeBinary(valuePb);
commonData.contract[0].parameter.value = {
owner_address: byteArray2hexStr(cancelAllUnfreezeV2Contract.getOwnerAddress_asU8()),
};
return commonData;
};
const DDelegateResourceContract = (type, rawDataHex) => {
const [commonData, valuePb] = DCommonData(type, rawDataHex);
const delegateResourceContract = DelegateResourceContract.deserializeBinary(valuePb);
commonData.contract[0].parameter.value = {
owner_address: byteArray2hexStr(delegateResourceContract.getOwnerAddress_asU8()),
balance: delegateResourceContract.getBalance(),
lock: delegateResourceContract.getLock(),
lock_period: delegateResourceContract.getLockPeriod(),
receiver_address: byteArray2hexStr(delegateResourceContract.getReceiverAddress_asU8()),
resource: getResourceName(delegateResourceContract.getResource())
};
return commonData;
};
const DUnDelegateResourceContract = (type, rawDataHex) => {
const [commonData, valuePb] = DCommonData(type, rawDataHex);
const undelegateResourceContract = UnDelegateResourceContract.deserializeBinary(valuePb);
commonData.contract[0].parameter.value = {
owner_address: byteArray2hexStr(undelegateResourceContract.getOwnerAddress_asU8()),
balance: undelegateResourceContract.getBalance(),
receiver_address: byteArray2hexStr(undelegateResourceContract.getReceiverAddress_asU8()),
resource: getResourceName(undelegateResourceContract.getResource()),
};
return commonData;
};
const DWithdrawExpireUnfreezeContract = (type, rawDataHex) => {
const [commonData, valuePb] = DCommonData(type, rawDataHex);
const withdrawExpireUnfreezeContract = WithdrawExpireUnfreezeContract.deserializeBinary(valuePb);
commonData.contract[0].parameter.value = {
owner_address: byteArray2hexStr(withdrawExpireUnfreezeContract.getOwnerAddress_asU8()),
};
return commonData;
};
const DeserializeTransaction = (type: string, rawDataHex: string) => {
if (!rawDataHex) {
throw new Error('rawDataHex cannot be empty');
}
if (!isHex(rawDataHex)) {
throw new Error('rawDataHex is not a valid hex string');
}
switch (type) {
case 'TriggerSmartContract':
return DTriggerSmartContract(type, rawDataHex);
case 'FreezeBalanceV2Contract':
return DFreezeBalanceV2Contract(type, rawDataHex);
case 'UnfreezeBalanceV2Contract':
return DUnfreezeBalanceV2Contract(type, rawDataHex);
case 'CancelAllUnfreezeV2Contract':
return DCancelAllUnfreezeV2Contract(type, rawDataHex);
case 'DelegateResourceContract':
return DDelegateResourceContract(type, rawDataHex);
case 'UnDelegateResourceContract':
return DUnDelegateResourceContract(type, rawDataHex);
case 'WithdrawExpireUnfreezeContract':
return DWithdrawExpireUnfreezeContract(type, rawDataHex);
default:
throw new Error(`trasaction ${type} not supported`);
}
}
export { txJsonToPb, txPbToTxID, txPbToRawDataHex, txJsonToPbWithArgs, txCheckWithArgs, txCheck,
DeserializeTransaction };