ウェブサイトからブロックチェーンにアクセスしてみる

ウェブサイトからブロックチェーンにアクセスしてみる:


はじめに



image.png


 前回の記事ではイーサリアムで動くフリマアプリのスマートコントラクトを作成しました.Remix(スマートコントラクトの総合開発環境)からフリマアプリを実行することは可能ですが,一般ユーザーには敷居が高いかもしれません.そこでフリマアプリにアクセスするためのウェブページのプロトタイプを作ってみました.まだ一般ユーザーに使ってもらい易いデザインには全くなっていないのですが笑,これから良くしていこうと思っています...(゚ー゚;A

 この記事ではコントラクトをテストネットワークに公開し,ウェブサイトからアクセスするところまでをご紹介したいと思います.


環境構築


MetaMask

MetaMaskはイーサリアム用のウォレットアプリで,これを使うとイーサリアムの送金やコントラクトの実行が簡単にできます.インストール方法についてはたくさん記事が出ていますので,割愛します.例えば以下を参考にして下さい.

 MetaMask(メタマスク)の使い方まとめ!入出金・トークン追加も超簡単


Web3js

Web3jsはjavaScriptからブロックチェーン上の情報にアクセスするためのライブラリです.Web3jsのGitHubからソースコード一式のzipファイルをダウンロードします.解凍するとweb3.js-develop\distにweb3.min.jsというファイルがありますので,ワーキングフォルダを作成し,そこにコピペして下さい.


Remix

現在コントラクトの開発にはsolidityという言語が最も使われています.Remixはsolidityの総合開発環境でブラウザ上で動くので,インストール作業はありません.以下にアクセスして下さい.

 https://remix.ethereum.org


テスト用のコントラクト

以下は名簿を作成するためのコントラクトです.ユーザーのウォレットアドレス,名前,Emailアドレスを記録します.このコントラクトをテストネットワークに公開し,ウェブサイトからアクセス出来るようにします。

pragma solidity ^0.4.23; 
 
contract registerAccount{ 
 
    uint public numAccount; // アカウント番号 
 
    // コンストラクタ 
    constructor() public { 
        numAccount = 0; 
    } 
 
    // アカウント情報を記録する構造体 
    struct account { 
        address addr; // ウォレットアドレス 
        string name;  // 名前 
        string email; // Emailアドレス 
    } 
    mapping(uint => account) public accounts; 
 
    // アカウント情報を登録する関数 
    function register(string _name, string _email) public { 
        accounts[numAccount].addr = msg.sender; 
        accounts[numAccount].name = _name; 
        accounts[numAccount].email = _email; 
        numAccount++; 
    } 
} 
ここで,RemixのJavaScript VMでコントラクトを実行してみます.JavaScript VMはコントラクトを疑似的に実行する環境で,ブロックチェーンへの書き込みは行われません.またマイニングを行わないので処理が高速で,デバックに便利です。


image.png


 Remixを起動したら上図を参考にしてコントラクトをコピペして下さい.次に右上のRunタブを選択し,実行環境がJavaScript VMになっていることを確認してます."Deploy"をクリックすると,右下にコントラクトが表示されます.
image.png


 コントラクトを選択すると,関数と変数の一覧が表示されます.registerに適当な名前とEmailを入力し"transact"をクリックしてみて下さい.その後accountsの"call"をクリックすると,情報が保存されていることが分かります.


コントラクトをテストネットにデプロイする

JavaScript VMでコントラクトの動作が確認できたら,イーサリアムのテストネットにコントラクトを公開します.イーサリアムにはライブネットとテストネットがあり,テストネットはコントラクトの動作確認を行うための環境です.よって,テストネット上で取引される仮想通貨は日本円やドルと交換することはできません.

 まずは,MetaMaskを起動し,Ropstenテストネットワークに接続して下さい.


image.png


 コントラクトの公開や実行にはRopstenテストネットワークのEtherが必要です.以下の方法でEtherを取得します.
image.png


 "振込"をクリックし,次に"ETHERを取得する"をクリックします.
image.png


 "request 1 ether from faucet"をクリックして下さい.しばらく待つとウォレットに1etherが入金されます.

 MetaMaskを起動し,Ropstenテストネットワークに接続した状態でRemixを開いてください.RunタブのEmvironmentはinjected Web3を選択します.Ropstenテストネットワークに接続されていれば,右側にRopstenと表示されるはずです.
image.png


 次に"Deploy"をクリックします.ここで,MetaMaskが起動し,以下の様な画面が表示されるはずです."確認"をクリックすれば,コントラクトがテストネットワークに公開されます.
image.png


 Remixからコントラクトを実行する方法はJavaScript VMの場合と同じですが,実行にはetherを消費します.試しにregisterを実行してみて下さい.MetaMaskが起動するはずです.なお,変数の取得にはetherはいらないので,MetaMaskは起動しません.


コントラクトにアクセスするウェブページを作成する


入力フォームを作る

まずは入力フォームを表示するhtmlファイルを作ります.ブラウザで表示するとこんな感じです.


image.png


registerAccount.html
<!DOCTYPE html> 
<html> 
<title>registerAccount</title> 
<head> 
<meta charset="UTF-8"> 
<script language="javascript" type="text/javascript" src="web3.min.js"></script> 
<script language="javascript" type="text/javascript" src="registerAccountAbi.js"></script> 
<script language="javascript" type="text/javascript" src="registerAccount.js"></script> 
</head> 
<body> 
    ユーザー名:<br> 
    <input name="UserName" id="UserName" type="text" value="" /><br> 
    Eメールアドレス:<br> 
    <input name="UserEmail" id="UserEmail" type="email" value="" /><br> 
    <p><button onclick="registerInfo()">登録</button></p><br> 
    アカウント番号:<br> 
    <input name="NumAccount" id="NumAccount" type="number" value="" /><br> 
    <p><button onclick="showInfo()">アカウント情報表示</button></p><br> 
    <ul id="AccountInfo"></ul> 
</body> 
</html> 


スクリプトを書く

スクリプトの解説は需要があれば追記しようと思います.ご不明な点があればコメントまたはご連絡下さい.m(__)m

registerAccount.js
// メタマスクがインストールされているかのチェック 
if (typeof web3 !== 'undefined') { 
    web3js = new Web3(web3.currentProvider); 
} else { 
    alert("MetaMaskをインストールして下さい."); 
} 
 
// メタマスクのアドレスを取得する 
web3js.eth.getAccounts(function(err, accounts) { 
    coinbase = accounts[0]; 
    console.log("coinbase is " + coinbase); 
    if (typeof coinbase === 'undefined') { 
        alert("MetaMaskを起動してください.") 
    } 
}); 
 
// コントラクトのアドレス 
const address = "0x89b88f608febd2e58c2be995e77e437c43ba1c7a"; 
 
// コントラクトのインスタンスを生成 
contract = new web3js.eth.Contract(abi, address); 
 
// アカウント登録する関数 
function registerInfo() { 
    // テキストボックスに入力されている情報を取得する 
    var UserName = document.getElementById("UserName").value; 
    var UserEmail = document.getElementById("UserEmail").value; 
 
    // コントラクトの呼び出し 
    return contract.methods.register(UserName, UserEmail) 
    .send({ from: coinbase }) 
    .on("receipt", function(receipt){ 
        console.log("success"); 
    }) 
    .on("error", function(error){ 
            console.log("error");  
    }); 
} 
 
// アカウント情報を表示する関数 
function showInfo() { 
    var NumAccount = document.getElementById("NumAccount").value; 
    // 表示されている情報を空にする 
    sl = document.getElementById('AccountInfo'); 
    while(sl.lastChild) { 
        sl.removeChild(sl.lastChild); 
    } 
 
    // 変数を取得する 
    contract.methods.accounts(NumAccount).call().then(function(account){ 
        for (var i = 0; i < Object.keys(account).length/2; i++) { 
            var li = document.createElement('li'); 
            li.textContent = Object.keys(account)[i+Object.keys(account).length/2] + " : " + account[i]; 
            document.getElementById('AccountInfo').appendChild(li); 
        } 
    }); 
} 


ABIを取得する

ABIにはコントラクトの変数や関数,パラメーターなどがどのようにやり取りするのかが記録されており,コントラクトの実行や変数の取得に必要な情報です.ABIはRemixから取得できます.CompileタブのABIをクリックするとABIがクリップボードにコピーされます.registerAccount.jsという名前で保存してください.

 

image.png


registerAccountAbi.js
var abi = [ 
    { 
        "constant": false, 
        "inputs": [ 
            { 
                "name": "_name", 
                "type": "string" 
            }, 
            { 
                "name": "_email", 
                "type": "string" 
            } 
        ], 
        "name": "register", 
        "outputs": [], 
        "payable": false, 
        "stateMutability": "nonpayable", 
        "type": "function" 
    }, 
    { 
        "constant": true, 
        "inputs": [], 
        "name": "numAccount", 
        "outputs": [ 
            { 
                "name": "", 
                "type": "uint256" 
            } 
        ], 
        "payable": false, 
        "stateMutability": "view", 
        "type": "function" 
    }, 
    { 
        "constant": true, 
        "inputs": [ 
            { 
                "name": "", 
                "type": "uint256" 
            } 
        ], 
        "name": "accounts", 
        "outputs": [ 
            { 
                "name": "addr", 
                "type": "address" 
            }, 
            { 
                "name": "name", 
                "type": "string" 
            }, 
            { 
                "name": "email", 
                "type": "string" 
            } 
        ], 
        "payable": false, 
        "stateMutability": "view", 
        "type": "function" 
    }, 
    { 
        "inputs": [], 
        "payable": false, 
        "stateMutability": "nonpayable", 
        "type": "constructor" 
    } 
] 


ウェブページの動作確認

以上で作成した3つのファイルとweb3.min.jsをワーキングフォルダに保存します.動作確認するにあたり1つ注意点があります.MetaMaskを起動した状態でWeb3ライブラリを使用しているウェブサイトを開くと,MetaMaskが接続しているネットワークが自動的に検出されます.ところが,registerAccount.htmlをダブルクリックで開いてしまうと,ftp接続されてしまいネットワークが検出されず,ブロックチェーンの情報を取得することができません.

 そこでMONGOOSE WEB SERVERを使ってregisterAccount.htmlにhttp接続します.以下から

MONGOOSE FREE EDITIONをダウンロードして下さい.

 https://cesanta.com/binary.html

使い方は簡単で,ダウンロードしたexeファイルをワーキングフォルダに保存し起動します.ワーキングフォルダ内のファイル一覧がブラウザに表示されますので,registerAccount.htmlを選択してください.


image.png


 これでregisterAccount.htmlからアカウントの登録とアカウント情報の表示ができるはずです.
image.png



フリマアプリのウェブページソースコード

これまでの内容を応用して作ったのが,フリマアプリにアクセスするためのWebページです.ソースコードは以下になります.

KappaMarket.html
<!DOCTYPE html> 
<html> 
<title>Kappaマーケット</title> 
<head> 
<meta charset="UTF-8"> 
<script language="javascript" type="text/javascript" src="web3.min.js"></script> 
<script language="javascript" type="text/javascript" src="KappaMarketAbi.js"></script> 
<script language="javascript" type="text/javascript" src="KappaMarket.js"></script> 
</head> 
<body> 
    <b>はじめに</b><br> 
    コントラクトの実行にはMetaMaskが必要です.<br> 
    このアプリはRopstenテストネット上で動いています.<br> 
    <table cellpadding="15"> 
        <tr valign="top"> 
            <td> 
                <p><b>アカウント登録</b><br> 
                最初にユーザー登録をして下さい.<br> 
                ユーザー名とEメールアドレスを入力し,登録ボタンをクリックして下さい.<br> 
                ※これはテストですが,登録内容は公開されるので個人情報は入力しないで下さい.<br> 
                <br> 
                ユーザー名:<br> 
                <input name="UserName" id="UserName" type="text" value="" /><br> 
                Eメールアドレス:<br> 
                <input name="UserEmail" id="UserEmail" type="email" value="" /><br> 
                <button onclick="registerAccount()">登録</button><br></p> 
            </td> 
        </tr> 
    </table> 
 
    <table cellpadding="15"> 
        <tr valign="top"> 
            <td> 
                <p><b>商品表示</b><br> 
                商品番号を入力しボタンをクリック<br> 
                すると出品されている商品の情報が<br> 
                表示されます.<br> 
                <br> 
                商品番号:<br> 
                <input name="showItem" id="showItem" type="number" value="" /><br> 
                <button onclick="showItem()">商品情報表示</button><br></p> 
                <button onclick="showImageGoogle()">googleドライブで商品画像表示</button><br></p> 
                ※IPFSで商品画像を表示する場合は<br> 
                予めIPFSのdaemonを起動して下さい.<br> 
                <button onclick="showImageIpfs()">IPFSで商品画像表示</button><br></p> 
                <ul id="Item"></ul> 
                <img id="Image"><br> 
            </td> 
 
            <td> 
                <p><b>アカウント情報表示</b><br> 
                ウォレットアドレスを入力しボタンを<br> 
                クリックするとアカウント情報が表示<br> 
                されます.<br> 
                <br> 
                アカウントアドレス:<br> 
                <input name="Address" id="Address" type="text" value="" /><br> 
                <button onclick="showAccount()">アカウント情報表示</button><br></p> 
                <ul id="Account"></ul> 
            </td> 
        </tr> 
    </table> 
 
    <table cellpadding="15"> 
        <tr valign="top"> 
            <td> 
                <p><b>1.出品</b><br> 
                商品情報を入力し出品ボタンをクリックします.<br> 
                <br> 
                商品名:<br> 
                <input name="ItemName" id="ItemName" type="text" value="" /><br> 
                商品説明:<br> 
                <textarea name="Description" id="Description" type="text" rows="4" cols="40" value=""></textarea><br> 
                商品価格(wei):<br> 
                <input name="Price" id="Price" type="number" value="" /><br> 
                商品画像の登録:<br> 
                GoogleドライブのファイルID:<br> 
                <input name="GoogleID" id="GoogleID" type="text" value="" /><br> 
                IPFSのファイルハッシュ:<br> 
                <input name="IPFSHash" id="IPFSHash" type="text" value="" /><br> 
                <button onclick="sell()">出品</button><br></p> 
            </td> 
 
            <td> 
                <p><b>2.購入</b><br> 
                購入したい商品の商品番号と価格を入力し,<br> 
                ボタンをクリックして下さい.<br> 
                ※料金は一旦コントラクトに預けられます.<br> 
                <br> 
                商品番号:<br> 
                <input name="NumItem" id="NumItem" type="number" value="" /><br> 
                価格(wei):<br> 
                <input name="BuyPrice" id="BuyPrice" type="number" value="" /><br> 
                <button onclick="buy()">購入</button><br></p> 
            </td> 
        </tr> 
    </table> 
 
    <table cellpadding="15"> 
        <tr valign="top"><td><b> 
            3.出品者と購入者は商品の送付に必要な情報をEメールで交換して下さい. 
        </b></td></tr> 
    </table> 
 
    <table cellpadding="15"> 
        <tr valign="top"> 
            <td> 
                <p><b>4.発送連絡</b><br> 
                出品者は商品の発送が完了したら,<br> 
                商品番号を指定し発送連絡します.<br> 
                <br> 
                商品番号:<br> 
                <input name="Ship" id="Ship" type="number" value="" /><br> 
                <button onclick="ship()">発送連絡</button><br></p> 
            </td> 
 
            <td> 
                <p><b>5.受取連絡</b><br> 
                購入者は商品の受取が完了したら,<br> 
                商品番号を指定し受取連絡します.<br> 
                ※受取連絡が完了するとコントラクト<br> 
                に預けられていた料金が出品者に支払<br> 
                われます.<br> 
                <br> 
                商品番号:<br> 
                <input name="Receive" id="Receive" type="number" value="" /><br> 
                <button onclick="receive()">受取連絡</button><br></p> 
            </td> 
        </tr> 
 
        <tr valign="top"> 
            <td> 
                <p><b>6.出品者を評価</b><br> 
                商品番号:<br> 
                <input name="Item-a" id="Item-a" type="number" value="" /><br> 
                評価値(-2から2の整数):<br> 
                <input name="SellerEvaluate" id="SellerEvaluate" type="number" value="" /><br> 
                <button onclick="sellerEvaluate()">出品者を評価</button><br></p> 
            </td> 
 
            <td> 
                <p><b>6.購入者を評価</b><br> 
                商品番号:<br> 
                <input name="Item-b" id="Item-b" type="number" value="" /><br> 
                評価値(-2から2の整数):<br> 
                <input name="BuyerEvaluate" id="BuyerEvaluate" type="number" value="" /><br> 
                <button onclick="buyerEvaluate()">購入者を評価</button><br></p> 
            </td> 
        </tr> 
    </table> 
</body> 
</html> 
KappaMarket.js
// メタマスクがインストールされているかのチェック 
if (typeof web3 !== 'undefined') { 
    web3js = new Web3(web3.currentProvider); 
} else { 
    alert("MetaMaskをインストールして下さい."); 
} 
 
// コントラクトを呼び出すアカウントのアドレス 
web3js.eth.getAccounts(function(err, accounts) { 
    coinbase = accounts[0]; 
    console.log("coinbase is " + coinbase); 
    if (typeof coinbase === 'undefined') { 
        alert("MetaMaskを起動してください.") 
    } 
}); 
 
// コントラクトのアドレス 
const address = "0x0a7e85e162ca77a7ef28c368fb342efab8a8f4c4"; 
 
// コントラクトのインスタンスを生成 
contract = new web3js.eth.Contract(abi, address); 
 
// アカウント登録 
function registerAccount() { 
    var UserName = document.getElementById("UserName").value; 
    var UserEmail = document.getElementById("UserEmail").value; 
 
    return contract.methods.registerAccount(UserName, UserEmail) 
    .send({ from: coinbase }) 
    .on("receipt", function(receipt){ 
        console.log("success"); 
    }) 
    .on("error", function(error){ 
            console.log("error");  
    }); 
} 
 
// 出品 
function sell() { 
    var ItemName = document.getElementById("ItemName").value; 
    var Description = document.getElementById("Description").value; 
    var Price = document.getElementById("Price").value; 
    var googleID = document.getElementById("GoogleID").value; 
    var IPFSHash = document.getElementById("IPFSHash").value; 
 
    return contract.methods.sell(ItemName, Description, Price, googleID, IPFSHash) 
    .send({ from: coinbase }) 
    .on("receipt", function(receipt){ 
        console.log("success"); 
    }) 
    .on("error", function(error){ 
            console.log("error");  
    }); 
} 
 
// 購入 
function buy() { 
    var NumItem = document.getElementById("NumItem").value; 
    var BuyPrice = document.getElementById("BuyPrice").value; 
 
    return contract.methods.buy(NumItem) 
    .send({ from: coinbase, value: BuyPrice }) 
    .on("receipt", function(receipt){ 
        console.log("success"); 
    }) 
    .on("error", function(error){ 
            console.log("error");  
    }); 
} 
 
// 発送連絡 
function ship() { 
    var NumItem = document.getElementById("Ship").value; 
 
    return contract.methods.ship(NumItem) 
    .send({ from: coinbase }) 
    .on("receipt", function(receipt){ 
        console.log("success"); 
    }) 
    .on("error", function(error){ 
            console.log("error");  
    }); 
} 
 
// 受取連絡 
function receive() { 
    var NumItem = document.getElementById("Receive").value; 
 
    return contract.methods.receive(NumItem) 
    .send({ from: coinbase }) 
    .on("receipt", function(receipt){ 
        console.log("success"); 
    }) 
    .on("error", function(error){ 
            console.log("error");  
    }); 
} 
 
// 出品者を評価 
function sellerEvaluate() { 
    var NumItem = document.getElementById("Item-a").value; 
    var SellerEvaluate = document.getElementById("SellerEvaluate").value; 
 
    return contract.methods.sellerEvaluate(NumItem, SellerEvaluate) 
    .send({ from: coinbase }) 
    .on("receipt", function(receipt){ 
        console.log("success"); 
    }) 
    .on("error", function(error){ 
            console.log("error");  
    }); 
} 
 
// 購入者を評価 
function buyerEvaluate() { 
    var NumItem = document.getElementById("Item-b").value; 
    var BuyerEvaluate = document.getElementById("BuyerEvaluate").value; 
 
    return contract.methods.buyerEvaluate(NumItem, BuyerEvaluate) 
    .send({ from: coinbase }) 
    .on("receipt", function(receipt){ 
        console.log("success"); 
    }) 
    .on("error", function(error){ 
            console.log("error");  
    }); 
} 
 
// 商品を表示する 
function showItem() { 
    var NumItem = document.getElementById("showItem").value; 
 
    sl = document.getElementById('Item'); 
    while(sl.lastChild) { 
        sl.removeChild(sl.lastChild); 
    } 
 
    contract.methods.items(NumItem).call().then(function(item){ 
        for (var i = 0; i < Object.keys(item).length/2; i++) { 
            var li = document.createElement('li'); 
            li.textContent = Object.keys(item)[i+Object.keys(item).length/2] + " : " + item[i]; 
            document.getElementById('Item').appendChild(li); 
        } 
    }); 
 
    contract.methods.images(NumItem).call().then(function(image){ 
        for (var i = 0; i < Object.keys(image).length/2; i++) { 
            var li = document.createElement('li'); 
            li.textContent = Object.keys(image)[i+Object.keys(image).length/2] + " : " + image[i]; 
            document.getElementById('Item').appendChild(li); 
        } 
    }); 
} 
 
// googleドライブで商品画像を表示 
function showImageGoogle(){ 
    var NumItem = document.getElementById("showItem").value; 
    var imageUrl; 
    contract.methods.images(NumItem).call().then(function(image){ 
        imageUrl = "http://drive.google.com/uc?export=view&id=" + image.googleDocID; 
        var win = window.open(imageUrl, '_blank'); 
        console.log(imageUrl); 
    }); 
} 
 
// IPFSで商品画像を表示 
function showImageIpfs(){ 
    var NumItem = document.getElementById("showItem").value; 
    var imageUrl; 
    contract.methods.images(NumItem).call().then(function(image){ 
        imageUrl = "http://localhost:8080/ipfs/" + image.ipfsHash; 
        var win = window.open(imageUrl, '_blank'); 
        console.log(imageUrl); 
    }); 
} 
 
// アカウント情報を表示する 
function showAccount() { 
    var Address = document.getElementById("Address").value; 
 
    sl = document.getElementById('Account'); 
    while(sl.lastChild) { 
        sl.removeChild(sl.lastChild); 
    } 
 
    contract.methods.accounts(Address).call().then(function(account){ 
        for (var i = 0; i < Object.keys(account).length/2; i++) { 
            var li = document.createElement('li'); 
            li.textContent = Object.keys(account)[i+Object.keys(account).length/2] + " : " + account[i]; 
            document.getElementById('Account').appendChild(li); 
        } 
    }); 
} 
KappaMarketAbi.json
var abi = [ 
    { 
        "constant": false, 
        "inputs": [ 
            { 
                "name": "_name", 
                "type": "string" 
            }, 
            { 
                "name": "_description", 
                "type": "string" 
            }, 
            { 
                "name": "_price", 
                "type": "uint256" 
            }, 
            { 
                "name": "_googleDocID", 
                "type": "string" 
            }, 
            { 
                "name": "_ipfsHash", 
                "type": "string" 
            } 
        ], 
        "name": "sell", 
        "outputs": [], 
        "payable": false, 
        "stateMutability": "nonpayable", 
        "type": "function" 
    }, 
    { 
        "constant": false, 
        "inputs": [ 
            { 
                "name": "_numItems", 
                "type": "uint256" 
            } 
        ], 
        "name": "ship", 
        "outputs": [], 
        "payable": false, 
        "stateMutability": "nonpayable", 
        "type": "function" 
    }, 
    { 
        "constant": false, 
        "inputs": [ 
            { 
                "name": "_numItems", 
                "type": "uint256" 
            } 
        ], 
        "name": "ownerStop", 
        "outputs": [], 
        "payable": false, 
        "stateMutability": "nonpayable", 
        "type": "function" 
    }, 
    { 
        "constant": false, 
        "inputs": [ 
            { 
                "name": "_numItems", 
                "type": "uint256" 
            }, 
            { 
                "name": "_name", 
                "type": "string" 
            }, 
            { 
                "name": "_description", 
                "type": "string" 
            }, 
            { 
                "name": "_price", 
                "type": "uint256" 
            }, 
            { 
                "name": "_googleDocID", 
                "type": "string" 
            }, 
            { 
                "name": "_IPFSHash", 
                "type": "string" 
            } 
        ], 
        "name": "modifyItem", 
        "outputs": [], 
        "payable": false, 
        "stateMutability": "nonpayable", 
        "type": "function" 
    }, 
    { 
        "constant": false, 
        "inputs": [], 
        "name": "kill", 
        "outputs": [], 
        "payable": false, 
        "stateMutability": "nonpayable", 
        "type": "function" 
    }, 
    { 
        "constant": true, 
        "inputs": [], 
        "name": "numItems", 
        "outputs": [ 
            { 
                "name": "", 
                "type": "uint256" 
            } 
        ], 
        "payable": false, 
        "stateMutability": "view", 
        "type": "function" 
    }, 
    { 
        "constant": true, 
        "inputs": [ 
            { 
                "name": "", 
                "type": "address" 
            } 
        ], 
        "name": "accounts", 
        "outputs": [ 
            { 
                "name": "name", 
                "type": "string" 
            }, 
            { 
                "name": "email", 
                "type": "string" 
            }, 
            { 
                "name": "numTransactions", 
                "type": "uint256" 
            }, 
            { 
                "name": "reputations", 
                "type": "int256" 
            }, 
            { 
                "name": "resistered", 
                "type": "bool" 
            } 
        ], 
        "payable": false, 
        "stateMutability": "view", 
        "type": "function" 
    }, 
    { 
        "constant": false, 
        "inputs": [ 
            { 
                "name": "_numItems", 
                "type": "uint256" 
            }, 
            { 
                "name": "_reputate", 
                "type": "int256" 
            } 
        ], 
        "name": "sellerEvaluate", 
        "outputs": [], 
        "payable": false, 
        "stateMutability": "nonpayable", 
        "type": "function" 
    }, 
    { 
        "constant": false, 
        "inputs": [ 
            { 
                "name": "_numItems", 
                "type": "uint256" 
            } 
        ], 
        "name": "sellerStop", 
        "outputs": [], 
        "payable": false, 
        "stateMutability": "nonpayable", 
        "type": "function" 
    }, 
    { 
        "constant": true, 
        "inputs": [ 
            { 
                "name": "", 
                "type": "uint256" 
            } 
        ], 
        "name": "images", 
        "outputs": [ 
            { 
                "name": "googleDocID", 
                "type": "string" 
            }, 
            { 
                "name": "ipfsHash", 
                "type": "string" 
            } 
        ], 
        "payable": false, 
        "stateMutability": "view", 
        "type": "function" 
    }, 
    { 
        "constant": false, 
        "inputs": [ 
            { 
                "name": "_numItems", 
                "type": "uint256" 
            } 
        ], 
        "name": "sellerRefund", 
        "outputs": [], 
        "payable": true, 
        "stateMutability": "payable", 
        "type": "function" 
    }, 
    { 
        "constant": true, 
        "inputs": [ 
            { 
                "name": "", 
                "type": "uint256" 
            } 
        ], 
        "name": "items", 
        "outputs": [ 
            { 
                "name": "sellerAddr", 
                "type": "address" 
            }, 
            { 
                "name": "buyerAddr", 
                "type": "address" 
            }, 
            { 
                "name": "seller", 
                "type": "string" 
            }, 
            { 
                "name": "name", 
                "type": "string" 
            }, 
            { 
                "name": "description", 
                "type": "string" 
            }, 
            { 
                "name": "price", 
                "type": "uint256" 
            }, 
            { 
                "name": "payment", 
                "type": "bool" 
            }, 
            { 
                "name": "shipment", 
                "type": "bool" 
            }, 
            { 
                "name": "receivement", 
                "type": "bool" 
            }, 
            { 
                "name": "sellerReputate", 
                "type": "bool" 
            }, 
            { 
                "name": "buyerReputate", 
                "type": "bool" 
            }, 
            { 
                "name": "stopSell", 
                "type": "bool" 
            } 
        ], 
        "payable": false, 
        "stateMutability": "view", 
        "type": "function" 
    }, 
    { 
        "constant": false, 
        "inputs": [ 
            { 
                "name": "_numItems", 
                "type": "uint256" 
            }, 
            { 
                "name": "_reputate", 
                "type": "int256" 
            } 
        ], 
        "name": "buyerEvaluate", 
        "outputs": [], 
        "payable": false, 
        "stateMutability": "nonpayable", 
        "type": "function" 
    }, 
    { 
        "constant": false, 
        "inputs": [ 
            { 
                "name": "_numItems", 
                "type": "uint256" 
            } 
        ], 
        "name": "receive", 
        "outputs": [], 
        "payable": true, 
        "stateMutability": "payable", 
        "type": "function" 
    }, 
    { 
        "constant": false, 
        "inputs": [ 
            { 
                "name": "_numItems", 
                "type": "uint256" 
            } 
        ], 
        "name": "buy", 
        "outputs": [], 
        "payable": true, 
        "stateMutability": "payable", 
        "type": "function" 
    }, 
    { 
        "constant": false, 
        "inputs": [ 
            { 
                "name": "_name", 
                "type": "string" 
            }, 
            { 
                "name": "_email", 
                "type": "string" 
            } 
        ], 
        "name": "registerAccount", 
        "outputs": [], 
        "payable": false, 
        "stateMutability": "nonpayable", 
        "type": "function" 
    }, 
    { 
        "constant": false, 
        "inputs": [ 
            { 
                "name": "_numItems", 
                "type": "uint256" 
            } 
        ], 
        "name": "ownerRefund", 
        "outputs": [], 
        "payable": true, 
        "stateMutability": "payable", 
        "type": "function" 
    }, 
    { 
        "constant": false, 
        "inputs": [ 
            { 
                "name": "_name", 
                "type": "string" 
            }, 
            { 
                "name": "_email", 
                "type": "string" 
            } 
        ], 
        "name": "modifyAccount", 
        "outputs": [], 
        "payable": false, 
        "stateMutability": "nonpayable", 
        "type": "function" 
    }, 
    { 
        "inputs": [], 
        "payable": false, 
        "stateMutability": "nonpayable", 
        "type": "constructor" 
    } 
] 


終わりに

使い易いユーザーインターフェースを作ったり,スマホアプリからアクセスできるようにしたいのですが,フロントエンド初心者なのでこれから勉強してスキルを身に着けていきたいと思っています.

コメント

このブログの人気の投稿

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2020-12-01 09:41:49 RSSフィード2020-12-01 09:00 分まとめ(69件)