Byteball開発者向け情報wiki - Byteballのチャットボット実装ガイド
このページは下記のサイトを日本語化したものです。
https://github.com/byteball/byteballcore/wiki/Writ...
英語が読めるかたは上記から直接ご確認いただいても問題ありません。
google翻訳そのままよりは若干ましな程度の翻訳精度ですが、ご活用下さい。


前提条件

チャットボットを起動するには、headlessノードが必要です。headlessノードは通常フルノードです。機能のサブセットはライトノードでも動作しますが、フルノードを前提に設計されていることは覚えておいてください。

まずあなたのチャットボット用にnode.jsパッケージを設定しましょう。まずbyteballcoreモジュールが必要で(貴方のプロジェクトのdependenciesに追加します)、更に支払いを行う場合はheadless-byteballモジュールも必要です。package.jsonの設定をこのように変更します。
"dependencies": {
     "headless-byteball": "git+https://github.com/byteball/headless-byteball.git",
     "byteballcore": "^0.2.33",
     .....
}

貴方のモジュールにwallet.jsのrequire()を加える必要があります。例え一切その機能を使わない場合でも。
require('byteballcore/wallet.js’);

設定ファイル変更

貴方のコンフィグ(conf.jsかconf.jsonの事です)に、ボットの名前とペアリング用の秘密コード(ペアリングコードの一部になります)を設定してください。
exports.deviceName = 'My test bot';
exports.permanent_pairing_secret = '0000';

ノード起動時に、ペアリングコードが表示されます。
====== my pairing code: A2WMb6JEIrMhxVk+I0gIIW1vmM3ToKoLkNF8TqUV5UvX@byteball.org/bb#0000

あなたのウェブサイトにこのペアリングコードを「byteball:」スキームとのリンクとして公開すると、ユーザーはあなたのリンクをクリックしてボットとチャットを開くことができます(リンクはByteballアプリで開き、チャットを開始します)。
<a href="byteball:A2WMb6JEIrMhxVk+I0gIIW1vmM3ToKoLkNF8TqUV5UvX@byteball.org/bb#0000">Chat with my test bot</a>

データベース

もしDAGを検索する必要があり、トランザクションの詳細を見たい場合、dbモジュールが必要です。
var db = require('byteballcore/db.js’);

Byteballデータベースのコピーに対してSQLクエリを実行します。 カスタムテーブルを追加することもできます。 明らかに、カスタムテーブルの外部のデータは変更したくないということです。

チャットメッセージを受信する

チャットのメッセージを受信するには、eventBusで「テキスト」イベントを登録します。
var eventBus = require('byteballcore/event_bus.js');
eventBus.on('text', function(from_address, text){
    // 貴方のコードをここにいれてください。
});

rom_addressはユーザーのデバイスアドレスです。(支払い用のウォレットアドレスと混同しないでください)。
textはそのユーザーからのメッセージです。

チャットメッセージを送る

以下のコードでメッセージを送ることができます。
var device = require('byteballcore/device.js');
device.sendMessageToDevice(user_device_address, 'text', ‘ここにボットからユーザーへのメッセージを入れます');

ペアリングの通知を受け取る

ユーザーが貴方のボットとペアリングしたとき(例えば貴方のボットへのリンクをクリックするとか)、貴方はペアリングの通知を受け取りユーザーを歓迎することができます:
eventBus.on('paired', function(from_address){
     var device = require('byteballcore/device.js');
     device.sendMessageToDevice(from_address, 'text', getMyWelcomeText());
});
*訳者補足:getMyWelcomeText()を使わずに直接テキストを書いても問題ないと思われます。

コマンド

定義済みのコマンドにアクセスするには、以下のようにレスポンスをフォーマットします。
click this link: [Command name](command:command code)

ユーザーは角括弧で囲まれたテキストを「コマンド名」と見なし、リンクとして強調表示され、ユーザーがクリックすると、コマンドコードのテキストがボットに送信されます。

支払いの要求

有効なByteballアドレスを貴方のbotの返信文に含めると、そのアドレスはユーザーのチャットウィンドウで自動的に強調表示され、クリックするとユーザーは任意の量の任意の資産をこのアドレスに支払うことができます。
あなたが特定の金額の支払いを要求する場合、このような書式で要求することができます。
Any text before[payment description, will be ignored](byteball:YOURBYTEBALLADDRESS?amount=123000&asset=base) any text after

Amountは最小単位のbytesです。 &asset=を省略すると、bytes支払いに設定されます。もしあなたが他の資産に対して支払い要求したい場合、blackbyte支払い用にoj8yEksX9Ubq7lLc+p6F2uyHUuynugeVq4+ikT67X6E=のような識別子を表示します(URLエンコードにすることを忘れないで下さい)
トランザクションごとに、ユーザーごとに一つの支払い先アドレスを生成することをお勧めします。

コード例
var walletDefinedByKeys = require('byteballcore/wallet_defined_by_keys.js');
walletDefinedByKeys.issueNextAddress(wallet, 0, function(objAddress){
     var byteball_address = objAddress.address;
     // work with this address, then send it over to the user
     device.sendMessageToDevice(user_device_address, 'text', "Please pay to "+byteball_address);
});

支払いの待機

もしあなたがheadless-walletを含める場合以下のコードを使います
var headlessWallet = require('headless-byteball');

あなたのアドレスのいずれかが支払いを受けたときに通知を受け取ることができます。
eventBus.on('new_my_transactions', function(arrUnits){
     // react to receipt of payment(s)
});

arrUnits はユニットの配列で(正確にいえば、ユニットハッシュ)あなたのウォレットアドレスに関するトランザクションが含まれています。
new_my_transactionsのイベントも外に発信されるトランザクションに誘発されるので、新しい取引で支払いが予定されているアドレスの1つをクレジットするかどうかを確認する必要があります。

最終的な支払い待ち

あなたのトランザクションが承認されたか通知を受けるには、[my_transactions_became_stable]イベントに登録する必要があります
eventBus.on('my_transactions_became_stable', function(arrUnits){
        // react to payment(s) becoming stable
});

arrUnitsはユニットの配列であり、あなたのアドレスを含む少なくとも1つのトランザクションが格納されています。
あるいは、新しいメインチェーンインデックス(MCI)が安定するたびに発行される[mci_became_stable]イベントに登録することもできます。
eventBus.on('mci_became_stable', function(mci){
        // check if there are any units you are interested in 
        // that had this MCI and react to their becoming stable
});

支払いの送信

支払いを送信するには、headless-walletを含める必要があります。
var headlessWallet = require('headless-byteball');
その上で下記の関数を使って下さい:
headlessWallet.issueChangeAddressAndSendPayment(asset, amount, user_byteball_address, user_device_address, function(err, unit){
        if (err){
                // something went wrong, maybe put this payment on a retry queue
                return;
        }
        // handle successful payment
});

asserはあなたが支払う資産を指定し(nullだとbytes支払い)、amountは最小単位での支払いの額です。もし支払いが成功した場合、コールバックでunitを取得してそれを保存したりこのユニットでさらにイベントを見ることができます。

スマートコントラクトの提供

もし新しいスマートコントラクトを作りたい場合、通常このような順序になります:
・ユーザーに支払いアドレスを訪ねる(スマートコントラクトに内包されます)
・ユーザーのアドレスとあなたのアドレスを契約の当事者としてコントラクトを定義
・あなたが契約の共有に支払いを行う
・同時に、特別なフォーマットの支払いリクエストをユーザーに送ります。あなたはユーザーの支払いを待ちます
・ユーザーがウォレット内のコントラクトを見て支払いに同意します
・あなたは支払いの通知を受け取って承認されるのを待ちます
・支払いが承認されたのち、コントラクトが完全な形で履行されます

ほとんどのステップは既によく知られていますが、以下では契約の作成と提供について説明します。これらの2つのステップは、ユーザーが新しい契約を設計するときにGUIウォレットで行われる処理に似ています。詳細はこちらサイト(https://github.com/byteball/byteball/blob/master/s...をごらん下さい。

契約の定義の登録

契約を定義するjavascriptオブジェクトを作成します。
var arrDefinition = ['or', [
        ['and', [
                ['address', USERADDRESS],
                conditions when user can unlock the contract
        ]],
        ['and', [
                ['address', MYADDRESS],
                conditions when I can unlock the contract
        ]]
]];

上記の定義であなたのアドレスとユーザーアドレスの位置を記述する別のオブジェクトを作成します:
var device = require('byteballcore/device.js');
var assocSignersByPath = {
        'r.0.0': {
                address: user_address,
                member_signing_path: 'r', // unused, should be always 'r'
                device_address: user_device_address
        },
        'r.1.0': {
                address: my_address,
                member_signing_path: 'r', // unused, should be always 'r'
                device_address: device.getMyDeviceAddress()
        }
};
このオブジェクトのキーには、配列の先頭の’r.0.0:’部分の2番目と3番目はorおよびand条件を示す項目になっています。条件はネストすることができるので、多くのインデックスが存在する可能性があります。これらはドットで区切られています。

次に、スマートコントラクトのアドレスを作成します:
var walletDefinedByAddresses = require('byteballcore/wallet_defined_by_addresses.js');
walletDefinedByAddresses.createNewSharedAddress(arrDefinition, assocSignersByPath, {
        ifError: function(err){
                // handle error
        },
        ifOk: function(shared_address){
                // new shared address created
        }
});
アドレスが正常に作成された場合、アドレスはすでに自動的にユーザーに送信されているため、ユーザーのウォレットはそれを認識します。

契約支払いの要求

ユーザーに契約支払いをリクエストするには、支払い要求と契約の定義の両方を含むbelo javascriptオブジェクト”objPaymentRequest”を作成し、オブジェクトをbase64形式でエンコードしてユーザに送信します。
var arrPayments = [{address: shared_address, amount: peer_amount, asset: peerAsset}];
var assocDefinitions = {};
assocDefinitions[shared_address] = {
        definition: arrDefinition,
        signers: assocSignersByPath
};
var objPaymentRequest = {payments: arrPayments, definitions: assocDefinitions};
var paymentJson = JSON.stringify(objPaymentRequest);
var paymentJsonBase64 = Buffer(paymentJson).toString('base64');
var paymentRequestCode = 'payment:'+paymentJsonBase64;
var paymentRequestText = '[your share of payment to the contract]('+paymentRequestCode+')';
device.sendMessageToDevice(correspondent.device_address, 'text', paymentRequestText);

ユーザーのウォレットがこのメッセージを解析し終えると、ユーザー定義が可能な形式で契約の定義を表示し、ユーザーに要求された金額を支払うように指示します。 支払いがDAGに表示されると、支払い待ちのコードが呼び出されます。

サンプルコード

上記の関数を実装するコードのサンプルを作業する場合は、既存のチャットボットのソースコードを参照してください。

Faucet: 支払いの送信
BTC exchange: 支払いの送受信
Merchant: 秘密鍵を保存せずに支払いの受け取る
Internal asset exchange: スマートコントラクトの依頼
GUI wallet: ボットではないですが、スマートコントラクトを提供するコードあり