api.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
  2. var Api = function Api(provider) {
  3. var Nat = require("./nat");
  4. var Map = require("./map");
  5. var Bytes = require("./bytes");
  6. var keccak256s = require("./hash").keccak256s;
  7. var send = function send(method) {
  8. return function () {
  9. for (var _len = arguments.length, params = Array(_len), _key = 0; _key < _len; _key++) {
  10. params[_key] = arguments[_key];
  11. }
  12. return new Promise(function (resolve, reject) {
  13. return provider.send(method, params, function (err, result) {
  14. return err ? reject(err) : resolve(result);
  15. });
  16. });
  17. };
  18. };
  19. // TODO check inputs
  20. // TODO move to proper file
  21. var encodeABI = function encodeABI(type, value) {
  22. if (type === "bytes") {
  23. var length = Bytes.length(value);
  24. var nextMul32 = (((length - 1) / 32 | 0) + 1) * 32;
  25. var lengthEncoded = encodeABI("uint256", Nat.fromNumber(length)).data;
  26. var bytesEncoded = Bytes.padRight(nextMul32, value);
  27. return { data: Bytes.concat(lengthEncoded, bytesEncoded), dynamic: true };
  28. } else if (type === "uint256" || type === "bytes32" || type === "address") {
  29. return { data: Bytes.pad(32, value), dynamic: false };
  30. } else {
  31. throw "Eth-lib can't encode ABI type " + type + " yet.";
  32. }
  33. };
  34. var sendTransaction = send("eth_sendTransaction");
  35. var sendRawTransaction = send("eth_sendRawTransaction");
  36. var getTransactionReceipt = send("eth_getTransactionReceipt");
  37. var compileSolidity = send("eth_compileSolidity");
  38. var call = send("eth_call");
  39. var getBalance = send("eth_getBalance");
  40. var accounts = send("eth_accounts");
  41. var removeEmptyTo = function removeEmptyTo(tx) {
  42. return tx.to === "" || tx.to === "0x" ? Map.remove("to")(tx) : tx;
  43. };
  44. var waitTransactionReceipt = getTransactionReceipt; // TODO: implement correctly
  45. var addTransactionDefaults = async function addTransactionDefaults(tx) {
  46. var baseDefaults = [tx.chainId || send("net_version")(), tx.gasPrice || send("eth_gasPrice")(), tx.nonce || send("eth_getTransactionCount")(tx.from, "latest"), tx.value || "0x0", tx.data || "0x"];
  47. var _ref = await Promise.all(baseDefaults),
  48. _ref2 = _slicedToArray(_ref, 5),
  49. chainIdNum = _ref2[0],
  50. gasPrice = _ref2[1],
  51. nonce = _ref2[2],
  52. value = _ref2[3],
  53. data = _ref2[4];
  54. var chainId = Nat.fromNumber(chainIdNum);
  55. var from = tx.from;
  56. var to = tx.to === "" || tx.to === "0x" ? null : tx.to;
  57. var gas = tx.gas ? tx.gas : Nat.div(Nat.mul((await send("eth_estimateGas")({
  58. from: tx.from,
  59. to: tx.to,
  60. value: tx.value,
  61. nonce: tx.nonce,
  62. data: tx.data
  63. })), "0x6"), "0x5");
  64. return {
  65. chainId: chainId,
  66. from: from.toLowerCase(),
  67. to: to.toLowerCase(),
  68. gasPrice: gasPrice,
  69. gas: gas,
  70. nonce: nonce,
  71. value: value,
  72. data: data.toLowerCase()
  73. };
  74. };
  75. var sendTransactionWithDefaults = async function sendTransactionWithDefaults(tx) {
  76. return sendTransaction(removeEmptyTo((await addTransactionDefaults(tx))));
  77. };
  78. var callWithDefaults = function callWithDefaults(tx, block) {
  79. return addTransactionDefaults(tx).then(function (tx) {
  80. return call(removeEmptyTo(tx), block || "latest");
  81. });
  82. };
  83. var callMethodData = function callMethodData(method) {
  84. return function () {
  85. for (var _len2 = arguments.length, params = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
  86. params[_key2] = arguments[_key2];
  87. }
  88. var methodSig = method.name + "(" + method.inputs.map(function (i) {
  89. return i.type;
  90. }).join(",") + ")";
  91. var methodHash = keccak256s(methodSig).slice(0, 10);
  92. var encodedParams = params.map(function (param, i) {
  93. return encodeABI(method.inputs[i].type, param);
  94. });
  95. var headBlock = "0x";
  96. var dataBlock = "0x";
  97. for (var i = 0; i < encodedParams.length; ++i) {
  98. if (encodedParams[i].dynamic) {
  99. var dataLoc = encodedParams.length * 32 + Bytes.length(dataBlock);
  100. headBlock = Bytes.concat(headBlock, Bytes.pad(32, Nat.fromNumber(dataLoc)));
  101. dataBlock = Bytes.concat(dataBlock, encodedParams[i].data);
  102. } else {
  103. headBlock = Bytes.concat(headBlock, encodedParams[i].data);
  104. }
  105. }
  106. return Bytes.flatten([methodHash, headBlock, dataBlock]);
  107. };
  108. };
  109. // Address, Address, ContractInterface -> Contract
  110. var contract = function contract(from, address, contractInterface) {
  111. var contract = {};
  112. contract._address = address;
  113. contract._from = from;
  114. contract.broadcast = {};
  115. contractInterface.forEach(function (method) {
  116. if (method && method.name) {
  117. var _call = function _call(type, value) {
  118. return function () {
  119. var transaction = {
  120. from: from,
  121. to: address,
  122. value: value,
  123. data: callMethodData(method).apply(undefined, arguments)
  124. };
  125. return type === "data" ? Promise.resolve(transaction) : method.constant ? callWithDefaults(transaction) : sendTransactionWithDefaults(transaction).then(type === "receipt" ? waitTransactionReceipt : function (x) {
  126. return x;
  127. });
  128. };
  129. };
  130. contract[method.name] = _call("receipt", "0x0");
  131. if (!method.constant) {
  132. contract[method.name + "_data"] = _call("data", "0x0");
  133. contract[method.name + "_pay"] = function (value) {
  134. return function () {
  135. return _call("receipt", value).apply(undefined, arguments);
  136. };
  137. };
  138. contract[method.name + "_pay_txHash"] = function (value) {
  139. return function () {
  140. return _call("txHash", value).apply(undefined, arguments);
  141. };
  142. };
  143. contract[method.name + "_txHash"] = _call("txHash", "0x0");
  144. }
  145. }
  146. });
  147. return contract;
  148. };
  149. // Address, Bytecode -> TxHash
  150. var deployBytecode_txHash = function deployBytecode_txHash(from, code) {
  151. return sendTransactionWithDefaults({ from: from, data: code, to: "" });
  152. };
  153. // Address, Bytecode -> Receipt
  154. var deployBytecode = function deployBytecode(from, code) {
  155. return deployBytecode_txHash(from, code).then(waitTransactionReceipt);
  156. };
  157. // Address, Bytecode, ContractInterface
  158. var deployBytecodeContract = function deployBytecodeContract(from, code, contractInterface) {
  159. return deployBytecode(from, code).then(function (receipt) {
  160. return contract(from, receipt.contractAddress, contractInterface);
  161. });
  162. };
  163. // Address, String, Address -> Contract
  164. var solidityContract = function solidityContract(from, source, at) {
  165. return compileSolidity(source).then(function (_ref3) {
  166. var abiDefinition = _ref3.info.abiDefinition;
  167. return contract(from, at, abiDefinition);
  168. });
  169. };
  170. // Address, String -> TxHash
  171. var deploySolidity_txHash = function deploySolidity_txHash(from, source) {
  172. return compileSolidity(source).then(function (_ref4) {
  173. var code = _ref4.code;
  174. return deployBytecode_txHash(from, code);
  175. });
  176. };
  177. // Address, String -> Receipt
  178. var deploySolidity = function deploySolidity(from, source) {
  179. return deploySolidity_txHash(from, source).then(waitTransactionReceipt);
  180. };
  181. // Address, String -> Contract
  182. var deploySolidityContract = function deploySolidityContract(from, source) {
  183. return compileSolidity(source).then(function (_ref5) {
  184. var code = _ref5.code,
  185. abiDefinition = _ref5.info.abiDefinition;
  186. return deployBytecodeContract(from, code, abiDefinition);
  187. });
  188. };
  189. return {
  190. send: send,
  191. sendTransaction: sendTransaction,
  192. sendRawTransaction: sendRawTransaction,
  193. getTransactionReceipt: getTransactionReceipt,
  194. call: call,
  195. getBalance: getBalance,
  196. accounts: accounts,
  197. waitTransactionReceipt: waitTransactionReceipt,
  198. addTransactionDefaults: addTransactionDefaults,
  199. sendTransactionWithDefaults: sendTransactionWithDefaults,
  200. callWithDefaults: callWithDefaults,
  201. callMethodData: callMethodData,
  202. contract: contract,
  203. deployBytecode_txHash: deployBytecode_txHash,
  204. deployBytecode: deployBytecode,
  205. deployBytecodeContract: deployBytecodeContract,
  206. compileSolidity: compileSolidity,
  207. solidityContract: solidityContract,
  208. deploySolidity_txHash: deploySolidity_txHash,
  209. deploySolidity: deploySolidity,
  210. deploySolidityContract: deploySolidityContract
  211. };
  212. };
  213. module.exports = Api;