狼爱上狸

我胡汉三又回来了

2019年6月29日 #

solc编译问题

1.安装solc
npm install -g solc
用IDEA编译sol时出现错误
solcjs.cmd --abi --bin CloudNoteService.sol -o C:\Users\Administrator\IdeaProjects\test
CloudNoteService.sol:1:1: ParserError: Source file requires different compiler version (current compiler is 0.5.10+commit.5a6ea5b1.Emscripten.clang - note that nightly builds are considered to be strictly less than the released version
pragma solidity ^0.4.22;
2.solcjs.cmd  --version//查看solc版本
0.5.10+commit.5a6ea5b1.Emscripten.clang
3.npm uninstall solc//卸载
4.npm install -g solc@0.4.24//安装solc0.4.24版本
5.C:\nodejs\node_modules\npm>solcjs.cmd --version//查看solc版本
0.4.24+commit.e67f0147.Emscripten.clang
6.solc跟web3一样,有版本的区别。

posted @ 2019-07-08 16:11 狼爱上狸 阅读(16) | 评论 (0)编辑 收藏

solidity官方开发文档

https://solidity-cn.readthedocs.io/zh/develop/

posted @ 2019-07-08 15:18 狼爱上狸 阅读(9) | 评论 (0)编辑 收藏

以太坊智能合约 —— 最佳安全开发指南

https://www.cnblogs.com/wanghui-garcia/p/9580573.html

posted @ 2019-07-07 15:57 狼爱上狸 阅读(13) | 评论 (0)编辑 收藏

IPFS + Ethereum(下篇):IPFS + Ethereum存储和获取图片

1. 项目描述

这篇文章通过truffle unbox react创建项目,安装ipfs-api,将图片存储到ipfs,将图片hash存储到Ethereum区块链,取数据时先从区块链读取图片hash,再通过hashipfs读取数据,解决了区块链大数据存储成本高昂的问题。

2. 效果图

3. 阅读本文需要掌握的知识

阅读本文需要将先学习上面的系列文章,由于本文前端使用了大量的React语法,所以建议学习一些React语法,还需要学习truffle framework

4. 源码

其实这篇文章的内容就是上面几篇文章的综合结合体,所以在这里我将不再对代码做过多的概述。

import React, {Component} from 'react' import SimpleStorageContract from '../build/contracts/SimpleStorage.json' import getWeb3 from './utils/getWeb3'  import './css/oswald.css' import './css/open-sans.css' import './css/pure-min.css' import './App.css'  const ipfsAPI = require('ipfs-api'); const ipfs = ipfsAPI({host: 'localhost', port: '5001', protocol: 'http'});  const contract = require('truffle-contract') const simpleStorage = contract(SimpleStorageContract) let account;  // Declaring this for later so we can chain functions on SimpleStorage. let contractInstance;  let saveImageOnIpfs = (reader) => {   return new Promise(function(resolve, reject) {     const buffer = Buffer.from(reader.result);     ipfs.add(buffer).then((response) => {       console.log(response)       resolve(response[0].hash);     }).catch((err) => {       console.error(err)       reject(err);     })   }) }  class App extends Component {   constructor(props) {     super(props)      this.state = {       blockChainHash: null,       web3: null,       address: null,       imgHash: null,       isWriteSuccess: false     }   }    componentWillMount() {      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");         console.log(res);       }     });      getWeb3.then(results => {       this.setState({web3: results.web3})        // Instantiate contract once web3 provided.       this.instantiateContract()     }).catch(() => {       console.log('Error finding web3.')     })   }    instantiateContract = () => {      simpleStorage.setProvider(this.state.web3.currentProvider);     this.state.web3.eth.getAccounts((error, accounts) => {       account = accounts[0];       simpleStorage.at('0x345ca3e014aaf5dca488057592ee47305d9b3e10').then((contract) => {         console.log(contract.address);         contractInstance = contract;         this.setState({address: contractInstance.address});         return;       });     })    }   render() {     return (<div className="App">       {         this.state.address           ? <h1>合约地址:{this.state.address}</h1>           : <div/>       }       <h2>上传图片到IPFS:</h2>       <div>         <label id="file">Choose file to upload</label>         <input type="file" ref="file" id="file" name="file" multiple="multiple"/>       </div>       <div>         <button onClick={() => {             var file = this.refs.file.files[0];             var reader = new FileReader();             // reader.readAsDataURL(file);             reader.readAsArrayBuffer(file)             reader.onloadend = function(e) {               console.log(reader);               saveImageOnIpfs(reader).then((hash) => {                 console.log(hash);                 this.setState({imgHash: hash})               });              }.bind(this);            }}>将图片上传到IPFS并返回图片HASH</button>       </div>       {         this.state.imgHash           ? <div>               <h2>imgHash:{this.state.imgHash}</h2>               <button onClick={() => {                   contractInstance.set(this.state.imgHash, {from: account}).then(() => {                     console.log('图片的hash已经写入到区块链!');                     this.setState({isWriteSuccess: true});                   })                 }}>将图片hash写到区块链:contractInstance.set(imgHash)</button>             </div>           : <div/>       }       {         this.state.isWriteSuccess           ? <div>               <h1>图片的hash已经写入到区块链!</h1>               <button onClick={() => {                   contractInstance.get({from: account}).then((data) => {                     console.log(data);                     this.setState({blockChainHash: data});                   })                 }}>从区块链读取图片hash:contractInstance.get()</button>             </div>           : <div/>       }       {         this.state.blockChainHash           ? <div>               <h3>从区块链读取到的hash值:{this.state.blockChainHash}</h3>             </div>           : <div/>       }       {         this.state.blockChainHash           ? <div>               <h2>浏览器访问:{"http://localhost:8080/ipfs/" + this.state.imgHash}</h2>               <img alt="" style={{                   width: 1600                 }} src={"http://localhost:8080/ipfs/" + this.state.imgHash}/>             </div>           : <img alt=""/>       }     </div>);   } }  export default App 

5. 源码修改

可以自己建立项目,也可以直接下载原博主的源码并进行修改。这里直接下载原博主的代码进行修改。

5.1 下载源码,安装依赖

$ git clone https://github.com/liyuechun/IPFS-Ethereum-Image.git $ cd IPFS-Ethereum-Image $ npm install 

5.2 查看源码端口

/Users/yuyang/IPFS-Ethereum-Image/src/utils/getWeb3.js

var provider = new Web3.providers.HttpProvider('http://127.0.0.1:9545') 

使用的端口是9545truffle develop 默认使用的端口就是9545,所以我们使用truffle develop作为测试私链。

5.3 启动私链

yuyangdeMacBook-Pro:IPFS-Ethereum-Image yuyang$ truffle develop Truffle Develop started at http://127.0.0.1:9545/  Accounts: (0) 0x627306090abab3a6e1400e9345bc60c78a8bef57 (1) 0xf17f52151ebef6c7334fad080c5704d77216b732 (2) 0xc5fdf4076b8f3a5357c5e395ab970b5b54098fef (3) 0x821aea9a577a9b44299b9c15c88cf3087f3b5544 (4) 0x0d1d4e623d10f9fba5db95830f7d3839406c6af2 (5) 0x2932b7a2355d6fecc4b5c0b6bd44cc31df247a2e (6) 0x2191ef87e392377ec08e7c08eb105ef5448eced5 (7) 0x0f4f2ac550a1b4e2280d04c21cea7ebd822934b5 (8) 0x6330a553fc93768f612722bb8c2ec78ac90b3bbc (9) 0x5aeda56215b167893e80b4fe645ba6d5bab767de  Private Keys: (0) c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3 (1) ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f (2) 0dbbe8e4ae425a6d2687f1a7e3ba17bc98c673636790f1b8ad91193c05875ef1 (3) c88b703fb08cbea894b6aeff5a544fb92e78a18e19814cd85da83b71f772aa6c (4) 388c684f0ba1ef5017716adb5d21a053ea8e90277d0868337519f97bede61418 (5) 659cbb0e2411a44db63778987b1e22153c086a95eb6b18bdf89de078917abc63 (6) 82d052c865f5763aad42add438569276c00d3d88a2d062d36b2bae914d58b8c8 (7) aa3680d5d48a8283413f7a108367c7299ca73f553735860a87b08f39395618b7 (8) 0f62d96d6675f32685bbdb8ac13cda7c23436f63efbb9d07700d8669ff12b7c4 (9) 8d5366123cb560bb606379f90a0bfd4769eecc0557f1b362dcae9012b548b1e5  Mnemonic: candy maple cake sugar pudding cream honey rich smooth crumble sweet treat  ⚠️  Important ⚠️  : This mnemonic was created for you by Truffle. It is not secure. Ensure you do not use it on production blockchains, or else you risk losing funds. 

5.4 编译和部署合约

truffle(develop)> compile truffle(develop)> migrate 

5.5 获取合约地址

Using network 'develop'.  Running migration: 1_initial_migration.js   Deploying Migrations...   ... 0x130a37fb2d60e34cc04fccbfc51c10b988d61378090b89eb4546cce2a6ef3490   Migrations: 0x8cdaf0cd259887258bc13a92c0a6da92698644c0 Saving successful migration to network...   ... 0xd7bc86d31bee32fa3988f1c1eabce403a1b5d570340a3a9cdba53a472ee8c956 Saving artifacts... Running migration: 2_deploy_contracts.js   Deploying SimpleStorage...   ... 0x8c51da613e7c0517e726926c18d535aed0d21c8f4c82668212a6cdfd193d21d8   SimpleStorage: 0x345ca3e014aaf5dca488057592ee47305d9b3e10 Saving successful migration to network...   ... 0xf36163615f41ef7ed8f4a8f192149a0bf633fe1a2398ce001bf44c43dc7bdda0 Saving artifacts... 

SimpleStorage合约地址为0x345ca3e014aaf5dca488057592ee47305d9b3e10。也可以从/Users/yuyang/IPFS-Ethereum-Image/build/contracts/SimpleStorage.json看到

"networks": {     "4447": {       "events": {},       "links": {},       "address": "0x345ca3e014aaf5dca488057592ee47305d9b3e10",       "transactionHash": "0x8c51da613e7c0517e726926c18d535aed0d21c8f4c82668212a6cdfd193d21d8"     }   }, 

5.6 修改App.js文件

/Users/yuyang/IPFS-Ethereum-Image/src/App.js

instantiateContract = () => {      simpleStorage.setProvider(this.state.web3.currentProvider);     this.state.web3.eth.getAccounts((error, accounts) => {       account = accounts[0];       simpleStorage.at('0x345ca3e014aaf5dca488057592ee47305d9b3e10').then((contract) => {         console.log(contract.address);         contractInstance = contract;         this.setState({address: contractInstance.address});         return;       });     })   } 

将其中的0x345ca3e014aaf5dca488057592ee47305d9b3e10合约地址替换为你的合约地址。

6. 启动程序

新开命令行启动IPFS节点

yuyangdeMacBook-Pro:~ yuyang$ ipfs daemon 

新开命令行启动程序

yuyangdeMacBook-Pro:~ yuyang$ npm start 

7. 配置MetaMask插件和准备以太坊账号

程序启动后,会自动打开浏览器。注意,因为MetaMask插件只支持Chrome浏览器和FireFox浏览器,所以你需要运行保持页面运行在这两种浏览器上。关于MetaMask插件这部分内容,请查看这篇文章

因为我们的私链是部署在http://127.0.0.1:9545上的,所以你需要让MetaMask插件的端口也指向http://127.0.0.1:9545。点击Custom RPC进行配置后,切换端口为http://127.0.0.1:9545

因为需要向区块写入数据,需要花费gas,如果你的当前Account中没有以太币,可以导入其他的Account。点击右上角头像图标。

点击Import Account

需要输入私钥。在我们输入truffle develop启动私链的时候,已经分配给了我们十个Account地址和对应的私钥,任一账号都有100以太币,随便选择一个私钥填入。

Accounts: (0) 0x627306090abab3a6e1400e9345bc60c78a8bef57 (1) 0xf17f52151ebef6c7334fad080c5704d77216b732 (2) 0xc5fdf4076b8f3a5357c5e395ab970b5b54098fef (3) 0x821aea9a577a9b44299b9c15c88cf3087f3b5544 (4) 0x0d1d4e623d10f9fba5db95830f7d3839406c6af2 (5) 0x2932b7a2355d6fecc4b5c0b6bd44cc31df247a2e (6) 0x2191ef87e392377ec08e7c08eb105ef5448eced5 (7) 0x0f4f2ac550a1b4e2280d04c21cea7ebd822934b5 (8) 0x6330a553fc93768f612722bb8c2ec78ac90b3bbc (9) 0x5aeda56215b167893e80b4fe645ba6d5bab767de  Private Keys: (0) c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3 (1) ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f (2) 0dbbe8e4ae425a6d2687f1a7e3ba17bc98c673636790f1b8ad91193c05875ef1 (3) c88b703fb08cbea894b6aeff5a544fb92e78a18e19814cd85da83b71f772aa6c (4) 388c684f0ba1ef5017716adb5d21a053ea8e90277d0868337519f97bede61418 (5) 659cbb0e2411a44db63778987b1e22153c086a95eb6b18bdf89de078917abc63 (6) 82d052c865f5763aad42add438569276c00d3d88a2d062d36b2bae914d58b8c8 (7) aa3680d5d48a8283413f7a108367c7299ca73f553735860a87b08f39395618b7 (8) 0f62d96d6675f32685bbdb8ac13cda7c23436f63efbb9d07700d8669ff12b7c4 (9) 8d5366123cb560bb606379f90a0bfd4769eecc0557f1b362dcae9012b548b1e5 

8. 运行程序

  1. 页面会显示当前合约的地址0x345ca3e014aaf5dca488057592ee47305d9b3e10

  2. 选择一张图片

  3. 点击上传到IPFS,并获取到图片hashQmSLnchQXh9gJrDKvQ5UFLZAj5f7icb2yWsWmcUKUYY3gj

  4. 点击将图片hash值保存到区块链,弹出MetaMask插件进行写入合约的确认

  5. 从区块链获取图片hashQmSLnchQXh9gJrDKvQ5UFLZAj5f7icb2yWsWmcUKUYY3gj

  6. 根据图片hash值,从IPFS进行访问

参考:【IPFS + 区块链 系列】 入门篇 - IPFS + Ethereum (下篇)-ipfs + Ethereum 大图片存储
作者:黎跃春



作者:yuyangray
链接:https://www.jianshu.com/p/3cb9520a23c0
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

posted @ 2019-07-07 15:04 狼爱上狸| 编辑 收藏

IPFS + Ethereum(上篇):JS+IPFS-API存储和获取数据

1. 内容简介

这篇文章将为大家讲解js-ipfs-api的简单使用,如何将数据上传到IPFS,以及如何从IPFS通过HASH读取数据。

2. IPFS-HTTP效果图

3. 实现步骤

3.1 安装create-react-app

参考文档:https://reactjs.org/tutorial/tutorial.html

yuyangdeMacBook-Pro:~ yuyang$ npm install -g create-react-app /Users/yuyang/.nvm/versions/node/v8.9.4/bin/create-react-app -> /Users/yuyang/.nvm/versions/node/v8.9.4/lib/node_modules/create-react-app/index.js + create-react-app@1.5.2 added 67 packages in 14.512s 

3.2 React项目创建

yuyangdeMacBook-Pro:~ yuyang$ create-react-app ipfs-http-demo  Creating a new React app in /Users/yuyang/ipfs-http-demo.  Installing packages. This might take a couple of minutes. Installing react, react-dom, and react-scripts...  ... ...   Success! Created ipfs-http-demo at /Users/yuyang/ipfs-http-demo Inside that directory, you can run several commands:    yarn start     Starts the development server.    yarn build     Bundles the app into static files for production.    yarn test     Starts the test runner.    yarn eject     Removes this tool and copies build dependencies, configuration files     and scripts into the app directory. If you do this, you can’t go back!  We suggest that you begin by typing:    cd ipfs-http-demo   yarn start  Happy hacking! 

3.3 运行React项目

yuyangdeMacBook-Pro:ipfs-http-demo yuyang$ npm start 
Compiled successfully!  You can now view ipfs-http-demo in the browser.    Local:            http://localhost:3000/   On Your Network:  http://192.168.0.4:3000/  Note that the development build is not optimized. To create a production build, use yarn build. 

3.4 浏览项目

浏览器会自动打开:http://localhost:3000/

效果如下:

3.5 安装ipfs-api

https://www.npmjs.com/package/ipfs-api

项目结构

安装ipfs-api

切换到项目根目录,安装ipfs-api

yuyangdeMacBook-Pro:ipfs-http-demo yuyang$ npm install --save ipfs-api  

ipfs-api安装完后,如上图所示,接下来刷新一下浏览器,看看项目是否有问题,正常来讲,一切会正常。

3.6 完成UI逻辑

拷贝下面的代码,将src/App.js里面的代码直接替换掉。

import React, { Component } from 'react'; import './App.css';  class App extends Component {         constructor(props) {           super(props);           this.state = {             strHash: null,             strContent: null           }       }      render() {       return (         <div className="App">           <input             ref="ipfsContent"            />           <button onClick={() => {             let ipfsContent = this.refs.ipfsContent.value;             console.log(ipfsContent);           }}>提交到IPFS</button>            <p>{this.state.strHash}</p>            <button onClick={() => {             console.log('从ipfs读取数据。')            }}>读取数据</button>            <h1>{this.state.strContent}</h1>         </div>       );     } }  export default App; 

上面的代码完成的工作是,当我们在输入框中输入一个字符串时,点击提交到IPFS按钮,将文本框中的内容取出来打印,后续我们需要将这个数据上传到IPFS。点击读取数据按钮,我们也只是随便打印了一个字符串,后面需要从IPFS读取数据,然后将读取的数据存储到状态机变量strContent中并且展示出来。

现在刷新网页,输入内容,点击提交到IPFS,Console打印出输入的内容。点击读取数据,Console打印出从ipfs读取数据。

3.7 导入IPFS

const ipfsAPI = require('ipfs-api'); const ipfs = ipfsAPI({host: 'localhost', port: '5001', protocol: 'http'}); 

3.8 编写上传大文本字符串到IPFS的Promise函数

saveTextBlobOnIpfs = (blob) => {     return new Promise(function(resolve, reject) {       const descBuffer = Buffer.from(blob, 'utf-8');       ipfs.add(descBuffer).then((response) => {         console.log(response)         resolve(response[0].hash);       }).catch((err) => {         console.error(err)         reject(err);       })     })   } 

response[0].hash返回的是数据上传到IPFS后返回的HASH字符串。

3.9 上传数据到IPFS

this.saveTextBlobOnIpfs(ipfsContent).then((hash) => {     console.log(hash);     this.setState({strHash: hash}); }); 

ipfsContent是从文本框中取到的数据,调用this.saveTextBlobOnIpfs方法将数据上传后,会返回字符串hash,并且将hash存储到状态机变量strHash中。

目前完整的代码:

import React, {Component} from 'react'; import './App.css';  const ipfsAPI = require('ipfs-api'); const ipfs = ipfsAPI({host: 'localhost', port: '5001', protocol: 'http'});  class App extends Component {    constructor(props) {     super(props);     this.state = {       strHash: null,       strContent: null     }   }    saveTextBlobOnIpfs = (blob) => {     return new Promise(function(resolve, reject) {       const descBuffer = Buffer.from(blob, 'utf-8');       ipfs.add(descBuffer).then((response) => {         console.log(response)         resolve(response[0].hash);       }).catch((err) => {         console.error(err)         reject(err);       })     })   }    render() {     return (<div className="App">       <input ref="ipfsContent" />       <button onClick={() => {           let ipfsContent = this.refs.ipfsContent.value;           console.log(ipfsContent);           this.saveTextBlobOnIpfs(ipfsContent).then((hash) => {             console.log(hash);             this.setState({strHash: hash});           });         }}>提交到IPFS</button>        <p>{this.state.strHash}</p>        <button onClick={() => {           console.log('从ipfs读取数据。')         }}>读取数据</button>       <h1>{this.state.strContent}</h1>     </div>);   } }  export default App; 

3.10 跨域资源共享CORS配置

跨域资源共享( CORS )配置,依次在终端执行下面的代码:

yuyangdeMacBook-Pro:ipfs-http-demo yuyang$ ipfs config --json API.HTTPHeaders.Access-Control-Allow-Methods '["PUT", "GET", "POST", "OPTIONS"]'  yuyangdeMacBook-Pro:ipfs-http-demo yuyang$ ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '["*"]'  yuyangdeMacBook-Pro:ipfs-http-demo yuyang$ ipfs config --json API.HTTPHeaders.Access-Control-Allow-Credentials '["true"]'  yuyangdeMacBook-Pro:ipfs-http-demo yuyang$ ipfs config --json API.HTTPHeaders.Access-Control-Allow-Headers '["Authorization"]'  yuyangdeMacBook-Pro:ipfs-http-demo yuyang$ ipfs config --json API.HTTPHeaders.Access-Control-Expose-Headers '["Location"]' 

用正确的端口运行daemon:

yuyangdeMacBook-Pro:ipfs-http-demo yuyang$ ipfs config Addresses.API /ip4/127.0.0.1/tcp/5001 yuyangdeMacBook-Pro:ipfs-http-demo yuyang$ ipfs config Addresses.API /ip4/127.0.0.1/tcp/5001 yuyangdeMacBook-Pro:ipfs-http-demo yuyang$ ipfs daemon 

3.11 刷新网页提交数据并在线查看数据

上传数据,并且查看返回hash值

在线查看上传到IPFS的数据

http://ipfs.io/ipfs/QmejvEPop4D7YUadeGqYWmZxHhLc4JBUCzJJHWMzdcMe2y

3.12 从IPFS读取数据

ipfs.cat(this.state.strHash).then((stream) => {     console.log(stream);     let strContent = Utf8ArrayToStr(stream);     console.log(strContent);     this.setState({strContent: strContent}); }); 

streamUint8Array类型的数据,下面的方法是将Uint8Array转换为string字符串。

Utf8ArrayToStr

function Utf8ArrayToStr(array) {     var out, i, len, c;     var char2, char3;      out = "";     len = array.length;     i = 0;     while(i < len) {     c = array[i++];     switch(c >> 4)       {         case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:           // 0xxxxxxx           out += String.fromCharCode(c);           break;         case 12: case 13:           // 110x xxxx   10xx xxxx           char2 = array[i++];           out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));           break;         case 14:           // 1110 xxxx  10xx xxxx  10xx xxxx           char2 = array[i++];           char3 = array[i++];           out += String.fromCharCode(((c & 0x0F) << 12) |                          ((char2 & 0x3F) << 6) |                          ((char3 & 0x3F) << 0));           break;         default:           break;       }     }      return out; } 

完整源码

import React, {Component} from 'react'; import './App.css';  const ipfsAPI = require('ipfs-api'); const ipfs = ipfsAPI({host: 'localhost', port: '5001', protocol: 'http'});  function Utf8ArrayToStr(array) {   var out,     I,     len,     c;   var char2,     char3;    out = "";   len = array.length;   i = 0;   while (i < len) {     c = array[i++];     switch (c >> 4) {       case 0:       case 1:       case 2:       case 3:       case 4:       case 5:       case 6:       case 7:         // 0xxxxxxx         out += String.fromCharCode(c);         break;       case 12:       case 13:         // 110x xxxx   10xx xxxx         char2 = array[i++];         out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));         break;       case 14:         // 1110 xxxx  10xx xxxx  10xx xxxx         char2 = array[i++];         char3 = array[i++];         out += String.fromCharCode(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));         break;       default:         break;     }   }    return out; }  class App extends Component {    constructor(props) {     super(props);     this.state = {       strHash: null,       strContent: null     }   }    saveTextBlobOnIpfs = (blob) => {     return new Promise(function(resolve, reject) {       const descBuffer = Buffer.from(blob, 'utf-8');       ipfs.add(descBuffer).then((response) => {         console.log(response)         resolve(response[0].hash);       }).catch((err) => {         console.error(err)         reject(err);       })     })   }    render() {     return (<div className="App">       <input ref="ipfsContent" />       <button onClick={() => {           let ipfsContent = this.refs.ipfsContent.value;           console.log(ipfsContent);           this.saveTextBlobOnIpfs(ipfsContent).then((hash) => {             console.log(hash);             this.setState({strHash: hash});           });         }}>提交到IPFS</button>        <p>{this.state.strHash}</p>        <button onClick={() => {           console.log('从ipfs读取数据。')           ipfs.cat(this.state.strHash).then((stream) => {             console.log(stream);             let strContent = Utf8ArrayToStr(stream);             console.log(strContent);             this.setState({strContent: strContent});           });         }}>读取数据</button>       <h1>{this.state.strContent}</h1>     </div>);   } }  export default App; 

4. 总结

这篇文章主要讲解如何配置React环境,如何创建React项目,如何安装js-ipfs-api,如何上传数据,如何设置开发环境,如何下载数据等等内容。通过这篇文章的系统学习,你会掌握js-ipfs-api在项目中的使用流程。



作者:yuyangray
链接:https://www.jianshu.com/p/48218aa9d724
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

posted @ 2019-07-07 15:03 狼爱上狸| 编辑 收藏

IPFS + Ethereum(中篇):图片存储到IPFS以及获取

1. 项目效果图

2. 创建React项目

yuyangdeMacBook-Pro:~ yuyang$ create-react-app ipfs_img 

3. 完成UI逻辑

将下面的代码拷贝替换掉App.js里面的代码。

import React, {Component} from 'react'  class App extends Component {   constructor(props) {     super(props)      this.state = {       imgSrc: null     }   }     render() {     return (<div className="App">        <h2>上传图片到IPFS:</h2>       <div>         <label id="file">Choose file to upload</label>         <input type="file" ref="file" id="file" name="file" multiple="multiple"/>       </div>       <div>         <button onClick={() => {             var file = this.refs.file.files[0];             var reader = new FileReader();             // reader.readAsDataURL(file);             reader.readAsArrayBuffer(file)             reader.onloadend = (e) => {               console.log(reader);             }            }}>Submit</button>       </div>       {         this.state.imgSrc             <div>               <h2>{"http://localhost:8080/ipfs/" + this.state.imgSrc}</h2>               <img alt="区块链部落" style= src={"http://localhost:8080/ipfs/" + this.state.imgSrc}/>             </div>           : <img alt=""/>       }     </div>);   } }  export default App 

4. 安装ipfs-api

yuyangdeMacBook-Pro:ipfs_img yuyang$ npm install --save ipfs-api 

5. App.js导入IPFS

const ipfsAPI = require('ipfs-api'); const ipfs = ipfsAPI({host: 'localhost', port: '5001', protocol: 'http'}); 

6. 实现上传图片到IPFS的Promise函数

let saveImageOnIpfs = (reader) => {   return new Promise(function(resolve, reject) {     const buffer = Buffer.from(reader.result);     ipfs.add(buffer).then((response) => {       console.log(response)       resolve(response[0].hash);     }).catch((err) => {       console.error(err)       reject(err);     })   }) } 

7. 上传图片到IPFS

var file = this.refs.file.files[0]; var reader = new FileReader(); // reader.readAsDataURL(file); reader.readAsArrayBuffer(file) reader.onloadend = function(e) {   console.log(reader);   saveImageOnIpfs(reader).then((hash) => {     console.log(hash);     this.setState({imgSrc: hash})   }); 
  • reader.readAsDataURL(file);上传图片路径。

  • reader.readAsArrayBuffer(file);上传图片内容。

上传图片

saveImageOnIpfs(reader).then((hash) => {     console.log(hash);     this.setState({imgSrc: hash})   }); 

hash即是上传到IPFS的图片的HASH地址,this.setState({imgSrc: hash})hash保存到状态机变量imgSrc中。

8. 完整代码

import React, {Component} from 'react'  const ipfsAPI = require('ipfs-api'); const ipfs = ipfsAPI({host: 'localhost', port: '5001', protocol: 'http'});  let saveImageOnIpfs = (reader) => {   return new Promise(function(resolve, reject) {     const buffer = Buffer.from(reader.result);     ipfs.add(buffer).then((response) => {       console.log(response)       resolve(response[0].hash);     }).catch((err) => {       console.error(err)       reject(err);     })   }) }  class App extends Component {   constructor(props) {     super(props)      this.state = {       imgSrc: null     }   }    render() {     return (       <div className="App">        <h2>上传图片到IPFS:</h2>       <div>         <label id="file">Choose file to upload</label>         <input type="file" ref="file" id="file" name="file" multiple="multiple"/>       </div>       <div>         <button onClick={() => {             var file = this.refs.file.files[0];             var reader = new FileReader();             // reader.readAsDataURL(file);             reader.readAsArrayBuffer(file)             reader.onloadend = (e) => {               console.log(reader);               saveImageOnIpfs(reader).then((hash) => {                 console.log(hash);                 this.setState({imgSrc: hash})               });             }            }}>Submit</button>       </div>       {         this.state.imgSrc             ?<div>               <h2>{"http://localhost:8080/ipfs/" + this.state.imgSrc}</h2>               <img alt="区块链部落" src={"http://localhost:8080/ipfs/" + this.state.imgSrc} />             </div>             :<img alt=""/>       }     </div>);   } }  export default App 

参考:【IPFS + 区块链 系列】 入门篇 - IPFS + Ethereum (中篇)-js-ipfs-api - 图片上传到IPFS以及下载

作者:黎跃春



作者:yuyangray
链接:https://www.jianshu.com/p/db2676952c48
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

posted @ 2019-07-07 15:01 狼爱上狸| 编辑 收藏

Ropsten申请测试币

http://faucet.ropsten.be:3001/上申请,只需要输入你在Ropsten网络上的账户地址就行,转币操作非常迅速,目前一次可申请1ETH,24小时后可再次申请;

posted @ 2019-07-05 21:59 狼爱上狸 阅读(11) | 评论 (0)编辑 收藏

校外访问

     摘要: 数字资源校外访问锦囊,拿走不谢! ...  阅读全文

posted @ 2019-07-05 11:17 狼爱上狸| 编辑 收藏

web3.eth.abi

1.web3的1.0以下版本不支持web3.eth.abi
2.var ethabi = require('web3-eth-abi');这种引用也有问题。
3.升级web3到1.0以上版本后测试通过:
var Web3 = require('web3');
var web3 = new Web3();

console.log(web3.eth.abi.encodeFunctionSignature('myMethod(uint256,string)'))

posted @ 2019-06-29 19:07 狼爱上狸 阅读(9) | 评论 (0)编辑 收藏

删除无用的系统服务项

方法: 在注册表中删除

运行regedit, 找到
HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services 中想要删除的服务。

 

重启电脑可以看到你所选定的服务项在服务列表中不存在了

posted @ 2019-06-29 11:41 狼爱上狸 阅读(12) | 评论 (0)编辑 收藏