payjoin_flutter 0.20.0 copy "payjoin_flutter: ^0.20.0" to clipboard
payjoin_flutter: ^0.20.0 copied to clipboard

A Flutter library for the [Payjoin Dev Kit](https://payjoindevkit.org/)

example/lib/main.dart

import 'dart:convert';

import 'package:bdk_flutter/bdk_flutter.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:payjoin_flutter/common.dart' as common;
import 'package:payjoin_flutter/uri.dart' as pay_join_uri;
import 'package:payjoin_flutter_example/bdk_client.dart';
import 'package:payjoin_flutter_example/payjoin_library.dart';

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

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

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
        debugShowCheckedModeBanner: false, home: PayJoin());
  }
}

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

  @override
  State<PayJoin> createState() => _PayJoinState();
}

class _PayJoinState extends State<PayJoin> {
  static const primaryColor = 0xffC71585;
  PayJoinLibrary payJoinLibrary = PayJoinLibrary();
  final sender = BdkClient(
      "wpkh(tprv8ZgxMBicQKsPdgsqhkRVYkBBULxG3HvyXtwhWKEgfH4bsU8bmaqhdbZvxq4Z7BLFtUrT58ynRDrBcfG3vNpNHsKTV5xCEgRoKaNNzcVW3HW/84'/1'/0'/0/*)#ln3hfgcf",
      Network.signet);
  final receiver = BdkClient(
      "wpkh(tprv8ZgxMBicQKsPfKJjrApLfm2BhWhV1JpL3StS8UPagm91Y215JGZktQKTtvErD92RKxEDYD9Sfc9eGZVkuH94NgEHPhz7rpgzhiNm2UPs1G1/84'/1'/0'/0/*)#h8uywf09",
      Network.signet);

  String displayText = "";
  String pjUri = "";
  late PartiallySignedTransaction senderPsbt;
  late PartiallySignedTransaction processedAndFinalizedPsbt;
  @override
  void initState() {
    sender.restoreWallet();
    receiver.restoreWallet();
    setState(() {
      displayText = "sender & receiver restored";
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: const Color(primaryColor),
        elevation: 0,
        centerTitle: false,
        title: Text('PayJoin App',
            style: GoogleFonts.ibmPlexMono(
                fontWeight: FontWeight.w900,
                fontSize: 18,
                color: Colors.white)), // Set this heigh
      ),
      body: SingleChildScrollView(
        child: Column(
          children: [
            Container(
              margin: const EdgeInsets.only(bottom: 50),
              padding: const EdgeInsets.only(left: 15, right: 15, bottom: 20),
              color: const Color(primaryColor),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.start,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text("Response: ",
                      textAlign: TextAlign.center,
                      style: GoogleFonts.manrope(
                          color: Colors.white,
                          fontSize: 12,
                          fontWeight: FontWeight.w700)),
                  Expanded(
                    child: SelectableText(
                      displayText,
                      maxLines: 3,
                      textAlign: TextAlign.start,
                      style: GoogleFonts.ibmPlexMono(
                          color: Colors.white,
                          fontSize: 12,
                          fontWeight: FontWeight.w700),
                    ),
                  ),
                ],
              ),
            ),
            TextButton(
                onPressed: () async {
                  await sender.syncWallet();
                  await receiver.syncWallet();
                  setState(() {
                    displayText = "sync complete";
                  });
                  debugPrint(
                      "sender balance: ${(sender.getBalance()).toString()}");
                },
                child: Text(
                  "Sync wallets",
                  style: GoogleFonts.manrope(
                      color: Colors.black,
                      fontSize: 14,
                      fontWeight: FontWeight.w800),
                )),
            TextButton(
                onPressed: () async {
                  final address = (receiver.getNewAddress()).address;
                  final res = await payJoinLibrary.buildPjUri(
                      0.0083285, address.toQrUri());
                  setState(() {
                    pjUri = res;
                    displayText = res;
                  });
                },
                child: Text(
                  "Build Receiver pj Uri",
                  style: GoogleFonts.manrope(
                      color: Colors.black,
                      fontSize: 14,
                      fontWeight: FontWeight.w800),
                )),
            TextButton(
                onPressed: () async {
                  final balance = sender.getBalance();
                  debugPrint("Sender Balance: ${balance.toString()}");
                  final uri = await pay_join_uri.Uri.fromStr(pjUri);
                  final address = uri.address();
                  int amount = (((uri.amount()) ?? 0) * 100000000).toInt();
                  final psbt = (await sender.createPsbt(address, amount, 2000));
                  debugPrint(
                    "\nOriginal sender psbt: ${psbt.toString()}",
                  );
                  setState(() {
                    senderPsbt = psbt;
                  });
                },
                child: Text(
                  "Create Sender psbt using receiver pjUri",
                  style: GoogleFonts.manrope(
                      color: Colors.black,
                      fontSize: 14,
                      fontWeight: FontWeight.w800),
                )),
            TextButton(
                onPressed: () async {
                  final (provisionalProposal, contextV1) = await payJoinLibrary
                      .handlePjRequest(senderPsbt.toString(), pjUri, (e) async {
                    final script = ScriptBuf(bytes: e);

                    return (receiver.getAddressInfo(script));
                  });
                  final unspent = receiver.listUnspent();
                  // Select receiver payjoin inputs.
                  Map<BigInt, common.OutPoint> candidateInputs = {
                    for (var input in unspent)
                      input.txout.value: common.OutPoint(
                          txid: input.outpoint.txid.toString(),
                          vout: input.outpoint.vout)
                  };
                  final selectedOutpoint = await provisionalProposal
                      .tryPreservingPrivacy(candidateInputs: candidateInputs);
                  var selectedUtxo = unspent.firstWhere(
                      (i) =>
                          i.outpoint.txid.toString() == selectedOutpoint.txid &&
                          i.outpoint.vout == selectedOutpoint.vout,
                      orElse: () => throw Exception('UTXO not found'));
                  var txoToContribute = common.TxOut(
                    value: selectedUtxo.txout.value,
                    scriptPubkey: selectedUtxo.txout.scriptPubkey.bytes,
                  );

                  var outpointToContribute = common.OutPoint(
                    txid: selectedUtxo.outpoint.txid.toString(),
                    vout: selectedUtxo.outpoint.vout,
                  );

                  await provisionalProposal.contributeWitnessInput(
                      txo: txoToContribute, outpoint: outpointToContribute);
                  final payJoinProposal = await provisionalProposal
                      .finalizeProposal(processPsbt: (e) async {
                    debugPrint("\n Original receiver unsigned psbt: $e");
                    return (await receiver.signPsbt(
                            await PartiallySignedTransaction.fromString(e)))
                        .toString();
                  });
                  final receiverPsbt = await payJoinProposal.psbt();
                  debugPrint("\n Original receiver psbt: $receiverPsbt");
                  final receiverProcessedPsbt = await contextV1.processResponse(
                      response: utf8.encode(receiverPsbt));
                  final senderProcessedPsbt = (await sender.signPsbt(
                      await PartiallySignedTransaction.fromString(
                          receiverProcessedPsbt)));
                  setState(() {
                    processedAndFinalizedPsbt = senderProcessedPsbt;
                  });
                },
                child: Text(
                  "Process and finalize receiver Pj request",
                  style: GoogleFonts.manrope(
                      color: Colors.black,
                      fontSize: 14,
                      fontWeight: FontWeight.w800),
                )),
            TextButton(
                onPressed: () async {
                  final res =
                      await sender.broadcastPsbt(processedAndFinalizedPsbt);
                  debugPrint("Broadcast success: $res");
                },
                child: Text(
                  "Broadcast processed psbt",
                  style: GoogleFonts.manrope(
                      color: Colors.black,
                      fontSize: 14,
                      fontWeight: FontWeight.w800),
                ))
          ],
        ),
      ),
    );
  }
}
5
likes
130
points
65
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter library for the [Payjoin Dev Kit](https://payjoindevkit.org/)

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

collection, ffi, flutter, flutter_rust_bridge, freezed_annotation, meta, uuid

More

Packages that depend on payjoin_flutter

Packages that implement payjoin_flutter