はじめに
昨日はDev Protocolのコントラクト実行を試してみましたが、今日はその処理をパッケージ化して使ってみたいと思います。
いずれはDev ProtocolのJavaScript/TypeScriptのインターフェースであるdev-kit-jsのDart実装のようなものを提供できればなと考えています。
パッケージ化に当たっては、web3dartを参考にさせていただきました。
実装
パッケージ化の準備
まず昨日までに実装したDev Protocolのステーキング数を取得する処理をパッケージ化します。
devkit.dart
フォルダを作成し、プロジェクトを開始します。
(dart create
コマンドでも作成できるみたいなのですが、今回は小さいプロジェクトのなの何もない状態から作成していきます。)
まずはパッケージの情報や依存パッケージの定義を行う pubspec.yaml
を作成します。
name: devkit
description: (Unofficial) Dart library to Dev Protocol Interface
version: 0.0.1
homepage: https://github.com/hhatto/devkit.dart
environment:
sdk: '>=2.12.0 <3.0.0'
dependencies:
web3dart: ^2.3.3
見様見真似なので、sdkバージョンの違いとかまだよく分かってない部分が多々あります。
これもよく分かってないですが、パッケージの依存解決するために dart pub get
しておきました。
$ dart pub get
これでpubspec.lock
作成されるのですが、他の言語とかだとlock系のファイルは保存しなかったりすると思うのですが、Dartはどうなんでしょうか。
一旦ファイルは作っておきます。(.gitignore
とかに追加しておくのかな...?)
これでパッケージ作成の準備は整いました。
パッケージの処理実装
先にディレクトリ構成だけ記載しておきます。
$ tree -L 4
.
├── lib
│ ├── devkit.dart
│ └── src
│ ├── abi
│ │ ├── lockup.dart
│ │ └── registry.dart
│ └── core.dart
├── pubspec.lock
└── pubspec.yaml
3 directories, 6 files
lib
ディレクトリ以下を少し説明しておきます。
-
lib/devkit.dart
はパッケージの定義やimport/exportを管理したりする最小限のファイルです。(別にここに処理書いてもいいとは思いますが、web3dartに合わせました。) -
lib/src/core.dart
はコントラクト実行等を行うメインの処理 -
lib/src/abi/...
はコントラクト用のABIの定義(昨日の記事で書いたものと同じです。)
まずlib/src/devkit.dart
は以下のような感じです。
library devkit;
export 'src/core.dart';
library
でライブラリ(パッケージ)定義してるのと、src/core.dart
の処理をエクスポートして、パッケージ使用者側から使えるようにしています。
次にlib/src/core.dart
は以下のような感じです。
処理自体は昨日実装したものをほぼ転用した形です。
import 'package:http/http.dart';
import 'package:web3dart/web3dart.dart';
import './abi/lockup.dart';
import './abi/registry.dart';
class DevKitClient {
DevKitClient(String apiUrl) {
var httpClient = new Client();
var ethClient = new Web3Client(apiUrl, httpClient);
_client = ethClient;
}
late final Web3Client _client;
registryContractFactory() {
EthereumAddress contractAddress = EthereumAddress.fromHex('0x1D415aa39D647834786EB9B5a333A50e9935b796');
final contract = DeployedContract(ContractAbi.fromJson(registryAbi, 'registry'), contractAddress);
return {
'lockup': () {
return _client.call(contract: contract, function: contract.function('lockup'), params: []);
}
};
}
lockupContractFactory(String lockupContractAddress) {
EthereumAddress contractAddress = EthereumAddress.fromHex(lockupContractAddress);
final contract = DeployedContract(ContractAbi.fromJson(lockupAbi, 'lockup'), contractAddress);
return {
'getPropertyValue': (String propertyAddress) {
EthereumAddress address = EthereumAddress.fromHex(propertyAddress);
return _client.call(contract: contract, function: contract.function('getPropertyValue'), params: [address]);
}
};
}
}
DevKitClient
にEthereumプロバイダ用のURLを渡しつつ、クライアント生成して、各コントラクトの処理を呼び出す感じです。Dart語彙力低いので、ここもよくわからず実装している感じはあります。
一応パッケージの実装はこれで終わりです。
Flutter側から呼び出す
今回はpub.devやGitHubにもあげていないので、ローカル環境のファイルパスを指定して、使います。
pubspec.yaml
に対象となるディレクトリのファイルパスを指定して、flutter pub get
します。
diff --git a/pubspec.yaml b/pubspec.yaml
index 1de5307..23d2968 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -35,6 +35,8 @@ dependencies:
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
web3dart: ^2.3.3
+ devkit:
+ path: /Users/hattori/work/devkit.dart
dev_dependencies:
flutter_test:
$ flutter pub get
pubspec.lock
にも反映されました。これで使用可能になります。
diff --git a/pubspec.lock b/pubspec.lock
index 536017b..730c4fe 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -141,6 +141,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.1"
+ devkit:
+ dependency: "direct main"
+ description:
+ path: "/Users/hattori/work/devkit.dart"
+ relative: false
+ source: path
+ version: "0.0.1"
fake_async:
dependency: transitive
description:
アプリのメインの処理があるlib/main.dart
を以下のように変更しました。
diff --git a/lib/main.dart b/lib/main.dart
index de3c27b..4f10121 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'package:web3dart/web3dart.dart';
+import 'package:devkit/devkit.dart';
import 'abi/lockup.dart';
import 'abi/registry.dart';
@@ -39,21 +40,16 @@ class _MyHomePageState extends State<MyHomePage> {
void getBalance(String address) async {
var apiUrl = "http://localhost:8545";
- var httpClient = new Client();
- var ethClient = new Web3Client(apiUrl, httpClient);
+ var client = new DevKitClient(apiUrl);
EthereumAddress propertyAddress = EthereumAddress.fromHex(address);
- EthereumAddress registryContractAddress = EthereumAddress.fromHex('0x1D415aa39D647834786EB9B5a333A50e9935b796');
- final registryContract =
- DeployedContract(ContractAbi.fromJson(registryAbi, 'registry'), registryContractAddress);
-
- final lockupContractAddresses = await ethClient.call(contract: registryContract, function: registryContract.function('lockup'), params: []);
- print(lockupContractAddresses);
- final lockupContract =
- DeployedContract(ContractAbi.fromJson(lockupAbi, 'lockup'), lockupContractAddresses[0]);
- final lockupValue = await ethClient.call(contract: lockupContract, function: lockupContract.function('getPropertyValue'), params: [propertyAddress]);
-
+ final registryContract = client.registryContractFactory();
+ final lockupContractAddress = await registryContract['lockup']();
+ print(lockupContractAddress);
+ final lockupContract = client.lockupContractFactory(lockupContractAddress[0].toString());
+ final lockupValue = await lockupContract['getPropertyValue'](propertyAddress.toString());
+ print(lockupValue);
_balance = (lockupValue[0] / BigInt.from(10).pow(18)).toDouble();
}
これで実行すると昨日と同じプロパティのステーク数が表示されるようになります。
おわりに
最小限の処理をパッケージ化し、Flutter側から使ってみました。
devkit.dart拡充したいですね。まずは冬休みにDart勉強してDart力を高めようと思います。
Dart/Flutter、サクサク開発できておもしろいです!!