# 使用 React + JS + Leo 在 Aleo 上构建应用程序指南

By [Yaakov](https://paragraph.com/@yaakov) · 2024-04-29

---

Leo 能帮助我们编写出去中心化的智能合约，但是智能合约是没法与普通用户进行交互的，和其它去中心化程序一样，这里需要传统的 Web2 知识帮忙构建和用户进行交互的图形界面，方便用户使用我们的智能合约。本教程将演示一个简单的可交互的去中心化应用程序。

现在正式开始我们的教程。

### 1\. 安装

在这之前需要确保你已经安装了 [Node.js](https://nodejs.org/en/) 18+ 以上的版本。

然后您将需要安装 React + JavaScript + Leo 模板，命令如下

    npm create aleo-app@latest
    

在应用模版安装完成之后再运行如下命令

    cd aleo-project
    npm install
    npm run install-leo
    npm run dev
    

上面的命令帮我们安装项目所需要的依赖库和 Leo 编程语言，然后在本地帮我们运行了一个 React 的应用程序的本地实例，可以通过 [http://localhost:5173](http://localhost:5173) 访问 。

顺便了解下程序的核心结构

*   src/App.jsx：React 应用程序的核心。
    
*   helloworld/：存放 Leo 程序的文件夹。
    
*   src/workers/worker.js：Leo 程序的 WebAssembly 模块（WASM）。
    

### 2\. 运行

现在我们打开链接 [http://localhost:5173](http://localhost:5173)

然后打开开发者控制台，然后点击 `execute helloworld.aleo` ，观察控制台的输出，正常情况如下

然后会弹出弹窗

### 3\. 部署程序

前面的合约是本地执行的，现在我们需要将合约部署到测试网上，在这之前我们需要一个有测试积分的账户用来部署程序。

首先创建账户

    leo account new 
    

> 注意：您的私钥、查看密钥和地址请保存在安全的地方，注意安全

拥有帐户后，需要使用官方提供的水龙头获取一些 Aleo 测试积分，这里获取测试积分有两种方式，一种是发送短信，另外一种是通过 Discord 的指定水龙头频道获取。

第一种获取方式：在[水龙头页面](https://faucet.aleo.org/)并按照那里的说明进行操作。

第二种获取方式：先将账户地址加入 [https://faucetgreenlist.snarkos.net/](https://faucetgreenlist.snarkos.net/) 名单，然后加入[Discord 服务器](https://discord.gg/aleo)并使用该频道。`#faucet`每 6 个小时只能发送一个请求，一天只能请求 15 个积分。一旦您发送了水龙头请求，Discord 就会在水龙头通道下启动一个线程来处理您的请求。

格式：

    /sendcredits aleo1address amt
    

例子：

    /sendcredits aleo13g7xe4u8mzy3mru2p0dfq4f49cczkm0arflqe8rlsmmhel4atu8sj7jnhe 15
    

记下水龙头 URL 后面的交易 ID。Discord 线程中的成功消息应如下所示：

    Transfer successful! for message ID: 1156693507768078496
    https://apiv2.aleo.network/testnet3/transaction/at12u62xwfew2rq32xee8nwhtlxghfjz7mm3528yj240nuezue625fqy4lhlp
    

到这里我们准备工作做完之后就可以开始部署程序。

> 注意：在 Aleo 上部署合约有一些限制需要注意，第一个是程序名称必须唯一；第二个是程序名称尽量不少于10个字符，因为越短需要花费在部署上的费用越高。

因为`helloworld`之前已经部署过，现在我们要修改他的名字保证唯一，但让我们使用 Leo 来创建和构建一个全新的程序。

    leo new helloworld_[randomsuffix]
    cd helloworld_[randomsuffix]
    

生成新`helloworld`项目后，您可以删除原始`helloworld`文件夹。

您会注意到 React 应用程序现在出现错误。导航到 React 应用程序的主目录并打开`App.jsx`. 将第 5 行的文件夹名称更改为刚刚我们创建的 Leo 的新项目的名称以消除错误：

    import helloworld_program from "../helloworld_[randomsuffix]/build/main.aleo?raw";
    

让我们再深入一点。回到 Leo 项目的根目录并将您的私钥添加到`.env` 中。将示例私钥替换为您自己的私钥。

    NETWORK=testnet3
    PRIVATE_KEY=APrivateKey...
    

完成此操作后，在新的 Leo 项目的根目录中，您可以自己尝试以下命令并观察终端中的输出：

    leo run main
    leo execute main
    

我们继续

在部署合约时，我们需要用从水龙头请求的积分支付部署费用。现在我们可以点 `Deploy helloworld.aleo` 按钮进行程序的部署，但是这个过程很慢，需要一些时间来扫描区块链上的交易，为了加快进程，我们直接提供我们获得的测试积分的准确记录来加快部署进程。让我们了解一下具体的解密过程。

当您从水龙头获得的积分是私有的，我们需要在交易中找到该私有记录记录。

之前从 Discord URL 获取您的交易 ID：

您可以使用 [https://api.explorer.aleo.org/v1/testnet3/transaction/\[insert-your-transaction-id\]](https://api.explorer.aleo.org/v1/testnet3/transaction/%5Binsert-your-transaction-id%5D) 接口在返回的 JSON 中 `object.execution.transitions[0].outputs[0].value` 位置找到加密的 record，看起来像这样：

然后跳转到 [aleo.tools/rest](https://aleo.tools/rest) 网页点击 `Record` ，然后填入你刚刚复制的 `record` 和前面创建账户生成 \`View Key 来解密该记录获取记录的明文。

解密后，复制明文记录并将其粘贴到 的第 67 行`src/workers/worker.js`。我们可以注释掉第 64 行，因为我们不希望扫描交易记录的功能处于活动状态，所以要手动替换它，

最终结果`worker.js`应该是这样的：

    // // Deploy the program to the Aleo network
    // const tx_id = await programManager.deploy(program, fee);
    
    // Optional: Pass in fee record manually to avoid long scan times
    const feeRecord = "{owner: aleo1qpjvun06n87jne3jwkml4jwdjqalw7n2qms03mcamenzczrj0uysp85fit.private, microcredits: 50000000u64.private, _nonce: 7736650979063383113375091219637426887776503149825722849440478642541635263210group.public}";
    const tx_id = await programManager.deploy(program, fee, undefined, feeRecord);
    

现在可以点击 `Deploy helloworld.aleo` 按钮开始部署了

![部署控制台](https://storage.googleapis.com/papyrus_images/d19593586ccad13d3bd4eeea79eff09b6a8ad7095fffb82a56642b8fa7a6307b.png)

部署控制台

部署成功的截图：

![部署成功](https://storage.googleapis.com/papyrus_images/ee54a55335e4a83c17a04a41204567adac5e6405771b3cf04a41a9eabe46cb60.png)

部署成功

到这里就成功部署了智能合约，也知道了如何创建去中心化的私有应用程序的流程了。

---

*Originally published on [Yaakov](https://paragraph.com/@yaakov/react-js-leo-aleo)*
