IOTA – helloworld 程序

IOTA节点公开了一个我们可以与之交互的HTTP API,而且与大多数IOTA的生态系统不同,它有一个实际的文档。 但是,查看这个参考文件是不可或缺的,我们宁愿使用客户端库来与我们的节点交互。

目前有三个官方客户端库,最成熟的客户端显然是我们想要使用的 - 一个名为iota.lib.js的JavaScript。 它基本上是http API端点的包装。

使用节点与节点交谈

让我们可以使用npm init引导的空的Node.JS项目开始, 然后用 npm install iota.lib.js  来安装IOTA的库。

要建立连接,我们需要指定IRI的位置,包括公共API端口(在节点的配置文件中指定为PORT,或者如果从命令行传递,则指定为-p)。 请注意,默认情况下,我们不需要任何密码 - 这就是为什么将节点的API端口隐藏于外部网络,或者使用--remote-auth和--remote-limit-api配置选项进行正确配置。

const IOTA = require('iota.lib.js')
const iota = new IOTA({
    host: 'http://192.168.1.162',
    port: 14265
})

现在让我们看看我们的节点使用getNodeInfo调用告诉我们自己的情况。 所有的API调用都遵循笨拙的Node.JS回调传递约定:

iota.api.getNodeInfo((error, nodeInfo) => {
    if (error) {
        console.error('getNodeInfo error', error)
    } else {
        console.log('getNodeInfo result', nodeInfo)
    }
}

除节点的版本和封装信息之外,我们将得到的是处理状态 - 是否有任何未决事务要传输,以及我们节点已知的最新里程碑。 如果我们的节点与网络同步,则后面的值应该每隔几分钟改变一次。

我的钱包在哪里?

IOTA中的地址可以理解为可以存储IOTA令牌的不同的钱包。这些是足够长的字符串,所以它是完全正确的生成它自己和 - 在实践中 - 确保其独特性。

为了要求一个给定的地址的所有权,我们需要拥有它所产生的种子 - 将种子想象成带有钱包的私人密钥。种子需要安全生成,可能不会使用公共网站。最简单的可能是使用macOS / Linux终端并运行:

cat /dev/urandom | LC_ALL=C tr -dc 'A-Z9' | fold -w 81 | head -n 1

现在,我们得到的看起来类似于FNCWNXJWJIVDGPRWNZYKOMKNIIATPPDKEVCZEWSZTEVIWJFCOUV9PJD9AUCEVQLFEAI9UBUAVQKVEBLKN,是我们的种子。我们负责安全和私密的存储,因为它可以完全访问我们将使用它创建的所有地址(钱包)。

要真正生成我们可以用来发送交易的地址,我们来使用我们的API:

const seed = 'FNCWNXJWJIVDGPRWNZYKOMKNIIATPPDKEVCZEWSZTEVIWJFCOUV9PJD9AUCEVQLFEAI9UBUAVQKVEBLKN' // keep it secure!
iota.api.getNewAddress(seed, (error, address) => {
   if (error) {
       console.error('getNewAddress error', error)
   } else {
       console.log('new address generated: ' + address)
   }
})

花费代币

我们现在准备提交我们的第一笔交易,或者 - API如何调用它 - 转账。除了货币价值(可以是零)之外,我们可以给我们的交易附加一个信息。该消息需要tryte编码 - 我们不需要太多关心它,幸运的是,我们有这个任务的帮手方法:iota.utils.toTrytes。

将我们的交易发送给IOTA纠纷的代码如下所示:

const Depth = 3 // constant defined by IOTA - how deep to look for the tips in the Tangle
const MinWeightMagnitude = 16 // constant defined by IOTA - the difficulty of PoW

const transfers = [
    {
        // where are we sending the transaction to?
        address: 'CHNLHJCYBZCYUI9DTHINDDWHNJWFCHQOTGABXFVZQHXF9BROTOIJZJSBXOVKCDGCXZTDDJUVTYBJZYAOH',
        
        // how many tokens are we transferring?
        value: 42,
        
        // do we want to comment on this transaction?
        message: iota.utils.toTrytes('Hello World!')        
    }
]

const options = {
    // addresses of the wallets we're using to fund this transfer
    inputs: ['ZISNLNSKMPDOORSSFRCBGQOPY9BI9SONMTDHJJDWBTTCYLFV9PQ9VSWNI9FHEAEFGROGZ9YHSMZYOGFQG']
}

iota.api.sendTransfer(seed, Depth, MinWeightMagnitude, transfers, options, (error, transactions) => {
  if (error) {
     console.error('sendTransfer error', error)
  } else {
     console.log('transactions sent!', transactions)
  }
})

我们需要指定我们发送带有消息的令牌的地址,以及令牌来自哪个(我们的)钱包(如果发送的是非零值)。在响应中,我们为每个提交的转移对象获取一个事务对象。

如果我们幸运的话,我们应该能够获得交易的哈希属性,将其粘贴在网上的一个在线纠结查看器,并看到我们的交易的细节。这将最有可能处于“待定”状态。这意味着交易被正确地附加到了“tangle”中,虽然它还没有被纠结树中的其他交易所验证,我们需要等一下。通常它会在几分钟内进入“确认”状态。

但是我们可能并不那么幸运,我们的交易可能会被附加到永远不会被验证的那部分树上,或者是因为在Tangle树中有太多的提示等待验证,所以它被提示选择“忘记”了算法(提示选择算法偏向于来自树顶部的事务),或者碰巧连接到产生错误的子树。

在这些情况下,我们的交易永远不会脱离“等待”状态,我们需要通过将我们的转账(称为“捆绑”)重新附加到“tangle”树的另一部分来解决问题。为了做到这一点,我们可以定期运行下面的代码:

iota.api.getLatestInclusion([hash], (error, inclusionStates) => {
  if (error) {
     console.error('getLatestInclusion error', error)
  } else if (inclusionStates[0]) {
     console.log('transaction is included (confirmed)! yay!') 
  } else {
     iota.api.replayBundle(hash, Depth, MinWeightMagnitude, (error, replayTransactions) => {
         // ad infinitum...?
     })
  }
})

这个过程可能看起来很奇怪,因为我们实际上正在向Tangle添加越来越多的重复 - 重放事务是一个单独的事务。我们现在可能需要跟踪原始和重放交易的“包含状态”(状态)。我们还需要再次重播一遍,以防几分钟后得不到验证。所有这一切都伴随着发行新交易的成本,但这实际上对整个IOTA网络是有利的,因为通过这样做,我们确认了另一对交易。而且还有双重支出确认方案,确保只有一个交易将被最终确认。

专栏作者:helxsz

个人简介:我共发表了 9 篇文章,总计被阅读了36,008 次,共获得了 111 个赞。

作者邮箱 作者主页 Ta的文章

发表评论

邮箱地址不会被公开。 必填项已用*标注