Flutter跨链桥接插件flutter_nekoton_bridge的使用

发布于 1周前 作者 phonegap100 来自 Flutter

Flutter跨链桥接插件flutter_nekoton_bridge的使用

本指南将帮助你了解如何在Flutter项目中使用flutter_nekoton_bridge插件。该插件基于flutter_rust_bridge生成器,允许你在Flutter应用中与Rust代码进行交互。

安装

首先,在你的pubspec.yaml文件中添加flutter_nekoton_bridge依赖:

dependencies:
  flutter_nekoton_bridge:

日志记录

在使用flutter_nekoton_bridge之前,你需要设置日志记录。推荐使用logging包来记录日志。以下是一个示例:

import 'package:logging/logging.dart';
import 'package:flutter_nekoton_bridge/flutter_nekoton_bridge.dart';

// 创建一个日志级别映射
static final Map<Level, fnb.LogLevel?> _logMap = {
  Level.ALL: fnb.LogLevel.Trace,
  Level.FINEST: fnb.LogLevel.Trace,
  Level.FINER: fnb.LogLevel.Trace,
  Level.FINE: fnb.LogLevel.Debug,
  Level.CONFIG: fnb.LogLevel.Debug,
  Level.INFO: fnb.LogLevel.Info,
  Level.WARNING: fnb.LogLevel.Warn,
  Level.SEVERE: fnb.LogLevel.Error,
  Level.SHOUT: fnb.LogLevel.Error,
  Level.OFF: null,
};

Level _toLogLevel(fnb.LogLevel level) {
  return _logMap.keys.firstWhere((key) => _logMap[key] == level);
}

// 日志处理器
void _logHandler(fnb.LogEntry logEntry) {
  final logLevel = _toLogLevel(logEntry.level);
  _log.log(logLevel, '${logEntry.tag}: ${logEntry.msg}');
}

// 初始化日志记录
void setupLogger() {
  Logger.root.level = Level.ALL; // 设置默认日志级别
  Logger.root.onRecord.listen(_logHandler); // 设置日志处理器
}

桥接初始化

在日志记录之后,你需要调用initRustToDartCaller函数来初始化桥接:

fnb.initRustToDartCaller();

桥接使用

固定点数

尽管我们在大多数情况下不使用scale,但建议在应用中使用Fixed包来处理固定点数。例如:

Fixed.fromInt(1234, scale: 3); // == 1.234
Fixed.fromBigInt(BigInt.from(1234), scale: 3); // == 1.234
final t1 = Fixed.fromDecimal(Decimal.fromInt(1), scale: 2); // == 1.00
final t3 = Fixed.parse('1.234', scale: 2); // == 1.23, scale: 2
金钱计算

我们推荐使用money2包来进行货币计算。例如:

import 'package:money2/money2.dart';

Money usd = Money.fromDouble('USD', 12.5);
print(usd.toString()); // 输出 "12.50 USD"

示例代码

以下是一个完整的示例代码,展示了如何在Flutter项目中使用flutter_nekoton_bridge插件:

import 'dart:async';
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter_nekoton_bridge/flutter_nekoton_bridge.dart';

Future<void> main() async {
  await NekotonBridge.init();
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  [@override](/user/override)
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late int sumResult;
  late Future<int> sumAsyncResult;
  String? fromMyClass;

  [@override](/user/override)
  void initState() {
    super.initState();
    sumResult = simpleAdderSync(a: 1, b: 2);
    sumAsyncResult = simpleAdder(a: 3, b: 4);

    // 这个设置不应该被移除或修改,因为它用于集成测试
    setupLogger(
      level: LogLevel.trace,
      mobileLogger: false,
      logHandler: (logEntry) => debugPrint(
        'FromLib: ${logEntry.level} ${logEntry.tag} ${logEntry.msg} (lib_time=${logEntry.timeMillis})',
      ),
    );
  }

  void _onPressed() async {
    fromMyClass = await queryMyClass();
    setState(() {});
  }

  void _onPressedLog() async {
    debugPrint('Log!');
    simpleLog(string: 'From dart: ${DateTime.now().toIso8601String()}');
  }

  void _onPressedPanic() async {
    debugPrint('Panic!');
    simplePanic();
  }

  // 缓存实例
  CallerWrapper? _caller;

  void _onPressedInitDartCaller() async {
    initRustToDartCaller();
    _caller = initCallerWrapper(CallerImpl());
  }

  List<CallerTestClassWrapper> testCallers = [];

  void _onPressedAddTestCaller() async {
    testCallers.add(await initCallerTestClassWrapper(Random().nextInt(1000)));
    setState(() {});
  }

  void _onPressedTriggerTestCallers() {
    for (var c in testCallers) {
      c.caller.callSomeFunc();
    }
  }

  void _onPressedDartCallFunc0(bool needResult) async {
    simpleCallFunc0(needResult: needResult);
  }

  void _onPressedDartCallFunc1(bool needResult) async {
    simpleCallFunc1(needResult: needResult);
  }

  void _onPressedDartCallFunc2() async {
    simpleCallFunc2();
  }

  void _onPressedDartCallFunc3() async {
    simpleCallFunc3();
    simpleCallFunc3();
    simpleCallFunc3();
    simpleCallFunc3();
    simpleCallFunc3();
    simpleCallFunc3();
    simpleCallFunc3();
    simpleCallFunc3();
    simpleCallFunc3();
    simpleCallFunc3();
    simpleCallFunc3();
    simpleCallFunc3();
  }

  // 这些按钮(带有*Test*回调)不应该被移除或修改,因为它们用于集成测试
  void _onPressedTestInfo() async {
    testLoggerInfo(string: 'test logger: info');
  }

  void _onPressedTestDebug() async {
    testLoggerDebug(string: 'test logger: debug');
  }

  void _onPressedTestWarn() async {
    testLoggerWarn(string: 'test logger: warn');
  }

  void _onPressedTestError() async {
    testLoggerError(string: 'test logger: error');
  }

  void _onPressedTestPanic() async {
    testLoggerPanic(string: 'test logger: panic');
  }

  void _testCallerCallTest0Async(bool needResult) async {
    final result = await testCallerCallTest0Async(
      string: 'testCallerCallTest0Async $needResult',
      needResult: needResult,
    );
    debugPrint('result ${result.toDynamic()}');
  }

  void _testCallerCallTest0Sync(bool needResult) {
    final result = testCallerCallTest0Sync(
      string: 'testCallerCallTest0Sync $needResult',
      needResult: needResult,
    );
    debugPrint('result ${result.toDynamic()}');
  }

  void _testCallerCallTest1Async(bool needResult) async {
    final futures = <Future<DynamicValue>>[];
    for (int i = 0; i < 7; i++) {
      futures.add(testCallerCallTest1Async(
        string: 'testCallerCallTest1Async $needResult',
        needResult: needResult,
      ));
    }
    final results = await Future.wait(futures);
    for (var result in results) {
      debugPrint('result ${result.toDynamic()}');
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    const textStyle = TextStyle(fontSize: 25);
    const spacerSmall = SizedBox(height: 10);
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Native Packages'),
        ),
        body: SingleChildScrollView(
          child: Container(
            padding: const EdgeInsets.all(10),
            child: Column(
              children: [
                const Text(
                  'logger-related',
                  style: textStyle,
                ),
                Wrap(
                  children: [
                    TextButton(
                      onPressed: () => _onPressedTestInfo(),
                      child: const Text('i'),
                    ),
                    TextButton(
                      onPressed: () => _onPressedTestDebug(),
                      child: const Text('d'),
                    ),
                    TextButton(
                      onPressed: () => _onPressedTestWarn(),
                      child: const Text('w'),
                    ),
                    TextButton(
                      onPressed: () => _onPressedTestError(),
                      child: const Text('e'),
                    ),
                    TextButton(
                      onPressed: () => _onPressedTestPanic(),
                      child: const Text('p'),
                    ),
                  ],
                ),
                const Text(
                  'caller-related',
                  style: textStyle,
                ),
                Wrap(
                  children: [
                    TextButton(
                      onPressed: _onPressedInitDartCaller,
                      child: const Text('initDartCaller'),
                    ),
                    TextButton(
                      onPressed: () => _testCallerCallTest0Async(false),
                      child: const Text('Test0Async'),
                    ),
                    TextButton(
                      onPressed: () => _testCallerCallTest0Async(true),
                      child: const Text('Test0AsyncResult'),
                    ),
                    TextButton(
                      onPressed: () => _testCallerCallTest0Sync(false),
                      child: const Text('Test0Sync'),
                    ),
                    TextButton(
                      onPressed: () => _testCallerCallTest0Sync(true),
                      child: const Text('Test0SyncResult'),
                    ),
                    TextButton(
                      onPressed: () => _testCallerCallTest1Async(true),
                      child: const Text('Test1AsyncResult'),
                    ),
                  ],
                ),
                Text(
                  'sum(1, 2) = $sumResult',
                  style: textStyle,
                  textAlign: TextAlign.center,
                ),
                spacerSmall,
                FutureBuilder<int>(
                  future: sumAsyncResult,
                  builder: (BuildContext context, AsyncSnapshot<int> value) {
                    final displayValue = (value.hasData) ? value.data : 'loading';
                    return Text(
                      'await sumAsync(3, 4) = $displayValue',
                      style: textStyle,
                      textAlign: TextAlign.center,
                    );
                  },
                ),
                TextButton(
                  onPressed: _onPressed,
                  child: Text('From MyClass $fromMyClass'),
                ),
                TextButton(
                  onPressed: _onPressedLog,
                  child: const Text('Log'),
                ),
                TextButton(
                  onPressed: _onPressedPanic,
                  child: const Text('Panic'),
                ),
                TextButton(
                  onPressed: () => _onPressedDartCallFunc0(true),
                  child: const Text('CallFunc0 WITH result'),
                ),
                TextButton(
                  onPressed: () => _onPressedDartCallFunc1(true),
                  child: const Text('CallFunc1 WITH result'),
                ),
                TextButton(
                  onPressed: () => _onPressedDartCallFunc0(false),
                  child: const Text('CallFunc0 WITHOUT result'),
                ),
                TextButton(
                  onPressed: () => _onPressedDartCallFunc1(false),
                  child: const Text('CallFunc1 WITHOUT result'),
                ),
                TextButton(
                  onPressed: () => _onPressedDartCallFunc2(),
                  child: const Text('CallFunc2'),
                ),
                TextButton(
                  onPressed: () => _onPressedAddTestCaller(),
                  child: const Text('Add test caller'),
                ),
                TextButton(
                  onPressed: () => _onPressedTriggerTestCallers(),
                  child: const Text('Trigger test callers'),
                ),
                TextButton(
                  onPressed: () => _onPressedDartCallFunc3(),
                  child: const Text('CallFunc3'),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

更多关于Flutter跨链桥接插件flutter_nekoton_bridge的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter跨链桥接插件flutter_nekoton_bridge的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何使用Flutter跨链桥接插件flutter_nekoton_bridge的示例代码案例。这个示例假定你已经有一个Flutter项目,并且已经添加了flutter_nekoton_bridge插件到你的pubspec.yaml文件中。

1. 添加依赖

首先,确保你的pubspec.yaml文件中包含以下依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_nekoton_bridge: ^latest_version # 替换为最新的版本号

然后运行flutter pub get来安装依赖。

2. 导入包

在你的Dart文件中导入flutter_nekoton_bridge包:

import 'package:flutter_nekoton_bridge/flutter_nekoton_bridge.dart';

3. 初始化插件

在你的应用的主文件(通常是main.dart)中初始化flutter_nekoton_bridge插件。

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  // 初始化 flutter_nekoton_bridge 插件
  NekotonBridge.initialize();

  runApp(MyApp());
}

4. 使用跨链桥接功能

下面是一个简单的例子,展示如何使用flutter_nekoton_bridge插件进行跨链操作。这里假设你需要从一个链传输资产到另一个链。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Nekoton Bridge Example'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: () async {
              try {
                // 示例参数,你需要根据实际情况调整
                String fromChainId = 'your_from_chain_id';
                String toChainId = 'your_to_chain_id';
                String assetId = 'your_asset_id';
                String amount = 'your_amount';
                String recipientAddress = 'recipient_address';

                // 调用跨链传输函数
                var result = await NekotonBridge.transferAsset(
                  fromChainId: fromChainId,
                  toChainId: toChainId,
                  assetId: assetId,
                  amount: amount,
                  recipientAddress: recipientAddress,
                );

                // 处理结果
                print('Transfer result: $result');
              } catch (e) {
                // 处理错误
                print('Error during transfer: $e');
              }
            },
            child: Text('Transfer Asset'),
          ),
        ),
      ),
    );
  }
}

注意事项

  1. 链ID和资产ID:在实际应用中,你需要根据目标链和资产的实际ID来替换示例代码中的fromChainIdtoChainIdassetId等参数。
  2. 用户授权:跨链传输通常需要用户授权,这个示例没有包含授权逻辑,你需要根据插件的文档和用户界面需求来添加。
  3. 错误处理:在实际应用中,错误处理会更加复杂,你可能需要更详细的错误分类和处理逻辑。

这个示例提供了一个基本的框架,你可以根据具体的需求和插件的API文档来扩展和完善功能。

回到顶部