# 去中心化社交协议Farcaster教程(a16z领投)

By [kool](https://paragraph.com/@kool) · 2022-07-14

---

### Step 1: 设置环境

在编写代码之前，您需要设置一个 Node.js 环境，推荐使用

[https://replit.com/](https://replit.com/)

它是一个基于 IDE 进行编程的浏览器。

1.在 repli 上注册一个免费帐户并登录；

2.点击左上角的create创建；

![](https://storage.googleapis.com/papyrus_images/af737b27fc650120e359a01d71fdb2949c7ec8c3f9f54d9032ebededb8dc1b39.png)

3.出现提示时选择 Node.js，然后点击Create Repl。

![](https://storage.googleapis.com/papyrus_images/ba15869208dbad4bbca8d33299846b16cfef71f7e488f9e8bec604c27bd74ba8.png)

还需要一个以太坊节点来与 Facaster Registry 合约对话。 建议使用 [Alchemy](https://www.alchemy.com/) 。 如果您是第一次注册，以下步骤可能会略有不同：

1.注册 [Alchemy.com](http://www.alchemy.com/) ，并登录。

![](https://storage.googleapis.com/papyrus_images/3dcf3162947762466bb11296798be263a6c167a810a0dc52bd9810c309af5754.png)

2.选择以太坊作为区块链，点击get started。

![](https://storage.googleapis.com/papyrus_images/4e0284315b651eda87fe8efa360c431883ba9fb2ccfa928014064e305ce0d74d.png)

3.team name和app name随便取，网络选择Rinkeby，点击Create APP。

![](https://storage.googleapis.com/papyrus_images/727df8dad0e5950fd0b3066a0b3c3ea45583a32fceb1d97eb232d023ff565d6b.png)

4.选择第一个免费的，点击continue。

![](https://storage.googleapis.com/papyrus_images/a3bb537510b8a05441fc22d8b5547dd5cca1c60f68118d58947d80f1170841d2.png)

5.点击跳过。

![](https://storage.googleapis.com/papyrus_images/47cc09fd71633ce1990b268e3978d3e140bc7f7721ce63f25397f1c4d4911fee.png)

6.继续点击跳过。

![](https://storage.googleapis.com/papyrus_images/6240ba6e63db4fb2d72d018b91d85d517b09e0e9ed0eb20044cde7ea559a2106.png)

7.点击continue。

![](https://storage.googleapis.com/papyrus_images/d2f5a07342c8371529e5a00323848f2242f896f94878d55c3951a6b78b0c5ba8.png)

8.随便输入什么,点击let‘s go。

![](https://storage.googleapis.com/papyrus_images/6bda57a42a24e1ba834b85932f707e91fb644d927231f4aec5be9a962026d02d.png)

9.点击view details。

![](https://storage.googleapis.com/papyrus_images/6accf3926b7ad81549aca376b289a78f5a26fee759ed9afa6b63161c7d92682f.png)

10.点击view key。

![](https://storage.googleapis.com/papyrus_images/4ec78ee52ad3cd1811e9264043d71f46d236179ab7c85beddfecf72484e19574.png)

11.找到HTTP的URL，复制v2/后面那部分代码，将其保存在某个地方。

![](https://storage.googleapis.com/papyrus_images/7765964e568fefec57e5f0b0c321632517fa1db42964f6ed93f874b8d5a84d22.png)

12.切换回 Replit 并转到右侧窗格中的 Shell 选项卡并运行以下代码：

npm install ethers [got@11.8.2](http://mailto:got@11.8.0.2/)

这将安装 [ethers](https://github.com/ethers-io/ethers.js) ，一个用于与 Ethereum 一起工作的库， [got](https://github.com/sindresorhus/got) ，一个用于发出 HTTP 请求的库。 您可能会看到一些关于缺少 package.json 的警告，您可以忽略这些警告。

![](https://storage.googleapis.com/papyrus_images/8c1876827b0be294977f85b1d9629e26fe67b07b8aea0c61b2eb4604c5d62e7d.png)

### Step 2: 连接到以太坊节点

1.切换到 Replit 中心窗格中的 index.js 选项卡，然后复制下面的代码片段。 确保将那一堆×换成step1 的第11步保存的代码，点击run。

const { providers, Contract, utils } = require("ethers"); const got = require("got");

const doStuff = async () => { const ALCHEMY\_SECRET = 'jeb8oUMpgcUfTe0-1A7\_0niISnRpmNhM'; // Replace with your secret const provider = new providers.AlchemyProvider('rinkeby', ALCHEMY\_SECRET);

const block = await provider.getBlockNumber(); console.log("The latest Ethereum block is:", block);

const REGISTRY\_CONTRACT\_ADDRESS = '0xe3Be01D99bAa8dB9905b33a3cA391238234B79D1' const REGISTRY\_ABI = \[ { name: 'getDirectoryUrl', inputs: \[{ internalType: 'bytes32', name: 'username', type: 'bytes32' }\], outputs: \[{ internalType: 'string', name: '', type: 'string'}\], stateMutability: 'view', type: 'function', }, { inputs: \[{ internalType: 'address', name: '', type: 'address' }\], name: 'addressToUsername', outputs: \[{ internalType: 'bytes32', name: '', type: 'bytes32' }\], stateMutability: 'view', type: 'function', }, \];

const registryContract = new Contract(REGISTRY\_CONTRACT\_ADDRESS, REGISTRY\_ABI, provider);

const username = 'v'; const byte32Name = utils.formatBytes32String(username); const directoryUrl = await registryContract.getDirectoryUrl(byte32Name); console.log(`${username}'s Host is located at: ${directoryUrl} \n`);

const directoryResponse = await got(directoryUrl); const directory = JSON.parse(directoryResponse.body); console.log(`${username}'s Directory is:` ); console.log(directory, '\\n');

const addressActivityUrl = directory.body.addressActivityUrl; const addressActivityResponse = await got(addressActivityUrl); const addressActivity = JSON.parse(addressActivityResponse.body); const cast = addressActivity\[0\]; console.log(`${username}'s most recent Cast was:` ) console.log(cast, '\\n');

const stringifiedCastBody = JSON.stringify(cast.body); const calculatedHash = utils.keccak256(utils.toUtf8Bytes(stringifiedCastBody)); const expectedHash = cast.merkleRoot;

if (calculatedHash !== expectedHash) { console.log(`FAILED: the calculated hash ${calculatedHash} does not match the one in the cast: ${expectedHash}`); } else { console.log(`PASSED: the calculated hash ${calculatedHash} matches the one in the cast`); }

const recoveredAddress = utils.verifyMessage(cast.merkleRoot, cast.signature); const expectedAddress = cast.body.address;

if (recoveredAddress !== expectedAddress) { console.log( `Failed: the recovered address ${recoveredAddress} does not match the address provided in the cast ${expectedAddress}` ); } else { console.log(`PASSED: the recovered address ${recoveredAddress} matches the one in the cast`); }

const encodedUsername = await registryContract.addressToUsername(expectedAddress); const expectedUsername = utils.parseBytes32String(encodedUsername); const castUsername = cast.body.username;

if (expectedUsername !== castUsername) { console.log(`FAILED: ${expectedAddress} does not own ${castUsername}, it owns ${expectedUsername}`); } else { console.log(`PASSED: ${expectedAddress} owns ${castUsername}`); } }

doStuff();

2.

![](https://storage.googleapis.com/papyrus_images/f07cd30a490186cca3742f599dfe7ea035ecf98187723e97e270b79d726a80a3.jpg)

### Step 3: 验证有用户名V的地址

如果这成功完成，您会看到如下消息：

通过：0x012D3606bAe7aebF03a04F8802c561330eAce70A 拥有 v

**恭喜 - 你已经在 Farcaster 上构建了你的第一个可以读取用户消息的应用程序！ 您还学习了如何验证签名，以便您可以安全地接收来自网络上任何用户的消息！**

---

*Originally published on [kool](https://paragraph.com/@kool/farcaster-a16z)*
