本文へ移動
    hazBasehazBaseDocs
    IMPLEMENTATION PATTERNS

    物理資産・在庫

    資産の識別情報と権利を結び付け、発行・移転・保有を扱う。

    実装パターン一覧
    具体例

    設備1台に紐づく権利を発行し、保有者を管理する

    配送ロボット A-001に関する契約上の権利を1,000単位で表し、そのうち10単位を取引先へ割り当てる構成です。設備そのものの情報は資産台帳に保存し、発行数や保有数はトークンで管理します。

    資産IDを指定すると、対応するトークン、現在の保有者・保有数、割当や移転の履歴を同じ画面で確認できます。

    システム構成と役割

    1. 資産管理画面

      設備情報、契約、割当先と数量を表示します。

      Web UI
    2. 業務API・資産台帳

      資産IDとトークンの対応、操作権限、処理の受付IDを管理します。

      Application API / DB
    3. 権利の発行・移転

      発行上限と保有残高を管理し、許可された移転を実行します。

      FlexibleTokenHelper
    4. 履歴の同期

      確定した取引を台帳に反映し、稼働や点検の記録と紐づけます。

      Transaction receipts / Events

    データモデル例

    業務DBに保存する情報と、チェーンやAPIで管理する情報を対応づけます。フィールド名とサンプル値は、この構成で使うアプリケーション側の設計例です。

    項目・値の例管理する場所役割・対応関係
    assetIdROBOT-A-001業務DB実物設備を識別する固定ID。機体番号や台帳番号との対応を保存します。
    agreementIdAGR-2027-001業務DBトークンが表す権利の契約と版。原本や個人情報はアクセス制御した場所に保存します。
    chainId + tokenAddresschainId / 0x…DBとチェーン同じアドレスでもチェーンが異なれば別のコントラクトです。必ず組で保存します。
    cap / decimals1000 / 0チェーンこの例は小数を使わず、1単位を1として扱います。発行上限は初期化時に設定します。
    holder / balancepartnerWallet / 10チェーン保有数の正はチェーン。DB側の一覧はイベントから作る検索用データです。
    operationId / transactionHashALLOC-001 / 0x…業務DB受付・送信・確定の状態と取引を対応づけ、再送による二重発行を防ぎます。

    処理の流れ

    1. 設備と権利を登録する

      A-001と契約AGR-2027-001を台帳に登録します。設備1台につき1コントラクトを使う構成なら、トークンの保有数をその設備に関する権利の数量として扱えます。

      Application DB: assetId → agreementId → tokenAddress
    2. トークンを初期化する

      FlexibleTokenを発行上限1,000、小数桁0で用意します。発行者にMINTER_ROLEを付与し、譲渡可否や必要なホワイトリストを設定します。

      FlexibleTokenHelper.deploy / attach
    3. 取引先に10単位を割り当てる

      割当申請を保存してからmintを呼び出します。確定したreceiptのハッシュを申請に紐づけ、残高を取得します。発行済みの単位を渡す場合は、保有者の署名でtransferを使用します。

      mint(recipient, amount) → balanceOf(recipient)
    4. 保有者の一覧を更新する

      Transferイベントを取り込み、chainId・transactionHash・logIndexを一意キーにして反映します。画面表示用のDBと、チェーンの残高を定期的に照合します。

      Transfer events / balanceOf
    5. 運用記録を重ねる

      稼働時間、点検、故障などはassetIdで台帳に紐づけます。権利の移転と設備の引渡しは別の状態として記録し、現物の確認が必要な処理は業務側で管理します。

      Application DB: operating_records.assetId

    コードを利用する前の準備

    • 初期化済みFlexibleTokenのアドレスと、対象チェーンに接続した発行者のSignerを用意します。
    • この例では発行上限1,000・小数桁0を使用します。unitsには表示上の数量を文字列で渡します。
    • 発行者のMINTER_ROLE、Pauseの状態、割当先に必要な参加条件を確認します。
    Install
    npm install --save-exact @hazbase/kit@0.9.0 ethers@6.16.0

    以下はアプリケーションから呼び出すTypeScriptの関数です。接続先・権限・対象データを引数として渡します。UI、DBへの保存、処理の再開は、上記の構成に沿って業務側へ組み込めます。

    設備IDを残して、10単位を割り当てる

    allocateAssetへassetId、tokenAddress、recipient、units: "10"、issuerを渡します。DBへの保存処理は返された値を使用して、業務API側に組み込めます。

    pattern-assets.ts
    import { FlexibleTokenHelper } from '@hazbase/kit';
    import { parseUnits } from 'ethers';
    type Signer = Parameters<typeof FlexibleTokenHelper.deploy>[1];
    
    export async function allocateAsset(input: {
      assetId: string;
      tokenAddress: string;
      recipient: string;
      units: string;
      issuer: Signer;
    }) {
      if (!input.issuer.provider) throw new Error('A connected signer is required.');
      // Requires an initialized token and a signer with MINTER_ROLE.
      const token = FlexibleTokenHelper.attach(input.tokenAddress, input.issuer);
      const amount = parseUnits(input.units, await token.decimals());
      if (amount <= 0n) throw new Error('Units must be positive.');
    
      const receipt = await token.mint(input.recipient, amount);
      const balance = await token.balanceOf(input.recipient);
      const network = await input.issuer.provider.getNetwork();
    
      // Persist this mapping in your asset register after confirmation.
      return {
        assetId: input.assetId,
        chainId: network.chainId.toString(),
        tokenAddress: input.tokenAddress,
        holder: input.recipient,
        allocatedAtomic: amount.toString(),
        balanceAtomic: balance.toString(),
        transactionHash: receipt.hash,
        blockNumber: receipt.blockNumber,
      };
    }
    
    コード例をダウンロード

    実行結果と、アプリケーションへの反映

    保有数が0だった割当先ではbalanceAtomicが"10"になります。transactionHashとblockNumberを操作履歴へ保存します。mintは追加発行なので、画面の再読込や通信の再試行から無条件に呼び直さない構成にします。

    実装で押さえておきたい点

    数量の単位

    小数桁が18のトークンへ10をそのまま渡すと、表示上の10単位にはなりません。コードではdecimalsを読み、parseUnitsで最小単位へ変換します。

    取引成功後にDB保存が失敗した場合

    チェーン上の発行は取り消されません。受付IDと送信時の取引ハッシュを保存できる送信処理を用意し、イベントから確定結果を回収します。

    資産ごとに異なる権利

    同じトークンの数量は同質として扱われます。設備ごとに条件が違う場合は別コントラクト、個体を1つずつ識別する場合はPrivilegeNFTなどの構成が候補です。

    用途に合わせた拡張

    在庫・保管物品への応用

    assetIdを保管ロットへ置き換え、ロット内で同質の物品を単位化できます。引渡し完了時の消込は、倉庫側の確認とトークンのburnを対応づけます。

    RWA Opsとの組み合わせ

    設備の定義、発行、割当、運用記録をまとめて扱う場合はRWA Opsも利用できます。独自画面や既存台帳との接続は、API・SDKによる構成と比較できます。