利用arweave进行第一个dapp开发(上篇)
1.获取代码并运行
从 github 克隆public-square-app模板的副本。
git clone https://github.com/DanMacDonald/public-square-app.git
这将创建一个我们可以导航到的 /public-square-app 目录。
cd public-square-app
然后我们可以运行两个命令,第一个是初始化我们的项目依赖,第二个是在开发者模式下启动它。
npm install
npm start
2.编写查询函数
我们需要的第一件事是一个查询函数,我们可以从应用程序的任何位置调用以从 arweave 检索数据。打开src/lib/api.js
文件并更新buildQuery
函数如下。稍后我们将使这个buildQuery
函数动态化并过滤不同的结果。
export const buildQuery = () => {
const queryObject = { query: `{
transactions(first: 100,
tags: [
{
name: "App-Name",
values: ["PublicSquare"]
},
{
name: "Content-Type",
values: ["text/plain"]
}
]
) {
edges {
node {
id
owner {
address
}
data {
size
}
block {
height
timestamp
}
tags {
name,
value
}
}
}
}
}`}
return queryObject;
}
3.集成 Arweave-js
首先,我们arweave-js
要从 npm 安装包。
npm install --save arweave
在src/lib/api.js
文件顶部添加以下行建立与arweave的交互。
import Arweave from 'arweave';
export const arweave = Arweave.init({});
这将创建一个 arweave api 对象的实例,其默认配置指向https://arweave.net网关。在代码库中的单个位置初始化 arweave,然后从其他地方引用它,这将使您的应用程序在未来更容易指向不同的环境或网关。
4.查询网关
现在让我们转到src/App.js
.
首先是通过buildQuery()
以下导入导入我们的 arweave 实例和函数。
import { buildQuery, arweave } from './lib/api';
然后编辑getPostInfos()
函数看起来像这样。
async function getPostInfos() {
const query = buildQuery();
const results = await arweave.api.post('/graphql', query)
.catch(err => {
console.error('GraphQL query failed');
throw new Error(err);
});
const edges = results.data.data.transactions.edges;
console.log(edges);
return [];
}
在这里,我们使用arweave-js
包向默认网关的 graphql 端点 ( https://arweave.net/graphql ) 发布 GraphQL 请求并等待响应。
现在我们只返回一个空数组,以免混淆示例项目代码的其余部分。
刷新显示 dApp 的浏览器选项卡,然后查看浏览器中的开发者控制台。
当站点加载时,您会在浏览器开发者控制台中看到类似的内容。
如果您完全展开第一个元素,您将看到我们在查询中请求的数据结构反映在结果中。
5.将数据绑定到视图组件
在src/App.js
,更新我们的导入语句以包含createPostInfo
.
import { buildQuery, arweave, createPostInfo } from './lib/api';
然后,用以下代码行替换return [];
末尾。getPostInfos()
return edges.map(edge => createPostInfo(edge.node));
将以下两行添加到App()
函数的开头。因此,让 React 知道我们将在应用程序级别存储此状态。
const [postInfos, setPostInfos] = React.useState([]);
const [isSearching, setIsSearching] = React.useState(false);
postInfos
状态是我们将保存我们的项目数组的地方postInfo
。React 足够聪明,只有在底层数据发生变化时才重新绑定使用这些项目的视图。通过将其存储在应用程序级别,它允许我们导航到 UI 的其他区域,而无需卸载我们的postInfos
. 虽然网关可能会处理我们在每次查看时间线时查询网关,但为什么不构建一点缓存并成为优秀的 arweave 生态系统参与者呢?isSearching
是一个状态标志,我们将使用它来控制在我们的查询运行时将显示的加载微调器的可见性。让用户知道正在发生某些事情是一种很好的感觉。当用户通过慢速连接进行连接时,这一点很重要。
是时候执行我们的postInfos
查询了。为此,我们将使用 React 的useEffect()
方法。修改useEffect()
我们刚刚添加的两行下面的代码,如下所示。
React.useEffect(() => {
setIsSearching(true)
getPostInfos().then(posts => {
setPostInfos(posts);
setIsSearching(false);
});
}, [])
useEffect()
的用法如下。
useEffect(<function to execute>, [<state items that trigger re-executing the function>]}
- 要执行的函数是我们想要完成的工作
useEffect()
。 - 第二个参数是一个状态变量数组(就像我们用 初始化的
postInfos
和变量)。如果我们不提供第二个参数,则每次渲染组件时都会运行该函数来执行。这将是可怕的垃圾邮件,并会导致重叠的异步网络请求,这将是一团糟。值得庆幸的是,我们可以为这个参数提供一个空数组,告诉仅在挂载父组件时运行要执行的函数。isSearching``useState()``useEffect()``<App />``useEffect()
在44-46行修改组件并传入我们的新状态属性。代码应如下所示。
<Home
isSearching={isSearching}
postInfos={postInfos}
/>}
并找到以该行开头const Home = (props) => {
和正下方的<header>Home</header>
部分,添加以下两行代码。
{props.isSearching && <ProgressSpinner />}
<Posts postInfos={props.postInfos} />
6.获取消息
在src/lib/api.js
编辑createPostInfo()
export const createPostInfo = (node) => {
const ownerAddress = node.owner.address;
const height = node.block ? node.block.height : -1;
const timestamp = node.block ? parseInt(node.block.timestamp, 10) * 1000 : -1;
const postInfo = {
txid: node.id,
owner: ownerAddress,
height: height,
length: node.data.size,
timestamp: timestamp,
request: null,
}
if (postInfo.length <= maxMessageLength) {
postInfo.request = arweave.api.get(`/${node.id}`, { timeout: 10000 })
.catch(() => { postInfo.error = 'timeout loading data' });
} else {
postInfo.error = `message is too large (exceeds ${maxMessageLength/1024}kb)`;
}
return postInfo;
}
关注公众号,及时获取大数据干货知识