Skip to main content

個人工具箱2018二月

· 4 min read

先記錄下來手邊使用的工具,才有機會從繁雜中歸納出簡單的使用規則。

2011 [^1] 年時紀錄了一次當時的個人工具箱,2016 年開始再次紀錄自己手邊工具箱的改變 [^2] [^3] [^4]🤹。 今年初工作上有了變化,也將家中的環境包含進配置列表中。

主要裝備

  • :computer:Dell XPS 13 (8550), Windows 10, i7 4GHz x4, 8GB RAM, 13.3" LCD,作業系統:Elementary OS + Windows
  • 📱One Plus 3, Android, 6GB RAM, 5.5" AMOLED
  • :headphones:Sony WI-1000 降噪耳機

  • 🖥24" LCD
  • ⌨羅技 K375s 鍵盤
  • 🖱 羅技 M720 滑鼠
  • :package:Synology NAS: 電影,影集,照片,資料備份
  • :bulb:Yeelight LED 燈泡
  • 備用 :computer:Macbook Air 13", 2012 年版
  • 備用 :tv:Chromecast 一代
  • 備用 :speaker:Echodot
  • 備用 Respberry Pi 3
  • 備用 :orange_book:Kindle Voyage

和去年相比的改變:

主力用:computer:Dell XPS 13",家中添購了一台🖥24" LCD 接筆電,搭配 3 轉 1 HDMI Hub,接🎮Nintendo Switch, Chromecast, Respberry Pi,可滿足影音相關需求。HDMI 設備通電時會自動切換到對應的設備。

上次記錄前即開始使用的⌨羅技 K375s 鍵盤與🖱羅技 M720 滑鼠,兩者特點都是同時支援使用 USB 或藍牙控制設備,讓我可以用一套鍵鼠控制多種設備。

🕸網站工具

設計工具

開發工具

  • 編輯器:VS Code
    • Blank Line at the End
    • Diff Tool
    • EditorConfig for VSCode
    • Go
    • Guides: more guide line
    • GitLens: more git info
    • Python
    • Settings Sync
    • solidity
    • Trailing Spaces
  • 版本控制:git
  • 套件管理:apt (Linux), nvm, yarn, Chocolatey(windows)

若需要在 Windows 上開發,能用 Chocolatey 處理的就用 Chocolatey 處理。

娛樂工具

  • 🎮Nintendo Switch
  • :tv:Chromecast (少用)
  • 🎮Steam /vlc (少用)

因為攜帶便利,現在主要只玩 NS 上的遊戲。Steam 上看到喜歡的遊戲,也盡量等 NS 上出了再買。

:iphone:Android 手機應用

  • 瀏覽器:Firefox for Android
  • 網頁更新通知:Web Alert
  • 閱讀:Feedly, Readmoo
  • 稍候閱讀:Pocket
  • 信箱:Inbox, Gmail
  • 地圖:Google 地圖
  • 記事:Keep
  • 內建相機,內建時鐘
  • 相簿:內建相簿,Google 相簿,Dropbox
  • 社交:Facebook, LINE, Twitter
  • 待辦事項:Todoist
  • 密碼管理:Bitwarden
  • 記帳: Toshl
  • 線上影片:Youtube
  • 有聲書:Audible
  • 音樂:豆瓣 FM
  • 健康:小米運動,Pokemon Go, 7Min workout

工具

  • 2 步驟認證:Duo Mobile
  • 旅遊:Google 翻譯,TripAdvisor
  • 影片播放:MX Player, DS video
  • 記錄看書狀況:Readmoo 分享書
  • 線上學習:Udemy, EggHead.io
  • IFTTT
  • 💳街口支付

Reference

如何撰寫智能合約(Smart Contract)?(IV)加入單元測試

· 6 min read

因為智能合約一旦部署就難以修改,因此合約的安全性極其重要,要避免合約中出現一些基礎錯誤,除了透過第三方驗證外,完整地單元測試 (unit test) 也是必需的。

目前最成熟的智能合約單元測試方式,還是透過Truffle開發框架來達成。有趣的是 Truffle 主要使用 Javascript 來撰寫智能合約的單元測試(也可以用 solidity 來寫)。

加入測試

接續上一篇建立的HelloToken合約,在test/目錄下加入test_hello_token.js測試檔案(如果覺得這份程式碼不易理解,可跳過這節,後面會介紹更簡潔的測試方法,到時再回來對照著看)。

var HelloToken = artifacts.require('HelloToken');

const INITIAL_SUPPLY = 100000;
let _totalSupply;

contract('HelloToken', function(accounts) {
it('should met initial supply', function() {
var contract;
HelloToken.deployed().then((instance) => {
contract = instance;
return contract.totalSupply.call();
}).then((totalSupply) => {
_totalSupply = totalSupply;
assert.equal(totalSupply.toNumber(), INITIAL_SUPPLY);
return contract.balanceOf(accounts[0]);
}).then((senderBalance) => {
assert.equal(_totalSupply.toNumber(), senderBalance.toNumber());
});
});
});

運行truffle test可看到測試通過的結果。

Contract: HelloToken
✓ should met initial supply

1 passing (11ms)

講解

var HelloToken = artifacts.require('HelloToken');

artifacts.require的用法和在migrations/中的用法相同,可以直接引入對應的智能合約。

contract('HelloToken', function(accounts) {
it('should met initial supply', function() {
});
});

Truffle 是使用 Javascript 開發中常見的Mocha測試框架和Chai斷言庫來做單元測試。差別只是把 Mocha test 中的 describe換成contract。根據官方文件 [^1],contact執行前會自動重新部署到 testrpc (或測試網路) 上,所以智能合約會是剛部署好乾淨的狀態。

此外,contract也會帶入accounts變數,裡面儲存了 testrpc 或其他你運行的測試網路所提供的帳號,開發者可以直接使用這些帳號來測試合約。

第一個測試是來測部署合約後預設的代幣數目是否正確。

var contract;
HelloToken.deployed().then((instance) => {
contract = instance;
return contract.totalSupply.call();
}).then((totalSupply) => {
...
});

這邊內容和在truffle console中輸入的測試內容雷同,使用Promise來確定每個非同步的操作都在上一個操作完成後才繼續執行。

上一個操作可以透過 return 語句回傳下個操作需要的參數。例如這邊then裡面傳入的totalSupply參數,是來自上一行return contract.totalSupply.call()的結果。

assert.equal(totalSupply.toNumber(), INITIAL_SUPPLY);
...
assert.equal(_totalSupply.toNumber(), senderBalance.toNumber());

這邊我們透過assert.equal語句驗證了HelloToken合約中的初始代幣總額與INITIAL_SUPPLY參數的值相符,且與合約部署者 (accounts[0]) 帳戶中擁有的總額相符。

使用 async/await 簡化測試

要理解這樣的 promise chain 需要一些練習。但其實上面的測試用例中,我們只想做好最後的兩個 assert 驗證。有沒有比較直覺的測試方法呢?

有的!2017 下半年,Javascript 語言支援了async/await語句 [2](只要安裝 Node 7.6 版以上即可使用),可以用更直覺的方式撰寫非同步的程式碼。

智能合約測試剛好也使用大量的非同步程式碼。使用async/await語句改寫後的智能合約測試程式碼如下:

var HelloToken = artifacts.require('HelloToken');

const INITIAL_SUPPLY = 100000;

contract('HelloToken', function(accounts) {
it('should met initial supply', async function() {
let contract = await HelloToken.deployed();
let totalSupply = await contract.totalSupply.call();
let senderBalance = await contract.balanceOf(accounts[0]);
assert.equal(totalSupply.toNumber(), INITIAL_SUPPLY);
assert.equal(totalSupply.toNumber(), senderBalance.toNumbe());
});
});

運行truffle test可看到測試通過的結果。

Contract: HelloToken
✓ should met initial supply

1 passing (11ms)

講解

it('should met initial supply', async function() {
});

要在程式碼中使用 async/await,需要在函式前加入async宣告,這樣解譯器才會解析函式中的await語法。

let contract = await HelloToken.deployed();
let totalSupply = await contract.totalSupply.call();
let senderBalance = await contract.balanceOf(accounts[0]);

透過在非同步的操作前加上await宣告,這三行程式會依照順序,等待第一行 await 語句執行完,取得contract變數後,再依序執行第二行語句。第二行語句執行完,取得totalSupply變數後,再繼續執行第三行語句以取得senderBalance變數。

後面兩個 assert 語句則與 promise 撰寫時完全一樣。這樣改寫後,程式碼的可讀性大大地提昇了!

加入轉帳測試

再透過async/await語句試著加入轉帳測試:

  it('should have right balance after transfer', async function() {
const AMOUNT = 123;
let contract = await HelloToken.deployed();
// check init balance
let account0Balance = await contract.balanceOf(accounts[0]);
let account1Balance = await contract.balanceOf(accounts[1]);
assert.equal(account0Balance.toNumber(), INITIAL_SUPPLY);
assert.equal(account1Balance.toNumber(), 0);
// check balance after transferred
await contract.transfer(accounts[1], AMOUNT);
account0Balance = await contract.balanceOf(accounts[0]);
account1Balance = await contract.balanceOf(accounts[1]);
assert.equal(account0Balance.toNumber(), INITIAL_SUPPLY - AMOUNT);
assert.equal(account1Balance.toNumber(), AMOUNT);
});

運行truffle test可看到測試通過的結果。

Contract: HelloToken
✓ should met initial supply
✓ should have right balance after transfer (92ms)

2 passing (151ms)

講解

let account0Balance = await contract.balanceOf(accounts[0]);
let account1Balance = await contract.balanceOf(accounts[1]);
assert.equal(account0Balance.toNumber(), INITIAL_SUPPLY);
assert.equal(account1Balance.toNumber(), 0);

範例的前半部測試帳號0帳號1中的代幣餘額。帳號0即部署代幣的帳號,因此擁有所有的HelloToken代幣,而帳號1中則沒有HelloToken代幣。

await contract.transfer(accounts[1], AMOUNT);

接著呼叫合約的transfer方法將一些代幣轉入帳號1。注意這些都是非同步的操作(送出傳輸命令後,要先等待區塊鍊確認),因此需要使用await語句。

account0Balance = await contract.balanceOf(accounts[0]);
account1Balance = await contract.balanceOf(accounts[1]);
assert.equal(account0Balance.toNumber(), INITIAL_SUPPLY - AMOUNT);
assert.equal(account1Balance.toNumber(), AMOUNT);

範例的後半部再次測試帳號0帳號1中的代幣餘額。結果符合轉帳後兩個帳戶的預期代幣數額。

結語

async/await語句相當適合拿來寫非同步的程式,這特性太適合用來寫智能合約的測試了。因為async/await這語法太新,所以大部分的參考資料都還在用Promise來撰寫。我建議當你看到相關的智能合約測試時,可以用 async/await 改寫看看,會有很不一樣的感受。

參考資料

[1] Writing Tests in Javascript http://truffleframework.com/docs/getting_started/javascript-tests [2] 6 Reasons Why JavaScript’s Async/Await Blows Promises Away (Tutorial)https://hackernoon.com/6-reasons-why-javascripts-async-await-blows-promises-away-tutorial-c7ec10518dd9

在 Linux 上設定 Ledger Nano S 硬體錢包

· 4 min read

今天已把前陣子買到的 Ledget Nano S 硬體錢包在 Windows 10/Elementary OS (/Ubuntu 16.04) 上設定好,正式開始使用。和預期一樣,雖然在 Linux 上剛開始設定時需要多做一些步驟,但是一旦設定好後,使用過程和在其他平台上並沒有區別。

過去透過 NAS,外接硬碟等方式來保護自己的相片,作品等「數位資產」,以防哪天檔案遺失或外流。現在要守護的範圍更要擴及「加密代幣」,即保護自己的「數位財產」。

MyEtherWallet 網站推薦任何擁有超過「2 周的薪資」數位財產的人,使用「硬體錢包」來保管自己的「加密代幣」,以避免可能的財產損失。

目前 Ledget Nano S 和 TREZOR 是兩款較多人使用的硬體錢包。硬體錢包的安全性從產生錢包帳號開始。硬體錢包帳號的私鑰一直保存在硬體設備中,只要保存好「recovery phase」(Mnemonic Seed),不會發生使用線上交易所時帳號或帳戶中的代幣可能被盜的風險。只有在發送代幣時需要解鎖錢包帳號。解鎖錢包帳號時,輸入 PIN 碼解鎖的過程,也是透過硬體錢包上的按鍵完成,從而避免了所使用的電腦可能已被入侵者安裝鍵盤側錄軟體而造成的財產上的風險。

設定流程

1. 設定 Ledget Nano S 硬體

在 Ledget Nano S 上透過按壓左右兩顆硬體按鈕,設定 4~8 字的 PIN Code 與 24 個單字的「recovery phase」,並用紙筆等實體方式記錄下來(千萬別用拍照的...)。完成後機器會隨機挑幾個次序測試,而你需要選擇對應的單字來確認安全性。如果以後機器壞了或遺失了,仍然可以透過這 24 個單字的「recovery phase」來取回帳號。

2. 在電腦上安裝 Chrome 或 Chromium

因為目前 Ledger Nano S 使用 Chrome App 技術來提供桌面應用程式,Chrome 也是唯一支援WebUSB API的瀏覽器...Google 近期公告 Chrome App 即將被 Progressive Web App 取代,我們拭目以待 Ledger 公司將拿出什麼方案來應對。

3. 安裝 Ledger Manager

前往https://www.ledgerwallet.com/apps/manager安裝 Ledger Manager。

4. 設定 USB 連線

這時開啟 Ledger Manager,將 Ledget Nano S 連線到電腦並解鎖,Ledger Manager 無法找到對應的設備。

這時可以參考What if Ledger Wallet is not recognized on Linux?在命令行環境下輸入以下命令:

wget -q -O - https://www.ledgerwallet.com/support/add_udev_rules.sh | sudo bash

執行後重新將 Ledget Nano S 連線到電腦並解鎖,可以看到 Ledger Manager 開始更新資料。

4. 安裝 Ethereum App

Ledger Manager 與 Ledget Nano S 連線後,除了可以更新韌體之外,也能安裝不同的「加密代幣」App 進 Ledget Nano S。

這邊選擇安裝 Ethereum App。

安裝完成後,在 Ledget Nano S 上可以看到多出一個Ethereum的圖示。

點選進入Ethereum,確認Browser Support選項為No (Ethereum> Settings > Browser Support > No),這樣稍後安裝的 Ledger Wallet Ethereum 才能辨識到 Ledget Nano S。

5. 安裝 Ledger Wallet Ethereum

參考How to install and use Ethereum and Ethereum Classic? 前往https://www.ledgerwallet.com/apps/ethereum下載 Ledger Wallet Ethereum App。

安裝好後重新將 Ledget Nano S 連線到電腦並解鎖,可以看到相關操作界面。

使用 MyEtherWallet 取代 Ledger Wallet Ethereum

若不喜歡使用 App,還可透過 MyEtherWallet 來存取。

參考Moving from MyEtherWallet to LedgerHow to use MyEtherWallet with Ledger 這兩篇設定,將Setting中的Contract DataBrowser support選項都設成Yes

Ethereum > Settings > Contract Data > Yes
Ethereum > Settings > Browser Support > Yes

透過 Chrome 瀏覽器,在 MyEtherWallet 中看到How would you like to access your wallet選項時,選擇Ledger Wallet並在硬體上解鎖即可。

參考資料

Firefox 使用者導覽 (Onboarding)

· 2 min read

隨著 Firefox 56,57 版的推出,我參與製作的 Firefox Onboarding 功能也正式和大眾見面了。

Firefox 56

在 Firefox 56 版中當新使用者開啟瀏覽器時,會看到一個可愛的狐狸頭。 Imgur

點進去可以看到一些功能導覽頁面。 Imgur

點擊導覽頁面右下方的按鈕的話,會聚焦到瀏覽器對應的功能區塊上,使用者可以快速嘗試這些功能。 Imgur

我們也加入了 Web assessibility,使用者可以只用鍵盤來瀏覽整個使用者導覽頁面。

Firefox Quantum (57)

經過使用者研究 (User research),在 Firefox Quantum (57) 版上我們針對 Onboarding 的體驗又做了不小的修改。

這次的更新除了主視覺與一些互動元素都變得不一樣之外,也加了個小彩蛋:新使用者 (全新的 profile) 和從過去版本升級的使用者,所看到的功能導覽項目是不盡相同的喔。

有興趣進一步了解我們怎麼製作 Onboarding Tour,可參考Onboarding 文件

為 Elementary OS 設定中文環境

· 2 min read

在前一篇文章中我已經設定好了雙系統(Elementary OS/Windows 10)開機。在這篇中將繼續把系統的基礎中文環境(中文界面 + 輸入法)設定起來。感謝前路上的貢獻者讓整個過程變得相當容易。

設定好的中文環境如下 Imgur

為什麼要用 Elementary OS?

其實 Ubuntu 等發行版的中文環境已經做得很好,如果使用 Ubuntu 等更成熟的發行版,基礎的中文環境都是預設好開箱即用的。

但我就是任性想用基於 Ubuntu,但是界面看起來更養眼的Elementary OS

調整語系

首先,打開Settings中的Language & Region,在左側Installed Languages選單中將界面切換到中文。並選擇完全安裝(Complete Installation)。

等待安裝好後重新登入,就可以看到全中文界面了。

安裝新酷音輸入法

在安裝好 Elementary OS 0.4.1 後,預設並沒有輸入法選項,但其實內部已安裝了 ibus 輸入法框架。

因為沒有內建輸入法,所以若要使用輸入法,需要自行安裝。

在命令列中輸入以下命令以安裝新酷音輸入法

$ sudo apt update
$ sudo apt install ibus-chewing

安裝好後再輸入ibus-setup,可開啟輸入法設定畫面

$ ibus-setup

在 「輸入法」 分頁底下的 「漢語」 子選單當中可以加入剛安裝的新酷音輸入法。

按「確定」,在設定畫面中可以看到的新酷音輸入法。

最後重要的步驟,就是將切換方式改成個人較習慣的Ctrl+Space

如此一來,就可以在 Elementary OS 上輸入中文啦!這篇文章就是從截圖到文章編輯 / 上傳,全程在已照上述方式安裝好 Elmentary OS 基礎中文環境的筆電上完成的。

fcitx 版

我也試了安裝 fcitx 版本的新酷音

$ sudo apt install fcitx fcitx-chewing

安裝好後使用im-config命令將預設輸入法框架切換成fcitx,重新開機後就可以看到輸入法圖示了。

參考資料