<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>xiaoju</title>
        <link>https://paragraph.com/@ikunfamily</link>
        <description>专业的区块链玩家</description>
        <lastBuildDate>Thu, 27 Aug 2026 00:32:09 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <image>
            <title>xiaoju</title>
            <url>https://storage.googleapis.com/papyrus_images/2f1c8beda552e5446ff29665070b1ef94d199010b17447b49712503f48865fa0.png</url>
            <link>https://paragraph.com/@ikunfamily</link>
        </image>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[STEPN 概述：让您保持活跃的赚钱协议]]></title>
            <link>https://paragraph.com/@ikunfamily/stepn</link>
            <guid>rx7s17wGwBlsBvbFGmXd</guid>
            <pubDate>Wed, 20 Jul 2022 05:27:09 GMT</pubDate>
            <description><![CDATA[STEPN 在 Web3 生活方式应用程序中结合了 Social-Fi 和 Game-Fi 元素，您可以在其中通过步行、慢跑或户外跑步来赚取游戏内的代币。 引领盈利行业 GameFi行业有望引领下一波加密采用浪潮，除了游戏赚钱模式外，还有移动赚钱 (M2E) 模式。STEPN 是顶级 M2E 游戏之一，在 3 月 2 日在 Binance Launchpad 上进行代币销售后，获得了31,000% 的巨额利润。 STEPN 在 Web3 生活方式应用程序中结合了 Social-Fi 和 Game-Fi 元素。通过在户外散步、慢跑或跑步，您可以获得游戏内代币GST，可用于升级和铸造新运动鞋。 来源 ‍ 简要背景 STEPN 的母公司 Satoshi Lab 由 Jerry Huang 和 Yawn Rong 于 2021 年创立。在 2021 年 9 月的招聘活动之后，STEPN 团队在 2021 年 12 月的Solana Ignition Hackathon中排名第四，吸引了投资者的兴趣。 之后，STEPN从 6th Man Ventures、Alameda Research、...]]></description>
            <content:encoded><![CDATA[<figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/85a94edee8bfe8b2389067938b7298ff46cd659ff5414f555e6904ca4b5166fd.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>STEPN 在 Web3 生活方式应用程序中结合了 Social-Fi 和 Game-Fi 元素，您可以在其中通过步行、慢跑或户外跑步来赚取游戏内的代币。</p><p>引领盈利行业 GameFi行业有望引领下一波加密采用浪潮，除了游戏赚钱模式外，还有移动赚钱 (M2E) 模式。STEPN 是顶级 M2E 游戏之一，在 3 月 2 日在 Binance Launchpad 上进行代币销售后，获得了31,000% 的巨额利润。</p><p>STEPN 在 Web3 生活方式应用程序中结合了 Social-Fi 和 Game-Fi 元素。通过在户外散步、慢跑或跑步，您可以获得游戏内代币GST，可用于升级和铸造新运动鞋。</p><p>来源 ‍</p><p>简要背景 STEPN 的母公司 Satoshi Lab 由 Jerry Huang 和 Yawn Rong 于 2021 年创立。在 2021 年 9 月的招聘活动之后，STEPN 团队在 2021 年 12 月的Solana Ignition Hackathon中排名第四，吸引了投资者的兴趣。</p><p>之后，STEPN从 6th Man Ventures、Alameda Research、Corner Ventures 等公司筹集了 500 万美元的种子轮融资。随着平台上唯一账户数量的增加，M2E 平台在 2022 年第一季度实现了 2680 万美元的可观收益。</p><p>‍</p><p>从 STEPN 应用程序开始 1.下载安装STEPN</p><p>太开始了，请访问 STEPN 网站。您可以通过点击下载按钮下载适用于 Android 或 iOS 的应用程序。</p><p>资源 ‍ 2.创建账户</p><p>安装完成后，您需要使用您的电子邮件地址进行注册。现在您将在电子邮件中收到验证码。输入代码后，在一分钟内点击登录。</p><p>之后，STEPN 将要求提供激活码。STEPN 激活码可以在STEPN Discord 服务器、STEPN Reddit和许多其他加密论坛上找到。</p><p>来源：STEPN 应用程序 ‍ 3.创建STEPN钱包</p><p>完成注册和激活码流程后，您将登陆应用主页。你的手机屏幕右上角会有一个钱包图标。点击它。您现在将看到两个选项卡：支出和钱包。点击钱包。点击钱包后，将出现一个弹出窗口。种子短语可用于创建新钱包或导入现有钱包。</p><p>让我们在应用程序中“创建一个新钱包”。点击“创建新钱包”。然后 STEPN 将要求您创建一个密码，您将需要该密码来锁定/解锁您的钱包。然后，您将看到一个种子短语。除了以数字方式存储它之外，还要以物理方式存储它。任何知道您的助记词的人都可以访问您的 STEPN 钱包。</p><p>来源：STEPN 应用程序 4. 将 SOL 转入 STEPN 钱包</p><p>设置密码并存储助记词后，转到应用内钱包并通过点击“接收”来复制接收地址。然后，去您首选的交易所购买和提取 $ SOL。在交易所的应用程序上点击提款。</p><p>输入您的 STEPN 钱包地址和您希望发送的 SOL 数量。然后，在完成验证 5 分钟后检查您的 STEPN 钱包。</p><ol><li><p>获得一双 NFT 运动鞋</p></li></ol><p>要在 STEPN 中赚钱，您必须购买与您的健身水平相匹配的NFT Sneaker。</p><p>有几个选项可用：</p><p>沃克（1-6 公里/小时） 慢跑者（4-10 公里/小时） 跑步者（8-20 公里/小时） 教练员（1-20公里/小时） 有一个应用内市场，您可以在其中购买 NFT 运动鞋。除了运动鞋，您还可以购买鞋盒。鞋盒中随机有一只 Sneaker。在撰写本文时，运动鞋的底价在 2.14 美元至 2.55 美元之间（约合 78 美元至 93 美元）。</p><p>来源：STEPN 应用程序 总的来说，目前您需要大约 2-3 $SOL 才能开始使用 STEPN。除了 Sneaker 价格外，请确保有少量 $SOL 可用于支付 gas 费用。每款运动鞋的 $GST 回报各不相同。</p><p>NFT Sneaker 页面包含所有详细信息，包括：</p><p>品质：普通、罕见、稀有、史诗、传奇 效率：提高 GST 代币收益 幸运：提高神秘盒子的掉落率 舒适：增强GMT 代币收益（30 级） 弹性：降低维修成本</p><p>来源：STEPN 应用程序 ‍ 6.到户外跑步</p><p>拿到 NFT 运动鞋后，在户外跑步、步行或慢跑时使用 GPS。如果您的 GPS 信号强，您将获得保证收入。低 GPS 信号或无信号将导致低至无增益。该应用程序旨在检测和忽略非有机运动（即，使用电动滑板车或将手机绑在狗身上）。此外，您必须根据您选择的运动鞋保持最佳速度。</p><ol><li><p>烧掉 $GST/$GMT</p></li></ol><p>在 STEPN 中，燃烧 $GST 意味着花费它。</p><p>您可以通过赚取的 $GST/$GMT 升级您的运动鞋，以提高它们的效率。 您可以保留或出售您铸造的运动鞋。 $GST/$GMT 可以换成 $USDC。 现在让我们研究一下 STEPN 的代币经济学。</p><p>‍</p><p>代币经济学 STEPN 加密货币经济模型由两个代币组成。$ GST是用于支付应用内奖励的实用代币。代币的供应量不受限制，但每次铸造、修复或升级时都会被烧毁。</p><p>Green Metaverse 代币（格林威治标准时间美元）的最大供应量上限为 60 亿，是 STEPN 的治理代币，也是投资者的主要价值储存手段。</p><p>根据截至 2030 年 3 月的归属时间表，GMT 的供应分配如下：</p><p>30% 用于应用内奖励 30% 保留在国库中 16.3% 预留给私人销售 14.2% 被团队保留 7% 预留给 Binance Launchpad 销售 2.5% 分配给顾问。</p><p>来源 GMT 持有者可以质押他们的代币以参与投票。在集体投票中，代币持有者决定将一定比例的代币捐赠给碳抵消计划。</p><p>奖励通常以 GST 支付，但某些参数（例如拥有 30 级运动鞋）允许他们在 GMT 时获得。随着时间的推移，代币的排放率由于各种机制而降低，包括减半计划。</p><p>‍</p><p>附加的功能 神秘盒子</p><p>在单人模式下移动时，神秘盒子会随机掉落。它包含 $GST 和宝石（1 - 3 级）。每个用户有四个神秘盒子插槽。神秘盒子有 10 种品质。收到神秘盒子后，倒计时会自动开始。当倒计时结束时，用户会花费少量 $GST（“基本成本”）来打开它。倒计时持续时间随着神秘盒子的质量而增加。</p><p>运动鞋质量</p><p>运动鞋有五种品质（普通、罕见、稀有、史诗和传奇）。铸造运动鞋时，每个属性的值都是在运动鞋质量决定的最小值和最大值之间随机选择的。因此，即使是相同品质的 Sneaker，也可能有着明显不同的属性等级。当达到某些里程碑时，用户需要消耗 $GMT 来升级他们的运动鞋。</p><p>‍ 制鞋业</p><p>在造鞋活动 (SME) 期间，用户使用他们拥有的两个运动鞋作为蓝图来“繁殖”，创建一个鞋盒。作为参考，这两款 Sneaker 将被称为 Vintages（父母）。</p><p>为了开始 SME，两个 Vintage 都必须由用户拥有（非租用）并且完全耐用。然后，用户可以通过访问 Mint 选项卡、选择 Sneaker 并按下 Mint 来选择要“繁殖”的 Sneaker。两种年份都有 72 小时的铸币冷却时间，但在此期间它们仍可用于移动。在此处了解铸币成本。</p><p>来源 ‍</p><p>游戏模式 独奏模式</p><p>用户通过穿着 NFT 运动鞋在单人模式中赚取代币。需要能源才能赚取 $GST。只有在用户获得 NFT 运动鞋后才会补充能量：1 能量等于 5 分钟的 Move-to-Earn 运动。</p><p>马拉松模式（开发中）</p><p>马拉松模式要求用户提前 24 小时在 Marathon Tab 下注册。马拉松将每周和每月举行一次。在此处了解有关每周马拉松和每月马拉松的更多信息。</p><p>‍</p><p>市场低迷影响STEPN STEPN 代币的价格随着整体熊市而下跌，因为治理代币和实用代币均较今年早些时候的历史高点下跌了 80% 至 98%。在 4 月达到顶峰时，$GMT 和 $GST 分别为 4.19 美元和 9.36 美元。此后，两个代币均呈下行趋势，形势严峻。</p><p>来源：GST 代币图表</p><p>来源：GMT 代币图表 一些社区成员将代币的急剧下降归因于 STEPN 应用程序在中国被禁止。</p><p>“自从中国禁赛以来，这就是一场大屠杀，价格大幅下跌，以至于对于小跑步者/步行者来说，去散步几乎没有回报。” 一位 STEPN 用户和BSC 新闻的密切接触者说。“Solana 和 GST 的价格下降了，鞋子变得非常便宜（我的鞋子损失惨重）。” 在 STEPN 流行的高峰期，用户可以通过在单人模式下在附近慢跑来赚取数百美元。即使使用基本运动鞋，也有可能以 9.36 美元的最高价格获得 3-4 美元 GST 的 NFT 每日奖励。目前，同样的步行，在 4 月份可以为用户赚取高达 40 美元的收益，但收益仅为 0.82 美元左右。</p><p>以前，使用 Solana NFT 的成本约为 600 美元，获得正的投资回报率大约需要 16 天。但目前，截至 7 月 14 日，购买最便宜的 Sneaker 的成本约为 69.88 美元。以目前的价格点，投资者需要大约 145 天才能达到收支平衡，每天的回报为 0.70 美元。结果，一些社区成员之间出现了看跌情绪。</p><p>“有些人还在玩游戏……我的意思是，距离禁令还有一个月的时间……如果我在中国，我会舒服地玩游戏，等到 7 月 10 日扔掉我的运动鞋离开。” STEPN Discord 的一位社区成员说。 ‍</p><p>积极推动 该公司在一篇Medium 帖子中表示，尽管过去几个月加密市场状况有所下降，但 STEPN 第二季度的利润为 1.225 亿美元。</p><p>资源 M2E 协议计划利用其利润的 5% 为其 GMT 代币启动回购和销毁计划。然而，为防止价格突然波动，回购和销毁过程“可能需要几周时间才能完成”。</p><p>此外，开发人员表示，除了回购和销毁计划之外，STEPN 将分配资本储备来改进现有功能并建立团队。尽管该协议面临挑战，但许多人仍然保持乐观。</p><p>“如果 STEPN 团队最终确定了他们的产品并开始了大规模的营销活动，那么事情仍然可能再次上升。散步或跑步的赚钱部分吸引了许多人，他们只是还不知道，或者还不习惯使用加密钱包，”一位接近BSC 新闻的 STEPN 成员说。“为了让 STEPN 成功，我认为他们需要针对没有加密领域经验的人开展大型营销活动，我认为他们应该为不了解私钥等的人提供托管钱包。 ” STEPN 报告称，该公司已经确定了几个投资其赚取资本的领域，以便改进游戏玩法。其中包括安全增强、防止机器人获得 GMT 的反作弊机制、建立开发人员和核心团队，以及确保赞助和合作伙伴关系。</p><p>“我投入了很多。我现在不担心回报，因为我专注于长期。现在，我正在增加我在两条链上的持股量，增加我的主要鞋子，并为第三领域做准备，”一位社区成员说。 在 SOL领域和 BNB 领域取得成功之后，STEPN 打算在以太坊上引入APE 领域。</p><p>STEPN 团队将这个 Realm 描述为“一个拥抱时尚和其他 NFT 社区的伟大实验”。 APE Realm 将为所有 STEPN 用户提供对创新的新 Realm 的访问，专注于可访问性和引入新用户。</p><p>资料来源： STEPN 路线图 ‍</p><p>离别的思念 由于行业低迷，以及中国数据法禁止存储公民 GPS 数据，STEPN 不得不屏蔽中国用户。此外，STEPN 的平台自推出以来一直受到一系列分布式拒绝服务 (DDoS) 攻击，导致用户在维护期间被警告“可能无法正确记录锻炼”。</p><p>然而，如果 STEPN 克服了这些障碍，加密货币市场可能会成为一个蓬勃发展的行业。此外，如果它的经济激励措施能激励一些人离开沙发开始行动，那也是一件好事。</p><p>来源 STEPN 社区在社交媒体上非常活跃，仅在 Twitter 上就有超过 640,000 名关注者。许多用户在 NFT 市场上创造了高流动性，使升级后的运动鞋更容易出售。最后但同样重要的是，即将到来的租赁升级和以太坊上的 Ape Realm 应该会增加用户群，增加所有代币的价值。</p><p>‍</p><p>什么是步骤： STEPN 是一个结合了 GameFi 和 SocialFi 元素的 Web3 应用程序，允许用户 Move &amp; Earn（移动和赚取）。用户将通过步行、慢跑或户外跑步来获得游戏内代币。STEPN 在 GST 和 GMT 两种代币机制下运行（治理代币，供应有限）。</p>]]></content:encoded>
            <author>ikunfamily@newsletter.paragraph.com (xiaoju)</author>
        </item>
        <item>
            <title><![CDATA[farcaster空投交互教程]]></title>
            <link>https://paragraph.com/@ikunfamily/farcaster</link>
            <guid>9hFVLGi9Jg7XDeKzjkN0</guid>
            <pubDate>Thu, 14 Jul 2022 02:56:07 GMT</pubDate>
            <description><![CDATA[用技术带你领略区块链魅力01-farcaster用技术带你领略区块链魅力，今天我们一起来看下a16z领投3000万美元的去中心化社交协议Farcaster怎么玩？ 1.首先我们需要一个node环境，这边官方建议我们是使用repli（repli.com），我们首先去到该网站建立一个nodejs的仓库在上面paul将他划分成了4个区，大家可以对照的看，当我们建立好后，在我们的命令脚本区输入： *npm install ethers got@11.8.2 安装我们的依赖，我们可以看到在我们的package.json中会有我们的依赖.2.将下面的代码放入到index.js中const { providers, Contract, utils } = require("ethers");const got = require("got"); const doStuff = async () => { const ALCHEMY_SECRET = 'YFNEz9ywV3392OD6ku7Vt1wADtjVAoYL'; // Replace with your secret const pro...]]></description>
            <content:encoded><![CDATA[<h1 id="h-01-farcaster" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">用技术带你领略区块链魅力01-farcaster</h1><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/7e0a3de9abf1d902c6badb3e7b1999253850e1bd80ad8440c44c738b24c2101e.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>用技术带你领略区块链魅力，今天我们一起来看下a16z领投3000万美元的去中心化社交协议Farcaster怎么玩？</p><p>1.首先我们需要一个node环境，这边官方建议我们是使用repli（repli.com），我们首先去到该网站建立一个nodejs的仓库</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/0a91c8edfd43c547afd8947a85ae501d25c1ad10aeab873bbf2881b26447f4af.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/97accc4e999fc20fa9e7da648a7e7bb36f8eab1f7d6d0e722496dd78ebe8b088.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>在上面paul将他划分成了4个区，大家可以对照的看，当我们建立好后，在我们的命令脚本区输入：</p><p>*</p><pre data-type="codeBlock" text="npm install ethers got@11.8.2
"><code>npm install ethers got<span class="hljs-keyword">@11</span>.8.2
</code></pre><p>安装我们的依赖，我们可以看到在我们的package.json中会有我们的依赖.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/cd7106026caf40560de88aeed574e59485f827ed2a4a64e6406379229ba895b0.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>2.将下面的代码放入到index.js中</p><blockquote><pre data-type="codeBlock" text="const { providers, Contract, utils } = require(&quot;ethers&quot;);const got = require(&quot;got&quot;);
const doStuff = async () =&gt; {  const ALCHEMY_SECRET = &apos;YFNEz9ywV3392OD6ku7Vt1wADtjVAoYL&apos;; // Replace with your secret  const provider = new providers.AlchemyProvider(&apos;rinkeby&apos;, ALCHEMY_SECRET);
    const block = await provider.getBlockNumber();  console.log(&quot;The latest Ethereum block is:&quot;, block);
  const REGISTRY_CONTRACT_ADDRESS = &apos;0xe3Be01D99bAa8dB9905b33a3cA391238234B79D1&apos;const REGISTRY_ABI = [  {    name: &apos;getDirectoryUrl&apos;,    inputs: [{ internalType: &apos;bytes32&apos;, name: &apos;username&apos;, type: &apos;bytes32&apos; }],    outputs: [{ internalType: &apos;string&apos;, name: &apos;&apos;, type: &apos;string&apos;}],    stateMutability: &apos;view&apos;,    type: &apos;function&apos;,  },  {  inputs: [{ internalType: &apos;address&apos;, name: &apos;&apos;, type: &apos;address&apos; }],  name: &apos;addressToUsername&apos;,  outputs: [{ internalType: &apos;bytes32&apos;, name: &apos;&apos;, type: &apos;bytes32&apos; }],  stateMutability: &apos;view&apos;,  type: &apos;function&apos;,  },];
const registryContract = new Contract(REGISTRY_CONTRACT_ADDRESS, REGISTRY_ABI, provider);
const username = &apos;v&apos;;const byte32Name = utils.formatBytes32String(username);const directoryUrl = await registryContract.getDirectoryUrl(byte32Name); console.log(`${username}&apos;s Host is located at: ${directoryUrl} \n`);
console.log(&apos;--------------&apos;);const directoryResponse = await got(directoryUrl);const directory = JSON.parse(directoryResponse.body);console.log(`${username}&apos;s Directory is: `);console.log(directory, &apos;\n&apos;);
  console.log(&apos;--------------------&apos;);const addressActivityUrl = directory.body.addressActivityUrl; const addressActivityResponse = await got(addressActivityUrl);const addressActivity = JSON.parse(addressActivityResponse.body);const cast = addressActivity[0];console.log(`${username}&apos;s most recent Cast was: `)console.log(cast, &apos;\n&apos;)
 console.log(&apos;---------++++----------&apos;);  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`);}console.log(&apos;---------++++=====----------&apos;);  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();

当我们点击run的时候，页面会出现以下的内容即可，已经在 Farcaster 上构建了你的第一个可以读取用户消息的应用程序！您还学习了如何验证签名，以便您可以安全地接收来自网络上任何用户的消息。


The latest Ethereum block is: 11019907
v&apos;s Host is located at: https://guardian.farcaster.xyz/origin/directory/0x012D3606bAe7aebF03a04F8802c561330eAce70A 

--------------
v&apos;s Directory is: 
{
  body: {
    addressActivityUrl: &apos;https://guardian.farcaster.xyz/origin/address_activity/0x012D3606bAe7aebF03a04F8802c561330eAce70A&apos;,
    avatarUrl: &apos;https://res.cloudinary.com/merkle-manufactory/image/fetch/c_fill,f_png,w_256/https://lh3.googleusercontent.com/sYAr036bd0bRpj7OX6B-F-MqLGznVkK3--DSneL_BT5GX4NZJ3Zu91PgjpD9-xuVJtHq0qirJfPZeMKrahz8Us2Tj_X8qdNPYC-imqs&apos;,
    displayName: &apos;Varun Srinivasan&apos;,
    proofUrl: &apos;https://guardian.farcaster.xyz/origin/proof/0x012D3606bAe7aebF03a04F8802c561330eAce70A&apos;,
    timestamp: 1651889730139,
    version: 1
  },
  merkleRoot: &apos;0xe766d07229f933a12ec12e91e7effb6e06cea69d79666c5e95cc2ccdb94960f3&apos;,
  signature: &apos;0xf21c1cbb656c7314bcbb6e7a84d416b5b5c0206fcbc0db0e17580addd42280b81bc3e8bc6f1e634a32077fc9259f8b0f0f77e1976a5342301a15c4a2bc2c52d31b&apos;
} 

--------------------
v&apos;s most recent Cast was: 
{
  body: {
    type: &apos;text-short&apos;,
    publishedAt: 1657754233248,
    sequence: 1375,
    username: &apos;v&apos;,
    address: &apos;0x012D3606bAe7aebF03a04F8802c561330eAce70A&apos;,
    data: {
      text: &apos;Secure key store is easier on desktop&apos;,
      replyParentMerkleRoot: &apos;0x93b8949490715d5ea935c82b00aff19d0f76dfc7bc700495527b4307d2f280e1&apos;
    },
    prevMerkleRoot: &apos;0xc8491c6343115d4de0598969d762167c5a08ce1aff416c3b32c2a8a2aadec401&apos;
  },
  merkleRoot: &apos;0x6184037488422b2307971ed4811b15b16407d209598404f0f75f131b9a376658&apos;,
  signature: &apos;0xa6da8c032f14a7f00396f53db2a32a065abfe830381053085af52f66fe66ddbb3a6221e2474627c0b2d8f213906b62cd6af3d6022bda771ab3fbc5a611b4c5261c&apos;,
  meta: {
    displayName: &apos;Varun Srinivasan&apos;,
    avatar: &apos;https://res.cloudinary.com/merkle-manufactory/image/fetch/c_fill,f_png,w_256/https://lh3.googleusercontent.com/sYAr036bd0bRpj7OX6B-F-MqLGznVkK3--DSneL_BT5GX4NZJ3Zu91PgjpD9-xuVJtHq0qirJfPZeMKrahz8Us2Tj_X8qdNPYC-imqs&apos;,
    isVerifiedAvatar: true,
    numReplyChildren: 1,
    reactions: { count: 4, type: &apos;Like&apos;, self: false },
    recasts: { count: 0, self: false },
    watches: { count: 0, self: false },
    replyParentUsername: {
      address: &apos;0xD69A8f3150792352A97940f5748BDD0506940091&apos;,
      username: &apos;ace&apos;
    }
  },
  attachments: { openGraph: [] }
} 

---------++++----------
PASSED: the calculated hash 0x6184037488422b2307971ed4811b15b16407d209598404f0f75f131b9a376658 matches the one in the cast
PASSED: the recovered address 0x012D3606bAe7aebF03a04F8802c561330eAce70A matches the one in the cast
---------++++=====----------
PASSED: 0x012D3606bAe7aebF03a04F8802c561330eAce70A owns v
"><code>const { providers, Contract, utils } <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"ethers"</span>);const got <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"got"</span>);
const doStuff <span class="hljs-operator">=</span> async () <span class="hljs-operator">=</span><span class="hljs-operator">></span> {  const ALCHEMY_SECRET <span class="hljs-operator">=</span> <span class="hljs-string">'YFNEz9ywV3392OD6ku7Vt1wADtjVAoYL'</span>; <span class="hljs-comment">// Replace with your secret  const provider = new providers.AlchemyProvider('rinkeby', ALCHEMY_SECRET);</span>
    const <span class="hljs-built_in">block</span> <span class="hljs-operator">=</span> await provider.getBlockNumber();  console.log(<span class="hljs-string">"The latest Ethereum block is:"</span>, <span class="hljs-built_in">block</span>);
  const REGISTRY_CONTRACT_ADDRESS <span class="hljs-operator">=</span> <span class="hljs-string">'0xe3Be01D99bAa8dB9905b33a3cA391238234B79D1'</span>const REGISTRY_ABI <span class="hljs-operator">=</span> [  {    name: <span class="hljs-string">'getDirectoryUrl'</span>,    inputs: [{ internalType: <span class="hljs-string">'bytes32'</span>, name: <span class="hljs-string">'username'</span>, <span class="hljs-keyword">type</span>: <span class="hljs-string">'bytes32'</span> }],    outputs: [{ internalType: <span class="hljs-string">'string'</span>, name: <span class="hljs-string">''</span>, <span class="hljs-keyword">type</span>: <span class="hljs-string">'string'</span>}],    stateMutability: <span class="hljs-string">'view'</span>,    <span class="hljs-keyword">type</span>: <span class="hljs-string">'function'</span>,  },  {  inputs: [{ internalType: <span class="hljs-string">'address'</span>, name: <span class="hljs-string">''</span>, <span class="hljs-keyword">type</span>: <span class="hljs-string">'address'</span> }],  name: <span class="hljs-string">'addressToUsername'</span>,  outputs: [{ internalType: <span class="hljs-string">'bytes32'</span>, name: <span class="hljs-string">''</span>, <span class="hljs-keyword">type</span>: <span class="hljs-string">'bytes32'</span> }],  stateMutability: <span class="hljs-string">'view'</span>,  <span class="hljs-keyword">type</span>: <span class="hljs-string">'function'</span>,  },];
const registryContract <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> Contract(REGISTRY_CONTRACT_ADDRESS, REGISTRY_ABI, provider);
const username <span class="hljs-operator">=</span> <span class="hljs-string">'v'</span>;const byte32Name <span class="hljs-operator">=</span> utils.formatBytes32String(username);const directoryUrl <span class="hljs-operator">=</span> await registryContract.getDirectoryUrl(byte32Name); console.log(`${username}<span class="hljs-string">'s Host is located at: ${directoryUrl} \n`);
console.log('</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-string">');const directoryResponse = await got(directoryUrl);const directory = JSON.parse(directoryResponse.body);console.log(`${username}'</span>s Directory <span class="hljs-keyword">is</span>: `);console.log(directory, <span class="hljs-string">'\n'</span>);
  console.log(<span class="hljs-string">'--------------------'</span>);const addressActivityUrl <span class="hljs-operator">=</span> directory.body.addressActivityUrl; const addressActivityResponse <span class="hljs-operator">=</span> await got(addressActivityUrl);const addressActivity <span class="hljs-operator">=</span> JSON.parse(addressActivityResponse.body);const cast <span class="hljs-operator">=</span> addressActivity[<span class="hljs-number">0</span>];console.log(`${username}<span class="hljs-string">'s most recent Cast was: `)console.log(cast, '</span>\n<span class="hljs-string">')
 console.log('</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">+</span><span class="hljs-operator">+</span><span class="hljs-operator">+</span><span class="hljs-operator">+</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-string">');  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`);}console.log('</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">+</span><span class="hljs-operator">+</span><span class="hljs-operator">+</span><span class="hljs-operator">+</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-string">');  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();

当我们点击run的时候，页面会出现以下的内容即可，已经在 Farcaster 上构建了你的第一个可以读取用户消息的应用程序！您还学习了如何验证签名，以便您可以安全地接收来自网络上任何用户的消息。


The latest Ethereum block is: 11019907
v'</span>s Host <span class="hljs-keyword">is</span> located at: https:<span class="hljs-comment">//guardian.farcaster.xyz/origin/directory/0x012D3606bAe7aebF03a04F8802c561330eAce70A </span>

<span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span>
v<span class="hljs-string">'s Directory is: 
{
  body: {
    addressActivityUrl: '</span>https:<span class="hljs-comment">//guardian.farcaster.xyz/origin/address_activity/0x012D3606bAe7aebF03a04F8802c561330eAce70A',</span>
    avatarUrl: <span class="hljs-string">'https://res.cloudinary.com/merkle-manufactory/image/fetch/c_fill,f_png,w_256/https://lh3.googleusercontent.com/sYAr036bd0bRpj7OX6B-F-MqLGznVkK3--DSneL_BT5GX4NZJ3Zu91PgjpD9-xuVJtHq0qirJfPZeMKrahz8Us2Tj_X8qdNPYC-imqs'</span>,
    displayName: <span class="hljs-string">'Varun Srinivasan'</span>,
    proofUrl: <span class="hljs-string">'https://guardian.farcaster.xyz/origin/proof/0x012D3606bAe7aebF03a04F8802c561330eAce70A'</span>,
    timestamp: <span class="hljs-number">1651889730139</span>,
    version: <span class="hljs-number">1</span>
  },
  merkleRoot: <span class="hljs-string">'0xe766d07229f933a12ec12e91e7effb6e06cea69d79666c5e95cc2ccdb94960f3'</span>,
  signature: <span class="hljs-string">'0xf21c1cbb656c7314bcbb6e7a84d416b5b5c0206fcbc0db0e17580addd42280b81bc3e8bc6f1e634a32077fc9259f8b0f0f77e1976a5342301a15c4a2bc2c52d31b'</span>
} 

<span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span>
v<span class="hljs-string">'s most recent Cast was: 
{
  body: {
    type: '</span>text<span class="hljs-operator">-</span>short<span class="hljs-string">',
    publishedAt: 1657754233248,
    sequence: 1375,
    username: '</span>v<span class="hljs-string">',
    address: '</span><span class="hljs-number">0x012D3606bAe7aebF03a04F8802c561330eAce70A</span><span class="hljs-string">',
    data: {
      text: '</span>Secure key store <span class="hljs-keyword">is</span> easier on desktop<span class="hljs-string">',
      replyParentMerkleRoot: '</span><span class="hljs-number">0x93b8949490715d5ea935c82b00aff19d0f76dfc7bc700495527b4307d2f280e1</span><span class="hljs-string">'
    },
    prevMerkleRoot: '</span><span class="hljs-number">0xc8491c6343115d4de0598969d762167c5a08ce1aff416c3b32c2a8a2aadec401</span><span class="hljs-string">'
  },
  merkleRoot: '</span><span class="hljs-number">0x6184037488422b2307971ed4811b15b16407d209598404f0f75f131b9a376658</span><span class="hljs-string">',
  signature: '</span><span class="hljs-number">0xa6da8c032f14a7f00396f53db2a32a065abfe830381053085af52f66fe66ddbb3a6221e2474627c0b2d8f213906b62cd6af3d6022bda771ab3fbc5a611b4c5261c</span><span class="hljs-string">',
  meta: {
    displayName: '</span>Varun Srinivasan<span class="hljs-string">',
    avatar: '</span>https:<span class="hljs-comment">//res.cloudinary.com/merkle-manufactory/image/fetch/c_fill,f_png,w_256/https://lh3.googleusercontent.com/sYAr036bd0bRpj7OX6B-F-MqLGznVkK3--DSneL_BT5GX4NZJ3Zu91PgjpD9-xuVJtHq0qirJfPZeMKrahz8Us2Tj_X8qdNPYC-imqs',</span>
    isVerifiedAvatar: <span class="hljs-literal">true</span>,
    numReplyChildren: <span class="hljs-number">1</span>,
    reactions: { count: <span class="hljs-number">4</span>, <span class="hljs-keyword">type</span>: <span class="hljs-string">'Like'</span>, <span class="hljs-built_in">self</span>: <span class="hljs-literal">false</span> },
    recasts: { count: <span class="hljs-number">0</span>, <span class="hljs-built_in">self</span>: <span class="hljs-literal">false</span> },
    watches: { count: <span class="hljs-number">0</span>, <span class="hljs-built_in">self</span>: <span class="hljs-literal">false</span> },
    replyParentUsername: {
      <span class="hljs-keyword">address</span>: <span class="hljs-string">'0xD69A8f3150792352A97940f5748BDD0506940091'</span>,
      username: <span class="hljs-string">'ace'</span>
    }
  },
  attachments: { openGraph: [] }
} 

<span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">+</span><span class="hljs-operator">+</span><span class="hljs-operator">+</span><span class="hljs-operator">+</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span>
PASSED: the calculated hash <span class="hljs-number">0x6184037488422b2307971ed4811b15b16407d209598404f0f75f131b9a376658</span> matches the one in the cast
PASSED: the recovered <span class="hljs-keyword">address</span> <span class="hljs-number">0x012D3606bAe7aebF03a04F8802c561330eAce70A</span> matches the one in the cast
<span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">+</span><span class="hljs-operator">+</span><span class="hljs-operator">+</span><span class="hljs-operator">+</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span>
PASSED: <span class="hljs-number">0x012D3606bAe7aebF03a04F8802c561330eAce70A</span> owns v
</code></pre></blockquote>]]></content:encoded>
            <author>ikunfamily@newsletter.paragraph.com (xiaoju)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/581572b732848aa1ef98f1d0f6993b4b7685ac9b7e479fd59e17f21fc19e0c0b.png" length="0" type="image/png"/>
        </item>
    </channel>
</rss>