Flutter数字货币钱包管理插件lightspark_wallet的使用

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

Flutter数字货币钱包管理插件lightspark_wallet的使用

这是Lightspark Wallet Flutter SDK!查看示例项目以了解如何使用它,或者阅读以下内容开始使用。

注意: 目前尚未准备好用于生产环境。但您可以自由地在内部进行测试!

开始使用

要使用钱包SDK,首先需要将其作为依赖项安装到您的应用中:

注意: 这个命令在SDK的第一个版本发布之前无法工作!目前还未上线。

flutter pub add lightspark_wallet

然后,导入它并构造一个钱包客户端:

import 'package:lightspark_wallet/lightspark_wallet.dart';

final client = LightsparkWalletClient();

通过JWT进行身份验证

当前版本的SDK支持JWT(JSON Web Token)身份验证,适用于客户端使用。要进行身份验证,您需要使用您的Lightspark账户ID和由您自己的服务器分配给用户的JWT进行登录。

jwt diagram

首先,您需要将您的账户公钥注册到Lightspark。您可以通过Lightspark账户设置页面完成此操作。您需要提供您想要用来签署JWT的账户的公钥。您可以使用以下命令生成密钥对:

openssl genrsa -out private.key 2048

这将生成一个名为private.key的私钥文件。然后,您可以使用以下命令生成公钥文件:

openssl rsa -in private.key -pubout -out public.key

接下来,您可以将公钥文件的内容复制到API令牌页面的“JWT公钥”字段中。同时,您还需要将私钥复制到您的服务器代码中(或存储在安全的密钥库或环境变量中),以便能够使用它来签署JWT。

接下来,您需要为用户创建一个JWT。您应该从后端暴露一个端点来创建这些令牌。例如,使用typescript+node服务器创建JWT:

import * as jwt from "jsonwebtoken";

// 创建包含JWT声明的JSON对象。
const claims = {
  aud: "https://api.lightspark.com",
  // 用户的唯一标识符。
  sub: "511c7eb8-9afe-4f69-989a-8d1113a33f3d",
  // 使用测试环境还是生产环境。
  test: true,
  iat: 1516239022,
  // JWT的过期时间。
  exp: 1799393363,
};

// 调用`jsonwebtoken`库的`sign()`方法,传入JSON对象和您的私钥。
const token = jwt.sign(claims, "your private key");

// 现在将token发送回客户端,以便他们可以使用它与Lightspark SDK进行身份验证。

现在在客户端,您可以使用JWT和您公司账户ID从账户设置页面登录:

await client.loginWithJWT(ACCOUNT_ID, jwt, SharedPreferencesJwtStorage());

您会注意到这个请求需要一个实现JwtStorage的参数。这可以用于保存凭证以便下次启动应用时使用。如果您想使用保存的JWT信息恢复钱包凭证,可以在客户端构造函数中传递一个JWT存储实现。例如,如果您以前使用了SharedPreferencesJwtStorage实现登录,您可以在应用启动时这样恢复凭证:

import 'package:lightspark_wallet/lightspark_wallet.dart';

final jwtStorage = SharedPreferencesJwtStorage();
final client = LightsparkWalletClient(authProvider: JwtAuthProvider(jwtStorage));

部署和初始化钱包

wallet state diagram

当用户首次登录时,他们的钱包初始状态为NOT_SETUP。您可以通过查询当前钱包的状态来识别这种状态:

final wallet = await client.getCurrentWallet();
if (wallet.status == WalletStatus.NOT_SETUP) {
  // 钱包未设置,因此我们需要部署它。
}

要部署钱包,您需要调用client.deployWallet(),然后等待钱包状态更新为DEPLOYED或FAILED。您可以通过轮询钱包或通过订阅钱包更新来实现这一点。

这里是一个每2秒轮询钱包状态的示例:

var wallet = await client.deployWallet();
while (
  wallet.status != WalletStatus.DEPLOYED &&
  wallet.status != WalletStatus.FAILED
) {
  await Future.delayed(const Duration(seconds: 2));
  wallet = await client.getCurrentWallet();
}

// 现在钱包要么已部署,要么失败。

另一种方法是使用辅助函数deployWalletAndAwaitDeployed

final walletStatus = await client.deployWalletAndAwaitDeployed();
if (walletStatus == WalletStatus.DEPLOYED) {
  // 钱包已部署!
} else {
  // 钱包部署失败。
}

一旦钱包部署成功,您就可以初始化它了。但是,您首先需要签名密钥才能完成敏感操作。

钱包的密钥生成

初始化钱包时,您需要提供一个公钥供钱包用于签署交易。请注意,这与您上面使用的JWT签名密钥不同。它应该是每个用户的唯一密钥。确保您的应用程序安全地存储该密钥对。丢失私钥会导致用户失去对其钱包的访问权限。目前,钱包SDK仅支持RSA-PSS密钥,但我们计划在未来支持其他类型的密钥。

为了方便起见,钱包SDK提供了一个generateRsaKeyPair()方法,可用于生成密钥对。然后,您可以按您希望的方式在应用程序代码中存储这些密钥。

import 'package:lightspark_wallet/lightspark_wallet.dart';

final keyPair = await generateRsaKeyPair();
const signingWalletPublicKey = keyPair.publicKey;
const signingWalletPrivateKey = keyPair.privateKey;

// 将密钥安全地存储起来。

初始化钱包

有了密钥之后,您就可以初始化钱包了!就像部署时一样,您可以通过轮询钱包或通过订阅钱包更新来完成。

var wallet = await client.initializeWallet(
  KeyType.RSA_OAEP,
  serializedPublicKey,
  serializedPrivateKey
);
while (
  wallet.status != WalletStatus.READY &&
  wallet.status != WalletStatus.FAILED
) {
  await Future.delayed(const Duration(seconds: 2));
  wallet = await client.getCurrentWallet();
}

// 现在钱包要么已准备好,要么失败。

另一种方法是使用辅助函数initializeWalletAndAwaitReady

final walletStatus = await client.initializeWalletAndAwaitReady(
  KeyType.RSA_OAEP,
  serializedPublicKey,
  serializedPrivateKey
);
if (walletStatus == WalletStatus.READY) {
  // 钱包已初始化!
} else {
  // 钱包初始化失败。
}

解锁钱包并发起请求

当钱包处于READY状态时,您可以发起请求。但是,为了完成像发送支付这样的敏感操作,您首先需要使用您之前生成的私钥解锁钱包。

await client.loadWalletSigningKey(serializedPublicKey, serializedPrivateKey);

现在您可以发起请求了!例如,创建一张发票:

final invoiceData = await client.createInvoice(
    100_000,
    memo: "mmmmm pizza",
);

或者支付发票:

final payment = await client.payInvoice(
  /* 编码后的发票 */ invoiceData.encodedPaymentRequest,
  /* 最大费用 */ 50_000
);

有关更多示例,请查看集成测试或查看示例应用

完整示例Demo

以下是一个完整的示例,展示了如何使用Lightspark Wallet插件:

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

import 'package:lightspark_wallet/lightspark_wallet.dart';
import 'package:lightspark_wallet_example/src/screens/account_screen.dart';
import 'package:lightspark_wallet_example/src/screens/login_screen.dart';
import 'package:provider/provider.dart';

import 'src/model/lightspark_client_notifier.dart';
import 'src/screens/home_screen.dart';

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => LightsparkClientNotifier(
        LightsparkWalletClient(
          authProvider: JwtAuthProvider(SecureStorageJwtStorage()),
        ),
      ),
      child: const MyApp(),
    ),
  );
}

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

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

class _MyAppState extends State<MyApp> {
  bool _isLoggedIn = false;
  int _selectedTabIndex = 0;

  [@override](/user/override)
  void didChangeDependencies() {
    super.didChangeDependencies();
    final client = Provider.of<LightsparkClientNotifier>(
      context,
      listen: false,
    ).value;
    client.isAuthorized().then((value) {
      setState(() {
        _isLoggedIn = value;
      });
    });
  }

  Future<bool> _loginWithJwt(String accountId, String jwt) async {
    final client = Provider.of<LightsparkClientNotifier>(
      context,
      listen: false,
    ).value;
    final jwtAuthStorage = SecureStorageJwtStorage();
    await client.loginWithJwt(
      accountId,
      jwt,
      jwtAuthStorage,
    );
    final loggedIn = await client.isAuthorized();
    setState(() {
      _isLoggedIn = loggedIn;
    });
    return loggedIn;
  }

  Future<void> _logout() async {
    final client = Provider.of<LightsparkClientNotifier>(
      context,
      listen: false,
    ).value;
    final authProvider = JwtAuthProvider(
      SecureStorageJwtStorage(),
    );
    await authProvider.logout();
    client.setAuthProvider(authProvider);
    setState(() {
      _isLoggedIn = false;
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData.from(
        useMaterial3: true,
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.blueGrey,
          primary: Colors.black,
        ),
      ).copyWith(
        appBarTheme: const AppBarTheme(
          elevation: 1,
        ),
        elevatedButtonTheme: ElevatedButtonThemeData(
          style: ElevatedButton.styleFrom(minimumSize: const Size(105, 45)),
        ),
        filledButtonTheme: FilledButtonThemeData(
          style: FilledButton.styleFrom(minimumSize: const Size(105, 45)),
        ),
      ),
      home: _isLoggedIn
          ? _buildHomeScreen()
          : LoginScreen(onLogin: _loginWithJwt),
    );
  }

  Widget _buildHomeScreen() {
    return Scaffold(
      body: [
        HomeScreen(onLogin: _loginWithJwt, onLogout: _logout),
        AccountScreen(onLogin: _loginWithJwt, onLogout: _logout)
      ][_selectedTabIndex],
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _selectedTabIndex,
        items: const [
          BottomNavigationBarItem(
            icon: Icon(Icons.wallet),
            label: 'Wallet',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.account_circle),
            label: 'Account',
          ),
        ],
        onTap: (index) {
          setState(() {
            _selectedTabIndex = index;
          });
        },
      ),
    );
  }
}

更多关于Flutter数字货币钱包管理插件lightspark_wallet的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter数字货币钱包管理插件lightspark_wallet的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用lightspark_wallet插件来管理数字货币钱包的示例代码。请注意,实际使用时需要根据lightspark_wallet插件的具体API文档进行调整,因为插件的接口和功能可能会随时间变化。

首先,确保你已经在pubspec.yaml文件中添加了lightspark_wallet依赖项:

dependencies:
  flutter:
    sdk: flutter
  lightspark_wallet: ^最新版本号  # 替换为实际发布的最新版本号

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

接下来,在你的Flutter项目中,你可以按照以下步骤使用lightspark_wallet插件:

  1. 初始化插件并创建钱包
import 'package:flutter/material.dart';
import 'package:lightspark_wallet/lightspark_wallet.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String walletAddress = '';

  @override
  void initState() {
    super.initState();
    _initializeWallet();
  }

  Future<void> _initializeWallet() async {
    try {
      // 初始化LightSpark Wallet插件
      await LightSparkWallet.initialize();

      // 创建一个新的钱包(注意:这只是一个示例,实际使用中应确保钱包的安全存储和管理)
      Wallet? newWallet = await LightSparkWallet.createWallet();

      if (newWallet != null) {
        setState(() {
          walletAddress = newWallet.address;
        });
      }
    } catch (e) {
      print('Error initializing wallet: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('LightSpark Wallet Example'),
        ),
        body: Center(
          child: Text('Your Wallet Address: $walletAddress'),
        ),
      ),
    );
  }
}
  1. 发送交易

在实际应用中,发送交易需要用户输入接收地址、金额等信息,并且需要处理私钥的安全问题。这里仅提供一个简化的示例:

Future<void> _sendTransaction(String recipientAddress, double amount) async {
  try {
    // 假设你已经有了要发送的金额和接收地址
    TransactionRequest request = TransactionRequest(
      recipient: recipientAddress,
      amount: amount,  // 注意:这里可能需要转换为最小单位,例如比特币的聪
      // 其他参数,如gas费、手续费等,根据具体需求设置
    );

    // 发送交易
    TransactionResult? result = await LightSparkWallet.sendTransaction(request);

    if (result != null && result.success) {
      print('Transaction sent successfully!');
    } else {
      print('Failed to send transaction: ${result?.errorMessage}');
    }
  } catch (e) {
    print('Error sending transaction: $e');
  }
}
  1. 查询余额

查询钱包余额同样需要处理网络请求和异步操作:

Future<void> _checkBalance() async {
  try {
    // 获取当前钱包的余额
    BalanceResult? balance = await LightSparkWallet.getBalance();

    if (balance != null) {
      print('Balance: ${balance.amount}');  // 注意:这里的金额单位可能需要根据具体币种调整
    } else {
      print('Failed to get balance.');
    }
  } catch (e) {
    print('Error checking balance: $e');
  }
}

请注意,以上代码仅作为示例,并未包含完整的错误处理和用户交互逻辑。在实际开发中,你需要确保用户输入的验证、私钥的安全存储、交易的确认等关键步骤得到妥善处理。

此外,由于lightspark_wallet插件的具体API和功能可能会变化,请参考插件的官方文档和示例代码进行开发。

回到顶部