Hunter  Krajcik

Hunter Krajcik

1662052920

A Simple Widget to Count The Amount Of Nested Widget Tree

widget_tree_depth_counter

Widget Tree Depth Counter

WidgetTreeDepthCounter is a simple widget to count the amount of nested widget tree, useful in the dynamic construction of the interface when it is important to know the depth of widget.

Image
WidgetTreeDepthCounter

Features

  • count of the depth of the widget with respect to the tree (all uses of WidgetTreeDepthCounter in the current tree are counted, the other types of widgets are not counted)

This widget can be used conveniently in such cases:

Dynamically manage the colors of widgets based on their position in the tree

in an app that manages chapter numbers it is very easy to renumber them in case a chapter is removed.

...

Many other cases where it is very difficult to manage a widget through fixed parameters to be managed based on the construction of the tree.

Usage

Make sure to check out the examples on GitHub.

Image
Example of operation in a widget tree

Installation

From pubspec.yaml

Add the following line to pubspec.yaml:

dependencies:
  widget_tree_depth_counter: <last-release>

and

flutter pub get

From cli

run following command:

flutter pub add widget_tree_depth_counter

Basic setup

Complete example available here.

ParentWidget(
  child: WidgetTreeDepthCounter(
    builder: (context, counter) => //counter=0
      Container(
        color: Theme.of(context)
          .primaryColor
          .withOpacity(counter * 0.05 + 0.05),
          child: WidgetTreeDepthCounter(
            builder: (context, counter) =>//counter=1
                Container(
                    color: Theme.of(context)
                    .primaryColor
                        .withOpacity(counter * 0.05 + 0.05),
                ),
          ),
      ),
  ),
),

WidgetTreeDepthCounter Properties

  • builder: Function called at layout time to construct the widget tree, return Widget.
  • count: With this parameter it's possible define or overwrite the current depth count value.

 

Use current counter value during build WidgetTreeDepthCounter

WidgetTreeDepthCounter uses Provider library to count the depth, but if it is necessary to access the current value to perform a sum (for example), it is possible to retrieve the count value through the `Provider 'functions:


WidgetTreeDepthCounter(
            count: context.read<DepthCounter>().value + 2,
            builder: (context, counter) =>
                Text(counter.toString()),
          )

Obviously to access the value via context.read<DepthCounter>() it is necessary that at least one WidgetTreeDepthCounter is present in the tree and provider package is required.

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add widget_tree_depth_counter

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  widget_tree_depth_counter: ^1.0.1

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:widget_tree_depth_counter/widget_tree_depth_counter.dart';

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:widget_tree_depth_counter/widget_tree_depth_counter.dart';
import 'package:widget_tree_depth_counter_example/helper/colored_container.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'WidgetTreeDepthCounter Example',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Widget tree depth counter'),
        centerTitle: true,
      ),
      body: Container(
        child: Center(
          child: ColorExample(),
        ),
      ),
    );
  }
}

class ColorExample extends StatelessWidget {
  const ColorExample({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) => Container(
        width: constraints.maxWidth * .9,
        height: constraints.maxHeight * .9,
        child: WidgetTreeDepthCounter(
          builder: (context, counter) => ColoredContainer(
            counter: counter,
            color: Theme.of(context)
                .primaryColor
                .withOpacity(counter * 0.05 + 0.05),
            child: WidgetTreeDepthCounter(
              builder: (context, counter) => ColoredContainer(
                counter: counter,
                color: Theme.of(context)
                    .primaryColor
                    .withOpacity(counter * 0.05 + 0.05),
                child: WidgetTreeDepthCounter(
                  builder: (context, counter) => ColoredContainer(
                    counter: counter,
                    color: Theme.of(context)
                        .primaryColor
                        .withOpacity(counter * 0.05 + 0.05),
                    child: Row(
                      children: [
                        Expanded(
                          flex: 1,
                          child: WidgetTreeDepthCounter(
                            builder: (context, counter) => ColoredContainer(
                              counter: counter,
                              color: Theme.of(context)
                                  .primaryColor
                                  .withOpacity(counter * 0.05 + 0.05),
                            ),
                          ),
                        ),
                        Expanded(
                          flex: 3,
                          child: WidgetTreeDepthCounter(
                            builder: (context, counter) => ColoredContainer(
                              counter: counter,
                              color: Theme.of(context)
                                  .primaryColor
                                  .withOpacity(counter * 0.05 + 0.05),
                              child: WidgetTreeDepthCounter(
                                builder: (context, counter) => ColoredContainer(
                                  counter: counter,
                                  color: Theme.of(context)
                                      .primaryColor
                                      .withOpacity(counter * 0.05 + 0.05),
                                  child: Row(
                                    children: [
                                      Expanded(
                                        child: WidgetTreeDepthCounter(
                                          builder: (context, counter) =>
                                              ColoredContainer(
                                            counter: counter,
                                            color: Theme.of(context)
                                                .primaryColor
                                                .withOpacity(
                                                    counter * 0.05 + 0.05),
                                            child: Column(
                                              children: [
                                                Expanded(
                                                  child: WidgetTreeDepthCounter(
                                                    builder:
                                                        (context, counter) =>
                                                            ColoredContainer(
                                                      counter: counter,
                                                      color: Theme.of(context)
                                                          .primaryColor
                                                          .withOpacity(
                                                              counter * 0.05 +
                                                                  0.05),
                                                    ),
                                                  ),
                                                ),
                                                Expanded(
                                                  child: WidgetTreeDepthCounter(
                                                    builder:
                                                        (context, counter) =>
                                                            ColoredContainer(
                                                      counter: counter,
                                                      color: Theme.of(context)
                                                          .primaryColor
                                                          .withOpacity(
                                                              counter * 0.05 +
                                                                  0.05),
                                                      child:
                                                          WidgetTreeDepthCounter(
                                                        builder: (context,
                                                                counter) =>
                                                            ColoredContainer(
                                                          counter: counter,
                                                          color: Theme.of(
                                                                  context)
                                                              .primaryColor
                                                              .withOpacity(
                                                                  counter *
                                                                          0.05 +
                                                                      0.05),
                                                        ),
                                                      ),
                                                    ),
                                                  ),
                                                ),
                                              ],
                                            ),
                                          ),
                                        ),
                                      ),
                                      Expanded(
                                        child: WidgetTreeDepthCounter(
                                          builder: (context, counter) =>
                                              ColoredContainer(
                                            counter: counter,
                                            color: Theme.of(context)
                                                .primaryColor
                                                .withOpacity(
                                                    counter * 0.05 + 0.05),
                                            child: Row(
                                              children: [
                                                Expanded(
                                                  child: WidgetTreeDepthCounter(
                                                    builder:
                                                        (context, counter) =>
                                                            ColoredContainer(
                                                      counter: counter,
                                                      color: Theme.of(context)
                                                          .primaryColor
                                                          .withOpacity(
                                                              counter * 0.05 +
                                                                  0.05),
                                                    ),
                                                  ),
                                                ),
                                                Expanded(
                                                  child: WidgetTreeDepthCounter(
                                                    builder:
                                                        (context, counter) =>
                                                            ColoredContainer(
                                                      counter: counter,
                                                      color: Theme.of(context)
                                                          .primaryColor
                                                          .withOpacity(
                                                              counter * 0.05 +
                                                                  0.05),
                                                    ),
                                                  ),
                                                ),
                                              ],
                                            ),
                                          ),
                                        ),
                                      ),
                                    ],
                                  ),
                                ),
                              ),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

📚 My other packages

Flutter

PackageVerisonScoreLikesTestCoverage
Pub Packagepub pointslikes  
Pub Packagepub pointslikes  
Pub Packagepub pointslikes  
Pub Packagepub pointslikes  

Dart

PackageVerisonScoreLikesTestCoverage
Pub Packagepub pointslikesTest CIcodecov

Download Details:

Author: Rickypid
Source Code: https://github.com/rickypid/widget_tree_depth_counter 
License: BSD-3-Clause license

#flutter #dart #widget #tree 

What is GEEK

Buddha Community

A Simple Widget to Count The Amount Of Nested Widget Tree
Hunter  Krajcik

Hunter Krajcik

1662052920

A Simple Widget to Count The Amount Of Nested Widget Tree

widget_tree_depth_counter

Widget Tree Depth Counter

WidgetTreeDepthCounter is a simple widget to count the amount of nested widget tree, useful in the dynamic construction of the interface when it is important to know the depth of widget.

Image
WidgetTreeDepthCounter

Features

  • count of the depth of the widget with respect to the tree (all uses of WidgetTreeDepthCounter in the current tree are counted, the other types of widgets are not counted)

This widget can be used conveniently in such cases:

Dynamically manage the colors of widgets based on their position in the tree

in an app that manages chapter numbers it is very easy to renumber them in case a chapter is removed.

...

Many other cases where it is very difficult to manage a widget through fixed parameters to be managed based on the construction of the tree.

Usage

Make sure to check out the examples on GitHub.

Image
Example of operation in a widget tree

Installation

From pubspec.yaml

Add the following line to pubspec.yaml:

dependencies:
  widget_tree_depth_counter: <last-release>

and

flutter pub get

From cli

run following command:

flutter pub add widget_tree_depth_counter

Basic setup

Complete example available here.

ParentWidget(
  child: WidgetTreeDepthCounter(
    builder: (context, counter) => //counter=0
      Container(
        color: Theme.of(context)
          .primaryColor
          .withOpacity(counter * 0.05 + 0.05),
          child: WidgetTreeDepthCounter(
            builder: (context, counter) =>//counter=1
                Container(
                    color: Theme.of(context)
                    .primaryColor
                        .withOpacity(counter * 0.05 + 0.05),
                ),
          ),
      ),
  ),
),

WidgetTreeDepthCounter Properties

  • builder: Function called at layout time to construct the widget tree, return Widget.
  • count: With this parameter it's possible define or overwrite the current depth count value.

 

Use current counter value during build WidgetTreeDepthCounter

WidgetTreeDepthCounter uses Provider library to count the depth, but if it is necessary to access the current value to perform a sum (for example), it is possible to retrieve the count value through the `Provider 'functions:


WidgetTreeDepthCounter(
            count: context.read<DepthCounter>().value + 2,
            builder: (context, counter) =>
                Text(counter.toString()),
          )

Obviously to access the value via context.read<DepthCounter>() it is necessary that at least one WidgetTreeDepthCounter is present in the tree and provider package is required.

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add widget_tree_depth_counter

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  widget_tree_depth_counter: ^1.0.1

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:widget_tree_depth_counter/widget_tree_depth_counter.dart';

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:widget_tree_depth_counter/widget_tree_depth_counter.dart';
import 'package:widget_tree_depth_counter_example/helper/colored_container.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'WidgetTreeDepthCounter Example',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Widget tree depth counter'),
        centerTitle: true,
      ),
      body: Container(
        child: Center(
          child: ColorExample(),
        ),
      ),
    );
  }
}

class ColorExample extends StatelessWidget {
  const ColorExample({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) => Container(
        width: constraints.maxWidth * .9,
        height: constraints.maxHeight * .9,
        child: WidgetTreeDepthCounter(
          builder: (context, counter) => ColoredContainer(
            counter: counter,
            color: Theme.of(context)
                .primaryColor
                .withOpacity(counter * 0.05 + 0.05),
            child: WidgetTreeDepthCounter(
              builder: (context, counter) => ColoredContainer(
                counter: counter,
                color: Theme.of(context)
                    .primaryColor
                    .withOpacity(counter * 0.05 + 0.05),
                child: WidgetTreeDepthCounter(
                  builder: (context, counter) => ColoredContainer(
                    counter: counter,
                    color: Theme.of(context)
                        .primaryColor
                        .withOpacity(counter * 0.05 + 0.05),
                    child: Row(
                      children: [
                        Expanded(
                          flex: 1,
                          child: WidgetTreeDepthCounter(
                            builder: (context, counter) => ColoredContainer(
                              counter: counter,
                              color: Theme.of(context)
                                  .primaryColor
                                  .withOpacity(counter * 0.05 + 0.05),
                            ),
                          ),
                        ),
                        Expanded(
                          flex: 3,
                          child: WidgetTreeDepthCounter(
                            builder: (context, counter) => ColoredContainer(
                              counter: counter,
                              color: Theme.of(context)
                                  .primaryColor
                                  .withOpacity(counter * 0.05 + 0.05),
                              child: WidgetTreeDepthCounter(
                                builder: (context, counter) => ColoredContainer(
                                  counter: counter,
                                  color: Theme.of(context)
                                      .primaryColor
                                      .withOpacity(counter * 0.05 + 0.05),
                                  child: Row(
                                    children: [
                                      Expanded(
                                        child: WidgetTreeDepthCounter(
                                          builder: (context, counter) =>
                                              ColoredContainer(
                                            counter: counter,
                                            color: Theme.of(context)
                                                .primaryColor
                                                .withOpacity(
                                                    counter * 0.05 + 0.05),
                                            child: Column(
                                              children: [
                                                Expanded(
                                                  child: WidgetTreeDepthCounter(
                                                    builder:
                                                        (context, counter) =>
                                                            ColoredContainer(
                                                      counter: counter,
                                                      color: Theme.of(context)
                                                          .primaryColor
                                                          .withOpacity(
                                                              counter * 0.05 +
                                                                  0.05),
                                                    ),
                                                  ),
                                                ),
                                                Expanded(
                                                  child: WidgetTreeDepthCounter(
                                                    builder:
                                                        (context, counter) =>
                                                            ColoredContainer(
                                                      counter: counter,
                                                      color: Theme.of(context)
                                                          .primaryColor
                                                          .withOpacity(
                                                              counter * 0.05 +
                                                                  0.05),
                                                      child:
                                                          WidgetTreeDepthCounter(
                                                        builder: (context,
                                                                counter) =>
                                                            ColoredContainer(
                                                          counter: counter,
                                                          color: Theme.of(
                                                                  context)
                                                              .primaryColor
                                                              .withOpacity(
                                                                  counter *
                                                                          0.05 +
                                                                      0.05),
                                                        ),
                                                      ),
                                                    ),
                                                  ),
                                                ),
                                              ],
                                            ),
                                          ),
                                        ),
                                      ),
                                      Expanded(
                                        child: WidgetTreeDepthCounter(
                                          builder: (context, counter) =>
                                              ColoredContainer(
                                            counter: counter,
                                            color: Theme.of(context)
                                                .primaryColor
                                                .withOpacity(
                                                    counter * 0.05 + 0.05),
                                            child: Row(
                                              children: [
                                                Expanded(
                                                  child: WidgetTreeDepthCounter(
                                                    builder:
                                                        (context, counter) =>
                                                            ColoredContainer(
                                                      counter: counter,
                                                      color: Theme.of(context)
                                                          .primaryColor
                                                          .withOpacity(
                                                              counter * 0.05 +
                                                                  0.05),
                                                    ),
                                                  ),
                                                ),
                                                Expanded(
                                                  child: WidgetTreeDepthCounter(
                                                    builder:
                                                        (context, counter) =>
                                                            ColoredContainer(
                                                      counter: counter,
                                                      color: Theme.of(context)
                                                          .primaryColor
                                                          .withOpacity(
                                                              counter * 0.05 +
                                                                  0.05),
                                                    ),
                                                  ),
                                                ),
                                              ],
                                            ),
                                          ),
                                        ),
                                      ),
                                    ],
                                  ),
                                ),
                              ),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

📚 My other packages

Flutter

PackageVerisonScoreLikesTestCoverage
Pub Packagepub pointslikes  
Pub Packagepub pointslikes  
Pub Packagepub pointslikes  
Pub Packagepub pointslikes  

Dart

PackageVerisonScoreLikesTestCoverage
Pub Packagepub pointslikesTest CIcodecov

Download Details:

Author: Rickypid
Source Code: https://github.com/rickypid/widget_tree_depth_counter 
License: BSD-3-Clause license

#flutter #dart #widget #tree 

Check if all the Nodes in a Binary Tree having common values are at least D distance apart

Given a Binary Tree and an integer D, the task is to check if the distance between all pairs of same node values in the Tree is ? D or not. If found to be true, then print Yes. Otherwise, print No.

Examples:

Input:_ D = 7 _

                1
              /   \ 
             2     3
            / \   /  \ 
           4   3  4   4

Output:_ Yes _

Explanation:

_The repeated value of nodes are 3 and 4. _

_The distance between the two nodes valued 3, is 3. _

_The maximum distance between any pair of nodes valued 4 is 4. _

Therefore, none of the distances exceed 7

Input:_ D = 1 _

          3
         / \
        3   3
             \
              3

Output:_ No _

Recommended: Please try your approach on {IDE} first, before moving on to the solution.

**Approach: **

The idea is to observe that the problem is similar to finding the distance between two nodes of a tree. But there can be multiple pairs of nodes for which we have to find the distance. Follow the steps below:

  1. Perform the Post Order Traversal of the given tree and find the distance between the repeated pairs of nodes.
  2. Find the nodes that are repeated in the tree using unordered_map.
  3. For each repeated node of a particular value, find the maximum possible distance between any pair.
  4. If that distance is > D, print “No”.
  5. If no such node value is found having a pair containing that value, exceeding **D, **then print “Yes”.

#greedy #recursion #searching #tree #binary tree #frequency-counting #postorder traversal #tree-traversal

Remove all leaf nodes from a Generic Tree or N-ary Tree

Given a Generic tree, the task is to delete the leaf nodes from the tree.

** Examples:**

Input: 
              5
          /  /  \  \
         1   2   3   8
        /   / \   \
       15  4   5   6 

Output:  
5 : 1 2 3
1 :
2 :
3 :

Explanation: 
Deleted leafs are:
8, 15, 4, 5, 6

Input:      
              8
         /    |    \
       9      7       2
     / | \    |    / / | \ \
    4  5 6    10  11 1 2  2 3
Output:  
8: 9 7 2
9:
7:
2:

**Approach: **Follow the steps given below to solve the problem

  • Take tree into the vector.
  • Traverse the tree and check the condition:
  • If current node is leaf then
  • Delete the leaf from vector
  • Else
  • Recursively call for every child.

Below is the implementation of the above approach:

#data structures #recursion #tree #n-ary-tree #tree-traversal #data analysis

Stratis Blockchain API をカスタムアプリケーションに統合する

この記事では、StratisBlockchainAPIをカスタムまたはサードパーティのアプリケーションに統合する方法を説明します。Angularアプリケーションを作成し、StratisPrivateAPIを統合します。Stratis Blockchain APIと対話し、カスタムアプリケーションで応答を表示します。さらに、この記事では、スマートコントラクトを展開するためのユーザーインターフェイスの作成について説明します。この記事では、スマートコントラクトの展開に必要なすべてのエンドポイントのコードについて説明し、提供しています。ただし、カスタムソフトウェア要件に応じて、アイデアを取得し、他のエンドポイントと対話することができます。スマートコントラクトの記述方法とバイトコードの生成方法の詳細については、こちらをご覧 ãã ã•ã„。

ソースコードは ã“ちらから入手できます。

前提条件

  • Angular用のIDE(VisualStudioまたはVisualStudio Code)
  • Stratis FullNode
  • スマートコントラクトのバイトコード

この記事では、Angular 12を使用しますが、他のバージョンでも同じです。

Angularアプリケーションを作成する

以下の手順に示すように、AngularCLIを使用してAngularアプリケーションを作成します。

Angular CLIをインストールします(お持ちでない場合)。

npm install -g @angular/cli

バッシュ

次のコマンドで新しいアプリを作成します。

ng new StratisFullNodeWebApp

JavaScript

プロジェクトフォルダに移動して、アプリケーションを実行します。Angularアプリケーションをビルドして実行するには、次のようにserveコマンドを使用します。

cd StratisFullNodeWebAppng serve

バッシュ

または、デフォルトのAngularアプリケーションを開くには:ビルド、実行、およびオープンを一度に実行する以下のコマンドを実行します。

ng serve --open

バッシュ

–openコマンドは、 http:// localhost:4200/にあるブラウザーに対してプロジェクトを開きます ã€‚ åŽç›Šæ€§ã®é«˜ã„UIを設計するために、AdminLTEテーマを実装しました。必要に応じて、ここからの手順に従って実装することもできます。 

Angularアプリでモデルを作成して追加する

各コンポーネントのすべてのモデルを保持する_modelフォルダーを作成します。

コマンドを使用してモデルを追加することも、以下に説明するように手動で追加することもできます。_modelフォルダーで右クリック–>新しいアイテムを追加–> typescriptファイルを追加し、構造に応じて名前を変更します。

モデルの下にconfig.tsファイルを追加しましょう。構成関連のすべての情報を保持でき、構成関連の情報を1か所から簡単に維持できる場所。これは、サービスまたはコンポーネントで呼び出すAPIのルート/ベースURLを配置するために作成しています。サンプル ã®config.ts ã‚³ãƒ¼ãƒ‰ã€

export const ROOT_URL: string = "http://localhost:38223";

JavaScript

ローカルホストで実行されているフルノードAPIを統合します:  http:// localhost:38223。

私はあなたがすでにFullNodeを持っていると仮定しました。お持ちでない場合は、 ã“ちらからダウンロードできます。プロジェクトを開き、devmodeでStratis.CirrusMinerDプロジェクトを実行します。以下のコマンドを使用して、FullNodeを実行できます。

cd StratisFullNode\src\Stratis.CirrusMinerDdotnet run -devmode=miner

バッシュ

ブラウザでhttp:// localhost:38223 / swagger / index.htmlを開くと、APIのリストが表示されます。

StratisBlockchainAPIをカスタムアプリケーションに統合する

ウォレットコンポーネント

ウォレットを統合するために、ウォレットサービスとウォレットコンポーネントを作成します。以下のコマンドを実行して、ウォレットのサービスとコンポーネントを生成します。

ng g service _service/stratisfullnode/walletng g component apicollection/wallet

バッシュ

この記事では、ウォレットAPIから3つのエンドポイントを実装しますが、他のAPIの実装も同様です。Wallet API Controllerから、Wallet Load、Wallet balance、WalletSplitcoinsの3つのエンドポイントを呼び出します。

エンドポイント:/ api / Wallet / load:Wallet Loadは、プライベートチェーンがスムーズに実行され、アプリがチェーンに接続されていることを確認するためのものです。

完全な設計後のウォレットロードには、以下のクレデンシャルを使用してください。

パラメーター価値
名前cirrusdev
パスワードパスワード

エンドポイント:/ api / Wallet / balance:ウォレットアドレス、金額などのリストを提供します。スマートコントラクトを展開するには、バランスの取れたウォレットアドレスが必要です。

エンドポイント:/ api / Wallet / splitcoins:要求された量の等しい値を作成し、バランスの取れたアドレスのリストを提供します。バランスの取れた1つのアドレスを取得し、より多くのアドレスが必要な場合は、これを使用してバランスを分割し、バランスのとれたより多くのアドレスを取得できます。

APIの投稿と応答を簡単に処理するには、それぞれのモデルを作成することをお勧めします。同様に、WalletLoad、WalletBalance、およびWalletSplitcoinsのモデルを作成します。ロードをウォレット化するには、名前とパスワードのパラメーターを渡す必要があります。したがって、名前とパスワードのプロパティを使用してモデルウォレットロードを作成します。

walletload.tsモデルのコードを  ä»¥ä¸‹ã«ç¤ºã—ます。

export class WalletLoad {  name: string = "";  password: string = "";}

JavaScript

同様に、Walletbalanceのモデルを作成します。walletbalance.ts ãƒ¢ãƒ‡ãƒ«ã®ã‚³ãƒ¼ãƒ‰ ã¯ã€

export class WalletBalance {  walletname: string = "";  accountname: string = "";  includebalancebyaddress: boolean=false;}

JavaScript

上記のように、WalletCoinSplitのモデルを作成します。waletsplitcoin.ts ã®ã‚³ãƒ¼ãƒ‰ã‚’ ä»¥ä¸‹ã«ç¤ºã—ます。

export class WalletSplitCoin {  walletName: string = "";  accountName: string = "";  walletPassword: string = "";  totalAmountToSplit: number = 1;  utxosCount: number = 1;}

JavaScript

ウォレットサービス

次に、ウォレットAPIのサービスクラスをwallet.services.tsとして ä½œæˆã—ます。configからルートURLをインポートし、ベースURLを使用してAPIエンドポイントを呼び出します。Stratis FullNodeのSwaggerページから、WalletLoadがパラメーター名とパスワードを必要とするpostメソッドであることがわかります。同様に、WalletSplitCoinも投稿であり、WalletBalanceはパラメーターを持つgetメソッドです。したがって、コードを記述し、それに応じてパラメーターを渡すことができます。

ここでは、次のように、このサービスで3つのメソッドを作成して作成します。

以下は、  ã“れらのAPIエンドポイントのwallet.services.tsクラスのコードです。

import { Injectable } from '@angular/core';import { HttpClient } from '@angular/common/http';import { ROOT_URL } from '../../_model/config';@Injectable({  providedIn: 'root'})export class WalletService {  constructor(private http: HttpClient) { }  LoadWallet(login:any) {    return this.http.post(ROOT_URL + '/api/Wallet/load', login, { observe: 'response' });  }  WalletBalance(params:any) {    return this.http.get(ROOT_URL + '/api/Wallet/balance', { params: params });  }  WalletSplitCoins(walletSplitCoin: any) {    return this.http.post(ROOT_URL + '/api/Wallet/splitcoins', walletSplitCoin);  }}

JavaScript

httpリクエストにはHttpClientが必要なので、以下に示すようにHttpClient in-app -module.ts ã‚’インポートします(そこで利用できない場合)。エラーが発生します。

StratisBlockchainAPIをカスタムアプリケーションに統合する

ウォレットコンポーネント

次に、Wallet Service、すべてのWallet関連モデルをインポートし、  wallet.component.ts ã§ã‚µãƒ¼ãƒ“スのメソッドを呼び出し、modelを使用してパラメーターを渡します。

wallet.component.tsのコード 

import { Component, OnInit } from '@angular/core';import { WalletLoad } from '../../_model/walletload';import { WalletService } from '../../_service/stratisfullnode/wallet.service';import { WalletBalance } from '../../_model/walletbalance';import { WalletSplitCoin } from '../../_model/walletsplitcoins';import { HttpParams } from '@angular/common/http';import Swal from 'sweetalert2';@Component({  selector: 'app-wallet',  templateUrl: './wallet.component.html',  styleUrls: ['./wallet.component.scss']})export class WalletComponent implements OnInit {  public login: WalletLoad = new WalletLoad();  public walletbalance: WalletBalance = new WalletBalance();  public walletSplitCoin: WalletSplitCoin = new WalletSplitCoin();  isConnected: boolean = false;  walletInfos: any;  walletbalances: any;  walletSplitedCoins: any;  constructor( private stratisFullNode: WalletService ) { }  IncludeBalanceByAddress: any = ['true', 'false']  ngOnInit(): void {    this.LoadWallet();  }  LoadWallet() {    this.stratisFullNode.LoadWallet(this.login).subscribe((response: any) => {      console.log(response);      if (response.ok) {        this.isConnected = true;      //  console.log(response);        Swal.fire('Successful', 'Full Node Connection successful', 'info');      } else {       Swal.fire('Oops...', 'Something went wrong!, Please contact your administrator', 'error');        //alert('Oops...');        (error: any) => {          console.log(error);        }      }    });  }  WalletBalance() {    let params = new HttpParams().set("WalletName", this.walletbalance.walletname).set("AccountName", this.walletbalance.accountname).set("IncludeBalanceByAddress", this.walletbalance.includebalancebyaddress);    this.stratisFullNode.WalletBalance(params).subscribe((response: any) => {      if (response.balances) {        this.walletbalances = response.balances;        //console.log(data);        console.log(this.walletbalances);      } else {      //  Swal.fire('Oops...', 'Something went wrong!, Please contact your administrator', 'error');        alert('Opps!!!!');        (error: any) => {          console.log(error);        }      }    });  }  WalletAplitCoins() {    this.stratisFullNode.WalletSplitCoins(this.walletSplitCoin).subscribe((response: any) => {      console.log(response);      if (response.outputs) {        this.walletSplitedCoins = response.outputs;        console.log(this.walletSplitedCoins);        //  alert('Load Successfully')      } else {        alert('Oops...');        (error: any) => {          console.log(error);        }      }    });  }}

JavaScript

ルーティングについては、ソースコードのapp-routing.module.tsを参照してください ã€‚各コンポーネントを追加した後、この app-routing.module.tsに追加できます。

ウォレットコンポーネントHTML

wallet.component.htmlでは、ユーザー入力としてパラメーターを渡すフォームを設計します。1つのフォームが必要で、エンドポイントごとにボタンを送信します。応答を受け取ると、送信ボタンのすぐ下に応答結果が表示されます。これがwallet.component.html ãƒšãƒ¼ã‚¸ã®å®Œå…¨ãªã‚³ãƒ¼ãƒ‰ã§ã™ ã€‚

<section class="content-header">
  <div class="container-fluid">
    <div class="row mb-2">
      <div class="col-sm-6">
        <h1>Stratis FullNode APIs </h1>
      </div>
      <div class="col-sm-6">
        <ol class="breadcrumb float-sm-right">
          <li class="breadcrumb-item"><a routerLink="/admin">Wallet</a></li>
          <li class="breadcrumb-item active">Load Wallet</li>
        </ol>
      </div>
    </div>
  </div><!-- /.container-fluid -->
</section>
<!-- Main content -->
<section class="content">
  <div class="container-fluid">
     <form (ngSubmit)="walletLoadForm.form.valid && LoadWallet()" #walletLoadForm="ngForm">
      <div class="card card-primary card-outline">
        <div class="card-header">
          <h3 class="card-title">Wallet Load</h3>
          <div class="card-tools">
            <button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fas fa-minus"></i></button>
          </div>
        </div>
        <!-- /.card-header -->
        <div class="card-body">
          <div class="row">
            <div class="col-md-6">
              <div class="form-group">
                <label>Name</label>
                <input type="text" class="form-control" placeholder="Name" [ngClass]="{ 'is-invalid': walletLoadForm.submitted && name.invalid }" [(ngModel)]="login.name" name="name" #name="ngModel" required>
                <div class="text-danger" *ngIf="walletLoadForm.submitted && name.invalid">
                  <p *ngIf="name.errors?.required">Name is required</p>
                </div>
              </div>
            </div>
            <div class="col-md-6">
              <div class="form-group">
                <label>Password</label>
                <input type="text" class="form-control" placeholder="Password" [(ngModel)]="login.password" name="type" #type="ngModel" [ngClass]="{ 'is-invalid': walletLoadForm.submitted && type.invalid }" required>
                <div class="text-danger" *ngIf="walletLoadForm.submitted && type.invalid">
                  <p *ngIf="type.errors?.required">Password is required</p>
                </div>
              </div>
            </div>

            <div class="col-sm-2">
              <button type="submit" class="btn btn-primary"><i class="fa fa-lock"></i> Load Wallet</button>
            </div>
            <!-- /.col -->
            <div class="col-sm-6" *ngIf="isConnected">
              <span class="badge badge-success float-sm-right"> Full Node Connection Successful</span>
            </div>
          </div>
        </div>
        <!-- /.card-body -->
      </div>
    </form>
    <!--Wallet Balance-->
    <form (ngSubmit)="walletBalanceForm.form.valid && WalletBalance()" #walletBalanceForm="ngForm">
      <!-- SELECT2 EXAMPLE -->
      <div class="card card-primary card-outline">
        <div class="card-header">
          <h3 class="card-title">Wallet Balance</h3>
          <div class="card-tools">
            <button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fas fa-minus"></i></button>
          </div>
        </div>
        <!-- /.card-header -->
        <div class="card-body">
          <div class="row">
            <div class="col-md-4">
              <div class="form-group">
                <label>Wallet Name</label>
                <input type="text" class="form-control" placeholder="Wallet Name" [ngClass]="{ 'is-invalid': walletBalanceForm.submitted && walletname.invalid }" [(ngModel)]="walletbalance.walletname" name="walletname" #walletname="ngModel" required>
                <div class="text-danger" *ngIf="walletBalanceForm.submitted && name.invalid">
                  <p *ngIf="walletname.errors?.required">Wallet Name is required</p>
                </div>
              </div>
            </div>
            <div class="col-md-4">
              <div class="form-group">
                <label>Account Name</label>
                <input type="text" class="form-control" placeholder="Account Name" [(ngModel)]="walletbalance.accountname" name="accountname" #accountname="ngModel" [ngClass]="{ 'is-invalid': walletBalanceForm.submitted && accountname.invalid }" required>
                <div class="text-danger" *ngIf="walletBalanceForm.submitted && accountname.invalid">
                  <p *ngIf="accountname.errors?.required">Account Name is required</p>
                </div>
              </div>
            </div>
            <div class="col-sm-4">
              <label for="includebalancebyaddress">IncludeBalanceByAddress</label>
              <select class="custom-select" [(ngModel)]="walletbalance.includebalancebyaddress" name="includebalancebyaddress">
                <option *ngFor="let includebalance of IncludeBalanceByAddress" [ngValue]="includebalance">{{includebalance}}</option>
              </select>
            </div>
          </div>
          <div>

          </div>
          <div class="row">
            <div class="col-sm-4">
              <button type="submit" class="btn btn-primary"><i class="fa fa-lock"></i> Load Wallet Balance</button>
            </div>
            <!-- /.col -->

          </div>
          <div *ngIf="walletbalances" class="card card-primary">
            <div class="card-body">
              <div class="row">
                <table id="appsettingtable" class="table table-striped table- table-bordered">
                  <thead>
                    <tr>
                      <th>Account Name</th>
                      <th>Path</th>
                      <th>CoinType</th>
                      <th>AmountConfirmed</th>
                      <th>Modified by</th>
                      <th>SpendableAmount </th>
                    </tr>
                  </thead>
                  <tbody>
                    <tr *ngFor="let balance of walletbalances">
                      <td>{{balance.accountName}}</td>
                      <td>{{balance.accountHdPath}}</td>
                      <td>{{balance.coinType}}</td>
                      <td>{{balance.amountConfirmed}}</td>
                      <td>{{balance.amountUnconfirmed}}</td>
                      <td>
                        {{balance.spendableAmount}}
                      </td>
                    </tr>
                  </tbody>
                </table>
              </div>
            </div>
            <!-- /.card-header -->
            <h3 class="card-title">List of Addresses</h3>
            <div *ngFor="let balance of walletbalances">
              <div *ngFor="let add of balance.addresses">
                <span><span class="badge">Address:</span>  {{add.address}}</span>
                <span><span class="badge">IsUsed:</span>  {{add.isUsed}}</span>
                <span><span class="badge">IsChange:</span>  {{add.isChange}}</span>
                <span><span class="badge">Amount Confirmed:</span>  {{add.amountConfirmed}}</span>
                <span><span class="badge">Amount Unconfirmed:</span>  {{add.amountUnconfirmed}}</span>
              </div>

            </div>
          </div>
        </div>
        <!-- /.card-body -->
      </div>

    </form>

    <!--Wallet Split Coins-->
    <form (ngSubmit)="walletSplitCoinForm.form.valid && WalletAplitCoins()" #walletSplitCoinForm="ngForm">
      <!-- SELECT2 EXAMPLE -->
      <div class="card card-primary card-outline">
        <div class="card-header">
          <h3 class="card-title">Wallet Split Coins</h3>
          <div class="card-tools">
            <button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fas fa-minus"></i></button>
          </div>
        </div>
        <!-- /.card-header -->
        <div class="card-body">
          <div class="row">
            <div class="col-md-4">
              <div class="form-group">
                <label>Wallet Name</label>
                <input type="text" class="form-control" placeholder="Wallet Name" [ngClass]="{ 'is-invalid': walletSplitCoinForm.submitted && walletNameSplitCoin.invalid }" [(ngModel)]="walletSplitCoin.walletName" name="walletName" #walletNameSplitCoin="ngModel" required>
                <div class="text-danger" *ngIf="walletSplitCoinForm.submitted && walletNameSplitCoin.invalid">
                  <p *ngIf="walletNameSplitCoin.errors?.required">Wallet Name is required</p>
                </div>
              </div>
            </div>
            <div class="col-md-4">
              <div class="form-group">
                <label>Account Name</label>
                <input type="text" class="form-control" placeholder="Account Name" [(ngModel)]="walletSplitCoin.accountName" name="accountName" #accountNameSplitCoin="ngModel" [ngClass]="{ 'is-invalid': walletSplitCoinForm.submitted && accountNameSplitCoin.invalid }" required>
                <div class="text-danger" *ngIf="walletSplitCoinForm.submitted && accountNameSplitCoin.invalid">
                  <p *ngIf="accountNameSplitCoin.errors?.required">Account Name is required</p>
                </div>
              </div>
            </div>
            <div class="col-md-4">
              <div class="form-group">
                <label>Wallet Password</label>
                <input type="text" class="form-control" placeholder="Wallet Password" [(ngModel)]="walletSplitCoin.walletPassword" name="walletPassword" #walletpassword="ngModel" [ngClass]="{ 'is-invalid': walletSplitCoinForm.submitted && walletpassword.invalid }" required>
                <div class="text-danger" *ngIf="walletSplitCoinForm.submitted && walletpassword.invalid">
                  <p *ngIf="walletpassword.errors?.required">Wallet Password is required</p>
                </div>
              </div>
            </div>
          </div>
          <div class="row">
            <div class="col-md-4">
              <div class="form-group">
                <label>Amount to Split</label>
                <input type="text" class="form-control" placeholder="No of Aplit" [(ngModel)]="walletSplitCoin.totalAmountToSplit" name="totalAmountToSplit" #totalAmountToSplit="ngModel" [ngClass]="{ 'is-invalid': walletSplitCoinForm.submitted && totalAmountToSplit.invalid }" required>
                <div class="text-danger" *ngIf="walletSplitCoinForm.submitted && totalAmountToSplit.invalid">
                  <p *ngIf="totalAmountToSplit.errors?.required">No of Split is required</p>
                </div>
              </div>
            </div>
            <div class="col-md-4">
              <div class="form-group">
                <label>No of Split</label>
                <input type="text" class="form-control" placeholder="No of Aplit" [(ngModel)]="walletSplitCoin.utxosCount" name="utxosCount" #utxosCount="ngModel" [ngClass]="{ 'is-invalid': walletSplitCoinForm.submitted && utxosCount.invalid }" required>
                <div class="text-danger" *ngIf="walletSplitCoinForm.submitted && utxosCount.invalid">
                  <p *ngIf="utxosCount.errors?.required">No of Split is required</p>
                </div>
              </div>
            </div>
          </div>
          <div class="row">
            <div class="col-sm-4">
              <button type="submit" class="btn btn-primary"><i class="fa fa-lock"></i> Wallet Split Coins</button>
            </div>
            <!-- /.col -->

          </div>
        </div>
        <!-- /.card-body -->
      </div>

      <div *ngIf="walletSplitedCoins" class="card card-primary">
        <!-- /.card-header -->
        <div class="card-body">
          <div class="row">
            <table id="appsettingtable" class="table table-striped table- table-bordered">
              <thead>
                <tr>
                  <th>Address</th>
                  <th>Amount</th>
                </tr>
              </thead>
              <tbody>
                <tr *ngFor="let splitCoin of walletSplitedCoins">
                  <td>{{splitCoin.address}}</td>
                  <td>{{splitCoin.amount}}</td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>
        <!-- /.card-body -->
        <div class="card-footer bg-gradient-green">
          Stratis Blockchain.
        </div>
      </div>
      <!-- /.card -->
    </form>
  </div>
</section>

マークアップ

上記のWalletのコード、WalletLoadの出力。

ウォレット残高の出力、

ウォレットスプリットコインの出力、

スマートコントラクトウォレット

同様に、SmartContractWalletから2つのAPIエンドポイントWalletCreateとWalletCallを実装します。エンドポイント:  / api / SmartContractWallet / create ã¯ã€Sctツールから生成されたバイトコードを使用してスマートコントラクトをデプロイするために使用されます。コントラクトの状態を変更する場合は、APIエンドポイント / api / SmartContractWallet/call ã‚’利用できます。前回の記事「 æŠ•ç¥¨å¥‘約」からビジネスケースの使用法を見ることができます。これらのエンドポイントを渡すにはパラメーターが必要なので、両方のエンドポイントのモデルを作成します。

SmartContractWalletCreateとしてモデルを作成します。smartcontractwalletcreate.tsモデルのコードを  ä»¥ä¸‹ã«ç¤ºã—ます。

export class SmartContractWalletCreate {  walletName: string = "";  accountName: string = "";  outpoints: Array<TransactionRequest> = [];  amount: number = 0;  password: string = "";  feeAmount: string = "";  contractCode: string = "";  gasPrice: number = 10000;  gasLimit: number=250000;  sender: string="";  parameters:Array<string>=[];}export class TransactionRequest {  index: number = 0;  transactionId: string = "";}

JavaScript

smartcontractwalletcall.tsのコード ã€

export class SmartContractWalletCall {  walletName: string = "";  accountName: string = "";  outpoints: Array<TransactionRequest> = [];  contractAddress: string = "";  methodName: string = "";  amount: number = 0;  password: string = "";  feeAmount: string = "";  gasPrice: number = 10000;  gasLimit: number = 250000;  sender: string = "";  parameters: Array<string> = [];}export class TransactionRequest {  index: number = 0;  transactionId: string = "";}

JavaScript

その後、角度コマンドに示すように、スマートコントラクトウォレットのサービスとコンポーネントを作成します。

ng g service _service/smartcontractwallet --skip-testsng g component apicollection/smartcontractwallet --skip-tests

バッシュ

SmartcontractwalletServiceのコード:  smartcontractwallet.service.ts。

import { Injectable } from '@angular/core';import { HttpClient } from '@angular/common/http';import { ROOT_URL } from '../../_model/config';@Injectable({  providedIn: 'root'})export class SmartcontractwalletService {  constructor(private http: HttpClient) { }  SmartContractWalletCreate(smartContractWalletCreate: any) {    return this.http.post(ROOT_URL + '/api/SmartContractWallet/create', smartContractWalletCreate);  }  SmartContractWalletCall(smartContractWalletCall: any) {    return this.http.post(ROOT_URL + '/api/SmartContractWallet/call', smartContractWalletCall);  }}

JavaScript

同様に、サービスとモデルをコンポーネントにインポートし、パラメーターを渡してAPIエンドポイントから応答を取得します。

smartcontractwallet.component.tsのコード 

import { Component, OnInit } from '@angular/core';import { SmartContractWalletCreate } from '../../_model/smartcontractwalletcreate';import { SmartcontractwalletService } from '../../_service/stratisfullnode/smartcontractwallet.service';import { HttpParams } from '@angular/common/http';import { SmartContractWalletCall } from '../../_model/smartcontractwalletcall';@Component({  selector: 'app-smartcontractwallet',  templateUrl: './smartcontractwallet.component.html',  styleUrls: ['./smartcontractwallet.component.scss']})export class SmartcontractwalletComponent implements OnInit {  public smartContractWalletCreate: SmartContractWalletCreate = new SmartContractWalletCreate();  public smartContractWalletCall: SmartContractWalletCall = new SmartContractWalletCall();  constructor(private smartcontractwalletService: SmartcontractwalletService) { }  contractOutputTrnHash: any;  smartcontractWalletCallOutput: any;  parameter: string = "";  testparam: null;  ngOnInit(): void {  }  SmartContractWalletCreate() {    this.smartContractWalletCreate.outpoints = [];    this.smartContractWalletCreate.parameters[0] = this.parameter;    if (this.parameter==="null") {      this.smartContractWalletCreate.parameters = [];    }   this.smartcontractwalletService.SmartContractWalletCreate(this.smartContractWalletCreate).subscribe((response: any) => {      console.log(response);      if (response) {        this.contractOutputTrnHash = response;        console.log(this.contractOutputTrnHash);        //  alert('Load Successfully')      } else {        // Swal.fire('Oops...', 'Something went wrong!, Please contact your administrator', 'error');        alert('Oops...');        (error: any) => {          console.log(error);        }      }    });  }  SmartContractWalletCall() {    this.smartContractWalletCall.outpoints = [];    this.smartContractWalletCall.parameters[0] = this.parameter;    if (this.parameter === "null") {      this.smartContractWalletCall.parameters = [];    }       this.smartcontractwalletService.SmartContractWalletCall(this.smartContractWalletCall).subscribe((response: any) => {      console.log(response);      if (response) {        this.smartcontractWalletCallOutput = response;        console.log(this.smartcontractWalletCallOutput);        //  alert('Load Successfully')      } else {        // Swal.fire('Oops...', 'Something went wrong!, Please contact your administrator', 'error');        alert('Oops...');        (error: any) => {          console.log(error);        }      }    });  }}

JavaScript

SmartContractWallet.Component.htmlページのHTML  ãƒšãƒ¼ã‚¸ã€‚

<section class="content-header">
  <div class="container-fluid">
    <div class="row mb-2">
      <div class="col-sm-6">
        <h1>Stratis FullNode APIs </h1>
      </div>
      <div class="col-sm-6">
        <ol class="breadcrumb float-sm-right">
          <!--<li class="breadcrumb-item"><a routerLink="/admin">Wallet</a></li>
          <li class="breadcrumb-item active">Load Wallet</li>-->
        </ol>
      </div>
    </div>
  </div><!-- /.container-fluid -->
</section>
<!--SmartContract Wallet Create-->
<form (ngSubmit)="smartContractWalletCreateForm.form.valid && SmartContractWalletCreate()" #smartContractWalletCreateForm="ngForm">
  <!-- SELECT2 EXAMPLE -->
  <div class="card card-primary card-outline">
    <div class="card-header">
      <h3 class="card-title">Smart Contract Wallet Create</h3>
      <div class="card-tools">
        <button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fas fa-minus"></i></button>
      </div>
    </div>
    <!-- /.card-header -->
    <div class="card-body">
      <div class="row">
        <div class="col-md-4">
          <div class="form-group">
            <label>Wallet Name</label>
            <input type="text" class="form-control" placeholder="Wallet Name" [ngClass]="{ 'is-invalid': smartContractWalletCreateForm.submitted && walletName.invalid }" [(ngModel)]="smartContractWalletCreate.walletName" name="walletName" #walletName="ngModel" required>
            <div class="text-danger" *ngIf="smartContractWalletCreateForm.submitted && walletName.invalid">
              <p *ngIf="walletName.errors?.required">Wallet Name is required</p>
            </div>
          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Account Name</label>
            <input type="text" class="form-control" placeholder="Account Name" [(ngModel)]="smartContractWalletCreate.accountName" name="accountName" #accountName="ngModel" [ngClass]="{ 'is-invalid': smartContractWalletCreateForm.submitted && accountName.invalid }" required>
            <div class="text-danger" *ngIf="smartContractWalletCreateForm.submitted && accountName.invalid">
              <p *ngIf="accountName.errors?.required">Account Name is required</p>
            </div>
          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Password</label>
            <input type="text" class="form-control" placeholder="Password" [(ngModel)]="smartContractWalletCreate.password" name="password" #password="ngModel" [ngClass]="{ 'is-invalid': smartContractWalletCreateForm.submitted && password.invalid }" required>
            <div class="text-danger" *ngIf="smartContractWalletCreateForm.submitted && password.invalid">
              <p *ngIf="password.errors?.required">Wallet Password is required</p>
            </div>
          </div>
        </div>
      </div>
      <div class="row">
        <div class="col-md-4">
          <div class="form-group">
            <label>Amount</label>
            <input type="text" class="form-control" placeholder="Amount" [(ngModel)]="smartContractWalletCreate.amount" name="amount" #amount="ngModel" [ngClass]="{ 'is-invalid': smartContractWalletCreateForm.submitted && amount.invalid }" required>
            <div class="text-danger" *ngIf="smartContractWalletCreateForm.submitted && amount.invalid">
              <p *ngIf="amount.errors?.required">Amount is required</p>
            </div>
          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Outpoints</label>
            <input type="text" class="form-control" placeholder="Outpoints" [(ngModel)]="smartContractWalletCreate.outpoints" name="outpoints" #outpoints="ngModel">
          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Fee Amount</label>
            <input type="text" class="form-control" placeholder="Fee Amount" [(ngModel)]="smartContractWalletCreate.feeAmount" name="feeAmount" #feeAmount="ngModel">
          </div>
        </div>
      </div>

      <div class="row">
        <div class="col-md-4">
          <div class="form-group">
            <label>Contract Code</label>
            <input type="text" class="form-control" placeholder="Contract Code" [(ngModel)]="smartContractWalletCreate.contractCode" name="contractCode" #contractCode="ngModel" [ngClass]="{ 'is-invalid': smartContractWalletCreateForm.submitted && contractCode.invalid }" required>
            <div class="text-danger" *ngIf="smartContractWalletCreateForm.submitted && contractCode.invalid">
              <p *ngIf="contractCode.errors?.required">Contract Code is required</p>
            </div>
          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Gas Price</label>
            <input type="text" class="form-control" placeholder="Gas Price" [(ngModel)]="smartContractWalletCreate.gasPrice" name="gasPrice" #gasPrice="ngModel">

          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Gas Limit</label>
            <input type="text" class="form-control" placeholder="Gas Limit" [(ngModel)]="smartContractWalletCreate.gasLimit" name="gasLimit" #gasLimit="ngModel">
          </div>
        </div>
      </div>

      <div class="row">
        <div class="col-md-4">
          <div class="form-group">
            <label>Sender</label>
            <input type="text" class="form-control" placeholder="Sender" [(ngModel)]="smartContractWalletCreate.sender" name="sender" #sender="ngModel" [ngClass]="{ 'is-invalid': smartContractWalletCreateForm.submitted && sender.invalid }" required>
            <!--<div class="text-danger" *ngIf="smartContractWalletCreateForm.submitted && sender.invalid">
              <p *ngIf="sender.errors?.required">Contract Code is required</p>
            </div>-->
          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Parameters</label>
            <input type="text" class="form-control" placeholder="Parameters" [(ngModel)]="parameter" name="parameters" #parameters="ngModel">
          </div>
        </div>
      </div>

      <div class="row">
        <div class="col-sm-4">
          <button type="submit" class="btn btn-primary"><i class="fa fa-lock"></i> Create Wallet</button>
        </div>
      </div>
      <div *ngIf="contractOutputTrnHash">
        <span>
          <span>Transaction Hash:  </span>  {{contractOutputTrnHash}}
        </span>
      </div>
    </div>
  </div>

</form>

<!--SmartContract Wallet Call-->
<form (ngSubmit)="smartContractWalletCallForm.form.valid && SmartContractWalletCall()" #smartContractWalletCallForm="ngForm">
  <div class="card card-primary card-outline">
    <div class="card-header">
      <h3 class="card-title">Smart Contract Wallet Call</h3>
      <div class="card-tools">
        <button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fas fa-minus"></i></button>
      </div>
    </div>
    <!-- /.card-header -->
    <div class="card-body">
      <div class="row">
        <div class="col-md-4">
          <div class="form-group">
            <label>Wallet Name</label>
            <input type="text" class="form-control" placeholder="Wallet Name" [ngClass]="{ 'is-invalid': smartContractWalletCallForm.submitted && walletName1.invalid }" [(ngModel)]="smartContractWalletCall.walletName" name="walletName1" #walletName1="ngModel" required>
            <div class="text-danger" *ngIf="smartContractWalletCallForm.submitted && walletName1.invalid">
              <p *ngIf="walletName1.errors?.required">Wallet Name is required</p>
            </div>
          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Account Name</label>
            <input type="text" class="form-control" placeholder="Account Name" [(ngModel)]="smartContractWalletCall.accountName" name="accountName1" #accountName1="ngModel" [ngClass]="{ 'is-invalid': smartContractWalletCallForm.submitted && accountName1.invalid }" required>
            <div class="text-danger" *ngIf="smartContractWalletCallForm.submitted && accountName1.invalid">
              <p *ngIf="accountName1.errors?.required">Account Name is required</p>
            </div>
          </div>
        </div>

        <div class="col-md-4">
          <div class="form-group">
            <label>Contract Address</label>
            <input type="text" class="form-control" placeholder="Contract Address" [(ngModel)]="smartContractWalletCall.contractAddress" name="contractAddress" #contractAddress="ngModel" [ngClass]="{ 'is-invalid': smartContractWalletCallForm.submitted && contractAddress.invalid }" required>
            <div class="text-danger" *ngIf="smartContractWalletCallForm.submitted && contractAddress.invalid">
              <p *ngIf="contractAddress.errors?.required">Contract Address is required</p>
            </div>
          </div>
        </div>
      </div>
      <div class="row">
        <div class="col-md-4">
          <div class="form-group">
            <label>Password</label>
            <input type="text" class="form-control" placeholder="Password" [(ngModel)]="smartContractWalletCall.password" name="password1" #password1="ngModel" [ngClass]="{ 'is-invalid': smartContractWalletCallForm.submitted && password1.invalid }" required>
            <div class="text-danger" *ngIf="smartContractWalletCallForm.submitted && password1.invalid">
              <p *ngIf="password1.errors?.required">Wallet Password is required</p>
            </div>
          </div>
        </div>

        <div class="col-md-4">
          <div class="form-group">
            <label>Amount</label>
            <input type="text" class="form-control" placeholder="Amount" [(ngModel)]="smartContractWalletCall.amount" name="amount" #amount="ngModel" [ngClass]="{ 'is-invalid': smartContractWalletCallForm.submitted && amount.invalid }" required>
            <div class="text-danger" *ngIf="smartContractWalletCallForm.submitted && amount.invalid">
              <p *ngIf="amount.errors?.required">Amount is required</p>
            </div>
          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Outpoints</label>
            <input type="text" class="form-control" placeholder="Outpoints" [(ngModel)]="smartContractWalletCall.outpoints" name="outpoints" #outpoints="ngModel">
          </div>
        </div>
      </div>
      <div class="row">
        <div class="col-md-4">
          <div class="form-group">
            <label>Fee Amount</label>
            <input type="text" class="form-control" placeholder="Fee Amount" [(ngModel)]="smartContractWalletCall.feeAmount" name="feeAmount" #feeAmount="ngModel">
          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Gas Price</label>
            <input type="text" class="form-control" placeholder="Gas Price" [(ngModel)]="smartContractWalletCall.gasPrice" name="gasPrice" #gasPrice="ngModel">

          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Gas Limit</label>
            <input type="text" class="form-control" placeholder="Gas Limit" [(ngModel)]="smartContractWalletCall.gasLimit" name="gasLimit" #gasLimit="ngModel">
          </div>
        </div>
      </div>
      <div class="row">
        <div class="col-md-4">
          <div class="form-group">
            <label>Sender</label>
            <input type="text" class="form-control" placeholder="Sender" [(ngModel)]="smartContractWalletCall.sender" name="sender1" #sender1="ngModel" [ngClass]="{ 'is-invalid': smartContractWalletCallForm.submitted && sender1.invalid }" required>
            <div class="text-danger" *ngIf="smartContractWalletCallForm.submitted && sender1.invalid">
              <p *ngIf="sender1.errors?.required">Sender is required</p>
            </div>
          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Method Name</label>
            <input type="text" class="form-control" placeholder="Method Name" [(ngModel)]="smartContractWalletCall.methodName" name="methodName" #methodName="ngModel" [ngClass]="{ 'is-invalid': smartContractWalletCallForm.submitted && methodName.invalid }" required>
            <div class="text-danger" *ngIf="smartContractWalletCallForm.submitted && methodName.invalid">
              <p *ngIf="methodName.errors?.required">Method Name is required</p>
            </div>
          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Parameters</label>
            <input type="text" class="form-control" placeholder="Parameters" [(ngModel)]="parameter" name="parameters" #parameters="ngModel">
          </div>
        </div>
      </div>
      <div class="row">
        <div class="col-sm-4">
          <button type="submit" class="btn btn-primary"><i class="fa fa-lock"></i> Wallet Call</button>
        </div>
        <!-- /.col -->
      </div>
      <div *ngIf="smartcontractWalletCallOutput">
        <h3 class="card-title">Response output</h3><br />
        <span><span class="badge">Fee :</span> {{smartcontractWalletCallOutput.fee}}</span><br />
        <span><span class="badge">Hex:</span>  {{smartcontractWalletCallOutput.hex}}</span><br />
        <span><span class="badge">Message:</span> {{smartcontractWalletCallOutput.message}}</span><br />
        <span><span class="badge">Success:</span>  {{smartcontractWalletCallOutput.success}}</span><br />
        <span><span class="Transaction Id">To:</span>  {{smartcontractWalletCallOutput.transactionId}}</span><br />
      </div>
    </div>
    <!-- /.card-body -->
    <div class="card-footer bg-gradient-green">
      Stratis Blockchain.
    </div>
  </div>
</form>

マークアップ

上記のスマートコントラクトウォレット作成ページの出力。

Amart Contract Wallet Call(エンドポイント:/ api / SmartContractWallet / call)と対話するための出力UI。

スマートコントラクトコンポーネント

SmartContract APIコントローラーから、トランザクションのレシートを提供するエンドポイント API / SmartContracts/receipt ã‚’呼び出します。トランザクションレシートを取得するには、トランザクションハッシュを渡す必要があります。使用ガス、差出人および宛先アドレス、ログなどを含むトランザクションレシートを提供します。さらに、エンドポイント / api / SmartContracts / local-callを統合 ã—て、トランザクションなしで契約付きのローカルコールを作成します。前回の記事で見たように、  å¸‚内通話と契約通話をいつ使用するか。

GetReceiptとLocal-Callのモデルを作成します。

smartcontractreceipt.tsのモデルコード 

export class SmartContractReceipt {  txHash: string = "";}

JavaScript

smartcontractlocalcall.ts ã‚¯ãƒ©ã‚¹ã®ãƒ¢ãƒ‡ãƒ«ã‚³ãƒ¼ãƒ‰ã€‚

export class SmartContractLocalCall {  contractAddress: string = "";  methodName: string = "";  amount: string = "";  gasPrice: number = 10000;  gasLimit: number = 250000;  sender: string = "";  parameters: Array<string> = [];}

JavaScript

スマートコントラクトAPIコントローラーのコンポーネントとサービスを生成します。

ng g service _service/smartcontract --skip-testsng g component apicollection/smartcontract --skip-tests

バッシュ

SmartContractService ã‚¯ãƒ©ã‚¹ã®ã‚³ãƒ¼ãƒ‰ ã€

import { Injectable } from '@angular/core';import { HttpClient } from '@angular/common/http';import { ROOT_URL } from '../../_model/config';@Injectable({  providedIn: 'root'})export class SmartcontractService {  constructor(private http: HttpClient) { }  SmartContractReceipt(params: any) {    return this.http.get(ROOT_URL + '/api/SmartContracts/receipt', { params: params });  }  SmartContractLocalCall(smartContractLocalCall: any) {    return this.http.post(ROOT_URL + '/api/SmartContracts/local-call', smartContractLocalCall);  }}

JavaScript

smartcontract.component.tsのコード ã€

import { Component, OnInit } from '@angular/core';import { SmartContractReceipt } from '../../_model/smartcontractreceipt';import { SmartContractLocalCall } from '../../_model/smartcontractlocalcall';import { SmartcontractService } from '../../_service/stratisfullnode/smartcontract.service';import { HttpParams } from '@angular/common/http';@Component({  selector: 'app-smartcontract',  templateUrl: './smartcontract.component.html',  styleUrls: ['./smartcontract.component.scss']})export class SmartcontractComponent implements OnInit {  public smartContractReceipt: SmartContractReceipt = new SmartContractReceipt();  public smartContractLocalCall: SmartContractLocalCall = new SmartContractLocalCall();  constructor(private smartcontractService: SmartcontractService) { }  resultGetReceipt: any;  parameter: string = "";  localCallResponseOut: any;  ngOnInit(): void {  }  SmartContractReceipt() {    let params = new HttpParams().set("txHash", this.smartContractReceipt.txHash);    this.smartcontractService.SmartContractReceipt(params).subscribe((response: any) => {      if (response) {        this.resultGetReceipt = response;        console.log(this.resultGetReceipt);      } else {        alert('Opps!!!!');        (error: any) => {          console.log(error);        }      }    });  }  SmartContractForLocalCall() {    this.smartContractLocalCall.parameters= [];    this.smartcontractService.SmartContractLocalCall(this.smartContractLocalCall).subscribe((response: any) => {      console.log(response);      if (response) {        this.localCallResponseOut = response;        console.log(this.localCallResponseOut);      } else {        alert('Oops...');        (error: any) => {          console.log(error);        }      }    });  }}

JavaScript

smartcontract.component.htmlのHTML  、

<section class="content-header">
  <div class="container-fluid">
    <div class="row mb-2">
      <div class="col-sm-6">
        <h1>Stratis FullNode APIs </h1>
      </div>
      <div class="col-sm-6">
        <ol class="breadcrumb float-sm-right">
        </ol>
      </div>
    </div>
  </div><!-- /.container-fluid -->
</section>
<!--Get Receipt-->

<form (ngSubmit)="smartcontractGetReceiptForm.form.valid && SmartContractReceipt()" #smartcontractGetReceiptForm="ngForm">
  <!-- SELECT2 EXAMPLE -->
  <div class="card card-primary card-outline">
    <div class="card-header">
      <h3 class="card-title">Smart Contract Receipt</h3>
      <div class="card-tools">
        <button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fas fa-minus"></i></button>
      </div>
    </div>
    <!-- /.card-header -->
    <div class="card-body">
      <div class="row">
        <div class="col-md-12">
          <div class="form-group">
            <label>Transaction Hash </label>
            <input type="text" class="form-control" placeholder="Transaction Hash" [ngClass]="{ 'is-invalid': smartcontractGetReceiptForm.submitted && txHash.invalid }" [(ngModel)]="smartContractReceipt.txHash" name="txHash" #txHash="ngModel" required>
            <div class="text-danger" *ngIf="smartcontractGetReceiptForm.submitted && txHash.invalid">
              <p *ngIf="txHash.errors?.required">Transaction Hash is required</p>
            </div>
          </div>
        </div>
      </div>

      <div class="row">
        <div class="col-sm-4">
          <button type="submit" class="btn btn-primary"><i class="fa fa-lock"></i> Get Receipt</button>
        </div>
        <!-- /.col -->

      </div>

      <!-- /.card-body -->
      <div *ngIf="resultGetReceipt">
        <h3 class="card-title">Response output</h3><br />
        <span><span class="badge">Transaction Hash:</span> {{resultGetReceipt.transactionHash}}</span><br />
        <span><span class="badge">Block Hash:</span>  {{resultGetReceipt.blockHash}}</span><br />
        <span><span class="badge">PostState:</span> {{resultGetReceipt.postState}}</span><br />
        <span><span class="badge">From:</span>  {{resultGetReceipt.from}}</span><br />
        <span><span class="badge">To:</span>  {{resultGetReceipt.to}}</span><br />
        <span><span class="badge">GasUsed:</span>  {{resultGetReceipt.gasUsed}}</span><br />
        <span><span class="badge">New Contract Address:</span> {{resultGetReceipt.newContractAddress}}</span><br />
        <span><span class="badge">Success:</span>  {{resultGetReceipt.success}}</span><br />
        <span><span class="badge">Return Value:</span> {{resultGetReceipt.returnValue}}</span><br />
        <span><span class="badge">Bloom:</span>  {{resultGetReceipt.bloom}}</span><br />
        <span><span class="badge">Error:</span>  {{resultGetReceipt.error}}</span><br />
        <span><span class="badge">Log:</span>  {{resultGetReceipt.logs}}</span><br />
      </div>
    </div>
  </div>

</form>


<form (ngSubmit)="smartcontractLocalCallForm.form.valid && SmartContractForLocalCall()" #smartcontractLocalCallForm="ngForm">
  <!-- SELECT2 EXAMPLE -->
  <div class="card card-primary card-outline">
    <div class="card-header">
      <h3 class="card-title">Smart Contract Local Call</h3>
      <div class="card-tools">
        <button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fas fa-minus"></i></button>
      </div>
    </div>
    <!-- /.card-header -->
    <div class="card-body">
      <div class="row">
        <div class="col-md-4">
          <div class="form-group">
            <label>Contract Address </label>
            <input type="text" class="form-control" placeholder="Contract Address" [ngClass]="{ 'is-invalid': smartcontractLocalCallForm.submitted && contractAddress.invalid }" [(ngModel)]="smartContractLocalCall.contractAddress" name="contractAddress" #contractAddress="ngModel" required>
            <div class="text-danger" *ngIf="smartcontractLocalCallForm.submitted && contractAddress.invalid">
              <p *ngIf="contractAddress.errors?.required">Contract Address is required</p>
            </div>
          </div>
        </div>

        <div class="col-md-4">
          <div class="form-group">
            <label>Method Name </label>
            <input type="text" class="form-control" placeholder="Method Name" [ngClass]="{ 'is-invalid': smartcontractLocalCallForm.submitted && methodName.invalid }" [(ngModel)]="smartContractLocalCall.methodName" name="methodName" #methodName="ngModel" required>
            <div class="text-danger" *ngIf="smartcontractLocalCallForm.submitted && methodName.invalid">
              <p *ngIf="methodName.errors?.required">Method Name is required</p>
            </div>
          </div>
        </div>

        <div class="col-md-4">
          <div class="form-group">
            <label>Amount</label>
            <input type="text" class="form-control" placeholder="Amount" [(ngModel)]="smartContractLocalCall.amount" name="amount" #amount="ngModel" [ngClass]="{ 'is-invalid': smartcontractLocalCallForm.submitted && amount.invalid }" required>

          </div>
        </div>
      </div>
      <div class="row">
        <div class="col-md-4">
          <div class="form-group">
            <label>Gas Price</label>
            <input type="text" class="form-control" placeholder="Gas Price" [(ngModel)]="smartContractLocalCall.gasPrice" name="gasPrice" #gasPrice="ngModel">

          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Gas Limit</label>
            <input type="text" class="form-control" placeholder="Gas Limit" [(ngModel)]="smartContractLocalCall.gasLimit" name="gasLimit" #gasLimit="ngModel">
          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Sender</label>
            <input type="text" class="form-control" placeholder="Sender" [(ngModel)]="smartContractLocalCall.sender" name="sender" #sender="ngModel">

          </div>
        </div>
      </div>
      <div class="row">
        <div class="col-md-4">
          <div class="form-group">
            <label>Parameters</label>
            <input type="text" class="form-control" placeholder="Parameters" [(ngModel)]="parameter" name="parameters" #parameters="ngModel">
          </div>
        </div>
      </div>

      <div class="row">
        <div class="col-sm-4">
          <button type="submit" class="btn btn-primary"><i class="fa fa-lock"></i> Make Local Call</button>
        </div>
      </div>

      <!-- /.card-body -->
      <div *ngIf="localCallResponseOut">
        <h3 class="card-title">Response output</h3><br />
        <span><span class="badge">Internal Transfer:</span>  {{localCallResponseOut.internalTransfers}}</span><br />
        <span><span class="badge">GasConsumed Value:</span> {{localCallResponseOut.gasConsumed.value}}</span><br />
        <span><span class="badge">Revert:</span>  {{localCallResponseOut.revert}}</span><br />
        <span><span class="badge">Error Message:</span>  {{localCallResponseOut.errorMessage}}</span><br />
        <span><span class="badge">Return:</span>  {{localCallResponseOut.return}}</span><br />
        <span><span class="badge">Log:</span>  {{localCallResponseOut.logs}}</span><br />
      </div>
    </div>
  </div>
  <div class="card-footer bg-gradient-green">
    Stratis Blockchain.
  </div>
  <!-- /.card -->
</form>

マークアップ

スマートコントラクトの出力レシートUIを取得します。

スマートコントラクト市内通話UI。

概要

したがって、StratisAPIを任意のカスタムアプリケーションに統合できます。この記事では、スマートコントラクトをデプロイできる独自のアプリケーションにStratisプライベートブロックチェーンを実装しました。さらに、記事では、APIの取得、投稿、応答モデルを管理し、サービス、APIのモデルを分離する方法を示しています。この記事では、入力および応答形式の出力を使用してStartisAPIを検証するためのユーザーインターフェイスを備えたコンポーネントを開発するための完全な手順について説明しました。さらに、これからアイデアを得て、アプリケーションのニーズに基づいて、任意のAPIエンドポイントをStratisBlockchainをカスタムアプリケーションに統合できます。リポジトリから取得できる完全なデモンストレーション用のAngularアプリケーションを開発しました ã€‚ 

ソース:https ://www.c-sharpcorner.com/article/integrate-stratis-blockchain-apis-in-your-custom-application/ 

#smartcontract #blockchain 

Integrate Stratis Blockchain APIs In Your Custom Application

In this article, I will elucidate how to integrate Stratis Blockchain API in custom or third-party applications. We will create an angular application and integrate Stratis Private APIs. We will interact with Stratis Blockchain APIs and show the response in the custom application. Additionally, this article will describe creating a user interface to deploy the Smart Contract. This write-up explains and provides the code for all endpoints necessary for deploying the Smart Contract; however, you can get ideas and interact with any other endpoints according to your custom software requirement. For more details on how to write Smart Contract and generate byte code, you can visit here.

The source code is available here.

Prerequisites

  • IDE for Angular (Visual Studio or Visual Studio Code) as per you
  • Stratis FullNode
  • Smart Contract Byte Code

For this article, we will be using angular 12, however, it will be the same for another version as well.

Create Angular Application

We will create an angular application with angular CLI as shown below steps,

Install Angular CLI ( if you don’t have it).

npm install -g @angular/cli

Bash

We will create a new app with the following command,

ng new StratisFullNodeWebApp

JavaScript

We will navigate to the project folder and run the application. To build and run the angular application we use the serve command as shown.

cd StratisFullNodeWebApp
ng serve

Bash

Alternatively, to open the default Angular Application: Run below command which builds, run and open at once.

ng serve --open

Bash

The –open command opens a project to the browser at http://localhost:4200/To design lucrative UI, I have implemented the AdminLTE theme. If you want, you can also implement it following steps from here.

Create and Add Model in Angular App

Create _model folder where we will keep all the models for each component.

We can add the model using the command and also manually as described below: In _model folder right-click–> add a new item –> Add typescript File and rename it according to your structure.

Let’s Add the config.ts file under the model. Where we can keep all the configuration-related information and it will be easy to maintain the configuration-related information from one place. I am creating this to put the root/base URL of API which we call in any services or components. Sample config.ts code,

export const ROOT_URL: string = "http://localhost:38223";

JavaScript

We will integrate the Full Node APIs running at localhost: http://localhost:38223.

I have assumed that you have FullNode already. If you don’t have you can download it from here. Open the project and run the Stratis.CirrusMinerD project in devmode. You can use the below command to run FullNode.

cd StratisFullNode\src\Stratis.CirrusMinerD
dotnet run -devmode=miner

Bash

Open http://localhost:38223/swagger/index.html in your browser and you can see a list of APIs.

Integrate Stratis Blockchain APIs in Your Custom Application

Wallet Component

To integrate the wallet, we will create a wallet service and wallet component. Run the below command to generate service and components for the wallet.

ng g service _service/stratisfullnode/wallet
ng g component apicollection/wallet

Bash

In this article, we will implement 3 endpoints from wallet API, however, the implementations of other API(s) will be similar. From the Wallet API Controller, we will call 3 endpoints: Wallet Load, Wallet balance, and WalletSplitcoins.

Endpoint: /api/Wallet/load: Wallet Load is to make sure the private chain is running smoothly and your app is connected with the chain.

Use the below credential for Wallet Load after the complete design.

ParametersValue
Namecirrusdev
Passwordpassword

Endpoint:/api/Wallet/balance: It gives the lists of Wallet addresses, amounts, etc. We need a wallet address having a balance on it to deploy the Smart Contract.

Endpoint: /api/Wallet/splitcoins: It creates the requested amount of equal value and gives the list of addresses with balance. If you get one address having balance and need more addresses, then you can use this to split balance and get more addresses with balance.

To handle API posts and responses easily, it is better to create a model for each of them. Likewise, we will create models for WalletLoad, WalletBalance, and WalletSplitcoins. In order to wallet Load, we have to pass parameters: name and password. Therefore, we will create a model walletload with name and password properties.

Code of walletload.ts model is given below,

export class WalletLoad {
  name: string = "";
  password: string = "";
}

JavaScript

Similarly, we will create a model for Walletbalance. Code of walletbalance.ts model is,

export class WalletBalance {
  walletname: string = "";
  accountname: string = "";
  includebalancebyaddress: boolean=false;
}

JavaScript

As above, we will create a model For WalletCoinSplit. Code for waletsplitcoin.ts is given below,

export class WalletSplitCoin {
  walletName: string = "";
  accountName: string = "";
  walletPassword: string = "";
  totalAmountToSplit: number = 1;
  utxosCount: number = 1;
}

JavaScript

Wallet Service

Now, we will create a service class for wallet API(s) as wallet.services.ts. We will import the Root URL from config and use the base URL to call API endpoints. From the Stratis FullNode swagger page, we can see WalletLoad is post method that needs parameters name and password. Similarly, WalletSplitCoin is also a post, and WalletBalance is a get method with parameters. So, we can write code and pass parameters accordingly.

Here, we will create creating three methods in this services as shown,

Below is the code of wallet.services.ts class for those API endpoints.

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { ROOT_URL } from '../../_model/config';
@Injectable({
  providedIn: 'root'
})
export class WalletService {

  constructor(private http: HttpClient) { }

  LoadWallet(login:any) {
    return this.http.post(ROOT_URL + '/api/Wallet/load', login, { observe: 'response' });
  }
  WalletBalance(params:any) {
    return this.http.get(ROOT_URL + '/api/Wallet/balance', { params: params });
  }

  WalletSplitCoins(walletSplitCoin: any) {
    return this.http.post(ROOT_URL + '/api/Wallet/splitcoins', walletSplitCoin);
  }
}

JavaScript

We need HttpClient for the http requests so import HttpClient in-app-module.ts as depicted below, if it is not available there, and face an error with it.

Integrate Stratis Blockchain APIs in Your Custom Application

Wallet Component

Now we will import Wallet Service, all Wallet-related models, and call methods of service in wallet.component.ts and pass parameters using model respectively.

Code of wallet.component.ts

import { Component, OnInit } from '@angular/core';
import { WalletLoad } from '../../_model/walletload';
import { WalletService } from '../../_service/stratisfullnode/wallet.service';
import { WalletBalance } from '../../_model/walletbalance';
import { WalletSplitCoin } from '../../_model/walletsplitcoins';
import { HttpParams } from '@angular/common/http';
import Swal from 'sweetalert2';

@Component({
  selector: 'app-wallet',
  templateUrl: './wallet.component.html',
  styleUrls: ['./wallet.component.scss']
})
export class WalletComponent implements OnInit {
  public login: WalletLoad = new WalletLoad();
  public walletbalance: WalletBalance = new WalletBalance();
  public walletSplitCoin: WalletSplitCoin = new WalletSplitCoin();
  isConnected: boolean = false;
  walletInfos: any;
  walletbalances: any;
  walletSplitedCoins: any;
  constructor( private stratisFullNode: WalletService ) { }

  IncludeBalanceByAddress: any = ['true', 'false']

  ngOnInit(): void {
    this.LoadWallet();
  }
  LoadWallet() {
    this.stratisFullNode.LoadWallet(this.login).subscribe((response: any) => {
      console.log(response);
      if (response.ok) {
        this.isConnected = true;
      //  console.log(response);
        Swal.fire('Successful', 'Full Node Connection successful', 'info');
      } else {
       Swal.fire('Oops...', 'Something went wrong!, Please contact your administrator', 'error');
        //alert('Oops...');
        (error: any) => {
          console.log(error);
        }
      }
    });
  }
  WalletBalance() {
    let params = new HttpParams().set("WalletName", this.walletbalance.walletname).set("AccountName", this.walletbalance.accountname).set("IncludeBalanceByAddress", this.walletbalance.includebalancebyaddress);
    this.stratisFullNode.WalletBalance(params).subscribe((response: any) => {
      if (response.balances) {
        this.walletbalances = response.balances;
        //console.log(data);
        console.log(this.walletbalances);
      } else {
      //  Swal.fire('Oops...', 'Something went wrong!, Please contact your administrator', 'error');
        alert('Opps!!!!');
        (error: any) => {
          console.log(error);
        }
      }
    });
  }
  WalletAplitCoins() {
    this.stratisFullNode.WalletSplitCoins(this.walletSplitCoin).subscribe((response: any) => {
      console.log(response);
      if (response.outputs) {
        this.walletSplitedCoins = response.outputs;
        console.log(this.walletSplitedCoins);
        //  alert('Load Successfully')
      } else {
        alert('Oops...');
        (error: any) => {
          console.log(error);
        }
      }
    });
  }
}

JavaScript

For routing, please refer to the app-routing.module.ts from source code. After addition of each component we can add it to this app-routing.module.ts.

Wallet Component Html

In wallet.component.html, we will design forms to pass parameters as user input. It needs one form and submits button for each endpoint. When it gets the response, we are showing the response results just below the submit button. Here is the complete code for wallet.component.html page.

<section class="content-header">
  <div class="container-fluid">
    <div class="row mb-2">
      <div class="col-sm-6">
        <h1>Stratis FullNode APIs </h1>
      </div>
      <div class="col-sm-6">
        <ol class="breadcrumb float-sm-right">
          <li class="breadcrumb-item"><a routerLink="/admin">Wallet</a></li>
          <li class="breadcrumb-item active">Load Wallet</li>
        </ol>
      </div>
    </div>
  </div><!-- /.container-fluid -->
</section>
<!-- Main content -->
<section class="content">
  <div class="container-fluid">
     <form (ngSubmit)="walletLoadForm.form.valid && LoadWallet()" #walletLoadForm="ngForm">
      <div class="card card-primary card-outline">
        <div class="card-header">
          <h3 class="card-title">Wallet Load</h3>
          <div class="card-tools">
            <button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fas fa-minus"></i></button>
          </div>
        </div>
        <!-- /.card-header -->
        <div class="card-body">
          <div class="row">
            <div class="col-md-6">
              <div class="form-group">
                <label>Name</label>
                <input type="text" class="form-control" placeholder="Name" [ngClass]="{ 'is-invalid': walletLoadForm.submitted && name.invalid }" [(ngModel)]="login.name" name="name" #name="ngModel" required>
                <div class="text-danger" *ngIf="walletLoadForm.submitted && name.invalid">
                  <p *ngIf="name.errors?.required">Name is required</p>
                </div>
              </div>
            </div>
            <div class="col-md-6">
              <div class="form-group">
                <label>Password</label>
                <input type="text" class="form-control" placeholder="Password" [(ngModel)]="login.password" name="type" #type="ngModel" [ngClass]="{ 'is-invalid': walletLoadForm.submitted && type.invalid }" required>
                <div class="text-danger" *ngIf="walletLoadForm.submitted && type.invalid">
                  <p *ngIf="type.errors?.required">Password is required</p>
                </div>
              </div>
            </div>

            <div class="col-sm-2">
              <button type="submit" class="btn btn-primary"><i class="fa fa-lock"></i> Load Wallet</button>
            </div>
            <!-- /.col -->
            <div class="col-sm-6" *ngIf="isConnected">
              <span class="badge badge-success float-sm-right"> Full Node Connection Successful</span>
            </div>
          </div>
        </div>
        <!-- /.card-body -->
      </div>
    </form>
    <!--Wallet Balance-->
    <form (ngSubmit)="walletBalanceForm.form.valid && WalletBalance()" #walletBalanceForm="ngForm">
      <!-- SELECT2 EXAMPLE -->
      <div class="card card-primary card-outline">
        <div class="card-header">
          <h3 class="card-title">Wallet Balance</h3>
          <div class="card-tools">
            <button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fas fa-minus"></i></button>
          </div>
        </div>
        <!-- /.card-header -->
        <div class="card-body">
          <div class="row">
            <div class="col-md-4">
              <div class="form-group">
                <label>Wallet Name</label>
                <input type="text" class="form-control" placeholder="Wallet Name" [ngClass]="{ 'is-invalid': walletBalanceForm.submitted && walletname.invalid }" [(ngModel)]="walletbalance.walletname" name="walletname" #walletname="ngModel" required>
                <div class="text-danger" *ngIf="walletBalanceForm.submitted && name.invalid">
                  <p *ngIf="walletname.errors?.required">Wallet Name is required</p>
                </div>
              </div>
            </div>
            <div class="col-md-4">
              <div class="form-group">
                <label>Account Name</label>
                <input type="text" class="form-control" placeholder="Account Name" [(ngModel)]="walletbalance.accountname" name="accountname" #accountname="ngModel" [ngClass]="{ 'is-invalid': walletBalanceForm.submitted && accountname.invalid }" required>
                <div class="text-danger" *ngIf="walletBalanceForm.submitted && accountname.invalid">
                  <p *ngIf="accountname.errors?.required">Account Name is required</p>
                </div>
              </div>
            </div>
            <div class="col-sm-4">
              <label for="includebalancebyaddress">IncludeBalanceByAddress</label>
              <select class="custom-select" [(ngModel)]="walletbalance.includebalancebyaddress" name="includebalancebyaddress">
                <option *ngFor="let includebalance of IncludeBalanceByAddress" [ngValue]="includebalance">{{includebalance}}</option>
              </select>
            </div>
          </div>
          <div>

          </div>
          <div class="row">
            <div class="col-sm-4">
              <button type="submit" class="btn btn-primary"><i class="fa fa-lock"></i> Load Wallet Balance</button>
            </div>
            <!-- /.col -->

          </div>
          <div *ngIf="walletbalances" class="card card-primary">
            <div class="card-body">
              <div class="row">
                <table id="appsettingtable" class="table table-striped table- table-bordered">
                  <thead>
                    <tr>
                      <th>Account Name</th>
                      <th>Path</th>
                      <th>CoinType</th>
                      <th>AmountConfirmed</th>
                      <th>Modified by</th>
                      <th>SpendableAmount </th>
                    </tr>
                  </thead>
                  <tbody>
                    <tr *ngFor="let balance of walletbalances">
                      <td>{{balance.accountName}}</td>
                      <td>{{balance.accountHdPath}}</td>
                      <td>{{balance.coinType}}</td>
                      <td>{{balance.amountConfirmed}}</td>
                      <td>{{balance.amountUnconfirmed}}</td>
                      <td>
                        {{balance.spendableAmount}}
                      </td>
                    </tr>
                  </tbody>
                </table>
              </div>
            </div>
            <!-- /.card-header -->
            <h3 class="card-title">List of Addresses</h3>
            <div *ngFor="let balance of walletbalances">
              <div *ngFor="let add of balance.addresses">
                <span><span class="badge">Address:</span>  {{add.address}}</span>
                <span><span class="badge">IsUsed:</span>  {{add.isUsed}}</span>
                <span><span class="badge">IsChange:</span>  {{add.isChange}}</span>
                <span><span class="badge">Amount Confirmed:</span>  {{add.amountConfirmed}}</span>
                <span><span class="badge">Amount Unconfirmed:</span>  {{add.amountUnconfirmed}}</span>
              </div>

            </div>
          </div>
        </div>
        <!-- /.card-body -->
      </div>

    </form>

    <!--Wallet Split Coins-->
    <form (ngSubmit)="walletSplitCoinForm.form.valid && WalletAplitCoins()" #walletSplitCoinForm="ngForm">
      <!-- SELECT2 EXAMPLE -->
      <div class="card card-primary card-outline">
        <div class="card-header">
          <h3 class="card-title">Wallet Split Coins</h3>
          <div class="card-tools">
            <button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fas fa-minus"></i></button>
          </div>
        </div>
        <!-- /.card-header -->
        <div class="card-body">
          <div class="row">
            <div class="col-md-4">
              <div class="form-group">
                <label>Wallet Name</label>
                <input type="text" class="form-control" placeholder="Wallet Name" [ngClass]="{ 'is-invalid': walletSplitCoinForm.submitted && walletNameSplitCoin.invalid }" [(ngModel)]="walletSplitCoin.walletName" name="walletName" #walletNameSplitCoin="ngModel" required>
                <div class="text-danger" *ngIf="walletSplitCoinForm.submitted && walletNameSplitCoin.invalid">
                  <p *ngIf="walletNameSplitCoin.errors?.required">Wallet Name is required</p>
                </div>
              </div>
            </div>
            <div class="col-md-4">
              <div class="form-group">
                <label>Account Name</label>
                <input type="text" class="form-control" placeholder="Account Name" [(ngModel)]="walletSplitCoin.accountName" name="accountName" #accountNameSplitCoin="ngModel" [ngClass]="{ 'is-invalid': walletSplitCoinForm.submitted && accountNameSplitCoin.invalid }" required>
                <div class="text-danger" *ngIf="walletSplitCoinForm.submitted && accountNameSplitCoin.invalid">
                  <p *ngIf="accountNameSplitCoin.errors?.required">Account Name is required</p>
                </div>
              </div>
            </div>
            <div class="col-md-4">
              <div class="form-group">
                <label>Wallet Password</label>
                <input type="text" class="form-control" placeholder="Wallet Password" [(ngModel)]="walletSplitCoin.walletPassword" name="walletPassword" #walletpassword="ngModel" [ngClass]="{ 'is-invalid': walletSplitCoinForm.submitted && walletpassword.invalid }" required>
                <div class="text-danger" *ngIf="walletSplitCoinForm.submitted && walletpassword.invalid">
                  <p *ngIf="walletpassword.errors?.required">Wallet Password is required</p>
                </div>
              </div>
            </div>
          </div>
          <div class="row">
            <div class="col-md-4">
              <div class="form-group">
                <label>Amount to Split</label>
                <input type="text" class="form-control" placeholder="No of Aplit" [(ngModel)]="walletSplitCoin.totalAmountToSplit" name="totalAmountToSplit" #totalAmountToSplit="ngModel" [ngClass]="{ 'is-invalid': walletSplitCoinForm.submitted && totalAmountToSplit.invalid }" required>
                <div class="text-danger" *ngIf="walletSplitCoinForm.submitted && totalAmountToSplit.invalid">
                  <p *ngIf="totalAmountToSplit.errors?.required">No of Split is required</p>
                </div>
              </div>
            </div>
            <div class="col-md-4">
              <div class="form-group">
                <label>No of Split</label>
                <input type="text" class="form-control" placeholder="No of Aplit" [(ngModel)]="walletSplitCoin.utxosCount" name="utxosCount" #utxosCount="ngModel" [ngClass]="{ 'is-invalid': walletSplitCoinForm.submitted && utxosCount.invalid }" required>
                <div class="text-danger" *ngIf="walletSplitCoinForm.submitted && utxosCount.invalid">
                  <p *ngIf="utxosCount.errors?.required">No of Split is required</p>
                </div>
              </div>
            </div>
          </div>
          <div class="row">
            <div class="col-sm-4">
              <button type="submit" class="btn btn-primary"><i class="fa fa-lock"></i> Wallet Split Coins</button>
            </div>
            <!-- /.col -->

          </div>
        </div>
        <!-- /.card-body -->
      </div>

      <div *ngIf="walletSplitedCoins" class="card card-primary">
        <!-- /.card-header -->
        <div class="card-body">
          <div class="row">
            <table id="appsettingtable" class="table table-striped table- table-bordered">
              <thead>
                <tr>
                  <th>Address</th>
                  <th>Amount</th>
                </tr>
              </thead>
              <tbody>
                <tr *ngFor="let splitCoin of walletSplitedCoins">
                  <td>{{splitCoin.address}}</td>
                  <td>{{splitCoin.amount}}</td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>
        <!-- /.card-body -->
        <div class="card-footer bg-gradient-green">
          Stratis Blockchain.
        </div>
      </div>
      <!-- /.card -->
    </form>
  </div>
</section>

Markup

The output of above code of Wallet, Wallet Load.

The output of Wallet Balance,

The output of Wallet Split Coin,

Smart Contract Wallet

Similarly, we will implement two API endpoints from SmartContractWallet: WalletCreate and WalletCall. Endpoint: /api/SmartContractWallet/create is used to deploy the Smart Contract using the Bytecode generated from the Sct tool. If we want to change the state of the contract, API endpoint /api/SmartContractWallet/call can be utilized. You can see business case use of it from the previous article Voting Contract. These endpoints need parameters to pass, So we will create a model for both endpoints.

Create model as SmartContractWalletCreate. Code of smartcontractwalletcreate.ts model is given below,

export class SmartContractWalletCreate {
  walletName: string = "";
  accountName: string = "";
  outpoints: Array<TransactionRequest> = [];
  amount: number = 0;
  password: string = "";
  feeAmount: string = "";
  contractCode: string = "";
  gasPrice: number = 10000;
  gasLimit: number=250000;
  sender: string="";

  parameters:Array<string>=[];
}
export class TransactionRequest {
  index: number = 0;
  transactionId: string = "";
}

JavaScript

Code for smartcontractwalletcall.ts,

export class SmartContractWalletCall {
  walletName: string = "";
  accountName: string = "";
  outpoints: Array<TransactionRequest> = [];
  contractAddress: string = "";
  methodName: string = "";
  amount: number = 0;
  password: string = "";
  feeAmount: string = "";
  gasPrice: number = 10000;
  gasLimit: number = 250000;
  sender: string = "";

  parameters: Array<string> = [];
}
export class TransactionRequest {
  index: number = 0;
  transactionId: string = "";
}

JavaScript

After that, we will create Service and Component for Smart Contract Wallet as shown in angular commands.

ng g service _service/smartcontractwallet --skip-tests
ng g component apicollection/smartcontractwallet --skip-tests

Bash

Code for SmartcontractwalletService: smartcontractwallet.service.ts.

import { Injectable } from '@angular/core';

import { HttpClient } from '@angular/common/http';
import { ROOT_URL } from '../../_model/config';

@Injectable({
  providedIn: 'root'
})
export class SmartcontractwalletService {

  constructor(private http: HttpClient) { }

  SmartContractWalletCreate(smartContractWalletCreate: any) {
    return this.http.post(ROOT_URL + '/api/SmartContractWallet/create', smartContractWalletCreate);
  }

  SmartContractWalletCall(smartContractWalletCall: any) {
    return this.http.post(ROOT_URL + '/api/SmartContractWallet/call', smartContractWalletCall);
  }
}

JavaScript

Similarly, we will import Service and model in component and pass parameters to get responses from API endpoints.

Code for smartcontractwallet.component.ts

import { Component, OnInit } from '@angular/core';
import { SmartContractWalletCreate } from '../../_model/smartcontractwalletcreate';
import { SmartcontractwalletService } from '../../_service/stratisfullnode/smartcontractwallet.service';
import { HttpParams } from '@angular/common/http';
import { SmartContractWalletCall } from '../../_model/smartcontractwalletcall';
@Component({
  selector: 'app-smartcontractwallet',
  templateUrl: './smartcontractwallet.component.html',
  styleUrls: ['./smartcontractwallet.component.scss']
})
export class SmartcontractwalletComponent implements OnInit {

  public smartContractWalletCreate: SmartContractWalletCreate = new SmartContractWalletCreate();
  public smartContractWalletCall: SmartContractWalletCall = new SmartContractWalletCall();
  constructor(private smartcontractwalletService: SmartcontractwalletService) { }
  contractOutputTrnHash: any;
  smartcontractWalletCallOutput: any;
  parameter: string = "";
  testparam: null;
  ngOnInit(): void {

  }
  SmartContractWalletCreate() {
    this.smartContractWalletCreate.outpoints = [];
    this.smartContractWalletCreate.parameters[0] = this.parameter;
    if (this.parameter==="null") {
      this.smartContractWalletCreate.parameters = [];
    }
   this.smartcontractwalletService.SmartContractWalletCreate(this.smartContractWalletCreate).subscribe((response: any) => {
      console.log(response);
      if (response) {
        this.contractOutputTrnHash = response;
        console.log(this.contractOutputTrnHash);
        //  alert('Load Successfully')
      } else {
        // Swal.fire('Oops...', 'Something went wrong!, Please contact your administrator', 'error');
        alert('Oops...');
        (error: any) => {
          console.log(error);
        }
      }
    });
  }


  SmartContractWalletCall() {
    this.smartContractWalletCall.outpoints = [];
    this.smartContractWalletCall.parameters[0] = this.parameter;
    if (this.parameter === "null") {
      this.smartContractWalletCall.parameters = [];
    }
       this.smartcontractwalletService.SmartContractWalletCall(this.smartContractWalletCall).subscribe((response: any) => {
      console.log(response);
      if (response) {
        this.smartcontractWalletCallOutput = response;
        console.log(this.smartcontractWalletCallOutput);
        //  alert('Load Successfully')
      } else {
        // Swal.fire('Oops...', 'Something went wrong!, Please contact your administrator', 'error');
        alert('Oops...');
        (error: any) => {
          console.log(error);
        }
      }
    });
  }
}

JavaScript

HTML page of SmartContractWallet.Component.html page.

<section class="content-header">
  <div class="container-fluid">
    <div class="row mb-2">
      <div class="col-sm-6">
        <h1>Stratis FullNode APIs </h1>
      </div>
      <div class="col-sm-6">
        <ol class="breadcrumb float-sm-right">
          <!--<li class="breadcrumb-item"><a routerLink="/admin">Wallet</a></li>
          <li class="breadcrumb-item active">Load Wallet</li>-->
        </ol>
      </div>
    </div>
  </div><!-- /.container-fluid -->
</section>
<!--SmartContract Wallet Create-->
<form (ngSubmit)="smartContractWalletCreateForm.form.valid && SmartContractWalletCreate()" #smartContractWalletCreateForm="ngForm">
  <!-- SELECT2 EXAMPLE -->
  <div class="card card-primary card-outline">
    <div class="card-header">
      <h3 class="card-title">Smart Contract Wallet Create</h3>
      <div class="card-tools">
        <button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fas fa-minus"></i></button>
      </div>
    </div>
    <!-- /.card-header -->
    <div class="card-body">
      <div class="row">
        <div class="col-md-4">
          <div class="form-group">
            <label>Wallet Name</label>
            <input type="text" class="form-control" placeholder="Wallet Name" [ngClass]="{ 'is-invalid': smartContractWalletCreateForm.submitted && walletName.invalid }" [(ngModel)]="smartContractWalletCreate.walletName" name="walletName" #walletName="ngModel" required>
            <div class="text-danger" *ngIf="smartContractWalletCreateForm.submitted && walletName.invalid">
              <p *ngIf="walletName.errors?.required">Wallet Name is required</p>
            </div>
          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Account Name</label>
            <input type="text" class="form-control" placeholder="Account Name" [(ngModel)]="smartContractWalletCreate.accountName" name="accountName" #accountName="ngModel" [ngClass]="{ 'is-invalid': smartContractWalletCreateForm.submitted && accountName.invalid }" required>
            <div class="text-danger" *ngIf="smartContractWalletCreateForm.submitted && accountName.invalid">
              <p *ngIf="accountName.errors?.required">Account Name is required</p>
            </div>
          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Password</label>
            <input type="text" class="form-control" placeholder="Password" [(ngModel)]="smartContractWalletCreate.password" name="password" #password="ngModel" [ngClass]="{ 'is-invalid': smartContractWalletCreateForm.submitted && password.invalid }" required>
            <div class="text-danger" *ngIf="smartContractWalletCreateForm.submitted && password.invalid">
              <p *ngIf="password.errors?.required">Wallet Password is required</p>
            </div>
          </div>
        </div>
      </div>
      <div class="row">
        <div class="col-md-4">
          <div class="form-group">
            <label>Amount</label>
            <input type="text" class="form-control" placeholder="Amount" [(ngModel)]="smartContractWalletCreate.amount" name="amount" #amount="ngModel" [ngClass]="{ 'is-invalid': smartContractWalletCreateForm.submitted && amount.invalid }" required>
            <div class="text-danger" *ngIf="smartContractWalletCreateForm.submitted && amount.invalid">
              <p *ngIf="amount.errors?.required">Amount is required</p>
            </div>
          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Outpoints</label>
            <input type="text" class="form-control" placeholder="Outpoints" [(ngModel)]="smartContractWalletCreate.outpoints" name="outpoints" #outpoints="ngModel">
          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Fee Amount</label>
            <input type="text" class="form-control" placeholder="Fee Amount" [(ngModel)]="smartContractWalletCreate.feeAmount" name="feeAmount" #feeAmount="ngModel">
          </div>
        </div>
      </div>

      <div class="row">
        <div class="col-md-4">
          <div class="form-group">
            <label>Contract Code</label>
            <input type="text" class="form-control" placeholder="Contract Code" [(ngModel)]="smartContractWalletCreate.contractCode" name="contractCode" #contractCode="ngModel" [ngClass]="{ 'is-invalid': smartContractWalletCreateForm.submitted && contractCode.invalid }" required>
            <div class="text-danger" *ngIf="smartContractWalletCreateForm.submitted && contractCode.invalid">
              <p *ngIf="contractCode.errors?.required">Contract Code is required</p>
            </div>
          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Gas Price</label>
            <input type="text" class="form-control" placeholder="Gas Price" [(ngModel)]="smartContractWalletCreate.gasPrice" name="gasPrice" #gasPrice="ngModel">

          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Gas Limit</label>
            <input type="text" class="form-control" placeholder="Gas Limit" [(ngModel)]="smartContractWalletCreate.gasLimit" name="gasLimit" #gasLimit="ngModel">
          </div>
        </div>
      </div>

      <div class="row">
        <div class="col-md-4">
          <div class="form-group">
            <label>Sender</label>
            <input type="text" class="form-control" placeholder="Sender" [(ngModel)]="smartContractWalletCreate.sender" name="sender" #sender="ngModel" [ngClass]="{ 'is-invalid': smartContractWalletCreateForm.submitted && sender.invalid }" required>
            <!--<div class="text-danger" *ngIf="smartContractWalletCreateForm.submitted && sender.invalid">
              <p *ngIf="sender.errors?.required">Contract Code is required</p>
            </div>-->
          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Parameters</label>
            <input type="text" class="form-control" placeholder="Parameters" [(ngModel)]="parameter" name="parameters" #parameters="ngModel">
          </div>
        </div>
      </div>

      <div class="row">
        <div class="col-sm-4">
          <button type="submit" class="btn btn-primary"><i class="fa fa-lock"></i> Create Wallet</button>
        </div>
      </div>
      <div *ngIf="contractOutputTrnHash">
        <span>
          <span>Transaction Hash:  </span>  {{contractOutputTrnHash}}
        </span>
      </div>
    </div>
  </div>

</form>

<!--SmartContract Wallet Call-->
<form (ngSubmit)="smartContractWalletCallForm.form.valid && SmartContractWalletCall()" #smartContractWalletCallForm="ngForm">
  <div class="card card-primary card-outline">
    <div class="card-header">
      <h3 class="card-title">Smart Contract Wallet Call</h3>
      <div class="card-tools">
        <button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fas fa-minus"></i></button>
      </div>
    </div>
    <!-- /.card-header -->
    <div class="card-body">
      <div class="row">
        <div class="col-md-4">
          <div class="form-group">
            <label>Wallet Name</label>
            <input type="text" class="form-control" placeholder="Wallet Name" [ngClass]="{ 'is-invalid': smartContractWalletCallForm.submitted && walletName1.invalid }" [(ngModel)]="smartContractWalletCall.walletName" name="walletName1" #walletName1="ngModel" required>
            <div class="text-danger" *ngIf="smartContractWalletCallForm.submitted && walletName1.invalid">
              <p *ngIf="walletName1.errors?.required">Wallet Name is required</p>
            </div>
          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Account Name</label>
            <input type="text" class="form-control" placeholder="Account Name" [(ngModel)]="smartContractWalletCall.accountName" name="accountName1" #accountName1="ngModel" [ngClass]="{ 'is-invalid': smartContractWalletCallForm.submitted && accountName1.invalid }" required>
            <div class="text-danger" *ngIf="smartContractWalletCallForm.submitted && accountName1.invalid">
              <p *ngIf="accountName1.errors?.required">Account Name is required</p>
            </div>
          </div>
        </div>

        <div class="col-md-4">
          <div class="form-group">
            <label>Contract Address</label>
            <input type="text" class="form-control" placeholder="Contract Address" [(ngModel)]="smartContractWalletCall.contractAddress" name="contractAddress" #contractAddress="ngModel" [ngClass]="{ 'is-invalid': smartContractWalletCallForm.submitted && contractAddress.invalid }" required>
            <div class="text-danger" *ngIf="smartContractWalletCallForm.submitted && contractAddress.invalid">
              <p *ngIf="contractAddress.errors?.required">Contract Address is required</p>
            </div>
          </div>
        </div>
      </div>
      <div class="row">
        <div class="col-md-4">
          <div class="form-group">
            <label>Password</label>
            <input type="text" class="form-control" placeholder="Password" [(ngModel)]="smartContractWalletCall.password" name="password1" #password1="ngModel" [ngClass]="{ 'is-invalid': smartContractWalletCallForm.submitted && password1.invalid }" required>
            <div class="text-danger" *ngIf="smartContractWalletCallForm.submitted && password1.invalid">
              <p *ngIf="password1.errors?.required">Wallet Password is required</p>
            </div>
          </div>
        </div>

        <div class="col-md-4">
          <div class="form-group">
            <label>Amount</label>
            <input type="text" class="form-control" placeholder="Amount" [(ngModel)]="smartContractWalletCall.amount" name="amount" #amount="ngModel" [ngClass]="{ 'is-invalid': smartContractWalletCallForm.submitted && amount.invalid }" required>
            <div class="text-danger" *ngIf="smartContractWalletCallForm.submitted && amount.invalid">
              <p *ngIf="amount.errors?.required">Amount is required</p>
            </div>
          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Outpoints</label>
            <input type="text" class="form-control" placeholder="Outpoints" [(ngModel)]="smartContractWalletCall.outpoints" name="outpoints" #outpoints="ngModel">
          </div>
        </div>
      </div>
      <div class="row">
        <div class="col-md-4">
          <div class="form-group">
            <label>Fee Amount</label>
            <input type="text" class="form-control" placeholder="Fee Amount" [(ngModel)]="smartContractWalletCall.feeAmount" name="feeAmount" #feeAmount="ngModel">
          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Gas Price</label>
            <input type="text" class="form-control" placeholder="Gas Price" [(ngModel)]="smartContractWalletCall.gasPrice" name="gasPrice" #gasPrice="ngModel">

          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Gas Limit</label>
            <input type="text" class="form-control" placeholder="Gas Limit" [(ngModel)]="smartContractWalletCall.gasLimit" name="gasLimit" #gasLimit="ngModel">
          </div>
        </div>
      </div>
      <div class="row">
        <div class="col-md-4">
          <div class="form-group">
            <label>Sender</label>
            <input type="text" class="form-control" placeholder="Sender" [(ngModel)]="smartContractWalletCall.sender" name="sender1" #sender1="ngModel" [ngClass]="{ 'is-invalid': smartContractWalletCallForm.submitted && sender1.invalid }" required>
            <div class="text-danger" *ngIf="smartContractWalletCallForm.submitted && sender1.invalid">
              <p *ngIf="sender1.errors?.required">Sender is required</p>
            </div>
          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Method Name</label>
            <input type="text" class="form-control" placeholder="Method Name" [(ngModel)]="smartContractWalletCall.methodName" name="methodName" #methodName="ngModel" [ngClass]="{ 'is-invalid': smartContractWalletCallForm.submitted && methodName.invalid }" required>
            <div class="text-danger" *ngIf="smartContractWalletCallForm.submitted && methodName.invalid">
              <p *ngIf="methodName.errors?.required">Method Name is required</p>
            </div>
          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Parameters</label>
            <input type="text" class="form-control" placeholder="Parameters" [(ngModel)]="parameter" name="parameters" #parameters="ngModel">
          </div>
        </div>
      </div>
      <div class="row">
        <div class="col-sm-4">
          <button type="submit" class="btn btn-primary"><i class="fa fa-lock"></i> Wallet Call</button>
        </div>
        <!-- /.col -->
      </div>
      <div *ngIf="smartcontractWalletCallOutput">
        <h3 class="card-title">Response output</h3><br />
        <span><span class="badge">Fee :</span> {{smartcontractWalletCallOutput.fee}}</span><br />
        <span><span class="badge">Hex:</span>  {{smartcontractWalletCallOutput.hex}}</span><br />
        <span><span class="badge">Message:</span> {{smartcontractWalletCallOutput.message}}</span><br />
        <span><span class="badge">Success:</span>  {{smartcontractWalletCallOutput.success}}</span><br />
        <span><span class="Transaction Id">To:</span>  {{smartcontractWalletCallOutput.transactionId}}</span><br />
      </div>
    </div>
    <!-- /.card-body -->
    <div class="card-footer bg-gradient-green">
      Stratis Blockchain.
    </div>
  </div>
</form>

Markup

The output of above Smart Contract Wallet Creates page.

Output UI to interact with Amart Contract Wallet Call (endpoint: /api/SmartContractWallet/call).

Smart Contract Component

From the SmartContract API Controller, we will call endpoint API/SmartContracts/receipt which gives the receipt of the transaction. We have to pass transaction hash to get transaction receipt. It gives transaction receipts including Gas Used, From and To address, Logs, etc. Additionally, we will integrate endpoint /api/SmartContracts/local-call which creates a local call with a contract without a transaction. As we saw in the previous article when to use local call and contract call.

We will create a Model for GetReceipt and Local-Call.

Model code for smartcontractreceipt.ts

export class SmartContractReceipt {
  txHash: string = "";
}

JavaScript

Model code for smartcontractlocalcall.ts class.

export class SmartContractLocalCall {
  contractAddress: string = "";
  methodName: string = "";
  amount: string = "";
  gasPrice: number = 10000;
  gasLimit: number = 250000;
  sender: string = "";
  parameters: Array<string> = [];
}

JavaScript

Generate Component and Service for Smart Contract API Controller.

ng g service _service/smartcontract --skip-tests
ng g component apicollection/smartcontract --skip-tests

Bash

Code of SmartContractService class,

import { Injectable } from '@angular/core';

import { HttpClient } from '@angular/common/http';
import { ROOT_URL } from '../../_model/config';

@Injectable({
  providedIn: 'root'
})
export class SmartcontractService {

  constructor(private http: HttpClient) { }
  SmartContractReceipt(params: any) {
    return this.http.get(ROOT_URL + '/api/SmartContracts/receipt', { params: params });
  }
  SmartContractLocalCall(smartContractLocalCall: any) {
    return this.http.post(ROOT_URL + '/api/SmartContracts/local-call', smartContractLocalCall);
  }
}

JavaScript

Code of smartcontract.component.ts,

import { Component, OnInit } from '@angular/core';

import { SmartContractReceipt } from '../../_model/smartcontractreceipt';
import { SmartContractLocalCall } from '../../_model/smartcontractlocalcall';
import { SmartcontractService } from '../../_service/stratisfullnode/smartcontract.service';
import { HttpParams } from '@angular/common/http';
@Component({
  selector: 'app-smartcontract',
  templateUrl: './smartcontract.component.html',
  styleUrls: ['./smartcontract.component.scss']
})
export class SmartcontractComponent implements OnInit {
  public smartContractReceipt: SmartContractReceipt = new SmartContractReceipt();
  public smartContractLocalCall: SmartContractLocalCall = new SmartContractLocalCall();
  constructor(private smartcontractService: SmartcontractService) { }
  resultGetReceipt: any;
  parameter: string = "";
  localCallResponseOut: any;
  ngOnInit(): void {

  }

  SmartContractReceipt() {
    let params = new HttpParams().set("txHash", this.smartContractReceipt.txHash);
    this.smartcontractService.SmartContractReceipt(params).subscribe((response: any) => {
      if (response) {
        this.resultGetReceipt = response;
        console.log(this.resultGetReceipt);
      } else {
        alert('Opps!!!!');
        (error: any) => {
          console.log(error);
        }
      }
    });
  }

  SmartContractForLocalCall() {
    this.smartContractLocalCall.parameters= [];    this.smartcontractService.SmartContractLocalCall(this.smartContractLocalCall).subscribe((response: any) => {
      console.log(response);
      if (response) {
        this.localCallResponseOut = response;
        console.log(this.localCallResponseOut);
      } else {
        alert('Oops...');
        (error: any) => {
          console.log(error);
        }
      }
    });
  }
}

JavaScript

HTML for smartcontract.component.html,

<section class="content-header">
  <div class="container-fluid">
    <div class="row mb-2">
      <div class="col-sm-6">
        <h1>Stratis FullNode APIs </h1>
      </div>
      <div class="col-sm-6">
        <ol class="breadcrumb float-sm-right">
        </ol>
      </div>
    </div>
  </div><!-- /.container-fluid -->
</section>
<!--Get Receipt-->

<form (ngSubmit)="smartcontractGetReceiptForm.form.valid && SmartContractReceipt()" #smartcontractGetReceiptForm="ngForm">
  <!-- SELECT2 EXAMPLE -->
  <div class="card card-primary card-outline">
    <div class="card-header">
      <h3 class="card-title">Smart Contract Receipt</h3>
      <div class="card-tools">
        <button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fas fa-minus"></i></button>
      </div>
    </div>
    <!-- /.card-header -->
    <div class="card-body">
      <div class="row">
        <div class="col-md-12">
          <div class="form-group">
            <label>Transaction Hash </label>
            <input type="text" class="form-control" placeholder="Transaction Hash" [ngClass]="{ 'is-invalid': smartcontractGetReceiptForm.submitted && txHash.invalid }" [(ngModel)]="smartContractReceipt.txHash" name="txHash" #txHash="ngModel" required>
            <div class="text-danger" *ngIf="smartcontractGetReceiptForm.submitted && txHash.invalid">
              <p *ngIf="txHash.errors?.required">Transaction Hash is required</p>
            </div>
          </div>
        </div>
      </div>

      <div class="row">
        <div class="col-sm-4">
          <button type="submit" class="btn btn-primary"><i class="fa fa-lock"></i> Get Receipt</button>
        </div>
        <!-- /.col -->

      </div>

      <!-- /.card-body -->
      <div *ngIf="resultGetReceipt">
        <h3 class="card-title">Response output</h3><br />
        <span><span class="badge">Transaction Hash:</span> {{resultGetReceipt.transactionHash}}</span><br />
        <span><span class="badge">Block Hash:</span>  {{resultGetReceipt.blockHash}}</span><br />
        <span><span class="badge">PostState:</span> {{resultGetReceipt.postState}}</span><br />
        <span><span class="badge">From:</span>  {{resultGetReceipt.from}}</span><br />
        <span><span class="badge">To:</span>  {{resultGetReceipt.to}}</span><br />
        <span><span class="badge">GasUsed:</span>  {{resultGetReceipt.gasUsed}}</span><br />
        <span><span class="badge">New Contract Address:</span> {{resultGetReceipt.newContractAddress}}</span><br />
        <span><span class="badge">Success:</span>  {{resultGetReceipt.success}}</span><br />
        <span><span class="badge">Return Value:</span> {{resultGetReceipt.returnValue}}</span><br />
        <span><span class="badge">Bloom:</span>  {{resultGetReceipt.bloom}}</span><br />
        <span><span class="badge">Error:</span>  {{resultGetReceipt.error}}</span><br />
        <span><span class="badge">Log:</span>  {{resultGetReceipt.logs}}</span><br />
      </div>
    </div>
  </div>

</form>


<form (ngSubmit)="smartcontractLocalCallForm.form.valid && SmartContractForLocalCall()" #smartcontractLocalCallForm="ngForm">
  <!-- SELECT2 EXAMPLE -->
  <div class="card card-primary card-outline">
    <div class="card-header">
      <h3 class="card-title">Smart Contract Local Call</h3>
      <div class="card-tools">
        <button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fas fa-minus"></i></button>
      </div>
    </div>
    <!-- /.card-header -->
    <div class="card-body">
      <div class="row">
        <div class="col-md-4">
          <div class="form-group">
            <label>Contract Address </label>
            <input type="text" class="form-control" placeholder="Contract Address" [ngClass]="{ 'is-invalid': smartcontractLocalCallForm.submitted && contractAddress.invalid }" [(ngModel)]="smartContractLocalCall.contractAddress" name="contractAddress" #contractAddress="ngModel" required>
            <div class="text-danger" *ngIf="smartcontractLocalCallForm.submitted && contractAddress.invalid">
              <p *ngIf="contractAddress.errors?.required">Contract Address is required</p>
            </div>
          </div>
        </div>

        <div class="col-md-4">
          <div class="form-group">
            <label>Method Name </label>
            <input type="text" class="form-control" placeholder="Method Name" [ngClass]="{ 'is-invalid': smartcontractLocalCallForm.submitted && methodName.invalid }" [(ngModel)]="smartContractLocalCall.methodName" name="methodName" #methodName="ngModel" required>
            <div class="text-danger" *ngIf="smartcontractLocalCallForm.submitted && methodName.invalid">
              <p *ngIf="methodName.errors?.required">Method Name is required</p>
            </div>
          </div>
        </div>

        <div class="col-md-4">
          <div class="form-group">
            <label>Amount</label>
            <input type="text" class="form-control" placeholder="Amount" [(ngModel)]="smartContractLocalCall.amount" name="amount" #amount="ngModel" [ngClass]="{ 'is-invalid': smartcontractLocalCallForm.submitted && amount.invalid }" required>

          </div>
        </div>
      </div>
      <div class="row">
        <div class="col-md-4">
          <div class="form-group">
            <label>Gas Price</label>
            <input type="text" class="form-control" placeholder="Gas Price" [(ngModel)]="smartContractLocalCall.gasPrice" name="gasPrice" #gasPrice="ngModel">

          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Gas Limit</label>
            <input type="text" class="form-control" placeholder="Gas Limit" [(ngModel)]="smartContractLocalCall.gasLimit" name="gasLimit" #gasLimit="ngModel">
          </div>
        </div>
        <div class="col-md-4">
          <div class="form-group">
            <label>Sender</label>
            <input type="text" class="form-control" placeholder="Sender" [(ngModel)]="smartContractLocalCall.sender" name="sender" #sender="ngModel">

          </div>
        </div>
      </div>
      <div class="row">
        <div class="col-md-4">
          <div class="form-group">
            <label>Parameters</label>
            <input type="text" class="form-control" placeholder="Parameters" [(ngModel)]="parameter" name="parameters" #parameters="ngModel">
          </div>
        </div>
      </div>

      <div class="row">
        <div class="col-sm-4">
          <button type="submit" class="btn btn-primary"><i class="fa fa-lock"></i> Make Local Call</button>
        </div>
      </div>

      <!-- /.card-body -->
      <div *ngIf="localCallResponseOut">
        <h3 class="card-title">Response output</h3><br />
        <span><span class="badge">Internal Transfer:</span>  {{localCallResponseOut.internalTransfers}}</span><br />
        <span><span class="badge">GasConsumed Value:</span> {{localCallResponseOut.gasConsumed.value}}</span><br />
        <span><span class="badge">Revert:</span>  {{localCallResponseOut.revert}}</span><br />
        <span><span class="badge">Error Message:</span>  {{localCallResponseOut.errorMessage}}</span><br />
        <span><span class="badge">Return:</span>  {{localCallResponseOut.return}}</span><br />
        <span><span class="badge">Log:</span>  {{localCallResponseOut.logs}}</span><br />
      </div>
    </div>
  </div>
  <div class="card-footer bg-gradient-green">
    Stratis Blockchain.
  </div>
  <!-- /.card -->
</form>

Markup

Output of Smart Contract Get Receipt UI.

Smart Contract Local call UI.

Summary

Hence, we can integrate Stratis API in any custom application. In this article, we have implemented Stratis private blockchain in our own application through which we can deploy the Smart Contract. Additionally, write-up has shown how can you manage the API get, post and response model as well as segregate services, models for APIs. The article has explained the complete steps to develop components with user interface to validate Startis API with input and response formatted output. Furthermore, you can take idea from this and integrate Stratis Blockchain any API endpoint to your custom application based on your application need. I have developed an angular application for complete demonstration which you can get from repository

Source: https://www.c-sharpcorner.com/article/integrate-stratis-blockchain-apis-in-your-custom-application/

#smartcontract #blockchain