# SmartWeave开发教程

By [W3.Hitchhiker](https://paragraph.com/@w3hitchhiker) · 2022-02-14

---

作者：Xiang｜W3.Hitchhiker

修订：Evelyn｜W3.Hitchhiker

官方智能合约参考文档
----------

[

GitHub - ArweaveTeam/SmartWeave: Simple, scalable smart contracts on the Arweave protocol.
------------------------------------------------------------------------------------------

Simple, scalable smart contracts on the Arweave protocol. - ArweaveTeam/SmartWeave

https://github.com

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

](https://github.com/ArweaveTeam/SmartWeave)

（↑**_点击此链接框，打开文档）_**

### SmartWeave

SmartWeave 使用 AR 代币使开发人员能够使用 Javascript 构建所有类型的智能合约应用程序。

#### 与以太坊智能合约区别：

1.  SmartWeave 合约是用 JavaScript 编码的（前端开发语言），不需要像学习 Solidity 那样学习新的编程语言。
    
2.  在以太坊上，将合约更新到最新状态的客户端是矿工，而在 Arweave 上，每次都会在客户端上更新状态。所以构建 SmartWeave 合约得注意，使用SmartWeave 并不适用所有的dapp。
    

由于 SW 合约本身是在客户端更新的，为了获取合约的最新状态，客户端需要通过每次交互来找到其最新的有效状态。与使用ardb从 Arweave 获取交易等其他选项相比，可能会很慢。

SmartWeave 合约分为三部分：

*   **合约源 （the contract source）**
    
*   **状态 (the state)**
    
*   **执行者 (SmartWeaveJS)**
    

### 合约状态

为了评估合约状态，SmartWeave 协议客户端：

1.  将所有合约的交互交易加载到请求的区块高度。
    
2.  对交互事务进行排序。交互的顺序首先由交互交易区块高度（即交易在链中被挖掘的时间）决定，其次由`sha256(transactionId + blockHash)`. 完整的顺序是`[ block_height, sha256(transactionId + blockHash) ]`.
    
3.  将排序后的交互应用到合约的`handler`功能上——评估合约的状态直到请求的区块高度。
    

### 合约源

合约源就是代码本身，用 JavaScript 编写。这是将在客户端（执行者）上运行以更新状态并获取最新且有效的状态的合约。合约它定义了项目将是什么，以及您希望它做什么。

合约源永远不会改变，这可以保证用户使用的东西永远是真实的。

#### 开始测试

状态通常是写合约的第一件事，让我们编写一些简单的代码测试，每次调用`increment`函数时都会增加调用者的余额。 `caller` 是与该合约源交互的钱包地址。

    export function handle(state, action) {
      const balances = state.balances;
      const input = action.input;
      const caller = action.caller;
      
      if(input.function === 'increment') {
          // If the caller already is a key of balances, increment, if not, set it to 1.
          if(caller in balances) {
            balances[caller]++;
          } else {
            balances[caller] = 1;
          }
      }
    }
    

_（该文件保存为first.js。）_

所有 SmartWeave 合约都必须以函数`（state，action）{}` 开头，因为这是执行程序调用的函数。其他所有内容都应该在该`handle`函数中。

现在`handle`本身很混乱，因为我们不知道`state`和`action`参数是什么。我们先解释一下这个`action`。 动作参数 `action` 是在执行 SmartWeave 合约时发送的动作，每次你想要对 SW 合约进行更新时，你都需要发送输入交易，这通常包括函数名称`input.function`和任何其他参数你需要和它一起发送。目前这种情况下，我们不需要发送任何其他内容，但例如我们可以发送`input.qty`来指定我们想要增加余额的数量，这也需要在合约源代码中指定才能正常工作。请记住，这是由钱包所有者控制的，因此我们需要在接收用户数据时始终具备条件，以防止出现意外的情况。

动作参数也将调用者作为该对象的键。同样，调用者是运行该函数的人。这是唯一起作用的两个键：`action`: `input` and `caller`.

### 状态(the state)

状态是合约状态，它让用户知道你的合约的更新是什么，以及它在哪里，在执行的那一刻。 这个会随着时间的推移（在客户端）更新，而合约源永远不会改变。 当我们第一次创建合约时，我们还需要发送一个状态，也就是初始状态。

#### 开始测试

我们可以在我们的合约源中看到，状态是一个 `balances` 对象，其中包括钱包地址（`caller`）作为键，并且每个调用者键都有一个数字作为其值。 在这个例子中，让我们为自己添加一些余额作为初始状态，状态是一个 JSON 对象：

    {
        "balances": {
            "S2aewhZzchiyRsAisLAdZKudF6r9JlO_WDSGkaLGMZ4": 10000
        }
    }
    

_（该文件保存为first.json）_

这表明当第一个人去读我们的合约时，第一个状态是这个地址有 1,000 个该代币余额。

状态和合约源都必须是发送到 Arweave 的单独交易，并且都只部署一次。 之后，通过发送包含`input`交易来更新状态。

部署
--

在说执行者之前，我们先来看看应该如何处理合约源和初始状态。 这两个都只是普通的交易，但带有一些特殊的标签。 我们可以使用 SmartWeaveJS 作为 CLI 工具来部署这些合约。

首先安装smartweave包（建议使用最新的稳定node版本）：

    npm install -g smartweave
    

然后可以通过以下指令部署合约：

    smartweave create [SRC LOCATION] [INITIAL STATE FILE] --key-file [YOUR KEYFILE]
    

SRC LOCATION 是指的合约源，INITIAL STATE FILE是初始状态文件，YOUR KEYFILE 是指生成钱包时的keyfile文件。参考下图配置：

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

交易ID： \_PMfm736sE\_pqPS-FQvYgkwqbm-8VJBPGlQRTm89ZBE

读取合约状态：

    smartweave read [CONTRACT TXID]
    

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

这样就成功部署了您的第一个 SmartWeave 合约。

与合约交互（写合约）:

    smartweave write [CONTRACT TXID] --key-file [YOUR KEYFILE] \
    
      --input "[CONTRACT INPUT STRING HERE]"
    

如果要测试不写入主网，与测试网络交互，请将 `--dry-run` 附加到 `--interact` 调用中.

但由于我们是来学习的，所以也可以了解下使用 [ArweaveJS](https://github.com/ArweaveTeam/arweave-js/#arweave-js) 手动创建这些交易。参考以下代码：

    import Arweave from 'arweave';
    const arweave = Arweave.init({
        host: 'arweave.net',
        protocol: 'https',
        port: 443
    });
    async function createContract() {
        // Let's first create the contract transaction.
        const contractTx = await arweave.createTransaction({ data: contractSource }, wallet);
        contractTx.addTag('App-Name', 'SmartWeaveContractSource');
        contractTx.addTag('App-Version', '0.3.0');
        contractTx.addTag('Content-Type', 'application/javascript');
        
        // Sign
        await arweave.transactions.sign(contractTx, wallet);
        // Let's keep the ID, it will be used in the state transaction.
        const contractSourceTxId = contractTx.id;
        
        // Deploy the contract source
        await arweave.transactions.post(contractTx);
        
        // Now, let's create the Initial State transaction
        const initialStateTx = await arweave.createTransaction({ data: initialState }, wallet);
        initialState.addTag('App-Name', 'SmartWeaveContract');
        initialState.addTag('App-Version', '0.3.0');
        initialState.addTag('Contract-Src', contractSourceTxId);
        initialState.addTag('Content-Type', 'application/json');
        
        // Sign
        await arweave.transactions.sign(initialState, wallet);
        const initialStateTxId = initialState.id;
        // Deploy
        await arweave.transactions.post(initialState);
    }
    createContract()
    

使用ArCode部署合约
------------

类似于以太坊的remix，AR也有自己的网页端部署工具

（↓**_点击此链接框，打开网页）_**

[https://arcode.studio/#/](https://arcode.studio/#/)

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

点击左下方登陆钱包，这里可以下载AR的钱包插件ArConnect进行连接，如果没有，可以先去下载。

进入后可以使用studio自带的代币合约部署，然后点击坐上的火箭图标进行部署。

此时需要选择部署的钱包，方法，部署网络，合约源，合约初始状态等。

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

部署成功后会获取交易ID

TX: YdVWeK5ftuIBmCTEbNQCwSFT13KZIJsuJ6OaVqjFvoY

这样就成功部署token-pst合约了。

与合约交互，读取合约数据：

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

与合约交互，写合约数据：

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

---

*Originally published on [W3.Hitchhiker](https://paragraph.com/@w3hitchhiker/smartweave)*
