むヌサリアムの開発に没頭。 パヌト3ナヌザヌアプリケヌション

以前の蚘事 パヌト1およびパヌト2 では、自分がノヌドであるこずを気にしない堎合にスマヌトコントラクトで分散アプリケヌションを䜿甚する方法に぀いお説明したした。 しかし、ナヌザヌが远加のアクションを実行するこずを䜙儀なくされるほど、より良い結果が埗られたす。 スマヌトコントラクトを䜿甚するには、プラむベヌトキヌを䜿甚しおトランザクションに眲名する必芁がありたす。そのため、残念ながら、远加のアクションなしでは実行できたせん。 この蚘事では、2぀のアプロヌチを怜蚎したす.1぀目は、Web3ラむブラリずMetaMaskプラグむンを䜿甚したJavaScriptの本栌的な分散アプリケヌションDApp、2぀目は同様のアプリケヌションですが、Ruby on Rails APIずEthereum.rb gemを䜿甚しおブロックチェヌンにアクセスしたす。



実際のDAppがどのように機胜するかを瀺すために、 公匏の䟋に觊発されたアプリケヌションを怜蚎しおください。 投祚ず任意のトランザクションの実行を䌎う民䞻䞻矩の代わりに、誰でもお金゚ヌテルの分配の提案を䜜成し、参加者が投祚し、期限埌に投祚の結果に応じお提案が履行されるかどうかの簡易チャリティコントラクトを䜜成したす。
この堎合のスマヌトコントラクトのロゞックはそれほど重芁ではありたせん。私たちの目暙は、ナヌザヌがブロックチェヌンず察話するためのオプションを瀺すこずです。
䜿甚するツヌルをもう少し詳しく怜蚎し、その埌、アプリケヌションに盎接移動したす。

䜿甚枈みツヌル


1.メタマスク


これはChromeブラりザ甚のプラグむンであり、開発者はFirefoxを蚈画しおいるず曞いおいたすが、これたでのずころChromeのみです。 こちらからダりンロヌドできたす。 プラグむンは2぀のこずを行いたす。


プラグむンの䜿甚方法の詳现に぀いおは、 公匏ペヌゞたたは
ネタバレの䞋
プラグむンでは、䞊郚のネットワヌク名をクリックしお、実際のネットワヌクずテストネットワヌクに接続できたす。



必芁に応じお、既存のキヌをむンポヌトできたすが、新しいキヌを䜜成する方が䟿利です。



GethたたはMistで䜜成されたキヌをむンポヌトする堎合は、むンポヌト時にJSONファむルを遞択し、ディレクトリ〜/ .ethereum / <network> / keystoreで目的のアドレスのファむルを芋぀けたす。 少なくずもこの蚘事の公開時点のUbuntuでは、JSONファむルを開く際にバグがあるこずに泚意しおください。ファむルを遞択するず、MetaMaskりィンドりが閉じおキヌがむンポヌトされたせん。 この堎合、拡匵アドレスchrome-extensionを䜿甚しお別のタブでMetaMaskを開いおみおください//nkbihfbeogaeaoehlefnkodbefgpgknn/popup.html
ずころで、テストネットワヌクを遞択しお[賌入]を抌すず、テストブロヌドキャストを配信するリ゜ヌスぞのリンクを取埗できたす。 Ropstenの堎合でも蛇口から゚ヌテル1をクリックするだけで



2. MetaMaskプラグむンでWeb3.jsラむブラリを䜿甚する


Web3.jsはJavaScriptラむブラリであり、 前の蚘事でGethで䜿甚したものず同じです。 MetaMaskは開いおいるすべおのペヌゞにWeb3.jsを埋め蟌むため、Chrome Developer Toolsのjavascriptコン゜ヌルで簡単なコマンドを盎接テストできたす。 この蚘事の執筆時点で、Web3.jsの珟圚のバヌゞョンは0.20.1であるこずに泚意するこずが重芁です。 バヌゞョン0.xxのドキュメントはこちらから入手できたす 。バヌゞョン1.0のドキュメントず混同しないでください リンク 。
2぀のコマンドを実行したす。1぀はデヌタ䟋アカりント残高を受信し、2぀目は倉曎したすたずえば、 前の蚘事の StringHolderスマヌトコントラクトで文字列を蚭定したす。 たず、MetaMaskでアカりントを䜜成し、目的のネットワヌクこの堎合はRopsten Test Networkに接続し、Developer Toolsコン゜ヌルに移動するこずを忘れないでください。


> web3.eth.getBalance(web3.eth.accounts[0], function(error, result) { console.log(web3.fromWei(result.toNumber())); } ) 

コントラクトメ゜ッドを呌び出すずきは、コヌルバック関数を最埌の匕数ずしお呌び出すこずを忘れないでください。 これを行うこずができたす

 > web3.eth.getBalance(web3.eth.accounts[0], console.log) null e {s: 1, e: 18, c: Array(2)} c:(2) [78950, 84540000000000] e:18 s:1 __proto__:Object 

Web3.jsは、数倀にBigNumberラむブラリを䜿甚したす。 䞊蚘の䟋では、回答は倉換されずに衚瀺されたす。
読み取りコマンドはすぐに実行され、スマヌトコントラクト constantずしおマヌクされおいconstant でデヌタを倉曎する関数を実行する堎合、MetaMaskはトランザクション眲名りィンドりを衚瀺したす。 これに぀いおは、 前の蚘事の StringHolderコントラクトを開き、その䞭のstringメ゜ッドを呌び出しお説明したす。

 > var address = "0x65cA73D13a2cc1dB6B92fd04eb4EBE4cEB70c5eC"; > var abi = [ { "constant": false, "inputs": [ { "name": "newString", "type": "string" } ], "name": "setString", "outputs": [], "payable": false, "type": "function" }, { "constant": true, "inputs": [], "name": "getString", "outputs": [ { "name": "", "type": "string", "value": "Hello World!" } ], "payable": false, "type": "function" } ]; > var contract = web3.eth.contract(abi); > var stringHolder = contract.at(address) > stringHolder.getString(console.log) null "Hello Dolly!!! 22" > stringHolder.setString("Hello from the other side!", console.log) 


setStringメ゜ッドを呌び出した埌、トランザクションずガスず゚ヌテルの掚定コストに関する情報を確認するよう求めるりィンドりが衚瀺されたす。 Submitをクリックしたす。 コン゜ヌルに、トランザクションのハッシュが衚瀺されたす。


しばらくしお、行が倉曎されたこずを確認したす。

 > stringHolder.setString("Hello from the other side!", console.log) "0x4252c00ff25b690846ec8ad3b4266047a75a1708153bcac24066da9cb01e6db5" > stringHolder.getString(console.log) null "Hello from the other side!" 

すべおが正垞に機胜したす。

3. Ethereum.rb


これは、RubyのEthereumブロックチェヌン githubぞのリンク を操䜜するためのラむブラリです。珟時点では、最も積極的にサポヌトされおいたす。
irbコン゜ヌルからStringHolderコントラクトを開いおみたしょう。

 > require “ethereum.rb” > abi = '[ { "constant": false, "inputs": [ { "name": "newString", "type": "string" } ], "name": "setString", "outputs": [], "payable": false, "type": "function" }, { "constant": true, "inputs": [], "name": "getString", "outputs": [ { "name": "", "type": "string", "value": "Hello World!" } ], "payable": false, "type": "function" } ]' > address = "0x65cA73D13a2cc1dB6B92fd04eb4EBE4cEB70c5eC" > contract = Ethereum::Contract.create(name: "StringHolder", address: address, abi: abi) > contract.call.get_string() “Hello from the other side!” 

キャメルケヌスgetStringは自動的にスネヌクケヌスget_stringに倉換されおいるこずに泚意しおください

ここでのメ゜ッド呌び出しの特城は、デヌタを取埗する必芁がある堎合にのみ、getterがcallを介しおcallれるこずです。 トランザクションでは、同期呌び出しの堎合はtransactが、非同期呌び出しの堎合はtransact_and_waitが必芁です。
トランザクションが䜜成されるset_string関数を呌び出しおみたしょう。 2぀の方法がありたすunlockAccount非掚奚ずトランザクションに眲名詳现は埌述。

 > Ethereum::IpcClient.new.personal_unlock_account(Ethereum::IpcClient.new.eth_coinbase["result"], "<>") 

トランザクションの送信者珟圚、ブロックを解陀しおいるものを割り圓おる必芁がありたす。

 > contract.sender = Ethereum::IpcClient.new.eth_coinbase["result"] 

次に、 transact_and_waitたたはtransact代入するtransact_and_wait call 、 call代わりにセッタヌを呌び出すこずができたす。

 > contract.transact_and_wait.set_string(“Hello darkness, my old friend”) 

私たちは終わりを埅っおいたす、私たちは電話したす

 > contract.call.get_string() 

倉曎が衚瀺されたす-すべおが機胜したす。

DAppは䜕をすべきか


問題を定匏化したす。 アカりントを持぀慈善団䜓を衚す契玄が必芁です。 この組織には、寄付の受領者ず提案の投祚者の䞡方ずしお行動できる登録ナヌザヌがいる堎合がありたす。 組織のアカりントから登録枈みアカりントの1぀にお金゚ヌテルを転送するオファヌを䜜成する方法が必芁です。 䞀床にすべおの゚ヌテルを取りたくはないように、制限を導入したす-提䟛できる゚ヌテルは1぀たでです。 次に投祚が行われ「賛成」たたは「反察」投祚できたす、特定の期限プロポヌザルが䜜成された瞬間から5分たでには完了できたせん。 締め切り埌も投祚は匕き続き受け付けられたすが、投祚を完了する機䌚があり、「反察」よりも「賛成」で終わる堎合は、組織のアカりントから受信者のアカりントに空気を移したす。 反察祚があれば-䜕もしたせん。
䞀般に、アプリケヌションスキヌムは次のずおりです。


2぀のjsモゞュヌルBlockchain.jsずBlockchainApi.jsは、ブロックチェヌンの操䜜を担圓したす。 それらは同じこずを行いたす。最初のものはWeb3.jsで動䜜し、MetaMaskノヌドを介しおブロックチェヌンに盎接アクセスし、2぀目はRails APIにajaxリク゚ストを行いたす。 クラむアントアプリケヌション自䜓はReactで蚘述されおおり、䜿甚する2぀のjsモゞュヌルに䟝存したせん。

チャリティ基本契玄


コントラクトは単䞀ファむルの圢匏であるため、特別な展開方法は䜿甚したせん。少なくずもMistを介しお 、少なくずもGethコマンドラむンを䜿甚しお、これを行うこずができたす。 ここからコヌドを䜿甚できたす。 䞀般的に、圌のスキヌムは次のように衚すこずができたす。



論理ブロックのCharity.sol契玄コヌドを怜蚎しおください。 たず、必芁なすべおの倉数の説明がありたす。

  uint public debatingPeriodInMinutes; //    Proposal[] public proposals; //   ,    uint public numProposals; //     proposals uint public numMembers; //    members mapping (address => uint) public memberId; //        members address[] public members; //    

マッピングを䜿甚するず、ナヌザヌのアドレスの配列でむンデックスを取埗できたす。 そのようなアドレスを持぀ナヌザヌが存圚しない堎合、このアドレスを持぀ナヌザヌが登録されおいるかどうかを刀断する関数に基づいお、むンデックス0が返されたす。 しかし、これにより配列の芁件が導入されたす。ナヌザヌはむンデックス1から始たる配列に栌玍する必芁がありたす。このロゞックを担圓するコヌドに぀いおは埌で説明したす。 䞀方、オファヌを保存するための構造がありたす。

  struct Proposal { address recipient; //  uint amount; //   string description; //   uint votingDeadline; //  bool executed; // ,       bool proposalPassed; // ,     uint numberOfVotes; //   int currentResult; //  , ““ = +1, “” = -1 Vote[] votes; //         ,    mapping (address => bool) voted; //    ,     -  } 

投祚の構造は、各文の配列に远加されたす

  struct Vote { bool inSupport; //   address voter; //     } 

ナヌザヌが登録されおいる堎合にのみ、远加されるメ゜ッドの実行が可胜であるこずを制埡できる修食子を怜蚎しおください。 既に述べたように、怜蚌コヌドは、存圚しないマッピング芁玠がむンデックス0䞎えるずいう事実に基づいおおり、むンデックス1から始たるナヌザヌを保存したす。

  modifier onlyMembers { require (memberId[msg.sender] != 0); //       _; //        } 

msgは、呌び出し元に関する情報を取埗できる構造です。 この堎合、 msg.senderは、この修食子を䜿甚しおメ゜ッドを呌び出したアカりントのアドレスです。

デプロむ時に実行されるコントラクトのコンストラクタヌに぀いお説明したす。 蚭定する必芁があるのは、各提案の投祚に割り圓おられた時間だけです。 さらに、メンバヌ配列のサむズを増やしたす。これは、サむズに基づいおナヌザヌを远加し、れロ芁玠が予玄されたたたになるためです。

  function Charity( uint _minutesForDebate ) payable { // payable ,       ,       debatingPeriodInMinutes = _minutesForDebate; members.length++; } 

ナヌザヌを远加する機胜

  function addMember(address _targetMember) { if (memberId[_targetMember] == 0) { // 0  ,     uint id; memberId[_targetMember] = members.length; //       ,     id = members.length++; //       members[id] = _targetMember; //     } } 

require関数に泚意しおください-叀いバヌゞョンのsolidityのthrowを眮き換えたした。 requireにtrueたたはfalseが枡されrequire 、 throwず同様のハンドラヌがトリガヌされ、トランザクション党䜓がロヌルバックされたす。
アドレスがナヌザヌのリストにあるかどうかを確認するには、次の関数を䜿甚したす。

 function isMember( address _targetMember ) constant returns ( bool ) { return ( memberId[_targetMember] != 0 ); } 

次の機胜は、提案を䜜成するこずです。寄付の受取人の䜏所、weiの゚ヌテルの量、および説明行を受け入れたす。 onlyMembers修食子がこの関数に適甚されたす。぀たり、すべおのコヌドが実行される前に、呌び出し元アカりントが登録されおいるかどうかがチェックされたす。 ここでは、 1 etherや1 minutesなどの倉換が衚瀺されたす。 このようなサフィックスの完党なリストはここで芋るこずができたす 。それらは䟿宜䞊䜜成されおおり、倀には適甚できたすが、倉数には適甚できたせん。 しかし、倉数に適甚するには、接尟蟞に1を远加するだけです。これは、この䟋では秒に倉換するために行われたす。

  function newProposal( address _beneficiary, //   uint _weiAmount, //    wei string _description //   ) onlyMembers returns (uint proposalID) { require( _weiAmount <= (1 ether) ); //    1  proposalID = proposals.length++; //     1 Proposal storage p = proposals[proposalID]; //      p.recipient = _beneficiary; p.amount = _weiAmount; p.description = _description; p.votingDeadline = now + debatingPeriodInMinutes * 1 minutes; //          p.executed = false; //     p.proposalPassed = false; p.numberOfVotes = 0; numProposals = proposalID + 1; //    return proposalID; } 

ここで、 nowキヌワヌドは珟圚の時刻ですが、トランザクションが呌び出された時点ではなく、ブロックが䜜成された時点に泚意しおください。 したがっお、締め切りは、プロポヌザルがブロックチェヌンで既に䜜成された瞬間からカりントされたす。

私たちのproposalsはpublicおいるずいう事実にもかかわらず、この方法では、配列の圢匏で最も単玔なフィヌルドのみを取埗できたす。 ぀たり、コントラクトのproposals(1)などのメ゜ッドを呌び出すず、むンデックス1プロポヌザルが配列{ recipient, amount, description, votingDeadline, executed, proposalPassed, numberOfVotes, currentResult }れ、構造内のvotesおよびvoted配列は返されたせん。 しかし、投祚を衚瀺するために、たたは投祚する機䌚を䞎えるために、ナヌザヌが特定の提案に投祚したかどうかに぀いおの情報が必芁です。 そしお、これを1回の呌び出しで行うこずをお勧めしたす。したがっお、音声ステヌタスずオファヌIDを必芁ずするアカりントを受け入れる特別な関数getProposalを䜿甚しお、アプリケヌションで衚瀺するためにProposal構造を読み取るずきにこの情報を取埗したす。

  function getProposal( address _member, uint _proposalNumber ) constant returns ( address, //      uint, string, uint, bool, bool, uint, int, int ) { Proposal memory proposal = proposals[ _proposalNumber ]; //     int vote = getVoted( _member, _proposalNumber ); //    ( )        return ( proposal.recipient, proposal.amount, proposal.description, proposal.votingDeadline, proposal.executed, proposal.proposalPassed, proposal.numberOfVotes, proposal.currentResult, vote ); //        } 

これは、特定のナヌザヌが特定の提案に投祚した方法を探す補助機胜です。 返される倀 0ナヌザヌが投祚しなかった堎合、 1ナヌザヌが「賛成」に投祚した堎合、 -1投祚が「反察」の堎合。

  function getVoted(address _member, uint _proposalNumber) constant returns(int) { Proposal storage p = proposals[_proposalNumber]; int result = 0; int true_int = 1; int false_int = -1; //    for (uint i = 0; i < p.numberOfVotes; i++) { if (p.votes[i].voter == _member) //     { result = p.votes[i].inSupport ? true_int : false_int; break; //       } } return result; } 

投祚特定の番号の提案に぀いおは、真賛成たたは停反察で投祚したす。

  function vote( uint _proposalNumber, //  ,     bool _supportsProposal //  ) onlyMembers returns (uint voteID) { Proposal storage p = proposals[_proposalNumber]; //        require (p.voted[msg.sender] != true); //       p.voted[msg.sender] = true; //     p.numberOfVotes++; //      if (_supportsProposal) { //   “” p.currentResult++; //    1 } else { //   p.currentResult--; //    1 } voteID = p.votes.length++; //       p.votes[voteID] = Vote({inSupport: _supportsProposal, voter: msg.sender}); //   return p.numberOfVotes; } 

最埌の関数executeProposalは、投祚を完了し、受信者のアドレスにexecuteProposalを送信するたたは送信しない機胜をexecuteProposalたす。

  function executeProposal(uint _proposalNumber) { //      Proposal storage p = proposals[_proposalNumber]; require ( !(now < p.votingDeadline || p.executed) ); //   1)  , 2)     p.executed = true; //    if (p.currentResult > 0) { //    “” require ( p.recipient.send(p.amount) ); //    p.proposalPassed = true; // ,    } else { //  “”    p.proposalPassed = false; // ,        } } 

最埌に、payable修食子を持぀空の関数がありたす。

 function () payable {} 

これは、契玄の䜏所に空気を送るために必芁です。 䞀般に空の関数は、関数呌び出しではないすべおのメッセヌゞを受信しお​​凊理する関数です。 私たちがする必芁があるのは、支払い可胜にするこずです。そうすれば、送られたガスは远加のアクションなしで契玄に入金されたす。 ただし、この修食子の他の関数は、この堎合、たずえばaddMember etherを送信できないこずに泚意しおください。

Web3.jsを䜿甚したアプリケヌションのバリ゚ヌション


䞻なアプリケヌションシナリオ

  1. ナヌザヌはMetaMaskを介しおRopstenネットワヌクに接続したす
  2. アカりントに゚ヌテルがない堎合、単䞀のトランザクションを完了するこずは䞍可胜です。 ゚ヌテルを受け取る機胜を远加したした。これは、口座残高が0.1゚ヌテル未満の堎合に利甚可胜になりたす。 これは、ブロヌドキャストの転送先アドレスを䜿甚しおajaxリク゚ストが行われるサヌドパヌティサヌビスを介しお実装されたす。
  3. スマヌトコントラクトを䜿甚した基本アクションは、ナヌザヌが組織のメンバヌになった埌にのみ䜿甚できたす。 これを行うには、スマヌトコントラクトのaddMemberメ゜ッドが呌び出されたす。
  4. 組織のメンバヌは、資金振替の提案以䞋「提案」を䜜成するか、既存の提案に投祚できたす。
  5. プロポヌザルの時間が満了するず䜜成時間+ 5分、プロポヌザルを完了するこずが可胜になりたす。その結果、投祚の分配に応じお、ブロヌドキャストが指定されたアドレスに転送されるかどうかが決たりたす。

アプリケヌションのデモは、 リンク -MetaMaskバヌゞョンで入手できたす。
゜ヌスコヌドはこちらです。

繰り返したすが、Web3.jsの珟圚のバヌゞョンが0.20.1であるずいう事実に泚目しおください。 しかし、バヌゞョン1.0はリリヌスの準備がすでに敎っおおり、その倉曎は非垞に重芁です。 前述したように、MetaMaskはweb3をペヌゞに埋め蟌み、すぐに䜿甚できたす。 しかし、ラむブラリが掻発に開発されおおり、ナヌザヌのアプリケヌションの操䜜性を保蚌する必芁があるずいう事実を考えるず、ロックバヌゞョンを䜿甚し、MetaMaskが埋め蟌むweb3オブゞェクトを再定矩する必芁がありたす。 ここでは、次の方法でこれを行いたす。

  initializeWeb3() { if (typeof web3 !== 'undefined') { //  MetaMask   const defaultAccount = web3.eth.defaultAccount; //    window.web3 = new Web3(web3.currentProvider); //    window.web3.eth.defaultAccount = defaultAccount; //    } } 

window.onloadむベントの埌にこれを行う必芁がありたす。
このコヌドで解決される非自明な問題の1぀は、公匏ドキュメントで提案されおいるようにwindow.web3 = new Web3(web3.currentProvider)を単玔に䜜成するず、デフォルトアカりントが遞択されないこずです。
既に述べたように、MetaMaskでも、リストからネットワヌクを遞択できたす。 Ropstenネットワヌク䞊の契玄アドレスを䜿甚したす。他のネットワヌク䞊のこれらのアドレスに接続しようずするず、結果は予枬できたせん。 したがっお、アプリケヌションぞのアクセスを提䟛する前に、ナヌザヌが同じネットワヌク䞊にいるかどうかを確認する必芁がありたす。 次のコマンドを䜿甚しお、ネットワヌクIDを取埗できたす。

 web3.version.getNetwork(function (err, netId) {}); 

ここでこのチェックを行い、結果をRopstenネットワヌクのidず比范したす-これは3です。

すべおのネットワヌクのIDのリストは、たずえば、net_versionの説明で芋るこずができたす。

ブロックチェヌンを操䜜するためのすべおのロゞックは、 blockchain.jsファむルにありたす。

ここには、ブロックチェヌンからデヌタを受信するための関数ずブロックチェヌン内のデヌタを倉曎する関数の2皮類の関数がありたす。 web3.jsのほずんどのメ゜ッドは非同期に実行され、最埌のパラメヌタヌずしおコヌルバックを受け入れたす。 倚くの堎合、デヌタを取埗するためにいく぀かのメ゜ッドを呌び出す必芁があり、䞀郚のメ゜ッドの呌び出しは他のメ゜ッドの結果に䟝存するため、Promiseを䜿甚するず䟿利です。 web3.jsのバヌゞョン1.0では、非同期メ゜ッドはデフォルトでプロミスを返したす。

ブロックチェヌンから情報を取埗する1぀の䟋を次に瀺したす。
getCurrentAccountInfo関数は、珟圚のアカりントのアドレス、残高、およびこのアカりントが組織のメンバヌであるかどうかのフラグを返したす。

 Blockchain.prototype.getCurrentAccountInfo = function() { const address = this.address; if (address == undefined) { return Promise.resolve({}); } const balancePromise = new Promise(function(resolve, reject) { web3.eth.getBalance(address, function(err, res) { err ? reject(err) : resolve(web3.fromWei(res).toNumber()); }); }); const authorizedPromise = new Promise(function(resolve, reject) { this.contractInstance.isMember(address, function(err, res) { err ? reject(err) : resolve(res); }); }.bind(this)); return new Promise(function(resolve, reject) { Promise.all([balancePromise, authorizedPromise]).then(function(data) { resolve({ address: address, balance: data[0], isMember: data[1] }); }); }); }; 

次に、ブロックチェヌン内のデヌタを倉曎する機胜、たずえば、参加者を組織に远加する機胜を怜蚎したす。

 Blockchain.prototype.becomeMember = function() { return new Promise(function(resolve, reject) { this.contractInstance.addMember(this.address, function(err, res) { err ? reject(err) : resolve(res); }); }.bind(this)); }; 

ご芧のずおり、構文は前の䟋ず倉わりたせん。この関数を実行するだけで、ブロックチェヌン内のデヌタを倉曎するトランザクションが䜜成されたす。
スマヌトコントラクトの関数を呌び出すず、その結果ずしおトランザクションが䜜成され、MetaMaskはこのトランザクションを確認するか拒吊するかをナヌザヌに求めたす。 ナヌザヌがトランザクションを確認するず、関数はトランザクションのハッシュを返したす。
明らかでないポむントの1぀は、トランザクションが成功したかどうかを確認する方法です。
䜿甚されたガスの量に基づいお、トランザクションのステヌタスを刀断できたす。 䜿甚可胜な最倧量のガスが䜿甚されおいる堎合、実行䞭に゚ラヌが発生したか、トランザクションを完了するのに十分なガスがありたせんでした。 次のようにステヌタスを確認したす。

 Blockchain.prototype.checkTransaction = function(transaction) { const txPromise = new Promise(function(resolve, reject) { web3.eth.getTransaction(transaction.transactionHash, function(err, res) { err ? reject(err) : resolve(res); }); }); const txReceiptPromise = new Promise(function(resolve, reject) { web3.eth.getTransactionReceipt(transaction.transactionHash, function(err, res) { err ? reject(err) : resolve(res); }); }); return new Promise(function(resolve, reject) { Promise.all([txPromise, txReceiptPromise]).then(function(res) { const tx = res[0]; const txReceipt = res[1]; const succeeded = txReceipt && txReceipt.blockNumber && txReceipt.gasUsed < tx.gas; const failed = txReceipt && txReceipt.blockNumber && txReceipt.gasUsed == tx.gas; let state = transactionStates.STATE_PENDING; if (succeeded) { state = transactionStates.STATE_SUCCEEDED; } else if (failed) { state = transactionStates.STATE_FAILED; } resolve(state); }); }); }; 


, localStorage , . — transactions-storage.js .

Ruby on Rails ethereum.rb


- , . , . , , , . - , . . , web3.js, , . Ruby on Rails, ethereum.rb, , web3.js.

— Rails API .
゜ヌスコヌドはこちらです。

ethereum.rb, , blockchain.js. , , , .

— , . , , LocalStorage , API.

:

  1. Create Account, , , .
  2. API auth token .
  3. .

js , — , . — .

 def proposals(address=nil) count = @contract_instance.call.num_proposals to = count - 1 from = count > PROPOSALS_LIMIT ? count - PROPOSALS_LIMIT : 0 res = (from..to).map do |idx| proposal = if address @contract_instance.call.get_proposal(address, idx) else @contract_instance.call.proposals(idx) end Proposal.new(proposal, idx) end res.sort_by(&:index).reverse end 

, — , . Eth . .

  def self.new_account new_key = Eth::Key.new return new_key.address.downcase, new_key.private_hex end def signed_transactions(private_key_hex) key = Eth::Key.new priv: private_key_hex #     @contract_instance.key = key #         res = yield(@contract_instance) #    @contract_instance.key = nil #      res end 

signed_transactions — , .
, Eth. key . ethereum.rb key . , , , .

signed_transactions Proposal, executeProposal :

  def finish_proposal(proposal_index, options={}) tx = signed_transactions(options[:private_key]) do |contract_instance| contract_instance.transact.execute_proposal(proposal_index) end tx.id end 

. , js .

 def transaction_status(tx_hash) tx = @client.eth_get_transaction_by_hash(tx_hash)['result'] tx_receipt = @client.eth_get_transaction_receipt(tx_hash)['result'] if tx_receipt block_number = tx_receipt['blockNumber'] gas_used = tx_receipt['gasUsed'].to_i(16) gas = tx['gas'].to_i(16) { succeeded: block_number && gas_used < gas, failed: block_number && gas_used == gas } end end 



.
- , — 0xe79d8738f0769ec69f09cef4cd497c9cc477733e — Ropsten.

結果は䜕ですか


, . Ruby MetaMask . , , , javascript ruby. .
. !

Ethereum:
1:
2: Web3.js

Source: https://habr.com/ru/post/J339080/


All Articles