Dapps
創建一個簡單的 DApp
我想實現
"Decentrilized Gallery"
,並將其實現到區塊鏈(乙太坊),它有點像:基本的 html 頁面,中間有一個按鈕,可以從本地電腦中選擇一張圖片,之後該圖片將在
IPFS 上“直播”。我知道如何做到這一點,使用 URL
連結作為圖片來源(有很多關於它的教程),但我想嘗試
從本地主機和通過 UI(我的按鈕)而不是通過網頁控制台上傳(教程做)。
誰能告訴我,我應該採取哪些基本步驟,或者指導我朝著正確的方向前進。或者至少,是否有可能或製造scence,會聽取任何建議和批評))
<!doctype> <html> <div class="upload"> <input type="file" class="file-input"> <input type="button" value="Browse"> <span class="filename">No file selected</span> </div> <head> <link rel="stylesheet" type="text/css" href="storage/web.css"> <script type="text/javascript" src="./ipfs/ipfs.js"></script> <script type="text/javascript" src="./web3/web3.min.js"></script> <script type="text/javascript"> /* Configuration variables */ var ipfsHost = 'localhost'; var ipfsAPIPort = '5001'; var ipfsWebPort = '8080'; var web3Host = 'http://localhost'; var web3Port = '8545'; /* IPFS initialization */ var ipfs = window.IpfsApi(ipfsHost, ipfsAPIPort) ipfs.swarm.peers(function (err, res) { if (err) { console.error(err); } else { var numPeers = res.Peers === null ? 0 : res.Peers.length; console.log("IPFS - connected to " + numPeers + " peers"); } }); /* web3 initialization */ var Web3 = require('web3'); var web3 = new Web3(); web3.setProvider(new web3.providers.HttpProvider(web3Host + ':' + web3Port)); if (!web3.isConnected()) { console.error("Ethereum - no connection to RPC server"); } else { console.log("Ethereum - connected to RPC server"); } /* JavaScript smart contract interface */ var contractInterface = [{ "constant": false, "inputs": [{ "name": "x", "type": "string" }], "name": "set", "outputs": [], "type": "function" }, { "constant": true, "inputs": [], "name": "get", "outputs": [{ "name": "x", "type": "string" }], "type": "function" }]; var account = web3.eth.accounts[0]; var contractObject = { from: account, gas: 300000, data: '0x6060604052610282806100126000396000f360606040526000357c0100000000000000000000000000000000000000000000000000000000900480634ed3885e146100445780636d4ce63c1461009a57610042565b005b6100986004808035906020019082018035906020019191908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050909091905050610115565b005b6100a760048050506101c6565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156101075780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b8060006000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061016457805160ff1916838001178555610195565b82800160010185558215610195579182015b82811115610194578251826000505591602001919060010190610176565b5b5090506101c091906101a2565b808211156101bc57600081815060009055506001016101a2565b5090565b50505b50565b602060405190810160405280600081526020015060006000508054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102735780601f1061024857610100808354040283529160200191610273565b820191906000526020600020905b81548152906001019060200180831161025657829003601f168201915b5050505050905061027f565b9056' }; var sendDataObject = { from: account, gas: 300000, }; window.ipfs = ipfs; window.web3 = web3; window.account = account; window.contractObject = contractObject; window.contract = web3.eth.contract(contractInterface); window.ipfsAddress = "http://" + ipfsHost + ':' + ipfsWebPort + "/ipfs"; function deployStorage() { window.IPFSHash = null; window.currentData = null; if (window.contractInstance) { console.error('Contract already been deployed at: ', window.contractAddress); return; } window.contract.new(window.contractObject, function (err, contract) { if (err) { console.error("Contract deployment error: ", err); } else if (contract.address) { window.contractAddress = contract.address; window.contractInstance = window.contract.at(contract.address); console.log("Contract successfully deployed at: ", contract.address); } else if (contract.transactionHash) { console.log("Awaiting contract deployment with transaction hash: ", contract.transactionHash); } else { console.error("Unresolved contract deployment error"); } }); } function storeContent(url) { window.ipfs.add(url, function(err, result) { if (err) { console.error("Content submission error:", err); return false; } else if (result && result[0] && result[0].Hash) { console.log("Content successfully stored. IPFS address:", result[0].Hash); } else { console.error("Unresolved content submission error"); return null; } }); } function storeAddress(data) { if (!window.contractInstance) { console.error('Ensure the storage contract has been deployed'); return; } if (window.currentData == data) { console.error("Overriding existing data with same data"); return; } window.contractInstance.set.sendTransaction(data, window.sendDataObject, function (err, result) { if (err) { console.error("Transaction submission error:", err); } else { window.currentData = data; console.log("Address successfully stored. Transaction hash:", result); } }); } function fetchContent() { if (!window.contractInstance) { console.error("Storage contract has not been deployed"); return; } window.contractInstance.get.call(function (err, result) { if (err) { console.error("Content fetch error:", err); } else if (result && window.IPFSHash == result) { console.log("New data is not mined yet. Current data: ", result); return; } else if (result) { window.IPFSHash = result; var URL = window.ipfsAddress + "/" + result; console.log("Content successfully retrieved. IPFS address", result); console.log("Content URL:", URL); } else { console.error('No data, verify the transaction has been mined'); } }); } function getBalance() { window.web3.eth.getBalance(window.account, function (err, balance) { console.log(parseFloat(window.web3.fromWei(balance, "ether"))); }); } </script> </head>
好吧,首先我建構了一些包含IPFS圖像上傳組件的dapp,一般來說概念很簡單。
您需要做的就是創建一個相對簡單的智能合約來儲存 ipfs 雜湊(唯一標識符)。您可以通過https://gateway.ipfs.io/ipfs/IPFSHASH訪問該圖像。看來您使用 javascript 界面的想法是正確的,但我認為您需要一個完整的 dapp。建議使用毛毛雨盒作為起點..
pragma solidity ^0.4.17; contract Contract { string ipfsHash; mapping (address => string[]) userToFiles; event (string ipfsHash, address owner) filesUploaded; function setHash(string x) public { ipfsHash = x; // update files // update array } function getHash() public view returns (string x) { return ipfsHash; } }
當然,在您的情況下,如果不是返回的圖像的一部分,您將需要某種方式來查看所有圖像。
免責聲明這是我自己建構的智能合約,我不保證安全性或其他任何內容,這在solidity V0.5.0中也不起作用。
pragma solidity ^0.4.24; /// @author David Li /// @notice Stores a filelist on solidity, since an array of structs cannot easily be returned /// the structs must be decomposed on the front-end /// @dev simple filelist contains ipfshash, filename, owner, tags and unix timestamp /// @dev one way to create a "trello" like application would require creating more modifiers and perhaps /// role based access control. /// @dev since I can't use an bytes32 array in solidity, I decided to have tag numbers /// corresponding to string names, almost like a dictionary look up. contract FileList { /// @dev struct that contains unique link to image (via IPFS), serial Id, and timestamp struct File { uint256 id; string ipfshash; bytes32 filename; bytes32[5] tags; address owner; uint256 timestamp; } uint256 public constant maxAmountOfFiles = 1000; // Owner => files mapping(address => File[maxAmountOfFiles]) public files; // Owner => last files id mapping(address => uint256) public lastIds; // consider mapping hash to set of tags /// @dev main event for smart contract, needed for drizzle to update list of files event fileAdded (uint256 fileid, string ipfshash, bytes32 _filename); event tagsAdded (bytes32[5] tags); /// @dev Add a file to the list /// @param ipfshash an ipfshash returned after an image is finished uploaded /// @param _filename name of file as a bytes32 as filenames should be short /// @param tags array of bytes32 used for sorting/searching files (e,g. blockchain, school, textbook) /// @notice updates mappings todos and lastIds function addFile(string ipfshash, bytes32 _filename, bytes32[5] tags) public { File memory myFile = File(lastIds[msg.sender], ipfshash, _filename, tags, msg.sender, now); // explicitly store tags myFile.tags = tags; emit tagsAdded (myFile.tags); // store new file in mapping files[msg.sender][lastIds[msg.sender]] = myFile; // emit event, also need for drizzle emit fileAdded(lastIds[msg.sender],ipfshash,_filename); if(lastIds[msg.sender] >= maxAmountOfFiles) lastIds[msg.sender] = 0; else lastIds[msg.sender]++; } /// @dev return the tags for a specific file /// @param owner --- address of person who uploaded the file /// @param _index --- the file desired, (first file uploaded, second , etc ...) function getFileTags(address owner, uint256 _index) external view returns (bytes32[5]) { return files[owner][_index].tags; } }
我使用一些鍊式承諾鍊式承諾載入數據。
我記得在IPFS 和 React發布一周後學習了這個教程
例如,您可以看到我建構的一個簡單的 dapp,Ipfs-Dapp ,用於在區塊鏈上儲存圖像。