index.js 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. // load network.js to get network/chain id
  2. document.body.appendChild(Object.assign(document.createElement("script"), { type: "text/javascript", src: "./network.js" }));
  3. // load web3modal to connect to wallet
  4. document.body.appendChild(Object.assign(document.createElement("script"), { type: "text/javascript", src: "./web3/lib/web3modal.js" }));
  5. // load web3js to create transactions
  6. document.body.appendChild(Object.assign(document.createElement("script"), { type: "text/javascript", src: "./web3/lib/web3.min.js" }));
  7. // uncomment to enable torus wallet
  8. // document.body.appendChild(Object.assign(document.createElement("script"), { type: "text/javascript", src: "https://unpkg.com/@toruslabs/torus-embed" }));
  9. // uncomment to enable walletconnect
  10. document.body.appendChild(Object.assign(document.createElement("script"), { type: "text/javascript", src: "https://unpkg.com/@walletconnect/web3-provider@1.8.0/dist/umd/index.min.js" }));
  11. // load web3gl to connect to unity
  12. window.web3gl = {
  13. networkId: 0,
  14. connect,
  15. connectAccount: "",
  16. signMessage,
  17. signMessageResponse: "",
  18. callContract,
  19. callContractResponse:"",
  20. callContractError:"",
  21. sendTransaction,
  22. sendTransactionResponse: "",
  23. sha3Message,
  24. hashMessageResponse: "",
  25. ecRecover,
  26. ecRecoverAddressResponse:"",
  27. sendTransactionResponse: "",
  28. sendTransactionData,
  29. sendTransactionResponseData:"",
  30. sendContract,
  31. sendContractResponse: "",
  32. };
  33. // will be defined after connect()
  34. let provider;
  35. let web3;
  36. /*
  37. paste this in inspector to connect to wallet:
  38. window.web3gl.connect()
  39. */
  40. async function connect() {
  41. // uncomment to enable torus and walletconnect
  42. const providerOptions = {
  43. // torus: {
  44. // package: Torus,
  45. // },
  46. // walletconnect: {
  47. // package: window.WalletConnectProvider.default,
  48. // options: {
  49. // infuraId: "00000000000000000000000000000000",
  50. // },
  51. // },
  52. };
  53. const web3Modal = new window.Web3Modal.default({
  54. providerOptions,
  55. });
  56. web3Modal.clearCachedProvider();
  57. // set provider
  58. provider = await web3Modal.connect();
  59. web3 = new Web3(provider);
  60. // set current network id
  61. web3gl.networkId = parseInt(provider.chainId);
  62. // if current network id is not equal to network id, then switch
  63. if (web3gl.networkId != window.web3ChainId) {
  64. try {
  65. await window.ethereum.request({
  66. method: "wallet_switchEthereumChain",
  67. params: [{ chainId: `0x${window.web3ChainId.toString(16)}` }], // chainId must be in hexadecimal numbers
  68. });
  69. } catch {
  70. // if network isn't added, pop-up metamask to add
  71. await addEthereumChain();
  72. }
  73. }
  74. // set current account
  75. // provider.selectedAddress works for metamask and torus
  76. // provider.accounts[0] works for walletconnect
  77. web3gl.connectAccount = provider.selectedAddress || provider.accounts[0];
  78. // refresh page if player changes account
  79. provider.on("accountsChanged", (accounts) => {
  80. window.location.reload();
  81. });
  82. // update if player changes network
  83. provider.on("chainChanged", (chainId) => {
  84. web3gl.networkId = parseInt(chainId);
  85. });
  86. }
  87. /*
  88. Will calculate the sha3 of the input.
  89. */
  90. async function sha3Message(message) {
  91. try {
  92. const hashedMessage = await web3.utils.sha3(message);
  93. window.web3gl.hashMessageResponse = hashedMessage;
  94. } catch (error) {
  95. window.web3gl.hashMessageResponse = error.message;
  96. }
  97. }
  98. /*
  99. Will recover the address of signer
  100. */
  101. async function ecRecover(message,signature) {
  102. try {
  103. const recoverAddress = await web3.eth.accounts.recover(message, signature);
  104. window.web3gl.ecRecoverAddressResponse = recoverAddress;
  105. } catch (error) {
  106. window.web3gl.ecRecoverAddressResponse = error.message;
  107. }
  108. }
  109. /*
  110. paste this in inspector to connect to sign message:
  111. window.web3gl.signMessage("hello")
  112. */
  113. async function signMessage(message) {
  114. try {
  115. const from = (await web3.eth.getAccounts())[0];
  116. const signature = await web3.eth.personal.sign(message, from, "");
  117. console.log(signature);
  118. window.web3gl.signMessageResponse = signature;
  119. } catch (error) {
  120. window.web3gl.signMessageResponse = error.message;
  121. }
  122. }
  123. /*
  124. paste this in inspector to send eth:
  125. const to = "0xdD4c825203f97984e7867F11eeCc813A036089D1"
  126. const value = "12300000000000000"
  127. const gasLimit = "21000" // gas limit
  128. const gasPrice = "33333333333"
  129. window.web3gl.sendTransaction(to, value, gasLimit, gasPrice);
  130. */
  131. async function sendTransaction(to, value, gasLimit, gasPrice) {
  132. const from = (await web3.eth.getAccounts())[0];
  133. web3.eth
  134. .sendTransaction({
  135. from,
  136. to,
  137. value,
  138. gas: gasLimit ? gasLimit : undefined,
  139. gasPrice: gasPrice ? gasPrice : undefined,
  140. })
  141. .on("transactionHash", (transactionHash) => {
  142. window.web3gl.sendTransactionResponse = transactionHash;
  143. })
  144. .on("error", (error) => {
  145. window.web3gl.sendTransactionResponse = error.message;
  146. });
  147. }
  148. /*
  149. paste this in inspector to send eth:
  150. const to = "0x20E7D0C4182149ADBeFE446E82358A2b2D5244e9"
  151. const value = "0"
  152. const gasPrice = "1100000010"
  153. const gasLimit = "228620" // gas limit
  154. const data = "0xd0def521000000000000000000000000d25b827d92b0fd656a1c829933e9b0b836d5c3e20000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002e516d586a576a6a4d55387233395543455a38343833614e6564774e5246524c767656396b7771314770436774686a000000000000000000000000000000000000"
  155. window.web3gl.sendTransactionData(to, value, gasPrice, gasLimit, data);
  156. */
  157. async function sendTransactionData(to, value, gasPrice, gasLimit, data) {
  158. const from = (await web3.eth.getAccounts())[0];
  159. web3.eth
  160. .sendTransaction({
  161. from,
  162. to,
  163. value,
  164. gasPrice: gasPrice ? gasPrice : undefined,
  165. gas: gasLimit ? gasLimit : undefined,
  166. data: data ? data : undefined,
  167. })
  168. .on("transactionHash", (transactionHash) => {
  169. window.web3gl.sendTransactionResponseData = transactionHash;
  170. })
  171. .on("error", (error) => {
  172. window.web3gl.sendTransactionResponseData = error.message;
  173. });
  174. }
  175. /*
  176. calls a non-mutable contract method.
  177. const method = "x"
  178. const abi = `[ { "inputs": [], "name": "increment", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "x", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" } ]`;
  179. const contract = "0xB6B8bB1e16A6F73f7078108538979336B9B7341C"
  180. const args = "[]"
  181. window.web3gl.callContract(method, abi, contract, args)
  182. */
  183. async function callContract(method, abi, contract, args) {
  184. const from = (await web3.eth.getAccounts())[0];
  185. new web3.eth.Contract(JSON.parse(abi), contract).methods[method](
  186. ...JSON.parse(args)
  187. ).call()
  188. .then((result) => window.web3gl.callContractResponse = result)
  189. .catch((error) => window.web3gl.callContractError = error.message);
  190. }
  191. /*
  192. paste this in inspector to connect to interact with contract:
  193. const method = "increment"
  194. const abi = `[ { "inputs": [], "name": "increment", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "x", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" } ]`;
  195. const contract = "0xB6B8bB1e16A6F73f7078108538979336B9B7341C"
  196. const args = "[]"
  197. const value = "0"
  198. const gasLimit = "222222" // gas limit
  199. const gasPrice = "333333333333"
  200. window.web3gl.sendContract(method, abi, contract, args, value, gasLimit, gasPrice)
  201. */
  202. async function sendContract(method, abi, contract, args, value, gasLimit, gasPrice) {
  203. const from = (await web3.eth.getAccounts())[0];
  204. new web3.eth.Contract(JSON.parse(abi), contract).methods[method](...JSON.parse(args))
  205. .send({
  206. from,
  207. value,
  208. gas: gasLimit ? gasLimit : undefined,
  209. gasPrice: gasPrice ? gasPrice : undefined,
  210. })
  211. .on("transactionHash", (transactionHash) => {
  212. window.web3gl.sendContractResponse = transactionHash;
  213. })
  214. .on("error", (error) => {
  215. window.web3gl.sendContractResponse = error.message;
  216. });
  217. }
  218. // add new wallet to in metamask
  219. async function addEthereumChain() {
  220. const account = (await web3.eth.getAccounts())[0];
  221. // fetch https://chainid.network/chains.json
  222. const response = await fetch("https://chainid.network/chains.json");
  223. const chains = await response.json();
  224. // find chain with network id
  225. const chain = chains.find((chain) => chain.chainId == window.web3ChainId);
  226. const params = {
  227. chainId: "0x" + chain.chainId.toString(16), // A 0x-prefixed hexadecimal string
  228. chainName: chain.name,
  229. nativeCurrency: {
  230. name: chain.nativeCurrency.name,
  231. symbol: chain.nativeCurrency.symbol, // 2-6 characters long
  232. decimals: chain.nativeCurrency.decimals,
  233. },
  234. rpcUrls: chain.rpc,
  235. blockExplorerUrls: [chain.explorers && chain.explorers.length > 0 && chain.explorers[0].url ? chain.explorers[0].url : chain.infoURL],
  236. };
  237. await window.ethereum
  238. .request({
  239. method: "wallet_addEthereumChain",
  240. params: [params, account],
  241. })
  242. .catch(() => {
  243. // I give up
  244. window.location.reload();
  245. });
  246. }