index.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import { TronWeb } from '../../tronweb.js';
  2. import utils from '../../utils/index.js';
  3. import { Method } from './method.js';
  4. export class Contract {
  5. tronWeb;
  6. abi;
  7. address;
  8. eventListener;
  9. bytecode;
  10. deployed;
  11. lastBlock;
  12. methods;
  13. methodInstances;
  14. props;
  15. constructor(tronWeb, abi = [], address) {
  16. if (!tronWeb || !(tronWeb instanceof TronWeb))
  17. throw new Error('Expected instance of TronWeb');
  18. this.tronWeb = tronWeb;
  19. this.address = address;
  20. this.abi = abi;
  21. this.eventListener = false;
  22. this.bytecode = false;
  23. this.deployed = false;
  24. this.lastBlock = false;
  25. this.methods = {};
  26. this.methodInstances = {};
  27. this.props = [];
  28. if (utils.address.isAddress(address)) {
  29. this.deployed = true;
  30. }
  31. else {
  32. this.address = false;
  33. }
  34. this.loadAbi(abi);
  35. }
  36. hasProperty(property) {
  37. // eslint-disable-next-line no-prototype-builtins
  38. return this.hasOwnProperty(property) || this.__proto__.hasOwnProperty(property);
  39. }
  40. loadAbi(abi) {
  41. this.abi = abi;
  42. this.methods = {};
  43. this.props.forEach((prop) => delete this[prop]);
  44. abi.forEach((func) => {
  45. // Don't build a method for constructor function. That's handled through contract create.
  46. // Don't build a method for error function.
  47. if (!func.type || /constructor|error/i.test(func.type))
  48. return;
  49. const method = new Method(this, func);
  50. const methodCall = method.onMethod.bind(method);
  51. const { name, functionSelector, signature } = method;
  52. this.methods[name] = methodCall;
  53. this.methods[functionSelector] = methodCall;
  54. this.methods[signature] = methodCall;
  55. this.methodInstances[name] = method;
  56. this.methodInstances[functionSelector] = method;
  57. this.methodInstances[signature] = method;
  58. if (!this.hasProperty(name)) {
  59. this[name] = methodCall;
  60. this.props.push(name);
  61. }
  62. if (!this.hasProperty(functionSelector)) {
  63. this[functionSelector] = methodCall;
  64. this.props.push(functionSelector);
  65. }
  66. if (!this.hasProperty(signature)) {
  67. this[signature] = methodCall;
  68. this.props.push(signature);
  69. }
  70. });
  71. }
  72. decodeInput(data) {
  73. const methodName = data.substring(0, 8);
  74. const inputData = data.substring(8);
  75. if (!this.methodInstances[methodName])
  76. throw new Error('Contract method ' + methodName + ' not found');
  77. const methodInstance = this.methodInstances[methodName];
  78. return {
  79. name: methodInstance.name,
  80. params: this.methodInstances[methodName].decodeInput(inputData),
  81. };
  82. }
  83. async new(options, privateKey = this.tronWeb.defaultPrivateKey) {
  84. const address = this.tronWeb.address.fromPrivateKey(privateKey);
  85. const transaction = await this.tronWeb.transactionBuilder.createSmartContract(options, address);
  86. const signedTransaction = await this.tronWeb.trx.sign(transaction, privateKey);
  87. const contract = await this.tronWeb.trx.sendRawTransaction(signedTransaction);
  88. if (contract.code) {
  89. throw {
  90. error: contract.code,
  91. message: this.tronWeb.toUtf8(contract.message),
  92. };
  93. }
  94. await utils.sleep(3000);
  95. return this.at(signedTransaction.contract_address);
  96. }
  97. async at(contractAddress) {
  98. try {
  99. const contract = await this.tronWeb.trx.getContract(contractAddress);
  100. if (!contract.contract_address) {
  101. throw new Error('Unknown error: ' + JSON.stringify(contract, null, 2));
  102. }
  103. this.address = contract.contract_address;
  104. this.bytecode = contract.bytecode;
  105. this.deployed = true;
  106. this.loadAbi(contract.abi ? (contract.abi.entrys ? contract.abi.entrys : []) : []);
  107. return this;
  108. }
  109. catch (ex) {
  110. if (ex.toString().includes('does not exist')) {
  111. throw new Error('Contract has not been deployed on the network');
  112. }
  113. throw new Error(ex);
  114. }
  115. }
  116. }
  117. export { Method } from './method.js';
  118. //# sourceMappingURL=index.js.map