Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Dapp跨平台相容性解決方案

164 views

Published on

傳統開發網頁需要處理不同瀏覽器相容性,在區塊鏈的世界除了瀏覽器外還需處理錢包的相容性 LEADBEST 為早期踏入 Dapp 開發團隊,從剛開始支持熱門錢包外為了讓更多使用者使用陸續踩到不同錢包的技術問題,因此設計了一套跨錢包 Dapp 瀏覽器相容性解決方案

Published in: Technology
  • Be the first to comment

Dapp跨平台相容性解決方案

  1. 1. Dapp跨平台相容性解決方案 2018 JSDC Mars Peng speed0939@gmail.com
  2. 2. Mars Peng (Mars Orange) Experience LEADBEST 資深技術經理 區塊鏈相關產品開發 時間軸(遠時)科技股份有限公司 技術部經理 Friday購物與鮮網開發 時間軸科技股份有限公司 資深工程師 行動裝置跨平台軟體開發以及網站服務開發 超過十年的開發與管理經驗 撰寫多種前後端框架與APP, Ember, Ag, React, Vue, Loopback ... 多次重大系統分析與技術選型
  3. 3. Dapp 不過就是個 WebApp ?
  4. 4. Web2.0
  5. 5. Web3.0
  6. 6. Dapp的所處環境 (desktop) DApp Browser Extention BlockChain
  7. 7. Dapp的所處環境 (mobile) Wallet APP Native Code PKey Manager WebView DApp BlockChain
  8. 8. Web3 & Ethereumjs-tx
  9. 9. Web3 & Provider Web3 Provider Send SendAsync Hook Metamask Blockchain JSON RPC Method
  10. 10. Wallet Web3 Provider Type wallet postMessage customAPI export PKey Metamask ✓ ✗ ✗ Imtoken ✗ ✓ ✗ Trust ✓ ✗ ✗ Edge ✗ ✗ ✓
  11. 11. Post message 是常規 CustomAPI 相對少見 Export PKey 是一把雙面刃 方便 VS 安全
  12. 12. 錢包運作原理 Provider sendAsync Wallet Wallet confirm UI Wallet PKey manager Block chainPost message and register callback with postId Check transaction data Sign transaction Send transaction Callback with postId
  13. 13. Trust Imtoken Metamask
  14. 14. Export PKey Dapp Get PKey Dapp confirm UI Ethereumjs-tx signTransaction Block chain Web3 sendRawTransaction All in the DApp javascript runtime User Input or Edge wallet Check transaction data Sign transaction Send transaction TxHash event or callback
  15. 15. Login WalletInfo 以Edge為例
  16. 16. 以Edge為例 3.send transaction function sendSigned(txData, cb) { const privateKey = ethereumjs.Buffer.Buffer.from('xxx', 'hex') const transaction = new ethereumjs.Tx(txData) transaction.sign(privateKey) const serializedTx = transaction.serialize().toString('hex') web3.eth.sendRawTransaction('0x' + serializedTx, cb) } 1.Edge Wallet Info keys: { dataKey: "" ethereumAddress: "" ethereumKey: "pkey" syncKey: "" } 2.get txCount and create txData web3.eth.getTransactionCount const txData = { nonce: web3.utils.toHex(txCount), gasLimit: web3.utils.toHex(25000), gasPrice: web3.utils.toHex(10e9), // 10 Gwei to: xxx, from: xxx, value: web3.utils.toHex(100000000000000000), chainId: 1 }
  17. 17. 依照投放市場選擇 沒有好不好 只有適不適合
  18. 18. Web3 版本差異 0.X 1.0 return sync http, callback promise event No promievent subscript No Contract events
  19. 19. 我們喜歡 1.0 但不幸的 目前幾乎市面上的錢包都是 Web3 0.x 版的 Provider
  20. 20. Trust Provider sendAsync method sendAsync method switch (payload.method) { // ... case "eth_sign": return this.eth_sign(payload); case "personal_sign": return this.personal_sign(payload); … // } postMessage method function eth_sign(payload) { this.postMessage("signMessage", payload.id, { data: payload.params[1] }); }
  21. 21. Using Web3 1.0.0 for Wallet App Web3 0.20.6 web3.version.getNetwork(function (err, networkId) { return networkTypeName(networkId); }); Web3 1.0.0 window.web3 = new Web3(web3.currentProvider); web3.eth.net.getNetworkType().then(function (networkType) { return networkType; });
  22. 22. Using Web3 1.0.0 for Wallet App (New Rule) if (window.ethereum) { if (!window.web3old) { window.web3 = new Web3(ethereum); // try catch … await ethereum.enable(); } } else if (window.web3) { if (!window.web3old) { window.web3 = new Web3(web3.currentProvider); } } // else … web3.eth.net.getNetworkType().then(function (networkType) { return networkType; });
  23. 23. 原本以為萬無一失 沒想到 不幸的事他又發生了
  24. 24. ImToken Provider sendAsync method sendAsync method else if ('personal_sign' == e.method) { var t = e.params; imToken.callAPI('transaction.personalSign', { message: t[0], address: t[1] } } ImToken 採用自有 SDK 進行呼叫 這會造成既使 web3 成功了 還是會遭到 SDK 阻擋 且2.0的早期版本還必須使用原始的 Provider 無法採用 1.0 API
  25. 25. 為了解決這個問題 我們擴展了web3 0.x版本 使其符合 1.0 API 並對其他錢包進行客製化
  26. 26. Dapp Loaded Metamask Inject Web3 v0.20 Dapp Load Web3 v1.0 Dapp Web3 v1.0 Wrapper Web3 v0.20 Dapp Call Web3 v1.0 Metamask Metamask Support Web3 1.0 Dapp Loaded Imtoken Inject Web3 v0.18 Dapp Load Web3 v1.0 Dapp Web3 v1.0 Wrapper Web3 v0.18 Dapp Call Web3 v1.0 Imtoken Imtoken Not support Web3 1.0 Dapp Load Web3 Extend Leadbest Web3 Extend Call Provider Then Wrapper Returen Promise Imtoken Web3 v0.18 Dapp Load Web3 v0.20 Leadbest Web3 Extend Call Ethereumjs-tx Then Wrapper Returen Promise Browser Web3 Extend Create Web3 v1.0 API Web3 Extend Create Web3 v1.0 API Dapp Load Web3 Extend Imtoken? Edge?
  27. 27. Extend Web3 to 1.0 if (web3.eth.Contract && web3.eth.Contract.constructor) { var contract = new web3.eth.Contract(ltcontract.main.interface); return contract; } else { web3.eth.Contract = function(abi, data) { if (typeof data == 'string') { this.MyContract = web3old.eth.contract(abi); this.contractInstance = this.MyContract.at(addr); coverFactory[`coverContractMethods${getProviderName()}`].call(this, this.contractInstance); return this.contractInstance; } else { this.MyContract = web3old.eth.contract(abi); coverFactory[`coverContractDeploy${getProviderName()}`].call(this, this.MyContract); return this.MyContract; } }; }
  28. 28. coverFactory.coverContractMethods = function(ins) { var self = this; ins.methods = {}; Object.keys(ins).map(function(value) { ins.methods[value] = function() { var obj = {}; var methodData = arguments; // ... call method obj.send = function(sendData) { var promiEvent = Web3PromiEvent(); ins[value].sendTransaction(...methodData, sendData, function(err, result) { if(err) { return promiEvent.reject(err); } promiEvent.eventEmitter.emit('transactionHash', result); promiEvent.resolve(result); }); return promiEvent.eventEmitter; }; return obj; }; });
  29. 29. 相容問題 全是坑 Metamask 不支援 signTransaction Imtoken SDK 檢查不能沒有 to address Trust gas 預估不準確 chiper 吃 cookie coinbase IOS 錯誤沒反應 等等等...
  30. 30. coverFactory.coverContractDployImtoken = function(ins) { ins.deploy = function(deployData) { var obj = {}; obj.send = function(sendData) { var contractData = ins.new.getData(...deployData.arguments, { data: deployData.data }); web3.eth.getTransactionCount(sendData.from, ‘pending', async function (err, txCount) { const txData = createTxData(contractData, txCount); // try catch const pKey = await promiseModal('pKeyModal'); const serializedTx = signTransactionTx(pKey, txData); var confirm = await promiseModal('confirmModal'); web3.eth.sendRawTransaction('0x' + serializedTx, function (err, result) { if (err) { return promiEvent.reject(err); } promiEvent.eventEmitter.emit('transactionHash', result); promiEvent.resolve(result); }) }); } } Imtoken 客製擴展
  31. 31. 我們喜歡 websocket 但不幸的 目前幾乎市面上的錢包都是 Http Provider
  32. 32. WS Provider var poolAddress = this.poolAddress; var web3WS = new Web3(new Web3.providers.WebsocketProvider(this.chainNetworkWS)); // wss://mainnet.infura.io/ws var czEvents = new web3WS.eth.Contract(ERC20Interface, this.tokenAddress); var options = {} czEvents.events.Transfer(options, async (error, event) => { if (error) { console.log(error) return } // some code })
  33. 33. PageInit Server Watch Address Event Block ChainScan Polling Check Set Polling Status On Event Ignore Polling Check Transction Polling Check BlockNumber > 3 Polling Server Get Token Addr Has Polling StatusNo Polling Status Check TxHash
  34. 34. 手機網路斷線甚至當機 交易異常中斷
  35. 35. 三段式交易 ServerAPI 第一段 ServerAPI 第二段 ServerAPI 第三段 Server Transaction Block Chain 1. Ajax Sending Data 2. Metamask 3. Ajax Sending TxHash 4. Sync Chain Polling update UI 5. Polling
  36. 36. 完整方案 Check DApp Browser Load Web3 & Extend Boot Web3 web3 web3old web3WS Check Network Check Account Check Whitelist Get in Plugin Extend extend-imtoken, extend-edge….
  37. 37. We Are Hiring 平面設計師 UI/UX產品設計師 PHP後端工程師(Sr. / Expert) Web前端工程師(Sr. / Expert) 網站可靠性工程師
  38. 38. 區塊鏈菁英交流群募集中Visit our official site! 加好友进入两岸交流群

×