blockstack.js 教程:如何在blockstack上寫壹個區塊鏈“臉書” 程序

Posted retrichere

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了blockstack.js 教程:如何在blockstack上寫壹個區塊鏈“臉書” 程序相关的知识,希望对你有一定的参考价值。

Blockstack.js 工具教程:

在本教程中,我們將使用Gaia存儲系統構建壹個區塊鏈微博應用程序,從而使用戶提交的文字和圖片沒有發布到中心服務器中,而是在自己的本地電腦。
此應用程序將是壹個完全分散且無需服務器的access . js應用程序。標識和存儲服務將由blockstack提供,

應用程序將能夠執行以下操作:

使用blockstack驗證用戶
用戶發布類似傳統微博(微信朋友圈)樣式的新狀態
在用戶配置文件中顯示狀態
查找其他用戶並查看其配置文件和狀態
我們將使用以下工具:

用於管理依賴關系和腳本的NPM
yo為塊堆棧反應應用程序生成樣板文件
用於驗證用戶和訪問Gaia存儲的blockstack
對於經驗豐富的blockstack開發人員:

添加publish _ data作用域以登錄請求
使用getFile ( ‘ filename . JSON ‘,{username: ‘ username . id ‘,decrypt: false } )從其他用戶讀取文件。
使用lookupProfile ( ‘username. id ‘ )查找用戶配置文件
如前所述使用putFile ( ‘ filename . JSON ‘,file,options ),其中選項設置為{ encrypt : false },以便禁用加密,其他人可以讀取您的文件。
安裝與生成

首先,安裝Yeoman以及blockstack應用程序生成器:

 
npm install -g yo generator-blockstack

  

 

接下來,為我們的應用程序創建壹個目錄,取個新的名字Publik :

mkdir publik && cd publik

  

然後,使用blockstack應用程序生成器生成壹個簡單的blockstack應用程序:

yo blockstack:react

  

響應提示後,應用程序生成器將創建所有應用程序文件,然後安裝所有依賴項。

要在本地運行應用程序:

npm start

  

並將瀏覽器打開到http://localhost : 8080。現在您應該看到壹個簡單的react應用程序,您可以使用blockstack ID登錄。

多用戶層數據存儲

 

在多用戶層數據存儲中,存儲在Gaia上的用戶文件通過用戶配置文件中的apps屬性對其他用戶可見。使用多用戶層數據存儲的每個應用程序都必須將其自身添加到用戶的配置文件. JSON文件中。在身份驗證期間請求publish _ data作用域時,blockstack瀏覽器將自動處理此部分。

因此,我們需要做的第壹件事是修改身份驗證請求以包括publish _ data範圍。
打開src/components/App.jsx並找到下面的方法:

handleSignIn(e) {
  e.preventDefault();
  redirectToSignIn();
}

  

將方法修改為:

handleSignIn(e) {
  e.preventDefault();
  const origin = window.location.origin
  redirectToSignIn(origin, origin + ‘/manifest.json‘, [‘store_write‘, ‘publish_data‘])
}

  


請註意,默認情況下,身份驗證請求包括啟用存儲的store _ write範圍。
如果您想註銷並再次登錄,程序將為提示用戶身份驗證的請求,妳將會允許該程序發布妳本地所存儲的文字或圖片。

 

技术分享图片

 

發布狀態:

在此步驟中,我們將添加允許發布和顯示“狀態”的功能。
讓我們打開src / components / profile . jsx,然後從blockstack. js中導入我們將使用的幾個方法。這些方法是putFile ( )、getFile ( )和lookupProfile ( )。將它們添加到文件頂部附近blockstack的import語句中:

import {
  isSignInPending,
  loadUserData,
  Person,
  getFile,
  putFile,
  lookupProfile
} from ‘blockstack‘;

  

然後,我們需要在構造函數( )的初始狀態中添加壹些屬性。構造函數應如下所示:

constructor(props) {
  super(props);

  this.state = {
    person: {
      name() {
        return Anonymous;
      },
      avatarUrl() {
        return avatarFallbackImage;
      },
    },
    username: "",
    newStatus: "",
    statuses: [],
    statusIndex: 0,
    isLoading: false    
  };
}

 

現在,讓我們修改render ( )方法以添加文本輸入和提交按鈕,以便可以發布用戶的“微博狀態”。將render ( )方法替換為以下內容:

 

render() {
  const { handleSignOut } = this.props;
  const { person } = this.state;
  const { username } = this.state;

  return (
    !isSignInPending() && person ?
    <div className="container">
      <div className="row">
        <div className="col-md-offset-3 col-md-6">
          <div className="col-md-12">
            <div className="avatar-section">
              <img
                src={ person.avatarUrl() ? person.avatarUrl() : avatarFallbackImage }
                className="img-rounded avatar"
                id="avatar-image"
              />
              <div className="username">
                <h1>
                  <span id="heading-name">{ person.name() ? person.name()
                    : ‘Nameless Person‘ }</span>
                  </h1>
                <span>{username}</span>
                <span>
                   | 
                  <a onClick={ handleSignOut.bind(this) }>(Logout)</a>
                </span>
              </div>
            </div>
          </div>

          <div className="new-status">
            <div className="col-md-12">
              <textarea className="input-status"
                value={this.state.newStatus}
                onChange={e => this.handleNewStatusChange(e)}
                placeholder="What‘s on your mind?"
              />
            </div>
            <div className="col-md-12">
              <button
                className="btn btn-primary btn-lg"
                onClick={e => this.handleNewStatusSubmit(e)}
              >
                Submit
              </button>
            </div>
          </div>

        </div>
      </div>
    </div> : null
  );
}

  

在上面的render ( )方法中,我們還顯示了用戶的blockstack ID。我們需要從用戶配置文件數據中提取這壹點。找到componentWillMount ( )方法,並在person屬性下面添加用戶名屬性:

 

componentWillMount() {
  this.setState({
    person: new Person(loadUserData().profile),
    username: loadUserData().username
  });
}

  

接下來,我們將添加兩種方法來處理輸入事件:

handleNewStatusChange(event) {
  this.setState({newStatus: event.target.value})
}

handleNewStatusSubmit(event) {
  this.saveNewStatus(this.state.newStatus)
  this.setState({
    newStatus: ""
  })
}

  

 

然後執行所需存儲操作,下面是保存壹個“微博狀態”的方法:
 

saveNewStatus(statusText) {
  let statuses = this.state.statuses

  let status = {
    id: this.state.statusIndex++,
    text: statusText.trim(),
    created_at: Date.now()
  }

  statuses.unshift(status)
  const options = { encrypt: false }
  putFile(‘statuses.json‘, JSON.stringify(statuses), options)
    .then(() => {
      this.setState({
        statuses: statuses
      })
    })
}

  

現在,您應該可以在文本框中鍵入壹個狀態,然後按“提交”按鈕將其保存。
當您按下submit (提交)按鈕時,您將看到什麽也不會發生。因為我們沒有添加任何代碼來顯示狀態。

顯示狀態

返回render ( )方法,並在包含文本輸入和提交按鈕的div元素正下方添加以下塊。

<div className="col-md-12 statuses">
  {this.state.isLoading && <span>Loading...</span>}
  {this.state.statuses.map((status) => (
      <div className="status" key={status.id}>
        {status.text}
      </div>
    )
  )}
</div>

  

 

我們還需要在頁面加載時獲取狀態,所以我們添加壹個名為fetchData ( )的新方法,並從componentDidMount ( )方法調用它

componentDidMount() {
  this.fetchData()
}

fetchData() {
  this.setState({ isLoading: true })
  const options = { decrypt: false }
  getFile(‘statuses.json‘, options)
    .then((file) => {
      var statuses = JSON.parse(file || ‘[]‘)
      this.setState({
        person: new Person(loadUserData().profile),
        username: loadUserData().username,
        statusIndex: statuses.length,
        statuses: statuses,
      })
    })
    .finally(() => {
      this.setState({ isLoading: false })
    })
}

  


此時,我們有壹個基本的“區塊鏈微博”應用程序,可以用來發布和查看自己的狀態。但是,無法查看其他用戶的狀態。在接下來的步驟中,我們將進入“多用戶數據存儲”部分。但是首先,讓我們花點時間來完善我們的應用程序。
打開src/styles/style.css,並用以下內容替換現有樣式:

 

/* Globals */
a,a:focus,a:hover{color:#fff;}
html,body{height:100%;text-align:center;background-color:#191b22;}
body{color:#fff}
.hide{display:none;}
.landing-heading{font-family:‘Lato‘,Sans-Serif;font-weight:400;}

/* Buttons */
.btn{font-family:‘Lato‘,Sans-Serif;padding:0.5625rem 2.5rem;font-size:0.8125rem;font-weight:400;line-height:1.75rem;border-radius:0!important;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-ms-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}
.btn-lg{font-size:1.5rem;padding:0.6875rem 3.4375rem;line-height:2.5rem;}
.btn:focus,.btn:active:focus,.btn.active:focus{outline:none;}
.btn-primary{color:#fff;border:1px solid #2C96FF;background-color:#2C96FF;}
.btn-primary:hover,.btn-primary:focus,.btn-primary:active{color:#fff;border:1px solid #1a6ec0;background-color:#1a6ec0;}

/* Avatar */
.avatar{width:100px;height:100px;}
.avatar-section{margin-bottom:25px;display:flex;text-align:left;}
.username{margin-left:20px;}

/* Scaffolding */
.site-wrapper{display:table;width:100%;height:100vh;min-height:100%;}
.site-wrapper-inner{display:flex;flex-direction:column;justify-content:center;margin-right:auto;margin-left:auto;width:100%;height:100vh;}
.panel-authed{padding:0 0 0 0;}

/* Home button */
.btn-home-hello{position:absolute;font-family:‘Source Code Pro‘,monospace;font-size:11px;font-weight:400;color:rgba(255,255,255,0.85);top:15px;left:15px;padding:3px 20px;background-color:rgba(255,255,255,0.15);border-radius:6px;-webkit-box-shadow:0px 0px 20px 0px rgba(0,0,0,0.15);-moz-box-shadow:0px 0px 20px 0px rgba(0,0,0,0.15);box-shadow:0px 0px 20px 0px rgba(0,0,0,0.15);}

/* Input */
input, textarea{color:#000;padding:10px;}
.input-status{width:100%;height:70px;border-radius:6px;}
.new-status{text-align:right;}

/* Statuses */
.statuses{padding-top:30px;}
.status{margin:15px 0px;padding:20px;background-color:#2e2e2e;border-radius:6px}

如果壹切順利,我們最終的結果應該是這樣的:

 

用戶配置文件查找

現在讓我們修改 Profile.jsx以顯示其他用戶的配置文件。我們將使用blockstack . js提供的lookupProfile ( )方法,我們在前面的導入語句中添加了該方法。lookupProfile ( )接受單個參數,該參數是要查找的配置文件的blockstack ID,並返回配置文件對象。
首先,我們將對應用程序的路由結構進行壹些更改,以便通過訪問http:// localhost:8080/other_user.id來查看其他用戶的配置文件
安裝 react-router:

npm install --save react-router-dom

打開src/index.js並添加到文件頂部:

import { BrowserRouter } from ‘react-router-dom‘

 

接下來,將src / index . js中的reactdom . render ( )方法更改為:

 

ReactDOM.render((
  <BrowserRouter>
    <App />
  </BrowserRouter>
), document.getElementById(‘root‘));

Then we‘ll need to go back to src/components/App.jsx and add the new route. Open src/components/App.jsx and import the Switch and Route components from react-router-dom:

import { Switch, Route } from ‘react-router-dom‘

接下來,在render ( )方法中找到下面的行:

<Profile handleSignOut=this.handleSignOut } />

並將其替換為:

 :
  <Switch>
    <Route
      path=‘/:username?‘
      render={
        routeProps => <Profile handleSignOut={ this.handleSignOut } {...routeProps} />
      }
    />
  </Switch>

這會設置路由並捕獲要用作配置文件查找用戶名的路由參數。
我們還需要在webpack配置中添加壹個規則,以便正確處理包含的URL路徑。角色。例如: http://localhost:8080/other_user.id 註意:在生產應用程序中,需要配置web服務器來處理此問題。
在根項目目錄中打開webpack . config . js,然後找到以下行:

historyApiFallback: {
  disableDotRule: true
},

 

更改為:

historyApiFallback: {
  disableDotRule: true
},

 

**註:我們需要再次運行啟動NPM,這樣才能生效。
現在,我們跳回到src / components / profile . jsx,並添加壹個方法來確定是查看本地用戶的配置文件還是其他用戶的配置文件。**

 

isLocal() {
  return this.props.match.params.username ? false : true
}

 

 

然後我們可以修改fetchData ( )方法,如下所示:

fetchData() {
  this.setState({ isLoading: true })
  if (this.isLocal()) {
    const options = { decrypt: false }
    getFile(‘statuses.json‘, options)
      .then((file) => {
        var statuses = JSON.parse(file || ‘[]‘)
        this.setState({
          person: new Person(loadUserData().profile),
          username: loadUserData().username,
          statusIndex: statuses.length,
          statuses: statuses,
        })
      })
      .finally(() => {
        this.setState({ isLoading: false })
      })
  } else {
    const username = this.props.match.params.username

    lookupProfile(username)
      .then((profile) => {
        this.setState({
          person: new Person(profile),
          username: username
        })
      })
      .catch((error) => {
        console.log(‘could not resolve profile‘)
      })
  }
}

我們首先使用isLocal ( )檢查是否正在查看本地用戶配置文件或其他用戶的配置文件。如果是本地用戶配置文件,我們將運行前面添加的getFile ( )函數。否則,我們使用lookupProfile ( )方法查找屬於用戶名的配置文件。

註意:對於https部署,用於名稱查找的默認塊堆棧核心API端點應更改為指向通過https提供的核心API。否則,由於瀏覽器阻止混合內容,名稱查找將失敗。有關詳細信息,請參閱blockstack . js文檔。

為了獲取用戶的狀態,我們在調用lookupProfile (用戶名)後立即向fetchData ( )添加以下lookupProfile(username)... catch((error)=>{..}塊:

const options = { username: username, decrypt: false }
getFile(‘statuses.json‘, options)
  .then((file) => {
    var statuses = JSON.parse(file || ‘[]‘)
    this.setState({
      statusIndex: statuses.length,
      statuses: statuses
    })
  })
  .catch((error) => {
    console.log(‘could not fetch statuses‘)
  })
  .finally(() => {
    this.setState({ isLoading: false })
  })

 

最後,我們需要有條件地呈現註銷按鈕、狀態輸入文本框和提交按鈕,以便它們在查看其他用戶的配置文件時不會顯示。在render ( )方法中,通過使用{ isLocal ( ) & &...}條件:

 

{this.isLocal() &&
  <span>
    &nbsp;|&nbsp;
    <a onClick={ handleSignOut.bind(this) }>(Logout)</a>
  </span>
}

//...

{this.isLocal() &&
  <div className="new-status">
    <div className="col-md-12">
      <textarea className="input-status"
        value={this.state.newStatus}
        onChange={this.handleNewStatusChange}
        placeholder="What‘s on your mind?"
      />
    </div>
    <div className="col-md-12 text-right">
      <button
        className="btn btn-primary btn-lg"
        onClick={this.handleNewStatusSubmit}
      >
        Submit
      </button>
    </div>
  </div>
}

 

ok!將瀏覽器指向http://localhost:8080/your_blockstack.id以查看配置文件。註意:您需要有壹個註冊的blockstack ID才能使此操作生效。

源代碼地址:

https://github.com/larrysalibra/publik

 

























以上是关于blockstack.js 教程:如何在blockstack上寫壹個區塊鏈“臉書” 程序的主要内容,如果未能解决你的问题,请参考以下文章

Code::Blocks汉化教程(附带汉化包)

Bukkit插件开发教程 - Block(方块)

在Code::Blocks中编译和使用wxWidgets3.0.0教程

Eigen教程

Code::Blocks

使用 block rom 将图像值存储在 fpga 中