您可以使用 Webpacker 在 Rails 6 应用程序中直接使用 Web3.js 吗?
Posted
技术标签:
【中文标题】您可以使用 Webpacker 在 Rails 6 应用程序中直接使用 Web3.js 吗?【英文标题】:Can you use Web3.js directly in a Rails 6 app using Webpacker? 【发布时间】:2020-05-07 19:14:15 【问题描述】:如何通过 Rails 6 应用与本地 Truffle Ganache 区块链进行交互?我已经在 vanilla javascript 中制作了 FixedSupplyToken 应用程序的原型,并且一切都按预期工作。接下来,我尝试将其移动到 Rails 6 应用程序中。我对使用 Ruby gem 感到紧张(ethereum.rb - 正在寻找人来接管维护,其他人似乎被遗弃了)。我想知道您是否可以使用 Webpacker 将 web3.js 直接导入 Rails 6? 我创建了一个新的 Rails 6 应用并添加了以下内容:
yarn add web3
yarn add truffle-contract
都安装并显示在 package.json 中:
"name": "app",
"private": true,
"dependencies":
"@fortawesome/fontawesome-free": "^5.12.0",
"@fortawesome/free-brands-svg-icons": "^5.12.0",
"@fortawesome/free-regular-svg-icons": "^5.12.0",
"@fortawesome/free-solid-svg-icons": "^5.12.0",
"@rails/actioncable": "^6.0.0",
"@rails/actiontext": "^6.0.2-1",
"@rails/activestorage": "^6.0.0",
"@rails/ujs": "^6.0.0",
"@rails/webpacker": "4.2.2",
"bootstrap": "^4.4.1",
"bootswatch": "^4.4.1",
"chart.js": "^2.9.3",
"chartkick": "^3.2.0",
"datatables.net-bs4": "^1.10.20",
"datatables.net-buttons-bs4": "^1.6.1",
"datatables.net-responsive-bs4": "^2.2.3",
"datatables.net-select-bs4": "^1.3.1",
"flatpickr": "^4.6.3",
"jquery": "^3.4.1",
"popper.js": "^1.16.0",
"trix": "^1.0.0",
"truffle-contract": "^4.0.31",
"turbolinks": "^5.2.0",
"vue": "^2.6.11",
"web3": "^1.2.5-rc.0"
,
"version": "0.1.0",
"devDependencies":
"webpack-dev-server": "^3.10.1"
然后我将它添加到 app/javascript/packs (web3/index.js):
// Import libraries we need.
import Web3 from 'web3';
import contract from 'truffle-contract';
// Import our contract artifacts and turn them into usable abstractions.
import token_artifacts from './FixedSupplyToken.json';
// TokenContract is our usable abstraction, which we'll use through the code below.
var TokenContract = contract(token_artifacts);
// The following code is to interact with contracts.
var accounts;
var account;
window.App =
start: function()
var self = this;
// Bootstrap the TokenContract abstraction for Use.
TokenContract.setProvider(web3.currentProvider);
// Get the initial account balance so it can be displayed.
web3.eth.getAccounts(function (err, accs)
if (err != null)
alert("There was an error fetching your accounts.");
return;
if (accs.length == 0)
alert("Couldn't get any accounts! Make sure your Ethereum client is configured correctly.");
return;
accounts = accs;
account = accounts[0];
);
,
initManageToken: function()
App.updateTokenBalance();
App.watchTokenEvents();
,
updateTokenBalance: function()
var tokenInstance;
TokenContract.deployed().then(function (instance)
tokenInstance = instance;
return tokenInstance.balanceOf.call(account);
).then(function (value)
console.log(value);
var balance_element = document.getElementById("balanceTokenInToken");
balance_element.innerhtml = value.valueOf();
).catch(function (e)
console.log(e);
App.setStatus("Error getting balance; see log.");
);
,
watchTokenEvents: function()
var tokenInstance;
TokenContract.deployed().then(function (instance)
tokenInstance = instance;
tokenInstance.allEvents(, fromBlock: 0, toBlock: 'latest').watch(function (error, result)
var alertbox = document.createElement("div");
alertbox.setAttribute("class", "alert alert-info alert-dismissible");
var closeBtn = document.createElement("button");
closeBtn.setAttribute("type", "button");
closeBtn.setAttribute("class", "close");
closeBtn.setAttribute("data-dismiss", "alert");
closeBtn.innerHTML = "<span>×</span>";
alertbox.appendChild(closeBtn);
var eventTitle = document.createElement("div");
eventTitle.innerHTML = '<strong>New Event: ' + result.event + '</strong>';
alertbox.appendChild(eventTitle);
var argsBox = document.createElement("textarea");
argsBox.setAttribute("class", "form-control");
argsBox.innerText = JSON.stringify(result.args);
alertbox.appendChild(argsBox);
document.getElementById("tokenEvents").appendChild(alertbox);
//document.getElementById("tokenEvents").innerHTML += '<div class="alert alert-info alert-dismissible" role="alert"> <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button><div></div><div>Args: '+JSON.stringify(result.args) + '</div></div>';
);
).catch(function (e)
console.log(e);
App.setStatus("Error getting balance; see log.");
);
,
sendToken: function()
var amount = parseInt(document.getElementById("inputAmountSendToken").value);
var receiver = document.getElementById("inputBeneficiarySendToken").value;
App.setStatus("Initiating transaction... (please wait)");
var tokenInstance;
return TokenContract.deployed().then(function (instance)
tokenInstance = instance;
return tokenInstance.transfer(receiver, amount, from: account);
).then(function ()
App.setStatus("Transaction complete!");
App.updateTokenBalance();
).catch(function (e)
console.log(e);
self.setStatus("Error sending coin; see log.");
);
,
allowanceToken: function()
var self = this;
var amount = parseInt(document.getElementById("inputAmountAllowanceToken").value);
var receiver = document.getElementById("inputBeneficiaryAllowanceToken").value;
this.setStatus("Initiating transaction... (please wait)");
var tokenInstance;
return TokenContract.deployed().then(function (instance)
tokenInstance = instance;
return tokenInstance.approve(receiver, amount, from: account);
).then(function ()
self.setStatus("Transaction complete!");
App.updateTokenBalance();
).catch(function (e)
console.log(e);
self.setStatus("Error sending coin; see log.");
);
;
document.addEventListener('load', function()
// Checking if Web3 has been injected by the browser (Mist/MetaMask)
if (typeof web3 !== 'undefined')
console.warn("Using web3 detected from external source. If you find that your accounts don't appear or you have 0 MetaCoin, ensure you've configured that source properly. If using MetaMask, see the following link. Feel free to delete this warning. :) http://truffleframework.com/tutorials/truffle-and-metamask")
// Use Mist/MetaMask's provider
window.web3 = new Web3(web3.currentProvider);
else
console.warn("No web3 detected. Falling back to http://localhost:8545. You should remove this fallback when you deploy live, as it's inherently insecure. Consider switching to Metamask for development. More info here: http://truffleframework.com/tutorials/truffle-and-metamask");
// fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)
window.web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:7545"));
);
然后,当我在 Docker 容器中启动 Rails 6 应用程序时,一切似乎都很好,直到 webpack-dev-server 尝试编译资产并抛出此错误:
webpack-dev-server | ℹ 「wdm」: Compiling...
webpack-dev-server | ✖ 「wdm」: Hash: 8531025c7b3abcc5d778
webpack-dev-server | Version: webpack 4.41.5
webpack-dev-server | Time: 1963ms
webpack-dev-server | Built at: 01/21/2020 4:46:26 PM
webpack-dev-server | Asset Size Chunks Chunk Names
webpack-dev-server | js/application-8df32eacba8ebdbf7444.js 6.49 MiB application [emitted] [immutable] application
webpack-dev-server | js/application-8df32eacba8ebdbf7444.js.map 6.93 MiB application [emitted] [dev] application
webpack-dev-server | manifest.json 1.9 KiB [emitted]
webpack-dev-server | media/images/Logo_medlarge-e2a09f85c0c6ed39d81ce70b3bd44e51.png 130 KiB
webpack-dev-server | media/images/pdf_icon-c00c8db0462b60773a72302f7b9d456b.png 1.36 KiB
webpack-dev-server | media/webfonts/fa-brands-400-088a34f7.eot 129 KiB
webpack-dev-server | media/webfonts/fa-brands-400-273dc9bf.ttf 129 KiB
webpack-dev-server | media/webfonts/fa-brands-400-822d94f1.woff2 74.2 KiB
webpack-dev-server | media/webfonts/fa-brands-400-d7229311.svg 692 KiB
webpack-dev-server | media/webfonts/fa-brands-400-f4920c94.woff 87 KiB
webpack-dev-server | media/webfonts/fa-regular-400-3ac49cb3.eot 33.6 KiB
webpack-dev-server | media/webfonts/fa-regular-400-9efb8697.woff2 13.3 KiB
webpack-dev-server | media/webfonts/fa-regular-400-a57bcf76.woff 16.4 KiB
webpack-dev-server | media/webfonts/fa-regular-400-d2e53334.svg 141 KiB
webpack-dev-server | media/webfonts/fa-regular-400-ece54318.ttf 33.3 KiB
webpack-dev-server | media/webfonts/fa-solid-900-2aa6edf8.ttf 189 KiB
webpack-dev-server | media/webfonts/fa-solid-900-7a5de9b0.svg 829 KiB
webpack-dev-server | media/webfonts/fa-solid-900-7fb1cdd9.eot 190 KiB
webpack-dev-server | media/webfonts/fa-solid-900-93f28454.woff 96.7 KiB
webpack-dev-server | media/webfonts/fa-solid-900-f6121be5.woff2 74.3 KiB
webpack-dev-server |
webpack-dev-server | ERROR in ./app/javascript/web3/index.js 126:22-26
webpack-dev-server | "export 'default' (imported as 'Web3') was not found in 'web3'
webpack-dev-server | at HarmonyImportSpecifierDependency._getErrors (/app/node_modules/webpack/lib/dependencies/HarmonyImportSpecifierDependency.js:109:11)
webpack-dev-server | at HarmonyImportSpecifierDependency.getErrors (/app/node_modules/webpack/lib/dependencies/HarmonyImportSpecifierDependency.js:68:16)
webpack-dev-server | at Compilation.reportDependencyErrorsAndWarnings (/app/node_modules/webpack/lib/Compilation.js:1463:22)
webpack-dev-server | at /app/node_modules/webpack/lib/Compilation.js:1258:10
webpack-dev-server | at AsyncSeriesHook.eval [as callAsync] (eval at create (/app/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:15:1)
webpack-dev-server | at AsyncSeriesHook.lazyCompileHook (/app/node_modules/tapable/lib/Hook.js:154:20)
webpack-dev-server | at Compilation.finish (/app/node_modules/webpack/lib/Compilation.js:1253:28)
webpack-dev-server | at /app/node_modules/webpack/lib/Compiler.js:672:17
webpack-dev-server | at _done (eval at create (/app/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:9:1)
webpack-dev-server | at eval (eval at create (/app/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:32:22)
webpack-dev-server |
webpack-dev-server | ERROR in ./app/javascript/web3/index.js 130:22-26
webpack-dev-server | "export 'default' (imported as 'Web3') was not found in 'web3'
webpack-dev-server | at HarmonyImportSpecifierDependency._getErrors (/app/node_modules/webpack/lib/dependencies/HarmonyImportSpecifierDependency.js:109:11)
webpack-dev-server | at HarmonyImportSpecifierDependency.getErrors (/app/node_modules/webpack/lib/dependencies/HarmonyImportSpecifierDependency.js:68:16)
webpack-dev-server | at Compilation.reportDependencyErrorsAndWarnings (/app/node_modules/webpack/lib/Compilation.js:1463:22)
webpack-dev-server | at /app/node_modules/webpack/lib/Compilation.js:1258:10
webpack-dev-server | at AsyncSeriesHook.eval [as callAsync] (eval at create (/app/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:15:1)
webpack-dev-server | at AsyncSeriesHook.lazyCompileHook (/app/node_modules/tapable/lib/Hook.js:154:20)
webpack-dev-server | at Compilation.finish (/app/node_modules/webpack/lib/Compilation.js:1253:28)
webpack-dev-server | at /app/node_modules/webpack/lib/Compiler.js:672:17
webpack-dev-server | at _done (eval at create (/app/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:9:1)
webpack-dev-server | at eval (eval at create (/app/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:32:22)
webpack-dev-server |
webpack-dev-server | ERROR in ./app/javascript/web3/index.js 130:31-35
webpack-dev-server | "export 'default' (imported as 'Web3') was not found in 'web3'
webpack-dev-server | at HarmonyImportSpecifierDependency._getErrors (/app/node_modules/webpack/lib/dependencies/HarmonyImportSpecifierDependency.js:109:11)
webpack-dev-server | at HarmonyImportSpecifierDependency.getErrors (/app/node_modules/webpack/lib/dependencies/HarmonyImportSpecifierDependency.js:68:16)
webpack-dev-server | at Compilation.reportDependencyErrorsAndWarnings (/app/node_modules/webpack/lib/Compilation.js:1463:22)
webpack-dev-server | at /app/node_modules/webpack/lib/Compilation.js:1258:10
webpack-dev-server | at AsyncSeriesHook.eval [as callAsync] (eval at create (/app/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:15:1)
webpack-dev-server | at AsyncSeriesHook.lazyCompileHook (/app/node_modules/tapable/lib/Hook.js:154:20)
webpack-dev-server | at Compilation.finish (/app/node_modules/webpack/lib/Compilation.js:1253:28)
webpack-dev-server | at /app/node_modules/webpack/lib/Compiler.js:672:17
webpack-dev-server | at _done (eval at create (/app/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:9:1)
webpack-dev-server | at eval (eval at create (/app/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:32:22)
webpack-dev-server | ℹ 「wdm」: Failed to compile.
Websearches 没有发现任何可能的解决方案,我也没有找到任何在 Rails 中使用 Webpacker 使用 web3.js 的示例。可能吗;有什么解决方案或例子吗? 谢谢!
【问题讨论】:
【参考方案1】:我认为这是一个命名冲突。您已将自己的 javascript 文件命名为 web3/index.js
,Webpack 将其视为 web3
;这与您尝试以相同名称导入的节点模块冲突。尝试将您自己的 javascript 文件夹/文件重命名为其他名称。相关问题:https://github.com/webpack/webpack/issues/4817#issuecomment-316119100
【讨论】:
我将 web3 目录重命名为 ethereum,并且 webpack-dev-server 编译时没有任何抱怨。谢谢!以上是关于您可以使用 Webpacker 在 Rails 6 应用程序中直接使用 Web3.js 吗?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Rails 6 和 webpacker 中使用 morris.js?
在 JS 模块中使用 Rails-UJS(带有 webpacker 的 Rails 6)
如何通过 Webpacker 使用 Rails 6.1 安装 Alpine JS 3
Rails 6.0.3.4 [Webpacker] 编译失败