https://github.com/MetaMask/metamask-extension/tree/develop/mascara
找了很多个实例,基本上很少是不使用线上钱包的,只有metamask-extension的mascara实例中实现了,下面是将整个metamask-extension下载下来,进行配置,然后运行的步骤:
进行环境部署:
Building locally
- Install version 8.11.3 and npm version 6.1.0
- If you are using (recommended) running
nvm use
will automatically choose the right node version for you. - Select npm 6.1.0:
npm install -g npm@6.1.0
- If you are using (recommended) running
- Install dependencies:
npm install
- Install gulp globally with
npm install -g gulp-cli
. - Build the project to the
./dist/
folder withgulp build
. - Optionally, to rebuild on file changes, run
gulp dev
. - To package .zip files for distribution, run
gulp zip
, or run the full build & zip withgulp dist
.
Uncompressed builds can be found in /dist
, compressed builds can be found in /builds
once they're built.
运行npm install时出现错误:
Unhandled rejection Error: Command failed: /usr/bin/git checkout 4.0error: pathspec '4.0' did not match any file(s) known to git. at ChildProcess.exithandler (child_process.js:291:12) at ChildProcess.emit (events.js:182:13) at maybeClose (internal/child_process.js:961:16) at Socket.stream.socket.on (internal/child_process.js:380:11) at Socket.emit (events.js:182:13) at Pipe._handle.close (net.js:595:12)
导致这个错误的原因在package.json这个文件中的:
"gulp": "github:gulpjs/gulp#4.0",
将其改成:
"gulp": "4.0",
就好了
再运行npm install,但是后面又出错:
/Users/user/.node-gyp/10.5.0/include/node/node.h:88:20: note: expanded from macro 'NODE_DEPRECATED' __attribute__((deprecated(message))) declarator ^../src/addon.cpp:59:36: error: no matching member function for call to 'NewInstance' info.GetReturnValue().Set(cons->NewInstance(argc... ~~~~~~^~~~~~~~~~~/Users/user/.node-gyp/10.5.0/include/node/v8.h:3914:44: note: candidate function not viable: requires single argument 'context', but 2 arguments were provided V8_WARN_UNUSED_RESULT MaybeLocal
这个原因好像是node版本,我的node版本是10.5.0的问题
后面找到个靠谱的方法,就是将之前的package-lock.json删掉,后面发现删了就好了:
old lock files were preventing us from getting the newer version of sha3 that fixed node 10 support.
之后运行gulp build去生成dist文件夹时也遇见了错误:
gulp buildfs.js:119 throw err; ^Error: ENOENT: no such file or directory, scandir '/Users/user/metamask-extension-8c3091aa7ad31e41e8f62bd5c0b803de45816b0e/node_modules/gulp-sass/node_modules/node-sass/vendor'
解决办法:
说是运行npm rebuild node-sass,如果没有报错,那就是成功了
然后重新运行gulp build,又遇见一个错:
[18:07:02] Did you forget to signal async completion?/Users/user/metamask-extension-8c3091aa7ad31e41e8f62bd5c0b803de45816b0e/gulpfile.js:522 throw err ^Error: Parsing file /Users/user/metamask-extension-8c3091aa7ad31e41e8f62bd5c0b803de45816b0e/node_modules/eth-sig-util/index.js: Identifier 'Buffer' has already been declared (2:8)
解决方法:
到文件处将
const { Buffer } = require('buffer');
注释掉,因为nodejs将Buffer定义为全局变量,不用require,然后再运行gulp build ,然后就成功了,然后就能够看见多了一个dist文件夹
然后就能够运行mascara了:
但是在运行npm run mascara的时候,会出错:
npm run mascara> metamask-crx@0.0.0 mascara /Users/user/metamask-extension-8c3091aa7ad31e41e8f62bd5c0b803de45816b0e> gulp dev:mascara & node ./mascara/example/serverMascara service listening on port 9001Dapp listening on port 9002events.js:167 throw er; // Unhandled 'error' event ^Error: Cannot find module 'uglifyify' from '/Users/user/metamask-extension-8c3091aa7ad31e41e8f62bd5c0b803de45816b0e'
解决办法:npm install uglifyify --save
然后后面再运行npm run mascara就没问题了
但是在浏览器上运行http://localhost:9002时又出现了很多问题
1.找不到proxy.js
在mascara/proxy/index.html 中有:
但是在当前目录下是没有这个文件的,这个文件其实在
mascara/src/proxy.js
解决这个问题的办法是在mascara/server/index.js中添加一行:
server.use(express.static(path.join(__dirname, '/../../src')))
并将
server.use(express.static(path.join(__dirname, '/../proxy')))
注释掉(后面发现其实可以不用注释,下面会说),然后将index.html中写成:
即可
2.添加proxy.js后又出现问题:找不到/script/background.js
出现问题的地方是proxy.js的:
const background = new SwController({ fileName: './script/background.js', keepAlive: true, keepAliveInterval: 30000, keepAliveDelay,})
将其改成'/background.js',即可
3.但是最后还是有一个问题:
Unhandled promise rejection:typeError:undefined is not an object(evaluating 'serviceWorker.postMessage')
我觉得原因是
background.on('ready', () => { const swStream = SwStream({ serviceWorker: background.controller, //这里 context: 'dapp', }) pageStream.pipe(swStream).pipe(pageStream) //serviceWorker.postMessage肯定是这里运行了,但是这个promise出现了问题})
好好看了一下下面这两个模块的实现,去找原因:
const SwController = require('sw-controller')//本博客const SwStream = require('sw-stream/lib/sw-stream.js')//本博客
然后后面看见:
sw-stream/lib/sw-stream.js(这里有serviceWorker.postMessage,那就是说明background.controller.postMessage出了问题)
const PortStream = require('./message-channel-port-stream')module.exports = SericeWorkerStreamfunction SericeWorkerStream({ serviceWorker, context }) { // create message channel for communication const messageChannel = new MessageChannel() // send handshake including port to respond on serviceWorker.postMessage({ action: 'handshake', context }, [messageChannel.port2]) // construct stream around local message channel port const portStream = new PortStream(messageChannel.port1) return portStream}
后面再查看了一下sw-controller的代码,发现它的使用情况与proxy.js上写的有所不同:
const SwController = require('sw-controller')const createSwStream = require('sw-stream')//这里proxy.js上面写的是require('sw-stream/lib/sw-stream.js')const controller = new SwController({ fileName: '/service-worker.js', // optional, scope used when registering service worker scope: '/', // default: true, pings the service worker to keep it alive keepAlive: true,})controller.once('ready', () => { const swStream = createSwStream({ serviceWorker: controller.getWorker(),//这里proxy.js上写的是background.controller,这很有可能就是controller没能真正得到,所以不能够使用postMessage的原因 }) // talk to the service worker})controller.startWorker()
因此后面将proxy.js改为:
const createParentStream = require('iframe-stream').ParentStreamconst SwController = require('sw-controller')// const SwStream = require('sw-stream/lib/sw-stream.js')const SwStream = require('sw-stream')//改了const keepAliveDelay = Math.floor(Math.random() * (30000 - 1000)) + 1000const background = new SwController({ fileName: '/background.js', keepAlive: true, keepAliveInterval: 30000, keepAliveDelay,})const pageStream = createParentStream()background.on('ready', () => { const swStream = SwStream({ // serviceWorker: background.controller, serviceWorker: background.getWorker(),//改了 context: 'dapp', }) pageStream.pipe(swStream).pipe(pageStream)})background.on('updatefound', () => window.location.reload())background.on('error', console.error)background.startWorker()
然后调用npm run mascara:
userdeMacBook-Pro:metamask-extension-8c3091aa7ad31e41e8f62bd5c0b803de45816b0e user$ npm run mascara> metamask-crx@0.0.0 mascara /Users/user/metamask-extension-8c3091aa7ad31e41e8f62bd5c0b803de45816b0e> gulp dev:mascara & node ./mascara/example/serverMascara service listening on port 9001Dapp listening on port 9002Bundle updated! (/Users/user/metamask-extension-8c3091aa7ad31e41e8f62bd5c0b803de45816b0e/mascara/example/app.js)[10:41:31] Using gulpfile ~/metamask-extension-8c3091aa7ad31e41e8f62bd5c0b803de45816b0e/gulpfile.js[10:41:31] Starting 'dev:mascara'...[10:41:31] Starting 'clean'...[10:41:31] Finished 'clean' after 132 ms[10:41:31] Starting 'dev:scss'...[10:41:32] Finished 'dev:scss' after 638 ms[10:41:32] Starting 'dev:mascara:js'...[10:41:32] Starting 'dev:copy'...[10:41:32] Starting 'dev:reload'...[10:41:32] Starting 'dev:mascara:js:ui'...[10:41:32] Starting 'dev:mascara:js:proxy'...[10:41:32] Starting 'dev:mascara:js:background'...[10:41:32] Starting 'dev:mascara:js:metamascara'...[10:41:32] Starting 'dev:copy:locales'...[10:41:32] Starting 'dev:copy:images'...[10:41:32] Starting 'dev:copy:contractImages'...[10:41:32] Starting 'dev:copy:fonts'...[10:41:32] Starting 'dev:copy:reload'...[10:41:32] Starting 'dev:copy:html'...[10:41:32] Starting 'dev:copy:manifest'...[10:41:32] Starting 'dev:copy:html:mascara'...[10:41:32] Finished 'dev:copy:html:mascara' after 89 ms[10:41:32] Finished 'dev:copy:manifest' after 153 ms[10:41:33] Finished 'dev:copy:reload' after 796 ms[10:41:33] Finished 'dev:copy:html' after 1.06 s[10:41:45] Finished 'dev:copy:locales' after 13 s[10:41:49] Finished 'dev:copy:images' after 17 s[10:41:51] 801665 bytes written (18.85 seconds)[10:41:51] Finished 'dev:mascara:js:proxy' after 19 s[10:41:53] 1236552 bytes written (20.51 seconds)[10:41:53] Finished 'dev:mascara:js:metamascara' after 21 s[10:41:59] 10910194 bytes written (27.35 seconds)[10:42:00] Finished 'dev:mascara:js:background' after 28 s[10:42:04] Finished 'dev:copy:contractImages' after 32 s[10:42:05] Finished 'dev:copy:fonts' after 33 s[10:42:05] Starting 'manifest:chrome'...[10:42:05] Finished 'manifest:chrome' after 40 ms[10:42:05] Starting 'manifest:opera'...[10:42:05] Finished 'manifest:opera' after 33 ms[10:42:05] Finished 'dev:copy' after 33 s[10:42:08] 27940940 bytes written (35.72 seconds)[10:42:09] Finished 'dev:mascara:js:ui' after 37 s[10:42:09] Finished 'dev:mascara:js' after 37 s
再在浏览器运行http://localhost:9002
然后就能够惊喜地发现,错误解决了: