Transaction handlers

対象読者: アーキテクト、アプリケーションおよびスマートコントラクト開発者

トランザクションハンドラによって、スマートコントラクト開発者は、アプリケーションとスマートコントラクトのやりとりの中の重要なポイントでの共通処理を定義することができます。 トランザクションハンドラは必須ではありませんが、定義された場合、スマートコントラクトで各トランザクションが実行される前あるいは後に制御を受け取ることができます。 スマートコントラクトで定義されていないトランザクションを実行しようとする要求があった場合に制御を受け取るハンドラもあります。

コマーシャルペーパースマートコントラクトのサンプルのトランザクションハンドラの例は、下記のとおりです。

develop.transactionhandler

Before・After・Unknownトランザクションハンドラ。 この例では、beforeTransaction()は、発行購入現金化トランザクションの前に呼ばれます。 afterTransaction()は、発行購入現金化トランザクションの後に呼ばれます。 unknownTransaction()は、スマートコントラクトで定義されていないトランザクションを実行しようとする要求があった場合にのみ呼ばれます。 (図は、beforeTransactionafterTransactionの箱を各トランザクションごとに繰り返し描かないで簡略化しています)

Types of handler

下記のように、アプリケーションとスマートコントラクトの別々の側面に対応する3種類のトランザクションハンドラがあります。

トランザクションハンドラの定義は、必須ではありません。 ハンドラが定義されていない場合でも、スマートコントラクトは正しく動作します。 スマートコントラクトは、ハンドラの種類ごとにそれぞれ一つまで定義することができます。

Defining a handler

トランザクションハンドラは、決められた名前のメソッドとして、スマートコントラクトに追加sれます。 下記が、各種類のハンドラを追加する例です。

CommercialPaperContract extends Contract {

    ...

    async beforeTransaction(ctx) {
        // トランザクションIDをコンソールに情報として出力します
        console.info(ctx.stub.getTxID());
    };

    async afterTransaction(ctx, result) {
        // このハンドラは台帳とやりとりを行います
        ctx.stub.cpList.putState(...);
    };

    async unknownTransaction(ctx) {
        // このハンドラは例外を投げます
        throw new Error('Unknown transaction function');
    };

}

トランザクションハンドラ定義の形式は全てのハンドラの種類で似ていますが、afterTransaction(ctx, result)は、トランザクションによって返された結果も受け取ることに注意してください。 APIドキュメントには、これらのハンドラの正確な形式の説明があります。

Handler processing

ハンドラがスマートコントラクトに追加されると、ハンドラはトランザクション処理の間に実行されます。 処理においては、ハンドラはトランザクションコンテキストであるctxを受け取り、何らかの処理を行い、完了時に制御を返します。処理は、下記のように続きます。

もし、ハンドラが関数及び引数にアクセスする必要がある場合、下記のように簡単に行うことができます。

async beforeTransaction(ctx) {
    // トランザクションの詳細を取得します
    let txnDetails = ctx.stub.getFunctionAndParameters();

    console.info(`Calling function: ${txnDetails.fcn} `);
    console.info(util.format(`Function arguments : %j ${stub.getArgs()} ``);
}

このハンドラが、トランザクションコンテキストを通じて、ユーティリティAPIであるgetFunctionAndParametersを呼んでいるのがわかるでしょう。

Multiple handlers

スマートコントラクトに対して、各種類のハンドラについて、最大一つまでしか定義することができません。 もし、スマートコントラクトが、before・after・unknown処理で複数の関数を呼ぶ必要がある場合は、適切なハンドラ関数がそれを管理しなければなりません。