factory.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import { Interface } from "../abi/index.js";
  2. import { getCreateAddress } from "../address/index.js";
  3. import { concat, defineProperties, getBytes, hexlify, assert, assertArgument } from "../utils/index.js";
  4. import { BaseContract, copyOverrides, resolveArgs } from "./contract.js";
  5. // A = Arguments to the constructor
  6. // I = Interface of deployed contracts
  7. /**
  8. * A **ContractFactory** is used to deploy a Contract to the blockchain.
  9. */
  10. export class ContractFactory {
  11. /**
  12. * The Contract Interface.
  13. */
  14. interface;
  15. /**
  16. * The Contract deployment bytecode. Often called the initcode.
  17. */
  18. bytecode;
  19. /**
  20. * The ContractRunner to deploy the Contract as.
  21. */
  22. runner;
  23. /**
  24. * Create a new **ContractFactory** with %%abi%% and %%bytecode%%,
  25. * optionally connected to %%runner%%.
  26. *
  27. * The %%bytecode%% may be the ``bytecode`` property within the
  28. * standard Solidity JSON output.
  29. */
  30. constructor(abi, bytecode, runner) {
  31. const iface = Interface.from(abi);
  32. // Dereference Solidity bytecode objects and allow a missing `0x`-prefix
  33. if (bytecode instanceof Uint8Array) {
  34. bytecode = hexlify(getBytes(bytecode));
  35. }
  36. else {
  37. if (typeof (bytecode) === "object") {
  38. bytecode = bytecode.object;
  39. }
  40. if (!bytecode.startsWith("0x")) {
  41. bytecode = "0x" + bytecode;
  42. }
  43. bytecode = hexlify(getBytes(bytecode));
  44. }
  45. defineProperties(this, {
  46. bytecode, interface: iface, runner: (runner || null)
  47. });
  48. }
  49. attach(target) {
  50. return new BaseContract(target, this.interface, this.runner);
  51. }
  52. /**
  53. * Resolves to the transaction to deploy the contract, passing %%args%%
  54. * into the constructor.
  55. */
  56. async getDeployTransaction(...args) {
  57. let overrides = {};
  58. const fragment = this.interface.deploy;
  59. if (fragment.inputs.length + 1 === args.length) {
  60. overrides = await copyOverrides(args.pop());
  61. }
  62. if (fragment.inputs.length !== args.length) {
  63. throw new Error("incorrect number of arguments to constructor");
  64. }
  65. const resolvedArgs = await resolveArgs(this.runner, fragment.inputs, args);
  66. const data = concat([this.bytecode, this.interface.encodeDeploy(resolvedArgs)]);
  67. return Object.assign({}, overrides, { data });
  68. }
  69. /**
  70. * Resolves to the Contract deployed by passing %%args%% into the
  71. * constructor.
  72. *
  73. * This will resolve to the Contract before it has been deployed to the
  74. * network, so the [[BaseContract-waitForDeployment]] should be used before
  75. * sending any transactions to it.
  76. */
  77. async deploy(...args) {
  78. const tx = await this.getDeployTransaction(...args);
  79. assert(this.runner && typeof (this.runner.sendTransaction) === "function", "factory runner does not support sending transactions", "UNSUPPORTED_OPERATION", {
  80. operation: "sendTransaction"
  81. });
  82. const sentTx = await this.runner.sendTransaction(tx);
  83. const address = getCreateAddress(sentTx);
  84. return new BaseContract(address, this.interface, this.runner, sentTx);
  85. }
  86. /**
  87. * Return a new **ContractFactory** with the same ABI and bytecode,
  88. * but connected to %%runner%%.
  89. */
  90. connect(runner) {
  91. return new ContractFactory(this.interface, this.bytecode, runner);
  92. }
  93. /**
  94. * Create a new **ContractFactory** from the standard Solidity JSON output.
  95. */
  96. static fromSolidity(output, runner) {
  97. assertArgument(output != null, "bad compiler output", "output", output);
  98. if (typeof (output) === "string") {
  99. output = JSON.parse(output);
  100. }
  101. const abi = output.abi;
  102. let bytecode = "";
  103. if (output.bytecode) {
  104. bytecode = output.bytecode;
  105. }
  106. else if (output.evm && output.evm.bytecode) {
  107. bytecode = output.evm.bytecode;
  108. }
  109. return new this(abi, bytecode, runner);
  110. }
  111. }
  112. //# sourceMappingURL=factory.js.map