diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index b546f81c..512a852d 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -41,6 +41,9 @@ jobs: - name: Get Flutter packages run: flutter pub get + + - name: Clone Mozilla's CA cert bundle module into root directory + run: git clone https://github.com/Chia-Network/mozilla-ca.git - name: Run simulator tests run: bash ./integration_test/run_tests.sh diff --git a/.gitignore b/.gitignore index a996cb93..44f71209 100644 --- a/.gitignore +++ b/.gitignore @@ -38,4 +38,7 @@ coverage/ # Ignore chialisp main.sym spend_bundle_hex.txt -simulator_gen_path.json \ No newline at end of file +simulator_gen_path.json + +# Ignore logs from exchange commands +exchange-log-*.txt \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 74ae9624..b18cb67c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,10 +1,4 @@ { "editor.defaultFormatter": "Dart-Code.dart-code", "editor.formatOnSave": true, - "dart.lineLength": 100, - "[dart]": { - "editor.rulers": [ - 100 - ], - } } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index c14de190..b9e35d23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Add NFT support - Add Offer support - Bug fixing and code cleanup +- Plot NFT mutation spend ## 1.0.18 diff --git a/bin/README.md b/bin/README.md index fac884b6..24b62614 100644 --- a/bin/README.md +++ b/bin/README.md @@ -28,18 +28,50 @@ dart bin/chia_crypto_utils.dart Get-CoinRecords --full-node-url ## Create Wallet With PlotNFT -Use this command to create a wallet with a new plotNFT: +Use this command to create a wallet with a new plotNFT and register it with a pool. To create a self-pooling plotNFT, omit the pool-url parameter. ```console -dart bin/chia_crypto_utils.dart Create-WalletWithPlotNFT --full-node-url --faucet-request-url --faucet-request-payload '{"address": "SEND_TO_ADDRESS", "amount": 0.0000000001}' -dart bin/chia_crypto_utils.dart Create-WalletWithPlotNFT --full-node-url --cert-path --key-path --faucet-request-url --faucet-request-payload '{"address": "SEND_TO_ADDRESS", "amount": 0.0000000001}' +dart bin/chia_crypto_utils.dart Create-WalletWithPlotNFT --full-node-url --faucet-request-url --faucet-request-payload '{"address": "SEND_TO_ADDRESS", "amount": 0.0000000001}' --pool-url +dart bin/chia_crypto_utils.dart Create-WalletWithPlotNFT --full-node-url --cert-path --key-path --faucet-request-url --faucet-request-payload '{"address": "SEND_TO_ADDRESS", "amount": 0.0000000001}' --pool-url ``` -Can also omit the faucet url and payload if you would like to manually send the XCH needed to create the PlotNFT: +Can also omit the faucet url and payload if you would like to manually send the XCH needed to create the plotNFT: ```console -dart bin/chia_crypto_utils.dart Create-WalletWithPlotNFT --full-node-url -dart bin/chia_crypto_utils.dart Create-WalletWithPlotNFT --full-node-url --cert-path --key-path +dart bin/chia_crypto_utils.dart Create-WalletWithPlotNFT --full-node-url --pool-url +dart bin/chia_crypto_utils.dart Create-WalletWithPlotNFT --full-node-url --cert-path --key-path --pool-url +``` + +## Mutate PlotNFT + +Use this command to leave a pool. + +```console +dart bin/chia_crypto_utils.dart Mutate-PlotNFT --full-node-url --faucet-request-url --faucet-request-payload '{"address": "SEND_TO_ADDRESS", "amount": 0.0000000001}' --mnemonic "mnemonic seed" +dart bin/chia_crypto_utils.dart Mutate-PlotNFT --full-node-url --cert-path --key-path --faucet-request-url --faucet-request-payload '{"address": "SEND_TO_ADDRESS", "amount": 0.0000000001}' --mnemonic "mnemonic seed" +``` + +Can also omit the faucet url and payload if you would like to manually send the XCH needed to mutate the plotNFT: + +```console +dart bin/chia_crypto_utils.dart Mutate-PlotNFT --full-node-url --mnemonic "mnemonic seed" +dart bin/chia_crypto_utils.dart Mutate-PlotNFT --full-node-url --cert-path --key-path --mnemonic "mnemonic seed" +``` + +## Register PlotNFT + +Use this command to register a PlotNFT with a pool. Should already be in farming to pool state. + +```console +dart bin/chia_crypto_utils.dart Register-PlotNFT --full-node-url --faucet-request-url --faucet-request-payload '{"address": "SEND_TO_ADDRESS", "amount": 0.0000000001}' --mnemonic "mnemonic seed" --launcher-id --pool-url +dart bin/chia_crypto_utils.dart Register-PlotNFT --full-node-url --cert-path --key-path --faucet-request-url --faucet-request-payload '{"address": "SEND_TO_ADDRESS", "amount": 0.0000000001}' --mnemonic "mnemonic seed" --launcher-id --pool-url +``` + +Can also omit the faucet url and payload if you would like to manually send the XCH needed to mutate the plotNFT: + +```console +dart bin/chia_crypto_utils.dart Register-PlotNFT --full-node-url --mnemonic "mnemonic seed" --launcher-id --pool-url +dart bin/chia_crypto_utils.dart Register-PlotNFT --full-node-url --cert-path --key-path --mnemonic "mnemonic seed" --launcher-id --pool-url ``` ## Get Farming Status diff --git a/bin/chia_crypto_utils.dart b/bin/chia_crypto_utils.dart index 426ec152..12bda22a 100644 --- a/bin/chia_crypto_utils.dart +++ b/bin/chia_crypto_utils.dart @@ -10,6 +10,7 @@ import 'package:chia_crypto_utils/src/command/core/nuke_keychain.dart'; import 'package:chia_crypto_utils/src/command/exchange/cross_chain_offer_exchange.dart'; import 'package:chia_crypto_utils/src/command/exchange/exchange_btc.dart'; import 'package:chia_crypto_utils/src/command/plot_nft/create_new_wallet_with_plotnft.dart'; +import 'package:chia_crypto_utils/src/command/plot_nft/get_coins_for_command.dart'; import 'package:chia_crypto_utils/src/core/resources/bip_39_words.dart'; late final ChiaFullNodeInterface fullNode; @@ -29,8 +30,10 @@ Future main(List args) async { ..argParser.addOption('cert-path', defaultsTo: '') ..argParser.addOption('key-path', defaultsTo: '') ..addCommand(CreateWalletWithPlotNFTCommand()) + ..addCommand(RegisterPlotNFTCommand()) ..addCommand(GetFarmingStatusCommand()) ..addCommand(GetCoinRecords()) + ..addCommand(MutatePlotNFTCommand()) ..addCommand(ExchangeBtcCommand()) ..addCommand(CrossChainOfferExchangeCommand()) ..addCommand(BurnDid()) @@ -49,7 +52,8 @@ Future main(List args) async { } // Configure environment based on user selections - LoggingContext().setLogLevel(LogLevel.fromString(results['log-level'] as String)); + LoggingContext() + .setLogLevel(LogLevel.fromString(results['log-level'] as String)); LoggingContext().setLogger((text) { stderr.write('$text\n'); }); @@ -60,15 +64,18 @@ Future main(List args) async { // construct the Chia full node interface var fullNodeUrl = results['full-node-url'] as String; - if (fullNodeUrl.endsWith('/')) fullNodeUrl = fullNodeUrl.substring(0, fullNodeUrl.length - 1); + if (fullNodeUrl.endsWith('/')) { + fullNodeUrl = fullNodeUrl.substring(0, fullNodeUrl.length - 1); + } final certBytesPath = results['cert-path'] as String; final keyBytesPath = results['key-path'] as String; if ((certBytesPath.isEmpty && keyBytesPath.isNotEmpty) || (certBytesPath.isNotEmpty && keyBytesPath.isEmpty)) { - LoggingContext() - .info('\nTo use options cert-path and key-path both parameters must be provided.'); + LoggingContext().info( + '\nTo use options cert-path and key-path both parameters must be provided.', + ); } else if (certBytesPath.isNotEmpty && keyBytesPath.isNotEmpty) { try { fullNode = ChiaFullNodeInterface.fromURL( @@ -80,7 +87,9 @@ Future main(List args) async { LoggingContext().error( '\nThere is a problem with the full node information you provided. Please try again.', ); - LoggingContext().error('\nThe full node should be in the form https://.\n'); + LoggingContext().error( + '\nThe full node should be in the form https://.\n', + ); LoggingContext().error( '\nex: When using a locally synced full node you can specify https://localhost:8555', ); @@ -93,8 +102,9 @@ Future main(List args) async { try { await fullNode.getBlockchainState(); } catch (e) { - LoggingContext() - .error("\nCouldn't verify full node running at URL you provided. Please try again."); + LoggingContext().error( + "\nCouldn't verify full node running at URL you provided. Please try again.", + ); exit(126); } @@ -119,7 +129,8 @@ class GetCoinRecords extends Command> { } @override - String get description => 'Gets coin records for a given address or puzzlehash'; + String get description => + 'Gets coin records for a given address or puzzlehash'; @override String get name => 'Get-CoinRecords'; @@ -171,8 +182,8 @@ class GetCoinRecords extends Command> { class CreateWalletWithPlotNFTCommand extends Command> { CreateWalletWithPlotNFTCommand() { argParser - ..addOption('pool-url', defaultsTo: 'https://xch-us-west.flexpool.io') - ..addOption('faucet-request-url') + ..addOption('pool-url', defaultsTo: '') + ..addOption('faucet-request-url', defaultsTo: '') ..addOption('faucet-request-payload', defaultsTo: '') ..addOption('output-config', defaultsTo: '') ..addOption( @@ -190,14 +201,13 @@ class CreateWalletWithPlotNFTCommand extends Command> { @override Future run() async { final faucetRequestURL = argResults!['faucet-request-url'] as String; - final faucetRequestPayload = argResults!['faucet-request-payload'] as String; + final faucetRequestPayload = + argResults!['faucet-request-payload'] as String; final outputConfigFile = argResults!['output-config'] as String; - final poolService = _getPoolServiceImpl( - argResults!['pool-url'] as String, - argResults!['certificate-bytes-path'] as String, - ); + final poolUrl = argResults!['pool-url'] as String; + final mnemonicPhrase = generateMnemonic(strength: 256); final mnemonic = mnemonicPhrase.split(' '); print('Mnemonic Phrase: $mnemonicPhrase'); @@ -207,7 +217,8 @@ class CreateWalletWithPlotNFTCommand extends Command> { keychainSecret, ); - final farmerPublicKeyHex = masterSkToFarmerSk(keychainSecret.masterPrivateKey).getG1().toHex(); + final farmerPublicKeyHex = + masterSkToFarmerSk(keychainSecret.masterPrivateKey).getG1().toHex(); print('Farmer public key: $farmerPublicKeyHex'); final coinAddress = Address.fromPuzzlehash( @@ -215,51 +226,29 @@ class CreateWalletWithPlotNFTCommand extends Command> { ChiaNetworkContextWrapper().blockchainNetwork.addressPrefix, ); - if (faucetRequestURL.isNotEmpty && faucetRequestPayload.isNotEmpty) { - final theFaucetRequestPayload = - faucetRequestPayload.replaceAll(RegExp('SEND_TO_ADDRESS'), coinAddress.address); - - final result = await Process.run('curl', [ - '-s', - '-d', - theFaucetRequestPayload, - '-H', - 'Content-Type: application/json', - '-X', - 'POST', - faucetRequestURL, - ]); - - stdout.write(result.stdout); - stderr.write(result.stderr); - } else { - print( - 'Please send at least 1 mojo and enough extra XCH to cover the fee to create the PlotNFT to: ${coinAddress.address}\n', - ); - print('Press any key when coin has been sent'); - stdin.readLineSync(); - } + await getCoinsForCommand( + faucetRequestURL: faucetRequestURL, + faucetRequestPayload: faucetRequestPayload, + puzzlehashes: keychain.puzzlehashes, + fullNode: fullNode, + message: + 'Please send 1 mojo and enough XCH to cover the fee to create a Ploft NFT to', + ); - var coins = []; - while (coins.isEmpty) { - print('waiting for coin...'); - await Future.delayed(const Duration(seconds: 3)); - coins = await fullNode.getCoinsByPuzzleHashes( - keychain.puzzlehashes, - includeSpentCoins: true, + PoolService? poolService; + if (poolUrl.isNotEmpty) { + poolService = _getPoolServiceImpl( + poolUrl, + argResults!['certificate-bytes-path'] as String, ); - - if (coins.isNotEmpty) { - print(coins); - } } try { final plotNFTDetails = await createNewWalletWithPlotNFT( - keychainSecret, - keychain, - poolService, - fullNode, + keychainSecret: keychainSecret, + keychain: keychain, + fullNode: fullNode, + poolService: poolService, ); if (outputConfigFile.isNotEmpty) { @@ -282,6 +271,142 @@ class CreateWalletWithPlotNFTCommand extends Command> { } } +class RegisterPlotNFTCommand extends Command> { + RegisterPlotNFTCommand() { + argParser + ..addOption('pool-url', defaultsTo: 'https://xch.spacefarmers.io') + ..addOption('mnemonic', defaultsTo: '') + ..addOption('launcher-id') + ..addOption('payout-address', defaultsTo: '') + ..addOption( + 'certificate-bytes-path', + defaultsTo: 'mozilla-ca/cacert.pem', + ); + } + + @override + String get description => + 'Registers a plotNFT with a pool. Should already be in farming to pool state.'; + + @override + String get name => 'Register-PlotNFT'; + + @override + Future run() async { + final poolUrl = argResults!['pool-url'] as String; + final launcherIdString = argResults!['launcher-id'] as String; + var payoutAddressString = argResults!['payout-address'] as String; + + var mnemonicPhrase = argResults!['mnemonic'] as String; + + try { + await PoolInterface.fromURL(poolUrl).getPoolInfo(); + } catch (e) { + throw ArgumentError('Invalid pool-url.'); + } + + if (mnemonicPhrase.isEmpty) { + print( + '\nPlease enter the mnemonic with the plot NFT you would like to register:', + ); + stdout.write('> '); + mnemonicPhrase = stdin.readLineSync()!; + } + + final mnemonic = mnemonicPhrase.split(' '); + + if (mnemonic.length != 12 && mnemonic.length != 24) { + throw ArgumentError( + '\nInvalid current mnemonic phrase. Must contain either 12 or 24 seed words', + ); + } + + final keychainSecret = KeychainCoreSecret.fromMnemonic(mnemonic); + final keychain = WalletKeychain.fromCoreSecret(keychainSecret); + + Puzzlehash? payoutPuzzlehash; + if (payoutAddressString.isEmpty) { + payoutPuzzlehash = keychain.puzzlehashes[1]; + print( + 'Payout Address: ${payoutPuzzlehash.toAddressWithContext().address}', + ); + } else { + Address? payoutAddress; + while (payoutAddress == null) { + try { + payoutAddress = Address(payoutAddressString); + } catch (e) { + print( + '\nPlease enter a valid address for the new owner pool payout address:', + ); + stdout.write('> '); + payoutAddressString = stdin.readLineSync()!; + } + } + payoutPuzzlehash = payoutAddress.toPuzzlehash(); + } + + final farmerPublicKeyHex = + masterSkToFarmerSk(keychainSecret.masterPrivateKey).getG1().toHex(); + print('Farmer public key: $farmerPublicKeyHex'); + + final plotNft = + await fullNode.getPlotNftByLauncherId(launcherIdString.hexToBytes()); + + if (plotNft == null) { + throw ArgumentError('Invalid launcher-id'); + } + + final ownerPublicKey = plotNft.poolState.ownerPublicKey; + + keychain.addSingletonWalletVectorForSingletonOwnerPublicKey( + ownerPublicKey, + keychainSecret.masterPrivateKey, + ); + + final singletonWalletVector = + keychain.getSingletonWalletVector(ownerPublicKey); + + final poolService = _getPoolServiceImpl( + poolUrl, + argResults!['certificate-bytes-path'] as String, + ); + + final addFarmerResponse = await poolService.registerAsFarmerWithPool( + plotNft: plotNft, + singletonWalletVector: singletonWalletVector!, + payoutPuzzlehash: payoutPuzzlehash, + ); + print('Pool welcome message: ${addFarmerResponse.welcomeMessage}'); + + GetFarmerResponse? farmerInfo; + var attempts = 0; + while (farmerInfo == null && attempts < 6) { + print('waiting for farmer information to become available...'); + try { + attempts = attempts + 1; + await Future.delayed(const Duration(seconds: 15)); + farmerInfo = await poolService.getFarmerInfo( + authenticationPrivateKey: + singletonWalletVector.poolingAuthenticationPrivateKey, + launcherId: plotNft.launcherId, + ); + } on PoolResponseException catch (e) { + if (e.poolErrorResponse.responseCode != PoolErrorState.farmerNotKnown) { + rethrow; + } + if (attempts == 5) { + print(e.poolErrorResponse.message); + } + } + } + + if (farmerInfo != null) { + print(farmerInfo); + } + } +} + class GetFarmingStatusCommand extends Command> { GetFarmingStatusCommand() { argParser.addOption( @@ -342,6 +467,111 @@ class GetFarmingStatusCommand extends Command> { } } +class MutatePlotNFTCommand extends Command> { + MutatePlotNFTCommand() { + argParser + ..addOption('mnemonic', defaultsTo: '') + ..addOption('pool-url', defaultsTo: 'https://xch.spacefarmers.io') + ..addOption( + 'certificate-bytes-path', + defaultsTo: 'mozilla-ca/cacert.pem', + ) + ..addOption('faucet-request-url', defaultsTo: '') + ..addOption('faucet-request-payload', defaultsTo: ''); + } + + @override + String get description => 'Mutate plot NFT to leave pool.'; + + @override + String get name => 'Mutate-PlotNFT'; + + @override + Future run() async { + var mnemonicPhrase = argResults!['mnemonic'] as String; + final poolUrl = argResults!['pool-url'] as String; + final faucetRequestURL = argResults!['faucet-request-url'] as String; + final faucetRequestPayload = + argResults!['faucet-request-payload'] as String; + + final plotNftWalletService = PlotNftWalletService(); + + try { + await PoolInterface.fromURL(poolUrl).getPoolInfo(); + } catch (e) { + throw ArgumentError('Invalid pool-url.'); + } + + if (mnemonicPhrase.isEmpty) { + print( + '\nPlease enter the mnemonic with the plot NFT you would like to transfer:', + ); + stdout.write('> '); + mnemonicPhrase = stdin.readLineSync()!; + } + + final mnemonic = mnemonicPhrase.split(' '); + + if (mnemonic.length != 12 && mnemonic.length != 24) { + throw ArgumentError( + '\nInvalid current mnemonic phrase. Must contain either 12 or 24 seed words', + ); + } + + final keychainSecret = KeychainCoreSecret.fromMnemonic(mnemonic); + final keychain = WalletKeychain.fromCoreSecret(keychainSecret); + + final plotNfts = await fullNode.scroungeForPlotNfts(keychain.puzzlehashes); + + if (plotNfts.isEmpty) { + throw ArgumentError('There are no plot NFTs on the current mnemonic.'); + } + + final coins = await getCoinsForCommand( + faucetRequestURL: faucetRequestURL, + faucetRequestPayload: faucetRequestPayload, + puzzlehashes: keychain.puzzlehashes, + fullNode: fullNode, + message: 'Please send 50 mojos to cover the fee to', + ); + + final plotNft = plotNfts[0]; + + print('\nStarting Pool State: ${plotNft.poolState}\n'); + + final singletonWalletVector = + keychain.getNextSingletonWalletVector(keychainSecret.masterPrivateKey); + + final poolInfo = await PoolInterface.fromURL(poolUrl).getPoolInfo(); + + final targetState = PoolState( + poolSingletonState: PoolSingletonState.leavingPool, + targetPuzzlehash: poolInfo.targetPuzzlehash, + ownerPublicKey: singletonWalletVector.singletonOwnerPublicKey, + relativeLockHeight: 0, + ); + + final plotNftMutationSpendBundle = + await plotNftWalletService.createPlotNftMutationSpendBundle( + plotNft: plotNft, + coinsForFee: coins, + fee: 49, + targetState: targetState, + keychain: keychain, + changePuzzleHash: keychain.puzzlehashes.first, + ); + + print('Pushing plot NFT mutation spend bundle\n'); + + await fullNode.pushAndWaitForSpendBundle(plotNftMutationSpendBundle); + + final mutatedPlotNft = + await fullNode.getPlotNftByLauncherId(plotNft.launcherId); + + print('\nEnding Pool State: ${mutatedPlotNft!.poolState}'); + } +} + class ExchangeBtcCommand extends Command> { ExchangeBtcCommand(); @@ -361,31 +591,29 @@ class CrossChainOfferExchangeCommand extends Command> { CrossChainOfferExchangeCommand(); @override - String get description => 'Initiates a cross chain offer exchange between XCH and BTC'; + String get description => + 'Initiates a cross chain offer exchange between XCH and BTC'; @override String get name => 'Make-CrossChainOfferExchange'; @override Future run() async { - print('\nAre you making a new cross chain offer, accepting an existing one, or'); - print('continuing an ongoing exchange?'); - print('\n1. Making cross chain offer'); - print('2. Accepting cross chain offer'); - print('3. Continuing ongoing exchange'); + print( + '\nAre you making a new cross chain offer or taking an existing offer?', + ); + print('\n1. Making offer'); + print('2. Taking offer'); String? choice; - - while (choice != '1' && choice != '2' && choice != '3') { + while (choice != '1' && choice != '2') { stdout.write('> '); choice = stdin.readLineSync()!.trim(); if (choice == '1') { await makeCrossChainOffer(fullNode); } else if (choice == '2') { - await acceptCrossChainOffer(fullNode); - } else if (choice == '3') { - await resumeCrossChainOfferExchange(fullNode); + await takeCrossChainOffer(fullNode); } else { print('\nNot a valid choice.'); } @@ -412,14 +640,16 @@ class NukeKeychain extends Command> { Future run() async { final mnemonic = argResults!['mnemonic'] as String; final walletSize = parseArgument(argResults!['wallet-size'], int.parse)!; - final burnBundleSize = parseArgument(argResults!['burn-bundle-size'], int.parse)!; + final burnBundleSize = + parseArgument(argResults!['burn-bundle-size'], int.parse)!; final feePerCoin = parseArgument(argResults!['fee-per-coin'], int.parse)!; final keychain = WalletKeychain.fromCoreSecret( KeychainCoreSecret.fromMnemonicString(mnemonic), walletSize: walletSize, ); - final enhancedFullNode = EnhancedChiaFullNodeInterface.fromUrl(fullNode.fullNode.baseURL); + final enhancedFullNode = + EnhancedChiaFullNodeInterface.fromUrl(fullNode.fullNode.baseURL); await nukeKeychain( keychain: keychain, fullNode: enhancedFullNode, @@ -448,24 +678,28 @@ class BurnDid extends Command> { @override Future run() async { final mnemonic = argResults!['mnemonic'] as String; - final did = parseArgument(argResults!['did'], DidInfo.parseDidFromEitherFormat)!; + final did = + parseArgument(argResults!['did'], DidInfo.parseDidFromEitherFormat)!; final walletSize = parseArgument(argResults!['wallet-size'], int.parse)!; final fee = parseArgument(argResults!['fee'], int.parse)!; final keychain = WalletKeychain.fromCoreSecret( KeychainCoreSecret.fromMnemonicString(mnemonic), walletSize: walletSize, ); - final enhancedFullNode = EnhancedChiaFullNodeInterface.fromUrl(fullNode.fullNode.baseURL); + final enhancedFullNode = + EnhancedChiaFullNodeInterface.fromUrl(fullNode.fullNode.baseURL); final didWalletService = DIDWalletService(); print('searching for DID'); - final didInfos = await enhancedFullNode.getDidRecordsByHints(keychain.puzzlehashes); + final didInfos = + await enhancedFullNode.getDidRecordsByHints(keychain.puzzlehashes); final matchingDids = didInfos.where((element) => element.did == did); if (matchingDids.isEmpty) { print("couldn't find did by keychain hints"); exit(1); } - final standardCoins = await enhancedFullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); + final standardCoins = + await enhancedFullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); final coinsForFee = selectCoinsForAmount(standardCoins, fee); @@ -484,7 +718,8 @@ class BurnDid extends Command> { await enhancedFullNode.pushTransaction(combinedSpendBundle); print('pushed DID burn spend bundle'); - await BlockchainUtils(enhancedFullNode, logger: print).waitForSpendBundle(combinedSpendBundle); + await BlockchainUtils(enhancedFullNode, logger: print) + .waitForSpendBundle(combinedSpendBundle); exit(0); } } @@ -509,7 +744,8 @@ class InspectDid extends Command> { final mnemonic = argResults!['mnemonic'] as String; final searchTypeName = argResults!['search-by'] as String; - final did = parseArgument(argResults!['did'], DidInfo.parseDidFromEitherFormat)!; + final did = + parseArgument(argResults!['did'], DidInfo.parseDidFromEitherFormat)!; final walletSize = parseArgument(argResults!['wallet-size'], int.parse)!; @@ -519,12 +755,14 @@ class InspectDid extends Command> { ); final searchType = DidSearchType.fromName(searchTypeName); - final enhancedFullNode = EnhancedChiaFullNodeInterface.fromUrl(fullNode.fullNode.baseURL); + final enhancedFullNode = + EnhancedChiaFullNodeInterface.fromUrl(fullNode.fullNode.baseURL); print('searching for did'); final didInfo = (await () async { switch (searchType) { case DidSearchType.hints: - final didInfos = await enhancedFullNode.getDidRecordsByHints(keychain.puzzlehashes); + final didInfos = await enhancedFullNode + .getDidRecordsByHints(keychain.puzzlehashes); final matchingDids = didInfos.where((element) => element.did == did); if (matchingDids.isEmpty) { return null; @@ -545,7 +783,9 @@ class InspectDid extends Command> { print('did: $did'); print('p2_puzzle_hash: ${didInfo.p2Puzzle.hash()}'); - final privateKey = keychain.getWalletVectorOrThrow(didInfo.p2Puzzle.hash()).childPrivateKey; + final privateKey = keychain + .getWalletVectorOrThrow(didInfo.p2Puzzle.hash()) + .childPrivateKey; print('did_private_key: ${privateKey.toHex()}'); } @@ -587,7 +827,8 @@ class TransferDidCommand extends Command> { } final secret = KeychainCoreSecret.fromMnemonic(mnemonic); print('\nkeychain fingerprint: ${secret.fingerprint}'); - final keychain = WalletKeychain.fromCoreSecret(secret, walletSize: walletSize); + final keychain = + WalletKeychain.fromCoreSecret(secret, walletSize: walletSize); final coins = await fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); final dids = currentDidAddress != null ? await fullNode.getDidRecordsFromHint(currentDidAddress.toPuzzlehash()) @@ -601,7 +842,9 @@ class TransferDidCommand extends Command> { minMojos: 20, ); } on InsufficientBalanceException catch (e) { - print('Insufficient balance to cover fee of $fee mojos: ${e.currentBalance} mojos'); + print( + 'Insufficient balance to cover fee of $fee mojos: ${e.currentBalance} mojos', + ); return null; } }(); @@ -643,7 +886,9 @@ class TransferDidCommand extends Command> { final spendableDid = didToTransfer.toDidInfo(keychain); if (spendableDid == null) { - print('Could not match inner puzzle for ${didToTransfer.did} with this keychain'); + print( + 'Could not match inner puzzle for ${didToTransfer.did} with this keychain', + ); exit(exitCode); } @@ -671,7 +916,9 @@ void printUsage(CommandRunner runner) { } void parseHelp(ArgResults results, CommandRunner runner) { - if (results.command == null || results.wasParsed('help') || results.command?.name == 'help') { + if (results.command == null || + results.wasParsed('help') || + results.command?.name == 'help') { if (results.arguments.isEmpty || results.command == null) { print('No command was provided.'); } diff --git a/bin/general_tools.dart b/bin/general_tools.dart index f70aad81..606bd40f 100644 --- a/bin/general_tools.dart +++ b/bin/general_tools.dart @@ -23,7 +23,8 @@ void main(List args) { parseHelp(results, runner); - LoggingContext().setLogLevel(LogLevel.fromString(results['log-level'] as String)); + LoggingContext() + .setLogLevel(LogLevel.fromString(results['log-level'] as String)); runner.run(args); } diff --git a/example/cold_wallet/main.dart b/example/cold_wallet/main.dart index a23a406f..ed1d12cc 100644 --- a/example/cold_wallet/main.dart +++ b/example/cold_wallet/main.dart @@ -5,6 +5,6 @@ import 'package:test/test.dart'; void main() async { test('generate an offline cold wallet', () { - expect(createColdWallet, returnsNormally); + expect(createColdWallet, returnsNormally); }); } diff --git a/integration_test/api_test/coin_market_cap_test.dart b/integration_test/api_test/coin_market_cap_test.dart index 7ba0ef53..d267a9aa 100644 --- a/integration_test/api_test/coin_market_cap_test.dart +++ b/integration_test/api_test/coin_market_cap_test.dart @@ -8,8 +8,11 @@ Future main() async { expect( coinMarketCapApi.getLatestQuoteById, throwsA( - isA() - .having((e) => e.message, 'an error message', equals('API key missing.')), + isA().having( + (e) => e.message, + 'an error message', + equals('API key missing.'), + ), ), ); }); @@ -19,8 +22,11 @@ Future main() async { expect( coinMarketCapApi.getLatestQuoteById, throwsA( - isA() - .having((e) => e.message, 'an error message', equals('This API Key is invalid.')), + isA().having( + (e) => e.message, + 'an error message', + equals('This API Key is invalid.'), + ), ), ); }); diff --git a/integration_test/api_test/dexie/dexie_test.dart b/integration_test/api_test/dexie/dexie_test.dart index bdf5c223..34d5ade7 100644 --- a/integration_test/api_test/dexie/dexie_test.dart +++ b/integration_test/api_test/dexie/dexie_test.dart @@ -5,13 +5,15 @@ void main() { final api = DexieOffersApi(); test('should fetch offer', () async { - final offer = await api.inspectOffer('3XmDauuggBsiUbUi9o8m4Gip69xf82rPqedT1C99svQk'); + final offer = + await api.inspectOffer('3XmDauuggBsiUbUi9o8m4Gip69xf82rPqedT1C99svQk'); expect(offer!.serializedOffer, rawOffer); }); test('should return null on phoney id', () async { - final offer = await api.inspectOffer('4XmDauuggBsibUi9o8m4Gip69xf82rPqedT1C99svQk'); + final offer = + await api.inspectOffer('4XmDauuggBsibUi9o8m4Gip69xf82rPqedT1C99svQk'); expect(offer, isNull); }); diff --git a/integration_test/api_test/enhanced_full_node_interface_test.dart b/integration_test/api_test/enhanced_full_node_interface_test.dart index d7aad959..22ff9dbf 100644 --- a/integration_test/api_test/enhanced_full_node_interface_test.dart +++ b/integration_test/api_test/enhanced_full_node_interface_test.dart @@ -18,7 +18,8 @@ Future main() async { SimulatorUtils.simulatorUrl, ); - final enhancedFullNode = EnhancedChiaFullNodeInterface(enhancedFullNodeHttpRpc); + final enhancedFullNode = + EnhancedChiaFullNodeInterface(enhancedFullNodeHttpRpc); final fullNode = SimulatorFullNodeInterface.withDefaultUrl(); @@ -28,13 +29,15 @@ Future main() async { final keychainSecret = KeychainCoreSecret.generate(); - final keychain = WalletKeychain.fromCoreSecret(keychainSecret, walletSize: 100); + final keychain = + WalletKeychain.fromCoreSecret(keychainSecret, walletSize: 100); ChiaNetworkContextWrapper().registerNetworkContext(Network.mainnet); final senderPuzzlehash = keychain.unhardenedMap.values.toList()[0].puzzlehash; final senderAddress = Address.fromContext(senderPuzzlehash); - final receiverPuzzlehash = keychain.unhardenedMap.values.toList()[1].puzzlehash; + final receiverPuzzlehash = + keychain.unhardenedMap.values.toList()[1].puzzlehash; for (var i = 0; i < 4; i++) { await fullNode.farmCoins(senderAddress); @@ -47,10 +50,12 @@ Future main() async { test('should correctly get paginated coins ', () async { for (var i = 0; i < 25; i++) { - await fullNode.farmCoins(keychain.puzzlehashes.random.toAddressWithContext()); + await fullNode + .farmCoins(keychain.puzzlehashes.random.toAddressWithContext()); await fullNode.moveToNextBlock(); - final coins = await fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); + final coins = + await fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); final spendBundle = standardWalletService.createSpendBundle( payments: [ @@ -95,7 +100,8 @@ Future main() async { PaginatedCoins? paginatedResponse; Bytes? lastId; do { - paginatedResponse = await enhancedFullNode.getCoinsByPuzzleHashesPaginated( + paginatedResponse = + await enhancedFullNode.getCoinsByPuzzleHashesPaginated( puzzlehashes, 5, includeSpentCoins: true, @@ -111,7 +117,8 @@ Future main() async { expectListEquality( expectedUnspentCoins, paginatedUnspentCoins, - (item) => item.toCoinBytes() + (item.parentSpend?.toBytes() ?? Bytes.empty), + (item) => + item.toCoinBytes() + (item.parentSpend?.toBytes() ?? Bytes.empty), ); expectListEquality( @@ -125,14 +132,20 @@ Future main() async { final hints = keychain.puzzlehashes; for (var i = 0; i < 20; i++) { - await fullNode.farmCoins(keychain.puzzlehashes.random.toAddressWithContext()); + await fullNode + .farmCoins(keychain.puzzlehashes.random.toAddressWithContext()); await fullNode.moveToNextBlock(); - final coins = await fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); + final coins = + await fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); final spendBundle = standardWalletService.createSpendBundle( payments: [ - Payment(coins[0].amount, receiverPuzzlehash, memos: [hints[i]]), + Payment( + coins[0].amount, + receiverPuzzlehash, + memos: [hints[i]], + ), ], coinsInput: [coins[0]], changePuzzlehash: senderPuzzlehash, @@ -189,7 +202,8 @@ Future main() async { expectListEquality( expectedUnspentCoins, paginatedUnspentCoins, - (item) => item.toCoinBytes() + (item.parentSpend?.toBytes() ?? Bytes.empty), + (item) => + item.toCoinBytes() + (item.parentSpend?.toBytes() ?? Bytes.empty), ); expectListEquality( @@ -205,7 +219,10 @@ Future main() async { ); for (final spentCoin in expectedSpentCoins) { - expect(spentCoin.coinSpend.toBytes(), coinSpends[spentCoin.id]!.toBytes()); + expect( + spentCoin.coinSpend.toBytes(), + coinSpends[spentCoin.id]!.toBytes(), + ); } }); group('Should additions with hints', () { @@ -213,8 +230,8 @@ Future main() async { test('at block height $blockHeight', () async { // print('testing block at height $blockHeight'); final block = await fullNode.getBlockRecordByHeight(blockHeight); - final additionsAndRemovals = - await fullNode.getAdditionsAndRemovals(block.blockRecord!.headerHash); + final additionsAndRemovals = await fullNode + .getAdditionsAndRemovals(block.blockRecord!.headerHash); print('expected additions: ${additionsAndRemovals.additions.length}'); print('expected removals: ${additionsAndRemovals.removals.length}'); @@ -223,12 +240,13 @@ Future main() async { '$blockHeight: ${additionsAndRemovals.additions.length + additionsAndRemovals.removals.length}', ); - final additionsAndRemovalsWithHints = - await enhancedFullNode.getAdditionsAndRemovalsWithHints(block.blockRecord!.headerHash); + final additionsAndRemovalsWithHints = await enhancedFullNode + .getAdditionsAndRemovalsWithHints(block.blockRecord!.headerHash); var progress = 0; for (final expectedItem in additionsAndRemovals.removals) { - final matchingItemWithHint = (additionsAndRemovalsWithHints.removals).singleWhere( + final matchingItemWithHint = + (additionsAndRemovalsWithHints.removals).singleWhere( (element) => element.id == expectedItem.id, ); final hint = matchingItemWithHint.hint; @@ -237,11 +255,13 @@ Future main() async { if (spend == null) { continue; } - final hint = spend.memosSync - .firstWhereOrNull((element) => element.length == Puzzlehash.bytesLength); + final hint = spend.memosSync.firstWhereOrNull( + (element) => element.length == Puzzlehash.bytesLength, + ); expect( - await fullNode.getCoinsByHints([if (hint != null) Puzzlehash(hint)]), + await fullNode + .getCoinsByHints([if (hint != null) Puzzlehash(hint)]), isEmpty, ); } else if (hint.length < Puzzlehash.bytesLength) { @@ -278,11 +298,14 @@ Future main() async { test('should correctly get coins by ids', () async { for (var i = 0; i < 20; i++) { - await fullNode.farmCoins(keychain.puzzlehashes.random.toAddressWithContext()); + await fullNode + .farmCoins(keychain.puzzlehashes.random.toAddressWithContext()); } - final coins = - (await fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes, includeSpentCoins: true)) - .toList(); + final coins = (await fullNode.getCoinsByPuzzleHashes( + keychain.puzzlehashes, + includeSpentCoins: true, + )) + .toList(); final then = DateTime.now(); diff --git a/integration_test/api_test/enhanced_full_node_network_test.dart b/integration_test/api_test/enhanced_full_node_network_test.dart index be3a3c31..9a083c36 100644 --- a/integration_test/api_test/enhanced_full_node_network_test.dart +++ b/integration_test/api_test/enhanced_full_node_network_test.dart @@ -8,8 +8,10 @@ import 'test_wallets.dart'; void main() { const url = 'FULL_NODE_URL'; - const enhancedFullNodeHttpRpc = EnhancedFullNodeHttpRpc(url, timeout: Duration(seconds: 30)); - const enhancedFullNode = EnhancedChiaFullNodeInterface(enhancedFullNodeHttpRpc); + const enhancedFullNodeHttpRpc = + EnhancedFullNodeHttpRpc(url, timeout: Duration(seconds: 30)); + const enhancedFullNode = + EnhancedChiaFullNodeInterface(enhancedFullNodeHttpRpc); const fullNodeRpc = FullNodeHttpRpc( url, @@ -50,10 +52,12 @@ void main() { final expectedSpendCoins = []; - for (final spentCoin in expectedCoins.where((element) => element.isSpent)) { + for (final spentCoin + in expectedCoins.where((element) => element.isSpent)) { final coinSpend = await enhancedFullNode.getCoinSpend(spentCoin); - expectedSpendCoins.add(SpentCoin.fromCoinSpend(spentCoin, coinSpend!)); + expectedSpendCoins + .add(SpentCoin.fromCoinSpend(spentCoin, coinSpend!)); } final paginatedUnspentCoins = []; @@ -61,7 +65,8 @@ void main() { PaginatedCoins? paginatedResponse; Bytes? lastId; do { - paginatedResponse = await enhancedFullNode.getCoinsByPuzzleHashesPaginated( + paginatedResponse = + await enhancedFullNode.getCoinsByPuzzleHashesPaginated( puzzlehashes, pageSize, startHeight: startHeight, @@ -79,7 +84,8 @@ void main() { expectListEquality( expectedUnspentCoins, paginatedUnspentCoins, - (item) => item.toCoinBytes() + (item.parentSpend?.toBytes() ?? Bytes.empty), + (item) => + item.toCoinBytes() + (item.parentSpend?.toBytes() ?? Bytes.empty), ); expectListEquality( @@ -117,10 +123,12 @@ void main() { final expectedSpendCoins = []; - for (final spentCoin in expectedCoins.where((element) => element.isSpent)) { + for (final spentCoin + in expectedCoins.where((element) => element.isSpent)) { final coinSpend = await enhancedFullNode.getCoinSpend(spentCoin); - expectedSpendCoins.add(SpentCoin.fromCoinSpend(spentCoin, coinSpend!)); + expectedSpendCoins + .add(SpentCoin.fromCoinSpend(spentCoin, coinSpend!)); } final paginatedUnspentCoins = []; @@ -145,7 +153,8 @@ void main() { expectListEquality( expectedUnspentCoins, paginatedUnspentCoins, - (item) => item.toCoinBytes() + (item.parentSpend?.toBytes() ?? Bytes.empty), + (item) => + item.toCoinBytes() + (item.parentSpend?.toBytes() ?? Bytes.empty), ); expectListEquality( @@ -162,19 +171,21 @@ void main() { test('at block height $blockHeight', () async { // print('testing block at height $blockHeight'); final block = await fullNode.getBlockRecordByHeight(blockHeight); - final additionsAndRemovals = - await fullNode.getAdditionsAndRemovals(block.blockRecord!.headerHash); + final additionsAndRemovals = await fullNode + .getAdditionsAndRemovals(block.blockRecord!.headerHash); print( '$blockHeight: ${additionsAndRemovals.additions.length + additionsAndRemovals.removals.length}', ); - final additionsAndRemovalsWithHints = - await enhancedFullNode.getAdditionsAndRemovalsWithHints(block.blockRecord!.headerHash); + final additionsAndRemovalsWithHints = await enhancedFullNode + .getAdditionsAndRemovalsWithHints(block.blockRecord!.headerHash); var progress = 0; - for (final expectedItem in additionsAndRemovals.removals + additionsAndRemovals.additions) { - final matchingItemWithHint = (additionsAndRemovalsWithHints.removals).singleWhere( + for (final expectedItem + in additionsAndRemovals.removals + additionsAndRemovals.additions) { + final matchingItemWithHint = + (additionsAndRemovalsWithHints.removals).singleWhere( (element) => element.id == expectedItem.id, orElse: () => additionsAndRemovalsWithHints.additions.singleWhere( (element) => element.id == expectedItem.id, @@ -187,7 +198,8 @@ void main() { continue; } expect( - spend.memosSync.where((element) => element.length == Puzzlehash.bytesLength), + spend.memosSync + .where((element) => element.length == Puzzlehash.bytesLength), isEmpty, ); } else if (hint.length < Puzzlehash.bytesLength) { @@ -223,12 +235,15 @@ void main() { }); test('should correctly get coin spends', () async { - final spentCoins = - (await fullNode.getCoinsByPuzzleHashes(puzzlehashes, includeSpentCoins: true)) - .where((element) => element.isSpent); + final spentCoins = (await fullNode.getCoinsByPuzzleHashes( + puzzlehashes, + includeSpentCoins: true, + )) + .where((element) => element.isSpent); - final coinSpends = await enhancedFullNode - .getCoinSpendsByIds(spentCoins.map((e) => e.id).toList() + [Puzzlehash.zeros()]); + final coinSpends = await enhancedFullNode.getCoinSpendsByIds( + spentCoins.map((e) => e.id).toList() + [Puzzlehash.zeros()], + ); for (final spentCoin in spentCoins) { final fetchedCoinSpend = await fullNode.getCoinSpend(spentCoin); @@ -237,8 +252,11 @@ void main() { }); test('should correctly get coins by ids', () async { - final coins = - (await fullNode.getCoinsByPuzzleHashes(puzzlehashes, includeSpentCoins: true)).toList(); + final coins = (await fullNode.getCoinsByPuzzleHashes( + puzzlehashes, + includeSpentCoins: true, + )) + .toList(); final then = DateTime.now(); @@ -267,7 +285,9 @@ void expectListEquality( for (final expectedItem in expectedList) { if (!actualList.any( - (actualItem) => getAttributeToCompare(expectedItem) == getAttributeToCompare(actualItem), + (actualItem) => + getAttributeToCompare(expectedItem) == + getAttributeToCompare(actualItem), )) { throw Exception( 'could not find expected item ${getAttributeToCompare(expectedItem)} in ${actualList.map(getAttributeToCompare).toList()}', @@ -275,7 +295,9 @@ void expectListEquality( } expect( actualList.any( - (actualItem) => getAttributeToCompare(expectedItem) == getAttributeToCompare(actualItem), + (actualItem) => + getAttributeToCompare(expectedItem) == + getAttributeToCompare(actualItem), ), true, ); diff --git a/integration_test/api_test/full_node_interface_test.dart b/integration_test/api_test/full_node_interface_test.dart index 88a00383..00b68332 100644 --- a/integration_test/api_test/full_node_interface_test.dart +++ b/integration_test/api_test/full_node_interface_test.dart @@ -60,17 +60,19 @@ Future main() async { await fullNodeSimulator.farmCoins(address); await fullNodeSimulator.moveToNextBlock(); - final standardCoins = await fullNodeSimulator.getCoinsByPuzzleHashes([puzzlehash]); + final standardCoins = + await fullNodeSimulator.getCoinsByPuzzleHashes([puzzlehash]); final originCoin = standardCoins[0]; // issue cat - final curriedTail = - delegatedTailProgram.curry([Program.fromAtom(walletVector.childPublicKey.toBytes())]); + final curriedTail = delegatedTailProgram + .curry([Program.fromAtom(walletVector.childPublicKey.toBytes())]); final assetId = Puzzlehash(curriedTail.hash()); final curriedGenesisByCoinIdPuzzle = genesisByCoinIdProgram.curry([Program.fromAtom(originCoin.id)]); - final tailSolution = Program.list([curriedGenesisByCoinIdPuzzle, Program.nil]); + final tailSolution = + Program.list([curriedGenesisByCoinIdPuzzle, Program.nil]); final signature = AugSchemeMPL.sign( walletVector.childPrivateKey, @@ -132,7 +134,8 @@ Future main() async { returnsNormally, ); expect( - () => coins.firstWhere((coin) => coin.puzzlehash == testCoin.puzzlehash), + () => + coins.firstWhere((coin) => coin.puzzlehash == testCoin.puzzlehash), returnsNormally, ); } @@ -140,7 +143,8 @@ Future main() async { test('should get standard coins by id', () async { //get coins by puzzlehash first because sometimes parent info comes back differently - final coinsGotByPuzzlehashes = await fullNodeSimulator.getCoinsByPuzzleHashes( + final coinsGotByPuzzlehashes = + await fullNodeSimulator.getCoinsByPuzzleHashes( testStandardCoins .map( (c) => c.puzzlehash, @@ -159,7 +163,8 @@ Future main() async { ); for (final coinGotByPuzzlehash in coinsGotByPuzzlehashes) { expect( - () => coinsGotByIds.firstWhere((coin) => coin.id == coinGotByPuzzlehash.id), + () => coinsGotByIds + .firstWhere((coin) => coin.id == coinGotByPuzzlehash.id), returnsNormally, ); } @@ -167,7 +172,8 @@ Future main() async { test('should get standard coins by parent id', () async { //get coins by puzzlehash first because sometimes parent info comes back differently - final coinsGotByPuzzlehashes = await fullNodeSimulator.getCoinsByPuzzleHashes( + final coinsGotByPuzzlehashes = + await fullNodeSimulator.getCoinsByPuzzleHashes( testStandardCoins .map( (c) => c.puzzlehash, @@ -186,7 +192,8 @@ Future main() async { ); for (final coinGotByPuzzlehash in coinsGotByPuzzlehashes) { expect( - () => coinsGotByParentIds.firstWhere((coin) => coin.id == coinGotByPuzzlehash.id), + () => coinsGotByParentIds + .firstWhere((coin) => coin.id == coinGotByPuzzlehash.id), returnsNormally, ); } @@ -226,7 +233,8 @@ Future main() async { for (final testCatCoin in testCatCoins) { // can't check for parentCoinInfo because it will change based on the coin used to mint the cat expect( - () => catCoins.firstWhere((catCoin) => catCoin.amount == testCatCoin.amount), + () => catCoins + .firstWhere((catCoin) => catCoin.amount == testCatCoin.amount), returnsNormally, ); expect( @@ -245,7 +253,8 @@ Future main() async { for (final testCatCoin in testCatCoins) { expect( - () => catCoins.firstWhere((catCoin) => catCoin.amount == testCatCoin.amount), + () => catCoins + .firstWhere((catCoin) => catCoin.amount == testCatCoin.amount), returnsNormally, ); expect( @@ -257,8 +266,10 @@ Future main() async { } }); - test('should correctly check for spent coins when there are spent coins', () async { - final spentCoinsCheck = await fullNodeSimulator.checkForSpentCoins(standardCoins); + test('should correctly check for spent coins when there are spent coins', + () async { + final spentCoinsCheck = + await fullNodeSimulator.checkForSpentCoins(standardCoins); expect( spentCoinsCheck, @@ -266,8 +277,10 @@ Future main() async { ); }); - test('should correctly check for spent coins when coins have not been spent', () async { - final spentCoinsCheck = await fullNodeSimulator.checkForSpentCoins(testStandardCoins); + test('should correctly check for spent coins when coins have not been spent', + () async { + final spentCoinsCheck = + await fullNodeSimulator.checkForSpentCoins(testStandardCoins); expect( spentCoinsCheck, @@ -302,22 +315,27 @@ Future main() async { expect(headerHash, isNotNull); if (headerHash != null) { - final additionsAndRemovals = await fullNodeSimulator.getAdditionsAndRemovals(headerHash); + final additionsAndRemovals = + await fullNodeSimulator.getAdditionsAndRemovals(headerHash); final additions = additionsAndRemovals.additions; final removals = additionsAndRemovals.removals; final expectedAdditions = spendBundle.additions; - final expectedRemovals = [standardCoins.firstWhere((coin) => coin.amount >= 10000)]; + final expectedRemovals = [ + standardCoins.firstWhere((coin) => coin.amount >= 10000) + ]; for (final expectedAddition in expectedAdditions) { expect( - () => additions.firstWhere((addition) => addition.id == expectedAddition.id), + () => additions + .firstWhere((addition) => addition.id == expectedAddition.id), returnsNormally, ); } for (final expectedRemoval in expectedRemovals) { expect( - () => removals.firstWhere((removal) => removal.id == expectedRemoval.id), + () => removals + .firstWhere((removal) => removal.id == expectedRemoval.id), returnsNormally, ); } diff --git a/integration_test/api_test/tail_database_test.dart b/integration_test/api_test/tail_database_test.dart index af726edd..34dc2b7e 100644 --- a/integration_test/api_test/tail_database_test.dart +++ b/integration_test/api_test/tail_database_test.dart @@ -8,19 +8,23 @@ Future main() async { LoggingContext().setLogTypes(api: true); test('should get tail info for asset ids', () async { - final stablyUsdAssetId = - Puzzlehash.fromHex('6d95dae356e32a71db5ddcb42224754a02524c615c5fc35f568c2af04774e589'); - final stablyUsdTailInfo = await tailDatabaseApi.getTailInfo(stablyUsdAssetId); + final stablyUsdAssetId = Puzzlehash.fromHex( + '6d95dae356e32a71db5ddcb42224754a02524c615c5fc35f568c2af04774e589', + ); + final stablyUsdTailInfo = + await tailDatabaseApi.getTailInfo(stablyUsdAssetId); expect(stablyUsdTailInfo.name, 'Stably USD'); - final catkchiAssetId = - Puzzlehash.fromHex('482b49902d310c53065c3531d398d41808f1390590d566815d67040f6a32d124'); + final catkchiAssetId = Puzzlehash.fromHex( + '482b49902d310c53065c3531d398d41808f1390590d566815d67040f6a32d124', + ); final catkchiTailInfo = await tailDatabaseApi.getTailInfo(catkchiAssetId); expect(catkchiTailInfo.name, 'Catkchi'); - // Chess is no longer listed on tail database after the CAT2 release. - final chessAssetId = - Puzzlehash.fromHex('a26bb00329235a4b46d0e402f9c1124279dcb1a30c3236679e1a7f1709a8d7c0'); + // Chess is no longer listed on tail database after the CAT2 release. + final chessAssetId = Puzzlehash.fromHex( + 'a26bb00329235a4b46d0e402f9c1124279dcb1a30c3236679e1a7f1709a8d7c0', + ); final chessTailInfo = await tailDatabaseApi.getTailInfo(chessAssetId); expect(chessTailInfo.name, isNull); }); diff --git a/integration_test/api_test/wallet_connect/wallet_connect_chia_lite_wallet_test.dart b/integration_test/api_test/wallet_connect/wallet_connect_chia_lite_wallet_test.dart index 2e039e59..e42dda30 100644 --- a/integration_test/api_test/wallet_connect/wallet_connect_chia_lite_wallet_test.dart +++ b/integration_test/api_test/wallet_connect/wallet_connect_chia_lite_wallet_test.dart @@ -103,7 +103,8 @@ Future main() async { test('Should request NFT info from Chia Lite Wallet', () async { // Navigate to NFTs, click on NFT you want to test, copy the NFT Coin ID and set it manually below - const coinId = '5011cdcdcfe38738f855f2ff9a08ef49c6e298761f97dd261173fb9b2a76bac3'; + const coinId = + '5011cdcdcfe38738f855f2ff9a08ef49c6e298761f97dd261173fb9b2a76bac3'; final response = await appClient.getNFTInfo( fingerprint: fingerprint, @@ -131,11 +132,14 @@ Future main() async { print(response.toJson()); }); - test('Should request Chia Lite Wallet to send a transaction and then get transaction data', + test( + 'Should request Chia Lite Wallet to send a transaction and then get transaction data', () async { final response = await appClient.sendTransaction( fingerprint: fingerprint, - address: const Address('xch17c3q8nrd88a06rs2kjdacj5w5p3mtnf0cqmpgxseh2xfzp5tgeesn7pwr9'), + address: const Address( + 'xch17c3q8nrd88a06rs2kjdacj5w5p3mtnf0cqmpgxseh2xfzp5tgeesn7pwr9', + ), amount: 50, fee: 50, ); @@ -154,18 +158,22 @@ Future main() async { print(transactionResponse.toJson()); }); - test('Should request Chia Lite Wallet to spend CAT and then get transaction data', () async { + test( + 'Should request Chia Lite Wallet to spend CAT and then get transaction data', + () async { final getWalletsResponse = await appClient.getWallets( fingerprint: fingerprint, ); - final catWallets = - getWalletsResponse.wallets.where((wallet) => wallet.type == ChiaWalletType.cat); + final catWallets = getWalletsResponse.wallets + .where((wallet) => wallet.type == ChiaWalletType.cat); // in order to go through first CAT wallet must have a non-zero balance final response = await appClient.spendCat( fingerprint: fingerprint, - address: const Address('xch17c3q8nrd88a06rs2kjdacj5w5p3mtnf0cqmpgxseh2xfzp5tgeesn7pwr9'), + address: const Address( + 'xch17c3q8nrd88a06rs2kjdacj5w5p3mtnf0cqmpgxseh2xfzp5tgeesn7pwr9', + ), amount: 1, fee: 50, walletId: catWallets.first.id, @@ -209,7 +217,8 @@ Future main() async { print(response.toJson()); }); - test('Should request Chia Lite Wallet to sign message by address and then verify signature', + test( + 'Should request Chia Lite Wallet to sign message by address and then verify signature', () async { final addressResponse = await appClient.getCurrentAddress( fingerprint: fingerprint, @@ -235,12 +244,15 @@ Future main() async { print(verifySignatureResponse.toJson()); }); - test('Should request Chia Lite Wallet to sign message by id and then verify signature', () async { + test( + 'Should request Chia Lite Wallet to sign message by id and then verify signature', + () async { // in order to run this test, you must have a did on your current wallet in the Chia Lite Wallet // navigate to Settings > Profiles, hover over DID and copy the DID ID (Hex) // manually set it to variable below - const didHex = '2c3b970e57261a7c77ca395072890c698b0d6e5fdd3447aaa43eea948df95b8c'; + const didHex = + '2c3b970e57261a7c77ca395072890c698b0d6e5fdd3447aaa43eea948df95b8c'; final signMessageResponse = await appClient.signMessageById( fingerprint: fingerprint, @@ -284,8 +296,9 @@ Future main() async { includeData: true, ); - final nftWallets = - getWalletsResponse.wallets.where((wallet) => wallet.type == ChiaWalletType.nft).toList(); + final nftWallets = getWalletsResponse.wallets + .where((wallet) => wallet.type == ChiaWalletType.nft) + .toList(); await Future.delayed(const Duration(seconds: 1)); @@ -302,14 +315,16 @@ Future main() async { print(response.toJson()); }); - test('Should request Chia Lite Wallet to create offer for wallet ids', () async { + test('Should request Chia Lite Wallet to create offer for wallet ids', + () async { final getWalletsResponse = await appClient.getWallets( fingerprint: fingerprint, includeData: true, ); - final catWalletId = - getWalletsResponse.wallets.firstWhere((wallet) => wallet.type == ChiaWalletType.cat).id; + final catWalletId = getWalletsResponse.wallets + .firstWhere((wallet) => wallet.type == ChiaWalletType.cat) + .id; final response = await appClient.createOfferForIds( fingerprint: fingerprint, @@ -322,8 +337,9 @@ Future main() async { test('Should request Chia Lite Wallet to add new CAT token', () async { final response = await appClient.addCatToken( fingerprint: fingerprint, - assetId: - Puzzlehash.fromHex('8ebf855de6eb146db5602f0456d2f0cbe750d57f821b6f91a8592ee9f1d4cf31'), + assetId: Puzzlehash.fromHex( + '8ebf855de6eb146db5602f0456d2f0cbe750d57f821b6f91a8592ee9f1d4cf31', + ), name: 'Marmot Coin', ); diff --git a/integration_test/api_test/wallet_connect/wallet_connect_mintgarden_test.dart b/integration_test/api_test/wallet_connect/wallet_connect_mintgarden_test.dart index 661fe08f..dfb88570 100644 --- a/integration_test/api_test/wallet_connect/wallet_connect_mintgarden_test.dart +++ b/integration_test/api_test/wallet_connect/wallet_connect_mintgarden_test.dart @@ -21,8 +21,10 @@ Future main() async { const mnemonic = ''; const mintGardenLink = ''; - final enhancedFullNodeInterface = - EnhancedChiaFullNodeInterface.fromUrl(mainnetUrl, timeout: const Duration(minutes: 10)); + final enhancedFullNodeInterface = EnhancedChiaFullNodeInterface.fromUrl( + mainnetUrl, + timeout: const Duration(minutes: 10), + ); ChiaNetworkContextWrapper().registerNetworkContext(Network.mainnet); diff --git a/integration_test/api_test/wallet_connect/wallet_connect_multiple_fingerprints_test.dart b/integration_test/api_test/wallet_connect/wallet_connect_multiple_fingerprints_test.dart index 1a8772f6..53f773fa 100644 --- a/integration_test/api_test/wallet_connect/wallet_connect_multiple_fingerprints_test.dart +++ b/integration_test/api_test/wallet_connect/wallet_connect_multiple_fingerprints_test.dart @@ -1,4 +1,6 @@ -@Skip('These tests should be run manually, as they depend on the WalletConnect relay server') +@Skip( + 'These tests should be run manually, as they depend on the WalletConnect relay server', +) @Timeout(Duration(minutes: 5)) import 'package:chia_crypto_utils/chia_crypto_utils.dart'; import 'package:test/test.dart'; @@ -16,7 +18,8 @@ Future main() async { final walletCore = Core(projectId: testWalletProjectId); final appCore = Core(projectId: walletConnectProjectId); - final web3Wallet = Web3Wallet(core: walletCore, metadata: defaultPairingMetadata); + final web3Wallet = + Web3Wallet(core: walletCore, metadata: defaultPairingMetadata); final web3App = Web3App(core: appCore, metadata: defaultPairingMetadata); test('Should approve session with multiple fingerprints', () async { diff --git a/integration_test/api_test/wallet_connect/wallet_connect_session_rejection_test.dart b/integration_test/api_test/wallet_connect/wallet_connect_session_rejection_test.dart index 5d8ca1d9..7dd43d84 100644 --- a/integration_test/api_test/wallet_connect/wallet_connect_session_rejection_test.dart +++ b/integration_test/api_test/wallet_connect/wallet_connect_session_rejection_test.dart @@ -1,4 +1,6 @@ -@Skip('These tests should be run manually, as they depend on the WalletConnect relay server') +@Skip( + 'These tests should be run manually, as they depend on the WalletConnect relay server', +) @Timeout(Duration(minutes: 5)) import 'package:chia_crypto_utils/chia_crypto_utils.dart'; import 'package:test/test.dart'; @@ -9,7 +11,8 @@ import 'package:walletconnect_flutter_v2/apis/web3wallet/web3wallet.dart'; Future main() async { final walletCore = Core(projectId: testWalletProjectId); final appCore = Core(projectId: walletConnectProjectId); - final web3Wallet = Web3Wallet(core: walletCore, metadata: defaultPairingMetadata); + final web3Wallet = + Web3Wallet(core: walletCore, metadata: defaultPairingMetadata); final web3App = Web3App(core: appCore, metadata: defaultPairingMetadata); test('Should throw exception when session proposal is rejected', () async { diff --git a/integration_test/api_test/wallet_connect/wallet_connect_simulator_test.dart b/integration_test/api_test/wallet_connect/wallet_connect_simulator_test.dart index 9d19cf70..3448ed94 100644 --- a/integration_test/api_test/wallet_connect/wallet_connect_simulator_test.dart +++ b/integration_test/api_test/wallet_connect/wallet_connect_simulator_test.dart @@ -1,4 +1,6 @@ -@Skip('These tests should be run manually, as they depend on the WalletConnect relay server') +@Skip( + 'These tests should be run manually, as they depend on the WalletConnect relay server', +) @Timeout(Duration(minutes: 5)) import 'package:chia_crypto_utils/chia_crypto_utils.dart'; import 'package:test/test.dart'; @@ -19,7 +21,8 @@ Future main() async { SimulatorUtils.simulatorUrl, ); - final enhancedFullNodeInterface = EnhancedChiaFullNodeInterface(enhancedFullNodeHttpRpc); + final enhancedFullNodeInterface = + EnhancedChiaFullNodeInterface(enhancedFullNodeHttpRpc); final fullNodeSimulator = SimulatorFullNodeInterface.withDefaultUrl(); @@ -82,9 +85,12 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - nftRecord = (await fullNodeSimulator.getNftRecordsByHint(meera.firstPuzzlehash)).single; + nftRecord = + (await fullNodeSimulator.getNftRecordsByHint(meera.firstPuzzlehash)) + .single; - final nftRecordWithMintInfo = (await nftRecord.fetchMintInfo(fullNodeSimulator))!; + final nftRecordWithMintInfo = + (await nftRecord.fetchMintInfo(fullNodeSimulator))!; nftInfo = NftInfo.fromNftRecordWithMintInfo(nftRecordWithMintInfo); @@ -96,7 +102,8 @@ Future main() async { // set up WalletConnect wallet client final walletCore = Core(projectId: testWalletProjectId); - final web3Wallet = Web3Wallet(core: walletCore, metadata: defaultPairingMetadata); + final web3Wallet = + Web3Wallet(core: walletCore, metadata: defaultPairingMetadata); fingerprint = meera.keychainSecret.fingerprint; @@ -138,12 +145,17 @@ Future main() async { }); test('Should request and receive current address data', () async { - final response = await appClient.getCurrentAddress(fingerprint: fingerprint); + final response = + await appClient.getCurrentAddress(fingerprint: fingerprint); - expect(response.address, equals(meera.firstPuzzlehash.toAddressWithContext())); + expect( + response.address, + equals(meera.firstPuzzlehash.toAddressWithContext()), + ); }); - test('Should make request and throw exception when request is rejected', () async { + test('Should make request and throw exception when request is rejected', + () async { requestHandler.approveRequest = false; expect( @@ -157,14 +169,17 @@ Future main() async { final response = await appClient.getNextAddress(fingerprint: fingerprint); - final expectedNewAddress = meera.puzzlehashes[initialLastIndex + 1].toAddressWithContext(); + final expectedNewAddress = + meera.puzzlehashes[initialLastIndex + 1].toAddressWithContext(); expect(response.address.address, equals(expectedNewAddress.address)); }); test('Should request and receive NFT info', () async { - final response = - await appClient.getNFTInfo(fingerprint: fingerprint, coinId: nftInfo.nftCoinId); + final response = await appClient.getNFTInfo( + fingerprint: fingerprint, + coinId: nftInfo.nftCoinId, + ); expect(response.nftInfo.toJson(), equals(nftInfo.toJson())); }); @@ -172,10 +187,16 @@ Future main() async { test('Should request and receive NFTs data', () async { final nftWalletIds = walletMap.nftWallets().keys.toList(); - final response = await appClient.getNFTs(fingerprint: fingerprint, walletIds: nftWalletIds); + final response = await appClient.getNFTs( + fingerprint: fingerprint, + walletIds: nftWalletIds, + ); expect(response.nfts.length, equals(1)); - expect(response.nfts.entries.single.value.single.toJson(), equals(nftInfo.toJson())); + expect( + response.nfts.entries.single.value.single.toJson(), + equals(nftInfo.toJson()), + ); }); test('Should request and receive paginated NFTs data', () async { @@ -212,14 +233,26 @@ Future main() async { test('Should request and receive wallet balance data', () async { final response = await appClient.getWalletBalance(fingerprint: fingerprint); - expect(response.balance.confirmedWalletBalance, equals(meera.standardCoins.totalValue)); + expect( + response.balance.confirmedWalletBalance, + equals(meera.standardCoins.totalValue), + ); expect(response.balance.fingerprint, equals(fingerprint)); expect(response.balance.pendingChange, equals(0)); expect(response.balance.pendingCoinRemovalCount, equals(0)); expect(response.balance.pendingChange, equals(0)); - expect(response.balance.spendableBalance, equals(meera.standardCoins.totalValue)); - expect(response.balance.unconfirmedWalletBalance, equals(meera.standardCoins.totalValue)); - expect(response.balance.unspentCoinCount, equals(meera.standardCoins.length)); + expect( + response.balance.spendableBalance, + equals(meera.standardCoins.totalValue), + ); + expect( + response.balance.unconfirmedWalletBalance, + equals(meera.standardCoins.totalValue), + ); + expect( + response.balance.unspentCoinCount, + equals(meera.standardCoins.length), + ); expect(response.balance.walletId, equals(1)); expect(response.balance.walletType, equals(ChiaWalletType.standard)); }); @@ -231,7 +264,8 @@ Future main() async { final walletTypes = response.wallets.map((wallet) => wallet.type); - final standardWallets = walletTypes.where((type) => type == ChiaWalletType.standard); + final standardWallets = + walletTypes.where((type) => type == ChiaWalletType.standard); final nftWallets = walletTypes.where((type) => type == ChiaWalletType.nft); final didWallets = walletTypes.where((type) => type == ChiaWalletType.did); final catWallets = walletTypes.where((type) => type == ChiaWalletType.cat); @@ -242,7 +276,8 @@ Future main() async { expect(catWallets.length, equals(1)); }); - test('Should make transaction request, wait for confirmation, and receive sent transaction data', + test( + 'Should make transaction request, wait for confirmation, and receive sent transaction data', () async { final meeraStartingBalance = meera.standardCoins.totalValue; final nathanStartingBalance = nathan.standardCoins.totalValue; @@ -260,9 +295,15 @@ Future main() async { fullNodeSimulator.stop(); expect(response.sentTransactionData.success, isTrue); - expect(response.sentTransactionData.transaction.amount, equals(standardAmount)); + expect( + response.sentTransactionData.transaction.amount, + equals(standardAmount), + ); expect(response.sentTransactionData.transaction.feeAmount, equals(fee)); - expect(response.sentTransactionData.transaction.toPuzzlehash, equals(nathan.firstPuzzlehash)); + expect( + response.sentTransactionData.transaction.toPuzzlehash, + equals(nathan.firstPuzzlehash), + ); expect(response.sentTransactionData.transaction.confirmed, isTrue); await fullNodeSimulator.moveToNextBlock(); @@ -272,7 +313,10 @@ Future main() async { final meeraEndingBalance = meera.standardCoins.totalValue; final nathanEndingBalance = nathan.standardCoins.totalValue; - expect(meeraEndingBalance, equals(meeraStartingBalance - fee - standardAmount)); + expect( + meeraEndingBalance, + equals(meeraStartingBalance - fee - standardAmount), + ); expect(nathanEndingBalance, equals(nathanStartingBalance + standardAmount)); }); @@ -290,9 +334,15 @@ Future main() async { ); expect(response.sentTransactionData.success, isTrue); - expect(response.sentTransactionData.transaction.amount, equals(standardAmount)); + expect( + response.sentTransactionData.transaction.amount, + equals(standardAmount), + ); expect(response.sentTransactionData.transaction.feeAmount, equals(fee)); - expect(response.sentTransactionData.transaction.toPuzzlehash, equals(nathan.firstPuzzlehash)); + expect( + response.sentTransactionData.transaction.toPuzzlehash, + equals(nathan.firstPuzzlehash), + ); expect(response.sentTransactionData.transaction.confirmed, isFalse); await fullNodeSimulator.moveToNextBlock(); @@ -302,11 +352,16 @@ Future main() async { final meeraEndingBalance = meera.standardCoins.totalValue; final nathanEndingBalance = nathan.standardCoins.totalValue; - expect(meeraEndingBalance, equals(meeraStartingBalance - fee - standardAmount)); + expect( + meeraEndingBalance, + equals(meeraStartingBalance - fee - standardAmount), + ); expect(nathanEndingBalance, equals(nathanStartingBalance + standardAmount)); }); - test('Should make a CAT transaction request and receive sent transaction data', () async { + test( + 'Should make a CAT transaction request and receive sent transaction data', + () async { final meeraStartingCatBalance = meera.catCoins.totalValue; final nathanStartingCatBalance = nathan.catCoins.totalValue; @@ -321,7 +376,10 @@ Future main() async { expect(response.sentTransactionData.success, isTrue); expect(response.sentTransactionData.transaction.amount, equals(catAmount)); expect(response.sentTransactionData.transaction.feeAmount, equals(fee)); - expect(response.sentTransactionData.transaction.toPuzzlehash, equals(nathan.firstPuzzlehash)); + expect( + response.sentTransactionData.transaction.toPuzzlehash, + equals(nathan.firstPuzzlehash), + ); expect(response.sentTransactionData.transaction.confirmed, isFalse); await fullNodeSimulator.moveToNextBlock(); @@ -332,14 +390,19 @@ Future main() async { final nathanEndingCatBalance = nathan.catCoins.totalValue; expect(meeraEndingCatBalance, equals(meeraStartingCatBalance - catAmount)); - expect(nathanEndingCatBalance, equals(nathanStartingCatBalance + catAmount)); + expect( + nathanEndingCatBalance, + equals(nathanStartingCatBalance + catAmount), + ); }); test('Should make a NFT transaction request and receive data', () async { - var meeraNfts = await fullNodeSimulator.getNftRecordsByHint(meera.firstPuzzlehash); + var meeraNfts = + await fullNodeSimulator.getNftRecordsByHint(meera.firstPuzzlehash); expect(meeraNfts.length, equals(1)); - var nathanNfts = await fullNodeSimulator.getNftRecordsByHint(nathan.firstPuzzlehash); + var nathanNfts = + await fullNodeSimulator.getNftRecordsByHint(nathan.firstPuzzlehash); expect(nathanNfts, isEmpty); final response = await appClient.sendTransaction( @@ -353,22 +416,28 @@ Future main() async { expect(response.sentTransactionData.success, isTrue); expect(response.sentTransactionData.transaction.amount, equals(1)); expect(response.sentTransactionData.transaction.feeAmount, equals(fee)); - expect(response.sentTransactionData.transaction.toPuzzlehash, equals(nathan.firstPuzzlehash)); + expect( + response.sentTransactionData.transaction.toPuzzlehash, + equals(nathan.firstPuzzlehash), + ); expect(response.sentTransactionData.transaction.confirmed, isFalse); await fullNodeSimulator.moveToNextBlock(); await meera.refreshCoins(); await nathan.refreshCoins(); - meeraNfts = await fullNodeSimulator.getNftRecordsByHint(meera.firstPuzzlehash); + meeraNfts = + await fullNodeSimulator.getNftRecordsByHint(meera.firstPuzzlehash); expect(meeraNfts, isEmpty); - nathanNfts = await fullNodeSimulator.getNftRecordsByHint(nathan.firstPuzzlehash); + nathanNfts = + await fullNodeSimulator.getNftRecordsByHint(nathan.firstPuzzlehash); expect(nathanNfts.length, equals(1)); expect(nathanNfts.single.launcherId, equals(nftInfo.launcherId)); }); - test('Should make request to spend CAT and receive sent transaction data', () async { + test('Should make request to spend CAT and receive sent transaction data', + () async { final meeraStartingCatBalance = meera.catCoins.totalValue; final nathanStartingCatBalance = nathan.catCoins.totalValue; @@ -383,7 +452,10 @@ Future main() async { expect(response.sentTransactionData.success, isTrue); expect(response.sentTransactionData.transaction.amount, equals(catAmount)); expect(response.sentTransactionData.transaction.feeAmount, equals(fee)); - expect(response.sentTransactionData.transaction.toPuzzlehash, equals(nathan.firstPuzzlehash)); + expect( + response.sentTransactionData.transaction.toPuzzlehash, + equals(nathan.firstPuzzlehash), + ); expect(response.sentTransactionData.transaction.confirmed, isFalse); await fullNodeSimulator.moveToNextBlock(); @@ -394,10 +466,14 @@ Future main() async { final nathanEndingCatBalance = nathan.catCoins.totalValue; expect(meeraEndingCatBalance, equals(meeraStartingCatBalance - catAmount)); - expect(nathanEndingCatBalance, equals(nathanStartingCatBalance + catAmount)); + expect( + nathanEndingCatBalance, + equals(nathanStartingCatBalance + catAmount), + ); }); - test('Should request to take CAT for XCH offer and receive response', () async { + test('Should request to take CAT for XCH offer and receive response', + () async { final nathanStartingStandardBalance = nathan.standardCoins.totalValue; final nathanStartingCatBalance = nathan.catCoins.totalValue; final meeraStartingStandardBalance = meera.standardCoins.totalValue; @@ -426,7 +502,10 @@ Future main() async { fullNodeSimulator.stop(); expect(response.takeOfferData.success, isTrue); - expect(response.takeOfferData.tradeRecord.takenOffer, equals(offer.toBech32())); + expect( + response.takeOfferData.tradeRecord.takenOffer, + equals(offer.toBech32()), + ); await fullNodeSimulator.moveToNextBlock(); await meera.refreshCoins(); @@ -447,10 +526,14 @@ Future main() async { nathanEndingStandardBalance, equals(nathanStartingStandardBalance - standardAmount), ); - expect(nathanEndingCatBalance, equals(nathanStartingCatBalance + catAmount)); + expect( + nathanEndingCatBalance, + equals(nathanStartingCatBalance + catAmount), + ); }); - test('Should request to take XCH for CAT offer and receive response', () async { + test('Should request to take XCH for CAT offer and receive response', + () async { await nathan.issueMultiIssuanceCat(); final nathanStartingStandardBalance = nathan.standardCoins.totalValue; @@ -463,11 +546,15 @@ Future main() async { final targetPuzzlehash = nathan.firstPuzzlehash; final offer = catOfferService.makeOffer( - coinsForOffer: MixedCoins(cats: nathan.catCoins, standardCoins: [nathan.standardCoins.first]), + coinsForOffer: MixedCoins( + cats: nathan.catCoins, + standardCoins: [nathan.standardCoins.first], + ), offeredAmounts: OfferedMixedAmounts(cat: {nathanCoinAssetId: catAmount}), changePuzzlehash: targetPuzzlehash, - requestedPayments: - RequestedMixedPayments(standard: [Payment(standardAmount, targetPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(standardAmount, targetPuzzlehash)], + ), keychain: nathan.keychain, fee: fee, ); @@ -483,7 +570,10 @@ Future main() async { fullNodeSimulator.stop(); expect(response.takeOfferData.success, isTrue); - expect(response.takeOfferData.tradeRecord.takenOffer, equals(offer.toBech32())); + expect( + response.takeOfferData.tradeRecord.takenOffer, + equals(offer.toBech32()), + ); await fullNodeSimulator.moveToNextBlock(); @@ -505,10 +595,14 @@ Future main() async { nathanEndingStandardBalance, equals(nathanStartingStandardBalance + standardAmount - fee), ); - expect(nathanEndingCatBalance, equals(nathanStartingCatBalance - catAmount)); + expect( + nathanEndingCatBalance, + equals(nathanStartingCatBalance - catAmount), + ); }); - test('Should request to take XCH for NFT offer and receive response', () async { + test('Should request to take XCH for NFT offer and receive response', + () async { // generate an NFT without owner DID for offer final spendBundle = nftWalletService.createGenerateNftSpendBundle( minterPuzzlehash: meera.puzzlehashes[2], @@ -526,12 +620,14 @@ Future main() async { await meera.farmCoins(); final requestedNftRecord = - (await fullNodeSimulator.getNftRecordsByHint(meera.puzzlehashes[2])).single; + (await fullNodeSimulator.getNftRecordsByHint(meera.puzzlehashes[2])) + .single; final nathanStartingStandardBalance = nathan.standardCoins.totalValue; final meeraStartingStandardBalance = meera.standardCoins.totalValue; - var nathanNfts = await enhancedFullNodeInterface.getNftRecordsByHints(nathan.puzzlehashes); + var nathanNfts = await enhancedFullNodeInterface + .getNftRecordsByHints(nathan.puzzlehashes); expect(nathanNfts, isEmpty); final targetPuzzlehash = nathan.firstPuzzlehash; @@ -555,7 +651,10 @@ Future main() async { fullNodeSimulator.stop(); expect(response.takeOfferData.success, isTrue); - expect(response.takeOfferData.tradeRecord.takenOffer, equals(offer.toBech32())); + expect( + response.takeOfferData.tradeRecord.takenOffer, + equals(offer.toBech32()), + ); await fullNodeSimulator.moveToNextBlock(); await meera.refreshCoins(); @@ -574,12 +673,14 @@ Future main() async { equals(nathanStartingStandardBalance - standardAmount), ); - nathanNfts = await enhancedFullNodeInterface.getNftRecordsByHints(nathan.puzzlehashes); + nathanNfts = await enhancedFullNodeInterface + .getNftRecordsByHints(nathan.puzzlehashes); expect(nathanNfts.length, equals(1)); expect(nathanNfts.single.launcherId, equals(requestedNftRecord.launcherId)); }); - test('Should request to take NFT for XCH offer and receive response', () async { + test('Should request to take NFT for XCH offer and receive response', + () async { final spendBundle = nftWalletService.createGenerateNftSpendBundle( minterPuzzlehash: nathan.puzzlehashes[1], metadata: inputMetadata, @@ -596,7 +697,8 @@ Future main() async { await nathan.farmCoins(); final offeredNftRecord = - (await fullNodeSimulator.getNftRecordsByHint(nathan.puzzlehashes[1])).single; + (await fullNodeSimulator.getNftRecordsByHint(nathan.puzzlehashes[1])) + .single; final offeredNft = offeredNftRecord.toNft(nathan.keychain); @@ -607,13 +709,17 @@ Future main() async { final nathanStartingStandardBalance = nathan.standardCoins.totalValue; final meeraStartingStandardBalance = meera.standardCoins.totalValue; - var meeraNfts = await enhancedFullNodeInterface.getNftRecordsByHints(meera.puzzlehashes); + var meeraNfts = await enhancedFullNodeInterface + .getNftRecordsByHints(meera.puzzlehashes); expect(meeraNfts.length, equals(1)); final targetPuzzlehash = nathan.firstPuzzlehash; final offer = catOfferService.makeOffer( - coinsForOffer: MixedCoins(nfts: [offeredNft], standardCoins: [nathan.standardCoins.first]), + coinsForOffer: MixedCoins( + nfts: [offeredNft], + standardCoins: [nathan.standardCoins.first], + ), changePuzzlehash: targetPuzzlehash, requestedPayments: RequestedMixedPayments( standard: [Payment(standardAmount, targetPuzzlehash)], @@ -632,7 +738,10 @@ Future main() async { fullNodeSimulator.stop(); expect(response.takeOfferData.success, isTrue); - expect(response.takeOfferData.tradeRecord.takenOffer, equals(offer.toBech32())); + expect( + response.takeOfferData.tradeRecord.takenOffer, + equals(offer.toBech32()), + ); await fullNodeSimulator.moveToNextBlock(); await meera.refreshCoins(); @@ -651,20 +760,24 @@ Future main() async { equals(nathanStartingStandardBalance + standardAmount - fee), ); - meeraNfts = await enhancedFullNodeInterface.getNftRecordsByHints(meera.puzzlehashes); + meeraNfts = await enhancedFullNodeInterface + .getNftRecordsByHints(meera.puzzlehashes); expect(meeraNfts.length, equals(2)); - final newNft = meeraNfts.where((nft) => nft.launcherId != nftRecord.launcherId); + final newNft = + meeraNfts.where((nft) => nft.launcherId != nftRecord.launcherId); expect(newNft.length, equals(1)); expect(newNft.single.launcherId, equals(offeredNftRecord.launcherId)); }); test('Should make a transfer NFT request and receive data', () async { - var meeraNfts = await fullNodeSimulator.getNftRecordsByHint(meera.firstPuzzlehash); + var meeraNfts = + await fullNodeSimulator.getNftRecordsByHint(meera.firstPuzzlehash); expect(meeraNfts.length, equals(1)); - var nathanNfts = await fullNodeSimulator.getNftRecordsByHint(nathan.firstPuzzlehash); + var nathanNfts = + await fullNodeSimulator.getNftRecordsByHint(nathan.firstPuzzlehash); expect(nathanNfts, isEmpty); final response = await appClient.transferNFT( @@ -676,7 +789,9 @@ Future main() async { ); expect( - response.transferNftData.spendBundle.coins.map((coin) => coin.id).contains(nftInfo.nftCoinId), + response.transferNftData.spendBundle.coins + .map((coin) => coin.id) + .contains(nftInfo.nftCoinId), isTrue, ); @@ -684,17 +799,20 @@ Future main() async { await meera.refreshCoins(); await nathan.refreshCoins(); - meeraNfts = await fullNodeSimulator.getNftRecordsByHint(meera.firstPuzzlehash); + meeraNfts = + await fullNodeSimulator.getNftRecordsByHint(meera.firstPuzzlehash); expect(meeraNfts, isEmpty); - nathanNfts = await fullNodeSimulator.getNftRecordsByHint(nathan.firstPuzzlehash); + nathanNfts = + await fullNodeSimulator.getNftRecordsByHint(nathan.firstPuzzlehash); expect(nathanNfts.length, equals(1)); expect(nathanNfts.single.launcherId, equals(nftInfo.launcherId)); }); - test('Should request to sign by address and receive signature data', () async { + test('Should request to sign by address and receive signature data', + () async { final walletVector = meera.keychain.getWalletVector(meera.puzzlehashes[2]); final response = await appClient.signMessageByAddress( @@ -739,8 +857,10 @@ Future main() async { () async { final walletVector = meera.keychain.getWalletVector(meera.puzzlehashes[2]); - final signature = - AugSchemeMPL.sign(walletVector!.childPrivateKey, Bytes.encodeFromString(message)); + final signature = AugSchemeMPL.sign( + walletVector!.childPrivateKey, + Bytes.encodeFromString(message), + ); final response = await appClient.verifySignature( fingerprint: fingerprint, @@ -760,7 +880,10 @@ Future main() async { final hexMessage = Bytes.encodeFromString(message).toHex(); - final signature = AugSchemeMPL.sign(walletVector!.childPrivateKey, hexMessage.hexToBytes()); + final signature = AugSchemeMPL.sign( + walletVector!.childPrivateKey, + hexMessage.hexToBytes(), + ); final response = await appClient.verifySignature( fingerprint: fingerprint, @@ -780,7 +903,8 @@ Future main() async { final chip002Message = constructChip002Message(message); - final signature = AugSchemeMPL.sign(walletVector!.childPrivateKey, chip002Message); + final signature = + AugSchemeMPL.sign(walletVector!.childPrivateKey, chip002Message); final response = await appClient.verifySignature( fingerprint: fingerprint, @@ -798,8 +922,10 @@ Future main() async { () async { final walletVector = meera.keychain.getWalletVector(meera.puzzlehashes[2]); - final signature = - AugSchemeMPL.sign(walletVector!.childPrivateKey, Bytes.encodeFromString(message)); + final signature = AugSchemeMPL.sign( + walletVector!.childPrivateKey, + Bytes.encodeFromString(message), + ); final response = await appClient.verifySignature( fingerprint: fingerprint, @@ -825,15 +951,18 @@ Future main() async { await meera.issueDid(); } - final didSigningService = WalletConnectDidSigningService(appClient, fullNodeSimulator); + final didSigningService = + WalletConnectDidSigningService(appClient, fullNodeSimulator); - final didInfo = await didSigningService.getDidInfoForDid(meera.didInfo!.did); + final didInfo = + await didSigningService.getDidInfoForDid(meera.didInfo!.did); expect(didInfo.did, equals(meera.didInfo!.did)); }); test('Should request to create offer file and receive response', () async { - final catWalletId = - walletMap.entries.firstWhere((entry) => entry.value.type == ChiaWalletType.cat).key; + final catWalletId = walletMap.entries + .firstWhere((entry) => entry.value.type == ChiaWalletType.cat) + .key; final response = await appClient.createOfferForIds( fingerprint: fingerprint, @@ -850,7 +979,8 @@ Future main() async { expect(offer.requestedAmounts.standard, equals(standardAmount)); }); - test('Should request to check offer validity of still valid offer and receive response', + test( + 'Should request to check offer validity of still valid offer and receive response', () async { final targetPuzzlehash = nathan.firstPuzzlehash; @@ -864,12 +994,17 @@ Future main() async { ), ); - final response = await appClient.checkOfferValidity(fingerprint: fingerprint, offer: offer); + final response = await appClient.checkOfferValidity( + fingerprint: fingerprint, + offer: offer, + ); expect(response.offerValidityData.valid, isTrue); }); - test('Should request to check offer validity of completed offer and receive response', () async { + test( + 'Should request to check offer validity of completed offer and receive response', + () async { final targetPuzzlehash = nathan.firstPuzzlehash; final offer = await nathan.offerService.createOffer( @@ -894,15 +1029,19 @@ Future main() async { expect(takeOfferResponse.takeOfferData.success, isTrue); - final validityResponse = - await appClient.checkOfferValidity(fingerprint: fingerprint, offer: offer); + final validityResponse = await appClient.checkOfferValidity( + fingerprint: fingerprint, + offer: offer, + ); expect(validityResponse.offerValidityData.valid, isFalse); }); - test('Should request to add CAT token to wallet and receive response', () async { - final assetId = - Puzzlehash.fromHex('8ebf855de6eb146db5602f0456d2f0cbe750d57f821b6f91a8592ee9f1d4cf31'); + test('Should request to add CAT token to wallet and receive response', + () async { + final assetId = Puzzlehash.fromHex( + '8ebf855de6eb146db5602f0456d2f0cbe750d57f821b6f91a8592ee9f1d4cf31', + ); const name = 'Marmot Coin'; final response = await appClient.addCatToken( diff --git a/integration_test/bin/create_wallet_with_plot_nft_command_test.dart b/integration_test/bin/create_wallet_with_plot_nft_command_test.dart new file mode 100644 index 00000000..bc30e17c --- /dev/null +++ b/integration_test/bin/create_wallet_with_plot_nft_command_test.dart @@ -0,0 +1,71 @@ +@Timeout(Duration(minutes: 3)) + +import 'dart:async'; + +import 'package:chia_crypto_utils/chia_crypto_utils.dart'; +import 'package:test/expect.dart'; +import 'package:test/scaffolding.dart'; +import 'package:test_process/test_process.dart'; + +import 'test_process_extension.dart'; + +Future main() async { + if (!(await SimulatorUtils.checkIfSimulatorIsRunning())) { + print(SimulatorUtils.simulatorNotRunningWarning); + return; + } + + final fullNodeSimulator = SimulatorFullNodeInterface.withDefaultUrl(); + ChiaNetworkContextWrapper().registerNetworkContext(Network.mainnet); + + const poolUrl = 'https://xch.spacefarmers.io'; + + test('should create plot nft', () async { + final process = await TestProcess.start( + 'dart', + [ + 'bin/chia_crypto_utils.dart', + 'Create-WalletWithPlotNFT', + '--full-node-url', + SimulatorUtils.defaultUrl, + '--pool-url', + poolUrl, + ], + ); + + const sendText = + 'Please send 1 mojo and enough XCH to cover the fee to create a Ploft NFT to'; + + final mnemonicStdout = await process.waitForStdout('Mnemonic'); + final mnemonic = mnemonicStdout.split(':').last.trim(); + + final coreSecret = KeychainCoreSecret.fromMnemonicString(mnemonic); + final keychain = WalletKeychain.fromCoreSecret(coreSecret); + + var plotNfts = + await fullNodeSimulator.scroungeForPlotNfts(keychain.puzzlehashes); + + expect(plotNfts, isEmpty); + + final sendStdout = await process.waitForStdout(sendText); + + final address = Address(sendStdout.split(':').last.trim()); + + await fullNodeSimulator.farmCoins(address); + + await process.stdout.next; + + process.enter(); + + fullNodeSimulator.run(); + + await process.nextUntilExit(); + + plotNfts = + await fullNodeSimulator.scroungeForPlotNfts(keychain.puzzlehashes); + + expect(plotNfts.length, equals(1)); + + fullNodeSimulator.stop(); + }); +} diff --git a/integration_test/bin/mutate_plot_nft_command_test.dart b/integration_test/bin/mutate_plot_nft_command_test.dart new file mode 100644 index 00000000..3d007f30 --- /dev/null +++ b/integration_test/bin/mutate_plot_nft_command_test.dart @@ -0,0 +1,102 @@ +@Timeout(Duration(minutes: 3)) + +import 'dart:async'; + +import 'package:chia_crypto_utils/chia_crypto_utils.dart'; +import 'package:test/expect.dart'; +import 'package:test/scaffolding.dart'; +import 'package:test_process/test_process.dart'; + +import 'test_process_extension.dart'; + +Future main() async { + if (!(await SimulatorUtils.checkIfSimulatorIsRunning())) { + print(SimulatorUtils.simulatorNotRunningWarning); + return; + } + + final fullNodeSimulator = SimulatorFullNodeInterface.withDefaultUrl(); + ChiaNetworkContextWrapper().registerNetworkContext(Network.mainnet); + + const poolUrl = 'https://xch.spacefarmers.io'; + + final poolWalletService = PlotNftWalletService(); + + test('should mutate ploft nft to leave pool', () async { + final grant = ChiaEnthusiast(fullNodeSimulator); + await grant.farmCoins(); + + final mnemonicString = grant.keychainSecret.mnemonicString; + + final genesisCoin = grant.standardCoins[0]; + final singletonWalletVector = grant.keychain + .getNextSingletonWalletVector(grant.keychainSecret.masterPrivateKey); + + final poolInfo = await PoolInterface.fromURL(poolUrl).getPoolInfo(); + final initialTargetState = PoolState( + poolSingletonState: PoolSingletonState.farmingToPool, + targetPuzzlehash: poolInfo.targetPuzzlehash, + ownerPublicKey: singletonWalletVector.singletonOwnerPublicKey, + relativeLockHeight: 0, + ); + + final plotNftSpendBundle = poolWalletService.createPoolNftSpendBundle( + initialTargetState: initialTargetState, + keychain: grant.keychain, + coins: grant.standardCoins, + genesisCoinId: genesisCoin.id, + p2SingletonDelayedPuzzlehash: grant.firstPuzzlehash, + changePuzzlehash: grant.firstPuzzlehash, + ); + + await fullNodeSimulator.pushTransaction(plotNftSpendBundle); + await fullNodeSimulator.moveToNextBlock(); + await grant.refreshCoins(); + + final launcherCoinPrototype = + PlotNftWalletService.makeLauncherCoin(genesisCoin.id); + + final launcherId = launcherCoinPrototype.id; + + final process = await TestProcess.start( + 'dart', + [ + 'bin/chia_crypto_utils.dart', + 'Mutate-PlotNFT', + '--full-node-url', + SimulatorUtils.defaultUrl, + '--pool-url', + poolUrl, + '--mnemonic', + mnemonicString, + ], + ); + + final sendStdout = + await process.waitForStdout('Please send 50 mojos to cover the fee to'); + + final address = Address(sendStdout.split(':').last.trim()); + + await fullNodeSimulator.farmCoins(address); + + await process.stdout.next; + + process.enter(); + + fullNodeSimulator.run(); + + await process.nextUntilExit(); + + final mutatedPlotNft = + await fullNodeSimulator.getPlotNftByLauncherId(launcherId); + + expect(mutatedPlotNft, isNotNull); + + expect( + mutatedPlotNft!.poolState.poolSingletonState, + equals(PoolSingletonState.leavingPool), + ); + + fullNodeSimulator.stop(); + }); +} diff --git a/integration_test/bin/test_process_extension.dart b/integration_test/bin/test_process_extension.dart new file mode 100644 index 00000000..3f4fad8b --- /dev/null +++ b/integration_test/bin/test_process_extension.dart @@ -0,0 +1,34 @@ +import 'package:test_process/test_process.dart'; + +extension ConvenienceMethods on TestProcess { + Future waitForStdout(String stdout) async { + String next; + do { + next = await this.stdout.next; + } while (!next.contains(stdout)); + + return next; + } + + Future nextWhileHasNext() async { + String next; + bool hasNext; + do { + next = await stdout.next; + + hasNext = await stdout.hasNext; + } while (hasNext); + + return next; + } + + Future nextUntilExit() async { + await nextWhileHasNext(); + + await shouldExit(0); + } + + void enter() { + stdin.write('\n'); + } +} diff --git a/integration_test/cat/cat1_melting_test.dart b/integration_test/cat/cat1_melting_test.dart index 4086d99f..23b6a264 100644 --- a/integration_test/cat/cat1_melting_test.dart +++ b/integration_test/cat/cat1_melting_test.dart @@ -39,9 +39,12 @@ Future main() async { await fullNodeSimulator.getCoinsByPuzzleHashes([address.toPuzzlehash()]); final originCoin = initialStandardCoins[0]; - final issuanceResult = cat1WalletService.makeMeltableMultiIssuanceCatSpendBundle( + final issuanceResult = + cat1WalletService.makeMeltableMultiIssuanceCatSpendBundle( genesisCoinId: originCoin.id, - standardCoins: [initialStandardCoins.firstWhere((coin) => coin.amount >= 10000)], + standardCoins: [ + initialStandardCoins.firstWhere((coin) => coin.amount >= 10000) + ], privateKey: walletSet.childPrivateKey, destinationPuzzlehash: puzzlehash, changePuzzlehash: puzzlehash, @@ -59,7 +62,8 @@ Future main() async { await fullNodeSimulator.pushTransaction(issuanceResult.spendBundle); await fullNodeSimulator.moveToNextBlock(); - final initialCats = await fullNodeSimulator.getCatCoinsByOuterPuzzleHashes([outerPuzzlehash]); + final initialCats = + await fullNodeSimulator.getCatCoinsByOuterPuzzleHashes([outerPuzzlehash]); // split issued cat up for tests final payments = []; @@ -78,8 +82,10 @@ Future main() async { await fullNodeSimulator.pushTransaction(sendBundle); await fullNodeSimulator.moveToNextBlock(); - final catCoins = await fullNodeSimulator.getCatCoinsByOuterPuzzleHashes([outerPuzzlehash]); - final standardCoins = await fullNodeSimulator.getCoinsByPuzzleHashes([puzzlehash]); + final catCoins = + await fullNodeSimulator.getCatCoinsByOuterPuzzleHashes([outerPuzzlehash]); + final standardCoins = + await fullNodeSimulator.getCoinsByPuzzleHashes([puzzlehash]); test('should completely melt cat coin', () async { final standardCoinsForTest = standardCoins.sublist(0, 2); @@ -88,7 +94,8 @@ Future main() async { final catCoinForTest = catCoins.removeAt(0); final initialXchBalance = await fullNodeSimulator.getBalance([puzzlehash]); - final initialCatBalance = await fullNodeSimulator.getBalance([outerPuzzlehash]); + final initialCatBalance = + await fullNodeSimulator.getBalance([outerPuzzlehash]); final meltSpendBundle = cat1WalletService.makeMeltingSpendBundle( catCoinToMelt: catCoinForTest, @@ -105,7 +112,8 @@ Future main() async { final finalXchBalance = await fullNodeSimulator.getBalance([puzzlehash]); expect(finalXchBalance - initialXchBalance, equals(catCoinForTest.amount)); - final finalCatBalance = await fullNodeSimulator.getBalance([outerPuzzlehash]); + final finalCatBalance = + await fullNodeSimulator.getBalance([outerPuzzlehash]); expect(finalCatBalance, equals(initialCatBalance - catCoinForTest.amount)); }); @@ -117,7 +125,8 @@ Future main() async { final amountToMelt = (catCoinForTest.amount / 2).round(); final initialXchBalance = await fullNodeSimulator.getBalance([puzzlehash]); - final initialCatBalance = await fullNodeSimulator.getBalance([outerPuzzlehash]); + final initialCatBalance = + await fullNodeSimulator.getBalance([outerPuzzlehash]); final meltSpendBundle = cat1WalletService.makeMeltingSpendBundle( catCoinToMelt: catCoinForTest, @@ -135,7 +144,8 @@ Future main() async { final finalXchBalance = await fullNodeSimulator.getBalance([puzzlehash]); expect(finalXchBalance, equals(amountToMelt + initialXchBalance)); - final finalCatBalance = await fullNodeSimulator.getBalance([outerPuzzlehash]); + final finalCatBalance = + await fullNodeSimulator.getBalance([outerPuzzlehash]); expect(finalCatBalance, equals(initialCatBalance - amountToMelt)); }); @@ -148,7 +158,8 @@ Future main() async { final fee = (amountToMelt * 0.2).round(); final initialXchBalance = await fullNodeSimulator.getBalance([puzzlehash]); - final initialCatBalance = await fullNodeSimulator.getBalance([outerPuzzlehash]); + final initialCatBalance = + await fullNodeSimulator.getBalance([outerPuzzlehash]); final meltSpendBundle = cat1WalletService.makeMeltingSpendBundle( catCoinToMelt: catCoinForTest, @@ -167,7 +178,8 @@ Future main() async { final finalXchBalance = await fullNodeSimulator.getBalance([puzzlehash]); expect(finalXchBalance, equals(amountToMelt + initialXchBalance - fee)); - final finalCatBalance = await fullNodeSimulator.getBalance([outerPuzzlehash]); + final finalCatBalance = + await fullNodeSimulator.getBalance([outerPuzzlehash]); expect(finalCatBalance, equals(initialCatBalance - amountToMelt)); }); } diff --git a/integration_test/cat/cat1_wallet_service_integration_test.dart b/integration_test/cat/cat1_wallet_service_integration_test.dart index e83d8c2b..e264f7cf 100644 --- a/integration_test/cat/cat1_wallet_service_integration_test.dart +++ b/integration_test/cat/cat1_wallet_service_integration_test.dart @@ -31,17 +31,19 @@ Future main() async { } await fullNodeSimulator.moveToNextBlock(); - var senderStandardCoins = await fullNodeSimulator.getCoinsByPuzzleHashes([senderPuzzlehash]); + var senderStandardCoins = + await fullNodeSimulator.getCoinsByPuzzleHashes([senderPuzzlehash]); final originCoin = senderStandardCoins[0]; // issue cat - final curriedTail = - delegatedTailProgram.curry([Program.fromAtom(senderWalletSet.childPublicKey.toBytes())]); + final curriedTail = delegatedTailProgram + .curry([Program.fromAtom(senderWalletSet.childPublicKey.toBytes())]); final assetId = Puzzlehash(curriedTail.hash()); final curriedGenesisByCoinIdPuzzle = genesisByCoinIdProgram.curry([Program.fromAtom(originCoin.id)]); - final tailSolution = Program.list([curriedGenesisByCoinIdPuzzle, Program.nil]); + final tailSolution = + Program.list([curriedGenesisByCoinIdPuzzle, Program.nil]); final signature = AugSchemeMPL.sign( senderWalletSet.childPrivateKey, @@ -51,7 +53,9 @@ Future main() async { final spendBundle = catWalletService.makeIssuanceSpendbundle( tail: curriedTail, solution: tailSolution, - standardCoins: [senderStandardCoins.firstWhere((coin) => coin.amount >= 10000)], + standardCoins: [ + senderStandardCoins.firstWhere((coin) => coin.amount >= 10000) + ], destinationPuzzlehash: senderPuzzlehash, changePuzzlehash: senderPuzzlehash, amount: 10000, @@ -67,7 +71,8 @@ Future main() async { ); assert(senderCatCoins.isNotEmpty, true); - senderStandardCoins = await fullNodeSimulator.getCoinsByPuzzleHashes([senderPuzzlehash]); + senderStandardCoins = + await fullNodeSimulator.getCoinsByPuzzleHashes([senderPuzzlehash]); final payments = []; for (var i = 0; i < 10; i++) { // to avoid duplicate coins amounts must differ @@ -83,22 +88,27 @@ Future main() async { await fullNodeSimulator.pushTransaction(sendBundle); await fullNodeSimulator.moveToNextBlock(); - final senderOuterPuzzlehash = WalletKeychain.makeCat1OuterPuzzleHash(senderPuzzlehash, assetId); + final senderOuterPuzzlehash = + WalletKeychain.makeCat1OuterPuzzleHash(senderPuzzlehash, assetId); final receiverWalletSet = keychain.unhardenedMap.values.toList()[1]; final receiverPuzzlehash = receiverWalletSet.puzzlehash; final receiverOuterPuzzlehash = WalletKeychain.makeCat1OuterPuzzleHash(receiverPuzzlehash, assetId); - senderCatCoins = await fullNodeSimulator.getCatCoinsByOuterPuzzleHashes([senderOuterPuzzlehash]); - senderStandardCoins = await fullNodeSimulator.getCoinsByPuzzleHashes([senderPuzzlehash]); + senderCatCoins = await fullNodeSimulator + .getCatCoinsByOuterPuzzleHashes([senderOuterPuzzlehash]); + senderStandardCoins = + await fullNodeSimulator.getCoinsByPuzzleHashes([senderPuzzlehash]); test('spends multiple cat coins correctly', () async { final catCoinsForThisTest = senderCatCoins.sublist(0, 2); senderCatCoins.removeWhere(catCoinsForThisTest.contains); - final senderStartingBalance = await fullNodeSimulator.getBalance([senderOuterPuzzlehash]); - final receiverStartingBalance = await fullNodeSimulator.getBalance([receiverOuterPuzzlehash]); + final senderStartingBalance = + await fullNodeSimulator.getBalance([senderOuterPuzzlehash]); + final receiverStartingBalance = + await fullNodeSimulator.getBalance([receiverOuterPuzzlehash]); final totalNateCoinValue = catCoinsForThisTest.fold( 0, @@ -116,10 +126,12 @@ Future main() async { await fullNodeSimulator.pushTransaction(spendBundle); await fullNodeSimulator.moveToNextBlock(); - final senderEndingBalance = await fullNodeSimulator.getBalance([senderOuterPuzzlehash]); + final senderEndingBalance = + await fullNodeSimulator.getBalance([senderOuterPuzzlehash]); expect(senderEndingBalance, senderStartingBalance - amountToSend); - final receiverEndingBalance = await fullNodeSimulator.getBalance([receiverOuterPuzzlehash]); + final receiverEndingBalance = + await fullNodeSimulator.getBalance([receiverOuterPuzzlehash]); expect(receiverEndingBalance, receiverStartingBalance + amountToSend); }); @@ -157,13 +169,15 @@ Future main() async { await fullNodeSimulator.pushTransaction(spendBundle); await fullNodeSimulator.moveToNextBlock(); - final senderEndingStandardCoinBalance = await fullNodeSimulator.getBalance([senderPuzzlehash]); + final senderEndingStandardCoinBalance = + await fullNodeSimulator.getBalance([senderPuzzlehash]); expect( senderEndingStandardCoinBalance, senderStartingStandardCoinBalance - fee, ); - final senderEndingNateCoinBalance = await fullNodeSimulator.getBalance([senderOuterPuzzlehash]); + final senderEndingNateCoinBalance = + await fullNodeSimulator.getBalance([senderOuterPuzzlehash]); expect( senderEndingNateCoinBalance, senderStartingNateCoinBalance - amountToSend, @@ -171,10 +185,14 @@ Future main() async { final receiverEndingNateCoinBalance = await fullNodeSimulator.getBalance([receiverOuterPuzzlehash]); - expect(receiverEndingNateCoinBalance, receiverStartingNateCoinBalance + amountToSend); + expect( + receiverEndingNateCoinBalance, + receiverStartingNateCoinBalance + amountToSend, + ); }); - test('Produces valid spendbundle with fee, multiple payments, and memos', () async { + test('Produces valid spendbundle with fee, multiple payments, and memos', + () async { final catCoinsForThisTest = senderCatCoins.sublist(0, 2); senderCatCoins.removeWhere(catCoinsForThisTest.contains); @@ -186,14 +204,21 @@ Future main() async { final senderStartingStandardCoinBalance = await fullNodeSimulator.getBalance([senderPuzzlehash]); - final receiverStartingCatCoins = - await fullNodeSimulator.getCoinsByPuzzleHashes([receiverOuterPuzzlehash]); - final receiverStartingNateCoinBalance = - receiverStartingCatCoins.fold(0, (int previousValue, coin) => previousValue + coin.amount); + final receiverStartingCatCoins = await fullNodeSimulator + .getCoinsByPuzzleHashes([receiverOuterPuzzlehash]); + final receiverStartingNateCoinBalance = receiverStartingCatCoins.fold( + 0, + (int previousValue, coin) => previousValue + coin.amount, + ); - final totalNateCoinValue = - catCoinsForThisTest.fold(0, (int previousValue, coin) => previousValue + coin.amount); - final sendAmounts = [(totalNateCoinValue * 0.4).round(), (totalNateCoinValue * 0.3).round()]; + final totalNateCoinValue = catCoinsForThisTest.fold( + 0, + (int previousValue, coin) => previousValue + coin.amount, + ); + final sendAmounts = [ + (totalNateCoinValue * 0.4).round(), + (totalNateCoinValue * 0.3).round() + ]; final totalAmountToSend = sendAmounts.fold( 0, (int previousValue, amount) => previousValue + amount, @@ -224,20 +249,34 @@ Future main() async { await fullNodeSimulator.pushTransaction(spendBundle); await fullNodeSimulator.moveToNextBlock(); - final senderEndingStandardCoinBalance = await fullNodeSimulator.getBalance([senderPuzzlehash]); - expect(senderEndingStandardCoinBalance, senderStartingStandardCoinBalance - fee); + final senderEndingStandardCoinBalance = + await fullNodeSimulator.getBalance([senderPuzzlehash]); + expect( + senderEndingStandardCoinBalance, + senderStartingStandardCoinBalance - fee, + ); - final senderEndingNateCoinBalance = await fullNodeSimulator.getBalance([senderOuterPuzzlehash]); - expect(senderEndingNateCoinBalance, senderStartingNateCoinBalance - totalAmountToSend); + final senderEndingNateCoinBalance = + await fullNodeSimulator.getBalance([senderOuterPuzzlehash]); + expect( + senderEndingNateCoinBalance, + senderStartingNateCoinBalance - totalAmountToSend, + ); - final receiverEndingCatCoins = - await fullNodeSimulator.getCoinsByPuzzleHashes([receiverOuterPuzzlehash]); - final receiverEndingNateCoinBalance = - receiverEndingCatCoins.fold(0, (int previousValue, coin) => previousValue + coin.amount); - expect(receiverEndingNateCoinBalance, receiverStartingNateCoinBalance + totalAmountToSend); + final receiverEndingCatCoins = await fullNodeSimulator + .getCoinsByPuzzleHashes([receiverOuterPuzzlehash]); + final receiverEndingNateCoinBalance = receiverEndingCatCoins.fold( + 0, + (int previousValue, coin) => previousValue + coin.amount, + ); + expect( + receiverEndingNateCoinBalance, + receiverStartingNateCoinBalance + totalAmountToSend, + ); - final newCoins = - receiverEndingCatCoins.where((coin) => !receiverStartingCatCoins.contains(coin)).toList(); + final newCoins = receiverEndingCatCoins + .where((coin) => !receiverStartingCatCoins.contains(coin)) + .toList(); expect(newCoins.length, 2); expect( () { diff --git a/integration_test/cat/cat_melting_test.dart b/integration_test/cat/cat_melting_test.dart index b983064b..24070aa1 100644 --- a/integration_test/cat/cat_melting_test.dart +++ b/integration_test/cat/cat_melting_test.dart @@ -38,9 +38,12 @@ Future main() async { await fullNodeSimulator.getCoinsByPuzzleHashes([address.toPuzzlehash()]); final originCoin = initialStandardCoins[0]; - final issuanceResult = catWalletService.makeMeltableMultiIssuanceCatSpendBundle( + final issuanceResult = + catWalletService.makeMeltableMultiIssuanceCatSpendBundle( genesisCoinId: originCoin.id, - standardCoins: [initialStandardCoins.firstWhere((coin) => coin.amount >= 10000)], + standardCoins: [ + initialStandardCoins.firstWhere((coin) => coin.amount >= 10000) + ], privateKey: walletSet.childPrivateKey, destinationPuzzlehash: puzzlehash, changePuzzlehash: puzzlehash, @@ -50,7 +53,6 @@ Future main() async { final tailRunningInfo = issuanceResult.tailRunningInfo; - await fullNodeSimulator.pushTransaction(issuanceResult.spendBundle); await fullNodeSimulator.moveToNextBlock(); @@ -59,7 +61,8 @@ Future main() async { tailRunningInfo.assetId, ); - final initialCats = await fullNodeSimulator.getCatCoinsByOuterPuzzleHashes([outerPuzzlehash]); + final initialCats = + await fullNodeSimulator.getCatCoinsByOuterPuzzleHashes([outerPuzzlehash]); // split issued cat up for tests final payments = []; @@ -78,8 +81,10 @@ Future main() async { await fullNodeSimulator.pushTransaction(sendBundle); await fullNodeSimulator.moveToNextBlock(); - final catCoins = await fullNodeSimulator.getCatCoinsByOuterPuzzleHashes([outerPuzzlehash]); - final standardCoins = await fullNodeSimulator.getCoinsByPuzzleHashes([puzzlehash]); + final catCoins = + await fullNodeSimulator.getCatCoinsByOuterPuzzleHashes([outerPuzzlehash]); + final standardCoins = + await fullNodeSimulator.getCoinsByPuzzleHashes([puzzlehash]); test('should completely melt cat coin', () async { final standardCoinsForTest = standardCoins.sublist(0, 2); @@ -88,7 +93,8 @@ Future main() async { final catCoinForTest = catCoins.removeAt(0); final initialXchBalance = await fullNodeSimulator.getBalance([puzzlehash]); - final initialCatBalance = await fullNodeSimulator.getBalance([outerPuzzlehash]); + final initialCatBalance = + await fullNodeSimulator.getBalance([outerPuzzlehash]); final meltSpendBundle = catWalletService.makeMeltingSpendBundle( catCoinToMelt: catCoinForTest, @@ -105,7 +111,8 @@ Future main() async { final finalXchBalance = await fullNodeSimulator.getBalance([puzzlehash]); expect(finalXchBalance - initialXchBalance, equals(catCoinForTest.amount)); - final finalCatBalance = await fullNodeSimulator.getBalance([outerPuzzlehash]); + final finalCatBalance = + await fullNodeSimulator.getBalance([outerPuzzlehash]); expect(finalCatBalance, equals(initialCatBalance - catCoinForTest.amount)); }); @@ -117,7 +124,8 @@ Future main() async { final amountToMelt = (catCoinForTest.amount / 2).round(); final initialXchBalance = await fullNodeSimulator.getBalance([puzzlehash]); - final initialCatBalance = await fullNodeSimulator.getBalance([outerPuzzlehash]); + final initialCatBalance = + await fullNodeSimulator.getBalance([outerPuzzlehash]); final meltSpendBundle = catWalletService.makeMeltingSpendBundle( catCoinToMelt: catCoinForTest, @@ -135,7 +143,8 @@ Future main() async { final finalXchBalance = await fullNodeSimulator.getBalance([puzzlehash]); expect(finalXchBalance, equals(amountToMelt + initialXchBalance)); - final finalCatBalance = await fullNodeSimulator.getBalance([outerPuzzlehash]); + final finalCatBalance = + await fullNodeSimulator.getBalance([outerPuzzlehash]); expect(finalCatBalance, equals(initialCatBalance - amountToMelt)); }); @@ -148,7 +157,8 @@ Future main() async { final fee = (amountToMelt * 0.2).round(); final initialXchBalance = await fullNodeSimulator.getBalance([puzzlehash]); - final initialCatBalance = await fullNodeSimulator.getBalance([outerPuzzlehash]); + final initialCatBalance = + await fullNodeSimulator.getBalance([outerPuzzlehash]); final meltSpendBundle = catWalletService.makeMeltingSpendBundle( catCoinToMelt: catCoinForTest, @@ -167,7 +177,8 @@ Future main() async { final finalXchBalance = await fullNodeSimulator.getBalance([puzzlehash]); expect(finalXchBalance, equals(amountToMelt + initialXchBalance - fee)); - final finalCatBalance = await fullNodeSimulator.getBalance([outerPuzzlehash]); + final finalCatBalance = + await fullNodeSimulator.getBalance([outerPuzzlehash]); expect(finalCatBalance, equals(initialCatBalance - amountToMelt)); }); } diff --git a/integration_test/cat/cat_multi_issuance_test.dart b/integration_test/cat/cat_multi_issuance_test.dart index e553e5a7..1a87a5ea 100644 --- a/integration_test/cat/cat_multi_issuance_test.dart +++ b/integration_test/cat/cat_multi_issuance_test.dart @@ -21,10 +21,12 @@ void main() async { ChiaNetworkContextWrapper().registerNetworkContext(Network.mainnet); final catWalletService = EverythingWithSignatureTailService(); - final tailPrivateKey = nathan.keychain.unhardenedWalletVectors.first.childPrivateKey; + final tailPrivateKey = + nathan.keychain.unhardenedWalletVectors.first.childPrivateKey; test('should issue cat multiple times', () async { - final standardCoin = nathan.standardCoins.firstWhere((coin) => coin.amount >= 10000); + final standardCoin = + nathan.standardCoins.firstWhere((coin) => coin.amount >= 10000); final issuanceResult = catWalletService.makeIssuanceSpendBundle( standardCoins: [standardCoin], tailPrivateKey: tailPrivateKey, diff --git a/integration_test/cat/cat_wallet_service_integration_test.dart b/integration_test/cat/cat_wallet_service_integration_test.dart index 2f055701..c54d6fc8 100644 --- a/integration_test/cat/cat_wallet_service_integration_test.dart +++ b/integration_test/cat/cat_wallet_service_integration_test.dart @@ -31,17 +31,19 @@ Future main() async { } await fullNodeSimulator.moveToNextBlock(); - var senderStandardCoins = await fullNodeSimulator.getCoinsByPuzzleHashes([senderPuzzlehash]); + var senderStandardCoins = + await fullNodeSimulator.getCoinsByPuzzleHashes([senderPuzzlehash]); final originCoin = senderStandardCoins[0]; // issue cat - final curriedTail = - delegatedTailProgram.curry([Program.fromAtom(senderWalletSet.childPublicKey.toBytes())]); + final curriedTail = delegatedTailProgram + .curry([Program.fromAtom(senderWalletSet.childPublicKey.toBytes())]); final assetId = Puzzlehash(curriedTail.hash()); final curriedGenesisByCoinIdPuzzle = genesisByCoinIdProgram.curry([Program.fromAtom(originCoin.id)]); - final tailSolution = Program.list([curriedGenesisByCoinIdPuzzle, Program.nil]); + final tailSolution = + Program.list([curriedGenesisByCoinIdPuzzle, Program.nil]); final signature = AugSchemeMPL.sign( senderWalletSet.childPrivateKey, @@ -51,7 +53,9 @@ Future main() async { final spendBundle = catWalletService.makeIssuanceSpendbundle( tail: curriedTail, solution: tailSolution, - standardCoins: [senderStandardCoins.firstWhere((coin) => coin.amount >= 10000)], + standardCoins: [ + senderStandardCoins.firstWhere((coin) => coin.amount >= 10000) + ], destinationPuzzlehash: senderPuzzlehash, changePuzzlehash: senderPuzzlehash, amount: 10000, @@ -67,7 +71,8 @@ Future main() async { ); assert(senderCatCoins.isNotEmpty, true); - senderStandardCoins = await fullNodeSimulator.getCoinsByPuzzleHashes([senderPuzzlehash]); + senderStandardCoins = + await fullNodeSimulator.getCoinsByPuzzleHashes([senderPuzzlehash]); final payments = []; for (var i = 0; i < 10; i++) { // to avoid duplicate coins amounts must differ @@ -83,14 +88,18 @@ Future main() async { await fullNodeSimulator.pushTransaction(sendBundle); await fullNodeSimulator.moveToNextBlock(); - final senderOuterPuzzlehash = WalletKeychain.makeOuterPuzzleHash(senderPuzzlehash, assetId); + final senderOuterPuzzlehash = + WalletKeychain.makeOuterPuzzleHash(senderPuzzlehash, assetId); final receiverWalletSet = keychain.unhardenedMap.values.toList()[1]; final receiverPuzzlehash = receiverWalletSet.puzzlehash; - final receiverOuterPuzzlehash = WalletKeychain.makeOuterPuzzleHash(receiverPuzzlehash, assetId); + final receiverOuterPuzzlehash = + WalletKeychain.makeOuterPuzzleHash(receiverPuzzlehash, assetId); - senderCatCoins = await fullNodeSimulator.getCatCoinsByOuterPuzzleHashes([senderOuterPuzzlehash]); - senderStandardCoins = await fullNodeSimulator.getCoinsByPuzzleHashes([senderPuzzlehash]); + senderCatCoins = await fullNodeSimulator + .getCatCoinsByOuterPuzzleHashes([senderOuterPuzzlehash]); + senderStandardCoins = + await fullNodeSimulator.getCoinsByPuzzleHashes([senderPuzzlehash]); test('spends multiple cat coins correctly', () async { final catCoinsForThisTest = senderCatCoins.sublist(0, 2); @@ -101,8 +110,10 @@ Future main() async { senderCatCoins.removeWhere(catCoinsForThisTest.contains); - final senderStartingBalance = await fullNodeSimulator.getBalance([senderOuterPuzzlehash]); - final receiverStartingBalance = await fullNodeSimulator.getBalance([receiverOuterPuzzlehash]); + final senderStartingBalance = + await fullNodeSimulator.getBalance([senderOuterPuzzlehash]); + final receiverStartingBalance = + await fullNodeSimulator.getBalance([receiverOuterPuzzlehash]); final totalNateCoinValue = catCoinsForThisTest.fold( 0, @@ -120,14 +131,16 @@ Future main() async { await fullNodeSimulator.pushTransaction(spendBundle); await fullNodeSimulator.moveToNextBlock(); - final senderEndingBalance = await fullNodeSimulator.getBalance([senderOuterPuzzlehash]); + final senderEndingBalance = + await fullNodeSimulator.getBalance([senderOuterPuzzlehash]); expect(senderEndingBalance, senderStartingBalance - amountToSend); - final receiverEndingBalance = await fullNodeSimulator.getBalance([receiverOuterPuzzlehash]); + final receiverEndingBalance = + await fullNodeSimulator.getBalance([receiverOuterPuzzlehash]); expect(receiverEndingBalance, receiverStartingBalance + amountToSend); - final receiverEndingCoins = - await fullNodeSimulator.getCatCoinsByOuterPuzzleHashes([receiverOuterPuzzlehash]); + final receiverEndingCoins = await fullNodeSimulator + .getCatCoinsByOuterPuzzleHashes([receiverOuterPuzzlehash]); for (final coin in receiverEndingCoins) { final p2PuzzleHash = await coin.getP2Puzzlehash(); expect(p2PuzzleHash, receiverPuzzlehash); @@ -169,13 +182,15 @@ Future main() async { await fullNodeSimulator.pushTransaction(spendBundle); await fullNodeSimulator.moveToNextBlock(); - final senderEndingStandardCoinBalance = await fullNodeSimulator.getBalance([senderPuzzlehash]); + final senderEndingStandardCoinBalance = + await fullNodeSimulator.getBalance([senderPuzzlehash]); expect( senderEndingStandardCoinBalance, senderStartingStandardCoinBalance - fee, ); - final senderEndingNateCoinBalance = await fullNodeSimulator.getBalance([senderOuterPuzzlehash]); + final senderEndingNateCoinBalance = + await fullNodeSimulator.getBalance([senderOuterPuzzlehash]); expect( senderEndingNateCoinBalance, senderStartingNateCoinBalance - amountToSend, @@ -183,10 +198,14 @@ Future main() async { final receiverEndingNateCoinBalance = await fullNodeSimulator.getBalance([receiverOuterPuzzlehash]); - expect(receiverEndingNateCoinBalance, receiverStartingNateCoinBalance + amountToSend); + expect( + receiverEndingNateCoinBalance, + receiverStartingNateCoinBalance + amountToSend, + ); }); - test('Produces valid spendbundle with fee, multiple payments, and memos', () async { + test('Produces valid spendbundle with fee, multiple payments, and memos', + () async { final catCoinsForThisTest = senderCatCoins.sublist(0, 2); senderCatCoins.removeWhere(catCoinsForThisTest.contains); @@ -198,14 +217,21 @@ Future main() async { final senderStartingStandardCoinBalance = await fullNodeSimulator.getBalance([senderPuzzlehash]); - final receiverStartingCatCoins = - await fullNodeSimulator.getCoinsByPuzzleHashes([receiverOuterPuzzlehash]); - final receiverStartingNateCoinBalance = - receiverStartingCatCoins.fold(0, (int previousValue, coin) => previousValue + coin.amount); + final receiverStartingCatCoins = await fullNodeSimulator + .getCoinsByPuzzleHashes([receiverOuterPuzzlehash]); + final receiverStartingNateCoinBalance = receiverStartingCatCoins.fold( + 0, + (int previousValue, coin) => previousValue + coin.amount, + ); - final totalNateCoinValue = - catCoinsForThisTest.fold(0, (int previousValue, coin) => previousValue + coin.amount); - final sendAmounts = [(totalNateCoinValue * 0.4).round(), (totalNateCoinValue * 0.3).round()]; + final totalNateCoinValue = catCoinsForThisTest.fold( + 0, + (int previousValue, coin) => previousValue + coin.amount, + ); + final sendAmounts = [ + (totalNateCoinValue * 0.4).round(), + (totalNateCoinValue * 0.3).round() + ]; final totalAmountToSend = sendAmounts.fold( 0, (int previousValue, amount) => previousValue + amount, @@ -236,20 +262,34 @@ Future main() async { await fullNodeSimulator.pushTransaction(spendBundle); await fullNodeSimulator.moveToNextBlock(); - final senderEndingStandardCoinBalance = await fullNodeSimulator.getBalance([senderPuzzlehash]); - expect(senderEndingStandardCoinBalance, senderStartingStandardCoinBalance - fee); + final senderEndingStandardCoinBalance = + await fullNodeSimulator.getBalance([senderPuzzlehash]); + expect( + senderEndingStandardCoinBalance, + senderStartingStandardCoinBalance - fee, + ); - final senderEndingNateCoinBalance = await fullNodeSimulator.getBalance([senderOuterPuzzlehash]); - expect(senderEndingNateCoinBalance, senderStartingNateCoinBalance - totalAmountToSend); + final senderEndingNateCoinBalance = + await fullNodeSimulator.getBalance([senderOuterPuzzlehash]); + expect( + senderEndingNateCoinBalance, + senderStartingNateCoinBalance - totalAmountToSend, + ); - final receiverEndingCatCoins = - await fullNodeSimulator.getCoinsByPuzzleHashes([receiverOuterPuzzlehash]); - final receiverEndingNateCoinBalance = - receiverEndingCatCoins.fold(0, (int previousValue, coin) => previousValue + coin.amount); - expect(receiverEndingNateCoinBalance, receiverStartingNateCoinBalance + totalAmountToSend); + final receiverEndingCatCoins = await fullNodeSimulator + .getCoinsByPuzzleHashes([receiverOuterPuzzlehash]); + final receiverEndingNateCoinBalance = receiverEndingCatCoins.fold( + 0, + (int previousValue, coin) => previousValue + coin.amount, + ); + expect( + receiverEndingNateCoinBalance, + receiverStartingNateCoinBalance + totalAmountToSend, + ); - final newCoins = - receiverEndingCatCoins.where((coin) => !receiverStartingCatCoins.contains(coin)).toList(); + final newCoins = receiverEndingCatCoins + .where((coin) => !receiverStartingCatCoins.contains(coin)) + .toList(); expect(newCoins.length, 2); expect( () { diff --git a/integration_test/coin_splitting/coin_splitting_test.dart b/integration_test/coin_splitting/coin_splitting_test.dart index a43f347b..21dc141c 100644 --- a/integration_test/coin_splitting/coin_splitting_test.dart +++ b/integration_test/coin_splitting/coin_splitting_test.dart @@ -69,7 +69,11 @@ void main() async { if (testCase.splitWidth > testCase.numberOfCoins) { expect( constructSpendBundle, - throwsA(predicate((p0) => p0 is InvalidCoinSplittingParametersException)), + throwsA( + predicate( + (p0) => p0 is InvalidCoinSplittingParametersException, + ), + ), ); return; } else { @@ -83,15 +87,18 @@ void main() async { await nathan.refreshCoins(); final endingCoins = nathan.standardCoins; - final totalFee = - (testCase.numberOfCoins / testCase.splitWidth).ceil() * testCase.feePerCoin; + final totalFee = (testCase.numberOfCoins / testCase.splitWidth).ceil() * + testCase.feePerCoin; expect( endingCoins.totalValue, initialCoins.totalValue - totalFee, ); - expect(endingCoins.length, initialCoins.length + testCase.numberOfCoins); + expect( + endingCoins.length, + initialCoins.length + testCase.numberOfCoins, + ); var matchingCoinAmounts = 0; diff --git a/integration_test/coin_switching/nft_verification.dart b/integration_test/coin_switching/nft_verification.dart deleted file mode 100644 index 8e2e9cbf..00000000 --- a/integration_test/coin_switching/nft_verification.dart +++ /dev/null @@ -1,21 +0,0 @@ -import 'package:chia_crypto_utils/chia_crypto_utils.dart'; - -void main() async { - final mnemonic = - 'sniff wrestle coin sign one expect seed spirit summer bracket choose lumber bottom risk hip jealous fold hotel baby account chest stock humor pudding' - .split(' '); - final keychain = - WalletKeychain.fromCoreSecret(KeychainCoreSecret.fromMnemonic(mnemonic), walletSize: 50); - LoggingContext().setLogLevel(LogLevel.low); - ChiaNetworkContextWrapper().registerNetworkContext(Network.mainnet); - - final fullNode = EnhancedChiaFullNodeInterface.fromUrl('https://chia.irulast-prod.com'); - - final nfts = await fullNode.getNftRecordsByHints(keychain.puzzlehashes); - - final nft = nfts.first; - - final proofOfNft = nft.getProofOfNft(keychain); - - print(await proofOfNft.verify(fullNode)); -} diff --git a/integration_test/coin_switching/nft_verification_test.dart b/integration_test/coin_switching/nft_verification_test.dart new file mode 100644 index 00000000..626f1215 --- /dev/null +++ b/integration_test/coin_switching/nft_verification_test.dart @@ -0,0 +1,30 @@ +@Skip('interacts with live full node') +import 'package:chia_crypto_utils/chia_crypto_utils.dart'; +import 'package:test/test.dart'; + +void main() async { + const url = 'FULL_NODE_URL'; + const mnemonicString = 'MNEMONIC_STRING'; + + final mnemonic = mnemonicString.split(' '); + final keychain = WalletKeychain.fromCoreSecret( + KeychainCoreSecret.fromMnemonic(mnemonic), + walletSize: 50, + ); + LoggingContext().setLogLevel(LogLevel.low); + ChiaNetworkContextWrapper().registerNetworkContext(Network.mainnet); + + final fullNode = EnhancedChiaFullNodeInterface.fromUrl(url); + + final nfts = await fullNode.getNftRecordsByHints(keychain.puzzlehashes); + + final nft = nfts.first; + + final proofOfNft = nft.getProofOfNft(keychain); + + test('should verify nft', () async { + final verificationResult = await proofOfNft.verify(fullNode); + + print(verificationResult); + }); +} diff --git a/integration_test/core/nuke_keychain_test.dart b/integration_test/core/nuke_keychain_test.dart index ec56c299..e17e5357 100644 --- a/integration_test/core/nuke_keychain_test.dart +++ b/integration_test/core/nuke_keychain_test.dart @@ -33,7 +33,8 @@ void main() async { await nathan.issueMultiIssuanceCat(); await nathan.issueMultiIssuanceCat(); - final nftBulkMintSpendBundle = NftWalletService().createDidNftBulkMintSpendBundle( + final nftBulkMintSpendBundle = + NftWalletService().createDidNftBulkMintSpendBundle( targetPuzzlehash: nathan.puzzlehashes.first, nftMintData: await NftMintingDataWithHashes.makeUniformBulkMintData( uriHashProvider: MockUriHashProvider(), @@ -70,7 +71,9 @@ void main() async { await meera.issueMultiIssuanceCat(); await fullNodeSimulator.pushTransaction( Cat2WalletService().createSpendBundle( - payments: [CatPayment(meera.catCoins.totalValue, nathan.puzzlehashes[i])], + payments: [ + CatPayment(meera.catCoins.totalValue, nathan.puzzlehashes[i]) + ], catCoinsInput: meera.catCoins, keychain: meera.keychain, ), @@ -88,8 +91,10 @@ void main() async { final initialStandardCoins = nathan.standardCoins; expect(initialStandardCoins.length, 19); - final initialNfts = await fullNode.getNftRecordsByHints(nathan.puzzlehashes); - final initialDids = await fullNode.getDidRecordsByHints(nathan.puzzlehashes); + final initialNfts = + await fullNode.getNftRecordsByHints(nathan.puzzlehashes); + final initialDids = + await fullNode.getDidRecordsByHints(nathan.puzzlehashes); expect(initialNfts.length, 10); expect(initialDids.length, 6); diff --git a/integration_test/custom_coins/dependent_coin/dependent_coin_test.dart b/integration_test/custom_coins/dependent_coin/dependent_coin_test.dart index 74389dd9..1e301c7c 100644 --- a/integration_test/custom_coins/dependent_coin/dependent_coin_test.dart +++ b/integration_test/custom_coins/dependent_coin/dependent_coin_test.dart @@ -57,7 +57,8 @@ void main() async { await nathan.refreshCoins(); - nftRecord = (await fullNodeSimulator.getNftRecordsByHint(targetPuzzleHash)).single; + nftRecord = + (await fullNodeSimulator.getNftRecordsByHint(targetPuzzleHash)).single; }); test('should create and spend dependent fee coin', () async { @@ -78,21 +79,25 @@ void main() async { final dependentCoin = dependentCoinsAndCreationBundle.dependentCoins.first; - await fullNodeSimulator.pushTransaction(dependentCoinsAndCreationBundle.creationBundle); + await fullNodeSimulator + .pushTransaction(dependentCoinsAndCreationBundle.creationBundle); await fullNodeSimulator.moveToNextBlock(); - final dependentCoinFromBlockchain = await fullNodeSimulator.getCoinById(dependentCoin.id); + final dependentCoinFromBlockchain = + await fullNodeSimulator.getCoinById(dependentCoin.id); expect(dependentCoin, dependentCoinFromBlockchain); - final dependentFeeBundle = dependentCoinWalletService.createFeeCoinSpendBundle( + final dependentFeeBundle = + dependentCoinWalletService.createFeeCoinSpendBundle( dependentCoin: dependentCoinsAndCreationBundle.dependentCoins.first, ); await fullNodeSimulator.pushTransaction(nftSendBundle + dependentFeeBundle); }); - test('should fail to spend dependent coin if condition is not satisfied', () async { + test('should fail to spend dependent coin if condition is not satisfied', + () async { final dependentCoinsAndCreationBundle = dependentCoinWalletService.createGenerateDependentCoinsSpendBundle( amountPerCoin: 50, @@ -104,14 +109,17 @@ void main() async { final dependentCoin = dependentCoinsAndCreationBundle.dependentCoins.first; - await fullNodeSimulator.pushTransaction(dependentCoinsAndCreationBundle.creationBundle); + await fullNodeSimulator + .pushTransaction(dependentCoinsAndCreationBundle.creationBundle); await fullNodeSimulator.moveToNextBlock(); - final dependentCoinFromBlockchain = await fullNodeSimulator.getCoinById(dependentCoin.id); + final dependentCoinFromBlockchain = + await fullNodeSimulator.getCoinById(dependentCoin.id); expect(dependentCoin, dependentCoinFromBlockchain); - final dependentFeeBundle = dependentCoinWalletService.createFeeCoinSpendBundle( + final dependentFeeBundle = + dependentCoinWalletService.createFeeCoinSpendBundle( dependentCoin: dependentCoinsAndCreationBundle.dependentCoins.first, ); // add pointless signature to avoid out of range full node bug @@ -127,7 +135,8 @@ void main() async { expect( () async { - await fullNodeSimulator.pushTransaction(mockSignatureSpendBundle + dependentFeeBundle); + await fullNodeSimulator + .pushTransaction(mockSignatureSpendBundle + dependentFeeBundle); }, throwsA(const TypeMatcher()), ); diff --git a/integration_test/did/did_exit_spend_test.dart b/integration_test/did/did_exit_spend_test.dart index ade1d3e1..95867351 100644 --- a/integration_test/did/did_exit_spend_test.dart +++ b/integration_test/did/did_exit_spend_test.dart @@ -25,14 +25,17 @@ Future main() async { final didWalletService = DIDWalletService(); final puzzlehash = walletVector.puzzlehash; - final address = - Address.fromPuzzlehash(puzzlehash, didWalletService.blockchainNetwork.addressPrefix); + final address = Address.fromPuzzlehash( + puzzlehash, + didWalletService.blockchainNetwork.addressPrefix, + ); await fullNodeSimulator.farmCoins(address); await fullNodeSimulator.farmCoins(address); await fullNodeSimulator.moveToNextBlock(); - final standardCoins = await fullNodeSimulator.getCoinsByPuzzleHashes([puzzlehash]); + final standardCoins = + await fullNodeSimulator.getCoinsByPuzzleHashes([puzzlehash]); final didSpendBundle = didWalletService.createGenerateDIDSpendBundle( standardCoins: [standardCoins[0]], @@ -44,7 +47,8 @@ Future main() async { await fullNodeSimulator.pushTransaction(didSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final didsAfterCreation = await fullNodeSimulator.getDidRecordsFromHint(walletVector.puzzlehash); + final didsAfterCreation = + await fullNodeSimulator.getDidRecordsFromHint(walletVector.puzzlehash); final didInfo = didsAfterCreation[0]; @@ -57,19 +61,22 @@ Future main() async { await fullNodeSimulator.pushTransaction(exitSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final didAfterDestruction = await fullNodeSimulator - .getDidRecordsByPuzzleHashes([walletVector.puzzlehash, exitWalletVector.puzzlehash]); + final didAfterDestruction = + await fullNodeSimulator.getDidRecordsByPuzzleHashes( + [walletVector.puzzlehash, exitWalletVector.puzzlehash], + ); expect(didAfterDestruction.length, equals(0)); - final newStandardCoins = - await fullNodeSimulator.getCoinsByPuzzleHashes([exitWalletVector.puzzlehash]); + final newStandardCoins = await fullNodeSimulator + .getCoinsByPuzzleHashes([exitWalletVector.puzzlehash]); expect(newStandardCoins.length, equals(1)); final newStandardCoin = newStandardCoins[0]; expect(newStandardCoin.amount, equals(didInfo.coin.amount - 1)); // should be able to spend standardCoin - final standardSpendBundle = didWalletService.standardWalletService.createSpendBundle( + final standardSpendBundle = + didWalletService.standardWalletService.createSpendBundle( payments: [Payment(newStandardCoin.amount, exitWalletVector.puzzlehash)], coinsInput: [newStandardCoin], keychain: keychain, diff --git a/integration_test/did/did_multiple_recovery_ids_test.dart b/integration_test/did/did_multiple_recovery_ids_test.dart index f693d896..4beb791c 100644 --- a/integration_test/did/did_multiple_recovery_ids_test.dart +++ b/integration_test/did/did_multiple_recovery_ids_test.dart @@ -37,9 +37,11 @@ Future main() async { var newInnerPuzzlehash = DIDWalletService.createInnerPuzzleForPk( publicKey: firstRecoveringEnthusiast.firstWalletVector.childPublicKey, - backupIdsHash: recoveryEnthusiasts.map((e) => e.didInfo!.did).toList().programHash(), + backupIdsHash: + recoveryEnthusiasts.map((e) => e.didInfo!.did).toList().programHash(), launcherCoinId: recoverableEnthusiast.didInfo!.did, - nVerificationsRequired: recoveryEnthusiasts.map((e) => e.didInfo!.did).toList().length, + nVerificationsRequired: + recoveryEnthusiasts.map((e) => e.didInfo!.did).toList().length, metadataProgram: null, ).hash(); @@ -49,8 +51,10 @@ Future main() async { final attestment = didWalletService.createAttestment( attestmentMakerDidInfo: recoveryEnthusiast.didInfo!, recoveringDidInfo: recoverableEnthusiast.didInfo!, - attestmentMakerPrivateKey: recoveryEnthusiast.firstWalletVector.childPrivateKey, - newPublicKey: firstRecoveringEnthusiast.firstWalletVector.childPublicKey, + attestmentMakerPrivateKey: + recoveryEnthusiast.firstWalletVector.childPrivateKey, + newPublicKey: + firstRecoveringEnthusiast.firstWalletVector.childPublicKey, newInnerPuzzlehash: newInnerPuzzlehash, ); await fullNodeSimulator.pushTransaction(attestment.attestmentSpendBundle); @@ -75,20 +79,27 @@ Future main() async { await recoveryEnthusiast.refreshDidInfo(); } - await firstRecoveringEnthusiast.recoverDid(recoverableEnthusiast.didInfo!.did); + await firstRecoveringEnthusiast + .recoverDid(recoverableEnthusiast.didInfo!.did); expect( firstRecoveringEnthusiast.didInfo!.p2Puzzle, - equals(getPuzzleFromPk(firstRecoveringEnthusiast.firstWalletVector.childPublicKey)), + equals( + getPuzzleFromPk( + firstRecoveringEnthusiast.firstWalletVector.childPublicKey, + ), + ), ); final secondRecoveringEnthusiast = ChiaEnthusiast(fullNodeSimulator); newInnerPuzzlehash = DIDWalletService.createInnerPuzzleForPk( publicKey: secondRecoveringEnthusiast.firstWalletVector.childPublicKey, - backupIdsHash: recoveryEnthusiasts.map((e) => e.didInfo!.did).toList().programHash(), + backupIdsHash: + recoveryEnthusiasts.map((e) => e.didInfo!.did).toList().programHash(), launcherCoinId: firstRecoveringEnthusiast.didInfo!.did, - nVerificationsRequired: recoveryEnthusiasts.map((e) => e.didInfo!.did).toList().length, + nVerificationsRequired: + recoveryEnthusiasts.map((e) => e.didInfo!.did).toList().length, metadataProgram: null, ).hash(); @@ -98,8 +109,10 @@ Future main() async { final attestment = didWalletService.createAttestment( attestmentMakerDidInfo: recoveryEnthusiast.didInfo!, recoveringDidInfo: firstRecoveringEnthusiast.didInfo!, - attestmentMakerPrivateKey: recoveryEnthusiast.firstWalletVector.childPrivateKey, - newPublicKey: secondRecoveringEnthusiast.firstWalletVector.childPublicKey, + attestmentMakerPrivateKey: + recoveryEnthusiast.firstWalletVector.childPrivateKey, + newPublicKey: + secondRecoveringEnthusiast.firstWalletVector.childPublicKey, newInnerPuzzlehash: newInnerPuzzlehash, ); await fullNodeSimulator.pushTransaction(attestment.attestmentSpendBundle); @@ -108,7 +121,8 @@ Future main() async { messageSpendBundle += attestment.messageSpendBundle; } - final secondRecoverySpendBundle = didWalletService.createRecoverySpendBundle( + final secondRecoverySpendBundle = + didWalletService.createRecoverySpendBundle( firstRecoveringEnthusiast.didInfo!, secondRecoveringEnthusiast.firstWalletVector.childPrivateKey, newInnerPuzzlehash, @@ -120,11 +134,16 @@ Future main() async { await fullNodeSimulator.pushTransaction(secondRecoverySpendBundle); await fullNodeSimulator.moveToNextBlock(); - await secondRecoveringEnthusiast.recoverDid(recoverableEnthusiast.didInfo!.did); + await secondRecoveringEnthusiast + .recoverDid(recoverableEnthusiast.didInfo!.did); expect( secondRecoveringEnthusiast.didInfo!.p2Puzzle, - equals(getPuzzleFromPk(secondRecoveringEnthusiast.firstWalletVector.childPublicKey)), + equals( + getPuzzleFromPk( + secondRecoveringEnthusiast.firstWalletVector.childPublicKey, + ), + ), ); }); } diff --git a/integration_test/did/did_single_recovery_id_test.dart b/integration_test/did/did_single_recovery_id_test.dart index 1564bf78..174ca131 100644 --- a/integration_test/did/did_single_recovery_id_test.dart +++ b/integration_test/did/did_single_recovery_id_test.dart @@ -25,8 +25,8 @@ Future main() async { await fullNodeSimulator.farmCoins(recoveryDidAddress); await fullNodeSimulator.moveToNextBlock(); - final recoveryDidStandardCoins = - await fullNodeSimulator.getCoinsByPuzzleHashes([recoveryDidWv.puzzlehash]); + final recoveryDidStandardCoins = await fullNodeSimulator + .getCoinsByPuzzleHashes([recoveryDidWv.puzzlehash]); final didRecoverySpendBundle = didWalletService.createGenerateDIDSpendBundle( standardCoins: [recoveryDidStandardCoins[0]], @@ -39,7 +39,8 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final recoveryDidInfos = await fullNodeSimulator.getDidRecordsFromHint(recoveryDidWv.puzzlehash); + final recoveryDidInfos = + await fullNodeSimulator.getDidRecordsFromHint(recoveryDidWv.puzzlehash); var recoveryDidWallet = DidWallet( recoveryDidWv, recoveryDidInfos[0].toDidInfoForPkOrThrow(recoveryDidWv.childPublicKey), @@ -53,10 +54,11 @@ Future main() async { await fullNodeSimulator.farmCoins(recoverableDidAddress); await fullNodeSimulator.moveToNextBlock(); - final recoverableDidStandardCoins = - await fullNodeSimulator.getCoinsByPuzzleHashes([recoverableDidWv.puzzlehash]); + final recoverableDidStandardCoins = await fullNodeSimulator + .getCoinsByPuzzleHashes([recoverableDidWv.puzzlehash]); - final recoverableDidSpendBundle = didWalletService.createGenerateDIDSpendBundle( + final recoverableDidSpendBundle = + didWalletService.createGenerateDIDSpendBundle( standardCoins: [recoverableDidStandardCoins[0]], targetPuzzleHash: recoverableDidWv.puzzlehash, keychain: keychain, @@ -67,8 +69,8 @@ Future main() async { await fullNodeSimulator.pushTransaction(recoverableDidSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final didInfos = - await fullNodeSimulator.getDidRecordsByPuzzleHashes([recoverableDidWv.puzzlehash]); + final didInfos = await fullNodeSimulator + .getDidRecordsByPuzzleHashes([recoverableDidWv.puzzlehash]); var recoverableDidInfo = didInfos[0]; test('should recover did with single backup id', () async { @@ -117,14 +119,19 @@ Future main() async { recoveryDidWallet = DidWallet( recoveryDidWallet.walletVector, - (await fullNodeSimulator.getDidRecordForDid(recoveryDidWallet.didInfo.did))! + (await fullNodeSimulator + .getDidRecordForDid(recoveryDidWallet.didInfo.did))! .toDidInfoForPkOrThrow(recoveryDidWallet.walletVector.childPublicKey), ); - recoverableDidInfo = (await fullNodeSimulator.getDidRecordForDid(recoverableDidInfo.did))! - .toDidInfoForPkOrThrow(newPublicKey); + recoverableDidInfo = + (await fullNodeSimulator.getDidRecordForDid(recoverableDidInfo.did))! + .toDidInfoForPkOrThrow(newPublicKey); - expect((recoverableDidInfo as DidInfo).p2Puzzle, equals(getPuzzleFromPk(newPublicKey))); + expect( + (recoverableDidInfo as DidInfo).p2Puzzle, + equals(getPuzzleFromPk(newPublicKey)), + ); final newerWalletVector = keychain.unhardenedMap.values.toList()[1]; newPublicKey = newerWalletVector.childPublicKey; @@ -163,9 +170,13 @@ Future main() async { print('finished second recovery'); - recoverableDidInfo = (await fullNodeSimulator.getDidRecordForDid(recoverableDidInfo.did))! - .toDidInfoForPkOrThrow(newPublicKey); - expect((recoverableDidInfo as DidInfo).p2Puzzle, equals(getPuzzleFromPk(newPublicKey))); + recoverableDidInfo = + (await fullNodeSimulator.getDidRecordForDid(recoverableDidInfo.did))! + .toDidInfoForPkOrThrow(newPublicKey); + expect( + (recoverableDidInfo as DidInfo).p2Puzzle, + equals(getPuzzleFromPk(newPublicKey)), + ); }); } diff --git a/integration_test/did/did_transfer_test.dart b/integration_test/did/did_transfer_test.dart index 0a746592..a93b9ee5 100644 --- a/integration_test/did/did_transfer_test.dart +++ b/integration_test/did/did_transfer_test.dart @@ -42,9 +42,10 @@ void main() async { await fullNodeSimulator.pushTransaction(nathanToGrantSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final grantDid = (await fullNodeSimulator.getDidRecordsFromHint(grant.firstPuzzlehash)) - .single - .toDidInfoOrThrow(grant.keychain); + final grantDid = + (await fullNodeSimulator.getDidRecordsFromHint(grant.firstPuzzlehash)) + .single + .toDidInfoOrThrow(grant.keychain); final grantToMeeraSpendBundle = didWalletService.createSpendBundle( newP2Puzzlehash: meera.firstPuzzlehash, @@ -55,9 +56,10 @@ void main() async { await fullNodeSimulator.pushTransaction(grantToMeeraSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final meeraDid = (await fullNodeSimulator.getDidRecordsFromHint(meera.firstPuzzlehash)) - .single - .toDidInfoOrThrow(meera.keychain); + final meeraDid = + (await fullNodeSimulator.getDidRecordsFromHint(meera.firstPuzzlehash)) + .single + .toDidInfoOrThrow(meera.keychain); final meeraToNathanSpendBundle = didWalletService.createSpendBundle( newP2Puzzlehash: nathan.firstPuzzlehash, @@ -67,9 +69,10 @@ void main() async { await fullNodeSimulator.pushTransaction(meeraToNathanSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final nathanDid = (await fullNodeSimulator.getDidRecordsFromHint(nathan.firstPuzzlehash)) - .single - .toDidInfoOrThrow(nathan.keychain); + final nathanDid = + (await fullNodeSimulator.getDidRecordsFromHint(nathan.firstPuzzlehash)) + .single + .toDidInfoOrThrow(nathan.keychain); expectDidEquality(nathanDid, origionalDid); @@ -83,7 +86,8 @@ void main() async { final targetPuzzleHash = nathan.puzzlehashes.first; await nathan.refreshCoins(); - final bulkMintSpendBundle = nftWalletService.createDidNftBulkMintSpendBundle( + final bulkMintSpendBundle = + nftWalletService.createDidNftBulkMintSpendBundle( minterPuzzlehash: targetPuzzleHash, nftMintData: await NftMintingDataWithHashes.makeUniformBulkMintData( uriHashProvider: MockUriHashProvider(), @@ -104,9 +108,11 @@ void main() async { await fullNodeSimulator.pushTransaction(bulkMintSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final nftRecords = await fullNodeSimulator.getNftRecordsByHint(targetPuzzleHash); - final mintedNftRecords = - nftRecords.where((element) => bulkMintSpendBundle.additions.contains(element.coin)); + final nftRecords = + await fullNodeSimulator.getNftRecordsByHint(targetPuzzleHash); + final mintedNftRecords = nftRecords.where( + (element) => bulkMintSpendBundle.additions.contains(element.coin), + ); expect(mintedNftRecords.length, 10); final mirror = ChiaEnthusiast(fullNodeSimulator); @@ -120,7 +126,8 @@ void main() async { } await fullNodeSimulator.moveToNextBlock(); - final sentNfts = await fullNodeSimulator.getNftRecordsByHint(mirror.firstPuzzlehash); + final sentNfts = + await fullNodeSimulator.getNftRecordsByHint(mirror.firstPuzzlehash); expect(sentNfts.length, 10); final finalDid = await fullNodeSimulator.getDidRecordForDid(nathanDid.did); @@ -148,7 +155,8 @@ void main() async { await fullNodeSimulator.pushTransaction(createNftSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final nfts = await fullNodeSimulator.getNftRecordsByHint(nathan.firstPuzzlehash); + final nfts = + await fullNodeSimulator.getNftRecordsByHint(nathan.firstPuzzlehash); await meera.issueDid(); @@ -168,7 +176,9 @@ void main() async { await fullNodeSimulator.pushTransaction(spendNftBundle); await fullNodeSimulator.moveToNextBlock(); - var meeraNft = (await fullNodeSimulator.getNftRecordsByHint(meera.firstPuzzlehash)).single; + var meeraNft = + (await fullNodeSimulator.getNftRecordsByHint(meera.firstPuzzlehash)) + .single; await fullNodeSimulator.pushTransaction( nftWalletService.createSpendBundle( @@ -187,9 +197,12 @@ void main() async { ); await fullNodeSimulator.moveToNextBlock(); - meeraNft = (await fullNodeSimulator.getNftRecordsByHint(meera.firstPuzzlehash)).single; + meeraNft = + (await fullNodeSimulator.getNftRecordsByHint(meera.firstPuzzlehash)) + .single; - final mintInfo = await fullNodeSimulator.getNftMintInfoForLauncherId(meeraNft.launcherId); + final mintInfo = await fullNodeSimulator + .getNftMintInfoForLauncherId(meeraNft.launcherId); expect(mintInfo!.minterDid, nathanDid.did); expect(meeraNft.ownershipLayerInfo!.currentDid, meera.didInfo!.did); diff --git a/integration_test/did/did_update_spend_test.dart b/integration_test/did/did_update_spend_test.dart index e0603155..733c57d5 100644 --- a/integration_test/did/did_update_spend_test.dart +++ b/integration_test/did/did_update_spend_test.dart @@ -26,8 +26,8 @@ Future main() async { await fullNodeSimulator.farmCoins(recoveryDidAddress); await fullNodeSimulator.moveToNextBlock(); - final recoveryDidStandardCoins = - await fullNodeSimulator.getCoinsByPuzzleHashes([recoveryDidWv.puzzlehash]); + final recoveryDidStandardCoins = await fullNodeSimulator + .getCoinsByPuzzleHashes([recoveryDidWv.puzzlehash]); final didRecoverySpendBundle = didWalletService.createGenerateDIDSpendBundle( standardCoins: [recoveryDidStandardCoins[0]], @@ -40,8 +40,8 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final recoveryDidInfos = - await fullNodeSimulator.getDidRecordsByPuzzleHashes([recoveryDidWv.puzzlehash]); + final recoveryDidInfos = await fullNodeSimulator + .getDidRecordsByPuzzleHashes([recoveryDidWv.puzzlehash]); final recoveryDidWallet = DidWallet( recoveryDidWv, recoveryDidInfos[0].toDidInfoForPkOrThrow(recoveryDidWv.childPublicKey), @@ -55,8 +55,8 @@ Future main() async { await fullNodeSimulator.farmCoins(didToUpdateAddress); await fullNodeSimulator.moveToNextBlock(); - final didToUpdateStandardCoins = - await fullNodeSimulator.getCoinsByPuzzleHashes([didToUpdateWv.puzzlehash]); + final didToUpdateStandardCoins = await fullNodeSimulator + .getCoinsByPuzzleHashes([didToUpdateWv.puzzlehash]); final didToUpdateSpendBundle = didWalletService.createGenerateDIDSpendBundle( standardCoins: [didToUpdateStandardCoins[0]], @@ -68,8 +68,10 @@ Future main() async { await fullNodeSimulator.pushTransaction(didToUpdateSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final didInfos = await fullNodeSimulator.getDidRecordsByPuzzleHashes([didToUpdateWv.puzzlehash]); - final didToUpdateInfo = didInfos[0].toDidInfoForPkOrThrow(didToUpdateWv.childPublicKey); + final didInfos = await fullNodeSimulator + .getDidRecordsByPuzzleHashes([didToUpdateWv.puzzlehash]); + final didToUpdateInfo = + didInfos[0].toDidInfoForPkOrThrow(didToUpdateWv.childPublicKey); test('should recover did with single backup id', () async { var newInnerPuzzlehash = DIDWalletService.createInnerPuzzle( @@ -88,7 +90,8 @@ Future main() async { await fullNodeSimulator.pushTransaction(updateSpend); await fullNodeSimulator.moveToNextBlock(); - final recoverableDidInfo = await fullNodeSimulator.getDidRecordForDid(didToUpdateInfo.did); + final recoverableDidInfo = + await fullNodeSimulator.getDidRecordForDid(didToUpdateInfo.did); final keychainSecret = KeychainCoreSecret.generate(); diff --git a/integration_test/did/did_verification_test.dart b/integration_test/did/did_verification_test.dart index 0283a77d..06f47336 100644 --- a/integration_test/did/did_verification_test.dart +++ b/integration_test/did/did_verification_test.dart @@ -31,7 +31,8 @@ Future main() async { await fullNodeSimulator.farmCoins(address); await fullNodeSimulator.moveToNextBlock(); - final standardCoins = await fullNodeSimulator.getCoinsByPuzzleHashes([puzzlehash]); + final standardCoins = + await fullNodeSimulator.getCoinsByPuzzleHashes([puzzlehash]); final didSpendBundle = didWalletService.createGenerateDIDSpendBundle( standardCoins: [standardCoins[0]], @@ -43,7 +44,8 @@ Future main() async { await fullNodeSimulator.pushTransaction(didSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final didInfos = await fullNodeSimulator.getDidRecordsByPuzzleHashes([walletVector.puzzlehash]); + final didInfos = await fullNodeSimulator + .getDidRecordsByPuzzleHashes([walletVector.puzzlehash]); assert(didInfos.length == 1, 'should creste one did'); final did = didInfos[0].did; diff --git a/integration_test/did/did_wallet_service_test.dart b/integration_test/did/did_wallet_service_test.dart index 25d35832..ec855575 100644 --- a/integration_test/did/did_wallet_service_test.dart +++ b/integration_test/did/did_wallet_service_test.dart @@ -24,18 +24,21 @@ Future main() async { final didWalletService = DIDWalletService(); final puzzlehash = walletVector.puzzlehash; - final address = - Address.fromPuzzlehash(puzzlehash, didWalletService.blockchainNetwork.addressPrefix); + final address = Address.fromPuzzlehash( + puzzlehash, + didWalletService.blockchainNetwork.addressPrefix, + ); await fullNodeSimulator.farmCoins(address); await fullNodeSimulator.farmCoins(address); await fullNodeSimulator.moveToNextBlock(); - final standardCoins = await fullNodeSimulator.getCoinsByPuzzleHashes([puzzlehash]); + final standardCoins = + await fullNodeSimulator.getCoinsByPuzzleHashes([puzzlehash]); test('should create and find DID', () async { - final didsBefore = - await fullNodeSimulator.getDidRecordsByPuzzleHashes([walletVector.puzzlehash]); + final didsBefore = await fullNodeSimulator + .getDidRecordsByPuzzleHashes([walletVector.puzzlehash]); final didSpendBundle = didWalletService.createGenerateDIDSpendBundle( standardCoins: [standardCoins[0]], @@ -47,7 +50,8 @@ Future main() async { await fullNodeSimulator.pushTransaction(didSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final didsAfter = await fullNodeSimulator.getDidRecordsFromHint(walletVector.puzzlehash); + final didsAfter = + await fullNodeSimulator.getDidRecordsFromHint(walletVector.puzzlehash); expect(didsAfter.length, equals(didsBefore.length + 1)); final did = await fullNodeSimulator.getCoinById(didsAfter[0].did); @@ -55,13 +59,14 @@ Future main() async { }); test('should create DID with backupIds', () async { - final didsBefore = - await fullNodeSimulator.getDidRecordsByPuzzleHashes([walletVector.puzzlehash]); + final didsBefore = await fullNodeSimulator + .getDidRecordsByPuzzleHashes([walletVector.puzzlehash]); final didSpendBundle = didWalletService.createGenerateDIDSpendBundle( standardCoins: [standardCoins[1]], targetPuzzleHash: walletVector.puzzlehash, - backupIds: keychain.unhardenedMap.values.map((wv) => wv.puzzlehash).toList(), + backupIds: + keychain.unhardenedMap.values.map((wv) => wv.puzzlehash).toList(), keychain: keychain, changePuzzlehash: puzzlehash, ); @@ -69,14 +74,14 @@ Future main() async { await fullNodeSimulator.pushTransaction(didSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final didsAfter = - await fullNodeSimulator.getDidRecordsByPuzzleHashes([walletVector.puzzlehash]); + final didsAfter = await fullNodeSimulator + .getDidRecordsByPuzzleHashes([walletVector.puzzlehash]); expect(didsAfter.length, equals(didsBefore.length + 1)); }); test('should create DID with fee', () async { - final didsBefore = - await fullNodeSimulator.getDidRecordsByPuzzleHashes([walletVector.puzzlehash]); + final didsBefore = await fullNodeSimulator + .getDidRecordsByPuzzleHashes([walletVector.puzzlehash]); final didSpendBundle = didWalletService.createGenerateDIDSpendBundle( standardCoins: [standardCoins[2]], @@ -89,8 +94,8 @@ Future main() async { await fullNodeSimulator.pushTransaction(didSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final didsAfter = - await fullNodeSimulator.getDidRecordsByPuzzleHashes([walletVector.puzzlehash]); + final didsAfter = await fullNodeSimulator + .getDidRecordsByPuzzleHashes([walletVector.puzzlehash]); expect(didsAfter.length, equals(didsBefore.length + 1)); final did = await fullNodeSimulator.getCoinById(didsAfter[0].did); diff --git a/integration_test/exchange/btc/cross_chain_offer/btc_exchange_service_test.dart b/integration_test/exchange/btc/cross_chain_offer/btc_exchange_service_test.dart index 13b07105..97dbc515 100644 --- a/integration_test/exchange/btc/cross_chain_offer/btc_exchange_service_test.dart +++ b/integration_test/exchange/btc/cross_chain_offer/btc_exchange_service_test.dart @@ -35,7 +35,8 @@ Future main() async { // it was generated by our exchange service const btcHolderSignedPublicKey = 'ac72743c39137845af0991c71796206c7784b49b76fa30f216ccdeba84e23b28b81d5af48a6cc754d6438057c084f206_b60876a2f323721d8404935991b2c2e392af7e07d93aeb68317646a4c72b7392c00c88331e1ca90330cc9511cd6f2a510b55ee0918ed4d1d58dbf06c805044b9dc906a58ed5252e9dd95d22ccdc9f3016e1848d95f998a2bfbe6f74f5040f688'; - final btcHolderPublicKey = exchangeService.parseSignedPublicKey(btcHolderSignedPublicKey); + final btcHolderPublicKey = + exchangeService.parseSignedPublicKey(btcHolderSignedPublicKey); // user inputs lightning payment request, which is decoded to get the payment hash const paymentRequest = @@ -66,7 +67,8 @@ Future main() async { await fullNodeSimulator.pushTransaction(spendBundle); await fullNodeSimulator.moveToNextBlock(); - final escrowCoins = await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash]); + final escrowCoins = + await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash]); // user specifies where they want to receive coins in clawback case final clawbackPuzzlehash = xchHolder.firstPuzzlehash; @@ -103,7 +105,8 @@ Future main() async { // it was generated by our exchange service const btcHolderSignedPublicKey = 'ac72743c39137845af0991c71796206c7784b49b76fa30f216ccdeba84e23b28b81d5af48a6cc754d6438057c084f206_b60876a2f323721d8404935991b2c2e392af7e07d93aeb68317646a4c72b7392c00c88331e1ca90330cc9511cd6f2a510b55ee0918ed4d1d58dbf06c805044b9dc906a58ed5252e9dd95d22ccdc9f3016e1848d95f998a2bfbe6f74f5040f688'; - final btcHolderPublicKey = exchangeService.parseSignedPublicKey(btcHolderSignedPublicKey); + final btcHolderPublicKey = + exchangeService.parseSignedPublicKey(btcHolderSignedPublicKey); // user inputs lightning payment request, which is decoded to get the payment hash const paymentRequest = @@ -134,12 +137,14 @@ Future main() async { await fullNodeSimulator.pushTransaction(spendBundle); await fullNodeSimulator.moveToNextBlock(); - final escrowCoins = await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash]); + final escrowCoins = + await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash]); // user specifies where they want to receive coins in clawback case final clawbackPuzzlehash = xchHolder.firstPuzzlehash; - final startingClawbackAddressBalance = await fullNodeSimulator.getBalance([clawbackPuzzlehash]); + final startingClawbackAddressBalance = + await fullNodeSimulator.getBalance([clawbackPuzzlehash]); // the clawback spend bundle can be pushed after the clawback delay has passed in order to reclaim funds // in the event that the other party doesn't pay the lightning invoice within that time @@ -162,7 +167,8 @@ Future main() async { await Future.delayed(const Duration(seconds: 10), () async { await fullNodeSimulator.pushTransaction(clawbackSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final endingClawbackAddressBalance = await fullNodeSimulator.getBalance([clawbackPuzzlehash]); + final endingClawbackAddressBalance = + await fullNodeSimulator.getBalance([clawbackPuzzlehash]); expect( endingClawbackAddressBalance, @@ -185,7 +191,8 @@ Future main() async { // it was generated by our exchange service const btcHolderSignedPublicKey = 'a83e5abe134e3d871f48bbbab7e0bd571700ca4a50694573dd301158f3458bdeb5d1e8c742558448f4d247118a21d4a5_a81d9d56a3514821c80a012819456b7eda8a9db4558a26811570ccff723deeb0dc4c2866f53455141b4853b80b515d4707726b8dbbb68cd9b478e0e93675e183cef0e03e97401f1ab02f9eea38d4caccdcf9b43ac0486a7d4792a35be6890b18'; - final btcHolderPublicKey = exchangeService.parseSignedPublicKey(btcHolderSignedPublicKey); + final btcHolderPublicKey = + exchangeService.parseSignedPublicKey(btcHolderSignedPublicKey); // user inputs lightning payment request, which is decoded to get the payment hash const paymentRequest = @@ -216,18 +223,21 @@ Future main() async { await fullNodeSimulator.pushTransaction(spendBundle); await fullNodeSimulator.moveToNextBlock(); - final escrowCoins = await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash]); + final escrowCoins = + await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash]); // user specifies where they want to receive coins in clawback case final clawbackPuzzlehash = xchHolder.firstPuzzlehash; - final startingClawbackAddressBalance = await fullNodeSimulator.getBalance([clawbackPuzzlehash]); + final startingClawbackAddressBalance = + await fullNodeSimulator.getBalance([clawbackPuzzlehash]); // in the event that something goes wrong with the exchange or the two parties mutually decide to // abort the exchange, the XCH holder may receive funds back before the clawback delay passes // if the BTC holder provides them with their private key - final btcHolderPrivateKey = - PrivateKey.fromHex('308f34305ed545c7b6bdefe9fff88176dc3b1a68c40f9065e2cf24c98bf6a4e1'); + final btcHolderPrivateKey = PrivateKey.fromHex( + '308f34305ed545c7b6bdefe9fff88176dc3b1a68c40f9065e2cf24c98bf6a4e1', + ); final clawbackSpendBundle = xchToBtcService.createClawbackSpendBundleWithPk( payments: [Payment(escrowCoins.totalValue, clawbackPuzzlehash)], @@ -240,7 +250,8 @@ Future main() async { await fullNodeSimulator.pushTransaction(clawbackSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final endingClawbackAddressBalance = await fullNodeSimulator.getBalance([clawbackPuzzlehash]); + final endingClawbackAddressBalance = + await fullNodeSimulator.getBalance([clawbackPuzzlehash]); expect( endingClawbackAddressBalance, @@ -262,7 +273,8 @@ Future main() async { // it was generated by our exchange service const btcHolderSignedPublicKey = 'a83e5abe134e3d871f48bbbab7e0bd571700ca4a50694573dd301158f3458bdeb5d1e8c742558448f4d247118a21d4a5_a81d9d56a3514821c80a012819456b7eda8a9db4558a26811570ccff723deeb0dc4c2866f53455141b4853b80b515d4707726b8dbbb68cd9b478e0e93675e183cef0e03e97401f1ab02f9eea38d4caccdcf9b43ac0486a7d4792a35be6890b18'; - final btcHolderPublicKey = exchangeService.parseSignedPublicKey(btcHolderSignedPublicKey); + final btcHolderPublicKey = + exchangeService.parseSignedPublicKey(btcHolderSignedPublicKey); // user inputs lightning payment request, which is decoded to get the payment hash const paymentRequest = @@ -293,7 +305,8 @@ Future main() async { await fullNodeSimulator.pushTransaction(spendBundle); await fullNodeSimulator.moveToNextBlock(); - final escrowCoins = await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash]); + final escrowCoins = + await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash]); // user specifies where they want to receive coins in clawback case final clawbackPuzzlehash = xchHolder.firstPuzzlehash; @@ -318,7 +331,8 @@ Future main() async { ); }); - test('should transfer XCH to escrow address and sweep funds to BTC holder using preimage', + test( + 'should transfer XCH to escrow address and sweep funds to BTC holder using preimage', () async { final xchHolder = ChiaEnthusiast(fullNodeSimulator, walletSize: 2); final btcHolder = ChiaEnthusiast(fullNodeSimulator, walletSize: 2); @@ -332,7 +346,8 @@ Future main() async { // it was generated by our exchange service const xchHolderSignedPublicKey = 'ad6abe3d432ccce5b40995611c4db6d71e2678f142b8635940c32c4b1c35dde7b01ab42581075eaee173aba747373f71_97c0d2c1acea7708df1eb4a75f625ca1fe95a9aa141a86c2e18bdfd1e8716cba2888f6230ea122ce9478a78f8257beaf0dfb81714f4de6337fa671cc29bb2d4e18e9aae31829016fd94f14e99f86a9ad990f2740d02583c6a85dc4b6b0233aaa'; - final xchHolderPublicKey = exchangeService.parseSignedPublicKey(xchHolderSignedPublicKey); + final xchHolderPublicKey = + exchangeService.parseSignedPublicKey(xchHolderSignedPublicKey); // user inputs lightning payment request, which is decoded to get the payment hash const paymentRequest = @@ -363,17 +378,20 @@ Future main() async { await fullNodeSimulator.pushTransaction(spendBundle); await fullNodeSimulator.moveToNextBlock(); - final escrowCoins = await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash]); + final escrowCoins = + await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash]); // user specifies where they want to receive funds final sweepPuzzlehash = btcHolder.firstPuzzlehash; - final startingSweepAddressBalance = await fullNodeSimulator.getBalance([sweepPuzzlehash]); + final startingSweepAddressBalance = + await fullNodeSimulator.getBalance([sweepPuzzlehash]); // the BTC holder inputs the lightning preimage receipt they receive upon payment of the // lightning invoice to sweep funds // the payment hash is the hash of the preimage final sweepPreimage = - '5c1f10653dc3ff0531b77351dc6676de2e1f5f53c9f0a8867bcb054648f46a32'.hexToBytes(); + '5c1f10653dc3ff0531b77351dc6676de2e1f5f53c9f0a8867bcb054648f46a32' + .hexToBytes(); final sweepSpendBundle = btcToXchService.createSweepSpendBundle( payments: [Payment(escrowCoins.totalValue, sweepPuzzlehash)], @@ -388,7 +406,8 @@ Future main() async { await fullNodeSimulator.pushTransaction(sweepSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final endingSweepAddressBalance = await fullNodeSimulator.getBalance([sweepPuzzlehash]); + final endingSweepAddressBalance = + await fullNodeSimulator.getBalance([sweepPuzzlehash]); expect( endingSweepAddressBalance, @@ -411,7 +430,8 @@ Future main() async { // it was generated by our exchange service const xchHolderSignedPublicKey = 'ad6abe3d432ccce5b40995611c4db6d71e2678f142b8635940c32c4b1c35dde7b01ab42581075eaee173aba747373f71_97c0d2c1acea7708df1eb4a75f625ca1fe95a9aa141a86c2e18bdfd1e8716cba2888f6230ea122ce9478a78f8257beaf0dfb81714f4de6337fa671cc29bb2d4e18e9aae31829016fd94f14e99f86a9ad990f2740d02583c6a85dc4b6b0233aaa'; - final xchHolderPublicKey = exchangeService.parseSignedPublicKey(xchHolderSignedPublicKey); + final xchHolderPublicKey = + exchangeService.parseSignedPublicKey(xchHolderSignedPublicKey); // user inputs lightning payment request, which is decoded to get the payment hash const paymentRequest = @@ -442,7 +462,8 @@ Future main() async { await fullNodeSimulator.pushTransaction(spendBundle); await fullNodeSimulator.moveToNextBlock(); - final escrowCoins = await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash]); + final escrowCoins = + await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash]); // user specifies where they want to receive funds final sweepPuzzlehash = btcHolder.firstPuzzlehash; @@ -466,7 +487,8 @@ Future main() async { ); }); - test('should transfer XCH to escrow address and sweep funds to BTC holder using private key', + test( + 'should transfer XCH to escrow address and sweep funds to BTC holder using private key', () async { final xchHolder = ChiaEnthusiast(fullNodeSimulator, walletSize: 2); final btcHolder = ChiaEnthusiast(fullNodeSimulator, walletSize: 2); @@ -480,7 +502,8 @@ Future main() async { // it was generated by our exchange service const xchHolderSignedPublicKey = 'a83e5abe134e3d871f48bbbab7e0bd571700ca4a50694573dd301158f3458bdeb5d1e8c742558448f4d247118a21d4a5_a81d9d56a3514821c80a012819456b7eda8a9db4558a26811570ccff723deeb0dc4c2866f53455141b4853b80b515d4707726b8dbbb68cd9b478e0e93675e183cef0e03e97401f1ab02f9eea38d4caccdcf9b43ac0486a7d4792a35be6890b18'; - final xchHolderPublicKey = exchangeService.parseSignedPublicKey(xchHolderSignedPublicKey); + final xchHolderPublicKey = + exchangeService.parseSignedPublicKey(xchHolderSignedPublicKey); // user inputs lightning payment request, which is decoded to get the payment hash const paymentRequest = @@ -511,16 +534,19 @@ Future main() async { await fullNodeSimulator.pushTransaction(spendBundle); await fullNodeSimulator.moveToNextBlock(); - final escrowCoins = await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash]); + final escrowCoins = + await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash]); // user specifies where they want to receive funds final sweepPuzzlehash = btcHolder.firstPuzzlehash; - final startingSweepAddressBalance = await fullNodeSimulator.getBalance([sweepPuzzlehash]); + final startingSweepAddressBalance = + await fullNodeSimulator.getBalance([sweepPuzzlehash]); // after the lightning invoice is paid, the XCH holder may share their disposable private key // the BTC holder inputs the private key, allowing them to sweep funds from the escrow address - final xchHolderPrivateKey = - PrivateKey.fromHex('308f34305ed545c7b6bdefe9fff88176dc3b1a68c40f9065e2cf24c98bf6a4e1'); + final xchHolderPrivateKey = PrivateKey.fromHex( + '308f34305ed545c7b6bdefe9fff88176dc3b1a68c40f9065e2cf24c98bf6a4e1', + ); final sweepSpendBundle = btcToXchService.createSweepSpendBundleWithPk( payments: [Payment(escrowCoins.totalValue, sweepPuzzlehash)], @@ -534,7 +560,8 @@ Future main() async { await fullNodeSimulator.pushTransaction(sweepSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final endingSweepAddressBalance = await fullNodeSimulator.getBalance([sweepPuzzlehash]); + final endingSweepAddressBalance = + await fullNodeSimulator.getBalance([sweepPuzzlehash]); expect( endingSweepAddressBalance, @@ -557,7 +584,8 @@ Future main() async { // it was generated by our exchange service const xchHolderSignedPublicKey = 'ad6abe3d432ccce5b40995611c4db6d71e2678f142b8635940c32c4b1c35dde7b01ab42581075eaee173aba747373f71_97c0d2c1acea7708df1eb4a75f625ca1fe95a9aa141a86c2e18bdfd1e8716cba2888f6230ea122ce9478a78f8257beaf0dfb81714f4de6337fa671cc29bb2d4e18e9aae31829016fd94f14e99f86a9ad990f2740d02583c6a85dc4b6b0233aaa'; - final xchHolderPublicKey = exchangeService.parseSignedPublicKey(xchHolderSignedPublicKey); + final xchHolderPublicKey = + exchangeService.parseSignedPublicKey(xchHolderSignedPublicKey); // user inputs lightning payment request, which is decoded to get the payment hash const paymentRequest = @@ -588,7 +616,8 @@ Future main() async { await fullNodeSimulator.pushTransaction(spendBundle); await fullNodeSimulator.moveToNextBlock(); - final escrowCoins = await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash]); + final escrowCoins = + await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash]); // user specifies where they want to receive funds final sweepPuzzlehash = btcHolder.firstPuzzlehash; @@ -663,10 +692,10 @@ Future main() async { await fullNodeSimulator.pushTransaction(spendBundle); await fullNodeSimulator.moveToNextBlock(); - final xchHolderescrowCoins = - await fullNodeSimulator.getCoinsByPuzzleHashes([xchHolderescrowPuzzlehash]); - final btcHolderescrowCoins = - await fullNodeSimulator.getCoinsByPuzzleHashes([btcHolderescrowPuzzlehash]); + final xchHolderescrowCoins = await fullNodeSimulator + .getCoinsByPuzzleHashes([xchHolderescrowPuzzlehash]); + final btcHolderescrowCoins = await fullNodeSimulator + .getCoinsByPuzzleHashes([btcHolderescrowPuzzlehash]); expect(xchHolderescrowCoins.totalValue, equals(xchHolderCoins.totalValue)); expect(btcHolderescrowCoins, isEmpty); @@ -685,8 +714,9 @@ Future main() async { // XCH holder accidentally shares the wrong signed public key // although it has the correct format, it was signed by the wrong private key - final xchHolderWrongPrivateKey = - PrivateKey.fromHex('308f34305ed545c7b6bdefe9fff88176dc3b1a68c40f9065e2cf24c98bf6a4e1'); + final xchHolderWrongPrivateKey = PrivateKey.fromHex( + '308f34305ed545c7b6bdefe9fff88176dc3b1a68c40f9065e2cf24c98bf6a4e1', + ); final xchHolderWrongSignedPublicKey = exchangeService.createSignedPublicKey(xchHolderWrongPrivateKey); @@ -736,10 +766,10 @@ Future main() async { await fullNodeSimulator.pushTransaction(spendBundle); await fullNodeSimulator.moveToNextBlock(); - final xchHolderescrowCoins = - await fullNodeSimulator.getCoinsByPuzzleHashes([xchHolderescrowPuzzlehash]); - final btcHolderescrowCoins = - await fullNodeSimulator.getCoinsByPuzzleHashes([btcHolderescrowPuzzlehash]); + final xchHolderescrowCoins = await fullNodeSimulator + .getCoinsByPuzzleHashes([xchHolderescrowPuzzlehash]); + final btcHolderescrowCoins = await fullNodeSimulator + .getCoinsByPuzzleHashes([btcHolderescrowPuzzlehash]); expect(xchHolderescrowCoins.totalValue, equals(xchHolderCoins.totalValue)); expect(btcHolderescrowCoins, isEmpty); diff --git a/integration_test/exchange/btc/cross_chain_offer/cross_chain_offer_file_test.dart b/integration_test/exchange/btc/cross_chain_offer/cross_chain_offer_file_test.dart index b6834ba2..2a4da39b 100644 --- a/integration_test/exchange/btc/cross_chain_offer/cross_chain_offer_file_test.dart +++ b/integration_test/exchange/btc/cross_chain_offer/cross_chain_offer_file_test.dart @@ -1,4 +1,6 @@ +@Timeout(Duration(minutes: 3)) import 'dart:async'; +import 'dart:math'; import 'package:chia_crypto_utils/chia_crypto_utils.dart'; import 'package:test/expect.dart'; @@ -13,307 +15,405 @@ Future main() async { final fullNodeSimulator = SimulatorFullNodeInterface.withDefaultUrl(); ChiaNetworkContextWrapper().registerNetworkContext(Network.mainnet); - final btcToXchService = BtcToXchService(); - final crossChainOfferService = CrossChainOfferService(fullNodeSimulator); - final standardWalletService = StandardWalletService(); + final crossChainOfferFileService = CrossChainOfferFileService(); + final exchangeOfferService = ExchangeOfferService(fullNodeSimulator); + + // constants + const mojos = 200000000; + const satoshis = 100; + const exchangeValidityTime = 600; + const paymentRequest = + 'lnbc1u1p3huyzkpp5vw6fkrw9lr3pvved40zpp4jway4g4ee6uzsaj208dxqxgm2rtkvqdqqcqzzgxqyz5vqrzjqwnvuc0u4txn35cafc7w94gxvq5p3cu9dd95f7hlrh0fvs46wpvhdrxkxglt5qydruqqqqryqqqqthqqpyrzjqw8c7yfutqqy3kz8662fxutjvef7q2ujsxtt45csu0k688lkzu3ldrxkxglt5qydruqqqqryqqqqthqqpysp5jzgpj4990chtj9f9g2f6mhvgtzajzckx774yuh0klnr3hmvrqtjq9qypqsqkrvl3sqd4q4dm9axttfa6frg7gffguq3rzuvvm2fpuqsgg90l4nz8zgc3wx7gggm04xtwq59vftm25emwp9mtvmvjg756dyzn2dm98qpakw4u8'; + final decodedPaymentRequest = decodeLightningPaymentRequest(paymentRequest); + final paymentHash = decodedPaymentRequest.paymentHash!; + final preimage = + '5c1f10653dc3ff0531b77351dc6676de2e1f5f53c9f0a8867bcb054648f46a32' + .hexToBytes(); test( - 'should create and accept XCH to BTC offer file and complete exchange by sweeping XCH to BTC holder with preimage', + 'should make and take XCH to BTC offer and complete exchange by sweeping XCH to BTC holder with preimage', () async { - final xchHolder = ChiaEnthusiast(fullNodeSimulator, walletSize: 2); - await xchHolder.farmCoins(); - await xchHolder.refreshCoins(); - - final btcHolder = ChiaEnthusiast(fullNodeSimulator, walletSize: 2); - await btcHolder.farmCoins(); - await btcHolder.refreshCoins(); + // maker side + final maker = ChiaEnthusiast(fullNodeSimulator, walletSize: 2); + for (var i = 0; i < 2; i++) { + await maker.farmCoins(); + } + await maker.refreshCoins(); + + final makerMasterPrivateKey = maker.keychainSecret.masterPrivateKey; + final makerDerivationIndex = + ExchangeOfferService.randomDerivationIndexForExchange(); + + final makerWalletVector = await WalletVector.fromPrivateKeyAsync( + makerMasterPrivateKey, + makerDerivationIndex, + ); - // A public/private key pair is generated for the XCH holder to use for the exchange - final xchHolderPrivateKey = PrivateKey.generate(); - final xchHolderPublicKey = xchHolderPrivateKey.getG1(); + final makerPrivateKey = makerWalletVector.childPrivateKey; + final makerPublicKey = makerPrivateKey.getG1(); - // XCH holder inputs details to create an cross chain offer file - const amountMojos = 100000; - const amountSatoshis = 100; + final messagePuzzlehash = makerWalletVector.puzzlehash; - final messageAddress = - Address.fromContext(xchHolder.keychain.unhardenedWalletVectors[1].puzzlehash); + final messageAddress = Address.fromContext(messagePuzzlehash); - const validityTimeHours = 1; - final currentUnixTimestamp = DateTime.now().millisecondsSinceEpoch ~/ 1000; - final validityTime = currentUnixTimestamp + (validityTimeHours * 60 * 60); + const offerValidityTimeHours = 1; + final currentUnixTimeStamp = DateTime.now().millisecondsSinceEpoch ~/ 1000; + final offerValidityTime = + currentUnixTimeStamp + (offerValidityTimeHours * 60 * 60); - const paymentRequest = - 'lnbc1u1p3huyzkpp5vw6fkrw9lr3pvved40zpp4jway4g4ee6uzsaj208dxqxgm2rtkvqdqqcqzzgxqyz5vqrzjqwnvuc0u4txn35cafc7w94gxvq5p3cu9dd95f7hlrh0fvs46wpvhdrxkxglt5qydruqqqqryqqqqthqqpyrzjqw8c7yfutqqy3kz8662fxutjvef7q2ujsxtt45csu0k688lkzu3ldrxkxglt5qydruqqqqryqqqqthqqpysp5jzgpj4990chtj9f9g2f6mhvgtzajzckx774yuh0klnr3hmvrqtjq9qypqsqkrvl3sqd4q4dm9axttfa6frg7gffguq3rzuvvm2fpuqsgg90l4nz8zgc3wx7gggm04xtwq59vftm25emwp9mtvmvjg756dyzn2dm98qpakw4u8'; - final decodedPaymentRequest = decodeLightningPaymentRequest(paymentRequest); + final unspentInitializationCoin = maker.standardCoins.first; + final initializationCoinId = unspentInitializationCoin.id; - final offerFile = crossChainOfferService.createXchToBtcOfferFile( - amountMojos: amountMojos, - amountSatoshis: amountSatoshis, + final offerFile = crossChainOfferFileService.createXchToBtcMakerOfferFile( + initializationCoinId: initializationCoinId, + amountMojos: mojos, + amountSatoshis: satoshis, messageAddress: messageAddress, - validityTime: validityTime, - requestorPublicKey: xchHolderPublicKey, + validityTime: offerValidityTime, + requestorPublicKey: makerPublicKey, paymentRequest: decodedPaymentRequest, ); - final serializedOfferFile = offerFile.serialize(xchHolderPrivateKey); - - // A public/private key pair is generated for the BTC holder to use for the exchange - final btcHolderPrivateKey = PrivateKey.generate(); - final btcHolderPublicKey = btcHolderPrivateKey.getG1(); - - // BTC holder's side views offer, deserialized it, checks validity, and creates a cross chain offer accept file - final deserializedOfferFile = - XchToBtcMakerOfferFile.fromSerializedOfferFile(serializedOfferFile); - expect(() => CrossChainOfferService.checkValidity(deserializedOfferFile), returnsNormally); - const postAcceptValidityTime = 600; + final serializedOfferFile = await offerFile.serializeAsync(makerPrivateKey); - final offerAcceptFile = crossChainOfferService.createBtcToXchAcceptFile( + // maker pushes initialization spend bundle to create offer + await exchangeOfferService.pushInitializationSpendBundle( + messagePuzzlehash: messagePuzzlehash, + coinsInput: [unspentInitializationCoin], + initializationCoinId: unspentInitializationCoin.id, + keychain: maker.keychain, + derivationIndex: makerDerivationIndex, serializedOfferFile: serializedOfferFile, - validityTime: postAcceptValidityTime, - requestorPublicKey: btcHolderPublicKey, + changePuzzlehash: maker.firstPuzzlehash, ); + await fullNodeSimulator.moveToNextBlock(); + await maker.refreshCoins(); - final serializedOfferAcceptFile = offerAcceptFile.serialize(btcHolderPrivateKey); + // taker side + final taker = ChiaEnthusiast(fullNodeSimulator, walletSize: 10); + await taker.farmCoins(); + await taker.refreshCoins(); - // BTC holder's side sends message coin with offer accept file to message puzzlehash and verifies receipt - final messagePuzzlehash = deserializedOfferFile.messageAddress.toPuzzlehash(); + final takerMasterPrivateKey = taker.keychainSecret.masterPrivateKey; + final takerDerivationIndex = Random.secure().nextInt(10); - await crossChainOfferService.sendMessageCoin( - keychain: btcHolder.keychain, - coinsInput: [btcHolder.standardCoins.first], - messagePuzzlehash: messagePuzzlehash, - requestorPrivateKey: btcHolderPrivateKey, - serializedOfferAcceptFile: serializedOfferAcceptFile, - changePuzzlehash: btcHolder.firstPuzzlehash, - fee: 50, + final takerWalletVector = await WalletVector.fromPrivateKeyAsync( + takerMasterPrivateKey, + takerDerivationIndex, ); - await fullNodeSimulator.moveToNextBlock(); + final takerPrivateKey = takerWalletVector.childPrivateKey; + final takerPublicKey = takerWalletVector.childPublicKey; + + final takerOfferFile = + crossChainOfferFileService.createBtcToXchTakerOfferFile( + initializationCoinId: initializationCoinId, + serializedMakerOfferFile: serializedOfferFile, + validityTime: exchangeValidityTime, + requestorPublicKey: takerPublicKey, + ); - final messageVerification = await crossChainOfferService.verifyMessageCoinReceipt( - messagePuzzlehash, - serializedOfferAcceptFile, + final serializedTakerOfferFile = + await takerOfferFile.serializeAsync(takerPrivateKey); + + final escrowPuzzlehash = BtcToXchService.generateEscrowPuzzlehash( + requestorPrivateKey: takerPrivateKey, + clawbackDelaySeconds: exchangeValidityTime, + sweepPaymentHash: paymentHash, + fulfillerPublicKey: makerPublicKey, ); - expect(messageVerification, equals(true)); + // taker sends message coin + final coinForMessageSpend = taker.standardCoins.first; - // BTC holder's side gets exchange info from offer file and offer accept file details - final btcHolderExchangeInfo = offerAcceptFile.getExchangeInfo(offerFile, btcHolderPrivateKey); - final btcHolderEscrowPuzzlehash = btcHolderExchangeInfo.escrowPuzzlehash; + await exchangeOfferService.sendMessageCoin( + initializationCoinId: initializationCoinId, + messagePuzzlehash: messagePuzzlehash, + coinsInput: [coinForMessageSpend], + keychain: taker.keychain, + serializedTakerOfferFile: serializedTakerOfferFile, + changePuzzlehash: taker.firstPuzzlehash, + ); - // XCH holder's side deserializes memo from the received coin - final offerAcceptFileMemo = await crossChainOfferService - .getOfferAcceptFileFromMessagePuzzlehash(messagePuzzlehash, serializedOfferFile); + await fullNodeSimulator.moveToNextBlock(); + await taker.refreshCoins(); - expect(offerAcceptFileMemo, equals(serializedOfferAcceptFile)); + // maker accepts message coin + final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, + serializedOfferFile: serializedOfferFile, + messagePuzzlehash: messagePuzzlehash, + exchangeType: ExchangeType.xchToBtc, + ); - final deserializedOfferAcceptFile = - BtcToXchTakerOfferFile.fromSerializedOfferFile(offerAcceptFileMemo!); + await exchangeOfferService.acceptMessageCoin( + initializationCoinId: initializationCoinId, + messageCoin: messageCoinInfo!.messageCoin, + masterPrivateKey: makerMasterPrivateKey, + derivationIndex: makerDerivationIndex, + serializedOfferFile: serializedOfferFile, + targetPuzzlehash: maker.firstPuzzlehash, + ); - // XCH holder's side gets exchange info from details in offer file and offer accept file - final xchHolderExchangeInfo = - offerFile.getExchangeInfo(deserializedOfferAcceptFile, xchHolderPrivateKey); - final xchHolderEscrowPuzzlehash = xchHolderExchangeInfo.escrowPuzzlehash; + await fullNodeSimulator.moveToNextBlock(); - // the escrow puzzlehashes from the two sides should match - expect(xchHolderExchangeInfo.escrowPuzzlehash, equals(btcHolderEscrowPuzzlehash)); + final spentMessageCoinChild = await fullNodeSimulator + .getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); - // XCH holder transfers XCH to escrow address - final coinsForExchange = xchHolder.standardCoins; + expect(spentMessageCoinChild, isNotNull); - final escrowSpendBundle = standardWalletService.createSpendBundle( - payments: [Payment(xchHolderExchangeInfo.amountMojos, xchHolderEscrowPuzzlehash)], - coinsInput: coinsForExchange, - keychain: xchHolder.keychain, - changePuzzlehash: xchHolder.firstPuzzlehash, + // maker transfers funds to escrow puzzlehash + final makerEscrowPuzzlehash = XchToBtcService.generateEscrowPuzzlehash( + requestorPrivateKey: makerPrivateKey, + clawbackDelaySeconds: exchangeValidityTime, + sweepPaymentHash: paymentHash, + fulfillerPublicKey: takerPublicKey, ); - await fullNodeSimulator.pushTransaction(escrowSpendBundle); + await maker.refreshCoins(); + await taker.refreshCoins(); + final startingMakerBalance = maker.standardCoins.totalValue; + final startingTakerBalance = taker.standardCoins.totalValue; + + var escrowPuzzlehashCoins = + await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash]); + expect(escrowPuzzlehashCoins.totalValue, equals(0)); + + await exchangeOfferService.transferFundsToEscrowPuzzlehash( + initializationCoinId: initializationCoinId, + mojos: mojos, + escrowPuzzlehash: makerEscrowPuzzlehash, + requestorPrivateKey: makerPrivateKey, + coinsInput: [maker.standardCoins.first], + keychain: maker.keychain, + changePuzzlehash: maker.firstPuzzlehash, + ); await fullNodeSimulator.moveToNextBlock(); - final escrowCoins = await fullNodeSimulator.getCoinsByPuzzleHashes([xchHolderEscrowPuzzlehash]); - - expect(escrowCoins.totalValue, equals(amountMojos)); - - // after the BTC holder sees that XCH has arrived at the escrow address, they pay the lightning invoice. - // the BTC holder inputs into the program the preimage that is revealed after payment and the puzzlehash - // where they want to receive their XCH, which then creates and pushes a spend bundle to sweep funds - final sweepPreimage = - '5c1f10653dc3ff0531b77351dc6676de2e1f5f53c9f0a8867bcb054648f46a32'.hexToBytes(); - final sweepPuzzlehash = btcHolder.firstPuzzlehash; - final startingSweepBalance = await fullNodeSimulator.getBalance([sweepPuzzlehash]); - - final sweepSpendBundle = btcToXchService.createSweepSpendBundle( - payments: [Payment(escrowCoins.totalValue, sweepPuzzlehash)], - coinsInput: escrowCoins, - requestorPrivateKey: btcHolderPrivateKey, - clawbackDelaySeconds: postAcceptValidityTime, - sweepPaymentHash: btcHolderExchangeInfo.paymentHash!, - fulfillerPublicKey: xchHolderPublicKey, - sweepPreimage: sweepPreimage, + escrowPuzzlehashCoins = + await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash]); + expect(escrowPuzzlehashCoins.totalValue, equals(mojos)); + + // wait for sufficient confirmations + await fullNodeSimulator.moveToNextBlock(blocks: 32); + + // taker sweeps escrow puzzlehash + await exchangeOfferService.sweepEscrowPuzzlehash( + initializationCoinId: initializationCoinId, + escrowPuzzlehash: escrowPuzzlehash, + requestorPuzzlehash: taker.firstPuzzlehash, + requestorPrivateKey: takerPrivateKey, + exchangeValidityTime: exchangeValidityTime, + paymentHash: paymentHash, + preimage: preimage, + fulfillerPublicKey: makerPublicKey, ); - await fullNodeSimulator.pushTransaction(sweepSpendBundle); - await fullNodeSimulator.moveToNextBlock(); - final endingSweepBalance = await fullNodeSimulator.getBalance([sweepPuzzlehash]); + await maker.refreshCoins(); + await taker.refreshCoins(); - expect( - endingSweepBalance, - equals(startingSweepBalance + amountMojos), - ); + final endingMakerBalance = maker.standardCoins.totalValue; + final endingTakerBalance = taker.standardCoins.totalValue; + + expect(endingMakerBalance, equals(startingMakerBalance - mojos)); + expect(endingTakerBalance, equals(startingTakerBalance + mojos)); }); test( - 'should create and accept BTC to XCH offer file and complete exchange by sweeping XCH to BTC holder with preimage', + 'should make and take BTC to XCH offer and complete exchange by sweeping XCH to BTC holder with preimage', () async { - final btcHolder = ChiaEnthusiast(fullNodeSimulator, walletSize: 2); - await btcHolder.farmCoins(); - await btcHolder.refreshCoins(); + // maker side + final maker = ChiaEnthusiast(fullNodeSimulator, walletSize: 2); + await maker.farmCoins(); + await maker.refreshCoins(); + + final makerMasterPrivateKey = maker.keychainSecret.masterPrivateKey; + final makerDerivationIndex = + ExchangeOfferService.randomDerivationIndexForExchange(); + + final makerWalletVector = await WalletVector.fromPrivateKeyAsync( + makerMasterPrivateKey, + makerDerivationIndex, + ); - final xchHolder = ChiaEnthusiast(fullNodeSimulator, walletSize: 2); - await xchHolder.farmCoins(); - await xchHolder.refreshCoins(); + final makerPrivateKey = makerWalletVector.childPrivateKey; + final makerPublicKey = makerPrivateKey.getG1(); - // A public/private key pair is generated for the BTC holder to use for the exchange - final btcHolderPrivateKey = PrivateKey.generate(); - final btcHolderPublicKey = btcHolderPrivateKey.getG1(); + final messagePuzzlehash = makerWalletVector.puzzlehash; - // BTC holder inputs details to create an cross chain offer file - const amountSatoshis = 100; - const amountMojos = 100000; + final messageAddress = Address.fromContext(messagePuzzlehash); - final messageAddress = - Address.fromContext(xchHolder.keychain.unhardenedWalletVectors[1].puzzlehash); + const offerValidityTimeHours = 1; + final currentUnixTimeStamp = DateTime.now().millisecondsSinceEpoch ~/ 1000; + final offerValidityTime = + currentUnixTimeStamp + (offerValidityTimeHours * 60 * 60); - const validityTimeHours = 1; - final currentUnixTimestamp = DateTime.now().millisecondsSinceEpoch ~/ 1000; - final validityTime = currentUnixTimestamp + (validityTimeHours * 60 * 60); + final unspentInitializationCoin = maker.standardCoins.first; + final initializationCoinId = unspentInitializationCoin.id; - final offerFile = crossChainOfferService.createBtcToXchOfferFile( - amountMojos: amountMojos, - amountSatoshis: amountSatoshis, + final offerFile = crossChainOfferFileService.createBtcToXchMakerOfferFile( + initializationCoinId: initializationCoinId, + amountMojos: mojos, + amountSatoshis: satoshis, messageAddress: messageAddress, - validityTime: validityTime, - requestorPublicKey: btcHolderPublicKey, + validityTime: offerValidityTime, + requestorPublicKey: makerPublicKey, ); - final serializedOfferFile = offerFile.serialize(btcHolderPrivateKey); - - // A public/private key pair is generated for the XCH holder to use for the exchange - final xchHolderPrivateKey = PrivateKey.generate(); - final xchHolderPublicKey = xchHolderPrivateKey.getG1(); + final serializedOfferFile = await offerFile.serializeAsync(makerPrivateKey); - // XCH holder's side views offer, deserialized it, checks validity, and creates a cross chain offer accept file - final deserializedOfferFile = - BtcToXchMakerOfferFile.fromSerializedOfferFile(serializedOfferFile); - expect(() => CrossChainOfferService.checkValidity(deserializedOfferFile), returnsNormally); - const postAcceptValidityTime = 600; - - const paymentRequest = - 'lnbc1u1p3huyzkpp5vw6fkrw9lr3pvved40zpp4jway4g4ee6uzsaj208dxqxgm2rtkvqdqqcqzzgxqyz5vqrzjqwnvuc0u4txn35cafc7w94gxvq5p3cu9dd95f7hlrh0fvs46wpvhdrxkxglt5qydruqqqqryqqqqthqqpyrzjqw8c7yfutqqy3kz8662fxutjvef7q2ujsxtt45csu0k688lkzu3ldrxkxglt5qydruqqqqryqqqqthqqpysp5jzgpj4990chtj9f9g2f6mhvgtzajzckx774yuh0klnr3hmvrqtjq9qypqsqkrvl3sqd4q4dm9axttfa6frg7gffguq3rzuvvm2fpuqsgg90l4nz8zgc3wx7gggm04xtwq59vftm25emwp9mtvmvjg756dyzn2dm98qpakw4u8'; - final decodedPaymentRequest = decodeLightningPaymentRequest(paymentRequest); - - final offerAcceptFile = crossChainOfferService.createXchToBtcAcceptFile( + // maker pushes initialization spend bundle to create offer + await exchangeOfferService.pushInitializationSpendBundle( + messagePuzzlehash: messagePuzzlehash, + coinsInput: [unspentInitializationCoin], + initializationCoinId: unspentInitializationCoin.id, + keychain: maker.keychain, + derivationIndex: makerDerivationIndex, serializedOfferFile: serializedOfferFile, - validityTime: postAcceptValidityTime, - requestorPublicKey: xchHolderPublicKey, - paymentRequest: decodedPaymentRequest, + changePuzzlehash: maker.firstPuzzlehash, ); + await fullNodeSimulator.moveToNextBlock(); + await maker.refreshCoins(); - final serializedOfferAcceptFile = offerAcceptFile.serialize(xchHolderPrivateKey); + // taker side + final taker = ChiaEnthusiast(fullNodeSimulator, walletSize: 10); + for (var i = 0; i < 2; i++) { + await taker.farmCoins(); + } + await taker.refreshCoins(); - // XCH holder sends message coin with offer accept file to message puzzlehash and verifies receipt - final messagePuzzlehash = deserializedOfferFile.messageAddress.toPuzzlehash(); + final takerMasterPrivateKey = taker.keychainSecret.masterPrivateKey; + final takerDerivationIndex = Random.secure().nextInt(10); - await crossChainOfferService.sendMessageCoin( - keychain: xchHolder.keychain, - coinsInput: [xchHolder.standardCoins.first], - messagePuzzlehash: messagePuzzlehash, - requestorPrivateKey: xchHolderPrivateKey, - serializedOfferAcceptFile: serializedOfferAcceptFile, - changePuzzlehash: xchHolder.firstPuzzlehash, + final takerWalletVector = await WalletVector.fromPrivateKeyAsync( + takerMasterPrivateKey, + takerDerivationIndex, ); - await fullNodeSimulator.moveToNextBlock(); + final takerPrivateKey = takerWalletVector.childPrivateKey; + final takerPublicKey = takerWalletVector.childPublicKey; - final messageVerification = await crossChainOfferService.verifyMessageCoinReceipt( - messagePuzzlehash, - serializedOfferAcceptFile, + final takerOfferFile = + crossChainOfferFileService.createXchToBtcTakerOfferFile( + initializationCoinId: initializationCoinId, + serializedMakerOfferFile: serializedOfferFile, + validityTime: exchangeValidityTime, + requestorPublicKey: takerPublicKey, + paymentRequest: decodedPaymentRequest, ); - expect(messageVerification, equals(true)); + final serializedTakerOfferFile = + await takerOfferFile.serializeAsync(takerPrivateKey); - // XCH holder's side gets exchange info from offer file and offer accept file details - final xchHolderExchangeInfo = offerAcceptFile.getExchangeInfo(offerFile, xchHolderPrivateKey); - final xchHolderEscrowPuzzlehash = xchHolderExchangeInfo.escrowPuzzlehash; + final escrowPuzzlehash = XchToBtcService.generateEscrowPuzzlehash( + requestorPrivateKey: takerPrivateKey, + clawbackDelaySeconds: exchangeValidityTime, + sweepPaymentHash: paymentHash, + fulfillerPublicKey: makerPublicKey, + ); - // BTC holder's side deserializes memo from the received coin - final offerAcceptFileMemo = await crossChainOfferService - .getOfferAcceptFileFromMessagePuzzlehash(messagePuzzlehash, serializedOfferFile); + // taker sends message coin + final coinForMessageSpend = taker.standardCoins.first; - expect(offerAcceptFileMemo, equals(serializedOfferAcceptFile)); + await exchangeOfferService.sendMessageCoin( + initializationCoinId: initializationCoinId, + messagePuzzlehash: messagePuzzlehash, + coinsInput: [coinForMessageSpend], + keychain: taker.keychain, + serializedTakerOfferFile: serializedTakerOfferFile, + changePuzzlehash: taker.firstPuzzlehash, + ); - final deserializedOfferAcceptFile = - XchToBtcTakerOfferFile.fromSerializedOfferFile(offerAcceptFileMemo!); + await fullNodeSimulator.moveToNextBlock(); + await taker.refreshCoins(); - // BTC holder's side gets escrow address from details in offer file and offer accept file - final btcHolderExchangeInfo = - offerFile.getExchangeInfo(deserializedOfferAcceptFile, btcHolderPrivateKey); - final btcHolderEscrowPuzzlehash = btcHolderExchangeInfo.escrowPuzzlehash; + // maker accepts message coin + final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, + serializedOfferFile: serializedOfferFile, + messagePuzzlehash: messagePuzzlehash, + exchangeType: ExchangeType.btcToXch, + satoshis: satoshis, + ); - // the escrow puzzlehashes on either side should match - expect(btcHolderEscrowPuzzlehash, equals(xchHolderEscrowPuzzlehash)); + await exchangeOfferService.acceptMessageCoin( + initializationCoinId: initializationCoinId, + messageCoin: messageCoinInfo!.messageCoin, + masterPrivateKey: makerMasterPrivateKey, + derivationIndex: makerDerivationIndex, + serializedOfferFile: serializedOfferFile, + targetPuzzlehash: maker.firstPuzzlehash, + ); - // XCH holder transfers XCH to escrow address - await xchHolder.refreshCoins(); - final coinsForExchange = xchHolder.standardCoins; + await fullNodeSimulator.moveToNextBlock(); - final escrowSpendBundle = standardWalletService.createSpendBundle( - payments: [Payment(xchHolderExchangeInfo.amountMojos, xchHolderEscrowPuzzlehash)], - coinsInput: coinsForExchange, - keychain: xchHolder.keychain, - changePuzzlehash: xchHolder.firstPuzzlehash, + final spentMessageCoinChild = await fullNodeSimulator + .getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); + + expect(spentMessageCoinChild, isNotNull); + + await maker.refreshCoins(); + await taker.refreshCoins(); + final startingMakerBalance = maker.standardCoins.totalValue; + final startingTakerBalance = taker.standardCoins.totalValue; + + var escrowPuzzlehashCoins = + await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash]); + expect(escrowPuzzlehashCoins.totalValue, equals(0)); + + // taker transfers funds to escrow puzzlehash + await exchangeOfferService.transferFundsToEscrowPuzzlehash( + initializationCoinId: initializationCoinId, + mojos: mojos, + escrowPuzzlehash: escrowPuzzlehash, + requestorPrivateKey: takerPrivateKey, + coinsInput: [taker.standardCoins.first], + keychain: taker.keychain, + changePuzzlehash: taker.firstPuzzlehash, ); - await fullNodeSimulator.pushTransaction(escrowSpendBundle); - await fullNodeSimulator.moveToNextBlock(); - final escrowCoins = await fullNodeSimulator.getCoinsByPuzzleHashes([btcHolderEscrowPuzzlehash]); - - expect(escrowCoins.totalValue, equals(amountMojos)); - - // after the BTC holder sees that XCH has arrived at the escrow address, they pay the lightning invoice. - // the BTC holder inputs into the program the preimage that is revealed after payment and the puzzlehash - // where they want to receive their XCH, which then creates and pushes a spend bundle to sweep funds - final sweepPreimage = - '5c1f10653dc3ff0531b77351dc6676de2e1f5f53c9f0a8867bcb054648f46a32'.hexToBytes(); - final sweepPuzzlehash = btcHolder.firstPuzzlehash; - final startingSweepBalance = await fullNodeSimulator.getBalance([sweepPuzzlehash]); - - final sweepSpendBundle = btcToXchService.createSweepSpendBundle( - payments: [Payment(escrowCoins.totalValue, sweepPuzzlehash)], - coinsInput: escrowCoins, - requestorPrivateKey: btcHolderPrivateKey, - clawbackDelaySeconds: postAcceptValidityTime, - sweepPaymentHash: btcHolderExchangeInfo.paymentHash!, - fulfillerPublicKey: xchHolderPublicKey, - sweepPreimage: sweepPreimage, + escrowPuzzlehashCoins = + await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash]); + expect(escrowPuzzlehashCoins.totalValue, equals(mojos)); + + // wait for sufficient confirmations + await fullNodeSimulator.moveToNextBlock( + blocks: blocksForSufficientConfirmation, + ); + + // maker sweeps escrow puzzlehash + final makerEscrowPuzzlehash = BtcToXchService.generateEscrowPuzzlehash( + requestorPrivateKey: makerPrivateKey, + clawbackDelaySeconds: exchangeValidityTime, + sweepPaymentHash: paymentHash, + fulfillerPublicKey: takerPublicKey, ); - await fullNodeSimulator.pushTransaction(sweepSpendBundle); + await exchangeOfferService.sweepEscrowPuzzlehash( + initializationCoinId: initializationCoinId, + escrowPuzzlehash: makerEscrowPuzzlehash, + requestorPuzzlehash: maker.firstPuzzlehash, + requestorPrivateKey: makerPrivateKey, + exchangeValidityTime: exchangeValidityTime, + paymentHash: paymentHash, + preimage: preimage, + fulfillerPublicKey: takerPublicKey, + ); await fullNodeSimulator.moveToNextBlock(); - final endingSweepBalance = await fullNodeSimulator.getBalance([sweepPuzzlehash]); + await maker.refreshCoins(); + await taker.refreshCoins(); - expect( - endingSweepBalance, - equals(startingSweepBalance + amountMojos), - ); + final endingMakerBalance = maker.standardCoins.totalValue; + final endingTakerBalance = taker.standardCoins.totalValue; + + expect(endingMakerBalance, equals(startingMakerBalance + mojos)); + expect(endingTakerBalance, equals(startingTakerBalance - mojos)); }); } diff --git a/integration_test/exchange/btc/exchange_offer_record_hydration_service/btc_to_xch_exchange_offer_record_hydration_test.dart b/integration_test/exchange/btc/exchange_offer_record_hydration_service/btc_to_xch_exchange_offer_record_hydration_test.dart index 853a76ce..4a64dbbc 100644 --- a/integration_test/exchange/btc/exchange_offer_record_hydration_service/btc_to_xch_exchange_offer_record_hydration_test.dart +++ b/integration_test/exchange/btc/exchange_offer_record_hydration_service/btc_to_xch_exchange_offer_record_hydration_test.dart @@ -1,5 +1,4 @@ @Timeout(Duration(minutes: 5)) -@Skip('Long') import 'dart:async'; import 'dart:math'; @@ -14,8 +13,9 @@ Future main() async { } final fullNodeSimulator = SimulatorFullNodeInterface.withDefaultUrl(); + ChiaNetworkContextWrapper().registerNetworkContext(Network.mainnet); - final crossChainOfferService = CrossChainOfferService(fullNodeSimulator); + final crossChainOfferFileService = CrossChainOfferFileService(); final exchangeOfferService = ExchangeOfferService(fullNodeSimulator); final exchangeOfferRecordHydrationService = ExchangeOfferRecordHydrationService(fullNodeSimulator); @@ -30,7 +30,9 @@ Future main() async { 'lnbc1u1p3huyzkpp5vw6fkrw9lr3pvved40zpp4jway4g4ee6uzsaj208dxqxgm2rtkvqdqqcqzzgxqyz5vqrzjqwnvuc0u4txn35cafc7w94gxvq5p3cu9dd95f7hlrh0fvs46wpvhdrxkxglt5qydruqqqqryqqqqthqqpyrzjqw8c7yfutqqy3kz8662fxutjvef7q2ujsxtt45csu0k688lkzu3ldrxkxglt5qydruqqqqryqqqqthqqpysp5jzgpj4990chtj9f9g2f6mhvgtzajzckx774yuh0klnr3hmvrqtjq9qypqsqkrvl3sqd4q4dm9axttfa6frg7gffguq3rzuvvm2fpuqsgg90l4nz8zgc3wx7gggm04xtwq59vftm25emwp9mtvmvjg756dyzn2dm98qpakw4u8'; final decodedPaymentRequest = decodeLightningPaymentRequest(paymentRequest); final paymentHash = decodedPaymentRequest.paymentHash!; - final preimage = '5c1f10653dc3ff0531b77351dc6676de2e1f5f53c9f0a8867bcb054648f46a32'.hexToBytes(); + final preimage = + '5c1f10653dc3ff0531b77351dc6676de2e1f5f53c9f0a8867bcb054648f46a32' + .hexToBytes(); late ChiaEnthusiast maker; late PrivateKey makerMasterPrivateKey; @@ -41,6 +43,7 @@ Future main() async { late int offerValidityTime; late String serializedOfferFile; late Coin initializationCoin; + late Bytes initializationCoinId; late DateTime initializedTime; late ChiaEnthusiast taker; @@ -57,7 +60,8 @@ Future main() async { await maker.refreshCoins(); makerMasterPrivateKey = maker.keychainSecret.masterPrivateKey; - makerDerivationIndex = ExchangeOfferService.randomDerivationIndexForExchange(); + makerDerivationIndex = + ExchangeOfferService.randomDerivationIndexForExchange(); final makerWalletVector = await WalletVector.fromPrivateKeyAsync( makerMasterPrivateKey, @@ -72,10 +76,15 @@ Future main() async { final messageAddress = Address.fromContext(messagePuzzlehash); const offerValidityTimeHours = 1; - final currentUnixTimestamp = DateTime.now().millisecondsSinceEpoch ~/ 1000; - offerValidityTime = currentUnixTimestamp + (offerValidityTimeHours * 60 * 60); + final currentUnixTimeStamp = DateTime.now().millisecondsSinceEpoch ~/ 1000; + offerValidityTime = + currentUnixTimeStamp + (offerValidityTimeHours * 60 * 60); + + final unspentInitializationCoin = maker.standardCoins.first; + initializationCoinId = unspentInitializationCoin.id; - final offerFile = crossChainOfferService.createBtcToXchOfferFile( + final offerFile = crossChainOfferFileService.createBtcToXchMakerOfferFile( + initializationCoinId: initializationCoinId, amountMojos: mojos, amountSatoshis: satoshis, messageAddress: messageAddress, @@ -86,7 +95,6 @@ Future main() async { serializedOfferFile = await offerFile.serializeAsync(makerPrivateKey); // maker pushes initialization spend bundle to create offer - final unspentInitializationCoin = maker.standardCoins.first; await exchangeOfferService.pushInitializationSpendBundle( messagePuzzlehash: messagePuzzlehash, @@ -100,9 +108,10 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await maker.refreshCoins(); - initializationCoin = (await fullNodeSimulator.getCoinById(unspentInitializationCoin.id))!; - initializedTime = - (await fullNodeSimulator.getDateTimeFromBlockIndex(initializationCoin.spentBlockIndex))!; + initializationCoin = + (await fullNodeSimulator.getCoinById(unspentInitializationCoin.id))!; + initializedTime = (await fullNodeSimulator + .getDateTimeFromBlockIndex(initializationCoin.spentBlockIndex))!; // taker side taker = ChiaEnthusiast(fullNodeSimulator, walletSize: 10); @@ -122,14 +131,17 @@ Future main() async { takerPrivateKey = takerWalletVector.childPrivateKey; takerPublicKey = takerWalletVector.childPublicKey; - final takerOfferFile = crossChainOfferService.createXchToBtcAcceptFile( - serializedOfferFile: serializedOfferFile, + final takerOfferFile = + crossChainOfferFileService.createXchToBtcTakerOfferFile( + initializationCoinId: initializationCoinId, + serializedMakerOfferFile: serializedOfferFile, validityTime: exchangeValidityTime, requestorPublicKey: takerPublicKey, paymentRequest: decodedPaymentRequest, ); - serializedTakerOfferFile = await takerOfferFile.serializeAsync(takerPrivateKey); + serializedTakerOfferFile = + await takerOfferFile.serializeAsync(takerPrivateKey); escrowPuzzlehash = XchToBtcService.generateEscrowPuzzlehash( requestorPrivateKey: takerPrivateKey, @@ -143,14 +155,15 @@ Future main() async { 'should restore exchange offer record using initialization coin from POV of BTC holder making offer', () { test('after offer is created', () async { - final initializationCoins = - await fullNodeSimulator.scroungeForExchangeInitializationCoins(maker.puzzlehashes); + final initializationCoins = await fullNodeSimulator + .scroungeForExchangeInitializationCoins(maker.puzzlehashes); expect(initializationCoins.length, equals(1)); expect(initializationCoins.contains(initializationCoin), isTrue); final hydratedExchangeOfferRecord = - await exchangeOfferRecordHydrationService.hydrateExchangeInitializationCoin( + await exchangeOfferRecordHydrationService + .hydrateExchangeInitializationCoin( initializationCoins.single, makerMasterPrivateKey, maker.keychain, @@ -159,7 +172,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -221,7 +234,7 @@ Future main() async { test('after maker cancels exchange offer', () async { await exchangeOfferService.cancelExchangeOffer( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -230,21 +243,24 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final cancelCoin = - await exchangeOfferService.getCancelCoin(initializationCoin, messagePuzzlehash); + final cancelCoin = await exchangeOfferService.getCancelCoin( + initializationCoin, + messagePuzzlehash, + ); - final expectedCanceledTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(cancelCoin.spentBlockIndex); + final expectedCanceledTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(cancelCoin.spentBlockIndex); // restoring exchange offer record - final initializationCoins = - await fullNodeSimulator.scroungeForExchangeInitializationCoins(maker.puzzlehashes); + final initializationCoins = await fullNodeSimulator + .scroungeForExchangeInitializationCoins(maker.puzzlehashes); expect(initializationCoins.length, equals(1)); expect(initializationCoins.contains(initializationCoin), isTrue); final hydratedExchangeOfferRecord = - await exchangeOfferRecordHydrationService.hydrateExchangeInitializationCoin( + await exchangeOfferRecordHydrationService + .hydrateExchangeInitializationCoin( initializationCoins.single, makerMasterPrivateKey, maker.keychain, @@ -253,7 +269,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -310,7 +326,10 @@ Future main() async { expect(hydratedExchangeOfferRecord.escrowTransferCompletedTime, isNull); expect(hydratedExchangeOfferRecord.sweepTime, isNull); expect(hydratedExchangeOfferRecord.clawbackTime, isNull); - expect(hydratedExchangeOfferRecord.canceledTime, equals(expectedCanceledTime)); + expect( + hydratedExchangeOfferRecord.canceledTime, + equals(expectedCanceledTime), + ); }); test('after message coin arrives', () async { @@ -318,7 +337,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -329,19 +348,20 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final expectedMessageCoin = - (await fullNodeSimulator.scroungeForReceivedNotificationCoins([messagePuzzlehash])) - .single; + final expectedMessageCoin = (await fullNodeSimulator + .scroungeForReceivedNotificationCoins([messagePuzzlehash])) + .single; // restoring exchange offer record - final initializationCoins = - await fullNodeSimulator.scroungeForExchangeInitializationCoins(maker.puzzlehashes); + final initializationCoins = await fullNodeSimulator + .scroungeForExchangeInitializationCoins(maker.puzzlehashes); expect(initializationCoins.length, equals(1)); expect(initializationCoins.contains(initializationCoin), isTrue); final hydratedExchangeOfferRecord = - await exchangeOfferRecordHydrationService.hydrateExchangeInitializationCoin( + await exchangeOfferRecordHydrationService + .hydrateExchangeInitializationCoin( initializationCoins.single, makerMasterPrivateKey, maker.keychain, @@ -350,7 +370,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -396,7 +416,10 @@ Future main() async { hydratedExchangeOfferRecord.initializedTime, equals(initializedTime), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(expectedMessageCoin.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(expectedMessageCoin.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(expectedMessageCoin.dateConfirmed), @@ -409,7 +432,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(exchangeValidityTime), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(takerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(takerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehash), @@ -426,7 +452,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -438,8 +464,9 @@ Future main() async { await taker.refreshCoins(); // maker accepts message coin - final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + final messageCoinInfo = + await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: makerExchangeType, @@ -447,7 +474,7 @@ Future main() async { ); await exchangeOfferService.acceptMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoinInfo!.messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -457,23 +484,24 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentMessageCoinChild = - await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); + final spentMessageCoinChild = await fullNodeSimulator + .getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); expect(spentMessageCoinChild, isNotNull); - final expectedMessageCoinAcceptedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); + final expectedMessageCoinAcceptedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); // restoring exchange offer record - final initializationCoins = - await fullNodeSimulator.scroungeForExchangeInitializationCoins(maker.puzzlehashes); + final initializationCoins = await fullNodeSimulator + .scroungeForExchangeInitializationCoins(maker.puzzlehashes); expect(initializationCoins.length, equals(1)); expect(initializationCoins.contains(initializationCoin), isTrue); final hydratedExchangeOfferRecord = - await exchangeOfferRecordHydrationService.hydrateExchangeInitializationCoin( + await exchangeOfferRecordHydrationService + .hydrateExchangeInitializationCoin( initializationCoins.single, makerMasterPrivateKey, maker.keychain, @@ -482,7 +510,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -528,7 +556,10 @@ Future main() async { hydratedExchangeOfferRecord.initializedTime, equals(initializedTime), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(messageCoinInfo.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(messageCoinInfo.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(messageCoinInfo.messageCoinReceivedTime), @@ -541,7 +572,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(exchangeValidityTime), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(takerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(takerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehash), @@ -557,7 +591,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -569,8 +603,9 @@ Future main() async { await taker.refreshCoins(); // maker declines message coin - final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + final messageCoinInfo = + await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: makerExchangeType, @@ -578,7 +613,7 @@ Future main() async { ); await exchangeOfferService.declineMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoinInfo!.messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -589,14 +624,15 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); // restoring exchange offer record - final initializationCoins = - await fullNodeSimulator.scroungeForExchangeInitializationCoins(maker.puzzlehashes); + final initializationCoins = await fullNodeSimulator + .scroungeForExchangeInitializationCoins(maker.puzzlehashes); expect(initializationCoins.length, equals(1)); expect(initializationCoins.contains(initializationCoin), isTrue); final hydratedExchangeOfferRecord = - await exchangeOfferRecordHydrationService.hydrateExchangeInitializationCoin( + await exchangeOfferRecordHydrationService + .hydrateExchangeInitializationCoin( initializationCoins.single, makerMasterPrivateKey, maker.keychain, @@ -605,7 +641,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -685,7 +721,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -697,8 +733,9 @@ Future main() async { await taker.refreshCoins(); // maker accepts message coin - final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + final messageCoinInfo = + await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: makerExchangeType, @@ -706,7 +743,7 @@ Future main() async { ); await exchangeOfferService.acceptMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoinInfo!.messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -716,17 +753,17 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentMessageCoinChild = - await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); + final spentMessageCoinChild = await fullNodeSimulator + .getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); expect(spentMessageCoinChild, isNotNull); - final expectedMessageCoinAcceptedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); + final expectedMessageCoinAcceptedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); // taker transfers funds to escrow puzzlehash await exchangeOfferService.transferFundsToEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, mojos: mojos, escrowPuzzlehash: escrowPuzzlehash, requestorPrivateKey: takerPrivateKey, @@ -739,25 +776,29 @@ Future main() async { await taker.refreshCoins(); final escrowCoin = - (await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash])).single; - final escrowCoinParent = await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); + (await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash])) + .single; + final escrowCoinParent = + await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); - final escrowTransferCompletedBlockIndex = escrowCoinParent!.spentBlockIndex; - final expectedEscrowTransferCompletedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); + final escrowTransferCompletedBlockIndex = + escrowCoinParent!.spentBlockIndex; + final expectedEscrowTransferCompletedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); final expectedEscrowTransferConfirmedBlockIndex = escrowTransferCompletedBlockIndex + blocksForSufficientConfirmation; // restoring exchange offer record - final initializationCoins = - await fullNodeSimulator.scroungeForExchangeInitializationCoins(maker.puzzlehashes); + final initializationCoins = await fullNodeSimulator + .scroungeForExchangeInitializationCoins(maker.puzzlehashes); expect(initializationCoins.length, equals(1)); expect(initializationCoins.contains(initializationCoin), isTrue); final hydratedExchangeOfferRecord = - await exchangeOfferRecordHydrationService.hydrateExchangeInitializationCoin( + await exchangeOfferRecordHydrationService + .hydrateExchangeInitializationCoin( initializationCoins.single, makerMasterPrivateKey, maker.keychain, @@ -766,7 +807,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -812,7 +853,10 @@ Future main() async { hydratedExchangeOfferRecord.initializedTime, equals(initializedTime), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(messageCoinInfo.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(messageCoinInfo.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(messageCoinInfo.messageCoinReceivedTime), @@ -825,7 +869,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(exchangeValidityTime), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(takerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(takerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehash), @@ -851,7 +898,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -863,8 +910,9 @@ Future main() async { await taker.refreshCoins(); // maker accepts message coin - final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + final messageCoinInfo = + await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: makerExchangeType, @@ -872,7 +920,7 @@ Future main() async { ); await exchangeOfferService.acceptMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoinInfo!.messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -882,17 +930,17 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentMessageCoinChild = - await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); + final spentMessageCoinChild = await fullNodeSimulator + .getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); expect(spentMessageCoinChild, isNotNull); - final expectedMessageCoinAcceptedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); + final expectedMessageCoinAcceptedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); // taker transfers funds to escrow puzzlehash await exchangeOfferService.transferFundsToEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, mojos: mojos, escrowPuzzlehash: escrowPuzzlehash, requestorPrivateKey: takerPrivateKey, @@ -905,29 +953,36 @@ Future main() async { await taker.refreshCoins(); final escrowCoin = - (await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash])).single; - final escrowCoinParent = await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); + (await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash])) + .single; + final escrowCoinParent = + await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); - final escrowTransferCompletedBlockIndex = escrowCoinParent!.spentBlockIndex; - final expectedEscrowTransferCompletedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); + final escrowTransferCompletedBlockIndex = + escrowCoinParent!.spentBlockIndex; + final expectedEscrowTransferCompletedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); final expectedEscrowTransferConfirmedBlockIndex = escrowTransferCompletedBlockIndex + blocksForSufficientConfirmation; // wait for sufficient confirmations - await fullNodeSimulator.moveToNextBlock(blocks: blocksForSufficientConfirmation); - final expectedEscrowTransferConfirmedTime = await fullNodeSimulator.getCurrentBlockDateTime(); + await fullNodeSimulator.moveToNextBlock( + blocks: blocksForSufficientConfirmation, + ); + final expectedEscrowTransferConfirmedTime = + await fullNodeSimulator.getCurrentBlockDateTime(); // restoring exchange offer record - final initializationCoins = - await fullNodeSimulator.scroungeForExchangeInitializationCoins(maker.puzzlehashes); + final initializationCoins = await fullNodeSimulator + .scroungeForExchangeInitializationCoins(maker.puzzlehashes); expect(initializationCoins.length, equals(1)); expect(initializationCoins.contains(initializationCoin), isTrue); final hydratedExchangeOfferRecord = - await exchangeOfferRecordHydrationService.hydrateExchangeInitializationCoin( + await exchangeOfferRecordHydrationService + .hydrateExchangeInitializationCoin( initializationCoins.single, makerMasterPrivateKey, maker.keychain, @@ -936,7 +991,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -982,7 +1037,10 @@ Future main() async { hydratedExchangeOfferRecord.initializedTime, equals(initializedTime), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(messageCoinInfo.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(messageCoinInfo.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(messageCoinInfo.messageCoinReceivedTime), @@ -995,7 +1053,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(exchangeValidityTime), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(takerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(takerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehash), @@ -1024,7 +1085,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -1036,8 +1097,9 @@ Future main() async { await taker.refreshCoins(); // maker accepts message coin - final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + final messageCoinInfo = + await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: makerExchangeType, @@ -1045,7 +1107,7 @@ Future main() async { ); await exchangeOfferService.acceptMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoinInfo!.messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -1055,17 +1117,17 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentMessageCoinChild = - await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); + final spentMessageCoinChild = await fullNodeSimulator + .getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); expect(spentMessageCoinChild, isNotNull); - final expectedMessageCoinAcceptedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); + final expectedMessageCoinAcceptedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); // taker transfers funds to escrow puzzlehash await exchangeOfferService.transferFundsToEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, mojos: mojos, escrowPuzzlehash: escrowPuzzlehash, requestorPrivateKey: takerPrivateKey, @@ -1078,18 +1140,24 @@ Future main() async { await taker.refreshCoins(); final escrowCoin = - (await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash])).single; - final escrowCoinParent = await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); + (await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash])) + .single; + final escrowCoinParent = + await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); - final escrowTransferCompletedBlockIndex = escrowCoinParent!.spentBlockIndex; - final expectedEscrowTransferCompletedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); + final escrowTransferCompletedBlockIndex = + escrowCoinParent!.spentBlockIndex; + final expectedEscrowTransferCompletedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); final expectedEscrowTransferConfirmedBlockIndex = escrowTransferCompletedBlockIndex + blocksForSufficientConfirmation; // wait for sufficient confirmations - await fullNodeSimulator.moveToNextBlock(blocks: blocksForSufficientConfirmation); - final expectedEscrowTransferConfirmedTime = await fullNodeSimulator.getCurrentBlockDateTime(); + await fullNodeSimulator.moveToNextBlock( + blocks: blocksForSufficientConfirmation, + ); + final expectedEscrowTransferConfirmedTime = + await fullNodeSimulator.getCurrentBlockDateTime(); // maker sweeps escrow puzzlehash final makerEscrowPuzzlehash = BtcToXchService.generateEscrowPuzzlehash( @@ -1100,7 +1168,7 @@ Future main() async { ); await exchangeOfferService.sweepEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, escrowPuzzlehash: makerEscrowPuzzlehash, requestorPuzzlehash: maker.firstPuzzlehash, requestorPrivateKey: makerPrivateKey, @@ -1112,19 +1180,21 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentEscrowCoin = await fullNodeSimulator.getCoinById(escrowCoin.id); - final expectedSweepTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentEscrowCoin!.spentBlockIndex); + final spentEscrowCoin = + await fullNodeSimulator.getCoinById(escrowCoin.id); + final expectedSweepTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentEscrowCoin!.spentBlockIndex); // restoring exchange offer record - final initializationCoins = - await fullNodeSimulator.scroungeForExchangeInitializationCoins(maker.puzzlehashes); + final initializationCoins = await fullNodeSimulator + .scroungeForExchangeInitializationCoins(maker.puzzlehashes); expect(initializationCoins.length, equals(1)); expect(initializationCoins.contains(initializationCoin), isTrue); final hydratedExchangeOfferRecord = - await exchangeOfferRecordHydrationService.hydrateExchangeInitializationCoin( + await exchangeOfferRecordHydrationService + .hydrateExchangeInitializationCoin( initializationCoins.single, makerMasterPrivateKey, maker.keychain, @@ -1133,7 +1203,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -1179,7 +1249,10 @@ Future main() async { hydratedExchangeOfferRecord.initializedTime, equals(initializedTime), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(messageCoinInfo.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(messageCoinInfo.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(messageCoinInfo.messageCoinReceivedTime), @@ -1192,7 +1265,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(exchangeValidityTime), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(takerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(takerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehash), @@ -1223,21 +1299,24 @@ Future main() async { // shorten delay for testing purposes const shortenedValidity = 5; - final takerOfferFileWithShortenedValidity = crossChainOfferService.createXchToBtcAcceptFile( - serializedOfferFile: serializedOfferFile, + final takerOfferFileWithShortenedValidity = + crossChainOfferFileService.createXchToBtcTakerOfferFile( + initializationCoinId: initializationCoinId, + serializedMakerOfferFile: serializedOfferFile, validityTime: shortenedValidity, requestorPublicKey: takerPublicKey, paymentRequest: decodedPaymentRequest, ); final serializedTakerOfferFileWithShortenedValidity = - await takerOfferFileWithShortenedValidity.serializeAsync(takerPrivateKey); + await takerOfferFileWithShortenedValidity + .serializeAsync(takerPrivateKey); // taker sends message coin final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -1249,8 +1328,9 @@ Future main() async { await taker.refreshCoins(); // maker accepts message coin - final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + final messageCoinInfo = + await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: makerExchangeType, @@ -1258,7 +1338,7 @@ Future main() async { ); await exchangeOfferService.acceptMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoinInfo!.messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -1268,16 +1348,17 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentMessageCoinChild = - await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); + final spentMessageCoinChild = await fullNodeSimulator + .getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); expect(spentMessageCoinChild, isNotNull); - final expectedMessageCoinAcceptedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); + final expectedMessageCoinAcceptedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); // taker transfers funds to escrow puzzlehash - final escrowPuzzlehashWithShortenedValidity = XchToBtcService.generateEscrowPuzzlehash( + final escrowPuzzlehashWithShortenedValidity = + XchToBtcService.generateEscrowPuzzlehash( requestorPrivateKey: takerPrivateKey, clawbackDelaySeconds: shortenedValidity, sweepPaymentHash: paymentHash, @@ -1285,7 +1366,7 @@ Future main() async { ); await exchangeOfferService.transferFundsToEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, mojos: mojos, escrowPuzzlehash: escrowPuzzlehashWithShortenedValidity, requestorPrivateKey: takerPrivateKey, @@ -1297,14 +1378,16 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await maker.refreshCoins(); - final escrowCoin = - (await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehashWithShortenedValidity])) - .single; - final escrowCoinParent = await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); + final escrowCoin = (await fullNodeSimulator + .getCoinsByPuzzleHashes([escrowPuzzlehashWithShortenedValidity])) + .single; + final escrowCoinParent = + await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); - final escrowTransferCompletedBlockIndex = escrowCoinParent!.spentBlockIndex; - final expectedEscrowTransferCompletedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); + final escrowTransferCompletedBlockIndex = + escrowCoinParent!.spentBlockIndex; + final expectedEscrowTransferCompletedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); final expectedEscrowTransferConfirmedBlockIndex = escrowTransferCompletedBlockIndex + blocksForSufficientConfirmation; @@ -1313,14 +1396,20 @@ Future main() async { await fullNodeSimulator.moveToNextBlock( blocks: blocksForSufficientConfirmation, ); + final expectedEscrowTransferConfirmedTime = + await fullNodeSimulator.getCurrentBlockDateTime(); - final expectedEscrowTransferConfirmedTime = await fullNodeSimulator.getCurrentBlockDateTime(); + // the earliest you can spend a time-locked coin is 2 blocks later, since the time is checked + // against the timestamp of the previous block + for (var i = 0; i < 2; i++) { + await fullNodeSimulator.moveToNextBlock(); + } // wait until clawback delay period has passed await Future.delayed(const Duration(seconds: 10), () async { // taker claws back funds at escrow puzzlehash await exchangeOfferService.clawbackEscrowFunds( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, escrowPuzzlehash: escrowPuzzlehashWithShortenedValidity, requestorPuzzlehash: taker.firstPuzzlehash, requestorPrivateKey: takerPrivateKey, @@ -1331,19 +1420,21 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentEscrowCoin = await fullNodeSimulator.getCoinById(escrowCoin.id); - final expectedClawbackTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentEscrowCoin!.spentBlockIndex); + final spentEscrowCoin = + await fullNodeSimulator.getCoinById(escrowCoin.id); + final expectedClawbackTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentEscrowCoin!.spentBlockIndex); // restoring exchange offer record - final initializationCoins = - await fullNodeSimulator.scroungeForExchangeInitializationCoins(maker.puzzlehashes); + final initializationCoins = await fullNodeSimulator + .scroungeForExchangeInitializationCoins(maker.puzzlehashes); expect(initializationCoins.length, equals(1)); expect(initializationCoins.contains(initializationCoin), isTrue); final hydratedExchangeOfferRecord = - await exchangeOfferRecordHydrationService.hydrateExchangeInitializationCoin( + await exchangeOfferRecordHydrationService + .hydrateExchangeInitializationCoin( initializationCoins.single, makerMasterPrivateKey, maker.keychain, @@ -1352,7 +1443,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -1394,7 +1485,10 @@ Future main() async { hydratedExchangeOfferRecord.lightningPaymentRequest!.paymentRequest, equals(paymentRequest), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(messageCoinInfo.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(messageCoinInfo.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(messageCoinInfo.messageCoinReceivedTime), @@ -1407,7 +1501,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(shortenedValidity), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(takerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(takerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehashWithShortenedValidity), @@ -1430,7 +1527,10 @@ Future main() async { expectedEscrowTransferConfirmedTime, ); expect(hydratedExchangeOfferRecord.sweepTime, isNull); - expect(hydratedExchangeOfferRecord.clawbackTime, equals(expectedClawbackTime)); + expect( + hydratedExchangeOfferRecord.clawbackTime, + equals(expectedClawbackTime), + ); expect(hydratedExchangeOfferRecord.canceledTime, isNull); }); }); @@ -1444,7 +1544,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -1455,16 +1555,16 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final expectedMessageCoin = - (await fullNodeSimulator.scroungeForReceivedNotificationCoins([messagePuzzlehash])) - .single; + final expectedMessageCoin = (await fullNodeSimulator + .scroungeForReceivedNotificationCoins([messagePuzzlehash])) + .single; - final expectedMessageCoinReceivedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); + final expectedMessageCoinReceivedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); // restoring exchange offer record - final sentMessageCoins = - await fullNodeSimulator.scroungeForSentNotificationCoins(taker.puzzlehashes); + final sentMessageCoins = await fullNodeSimulator + .scroungeForSentNotificationCoins(taker.puzzlehashes); expect(sentMessageCoins.length, equals(1)); @@ -1477,7 +1577,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -1519,7 +1619,10 @@ Future main() async { hydratedExchangeOfferRecord.lightningPaymentRequest!.paymentRequest, equals(paymentRequest), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(expectedMessageCoin.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(expectedMessageCoin.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(expectedMessageCoinReceivedTime), @@ -1532,7 +1635,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(exchangeValidityTime), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(makerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(makerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehash), @@ -1551,7 +1657,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -1562,16 +1668,16 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final expectedMessageCoin = - (await fullNodeSimulator.scroungeForReceivedNotificationCoins([messagePuzzlehash])) - .single; + final expectedMessageCoin = (await fullNodeSimulator + .scroungeForReceivedNotificationCoins([messagePuzzlehash])) + .single; - final expectedMessageCoinReceivedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); + final expectedMessageCoinReceivedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); // maker cancels offer await exchangeOfferService.cancelExchangeOffer( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -1580,15 +1686,17 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final cancelCoin = - await exchangeOfferService.getCancelCoin(initializationCoin, messagePuzzlehash); + final cancelCoin = await exchangeOfferService.getCancelCoin( + initializationCoin, + messagePuzzlehash, + ); - final expectedCanceledTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(cancelCoin.spentBlockIndex); + final expectedCanceledTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(cancelCoin.spentBlockIndex); // restoring exchange offer record - final sentMessageCoins = - await fullNodeSimulator.scroungeForSentNotificationCoins(taker.puzzlehashes); + final sentMessageCoins = await fullNodeSimulator + .scroungeForSentNotificationCoins(taker.puzzlehashes); expect(sentMessageCoins.length, equals(1)); @@ -1601,7 +1709,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -1643,7 +1751,10 @@ Future main() async { hydratedExchangeOfferRecord.lightningPaymentRequest!.paymentRequest, equals(paymentRequest), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(expectedMessageCoin.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(expectedMessageCoin.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(expectedMessageCoinReceivedTime), @@ -1656,7 +1767,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(exchangeValidityTime), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(makerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(makerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehash), @@ -1667,7 +1781,10 @@ Future main() async { expect(hydratedExchangeOfferRecord.escrowCoinId, isNull); expect(hydratedExchangeOfferRecord.sweepTime, isNull); expect(hydratedExchangeOfferRecord.clawbackTime, isNull); - expect(hydratedExchangeOfferRecord.canceledTime, equals(expectedCanceledTime)); + expect( + hydratedExchangeOfferRecord.canceledTime, + equals(expectedCanceledTime), + ); }); test('after maker accepts message coin', () async { @@ -1675,7 +1792,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -1686,16 +1803,17 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final expectedMessageCoin = - (await fullNodeSimulator.scroungeForReceivedNotificationCoins([messagePuzzlehash])) - .single; + final expectedMessageCoin = (await fullNodeSimulator + .scroungeForReceivedNotificationCoins([messagePuzzlehash])) + .single; - final expectedMessageCoinReceivedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); + final expectedMessageCoinReceivedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); // maker accepts message coin - final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + final messageCoinInfo = + await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: makerExchangeType, @@ -1703,7 +1821,7 @@ Future main() async { ); await exchangeOfferService.acceptMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoinInfo!.messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -1713,17 +1831,17 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentMessageCoinChild = - await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); + final spentMessageCoinChild = await fullNodeSimulator + .getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); expect(spentMessageCoinChild, isNotNull); - final expectedMessageCoinAcceptedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); + final expectedMessageCoinAcceptedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); // restoring exchange offer record - final sentMessageCoins = - await fullNodeSimulator.scroungeForSentNotificationCoins(taker.puzzlehashes); + final sentMessageCoins = await fullNodeSimulator + .scroungeForSentNotificationCoins(taker.puzzlehashes); expect(sentMessageCoins.length, equals(1)); @@ -1736,7 +1854,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -1778,7 +1896,10 @@ Future main() async { hydratedExchangeOfferRecord.lightningPaymentRequest!.paymentRequest, equals(paymentRequest), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(expectedMessageCoin.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(expectedMessageCoin.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(expectedMessageCoinReceivedTime), @@ -1791,7 +1912,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(exchangeValidityTime), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(makerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(makerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehash), @@ -1813,7 +1937,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -1824,16 +1948,17 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final expectedMessageCoin = - (await fullNodeSimulator.scroungeForReceivedNotificationCoins([messagePuzzlehash])) - .single; + final expectedMessageCoin = (await fullNodeSimulator + .scroungeForReceivedNotificationCoins([messagePuzzlehash])) + .single; - final expectedMessageCoinReceivedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); + final expectedMessageCoinReceivedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); // maker declines message coin - final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + final messageCoinInfo = + await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: makerExchangeType, @@ -1841,7 +1966,7 @@ Future main() async { ); await exchangeOfferService.declineMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoinInfo!.messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -1851,17 +1976,17 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentMessageCoinChild = - await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); + final spentMessageCoinChild = await fullNodeSimulator + .getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); expect(spentMessageCoinChild, isNotNull); - final expectedMessageCoinDeclinedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); + final expectedMessageCoinDeclinedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); // restoring exchange offer record - final sentMessageCoins = - await fullNodeSimulator.scroungeForSentNotificationCoins(taker.puzzlehashes); + final sentMessageCoins = await fullNodeSimulator + .scroungeForSentNotificationCoins(taker.puzzlehashes); expect(sentMessageCoins.length, equals(1)); @@ -1874,7 +1999,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -1916,7 +2041,10 @@ Future main() async { hydratedExchangeOfferRecord.lightningPaymentRequest!.paymentRequest, equals(paymentRequest), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(expectedMessageCoin.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(expectedMessageCoin.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(expectedMessageCoinReceivedTime), @@ -1929,7 +2057,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(exchangeValidityTime), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(makerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(makerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehash), @@ -1951,7 +2082,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -1962,16 +2093,17 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final expectedMessageCoin = - (await fullNodeSimulator.scroungeForReceivedNotificationCoins([messagePuzzlehash])) - .single; + final expectedMessageCoin = (await fullNodeSimulator + .scroungeForReceivedNotificationCoins([messagePuzzlehash])) + .single; - final expectedMessageCoinReceivedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); + final expectedMessageCoinReceivedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); // maker accepts message coin - final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + final messageCoinInfo = + await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: makerExchangeType, @@ -1979,7 +2111,7 @@ Future main() async { ); await exchangeOfferService.acceptMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoinInfo!.messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -1989,17 +2121,17 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentMessageCoinChild = - await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); + final spentMessageCoinChild = await fullNodeSimulator + .getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); expect(spentMessageCoinChild, isNotNull); - final expectedMessageCoinAcceptedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); + final expectedMessageCoinAcceptedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); // taker transfers funds to escrow puzzlehash await exchangeOfferService.transferFundsToEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, mojos: mojos, escrowPuzzlehash: escrowPuzzlehash, requestorPrivateKey: takerPrivateKey, @@ -2012,19 +2144,22 @@ Future main() async { await taker.refreshCoins(); final escrowCoin = - (await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash])).single; - final escrowCoinParent = await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); + (await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash])) + .single; + final escrowCoinParent = + await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); - final escrowTransferCompletedBlockIndex = escrowCoinParent!.spentBlockIndex; - final expectedEscrowTransferCompletedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); + final escrowTransferCompletedBlockIndex = + escrowCoinParent!.spentBlockIndex; + final expectedEscrowTransferCompletedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); final expectedEscrowTransferConfirmedBlockIndex = escrowTransferCompletedBlockIndex + blocksForSufficientConfirmation; // restoring exchange offer record - final sentMessageCoins = - await fullNodeSimulator.scroungeForSentNotificationCoins(taker.puzzlehashes); + final sentMessageCoins = await fullNodeSimulator + .scroungeForSentNotificationCoins(taker.puzzlehashes); expect(sentMessageCoins.length, equals(1)); @@ -2037,7 +2172,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -2079,7 +2214,10 @@ Future main() async { hydratedExchangeOfferRecord.lightningPaymentRequest!.paymentRequest, equals(paymentRequest), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(expectedMessageCoin.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(expectedMessageCoin.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(expectedMessageCoinReceivedTime), @@ -2092,7 +2230,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(exchangeValidityTime), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(makerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(makerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehash), @@ -2122,7 +2263,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -2133,16 +2274,17 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final expectedMessageCoin = - (await fullNodeSimulator.scroungeForReceivedNotificationCoins([messagePuzzlehash])) - .single; + final expectedMessageCoin = (await fullNodeSimulator + .scroungeForReceivedNotificationCoins([messagePuzzlehash])) + .single; - final expectedMessageCoinReceivedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); + final expectedMessageCoinReceivedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); // maker accepts message coin - final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + final messageCoinInfo = + await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: makerExchangeType, @@ -2150,7 +2292,7 @@ Future main() async { ); await exchangeOfferService.acceptMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoinInfo!.messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -2160,17 +2302,17 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentMessageCoinChild = - await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); + final spentMessageCoinChild = await fullNodeSimulator + .getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); expect(spentMessageCoinChild, isNotNull); - final expectedMessageCoinAcceptedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); + final expectedMessageCoinAcceptedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); // taker transfers funds to escrow puzzlehash await exchangeOfferService.transferFundsToEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, mojos: mojos, escrowPuzzlehash: escrowPuzzlehash, requestorPrivateKey: takerPrivateKey, @@ -2183,24 +2325,29 @@ Future main() async { await taker.refreshCoins(); final escrowCoin = - (await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash])).single; - final escrowCoinParent = await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); + (await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash])) + .single; + final escrowCoinParent = + await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); - final escrowTransferCompletedBlockIndex = escrowCoinParent!.spentBlockIndex; - final expectedEscrowTransferCompletedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); + final escrowTransferCompletedBlockIndex = + escrowCoinParent!.spentBlockIndex; + final expectedEscrowTransferCompletedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); final expectedEscrowTransferConfirmedBlockIndex = escrowTransferCompletedBlockIndex + blocksForSufficientConfirmation; // wait for sufficient confirmations - await fullNodeSimulator.moveToNextBlock(blocks: blocksForSufficientConfirmation); - - final expectedEscrowTransferConfirmedTime = await fullNodeSimulator.getCurrentBlockDateTime(); + await fullNodeSimulator.moveToNextBlock( + blocks: blocksForSufficientConfirmation, + ); + final expectedEscrowTransferConfirmedTime = + await fullNodeSimulator.getCurrentBlockDateTime(); // restoring exchange offer record - final sentMessageCoins = - await fullNodeSimulator.scroungeForSentNotificationCoins(taker.puzzlehashes); + final sentMessageCoins = await fullNodeSimulator + .scroungeForSentNotificationCoins(taker.puzzlehashes); expect(sentMessageCoins.length, equals(1)); @@ -2213,7 +2360,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -2255,7 +2402,10 @@ Future main() async { hydratedExchangeOfferRecord.lightningPaymentRequest!.paymentRequest, equals(paymentRequest), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(expectedMessageCoin.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(expectedMessageCoin.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(expectedMessageCoinReceivedTime), @@ -2268,7 +2418,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(exchangeValidityTime), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(makerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(makerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehash), @@ -2301,7 +2454,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -2312,16 +2465,17 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final expectedMessageCoin = - (await fullNodeSimulator.scroungeForReceivedNotificationCoins([messagePuzzlehash])) - .single; + final expectedMessageCoin = (await fullNodeSimulator + .scroungeForReceivedNotificationCoins([messagePuzzlehash])) + .single; - final expectedMessageCoinReceivedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); + final expectedMessageCoinReceivedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); // maker accepts message coin - final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + final messageCoinInfo = + await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: makerExchangeType, @@ -2329,7 +2483,7 @@ Future main() async { ); await exchangeOfferService.acceptMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoinInfo!.messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -2339,16 +2493,16 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentMessageCoinChild = - await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); + final spentMessageCoinChild = await fullNodeSimulator + .getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); expect(spentMessageCoinChild, isNotNull); - final expectedMessageCoinAcceptedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); + final expectedMessageCoinAcceptedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); // taker transfers funds to escrow puzzlehash await exchangeOfferService.transferFundsToEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, mojos: mojos, escrowPuzzlehash: escrowPuzzlehash, requestorPrivateKey: takerPrivateKey, @@ -2361,19 +2515,25 @@ Future main() async { await taker.refreshCoins(); final escrowCoin = - (await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash])).single; - final escrowCoinParent = await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); + (await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash])) + .single; + final escrowCoinParent = + await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); - final escrowTransferCompletedBlockIndex = escrowCoinParent!.spentBlockIndex; - final expectedEscrowTransferCompletedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); + final escrowTransferCompletedBlockIndex = + escrowCoinParent!.spentBlockIndex; + final expectedEscrowTransferCompletedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); final expectedEscrowTransferConfirmedBlockIndex = escrowTransferCompletedBlockIndex + blocksForSufficientConfirmation; // wait for sufficient confirmations - await fullNodeSimulator.moveToNextBlock(blocks: blocksForSufficientConfirmation); - final expectedEscrowTransferConfirmedTime = await fullNodeSimulator.getCurrentBlockDateTime(); + await fullNodeSimulator.moveToNextBlock( + blocks: blocksForSufficientConfirmation, + ); + final expectedEscrowTransferConfirmedTime = + await fullNodeSimulator.getCurrentBlockDateTime(); // maker sweeps escrow puzzlehash final makerEscrowPuzzlehash = BtcToXchService.generateEscrowPuzzlehash( @@ -2384,7 +2544,7 @@ Future main() async { ); await exchangeOfferService.sweepEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, escrowPuzzlehash: makerEscrowPuzzlehash, requestorPuzzlehash: maker.firstPuzzlehash, requestorPrivateKey: makerPrivateKey, @@ -2396,13 +2556,14 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentEscrowCoin = await fullNodeSimulator.getCoinById(escrowCoin.id); - final expectedSweepTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentEscrowCoin!.spentBlockIndex); + final spentEscrowCoin = + await fullNodeSimulator.getCoinById(escrowCoin.id); + final expectedSweepTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentEscrowCoin!.spentBlockIndex); // restoring exchange offer record - final sentMessageCoins = - await fullNodeSimulator.scroungeForSentNotificationCoins(taker.puzzlehashes); + final sentMessageCoins = await fullNodeSimulator + .scroungeForSentNotificationCoins(taker.puzzlehashes); expect(sentMessageCoins.length, equals(1)); @@ -2415,7 +2576,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -2457,7 +2618,10 @@ Future main() async { hydratedExchangeOfferRecord.lightningPaymentRequest!.paymentRequest, equals(paymentRequest), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(expectedMessageCoin.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(expectedMessageCoin.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(expectedMessageCoinReceivedTime), @@ -2470,7 +2634,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(exchangeValidityTime), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(makerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(makerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehash), @@ -2502,21 +2669,24 @@ Future main() async { // shorten delay for testing purposes const shortenedValidity = 5; - final takerOfferFileWithShortenedValidity = crossChainOfferService.createXchToBtcAcceptFile( - serializedOfferFile: serializedOfferFile, + final takerOfferFileWithShortenedValidity = + crossChainOfferFileService.createXchToBtcTakerOfferFile( + initializationCoinId: initializationCoinId, + serializedMakerOfferFile: serializedOfferFile, validityTime: shortenedValidity, requestorPublicKey: takerPublicKey, paymentRequest: decodedPaymentRequest, ); final serializedTakerOfferFileWithShortenedValidity = - await takerOfferFileWithShortenedValidity.serializeAsync(takerPrivateKey); + await takerOfferFileWithShortenedValidity + .serializeAsync(takerPrivateKey); // taker sends message coin final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -2528,8 +2698,9 @@ Future main() async { await taker.refreshCoins(); // maker accepts message coin - final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + final messageCoinInfo = + await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: makerExchangeType, @@ -2537,7 +2708,7 @@ Future main() async { ); await exchangeOfferService.acceptMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoinInfo!.messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -2547,16 +2718,17 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentMessageCoinChild = - await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); + final spentMessageCoinChild = await fullNodeSimulator + .getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); expect(spentMessageCoinChild, isNotNull); - final expectedMessageCoinAcceptedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); + final expectedMessageCoinAcceptedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); // taker transfers funds to escrow puzzlehash - final escrowPuzzlehashWithShortenedValidity = XchToBtcService.generateEscrowPuzzlehash( + final escrowPuzzlehashWithShortenedValidity = + XchToBtcService.generateEscrowPuzzlehash( requestorPrivateKey: takerPrivateKey, clawbackDelaySeconds: shortenedValidity, sweepPaymentHash: paymentHash, @@ -2564,7 +2736,7 @@ Future main() async { ); await exchangeOfferService.transferFundsToEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, mojos: mojos, escrowPuzzlehash: escrowPuzzlehashWithShortenedValidity, requestorPrivateKey: takerPrivateKey, @@ -2576,26 +2748,37 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await maker.refreshCoins(); - final escrowCoin = - (await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehashWithShortenedValidity])) - .single; - final escrowCoinParent = await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); + final escrowCoin = (await fullNodeSimulator + .getCoinsByPuzzleHashes([escrowPuzzlehashWithShortenedValidity])) + .single; + final escrowCoinParent = + await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); - final escrowTransferCompletedBlockIndex = escrowCoinParent!.spentBlockIndex; - final expectedEscrowTransferCompletedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); + final escrowTransferCompletedBlockIndex = + escrowCoinParent!.spentBlockIndex; + final expectedEscrowTransferCompletedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); final expectedEscrowTransferConfirmedBlockIndex = escrowTransferCompletedBlockIndex + blocksForSufficientConfirmation; // wait for sufficient confirmations - await fullNodeSimulator.moveToNextBlock(blocks: blocksForSufficientConfirmation); - final expectedEscrowTransferConfirmedTime = await fullNodeSimulator.getCurrentBlockDateTime(); + await fullNodeSimulator.moveToNextBlock( + blocks: blocksForSufficientConfirmation, + ); + final expectedEscrowTransferConfirmedTime = + await fullNodeSimulator.getCurrentBlockDateTime(); + + // the earliest you can spend a time-locked coin is 2 blocks later, since the time is checked + // against the timestamp of the previous block + for (var i = 0; i < 2; i++) { + await fullNodeSimulator.moveToNextBlock(); + } await Future.delayed(const Duration(seconds: 10), () async { // maker claws back funds at escrow puzzlehash await exchangeOfferService.clawbackEscrowFunds( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, escrowPuzzlehash: escrowPuzzlehashWithShortenedValidity, requestorPuzzlehash: taker.firstPuzzlehash, requestorPrivateKey: takerPrivateKey, @@ -2606,13 +2789,14 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentEscrowCoin = await fullNodeSimulator.getCoinById(escrowCoin.id); - final expectedClawbackTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentEscrowCoin!.spentBlockIndex); + final spentEscrowCoin = + await fullNodeSimulator.getCoinById(escrowCoin.id); + final expectedClawbackTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentEscrowCoin!.spentBlockIndex); // restoring exchange offer record - final sentMessageCoins = - await fullNodeSimulator.scroungeForSentNotificationCoins(taker.puzzlehashes); + final sentMessageCoins = await fullNodeSimulator + .scroungeForSentNotificationCoins(taker.puzzlehashes); expect(sentMessageCoins.length, equals(1)); @@ -2625,7 +2809,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -2667,7 +2851,10 @@ Future main() async { hydratedExchangeOfferRecord.lightningPaymentRequest!.paymentRequest, equals(paymentRequest), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(messageCoinInfo.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(messageCoinInfo.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(messageCoinInfo.messageCoinReceivedTime), @@ -2680,7 +2867,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(shortenedValidity), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(makerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(makerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehashWithShortenedValidity), @@ -2704,7 +2894,10 @@ Future main() async { ); expect(hydratedExchangeOfferRecord.escrowCoinId, equals(escrowCoin.id)); expect(hydratedExchangeOfferRecord.sweepTime, isNull); - expect(hydratedExchangeOfferRecord.clawbackTime, equals(expectedClawbackTime)); + expect( + hydratedExchangeOfferRecord.clawbackTime, + equals(expectedClawbackTime), + ); expect(hydratedExchangeOfferRecord.canceledTime, isNull); }); }); diff --git a/integration_test/exchange/btc/exchange_offer_record_hydration_service/exchange_offer_record_hydration_exception_test.dart b/integration_test/exchange/btc/exchange_offer_record_hydration_service/exchange_offer_record_hydration_exception_test.dart index 8a0ff543..f9242de6 100644 --- a/integration_test/exchange/btc/exchange_offer_record_hydration_service/exchange_offer_record_hydration_exception_test.dart +++ b/integration_test/exchange/btc/exchange_offer_record_hydration_service/exchange_offer_record_hydration_exception_test.dart @@ -23,10 +23,13 @@ Future main() async { await nathan.refreshCoins(); }); - test('should throw exception when trying to hydrate invalid initialization coin', () async { + test( + 'should throw exception when trying to hydrate invalid initialization coin', + () async { expect( () async { - await exchangeOfferRecordHydrationService.hydrateExchangeInitializationCoin( + await exchangeOfferRecordHydrationService + .hydrateExchangeInitializationCoin( nathan.standardCoins.first, nathan.keychainSecret.masterPrivateKey, nathan.keychain, @@ -36,13 +39,15 @@ Future main() async { ); }); - test('should throw exception when trying to hydrate invalid message coin', () async { + test('should throw exception when trying to hydrate invalid message coin', + () async { // creating notification coin that isn't an exchange message coin final notificationService = NotificationWalletService(); final targetPuzzlehash = nathan.puzzlehashes[1]; - final notificationSpendBundle = notificationService.createNotificationSpendBundle( + final notificationSpendBundle = + notificationService.createNotificationSpendBundle( targetPuzzlehash: targetPuzzlehash, message: [Memo(encodeInt(1000))], amount: minimumNotificationCoinAmount, @@ -54,8 +59,9 @@ Future main() async { await fullNodeSimulator.pushTransaction(notificationSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final notificationCoin = - (await fullNodeSimulator.scroungeForReceivedNotificationCoins([targetPuzzlehash])).single; + final notificationCoin = (await fullNodeSimulator + .scroungeForReceivedNotificationCoins([targetPuzzlehash])) + .single; expect( () async { diff --git a/integration_test/exchange/btc/exchange_offer_record_hydration_service/exchange_offer_record_hydration_with_errant_coin_test.dart b/integration_test/exchange/btc/exchange_offer_record_hydration_service/exchange_offer_record_hydration_with_errant_coin_test.dart index 7e35c7db..30abb568 100644 --- a/integration_test/exchange/btc/exchange_offer_record_hydration_service/exchange_offer_record_hydration_with_errant_coin_test.dart +++ b/integration_test/exchange/btc/exchange_offer_record_hydration_service/exchange_offer_record_hydration_with_errant_coin_test.dart @@ -1,5 +1,4 @@ @Timeout(Duration(minutes: 5)) -@Skip('Long') import 'dart:async'; import 'dart:math'; @@ -12,10 +11,10 @@ Future main() async { print(SimulatorUtils.simulatorNotRunningWarning); return; } - final fullNodeSimulator = SimulatorFullNodeInterface.withDefaultUrl(); + ChiaNetworkContextWrapper().registerNetworkContext(Network.mainnet); - final crossChainOfferService = CrossChainOfferService(fullNodeSimulator); + final crossChainOfferFileService = CrossChainOfferFileService(); final exchangeOfferService = ExchangeOfferService(fullNodeSimulator); final exchangeOfferRecordHydrationService = ExchangeOfferRecordHydrationService(fullNodeSimulator); @@ -29,7 +28,9 @@ Future main() async { 'lnbc1u1p3huyzkpp5vw6fkrw9lr3pvved40zpp4jway4g4ee6uzsaj208dxqxgm2rtkvqdqqcqzzgxqyz5vqrzjqwnvuc0u4txn35cafc7w94gxvq5p3cu9dd95f7hlrh0fvs46wpvhdrxkxglt5qydruqqqqryqqqqthqqpyrzjqw8c7yfutqqy3kz8662fxutjvef7q2ujsxtt45csu0k688lkzu3ldrxkxglt5qydruqqqqryqqqqthqqpysp5jzgpj4990chtj9f9g2f6mhvgtzajzckx774yuh0klnr3hmvrqtjq9qypqsqkrvl3sqd4q4dm9axttfa6frg7gffguq3rzuvvm2fpuqsgg90l4nz8zgc3wx7gggm04xtwq59vftm25emwp9mtvmvjg756dyzn2dm98qpakw4u8'; final decodedPaymentRequest = decodeLightningPaymentRequest(paymentRequest); final paymentHash = decodedPaymentRequest.paymentHash!; - final preimage = '5c1f10653dc3ff0531b77351dc6676de2e1f5f53c9f0a8867bcb054648f46a32'.hexToBytes(); + final preimage = + '5c1f10653dc3ff0531b77351dc6676de2e1f5f53c9f0a8867bcb054648f46a32' + .hexToBytes(); late ChiaEnthusiast maker; late PrivateKey makerMasterPrivateKey; @@ -40,6 +41,7 @@ Future main() async { late int offerValidityTime; late String serializedOfferFile; late Coin initializationCoin; + late Bytes initializationCoinId; late DateTime initializedTime; late ChiaEnthusiast taker; @@ -61,7 +63,8 @@ Future main() async { await maker.refreshCoins(); makerMasterPrivateKey = maker.keychainSecret.masterPrivateKey; - makerDerivationIndex = ExchangeOfferService.randomDerivationIndexForExchange(); + makerDerivationIndex = + ExchangeOfferService.randomDerivationIndexForExchange(); final makerWalletVector = await WalletVector.fromPrivateKeyAsync( makerMasterPrivateKey, @@ -76,10 +79,15 @@ Future main() async { final messageAddress = Address.fromContext(messagePuzzlehash); const offerValidityTimeHours = 1; - final currentUnixTimestamp = DateTime.now().millisecondsSinceEpoch ~/ 1000; - offerValidityTime = currentUnixTimestamp + (offerValidityTimeHours * 60 * 60); + final currentUnixTimeStamp = DateTime.now().millisecondsSinceEpoch ~/ 1000; + offerValidityTime = + currentUnixTimeStamp + (offerValidityTimeHours * 60 * 60); + + final unspentInitializationCoin = maker.standardCoins.first; + initializationCoinId = unspentInitializationCoin.id; - final offerFile = crossChainOfferService.createXchToBtcOfferFile( + final offerFile = crossChainOfferFileService.createXchToBtcMakerOfferFile( + initializationCoinId: initializationCoinId, amountMojos: mojos, amountSatoshis: satoshis, messageAddress: messageAddress, @@ -91,7 +99,6 @@ Future main() async { serializedOfferFile = await offerFile.serializeAsync(makerPrivateKey); // maker pushes initialization spend bundle to create offer - final unspentInitializationCoin = maker.standardCoins.first; await exchangeOfferService.pushInitializationSpendBundle( messagePuzzlehash: messagePuzzlehash, @@ -105,9 +112,10 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await maker.refreshCoins(); - initializationCoin = (await fullNodeSimulator.getCoinById(unspentInitializationCoin.id))!; - initializedTime = - (await fullNodeSimulator.getDateTimeFromBlockIndex(initializationCoin.spentBlockIndex))!; + initializationCoin = + (await fullNodeSimulator.getCoinById(unspentInitializationCoin.id))!; + initializedTime = (await fullNodeSimulator + .getDateTimeFromBlockIndex(initializationCoin.spentBlockIndex))!; // taker side taker = ChiaEnthusiast(fullNodeSimulator, walletSize: 10); @@ -125,13 +133,16 @@ Future main() async { takerPrivateKey = takerWalletVector.childPrivateKey; takerPublicKey = takerWalletVector.childPublicKey; - final takerOfferFile = crossChainOfferService.createBtcToXchAcceptFile( - serializedOfferFile: serializedOfferFile, + final takerOfferFile = + crossChainOfferFileService.createBtcToXchTakerOfferFile( + initializationCoinId: initializationCoinId, + serializedMakerOfferFile: serializedOfferFile, validityTime: exchangeValidityTime, requestorPublicKey: takerPublicKey, ); - serializedTakerOfferFile = await takerOfferFile.serializeAsync(takerPrivateKey); + serializedTakerOfferFile = + await takerOfferFile.serializeAsync(takerPrivateKey); escrowPuzzlehash = BtcToXchService.generateEscrowPuzzlehash( requestorPrivateKey: takerPrivateKey, @@ -144,8 +155,10 @@ Future main() async { errantCoinSender = ChiaEnthusiast(fullNodeSimulator); await errantCoinSender.farmCoins(); await errantCoinSender.refreshCoins(); - final errantCoinSenderWalletVector = - await WalletVector.fromPrivateKeyAsync(errantCoinSender.keychainSecret.masterPrivateKey, 1); + final errantCoinSenderWalletVector = await WalletVector.fromPrivateKeyAsync( + errantCoinSender.keychainSecret.masterPrivateKey, + 1, + ); errantCoinSenderPrivateKey = errantCoinSenderWalletVector.childPrivateKey; }); @@ -156,7 +169,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -169,14 +182,14 @@ Future main() async { // maker accepts message coin final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: makerExchangeType, ); await exchangeOfferService.acceptMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoinInfo!.messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -186,12 +199,12 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentMessageCoinChild = - await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); + final spentMessageCoinChild = await fullNodeSimulator + .getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); expect(spentMessageCoinChild, isNotNull); - final expectedMessageCoinAcceptedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); + final expectedMessageCoinAcceptedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); // maker transfers funds to escrow puzzlehash final makerEscrowPuzzlehash = XchToBtcService.generateEscrowPuzzlehash( @@ -204,7 +217,7 @@ Future main() async { final escrowCoinParent = maker.standardCoins.first; await exchangeOfferService.transferFundsToEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, mojos: mojos, escrowPuzzlehash: makerEscrowPuzzlehash, requestorPrivateKey: makerPrivateKey, @@ -216,25 +229,31 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await maker.refreshCoins(); - final escrowCoin = (await fullNodeSimulator.getCoinsByPuzzleHashes([makerEscrowPuzzlehash])) + final escrowCoin = (await fullNodeSimulator + .getCoinsByPuzzleHashes([makerEscrowPuzzlehash])) .where((coin) => coin.parentCoinInfo == escrowCoinParent.id) .single; - final spentEscrowCoinParent = await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); + final spentEscrowCoinParent = + await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); - final escrowTransferCompletedBlockIndex = spentEscrowCoinParent!.spentBlockIndex; - final expectedEscrowTransferCompletedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); + final escrowTransferCompletedBlockIndex = + spentEscrowCoinParent!.spentBlockIndex; + final expectedEscrowTransferCompletedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); final expectedEscrowTransferConfirmedBlockIndex = escrowTransferCompletedBlockIndex + blocksForSufficientConfirmation; // wait for sufficient confirmations - await fullNodeSimulator.moveToNextBlock(blocks: blocksForSufficientConfirmation); - final expectedEscrowTransferConfirmedTime = await fullNodeSimulator.getCurrentBlockDateTime(); + await fullNodeSimulator.moveToNextBlock( + blocks: blocksForSufficientConfirmation, + ); + final expectedEscrowTransferConfirmedTime = + await fullNodeSimulator.getCurrentBlockDateTime(); // malicious actor sends an errant coin to the leaked escrow puzzlehash final memos = ExchangeCoinMemos( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, requestorPrivateKey: errantCoinSenderPrivateKey, ).toMemos(); @@ -244,7 +263,7 @@ Future main() async { 1, escrowPuzzlehash, memos: memos, - ), + ) ], coinsInput: [errantCoinSender.standardCoins.first], keychain: errantCoinSender.keychain, @@ -256,7 +275,7 @@ Future main() async { // taker sweeps escrow puzzlehash await exchangeOfferService.sweepEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, escrowPuzzlehash: escrowPuzzlehash, requestorPuzzlehash: taker.firstPuzzlehash, requestorPrivateKey: takerPrivateKey, @@ -269,18 +288,19 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); final spentEscrowCoin = await fullNodeSimulator.getCoinById(escrowCoin.id); - final expectedSweepTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentEscrowCoin!.spentBlockIndex); + final expectedSweepTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentEscrowCoin!.spentBlockIndex); // restoring exchange offer record - final initializationCoins = - await fullNodeSimulator.scroungeForExchangeInitializationCoins(maker.puzzlehashes); + final initializationCoins = await fullNodeSimulator + .scroungeForExchangeInitializationCoins(maker.puzzlehashes); expect(initializationCoins.length, equals(1)); expect(initializationCoins.contains(initializationCoin), isTrue); final hydratedExchangeOfferRecord = - await exchangeOfferRecordHydrationService.hydrateExchangeInitializationCoin( + await exchangeOfferRecordHydrationService + .hydrateExchangeInitializationCoin( initializationCoins.single, makerMasterPrivateKey, maker.keychain, @@ -289,7 +309,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -335,7 +355,10 @@ Future main() async { hydratedExchangeOfferRecord.initializedTime, equals(initializedTime), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(messageCoinInfo.messageCoin.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(messageCoinInfo.messageCoin.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(messageCoinInfo.messageCoinReceivedTime), @@ -348,7 +371,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(exchangeValidityTime), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(takerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(takerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehash), diff --git a/integration_test/exchange/btc/exchange_offer_record_hydration_service/xch_to_btc_exchange_offer_record_hydration_test.dart b/integration_test/exchange/btc/exchange_offer_record_hydration_service/xch_to_btc_exchange_offer_record_hydration_test.dart index c3d9aaab..90b53fc1 100644 --- a/integration_test/exchange/btc/exchange_offer_record_hydration_service/xch_to_btc_exchange_offer_record_hydration_test.dart +++ b/integration_test/exchange/btc/exchange_offer_record_hydration_service/xch_to_btc_exchange_offer_record_hydration_test.dart @@ -1,6 +1,4 @@ @Timeout(Duration(minutes: 5)) -@Skip('Long') - import 'dart:async'; import 'dart:math'; @@ -15,8 +13,9 @@ Future main() async { } final fullNodeSimulator = SimulatorFullNodeInterface.withDefaultUrl(); + ChiaNetworkContextWrapper().registerNetworkContext(Network.mainnet); - final crossChainOfferService = CrossChainOfferService(fullNodeSimulator); + final crossChainOfferFileService = CrossChainOfferFileService(); final exchangeOfferService = ExchangeOfferService(fullNodeSimulator); final exchangeOfferRecordHydrationService = ExchangeOfferRecordHydrationService(fullNodeSimulator); @@ -32,7 +31,9 @@ Future main() async { 'lnbc1u1p3huyzkpp5vw6fkrw9lr3pvved40zpp4jway4g4ee6uzsaj208dxqxgm2rtkvqdqqcqzzgxqyz5vqrzjqwnvuc0u4txn35cafc7w94gxvq5p3cu9dd95f7hlrh0fvs46wpvhdrxkxglt5qydruqqqqryqqqqthqqpyrzjqw8c7yfutqqy3kz8662fxutjvef7q2ujsxtt45csu0k688lkzu3ldrxkxglt5qydruqqqqryqqqqthqqpysp5jzgpj4990chtj9f9g2f6mhvgtzajzckx774yuh0klnr3hmvrqtjq9qypqsqkrvl3sqd4q4dm9axttfa6frg7gffguq3rzuvvm2fpuqsgg90l4nz8zgc3wx7gggm04xtwq59vftm25emwp9mtvmvjg756dyzn2dm98qpakw4u8'; final decodedPaymentRequest = decodeLightningPaymentRequest(paymentRequest); final paymentHash = decodedPaymentRequest.paymentHash!; - final preimage = '5c1f10653dc3ff0531b77351dc6676de2e1f5f53c9f0a8867bcb054648f46a32'.hexToBytes(); + final preimage = + '5c1f10653dc3ff0531b77351dc6676de2e1f5f53c9f0a8867bcb054648f46a32' + .hexToBytes(); late ChiaEnthusiast maker; late PrivateKey makerMasterPrivateKey; @@ -43,6 +44,7 @@ Future main() async { late int offerValidityTime; late String serializedOfferFile; late Coin initializationCoin; + late Bytes initializationCoinId; late DateTime initializedTime; late ChiaEnthusiast taker; @@ -61,7 +63,8 @@ Future main() async { await maker.refreshCoins(); makerMasterPrivateKey = maker.keychainSecret.masterPrivateKey; - makerDerivationIndex = ExchangeOfferService.randomDerivationIndexForExchange(); + makerDerivationIndex = + ExchangeOfferService.randomDerivationIndexForExchange(); final makerWalletVector = await WalletVector.fromPrivateKeyAsync( makerMasterPrivateKey, @@ -76,10 +79,15 @@ Future main() async { final messageAddress = Address.fromContext(messagePuzzlehash); const offerValidityTimeHours = 1; - final currentUnixTimestamp = DateTime.now().millisecondsSinceEpoch ~/ 1000; - offerValidityTime = currentUnixTimestamp + (offerValidityTimeHours * 60 * 60); + final currentUnixTimeStamp = DateTime.now().millisecondsSinceEpoch ~/ 1000; + offerValidityTime = + currentUnixTimeStamp + (offerValidityTimeHours * 60 * 60); + + final unspentInitializationCoin = maker.standardCoins.first; + initializationCoinId = unspentInitializationCoin.id; - final offerFile = crossChainOfferService.createXchToBtcOfferFile( + final offerFile = crossChainOfferFileService.createXchToBtcMakerOfferFile( + initializationCoinId: initializationCoinId, amountMojos: mojos, amountSatoshis: satoshis, messageAddress: messageAddress, @@ -91,7 +99,6 @@ Future main() async { serializedOfferFile = await offerFile.serializeAsync(makerPrivateKey); // maker pushes initialization spend bundle to create offer - final unspentInitializationCoin = maker.standardCoins.first; await exchangeOfferService.pushInitializationSpendBundle( messagePuzzlehash: messagePuzzlehash, @@ -105,9 +112,10 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await maker.refreshCoins(); - initializationCoin = (await fullNodeSimulator.getCoinById(unspentInitializationCoin.id))!; - initializedTime = - (await fullNodeSimulator.getDateTimeFromBlockIndex(initializationCoin.spentBlockIndex))!; + initializationCoin = + (await fullNodeSimulator.getCoinById(unspentInitializationCoin.id))!; + initializedTime = (await fullNodeSimulator + .getDateTimeFromBlockIndex(initializationCoin.spentBlockIndex))!; // taker side taker = ChiaEnthusiast(fullNodeSimulator, walletSize: 10); @@ -125,13 +133,16 @@ Future main() async { takerPrivateKey = takerWalletVector.childPrivateKey; takerPublicKey = takerWalletVector.childPublicKey; - final takerOfferFile = crossChainOfferService.createBtcToXchAcceptFile( - serializedOfferFile: serializedOfferFile, + final takerOfferFile = + crossChainOfferFileService.createBtcToXchTakerOfferFile( + initializationCoinId: initializationCoinId, + serializedMakerOfferFile: serializedOfferFile, validityTime: exchangeValidityTime, requestorPublicKey: takerPublicKey, ); - serializedTakerOfferFile = await takerOfferFile.serializeAsync(takerPrivateKey); + serializedTakerOfferFile = + await takerOfferFile.serializeAsync(takerPrivateKey); escrowPuzzlehash = BtcToXchService.generateEscrowPuzzlehash( requestorPrivateKey: takerPrivateKey, @@ -145,14 +156,15 @@ Future main() async { 'should restore exchange offer record using initialization coin from POV of XCH holder making offer', () { test('after offer is created', () async { - final initializationCoins = - await fullNodeSimulator.scroungeForExchangeInitializationCoins(maker.puzzlehashes); + final initializationCoins = await fullNodeSimulator + .scroungeForExchangeInitializationCoins(maker.puzzlehashes); expect(initializationCoins.length, equals(1)); expect(initializationCoins.contains(initializationCoin), isTrue); final hydratedExchangeOfferRecord = - await exchangeOfferRecordHydrationService.hydrateExchangeInitializationCoin( + await exchangeOfferRecordHydrationService + .hydrateExchangeInitializationCoin( initializationCoins.single, makerMasterPrivateKey, maker.keychain, @@ -161,7 +173,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -230,14 +242,15 @@ Future main() async { expect(response.success, isTrue); // restoring exchange offer record - final initializationCoins = - await fullNodeSimulator.scroungeForExchangeInitializationCoins(maker.puzzlehashes); + final initializationCoins = await fullNodeSimulator + .scroungeForExchangeInitializationCoins(maker.puzzlehashes); expect(initializationCoins.length, equals(1)); expect(initializationCoins.contains(initializationCoin), isTrue); final hydratedExchangeOfferRecord = - await exchangeOfferRecordHydrationService.hydrateExchangeInitializationCoin( + await exchangeOfferRecordHydrationService + .hydrateExchangeInitializationCoin( initializationCoins.single, makerMasterPrivateKey, maker.keychain, @@ -246,7 +259,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -311,7 +324,7 @@ Future main() async { test('after maker cancels exchange offer', () async { await exchangeOfferService.cancelExchangeOffer( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -320,21 +333,24 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final cancelCoin = - await exchangeOfferService.getCancelCoin(initializationCoin, messagePuzzlehash); + final cancelCoin = await exchangeOfferService.getCancelCoin( + initializationCoin, + messagePuzzlehash, + ); - final expectedCanceledTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(cancelCoin.spentBlockIndex); + final expectedCanceledTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(cancelCoin.spentBlockIndex); // restoring exchange offer record - final initializationCoins = - await fullNodeSimulator.scroungeForExchangeInitializationCoins(maker.puzzlehashes); + final initializationCoins = await fullNodeSimulator + .scroungeForExchangeInitializationCoins(maker.puzzlehashes); expect(initializationCoins.length, equals(1)); expect(initializationCoins.contains(initializationCoin), isTrue); final hydratedExchangeOfferRecord = - await exchangeOfferRecordHydrationService.hydrateExchangeInitializationCoin( + await exchangeOfferRecordHydrationService + .hydrateExchangeInitializationCoin( initializationCoins.single, makerMasterPrivateKey, maker.keychain, @@ -343,7 +359,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -400,7 +416,10 @@ Future main() async { expect(hydratedExchangeOfferRecord.escrowTransferCompletedTime, isNull); expect(hydratedExchangeOfferRecord.sweepTime, isNull); expect(hydratedExchangeOfferRecord.clawbackTime, isNull); - expect(hydratedExchangeOfferRecord.canceledTime, equals(expectedCanceledTime)); + expect( + hydratedExchangeOfferRecord.canceledTime, + equals(expectedCanceledTime), + ); }); test('after message coin arrives', () async { @@ -408,7 +427,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -419,19 +438,20 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final expectedMessageCoin = - (await fullNodeSimulator.scroungeForReceivedNotificationCoins([messagePuzzlehash])) - .single; + final expectedMessageCoin = (await fullNodeSimulator + .scroungeForReceivedNotificationCoins([messagePuzzlehash])) + .single; // restoring exchange offer record - final initializationCoins = - await fullNodeSimulator.scroungeForExchangeInitializationCoins(maker.puzzlehashes); + final initializationCoins = await fullNodeSimulator + .scroungeForExchangeInitializationCoins(maker.puzzlehashes); expect(initializationCoins.length, equals(1)); expect(initializationCoins.contains(initializationCoin), isTrue); final hydratedExchangeOfferRecord = - await exchangeOfferRecordHydrationService.hydrateExchangeInitializationCoin( + await exchangeOfferRecordHydrationService + .hydrateExchangeInitializationCoin( initializationCoins.single, makerMasterPrivateKey, maker.keychain, @@ -440,7 +460,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -486,7 +506,10 @@ Future main() async { hydratedExchangeOfferRecord.initializedTime, equals(initializedTime), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(expectedMessageCoin.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(expectedMessageCoin.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(expectedMessageCoin.dateConfirmed), @@ -499,7 +522,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(exchangeValidityTime), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(takerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(takerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehash), @@ -516,7 +542,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -528,15 +554,16 @@ Future main() async { await taker.refreshCoins(); // maker accepts message coin - final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + final messageCoinInfo = + await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: makerExchangeType, ); await exchangeOfferService.acceptMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoinInfo!.messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -546,23 +573,24 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentMessageCoinChild = - await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); + final spentMessageCoinChild = await fullNodeSimulator + .getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); expect(spentMessageCoinChild, isNotNull); - final expectedMessageCoinAcceptedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); + final expectedMessageCoinAcceptedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); // restoring exchange offer record - final initializationCoins = - await fullNodeSimulator.scroungeForExchangeInitializationCoins(maker.puzzlehashes); + final initializationCoins = await fullNodeSimulator + .scroungeForExchangeInitializationCoins(maker.puzzlehashes); expect(initializationCoins.length, equals(1)); expect(initializationCoins.contains(initializationCoin), isTrue); final hydratedExchangeOfferRecord = - await exchangeOfferRecordHydrationService.hydrateExchangeInitializationCoin( + await exchangeOfferRecordHydrationService + .hydrateExchangeInitializationCoin( initializationCoins.single, makerMasterPrivateKey, maker.keychain, @@ -571,7 +599,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -617,7 +645,10 @@ Future main() async { hydratedExchangeOfferRecord.initializedTime, equals(initializedTime), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(messageCoinInfo.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(messageCoinInfo.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(messageCoinInfo.messageCoinReceivedTime), @@ -630,7 +661,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(exchangeValidityTime), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(takerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(takerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehash), @@ -646,7 +680,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -658,15 +692,16 @@ Future main() async { await taker.refreshCoins(); // maker declines message coin - final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + final messageCoinInfo = + await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: makerExchangeType, ); await exchangeOfferService.declineMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoinInfo!.messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -677,14 +712,15 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); // restoring exchange offer record - final initializationCoins = - await fullNodeSimulator.scroungeForExchangeInitializationCoins(maker.puzzlehashes); + final initializationCoins = await fullNodeSimulator + .scroungeForExchangeInitializationCoins(maker.puzzlehashes); expect(initializationCoins.length, equals(1)); expect(initializationCoins.contains(initializationCoin), isTrue); final hydratedExchangeOfferRecord = - await exchangeOfferRecordHydrationService.hydrateExchangeInitializationCoin( + await exchangeOfferRecordHydrationService + .hydrateExchangeInitializationCoin( initializationCoins.single, makerMasterPrivateKey, maker.keychain, @@ -693,7 +729,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -773,7 +809,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -785,15 +821,16 @@ Future main() async { await taker.refreshCoins(); // maker accepts message coin - final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + final messageCoinInfo = + await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: makerExchangeType, ); await exchangeOfferService.acceptMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoinInfo!.messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -803,13 +840,13 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentMessageCoinChild = - await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); + final spentMessageCoinChild = await fullNodeSimulator + .getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); expect(spentMessageCoinChild, isNotNull); - final expectedMessageCoinAcceptedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); + final expectedMessageCoinAcceptedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); // maker transfers funds to escrow puzzlehash final makerEscrowPuzzlehash = XchToBtcService.generateEscrowPuzzlehash( @@ -820,7 +857,7 @@ Future main() async { ); await exchangeOfferService.transferFundsToEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, mojos: mojos, escrowPuzzlehash: makerEscrowPuzzlehash, requestorPrivateKey: makerPrivateKey, @@ -832,26 +869,30 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await maker.refreshCoins(); - final escrowCoin = - (await fullNodeSimulator.getCoinsByPuzzleHashes([makerEscrowPuzzlehash])).single; - final escrowCoinParent = await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); + final escrowCoin = (await fullNodeSimulator + .getCoinsByPuzzleHashes([makerEscrowPuzzlehash])) + .single; + final escrowCoinParent = + await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); - final escrowTransferCompletedBlockIndex = escrowCoinParent!.spentBlockIndex; - final expectedEscrowTransferCompletedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); + final escrowTransferCompletedBlockIndex = + escrowCoinParent!.spentBlockIndex; + final expectedEscrowTransferCompletedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); final expectedEscrowTransferConfirmedBlockIndex = escrowTransferCompletedBlockIndex + blocksForSufficientConfirmation; // restoring exchange offer record - final initializationCoins = - await fullNodeSimulator.scroungeForExchangeInitializationCoins(maker.puzzlehashes); + final initializationCoins = await fullNodeSimulator + .scroungeForExchangeInitializationCoins(maker.puzzlehashes); expect(initializationCoins.length, equals(1)); expect(initializationCoins.contains(initializationCoin), isTrue); final hydratedExchangeOfferRecord = - await exchangeOfferRecordHydrationService.hydrateExchangeInitializationCoin( + await exchangeOfferRecordHydrationService + .hydrateExchangeInitializationCoin( initializationCoins.single, makerMasterPrivateKey, maker.keychain, @@ -860,7 +901,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -906,7 +947,10 @@ Future main() async { hydratedExchangeOfferRecord.initializedTime, equals(initializedTime), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(messageCoinInfo.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(messageCoinInfo.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(messageCoinInfo.messageCoinReceivedTime), @@ -919,7 +963,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(exchangeValidityTime), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(takerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(takerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehash), @@ -945,7 +992,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -957,15 +1004,16 @@ Future main() async { await taker.refreshCoins(); // maker accepts message coin - final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + final messageCoinInfo = + await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: makerExchangeType, ); await exchangeOfferService.acceptMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoinInfo!.messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -975,13 +1023,13 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentMessageCoinChild = - await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); + final spentMessageCoinChild = await fullNodeSimulator + .getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); expect(spentMessageCoinChild, isNotNull); - final expectedMessageCoinAcceptedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); + final expectedMessageCoinAcceptedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); // maker transfers funds to escrow puzzlehash final makerEscrowPuzzlehash = XchToBtcService.generateEscrowPuzzlehash( @@ -992,7 +1040,7 @@ Future main() async { ); await exchangeOfferService.transferFundsToEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, mojos: mojos, escrowPuzzlehash: makerEscrowPuzzlehash, requestorPrivateKey: makerPrivateKey, @@ -1004,30 +1052,37 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await maker.refreshCoins(); - final escrowCoin = - (await fullNodeSimulator.getCoinsByPuzzleHashes([makerEscrowPuzzlehash])).single; - final escrowCoinParent = await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); + final escrowCoin = (await fullNodeSimulator + .getCoinsByPuzzleHashes([makerEscrowPuzzlehash])) + .single; + final escrowCoinParent = + await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); - final escrowTransferCompletedBlockIndex = escrowCoinParent!.spentBlockIndex; - final expectedEscrowTransferCompletedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); + final escrowTransferCompletedBlockIndex = + escrowCoinParent!.spentBlockIndex; + final expectedEscrowTransferCompletedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); final expectedEscrowTransferConfirmedBlockIndex = escrowTransferCompletedBlockIndex + blocksForSufficientConfirmation; // wait for sufficient confirmations - await fullNodeSimulator.moveToNextBlock(blocks: blocksForSufficientConfirmation); - final expectedEscrowTransferConfirmedTime = await fullNodeSimulator.getCurrentBlockDateTime(); + await fullNodeSimulator.moveToNextBlock( + blocks: blocksForSufficientConfirmation, + ); + final expectedEscrowTransferConfirmedTime = + await fullNodeSimulator.getCurrentBlockDateTime(); // restoring exchange offer record - final initializationCoins = - await fullNodeSimulator.scroungeForExchangeInitializationCoins(maker.puzzlehashes); + final initializationCoins = await fullNodeSimulator + .scroungeForExchangeInitializationCoins(maker.puzzlehashes); expect(initializationCoins.length, equals(1)); expect(initializationCoins.contains(initializationCoin), isTrue); final hydratedExchangeOfferRecord = - await exchangeOfferRecordHydrationService.hydrateExchangeInitializationCoin( + await exchangeOfferRecordHydrationService + .hydrateExchangeInitializationCoin( initializationCoins.single, makerMasterPrivateKey, maker.keychain, @@ -1036,7 +1091,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -1082,7 +1137,10 @@ Future main() async { hydratedExchangeOfferRecord.initializedTime, equals(initializedTime), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(messageCoinInfo.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(messageCoinInfo.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(messageCoinInfo.messageCoinReceivedTime), @@ -1095,7 +1153,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(exchangeValidityTime), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(takerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(takerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehash), @@ -1124,7 +1185,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -1136,15 +1197,16 @@ Future main() async { await taker.refreshCoins(); // maker accepts message coin - final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + final messageCoinInfo = + await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: makerExchangeType, ); await exchangeOfferService.acceptMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoinInfo!.messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -1154,12 +1216,12 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentMessageCoinChild = - await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); + final spentMessageCoinChild = await fullNodeSimulator + .getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); expect(spentMessageCoinChild, isNotNull); - final expectedMessageCoinAcceptedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); + final expectedMessageCoinAcceptedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); // maker transfers funds to escrow puzzlehash final makerEscrowPuzzlehash = XchToBtcService.generateEscrowPuzzlehash( @@ -1170,7 +1232,7 @@ Future main() async { ); await exchangeOfferService.transferFundsToEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, mojos: mojos, escrowPuzzlehash: makerEscrowPuzzlehash, requestorPrivateKey: makerPrivateKey, @@ -1182,24 +1244,30 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await maker.refreshCoins(); - final escrowCoin = - (await fullNodeSimulator.getCoinsByPuzzleHashes([makerEscrowPuzzlehash])).single; - final escrowCoinParent = await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); + final escrowCoin = (await fullNodeSimulator + .getCoinsByPuzzleHashes([makerEscrowPuzzlehash])) + .single; + final escrowCoinParent = + await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); - final escrowTransferCompletedBlockIndex = escrowCoinParent!.spentBlockIndex; - final expectedEscrowTransferCompletedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); + final escrowTransferCompletedBlockIndex = + escrowCoinParent!.spentBlockIndex; + final expectedEscrowTransferCompletedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); final expectedEscrowTransferConfirmedBlockIndex = escrowTransferCompletedBlockIndex + blocksForSufficientConfirmation; // wait for sufficient confirmations - await fullNodeSimulator.moveToNextBlock(blocks: blocksForSufficientConfirmation); - final expectedEscrowTransferConfirmedTime = await fullNodeSimulator.getCurrentBlockDateTime(); + await fullNodeSimulator.moveToNextBlock( + blocks: blocksForSufficientConfirmation, + ); + final expectedEscrowTransferConfirmedTime = + await fullNodeSimulator.getCurrentBlockDateTime(); // taker sweeps escrow puzzlehash await exchangeOfferService.sweepEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, escrowPuzzlehash: escrowPuzzlehash, requestorPuzzlehash: taker.firstPuzzlehash, requestorPrivateKey: takerPrivateKey, @@ -1211,19 +1279,21 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentEscrowCoin = await fullNodeSimulator.getCoinById(escrowCoin.id); - final expectedSweepTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentEscrowCoin!.spentBlockIndex); + final spentEscrowCoin = + await fullNodeSimulator.getCoinById(escrowCoin.id); + final expectedSweepTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentEscrowCoin!.spentBlockIndex); // restoring exchange offer record - final initializationCoins = - await fullNodeSimulator.scroungeForExchangeInitializationCoins(maker.puzzlehashes); + final initializationCoins = await fullNodeSimulator + .scroungeForExchangeInitializationCoins(maker.puzzlehashes); expect(initializationCoins.length, equals(1)); expect(initializationCoins.contains(initializationCoin), isTrue); final hydratedExchangeOfferRecord = - await exchangeOfferRecordHydrationService.hydrateExchangeInitializationCoin( + await exchangeOfferRecordHydrationService + .hydrateExchangeInitializationCoin( initializationCoins.single, makerMasterPrivateKey, maker.keychain, @@ -1232,7 +1302,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -1278,7 +1348,10 @@ Future main() async { hydratedExchangeOfferRecord.initializedTime, equals(initializedTime), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(messageCoinInfo.messageCoin.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(messageCoinInfo.messageCoin.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(messageCoinInfo.messageCoinReceivedTime), @@ -1291,7 +1364,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(exchangeValidityTime), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(takerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(takerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehash), @@ -1322,20 +1398,23 @@ Future main() async { // shorten delay for testing purposes const shortenedValidity = 5; - final takerOfferFileWithShortenedValidity = crossChainOfferService.createBtcToXchAcceptFile( - serializedOfferFile: serializedOfferFile, + final takerOfferFileWithShortenedValidity = + crossChainOfferFileService.createBtcToXchTakerOfferFile( + initializationCoinId: initializationCoinId, + serializedMakerOfferFile: serializedOfferFile, validityTime: shortenedValidity, requestorPublicKey: takerPublicKey, ); final serializedTakerOfferFileWithShortenedValidity = - await takerOfferFileWithShortenedValidity.serializeAsync(takerPrivateKey); + await takerOfferFileWithShortenedValidity + .serializeAsync(takerPrivateKey); // taker sends message coin final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -1347,15 +1426,16 @@ Future main() async { await taker.refreshCoins(); // maker accepts message coin - final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + final messageCoinInfo = + await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: makerExchangeType, ); await exchangeOfferService.acceptMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoinInfo!.messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -1365,12 +1445,12 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentMessageCoinChild = - await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); + final spentMessageCoinChild = await fullNodeSimulator + .getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); expect(spentMessageCoinChild, isNotNull); - final expectedMessageCoinAcceptedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); + final expectedMessageCoinAcceptedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); // maker transfers funds to escrow puzzlehash final makerEscrowPuzzlehash = XchToBtcService.generateEscrowPuzzlehash( @@ -1381,7 +1461,7 @@ Future main() async { ); await exchangeOfferService.transferFundsToEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, mojos: mojos, escrowPuzzlehash: makerEscrowPuzzlehash, requestorPrivateKey: makerPrivateKey, @@ -1393,26 +1473,38 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await maker.refreshCoins(); - final escrowCoin = - (await fullNodeSimulator.getCoinsByPuzzleHashes([makerEscrowPuzzlehash])).single; - final escrowCoinParent = await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); + final escrowCoin = (await fullNodeSimulator + .getCoinsByPuzzleHashes([makerEscrowPuzzlehash])) + .single; + final escrowCoinParent = + await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); - final escrowTransferCompletedBlockIndex = escrowCoinParent!.spentBlockIndex; - final expectedEscrowTransferCompletedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); + final escrowTransferCompletedBlockIndex = + escrowCoinParent!.spentBlockIndex; + final expectedEscrowTransferCompletedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); final expectedEscrowTransferConfirmedBlockIndex = escrowTransferCompletedBlockIndex + blocksForSufficientConfirmation; // wait for sufficient confirmations - await fullNodeSimulator.moveToNextBlock(blocks: blocksForSufficientConfirmation); - final expectedEscrowTransferConfirmedTime = await fullNodeSimulator.getCurrentBlockDateTime(); + await fullNodeSimulator.moveToNextBlock( + blocks: blocksForSufficientConfirmation, + ); + final expectedEscrowTransferConfirmedTime = + await fullNodeSimulator.getCurrentBlockDateTime(); + + // the earliest you can spend a time-locked coin is 2 blocks later, since the time is checked + // against the timestamp of the previous block + for (var i = 0; i < 2; i++) { + await fullNodeSimulator.moveToNextBlock(); + } // wait until clawback delay period has passed await Future.delayed(const Duration(seconds: 10), () async { // maker claws back funds at escrow puzzlehash await exchangeOfferService.clawbackEscrowFunds( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, escrowPuzzlehash: makerEscrowPuzzlehash, requestorPuzzlehash: maker.firstPuzzlehash, requestorPrivateKey: makerPrivateKey, @@ -1423,19 +1515,21 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentEscrowCoin = await fullNodeSimulator.getCoinById(escrowCoin.id); - final expectedClawbackTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentEscrowCoin!.spentBlockIndex); + final spentEscrowCoin = + await fullNodeSimulator.getCoinById(escrowCoin.id); + final expectedClawbackTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentEscrowCoin!.spentBlockIndex); // restoring exchange offer record - final initializationCoins = - await fullNodeSimulator.scroungeForExchangeInitializationCoins(maker.puzzlehashes); + final initializationCoins = await fullNodeSimulator + .scroungeForExchangeInitializationCoins(maker.puzzlehashes); expect(initializationCoins.length, equals(1)); expect(initializationCoins.contains(initializationCoin), isTrue); final hydratedExchangeOfferRecord = - await exchangeOfferRecordHydrationService.hydrateExchangeInitializationCoin( + await exchangeOfferRecordHydrationService + .hydrateExchangeInitializationCoin( initializationCoins.single, makerMasterPrivateKey, maker.keychain, @@ -1444,7 +1538,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -1486,7 +1580,10 @@ Future main() async { hydratedExchangeOfferRecord.lightningPaymentRequest!.paymentRequest, equals(paymentRequest), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(messageCoinInfo.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(messageCoinInfo.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(messageCoinInfo.messageCoinReceivedTime), @@ -1499,7 +1596,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(shortenedValidity), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(takerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(takerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(makerEscrowPuzzlehash), @@ -1522,7 +1622,10 @@ Future main() async { expectedEscrowTransferConfirmedTime, ); expect(hydratedExchangeOfferRecord.sweepTime, isNull); - expect(hydratedExchangeOfferRecord.clawbackTime, equals(expectedClawbackTime)); + expect( + hydratedExchangeOfferRecord.clawbackTime, + equals(expectedClawbackTime), + ); expect(hydratedExchangeOfferRecord.canceledTime, isNull); }); }); @@ -1536,7 +1639,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -1547,16 +1650,16 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final expectedMessageCoin = - (await fullNodeSimulator.scroungeForReceivedNotificationCoins([messagePuzzlehash])) - .single; + final expectedMessageCoin = (await fullNodeSimulator + .scroungeForReceivedNotificationCoins([messagePuzzlehash])) + .single; - final expectedMessageCoinReceivedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); + final expectedMessageCoinReceivedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); // restoring exchange offer record - final sentMessageCoins = - await fullNodeSimulator.scroungeForSentNotificationCoins(taker.puzzlehashes); + final sentMessageCoins = await fullNodeSimulator + .scroungeForSentNotificationCoins(taker.puzzlehashes); expect(sentMessageCoins.length, equals(1)); @@ -1569,7 +1672,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -1611,7 +1714,10 @@ Future main() async { hydratedExchangeOfferRecord.lightningPaymentRequest!.paymentRequest, equals(paymentRequest), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(expectedMessageCoin.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(expectedMessageCoin.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(expectedMessageCoinReceivedTime), @@ -1624,7 +1730,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(exchangeValidityTime), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(makerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(makerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehash), @@ -1647,7 +1756,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -1658,16 +1767,16 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final expectedMessageCoin = - (await fullNodeSimulator.scroungeForReceivedNotificationCoins([messagePuzzlehash])) - .single; + final expectedMessageCoin = (await fullNodeSimulator + .scroungeForReceivedNotificationCoins([messagePuzzlehash])) + .single; - final expectedMessageCoinReceivedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); + final expectedMessageCoinReceivedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); // restoring exchange offer record - final sentMessageCoins = - await fullNodeSimulator.scroungeForSentNotificationCoins(taker.puzzlehashes); + final sentMessageCoins = await fullNodeSimulator + .scroungeForSentNotificationCoins(taker.puzzlehashes); expect(sentMessageCoins.length, equals(1)); @@ -1680,7 +1789,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -1723,7 +1832,10 @@ Future main() async { hydratedExchangeOfferRecord.lightningPaymentRequest!.paymentRequest, equals(paymentRequest), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(expectedMessageCoin.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(expectedMessageCoin.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(expectedMessageCoinReceivedTime), @@ -1736,7 +1848,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(exchangeValidityTime), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(makerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(makerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehash), @@ -1757,7 +1872,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -1768,16 +1883,16 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final expectedMessageCoin = - (await fullNodeSimulator.scroungeForReceivedNotificationCoins([messagePuzzlehash])) - .single; + final expectedMessageCoin = (await fullNodeSimulator + .scroungeForReceivedNotificationCoins([messagePuzzlehash])) + .single; - final expectedMessageCoinReceivedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); + final expectedMessageCoinReceivedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); // maker cancels offer await exchangeOfferService.cancelExchangeOffer( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -1786,15 +1901,17 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final cancelCoin = - await exchangeOfferService.getCancelCoin(initializationCoin, messagePuzzlehash); + final cancelCoin = await exchangeOfferService.getCancelCoin( + initializationCoin, + messagePuzzlehash, + ); - final expectedCanceledTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(cancelCoin.spentBlockIndex); + final expectedCanceledTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(cancelCoin.spentBlockIndex); // restoring exchange offer record - final sentMessageCoins = - await fullNodeSimulator.scroungeForSentNotificationCoins(taker.puzzlehashes); + final sentMessageCoins = await fullNodeSimulator + .scroungeForSentNotificationCoins(taker.puzzlehashes); expect(sentMessageCoins.length, equals(1)); @@ -1807,7 +1924,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -1849,7 +1966,10 @@ Future main() async { hydratedExchangeOfferRecord.lightningPaymentRequest!.paymentRequest, equals(paymentRequest), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(expectedMessageCoin.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(expectedMessageCoin.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(expectedMessageCoinReceivedTime), @@ -1862,7 +1982,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(exchangeValidityTime), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(makerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(makerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehash), @@ -1873,7 +1996,10 @@ Future main() async { expect(hydratedExchangeOfferRecord.escrowCoinId, isNull); expect(hydratedExchangeOfferRecord.sweepTime, isNull); expect(hydratedExchangeOfferRecord.clawbackTime, isNull); - expect(hydratedExchangeOfferRecord.canceledTime, equals(expectedCanceledTime)); + expect( + hydratedExchangeOfferRecord.canceledTime, + equals(expectedCanceledTime), + ); }); test('after maker accepts message coin', () async { @@ -1881,7 +2007,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -1892,23 +2018,24 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final expectedMessageCoin = - (await fullNodeSimulator.scroungeForReceivedNotificationCoins([messagePuzzlehash])) - .single; + final expectedMessageCoin = (await fullNodeSimulator + .scroungeForReceivedNotificationCoins([messagePuzzlehash])) + .single; - final expectedMessageCoinReceivedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); + final expectedMessageCoinReceivedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); // maker accepts message coin - final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + final messageCoinInfo = + await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: makerExchangeType, ); await exchangeOfferService.acceptMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoinInfo!.messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -1918,17 +2045,17 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentMessageCoinChild = - await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); + final spentMessageCoinChild = await fullNodeSimulator + .getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); expect(spentMessageCoinChild, isNotNull); - final expectedMessageCoinAcceptedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); + final expectedMessageCoinAcceptedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); // restoring exchange offer record - final sentMessageCoins = - await fullNodeSimulator.scroungeForSentNotificationCoins(taker.puzzlehashes); + final sentMessageCoins = await fullNodeSimulator + .scroungeForSentNotificationCoins(taker.puzzlehashes); expect(sentMessageCoins.length, equals(1)); @@ -1941,7 +2068,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -1983,7 +2110,10 @@ Future main() async { hydratedExchangeOfferRecord.lightningPaymentRequest!.paymentRequest, equals(paymentRequest), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(expectedMessageCoin.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(expectedMessageCoin.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(expectedMessageCoinReceivedTime), @@ -1996,7 +2126,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(exchangeValidityTime), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(makerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(makerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehash), @@ -2018,7 +2151,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -2029,23 +2162,24 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final expectedMessageCoin = - (await fullNodeSimulator.scroungeForReceivedNotificationCoins([messagePuzzlehash])) - .single; + final expectedMessageCoin = (await fullNodeSimulator + .scroungeForReceivedNotificationCoins([messagePuzzlehash])) + .single; - final expectedMessageCoinReceivedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); + final expectedMessageCoinReceivedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); // maker declines message coin - final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + final messageCoinInfo = + await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: makerExchangeType, ); await exchangeOfferService.declineMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoinInfo!.messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -2055,17 +2189,17 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentMessageCoinChild = - await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); + final spentMessageCoinChild = await fullNodeSimulator + .getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); expect(spentMessageCoinChild, isNotNull); - final expectedMessageCoinDeclinedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); + final expectedMessageCoinDeclinedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); // restoring exchange offer record - final sentMessageCoins = - await fullNodeSimulator.scroungeForSentNotificationCoins(taker.puzzlehashes); + final sentMessageCoins = await fullNodeSimulator + .scroungeForSentNotificationCoins(taker.puzzlehashes); expect(sentMessageCoins.length, equals(1)); @@ -2078,7 +2212,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -2120,7 +2254,10 @@ Future main() async { hydratedExchangeOfferRecord.lightningPaymentRequest!.paymentRequest, equals(paymentRequest), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(expectedMessageCoin.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(expectedMessageCoin.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(expectedMessageCoinReceivedTime), @@ -2133,7 +2270,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(exchangeValidityTime), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(makerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(makerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehash), @@ -2155,7 +2295,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -2166,23 +2306,24 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final expectedMessageCoin = - (await fullNodeSimulator.scroungeForReceivedNotificationCoins([messagePuzzlehash])) - .single; + final expectedMessageCoin = (await fullNodeSimulator + .scroungeForReceivedNotificationCoins([messagePuzzlehash])) + .single; - final expectedMessageCoinReceivedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); + final expectedMessageCoinReceivedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); // maker accepts message coin - final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + final messageCoinInfo = + await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: makerExchangeType, ); await exchangeOfferService.acceptMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoinInfo!.messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -2192,12 +2333,12 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentMessageCoinChild = - await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); + final spentMessageCoinChild = await fullNodeSimulator + .getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); expect(spentMessageCoinChild, isNotNull); - final expectedMessageCoinAcceptedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); + final expectedMessageCoinAcceptedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); // maker transfers funds to escrow puzzlehash final makerEscrowPuzzlehash = XchToBtcService.generateEscrowPuzzlehash( @@ -2208,7 +2349,7 @@ Future main() async { ); await exchangeOfferService.transferFundsToEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, mojos: mojos, escrowPuzzlehash: makerEscrowPuzzlehash, requestorPrivateKey: makerPrivateKey, @@ -2220,20 +2361,23 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await maker.refreshCoins(); - final escrowCoin = - (await fullNodeSimulator.getCoinsByPuzzleHashes([makerEscrowPuzzlehash])).single; - final escrowCoinParent = await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); + final escrowCoin = (await fullNodeSimulator + .getCoinsByPuzzleHashes([makerEscrowPuzzlehash])) + .single; + final escrowCoinParent = + await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); - final escrowTransferCompletedBlockIndex = escrowCoinParent!.spentBlockIndex; - final expectedEscrowTransferCompletedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); + final escrowTransferCompletedBlockIndex = + escrowCoinParent!.spentBlockIndex; + final expectedEscrowTransferCompletedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); final expectedEscrowTransferConfirmedBlockIndex = escrowTransferCompletedBlockIndex + blocksForSufficientConfirmation; // restoring exchange offer record - final sentMessageCoins = - await fullNodeSimulator.scroungeForSentNotificationCoins(taker.puzzlehashes); + final sentMessageCoins = await fullNodeSimulator + .scroungeForSentNotificationCoins(taker.puzzlehashes); expect(sentMessageCoins.length, equals(1)); @@ -2246,7 +2390,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -2288,7 +2432,10 @@ Future main() async { hydratedExchangeOfferRecord.lightningPaymentRequest!.paymentRequest, equals(paymentRequest), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(expectedMessageCoin.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(expectedMessageCoin.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(expectedMessageCoinReceivedTime), @@ -2301,7 +2448,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(exchangeValidityTime), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(makerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(makerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehash), @@ -2331,7 +2481,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -2342,23 +2492,24 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final expectedMessageCoin = - (await fullNodeSimulator.scroungeForReceivedNotificationCoins([messagePuzzlehash])) - .single; + final expectedMessageCoin = (await fullNodeSimulator + .scroungeForReceivedNotificationCoins([messagePuzzlehash])) + .single; - final expectedMessageCoinReceivedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); + final expectedMessageCoinReceivedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); // maker accepts message coin - final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + final messageCoinInfo = + await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: makerExchangeType, ); await exchangeOfferService.acceptMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoinInfo!.messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -2368,12 +2519,12 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentMessageCoinChild = - await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); + final spentMessageCoinChild = await fullNodeSimulator + .getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); expect(spentMessageCoinChild, isNotNull); - final expectedMessageCoinAcceptedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); + final expectedMessageCoinAcceptedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); // maker transfers funds to escrow puzzlehash final makerEscrowPuzzlehash = XchToBtcService.generateEscrowPuzzlehash( @@ -2384,7 +2535,7 @@ Future main() async { ); await exchangeOfferService.transferFundsToEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, mojos: mojos, escrowPuzzlehash: makerEscrowPuzzlehash, requestorPrivateKey: makerPrivateKey, @@ -2396,24 +2547,30 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await maker.refreshCoins(); - final escrowCoin = - (await fullNodeSimulator.getCoinsByPuzzleHashes([makerEscrowPuzzlehash])).single; - final escrowCoinParent = await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); + final escrowCoin = (await fullNodeSimulator + .getCoinsByPuzzleHashes([makerEscrowPuzzlehash])) + .single; + final escrowCoinParent = + await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); - final escrowTransferCompletedBlockIndex = escrowCoinParent!.spentBlockIndex; - final expectedEscrowTransferCompletedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); + final escrowTransferCompletedBlockIndex = + escrowCoinParent!.spentBlockIndex; + final expectedEscrowTransferCompletedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); final expectedEscrowTransferConfirmedBlockIndex = escrowTransferCompletedBlockIndex + blocksForSufficientConfirmation; // wait for sufficient confirmations - await fullNodeSimulator.moveToNextBlock(blocks: blocksForSufficientConfirmation); - final expectedEscrowTransferConfirmedTime = await fullNodeSimulator.getCurrentBlockDateTime(); + await fullNodeSimulator.moveToNextBlock( + blocks: blocksForSufficientConfirmation, + ); + final expectedEscrowTransferConfirmedTime = + await fullNodeSimulator.getCurrentBlockDateTime(); // restoring exchange offer record - final sentMessageCoins = - await fullNodeSimulator.scroungeForSentNotificationCoins(taker.puzzlehashes); + final sentMessageCoins = await fullNodeSimulator + .scroungeForSentNotificationCoins(taker.puzzlehashes); expect(sentMessageCoins.length, equals(1)); @@ -2426,7 +2583,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -2468,7 +2625,10 @@ Future main() async { hydratedExchangeOfferRecord.lightningPaymentRequest!.paymentRequest, equals(paymentRequest), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(expectedMessageCoin.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(expectedMessageCoin.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(expectedMessageCoinReceivedTime), @@ -2481,7 +2641,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(exchangeValidityTime), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(makerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(makerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehash), @@ -2514,7 +2677,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -2525,23 +2688,24 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final expectedMessageCoin = - (await fullNodeSimulator.scroungeForReceivedNotificationCoins([messagePuzzlehash])) - .single; + final expectedMessageCoin = (await fullNodeSimulator + .scroungeForReceivedNotificationCoins([messagePuzzlehash])) + .single; - final expectedMessageCoinReceivedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); + final expectedMessageCoinReceivedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); // maker accepts message coin - final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + final messageCoinInfo = + await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: makerExchangeType, ); await exchangeOfferService.acceptMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoinInfo!.messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -2550,13 +2714,13 @@ Future main() async { ); await fullNodeSimulator.moveToNextBlock(); - final spentMessageCoinChild = - await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); + final spentMessageCoinChild = await fullNodeSimulator + .getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); expect(spentMessageCoinChild, isNotNull); - final expectedMessageCoinAcceptedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); + final expectedMessageCoinAcceptedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); // maker transfers funds to escrow puzzlehash final makerEscrowPuzzlehash = XchToBtcService.generateEscrowPuzzlehash( @@ -2567,7 +2731,7 @@ Future main() async { ); await exchangeOfferService.transferFundsToEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, mojos: mojos, escrowPuzzlehash: makerEscrowPuzzlehash, requestorPrivateKey: makerPrivateKey, @@ -2579,24 +2743,30 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await maker.refreshCoins(); - final escrowCoin = - (await fullNodeSimulator.getCoinsByPuzzleHashes([makerEscrowPuzzlehash])).single; - final escrowCoinParent = await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); + final escrowCoin = (await fullNodeSimulator + .getCoinsByPuzzleHashes([makerEscrowPuzzlehash])) + .single; + final escrowCoinParent = + await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); - final escrowTransferCompletedBlockIndex = escrowCoinParent!.spentBlockIndex; - final expectedEscrowTransferCompletedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); + final escrowTransferCompletedBlockIndex = + escrowCoinParent!.spentBlockIndex; + final expectedEscrowTransferCompletedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); final expectedEscrowTransferConfirmedBlockIndex = escrowTransferCompletedBlockIndex + blocksForSufficientConfirmation; // wait for sufficient confirmations - await fullNodeSimulator.moveToNextBlock(blocks: blocksForSufficientConfirmation); - final expectedEscrowTransferConfirmedTime = await fullNodeSimulator.getCurrentBlockDateTime(); + await fullNodeSimulator.moveToNextBlock( + blocks: blocksForSufficientConfirmation, + ); + final expectedEscrowTransferConfirmedTime = + await fullNodeSimulator.getCurrentBlockDateTime(); // taker sweeps escrow puzzlehash await exchangeOfferService.sweepEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, escrowPuzzlehash: escrowPuzzlehash, requestorPuzzlehash: taker.firstPuzzlehash, requestorPrivateKey: takerPrivateKey, @@ -2608,13 +2778,14 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentEscrowCoin = await fullNodeSimulator.getCoinById(escrowCoin.id); - final expectedSweepTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentEscrowCoin!.spentBlockIndex); + final spentEscrowCoin = + await fullNodeSimulator.getCoinById(escrowCoin.id); + final expectedSweepTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentEscrowCoin!.spentBlockIndex); // restoring exchange offer record - final sentMessageCoins = - await fullNodeSimulator.scroungeForSentNotificationCoins(taker.puzzlehashes); + final sentMessageCoins = await fullNodeSimulator + .scroungeForSentNotificationCoins(taker.puzzlehashes); expect(sentMessageCoins.length, equals(1)); @@ -2627,7 +2798,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -2669,7 +2840,10 @@ Future main() async { hydratedExchangeOfferRecord.lightningPaymentRequest!.paymentRequest, equals(paymentRequest), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(expectedMessageCoin.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(expectedMessageCoin.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(expectedMessageCoinReceivedTime), @@ -2682,7 +2856,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(exchangeValidityTime), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(makerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(makerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehash), @@ -2714,20 +2891,23 @@ Future main() async { // shorten delay for testing purposes const shortenedValidity = 5; - final takerOfferFileWithShortenedValidity = crossChainOfferService.createBtcToXchAcceptFile( - serializedOfferFile: serializedOfferFile, + final takerOfferFileWithShortenedValidity = + crossChainOfferFileService.createBtcToXchTakerOfferFile( + initializationCoinId: initializationCoinId, + serializedMakerOfferFile: serializedOfferFile, validityTime: shortenedValidity, requestorPublicKey: takerPublicKey, ); final serializedTakerOfferFileWithShortenedValidity = - await takerOfferFileWithShortenedValidity.serializeAsync(takerPrivateKey); + await takerOfferFileWithShortenedValidity + .serializeAsync(takerPrivateKey); // taker sends message coin final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -2738,23 +2918,24 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final expectedMessageCoin = - (await fullNodeSimulator.scroungeForReceivedNotificationCoins([messagePuzzlehash])) - .single; + final expectedMessageCoin = (await fullNodeSimulator + .scroungeForReceivedNotificationCoins([messagePuzzlehash])) + .single; - final expectedMessageCoinReceivedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); + final expectedMessageCoinReceivedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(expectedMessageCoin.spentBlockIndex); // maker accepts message coin - final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + final messageCoinInfo = + await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: makerExchangeType, ); await exchangeOfferService.acceptMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoinInfo!.messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -2764,16 +2945,17 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentMessageCoinChild = - await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); + final spentMessageCoinChild = await fullNodeSimulator + .getSingleChildCoinFromCoin(messageCoinInfo.messageCoin); expect(spentMessageCoinChild, isNotNull); - final expectedMessageCoinAcceptedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); + final expectedMessageCoinAcceptedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentMessageCoinChild!.spentBlockIndex); // maker transfers funds to escrow puzzlehash - final escrowPuzzlehashWithShortenedValidity = XchToBtcService.generateEscrowPuzzlehash( + final escrowPuzzlehashWithShortenedValidity = + XchToBtcService.generateEscrowPuzzlehash( requestorPrivateKey: makerPrivateKey, clawbackDelaySeconds: shortenedValidity, sweepPaymentHash: paymentHash, @@ -2781,7 +2963,7 @@ Future main() async { ); await exchangeOfferService.transferFundsToEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, mojos: mojos, escrowPuzzlehash: escrowPuzzlehashWithShortenedValidity, requestorPrivateKey: makerPrivateKey, @@ -2793,26 +2975,37 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await maker.refreshCoins(); - final escrowCoin = - (await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehashWithShortenedValidity])) - .single; - final escrowCoinParent = await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); + final escrowCoin = (await fullNodeSimulator + .getCoinsByPuzzleHashes([escrowPuzzlehashWithShortenedValidity])) + .single; + final escrowCoinParent = + await fullNodeSimulator.getCoinById(escrowCoin.parentCoinInfo); - final escrowTransferCompletedBlockIndex = escrowCoinParent!.spentBlockIndex; - final expectedEscrowTransferCompletedTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); + final escrowTransferCompletedBlockIndex = + escrowCoinParent!.spentBlockIndex; + final expectedEscrowTransferCompletedTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); final expectedEscrowTransferConfirmedBlockIndex = escrowTransferCompletedBlockIndex + blocksForSufficientConfirmation; // wait for sufficient confirmations - await fullNodeSimulator.moveToNextBlock(blocks: blocksForSufficientConfirmation); - final expectedEscrowTransferConfirmedTime = await fullNodeSimulator.getCurrentBlockDateTime(); + await fullNodeSimulator.moveToNextBlock( + blocks: blocksForSufficientConfirmation, + ); + final expectedEscrowTransferConfirmedTime = + await fullNodeSimulator.getCurrentBlockDateTime(); + + // the earliest you can spend a time-locked coin is 2 blocks later, since the time is checked + // against the timestamp of the previous block + for (var i = 0; i < 2; i++) { + await fullNodeSimulator.moveToNextBlock(); + } await Future.delayed(const Duration(seconds: 10), () async { // maker claws back funds at escrow puzzlehash await exchangeOfferService.clawbackEscrowFunds( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, escrowPuzzlehash: escrowPuzzlehashWithShortenedValidity, requestorPuzzlehash: maker.firstPuzzlehash, requestorPrivateKey: makerPrivateKey, @@ -2823,13 +3016,14 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); - final spentEscrowCoin = await fullNodeSimulator.getCoinById(escrowCoin.id); - final expectedClawbackTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(spentEscrowCoin!.spentBlockIndex); + final spentEscrowCoin = + await fullNodeSimulator.getCoinById(escrowCoin.id); + final expectedClawbackTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(spentEscrowCoin!.spentBlockIndex); // restoring exchange offer record - final sentMessageCoins = - await fullNodeSimulator.scroungeForSentNotificationCoins(taker.puzzlehashes); + final sentMessageCoins = await fullNodeSimulator + .scroungeForSentNotificationCoins(taker.puzzlehashes); expect(sentMessageCoins.length, equals(1)); @@ -2842,7 +3036,7 @@ Future main() async { expect(hydratedExchangeOfferRecord, isNotNull); expect( hydratedExchangeOfferRecord.initializationCoinId, - equals(initializationCoin.id), + equals(initializationCoinId), ); expect( hydratedExchangeOfferRecord.derivationIndex, @@ -2884,7 +3078,10 @@ Future main() async { hydratedExchangeOfferRecord.lightningPaymentRequest!.paymentRequest, equals(paymentRequest), ); - expect(hydratedExchangeOfferRecord.messageCoinId, equals(expectedMessageCoin.id)); + expect( + hydratedExchangeOfferRecord.messageCoinId, + equals(expectedMessageCoin.id), + ); expect( hydratedExchangeOfferRecord.messageCoinReceivedTime, equals(expectedMessageCoinReceivedTime), @@ -2897,7 +3094,10 @@ Future main() async { hydratedExchangeOfferRecord.exchangeValidityTime, equals(shortenedValidity), ); - expect(hydratedExchangeOfferRecord.fulfillerPublicKey, equals(makerPublicKey)); + expect( + hydratedExchangeOfferRecord.fulfillerPublicKey, + equals(makerPublicKey), + ); expect( hydratedExchangeOfferRecord.escrowPuzzlehash, equals(escrowPuzzlehashWithShortenedValidity), @@ -2921,7 +3121,10 @@ Future main() async { ); expect(hydratedExchangeOfferRecord.escrowCoinId, equals(escrowCoin.id)); expect(hydratedExchangeOfferRecord.sweepTime, isNull); - expect(hydratedExchangeOfferRecord.clawbackTime, equals(expectedClawbackTime)); + expect( + hydratedExchangeOfferRecord.clawbackTime, + equals(expectedClawbackTime), + ); expect(hydratedExchangeOfferRecord.canceledTime, isNull); }); }); diff --git a/integration_test/exchange/btc/exchange_offer_service/exchange_offer_service_test.dart b/integration_test/exchange/btc/exchange_offer_service/exchange_offer_service_test.dart index b4ee389c..ce52b083 100644 --- a/integration_test/exchange/btc/exchange_offer_service/exchange_offer_service_test.dart +++ b/integration_test/exchange/btc/exchange_offer_service/exchange_offer_service_test.dart @@ -17,7 +17,7 @@ Future main() async { final fullNodeSimulator = SimulatorFullNodeInterface.withDefaultUrl(); ChiaNetworkContextWrapper().registerNetworkContext(Network.mainnet); - final crossChainOfferService = CrossChainOfferService(fullNodeSimulator); + final crossChainOfferFileService = CrossChainOfferFileService(); final exchangeOfferService = ExchangeOfferService(fullNodeSimulator); // constants @@ -28,7 +28,9 @@ Future main() async { 'lnbc1u1p3huyzkpp5vw6fkrw9lr3pvved40zpp4jway4g4ee6uzsaj208dxqxgm2rtkvqdqqcqzzgxqyz5vqrzjqwnvuc0u4txn35cafc7w94gxvq5p3cu9dd95f7hlrh0fvs46wpvhdrxkxglt5qydruqqqqryqqqqthqqpyrzjqw8c7yfutqqy3kz8662fxutjvef7q2ujsxtt45csu0k688lkzu3ldrxkxglt5qydruqqqqryqqqqthqqpysp5jzgpj4990chtj9f9g2f6mhvgtzajzckx774yuh0klnr3hmvrqtjq9qypqsqkrvl3sqd4q4dm9axttfa6frg7gffguq3rzuvvm2fpuqsgg90l4nz8zgc3wx7gggm04xtwq59vftm25emwp9mtvmvjg756dyzn2dm98qpakw4u8'; final decodedPaymentRequest = decodeLightningPaymentRequest(paymentRequest); final paymentHash = decodedPaymentRequest.paymentHash!; - final preimage = '5c1f10653dc3ff0531b77351dc6676de2e1f5f53c9f0a8867bcb054648f46a32'.hexToBytes(); + final preimage = + '5c1f10653dc3ff0531b77351dc6676de2e1f5f53c9f0a8867bcb054648f46a32' + .hexToBytes(); const fee = 50; late ChiaEnthusiast maker; @@ -39,7 +41,7 @@ Future main() async { late Puzzlehash messagePuzzlehash; late int offerValidityTime; late String serializedOfferFile; - late Coin initializationCoin; + late Bytes initializationCoinId; late CoinSpend initializationCoinSpend; late ChiaEnthusiast taker; @@ -58,7 +60,8 @@ Future main() async { await maker.refreshCoins(); makerMasterPrivateKey = maker.keychainSecret.masterPrivateKey; - makerDerivationIndex = ExchangeOfferService.randomDerivationIndexForExchange(); + makerDerivationIndex = + ExchangeOfferService.randomDerivationIndexForExchange(); final makerWalletVector = await WalletVector.fromPrivateKeyAsync( makerMasterPrivateKey, @@ -74,9 +77,14 @@ Future main() async { const offerValidityTimeHours = 1; final currentUnixTimestamp = DateTime.now().millisecondsSinceEpoch ~/ 1000; - offerValidityTime = currentUnixTimestamp + (offerValidityTimeHours * 60 * 60); + offerValidityTime = + currentUnixTimestamp + (offerValidityTimeHours * 60 * 60); - final offerFile = crossChainOfferService.createXchToBtcOfferFile( + final unspentInitializationCoin = maker.standardCoins.first; + initializationCoinId = unspentInitializationCoin.id; + + final offerFile = crossChainOfferFileService.createXchToBtcMakerOfferFile( + initializationCoinId: initializationCoinId, amountMojos: mojos, amountSatoshis: satoshis, messageAddress: messageAddress, @@ -88,7 +96,6 @@ Future main() async { serializedOfferFile = await offerFile.serializeAsync(makerPrivateKey); // maker pushes initialization spend bundle to create offer - final unspentInitializationCoin = maker.standardCoins.first; await exchangeOfferService.pushInitializationSpendBundle( messagePuzzlehash: messagePuzzlehash, @@ -102,9 +109,11 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await maker.refreshCoins(); - initializationCoin = (await fullNodeSimulator.getCoinById(unspentInitializationCoin.id))!; + final initializationCoin = + (await fullNodeSimulator.getCoinById(unspentInitializationCoin.id))!; - initializationCoinSpend = (await fullNodeSimulator.getCoinSpend(initializationCoin))!; + initializationCoinSpend = + (await fullNodeSimulator.getCoinSpend(initializationCoin))!; // taker side taker = ChiaEnthusiast(fullNodeSimulator, walletSize: 10); @@ -124,13 +133,16 @@ Future main() async { takerPrivateKey = takerWalletVector.childPrivateKey; takerPublicKey = takerWalletVector.childPublicKey; - final offerAcceptFile = crossChainOfferService.createBtcToXchAcceptFile( - serializedOfferFile: serializedOfferFile, + final offerAcceptFile = + crossChainOfferFileService.createBtcToXchTakerOfferFile( + initializationCoinId: initializationCoinId, + serializedMakerOfferFile: serializedOfferFile, validityTime: exchangeValidityTime, requestorPublicKey: takerPublicKey, ); - serializedOfferAcceptFile = await offerAcceptFile.serializeAsync(takerPrivateKey); + serializedOfferAcceptFile = + await offerAcceptFile.serializeAsync(takerPrivateKey); escrowPuzzlehash = BtcToXchService.generateEscrowPuzzlehash( requestorPrivateKey: takerPrivateKey, @@ -151,14 +163,15 @@ Future main() async { }); test('should find valid initialization coin', () async { - final initializationCoins = - await fullNodeSimulator.scroungeForExchangeInitializationCoins(maker.puzzlehashes); + final initializationCoins = await fullNodeSimulator + .scroungeForExchangeInitializationCoins(maker.puzzlehashes); expect(initializationCoins.length, equals(1)); - expect(initializationCoins.single.id, equals(initializationCoin.id)); + expect(initializationCoins.single.id, equals(initializationCoinId)); }); test('should find multiple valid initialization coins', () async { - final makerDerivationIndex2 = ExchangeOfferService.randomDerivationIndexForExchange(); + final makerDerivationIndex2 = + ExchangeOfferService.randomDerivationIndexForExchange(); final makerWalletVector2 = await WalletVector.fromPrivateKeyAsync( makerMasterPrivateKey, @@ -182,13 +195,14 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await maker.refreshCoins(); - final initializationCoins = - await fullNodeSimulator.scroungeForExchangeInitializationCoins(maker.puzzlehashes); + final initializationCoins = await fullNodeSimulator + .scroungeForExchangeInitializationCoins(maker.puzzlehashes); expect(initializationCoins.length, equals(2)); - final initializationCoinIds = initializationCoins.map((coin) => coin.id).toList(); + final initializationCoinIds = + initializationCoins.map((coin) => coin.id).toList(); - expect(initializationCoinIds, contains(initializationCoin.id)); + expect(initializationCoinIds, contains(initializationCoinId)); expect(initializationCoinIds, contains(initializationCoin2.id)); }); @@ -197,7 +211,8 @@ Future main() async { final initializationCoin2 = maker.standardCoins.first; - final incorrectInitializationSpendBundle = standardWalletService.createSpendBundle( + final incorrectInitializationSpendBundle = + standardWalletService.createSpendBundle( payments: [ Payment( 4, @@ -217,31 +232,41 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await maker.refreshCoins(); - final initializationCoins = - await fullNodeSimulator.scroungeForExchangeInitializationCoins(maker.puzzlehashes); + final initializationCoins = await fullNodeSimulator + .scroungeForExchangeInitializationCoins(maker.puzzlehashes); - final filteredInitializationCoins = - initializationCoins.where((coin) => coin.parentCoinInfo == initializationCoin2.id); + final filteredInitializationCoins = initializationCoins + .where((coin) => coin.parentCoinInfo == initializationCoin2.id); expect(filteredInitializationCoins, isEmpty); }); test('should correctly find cancel coin', () async { final cancelCoinId = initializationCoinSpend.additions - .where((addition) => addition.puzzlehash == messagePuzzlehash && addition.amount == 3) + .where( + (addition) => + addition.puzzlehash == messagePuzzlehash && addition.amount == 3, + ) .single .id; - final expectedCancelCoin = await fullNodeSimulator.getCoinById(cancelCoinId); + final expectedCancelCoin = + await fullNodeSimulator.getCoinById(cancelCoinId); + + final initializationCoin = + await fullNodeSimulator.getCoinById(initializationCoinId); - final cancelCoin = - await exchangeOfferService.getCancelCoin(initializationCoin, messagePuzzlehash); + final cancelCoin = await exchangeOfferService.getCancelCoin( + initializationCoin!, + messagePuzzlehash, + ); expect(cancelCoin, equals(expectedCancelCoin)); }); test( 'should throw exception when trying to find cancel coin from an offer that has not been initialized', () async { - final makerDerivationIndex2 = ExchangeOfferService.randomDerivationIndexForExchange(); + final makerDerivationIndex2 = + ExchangeOfferService.randomDerivationIndexForExchange(); final makerWalletVector2 = await WalletVector.fromPrivateKeyAsync( makerMasterPrivateKey, @@ -254,7 +279,10 @@ Future main() async { expect( () async { - await exchangeOfferService.getCancelCoin(initializationCoin2, messagePuzzlehash2); + await exchangeOfferService.getCancelCoin( + initializationCoin2, + messagePuzzlehash2, + ); }, throwsA(isA()), ); @@ -263,13 +291,18 @@ Future main() async { test( 'should cancel an exchange offer by spending 3 mojo child of initialization coin at message puzzlehash with expected memo', () async { - final unspentCancelCoin = - await exchangeOfferService.getCancelCoin(initializationCoin, messagePuzzlehash); + final initializationCoin = + await fullNodeSimulator.getCoinById(initializationCoinId); + + final unspentCancelCoin = await exchangeOfferService.getCancelCoin( + initializationCoin!, + messagePuzzlehash, + ); expect(unspentCancelCoin.isNotSpent, isTrue); await exchangeOfferService.cancelExchangeOffer( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -277,25 +310,33 @@ Future main() async { ); await fullNodeSimulator.moveToNextBlock(); - final spentCancelCoin = await fullNodeSimulator.getCoinById(unspentCancelCoin.id); + final spentCancelCoin = + await fullNodeSimulator.getCoinById(unspentCancelCoin.id); expect(spentCancelCoin!.isSpent, isTrue); - final cancelationCoinSpend = await fullNodeSimulator.getCoinSpend(spentCancelCoin); + final cancelationCoinSpend = + await fullNodeSimulator.getCoinSpend(spentCancelCoin); final memos = await cancelationCoinSpend!.memos; - expect(memos.contains(initializationCoin.id), isTrue); + expect(memos.contains(initializationCoinId), isTrue); }); - test('should throw exception when trying to cancel an offer that has already been canceled', + test( + 'should throw exception when trying to cancel an offer that has already been canceled', () async { - final unspentCancelCoin = - await exchangeOfferService.getCancelCoin(initializationCoin, messagePuzzlehash); + final initializationCoin = + await fullNodeSimulator.getCoinById(initializationCoinId); + + final unspentCancelCoin = await exchangeOfferService.getCancelCoin( + initializationCoin!, + messagePuzzlehash, + ); expect(unspentCancelCoin.isNotSpent, isTrue); await exchangeOfferService.cancelExchangeOffer( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -306,7 +347,7 @@ Future main() async { expect( () async { await exchangeOfferService.cancelExchangeOffer( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -324,25 +365,27 @@ Future main() async { coinsInput: [coinForMessageSpend], keychain: taker.keychain, serializedTakerOfferFile: serializedOfferAcceptFile, - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, changePuzzlehash: taker.firstPuzzlehash, ); await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final spentMessageCoinParent = await fullNodeSimulator.getCoinById(coinForMessageSpend.id); - final messageCoinSpend = await fullNodeSimulator.getCoinSpend(spentMessageCoinParent!); + final spentMessageCoinParent = + await fullNodeSimulator.getCoinById(coinForMessageSpend.id); + final messageCoinSpend = + await fullNodeSimulator.getCoinSpend(spentMessageCoinParent!); final memos = await messageCoinSpend!.memos; expect(memos.length, equals(3)); expect(memos[0], equals(Bytes(messagePuzzlehash))); - expect(memos[1], equals(initializationCoin.id)); + expect(memos[1], equals(initializationCoinId)); expect(memos[2], equals(Bytes.encodeFromString(serializedOfferAcceptFile))); - final messageCoins = - await fullNodeSimulator.getCoinsByHint(messagePuzzlehash, includeSpentCoins: true); + final messageCoins = await fullNodeSimulator + .getCoinsByHint(messagePuzzlehash, includeSpentCoins: true); expect(messageCoins.length, equals(1)); }); @@ -350,13 +393,18 @@ Future main() async { test( 'should throw exception when trying to send message coin for an offer that has already been canceled', () async { - final unspentCancelCoin = - await exchangeOfferService.getCancelCoin(initializationCoin, messagePuzzlehash); + final initializationCoin = + await fullNodeSimulator.getCoinById(initializationCoinId); + + final unspentCancelCoin = await exchangeOfferService.getCancelCoin( + initializationCoin!, + messagePuzzlehash, + ); expect(unspentCancelCoin.isNotSpent, isTrue); await exchangeOfferService.cancelExchangeOffer( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -373,7 +421,7 @@ Future main() async { coinsInput: [coinForMessageSpend], keychain: taker.keychain, serializedTakerOfferFile: serializedOfferAcceptFile, - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, changePuzzlehash: taker.firstPuzzlehash, ); }, @@ -388,15 +436,16 @@ Future main() async { coinsInput: [coinForMessageSpend], keychain: taker.keychain, serializedTakerOfferFile: serializedOfferAcceptFile, - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, changePuzzlehash: taker.firstPuzzlehash, ); await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final messageCoin = - (await fullNodeSimulator.getCoinsByHint(messagePuzzlehash, includeSpentCoins: true)).single; + final messageCoin = (await fullNodeSimulator + .getCoinsByHint(messagePuzzlehash, includeSpentCoins: true)) + .single; final expectedMessageCoinChild = (await fullNodeSimulator.getCoinsByPuzzleHashes([messagePuzzlehash])) @@ -404,7 +453,8 @@ Future main() async { .toList() .single; - final messageCoinChild = await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoin); + final messageCoinChild = + await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoin); expect(messageCoinChild, expectedMessageCoinChild); }); @@ -416,23 +466,25 @@ Future main() async { coinsInput: [coinForMessageSpend], keychain: taker.keychain, serializedTakerOfferFile: serializedOfferAcceptFile, - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, changePuzzlehash: taker.firstPuzzlehash, ); await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final messageCoin = - (await fullNodeSimulator.getCoinsByHint(messagePuzzlehash, includeSpentCoins: true)).single; + final messageCoin = (await fullNodeSimulator + .getCoinsByHint(messagePuzzlehash, includeSpentCoins: true)) + .single; - final messageCoinChild = await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoin); + final messageCoinChild = + await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoin); expect(messageCoinChild, isNotNull); expect(messageCoinChild!.isNotSpent, isTrue); await exchangeOfferService.declineMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -441,9 +493,11 @@ Future main() async { ); await fullNodeSimulator.moveToNextBlock(); - final spentMessageCoin = await fullNodeSimulator.getCoinById(messageCoin.id); + final spentMessageCoin = + await fullNodeSimulator.getCoinById(messageCoin.id); expect(spentMessageCoin!.isSpent, isTrue); - final declinationCoinSpend = await fullNodeSimulator.getCoinSpend(spentMessageCoin); + final declinationCoinSpend = + await fullNodeSimulator.getCoinSpend(spentMessageCoin); final memos = await declinationCoinSpend!.memos; expect(memos.isEmpty, isTrue); }); @@ -455,17 +509,19 @@ Future main() async { coinsInput: [coinForMessageSpend], keychain: taker.keychain, serializedTakerOfferFile: serializedOfferAcceptFile, - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, changePuzzlehash: taker.firstPuzzlehash, ); await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final messageCoin = - (await fullNodeSimulator.getCoinsByHint(messagePuzzlehash, includeSpentCoins: true)).single; + final messageCoin = (await fullNodeSimulator + .getCoinsByHint(messagePuzzlehash, includeSpentCoins: true)) + .single; - final messageCoinChild = await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoin); + final messageCoinChild = + await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoin); expect(messageCoinChild, isNotNull); expect(messageCoinChild!.isNotSpent, isTrue); @@ -473,7 +529,7 @@ Future main() async { final startingMakerBalance = maker.standardCoins.totalValue; await exchangeOfferService.declineMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -488,7 +544,10 @@ Future main() async { await maker.refreshCoins(); final endingMakerBalance = maker.standardCoins.totalValue; - expect(endingMakerBalance, equals(startingMakerBalance - fee + minimumNotificationCoinAmount)); + expect( + endingMakerBalance, + equals(startingMakerBalance - fee + minimumNotificationCoinAmount), + ); }); test('should accept message coin by spending with expected memo', () async { @@ -498,23 +557,25 @@ Future main() async { coinsInput: [coinForMessageSpend], keychain: taker.keychain, serializedTakerOfferFile: serializedOfferAcceptFile, - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, changePuzzlehash: taker.firstPuzzlehash, ); await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final messageCoin = - (await fullNodeSimulator.getCoinsByHint(messagePuzzlehash, includeSpentCoins: true)).single; + final messageCoin = (await fullNodeSimulator + .getCoinsByHint(messagePuzzlehash, includeSpentCoins: true)) + .single; - final messageCoinChild = await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoin); + final messageCoinChild = + await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoin); expect(messageCoinChild, isNotNull); expect(messageCoinChild!.isNotSpent, isTrue); await exchangeOfferService.acceptMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -526,11 +587,13 @@ Future main() async { ); await fullNodeSimulator.moveToNextBlock(); - final spentMessageCoinChild = await fullNodeSimulator.getCoinById(messageCoinChild.id); + final spentMessageCoinChild = + await fullNodeSimulator.getCoinById(messageCoinChild.id); expect(spentMessageCoinChild!.isSpent, isTrue); - final acceptanceCoinSpend = await fullNodeSimulator.getCoinSpend(spentMessageCoinChild); + final acceptanceCoinSpend = + await fullNodeSimulator.getCoinSpend(spentMessageCoinChild); final memos = await acceptanceCoinSpend!.memos; - expect(memos.contains(initializationCoin.id), isTrue); + expect(memos.contains(initializationCoinId), isTrue); }); test('should accept message coin with fee', () async { @@ -540,17 +603,19 @@ Future main() async { coinsInput: [coinForMessageSpend], keychain: taker.keychain, serializedTakerOfferFile: serializedOfferAcceptFile, - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, changePuzzlehash: taker.firstPuzzlehash, ); await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final messageCoin = - (await fullNodeSimulator.getCoinsByHint(messagePuzzlehash, includeSpentCoins: true)).single; + final messageCoin = (await fullNodeSimulator + .getCoinsByHint(messagePuzzlehash, includeSpentCoins: true)) + .single; - final messageCoinChild = await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoin); + final messageCoinChild = + await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoin); expect(messageCoinChild, isNotNull); expect(messageCoinChild!.isNotSpent, isTrue); @@ -558,7 +623,7 @@ Future main() async { final startingMakerBalance = maker.standardCoins.totalValue; await exchangeOfferService.acceptMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -573,10 +638,14 @@ Future main() async { await maker.refreshCoins(); final endingMakerBalance = maker.standardCoins.totalValue; - expect(endingMakerBalance, equals(startingMakerBalance - fee + minimumNotificationCoinAmount)); + expect( + endingMakerBalance, + equals(startingMakerBalance - fee + minimumNotificationCoinAmount), + ); }); - test('should throw exception if fee is greater than zero and inputs for fee are missing', + test( + 'should throw exception if fee is greater than zero and inputs for fee are missing', () async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( @@ -584,17 +653,19 @@ Future main() async { coinsInput: [coinForMessageSpend], keychain: taker.keychain, serializedTakerOfferFile: serializedOfferAcceptFile, - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, changePuzzlehash: taker.firstPuzzlehash, ); await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final messageCoin = - (await fullNodeSimulator.getCoinsByHint(messagePuzzlehash, includeSpentCoins: true)).single; + final messageCoin = (await fullNodeSimulator + .getCoinsByHint(messagePuzzlehash, includeSpentCoins: true)) + .single; - final messageCoinChild = await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoin); + final messageCoinChild = + await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoin); expect(messageCoinChild, isNotNull); expect(messageCoinChild!.isNotSpent, isTrue); @@ -602,7 +673,7 @@ Future main() async { expect( () async { await exchangeOfferService.acceptMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -617,10 +688,12 @@ Future main() async { ); }); - test('should throw exception when trying to accept already declined message coin', () async { + test( + 'should throw exception when trying to accept already declined message coin', + () async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -631,16 +704,18 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final messageCoin = - (await fullNodeSimulator.getCoinsByHint(messagePuzzlehash, includeSpentCoins: true)).single; + final messageCoin = (await fullNodeSimulator + .getCoinsByHint(messagePuzzlehash, includeSpentCoins: true)) + .single; - final messageCoinChild = await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoin); + final messageCoinChild = + await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoin); expect(messageCoinChild, isNotNull); expect(messageCoinChild!.isNotSpent, isTrue); await exchangeOfferService.declineMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -652,7 +727,7 @@ Future main() async { expect( () async { await exchangeOfferService.acceptMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -664,10 +739,12 @@ Future main() async { ); }); - test('should throw exception when trying to decline already accepted message coin', () async { + test( + 'should throw exception when trying to decline already accepted message coin', + () async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -678,16 +755,18 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final messageCoin = - (await fullNodeSimulator.getCoinsByHint(messagePuzzlehash, includeSpentCoins: true)).single; + final messageCoin = (await fullNodeSimulator + .getCoinsByHint(messagePuzzlehash, includeSpentCoins: true)) + .single; - final messageCoinChild = await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoin); + final messageCoinChild = + await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoin); expect(messageCoinChild, isNotNull); expect(messageCoinChild!.isNotSpent, isTrue); await exchangeOfferService.acceptMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -699,7 +778,7 @@ Future main() async { expect( () async { await exchangeOfferService.declineMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -714,7 +793,7 @@ Future main() async { test('should get info for next valid message coin', () async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -725,14 +804,15 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final messageCoin = - (await fullNodeSimulator.getCoinsByHint(messagePuzzlehash, includeSpentCoins: true)).single; + final messageCoin = (await fullNodeSimulator + .getCoinsByHint(messagePuzzlehash, includeSpentCoins: true)) + .single; - final messageCoinSpentTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(messageCoin.spentBlockIndex); + final messageCoinSpentTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(messageCoin.spentBlockIndex); final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: ExchangeType.xchToBtc, @@ -740,15 +820,24 @@ Future main() async { expect(messageCoinInfo, isNotNull); expect(messageCoinInfo!.messageCoin, equals(messageCoin)); - expect(messageCoinInfo.serializedOfferAcceptFile, equals(serializedOfferAcceptFile)); + expect( + messageCoinInfo.serializedOfferAcceptFile, + equals(serializedOfferAcceptFile), + ); expect(messageCoinInfo.fulfillerPublicKey, equals(takerPublicKey)); - expect(messageCoinInfo.messageCoinReceivedTime, equals(messageCoinSpentTime)); + expect( + messageCoinInfo.messageCoinReceivedTime, + equals(messageCoinSpentTime), + ); expect(messageCoinInfo.exchangeValidityTime, equals(exchangeValidityTime)); }); - test('should not get message coin info for coin with wrong offer file type', () async { - final xchToBtcOfferAcceptFile = crossChainOfferService.createXchToBtcAcceptFile( - serializedOfferFile: serializedOfferFile, + test('should not get message coin info for coin with wrong offer file type', + () async { + final xchToBtcOfferAcceptFile = + crossChainOfferFileService.createXchToBtcTakerOfferFile( + initializationCoinId: initializationCoinId, + serializedMakerOfferFile: serializedOfferFile, validityTime: exchangeValidityTime, requestorPublicKey: takerPublicKey, paymentRequest: decodedPaymentRequest, @@ -759,7 +848,7 @@ Future main() async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -771,7 +860,7 @@ Future main() async { await taker.refreshCoins(); final messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: ExchangeType.xchToBtc, @@ -780,10 +869,11 @@ Future main() async { expect(messageCoinInfo, isNull); }); - test('should correctly parse message coin info for accepted message coin', () async { + test('should correctly parse message coin info for accepted message coin', + () async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -794,15 +884,16 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final unspentMessageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + final unspentMessageCoinInfo = + await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: ExchangeType.xchToBtc, ); await exchangeOfferService.acceptMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: unspentMessageCoinInfo!.messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -814,46 +905,55 @@ Future main() async { ); await fullNodeSimulator.moveToNextBlock(); - final messageCoins = - await fullNodeSimulator.scroungeForReceivedNotificationCoins([messagePuzzlehash]); + final messageCoins = await fullNodeSimulator + .scroungeForReceivedNotificationCoins([messagePuzzlehash]); expect(messageCoins.length, equals(1)); final messageCoin = messageCoins.single; - final messageCoinInfo = await exchangeOfferService.parseAndValidateReceivedMessageCoin( + final messageCoinInfo = + await exchangeOfferService.parseAndValidateReceivedMessageCoin( messageCoin: messageCoin, - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: ExchangeType.xchToBtc, ); - final messageCoinChild = await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoin); + final messageCoinChild = + await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoin); expect(messageCoinChild, isNotNull); expect(messageCoinChild!.isSpent, isTrue); - final messageCoinChildSpentTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(messageCoinChild.spentBlockIndex); + final messageCoinChildSpentTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(messageCoinChild.spentBlockIndex); expect(messageCoinInfo, isNotNull); expect(messageCoinInfo!.messageCoin, equals(messageCoin)); - expect(messageCoinInfo.serializedOfferAcceptFile, equals(serializedOfferAcceptFile)); + expect( + messageCoinInfo.serializedOfferAcceptFile, + equals(serializedOfferAcceptFile), + ); expect(messageCoinInfo.fulfillerPublicKey, equals(takerPublicKey)); expect( messageCoinInfo.messageCoinReceivedTime, equals(messageCoinInfo.messageCoinReceivedTime), ); expect(messageCoinInfo.exchangeValidityTime, equals(exchangeValidityTime)); - expect(messageCoinInfo.messageCoinAcceptedTime, equals(messageCoinChildSpentTime)); + expect( + messageCoinInfo.messageCoinAcceptedTime, + equals(messageCoinChildSpentTime), + ); expect(messageCoinInfo.messageCoinDeclinedTime, isNull); }); - test('should correctly parse message coin info for declined message coin', () async { + test('should correctly parse message coin info for declined message coin', + () async { final coinForMessageSpend = taker.standardCoins.first; await exchangeOfferService.sendMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messagePuzzlehash: messagePuzzlehash, coinsInput: [coinForMessageSpend], keychain: taker.keychain, @@ -864,15 +964,16 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await taker.refreshCoins(); - final unspentMessageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( - initializationCoinId: initializationCoin.id, + final unspentMessageCoinInfo = + await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: ExchangeType.xchToBtc, ); await exchangeOfferService.declineMessageCoin( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, messageCoin: unspentMessageCoinInfo!.messageCoin, masterPrivateKey: makerMasterPrivateKey, derivationIndex: makerDerivationIndex, @@ -884,39 +985,47 @@ Future main() async { ); await fullNodeSimulator.moveToNextBlock(); - final messageCoins = - await fullNodeSimulator.scroungeForReceivedNotificationCoins([messagePuzzlehash]); + final messageCoins = await fullNodeSimulator + .scroungeForReceivedNotificationCoins([messagePuzzlehash]); expect(messageCoins.length, equals(1)); final messageCoin = messageCoins.single; - final messageCoinInfo = await exchangeOfferService.parseAndValidateReceivedMessageCoin( + final messageCoinInfo = + await exchangeOfferService.parseAndValidateReceivedMessageCoin( messageCoin: messageCoin, - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, messagePuzzlehash: messagePuzzlehash, exchangeType: ExchangeType.xchToBtc, ); - final messageCoinChild = await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoin); + final messageCoinChild = + await fullNodeSimulator.getSingleChildCoinFromCoin(messageCoin); expect(messageCoinChild, isNotNull); expect(messageCoinChild!.isSpent, isTrue); - final messageCoinChildSpentTime = - await fullNodeSimulator.getDateTimeFromBlockIndex(messageCoinChild.spentBlockIndex); + final messageCoinChildSpentTime = await fullNodeSimulator + .getDateTimeFromBlockIndex(messageCoinChild.spentBlockIndex); expect(messageCoinInfo, isNotNull); expect(messageCoinInfo!.messageCoin, equals(messageCoin)); - expect(messageCoinInfo.serializedOfferAcceptFile, equals(serializedOfferAcceptFile)); + expect( + messageCoinInfo.serializedOfferAcceptFile, + equals(serializedOfferAcceptFile), + ); expect(messageCoinInfo.fulfillerPublicKey, equals(takerPublicKey)); expect( messageCoinInfo.messageCoinReceivedTime, equals(messageCoinInfo.messageCoinReceivedTime), ); expect(messageCoinInfo.exchangeValidityTime, equals(exchangeValidityTime)); - expect(messageCoinInfo.messageCoinDeclinedTime, equals(messageCoinChildSpentTime)); + expect( + messageCoinInfo.messageCoinDeclinedTime, + equals(messageCoinChildSpentTime), + ); expect(messageCoinInfo.messageCoinAcceptedTime, isNull); }); @@ -931,7 +1040,7 @@ Future main() async { final startingMakerBalance = maker.standardCoins.totalValue; await exchangeOfferService.transferFundsToEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, mojos: mojos, escrowPuzzlehash: makerEscrowPuzzlehash, requestorPrivateKey: makerPrivateKey, @@ -945,7 +1054,8 @@ Future main() async { final endingMakerBalance = maker.standardCoins.totalValue; - final escrowCoins = await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash]); + final escrowCoins = + await fullNodeSimulator.getCoinsByPuzzleHashes([escrowPuzzlehash]); expect(escrowCoins.totalValue, equals(mojos)); expect(endingMakerBalance, equals(startingMakerBalance - mojos)); @@ -960,7 +1070,7 @@ Future main() async { ); await exchangeOfferService.transferFundsToEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, mojos: mojos, escrowPuzzlehash: makerEscrowPuzzlehash, requestorPrivateKey: makerPrivateKey, @@ -975,7 +1085,7 @@ Future main() async { final startingTakerBalance = taker.standardCoins.totalValue; await exchangeOfferService.sweepEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, escrowPuzzlehash: escrowPuzzlehash, requestorPuzzlehash: taker.firstPuzzlehash, requestorPrivateKey: takerPrivateKey, @@ -1006,7 +1116,7 @@ Future main() async { ); await exchangeOfferService.transferFundsToEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, mojos: mojos, escrowPuzzlehash: makerEscrowPuzzlehash, requestorPrivateKey: makerPrivateKey, @@ -1021,7 +1131,7 @@ Future main() async { final startingTakerBalance = taker.standardCoins.totalValue; await exchangeOfferService.sweepEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, escrowPuzzlehash: escrowPuzzlehash, requestorPuzzlehash: taker.firstPuzzlehash, requestorPrivateKey: takerPrivateKey, @@ -1060,7 +1170,7 @@ Future main() async { ); await exchangeOfferService.transferFundsToEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, mojos: mojos, escrowPuzzlehash: makerEscrowPuzzlehash, requestorPrivateKey: makerPrivateKey, @@ -1084,7 +1194,7 @@ Future main() async { await Future.delayed(const Duration(seconds: 10), () async { // maker claws back funds at escrow puzzlehash await exchangeOfferService.clawbackEscrowFunds( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, escrowPuzzlehash: makerEscrowPuzzlehash, requestorPuzzlehash: maker.firstPuzzlehash, requestorPrivateKey: makerPrivateKey, @@ -1114,7 +1224,7 @@ Future main() async { ); await exchangeOfferService.transferFundsToEscrowPuzzlehash( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, mojos: mojos, escrowPuzzlehash: makerEscrowPuzzlehash, requestorPrivateKey: makerPrivateKey, @@ -1138,7 +1248,7 @@ Future main() async { await Future.delayed(const Duration(seconds: 10), () async { // maker claws back funds at escrow puzzlehash await exchangeOfferService.clawbackEscrowFunds( - initializationCoinId: initializationCoin.id, + initializationCoinId: initializationCoinId, escrowPuzzlehash: makerEscrowPuzzlehash, requestorPuzzlehash: maker.firstPuzzlehash, requestorPrivateKey: makerPrivateKey, diff --git a/integration_test/namesdao/namesdao_test.dart b/integration_test/namesdao/namesdao_test.dart index 5664c7e5..ca7592ec 100644 --- a/integration_test/namesdao/namesdao_test.dart +++ b/integration_test/namesdao/namesdao_test.dart @@ -11,7 +11,8 @@ Future main() async { expect(nameInfo?.address.address, equals(null)); }); - test('should get name info for valid name ___CloakedRegistration.xch', () async { + test('should get name info for valid name ___CloakedRegistration.xch', + () async { const name = '___CloakedRegistration.xch'; final nameInfo = await namesdaoInterface.getNameInfo(name); expect( diff --git a/integration_test/namesdao/pay_to_namesdao_test.dart b/integration_test/namesdao/pay_to_namesdao_test.dart index aaa42354..28ebe425 100644 --- a/integration_test/namesdao/pay_to_namesdao_test.dart +++ b/integration_test/namesdao/pay_to_namesdao_test.dart @@ -12,7 +12,8 @@ Future main() async { final meera = ChiaEnthusiast(fullNodeSimulator); - final xchService = XchService(fullNode: fullNodeSimulator, keychain: meera.keychain); + final xchService = + XchService(fullNode: fullNodeSimulator, keychain: meera.keychain); final namesdaoApi = NamesdaoApi(); const ccuNamesdao = 'ChiaCryptoUtils.xch'; @@ -24,7 +25,8 @@ Future main() async { await meera.refreshCoins(); test('should send XCH to Namesdao name', () async { - final startingBalance = await fullNodeSimulator.getBalance([ccuNamesdaoPuzzlehash]); + final startingBalance = + await fullNodeSimulator.getBalance([ccuNamesdaoPuzzlehash]); final coinToSend = meera.standardCoins[0]; @@ -38,12 +40,14 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await meera.refreshCoins(); - final endingBalance = await fullNodeSimulator.getBalance([ccuNamesdaoPuzzlehash]); + final endingBalance = + await fullNodeSimulator.getBalance([ccuNamesdaoPuzzlehash]); expect(endingBalance - startingBalance, equals(coinToSend.amount)); }); - test('should throw exception when sending XCH to invalid Namesdao name', () async { + test('should throw exception when sending XCH to invalid Namesdao name', + () async { expect( () async { await xchService.sendXchToNamesdao( diff --git a/integration_test/nft/nft_data_hash_test.dart b/integration_test/nft/nft_data_hash_test.dart index f9366bfc..1ad1dee8 100644 --- a/integration_test/nft/nft_data_hash_test.dart +++ b/integration_test/nft/nft_data_hash_test.dart @@ -2,10 +2,12 @@ import 'package:chia_crypto_utils/chia_crypto_utils.dart'; import 'package:test/test.dart'; void main() async { - final expectedMetadataHash = - Bytes.fromHex('2a547a139a5f8d56268525cdec4ffd5117f81d904475c5bcb60e3c58a6121fa7'); - final expectedDataHash = - Bytes.fromHex('0974e28983f967f94025b0b37e27e785e0d05b8f59d9b9686127924095ad0c87'); + final expectedMetadataHash = Bytes.fromHex( + '2a547a139a5f8d56268525cdec4ffd5117f81d904475c5bcb60e3c58a6121fa7', + ); + final expectedDataHash = Bytes.fromHex( + '0974e28983f967f94025b0b37e27e785e0d05b8f59d9b9686127924095ad0c87', + ); final uriHashProvider = UriHashProvider(); diff --git a/integration_test/nft/nft_did_fetch_test.dart b/integration_test/nft/nft_did_fetch_test.dart index 381ace5f..472e41c8 100644 --- a/integration_test/nft/nft_did_fetch_test.dart +++ b/integration_test/nft/nft_did_fetch_test.dart @@ -7,12 +7,13 @@ void main() async { final fullNode = EnhancedChiaFullNodeInterface.fromUrl('FULL_NODE_URL'); - final launcherId = const Address('nft1ysdwllpf63rps75faxnkf7wkpnreyls2x0hqty2emd0f6wk4a34st2ptdj') - .toPuzzlehash(); + final launcherId = const Address( + 'nft1ysdwllpf63rps75faxnkf7wkpnreyls2x0hqty2emd0f6wk4a34st2ptdj', + ).toPuzzlehash(); - final chunkDid = - const Address('did:chia:13zkzl0jrn6x79mwgjx7q5eeplfcfl86thf5uws2ssy9w8gypt9kqse8xph') - .toPuzzlehash(); + final chunkDid = const Address( + 'did:chia:13zkzl0jrn6x79mwgjx7q5eeplfcfl86thf5uws2ssy9w8gypt9kqse8xph', + ).toPuzzlehash(); test('should get chunk minter did', () async { final mintInfo = await fullNode.getNftMintInfoForLauncherId(launcherId); diff --git a/integration_test/nft/nft_generation_test.dart b/integration_test/nft/nft_generation_test.dart index 84085c0d..c919742c 100644 --- a/integration_test/nft/nft_generation_test.dart +++ b/integration_test/nft/nft_generation_test.dart @@ -60,7 +60,8 @@ void main() async { await nathan.refreshCoins(); - final nftCoins = await fullNodeSimulator.getNftRecordsByHint(targetPuzzleHash); + final nftCoins = + await fullNodeSimulator.getNftRecordsByHint(targetPuzzleHash); expect(nftCoins.single.metadata, inputMetadata); final meera = ChiaEnthusiast(fullNodeSimulator, walletSize: 5); @@ -79,9 +80,12 @@ void main() async { await fullNodeSimulator.pushTransaction(sendBundle); await fullNodeSimulator.moveToNextBlock(); - final meeraNft = (await fullNodeSimulator.getNftRecordsByHint(meera.firstPuzzlehash)).single; + final meeraNft = + (await fullNodeSimulator.getNftRecordsByHint(meera.firstPuzzlehash)) + .single; - var nathanNfts = await fullNodeSimulator.getNftRecordsByHint(nathan.firstPuzzlehash); + var nathanNfts = + await fullNodeSimulator.getNftRecordsByHint(nathan.firstPuzzlehash); expect(nathanNfts, isEmpty); expect(meeraNft.metadata, inputMetadata); @@ -98,7 +102,8 @@ void main() async { await fullNodeSimulator.pushTransaction(toNathanSpendBundle); await fullNodeSimulator.moveToNextBlock(); - nathanNfts = await fullNodeSimulator.getNftRecordsByHint(nathan.firstPuzzlehash); + nathanNfts = + await fullNodeSimulator.getNftRecordsByHint(nathan.firstPuzzlehash); expect(nathanNfts.single.metadata, inputMetadata); }); @@ -113,7 +118,8 @@ void main() async { final catMintOriginCoin = nftFaucet.standardCoins.first; - final issuanceResult = catWalletService.makeMeltableMultiIssuanceCatSpendBundle( + final issuanceResult = + catWalletService.makeMeltableMultiIssuanceCatSpendBundle( genesisCoinId: catMintOriginCoin.id, standardCoins: [catMintOriginCoin], privateKey: nftFaucet.firstWalletVector.childPrivateKey, @@ -173,8 +179,8 @@ void main() async { user.firstPuzzlehash, ); expect(nftCoins.single.metadata, inputMetadata); - final mintInfo = - await fullNodeSimulator.getNftMintInfoForLauncherId(nftCoins.single.launcherId); + final mintInfo = await fullNodeSimulator + .getNftMintInfoForLauncherId(nftCoins.single.launcherId); expect(mintInfo!.minterDid, null); }); @@ -195,7 +201,9 @@ void main() async { await fullNodeSimulator.moveToNextBlock(); - var didInfo = (await fullNodeSimulator.getDidRecordsByPuzzleHashes(nathan.puzzlehashes)).single; + var didInfo = (await fullNodeSimulator + .getDidRecordsByPuzzleHashes(nathan.puzzlehashes)) + .single; await nathan.refreshCoins(); final createNftSpendBundle = nftWalletService.createGenerateNftSpendBundle( @@ -213,7 +221,8 @@ void main() async { await fullNodeSimulator.pushTransaction(createNftSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final nfts = await fullNodeSimulator.getNftRecordsByHint(nathan.firstPuzzlehash); + final nfts = + await fullNodeSimulator.getNftRecordsByHint(nathan.firstPuzzlehash); final meera = ChiaEnthusiast(fullNodeSimulator, walletSize: 5); @@ -235,7 +244,9 @@ void main() async { await fullNodeSimulator.pushTransaction(spendNftBundle); await fullNodeSimulator.moveToNextBlock(); - var meeraNft = (await fullNodeSimulator.getNftRecordsByHint(meera.firstPuzzlehash)).single; + var meeraNft = + (await fullNodeSimulator.getNftRecordsByHint(meera.firstPuzzlehash)) + .single; await fullNodeSimulator.pushTransaction( nftWalletService.createSpendBundle( @@ -254,9 +265,12 @@ void main() async { ); await fullNodeSimulator.moveToNextBlock(); - meeraNft = (await fullNodeSimulator.getNftRecordsByHint(meera.firstPuzzlehash)).single; + meeraNft = + (await fullNodeSimulator.getNftRecordsByHint(meera.firstPuzzlehash)) + .single; - final mintInfo = await fullNodeSimulator.getNftMintInfoForLauncherId(meeraNft.launcherId); + final mintInfo = await fullNodeSimulator + .getNftMintInfoForLauncherId(meeraNft.launcherId); expect(mintInfo!.minterDid, didInfo.did); expect(meeraNft.ownershipLayerInfo!.currentDid, meera.didInfo!.did); @@ -279,11 +293,16 @@ void main() async { await fullNodeSimulator.moveToNextBlock(); - final did = - (await fullNodeSimulator.getDidRecordsFromHint(didWalletVector.puzzlehash)).single.did; + final did = (await fullNodeSimulator + .getDidRecordsFromHint(didWalletVector.puzzlehash)) + .single + .did; for (var i = 0; i < 5; i++) { - final didInfo = await fullNodeSimulator.getDidRecordFromHint(didWalletVector.puzzlehash, did); + final didInfo = await fullNodeSimulator.getDidRecordFromHint( + didWalletVector.puzzlehash, + did, + ); final didMessagesSpendBundle = didWalletService.createSpendBundle( didInfo: didInfo!.toDidInfoOrThrow(nathan.keychain), @@ -294,7 +313,10 @@ void main() async { await fullNodeSimulator.moveToNextBlock(); } - final didInfo = await fullNodeSimulator.getDidRecordFromHint(didWalletVector.puzzlehash, did); + final didInfo = await fullNodeSimulator.getDidRecordFromHint( + didWalletVector.puzzlehash, + did, + ); final sendBundle = didWalletService.createSpendBundle( newP2Puzzlehash: meera.firstPuzzlehash, @@ -305,7 +327,10 @@ void main() async { await fullNodeSimulator.pushTransaction(sendBundle); await fullNodeSimulator.moveToNextBlock(); - final finalDid = await fullNodeSimulator.getDidRecordFromHint(didWalletVector.puzzlehash, did); + final finalDid = await fullNodeSimulator.getDidRecordFromHint( + didWalletVector.puzzlehash, + did, + ); expect(finalDid, isNull); }); @@ -322,8 +347,9 @@ void main() async { await fullNodeSimulator.pushTransaction(createDidSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final didInfoOriginal = - (await fullNodeSimulator.getDidRecordsByPuzzleHashes(nathan.puzzlehashes)).single; + final didInfoOriginal = (await fullNodeSimulator + .getDidRecordsByPuzzleHashes(nathan.puzzlehashes)) + .single; final did = didInfoOriginal.did; @@ -333,7 +359,8 @@ void main() async { final targetPuzzleHash = nathan.puzzlehashes.first; - final bulkMintSpendBundle = nftWalletService.createDidNftBulkMintSpendBundle( + final bulkMintSpendBundle = + nftWalletService.createDidNftBulkMintSpendBundle( minterPuzzlehash: targetPuzzleHash, nftMintData: await NftMintingDataWithHashes.makeUniformBulkMintData( uriHashProvider: MockUriHashProvider(), @@ -354,9 +381,11 @@ void main() async { await fullNodeSimulator.pushTransaction(bulkMintSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final nftRecords = await fullNodeSimulator.getNftRecordsByHint(targetPuzzleHash); - final mintedNftRecords = - nftRecords.where((element) => bulkMintSpendBundle.additions.contains(element.coin)); + final nftRecords = + await fullNodeSimulator.getNftRecordsByHint(targetPuzzleHash); + final mintedNftRecords = nftRecords.where( + (element) => bulkMintSpendBundle.additions.contains(element.coin), + ); expect(mintedNftRecords.length, 10); final mirror = ChiaEnthusiast(fullNodeSimulator); var expectedEditionNumber = 1; @@ -373,7 +402,8 @@ void main() async { } await fullNodeSimulator.moveToNextBlock(); - final sentNfts = await fullNodeSimulator.getNftRecordsByHint(mirror.firstPuzzlehash); + final sentNfts = + await fullNodeSimulator.getNftRecordsByHint(mirror.firstPuzzlehash); expect(sentNfts.length, 10); }); @@ -390,8 +420,9 @@ void main() async { await fullNodeSimulator.pushTransaction(createDidSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final didInfoOriginal = - (await fullNodeSimulator.getDidRecordsByPuzzleHashes(nathan.puzzlehashes)).single; + final didInfoOriginal = (await fullNodeSimulator + .getDidRecordsByPuzzleHashes(nathan.puzzlehashes)) + .single; final did = didInfoOriginal.did; @@ -401,7 +432,8 @@ void main() async { final targetPuzzleHash = nathan.puzzlehashes.first; - final bulkMintSpendBundle = nftWalletService.createDidNftBulkMintSpendBundle( + final bulkMintSpendBundle = + nftWalletService.createDidNftBulkMintSpendBundle( minterPuzzlehash: targetPuzzleHash, nftMintData: [ for (var i = 0; i < 10; i++) @@ -423,9 +455,11 @@ void main() async { await fullNodeSimulator.pushTransaction(bulkMintSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final nftRecords = await fullNodeSimulator.getNftRecordsByHint(targetPuzzleHash); - final mintedNftRecords = - nftRecords.where((element) => bulkMintSpendBundle.additions.contains(element.coin)); + final nftRecords = + await fullNodeSimulator.getNftRecordsByHint(targetPuzzleHash); + final mintedNftRecords = nftRecords.where( + (element) => bulkMintSpendBundle.additions.contains(element.coin), + ); expect(mintedNftRecords.length, 10); final mirror = ChiaEnthusiast(fullNodeSimulator); @@ -442,7 +476,8 @@ void main() async { } await fullNodeSimulator.moveToNextBlock(); - final sentNfts = await fullNodeSimulator.getNftRecordsByHint(mirror.firstPuzzlehash); + final sentNfts = + await fullNodeSimulator.getNftRecordsByHint(mirror.firstPuzzlehash); expect(sentNfts.length, 10); }); } diff --git a/integration_test/nft/nft_id_test.dart b/integration_test/nft/nft_id_test.dart index 4eeb2c86..9d96ec4a 100644 --- a/integration_test/nft/nft_id_test.dart +++ b/integration_test/nft/nft_id_test.dart @@ -3,8 +3,9 @@ import 'package:test/test.dart'; void main() { test('should get correct mint garden link for nft', () async { - final launcherId = - Bytes.fromHex('dcb1e09d7a3053b31cd512a161d5d8f54deaac4d7d16d0119dfd597b122d3269'); + final launcherId = Bytes.fromHex( + 'dcb1e09d7a3053b31cd512a161d5d8f54deaac4d7d16d0119dfd597b122d3269', + ); const actualLink = 'https://mintgarden.io/nfts/nft1mjc7p8t6xpfmx8x4z2skr4wc74x74tzd05tdqyval4vhky3dxf5su3q2em'; final nftId = NftId.fromLauncherId(launcherId); diff --git a/integration_test/nft/nft_puzzles_test.dart b/integration_test/nft/nft_puzzles_test.dart index 147074a6..71068ed9 100644 --- a/integration_test/nft/nft_puzzles_test.dart +++ b/integration_test/nft/nft_puzzles_test.dart @@ -46,7 +46,11 @@ void main() { // solution final standardInnerSolution = BaseWalletService.makeSolutionFromConditions([ - CreateCoinCondition(receiverWalletVector.puzzlehash, 1, memos: [senderWalletVector.puzzlehash]), + CreateCoinCondition( + receiverWalletVector.puzzlehash, + 1, + memos: [senderWalletVector.puzzlehash], + ), ]); final magicCondition = NftDidMagicConditionCondition(); @@ -56,7 +60,10 @@ void main() { Program.list([]), Program.cons( Program.fromInt(1), - Program.cons(magicCondition.toProgram(), standardInnerSolution.rest().first().rest()), + Program.cons( + magicCondition.toProgram(), + standardInnerSolution.rest().first().rest(), + ), ), Program.list([]), ]), @@ -85,7 +92,10 @@ void main() { ); final nftOutputConditions = createCoinConditions.where( - (element) => element.amount == 1 && element.memos != null && element.memos!.isNotEmpty, + (element) => + element.amount == 1 && + element.memos != null && + element.memos!.isNotEmpty, ); if (nftOutputConditions.isEmpty) { diff --git a/integration_test/nft/nft_verification_test.dart b/integration_test/nft/nft_verification_test.dart index 3e5882f5..1fae1b74 100644 --- a/integration_test/nft/nft_verification_test.dart +++ b/integration_test/nft/nft_verification_test.dart @@ -53,7 +53,8 @@ void main() async { await nftHolder.refreshCoins(); - final nftCoins = await fullNodeSimulator.getNftRecordsByHint(targetPuzzleHash); + final nftCoins = + await fullNodeSimulator.getNftRecordsByHint(targetPuzzleHash); expect(nftCoins.single.metadata, inputMetadata); final nft = nftCoins.single; diff --git a/integration_test/notification/notification_coin_test.dart b/integration_test/notification/notification_coin_test.dart index b7b528f9..57e600ce 100644 --- a/integration_test/notification/notification_coin_test.dart +++ b/integration_test/notification/notification_coin_test.dart @@ -35,7 +35,8 @@ Future main() async { }); test('should send and parse notification coin', () async { - final notificationSpendBundle = notificationService.createNotificationSpendBundle( + final notificationSpendBundle = + notificationService.createNotificationSpendBundle( targetPuzzlehash: targetPuzzlehash, message: [Memo(memo)], amount: minimumNotificationCoinAmount, @@ -47,8 +48,8 @@ Future main() async { await fullNodeSimulator.pushTransaction(notificationSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final coinsByHint = - await fullNodeSimulator.getCoinsByHints([targetPuzzlehash], includeSpentCoins: true); + final coinsByHint = await fullNodeSimulator + .getCoinsByHints([targetPuzzlehash], includeSpentCoins: true); expect(coinsByHint.length, equals(1)); @@ -62,7 +63,10 @@ Future main() async { expect(notificationCoin.isSpent, isTrue); expect(notificationCoin.amount, minimumNotificationCoinAmount); expect(notificationCoin.puzzlehash, equals(expectedNotificationPuzzlehash)); - expect(notificationCoin.parentCoinInfo, equals(coinForNotificationSpend.id)); + expect( + notificationCoin.parentCoinInfo, + equals(coinForNotificationSpend.id), + ); final fullNotificationCoin = await fullNodeSimulator.getNotificationCoinFromCoin(notificationCoin); @@ -72,7 +76,8 @@ Future main() async { expect(fullNotificationCoin.message.single, equals(memo)); }); - test('should return null when trying to parse standard hinted coin', () async { + test('should return null when trying to parse standard hinted coin', + () async { final standardSpendBundle = standardWalletService.createSpendBundle( payments: [ Payment( @@ -88,19 +93,24 @@ Future main() async { await fullNodeSimulator.pushTransaction(standardSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final coinsByHint = await fullNodeSimulator.getCoinsByHint(targetPuzzlehash); + final coinsByHint = + await fullNodeSimulator.getCoinsByHint(targetPuzzlehash); expect(coinsByHint.length, equals(1)); final coinByHint = coinsByHint.single; - final notificationCoin = await fullNodeSimulator.getNotificationCoinFromCoin(coinByHint); + final notificationCoin = + await fullNodeSimulator.getNotificationCoinFromCoin(coinByHint); expect(notificationCoin, isNull); }); - test('should throw exception when trying to construct notification coin from standard coin spend', + test( + 'should throw exception when trying to construct notification coin from standard coin spend', () async { final standardSpendBundle = standardWalletService.createSpendBundle( - payments: [Payment(minimumNotificationCoinAmount, sender.puzzlehashes[1])], + payments: [ + Payment(minimumNotificationCoinAmount, sender.puzzlehashes[1]) + ], coinsInput: [coinForNotificationSpend], keychain: sender.keychain, changePuzzlehash: sender.firstPuzzlehash, @@ -108,11 +118,13 @@ Future main() async { await fullNodeSimulator.pushTransaction(standardSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final spentCoin = await fullNodeSimulator.getCoinById(coinForNotificationSpend.id); + final spentCoin = + await fullNodeSimulator.getCoinById(coinForNotificationSpend.id); final coinSpend = await fullNodeSimulator.getCoinSpend(spentCoin!); - final childCoin = - coinSpend!.additions.where((coin) => coin.amount == minimumNotificationCoinAmount).single; + final childCoin = coinSpend!.additions + .where((coin) => coin.amount == minimumNotificationCoinAmount) + .single; final secondSpendBundle = standardWalletService.createSpendBundle( payments: [Payment(minimumNotificationCoinAmount, targetPuzzlehash)], @@ -137,7 +149,8 @@ Future main() async { }); test('should send and parse notification coin with multiple memos', () async { - final notificationSpendBundle = notificationService.createNotificationSpendBundle( + final notificationSpendBundle = + notificationService.createNotificationSpendBundle( targetPuzzlehash: targetPuzzlehash, message: [Memo(memo), Memo(memo2)], amount: minimumNotificationCoinAmount, @@ -149,8 +162,8 @@ Future main() async { await fullNodeSimulator.pushTransaction(notificationSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final coinsByHint = - await fullNodeSimulator.getCoinsByHints([targetPuzzlehash], includeSpentCoins: true); + final coinsByHint = await fullNodeSimulator + .getCoinsByHints([targetPuzzlehash], includeSpentCoins: true); expect(coinsByHint.length, equals(1)); @@ -164,7 +177,10 @@ Future main() async { expect(notificationCoin.isSpent, isTrue); expect(notificationCoin.amount, minimumNotificationCoinAmount); expect(notificationCoin.puzzlehash, equals(expectedNotificationPuzzlehash)); - expect(notificationCoin.parentCoinInfo, equals(coinForNotificationSpend.id)); + expect( + notificationCoin.parentCoinInfo, + equals(coinForNotificationSpend.id), + ); final fullNotificationCoin = await fullNodeSimulator.getNotificationCoinFromCoin(notificationCoin); @@ -177,7 +193,8 @@ Future main() async { }); test('should find received notification coin', () async { - final notificationSpendBundle = notificationService.createNotificationSpendBundle( + final notificationSpendBundle = + notificationService.createNotificationSpendBundle( targetPuzzlehash: targetPuzzlehash, message: [Memo(memo)], amount: minimumNotificationCoinAmount, @@ -189,8 +206,8 @@ Future main() async { await fullNodeSimulator.pushTransaction(notificationSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final receivedNotificationCoins = - await fullNodeSimulator.scroungeForReceivedNotificationCoins([targetPuzzlehash]); + final receivedNotificationCoins = await fullNodeSimulator + .scroungeForReceivedNotificationCoins([targetPuzzlehash]); expect(receivedNotificationCoins.length, equals(1)); @@ -199,11 +216,15 @@ Future main() async { expect(notificationCoin.amount, equals(minimumNotificationCoinAmount)); expect(notificationCoin.message.single, equals(memo)); expect(notificationCoin.targetPuzzlehash, equals(targetPuzzlehash)); - expect(notificationCoin.parentCoinInfo, equals(coinForNotificationSpend.id)); + expect( + notificationCoin.parentCoinInfo, + equals(coinForNotificationSpend.id), + ); }); test('should find multiple received notification coins', () async { - final notificationSpendBundle = notificationService.createNotificationSpendBundle( + final notificationSpendBundle = + notificationService.createNotificationSpendBundle( targetPuzzlehash: targetPuzzlehash, message: [Memo(memo)], amount: minimumNotificationCoinAmount, @@ -220,7 +241,8 @@ Future main() async { await sender2.refreshCoins(); final coinForNotificationSpend2 = sender2.standardCoins.first; - final notificationSpendBundle2 = notificationService.createNotificationSpendBundle( + final notificationSpendBundle2 = + notificationService.createNotificationSpendBundle( targetPuzzlehash: targetPuzzlehash, message: [Memo(memo2)], amount: minimumNotificationCoinAmount, @@ -232,8 +254,8 @@ Future main() async { await fullNodeSimulator.pushTransaction(notificationSpendBundle2); await fullNodeSimulator.moveToNextBlock(); - final receivedNotificationCoins = - await fullNodeSimulator.scroungeForReceivedNotificationCoins([targetPuzzlehash]); + final receivedNotificationCoins = await fullNodeSimulator + .scroungeForReceivedNotificationCoins([targetPuzzlehash]); expect(receivedNotificationCoins.length, equals(2)); @@ -252,11 +274,15 @@ Future main() async { expect(notificationCoin2.amount, equals(minimumNotificationCoinAmount)); expect(notificationCoin2.message.single, equals(memo2)); expect(notificationCoin2.targetPuzzlehash, equals(targetPuzzlehash)); - expect(notificationCoin2.parentCoinInfo, equals(coinForNotificationSpend2.id)); + expect( + notificationCoin2.parentCoinInfo, + equals(coinForNotificationSpend2.id), + ); }); test('should find sent notification coin', () async { - final notificationSpendBundle = notificationService.createNotificationSpendBundle( + final notificationSpendBundle = + notificationService.createNotificationSpendBundle( targetPuzzlehash: targetPuzzlehash, message: [Memo(memo)], amount: minimumNotificationCoinAmount, @@ -268,8 +294,8 @@ Future main() async { await fullNodeSimulator.pushTransaction(notificationSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final sentNotificationCoins = - await fullNodeSimulator.scroungeForSentNotificationCoins(sender.puzzlehashes); + final sentNotificationCoins = await fullNodeSimulator + .scroungeForSentNotificationCoins(sender.puzzlehashes); expect(sentNotificationCoins.length, equals(1)); @@ -278,11 +304,15 @@ Future main() async { expect(notificationCoin.amount, equals(minimumNotificationCoinAmount)); expect(notificationCoin.message.single, equals(memo)); expect(notificationCoin.targetPuzzlehash, equals(targetPuzzlehash)); - expect(notificationCoin.parentCoinInfo, equals(coinForNotificationSpend.id)); + expect( + notificationCoin.parentCoinInfo, + equals(coinForNotificationSpend.id), + ); }); test('should find multiple sent notification coins', () async { - final notificationSpendBundle = notificationService.createNotificationSpendBundle( + final notificationSpendBundle = + notificationService.createNotificationSpendBundle( targetPuzzlehash: targetPuzzlehash, message: [Memo(memo)], amount: minimumNotificationCoinAmount, @@ -293,7 +323,8 @@ Future main() async { final coinForNotificationSpend2 = sender.standardCoins.last; - final notificationSpendBundle2 = notificationService.createNotificationSpendBundle( + final notificationSpendBundle2 = + notificationService.createNotificationSpendBundle( targetPuzzlehash: targetPuzzlehash, message: [Memo(memo2)], amount: minimumNotificationCoinAmount, @@ -302,11 +333,12 @@ Future main() async { changePuzzlehash: sender.firstPuzzlehash, ); - await fullNodeSimulator.pushTransaction(notificationSpendBundle + notificationSpendBundle2); + await fullNodeSimulator + .pushTransaction(notificationSpendBundle + notificationSpendBundle2); await fullNodeSimulator.moveToNextBlock(); - final sentNotificationCoins = - await fullNodeSimulator.scroungeForSentNotificationCoins(sender.puzzlehashes); + final sentNotificationCoins = await fullNodeSimulator + .scroungeForSentNotificationCoins(sender.puzzlehashes); final notificationCoin1 = sentNotificationCoins .where((coin) => coin.parentCoinInfo == coinForNotificationSpend.id) @@ -323,6 +355,9 @@ Future main() async { expect(notificationCoin2.amount, equals(minimumNotificationCoinAmount)); expect(notificationCoin2.message.single, equals(memo2)); expect(notificationCoin2.targetPuzzlehash, equals(targetPuzzlehash)); - expect(notificationCoin2.parentCoinInfo, equals(coinForNotificationSpend2.id)); + expect( + notificationCoin2.parentCoinInfo, + equals(coinForNotificationSpend2.id), + ); }); } diff --git a/integration_test/offer/cat_offer_test.dart b/integration_test/offer/cat_offer_test.dart index c2b7479d..16785946 100644 --- a/integration_test/offer/cat_offer_test.dart +++ b/integration_test/offer/cat_offer_test.dart @@ -15,22 +15,29 @@ Future main() async { CatOfferWalletService(), Cat1OfferWalletService(), ]) { - final nathan = - ChiaEnthusiast(fullNodeSimulator, catWalletService: catOfferService.catWalletService); + final nathan = ChiaEnthusiast( + fullNodeSimulator, + catWalletService: catOfferService.catWalletService, + ); await nathan.farmCoins(); await nathan.issueMultiIssuanceCat(); - final grant = - ChiaEnthusiast(fullNodeSimulator, catWalletService: catOfferService.catWalletService); + final grant = ChiaEnthusiast( + fullNodeSimulator, + catWalletService: catOfferService.catWalletService, + ); await grant.farmCoins(); await grant.issueMultiIssuanceCat(); - final ian = - ChiaEnthusiast(fullNodeSimulator, catWalletService: catOfferService.catWalletService); + final ian = ChiaEnthusiast( + fullNodeSimulator, + catWalletService: catOfferService.catWalletService, + ); await ian.farmCoins(); await ian.issueMultiIssuanceCat(); - final catType = catOfferService.catWalletService.spendType.name.toUpperCase(); + final catType = + catOfferService.catWalletService.spendType.name.toUpperCase(); final nathanCoinAssetId = nathan.catCoinMap.keys.first; final grantCoinAssetId = grant.catCoinMap.keys.first; @@ -42,8 +49,9 @@ Future main() async { final grantStartingCatBalance = grant.catCoins.totalValue; final offeredAmounts = MixedAmounts(cat: {nathanCoinAssetId: 1000}); - final requestedPayments = - RequestedMixedPayments(standard: [Payment(1000, nathan.firstPuzzlehash)]); + final requestedPayments = RequestedMixedPayments( + standard: [Payment(1000, nathan.firstPuzzlehash)], + ); // sell cat final offer = await nathan.offerService.createOffer( @@ -60,11 +68,13 @@ Future main() async { expect(offer.isComplete, false); - final acceptedOffer = await grant.offerService.createTakeOfferAsync(deserialized, fee: 0); + final acceptedOffer = + await grant.offerService.createTakeOfferAsync(deserialized, fee: 0); expect(acceptedOffer.isComplete, true); - await fullNodeSimulator.pushTransaction(await acceptedOffer.toSpendBundleAsync()); + await fullNodeSimulator + .pushTransaction(await acceptedOffer.toSpendBundleAsync()); await fullNodeSimulator.moveToNextBlock(); await grant.refreshCoins(); @@ -81,11 +91,15 @@ Future main() async { ); expect(nathanEndingCatBalance, equals(nathanStartingCatBalance - 1000)); - expect(grantEndingStandardBalance, equals(grantStartingStandardBalance - 1000)); + expect( + grantEndingStandardBalance, + equals(grantStartingStandardBalance - 1000), + ); expect(grantEndingCatBalance, equals(grantStartingCatBalance + 1000)); }); - test('should complete and submit a $catType offer with left over value', () async { + test('should complete and submit a $catType offer with left over value', + () async { final nathanStartingStandardBalance = nathan.standardCoins.totalValue; final nathanStartingCatBalance = nathan.catCoins.totalValue; final grantStartingStandardBalance = grant.standardCoins.totalValue; @@ -99,8 +113,9 @@ Future main() async { final askOffer = await nathan.offerService.createOffer( offeredAmounts: MixedAmounts(cat: {nathanCoinAssetId: 1000}), changePuzzlehash: nathan.firstPuzzlehash, - requestedPayments: - RequestedMixedPayments(standard: [Payment(1000, nathan.firstPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(1000, nathan.firstPuzzlehash)], + ), ); expect(askOffer.isComplete, false); @@ -122,7 +137,8 @@ Future main() async { final completedOffer = askOffer + bidOffer; expect(completedOffer.isComplete, true); - await fullNodeSimulator.pushTransaction(completedOffer.toSpendBundle(ian.firstPuzzlehash)); + await fullNodeSimulator + .pushTransaction(completedOffer.toSpendBundle(ian.firstPuzzlehash)); await fullNodeSimulator.moveToNextBlock(); await grant.refreshCoins(); @@ -142,10 +158,16 @@ Future main() async { ); expect(nathanEndingCatBalance, equals(nathanStartingCatBalance - 1000)); - expect(grantEndingStandardBalance, equals(grantStartingStandardBalance - 1100)); + expect( + grantEndingStandardBalance, + equals(grantStartingStandardBalance - 1100), + ); expect(grantEndingCatBalance, equals(grantStartingCatBalance + 900)); - expect(ianEndingStandardBalance, equals(ianStartingStandardBalance + 100)); + expect( + ianEndingStandardBalance, + equals(ianStartingStandardBalance + 100), + ); expect(ianEndingCatBalance, equals(ianStartingCatBalance + 100)); }); @@ -156,7 +178,8 @@ Future main() async { final ianStartingCatBalance = ian.catCoins.totalValue; final checkOffer = await grant.offerService.createOffer( - offeredAmounts: MixedAmounts(cat: {grantCoinAssetId: 1000}, standard: 500), + offeredAmounts: + MixedAmounts(cat: {grantCoinAssetId: 1000}, standard: 500), requestedPayments: null, changePuzzlehash: grant.firstPuzzlehash, ); @@ -169,7 +192,8 @@ Future main() async { ); expect(checkCashingOffer.isComplete, true); - await fullNodeSimulator.pushTransaction(checkCashingOffer.toSpendBundle()); + await fullNodeSimulator + .pushTransaction(checkCashingOffer.toSpendBundle()); await fullNodeSimulator.moveToNextBlock(); await grant.refreshCoins(); @@ -180,10 +204,16 @@ Future main() async { final ianEndingStandardBalance = ian.standardCoins.totalValue; final ianEndingCatBalance = ian.catCoins.totalValue; - expect(grantEndingStandardBalance, equals(grantStartingStandardBalance - 500)); + expect( + grantEndingStandardBalance, + equals(grantStartingStandardBalance - 500), + ); expect(grantEndingCatBalance, equals(grantStartingCatBalance - 1000)); - expect(ianEndingStandardBalance, equals(ianStartingStandardBalance + 500 - 50)); + expect( + ianEndingStandardBalance, + equals(ianStartingStandardBalance + 500 - 50), + ); expect(ianEndingCatBalance, equals(ianStartingCatBalance + 1000)); }); @@ -211,7 +241,8 @@ Future main() async { ); expect(invoicePaymentOffer.isComplete, true); - await fullNodeSimulator.pushTransaction(invoicePaymentOffer.toSpendBundle()); + await fullNodeSimulator + .pushTransaction(invoicePaymentOffer.toSpendBundle()); await fullNodeSimulator.moveToNextBlock(); await grant.refreshCoins(); @@ -222,14 +253,21 @@ Future main() async { final ianEndingStandardBalance = ian.standardCoins.totalValue; final ianEndingCatBalance = ian.catCoins.totalValue; - expect(grantEndingStandardBalance, equals(grantStartingStandardBalance + 500)); + expect( + grantEndingStandardBalance, + equals(grantStartingStandardBalance + 500), + ); expect(grantEndingCatBalance, equals(grantStartingCatBalance + 1000)); - expect(ianEndingStandardBalance, equals(ianStartingStandardBalance - 500 - fee)); + expect( + ianEndingStandardBalance, + equals(ianStartingStandardBalance - 500 - fee), + ); expect(ianEndingCatBalance, equals(ianStartingCatBalance - 1000)); }); - test('should complete and submit a $catType offer with three parties', () async { + test('should complete and submit a $catType offer with three parties', + () async { final nathanStartingStandardBalance = nathan.standardCoins.totalValue; final nathanStartingCatBalance = nathan.catCoins.totalValue; final grantStartingStandardBalance = grant.standardCoins.totalValue; @@ -241,8 +279,9 @@ Future main() async { coinsForOffer: MixedCoins(cats: nathan.catCoins), offeredAmounts: OfferedMixedAmounts(cat: {nathanCoinAssetId: 1000}), changePuzzlehash: nathan.firstPuzzlehash, - requestedPayments: - RequestedMixedPayments(standard: [Payment(1000, nathan.firstPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(1000, nathan.firstPuzzlehash)], + ), keychain: nathan.keychain, ); expect(askOffer.isComplete, false); @@ -298,10 +337,16 @@ Future main() async { ); expect(nathanEndingCatBalance, equals(nathanStartingCatBalance - 1000)); - expect(grantEndingStandardBalance, equals(grantStartingStandardBalance - 250)); + expect( + grantEndingStandardBalance, + equals(grantStartingStandardBalance - 250), + ); expect(grantEndingCatBalance, equals(grantStartingCatBalance + 500)); - expect(ianEndingStandardBalance, equals(ianStartingStandardBalance - 750)); + expect( + ianEndingStandardBalance, + equals(ianStartingStandardBalance - 750), + ); expect(ianEndingCatBalance, equals(ianStartingCatBalance + 500)); }); @@ -310,15 +355,17 @@ Future main() async { coinsForOffer: MixedCoins(cats: nathan.catCoins), offeredAmounts: OfferedMixedAmounts(cat: {nathanCoinAssetId: 1000}), changePuzzlehash: nathan.firstPuzzlehash, - requestedPayments: - RequestedMixedPayments(standard: [Payment(1000, nathan.firstPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(1000, nathan.firstPuzzlehash)], + ), keychain: nathan.keychain, ); expect(askOffer.isComplete, false); final bidOfferRequestedAmounts = askOffer.offeredAmounts; - final payments = bidOfferRequestedAmounts.toPayments(grant.firstPuzzlehash); + final payments = + bidOfferRequestedAmounts.toPayments(grant.firstPuzzlehash); final bidOffer = catOfferService.makeOffer( coinsForOffer: MixedCoins( @@ -326,8 +373,10 @@ Future main() async { ), requestedPayments: RequestedMixedPayments( cat: payments.cat.map( - (key, value) => - MapEntry(key, value.map((e) => CatPayment(e.amount, e.puzzlehash)).toList()), + (key, value) => MapEntry( + key, + value.map((e) => CatPayment(e.amount, e.puzzlehash)).toList(), + ), ), standard: payments.standard, ), @@ -340,7 +389,9 @@ Future main() async { expect( () async { - await fullNodeSimulator.pushTransaction(acceptedOffer.toSpendBundle(ian.firstPuzzlehash)); + await fullNodeSimulator.pushTransaction( + acceptedOffer.toSpendBundle(ian.firstPuzzlehash), + ); }, throwsA(isA()), ); diff --git a/integration_test/offer/checking_for_spent_coins_test.dart b/integration_test/offer/checking_for_spent_coins_test.dart index 0423f17c..9c15de5e 100644 --- a/integration_test/offer/checking_for_spent_coins_test.dart +++ b/integration_test/offer/checking_for_spent_coins_test.dart @@ -23,12 +23,14 @@ Future main() async { coinsForOffer: MixedCoins(standardCoins: adam.standardCoins), offeredAmounts: const OfferedMixedAmounts(standard: 5000), changePuzzlehash: adam.firstPuzzlehash, - requestedPayments: RequestedMixedPayments(standard: [Payment(1000, adam.firstPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(1000, adam.firstPuzzlehash)], + ), keychain: adam.keychain, ); - var offerContainsSpentCoins = - await fullNodeSimulator.checkForSpentCoins(offer.offeredSpendBundle.coins); + var offerContainsSpentCoins = await fullNodeSimulator + .checkForSpentCoins(offer.offeredSpendBundle.coins); expect(offerContainsSpentCoins, false); final spendBundle = walletService.createSpendBundle( @@ -41,8 +43,8 @@ Future main() async { await fullNodeSimulator.pushTransaction(spendBundle); await fullNodeSimulator.moveToNextBlock(); - offerContainsSpentCoins = - await fullNodeSimulator.checkForSpentCoins(offer.offeredSpendBundle.coins); + offerContainsSpentCoins = await fullNodeSimulator + .checkForSpentCoins(offer.offeredSpendBundle.coins); expect(offerContainsSpentCoins, true); }); @@ -54,12 +56,14 @@ Future main() async { coinsForOffer: MixedCoins(standardCoins: isaac.standardCoins), offeredAmounts: const OfferedMixedAmounts(standard: 5000), changePuzzlehash: isaac.firstPuzzlehash, - requestedPayments: RequestedMixedPayments(standard: [Payment(1000, isaac.firstPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(1000, isaac.firstPuzzlehash)], + ), keychain: isaac.keychain, ); - var offerContainsSpentCoins = - await fullNodeSimulator.checkForSpentCoins(offer.offeredSpendBundle.coins); + var offerContainsSpentCoins = await fullNodeSimulator + .checkForSpentCoins(offer.offeredSpendBundle.coins); expect(offerContainsSpentCoins, false); final spendBundle = walletService.createSpendBundle( @@ -72,8 +76,8 @@ Future main() async { await fullNodeSimulator.pushTransaction(spendBundle); await fullNodeSimulator.moveToNextBlock(); - offerContainsSpentCoins = - await fullNodeSimulator.checkForSpentCoins(offer.offeredSpendBundle.coins); + offerContainsSpentCoins = await fullNodeSimulator + .checkForSpentCoins(offer.offeredSpendBundle.coins); expect(offerContainsSpentCoins, true); }); @@ -94,11 +98,15 @@ Future main() async { final offer = Offer.fromBech32(offerBinOfferFile); try { - final parsedOffer = - await OfferWalletService.parseOffer(offer, tailDatabaseApi: TailDatabaseApi()); + final parsedOffer = await OfferWalletService.parseOffer( + offer, + tailDatabaseApi: TailDatabaseApi(), + ); expect( - parsedOffer.requestedAmounts.cats.firstWhere((cat) => cat.name == 'Spacebucks').amount, + parsedOffer.requestedAmounts.cats + .firstWhere((cat) => cat.name == 'Spacebucks') + .amount, equals(50000.0), ); expect(parsedOffer.offeredAmounts.xch, equals(0.51)); diff --git a/integration_test/offer/malicious_offer_test.dart b/integration_test/offer/malicious_offer_test.dart index 1ca1f1d0..883d2cf9 100644 --- a/integration_test/offer/malicious_offer_test.dart +++ b/integration_test/offer/malicious_offer_test.dart @@ -78,7 +78,8 @@ Future main() async { expect( () async { - catOfferService.standardWalletService.validateSpendBundle(badSpendBundle); + catOfferService.standardWalletService + .validateSpendBundle(badSpendBundle); }, throwsA(isA()), ); @@ -98,8 +99,10 @@ Future main() async { ]), ); - final negativeBundle = - SpendBundle(coinSpends: [negativeSpend], signatures: {JacobianPoint.generateG2()}); + final negativeBundle = SpendBundle( + coinSpends: [negativeSpend], + signatures: {JacobianPoint.generateG2()}, + ); expect( () async { await fullNodeSimulator.pushTransaction(negativeBundle); @@ -126,7 +129,10 @@ Future main() async { expect( () async { await fullNodeSimulator.pushTransaction( - SpendBundle(coinSpends: [tooLargeSpend], signatures: {JacobianPoint.generateG2()}), + SpendBundle( + coinSpends: [tooLargeSpend], + signatures: {JacobianPoint.generateG2()}, + ), ); }, throwsA(isA()), @@ -181,7 +187,8 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); }); - test('should fail on double spend with a duplicate coin recreation', () async { + test('should fail on double spend with a duplicate coin recreation', + () async { final doubleSpend = CoinSpend( coin: acsCoinParent, puzzleReveal: acs, diff --git a/integration_test/offer/nft_offer_test.dart b/integration_test/offer/nft_offer_test.dart index 367fe523..84ef489b 100644 --- a/integration_test/offer/nft_offer_test.dart +++ b/integration_test/offer/nft_offer_test.dart @@ -54,7 +54,8 @@ void main() async { await offerMaker.refreshCoins(); - final nftCoins = await fullNodeSimulator.getNftRecordsByHint(targetPuzzleHash); + final nftCoins = + await fullNodeSimulator.getNftRecordsByHint(targetPuzzleHash); expect(nftCoins.single.metadata, inputMetadata); final nft = nftCoins.single.toNft(offerMaker.keychain); @@ -68,10 +69,12 @@ void main() async { changePuzzleHash: offerMaker.firstPuzzlehash, ); - await fullNodeSimulator.pushTransaction(dependentCoinCreationBundle.creationBundle); + await fullNodeSimulator + .pushTransaction(dependentCoinCreationBundle.creationBundle); await fullNodeSimulator.moveToNextBlock(); - final dependentFeeCoinBundle = dependentCoinService.createFeeCoinSpendBundle( + final dependentFeeCoinBundle = + dependentCoinService.createFeeCoinSpendBundle( dependentCoin: dependentCoinCreationBundle.dependentCoins[0], ); @@ -81,11 +84,14 @@ void main() async { final nftForXchOffer = offerService .makeOffer( - coinsForOffer: - MixedCoins(nfts: [nft], standardCoins: offerMaker.standardCoins.sublist(0, 1)), + coinsForOffer: MixedCoins( + nfts: [nft], + standardCoins: offerMaker.standardCoins.sublist(0, 1), + ), keychain: offerMaker.keychain, - requestedPayments: - RequestedMixedPayments(standard: [Payment(5000, offerMaker.puzzlehashes.first)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(5000, offerMaker.puzzlehashes.first)], + ), fee: 100, changePuzzlehash: offerMaker.firstPuzzlehash, ) @@ -133,8 +139,9 @@ void main() async { await fullNodeSimulator.moveToNextBlock(); - final didInfo = - (await fullNodeSimulator.getDidRecordsByPuzzleHashes(offerMaker.puzzlehashes)).single; + final didInfo = (await fullNodeSimulator + .getDidRecordsByPuzzleHashes(offerMaker.puzzlehashes)) + .single; await offerMaker.refreshCoins(); final targetPuzzleHash = offerMaker.puzzlehashes[1]; final spendBundle = nftWalletService.createGenerateNftSpendBundle( @@ -153,7 +160,8 @@ void main() async { await offerMaker.refreshCoins(); - final nftCoins = await fullNodeSimulator.getNftRecordsByHint(targetPuzzleHash); + final nftCoins = + await fullNodeSimulator.getNftRecordsByHint(targetPuzzleHash); expect(nftCoins.single.metadata, inputMetadata); final nft = nftCoins.single.toNft(offerMaker.keychain); @@ -167,10 +175,12 @@ void main() async { changePuzzleHash: offerMaker.firstPuzzlehash, ); - await fullNodeSimulator.pushTransaction(dependentCoinCreationBundle.creationBundle); + await fullNodeSimulator + .pushTransaction(dependentCoinCreationBundle.creationBundle); await fullNodeSimulator.moveToNextBlock(); - final dependentFeeCoinBundle = dependentCoinService.createFeeCoinSpendBundle( + final dependentFeeCoinBundle = + dependentCoinService.createFeeCoinSpendBundle( dependentCoin: dependentCoinCreationBundle.dependentCoins[0], ); @@ -214,8 +224,9 @@ void main() async { await fullNodeSimulator.moveToNextBlock(); - final didInfo = - (await fullNodeSimulator.getDidRecordsByPuzzleHashes(offerMaker.puzzlehashes)).single; + final didInfo = (await fullNodeSimulator + .getDidRecordsByPuzzleHashes(offerMaker.puzzlehashes)) + .single; await offerMaker.refreshCoins(); final targetPuzzleHash = offerMaker.puzzlehashes[1]; final spendBundle = nftWalletService.createGenerateNftSpendBundle( @@ -234,7 +245,8 @@ void main() async { await offerMaker.refreshCoins(); - final nftCoins = await fullNodeSimulator.getNftRecordsByHint(targetPuzzleHash); + final nftCoins = + await fullNodeSimulator.getNftRecordsByHint(targetPuzzleHash); expect(nftCoins.single.metadata.toProgram(), inputMetadata.toProgram()); final nft = nftCoins.single.toNft(offerMaker.keychain); @@ -248,10 +260,12 @@ void main() async { changePuzzleHash: offerMaker.firstPuzzlehash, ); - await fullNodeSimulator.pushTransaction(dependentCoinCreationBundle.creationBundle); + await fullNodeSimulator + .pushTransaction(dependentCoinCreationBundle.creationBundle); await fullNodeSimulator.moveToNextBlock(); - final dependentFeeCoinBundle = dependentCoinService.createFeeCoinSpendBundle( + final dependentFeeCoinBundle = + dependentCoinService.createFeeCoinSpendBundle( dependentCoin: dependentCoinCreationBundle.dependentCoins[0], ); await offerMaker.refreshCoins(); @@ -259,8 +273,9 @@ void main() async { final nftForXchOffer = (await offerMaker.offerService.createOffer( offeredAmounts: MixedAmounts(nft: {Puzzlehash(nft.launcherId)}), - requestedPayments: - RequestedMixedPayments(standard: [Payment(5000, offerMaker.puzzlehashes.first)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(5000, offerMaker.puzzlehashes.first)], + ), changePuzzlehash: offerMaker.firstPuzzlehash, )) .withAdditionalBundle(dependentFeeCoinBundle); @@ -302,8 +317,9 @@ void main() async { await fullNodeSimulator.moveToNextBlock(); - final didInfo = - (await fullNodeSimulator.getDidRecordsByPuzzleHashes(offerMaker.puzzlehashes)).single; + final didInfo = (await fullNodeSimulator + .getDidRecordsByPuzzleHashes(offerMaker.puzzlehashes)) + .single; await offerMaker.refreshCoins(); print('royalty puzzlehash:${offerMaker.firstPuzzlehash}}'); @@ -326,7 +342,8 @@ void main() async { await offerMaker.refreshCoins(); - final nftCoins = await fullNodeSimulator.getNftRecordsByHint(targetPuzzleHash); + final nftCoins = + await fullNodeSimulator.getNftRecordsByHint(targetPuzzleHash); expect(nftCoins.single.metadata, inputMetadata); final nft = nftCoins.single.toNft(offerMaker.keychain); @@ -381,8 +398,9 @@ void main() async { await fullNodeSimulator.moveToNextBlock(); - final didInfo = - (await fullNodeSimulator.getDidRecordsByPuzzleHashes(offerMaker.puzzlehashes)).single; + final didInfo = (await fullNodeSimulator + .getDidRecordsByPuzzleHashes(offerMaker.puzzlehashes)) + .single; final artist = ChiaEnthusiast(fullNodeSimulator); @@ -408,7 +426,8 @@ void main() async { await fullNodeSimulator.moveToNextBlock(); await offerMaker.refreshCoins(); - final nfts = await fullNodeSimulator.getNftRecordsByHint(offerMaker.firstPuzzlehash); + final nfts = + await fullNodeSimulator.getNftRecordsByHint(offerMaker.firstPuzzlehash); final nft = nfts.single.toNft(offerMaker.keychain); @@ -417,8 +436,9 @@ void main() async { final nftForXchOffer = await offerMaker.offerService.createOffer( offeredAmounts: MixedAmounts(nft: {Puzzlehash(nft.launcherId)}), - requestedPayments: - RequestedMixedPayments(standard: [Payment(requestedAmount, offerMaker.firstPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(requestedAmount, offerMaker.firstPuzzlehash)], + ), changePuzzlehash: offerMaker.firstPuzzlehash, ); @@ -480,8 +500,9 @@ void main() async { await fullNodeSimulator.moveToNextBlock(); - final didInfo = - (await fullNodeSimulator.getDidRecordsByPuzzleHashes(offerMaker.puzzlehashes)).single; + final didInfo = (await fullNodeSimulator + .getDidRecordsByPuzzleHashes(offerMaker.puzzlehashes)) + .single; final artist = ChiaEnthusiast(fullNodeSimulator); @@ -505,18 +526,24 @@ void main() async { await fullNodeSimulator.moveToNextBlock(); await offerMaker.refreshCoins(); - final nfts = await fullNodeSimulator.getNftRecordsByHint(offerMaker.firstPuzzlehash); + final nfts = + await fullNodeSimulator.getNftRecordsByHint(offerMaker.firstPuzzlehash); final offerMakerStartingCatBalance = offerMaker.catCoins.totalValue; - final offerMakerStartingStandardBalance = offerMaker.standardCoins.totalValue; + final offerMakerStartingStandardBalance = + offerMaker.standardCoins.totalValue; final nft = nfts.single.toNft(offerMaker.keychain); final nftForXchOffer = await offerMaker.offerService.createOffer( offeredAmounts: MixedAmounts(nft: {Puzzlehash(nft.launcherId)}), requestedPayments: RequestedMixedPayments( - standard: [Payment(requestedStandardAmount, offerMaker.firstPuzzlehash)], + standard: [ + Payment(requestedStandardAmount, offerMaker.firstPuzzlehash) + ], cat: { - catAssetId: [CatPayment(requestedCatAmount, offerMaker.firstPuzzlehash)], + catAssetId: [ + CatPayment(requestedCatAmount, offerMaker.firstPuzzlehash) + ], }, ), changePuzzlehash: offerMaker.firstPuzzlehash, @@ -525,7 +552,8 @@ void main() async { final takeTargetPuzzlehash = offerTaker.puzzlehashes.last; final initialTakerStandardBalance = offerTaker.standardCoins.totalValue; - final initialTakerCatBalance = offerTaker.catCoinMap[catAssetId]!.totalValue; + final initialTakerCatBalance = + offerTaker.catCoinMap[catAssetId]!.totalValue; const fee = 100; @@ -551,7 +579,8 @@ void main() async { await artist.refreshCoins(); final offerTakerEndingStandardBalance = offerTaker.standardCoins.totalValue; - final offerTakerEndingCatBalance = offerTaker.catCoinMap[catAssetId]!.totalValue; + final offerTakerEndingCatBalance = + offerTaker.catCoinMap[catAssetId]!.totalValue; const standardRoyaltyAmount = royaltyPercentage * requestedStandardAmount; @@ -559,7 +588,10 @@ void main() async { expect( offerTakerEndingStandardBalance, - initialTakerStandardBalance - requestedStandardAmount - fee - standardRoyaltyAmount, + initialTakerStandardBalance - + requestedStandardAmount - + fee - + standardRoyaltyAmount, ); expect( @@ -570,10 +602,16 @@ void main() async { final offerMakerEndingCatBalance = offerMaker.catCoins.totalValue; final offerMakerEndingStandardBalance = offerMaker.standardCoins.totalValue; - expect(artist.standardCoins.totalValue, royaltyPercentage * requestedStandardAmount); + expect( + artist.standardCoins.totalValue, + royaltyPercentage * requestedStandardAmount, + ); expect(artist.catCoins.totalValue, royaltyPercentage * requestedCatAmount); - expect(offerMakerEndingCatBalance, offerMakerStartingCatBalance + requestedCatAmount); + expect( + offerMakerEndingCatBalance, + offerMakerStartingCatBalance + requestedCatAmount, + ); expect( offerMakerEndingStandardBalance, offerMakerStartingStandardBalance + requestedStandardAmount, diff --git a/integration_test/offer/parse_offer_lineages_test.dart b/integration_test/offer/parse_offer_lineages_test.dart index f7d9cc0d..1cbc4958 100644 --- a/integration_test/offer/parse_offer_lineages_test.dart +++ b/integration_test/offer/parse_offer_lineages_test.dart @@ -13,26 +13,32 @@ void main() { walletSize: 100, ); test('Should parse lineages from offer service', () async { - final lineages = await OfferService.getLineagesFromOfferSpendBundle(spendBundle, fullNode); + final lineages = await OfferService.getLineagesFromOfferSpendBundle( + spendBundle, + fullNode, + ); final puzzlehashes = keychain.puzzlehashes.toSet(); for (final lineage in lineages) { - final originalDriver = - await PuzzleDriver.matchAsync(lineage.originalParentSpend!.puzzleReveal); + final originalDriver = await PuzzleDriver.matchAsync( + lineage.originalParentSpend!.puzzleReveal, + ); if (originalDriver == null) { throw UnsupportedCoinException(lineage.originalParentSpend!); } - final originP2Puzzlehash = originalDriver.getP2Puzzle(lineage.originalCoinSpend).hash(); + final originP2Puzzlehash = + originalDriver.getP2Puzzle(lineage.originalCoinSpend).hash(); print(originP2Puzzlehash); if (!puzzlehashes.contains(originP2Puzzlehash)) { continue; } - for (final p2Payment in await originalDriver - .getP2PaymentsAsync(lineage.intermediateSpendWithAdditions.coinSpend)) { + for (final p2Payment in await originalDriver.getP2PaymentsAsync( + lineage.intermediateSpendWithAdditions.coinSpend, + )) { print(p2Payment); } } diff --git a/integration_test/offer/submitted_offer_parsing_test.dart b/integration_test/offer/submitted_offer_parsing_test.dart index ce939f6a..ffde2a3b 100644 --- a/integration_test/offer/submitted_offer_parsing_test.dart +++ b/integration_test/offer/submitted_offer_parsing_test.dart @@ -35,8 +35,11 @@ void main() async { print('offer maker first puzzlehash: ${offerMaker.firstPuzzlehash}'); - final takeOffer = await offerTaker.offerService - .createTakeOffer(makeOffer, fee: 100, targetPuzzlehash: offerTaker.firstPuzzlehash); + final takeOffer = await offerTaker.offerService.createTakeOffer( + makeOffer, + fee: 100, + targetPuzzlehash: offerTaker.firstPuzzlehash, + ); print('offer taker first puzzlehash: ${offerTaker.firstPuzzlehash}'); @@ -52,7 +55,8 @@ void main() async { print('settlementProgramHashes: $settlementProgramHashes'); for (final addition in additionsWithParents) { - final puzzleDriver = PuzzleDriver.match(addition.parentSpend!.puzzleReveal); + final puzzleDriver = + PuzzleDriver.match(addition.parentSpend!.puzzleReveal); if (puzzleDriver == null) { print('null puzzle driver'); diff --git a/integration_test/plot_nft/mainnet_plot_nft_creation_and_registration.dart b/integration_test/plot_nft/mainnet_plot_nft_creation_and_registration.dart index 6d58e0d3..71b5fb58 100644 --- a/integration_test/plot_nft/mainnet_plot_nft_creation_and_registration.dart +++ b/integration_test/plot_nft/mainnet_plot_nft_creation_and_registration.dart @@ -10,7 +10,8 @@ Future main() async { const fullNodeUrl = 'FULL_NODE_URL'; // clone this for certificate chain: https://github.com/Chia-Network/mozilla-ca.git - final certificateBytes = Bytes(File('CERTIFICATE_BYTES_PATH').readAsBytesSync()); + final certificateBytes = + Bytes(File('CERTIFICATE_BYTES_PATH').readAsBytesSync()); const fullNodeRpc = FullNodeHttpRpc( fullNodeUrl, @@ -36,8 +37,10 @@ Future main() async { final keychain = WalletKeychain.fromWalletSets(walletsSetList); - final singletonWalletVector = - SingletonWalletVector.fromMasterPrivateKey(keychainSecret.masterPrivateKey, 20); + final singletonWalletVector = SingletonWalletVector.fromMasterPrivateKey( + keychainSecret.masterPrivateKey, + 20, + ); final coins = await fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); diff --git a/integration_test/plot_nft/pool_integration_test.dart b/integration_test/plot_nft/pool_integration_test.dart index 34fc755c..dcf02fa7 100644 --- a/integration_test/plot_nft/pool_integration_test.dart +++ b/integration_test/plot_nft/pool_integration_test.dart @@ -13,13 +13,15 @@ Future main() async { ChiaNetworkContextWrapper().registerNetworkContext(Network.mainnet); final poolWalletService = PlotNftWalletService(); - final nathan = ChiaEnthusiast(fullNodeSimulator, walletSize: 2); + final nathan = ChiaEnthusiast(fullNodeSimulator, walletSize: 3); await nathan.farmCoins(); + const poolUrl = 'https://xch.spacefarmers.io'; + test('should create plot nft', () async { final genesisCoin = nathan.standardCoins[0]; - final singletonWalletVector = - nathan.keychain.getNextSingletonWalletVector(nathan.keychainSecret.masterPrivateKey); + final singletonWalletVector = nathan.keychain + .getNextSingletonWalletVector(nathan.keychainSecret.masterPrivateKey); final initialTargetState = PoolState( poolSingletonState: PoolSingletonState.selfPooling, @@ -40,9 +42,11 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await nathan.refreshCoins(); - final launcherCoinPrototype = PlotNftWalletService.makeLauncherCoin(genesisCoin.id); + final launcherCoinPrototype = + PlotNftWalletService.makeLauncherCoin(genesisCoin.id); - final plotNft = (await fullNodeSimulator.getPlotNftByLauncherId(launcherCoinPrototype.id))!; + final plotNft = (await fullNodeSimulator + .getPlotNftByLauncherId(launcherCoinPrototype.id))!; expect( plotNft.poolState.toHex(), equals(initialTargetState.toHex()), @@ -56,8 +60,8 @@ Future main() async { test('should create plot nft with fee', () async { final genesisCoin = nathan.standardCoins[0]; - final singletonWalletVector = - nathan.keychain.getNextSingletonWalletVector(nathan.keychainSecret.masterPrivateKey); + final singletonWalletVector = nathan.keychain + .getNextSingletonWalletVector(nathan.keychainSecret.masterPrivateKey); final initialTargetState = PoolState( poolSingletonState: PoolSingletonState.selfPooling, @@ -78,9 +82,11 @@ Future main() async { await fullNodeSimulator.pushTransaction(plotNftSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final launcherCoinPrototype = PlotNftWalletService.makeLauncherCoin(genesisCoin.id); + final launcherCoinPrototype = + PlotNftWalletService.makeLauncherCoin(genesisCoin.id); - final plotNft = await fullNodeSimulator.getPlotNftByLauncherId(launcherCoinPrototype.id); + final plotNft = await fullNodeSimulator + .getPlotNftByLauncherId(launcherCoinPrototype.id); expect( plotNft!.poolState.toHex(), equals(initialTargetState.toHex()), @@ -96,8 +102,8 @@ Future main() async { final grant = ChiaEnthusiast(fullNodeSimulator, walletSize: 5); await grant.farmCoins(); - final singletonWalletVector = - grant.keychain.getNextSingletonWalletVector(grant.keychainSecret.masterPrivateKey); + final singletonWalletVector = grant.keychain + .getNextSingletonWalletVector(grant.keychainSecret.masterPrivateKey); final genesisCoin = grant.standardCoins[0]; @@ -120,7 +126,8 @@ Future main() async { await fullNodeSimulator.pushTransaction(plotNftSpendBundle); await fullNodeSimulator.moveToNextBlock(); - final plotNfts = await fullNodeSimulator.scroungeForPlotNfts(grant.puzzlehashes); + final plotNfts = + await fullNodeSimulator.scroungeForPlotNfts(grant.puzzlehashes); expect(plotNfts.length, equals(1)); final plotNft = plotNfts[0]; @@ -141,8 +148,8 @@ Future main() async { for (var i = 0; i < 4; i++) { await meera.farmCoins(); - final singletonWalletVector = - meera.keychain.getNextSingletonWalletVector(meera.keychainSecret.masterPrivateKey); + final singletonWalletVector = meera.keychain + .getNextSingletonWalletVector(meera.keychainSecret.masterPrivateKey); final genesisCoin = meera.standardCoins[0]; @@ -166,9 +173,11 @@ Future main() async { await fullNodeSimulator.moveToNextBlock(); await meera.refreshCoins(); - final launcherCoinPrototype = PlotNftWalletService.makeLauncherCoin(genesisCoin.id); + final launcherCoinPrototype = + PlotNftWalletService.makeLauncherCoin(genesisCoin.id); - final plotNft = await fullNodeSimulator.getPlotNftByLauncherId(launcherCoinPrototype.id); + final plotNft = await fullNodeSimulator + .getPlotNftByLauncherId(launcherCoinPrototype.id); expect( plotNft!.poolState.toHex(), equals(initialTargetState.toHex()), @@ -180,7 +189,382 @@ Future main() async { expect(plotNft.delayPuzzlehash, equals(meera.firstPuzzlehash)); } - final plotNfts = await fullNodeSimulator.scroungeForPlotNfts(meera.puzzlehashes); + final plotNfts = + await fullNodeSimulator.scroungeForPlotNfts(meera.puzzlehashes); expect(plotNfts.length, equals(4)); }); + + test( + 'should create and mutate plot nft from state self pooling to joining a pool', + () async { + final pool = PoolInterface.fromURL(poolUrl); + + final poolInfo = await pool.getPoolInfo(); + + final genesisCoin = nathan.standardCoins[0]; + final singletonWalletVector = nathan.keychain + .getNextSingletonWalletVector(nathan.keychainSecret.masterPrivateKey); + + final initialTargetState = PoolState( + poolSingletonState: PoolSingletonState.selfPooling, + targetPuzzlehash: nathan.puzzlehashes[1], + ownerPublicKey: singletonWalletVector.singletonOwnerPublicKey, + relativeLockHeight: 0, + ); + + final plotNftSpendBundle = poolWalletService.createPoolNftSpendBundle( + initialTargetState: initialTargetState, + keychain: nathan.keychain, + coins: nathan.standardCoins, + genesisCoinId: genesisCoin.id, + p2SingletonDelayedPuzzlehash: nathan.firstPuzzlehash, + changePuzzlehash: nathan.firstPuzzlehash, + ); + + await fullNodeSimulator.pushTransaction(plotNftSpendBundle); + await fullNodeSimulator.moveToNextBlock(); + await nathan.refreshCoins(); + + final launcherCoinPrototype = + PlotNftWalletService.makeLauncherCoin(genesisCoin.id); + + final plotNft = (await fullNodeSimulator + .getPlotNftByLauncherId(launcherCoinPrototype.id))!; + expect( + plotNft.poolState.toHex(), + equals(initialTargetState.toHex()), + ); + expect( + plotNft.delayTime, + equals(PlotNftWalletService.defaultDelayTime), + ); + expect(plotNft.delayPuzzlehash, equals(nathan.firstPuzzlehash)); + + await nathan.farmCoins(); + await nathan.refreshCoins(); + + final targetState = PoolState( + poolSingletonState: PoolSingletonState.farmingToPool, + targetPuzzlehash: poolInfo.targetPuzzlehash, + ownerPublicKey: singletonWalletVector.singletonOwnerPublicKey, + relativeLockHeight: 100, + poolUrl: poolUrl, + ); + + final plotNftMutationSpendBundle = + await poolWalletService.createPlotNftMutationSpendBundle( + plotNft: plotNft, + targetState: targetState, + keychain: nathan.keychain, + ); + + await fullNodeSimulator.pushTransaction(plotNftMutationSpendBundle); + await fullNodeSimulator.moveToNextBlock(); + await nathan.refreshCoins(); + + final mutatedPlotNft = (await fullNodeSimulator + .getPlotNftByLauncherId(launcherCoinPrototype.id))!; + + expect( + mutatedPlotNft.poolState.toHex(), + equals(targetState.toHex()), + ); + }); + + test( + 'should create plot nft in farmingToPool state, leave pool, and transfer ownership', + () async { + final genesisCoin = nathan.standardCoins[0]; + final singletonWalletVector = nathan.keychain + .getNextSingletonWalletVector(nathan.keychainSecret.masterPrivateKey); + + final poolInfo = await PoolInterface.fromURL(poolUrl).getPoolInfo(); + final initialTargetState = PoolState( + poolSingletonState: PoolSingletonState.farmingToPool, + targetPuzzlehash: poolInfo.targetPuzzlehash, + ownerPublicKey: singletonWalletVector.singletonOwnerPublicKey, + relativeLockHeight: 0, + ); + + final plotNftSpendBundle = poolWalletService.createPoolNftSpendBundle( + initialTargetState: initialTargetState, + keychain: nathan.keychain, + coins: nathan.standardCoins, + genesisCoinId: genesisCoin.id, + p2SingletonDelayedPuzzlehash: nathan.firstPuzzlehash, + changePuzzlehash: nathan.firstPuzzlehash, + ); + + await fullNodeSimulator.pushTransaction(plotNftSpendBundle); + await fullNodeSimulator.moveToNextBlock(); + await nathan.refreshCoins(); + + final launcherCoinPrototype = + PlotNftWalletService.makeLauncherCoin(genesisCoin.id); + + final plotNft = (await fullNodeSimulator + .getPlotNftByLauncherId(launcherCoinPrototype.id))!; + + expect( + plotNft.poolState.toHex(), + equals(initialTargetState.toHex()), + ); + expect( + plotNft.delayTime, + equals(PlotNftWalletService.defaultDelayTime), + ); + expect(plotNft.delayPuzzlehash, equals(nathan.firstPuzzlehash)); + + await nathan.farmCoins(); + await nathan.refreshCoins(); + + final meera = ChiaEnthusiast(fullNodeSimulator); + + final meeraSingletonWalletVector = meera.keychain + .getNextSingletonWalletVector(meera.keychainSecret.masterPrivateKey); + + final targetState = PoolState( + poolSingletonState: PoolSingletonState.leavingPool, + targetPuzzlehash: poolInfo.targetPuzzlehash, + ownerPublicKey: singletonWalletVector.singletonOwnerPublicKey, + relativeLockHeight: 0, + ); + + final plotNftMutationSpendBundle = + await poolWalletService.createPlotNftMutationSpendBundle( + plotNft: plotNft, + targetState: targetState, + keychain: nathan.keychain, + ); + + await fullNodeSimulator.pushTransaction(plotNftMutationSpendBundle); + await fullNodeSimulator.moveToNextBlock(); + await nathan.refreshCoins(); + + final leftPoolPlotNft = (await fullNodeSimulator + .getPlotNftByLauncherId(launcherCoinPrototype.id))!; + + expect( + leftPoolPlotNft.poolState.toHex(), + equals(targetState.toHex()), + ); + + final transferTargetState = PoolState( + poolSingletonState: PoolSingletonState.farmingToPool, + targetPuzzlehash: poolInfo.targetPuzzlehash, + ownerPublicKey: meeraSingletonWalletVector.singletonOwnerPublicKey, + relativeLockHeight: poolInfo.relativeLockHeight, + poolUrl: poolUrl, + ); + + final transferAndJoinPoolSpendBundle = + await poolWalletService.createTransferPlotNftSpendBundle( + coins: nathan.standardCoins, + plotNft: leftPoolPlotNft, + targetOwnerPublicKey: meeraSingletonWalletVector.singletonOwnerPublicKey, + keychain: nathan.keychain, + newPoolSingletonState: PoolSingletonState.farmingToPool, + changePuzzleHash: nathan.firstPuzzlehash, + poolUrl: transferTargetState.poolUrl, + ); + + await fullNodeSimulator.pushTransaction(transferAndJoinPoolSpendBundle); + await fullNodeSimulator.moveToNextBlock(); + await nathan.refreshCoins(); + + final plotNftTreasureMapCoin = (await fullNodeSimulator.getCoinsByHint( + meeraSingletonWalletVector.plotNftHint, + )) + .single; + + final transferredPlotNft = await fullNodeSimulator + .getPlotNftByLauncherId(plotNftTreasureMapCoin.puzzlehash); + + expect( + transferredPlotNft!.poolState.toHex(), + equals(transferTargetState.toHex()), + ); + }); + + test( + 'should create plot nft in selfPooling state and transfer ownership no with treasure map spend', + () async { + final genesisCoin = nathan.standardCoins[0]; + final singletonWalletVector = nathan.keychain + .getNextSingletonWalletVector(nathan.keychainSecret.masterPrivateKey); + + final initialTargetState = PoolState( + poolSingletonState: PoolSingletonState.selfPooling, + targetPuzzlehash: nathan.puzzlehashes[1], + ownerPublicKey: singletonWalletVector.singletonOwnerPublicKey, + relativeLockHeight: 0, + ); + + final plotNftSpendBundle = poolWalletService.createPoolNftSpendBundle( + initialTargetState: initialTargetState, + keychain: nathan.keychain, + coins: nathan.standardCoins, + genesisCoinId: genesisCoin.id, + p2SingletonDelayedPuzzlehash: nathan.firstPuzzlehash, + changePuzzlehash: nathan.firstPuzzlehash, + ); + + await fullNodeSimulator.pushTransaction(plotNftSpendBundle); + await fullNodeSimulator.moveToNextBlock(); + await nathan.refreshCoins(); + + final launcherCoinPrototype = + PlotNftWalletService.makeLauncherCoin(genesisCoin.id); + + final plotNft = (await fullNodeSimulator + .getPlotNftByLauncherId(launcherCoinPrototype.id))!; + + expect( + plotNft.poolState.toHex(), + equals(initialTargetState.toHex()), + ); + expect( + plotNft.delayTime, + equals(PlotNftWalletService.defaultDelayTime), + ); + expect(plotNft.delayPuzzlehash, equals(nathan.firstPuzzlehash)); + + await nathan.farmCoins(); + await nathan.refreshCoins(); + + final meera = ChiaEnthusiast(fullNodeSimulator); + + final meeraSingletonWalletVector = meera.keychain + .getNextSingletonWalletVector(meera.keychainSecret.masterPrivateKey); + + final poolInfo = await PoolInterface.fromURL(poolUrl).getPoolInfo(); + + final transferTargetState = PoolState( + poolSingletonState: PoolSingletonState.farmingToPool, + targetPuzzlehash: poolInfo.targetPuzzlehash, + ownerPublicKey: meeraSingletonWalletVector.singletonOwnerPublicKey, + relativeLockHeight: poolInfo.relativeLockHeight, + poolUrl: poolUrl, + ); + + final transferSpendBundle = + await poolWalletService.createTransferPlotNftSpendBundle( + coins: nathan.standardCoins, + plotNft: plotNft, + targetOwnerPublicKey: meeraSingletonWalletVector.singletonOwnerPublicKey, + keychain: nathan.keychain, + newPoolSingletonState: PoolSingletonState.farmingToPool, + changePuzzleHash: nathan.firstPuzzlehash, + poolUrl: transferTargetState.poolUrl, + ); + + await fullNodeSimulator.pushTransaction(transferSpendBundle); + await fullNodeSimulator.moveToNextBlock(); + await nathan.refreshCoins(); + + final plotNftTreasureMapCoin = (await fullNodeSimulator.getCoinsByHint( + meeraSingletonWalletVector.plotNftHint, + )) + .single; + + final transferredPlotNft = await fullNodeSimulator + .getPlotNftByLauncherId(plotNftTreasureMapCoin.puzzlehash); + + expect( + transferredPlotNft!.poolState.toHex(), + equals(transferTargetState.toHex()), + ); + }); + + test('should create plot nft in selfPooling state and transfer ownership', + () async { + final genesisCoin = nathan.standardCoins[0]; + final singletonWalletVector = nathan.keychain + .getNextSingletonWalletVector(nathan.keychainSecret.masterPrivateKey); + + final initialTargetState = PoolState( + poolSingletonState: PoolSingletonState.selfPooling, + targetPuzzlehash: nathan.puzzlehashes[1], + ownerPublicKey: singletonWalletVector.singletonOwnerPublicKey, + relativeLockHeight: 0, + ); + + final plotNftSpendBundle = poolWalletService.createPoolNftSpendBundle( + initialTargetState: initialTargetState, + keychain: nathan.keychain, + coins: nathan.standardCoins, + genesisCoinId: genesisCoin.id, + p2SingletonDelayedPuzzlehash: nathan.firstPuzzlehash, + changePuzzlehash: nathan.firstPuzzlehash, + ); + + await fullNodeSimulator.pushTransaction(plotNftSpendBundle); + await fullNodeSimulator.moveToNextBlock(); + await nathan.refreshCoins(); + + final launcherCoinPrototype = + PlotNftWalletService.makeLauncherCoin(genesisCoin.id); + + final plotNft = (await fullNodeSimulator + .getPlotNftByLauncherId(launcherCoinPrototype.id))!; + + expect( + plotNft.poolState.toHex(), + equals(initialTargetState.toHex()), + ); + expect( + plotNft.delayTime, + equals(PlotNftWalletService.defaultDelayTime), + ); + expect(plotNft.delayPuzzlehash, equals(nathan.firstPuzzlehash)); + + await nathan.farmCoins(); + await nathan.refreshCoins(); + + final meera = ChiaEnthusiast(fullNodeSimulator); + + final meeraSingletonWalletVector = meera.keychain + .getNextSingletonWalletVector(meera.keychainSecret.masterPrivateKey); + + final poolInfo = await PoolInterface.fromURL(poolUrl).getPoolInfo(); + + final transferTargetState = PoolState( + poolSingletonState: PoolSingletonState.farmingToPool, + targetPuzzlehash: poolInfo.targetPuzzlehash, + ownerPublicKey: meeraSingletonWalletVector.singletonOwnerPublicKey, + relativeLockHeight: poolInfo.relativeLockHeight, + poolUrl: poolUrl, + ); + + final transferSpendBundle = + await poolWalletService.createPlotNftTransferSpendBundle( + plotNft: plotNft, + coinsForTreasureMapCoin: [nathan.standardCoins.first], + receiverPuzzlehash: meera.firstPuzzlehash, + keychain: nathan.keychain, + changePuzzleHash: nathan.firstPuzzlehash, + targetState: transferTargetState, + ); + // print('--------\n'); + // transferSpendBundle.debug(); + + await fullNodeSimulator.pushTransaction(transferSpendBundle); + await fullNodeSimulator.moveToNextBlock(); + await nathan.refreshCoins(); + + // final puzzlehash = + // SingletonService.puzzleForSingleton(plotNft.launcherId, singletonOutputInnerPuzzleProgram) + // .hash(); + + final sibling = + await fullNodeSimulator.getCoinsByHint(meera.firstPuzzlehash); + + final transferredPlotNft = await fullNodeSimulator + .getPlotNftByLauncherId(sibling.single.puzzlehash); + + expect( + transferredPlotNft!.poolState.toHex(), + equals(transferTargetState.toHex()), + ); + }); } diff --git a/integration_test/simulator/simulator_test.dart b/integration_test/simulator/simulator_test.dart index bf1c46b2..a8aa523f 100644 --- a/integration_test/simulator/simulator_test.dart +++ b/integration_test/simulator/simulator_test.dart @@ -17,8 +17,9 @@ void main() async { test('should parse responses', () async { final isAutofarming = await fullNodeSimulator.getIsAutofarming(); - final newIsAutofarming = - await fullNodeSimulator.setShouldAutofarm(shouldAutofarm: !isAutofarming); + final newIsAutofarming = await fullNodeSimulator.setShouldAutofarm( + shouldAutofarm: !isAutofarming, + ); expect(newIsAutofarming, !isAutofarming); }); diff --git a/integration_test/standard/wallet_service_integration_test.dart b/integration_test/standard/wallet_service_integration_test.dart index d95e1f37..b37dbaff 100644 --- a/integration_test/standard/wallet_service_integration_test.dart +++ b/integration_test/standard/wallet_service_integration_test.dart @@ -32,16 +32,20 @@ Future main() async { senderPuzzlehash, walletService.blockchainNetwork.addressPrefix, ); - final receiverPuzzlehash = keychain.unhardenedMap.values.toList()[1].puzzlehash; + final receiverPuzzlehash = + keychain.unhardenedMap.values.toList()[1].puzzlehash; await fullNodeSimulator.farmCoins(senderAddress, blocks: nTests); await fullNodeSimulator.moveToNextBlock(); - final coins = await fullNodeSimulator.getCoinsByPuzzleHashes([senderPuzzlehash]); + final coins = + await fullNodeSimulator.getCoinsByPuzzleHashes([senderPuzzlehash]); test('Should push transaction with fee', () async { - final startingSenderBalance = await fullNodeSimulator.getBalance([senderPuzzlehash]); + final startingSenderBalance = + await fullNodeSimulator.getBalance([senderPuzzlehash]); - final startingReceiverBalance = await fullNodeSimulator.getBalance([receiverPuzzlehash]); + final startingReceiverBalance = + await fullNodeSimulator.getBalance([receiverPuzzlehash]); final coinsToSend = coins.sublist(0, 2); coins.removeWhere(coinsToSend.contains); @@ -64,17 +68,21 @@ Future main() async { await fullNodeSimulator.pushTransaction(spendBundle); await fullNodeSimulator.moveToNextBlock(); - final endingSenderBalance = await fullNodeSimulator.getBalance([senderPuzzlehash]); + final endingSenderBalance = + await fullNodeSimulator.getBalance([senderPuzzlehash]); expect(startingSenderBalance - endingSenderBalance, amountToSend + fee); - final endingReceiverBalance = await fullNodeSimulator.getBalance([receiverPuzzlehash]); + final endingReceiverBalance = + await fullNodeSimulator.getBalance([receiverPuzzlehash]); expect(endingReceiverBalance - startingReceiverBalance, amountToSend); }); test('Should push transaction without fee', () async { - final startingSenderBalance = await fullNodeSimulator.getBalance([senderPuzzlehash]); + final startingSenderBalance = + await fullNodeSimulator.getBalance([senderPuzzlehash]); - final startingReceiverBalance = await fullNodeSimulator.getBalance([receiverPuzzlehash]); + final startingReceiverBalance = + await fullNodeSimulator.getBalance([receiverPuzzlehash]); final coinsToSend = coins.sublist(0, 2); coins.removeWhere(coinsToSend.contains); @@ -95,15 +103,18 @@ Future main() async { await fullNodeSimulator.pushTransaction(spendBundle); await fullNodeSimulator.moveToNextBlock(); - final endingSenderBalance = await fullNodeSimulator.getBalance([senderPuzzlehash]); + final endingSenderBalance = + await fullNodeSimulator.getBalance([senderPuzzlehash]); expect(startingSenderBalance - endingSenderBalance, amountToSend); - final endingReceiverBalance = await fullNodeSimulator.getBalance([receiverPuzzlehash]); + final endingReceiverBalance = + await fullNodeSimulator.getBalance([receiverPuzzlehash]); expect(endingReceiverBalance - startingReceiverBalance, amountToSend); }); test('Should push transaction with multiple payments', () async { - final startingSenderBalance = await fullNodeSimulator.getBalance([senderPuzzlehash]); + final startingSenderBalance = + await fullNodeSimulator.getBalance([senderPuzzlehash]); final startingReceiverCoins = await fullNodeSimulator.getCoinsByPuzzleHashes([receiverPuzzlehash]); @@ -119,10 +130,15 @@ Future main() async { 0, (int previousValue, element) => previousValue + element.amount, ); - final amountsToSend = [(coinsValue * 0.2).round(), (coinsValue * 0.6).round()]; - final totalAmountToSend = amountsToSend.fold(0, (int previousValue, a) => previousValue + a); + final amountsToSend = [ + (coinsValue * 0.2).round(), + (coinsValue * 0.6).round() + ]; + final totalAmountToSend = + amountsToSend.fold(0, (int previousValue, a) => previousValue + a); - final payments = amountsToSend.map((a) => Payment(a, receiverPuzzlehash)).toList(); + final payments = + amountsToSend.map((a) => Payment(a, receiverPuzzlehash)).toList(); final spendBundle = walletService.createSpendBundle( payments: payments, @@ -134,13 +150,14 @@ Future main() async { await fullNodeSimulator.pushTransaction(spendBundle); await fullNodeSimulator.moveToNextBlock(); - final endingSenderBalance = await fullNodeSimulator.getBalance([senderPuzzlehash]); + final endingSenderBalance = + await fullNodeSimulator.getBalance([senderPuzzlehash]); expect(startingSenderBalance - endingSenderBalance, totalAmountToSend); final endingReceiverCoins = await fullNodeSimulator.getCoinsByPuzzleHashes([receiverPuzzlehash]); - final newReceiverCoins = - endingReceiverCoins.where((coin) => !startingReceiverCoins.contains(coin)); + final newReceiverCoins = endingReceiverCoins + .where((coin) => !startingReceiverCoins.contains(coin)); expect(newReceiverCoins.length == 2, true); expect( () { @@ -160,9 +177,11 @@ Future main() async { }); test('Should push transaction with origin', () async { - final startingSenderBalance = await fullNodeSimulator.getBalance([senderPuzzlehash]); + final startingSenderBalance = + await fullNodeSimulator.getBalance([senderPuzzlehash]); - final startingReceiverBalance = await fullNodeSimulator.getBalance([receiverPuzzlehash]); + final startingReceiverBalance = + await fullNodeSimulator.getBalance([receiverPuzzlehash]); final coinsToSend = coins.sublist(0, 2); coins.removeWhere(coinsToSend.contains); @@ -184,10 +203,12 @@ Future main() async { await fullNodeSimulator.pushTransaction(spendBundle); await fullNodeSimulator.moveToNextBlock(); - final endingSenderBalance = await fullNodeSimulator.getBalance([senderPuzzlehash]); + final endingSenderBalance = + await fullNodeSimulator.getBalance([senderPuzzlehash]); expect(startingSenderBalance - endingSenderBalance, amountToSend); - final endingReceiverBalance = await fullNodeSimulator.getBalance([receiverPuzzlehash]); + final endingReceiverBalance = + await fullNodeSimulator.getBalance([receiverPuzzlehash]); expect(endingReceiverBalance - startingReceiverBalance, amountToSend); }); @@ -221,8 +242,8 @@ Future main() async { print(coinsByMemo); final expectedAdditions = spendBundle.additions; - final expectedOutgoingAdditions = - expectedAdditions.where((element) => element.puzzlehash == receiverPuzzlehash); + final expectedOutgoingAdditions = expectedAdditions + .where((element) => element.puzzlehash == receiverPuzzlehash); for (final expectedAddition in expectedOutgoingAdditions) { expect( diff --git a/lib/src/api/client.dart b/lib/src/api/client.dart index a4cc05fe..ae6ef092 100644 --- a/lib/src/api/client.dart +++ b/lib/src/api/client.dart @@ -65,7 +65,8 @@ class Client { } }); } - request.headers.contentType = ContentType('application', 'json', charset: 'utf-8'); + request.headers.contentType = + ContentType('application', 'json', charset: 'utf-8'); final response = await request.close().timeout( timeout, @@ -100,7 +101,8 @@ class Client { request.headers.add(key, value); }); } - request.headers.contentType = ContentType('application', 'json', charset: 'utf-8'); + request.headers.contentType = + ContentType('application', 'json', charset: 'utf-8'); request.write(jsonEncode(requestBody)); final response = await request.close().timeout( @@ -117,7 +119,9 @@ class Client { } on HttpException catch (e) { LoggingContext().api(e.toString()); - if (e.toString().contains('Connection closed before full header was received')) { + if (e + .toString() + .contains('Connection closed before full header was received')) { throw BadAuthenticationException(); } rethrow; @@ -186,7 +190,8 @@ class Client { : null, 'certificate': response.certificate != null ? { - 'end_validity': response.certificate!.endValidity.toIso8601String(), + 'end_validity': + response.certificate!.endValidity.toIso8601String(), 'issuer': response.certificate!.issuer, 'pem': response.certificate!.pem, } @@ -219,5 +224,6 @@ class Response { int statusCode; @override - String toString() => 'Response(body: ${body.trim()}, statusCode: $statusCode)'; + String toString() => + 'Response(body: ${body.trim()}, statusCode: $statusCode)'; } diff --git a/lib/src/api/coin_market_cap/coin_market_cap_api.dart b/lib/src/api/coin_market_cap/coin_market_cap_api.dart index 6db72193..0dacde47 100644 --- a/lib/src/api/coin_market_cap/coin_market_cap_api.dart +++ b/lib/src/api/coin_market_cap/coin_market_cap_api.dart @@ -16,14 +16,20 @@ class CoinMarketCapApi { Client get client => Client(baseURL); - Future getLatestQuoteById([String convertSymbol = 'USD']) async { + Future getLatestQuoteById([ + String convertSymbol = 'USD', + ]) async { final response = await client.get( Uri.parse('v2/cryptocurrency/quotes/latest'), - queryParameters: {'id': xchCoinMarketCapId, 'convert': convertSymbol}, + queryParameters: { + 'id': xchCoinMarketCapId, + 'convert': convertSymbol + }, additionalHeaders: {'X-CMC_PRO_API_KEY': apiKey}, ); final responseJson = jsonDecode(response.body) as Map; - final status = Status.fromJson(responseJson['status'] as Map); + final status = + Status.fromJson(responseJson['status'] as Map); if (status.errorCode == 0) { final data = responseJson['data'] as Map; final crypto = data[xchCoinMarketCapId] as Map; diff --git a/lib/src/api/coin_market_cap/models/cryptocurrency.dart b/lib/src/api/coin_market_cap/models/cryptocurrency.dart index 6d34d48a..8d048c86 100644 --- a/lib/src/api/coin_market_cap/models/cryptocurrency.dart +++ b/lib/src/api/coin_market_cap/models/cryptocurrency.dart @@ -42,7 +42,8 @@ class Cryptocurrency { late Quote quote; @override - String toString() => 'Cryptocurrency(id: $id, name: $name, symbol: $symbol, slug: $slug, ' + String toString() => + 'Cryptocurrency(id: $id, name: $name, symbol: $symbol, slug: $slug, ' 'isActive: $isActive, isFiat: $isFiat, cmcRank: $cmcRank, numMarketPairs: $numMarketPairs, ' 'circulatingSupply: $circulatingSupply, totalSupply: $totalSupply, maxSupply: $maxSupply, ' 'dateAdded: $dateAdded, tags: $tags, platform: $platform)'; diff --git a/lib/src/api/coin_market_cap/models/platform.dart b/lib/src/api/coin_market_cap/models/platform.dart index 92db90b4..d90ed9a1 100644 --- a/lib/src/api/coin_market_cap/models/platform.dart +++ b/lib/src/api/coin_market_cap/models/platform.dart @@ -12,6 +12,7 @@ class Platform { final String tokenAddress; @override - String toString() => 'Platform(id: $id, name: $name, symbol: $symbol, slug: $slug, ' + String toString() => + 'Platform(id: $id, name: $name, symbol: $symbol, slug: $slug, ' 'tokenAddress: $tokenAddress)'; } diff --git a/lib/src/api/coin_market_cap/models/quote.dart b/lib/src/api/coin_market_cap/models/quote.dart index ee81186b..4bdc1f0f 100644 --- a/lib/src/api/coin_market_cap/models/quote.dart +++ b/lib/src/api/coin_market_cap/models/quote.dart @@ -26,7 +26,8 @@ class Quote { final String lastUpdated; @override - String toString() => 'Quote(symbol: $symbol, price: $price, volume24h: $volume24h, ' + String toString() => + 'Quote(symbol: $symbol, price: $price, volume24h: $volume24h, ' 'volumeChange24h: $volumeChange24h, marketCap: $marketCap, ' 'marketCapDominance: $marketCapDominance, fullyDilutedMarketCap: $fullyDilutedMarketCap, ' 'percentChange1h: $percentChange1h, percentChange24h: $percentChange24h, ' diff --git a/lib/src/api/coin_splitting/service/coin_splitting_service.dart b/lib/src/api/coin_splitting/service/coin_splitting_service.dart index 3368c6c1..6d6ff2ac 100644 --- a/lib/src/api/coin_splitting/service/coin_splitting_service.dart +++ b/lib/src/api/coin_splitting/service/coin_splitting_service.dart @@ -3,10 +3,13 @@ import 'dart:math'; import 'package:chia_crypto_utils/chia_crypto_utils.dart'; class CoinSplittingService { - CoinSplittingService(this.fullNode, {this.coinSearchWaitPeriod = _defaultCoinSearchWaitPeriod}) - : blockchainUtils = BlockchainUtils(fullNode); - CoinSplittingService.fromContext({this.coinSearchWaitPeriod = _defaultCoinSearchWaitPeriod}) - : fullNode = ChiaFullNodeInterface.fromContext(), + CoinSplittingService( + this.fullNode, { + this.coinSearchWaitPeriod = _defaultCoinSearchWaitPeriod, + }) : blockchainUtils = BlockchainUtils(fullNode); + CoinSplittingService.fromContext({ + this.coinSearchWaitPeriod = _defaultCoinSearchWaitPeriod, + }) : fullNode = ChiaFullNodeInterface.fromContext(), blockchainUtils = BlockchainUtils.fromContext(); final ChiaFullNodeInterface fullNode; @@ -34,9 +37,12 @@ class CoinSplittingService { logger('number of $splitWidth width splits: $numberOfNWidthSplits'); - final resultingCoinsFromNWidthSplits = pow(splitWidth, numberOfNWidthSplits).toInt(); - final numberOfDecaSplits = - calculateNumberOfDecaSplitsRequired(resultingCoinsFromNWidthSplits, desiredNumberOfCoins); + final resultingCoinsFromNWidthSplits = + pow(splitWidth, numberOfNWidthSplits).toInt(); + final numberOfDecaSplits = calculateNumberOfDecaSplitsRequired( + resultingCoinsFromNWidthSplits, + desiredNumberOfCoins, + ); logger('number of 10 width splits: $numberOfDecaSplits'); @@ -74,13 +80,16 @@ class CoinSplittingService { logger('joined standard coins for fee'); if (feeCoins.length != 1) { - throw Exception('should only be one standard coin after join. got ${feeCoins.length}'); + throw Exception( + 'should only be one standard coin after join. got ${feeCoins.length}', + ); } } final relevantPuzzleHashes = keychain.puzzlehashes.sublist(0, splitWidth); - final relevantOuterPuzzleHashes = - keychain.getOuterPuzzleHashesForAssetId(catCoinToSplit.assetId).sublist(0, splitWidth); + final relevantOuterPuzzleHashes = keychain + .getOuterPuzzleHashesForAssetId(catCoinToSplit.assetId) + .sublist(0, splitWidth); var catCoins = [catCoinToSplit]; @@ -153,7 +162,9 @@ class CoinSplittingService { startHeight: earliestSpentBlockIndex, ); - return catCoins.where((cc) => catParentCoinIds.contains(cc.parentCoinInfo)).toList(); + return catCoins + .where((cc) => catParentCoinIds.contains(cc.parentCoinInfo)) + .toList(); } Future> getChildCoinsByPuzzlehashes( @@ -167,7 +178,9 @@ class CoinSplittingService { startHeight: earliestSpentBlockIndex, ); - return standardCoins.where((c) => parentCoinIds.contains(c.parentCoinInfo)).toList(); + return standardCoins + .where((c) => parentCoinIds.contains(c.parentCoinInfo)) + .toList(); } Future createAndPushFinalSplittingTransactions({ @@ -256,7 +269,8 @@ class CoinSplittingService { keychain: keychain, ); - final totalFeeAmount = splitWidth * feePerCoin * 2; // fee coin and cat coin + final totalFeeAmount = + splitWidth * feePerCoin * 2; // fee coin and cat coin final standardCoinValueMinusFee = standardCoin.amount - totalFeeAmount; final standardPayments = makeSplittingPayments( @@ -273,7 +287,8 @@ class CoinSplittingService { ); parentIdsToLookFor.add(catCoin.id); - transactionFutures.add(fullNode.pushTransaction(catSpendBundle + standardSpendBundle)); + transactionFutures + .add(fullNode.pushTransaction(catSpendBundle + standardSpendBundle)); } await Future.wait(transactionFutures); @@ -329,7 +344,9 @@ class CoinSplittingService { return waitForTransactionsAndGetFirstSpentIndex([coins.first.id]); } - Future waitForTransactionsAndGetFirstSpentIndex(List parentIds) async { + Future waitForTransactionsAndGetFirstSpentIndex( + List parentIds, + ) async { final spentCoins = await blockchainUtils.waitForTransactions( parentIds, coinSearchWaitPeriod: coinSearchWaitPeriod, @@ -378,7 +395,8 @@ class CoinSplittingService { // pow(...) returns negative went out of bounds while (maxResultingCoins <= 0) { maxNWidthSplitIndex--; - maxResultingCoins = pow(initialSplitWidth, maxNWidthSplitIndex).powerOfTen; + maxResultingCoins = + pow(initialSplitWidth, maxNWidthSplitIndex).powerOfTen; } final maxResultingCoinsPowerOfTen = maxResultingCoins.powerOfTen; @@ -392,14 +410,16 @@ class CoinSplittingService { final desiredNumberOfCoinsAdjusted = desiredNumberOfCoins.toNthPowerOfTen(maxResultingCoinsPowerOfTen); - final resultingCoinsAdjusted = resultingCoins.toNthPowerOfTen(maxResultingCoinsPowerOfTen); + final resultingCoinsAdjusted = + resultingCoins.toNthPowerOfTen(maxResultingCoinsPowerOfTen); var difference = desiredNumberOfCoinsAdjusted - resultingCoinsAdjusted; if (difference < 0) { final resultingCoinsDigitsMinusOneToCompare = resultingCoins.toNthPowerOfTen(maxResultingCoinsPowerOfTen - 1); - difference = desiredNumberOfCoinsAdjusted - resultingCoinsDigitsMinusOneToCompare; + difference = desiredNumberOfCoinsAdjusted - + resultingCoinsDigitsMinusOneToCompare; } if (difference < smallestDifference) { @@ -416,7 +436,8 @@ class CoinSplittingService { int desiredNumberOfCoins, ) { var numberOfDecaSplits = 0; - while (resultingCoinsFromNWidthSplits * pow(10, numberOfDecaSplits) <= desiredNumberOfCoins) { + while (resultingCoinsFromNWidthSplits * pow(10, numberOfDecaSplits) <= + desiredNumberOfCoins) { numberOfDecaSplits++; } // want just under desired amount @@ -448,7 +469,9 @@ class CoinSplittingService { } if (desiredCoinAmount > catCoinAmount) { - throw ArgumentError('Cat balance is not enough to meet desired splitting parameters'); + throw ArgumentError( + 'Cat balance is not enough to meet desired splitting parameters', + ); } // check that fee coins don't get too small @@ -470,7 +493,9 @@ class CoinSplittingService { } if (feePerCoin > feeCoinAmount) { - throw ArgumentError('Standard balance is not enough to meet desired splitting parameters'); + throw ArgumentError( + 'Standard balance is not enough to meet desired splitting parameters', + ); } } } diff --git a/lib/src/api/coin_splitting/service/standard_coin_splitting_service_updated.dart b/lib/src/api/coin_splitting/service/standard_coin_splitting_service_updated.dart index 01238670..46101174 100644 --- a/lib/src/api/coin_splitting/service/standard_coin_splitting_service_updated.dart +++ b/lib/src/api/coin_splitting/service/standard_coin_splitting_service_updated.dart @@ -24,7 +24,8 @@ class StandardCoinSplittingService { ); } final changePh = changePuzzleHash ?? keychain.puzzlehashes.first; - final splitPuzzlehashes = keychain.puzzlehashes.where((ph) => ph != changePh).toList(); + final splitPuzzlehashes = + keychain.puzzlehashes.where((ph) => ph != changePh).toList(); var totalCoinsCreated = 0; @@ -53,8 +54,8 @@ class StandardCoinSplittingService { var totalSpendBundle = initialSplitSpendBundle; // need to make sure we don't spend changeback coin so we use up all of the surplus value from the initial split spend bundle - var previousSplitNetAdditions = - initialSplitSpendBundle.netAdditions.where((element) => element.puzzlehash != changePh); + var previousSplitNetAdditions = initialSplitSpendBundle.netAdditions + .where((element) => element.puzzlehash != changePh); var splitCount = 1; while (totalCoinsCreated < targetCoinCount) { @@ -65,7 +66,8 @@ class StandardCoinSplittingService { if (previousSplitAddition.amount != targetAmountPerCoin) { print(previousSplitAddition); } - final numberOfCoinsToCreate = min(splitWidth, targetCoinCount - totalCoinsCreated); + final numberOfCoinsToCreate = + min(splitWidth, targetCoinCount - totalCoinsCreated); if (numberOfCoinsToCreate == 0) { break; } @@ -86,7 +88,8 @@ class StandardCoinSplittingService { totalSpendBundle += spendBundle; splitNetAdditions.addAll( - spendBundle.netAdditions.where((element) => element.puzzlehash != changePh), + spendBundle.netAdditions + .where((element) => element.puzzlehash != changePh), ); totalCoinsCreated += numberOfCoinsToCreate; diff --git a/lib/src/api/dexie/dexie_api.dart b/lib/src/api/dexie/dexie_api.dart index 9ac1238d..30cd868f 100644 --- a/lib/src/api/dexie/dexie_api.dart +++ b/lib/src/api/dexie/dexie_api.dart @@ -21,7 +21,9 @@ class DexieOffersApi { throw DexieApiErrorException(errorMessage: baseResponse.errorMessage); } - return DexieOffer.fromJson(pick(bodyJson, 'offer').letJsonOrThrow((json) => json)); + return DexieOffer.fromJson( + pick(bodyJson, 'offer').letJsonOrThrow((json) => json), + ); } } diff --git a/lib/src/api/enhanced_full_node/enhanced_chia_full_node_interface.dart b/lib/src/api/enhanced_full_node/enhanced_chia_full_node_interface.dart index c412646e..26c9645c 100644 --- a/lib/src/api/enhanced_full_node/enhanced_chia_full_node_interface.dart +++ b/lib/src/api/enhanced_full_node/enhanced_chia_full_node_interface.dart @@ -32,7 +32,8 @@ class EnhancedChiaFullNodeInterface extends ChiaFullNodeInterface { Bytes? lastId, bool includeSpentCoins = false, }) async { - final recordsResponse = await enhancedFullNode.getCoinRecordsByPuzzleHashesPaginated( + final recordsResponse = + await enhancedFullNode.getCoinRecordsByPuzzleHashesPaginated( puzzlehashes, maxNumberOfCoins, startHeight: startHeight, @@ -110,7 +111,8 @@ class EnhancedChiaFullNodeInterface extends ChiaFullNodeInterface { Bytes? lastId, bool includeSpentCoins = false, }) async { - final recordsResponse = await enhancedFullNode.getCoinRecordsByHintsPaginated( + final recordsResponse = + await enhancedFullNode.getCoinRecordsByHintsPaginated( hints, maxNumberOfCoins, startHeight: startHeight, @@ -210,8 +212,11 @@ class EnhancedChiaFullNodeInterface extends ChiaFullNodeInterface { return response.coinSpendsMap; } - Future getAdditionsAndRemovalsWithHints(Bytes headerHash) async { - final response = await enhancedFullNode.getAdditionsAndRemovalsWithHints(headerHash); + Future getAdditionsAndRemovalsWithHints( + Bytes headerHash, + ) async { + final response = + await enhancedFullNode.getAdditionsAndRemovalsWithHints(headerHash); ChiaFullNodeInterface.mapResponseToError(response); return AdditionsAndRemovalsWithHints( additions: response.additions!, @@ -237,7 +242,8 @@ class EnhancedChiaFullNodeInterface extends ChiaFullNodeInterface { @override Future> getDidsFromCoins(List coins) async { final didInfos = []; - final parentSpends = await getCoinSpendsByIds(coins.map((e) => e.parentCoinInfo).toList()); + final parentSpends = + await getCoinSpendsByIds(coins.map((e) => e.parentCoinInfo).toList()); for (final coin in coins) { if (coin.amount.isEven) { continue; diff --git a/lib/src/api/enhanced_full_node/enhanced_full_node.dart b/lib/src/api/enhanced_full_node/enhanced_full_node.dart index fbd07263..95196761 100644 --- a/lib/src/api/enhanced_full_node/enhanced_full_node.dart +++ b/lib/src/api/enhanced_full_node/enhanced_full_node.dart @@ -4,7 +4,8 @@ import 'package:chia_crypto_utils/src/api/enhanced_full_node/models/responses/co abstract class EnhancedFullNode extends FullNode { EnhancedFullNode(super.baseURL); - Future getCoinRecordsByPuzzleHashesPaginated( + Future + getCoinRecordsByPuzzleHashesPaginated( List puzzlehashes, int maxNumberOfCoins, { int? startHeight, @@ -29,7 +30,8 @@ abstract class EnhancedFullNode extends FullNode { bool includeSpentCoins = false, }); - Future getAdditionsAndRemovalsWithHints( + Future + getAdditionsAndRemovalsWithHints( Bytes headerHash, ); diff --git a/lib/src/api/enhanced_full_node/enhanced_full_node_rpc.dart b/lib/src/api/enhanced_full_node/enhanced_full_node_rpc.dart index de0f3402..ce8cea98 100644 --- a/lib/src/api/enhanced_full_node/enhanced_full_node_rpc.dart +++ b/lib/src/api/enhanced_full_node/enhanced_full_node_rpc.dart @@ -32,7 +32,8 @@ class EnhancedFullNodeHttpRpc implements EnhancedFullNode { Client get client => _delegate.client; @override - Future getCoinRecordsByPuzzleHashesPaginated( + Future + getCoinRecordsByPuzzleHashesPaginated( List puzzlehashes, int maxNumberOfCoins, { int? startHeight, @@ -131,7 +132,8 @@ class EnhancedFullNodeHttpRpc implements EnhancedFullNode { } @override - Future getAdditionsAndRemovalsWithHints( + Future + getAdditionsAndRemovalsWithHints( Bytes headerHash, ) async { final response = await client.post( @@ -146,7 +148,9 @@ class EnhancedFullNodeHttpRpc implements EnhancedFullNode { } @override - Future getAdditionsAndRemovals(Bytes headerHash) { + Future getAdditionsAndRemovals( + Bytes headerHash, + ) { return _delegate.getAdditionsAndRemovals(headerHash); } @@ -220,7 +224,10 @@ class EnhancedFullNodeHttpRpc implements EnhancedFullNode { if (endHeight != null) { body['end_height'] = endHeight; } - final response = await client.post(Uri.parse('get_puzzles_and_solutions_by_names'), body); + final response = await client.post( + Uri.parse('get_puzzles_and_solutions_by_names'), + body, + ); FullNodeHttpRpc.mapResponseToError(response); return GetCoinSpendsByIdsResponse.fromJson( diff --git a/lib/src/api/enhanced_full_node/models/chia_coin_record_with_coin_spend.dart b/lib/src/api/enhanced_full_node/models/chia_coin_record_with_coin_spend.dart index a78b049f..83e34d23 100644 --- a/lib/src/api/enhanced_full_node/models/chia_coin_record_with_coin_spend.dart +++ b/lib/src/api/enhanced_full_node/models/chia_coin_record_with_coin_spend.dart @@ -28,7 +28,9 @@ class ChiaCoinRecordWithCoinSpend extends ChiaCoinRecord { : CoinSpend.fromJson(json['coin_spend'] as Map), parentSpend: (json['parent_coin_spend'] == null) ? null - : CoinSpend.fromJson(json['parent_coin_spend'] as Map), + : CoinSpend.fromJson( + json['parent_coin_spend'] as Map, + ), ); } final CoinSpend? coinSpend; diff --git a/lib/src/api/enhanced_full_node/models/paginated_coins.dart b/lib/src/api/enhanced_full_node/models/paginated_coins.dart index 701e2b29..7e702d00 100644 --- a/lib/src/api/enhanced_full_node/models/paginated_coins.dart +++ b/lib/src/api/enhanced_full_node/models/paginated_coins.dart @@ -11,13 +11,15 @@ class PaginatedCoins with ToJsonMixin { final unspentCoins = (json['unspent_coins'] as List) .map( - (dynamic value) => CoinWithParentSpend.fromJson(value as Map), + (dynamic value) => + CoinWithParentSpend.fromJson(value as Map), ) .toList(); final lastIdSerialized = json['last_id'] as String?; - final lastId = (lastIdSerialized != null) ? Bytes.fromHex(lastIdSerialized) : null; + final lastId = + (lastIdSerialized != null) ? Bytes.fromHex(lastIdSerialized) : null; final totalCoinCount = json['total_coin_count'] as int?; return PaginatedCoins(spentCoins, unspentCoins, lastId, totalCoinCount); diff --git a/lib/src/api/enhanced_full_node/models/responses/additions_and_removals_with_hints_response.dart b/lib/src/api/enhanced_full_node/models/responses/additions_and_removals_with_hints_response.dart index 148b4b23..2c9705ba 100644 --- a/lib/src/api/enhanced_full_node/models/responses/additions_and_removals_with_hints_response.dart +++ b/lib/src/api/enhanced_full_node/models/responses/additions_and_removals_with_hints_response.dart @@ -8,14 +8,19 @@ class GetAdditionsAndRemovalsWithHintsResponse extends ChiaBaseResponse { required super.error, }); - factory GetAdditionsAndRemovalsWithHintsResponse.fromJson(Map json) { + factory GetAdditionsAndRemovalsWithHintsResponse.fromJson( + Map json, + ) { final chiaBaseResponse = ChiaBaseResponse.fromJson(json); if (chiaBaseResponse.success) { return GetAdditionsAndRemovalsWithHintsResponse( - additions: - _coinListFromJson(List>.from(json['additions'] as Iterable)), - removals: _coinListFromJson(List>.from(json['removals'] as Iterable)), + additions: _coinListFromJson( + List>.from(json['additions'] as Iterable), + ), + removals: _coinListFromJson( + List>.from(json['removals'] as Iterable), + ), success: chiaBaseResponse.success, error: chiaBaseResponse.error, ); diff --git a/lib/src/api/enhanced_full_node/models/responses/coin_records_with_coin_spends_result.dart b/lib/src/api/enhanced_full_node/models/responses/coin_records_with_coin_spends_result.dart index 1b80947a..277504bf 100644 --- a/lib/src/api/enhanced_full_node/models/responses/coin_records_with_coin_spends_result.dart +++ b/lib/src/api/enhanced_full_node/models/responses/coin_records_with_coin_spends_result.dart @@ -13,21 +13,25 @@ class CoinRecordsWithCoinSpendsResponse extends ChiaBaseResponse { required super.error, }); - factory CoinRecordsWithCoinSpendsResponse.fromJson(Map json) { + factory CoinRecordsWithCoinSpendsResponse.fromJson( + Map json, + ) { final chiaBaseResponse = ChiaBaseResponse.fromJson(json); final coinRecords = json['coin_records'] != null ? (json['coin_records'] as List) .map( - (dynamic value) => - ChiaCoinRecordWithCoinSpend.fromJson(value as Map), + (dynamic value) => ChiaCoinRecordWithCoinSpend.fromJson( + value as Map, + ), ) .toList() : []; final lastIdSerialized = json['last_id'] as String?; - final lastId = (lastIdSerialized != null) ? Bytes.fromHex(lastIdSerialized) : null; + final lastId = + (lastIdSerialized != null) ? Bytes.fromHex(lastIdSerialized) : null; return CoinRecordsWithCoinSpendsResponse( coinRecords: coinRecords, diff --git a/lib/src/api/full_node/cached_chia_full_node_interface.dart b/lib/src/api/full_node/cached_chia_full_node_interface.dart index 7aff5e1a..ad7b66bb 100644 --- a/lib/src/api/full_node/cached_chia_full_node_interface.dart +++ b/lib/src/api/full_node/cached_chia_full_node_interface.dart @@ -2,7 +2,10 @@ import 'package:chia_crypto_utils/chia_crypto_utils.dart'; import 'package:chia_crypto_utils/src/api/full_node/full_node_cache.dart'; class CachedChiaFullNodeInterface extends ChiaFullNodeInterface { - factory CachedChiaFullNodeInterface(ChiaFullNodeInterface delegate, FullNodeCache cache) { + factory CachedChiaFullNodeInterface( + ChiaFullNodeInterface delegate, + FullNodeCache cache, + ) { return CachedChiaFullNodeInterface._(delegate.fullNode, delegate, cache); } CachedChiaFullNodeInterface._(super.fullNode, this.delegate, this.cache); diff --git a/lib/src/api/full_node/chia_full_node_interface.dart b/lib/src/api/full_node/chia_full_node_interface.dart index ed8cb287..af6350b4 100644 --- a/lib/src/api/full_node/chia_full_node_interface.dart +++ b/lib/src/api/full_node/chia_full_node_interface.dart @@ -7,7 +7,6 @@ import 'package:chia_crypto_utils/src/api/full_node/exceptions/full_node_error.d import 'package:chia_crypto_utils/src/core/models/block_with_reference_blocks.dart'; import 'package:chia_crypto_utils/src/core/models/blockchain_state.dart'; import 'package:chia_crypto_utils/src/core/models/full_block.dart'; -import 'package:chia_crypto_utils/src/plot_nft/models/exceptions/invalid_pool_singleton_exception.dart'; import 'package:collection/collection.dart'; class ChiaFullNodeInterface { @@ -30,7 +29,8 @@ class ChiaFullNodeInterface { ); } - ChiaFullNodeInterface.fromContext() : fullNode = FullNodeHttpRpc.fromContext(); + ChiaFullNodeInterface.fromContext() + : fullNode = FullNodeHttpRpc.fromContext(); final FullNode fullNode; @@ -48,7 +48,9 @@ class ChiaFullNodeInterface { ); mapResponseToError(recordsResponse); - return recordsResponse.coinRecords.map((record) => record.toCoin()).toList(); + return recordsResponse.coinRecords + .map((record) => record.toCoin()) + .toList(); } Future getBalance( @@ -61,7 +63,8 @@ class ChiaFullNodeInterface { startHeight: startHeight, endHeight: endHeight, ); - final balance = coins.fold(0, (int previousValue, coin) => previousValue + coin.amount); + final balance = + coins.fold(0, (int previousValue, coin) => previousValue + coin.amount); return balance; } @@ -100,7 +103,9 @@ class ChiaFullNodeInterface { ); mapResponseToError(coinRecordsResponse); - return coinRecordsResponse.coinRecords.map((record) => record.toCoin()).toList(); + return coinRecordsResponse.coinRecords + .map((record) => record.toCoin()) + .toList(); } Future> getCoinsByParentIds( @@ -117,7 +122,9 @@ class ChiaFullNodeInterface { ); mapResponseToError(coinRecordsResponse); - return coinRecordsResponse.coinRecords.map((record) => record.toCoin()).toList(); + return coinRecordsResponse.coinRecords + .map((record) => record.toCoin()) + .toList(); } Future> getCoinsByHint( @@ -134,7 +141,9 @@ class ChiaFullNodeInterface { ); mapResponseToError(coinRecordsResponse); - return coinRecordsResponse.coinRecords.map((record) => record.toCoin()).toList(); + return coinRecordsResponse.coinRecords + .map((record) => record.toCoin()) + .toList(); } Future> getCoinsByHints( @@ -252,7 +261,8 @@ class ChiaFullNodeInterface { final launcherAdditions = await launcherSpend!.additionsAsync; - final eveAddition = launcherAdditions.singleWhere((element) => element.amount == 1); + final eveAddition = + launcherAdditions.singleWhere((element) => element.amount == 1); var nftCoin = await getCoinById(eveAddition.id); @@ -273,7 +283,9 @@ class ChiaFullNodeInterface { first = false; } final nextSingletonCoinPrototype = - SingletonService.getMostRecentSingletonCoinFromCoinSpend(nftParentSpend!); + SingletonService.getMostRecentSingletonCoinFromCoinSpend( + nftParentSpend!, + ); nftCoin = await getCoinById(nextSingletonCoinPrototype.id); } @@ -301,7 +313,8 @@ class ChiaFullNodeInterface { final launcherAdditions = await launcherSpend!.additionsAsync; - final evgAddition = launcherAdditions.singleWhere((element) => element.amount == 1); + final evgAddition = + launcherAdditions.singleWhere((element) => element.amount == 1); final evgCoin = await getCoinById(evgAddition.id); @@ -312,7 +325,8 @@ class ChiaFullNodeInterface { return mintInfo; } - final intermediateLauncherCoin = await getCoinById(launcherCoin.parentCoinInfo); + final intermediateLauncherCoin = + await getCoinById(launcherCoin.parentCoinInfo); final didSpend = await getParentSpend(intermediateLauncherCoin!); @@ -340,15 +354,18 @@ class ChiaFullNodeInterface { Future getParentSpend(Coin coin) async { if (coin.coinbase) return null; - final coinSpendResponse = - await fullNode.getPuzzleAndSolution(coin.parentCoinInfo, coin.confirmedBlockIndex); + final coinSpendResponse = await fullNode.getPuzzleAndSolution( + coin.parentCoinInfo, + coin.confirmedBlockIndex, + ); mapResponseToError(coinSpendResponse); return coinSpendResponse.coinSpend; } Future getCoinSpend(Coin coin) async { - final coinSpendResponse = await fullNode.getPuzzleAndSolution(coin.id, coin.spentBlockIndex); + final coinSpendResponse = + await fullNode.getPuzzleAndSolution(coin.id, coin.spentBlockIndex); mapResponseToError(coinSpendResponse); return coinSpendResponse.coinSpend; @@ -409,8 +426,11 @@ class ChiaFullNodeInterface { return List.from(results.where((element) => element != null)); } - Future> scroungeForPlotNfts(List puzzlehashes) async { - final allCoins = await getCoinsByPuzzleHashes(puzzlehashes, includeSpentCoins: true); + Future> scroungeForPlotNfts( + List puzzlehashes, + ) async { + final allCoins = + await getCoinsByPuzzleHashes(puzzlehashes, includeSpentCoins: true); final spentCoins = allCoins.where((c) => c.isSpent); final plotNfts = []; @@ -423,7 +443,7 @@ class ChiaFullNodeInterface { try { final plotNft = await getPlotNftByLauncherId(launcherId); plotNfts.add(plotNft!); - } on InvalidPoolSingletonException { + } catch (e) { // pass. Launcher id was not for plot nft } } @@ -437,20 +457,28 @@ class ChiaFullNodeInterface { if (launcherCoin == null) { return null; } + final launcherCoinSpend = await getCoinSpend(launcherCoin); - final initialExtraData = PlotNftWalletService.launcherCoinSpendToExtraData(launcherCoinSpend!); + final initialExtraData = + PlotNftWalletService.launcherCoinSpendToExtraData(launcherCoinSpend!); final firstSingletonCoinPrototype = - SingletonService.getMostRecentSingletonCoinFromCoinSpend(launcherCoinSpend); + SingletonService.getMostRecentSingletonCoinFromCoinSpend( + launcherCoinSpend, + ); var lastNotNullPoolState = initialExtraData.poolState; var singletonCoin = await getCoinById(firstSingletonCoinPrototype.id); + CoinSpend? lastCoinSpend; while (singletonCoin!.isSpent) { - final lastCoinSpend = (await getCoinSpend(singletonCoin))!; + lastCoinSpend = await getCoinSpend(singletonCoin); final nextSingletonCoinPrototype = - SingletonService.getMostRecentSingletonCoinFromCoinSpend(lastCoinSpend); - final poolState = PlotNftWalletService.coinSpendToPoolState(lastCoinSpend); + SingletonService.getMostRecentSingletonCoinFromCoinSpend( + lastCoinSpend!, + ); + final poolState = + PlotNftWalletService.coinSpendToPoolState(lastCoinSpend); if (poolState != null) { lastNotNullPoolState = poolState; } @@ -458,6 +486,23 @@ class ChiaFullNodeInterface { singletonCoin = await getCoinById(nextSingletonCoinPrototype.id); } + LineageProof? lineageProof; + if (singletonCoin.parentCoinInfo == launcherId) { + lineageProof = LineageProof( + parentCoinInfo: launcherCoin.parentCoinInfo, + innerPuzzlehash: null, + amount: launcherCoin.amount, + ); + } else { + final innerPuzzle = lastCoinSpend!.puzzleReveal.uncurry().arguments[1]; + + lineageProof = LineageProof( + parentCoinInfo: lastCoinSpend.coin.parentCoinInfo, + innerPuzzlehash: innerPuzzle.hash(), + amount: lastCoinSpend.coin.amount, + ); + } + PlotNftWalletService().validateSingletonPuzzlehash( singletonPuzzlehash: singletonCoin.puzzlehash, launcherId: launcherId, @@ -472,6 +517,7 @@ class ChiaFullNodeInterface { poolState: lastNotNullPoolState, delayPuzzlehash: initialExtraData.delayPuzzlehash, delayTime: initialExtraData.delayTime, + lineageProof: lineageProof, ); } @@ -480,7 +526,8 @@ class ChiaFullNodeInterface { Future> scroungeForExchangeInitializationCoins( List puzzlehashes, ) async { - final allCoins = await getCoinsByPuzzleHashes(puzzlehashes, includeSpentCoins: true); + final allCoins = + await getCoinsByPuzzleHashes(puzzlehashes, includeSpentCoins: true); final initializationCoins = []; for (final coin in allCoins) { @@ -491,7 +538,9 @@ class ChiaFullNodeInterface { final paymentsAndAdditions = await coinSpend!.paymentsAndAdditionsAsync; // if there is no 3 mojo child, which is used to cancel the offer, this is not a valid initialization coin - if (paymentsAndAdditions.additions.where((addition) => addition.amount == 3).isEmpty) { + if (paymentsAndAdditions.additions + .where((addition) => addition.amount == 3) + .isEmpty) { continue; } @@ -502,13 +551,16 @@ class ChiaFullNodeInterface { try { final derivationIndexMemo = decodeInt(memos.first); - if (derivationIndexMemo.toString().length != ExchangeOfferService.derivationIndexLength) { + if (derivationIndexMemo.toString().length != + ExchangeOfferService.derivationIndexLength) { continue; } final serializedOfferFileMemo = memos.last.decodedString; final offerFile = - await CrossChainOfferFile.fromSerializedOfferFileAsync(serializedOfferFileMemo!); + await CrossChainOfferFile.fromSerializedOfferFileAsync( + serializedOfferFileMemo!, + ); if (offerFile.prefix != CrossChainOfferFilePrefix.ccoffer) continue; } catch (e) { continue; @@ -522,7 +574,8 @@ class ChiaFullNodeInterface { Future> scroungeForReceivedNotificationCoins( List puzzlehashes, ) async { - final coinsByHint = await getCoinsByHints(puzzlehashes, includeSpentCoins: true); + final coinsByHint = + await getCoinsByHints(puzzlehashes, includeSpentCoins: true); final spentCoins = coinsByHint.where((c) => c.isSpent); final notificationCoins = []; @@ -549,7 +602,8 @@ class ChiaFullNodeInterface { Future> scroungeForSentNotificationCoins( List puzzlehashes, ) async { - final allCoins = await getCoinsByPuzzleHashes(puzzlehashes, includeSpentCoins: true); + final allCoins = + await getCoinsByPuzzleHashes(puzzlehashes, includeSpentCoins: true); final spentCoins = allCoins.where((c) => c.isSpent); final notificationCoins = []; @@ -583,7 +637,10 @@ class ChiaFullNodeInterface { if (coin.isNotSpent) return null; final parentCoinSpend = await getParentSpend(coin); - return NotificationCoin.fromParentSpend(parentCoinSpend: parentCoinSpend!, coin: coin); + return NotificationCoin.fromParentSpend( + parentCoinSpend: parentCoinSpend!, + coin: coin, + ); } Future checkForSpentCoins(List coins) async { @@ -600,14 +657,19 @@ class ChiaFullNodeInterface { return blockchainStateResponse.blockchainState; } - Future> getBlockRecords(int startHeight, int endHeight) async { + Future> getBlockRecords( + int startHeight, + int endHeight, + ) async { final response = await fullNode.getBlockRecords(startHeight, endHeight); mapResponseToError(response); return response.blockRecords!; } - Future getBlockRecordByHeight(int height) async { + Future getBlockRecordByHeight( + int height, + ) async { final response = await fullNode.getBlockRecordByHeight(height); mapResponseToError(response); @@ -617,7 +679,10 @@ class ChiaFullNodeInterface { Future getAdditionsAndRemovals(Bytes headerHash) async { final response = await fullNode.getAdditionsAndRemovals(headerHash); mapResponseToError(response); - return AdditionsAndRemovals(additions: response.additions!, removals: response.removals!); + return AdditionsAndRemovals( + additions: response.additions!, + removals: response.removals!, + ); } Future getAllMempoolItems() async { @@ -625,14 +690,18 @@ class ChiaFullNodeInterface { return response; } - Future> getDidRecordsByPuzzleHashes(List puzzlehashes) async { - final spentCoins = (await getCoinsByPuzzleHashes(puzzlehashes, includeSpentCoins: true)) - .where((coin) => coin.spentBlockIndex != 0); + Future> getDidRecordsByPuzzleHashes( + List puzzlehashes, + ) async { + final spentCoins = + (await getCoinsByPuzzleHashes(puzzlehashes, includeSpentCoins: true)) + .where((coin) => coin.spentBlockIndex != 0); final launcherCoinPrototypes = []; for (final spentCoin in spentCoins) { final coinSpend = await getCoinSpend(spentCoin); - final createCoinConditions = BaseWalletService.extractConditionsFromSolution( + final createCoinConditions = + BaseWalletService.extractConditionsFromSolution( coinSpend!.solution, CreateCoinCondition.isThisCondition, CreateCoinCondition.fromProgram, @@ -670,7 +739,8 @@ class ChiaFullNodeInterface { final originCoinSpend = await getCoinSpend(originCoin!); // didPuzzlehash is first argument in origin coin spend solution - final didPuzzlehash = Puzzlehash(originCoinSpend!.solution.toList()[0].atom); + final didPuzzlehash = + Puzzlehash(originCoinSpend!.solution.toList()[0].atom); final eveCoinPrototype = CoinPrototype( parentCoinInfo: originCoin.id, @@ -695,7 +765,9 @@ class ChiaFullNodeInterface { while (didCoin!.isSpent) { didCoinParentSpend = await getCoinSpend(didCoin); final nextSingletonCoinPrototype = - SingletonService.getMostRecentSingletonCoinFromCoinSpend(didCoinParentSpend!); + SingletonService.getMostRecentSingletonCoinFromCoinSpend( + didCoinParentSpend!, + ); didCoin = await getCoinById(nextSingletonCoinPrototype.id); } @@ -714,7 +786,8 @@ class ChiaFullNodeInterface { final errorMessage = baseResponse.error!; // no error on resource not found - if (errorMessage.contains('not found') || passStrings.any(errorMessage.contains)) { + if (errorMessage.contains('not found') || + passStrings.any(errorMessage.contains)) { return; } @@ -735,7 +808,8 @@ class ChiaFullNodeInterface { Future getDateTimeFromBlockIndex(int spentBlockIndex) async { try { - final blockRecordByHeight = await fullNode.getBlockRecordByHeight(spentBlockIndex); + final blockRecordByHeight = + await fullNode.getBlockRecordByHeight(spentBlockIndex); return blockRecordByHeight.blockRecord?.dateTime; } catch (e) { return null; @@ -760,7 +834,8 @@ class ChiaFullNodeInterface { Future getSingleChildCoinFromCoin(Coin messageCoin) async { try { final messageCoinSpend = await getCoinSpend(messageCoin); - final messageCoinChildId = (await messageCoinSpend!.additionsAsync).single.id; + final messageCoinChildId = + (await messageCoinSpend!.additionsAsync).single.id; final messageCoinChild = await getCoinById(messageCoinChildId); return messageCoinChild; } catch (e) { @@ -769,13 +844,16 @@ class ChiaFullNodeInterface { } Future getBlockByIndex(int index) async { - final response = await fullNode.getBlocks(index, index + 1, excludeReorged: true); + final response = + await fullNode.getBlocks(index, index + 1, excludeReorged: true); mapResponseToError(response); return response.blocks.singleOrNull; } - Future getBlockWithReferenceBlocks(int index) async { + Future getBlockWithReferenceBlocks( + int index, + ) async { final block = await getBlockByIndex(index); if (block == null) { diff --git a/lib/src/api/full_node/full_node.dart b/lib/src/api/full_node/full_node.dart index 60afaf6f..5f88a7dd 100644 --- a/lib/src/api/full_node/full_node.dart +++ b/lib/src/api/full_node/full_node.dart @@ -41,7 +41,9 @@ abstract class FullNode { Future getBlockchainState(); - Future getAdditionsAndRemovals(Bytes headerHash); + Future getAdditionsAndRemovals( + Bytes headerHash, + ); Future getBlockRecordByHeight(int height); Future getBlockRecords(int start, int end); diff --git a/lib/src/api/full_node/full_node_http_rpc.dart b/lib/src/api/full_node/full_node_http_rpc.dart index 511dd80a..34b2e0b3 100644 --- a/lib/src/api/full_node/full_node_http_rpc.dart +++ b/lib/src/api/full_node/full_node_http_rpc.dart @@ -102,7 +102,8 @@ class FullNodeHttpRpc implements FullNode { if (endHeight != null) { body['end_height'] = endHeight; } - final response = await client.post(Uri.parse('get_coin_records_by_hint'), body); + final response = + await client.post(Uri.parse('get_coin_records_by_hint'), body); mapResponseToError(response); return CoinRecordsResponse.fromJson( @@ -127,7 +128,8 @@ class FullNodeHttpRpc implements FullNode { body['end_height'] = endHeight; } body['include_spent_coins'] = includeSpentCoins; - final response = await client.post(Uri.parse('get_coin_records_by_parent_ids'), body); + final response = + await client.post(Uri.parse('get_coin_records_by_parent_ids'), body); mapResponseToError(response); return CoinRecordsResponse.fromJson( @@ -164,7 +166,8 @@ class FullNodeHttpRpc implements FullNode { body['end_height'] = endHeight; } body['include_spent_coins'] = includeSpentCoins; - final response = await client.post(Uri.parse('get_coin_records_by_names'), body); + final response = + await client.post(Uri.parse('get_coin_records_by_names'), body); mapResponseToError(response); return CoinRecordsResponse.fromJson( @@ -190,7 +193,8 @@ class FullNodeHttpRpc implements FullNode { @override Future getBlockchainState() async { - final response = await client.post(Uri.parse('get_blockchain_state'), {}); + final response = await client + .post(Uri.parse('get_blockchain_state'), {}); mapResponseToError(response); return BlockchainStateResponse.fromJson( @@ -199,7 +203,9 @@ class FullNodeHttpRpc implements FullNode { } @override - Future getAdditionsAndRemovals(Bytes headerHash) async { + Future getAdditionsAndRemovals( + Bytes headerHash, + ) async { final response = await client.post( Uri.parse('get_additions_and_removals'), {'header_hash': headerHash.toHex()}, @@ -212,7 +218,9 @@ class FullNodeHttpRpc implements FullNode { } @override - Future getBlockRecordByHeight(int height) async { + Future getBlockRecordByHeight( + int height, + ) async { final response = await client.post( Uri.parse('get_block_record_by_height'), {'height': height}, @@ -243,7 +251,9 @@ class FullNodeHttpRpc implements FullNode { @override bool operator ==(Object other) => identical(this, other) || - other is FullNodeHttpRpc && runtimeType == other.runtimeType && baseURL == other.baseURL; + other is FullNodeHttpRpc && + runtimeType == other.runtimeType && + baseURL == other.baseURL; @override int get hashCode => runtimeType.hashCode ^ baseURL.hashCode; diff --git a/lib/src/api/full_node/full_node_utils.dart b/lib/src/api/full_node/full_node_utils.dart index f302b696..a03c5aa3 100644 --- a/lib/src/api/full_node/full_node_utils.dart +++ b/lib/src/api/full_node/full_node_utils.dart @@ -12,7 +12,8 @@ class FullNodeUtils { static const String defaultUrl = 'https://localhost:8555'; - String get checkNetworkMessage => 'Check if your full node is runing on $network'; + String get checkNetworkMessage => + 'Check if your full node is runing on $network'; String get sslPath => '${Platform.environment['HOME']}/.chia/${network.name}/config/ssl/full_node'; diff --git a/lib/src/api/full_node/models/chia_models/mempool_item.dart b/lib/src/api/full_node/models/chia_models/mempool_item.dart index f0d2c263..e93a9c5d 100644 --- a/lib/src/api/full_node/models/chia_models/mempool_item.dart +++ b/lib/src/api/full_node/models/chia_models/mempool_item.dart @@ -10,15 +10,18 @@ class MempoolItem { }); factory MempoolItem.fromJson(Map json) { - final additions = List>.from(json['additions'] as Iterable) - .map(CoinPrototype.fromJson) - .toList(); - final removals = List>.from(json['removals'] as Iterable) - .map(CoinPrototype.fromJson) - .toList(); + final additions = + List>.from(json['additions'] as Iterable) + .map(CoinPrototype.fromJson) + .toList(); + final removals = + List>.from(json['removals'] as Iterable) + .map(CoinPrototype.fromJson) + .toList(); final fee = json['fee'] as int; - final spendBundle = SpendBundle.fromJson(json['spend_bundle'] as Map); + final spendBundle = + SpendBundle.fromJson(json['spend_bundle'] as Map); final spendBundleId = Bytes.fromHex(json['spend_bundle_name'] as String); return MempoolItem( diff --git a/lib/src/api/full_node/models/chia_models/npc_result.dart b/lib/src/api/full_node/models/chia_models/npc_result.dart index 356860e0..5a88c197 100644 --- a/lib/src/api/full_node/models/chia_models/npc_result.dart +++ b/lib/src/api/full_node/models/chia_models/npc_result.dart @@ -6,9 +6,10 @@ class NpcResult { factory NpcResult.fromJson(Map json) { final cost = json['clvm_cost'] as int?; final conds = json['conds'] as Map; - final spendConditionsList = List>.from(conds['spends'] as Iterable) - .map(SpendConditions.fromJson) - .toList(); + final spendConditionsList = + List>.from(conds['spends'] as Iterable) + .map(SpendConditions.fromJson) + .toList(); return NpcResult(cost, spendConditionsList); } diff --git a/lib/src/api/full_node/models/chia_models/spend_conditions.dart b/lib/src/api/full_node/models/chia_models/spend_conditions.dart index 26cbde03..bcd83a6c 100644 --- a/lib/src/api/full_node/models/chia_models/spend_conditions.dart +++ b/lib/src/api/full_node/models/chia_models/spend_conditions.dart @@ -9,11 +9,12 @@ class SpendConditions { factory SpendConditions.fromJson(Map json) { print(json); - final createCoinConditions = List>.from(json['create_coin'] as Iterable) - .map( - (e) => CreateCoinCondition.fromJsonList(List.from(e)), - ) - .toList(); + final createCoinConditions = + List>.from(json['create_coin'] as Iterable) + .map( + (e) => CreateCoinCondition.fromJsonList(List.from(e)), + ) + .toList(); final coinId = Bytes.fromHex(json['coin_name'] as String); final puzzlehash = Puzzlehash.fromHex(json['puzzle_hash'] as String); diff --git a/lib/src/api/full_node/models/responses/coin_records_response.dart b/lib/src/api/full_node/models/responses/coin_records_response.dart index 8d617ef9..ecd9fe0f 100644 --- a/lib/src/api/full_node/models/responses/coin_records_response.dart +++ b/lib/src/api/full_node/models/responses/coin_records_response.dart @@ -18,7 +18,8 @@ class CoinRecordsResponse extends ChiaBaseResponse { final coinRecords = json['coin_records'] != null ? (json['coin_records'] as List) .map( - (dynamic value) => ChiaCoinRecord.fromJson(value as Map), + (dynamic value) => + ChiaCoinRecord.fromJson(value as Map), ) .toList() : []; diff --git a/lib/src/api/full_node/models/responses/coin_spend_response.dart b/lib/src/api/full_node/models/responses/coin_spend_response.dart index cf7f2c6b..9e445b35 100644 --- a/lib/src/api/full_node/models/responses/coin_spend_response.dart +++ b/lib/src/api/full_node/models/responses/coin_spend_response.dart @@ -25,5 +25,6 @@ class CoinSpendResponse extends ChiaBaseResponse { final CoinSpend? coinSpend; @override - String toString() => 'CoinSpendResponse(coinSpend: $coinSpend, success: $success, error: $error)'; + String toString() => + 'CoinSpendResponse(coinSpend: $coinSpend, success: $success, error: $error)'; } diff --git a/lib/src/api/full_node/models/responses/get_additions_and_removals_response.dart b/lib/src/api/full_node/models/responses/get_additions_and_removals_response.dart index b4a821b2..3c8eb1d9 100644 --- a/lib/src/api/full_node/models/responses/get_additions_and_removals_response.dart +++ b/lib/src/api/full_node/models/responses/get_additions_and_removals_response.dart @@ -15,9 +15,12 @@ class GetAdditionsAndRemovalsResponse extends ChiaBaseResponse { if (chiaBaseResponse.success) { return GetAdditionsAndRemovalsResponse( - additions: - _coinListFromJson(List>.from(json['additions'] as Iterable)), - removals: _coinListFromJson(List>.from(json['removals'] as Iterable)), + additions: _coinListFromJson( + List>.from(json['additions'] as Iterable), + ), + removals: _coinListFromJson( + List>.from(json['removals'] as Iterable), + ), success: chiaBaseResponse.success, error: chiaBaseResponse.error, ); diff --git a/lib/src/api/full_node/models/responses/get_block_record_by_height_response.dart b/lib/src/api/full_node/models/responses/get_block_record_by_height_response.dart index 6a287ba3..296587c3 100644 --- a/lib/src/api/full_node/models/responses/get_block_record_by_height_response.dart +++ b/lib/src/api/full_node/models/responses/get_block_record_by_height_response.dart @@ -13,7 +13,8 @@ class GetBlockRecordByHeightResponse extends ChiaBaseResponse { final chiaBaseResponse = ChiaBaseResponse.fromJson(json); return GetBlockRecordByHeightResponse( - blockRecord: BlockRecord.fromJson(json['block_record'] as Map), + blockRecord: + BlockRecord.fromJson(json['block_record'] as Map), success: chiaBaseResponse.success, error: chiaBaseResponse.error, ); diff --git a/lib/src/api/full_node/models/responses/mempool_items_response.dart b/lib/src/api/full_node/models/responses/mempool_items_response.dart index c7b2f1f6..ee397517 100644 --- a/lib/src/api/full_node/models/responses/mempool_items_response.dart +++ b/lib/src/api/full_node/models/responses/mempool_items_response.dart @@ -8,7 +8,9 @@ class MempoolItemsResponse { final mempoolItemsJson = json['mempool_items'] as Map; for (final mempoolItemJsonEntry in mempoolItemsJson.entries) { mempoolItemMap[Bytes.fromHex(mempoolItemJsonEntry.key)] = - MempoolItem.fromJson(mempoolItemJsonEntry.value as Map); + MempoolItem.fromJson( + mempoolItemJsonEntry.value as Map, + ); } return MempoolItemsResponse(mempoolItemMap); diff --git a/lib/src/api/full_node/simulator/simulator_full_node_interface.dart b/lib/src/api/full_node/simulator/simulator_full_node_interface.dart index 6e72478a..8ea0dbd2 100644 --- a/lib/src/api/full_node/simulator/simulator_full_node_interface.dart +++ b/lib/src/api/full_node/simulator/simulator_full_node_interface.dart @@ -8,7 +8,9 @@ class SimulatorFullNodeInterface extends ChiaFullNodeInterface { SimulatorFullNodeInterface(this.fullNode) : super(fullNode); factory SimulatorFullNodeInterface.withDefaultUrl() { - return SimulatorFullNodeInterface(SimulatorHttpRpc(SimulatorUtils.defaultUrl)); + return SimulatorFullNodeInterface( + SimulatorHttpRpc(SimulatorUtils.defaultUrl), + ); } @override @@ -19,7 +21,10 @@ class SimulatorFullNodeInterface extends ChiaFullNodeInterface { static const utilAddress = Address('xch1ye5dzd44kkatnxx2je4s2agpwtqds5lsm5mlyef7plum5danxalq2dnqap'); - Future moveToNextBlock({int blocks = 1, bool makeCallForEachBlock = true}) async { + Future moveToNextBlock({ + int blocks = 1, + bool makeCallForEachBlock = true, + }) async { if (makeCallForEachBlock) { for (var i = 0; i < blocks; i++) { await fullNode.farmTransactionBlocks(utilAddress); diff --git a/lib/src/api/full_node/simulator/simulator_http_rpc.dart b/lib/src/api/full_node/simulator/simulator_http_rpc.dart index 167c42f7..af240b63 100644 --- a/lib/src/api/full_node/simulator/simulator_http_rpc.dart +++ b/lib/src/api/full_node/simulator/simulator_http_rpc.dart @@ -6,7 +6,12 @@ import 'package:chia_crypto_utils/chia_crypto_utils.dart'; import 'package:chia_crypto_utils/src/api/full_node/simulator/responses/auto_farm_response.dart'; class SimulatorHttpRpc extends FullNodeHttpRpc { - const SimulatorHttpRpc(super.baseUrl, {super.certBytes, super.keyBytes,super.timeout,}); + const SimulatorHttpRpc( + super.baseUrl, { + super.certBytes, + super.keyBytes, + super.timeout, + }); Future farmTransactionBlocks( Address address, { @@ -15,7 +20,11 @@ class SimulatorHttpRpc extends FullNodeHttpRpc { }) async { final responseData = await client.post( Uri.parse('farm_block'), - {'address': address.address, 'blocks': blocks, 'guarantee_tx_block': transactionBlock}, + { + 'address': address.address, + 'blocks': blocks, + 'guarantee_tx_block': transactionBlock + }, ); FullNodeHttpRpc.mapResponseToError(responseData); @@ -24,7 +33,9 @@ class SimulatorHttpRpc extends FullNodeHttpRpc { ); } - Future updateAutofarmConfig({required bool shouldAutofarm}) async { + Future updateAutofarmConfig({ + required bool shouldAutofarm, + }) async { final responseData = await client.post( Uri.parse('set_auto_farming'), {'auto_farm': shouldAutofarm}, diff --git a/lib/src/api/full_node/simulator/util/chia_enthusiast.dart b/lib/src/api/full_node/simulator/util/chia_enthusiast.dart index 4779942e..40f6c04b 100644 --- a/lib/src/api/full_node/simulator/util/chia_enthusiast.dart +++ b/lib/src/api/full_node/simulator/util/chia_enthusiast.dart @@ -16,7 +16,8 @@ class ChiaEnthusiast extends ChiaEnthusiastBase { Wallet get wallet => ColdWallet(fullNode: fullNode, keychain: keychain); - OfferService get offerService => OfferService(wallet, OfferWalletService(catWalletService)); + OfferService get offerService => + OfferService(wallet, OfferWalletService(catWalletService)); EnhancedChiaFullNodeInterface get fullNode => EnhancedChiaFullNodeInterface.fromUrl(fullNodeSimulator.fullNode.baseURL); @@ -36,7 +37,8 @@ class ChiaEnthusiast extends ChiaEnthusiastBase { } Future refreshCoins() async { - standardCoins = await fullNodeSimulator.getCoinsByPuzzleHashes(puzzlehashes); + standardCoins = + await fullNodeSimulator.getCoinsByPuzzleHashes(puzzlehashes); catCoins = (await fullNode.getCatCoinsByHints(puzzlehashes)) .where((element) => element.type == catType) @@ -55,17 +57,21 @@ class ChiaEnthusiast extends ChiaEnthusiastBase { await refreshCoins(); final privateKeyForCat = privateKey ?? firstWalletVector.childPrivateKey; - final curriedTail = - delegatedTailProgram.curry([Program.fromAtom(privateKeyForCat.getG1().toBytes())]); + final curriedTail = delegatedTailProgram + .curry([Program.fromAtom(privateKeyForCat.getG1().toBytes())]); final assetId = Puzzlehash(curriedTail.hash()); final originCoin = standardCoins[0]; final curriedGenesisByCoinIdPuzzle = genesisByCoinIdProgram.curry([Program.fromAtom(originCoin.id)]); - final tailSolution = Program.list([curriedGenesisByCoinIdPuzzle, Program.nil]); + final tailSolution = + Program.list([curriedGenesisByCoinIdPuzzle, Program.nil]); - final signature = AugSchemeMPL.sign(privateKeyForCat, curriedGenesisByCoinIdPuzzle.hash()); + final signature = AugSchemeMPL.sign( + privateKeyForCat, + curriedGenesisByCoinIdPuzzle.hash(), + ); final spendBundle = catWalletService.makeIssuanceSpendbundle( tail: curriedTail, @@ -87,7 +93,8 @@ class ChiaEnthusiast extends ChiaEnthusiastBase { Future issueDid([List recoveryIds = const []]) async { await refreshCoins(); - final didRecoverySpendBundle = didWalletService.createGenerateDIDSpendBundle( + final didRecoverySpendBundle = + didWalletService.createGenerateDIDSpendBundle( standardCoins: [standardCoins[0]], targetPuzzleHash: firstWalletVector.puzzlehash, keychain: keychain, @@ -100,7 +107,8 @@ class ChiaEnthusiast extends ChiaEnthusiastBase { await fullNodeSimulator.moveToNextBlock(); - final didInfos = await fullNodeSimulator.getDidRecordsFromHint(firstWalletVector.puzzlehash); + final didInfos = await fullNodeSimulator + .getDidRecordsFromHint(firstWalletVector.puzzlehash); if (didInfos.length > 1) { throw Exception('Chia enthusiast can only have one did'); @@ -114,10 +122,12 @@ class ChiaEnthusiast extends ChiaEnthusiastBase { if (didInfo == null) { throw Exception('Did must be issued before it can be refreshed'); } - didInfo = (await fullNodeSimulator.getDidRecordForDid(didInfo!.did))?.toDidInfo(keychain); + didInfo = (await fullNodeSimulator.getDidRecordForDid(didInfo!.did)) + ?.toDidInfo(keychain); } Future recoverDid(Bytes did) async { - didInfo = (await fullNodeSimulator.getDidRecordForDid(did))?.toDidInfo(keychain); + didInfo = + (await fullNodeSimulator.getDidRecordForDid(did))?.toDidInfo(keychain); } } diff --git a/lib/src/api/full_node/simulator/util/chia_enthusiast_base.dart b/lib/src/api/full_node/simulator/util/chia_enthusiast_base.dart index 72fd382f..68c95738 100644 --- a/lib/src/api/full_node/simulator/util/chia_enthusiast_base.dart +++ b/lib/src/api/full_node/simulator/util/chia_enthusiast_base.dart @@ -22,8 +22,10 @@ class ChiaEnthusiastBase { List standardCoins = []; List catCoins = []; - List get cat1Coins => catCoins.where((c) => c.catVersion == 1).toList(); - List get cat2Coins => catCoins.where((c) => c.catVersion == 2).toList(); + List get cat1Coins => + catCoins.where((c) => c.catVersion == 1).toList(); + List get cat2Coins => + catCoins.where((c) => c.catVersion == 2).toList(); DidInfo? didInfo; late WalletKeychain keychain; @@ -34,10 +36,12 @@ class ChiaEnthusiastBase { List get outerPuzzlehashes => keychain.unhardenedMap.values.fold( [], - (previousValue, wv) => previousValue + wv.assetIdtoOuterPuzzlehash.values.toList(), + (previousValue, wv) => + previousValue + wv.assetIdtoOuterPuzzlehash.values.toList(), ); - UnhardenedWalletVector get firstWalletVector => keychain.unhardenedMap.values.first; + UnhardenedWalletVector get firstWalletVector => + keychain.unhardenedMap.values.first; Puzzlehash get firstPuzzlehash => firstWalletVector.puzzlehash; diff --git a/lib/src/api/full_node/simulator/util/simulator_utils.dart b/lib/src/api/full_node/simulator/util/simulator_utils.dart index 7f8e892e..b3b3a6a9 100644 --- a/lib/src/api/full_node/simulator/util/simulator_utils.dart +++ b/lib/src/api/full_node/simulator/util/simulator_utils.dart @@ -18,12 +18,16 @@ class SimulatorUtils { return null; } - final json = jsonDecode(genPathFile.readAsStringSync()) as Map; + final json = + jsonDecode(genPathFile.readAsStringSync()) as Map; return json['path'] as String; } + static String? simulatorGeneratedFilesPathOverride; + // if you are using this class outside of chia-crypto-utils you must set FULL_NODE_SIMULATOR_GEN_PATH - static String simulatorGeneratedFilesPathVariableName = 'FULL_NODE_SIMULATOR_GEN_PATH'; + static String simulatorGeneratedFilesPathVariableName = + 'FULL_NODE_SIMULATOR_GEN_PATH'; static String get defaultgeneratedFilesPath => path.join(path.current, 'lib/src/api/full_node/simulator/run'); diff --git a/lib/src/api/namesdao/models/name_info.dart b/lib/src/api/namesdao/models/name_info.dart index a4049824..0f05e78c 100644 --- a/lib/src/api/namesdao/models/name_info.dart +++ b/lib/src/api/namesdao/models/name_info.dart @@ -4,7 +4,8 @@ class NameInfo with ToJsonMixin { NameInfo({ required this.address, }); - NameInfo.fromJson(Map json) : address = Address(json['address'] as String); + NameInfo.fromJson(Map json) + : address = Address(json['address'] as String); final Address address; diff --git a/lib/src/api/namesdao/models/name_registration_price.dart b/lib/src/api/namesdao/models/name_registration_price.dart index dc427843..d6367923 100644 --- a/lib/src/api/namesdao/models/name_registration_price.dart +++ b/lib/src/api/namesdao/models/name_registration_price.dart @@ -22,7 +22,10 @@ class NameRegistrationPrice extends Equatable { } } - return NameRegistrationPrice(xch: pick(json, _xchKey).asDoubleOrThrow(), catPrices: catPrices); + return NameRegistrationPrice( + xch: pick(json, _xchKey).asDoubleOrThrow(), + catPrices: catPrices, + ); } static const _xchKey = 'XCH'; diff --git a/lib/src/api/namesdao/namesdao_api.dart b/lib/src/api/namesdao/namesdao_api.dart index 63d03481..a9dd0bab 100644 --- a/lib/src/api/namesdao/namesdao_api.dart +++ b/lib/src/api/namesdao/namesdao_api.dart @@ -36,8 +36,11 @@ class _NamesdaoApi implements NamesdaoApi { @override Future getRegistrationInfo() async { - final response = await Client('https://api.namesdao.org/v1').get(Uri.parse('info')); + final response = + await Client('https://api.namesdao.org/v1').get(Uri.parse('info')); - return NameRegistrationInfo.fromJson(jsonDecode(response.body) as Map); + return NameRegistrationInfo.fromJson( + jsonDecode(response.body) as Map, + ); } } diff --git a/lib/src/api/nft_minting/uri_hash_provider.dart b/lib/src/api/nft_minting/uri_hash_provider.dart index 1c430992..e06c2f1e 100644 --- a/lib/src/api/nft_minting/uri_hash_provider.dart +++ b/lib/src/api/nft_minting/uri_hash_provider.dart @@ -29,7 +29,9 @@ class _UriHashProvider implements UriHashProvider { Future getHashForUri(String uri) async { final data = await http.get(Uri.parse(uri)); if (data.statusCode != 200) { - throw HttpException('Error fetching uri $uri (code: ${data.statusCode}, msg: ${data.body})'); + throw HttpException( + 'Error fetching uri $uri (code: ${data.statusCode}, msg: ${data.body})', + ); } return Bytes(data.bodyBytes).sha256Hash(); diff --git a/lib/src/api/pool/models/get_farmer_response.dart b/lib/src/api/pool/models/get_farmer_response.dart index 8bd6f50b..4ead8f77 100644 --- a/lib/src/api/pool/models/get_farmer_response.dart +++ b/lib/src/api/pool/models/get_farmer_response.dart @@ -9,8 +9,10 @@ class GetFarmerResponse { }); factory GetFarmerResponse.fromJson(Map json) { return GetFarmerResponse( - authenticationPublicKey: JacobianPoint.fromHexG1(json['authentication_public_key'] as String), - payoutInstructions: Puzzlehash.fromHex(json['payout_instructions'] as String), + authenticationPublicKey: + JacobianPoint.fromHexG1(json['authentication_public_key'] as String), + payoutInstructions: + Puzzlehash.fromHex(json['payout_instructions'] as String), currentDifficulty: json['current_difficulty'] as int, currentPoints: json['current_points'] as int, ); diff --git a/lib/src/api/pool/models/pool_info.dart b/lib/src/api/pool/models/pool_info.dart index 51b32af3..a4b003c8 100644 --- a/lib/src/api/pool/models/pool_info.dart +++ b/lib/src/api/pool/models/pool_info.dart @@ -15,13 +15,16 @@ class PoolInfo { factory PoolInfo.fromJson(Map json) { return PoolInfo( description: json['description'] as String, - fee: json['fee'] is double ? json['fee'].toString() : json['fee'] as String, + fee: json['fee'] is double + ? json['fee'].toString() + : json['fee'] as String, logoUrl: json['logo_url'] as String, minimumDifficulty: json['minimum_difficulty'] as num, name: json['name'] as String, protocolVersion: json['protocol_version'] as int, relativeLockHeight: json['relative_lock_height'] as int, - targetPuzzlehash: Puzzlehash.fromHex(json['target_puzzle_hash'] as String), + targetPuzzlehash: + Puzzlehash.fromHex(json['target_puzzle_hash'] as String), authenticationTokenTimeout: json['authentication_token_timeout'] as int, ); } @@ -36,5 +39,6 @@ class PoolInfo { final int authenticationTokenTimeout; @override - String toString() => 'PoolInfo(name: $name, description: $description, fee: $fee, minimumDifficulty: $minimumDifficulty, protocolVersion: $protocolVersion, relativeLockHeight: $relativeLockHeight, targetPuzzlehash: $targetPuzzlehash, authenticationTokenTimeout: $authenticationTokenTimeout, logoUrl: $logoUrl)'; + String toString() => + 'PoolInfo(name: $name, description: $description, fee: $fee, minimumDifficulty: $minimumDifficulty, protocolVersion: $protocolVersion, relativeLockHeight: $relativeLockHeight, targetPuzzlehash: $targetPuzzlehash, authenticationTokenTimeout: $authenticationTokenTimeout, logoUrl: $logoUrl)'; } diff --git a/lib/src/api/pool/pool_http_rest.dart b/lib/src/api/pool/pool_http_rest.dart index b343715e..e89c80ec 100644 --- a/lib/src/api/pool/pool_http_rest.dart +++ b/lib/src/api/pool/pool_http_rest.dart @@ -27,13 +27,18 @@ class PoolHttpREST { ); } - Future addFarmer(PostFarmerPayload payload, JacobianPoint signature) async { + Future addFarmer( + PostFarmerPayload payload, + JacobianPoint signature, + ) async { final response = await client.post(Uri.parse('farmer'), { 'payload': payload.toJson(), 'signature': signature.toHexWithPrefix(), }); mapResponseToError(response); - return AddFarmerResponse.fromJson(jsonDecode(response.body) as Map); + return AddFarmerResponse.fromJson( + jsonDecode(response.body) as Map, + ); } Future getFarmer( @@ -50,7 +55,9 @@ class PoolHttpREST { }, ); mapResponseToError(response); - return GetFarmerResponse.fromJson(jsonDecode(response.body) as Map); + return GetFarmerResponse.fromJson( + jsonDecode(response.body) as Map, + ); } void mapResponseToError(Response response) { diff --git a/lib/src/api/pool/pool_interface.dart b/lib/src/api/pool/pool_interface.dart index 7d673bc9..0fa37ee5 100644 --- a/lib/src/api/pool/pool_interface.dart +++ b/lib/src/api/pool/pool_interface.dart @@ -3,7 +3,10 @@ import 'package:chia_crypto_utils/chia_crypto_utils.dart'; class PoolInterface { const PoolInterface(this.pool); - factory PoolInterface.fromURL(String poolUrl, {String? certificateBytesPath}) { + factory PoolInterface.fromURL( + String poolUrl, { + String? certificateBytesPath, + }) { return PoolInterface( PoolHttpREST( poolUrl, diff --git a/lib/src/api/pool/service/pool_service_implementation.dart b/lib/src/api/pool/service/pool_service_implementation.dart index 092773e6..15e496bc 100644 --- a/lib/src/api/pool/service/pool_service_implementation.dart +++ b/lib/src/api/pool/service/pool_service_implementation.dart @@ -38,8 +38,9 @@ class PoolServiceImpl implements PoolService { poolUrl: pool.poolUrl, ); - final genesisCoin = - (genesisCoinId != null) ? coins.singleWhere((c) => c.id == genesisCoinId) : coins[0]; + final genesisCoin = (genesisCoinId != null) + ? coins.singleWhere((c) => c.id == genesisCoinId) + : coins[0]; final plotNftSpendBundle = plotNftWalletService.createPoolNftSpendBundle( initialTargetState: initialTargetState, @@ -62,7 +63,8 @@ class PoolServiceImpl implements PoolService { required SingletonWalletVector singletonWalletVector, required Puzzlehash payoutPuzzlehash, }) async { - if (singletonWalletVector.singletonOwnerPublicKey != plotNft.poolState.ownerPublicKey) { + if (singletonWalletVector.singletonOwnerPublicKey != + plotNft.poolState.ownerPublicKey) { throw ArgumentError( 'Provided SingletonWalletVector does not match plotNft owner public key', ); @@ -72,8 +74,10 @@ class PoolServiceImpl implements PoolService { return pool.addFarmer( launcherId: plotNft.launcherId, - authenticationToken: getCurrentAuthenticationToken(poolInfo.authenticationTokenTimeout), - authenticationPublicKey: singletonWalletVector.poolingAuthenticationPublicKey, + authenticationToken: + getCurrentAuthenticationToken(poolInfo.authenticationTokenTimeout), + authenticationPublicKey: + singletonWalletVector.poolingAuthenticationPublicKey, payoutPuzzlehash: payoutPuzzlehash, singletonOwnerPrivateKey: singletonWalletVector.singletonOwnerPrivateKey, ); @@ -86,7 +90,8 @@ class PoolServiceImpl implements PoolService { }) async { final poolInfo = await pool.getPoolInfo(); - final authenticationToken = getCurrentAuthenticationToken(poolInfo.authenticationTokenTimeout); + final authenticationToken = + getCurrentAuthenticationToken(poolInfo.authenticationTokenTimeout); return pool.getFarmer( launcherId: launcherId, diff --git a/lib/src/api/remote_storage/nft_storage_api.dart b/lib/src/api/remote_storage/nft_storage_api.dart index fd199303..c61738d9 100644 --- a/lib/src/api/remote_storage/nft_storage_api.dart +++ b/lib/src/api/remote_storage/nft_storage_api.dart @@ -18,7 +18,9 @@ class _NftStorageApi implements NftStorageApi { ); final decodedBody = utf8.decode(response.bodyBytes, allowMalformed: true); - return NftData0007.fromJson(jsonDecode(decodedBody) as Map); + return NftData0007.fromJson( + jsonDecode(decodedBody) as Map, + ); } } @@ -35,7 +37,9 @@ extension GetNftRecordsWithData on Iterable { } final records = await Future.wait(hydratedRecordFutures); - return List.from(records.where((element) => element != null)); + return List.from( + records.where((element) => element != null), + ); } Future> hydrateAndFetchMintInfo( @@ -50,6 +54,8 @@ extension GetNftRecordsWithData on Iterable { } final records = await Future.wait(hydratedRecordFutures); - return List.from(records.where((element) => element != null)); + return List.from( + records.where((element) => element != null), + ); } } diff --git a/lib/src/api/remote_storage/upload/implementations/nft_storage/nft_storage_upload_api.dart b/lib/src/api/remote_storage/upload/implementations/nft_storage/nft_storage_upload_api.dart index 7e4a37f3..0e4187c2 100644 --- a/lib/src/api/remote_storage/upload/implementations/nft_storage/nft_storage_upload_api.dart +++ b/lib/src/api/remote_storage/upload/implementations/nft_storage/nft_storage_upload_api.dart @@ -16,7 +16,10 @@ class NftStorageUploadApiI implements NftStorageUploadApi { final String _apiKey; @override - Future uploadBytes(Bytes bytes, {ContentType? contentType}) async { + Future uploadBytes( + Bytes bytes, { + ContentType? contentType, + }) async { final response = await http.post( _uri, body: bytes.byteList, @@ -29,7 +32,8 @@ class NftStorageUploadApiI implements NftStorageUploadApi { final body = jsonDecode(response.body) as Map; _validateResponse(response.statusCode, body); - final result = NftStorageUploadResponse.fromJson(pick(body, 'value').asJsonOrThrow()); + final result = + NftStorageUploadResponse.fromJson(pick(body, 'value').asJsonOrThrow()); return result; } diff --git a/lib/src/api/remote_storage/upload/remote_storage_upload_api.dart b/lib/src/api/remote_storage/upload/remote_storage_upload_api.dart index e1fc081c..b05290f7 100644 --- a/lib/src/api/remote_storage/upload/remote_storage_upload_api.dart +++ b/lib/src/api/remote_storage/upload/remote_storage_upload_api.dart @@ -9,7 +9,10 @@ abstract class NftStorageUploadApi { factory NftStorageUploadApi(String apiKey) => NftStorageUploadApiI(apiKey); /// throws [TooManyRequestsException], [NftStorageUploadException] - Future uploadBytes(Bytes bytes, {ContentType? contentType}); + Future uploadBytes( + Bytes bytes, { + ContentType? contentType, + }); } extension UploadTypesX on NftStorageUploadApi { @@ -20,7 +23,10 @@ extension UploadTypesX on NftStorageUploadApi { ); } - Future uploadFile(File file, {ContentType? contentType}) { + Future uploadFile( + File file, { + ContentType? contentType, + }) { return uploadBytes(Bytes(file.readAsBytesSync()), contentType: contentType); } } diff --git a/lib/src/api/remote_storage/upload/remote_storage_upload_api_cache.dart b/lib/src/api/remote_storage/upload/remote_storage_upload_api_cache.dart index f49ebd46..04068507 100644 --- a/lib/src/api/remote_storage/upload/remote_storage_upload_api_cache.dart +++ b/lib/src/api/remote_storage/upload/remote_storage_upload_api_cache.dart @@ -6,7 +6,10 @@ import 'package:chia_crypto_utils/src/api/remote_storage/upload/remote_storage_u import 'package:synchronized/synchronized.dart'; abstract class NftStorageUploadCache { - Future add(RemoteUploadRequest request, NftStorageUploadResponse response); + Future add( + RemoteUploadRequest request, + NftStorageUploadResponse response, + ); NftStorageUploadResponse? get(RemoteUploadRequest request); } @@ -33,7 +36,10 @@ class NftStorageApiJsonCache implements NftStorageUploadCache { } @override - Future add(RemoteUploadRequest request, NftStorageUploadResponse response) { + Future add( + RemoteUploadRequest request, + NftStorageUploadResponse response, + ) { return _lock.synchronized(() async { final json = _currentJson; json[request.cacheKey] = response.toJson(); @@ -48,6 +54,8 @@ class NftStorageApiJsonCache implements NftStorageUploadCache { if (!current.containsKey(key)) { return null; } - return NftStorageUploadResponse.fromJson(current[key] as Map); + return NftStorageUploadResponse.fromJson( + current[key] as Map, + ); } } diff --git a/lib/src/api/remote_storage/upload/remote_storage_upload_api_cached.dart b/lib/src/api/remote_storage/upload/remote_storage_upload_api_cached.dart index e9387f82..29e918d9 100644 --- a/lib/src/api/remote_storage/upload/remote_storage_upload_api_cached.dart +++ b/lib/src/api/remote_storage/upload/remote_storage_upload_api_cached.dart @@ -20,19 +20,24 @@ class NftStorageUploadApiCached implements NftStorageUploadApi { NftStorageUploadApi delegate, { required NftStorageUploadCache cache, }) { - final localStorageCachedApi = NftStorageUploadApiCached._(delegate, cache: cache); + final localStorageCachedApi = + NftStorageUploadApiCached._(delegate, cache: cache); return _SynchronizedRequestUploadApi(localStorageCachedApi); } @override - Future uploadBytes(Bytes bytes, {ContentType? contentType}) async { + Future uploadBytes( + Bytes bytes, { + ContentType? contentType, + }) async { final request = RemoteUploadRequest(bytes, contentType); final cachedResponse = cache.get(request); if (cachedResponse != null) { return cachedResponse; } - final response = await delegate.uploadBytes(bytes, contentType: contentType); + final response = + await delegate.uploadBytes(bytes, contentType: contentType); await cache.add(request, response); @@ -48,7 +53,10 @@ class _SynchronizedRequestUploadApi implements NftStorageUploadApi { final _inProgressRequestMap = >{}; @override - Future uploadBytes(Bytes bytes, {ContentType? contentType}) async { + Future uploadBytes( + Bytes bytes, { + ContentType? contentType, + }) async { final request = RemoteUploadRequest(bytes, contentType); final cacheKey = request.cacheKey; if (_inProgressRequestMap.containsKey(cacheKey)) { @@ -58,7 +66,8 @@ class _SynchronizedRequestUploadApi implements NftStorageUploadApi { _inProgressRequestMap[cacheKey] = completer; try { - final result = await delegate.uploadBytes(bytes, contentType: contentType); + final result = + await delegate.uploadBytes(bytes, contentType: contentType); completer.complete(result); return result; } catch (e, st) { diff --git a/lib/src/api/remote_storage/upload/remote_storage_upload_api_with_backoff.dart b/lib/src/api/remote_storage/upload/remote_storage_upload_api_with_backoff.dart index 63b93201..07c34ec2 100644 --- a/lib/src/api/remote_storage/upload/remote_storage_upload_api_with_backoff.dart +++ b/lib/src/api/remote_storage/upload/remote_storage_upload_api_with_backoff.dart @@ -19,10 +19,14 @@ class NftStorageUploadApiWithBinaryBackoff implements NftStorageUploadApi { final Duration initialBackoffDuration; @override - Future uploadBytes(Bytes bytes, {ContentType? contentType}) async { + Future uploadBytes( + Bytes bytes, { + ContentType? contentType, + }) async { final request = RemoteUploadRequest(bytes, contentType); - final response = await _completeRequestWithBackoff(request, initialBackoffDuration); + final response = + await _completeRequestWithBackoff(request, initialBackoffDuration); return response; } @@ -34,10 +38,15 @@ class NftStorageUploadApiWithBinaryBackoff implements NftStorageUploadApi { int clientExceptionCount = 0, }) async { try { - final response = await delegate.uploadBytes(request.bytes, contentType: request.contentType); + final response = await delegate.uploadBytes( + request.bytes, + contentType: request.contentType, + ); return response; } on TooManyRequestsException { - LoggingContext().info('Too many requests: backing off nft storage for $backoffDuration'); + LoggingContext().info( + 'Too many requests: backing off nft storage for $backoffDuration', + ); await Future.delayed(backoffDuration); return _completeRequestWithBackoff( request, @@ -48,8 +57,9 @@ class NftStorageUploadApiWithBinaryBackoff implements NftStorageUploadApi { LoggingContext().info('max upload socket exceptions reached'); rethrow; } - LoggingContext() - .info('Client exception:${e.message}, backing off nft storage for $backoffDuration'); + LoggingContext().info( + 'Client exception:${e.message}, backing off nft storage for $backoffDuration', + ); await Future.delayed(backoffDuration); return _completeRequestWithBackoff( request, diff --git a/lib/src/api/standard/xch_service.dart b/lib/src/api/standard/xch_service.dart index 5dab05a6..fb349af0 100644 --- a/lib/src/api/standard/xch_service.dart +++ b/lib/src/api/standard/xch_service.dart @@ -32,7 +32,8 @@ class XchService { int fee = 0, Puzzlehash? changePuzzlehash, }) async { - final changePuzzlehashToUse = changePuzzlehash ?? keychain.puzzlehashes.first; + final changePuzzlehashToUse = + changePuzzlehash ?? keychain.puzzlehashes.first; final spendBundle = walletService.createSpendBundle( payments: payments, coinsInput: coins, @@ -58,7 +59,8 @@ class XchService { throw InvalidNamesdaoName(); } else { final puzzlehash = nameInfo.address.toPuzzlehash(); - final response = await sendXch(coins: coins, amount: amount, puzzlehash: puzzlehash); + final response = + await sendXch(coins: coins, amount: amount, puzzlehash: puzzlehash); return response; } } diff --git a/lib/src/api/tail_database/models/tail_info.dart b/lib/src/api/tail_database/models/tail_info.dart index ac836f6c..c5ffd924 100644 --- a/lib/src/api/tail_database/models/tail_info.dart +++ b/lib/src/api/tail_database/models/tail_info.dart @@ -27,7 +27,8 @@ class TailInfo with ToJsonMixin { logoUrl: pick(json, 'nft_uri').asStringOrNull(), websiteUrl: pick(json, 'website_url').asStringOrNull(), clsp: pick(json, 'chialisp').asStringOrNull(), - hashgreenInfo: pick(json, 'hashgreen').letJsonOrNull(HashgreenInfo.fromJson), + hashgreenInfo: + pick(json, 'hashgreen').letJsonOrNull(HashgreenInfo.fromJson), ); } diff --git a/lib/src/api/tail_database/tail_database_api.dart b/lib/src/api/tail_database/tail_database_api.dart index 6b341403..0a4524ae 100644 --- a/lib/src/api/tail_database/tail_database_api.dart +++ b/lib/src/api/tail_database/tail_database_api.dart @@ -21,7 +21,9 @@ class _TailDatabaseApi implements TailDatabaseApi { ); try { - return TailInfo.fromJson(jsonDecode(response.body) as Map); + return TailInfo.fromJson( + jsonDecode(response.body) as Map, + ); } on FormatException catch (e) { throw FormatException( 'Could not to parse response from tail database for asset id $assetId: ${e.message}', diff --git a/lib/src/api/utils/blockchain_utils.dart b/lib/src/api/utils/blockchain_utils.dart index deb699cf..00c05539 100644 --- a/lib/src/api/utils/blockchain_utils.dart +++ b/lib/src/api/utils/blockchain_utils.dart @@ -1,7 +1,10 @@ import 'package:chia_crypto_utils/chia_crypto_utils.dart'; abstract class BlockchainUtils { - factory BlockchainUtils(ChiaFullNodeInterface fullNode, {LoggingFunction? logger}) => + factory BlockchainUtils( + ChiaFullNodeInterface fullNode, { + LoggingFunction? logger, + }) => _BlockchainUtils(fullNode, logger: logger); factory BlockchainUtils.fromContext({LoggingFunction? logger}) => @@ -44,7 +47,10 @@ class _BlockchainUtils implements BlockchainUtils { while (unspentIds.isNotEmpty) { logger(logMessage); - final coins = await fullNode.getCoinsByIds(unspentIds.toList(), includeSpentCoins: true); + final coins = await fullNode.getCoinsByIds( + unspentIds.toList(), + includeSpentCoins: true, + ); final spentCoins = coins.where((coin) => coin.isSpent); diff --git a/lib/src/api/utils/get_spend_bundle_for_coin.dart b/lib/src/api/utils/get_spend_bundle_for_coin.dart index fcc0df82..04c243b6 100644 --- a/lib/src/api/utils/get_spend_bundle_for_coin.dart +++ b/lib/src/api/utils/get_spend_bundle_for_coin.dart @@ -14,7 +14,8 @@ Future constructSpendBundleOfCoin( final thisCoinName = coinId; - final blockWithReferences = await fullNode.getBlockWithReferenceBlocks(coin.spentBlockIndex); + final blockWithReferences = + await fullNode.getBlockWithReferenceBlocks(coin.spentBlockIndex); if (blockWithReferences == null) { return null; @@ -22,8 +23,11 @@ Future constructSpendBundleOfCoin( final outputProgram = await _parseBlock(blockWithReferences); - final blockSpends = - outputProgram.first().toList().map(CoinSpend.fromGeneratorCoinProgram).toList(); + final blockSpends = outputProgram + .first() + .toList() + .map(CoinSpend.fromGeneratorCoinProgram) + .toList(); final puzAnnoCreates = []; final puzAnnoAsserts = []; @@ -42,24 +46,30 @@ Future constructSpendBundleOfCoin( for (final condition in conditions) { switch (condition.code) { case CreateCoinAnnouncementCondition.conditionCode: - final message = (coin.id + condition.arguments.first.atom).sha256Hash(); + final message = + (coin.id + condition.arguments.first.atom).sha256Hash(); - coinAnnoCreates.add(CoinAnnouncementMessage(coinId: coinId, message: message)); + coinAnnoCreates + .add(CoinAnnouncementMessage(coinId: coinId, message: message)); break; case AssertCoinAnnouncementCondition.conditionCode: final message = condition.arguments.first.atom; - coinAnnoAsserts.add(CoinAnnouncementMessage(coinId: coinId, message: message)); + coinAnnoAsserts + .add(CoinAnnouncementMessage(coinId: coinId, message: message)); break; case CreatePuzzleAnnouncementCondition.conditionCode: - final message = (coin.puzzlehash + condition.arguments.first.atom).sha256Hash(); - puzAnnoCreates.add(CoinAnnouncementMessage(coinId: coinId, message: message)); + final message = + (coin.puzzlehash + condition.arguments.first.atom).sha256Hash(); + puzAnnoCreates + .add(CoinAnnouncementMessage(coinId: coinId, message: message)); break; case AssertPuzzleAnnouncementCondition.conditionCode: final message = condition.arguments.first.atom; - puzAnnoAsserts.add(CoinAnnouncementMessage(coinId: coinId, message: message)); + puzAnnoAsserts + .add(CoinAnnouncementMessage(coinId: coinId, message: message)); break; case CreateCoinCondition.conditionCode: @@ -94,30 +104,34 @@ Future constructSpendBundleOfCoin( final coin = coinsToDeal.removeAt(0); coinsDealed.add(coin); - for (final puzzleAnnoAssert in puzAnnoAsserts.where((element) => element.coinId == coin)) { - for (final puzzleAnnoCreate - in puzAnnoCreates.where((element) => element.message == puzzleAnnoAssert.message)) { + for (final puzzleAnnoAssert + in puzAnnoAsserts.where((element) => element.coinId == coin)) { + for (final puzzleAnnoCreate in puzAnnoCreates + .where((element) => element.message == puzzleAnnoAssert.message)) { addToCTD(puzzleAnnoCreate.coinId); } } - for (final puzzleAnnoCreate in puzAnnoCreates.where((element) => element.coinId == coin)) { - for (final puzzleAnnoAssert - in puzAnnoAsserts.where((element) => element.message == puzzleAnnoCreate.message)) { + for (final puzzleAnnoCreate + in puzAnnoCreates.where((element) => element.coinId == coin)) { + for (final puzzleAnnoAssert in puzAnnoAsserts + .where((element) => element.message == puzzleAnnoCreate.message)) { addToCTD(puzzleAnnoAssert.coinId); } } - for (final coinAnnoAssert in coinAnnoAsserts.where((element) => element.coinId == coin)) { - for (final coinAnnoCreate - in coinAnnoCreates.where((element) => element.message == coinAnnoAssert.message)) { + for (final coinAnnoAssert + in coinAnnoAsserts.where((element) => element.coinId == coin)) { + for (final coinAnnoCreate in coinAnnoCreates + .where((element) => element.message == coinAnnoAssert.message)) { addToCTD(coinAnnoCreate.coinId); } } - for (final coinAnnoCreate in coinAnnoCreates.where((element) => element.coinId == coin)) { - for (final coinAnnoAssert - in coinAnnoAsserts.where((element) => element.message == coinAnnoCreate.message)) { + for (final coinAnnoCreate + in coinAnnoCreates.where((element) => element.coinId == coin)) { + for (final coinAnnoAssert in coinAnnoAsserts + .where((element) => element.message == coinAnnoCreate.message)) { addToCTD(coinAnnoAssert.coinId); } } @@ -128,7 +142,8 @@ Future constructSpendBundleOfCoin( } } - final spendBundleSpends = blockSpends.where((element) => coinsDealed.contains(element.coin.id)); + final spendBundleSpends = + blockSpends.where((element) => coinsDealed.contains(element.coin.id)); return SpendBundle( coinSpends: spendBundleSpends.toList(), diff --git a/lib/src/api/utils/parsing/deep_pick_extension.dart b/lib/src/api/utils/parsing/deep_pick_extension.dart index ce92fa62..d752f382 100644 --- a/lib/src/api/utils/parsing/deep_pick_extension.dart +++ b/lib/src/api/utils/parsing/deep_pick_extension.dart @@ -14,13 +14,17 @@ extension CustomLets on Pick { Bytes asBytesOrThrow() { final bytes = asBytesOrNull(); - if (bytes == null) throw Exception('failed parsing as bytes: $value at $path'); + if (bytes == null) { + throw Exception('failed parsing as bytes: $value at $path'); + } return bytes; } R letBytesOrThrow(R Function(Bytes bytes) parseBytes) { final item = letBytesOrNull(parseBytes); - if (item == null) throw Exception('failed parsing as bytes: $value at $path'); + if (item == null) { + throw Exception('failed parsing as bytes: $value at $path'); + } return item; } @@ -43,7 +47,9 @@ extension CustomLets on Pick { Map asJsonOrThrow() { final json = asJsonOrNull(); - if (json == null) throw Exception('failed parsing as json: $value at $path'); + if (json == null) { + throw Exception('failed parsing as json: $value at $path'); + } return json; } @@ -57,17 +63,25 @@ extension CustomLets on Pick { R letJsonOrThrow(R Function(Map json) parseJson) { final item = _parsePossibleXFromJson(value, parseJson); - if (item == null) throw Exception('failed parsing as json: $value at $path'); + if (item == null) { + throw Exception('failed parsing as json: $value at $path'); + } return item; } - List? letJsonListOrNull(R Function(Map json) parseJson) { + List? letJsonListOrNull( + R Function(Map json) parseJson, + ) { return _parsePossibleListOfXFromListOfJson(value, parseJson); } - List letJsonListOrThrow(R Function(Map json) parseJson) { + List letJsonListOrThrow( + R Function(Map json) parseJson, + ) { final list = _parsePossibleListOfXFromListOfJson(value, parseJson); - if (list == null) throw Exception('failed parsing as list of json: $value at $path'); + if (list == null) { + throw Exception('failed parsing as list of json: $value at $path'); + } return list; } @@ -77,7 +91,9 @@ extension CustomLets on Pick { R letStringOrThrow(R Function(String string) parseString) { final item = _parsePossibleXFromString(value, parseString); - if (item == null) throw Exception('failed parsing as string: $value at $path'); + if (item == null) { + throw Exception('failed parsing as string: $value at $path'); + } return item; } @@ -91,7 +107,9 @@ extension CustomLets on Pick { List letStringListOrThrow(R Function(String string) parseString) { final item = _parsePossibleListOfXFromListOfStrings(value, parseString); - if (item == null) throw Exception('failed parsing as list of strings: $value at $path'); + if (item == null) { + throw Exception('failed parsing as list of strings: $value at $path'); + } return item; } } diff --git a/lib/src/api/wallet_connect/models/chia_wallet_info/chia_wallet_info.dart b/lib/src/api/wallet_connect/models/chia_wallet_info/chia_wallet_info.dart index 08e594ae..034a11aa 100644 --- a/lib/src/api/wallet_connect/models/chia_wallet_info/chia_wallet_info.dart +++ b/lib/src/api/wallet_connect/models/chia_wallet_info/chia_wallet_info.dart @@ -98,27 +98,38 @@ enum ChiaWalletType { const ChiaWalletType(this.chiaIndex); factory ChiaWalletType.fromString(String typeString) { - return ChiaWalletType.values.where((type) => typeString.split('_').first == type.name).single; + return ChiaWalletType.values + .where((type) => typeString.split('_').first == type.name) + .single; } factory ChiaWalletType.fromIndex(int index) { - return ChiaWalletType.values.where((type) => type.chiaIndex == index).single; + return ChiaWalletType.values + .where((type) => type.chiaIndex == index) + .single; } final int chiaIndex; } extension WalletsOfType on Map { - Map _getWalletsOfType(ChiaWalletType type, [List walletIds = const []]) { + Map _getWalletsOfType( + ChiaWalletType type, [ + List walletIds = const [], + ]) { final filteredMap = Map.from(this) ..removeWhere( - (key, value) => value.type != type || (walletIds.isNotEmpty && !walletIds.contains(key)), + (key, value) => + value.type != type || + (walletIds.isNotEmpty && !walletIds.contains(key)), ); return filteredMap.map((key, value) => MapEntry(key, value as T)); } - Map nftWallets([List walletIds = const []]) => + Map nftWallets([ + List walletIds = const [], + ]) => _getWalletsOfType(ChiaWalletType.nft, walletIds); Map catWallets([List walletIds = const []]) => @@ -129,13 +140,15 @@ extension WalletsOfType on Map { } extension AssetIdsGetterX on Map { - Map get assetIdMap => map((key, value) => MapEntry(key, value.assetId)); + Map get assetIdMap => + map((key, value) => MapEntry(key, value.assetId)); List get assetIds => assetIdMap.values.toList(); } extension NftInfosGetterX on Map { - Map> get nftInfosMap => map((key, value) => MapEntry(key, value.nftInfos)); + Map> get nftInfosMap => + map((key, value) => MapEntry(key, value.nftInfos)); List get nftInfos { final nftInfos = []; @@ -148,7 +161,10 @@ extension NftInfosGetterX on Map { } Map> get launcherIdsMap => map( - (key, value) => MapEntry(key, value.nftInfos.map((nftInfo) => nftInfo.launcherId).toList()), + (key, value) => MapEntry( + key, + value.nftInfos.map((nftInfo) => nftInfo.launcherId).toList(), + ), ); } @@ -162,11 +178,13 @@ extension NftInfosListGetterX on List { return nftInfos; } - List get launcherIds => nftInfos.map((nftInfo) => nftInfo.launcherId).toList(); + List get launcherIds => + nftInfos.map((nftInfo) => nftInfo.launcherId).toList(); } extension DIDs on Map { - Map get didMap => map((key, value) => MapEntry(key, value.didInfoWithOriginCoin.did)); + Map get didMap => + map((key, value) => MapEntry(key, value.didInfoWithOriginCoin.did)); List get dids => didMap.values.toList(); } diff --git a/lib/src/api/wallet_connect/models/chia_wallet_info/nft_wallet_info.dart b/lib/src/api/wallet_connect/models/chia_wallet_info/nft_wallet_info.dart index 7ec98232..7f3612d3 100644 --- a/lib/src/api/wallet_connect/models/chia_wallet_info/nft_wallet_info.dart +++ b/lib/src/api/wallet_connect/models/chia_wallet_info/nft_wallet_info.dart @@ -13,7 +13,9 @@ class NftWalletInfo with WalletInfoDecorator implements ChiaWalletInfo { type: ChiaWalletType.nft, data: jsonEncode({'did_info': did?.toHex()}), meta: { - 'did': did != null ? Address.fromPuzzlehash(Puzzlehash(did), didPrefix).address : '', + 'did': did != null + ? Address.fromPuzzlehash(Puzzlehash(did), didPrefix).address + : '', }, ); diff --git a/lib/src/api/wallet_connect/models/commands/check_offer_validity_command.dart b/lib/src/api/wallet_connect/models/commands/check_offer_validity_command.dart index 62758f01..572d7c00 100644 --- a/lib/src/api/wallet_connect/models/commands/check_offer_validity_command.dart +++ b/lib/src/api/wallet_connect/models/commands/check_offer_validity_command.dart @@ -12,7 +12,8 @@ class CheckOfferValidityCommand implements WalletConnectCommand { } @override - WalletConnectCommandType get type => WalletConnectCommandType.checkOfferValidity; + WalletConnectCommandType get type => + WalletConnectCommandType.checkOfferValidity; final Offer offer; @@ -29,8 +30,9 @@ class CheckOfferValidityResponse factory CheckOfferValidityResponse.fromJson(Map json) { final baseResponse = WalletConnectCommandBaseResponseImp.fromJson(json); - final offerValidityData = - OfferValidityData.fromJson(pick(json, 'data').letJsonOrThrow((json) => json)); + final offerValidityData = OfferValidityData.fromJson( + pick(json, 'data').letJsonOrThrow((json) => json), + ); return CheckOfferValidityResponse(baseResponse, offerValidityData); } diff --git a/lib/src/api/wallet_connect/models/commands/create_offer_for_ids_command.dart b/lib/src/api/wallet_connect/models/commands/create_offer_for_ids_command.dart index 2f9cc2c4..762a7d62 100644 --- a/lib/src/api/wallet_connect/models/commands/create_offer_for_ids_command.dart +++ b/lib/src/api/wallet_connect/models/commands/create_offer_for_ids_command.dart @@ -11,16 +11,19 @@ class CreateOfferForIdsCommand implements WalletConnectCommand { factory CreateOfferForIdsCommand.fromParams(Map params) { return CreateOfferForIdsCommand( offerMap: pick(params, 'offer').letJsonOrThrow( - (json) => json.map((key, value) => MapEntry(key, int.parse(value.toString()))), + (json) => json + .map((key, value) => MapEntry(key, int.parse(value.toString()))), ), driverDict: pick(params, 'driverDict').letJsonOrThrow((json) => json), validateOnly: pick(params, 'validateOnly').asBoolOrFalse(), - disableJsonFormatting: pick(params, 'disableJSONFormatting').asBoolOrFalse(), + disableJsonFormatting: + pick(params, 'disableJSONFormatting').asBoolOrFalse(), ); } @override - WalletConnectCommandType get type => WalletConnectCommandType.createOfferForIds; + WalletConnectCommandType get type => + WalletConnectCommandType.createOfferForIds; /// Map of walletId to amount. If amount is negative, it is being offered,else it is being requested. final Map offerMap; @@ -46,8 +49,9 @@ class CreateOfferForIdsResponse factory CreateOfferForIdsResponse.fromJson(Map json) { final baseResponse = WalletConnectCommandBaseResponseImp.fromJson(json); - final createdOfferData = - CreatedOfferData.fromJson(pick(json, 'data').letJsonOrThrow((json) => json)); + final createdOfferData = CreatedOfferData.fromJson( + pick(json, 'data').letJsonOrThrow((json) => json), + ); return CreateOfferForIdsResponse(baseResponse, createdOfferData); } @@ -73,7 +77,8 @@ class CreatedOfferData { factory CreatedOfferData.fromJson(Map json) { return CreatedOfferData( offer: Offer.fromBech32(pick(json, 'offer').asStringOrThrow()), - tradeRecord: pick(json, 'tradeRecord').letJsonOrThrow(TradeRecord.fromJson), + tradeRecord: + pick(json, 'tradeRecord').letJsonOrThrow(TradeRecord.fromJson), ); } diff --git a/lib/src/api/wallet_connect/models/commands/get_current_address_command.dart b/lib/src/api/wallet_connect/models/commands/get_current_address_command.dart index 3247eb88..d2897bc4 100644 --- a/lib/src/api/wallet_connect/models/commands/get_current_address_command.dart +++ b/lib/src/api/wallet_connect/models/commands/get_current_address_command.dart @@ -6,11 +6,14 @@ class GetCurrentAddressCommand implements WalletConnectCommand { this.walletId = 1, }); factory GetCurrentAddressCommand.fromParams(Map params) { - return GetCurrentAddressCommand(walletId: pick(params, 'walletId').asIntOrNull()); + return GetCurrentAddressCommand( + walletId: pick(params, 'walletId').asIntOrNull(), + ); } @override - WalletConnectCommandType get type => WalletConnectCommandType.getCurrentAddress; + WalletConnectCommandType get type => + WalletConnectCommandType.getCurrentAddress; final int? walletId; diff --git a/lib/src/api/wallet_connect/models/commands/get_nft_info_command.dart b/lib/src/api/wallet_connect/models/commands/get_nft_info_command.dart index 79f18f92..1e41cc54 100644 --- a/lib/src/api/wallet_connect/models/commands/get_nft_info_command.dart +++ b/lib/src/api/wallet_connect/models/commands/get_nft_info_command.dart @@ -29,7 +29,8 @@ class GetNftInfoResponse factory GetNftInfoResponse.fromJson(Map json) { final baseResponse = WalletConnectCommandBaseResponseImp.fromJson(json); - final nftInfo = NftInfo.fromJson(pick(json, 'data').letJsonOrThrow((json) => json)); + final nftInfo = + NftInfo.fromJson(pick(json, 'data').letJsonOrThrow((json) => json)); return GetNftInfoResponse(baseResponse, nftInfo); } @@ -72,24 +73,30 @@ class NftInfo { factory NftInfo.fromJson(Map json) { return NftInfo( launcherId: pick(json, 'launcherId').asStringOrThrow().hexToBytes(), - launcherPuzzlehash: Puzzlehash.fromHex(pick(json, 'launcherPuzhash').asStringOrThrow()), + launcherPuzzlehash: + Puzzlehash.fromHex(pick(json, 'launcherPuzhash').asStringOrThrow()), nftCoinId: pick(json, 'nftCoinId').asStringOrThrow().hexToBytes(), dataHash: pick(json, 'dataHash').asStringOrThrow().hexToBytes(), dataUris: pick(json, 'dataUris').letStringListOrThrow((string) => string), chainInfo: pick(json, 'chainInfo').asStringOrThrow(), licenseHash: pick(json, 'licenseHash').asStringOrThrow().hexToBytes(), - licenseUris: pick(json, 'licenseUris').letStringListOrThrow((string) => string), + licenseUris: + pick(json, 'licenseUris').letStringListOrThrow((string) => string), metadataHash: pick(json, 'metadataHash').asStringOrThrow().hexToBytes(), - metadataUris: pick(json, 'metadataUris').letStringListOrThrow((string) => string), + metadataUris: + pick(json, 'metadataUris').letStringListOrThrow((string) => string), mintHeight: pick(json, 'mintHeight').asIntOrThrow(), ownerDid: pick(json, 'ownerDid').asStringOrNull()?.hexToBytes(), editionNumber: pick(json, 'editionNumber').asIntOrThrow(), editionTotal: pick(json, 'editionTotal').asIntOrThrow(), supportsDid: pick(json, 'supportsDid').asBoolOrThrow(), - updaterPuzzlehash: Puzzlehash.fromHex(pick(json, 'updaterPuzhash').asStringOrThrow()), + updaterPuzzlehash: + Puzzlehash.fromHex(pick(json, 'updaterPuzhash').asStringOrThrow()), royaltyPercentage: pick(json, 'royaltyPercentage').asIntOrNull(), royaltyPuzzlehash: json['royaltyPuzzleHash'] != null - ? Puzzlehash.fromHex(pick(json, 'royaltyPuzzleHash').asStringOrThrow()) + ? Puzzlehash.fromHex( + pick(json, 'royaltyPuzzleHash').asStringOrThrow(), + ) : null, ); } @@ -194,12 +201,30 @@ class ChainInfo { Program toProgram() { return Program.list( [ - Program.cons(Program.fromString('u'), Program.fromString(dataUris.toString())), - Program.cons(Program.fromString('h'), Program.fromString(dataHash.toHex())), - Program.cons(Program.fromString('mu'), Program.fromString(metadataUris.toString())), - Program.cons(Program.fromString('lu'), Program.fromString(licenseUris.toString())), - Program.cons(Program.fromString('sn'), Program.fromString(metadataHash.toHex())), - Program.cons(Program.fromString('st'), Program.fromString(licenseHash.toHex())), + Program.cons( + Program.fromString('u'), + Program.fromString(dataUris.toString()), + ), + Program.cons( + Program.fromString('h'), + Program.fromString(dataHash.toHex()), + ), + Program.cons( + Program.fromString('mu'), + Program.fromString(metadataUris.toString()), + ), + Program.cons( + Program.fromString('lu'), + Program.fromString(licenseUris.toString()), + ), + Program.cons( + Program.fromString('sn'), + Program.fromString(metadataHash.toHex()), + ), + Program.cons( + Program.fromString('st'), + Program.fromString(licenseHash.toHex()), + ), ], ); } diff --git a/lib/src/api/wallet_connect/models/commands/get_nfts_command.dart b/lib/src/api/wallet_connect/models/commands/get_nfts_command.dart index 6ae991ec..bf966890 100644 --- a/lib/src/api/wallet_connect/models/commands/get_nfts_command.dart +++ b/lib/src/api/wallet_connect/models/commands/get_nfts_command.dart @@ -9,7 +9,8 @@ class GetNftsCommand implements WalletConnectCommand { }); factory GetNftsCommand.fromParams(Map params) { return GetNftsCommand( - walletIds: pick(params, 'walletIds').asListOrThrow((json) => json.asIntOrThrow()), + walletIds: pick(params, 'walletIds') + .asListOrThrow((json) => json.asIntOrThrow()), startIndex: pick(params, 'startIndex').asIntOrNull(), num: pick(params, 'num').asIntOrNull(), ); @@ -42,7 +43,12 @@ class GetNftsResponse final nfts = pick(json, 'data').asMapOrThrow>().map( (key, value) => MapEntry( int.parse(key), - value.map((nftJson) => NftInfo.fromJson(nftJson as Map)).toList(), + value + .map( + (nftJson) => + NftInfo.fromJson(nftJson as Map), + ) + .toList(), ), ); @@ -58,7 +64,10 @@ class GetNftsResponse return { ...delegate.toJson(), 'data': nfts.map( - (key, value) => MapEntry(key.toString(), value.map((nftInfo) => nftInfo.toJson()).toList()), + (key, value) => MapEntry( + key.toString(), + value.map((nftInfo) => nftInfo.toJson()).toList(), + ), ), }; } diff --git a/lib/src/api/wallet_connect/models/commands/get_nfts_count_command.dart b/lib/src/api/wallet_connect/models/commands/get_nfts_count_command.dart index c8b38988..72a9192e 100644 --- a/lib/src/api/wallet_connect/models/commands/get_nfts_count_command.dart +++ b/lib/src/api/wallet_connect/models/commands/get_nfts_count_command.dart @@ -7,7 +7,8 @@ class GetNftsCountCommand implements WalletConnectCommand { }); factory GetNftsCountCommand.fromParams(Map params) { return GetNftsCountCommand( - walletIds: pick(params, 'walletIds').asListOrThrow((json) => json.asIntOrThrow()), + walletIds: pick(params, 'walletIds') + .asListOrThrow((json) => json.asIntOrThrow()), ); } diff --git a/lib/src/api/wallet_connect/models/commands/get_sync_status_command.dart b/lib/src/api/wallet_connect/models/commands/get_sync_status_command.dart index ae133a35..d8acca94 100644 --- a/lib/src/api/wallet_connect/models/commands/get_sync_status_command.dart +++ b/lib/src/api/wallet_connect/models/commands/get_sync_status_command.dart @@ -20,8 +20,9 @@ class GetSyncStatusResponse factory GetSyncStatusResponse.fromJson(Map json) { final baseResponse = WalletConnectCommandBaseResponseImp.fromJson(json); - final syncStatusData = - SyncStatusData.fromJson(pick(json, 'data').letJsonOrThrow((json) => json)); + final syncStatusData = SyncStatusData.fromJson( + pick(json, 'data').letJsonOrThrow((json) => json), + ); return GetSyncStatusResponse(baseResponse, syncStatusData); } diff --git a/lib/src/api/wallet_connect/models/commands/get_transaction_command.dart b/lib/src/api/wallet_connect/models/commands/get_transaction_command.dart index 8bf8c483..b5576d2e 100644 --- a/lib/src/api/wallet_connect/models/commands/get_transaction_command.dart +++ b/lib/src/api/wallet_connect/models/commands/get_transaction_command.dart @@ -8,7 +8,8 @@ class GetTransactionCommand implements WalletConnectCommand { }); factory GetTransactionCommand.fromParams(Map params) { return GetTransactionCommand( - transactionId: Bytes.fromHex(pick(params, 'transactionId').asStringOrThrow()), + transactionId: + Bytes.fromHex(pick(params, 'transactionId').asStringOrThrow()), ); } @@ -33,7 +34,8 @@ class GetTransactionResponse factory GetTransactionResponse.fromJson(Map json) { final baseResponse = WalletConnectCommandBaseResponseImp.fromJson(json); - final transactionRecord = pick(json, 'data').letJsonOrThrow(TransactionRecord.fromJson); + final transactionRecord = + pick(json, 'data').letJsonOrThrow(TransactionRecord.fromJson); return GetTransactionResponse(baseResponse, transactionRecord); } @@ -83,7 +85,9 @@ class TransactionRecord { memos = memoMap.map( (key, value) => MapEntry( key.hexToBytes(), - (value as List).map((memo) => Memo(memo.toString().hexToBytes())).toList(), + (value as List) + .map((memo) => Memo(memo.toString().hexToBytes())) + .toList(), ), ); } catch (e) { @@ -99,7 +103,8 @@ class TransactionRecord { } return TransactionRecord( - additions: pick(json, 'additions').letJsonListOrThrow(CoinPrototype.fromCamelJson), + additions: pick(json, 'additions') + .letJsonListOrThrow(CoinPrototype.fromCamelJson), amount: pick(json, 'amount').asIntOrThrow(), confirmed: pick(json, 'confirmed').asBoolOrThrow(), confirmedAtHeight: pick(json, 'confirmedAtHeight').asIntOrThrow(), @@ -107,14 +112,17 @@ class TransactionRecord { feeAmount: pick(json, 'feeAmount').asIntOrThrow(), memos: memos, name: pick(json, 'name').asStringOrThrow(), - removals: pick(json, 'removals').letJsonListOrThrow(CoinPrototype.fromCamelJson), + removals: pick(json, 'removals') + .letJsonListOrThrow(CoinPrototype.fromCamelJson), sent: pick(json, 'sent').asIntOrThrow(), sentTo: pick(json, 'sentTo').asListOrEmpty((p0) => p0.asString()), toAddress: Address(pick(json, 'toAddress').asStringOrThrow()), - toPuzzlehash: Puzzlehash.fromHex(pick(json, 'toPuzzleHash').asStringOrThrow()), + toPuzzlehash: + Puzzlehash.fromHex(pick(json, 'toPuzzleHash').asStringOrThrow()), type: ChiaTransactionType.values[pick(json, 'type').asIntOrThrow()], walletId: pick(json, 'walletId').asIntOrThrow(), - spendBundle: pick(json, 'spendBundle').letJsonOrNull(SpendBundle.fromCamelJson), + spendBundle: + pick(json, 'spendBundle').letJsonOrNull(SpendBundle.fromCamelJson), tradeId: pick(json, 'tradeId').asStringOrNull()?.hexToBytes(), ); } @@ -145,8 +153,10 @@ class TransactionRecord { 'confirmedAtHeight': confirmedAtHeight, 'createdAtTime': createdAtTime, 'feeAmount': feeAmount, - 'memos': memos - .map((key, value) => MapEntry(key.toHex(), value.map((memo) => memo.toHex()).toList())), + 'memos': memos.map( + (key, value) => + MapEntry(key.toHex(), value.map((memo) => memo.toHex()).toList()), + ), 'name': name, 'removals': removals.map((coin) => coin.toCamelJson()).toList(), 'sent': sent, @@ -183,7 +193,11 @@ class Peer { Peer? maybeFromList(List list) { try { - return Peer(list[0], InclusionStatus.fromIndex(int.parse(list[1])), list[3]); + return Peer( + list[0], + InclusionStatus.fromIndex(int.parse(list[1])), + list[3], + ); } catch (e) { return null; } diff --git a/lib/src/api/wallet_connect/models/commands/get_wallet_balance_command.dart b/lib/src/api/wallet_connect/models/commands/get_wallet_balance_command.dart index 46265322..e44855e4 100644 --- a/lib/src/api/wallet_connect/models/commands/get_wallet_balance_command.dart +++ b/lib/src/api/wallet_connect/models/commands/get_wallet_balance_command.dart @@ -4,11 +4,14 @@ import 'package:deep_pick/deep_pick.dart'; class GetWalletBalanceCommand implements WalletConnectCommand { const GetWalletBalanceCommand({this.walletId = 1}); factory GetWalletBalanceCommand.fromParams(Map params) { - return GetWalletBalanceCommand(walletId: pick(params, 'walletId').asIntOrNull()); + return GetWalletBalanceCommand( + walletId: pick(params, 'walletId').asIntOrNull(), + ); } @override - WalletConnectCommandType get type => WalletConnectCommandType.getWalletBalance; + WalletConnectCommandType get type => + WalletConnectCommandType.getWalletBalance; final int? walletId; @@ -25,7 +28,9 @@ class GetWalletBalanceResponse factory GetWalletBalanceResponse.fromJson(Map json) { final baseResponse = WalletConnectCommandBaseResponseImp.fromJson(json); - final balance = WalletBalance.fromJson(pick(json, 'data').letJsonOrThrow((json) => json)); + final balance = WalletBalance.fromJson( + pick(json, 'data').letJsonOrThrow((json) => json), + ); return GetWalletBalanceResponse(baseResponse, balance); } @@ -57,16 +62,20 @@ class WalletBalance { }); factory WalletBalance.fromJson(Map json) { return WalletBalance( - confirmedWalletBalance: pick(json, 'confirmedWalletBalance').asIntOrThrow(), + confirmedWalletBalance: + pick(json, 'confirmedWalletBalance').asIntOrThrow(), fingerprint: pick(json, 'fingerprint').asIntOrThrow(), maxSendAmount: pick(json, 'maxSendAmount').asIntOrThrow(), pendingChange: pick(json, 'pendingChange').asIntOrThrow(), - pendingCoinRemovalCount: pick(json, 'pendingCoinRemovalCount').asIntOrThrow(), + pendingCoinRemovalCount: + pick(json, 'pendingCoinRemovalCount').asIntOrThrow(), spendableBalance: pick(json, 'spendableBalance').asIntOrThrow(), - unconfirmedWalletBalance: pick(json, 'unconfirmedWalletBalance').asIntOrThrow(), + unconfirmedWalletBalance: + pick(json, 'unconfirmedWalletBalance').asIntOrThrow(), unspentCoinCount: pick(json, 'unspentCoinCount').asIntOrThrow(), walletId: pick(json, 'walletId').asIntOrThrow(), - walletType: ChiaWalletType.fromIndex(pick(json, 'walletType').asIntOrThrow()), + walletType: + ChiaWalletType.fromIndex(pick(json, 'walletType').asIntOrThrow()), ); } diff --git a/lib/src/api/wallet_connect/models/commands/get_wallets_command.dart b/lib/src/api/wallet_connect/models/commands/get_wallets_command.dart index 844ac098..2b7efb91 100644 --- a/lib/src/api/wallet_connect/models/commands/get_wallets_command.dart +++ b/lib/src/api/wallet_connect/models/commands/get_wallets_command.dart @@ -10,7 +10,8 @@ class GetWalletsCommand implements WalletConnectCommand { final typeIndex = pick(params, 'type').asIntOrNull(); return GetWalletsCommand( includeData: pick(params, 'includeData').asBoolOrFalse(), - walletType: typeIndex != null ? ChiaWalletType.fromIndex(typeIndex) : null, + walletType: + typeIndex != null ? ChiaWalletType.fromIndex(typeIndex) : null, ); } @@ -36,7 +37,8 @@ class GetWalletsResponse factory GetWalletsResponse.fromJson(Map json) { final baseResponse = WalletConnectCommandBaseResponseImp.fromJson(json); - final wallets = pick(json, 'data').letJsonListOrThrow(ChiaWalletInfoImp.fromJson); + final wallets = + pick(json, 'data').letJsonListOrThrow(ChiaWalletInfoImp.fromJson); return GetWalletsResponse(baseResponse, wallets); } diff --git a/lib/src/api/wallet_connect/models/commands/log_in_command.dart b/lib/src/api/wallet_connect/models/commands/log_in_command.dart index cf5bd11c..e2c2f8e8 100644 --- a/lib/src/api/wallet_connect/models/commands/log_in_command.dart +++ b/lib/src/api/wallet_connect/models/commands/log_in_command.dart @@ -6,7 +6,9 @@ class LogInCommand implements WalletConnectCommand { required this.fingerprint, }); factory LogInCommand.fromParams(Map params) { - return LogInCommand(fingerprint: pick(params, 'fingerprint').asIntOrThrow()); + return LogInCommand( + fingerprint: pick(params, 'fingerprint').asIntOrThrow(), + ); } @override @@ -27,7 +29,10 @@ class LogInResponse factory LogInResponse.fromJson(Map json) { final baseResponse = WalletConnectCommandBaseResponseImp.fromJson(json); - return LogInResponse(baseResponse, pick(json, 'data').letJsonOrThrow(LogInData.fromJson)); + return LogInResponse( + baseResponse, + pick(json, 'data').letJsonOrThrow(LogInData.fromJson), + ); } @override diff --git a/lib/src/api/wallet_connect/models/commands/send_transaction_command.dart b/lib/src/api/wallet_connect/models/commands/send_transaction_command.dart index 1f488f66..0e3a6c5f 100644 --- a/lib/src/api/wallet_connect/models/commands/send_transaction_command.dart +++ b/lib/src/api/wallet_connect/models/commands/send_transaction_command.dart @@ -51,7 +51,8 @@ class SendTransactionResponse factory SendTransactionResponse.fromJson(Map json) { final baseResponse = WalletConnectCommandBaseResponseImp.fromJson(json); - final sentTransactionData = pick(json, 'data').letJsonOrThrow(SentTransactionData.fromJson); + final sentTransactionData = + pick(json, 'data').letJsonOrThrow(SentTransactionData.fromJson); return SendTransactionResponse(baseResponse, sentTransactionData); } @@ -77,7 +78,8 @@ class SentTransactionData { }); factory SentTransactionData.fromJson(Map json) { return SentTransactionData( - transaction: pick(json, 'transaction').letJsonOrThrow(TransactionRecord.fromJson), + transaction: + pick(json, 'transaction').letJsonOrThrow(TransactionRecord.fromJson), transactionId: pick(json, 'transactionId').asStringOrThrow(), success: pick(json, 'success').asBoolOrThrow(), ); diff --git a/lib/src/api/wallet_connect/models/commands/sign_message_by_address_command.dart b/lib/src/api/wallet_connect/models/commands/sign_message_by_address_command.dart index 5e57e35b..233c432d 100644 --- a/lib/src/api/wallet_connect/models/commands/sign_message_by_address_command.dart +++ b/lib/src/api/wallet_connect/models/commands/sign_message_by_address_command.dart @@ -2,7 +2,10 @@ import 'package:chia_crypto_utils/chia_crypto_utils.dart'; import 'package:deep_pick/deep_pick.dart'; class SignMessageByAddressCommand implements WalletConnectCommand { - const SignMessageByAddressCommand({required this.address, required this.message}); + const SignMessageByAddressCommand({ + required this.address, + required this.message, + }); factory SignMessageByAddressCommand.fromParams(Map params) { return SignMessageByAddressCommand( address: Address(pick(params, 'address').asStringOrThrow()), @@ -11,7 +14,8 @@ class SignMessageByAddressCommand implements WalletConnectCommand { } @override - WalletConnectCommandType get type => WalletConnectCommandType.signMessageByAddress; + WalletConnectCommandType get type => + WalletConnectCommandType.signMessageByAddress; final Address address; final String message; @@ -60,9 +64,12 @@ class SignMessageByAddressData { }); factory SignMessageByAddressData.fromJson(Map json) { return SignMessageByAddressData( - publicKey: JacobianPoint.fromHexG1(pick(json, 'pubkey').asStringOrThrow()), - signature: JacobianPoint.fromHexG2(pick(json, 'signature').asStringOrThrow()), - signingMode: SigningMode.fromString(pick(json, 'signingMode').asStringOrThrow()), + publicKey: + JacobianPoint.fromHexG1(pick(json, 'pubkey').asStringOrThrow()), + signature: + JacobianPoint.fromHexG2(pick(json, 'signature').asStringOrThrow()), + signingMode: + SigningMode.fromString(pick(json, 'signingMode').asStringOrThrow()), success: pick(json, 'success').asBoolOrThrow(), ); } diff --git a/lib/src/api/wallet_connect/models/commands/sign_message_by_id_command.dart b/lib/src/api/wallet_connect/models/commands/sign_message_by_id_command.dart index f3493280..762ba66d 100644 --- a/lib/src/api/wallet_connect/models/commands/sign_message_by_id_command.dart +++ b/lib/src/api/wallet_connect/models/commands/sign_message_by_id_command.dart @@ -5,7 +5,9 @@ class SignMessageByIdCommand implements WalletConnectCommand { const SignMessageByIdCommand({required this.id, required this.message}); factory SignMessageByIdCommand.fromParams(Map params) { return SignMessageByIdCommand( - id: DidInfo.parseDidFromEitherFormat(pick(params, 'id').asStringOrThrow()), + id: DidInfo.parseDidFromEitherFormat( + pick(params, 'id').asStringOrThrow(), + ), message: pick(params, 'message').asStringOrThrow(), ); } @@ -62,9 +64,12 @@ class SignMessageByIdData { factory SignMessageByIdData.fromJson(Map json) { return SignMessageByIdData( latestCoinId: pick(json, 'latestCoinId').asStringOrThrow().hexToBytes(), - publicKey: JacobianPoint.fromHexG1(pick(json, 'pubkey').asStringOrThrow()), - signature: JacobianPoint.fromHexG2(pick(json, 'signature').asStringOrThrow()), - signingMode: SigningMode.fromString(pick(json, 'signingMode').asStringOrThrow()), + publicKey: + JacobianPoint.fromHexG1(pick(json, 'pubkey').asStringOrThrow()), + signature: + JacobianPoint.fromHexG2(pick(json, 'signature').asStringOrThrow()), + signingMode: + SigningMode.fromString(pick(json, 'signingMode').asStringOrThrow()), success: pick(json, 'success').asBoolOrThrow(), ); } diff --git a/lib/src/api/wallet_connect/models/commands/sign_spend_bundle.dart b/lib/src/api/wallet_connect/models/commands/sign_spend_bundle.dart index 9ac91cd0..b8a8be58 100644 --- a/lib/src/api/wallet_connect/models/commands/sign_spend_bundle.dart +++ b/lib/src/api/wallet_connect/models/commands/sign_spend_bundle.dart @@ -7,7 +7,8 @@ class SignSpendBundleCommand implements WalletConnectCommand { }); factory SignSpendBundleCommand.fromParams(Map params) { return SignSpendBundleCommand( - spendBundle: pick(params, 'spendBundle').letJsonOrThrow(SpendBundle.fromJson), + spendBundle: + pick(params, 'spendBundle').letJsonOrThrow(SpendBundle.fromJson), ); } @@ -29,7 +30,8 @@ class SignSpendBundleResponse factory SignSpendBundleResponse.fromJson(Map json) { final baseResponse = WalletConnectCommandBaseResponseImp.fromJson(json); - final signature = pick(json, 'data').letStringOrThrow(JacobianPoint.fromHexG2); + final signature = + pick(json, 'data').letStringOrThrow(JacobianPoint.fromHexG2); return SignSpendBundleResponse(baseResponse, signature); } diff --git a/lib/src/api/wallet_connect/models/commands/spend_cat_command.dart b/lib/src/api/wallet_connect/models/commands/spend_cat_command.dart index b92b7b01..b1136655 100644 --- a/lib/src/api/wallet_connect/models/commands/spend_cat_command.dart +++ b/lib/src/api/wallet_connect/models/commands/spend_cat_command.dart @@ -17,7 +17,8 @@ class SpendCatCommand implements WalletConnectCommand { amount: pick(params, 'amount').asIntOrThrow(), fee: pick(params, 'fee').asIntOrThrow(), waitForConfirmation: pick(params, 'waitForConfirmation').asBoolOrFalse(), - memos: pick(params, 'memos').letStringListOrNull((string) => string) ?? [], + memos: + pick(params, 'memos').letStringListOrNull((string) => string) ?? [], ); } diff --git a/lib/src/api/wallet_connect/models/commands/take_offer_command.dart b/lib/src/api/wallet_connect/models/commands/take_offer_command.dart index 099247f0..b9ba4312 100644 --- a/lib/src/api/wallet_connect/models/commands/take_offer_command.dart +++ b/lib/src/api/wallet_connect/models/commands/take_offer_command.dart @@ -38,7 +38,8 @@ class TakeOfferResponse factory TakeOfferResponse.fromJson(Map json) { final baseResponse = WalletConnectCommandBaseResponseImp.fromJson(json); - final takeOfferData = pick(json, 'data').letJsonOrThrow(TakeOfferData.fromJson); + final takeOfferData = + pick(json, 'data').letJsonOrThrow(TakeOfferData.fromJson); return TakeOfferResponse(baseResponse, takeOfferData); } @@ -62,7 +63,8 @@ class TakeOfferData { }); factory TakeOfferData.fromJson(Map json) { return TakeOfferData( - tradeRecord: pick(json, 'tradeRecord').letJsonOrThrow(TradeRecord.fromJson), + tradeRecord: + pick(json, 'tradeRecord').letJsonOrThrow(TradeRecord.fromJson), success: pick(json, 'success').asBoolOrThrow(), ); } @@ -101,7 +103,8 @@ class TradeRecord { isMyOffer: pick(json, 'isMyOffer').asBoolOrThrow(), sent: pick(json, 'sent').asIntOrThrow(), sentTo: pick(json, 'sentTo').asListOrEmpty((p0) => p0.asString()), - coinsOfInterest: pick(json, 'coinsOfInterest').letJsonListOrThrow(CoinPrototype.fromJson), + coinsOfInterest: pick(json, 'coinsOfInterest') + .letJsonListOrThrow(CoinPrototype.fromJson), tradeId: pick(json, 'tradeId').asStringOrThrow().hexToBytes(), status: TradeStatus.fromString(pick(json, 'status').asStringOrThrow()), takenOffer: pick(json, 'takenOffer').asStringOrNull(), diff --git a/lib/src/api/wallet_connect/models/commands/transfer_nft_command.dart b/lib/src/api/wallet_connect/models/commands/transfer_nft_command.dart index 6fd7683c..2cb4f634 100644 --- a/lib/src/api/wallet_connect/models/commands/transfer_nft_command.dart +++ b/lib/src/api/wallet_connect/models/commands/transfer_nft_command.dart @@ -13,7 +13,8 @@ class TransferNftCommand implements WalletConnectCommand { return TransferNftCommand( walletId: pick(params, 'walletId').asIntOrThrow(), targetAddress: Address(pick(params, 'targetAddress').asStringOrThrow()), - nftCoinIds: pick(params, 'nftCoinIds').letStringListOrThrow((string) => string.hexToBytes()), + nftCoinIds: pick(params, 'nftCoinIds') + .letStringListOrThrow((string) => string.hexToBytes()), fee: pick(params, 'fee').asIntOrThrow(), ); } @@ -45,7 +46,8 @@ class TransferNftResponse factory TransferNftResponse.fromJson(Map json) { final baseResponse = WalletConnectCommandBaseResponseImp.fromJson(json); - final transferNftData = pick(json, 'data').letJsonOrThrow(TransferNftData.fromJson); + final transferNftData = + pick(json, 'data').letJsonOrThrow(TransferNftData.fromJson); return TransferNftResponse(baseResponse, transferNftData); } diff --git a/lib/src/api/wallet_connect/models/commands/verify_signature_command.dart b/lib/src/api/wallet_connect/models/commands/verify_signature_command.dart index 8980a96c..042a2284 100644 --- a/lib/src/api/wallet_connect/models/commands/verify_signature_command.dart +++ b/lib/src/api/wallet_connect/models/commands/verify_signature_command.dart @@ -11,12 +11,17 @@ class VerifySignatureCommand implements WalletConnectCommand { }); factory VerifySignatureCommand.fromParams(Map params) { return VerifySignatureCommand( - publicKey: JacobianPoint.fromHexG1(pick(params, 'pubkey').asStringOrThrow()), + publicKey: + JacobianPoint.fromHexG1(pick(params, 'pubkey').asStringOrThrow()), message: pick(params, 'message').asStringOrThrow(), - signature: JacobianPoint.fromHexG2(pick(params, 'signature').asStringOrThrow()), - address: - params['address'] != null ? Address(pick(params, 'address').asStringOrThrow()) : null, - signingMode: SigningMode.maybeFromString(pick(params, 'signingMode').asStringOrNull()), + signature: + JacobianPoint.fromHexG2(pick(params, 'signature').asStringOrThrow()), + address: params['address'] != null + ? Address(pick(params, 'address').asStringOrThrow()) + : null, + signingMode: SigningMode.maybeFromString( + pick(params, 'signingMode').asStringOrNull(), + ), ); } @@ -109,7 +114,9 @@ enum SigningMode { const SigningMode(this.fullName); factory SigningMode.fromString(String modeString) { - return SigningMode.values.where((value) => value.fullName == modeString).single; + return SigningMode.values + .where((value) => value.fullName == modeString) + .single; } final String fullName; diff --git a/lib/src/api/wallet_connect/models/commands/wallet_connect_command.dart b/lib/src/api/wallet_connect/models/commands/wallet_connect_command.dart index f81abf7d..c92dd094 100644 --- a/lib/src/api/wallet_connect/models/commands/wallet_connect_command.dart +++ b/lib/src/api/wallet_connect/models/commands/wallet_connect_command.dart @@ -81,16 +81,21 @@ enum WalletConnectCommandType { addCATToken; factory WalletConnectCommandType.fromString(String commandString) { - return WalletConnectCommandType.values.where((value) => value.name == commandString).single; + return WalletConnectCommandType.values + .where((value) => value.name == commandString) + .single; } factory WalletConnectCommandType.fromMethod(String method) { - return WalletConnectCommandType.values.where((value) => value.commandName == method).single; + return WalletConnectCommandType.values + .where((value) => value.commandName == method) + .single; } String get commandName => 'chia_$name'; } extension CommandNames on List { - List get commandNames => map((command) => command.commandName).toList(); + List get commandNames => + map((command) => command.commandName).toList(); } diff --git a/lib/src/api/wallet_connect/models/commands/wallet_connect_command_error_response.dart b/lib/src/api/wallet_connect/models/commands/wallet_connect_command_error_response.dart index 23d7d36e..8fd6cecd 100644 --- a/lib/src/api/wallet_connect/models/commands/wallet_connect_command_error_response.dart +++ b/lib/src/api/wallet_connect/models/commands/wallet_connect_command_error_response.dart @@ -5,7 +5,9 @@ class WalletConnectCommandErrorResponse with ToJsonMixin, WalletConnectCommandResponseDecoratorMixin implements WalletConnectCommandBaseResponse { const WalletConnectCommandErrorResponse(this.delegate, this.error); - factory WalletConnectCommandErrorResponse.fromJson(Map json) { + factory WalletConnectCommandErrorResponse.fromJson( + Map json, + ) { final baseResponse = WalletConnectCommandBaseResponseImp.fromJson(json); final error = pick(json, 'error').letStringOrThrow((string) => string); diff --git a/lib/src/api/wallet_connect/models/commands/wallet_connect_command_response.dart b/lib/src/api/wallet_connect/models/commands/wallet_connect_command_response.dart index 88649b38..d4e93651 100644 --- a/lib/src/api/wallet_connect/models/commands/wallet_connect_command_response.dart +++ b/lib/src/api/wallet_connect/models/commands/wallet_connect_command_response.dart @@ -44,10 +44,13 @@ class WalletConnectCommandBaseResponseImp this.isSuccess, this.isError, }); - factory WalletConnectCommandBaseResponseImp.fromJson(Map json) { + factory WalletConnectCommandBaseResponseImp.fromJson( + Map json, + ) { return WalletConnectCommandBaseResponseImp( status: pick(json, 'status').asStringOrNull(), - endpointName: pick(json, 'endpointName').letStringOrNull(WalletConnectCommandType.fromString), + endpointName: pick(json, 'endpointName') + .letStringOrNull(WalletConnectCommandType.fromString), requestId: pick(json, 'requestId').asStringOrNull(), originalArgs: pick(json, 'originalArgs').letJsonOrNull((json) => json), startedTimestamp: pick(json, 'startedTimestamp').asIntOrNull(), @@ -165,7 +168,8 @@ class WalletConnectCommandBaseResponseImp } } -mixin WalletConnectCommandResponseDecoratorMixin implements WalletConnectCommandBaseResponse { +mixin WalletConnectCommandResponseDecoratorMixin + implements WalletConnectCommandBaseResponse { WalletConnectCommandBaseResponse get delegate; @override diff --git a/lib/src/api/wallet_connect/service/wallet_client/cold_wallet.dart b/lib/src/api/wallet_connect/service/wallet_client/cold_wallet.dart index 505917f5..524f78ca 100644 --- a/lib/src/api/wallet_connect/service/wallet_client/cold_wallet.dart +++ b/lib/src/api/wallet_connect/service/wallet_client/cold_wallet.dart @@ -14,15 +14,18 @@ class ColdWallet implements Wallet { WalletKeychain getKeychain() => keychain; @override - Future> getCatCoins() => fullNode.getCatCoinsByHints(keychain.puzzlehashes); + Future> getCatCoins() => + fullNode.getCatCoinsByHints(keychain.puzzlehashes); @override Future> getDidInfosWithOriginCoin() async { - final didRecords = await fullNode.getDidRecordsByHints(keychain.puzzlehashes); + final didRecords = + await fullNode.getDidRecordsByHints(keychain.puzzlehashes); final didInfosWithOriginCoin = []; for (final didRecord in didRecords) { - final didInfoWithOriginCoin = await didRecord.toDidInfo(keychain)?.fetchOriginCoin(fullNode); + final didInfoWithOriginCoin = + await didRecord.toDidInfo(keychain)?.fetchOriginCoin(fullNode); if (didInfoWithOriginCoin != null) { didInfosWithOriginCoin.add(didInfoWithOriginCoin); @@ -34,7 +37,8 @@ class ColdWallet implements Wallet { @override Future> getNftRecordsWithMintInfo() async { - final nftRecords = await fullNode.getNftRecordsByHints(keychain.puzzlehashes); + final nftRecords = + await fullNode.getNftRecordsByHints(keychain.puzzlehashes); final nftRecordsWithMintInfo = []; @@ -50,7 +54,10 @@ class ColdWallet implements Wallet { } @override - Future> getCatCoinsByAssetId(Puzzlehash assetId, {int catVersion = 2}) { + Future> getCatCoinsByAssetId( + Puzzlehash assetId, { + int catVersion = 2, + }) { if (!keychain.hasAssetId(assetId)) { switch (catVersion) { case 1: @@ -61,18 +68,23 @@ class ColdWallet implements Wallet { break; default: - throw InvalidCatException(message: 'Invalid cat version: $catVersion'); + throw InvalidCatException( + message: 'Invalid cat version: $catVersion', + ); } } final outerPuzzlehashes = keychain.getOuterPuzzleHashesForAssetId(assetId); - return fullNode - .getCatCoinsByOuterPuzzleHashes(outerPuzzlehashes) - .then((value) => value.where((element) => element.catVersion == catVersion).toList()); + return fullNode.getCatCoinsByOuterPuzzleHashes(outerPuzzlehashes).then( + (value) => value + .where((element) => element.catVersion == catVersion) + .toList(), + ); } @override - Future> getCoins() => fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); + Future> getCoins() => + fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); @override Future getNftRecordByLauncherId(Bytes launcherId) => fullNode.getNftByLauncherId(launcherId); diff --git a/lib/src/api/wallet_connect/service/wallet_client/full_node_request_handler.dart b/lib/src/api/wallet_connect/service/wallet_client/full_node_request_handler.dart index bce690bd..cf982362 100644 --- a/lib/src/api/wallet_connect/service/wallet_client/full_node_request_handler.dart +++ b/lib/src/api/wallet_connect/service/wallet_client/full_node_request_handler.dart @@ -17,7 +17,8 @@ class FullNodeWalletConnectRequestHandler Wallet get wallet => ColdWallet(fullNode: fullNode, keychain: keychain); @override - OfferService get offerService => OfferService(wallet, CatOfferWalletService()); + OfferService get offerService => + OfferService(wallet, CatOfferWalletService()); @override final EnhancedChiaFullNodeInterface fullNode; @@ -69,7 +70,8 @@ class FullNodeWalletConnectRequestHandler final tempWalletMap = Map.from(walletInfoMap!); final catCoins = await wallet.getCatCoins(); - final assetIds = catCoins.map((catCoin) => catCoin.assetId).toSet().toList(); + final assetIds = + catCoins.map((catCoin) => catCoin.assetId).toSet().toList(); final nftRecords = await wallet.getNftRecordsWithMintInfo(); final didInfos = await wallet.getDidInfosWithOriginCoin(); final dids = didInfos.map((didRecord) => didRecord.did).toList(); @@ -83,27 +85,31 @@ class FullNodeWalletConnectRequestHandler // we want to keep CAT wallets that are named, even if they no longer have any coins, since these // are wallets that the user explicitly added - final currentAssetIdsOfUnnamedWallets = - Map.fromEntries(currentCatWallets.entries.where((element) => element.value.name == null)) - .assetIdMap; + final currentAssetIdsOfUnnamedWallets = Map.fromEntries( + currentCatWallets.entries.where((element) => element.value.name == null), + ).assetIdMap; final catWalletIdsToRemove = Map.fromEntries( - currentAssetIdsOfUnnamedWallets.entries.where((entry) => !assetIds.contains(entry.value)), + currentAssetIdsOfUnnamedWallets.entries + .where((entry) => !assetIds.contains(entry.value)), ).keys; walletIdsToRemove.addAll(catWalletIdsToRemove); - final assetIdsToAdd = - assetIds.where((assetId) => !currentAssetIds.containsValue(assetId)).toSet(); + final assetIdsToAdd = assetIds + .where((assetId) => !currentAssetIds.containsValue(assetId)) + .toSet(); // did wallets final currentDids = tempWalletMap.didWallets().didMap; - final didWalletIdsToRemove = - Map.fromEntries(currentDids.entries.where((entry) => !dids.contains(entry.value))).keys; + final didWalletIdsToRemove = Map.fromEntries( + currentDids.entries.where((entry) => !dids.contains(entry.value)), + ).keys; walletIdsToRemove.addAll(didWalletIdsToRemove); - final didInfosToAdd = - didInfos.where((didInfo) => !currentDids.containsValue(didInfo.did)).toList(); + final didInfosToAdd = didInfos + .where((didInfo) => !currentDids.containsValue(didInfo.did)) + .toList(); tempWalletMap.removeWhere((key, value) => walletIdsToRemove.contains(key)); @@ -113,22 +119,26 @@ class FullNodeWalletConnectRequestHandler final nftWalletsToRemove = {}; final nftWalletsWithNullDid = Map.fromEntries( - currentNftWallets.entries.where((nftWallet) => nftWallet.value.did == null), + currentNftWallets.entries + .where((nftWallet) => nftWallet.value.did == null), ); final currentNftWalletsWithDid = Map.fromEntries( - currentNftWallets.entries - .where((nftWallet) => nftWalletsWithNullDid.keys.contains(nftWallet.key)), + currentNftWallets.entries.where( + (nftWallet) => nftWalletsWithNullDid.keys.contains(nftWallet.key), + ), ); // remove nft wallets associated with dids that are no longer owned final currentNftWalletIdsWithDid = Map.fromEntries( - currentNftWallets.entries - .where((nftWallet) => !currentNftWalletsWithDid.keys.contains(nftWallet.key)), + currentNftWallets.entries.where( + (nftWallet) => !currentNftWalletsWithDid.keys.contains(nftWallet.key), + ), ); final nftWalletsWithDidToRemove = Map.fromEntries( - currentNftWalletIdsWithDid.entries.where((entry) => dids.contains(entry.value.meta['did'])), + currentNftWalletIdsWithDid.entries + .where((entry) => dids.contains(entry.value.meta['did'])), ); nftWalletsToRemove.addAll(nftWalletsWithDidToRemove); @@ -139,8 +149,10 @@ class FullNodeWalletConnectRequestHandler final nftRecordsToAdd = nftRecords .where( (nftRecord) => - !currentNftWallets.launcherIdsMap.containsValue(nftRecord.launcherId) || - nftWalletsToRemove.launcherIdsMap.containsValue(nftRecord.launcherId) || + !currentNftWallets.launcherIdsMap + .containsValue(nftRecord.launcherId) || + nftWalletsToRemove.launcherIdsMap + .containsValue(nftRecord.launcherId) || (nftWalletsWithNullDid.isNotEmpty && nftWalletsWithNullDid.nftInfos .map((e) => e.launcherId) @@ -155,8 +167,9 @@ class FullNodeWalletConnectRequestHandler assetIds: assetIdsToAdd, nftRecords: nftRecordsToAdd, didInfos: didInfosToAdd, - unassignedNftWalletId: - nftWalletsWithNullDid.isNotEmpty ? nftWalletsWithNullDid.keys.first : null, + unassignedNftWalletId: nftWalletsWithNullDid.isNotEmpty + ? nftWalletsWithNullDid.keys.first + : null, ); } @@ -181,7 +194,10 @@ class FullNodeWalletConnectRequestHandler tempWalletMap[id] = DIDWalletInfo(didInfoWithOriginCoin: didInfo, id: id); final nftRecordsOwned = nftRecords - .where((nftRecord) => nftRecord.ownershipLayerInfo?.currentDid == didInfo.did) + .where( + (nftRecord) => + nftRecord.ownershipLayerInfo?.currentDid == didInfo.did, + ) .toList(); final nftInfosOwned = []; @@ -191,12 +207,15 @@ class FullNodeWalletConnectRequestHandler // Add an NFT wallet for each DID which the NFTs owned by that DID are assigned to, following Chia's pattern id++; - tempWalletMap[id] = - NftWalletInfoWithNftInfos(id: id, did: didInfo.did, nftInfos: nftInfosOwned); + tempWalletMap[id] = NftWalletInfoWithNftInfos( + id: id, + did: didInfo.did, + nftInfos: nftInfosOwned, + ); } - final nftRecordsWithoutDid = - nftRecords.where((nftRecord) => nftRecord.ownershipLayerInfo?.currentDid == null); + final nftRecordsWithoutDid = nftRecords + .where((nftRecord) => nftRecord.ownershipLayerInfo?.currentDid == null); // Add remaining unassigned NFTs to a singel NFT wallet if (nftRecordsWithoutDid.isNotEmpty) { @@ -208,7 +227,9 @@ class FullNodeWalletConnectRequestHandler tempWalletMap[id] = NftWalletInfoWithNftInfos( id: id, did: null, - nftInfos: nftRecordsWithoutDid.map(NftInfo.fromNftRecordWithMintInfo).toList(), + nftInfos: nftRecordsWithoutDid + .map(NftInfo.fromNftRecordWithMintInfo) + .toList(), ); } @@ -272,7 +293,10 @@ class FullNodeWalletConnectRequestHandler executeCheckOfferValidity(command); @override - GetAddressResponse getCurrentAddress(GetCurrentAddressCommand command, SessionData sessionData) { + GetAddressResponse getCurrentAddress( + GetCurrentAddressCommand command, + SessionData sessionData, + ) { final startedTimestamp = DateTime.now().unixTimestamp; final address = Address.fromContext(keychain.puzzlehashes.first); @@ -287,7 +311,10 @@ class FullNodeWalletConnectRequestHandler } @override - GetAddressResponse getNextAddress(GetNextAddressCommand command, SessionData sessionData) { + GetAddressResponse getNextAddress( + GetNextAddressCommand command, + SessionData sessionData, + ) { final startedTimestamp = DateTime.now().unixTimestamp; final address = Address.fromContext( @@ -348,7 +375,10 @@ class FullNodeWalletConnectRequestHandler final did = (wallet as DIDWalletInfo).didInfoWithOriginCoin.did; final nftCoinIds = Map.fromEntries( - walletInfoMap!.nftWallets().entries.where((entry) => entry.value.did == did), + walletInfoMap! + .nftWallets() + .entries + .where((entry) => entry.value.did == did), ).nftInfos.map((info) => info.nftCoinId).toList(); coinCount = nftCoinIds.length; @@ -366,7 +396,8 @@ class FullNodeWalletConnectRequestHandler final additions = []; final removals = []; for (final mempoolItem in mempoolItemsResponse.mempoolItemMap.values) { - final nftRecords = await NftRecord.nftRecordsFromSpendBundle(mempoolItem.spendBundle); + final nftRecords = + await NftRecord.nftRecordsFromSpendBundle(mempoolItem.spendBundle); for (final nftRecord in nftRecords) { if (nftRecord.ownershipLayerInfo?.currentDid == did) { @@ -385,10 +416,11 @@ class FullNodeWalletConnectRequestHandler coinCount = 0; balance = 0; } else if (wallet.type == ChiaWalletType.cat) { - final outerPuzzlehashesForAssetId = - keychain.getOuterPuzzleHashesForAssetId((wallet as CatWalletInfo).assetId); + final outerPuzzlehashesForAssetId = keychain + .getOuterPuzzleHashesForAssetId((wallet as CatWalletInfo).assetId); - final catCoins = await fullNode.getCatCoinsByOuterPuzzleHashes(outerPuzzlehashesForAssetId); + final catCoins = await fullNode + .getCatCoinsByOuterPuzzleHashes(outerPuzzlehashesForAssetId); coinCount = catCoins.length; balance = catCoins.totalValue; @@ -476,8 +508,9 @@ class FullNodeWalletConnectRequestHandler late final SpendBundle spendBundle; if (wallet.type == ChiaWalletType.nft) { - final nftRecord = await fullNode - .getNftByLauncherId((wallet as NftWalletInfoWithNftInfos).nftInfos.first.launcherId); + final nftRecord = await fullNode.getNftByLauncherId( + (wallet as NftWalletInfoWithNftInfos).nftInfos.first.launcherId, + ); final nftTransferSpendBundle = await _createNftTransferSpendBundle( nftRecord: nftRecord!, @@ -496,7 +529,8 @@ class FullNodeWalletConnectRequestHandler memos: memos, ); } else if (wallet.type == ChiaWalletType.standard) { - final allCoins = await fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); + final allCoins = + await fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); final coinsInput = selectCoinsForAmount(allCoins, command.amount); @@ -585,12 +619,14 @@ class FullNodeWalletConnectRequestHandler required Puzzlehash targetPuzzlehash, List memos = const [], }) async { - final allCatCoins = await fullNode - .getCatCoinsByOuterPuzzleHashes(keychain.getOuterPuzzleHashesForAssetId(assetId)); + final allCatCoins = await fullNode.getCatCoinsByOuterPuzzleHashes( + keychain.getOuterPuzzleHashesForAssetId(assetId), + ); final catCoins = selectCoinsForAmount(allCatCoins, amount); - final allCoins = await fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); + final allCoins = + await fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); final coinsForFee = selectCoinsForAmount(allCoins, fee); @@ -611,7 +647,10 @@ class FullNodeWalletConnectRequestHandler } @override - Future spendCat(SpendCatCommand command, SessionData sessionData) async { + Future spendCat( + SpendCatCommand command, + SessionData sessionData, + ) async { final startedTimestamp = DateTime.now().unixTimestamp; await indexWalletMap(); @@ -709,7 +748,8 @@ class FullNodeWalletConnectRequestHandler required int fee, List memos = const [], }) async { - final allCoins = await fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); + final allCoins = + await fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); final coinsForFee = selectCoinsForAmount(allCoins, fee); @@ -767,7 +807,11 @@ class FullNodeWalletConnectRequestHandler command: command, startedTimestamp: startedTimestamp, ), - TransferNftData(spendBundle: totalSpendBundle, walletId: wallet.id, success: true), + TransferNftData( + spendBundle: totalSpendBundle, + walletId: wallet.id, + success: true, + ), ); } @@ -803,11 +847,14 @@ class FullNodeWalletConnectRequestHandler } @override - Future takeOffer(TakeOfferCommand command, SessionData sessionData) async { + Future takeOffer( + TakeOfferCommand command, + SessionData sessionData, + ) async { final startedTimestamp = DateTime.now().unixTimestamp; - final takeOffer = - await offerService.createTakeOffer(Offer.fromBech32(command.offer), fee: command.fee); + final takeOffer = await offerService + .createTakeOffer(Offer.fromBech32(command.offer), fee: command.fee); final spendBundle = takeOffer.toSpendBundle(); @@ -848,7 +895,8 @@ class FullNodeWalletConnectRequestHandler final puzzlehash = keychain.puzzlehashes[2]; - final parsedOfferMap = await parseAmountsFromOfferMap(command.offerMap, puzzlehash); + final parsedOfferMap = + await parseAmountsFromOfferMap(command.offerMap, puzzlehash); final offer = await offerService.createOfferAsync( offeredAmounts: parsedOfferMap.offeredAmounts, @@ -877,7 +925,10 @@ class FullNodeWalletConnectRequestHandler } @override - Future getNftInfo(GetNftInfoCommand command, SessionData sessionData) async { + Future getNftInfo( + GetNftInfoCommand command, + SessionData sessionData, + ) async { final startedTimestamp = DateTime.now().unixTimestamp; await indexWalletMap(); @@ -897,7 +948,10 @@ class FullNodeWalletConnectRequestHandler } @override - Future getNfts(GetNftsCommand command, SessionData sessionData) async { + Future getNfts( + GetNftsCommand command, + SessionData sessionData, + ) async { final startedTimestamp = DateTime.now().unixTimestamp; await indexWalletMap(); @@ -940,14 +994,18 @@ class FullNodeWalletConnectRequestHandler } @override - Future getWallets(GetWalletsCommand command, SessionData sessionData) async { + Future getWallets( + GetWalletsCommand command, + SessionData sessionData, + ) async { final startedTimestamp = DateTime.now().unixTimestamp; await indexWalletMap(); late final List walletsData; if (!command.includeData) { - walletsData = walletInfoMap!.values.map((wallet) => wallet.stripData()).toList(); + walletsData = + walletInfoMap!.values.map((wallet) => wallet.stripData()).toList(); } else { walletsData = walletInfoMap!.values.toList(); } @@ -1017,8 +1075,11 @@ class FullNodeWalletConnectRequestHandler keychain.addOuterPuzzleHashesForAssetId(command.assetId); - walletInfoMap![walletId] = - CatWalletInfo(assetId: command.assetId, id: walletId, name: command.name); + walletInfoMap![walletId] = CatWalletInfo( + assetId: command.assetId, + id: walletId, + name: command.name, + ); return AddCatTokenResponse( WalletConnectCommandBaseResponseImp.success( diff --git a/lib/src/api/wallet_connect/service/wallet_client/mixins/irulast_request_handler_mixin.dart b/lib/src/api/wallet_connect/service/wallet_client/mixins/irulast_request_handler_mixin.dart index d68cd37c..93c1e36a 100644 --- a/lib/src/api/wallet_connect/service/wallet_client/mixins/irulast_request_handler_mixin.dart +++ b/lib/src/api/wallet_connect/service/wallet_client/mixins/irulast_request_handler_mixin.dart @@ -4,7 +4,8 @@ import 'package:chia_crypto_utils/chia_crypto_utils.dart'; /// Creates a mapping of walletId to [ChiaWalletInfo] in order to conform to Chia's standard and holds /// functionality for command execution methods that is shared between implementations of [WalletConnectRequestHandler]. -mixin IrulastWalletConnectRequestHandlerMixin implements WalletConnectRequestHandler { +mixin IrulastWalletConnectRequestHandlerMixin + implements WalletConnectRequestHandler { OfferService get offerService; Wallet get wallet; ChiaFullNodeInterface get fullNode; @@ -22,7 +23,8 @@ mixin IrulastWalletConnectRequestHandlerMixin implements WalletConnectRequestHan final walletVector = keychain.getWalletVector(puzzlehash); - final syntheticSecretKey = calculateSyntheticPrivateKey(walletVector!.childPrivateKey); + final syntheticSecretKey = + calculateSyntheticPrivateKey(walletVector!.childPrivateKey); final message = constructChip002Message(command.message); @@ -52,7 +54,8 @@ mixin IrulastWalletConnectRequestHandlerMixin implements WalletConnectRequestHan final walletVector = keychain.getWalletVector(p2Puzzlehash); - final syntheticSecretKey = calculateSyntheticPrivateKey(walletVector!.childPrivateKey); + final syntheticSecretKey = + calculateSyntheticPrivateKey(walletVector!.childPrivateKey); final message = constructChip002Message(command.message); @@ -73,7 +76,9 @@ mixin IrulastWalletConnectRequestHandlerMixin implements WalletConnectRequestHan ); } - Future executeVerifySignature(VerifySignatureCommand command) async { + Future executeVerifySignature( + VerifySignatureCommand command, + ) async { final startedTimestamp = DateTime.now().unixTimestamp; // default to CHIP-002 because that is how messages are signed with the sign methods on this handler @@ -163,8 +168,11 @@ mixin IrulastWalletConnectRequestHandlerMixin implements WalletConnectRequestHan } } - final offeredAmounts = - MixedAmounts(standard: offeredXch, cat: offeredCat, nft: offeredNftLauncherIds); + final offeredAmounts = MixedAmounts( + standard: offeredXch, + cat: offeredCat, + nft: offeredNftLauncherIds, + ); final requestedPayments = RequestedMixedPayments( standard: requestedStandard, @@ -217,7 +225,9 @@ mixin IrulastWalletConnectRequestHandlerMixin implements WalletConnectRequestHan ); } - Future executeSignSpendBundle(SignSpendBundleCommand command) async { + Future executeSignSpendBundle( + SignSpendBundleCommand command, + ) async { final startedTimestamp = DateTime.now().unixTimestamp; final keychain = await wallet.getKeychain(); diff --git a/lib/src/api/wallet_connect/service/wallet_client/wallet_connect_request_handler.dart b/lib/src/api/wallet_connect/service/wallet_client/wallet_connect_request_handler.dart index c6c14897..f36146cf 100644 --- a/lib/src/api/wallet_connect/service/wallet_client/wallet_connect_request_handler.dart +++ b/lib/src/api/wallet_connect/service/wallet_client/wallet_connect_request_handler.dart @@ -33,11 +33,20 @@ abstract class WalletConnectRequestHandler { SessionData sessionData, ); - FutureOr getNftsCount(GetNftsCountCommand command, SessionData sessionData); + FutureOr getNftsCount( + GetNftsCountCommand command, + SessionData sessionData, + ); - FutureOr getNftInfo(GetNftInfoCommand command, SessionData sessionData); + FutureOr getNftInfo( + GetNftInfoCommand command, + SessionData sessionData, + ); - FutureOr getNfts(GetNftsCommand command, SessionData sessionData); + FutureOr getNfts( + GetNftsCommand command, + SessionData sessionData, + ); FutureOr getSyncStatus(SessionData sessionData); @@ -51,7 +60,10 @@ abstract class WalletConnectRequestHandler { SessionData sessionData, ); - FutureOr getWallets(GetWalletsCommand command, SessionData sessionData); + FutureOr getWallets( + GetWalletsCommand command, + SessionData sessionData, + ); FutureOr sendTransaction( SendTransactionCommand command, @@ -68,11 +80,20 @@ abstract class WalletConnectRequestHandler { SessionData sessionData, ); - FutureOr spendCat(SpendCatCommand command, SessionData sessionData); + FutureOr spendCat( + SpendCatCommand command, + SessionData sessionData, + ); - FutureOr takeOffer(TakeOfferCommand command, SessionData sessionData); + FutureOr takeOffer( + TakeOfferCommand command, + SessionData sessionData, + ); - FutureOr transferNft(TransferNftCommand command, SessionData sessionData); + FutureOr transferNft( + TransferNftCommand command, + SessionData sessionData, + ); FutureOr verifySignature( VerifySignatureCommand command, @@ -101,7 +122,10 @@ extension CommandMethods on WalletConnectRequestHandler { dynamic params, ) { try { - return WalletConnectCommand.fromParams(type, params as Map); + return WalletConnectCommand.fromParams( + type, + params as Map, + ); } catch (e) { throw ErrorParsingWalletConnectCommand(); } @@ -115,53 +139,83 @@ extension CommandMethods on WalletConnectRequestHandler { late final WalletConnectCommandBaseResponse response; switch (command.type) { case WalletConnectCommandType.getTransaction: - response = await getTransaction(command as GetTransactionCommand, sessionData); + response = await getTransaction( + command as GetTransactionCommand, + sessionData, + ); break; case WalletConnectCommandType.getWalletBalance: - response = await getWalletBalance(command as GetWalletBalanceCommand, sessionData); + response = await getWalletBalance( + command as GetWalletBalanceCommand, + sessionData, + ); break; case WalletConnectCommandType.getNFTs: response = await getNfts(command as GetNftsCommand, sessionData); break; case WalletConnectCommandType.getNFTInfo: - response = await getNftInfo(command as GetNftInfoCommand, sessionData); + response = + await getNftInfo(command as GetNftInfoCommand, sessionData); break; case WalletConnectCommandType.getNFTsCount: - response = await getNftsCount(command as GetNftsCountCommand, sessionData); + response = + await getNftsCount(command as GetNftsCountCommand, sessionData); break; case WalletConnectCommandType.signMessageById: - response = await signMessageById(command as SignMessageByIdCommand, sessionData); + response = await signMessageById( + command as SignMessageByIdCommand, + sessionData, + ); break; case WalletConnectCommandType.signMessageByAddress: - response = - await signMessageByAddress(command as SignMessageByAddressCommand, sessionData); + response = await signMessageByAddress( + command as SignMessageByAddressCommand, + sessionData, + ); break; case WalletConnectCommandType.verifySignature: - response = await verifySignature(command as VerifySignatureCommand, sessionData); + response = await verifySignature( + command as VerifySignatureCommand, + sessionData, + ); break; case WalletConnectCommandType.checkOfferValidity: - response = await checkOfferValidity(command as CheckOfferValidityCommand, sessionData); + response = await checkOfferValidity( + command as CheckOfferValidityCommand, + sessionData, + ); break; case WalletConnectCommandType.transferNFT: - response = await transferNft(command as TransferNftCommand, sessionData); + response = + await transferNft(command as TransferNftCommand, sessionData); break; case WalletConnectCommandType.sendTransaction: - response = await sendTransaction(command as SendTransactionCommand, sessionData); + response = await sendTransaction( + command as SendTransactionCommand, + sessionData, + ); break; case WalletConnectCommandType.takeOffer: response = await takeOffer(command as TakeOfferCommand, sessionData); break; case WalletConnectCommandType.getWallets: - response = await getWallets(command as GetWalletsCommand, sessionData); + response = + await getWallets(command as GetWalletsCommand, sessionData); break; case WalletConnectCommandType.spendCAT: response = await spendCat(command as SpendCatCommand, sessionData); break; case WalletConnectCommandType.getCurrentAddress: - response = await getCurrentAddress(command as GetCurrentAddressCommand, sessionData); + response = await getCurrentAddress( + command as GetCurrentAddressCommand, + sessionData, + ); break; case WalletConnectCommandType.getNextAddress: - response = await getNextAddress(command as GetNextAddressCommand, sessionData); + response = await getNextAddress( + command as GetNextAddressCommand, + sessionData, + ); break; case WalletConnectCommandType.getSyncStatus: response = await getSyncStatus(sessionData); @@ -170,14 +224,21 @@ extension CommandMethods on WalletConnectRequestHandler { response = await logIn(command as LogInCommand, sessionData); break; case WalletConnectCommandType.createOfferForIds: - response = await createOfferForIds(command as CreateOfferForIdsCommand, sessionData); + response = await createOfferForIds( + command as CreateOfferForIdsCommand, + sessionData, + ); break; case WalletConnectCommandType.signSpendBundle: - response = await signSpendBundle(command as SignSpendBundleCommand, sessionData); + response = await signSpendBundle( + command as SignSpendBundleCommand, + sessionData, + ); break; case WalletConnectCommandType.addCATToken: - response = await addCatToken(command as AddCatTokenCommand, sessionData); + response = + await addCatToken(command as AddCatTokenCommand, sessionData); break; } diff --git a/lib/src/api/wallet_connect/service/wallet_client/wallet_connect_wallet_client.dart b/lib/src/api/wallet_connect/service/wallet_client/wallet_connect_wallet_client.dart index 6ae5b204..1997bad8 100644 --- a/lib/src/api/wallet_connect/service/wallet_client/wallet_connect_wallet_client.dart +++ b/lib/src/api/wallet_connect/service/wallet_client/wallet_connect_wallet_client.dart @@ -31,7 +31,8 @@ class WalletConnectWalletClient { Future init() async { await web3Wallet.init(); - web3Wallet.onSessionProposal.subscribe((SessionProposalEvent? sessionProposal) async { + web3Wallet.onSessionProposal + .subscribe((SessionProposalEvent? sessionProposal) async { if (sessionProposal == null) { return; } @@ -58,12 +59,17 @@ class WalletConnectWalletClient { final chiaNamespace = requiredNamespaces['chia']; if (chiaNamespace == null) { - await rejectSession(sessionProposal.id, Errors.getSdkError(Errors.NON_CONFORMING_NAMESPACES)); + await rejectSession( + sessionProposal.id, + Errors.getSdkError(Errors.NON_CONFORMING_NAMESPACES), + ); LoggingContext().info('rejecting due to chia namespace missing'); return; } - final commands = chiaNamespace.methods.where((method) => method.startsWith('chia_')).toList(); + final commands = chiaNamespace.methods + .where((method) => method.startsWith('chia_')) + .toList(); if (handleProposal == null) { throw UnregisteredSessionProposalHandler(); @@ -72,11 +78,15 @@ class WalletConnectWalletClient { final fingerprints = await handleProposal!(sessionProposal); if (fingerprints != null) { - final approveResponse = await approveSession(sessionProposal.id, fingerprints, commands); + final approveResponse = + await approveSession(sessionProposal.id, fingerprints, commands); await handleSessionApproval?.call(approveResponse); } else { - await rejectSession(sessionProposal.id, Errors.getSdkError(Errors.USER_REJECTED)); + await rejectSession( + sessionProposal.id, + Errors.getSdkError(Errors.USER_REJECTED), + ); } } @@ -99,7 +109,8 @@ class WalletConnectWalletClient { ), }; - final response = await web3Wallet.approveSession(id: id, namespaces: namespaces); + final response = + await web3Wallet.approveSession(id: id, namespaces: namespaces); return response; } @@ -140,11 +151,15 @@ class WalletConnectWalletClient { this.requestHandler = requestHandler; } - void registerProposalHandler(WalletConnectSessionProposalHandler proposalHandler) { + void registerProposalHandler( + WalletConnectSessionProposalHandler proposalHandler, + ) { handleProposal = proposalHandler; } - void registerSessionApprovalHandler(WalletConnectSessionApprovalHandler approvalHandler) { + void registerSessionApprovalHandler( + WalletConnectSessionApprovalHandler approvalHandler, + ) { handleSessionApproval = approvalHandler; } } diff --git a/lib/src/api/wallet_connect/service/wallet_connect_app_client.dart b/lib/src/api/wallet_connect/service/wallet_connect_app_client.dart index c58d80c5..8e10cdae 100644 --- a/lib/src/api/wallet_connect/service/wallet_connect_app_client.dart +++ b/lib/src/api/wallet_connect/service/wallet_connect_app_client.dart @@ -97,7 +97,9 @@ class WalletConnectAppClient { return _waitForSessionApproval(connectResponse); } - Future _waitForSessionApproval(ConnectResponse connectResponse) async { + Future _waitForSessionApproval( + ConnectResponse connectResponse, + ) async { print('waiting for session to be approved'); try { final sessionData = await connectResponse.session.future; @@ -126,7 +128,8 @@ class WalletConnectAppClient { }) async { return request( fingerprint: fingerprint, - command: GetTransactionCommand(transactionId: Bytes.fromHex(transactionId)), + command: + GetTransactionCommand(transactionId: Bytes.fromHex(transactionId)), parseResponse: GetTransactionResponse.fromJson, ); } @@ -150,7 +153,11 @@ class WalletConnectAppClient { }) async { return request( fingerprint: fingerprint, - command: GetNftsCommand(walletIds: walletIds, startIndex: startIndex, num: num), + command: GetNftsCommand( + walletIds: walletIds, + startIndex: startIndex, + num: num, + ), parseResponse: GetNftsResponse.fromJson, ); } @@ -485,8 +492,10 @@ class WalletConnectAppClient { } extension Fingerprints on SessionData { - List get fingerprints => - namespaces['chia']!.accounts.map((account) => int.parse(account.split(':').last)).toList(); + List get fingerprints => namespaces['chia']! + .accounts + .map((account) => int.parse(account.split(':').last)) + .toList(); } class NotConnectedException implements Exception { diff --git a/lib/src/api/wallet_connect/utils/transaction_memos.dart b/lib/src/api/wallet_connect/utils/transaction_memos.dart index 5123ebac..6c320f98 100644 --- a/lib/src/api/wallet_connect/utils/transaction_memos.dart +++ b/lib/src/api/wallet_connect/utils/transaction_memos.dart @@ -1,6 +1,9 @@ import 'package:chia_crypto_utils/chia_crypto_utils.dart'; -Map> makeTransactionMemos(SpendBundle spendBundle, List memos) { +Map> makeTransactionMemos( + SpendBundle spendBundle, + List memos, +) { return Map.fromEntries( spendBundle.coins.map((coin) => MapEntry(coin.id, memos)), ); diff --git a/lib/src/bls/ec/affine_point.dart b/lib/src/bls/ec/affine_point.dart index 0b0c8d72..cd851398 100644 --- a/lib/src/bls/ec/affine_point.dart +++ b/lib/src/bls/ec/affine_point.dart @@ -96,7 +96,10 @@ class AffinePoint { @override bool operator ==(Object other) => - other is AffinePoint && x == other.x && y == other.y && infinity == other.infinity; + other is AffinePoint && + x == other.x && + y == other.y && + infinity == other.infinity; @override int get hashCode => hash3(x, y, infinity); diff --git a/lib/src/bls/ec/ec.dart b/lib/src/bls/ec/ec.dart index e6ed5211..219a7438 100644 --- a/lib/src/bls/ec/ec.dart +++ b/lib/src/bls/ec/ec.dart @@ -41,7 +41,8 @@ class EC { } final defaultEc = EC(q, a, b, gx, gy, g2x, g2y, n, h, x, k, sqrtN3, sqrtN3m1o2); -final defaultEcTwist = EC(q, aTwist, bTwist, gx, gy, g2x, g2y, n, hEff, x, k, sqrtN3, sqrtN3m1o2); +final defaultEcTwist = + EC(q, aTwist, bTwist, gx, gy, g2x, g2y, n, hEff, x, k, sqrtN3, sqrtN3m1o2); bool signFq(Fq element, {EC? ec}) { ec ??= defaultEc; @@ -146,9 +147,10 @@ JacobianPoint evalIso(JacobianPoint P, List> mapCoeffs, EC ec) { final mapVals = List.filled(4, null); for (final item in enumerate(mapCoeffs)) { - final coeffsZ = zip([item.value.reversed.toList(), zPows.sublist(0, item.value.length)]) - .map((item) => item[0] * item[1]) - .toList(); + final coeffsZ = + zip([item.value.reversed.toList(), zPows.sublist(0, item.value.length)]) + .map((item) => item[0] * item[1]) + .toList(); var tmp = coeffsZ[0]; for (final coeff in coeffsZ.sublist(1, coeffsZ.length)) { tmp *= x; diff --git a/lib/src/bls/ec/jacobian_point.dart b/lib/src/bls/ec/jacobian_point.dart index 8fd8d7b7..9f3a0bec 100644 --- a/lib/src/bls/ec/jacobian_point.dart +++ b/lib/src/bls/ec/jacobian_point.dart @@ -12,8 +12,6 @@ import 'package:meta/meta.dart'; @immutable class JacobianPoint with ToBytesMixin, ToProgramMixin { - static const g1BytesLength = 48; - static const g2BytesLength = 96; JacobianPoint(this.x, this.y, this.z, this.infinity, {EC? ec}) : ec = ec ?? defaultEc, isExtension = x is! Fq { @@ -23,6 +21,79 @@ class JacobianPoint with ToBytesMixin, ToProgramMixin { ); } } + factory JacobianPoint.fromBytesG2(List bytes, {bool? isExtension}) { + isExtension ??= true; + return JacobianPoint.fromBytes(bytes, isExtension, ec: defaultEcTwist); + } + + factory JacobianPoint.fromHexG2(String hex, {bool? isExtension}) { + return JacobianPoint.fromBytesG2( + const HexDecoder().convert(hex.stripBytesPrefix()), + isExtension: isExtension, + ); + } + + factory JacobianPoint.fromHexG1(String hex, {bool? isExtension}) { + return JacobianPoint.fromBytesG1( + const HexDecoder().convert(hex.stripBytesPrefix()), + isExtension: isExtension, + ); + } + + factory JacobianPoint.fromBytesG1(List bytes, {bool? isExtension}) { + isExtension ??= false; + return JacobianPoint.fromBytes(bytes, isExtension, ec: defaultEc); + } + + factory JacobianPoint.infinityG2({bool? isExtension}) { + isExtension ??= true; + return JacobianPoint( + isExtension ? Fq2.zero(defaultEcTwist.q) : Fq.zero(defaultEcTwist.q), + isExtension ? Fq2.zero(defaultEcTwist.q) : Fq.zero(defaultEcTwist.q), + isExtension ? Fq2.zero(defaultEcTwist.q) : Fq.zero(defaultEcTwist.q), + true, + ec: defaultEcTwist, + ); + } + + factory JacobianPoint.infinityG1({bool? isExtension}) { + isExtension ??= false; + return JacobianPoint( + isExtension ? Fq2.zero(defaultEc.q) : Fq.zero(defaultEc.q), + isExtension ? Fq2.zero(defaultEc.q) : Fq.zero(defaultEc.q), + isExtension ? Fq2.zero(defaultEc.q) : Fq.zero(defaultEc.q), + true, + ec: defaultEc, + ); + } + + factory JacobianPoint.generateG2() => AffinePoint( + defaultEcTwist.g2x, + defaultEcTwist.g2y, + false, + ec: defaultEcTwist, + ).toJacobian(); + + factory JacobianPoint.generateG1() => + AffinePoint(defaultEc.gx, defaultEc.gy, false, ec: defaultEc) + .toJacobian(); + + factory JacobianPoint.fromHex(String hex, bool isExtension, {EC? ec}) => + JacobianPoint.fromBytes( + const HexDecoder().convert(hex), + isExtension, + ec: ec, + ); + + factory JacobianPoint.fromStreamG2(Iterator iterator) { + final signatureBytes = iterator.extractBytesAndAdvance(g2BytesLength); + return JacobianPoint.fromBytesG2(signatureBytes); + } + + factory JacobianPoint.fromStreamG1(Iterator iterator) { + final publicKeyBytes = iterator.extractBytesAndAdvance(g1BytesLength); + return JacobianPoint.fromBytesG1(publicKeyBytes); + } factory JacobianPoint.fromBytes(List bytes, bool isExtension, {EC? ec}) { ec ??= defaultEc; @@ -61,7 +132,8 @@ class JacobianPoint with ToBytesMixin, ToProgramMixin { ec: ec, ).toJacobian(); } - final x = isExtension ? Fq2.fromBytes(bytes, ec.q) : Fq.fromBytes(bytes, ec.q); + final x = + isExtension ? Fq2.fromBytes(bytes, ec.q) : Fq.fromBytes(bytes, ec.q); final yValue = yForX(x, ec: ec); bool sign; if (isExtension) { @@ -72,78 +144,8 @@ class JacobianPoint with ToBytesMixin, ToProgramMixin { final y = sign == (bitS != 0) ? yValue : -yValue; return AffinePoint(x, y, false, ec: ec).toJacobian(); } - - factory JacobianPoint.fromStreamG1(Iterator iterator) { - final publicKeyBytes = iterator.extractBytesAndAdvance(g1BytesLength); - return JacobianPoint.fromBytesG1(publicKeyBytes); - } - - factory JacobianPoint.fromStreamG2(Iterator iterator) { - final signatureBytes = iterator.extractBytesAndAdvance(g2BytesLength); - return JacobianPoint.fromBytesG2(signatureBytes); - } - - factory JacobianPoint.fromHex(String hex, bool isExtension, {EC? ec}) => JacobianPoint.fromBytes( - const HexDecoder().convert(hex), - isExtension, - ec: ec, - ); - - factory JacobianPoint.generateG1() => - AffinePoint(defaultEc.gx, defaultEc.gy, false, ec: defaultEc).toJacobian(); - - factory JacobianPoint.generateG2() => AffinePoint( - defaultEcTwist.g2x, - defaultEcTwist.g2y, - false, - ec: defaultEcTwist, - ).toJacobian(); - - factory JacobianPoint.infinityG1({bool? isExtension}) { - isExtension ??= false; - return JacobianPoint( - isExtension ? Fq2.zero(defaultEc.q) : Fq.zero(defaultEc.q), - isExtension ? Fq2.zero(defaultEc.q) : Fq.zero(defaultEc.q), - isExtension ? Fq2.zero(defaultEc.q) : Fq.zero(defaultEc.q), - true, - ec: defaultEc, - ); - } - - factory JacobianPoint.infinityG2({bool? isExtension}) { - isExtension ??= true; - return JacobianPoint( - isExtension ? Fq2.zero(defaultEcTwist.q) : Fq.zero(defaultEcTwist.q), - isExtension ? Fq2.zero(defaultEcTwist.q) : Fq.zero(defaultEcTwist.q), - isExtension ? Fq2.zero(defaultEcTwist.q) : Fq.zero(defaultEcTwist.q), - true, - ec: defaultEcTwist, - ); - } - - factory JacobianPoint.fromBytesG1(List bytes, {bool? isExtension}) { - isExtension ??= false; - return JacobianPoint.fromBytes(bytes, isExtension, ec: defaultEc); - } - - factory JacobianPoint.fromHexG1(String hex, {bool? isExtension}) { - return JacobianPoint.fromBytesG1( - const HexDecoder().convert(hex.stripBytesPrefix()), - isExtension: isExtension, - ); - } - - factory JacobianPoint.fromHexG2(String hex, {bool? isExtension}) { - return JacobianPoint.fromBytesG2( - const HexDecoder().convert(hex.stripBytesPrefix()), - isExtension: isExtension, - ); - } - - factory JacobianPoint.fromBytesG2(List bytes, {bool? isExtension}) { - isExtension ??= true; - return JacobianPoint.fromBytes(bytes, isExtension, ec: defaultEcTwist); - } + static const g1BytesLength = 48; + static const g2BytesLength = 96; final Field x; final Field y; @@ -210,7 +212,8 @@ class JacobianPoint with ToBytesMixin, ToProgramMixin { return JacobianPoint(X_p, Y_p, Z_p, false, ec: ec); } - int getFingerprint() => bytesToInt(sha256.convert(toBytes()).bytes.sublist(0, 4), Endian.big); + int getFingerprint() => + bytesToInt(sha256.convert(toBytes()).bytes.sublist(0, 4), Endian.big); JacobianPoint operator -() => (-toAffine()).toJacobian(); @@ -256,7 +259,8 @@ class JacobianPoint with ToBytesMixin, ToProgramMixin { } @override - bool operator ==(Object other) => other is JacobianPoint && toAffine() == other.toAffine(); + bool operator ==(Object other) => + other is JacobianPoint && toAffine() == other.toAffine(); @override int get hashCode => toBytes().hashCode; @@ -264,7 +268,8 @@ class JacobianPoint with ToBytesMixin, ToProgramMixin { @override String toString() => 'JacobianPoint(0x${toHex()})'; - JacobianPoint clone() => JacobianPoint(x.clone(), y.clone(), z.clone(), infinity, ec: ec); + JacobianPoint clone() => + JacobianPoint(x.clone(), y.clone(), z.clone(), infinity, ec: ec); @override Program toProgram() { diff --git a/lib/src/bls/field/extensions/fq12.dart b/lib/src/bls/field/extensions/fq12.dart index d71ff93e..be8eed53 100644 --- a/lib/src/bls/field/extensions/fq12.dart +++ b/lib/src/bls/field/extensions/fq12.dart @@ -30,11 +30,14 @@ class Fq12 extends FieldExtBase { } @override - Fq12 construct(BigInt Q, List args, Field? root) => Fq12(Q, args, root: root); + Fq12 construct(BigInt Q, List args, Field? root) => + Fq12(Q, args, root: root); factory Fq12.fromFq(BigInt Q, Fq fq) => Fq12.nil().myFromFq(Q, fq); - factory Fq12.fromBytes(List bytes, BigInt Q) => Fq12.nil().myFromBytes(bytes, Q) as Fq12; - factory Fq12.fromHex(String hex, BigInt Q) => Fq12.nil().myFromHex(hex, Q) as Fq12; + factory Fq12.fromBytes(List bytes, BigInt Q) => + Fq12.nil().myFromBytes(bytes, Q) as Fq12; + factory Fq12.fromHex(String hex, BigInt Q) => + Fq12.nil().myFromHex(hex, Q) as Fq12; factory Fq12.zero(BigInt Q) => Fq12.nil().myZero(Q); factory Fq12.one(BigInt Q) => Fq12.nil().myOne(Q); } diff --git a/lib/src/bls/field/extensions/fq2.dart b/lib/src/bls/field/extensions/fq2.dart index 7ae853fd..3670eadf 100644 --- a/lib/src/bls/field/extensions/fq2.dart +++ b/lib/src/bls/field/extensions/fq2.dart @@ -51,11 +51,14 @@ class Fq2 extends FieldExtBase { } @override - Fq2 construct(BigInt Q, List args, Field? root) => Fq2(Q, args, root: root); + Fq2 construct(BigInt Q, List args, Field? root) => + Fq2(Q, args, root: root); factory Fq2.fromFq(BigInt Q, Fq fq) => Fq2.nil().myFromFq(Q, fq); - factory Fq2.fromBytes(List bytes, BigInt Q) => Fq2.nil().myFromBytes(bytes, Q) as Fq2; - factory Fq2.fromHex(String hex, BigInt Q) => Fq2.nil().myFromHex(hex, Q) as Fq2; + factory Fq2.fromBytes(List bytes, BigInt Q) => + Fq2.nil().myFromBytes(bytes, Q) as Fq2; + factory Fq2.fromHex(String hex, BigInt Q) => + Fq2.nil().myFromHex(hex, Q) as Fq2; factory Fq2.zero(BigInt Q) => Fq2.nil().myZero(Q); factory Fq2.one(BigInt Q) => Fq2.nil().myOne(Q); } diff --git a/lib/src/bls/field/extensions/fq6.dart b/lib/src/bls/field/extensions/fq6.dart index 32f4e8ec..7392c0c7 100644 --- a/lib/src/bls/field/extensions/fq6.dart +++ b/lib/src/bls/field/extensions/fq6.dart @@ -40,11 +40,14 @@ class Fq6 extends FieldExtBase { } @override - Fq6 construct(BigInt Q, List args, Field? root) => Fq6(Q, args, root: root); + Fq6 construct(BigInt Q, List args, Field? root) => + Fq6(Q, args, root: root); factory Fq6.fromFq(BigInt Q, Fq fq) => Fq6.nil().myFromFq(Q, fq); - factory Fq6.fromBytes(List bytes, BigInt Q) => Fq6.nil().myFromBytes(bytes, Q) as Fq6; - factory Fq6.fromHex(String hex, BigInt Q) => Fq6.nil().myFromHex(hex, Q) as Fq6; + factory Fq6.fromBytes(List bytes, BigInt Q) => + Fq6.nil().myFromBytes(bytes, Q) as Fq6; + factory Fq6.fromHex(String hex, BigInt Q) => + Fq6.nil().myFromHex(hex, Q) as Fq6; factory Fq6.zero(BigInt Q) => Fq6.nil().myZero(Q); factory Fq6.one(BigInt Q) => Fq6.nil().myOne(Q); } diff --git a/lib/src/bls/field/field_base.dart b/lib/src/bls/field/field_base.dart index bb0e7381..129354eb 100644 --- a/lib/src/bls/field/field_base.dart +++ b/lib/src/bls/field/field_base.dart @@ -97,7 +97,8 @@ class Fq extends Field { } @override - bool equal(dynamic other) => other is Fq && value == other.value && Q == other.Q; + bool equal(dynamic other) => + other is Fq && value == other.value && Q == other.Q; @override String toString() { diff --git a/lib/src/bls/field/field_ext.dart b/lib/src/bls/field/field_ext.dart index a63cd06e..676a6206 100644 --- a/lib/src/bls/field/field_ext.dart +++ b/lib/src/bls/field/field_ext.dart @@ -57,7 +57,9 @@ abstract class FieldExtBase> extends Field { return construct( Q, - zip([elements, otherNew]).map((element) => element[0] + element[1]).toList(), + zip([elements, otherNew]) + .map((element) => element[0] + element[1]) + .toList(), root, ); } @@ -222,7 +224,8 @@ abstract class FieldExtBase> extends Field { } @override - FieldExtBase myFromHex(String hex, BigInt Q) => myFromBytes(const HexDecoder().convert(hex), Q); + FieldExtBase myFromHex(String hex, BigInt Q) => + myFromBytes(const HexDecoder().convert(hex), Q); @override F pow(BigInt exponent) { @@ -297,7 +300,8 @@ abstract class FieldExtBase> extends Field { .map( (element) => element.index == 0 ? element.value.qiPower(_i) - : element.value.qiPower(_i) * getFrobCoeff([extension, _i, element.index]), + : element.value.qiPower(_i) * + getFrobCoeff([extension, _i, element.index]), ) .toList(); return construct(Q, items, root); diff --git a/lib/src/bls/hash_to_field.dart b/lib/src/bls/hash_to_field.dart index 1824225a..e47f2688 100644 --- a/lib/src/bls/hash_to_field.dart +++ b/lib/src/bls/hash_to_field.dart @@ -20,7 +20,8 @@ List I2OSP(BigInt val, int length) { } final result = bytes; final toBytesVal = bigIntToBytes(val, length, Endian.big); - assert(listsEqual(result, toBytesVal), 'Expected $toBytesVal, but found $result'); + assert(listsEqual(result, toBytesVal), + 'Expected $toBytesVal, but found $result'); return result; } @@ -38,7 +39,8 @@ Bytes bytesXor(List a, List b) { return Bytes(zip([a, b]).map((element) => element[0] ^ element[1]).toList()); } -Bytes expandMessageXmd(List msg, List DST, int lenInBytes, Hash hash) { +Bytes expandMessageXmd( + List msg, List DST, int lenInBytes, Hash hash) { final bInBytes = hash.convert([]).bytes.length; final rInBytes = hash.blockSize; final ell = (lenInBytes + bInBytes - 1) ~/ bInBytes; @@ -48,12 +50,18 @@ Bytes expandMessageXmd(List msg, List DST, int lenInBytes, Hash hash) final DST_prime = DST + I2OSP(BigInt.from(DST.length), 1); final Z_pad = I2OSP(BigInt.zero, rInBytes); final l_i_b_str = I2OSP(BigInt.from(lenInBytes), 2); - final b_0 = hash.convert(Z_pad + msg + l_i_b_str + I2OSP(BigInt.zero, 1) + DST_prime).bytes; + final b_0 = hash + .convert(Z_pad + msg + l_i_b_str + I2OSP(BigInt.zero, 1) + DST_prime) + .bytes; final bVals = >[]; bVals.add(hash.convert(b_0 + I2OSP(BigInt.one, 1) + DST_prime).bytes); for (var i = 1; i < ell; i++) { bVals.add( - hash.convert(bytesXor(b_0, bVals[i - 1]) + I2OSP(BigInt.from(i + 1), 1) + DST_prime).bytes, + hash + .convert(bytesXor(b_0, bVals[i - 1]) + + I2OSP(BigInt.from(i + 1), 1) + + DST_prime) + .bytes, ); } final pseudoRandomBytes = []; @@ -63,7 +71,8 @@ Bytes expandMessageXmd(List msg, List DST, int lenInBytes, Hash hash) return Bytes(pseudoRandomBytes.sublist(0, lenInBytes)); } -Bytes expandMessageXof(List msg, List DST, int lenInBytes, Hash hash) { +Bytes expandMessageXof( + List msg, List DST, int lenInBytes, Hash hash) { final DST_prime = DST + I2OSP(BigInt.from(DST.length), 1); final msg_prime = msg + I2OSP(BigInt.from(lenInBytes), 2) + DST_prime; return Bytes(hash.convert(msg_prime).bytes.sublist(0, lenInBytes)); diff --git a/lib/src/bls/hd_keys.dart b/lib/src/bls/hd_keys.dart index 8cba73be..48457a78 100644 --- a/lib/src/bls/hd_keys.dart +++ b/lib/src/bls/hd_keys.dart @@ -7,7 +7,8 @@ import 'package:chia_crypto_utils/src/bls/util.dart'; PrivateKey keyGen(List seed) { const L = 48; - final okm = extractExpand(L, seed + [0], utf8.encode('BLS-SIG-KEYGEN-SALT-'), [0, L]); + final okm = + extractExpand(L, seed + [0], utf8.encode('BLS-SIG-KEYGEN-SALT-'), [0, L]); return PrivateKey(bytesToBigInt(okm, Endian.big) % defaultEc.n); } @@ -36,7 +37,8 @@ PrivateKey deriveChildSk(PrivateKey parentSk, int index) { } PrivateKey deriveChildSkUnhardened(PrivateKey parentSk, int index) { - final h = hash256(parentSk.getG1().toBytes() + intToBytes(index, 4, Endian.big)); + final h = + hash256(parentSk.getG1().toBytes() + intToBytes(index, 4, Endian.big)); return PrivateKey.aggregate([PrivateKey.fromBytes(h), parentSk]); } diff --git a/lib/src/bls/op_swu_g2.dart b/lib/src/bls/op_swu_g2.dart index 83eb1679..b49f6595 100644 --- a/lib/src/bls/op_swu_g2.dart +++ b/lib/src/bls/op_swu_g2.dart @@ -215,18 +215,21 @@ final etas = [ ]; JacobianPoint osswu2Help(Fq2 t) { - final numDenCommon = xi_2.pow(BigInt.two) * t.pow(BigInt.from(4)) + xi_2 * t.pow(BigInt.from(2)); + final numDenCommon = xi_2.pow(BigInt.two) * t.pow(BigInt.from(4)) + + xi_2 * t.pow(BigInt.from(2)); final x0_num = Ell2p_b * (numDenCommon + Fq(q, BigInt.one)); var x0_den = -Ell2p_a * numDenCommon; // ignore: unrelated_type_equality_checks x0_den = x0_den == BigInt.zero ? Ell2p_a * xi_2 : x0_den; final gx0_den = x0_den.pow(BigInt.from(3)); - final gx0_num = - Ell2p_b * gx0_den + Ell2p_a * x0_num * x0_den.pow(BigInt.two) + x0_num.pow(BigInt.from(3)); + final gx0_num = Ell2p_b * gx0_den + + Ell2p_a * x0_num * x0_den.pow(BigInt.two) + + x0_num.pow(BigInt.from(3)); var tmp1 = gx0_den.pow(BigInt.from(7)); final tmp2 = gx0_num * tmp1; tmp1 *= tmp2 * gx0_den; - var sqrtCandidate = tmp2 * tmp1.pow((q.pow(2) - BigInt.from(9)) ~/ BigInt.from(16)); + var sqrtCandidate = + tmp2 * tmp1.pow((q.pow(2) - BigInt.from(9)) ~/ BigInt.from(16)); for (final root in rootsOfUnity) { var y0 = sqrtCandidate * root as Fq2; if (y0.pow(BigInt.two) * gx0_den == gx0_num) { @@ -281,7 +284,8 @@ JacobianPoint optSwu2Map(Fq2 t, Fq2? t2) { } JacobianPoint g2Map(List alpha, List DST) { - final elements = - Hp2(alpha, 2, DST).map((hh) => Fq2(q, hh.map((value) => Fq(q, value)).toList())).toList(); + final elements = Hp2(alpha, 2, DST) + .map((hh) => Fq2(q, hh.map((value) => Fq(q, value)).toList())) + .toList(); return optSwu2Map(elements[0], elements[1]); } diff --git a/lib/src/bls/pairing.dart b/lib/src/bls/pairing.dart index c8070e1c..aa69ad09 100644 --- a/lib/src/bls/pairing.dart +++ b/lib/src/bls/pairing.dart @@ -22,8 +22,9 @@ List intToBits(BigInt i) { Field doubleLineEval(AffinePoint R, AffinePoint P, {EC? ec}) { ec ??= defaultEc; final R12 = R.untwist(); - final slope = - Fq(ec.q, BigInt.from(3)) * (R12.x.pow(BigInt.two) + ec.a) / (R12.y * Fq(ec.q, BigInt.two)); + final slope = Fq(ec.q, BigInt.from(3)) * + (R12.x.pow(BigInt.two) + ec.a) / + (R12.y * Fq(ec.q, BigInt.two)); final v = R12.y - R12.x * slope; return P.y - P.x * slope - v; } @@ -83,7 +84,8 @@ Fq12 atePairingMulti(List Ps, List Qs, {EC? ec}) { final T = (t - BigInt.one).abs(); var prod = Fq12.one(ec.q); for (var i = 0; i < Qs.length; i++) { - prod = prod * millerLoop(T, Ps[i].toAffine(), Qs[i].toAffine(), ec: ec) as Fq12; + prod = prod * millerLoop(T, Ps[i].toAffine(), Qs[i].toAffine(), ec: ec) + as Fq12; } return finalExponentiation(prod, ec: ec); } diff --git a/lib/src/bls/private_key.dart b/lib/src/bls/private_key.dart index 39c4c83f..f61c84d9 100644 --- a/lib/src/bls/private_key.dart +++ b/lib/src/bls/private_key.dart @@ -40,7 +40,8 @@ class PrivateKey with ToBytesMixin { } } - factory PrivateKey.fromHex(String hex) => PrivateKey.fromBytes(const HexDecoder().convert(hex)); + factory PrivateKey.fromHex(String hex) => + PrivateKey.fromBytes(const HexDecoder().convert(hex)); factory PrivateKey.fromSeed(List seed) { const L = 48; @@ -54,7 +55,8 @@ class PrivateKey with ToBytesMixin { } factory PrivateKey.generate() { - final bytes = List.generate(32, (index) => Random.secure().nextInt(256)); + final bytes = + List.generate(32, (index) => Random.secure().nextInt(256)); return PrivateKey.fromBytes(bytes); } @@ -87,7 +89,8 @@ class PrivateKey with ToBytesMixin { String toString() => 'PrivateKey(0x${toHex()})'; @override - bool operator ==(dynamic other) => other is PrivateKey && value == other.value; + bool operator ==(dynamic other) => + other is PrivateKey && value == other.value; @override int get hashCode => runtimeType.hashCode ^ value.hashCode; diff --git a/lib/src/bls/schemes.dart b/lib/src/bls/schemes.dart index 714aa624..8b39cb51 100644 --- a/lib/src/bls/schemes.dart +++ b/lib/src/bls/schemes.dart @@ -7,22 +7,26 @@ import 'package:chia_crypto_utils/src/bls/pairing.dart'; import 'package:deep_pick/deep_pick.dart'; import 'package:quiver/collection.dart'; -final basicSchemeDst = utf8.encode('BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_'); +final basicSchemeDst = + utf8.encode('BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_'); final augSchemeDst = utf8.encode('BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_AUG_'); final popSchemeDst = utf8.encode('BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_'); -final popSchemePopDst = utf8.encode('BLS_POP_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_'); +final popSchemePopDst = + utf8.encode('BLS_POP_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_'); JacobianPoint coreSignMpl(PrivateKey sk, List message, List dst) { return g2Map(message, dst) * sk.value; } -bool coreVerifyMpl(JacobianPoint pk, List message, JacobianPoint signature, List dst) { +bool coreVerifyMpl(JacobianPoint pk, List message, JacobianPoint signature, + List dst) { if (!signature.isValid || !pk.isValid) { return false; } final q = g2Map(message, dst); final one = Fq12.one(defaultEc.q); - final pairingResult = atePairingMulti([pk, -JacobianPoint.generateG1()], [q, signature]); + final pairingResult = + atePairingMulti([pk, -JacobianPoint.generateG1()], [q, signature]); return pairingResult == one; } @@ -72,7 +76,8 @@ class BasicSchemeMPL { return coreSignMpl(sk, message, basicSchemeDst); } - static bool verify(JacobianPoint pk, List message, JacobianPoint signature) { + static bool verify( + JacobianPoint pk, List message, JacobianPoint signature) { return coreVerifyMpl(pk, message, signature, basicSchemeDst); } @@ -138,7 +143,8 @@ class AugSchemeMPL { ); } - static bool verify(JacobianPoint pk, List message, JacobianPoint signature) { + static bool verify( + JacobianPoint pk, List message, JacobianPoint signature) { return coreVerifyMpl(pk, pk.toBytes() + message, signature, augSchemeDst); } @@ -150,15 +156,16 @@ class AugSchemeMPL { return spawnAndWaitForIsolate( taskArgument: VerifyArguments(pk, message, signature), isolateTask: _verifyTask, - handleTaskCompletion: (taskResultJson) => pick(taskResultJson, 'valid').asBoolOrThrow(), + handleTaskCompletion: (taskResultJson) => + pick(taskResultJson, 'valid').asBoolOrThrow(), ); } static Map _verifyTask( VerifyArguments args, ) { - final valid = - coreVerifyMpl(args.pk, args.pk.toBytes() + args.message, args.signature, augSchemeDst); + final valid = coreVerifyMpl(args.pk, args.pk.toBytes() + args.message, + args.signature, augSchemeDst); return { 'valid': valid, }; @@ -205,7 +212,8 @@ class PopSchemeMPL { return coreSignMpl(sk, message, popSchemeDst); } - static bool verify(JacobianPoint pk, List message, JacobianPoint signature) { + static bool verify( + JacobianPoint pk, List message, JacobianPoint signature) { return coreVerifyMpl(pk, message, signature, popSchemeDst); } @@ -242,7 +250,8 @@ class PopSchemeMPL { assert(pk.isValid); final q = g2Map(pk.toBytes(), popSchemePopDst); final one = Fq12.one(defaultEc.q); - final pairingResult = atePairingMulti([pk, -JacobianPoint.generateG1()], [q, proof]); + final pairingResult = + atePairingMulti([pk, -JacobianPoint.generateG1()], [q, proof]); return pairingResult == one; } on AssertionError { return false; diff --git a/lib/src/cat/models/cat_coin_base.dart b/lib/src/cat/models/cat_coin_base.dart index 498d42ff..713d7895 100644 --- a/lib/src/cat/models/cat_coin_base.dart +++ b/lib/src/cat/models/cat_coin_base.dart @@ -60,7 +60,8 @@ abstract class CatCoin implements CoinPrototype { factory CatCoin.fromJson(Map json) { final coin = pick(json, 'coin').letJsonOrThrow(CoinPrototype.fromJson); - final parentSpend = pick(json, 'parent_spend').letJsonOrThrow(CoinSpend.fromJson); + final parentSpend = + pick(json, 'parent_spend').letJsonOrThrow(CoinSpend.fromJson); return CatCoin.fromParentSpend( parentCoinSpend: parentSpend, @@ -72,7 +73,8 @@ abstract class CatCoin implements CoinPrototype { required CoinSpend parentCoinSpend, required CoinPrototype coin, }) async { - final uncurriedCatProgram = await parentCoinSpend.puzzleReveal.uncurryAsync(); + final uncurriedCatProgram = + await parentCoinSpend.puzzleReveal.uncurryAsync(); return _CatCoin._fromUncurriedPuzzle( parentCoinSpend: parentCoinSpend, uncurriedCatProgram: uncurriedCatProgram, @@ -180,7 +182,9 @@ extension CatFunctionality on CatCoin { /// current p2Puzzlehash of [CatCoin] calculated by looking through [CreateCoinCondition]s of parent solution /// /// client can optionally pass in their standard puzzlehashes to make parsing more efficient in case of airdrop - Future getP2Puzzlehash({Set puzzlehashesToFilterBy = const {}}) async { + Future getP2Puzzlehash({ + Set puzzlehashesToFilterBy = const {}, + }) async { final result = await compute( _calculateCatP2PuzzleHashTask, _CalculateCatP2PuzzleHashArgument(this, puzzlehashesToFilterBy), @@ -194,7 +198,9 @@ extension CatFunctionality on CatCoin { } /// see [getP2Puzzlehash] for documentation - Puzzlehash getP2PuzzlehashSync({Set puzzlehashesToFilterBy = const {}}) { + Puzzlehash getP2PuzzlehashSync({ + Set puzzlehashesToFilterBy = const {}, + }) { final result = _calculateCatP2PuzzleHashTask( _CalculateCatP2PuzzleHashArgument(this, puzzlehashesToFilterBy), ); @@ -211,9 +217,11 @@ String? _calculateCatP2PuzzleHashTask(_CalculateCatP2PuzzleHashArgument args) { final catCoin = args.coin; final puzzleHashesToCheck = args.puzzlehashesToFilterBy; final innerSolution = catCoin.parentCoinSpend.solution.toList()[0]; - final innerPuzzle = catCoin.parentCoinSpend.puzzleReveal.uncurry().arguments[2]; + final innerPuzzle = + catCoin.parentCoinSpend.puzzleReveal.uncurry().arguments[2]; - final createCoinConditions = BaseWalletService.extractConditionsFromProgramList( + final createCoinConditions = + BaseWalletService.extractConditionsFromProgramList( innerPuzzle.run(innerSolution).program.toList(), CreateCoinCondition.isThisCondition, CreateCoinCondition.fromProgram, @@ -232,7 +240,8 @@ String? _calculateCatP2PuzzleHashTask(_CalculateCatP2PuzzleHashArgument args) { for (final createCoinCondition in matchingAmountConditions) { final potentialP2PuzzleHash = createCoinCondition.destinationPuzzlehash; // optionally filter by client provided puzzle hashes - if (shouldCheckPuzzleHashes && !puzzleHashesToCheck.contains(potentialP2PuzzleHash)) { + if (shouldCheckPuzzleHashes && + !puzzleHashesToCheck.contains(potentialP2PuzzleHash)) { continue; } final outerPuzzleHash = WalletKeychain.makeOuterPuzzleHashForCatProgram( diff --git a/lib/src/cat/models/cat_coin_record_base.dart b/lib/src/cat/models/cat_coin_record_base.dart index a570142a..571e8457 100644 --- a/lib/src/cat/models/cat_coin_record_base.dart +++ b/lib/src/cat/models/cat_coin_record_base.dart @@ -13,7 +13,8 @@ class CatFullCoin with CoinPrototypeDecoratorMixin implements CatCoin, Coin { required CoinSpend parentCoinSpend, required Coin coin, }) { - final catCoinBase = CatCoin.fromParentSpend(parentCoinSpend: parentCoinSpend, coin: coin); + final catCoinBase = + CatCoin.fromParentSpend(parentCoinSpend: parentCoinSpend, coin: coin); return CatFullCoin( parentCoinSpend: parentCoinSpend, catProgram: catCoinBase.catProgram, @@ -27,8 +28,10 @@ class CatFullCoin with CoinPrototypeDecoratorMixin implements CatCoin, Coin { required CoinSpend parentCoinSpend, required Coin coin, }) async { - final catCoinBase = - await CatCoin.fromParentSpendAsync(parentCoinSpend: parentCoinSpend, coin: coin); + final catCoinBase = await CatCoin.fromParentSpendAsync( + parentCoinSpend: parentCoinSpend, + coin: coin, + ); return CatFullCoin( parentCoinSpend: parentCoinSpend, catProgram: catCoinBase.catProgram, diff --git a/lib/src/cat/models/cat_payment.dart b/lib/src/cat/models/cat_payment.dart index 5dd0aaaf..eb89f04f 100644 --- a/lib/src/cat/models/cat_payment.dart +++ b/lib/src/cat/models/cat_payment.dart @@ -6,10 +6,16 @@ class CatPayment extends Payment { memos: [puzzlehash, ...memos], ); - CatPayment.withStringMemos(super.amount, super.puzzlehash, {List memos = const []}) - : super(memos: [puzzlehash, ...memos.map(Bytes.encodeFromString)]); - CatPayment.withIntMemos(super.amount, super.puzzlehash, {List memos = const []}) - : super( + CatPayment.withStringMemos( + super.amount, + super.puzzlehash, { + List memos = const [], + }) : super(memos: [puzzlehash, ...memos.map(Bytes.encodeFromString)]); + CatPayment.withIntMemos( + super.amount, + super.puzzlehash, { + List memos = const [], + }) : super( memos: [ puzzlehash, ...memos.map( diff --git a/lib/src/cat/models/cat_solution.dart b/lib/src/cat/models/cat_solution.dart index 12fb03b7..57ffc78d 100644 --- a/lib/src/cat/models/cat_solution.dart +++ b/lib/src/cat/models/cat_solution.dart @@ -40,7 +40,8 @@ class CatSolution with ToProgramMixin { try { return CatSolution.fromProgram(program); } catch (e) { - LoggingContext().error('Error parsing cat solution from program: $program'); + LoggingContext() + .error('Error parsing cat solution from program: $program'); return null; } } @@ -69,7 +70,8 @@ class CatSolution with ToProgramMixin { CoinPrototype getChild(Puzzlehash assetId) { return CoinPrototype( parentCoinInfo: nextCoinProof.parentCoinInfo, - puzzlehash: WalletKeychain.makeOuterPuzzleHash(nextCoinProof.puzzlehash, assetId), + puzzlehash: + WalletKeychain.makeOuterPuzzleHash(nextCoinProof.puzzlehash, assetId), amount: nextCoinProof.amount, ); } diff --git a/lib/src/cat/models/conditions/run_tail_condition.dart b/lib/src/cat/models/conditions/run_tail_condition.dart index ecf5147e..d0a0cd79 100644 --- a/lib/src/cat/models/conditions/run_tail_condition.dart +++ b/lib/src/cat/models/conditions/run_tail_condition.dart @@ -29,7 +29,8 @@ class RunTailCondition implements Condition { if (conditionParts.length != 5) { return false; } - if (conditionParts[0].toInt() != conditionCode || conditionParts[2].toInt() != magicCatNumber) { + if (conditionParts[0].toInt() != conditionCode || + conditionParts[2].toInt() != magicCatNumber) { return false; } return true; diff --git a/lib/src/cat/models/spendable_cat.dart b/lib/src/cat/models/spendable_cat.dart index 4611a386..d82841d6 100644 --- a/lib/src/cat/models/spendable_cat.dart +++ b/lib/src/cat/models/spendable_cat.dart @@ -32,14 +32,17 @@ class SpendableCat { // calculate deltas for (final spendableCat in spendableCats) { - final conditionPrograms = - spendableCat.innerPuzzle.run(spendableCat.innerSolution).program.toList(); + final conditionPrograms = spendableCat.innerPuzzle + .run(spendableCat.innerSolution) + .program + .toList(); var total = spendableCat.extraDelta * -1; for (final createCoinConditionProgram in conditionPrograms.where(CreateCoinCondition.isThisCondition)) { if (!createCoinConditionProgram.toSource().contains('-113')) { - final createCoinCondition = CreateCoinCondition.fromProgram(createCoinConditionProgram); + final createCoinCondition = + CreateCoinCondition.fromProgram(createCoinConditionProgram); total += createCoinCondition.amount; } } diff --git a/lib/src/cat/service/tails/everything_with_signature_tail_service.dart b/lib/src/cat/service/tails/everything_with_signature_tail_service.dart index a548fb09..19fa9275 100644 --- a/lib/src/cat/service/tails/everything_with_signature_tail_service.dart +++ b/lib/src/cat/service/tails/everything_with_signature_tail_service.dart @@ -5,9 +5,11 @@ class EverythingWithSignatureTailService { EverythingWithSignatureTailService([this._catWalletService]); final CatWalletService? _catWalletService; - CatWalletService get catWalletService => _catWalletService ?? Cat2WalletService(); + CatWalletService get catWalletService => + _catWalletService ?? Cat2WalletService(); - StandardWalletService get standardWalletService => catWalletService.standardWalletService; + StandardWalletService get standardWalletService => + catWalletService.standardWalletService; static Program constructTail(PrivateKey privateKey) { final curriedTail = everythingWithSignatureProgram.curry( @@ -109,7 +111,8 @@ class EverythingWithSignatureTailService { inputAmountToMelt: desiredAmountToMelt, catCoinToMelt: catCoinToMelt, puzzlehashToClaimXchTo: puzzlehashToClaimXchTo, - standardCoinsForXchClaimingSpendBundle: standardCoinsForXchClaimingSpendBundle, + standardCoinsForXchClaimingSpendBundle: + standardCoinsForXchClaimingSpendBundle, tailRunningInfo: TailRunningInfo( tail: curriedTail, signature: signature, diff --git a/lib/src/cat/service/wallet.dart b/lib/src/cat/service/wallet.dart index 8f04fa51..0f85a753 100644 --- a/lib/src/cat/service/wallet.dart +++ b/lib/src/cat/service/wallet.dart @@ -10,7 +10,11 @@ import 'package:chia_crypto_utils/src/standard/exceptions/spend_bundle_validatio import 'package:chia_crypto_utils/src/standard/exceptions/spend_bundle_validation/multiple_origin_coin_exception.dart'; abstract class CatWalletService extends BaseWalletService { - CatWalletService(this.catProgram, this.spendType, this.innerPuzzleAnnouncementMorphBytes); + CatWalletService( + this.catProgram, + this.spendType, + this.innerPuzzleAnnouncementMorphBytes, + ); factory CatWalletService.fromCatProgram(Program catProgram) { if (catProgram == cat2Program) { @@ -66,15 +70,17 @@ abstract class CatWalletService extends BaseWalletService { return; } try { - final catInnerPuzzlehashes = catCoinsInput.map((e) => e.getP2PuzzlehashSync()); + final catInnerPuzzlehashes = + catCoinsInput.map((e) => e.getP2PuzzlehashSync()); keychain.addOuterPuzzleHashesForInnerPuzzleHashesGeneric( catInnerPuzzlehashes.toList(), catCoinsInput.first.assetId, catProgram, ); } catch (e) { - LoggingContext() - .error('Error adding outer puzzlehashes to keychain for cats in fallback: $e'); + LoggingContext().error( + 'Error adding outer puzzlehashes to keychain for cats in fallback: $e', + ); } } @@ -84,7 +90,8 @@ abstract class CatWalletService extends BaseWalletService { required WalletKeychain keychain, Puzzlehash? changePuzzlehash, List standardCoinsForFee = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], List additionalConditions = const [], int fee = 0, bool shouldAddCatOuterPuzzlehashesToKeychain = true, @@ -101,8 +108,10 @@ abstract class CatWalletService extends BaseWalletService { ); } - final totalCatPaymentAmount = - payments.fold(0, (int previousValue, payment) => previousValue + payment.amount); + final totalCatPaymentAmount = payments.fold( + 0, + (int previousValue, payment) => previousValue + payment.amount, + ); final catCoins = List.from(catCoinsInput); @@ -157,7 +166,11 @@ abstract class CatWalletService extends BaseWalletService { final createdCoins = []; conditions - ..add(CreateCoinAnnouncementCondition(primaryAssertCoinAnnouncement.message)) + ..add( + CreateCoinAnnouncementCondition( + primaryAssertCoinAnnouncement.message, + ), + ) ..addAll(puzzleAnnouncementsToAssert) ..addAll(additionalConditions); @@ -186,10 +199,12 @@ abstract class CatWalletService extends BaseWalletService { ); } - innerSolution = BaseWalletService.makeSolutionFromConditions(conditions); - } else { innerSolution = - BaseWalletService.makeSolutionFromConditions([primaryAssertCoinAnnouncement!]); + BaseWalletService.makeSolutionFromConditions(conditions); + } else { + innerSolution = BaseWalletService.makeSolutionFromConditions( + [primaryAssertCoinAnnouncement!], + ); } final innerPuzzle = getPuzzleFromPk(coinPublicKey); @@ -203,9 +218,11 @@ abstract class CatWalletService extends BaseWalletService { ); } - final immutableSpendableCats = List.unmodifiable(spendableCats); + final immutableSpendableCats = + List.unmodifiable(spendableCats); - final catSpendBundle = makeUnsignedSpendBundleForSpendableCats(immutableSpendableCats); + final catSpendBundle = + makeUnsignedSpendBundleForSpendableCats(immutableSpendableCats); if (feeStandardSpendBundle != null) { final combinedSpendBundle = catSpendBundle + feeStandardSpendBundle; @@ -227,12 +244,15 @@ abstract class CatWalletService extends BaseWalletService { int fee = 0, }) { final publicKey = privateKey.getG1(); - final curriedTail = delegatedTailProgram.curry([Program.fromAtom(publicKey.toBytes())]); + final curriedTail = + delegatedTailProgram.curry([Program.fromAtom(publicKey.toBytes())]); - final curriedGenesisByCoinId = genesisByCoinIdProgram.curry([Program.fromAtom(genesisCoinId)]); + final curriedGenesisByCoinId = + genesisByCoinIdProgram.curry([Program.fromAtom(genesisCoinId)]); final tailSolution = Program.list([curriedGenesisByCoinId, Program.nil]); - final signature = AugSchemeMPL.sign(privateKey, curriedGenesisByCoinId.hash()); + final signature = + AugSchemeMPL.sign(privateKey, curriedGenesisByCoinId.hash()); final spendBundle = makeIssuanceSpendbundle( tail: curriedTail, @@ -268,11 +288,13 @@ abstract class CatWalletService extends BaseWalletService { int fee = 0, }) { final publicKey = privateKey.getG1(); - final curriedTail = delegatedTailProgram.curry([Program.fromAtom(publicKey.toBytes())]); + final curriedTail = + delegatedTailProgram.curry([Program.fromAtom(publicKey.toBytes())]); final curriedMeltableGenesisByCoinIdPuzzle = meltableGenesisByCoinIdProgram.curry([Program.fromAtom(genesisCoinId)]); - final tailSolution = Program.list([curriedMeltableGenesisByCoinIdPuzzle, Program.nil]); + final tailSolution = + Program.list([curriedMeltableGenesisByCoinIdPuzzle, Program.nil]); final issuanceSignature = AugSchemeMPL.sign( privateKey, @@ -311,7 +333,10 @@ abstract class CatWalletService extends BaseWalletService { required Puzzlehash changePuzzlehash, int? inputAmountToMelt, }) { - _addOuterPuzzlehashesToKeychainForCats(catCoinsInput: [catCoinToMelt], keychain: keychain); + _addOuterPuzzlehashesToKeychainForCats( + catCoinsInput: [catCoinToMelt], + keychain: keychain, + ); final amountToMelt = inputAmountToMelt ?? catCoinToMelt.amount; final catChange = catCoinToMelt.amount - amountToMelt; @@ -330,7 +355,8 @@ abstract class CatWalletService extends BaseWalletService { conditions.add(CreateCoinCondition(changePuzzlehash, catChange)); } - final innerSolution = BaseWalletService.makeSolutionFromConditions(conditions); + final innerSolution = + BaseWalletService.makeSolutionFromConditions(conditions); final spendableCat = SpendableCat( coin: catCoinToMelt, @@ -340,9 +366,12 @@ abstract class CatWalletService extends BaseWalletService { ); final meltSpendBundle = - makeUnsignedSpendBundleForSpendableCats([spendableCat]).sign(keychain).signedBundle; + makeUnsignedSpendBundleForSpendableCats([spendableCat]) + .sign(keychain) + .signedBundle; - final totalStandardCoinValue = standardCoinsForXchClaimingSpendBundle.totalValue; + final totalStandardCoinValue = + standardCoinsForXchClaimingSpendBundle.totalValue; final xchClaimingSpendbundle = standardWalletService.createSpendBundle( payments: [ @@ -356,8 +385,8 @@ abstract class CatWalletService extends BaseWalletService { fee: fee, ); - final finalSpendbundle = - (meltSpendBundle + xchClaimingSpendbundle).withSignature(tailRunningInfo.signature); + final finalSpendbundle = (meltSpendBundle + xchClaimingSpendbundle) + .withSignature(tailRunningInfo.signature); return finalSpendbundle; } @@ -378,7 +407,13 @@ abstract class CatWalletService extends BaseWalletService { Program.fromInt(1), Program.list([ Program.list( - [Program.fromInt(51), Program.fromInt(0), Program.fromInt(-113), tail, solution], + [ + Program.fromInt(51), + Program.fromInt(0), + Program.fromInt(-113), + tail, + solution + ], ), Program.list([ Program.fromInt(51), @@ -420,18 +455,24 @@ abstract class CatWalletService extends BaseWalletService { catProgram: catProgram, ); - final spendableEve = - SpendableCat(coin: eveCatCoin, innerPuzzle: payToPuzzle, innerSolution: Program.nil); + final spendableEve = SpendableCat( + coin: eveCatCoin, + innerPuzzle: payToPuzzle, + innerSolution: Program.nil, + ); - final eveUnsignedSpendbundle = makeUnsignedSpendBundleForSpendableCats([spendableEve]); + final eveUnsignedSpendbundle = + makeUnsignedSpendBundleForSpendableCats([spendableEve]); - final finalSpendBundle = - (standardSpendBundle + eveUnsignedSpendbundle).withSignature(makeSignature(eveCoin)); + final finalSpendBundle = (standardSpendBundle + eveUnsignedSpendbundle) + .withSignature(makeSignature(eveCoin)); return finalSpendBundle; } - SpendBundle makeUnsignedSpendBundleForSpendableCats(List spendableCats) { + SpendBundle makeUnsignedSpendBundleForSpendableCats( + List spendableCats, + ) { SpendableCat.calculateAndAttachSubtotals(spendableCats); final spends = []; @@ -533,8 +574,11 @@ abstract class CatWalletService extends BaseWalletService { required Program innerPuzzle, required Puzzlehash assetId, }) { - return catProgram - .curry([Program.fromAtom(catProgram.hash()), Program.fromAtom(assetId), innerPuzzle]); + return catProgram.curry([ + Program.fromAtom(catProgram.hash()), + Program.fromAtom(assetId), + innerPuzzle + ]); } void validateSpendBundle(SpendBundle spendBundle) { @@ -545,9 +589,11 @@ abstract class CatWalletService extends BaseWalletService { final coinsToCreate = []; final coinsBeingSpent = []; Bytes? originId; - final catSpends = spendBundle.coinSpends.where((spend) => spend.type == spendType); + final catSpends = + spendBundle.coinSpends.where((spend) => spend.type == spendType); for (final catSpend in catSpends) { - final outputConditions = catSpend.puzzleReveal.run(catSpend.solution).program.toList(); + final outputConditions = + catSpend.puzzleReveal.run(catSpend.solution).program.toList(); // find create_coin conditions final coinCreationConditions = outputConditions @@ -576,8 +622,9 @@ abstract class CatWalletService extends BaseWalletService { // origin id doesn't contain its own assert coin announcement if (catSpend.coin.id != originId) { - final assertCoinAnnouncementPrograms = - outputConditions.where(AssertCoinAnnouncementCondition.isThisCondition).toList(); + final assertCoinAnnouncementPrograms = outputConditions + .where(AssertCoinAnnouncementCondition.isThisCondition) + .toList(); // set actualAssertCoinAnnouncementIds only if it is null actualAssertCoinAnnouncementIds ??= assertCoinAnnouncementPrograms @@ -612,7 +659,8 @@ abstract class CatWalletService extends BaseWalletService { morphBytes: innerPuzzleAnnouncementMorphBytes, ); - if (!actualAssertCoinAnnouncementIds!.contains(constructedAnnouncement.announcementId)) { + if (!actualAssertCoinAnnouncementIds! + .contains(constructedAnnouncement.announcementId)) { throw IncorrectAnnouncementIdException(); } } diff --git a/lib/src/clvm/bytes.dart b/lib/src/clvm/bytes.dart index 0bcc52f3..b8898c04 100644 --- a/lib/src/clvm/bytes.dart +++ b/lib/src/clvm/bytes.dart @@ -80,7 +80,9 @@ extension SerializePuzzlehashes on Iterable { } } -class Bytes extends Comparable with ToBytesMixin, ToProgramMixin implements List { +class Bytes extends Comparable + with ToBytesMixin, ToProgramMixin + implements List { Bytes(List bytesList) : _byteList = Uint8List.fromList(bytesList); factory Bytes.zeros(int size) { @@ -98,7 +100,8 @@ class Bytes extends Comparable with ToBytesMixin, ToProgramMixin implemen return iterator.extractBytesAndAdvance(length); } - Bytes.encodeFromString(String text) : _byteList = Uint8List.fromList(utf8.encode(text)); + Bytes.encodeFromString(String text) + : _byteList = Uint8List.fromList(utf8.encode(text)); factory Bytes.fromHex(String hex) { if (hex.startsWith(bytesPrefix)) { diff --git a/lib/src/clvm/bytes_utils.dart b/lib/src/clvm/bytes_utils.dart index 765974a9..7bb7f82e 100644 --- a/lib/src/clvm/bytes_utils.dart +++ b/lib/src/clvm/bytes_utils.dart @@ -5,16 +5,20 @@ import 'package:chia_crypto_utils/chia_crypto_utils.dart'; import 'package:chia_crypto_utils/src/clvm/exceptions/unexpected_end_of_bytes_exception.dart'; String flip(String binary) { - return binary.replaceAllMapped(RegExp('[01]'), (match) => match.group(0) == '1' ? '0' : '1'); + return binary.replaceAllMapped( + RegExp('[01]'), (match) => match.group(0) == '1' ? '0' : '1'); } Bytes intToBytes(int value, int size, Endian endian, {bool signed = false}) { if (value < 0 && !signed) { throw ArgumentError('Cannot convert negative int to unsigned.'); } - var binary = (value < 0 ? -value : value).toRadixString(2).padLeft(size * 8, '0'); + var binary = + (value < 0 ? -value : value).toRadixString(2).padLeft(size * 8, '0'); if (value < 0) { - binary = (int.parse(flip(binary), radix: 2) + 1).toRadixString(2).padLeft(size * 8, '0'); + binary = (int.parse(flip(binary), radix: 2) + 1) + .toRadixString(2) + .padLeft(size * 8, '0'); } var bytes = RegExp('[01]{8}') .allMatches(binary) @@ -70,13 +74,16 @@ int bytesToInt(List bytes, Endian endian, {bool signed = false}) { if (bytes.isEmpty) { return 0; } - final sign = - bytes[endian == Endian.little ? bytes.length - 1 : 0].toRadixString(2).padLeft(8, '0')[0]; + final sign = bytes[endian == Endian.little ? bytes.length - 1 : 0] + .toRadixString(2) + .padLeft(8, '0')[0]; final byteList = (endian == Endian.little ? bytes.reversed : bytes).toList(); - var binary = byteList.map((byte) => byte.toRadixString(2).padLeft(8, '0')).join(); + var binary = + byteList.map((byte) => byte.toRadixString(2).padLeft(8, '0')).join(); if (sign == '1' && signed) { - binary = - (int.parse(flip(binary), radix: 2) + 1).toRadixString(2).padLeft(bytes.length * 8, '0'); + binary = (int.parse(flip(binary), radix: 2) + 1) + .toRadixString(2) + .padLeft(bytes.length * 8, '0'); } final result = int.parse(binary, radix: 2); return sign == '1' && signed ? -result : result; @@ -86,14 +93,18 @@ int decodeInt(List bytes) { return bytesToInt(bytes, Endian.big, signed: true); } -Bytes bigIntToBytes(BigInt value, int size, Endian endian, {bool signed = false}) { +Bytes bigIntToBytes(BigInt value, int size, Endian endian, + {bool signed = false}) { if (value < BigInt.zero && !signed) { throw ArgumentError('Cannot convert negative bigint to unsigned.'); } - var binary = (value < BigInt.zero ? -value : value).toRadixString(2).padLeft(size * 8, '0'); + var binary = (value < BigInt.zero ? -value : value) + .toRadixString(2) + .padLeft(size * 8, '0'); if (value < BigInt.zero) { - binary = - (BigInt.parse(flip(binary), radix: 2) + BigInt.one).toRadixString(2).padLeft(size * 8, '0'); + binary = (BigInt.parse(flip(binary), radix: 2) + BigInt.one) + .toRadixString(2) + .padLeft(size * 8, '0'); } var bytes = RegExp('[01]{8}') .allMatches(binary) diff --git a/lib/src/clvm/operators.dart b/lib/src/clvm/operators.dart index b01f4499..a3d86449 100644 --- a/lib/src/clvm/operators.dart +++ b/lib/src/clvm/operators.dart @@ -39,7 +39,8 @@ Map operators = { return Output( Program.fromBool(bytesEqual(list[0].atom, list[1].atom)), Cost.eqBaseCost + - (BigInt.from(list[0].atom.length) + BigInt.from(list[1].atom.length)) * + (BigInt.from(list[0].atom.length) + + BigInt.from(list[1].atom.length)) * Cost.eqCostPerByte, ); }, @@ -54,7 +55,8 @@ Map operators = { cost += Cost.sha256CostPerArg; } cost += BigInt.from(argLength) * Cost.sha256CostPerByte; - return mallocCost(Output(Program.fromAtom(sha256.convert(bytes).bytes), cost)); + return mallocCost( + Output(Program.fromAtom(sha256.convert(bytes).bytes), cost)); }, keywords['+']!: (args) { final list = args.toAtomList(suffix: 'in +'); @@ -97,8 +99,10 @@ Map operators = { var size = list[0].atom.length; for (final arg in list.sublist(1)) { cost += Cost.mulCostPerOp + - (BigInt.from(arg.atom.length) + BigInt.from(size)) * Cost.mulLinearCostPerByte + - (BigInt.from(arg.atom.length) * BigInt.from(size)) ~/ Cost.mulSquareCostPerByteDivider; + (BigInt.from(arg.atom.length) + BigInt.from(size)) * + Cost.mulLinearCostPerByte + + (BigInt.from(arg.atom.length) * BigInt.from(size)) ~/ + Cost.mulSquareCostPerByteDivider; value *= arg.toBigInt(); size = limbsForInt(value); } @@ -112,8 +116,9 @@ Map operators = { if (denominator == BigInt.zero) { throw UnsupportedError('Dividing by zero'); } - cost += (BigInt.from(list[0].atom.length) + BigInt.from(list[1].atom.length)) * - Cost.divmodCostPerByte; + cost += + (BigInt.from(list[0].atom.length) + BigInt.from(list[1].atom.length)) * + Cost.divmodCostPerByte; final positive = numerator.sign == denominator.sign; var quotientValue = numerator ~/ denominator; var remainderValue = numerator % denominator; @@ -125,7 +130,8 @@ Map operators = { } final quotient = Program.fromBigInt(quotientValue); final remainder = Program.fromBigInt(remainderValue); - cost += (BigInt.from(quotient.atom.length) + BigInt.from(remainder.atom.length)) * + cost += (BigInt.from(quotient.atom.length) + + BigInt.from(remainder.atom.length)) * Cost.mallocCostPerByte; return Output(Program.cons(quotient, remainder), cost); }, @@ -138,7 +144,8 @@ Map operators = { throw UnsupportedError('Dividing by zero'); } cost += - (BigInt.from(list[0].atom.length) + BigInt.from(list[1].atom.length)) * Cost.divCostPerByte; + (BigInt.from(list[0].atom.length) + BigInt.from(list[1].atom.length)) * + Cost.divCostPerByte; var quotientValue = numerator ~/ denominator; final remainderValue = numerator % denominator; if (numerator.sign != denominator.sign && remainderValue != BigInt.zero) { @@ -151,24 +158,31 @@ Map operators = { final list = args.toAtomList(size: 2, suffix: 'in >'); var cost = Cost.grBaseCost; cost += - (BigInt.from(list[0].atom.length) + BigInt.from(list[1].atom.length)) * Cost.grCostPerByte; - final result = Output(Program.fromBool(list[0].toBigInt() > list[1].toBigInt()), cost); + (BigInt.from(list[0].atom.length) + BigInt.from(list[1].atom.length)) * + Cost.grCostPerByte; + final result = + Output(Program.fromBool(list[0].toBigInt() > list[1].toBigInt()), cost); return result; }, keywords['>s']!: (args) { final list = args.toAtomList(size: 2, suffix: 'in >s'); final cost = Cost.grsBaseCost + - (BigInt.from(list[0].atom.length) + BigInt.from(list[1].atom.length)) * Cost.grsCostPerByte; - return Output(Program.fromBool(list[0].atomHex().compareTo(list[1].atomHex()) == 1), cost); + (BigInt.from(list[0].atom.length) + BigInt.from(list[1].atom.length)) * + Cost.grsCostPerByte; + return Output( + Program.fromBool(list[0].atomHex().compareTo(list[1].atomHex()) == 1), + cost); }, keywords['pubkey_for_exp']!: (args) { final list = args.toAtomList(size: 1, suffix: 'in pubkey_for_exp'); final value = list[0].toBigInt() % - BigInt.parse('0x73EDA753299D7D483339D80809A1D80553BDA402FFFE5BFEFFFFFFFF00000001'); + BigInt.parse( + '0x73EDA753299D7D483339D80809A1D80553BDA402FFFE5BFEFFFFFFFF00000001'); final exponent = PrivateKey.fromBytes(bigIntToBytes(value, 32, Endian.big)); var cost = Cost.pubkeyBaseCost; cost += BigInt.from(list[0].atom.length) * Cost.pubkeyCostPerByte; - return mallocCost(Output(Program.fromAtom(exponent.getG1().toBytes()), cost)); + return mallocCost( + Output(Program.fromAtom(exponent.getG1().toBytes()), cost)); }, keywords['point_add']!: (args) { var cost = Cost.pointAddBaseCost; @@ -182,13 +196,15 @@ Map operators = { keywords['strlen']!: (args) { final list = args.toAtomList(size: 1, suffix: 'in strlen'); final size = list[0].atom.length; - final cost = Cost.strlenBaseCost + BigInt.from(size) * Cost.strlenCostPerByte; + final cost = + Cost.strlenBaseCost + BigInt.from(size) * Cost.strlenCostPerByte; return mallocCost(Output(Program.fromInt(size), cost)); }, keywords['substr']!: (args) { final list = args.toAtomList(min: 2, max: 3, suffix: 'in substr'); final str = list[0].atom; - if (list[1].atom.length > 4 || (list.length == 3 && list[2].atom.length > 4)) { + if (list[1].atom.length > 4 || + (list.length == 3 && list[2].atom.length > 4)) { throw ArgumentError('Expected 4 byte indices for substr.'); } final from = list[1].toInt(); @@ -248,12 +264,16 @@ Map operators = { Cost.lshiftCostPerByte; return mallocCost(Output(Program.fromBigInt(value), cost)); }, - keywords['logand']!: (args) => binopReduction('logand', -BigInt.one, args, (a, b) => a & b), - keywords['logior']!: (args) => binopReduction('logior', BigInt.zero, args, (a, b) => a | b), - keywords['logxor']!: (args) => binopReduction('logxor', BigInt.zero, args, (a, b) => a ^ b), + keywords['logand']!: (args) => + binopReduction('logand', -BigInt.one, args, (a, b) => a & b), + keywords['logior']!: (args) => + binopReduction('logior', BigInt.zero, args, (a, b) => a | b), + keywords['logxor']!: (args) => + binopReduction('logxor', BigInt.zero, args, (a, b) => a ^ b), keywords['lognot']!: (args) { final items = args.toAtomList(size: 1, suffix: 'in lognot'); - final cost = Cost.lognotBaseCost + BigInt.from(items[0].atom.length) * Cost.lognotCostPerByte; + final cost = Cost.lognotBaseCost + + BigInt.from(items[0].atom.length) * Cost.lognotCostPerByte; return mallocCost(Output(Program.fromBigInt(~items[0].toBigInt()), cost)); }, keywords['not']!: (args) { @@ -263,7 +283,8 @@ Map operators = { }, keywords['any']!: (args) { final items = args.toList(suffix: 'in any'); - final cost = Cost.boolBaseCost + BigInt.from(items.length) * Cost.boolCostPerArg; + final cost = + Cost.boolBaseCost + BigInt.from(items.length) * Cost.boolCostPerArg; var result = false; for (final value in items) { if (!value.isNull) { @@ -275,7 +296,8 @@ Map operators = { }, keywords['all']!: (args) { final items = args.toList(suffix: 'in all'); - final cost = Cost.boolBaseCost + BigInt.from(items.length) * Cost.boolCostPerArg; + final cost = + Cost.boolBaseCost + BigInt.from(items.length) * Cost.boolCostPerArg; var result = true; for (final value in items) { if (value.isNull) { @@ -319,7 +341,8 @@ Output binopReduction( Output mallocCost(Output output) { return Output( output.program, - output.cost + BigInt.from(output.program.atom.length) * Cost.mallocCostPerByte, + output.cost + + BigInt.from(output.program.atom.length) * Cost.mallocCostPerByte, ); } @@ -342,7 +365,8 @@ Output runOperator(Program op, Program args, RunOptions options) { throw StateError('Invalid operator.'); } final costFunction = (op.atom[op.atom.length - 1] & 0xc0) >> 6; - final costMultiplier = bytesToInt(op.atom.sublist(0, op.atom.length - 1), Endian.big) + 1; + final costMultiplier = + bytesToInt(op.atom.sublist(0, op.atom.length - 1), Endian.big) + 1; BigInt cost; if (costFunction == 0) { cost = BigInt.one; @@ -371,7 +395,8 @@ Output runOperator(Program op, Program args, RunOptions options) { throw StateError('Expected int arguments.'); } cost += Cost.mulCostPerOp + - (BigInt.from(item.atom.length) + BigInt.from(current)) * Cost.mulLinearCostPerByte + + (BigInt.from(item.atom.length) + BigInt.from(current)) * + Cost.mulLinearCostPerByte + (BigInt.from(item.atom.length) * BigInt.from(current)) ~/ Cost.mulSquareCostPerByteDivider; current += item.atom.length; diff --git a/lib/src/clvm/parser.dart b/lib/src/clvm/parser.dart index 6a1d5eaa..f5d90808 100644 --- a/lib/src/clvm/parser.dart +++ b/lib/src/clvm/parser.dart @@ -67,23 +67,27 @@ Program tokenizeCons(String source, Iterator tokens) { final consStart = token.index; final first = tokenizeExpr(source, tokens); if (!tokens.moveNext()) { - throw StateError('Unexpected end of source at ${Position(source, token.index)}.'); + throw StateError( + 'Unexpected end of source at ${Position(source, token.index)}.'); } token = tokens.current; Program rest; if (token.text == '.') { final dotStart = token.index; if (!tokens.moveNext()) { - throw StateError('Unexpected end of source at ${Position(source, token.index)}.'); + throw StateError( + 'Unexpected end of source at ${Position(source, token.index)}.'); } token = tokens.current; rest = tokenizeExpr(source, tokens); if (!tokens.moveNext()) { - throw StateError('Unexpected end of source at ${Position(source, token.index)}.'); + throw StateError( + 'Unexpected end of source at ${Position(source, token.index)}.'); } token = tokens.current; if (token.text != ')') { - throw StateError('Illegal dot expression at ${Position(source, dotStart)}.'); + throw StateError( + 'Illegal dot expression at ${Position(source, dotStart)}.'); } } else { rest = tokenizeCons(source, tokens); @@ -99,7 +103,8 @@ Program? tokenizeInt(String source, Token token) { } Program? tokenizeHex(String source, Token token) { - if (token.text.length >= 2 && token.text.substring(0, 2).toUpperCase() == '0X') { + if (token.text.length >= 2 && + token.text.substring(0, 2).toUpperCase() == '0X') { var hex = token.text.substring(2); if (hex.length % 2 == 1) { hex = '0$hex'; @@ -123,7 +128,8 @@ Program? tokenizeQuotes(String source, Token token) { return null; } if (token.text[token.text.length - 1] != quote) { - throw StateError('Unterminated string ${token.text} at ${Position(source, token.index)}.'); + throw StateError( + 'Unterminated string ${token.text} at ${Position(source, token.index)}.'); } return Program.fromString(token.text.substring(1, token.text.length - 1)) ..at(Position(source, token.index)); @@ -135,7 +141,9 @@ Program? tokenizeSymbol(String source, Token token) { text = text.substring(1); } final keyword = keywords[text]; - return (keyword != null ? Program.fromBigInt(keyword) : Program.fromString(text)) + return (keyword != null + ? Program.fromBigInt(keyword) + : Program.fromString(text)) ..at(Position(source, token.index)); } @@ -143,7 +151,8 @@ Program tokenizeExpr(String source, Iterator tokens) { final token = tokens.current; if (token.text == '(') { if (!tokens.moveNext()) { - throw StateError('Unexpected end of source at ${Position(source, token.index)}.'); + throw StateError( + 'Unexpected end of source at ${Position(source, token.index)}.'); } return tokenizeCons(source, tokens); } diff --git a/lib/src/clvm/program.dart b/lib/src/clvm/program.dart index 3621dc63..6d765f84 100644 --- a/lib/src/clvm/program.dart +++ b/lib/src/clvm/program.dart @@ -64,7 +64,8 @@ class Program with ToBytesMixin, ToProgramMixin { if (atom == null) return Program.nil; return Program.fromAtom(atom); } - Program.fromAtomHex(String hex) : _atom = Bytes(const HexDecoder().convert(hex)); + Program.fromAtomHex(String hex) + : _atom = Bytes(const HexDecoder().convert(hex)); // ignore: avoid_positional_boolean_parameters Program.fromBool(bool value) : _atom = Bytes(value ? [1] : []); Program.fromInt(int number) : _atom = encodeInt(number); @@ -146,7 +147,8 @@ class Program with ToBytesMixin, ToProgramMixin { : toBigInt() == other.toBigInt()); @override - int get hashCode => isCons ? hash2(first().hashCode, rest().hashCode) : toBigInt().hashCode; + int get hashCode => + isCons ? hash2(first().hashCode, rest().hashCode) : toBigInt().hashCode; bool get isNull => isAtom && atom.isEmpty; bool get isAtom => _atom != null; @@ -210,8 +212,10 @@ class Program with ToBytesMixin, ToProgramMixin { return Program.parse('(a (q . ${toString()}) $current)'); } - static Map _curryIsolateTask(CurryIsolateArguments arguments) { - final curriedProgram = arguments.programToCurryTo.curry(arguments.programsToCurryIn); + static Map _curryIsolateTask( + CurryIsolateArguments arguments) { + final curriedProgram = + arguments.programToCurryTo.curry(arguments.programsToCurryIn); return { 'program': curriedProgram.toHex(), }; @@ -324,7 +328,9 @@ class Program with ToBytesMixin, ToProgramMixin { return Puzzlehash(sha256.convert([1] + atom.toList()).bytes); } else { return Puzzlehash( - sha256.convert([2] + cons[0].hash().toList() + cons[1].hash().toList()).bytes, + sha256 + .convert([2] + cons[0].hash().toList() + cons[1].hash().toList()) + .bytes, ); } } @@ -552,7 +558,8 @@ class Program with ToBytesMixin, ToProgramMixin { if (showKeywords) { try { final value = cons[0].toBigInt(); - buffer.write(keywords.keys.firstWhere((key) => keywords[key] == value)); + buffer + .write(keywords.keys.firstWhere((key) => keywords[key] == value)); } catch (e) { buffer.write(cons[0].toSource(showKeywords: showKeywords)); } @@ -561,7 +568,8 @@ class Program with ToBytesMixin, ToProgramMixin { } var current = cons[1]; while (current.isCons) { - buffer.write(' ${current.cons[0].toSource(showKeywords: showKeywords)}'); + buffer + .write(' ${current.cons[0].toSource(showKeywords: showKeywords)}'); current = current.cons[1]; } if (!current.isNull) { @@ -579,7 +587,8 @@ class Program with ToBytesMixin, ToProgramMixin { class ModAndArguments { ModAndArguments(this.arguments, this.mod); - factory ModAndArguments.fromJson(Map json) => ModAndArguments( + factory ModAndArguments.fromJson(Map json) => + ModAndArguments( List.from(json['arguments'] as Iterable) .map(Program.deserializeHex) .toList(), @@ -589,8 +598,10 @@ class ModAndArguments { List arguments; Program mod; - Map toJson() => - {'mod': mod, 'arguments': arguments.map((e) => e.toHex()).toList()}; + Map toJson() => { + 'mod': mod, + 'arguments': arguments.map((e) => e.toHex()).toList() + }; } class PuzzleAndSolution { diff --git a/lib/src/command/cat/mint_cat_and_nft.dart b/lib/src/command/cat/mint_cat_and_nft.dart index cb5a8bd5..c3811160 100644 --- a/lib/src/command/cat/mint_cat_and_nft.dart +++ b/lib/src/command/cat/mint_cat_and_nft.dart @@ -41,8 +41,9 @@ Future mintEverythingWithSignatureCatAndNft({ final netAdditions = catIssuanceSpendBundle.netAdditions.toSet(); - final resultingCat = (await fullNode.getCatCoinsByHints([destinationPuzzleHash])) - .singleWhere(netAdditions.contains); + final resultingCat = + (await fullNode.getCatCoinsByHints([destinationPuzzleHash])) + .singleWhere(netAdditions.contains); print('asset id:${resultingCat.assetId}'); @@ -51,8 +52,9 @@ Future mintEverythingWithSignatureCatAndNft({ coins = await fullNode.getCoinsByPuzzleHashes(nonSwitchPuzzleHashes); - final didInfo = - await fullNode.getDidRecordsByHints([getPuzzleFromPk(didPrivateKey.getG1()).hash()]).then( + final didInfo = await fullNode.getDidRecordsByHints( + [getPuzzleFromPk(didPrivateKey.getG1()).hash()], + ).then( (value) => value.singleWhere((element) => element.did == did), ); diff --git a/lib/src/command/core/nuke_keychain.dart b/lib/src/command/core/nuke_keychain.dart index 649d48e2..2450bdce 100644 --- a/lib/src/command/core/nuke_keychain.dart +++ b/lib/src/command/core/nuke_keychain.dart @@ -7,7 +7,6 @@ Future nukeKeychain({ required int feePerCoin, required int burnBundleSize, }) async { - return transferKeychain( destinationPuzzlehash: burnPuzzlehash, keychain: keychain, @@ -31,11 +30,13 @@ Future transferKeychain({ final catCoins = await fullNode.getCatCoinsByHints(keychain.puzzlehashes); - final catCoinsGroupedByAssetId = - catCoins.where((element) => element.type == SpendType.cat).groupByAssetId(); + final catCoinsGroupedByAssetId = catCoins + .where((element) => element.type == SpendType.cat) + .groupByAssetId(); - final batchedCatMap = catCoinsGroupedByAssetId - .map((key, value) => MapEntry(key, value.splitIntoBatches(spendBundleSize))); + final batchedCatMap = catCoinsGroupedByAssetId.map( + (key, value) => MapEntry(key, value.splitIntoBatches(spendBundleSize)), + ); for (final catMapEntry in batchedCatMap.entries) { keychain.addOuterPuzzleHashesForAssetId(catMapEntry.key); @@ -45,7 +46,8 @@ Future transferKeychain({ for (final listEntry in batchedCats.asMap().entries) { final catBatch = listEntry.value; final index = listEntry.key; - final standardCoins = await fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); + final standardCoins = + await fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); final fee = catBatch.length * feePerCoin; final standardCoinsForFee = selectCoinsForAmount( @@ -64,7 +66,9 @@ Future transferKeychain({ ); await fullNode.pushTransaction(spendBundle); - print('pushed ${catMapEntry.key} cat spend bundle (${index + 1}/${batchedCats.length})'); + print( + 'pushed ${catMapEntry.key} cat spend bundle (${index + 1}/${batchedCats.length})', + ); await blockchainUtils.waitForSpendBundle(spendBundle); } } @@ -78,7 +82,8 @@ Future transferKeychain({ final nftBatch = listEntry.value; final index = listEntry.key; - final standardCoins = await fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); + final standardCoins = + await fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); final fee = nftBatch.length * feePerCoin; final standardCoinsForFee = selectCoinsForAmount( @@ -118,7 +123,8 @@ Future transferKeychain({ final didBatch = listEntry.value; final index = listEntry.key; - final standardCoins = await fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); + final standardCoins = + await fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); final fee = didBatch.length * feePerCoin; final standardCoinsForFee = selectCoinsForAmount( @@ -150,9 +156,11 @@ Future transferKeychain({ await blockchainUtils.waitForSpendBundle(totalSpendBundle); } - final standardCoinsToNuke = await fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); + final standardCoinsToNuke = + await fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); - final batchedStandardCoins = standardCoinsToNuke.splitIntoBatches(spendBundleSize); + final batchedStandardCoins = + standardCoinsToNuke.splitIntoBatches(spendBundleSize); print('sending standard coins'); for (final entry in batchedStandardCoins.asMap().entries) { final index = entry.key; @@ -167,7 +175,9 @@ Future transferKeychain({ ); await fullNode.pushTransaction(spendBundle); - print('pushed standard spend bundle (${index + 1}/${batchedStandardCoins.length})'); + print( + 'pushed standard spend bundle (${index + 1}/${batchedStandardCoins.length})', + ); await blockchainUtils.waitForSpendBundle(spendBundle); } } diff --git a/lib/src/command/exchange/cross_chain_offer_exchange.dart b/lib/src/command/exchange/cross_chain_offer_exchange.dart index d0cda61a..1cb194a2 100644 --- a/lib/src/command/exchange/cross_chain_offer_exchange.dart +++ b/lib/src/command/exchange/cross_chain_offer_exchange.dart @@ -1,19 +1,39 @@ import 'dart:async'; import 'dart:io'; +import 'dart:math'; import 'package:chia_crypto_utils/chia_crypto_utils.dart'; import 'package:chia_crypto_utils/src/command/exchange/exchange_btc.dart'; -late final ChiaFullNodeInterface _fullNode; -final _xchToBtcService = XchToBtcService(); -final _btcToXchService = BtcToXchService(); -final _crossChainOfferService = CrossChainOfferService(_fullNode); -final _standardWalletService = StandardWalletService(); +late final ChiaFullNodeInterface fullNode; +late final File logFile; +final xchToBtcService = XchToBtcService(); +final btcToXchService = BtcToXchService(); +final crossChainOfferService = CrossChainOfferFileService(); +final standardWalletService = StandardWalletService(); +final exchangeOfferWalletService = ExchangeOfferWalletService(); +final exchangeOfferService = ExchangeOfferService(fullNode); + +const fee = 50; Future makeCrossChainOffer(ChiaFullNodeInterface fullNodeFromUrl) async { - _fullNode = fullNodeFromUrl; - final requestorPrivateKey = PrivateKey.generate(); + fullNode = fullNodeFromUrl; + + final keychainCoreSecret = KeychainCoreSecret.generate(); + final keychain = WalletKeychain.fromCoreSecret(keychainCoreSecret); + final masterPrivateKey = keychainCoreSecret.masterPrivateKey; + final derivationIndex = + ExchangeOfferService.randomDerivationIndexForExchange(); + + final walletVector = + await WalletVector.fromPrivateKeyAsync(masterPrivateKey, derivationIndex); + + final requestorPrivateKey = walletVector.childPrivateKey; final requestorPublicKey = requestorPrivateKey.getG1(); + final messagePuzzlehash = walletVector.puzzlehash; + final messageAddress = messagePuzzlehash.toAddressWithContext(); + final requestorPuzzlehash = keychain.puzzlehashes.first; + XchScanResponse? response; while (response == null) { response = await XchScan().getChiaPrice(); @@ -25,14 +45,19 @@ Future makeCrossChainOffer(ChiaFullNodeInterface fullNodeFromUrl) async { print('\nThese are the current prices of XCH and BTC:'); print('1 XCH = $btcPerXch BTC or ${usdPerXch.toStringAsFixed(2)} USD'); - print('1 BTC = ${xchPerBtc.toStringAsFixed(8)} XCH or ${usdPerBtc.toStringAsFixed(2)} USD'); + print( + '1 BTC = ${xchPerBtc.toStringAsFixed(8)} XCH or ${usdPerBtc.toStringAsFixed(2)} USD', + ); await Future.delayed(const Duration(seconds: 1)); - print('\nAre you offering XCH in exchange for BTC or BTC in exchange for XCH?'); + print( + '\nAre you offering XCH in exchange for BTC or BTC in exchange for XCH?', + ); print('1. XCH in exchange for BTC'); print('2. BTC in exchange for XCH'); String? choice; + ExchangeType? exchangeType; ExchangeAmountType? offeredAmountType; ExchangeAmountType? requestedAmountType; String? offeredDenomination; @@ -43,11 +68,13 @@ Future makeCrossChainOffer(ChiaFullNodeInterface fullNodeFromUrl) async { choice = stdin.readLineSync()!.trim(); if (choice == '1') { + exchangeType = ExchangeType.xchToBtc; offeredAmountType = ExchangeAmountType.XCH; requestedAmountType = ExchangeAmountType.BTC; offeredDenomination = 'mojos'; requestedDenomination = 'satoshis'; } else if (choice == '2') { + exchangeType = ExchangeType.btcToXch; offeredAmountType = ExchangeAmountType.BTC; requestedAmountType = ExchangeAmountType.XCH; offeredDenomination = 'satoshis'; @@ -83,19 +110,6 @@ Future makeCrossChainOffer(ChiaFullNodeInterface fullNodeFromUrl) async { } } - print('\nEnter an XCH address for interested parties to send message coins to.'); - Puzzlehash? messagePuzzlehash; - while (messagePuzzlehash == null) { - stdout.write('> '); - try { - messagePuzzlehash = Address(stdin.readLineSync()!.trim().toLowerCase()).toPuzzlehash(); - } catch (e) { - print("\nCouldn't verify your address. Please try again:"); - } - } - - final messageAddress = messagePuzzlehash.toAddressWithContext(); - print('\nEnter how long you want this offer to be valid for in hours:'); int? validityTimeHours; while (validityTimeHours == null) { @@ -107,136 +121,386 @@ Future makeCrossChainOffer(ChiaFullNodeInterface fullNodeFromUrl) async { } } - final currentUnixTimestamp = DateTime.now().millisecondsSinceEpoch ~/ 1000; - final validityTime = currentUnixTimestamp + (validityTimeHours * 60 * 60); - - CrossChainOfferFile? offerFile; + final currentUnixTimeStamp = DateTime.now().millisecondsSinceEpoch ~/ 1000; + final validityTime = currentUnixTimeStamp + (validityTimeHours * 60 * 60); - if (choice == '1') { + LightningPaymentRequest? requestorPaymentRequest; + if (offeredAmountType == ExchangeAmountType.XCH) { print( '\nCreate a lightning payment request for $requestedAmountValue satoshis and paste it here:', ); - LightningPaymentRequest? paymentRequest; - while (paymentRequest == null) { + while (requestorPaymentRequest == null) { stdout.write('> '); try { final paymentRequestString = stdin.readLineSync()!.trim().toLowerCase(); - paymentRequest = decodeLightningPaymentRequest(paymentRequestString); + requestorPaymentRequest = + decodeLightningPaymentRequest(paymentRequestString); } catch (e) { - print("\nCouldn't validate the lightning payment request. Please try again:"); + print( + "\nCouldn't validate the lightning payment request. Please try again:", + ); } } + } - offerFile = _crossChainOfferService.createXchToBtcOfferFile( - amountMojos: offeredAmountValue, - amountSatoshis: requestedAmountValue, - messageAddress: messageAddress, - validityTime: validityTime, - requestorPublicKey: requestorPublicKey, - paymentRequest: paymentRequest, - ); - } else { - offerFile = _crossChainOfferService.createBtcToXchOfferFile( - amountMojos: requestedAmountValue, - amountSatoshis: offeredAmountValue, - messageAddress: messageAddress, - validityTime: validityTime, - requestorPublicKey: requestorPublicKey, - ); + final mojos = exchangeType == ExchangeType.xchToBtc + ? offeredAmountValue + : requestedAmountValue; + + // ask for enough XCH for the exchange from user to cover initialization, message coin acceptance, + // escrow transfer (in case of XCH holder), and clawback or sweep + final amountToSend = + 3 + (fee * 3) + (exchangeType == ExchangeType.xchToBtc ? mojos + fee : 0); + final coinPuzzlehash = keychain.puzzlehashes.first; + final coinAddress = Address.fromContext(coinPuzzlehash); + + logFile = await generateLogFile( + mnemonicSeed: keychainCoreSecret.mnemonicString, + requestorPrivateKey: requestorPrivateKey, + ); + + print( + '\nPlease send ${amountToSend > mojoCutoff ? '${(amountToSend / mojosPerXch).toStringAsFixed(12)} XCH' : '$amountToSend mojos'} to the following address.', + ); + print( + 'These funds will be used to cover the transactions that make up the exchange.', + ); + print( + 'You can use the mnemonic found in the log file to claim any XCH leftover', + ); + print('at the end of the exchange or if the program closes prematurely.'); + print(coinAddress.address); + + final sentCoins = await waitForUserToSendXch(coinPuzzlehash, amountToSend); + + final coinsForInitialization = selectCoinsForAmount(sentCoins, 3 + fee); + + final initializationCoinId = coinsForInitialization.first.id; + + late final MakerCrossChainOfferFile offerFile; + switch (exchangeType!) { + case ExchangeType.xchToBtc: + offerFile = crossChainOfferService.createXchToBtcMakerOfferFile( + initializationCoinId: initializationCoinId, + amountMojos: offeredAmountValue, + amountSatoshis: requestedAmountValue, + messageAddress: messageAddress, + validityTime: validityTime, + requestorPublicKey: requestorPublicKey, + paymentRequest: requestorPaymentRequest!, + ); + break; + case ExchangeType.btcToXch: + offerFile = crossChainOfferService.createBtcToXchMakerOfferFile( + initializationCoinId: initializationCoinId, + amountMojos: requestedAmountValue, + amountSatoshis: offeredAmountValue, + messageAddress: messageAddress, + validityTime: validityTime, + requestorPublicKey: requestorPublicKey, + ); + break; } final serializedOfferFile = offerFile.serialize(requestorPrivateKey); + await writeToLogFile( + logFile, + 'Maker Offer File', + serializedOfferFile, + ); + print('\nBelow is your serialized offer file.'); print(serializedOfferFile); - await generateLogFile(requestorPrivateKey, serializedOfferFile); + final initializationSpendBundle = + exchangeOfferWalletService.createInitializationSpendBundle( + messagePuzzlehash: messagePuzzlehash, + coinsInput: coinsForInitialization, + initializationCoinId: initializationCoinId, + keychain: keychain, + derivationIndex: derivationIndex, + serializedOfferFile: serializedOfferFile, + changePuzzlehash: requestorPuzzlehash, + fee: 50, + ); - print('\nSend serialized offer file to Dexie? Y/N'); + await fullNode.pushTransaction(initializationSpendBundle); - var confirmation = ''; - while (!confirmation.startsWith('y') && !confirmation.startsWith('n')) { - stdout.write('> '); - confirmation = stdin.readLineSync()!.trim().toLowerCase(); - if (confirmation.startsWith('y')) { - final response = await DexieExchangeOfferApi().postOffer(serializedOfferFile); - if (response.success == true) { - print('\nOffer has been successfully added to Dexie. Your offer ID is:'); - print(response.id); + await writeToLogFile( + logFile, + 'Initialization Spend Bundle', + initializationSpendBundle.toJson().toString(), + ); + + await waitForTransactionToComplete( + coinBeingSpentId: initializationCoinId, + startMessage: 'Initializating offer...', + waitingMessage: 'Waiting for initialization transaction to complete...', + completionMessage: 'Offer initialized!', + ); + + // print('\nSend serialized offer file to Dexie? Y/N'); + + // var confirmation = ''; + // while (!confirmation.startsWith('y') && !confirmation.startsWith('n')) { + // stdout.write('> '); + // confirmation = stdin.readLineSync()!.trim().toLowerCase(); + // if (confirmation.startsWith('y')) { + // final response = + // await DexieExchangeOfferApi().postOffer(serializedOfferFile); + // if (response.success == true) { + // print( + // '\nOffer has been successfully added to Dexie. Your offer ID is:', + // ); + // print(response.id); + // } else { + // print('Request failed. Please try again.'); + // exit(exitCode); + // } + // } else if (confirmation.startsWith('n')) { + // continue; + // } else { + // print('\nNot a valid choice.'); + // } + // } + + print( + '\nPress any key to start waiting for a message coin with a taker offer', + ); + print('file to arrive at the address you supplied.'); + stdin.readLineSync(); + + var messageCoinAccepted = false; + MessageCoinInfo? messageCoinInfo; + final declinedMessageCoinIds = []; + while (!messageCoinAccepted) { + while (messageCoinInfo == null) { + print('Waiting for message coin...'); + await Future.delayed(const Duration(seconds: 10)); + messageCoinInfo = await exchangeOfferService.getNextValidMessageCoin( + initializationCoinId: initializationCoinId, + serializedOfferFile: serializedOfferFile, + messagePuzzlehash: messagePuzzlehash, + exchangeType: exchangeType, + satoshis: + exchangeType == ExchangeType.btcToXch ? offerFile.satoshis : null, + declinedMessageCoinIds: declinedMessageCoinIds, + ); + } + + final messageCoin = messageCoinInfo.messageCoin; + final messageCoinChild = + await fullNode.getSingleChildCoinFromCoin(messageCoin); + final messageCoinChildId = messageCoinChild!.id; + + print('\nA message coin has arrived!'); + print('\nValidity time: ${messageCoinInfo.exchangeValidityTime}'); + print('\nPublic key: ${messageCoinInfo.fulfillerPublicKey.toHex()}'); + if (messageCoinInfo.lightningPaymentRequest != null) { + print( + '\nLightning Payment Request: ${messageCoinInfo.lightningPaymentRequest!.paymentRequest}', + ); + } + + print( + '\nAfter the message coin is accepted, the exchange must be completed within ${messageCoinInfo.exchangeValidityTime ~/ 60} minutes.', + ); + print('Do you accept? Y/N'); + + var messageCoinDecision = ''; + while (!messageCoinDecision.startsWith('y') && + !messageCoinDecision.startsWith('n')) { + stdout.write('> '); + messageCoinDecision = stdin.readLineSync()!.trim().toLowerCase(); + if (messageCoinDecision.startsWith('y')) { + final messageCoinAcceptanceSpendBundle = + exchangeOfferWalletService.createMessageCoinAcceptanceSpendBundle( + initializationCoinId: initializationCoinId, + messageCoinChild: messageCoinChild, + targetPuzzlehash: requestorPuzzlehash, + walletVector: walletVector, + ); + + final unspentCoins = + await fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); + + final feeSpendBundle = standardWalletService.createFeeSpendBundle( + fee: fee, + standardCoins: selectCoinsForAmount(unspentCoins, fee), + keychain: keychain, + changePuzzlehash: requestorPuzzlehash, + ); + + final totalMessageCoinAcceptanceSpendBundle = + messageCoinAcceptanceSpendBundle + feeSpendBundle; + + await fullNode.pushTransaction(totalMessageCoinAcceptanceSpendBundle); + + await writeToLogFile( + logFile, + 'Message Coin Acceptance Spend Bundle', + totalMessageCoinAcceptanceSpendBundle.toJson().toString(), + ); + + await writeToLogFile( + logFile, + 'Taker Offer File', + messageCoinInfo!.serializedOfferAcceptFile, + ); + + await waitForTransactionToComplete( + coinBeingSpentId: messageCoinChildId, + startMessage: 'Accepting message coin...', + waitingMessage: 'Waiting for acceptance transaction to complete...', + completionMessage: 'Message coin acceptance transaction complete!', + ); + messageCoinAccepted = true; + } else if (messageCoinDecision.startsWith('n')) { + final messageCoinDeclinationSpendBundle = + exchangeOfferWalletService.createMessageCoinDeclinationSpendBundle( + messageCoinChild: messageCoinChild, + targetPuzzlehash: requestorPuzzlehash, + walletVector: walletVector, + ); + + final unspentCoins = + await fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); + + final feeSpendBundle = standardWalletService.createFeeSpendBundle( + fee: fee, + standardCoins: selectCoinsForAmount(unspentCoins, fee), + keychain: keychain, + changePuzzlehash: requestorPuzzlehash, + ); + + final totalMessageCoinDeclinationSpendBundle = + messageCoinDeclinationSpendBundle + feeSpendBundle; + + await fullNode.pushTransaction(totalMessageCoinDeclinationSpendBundle); + + declinedMessageCoinIds.add(messageCoin.id); + + await waitForTransactionToComplete( + coinBeingSpentId: messageCoinChildId, + startMessage: 'Declining message coin...', + waitingMessage: 'Waiting for declination transaction to complete...', + completionMessage: 'Message coin declination transaction complete.', + ); + + print(''); + + messageCoinInfo = null; } else { - print('Request failed. Please try again.'); - exit(exitCode); + print('\nNot a valid choice.'); } - } else if (confirmation.startsWith('n')) { - continue; - } else { - print('\nNot a valid choice.'); } } - print('\nPress any key to start waiting for a message coin with an offer accept'); - print('file to arrive at the address you supplied.'); - stdin.readLineSync(); + final exchangeValidityTime = messageCoinInfo!.exchangeValidityTime; + final fulfillerPublicKey = messageCoinInfo.fulfillerPublicKey; - final offerAcceptFileMemo = await waitForMessageCoin(messagePuzzlehash, serializedOfferFile); + final lightningPaymentRequest = + (requestorPaymentRequest ?? messageCoinInfo.lightningPaymentRequest)!; - print('\nA message coin with an offer accept file has arrived:'); - print(offerAcceptFileMemo); + final paymentHash = lightningPaymentRequest.paymentHash!; - final deserializedOfferAcceptFile = - TakerCrossChainOfferFile.fromSerializedOfferFile(offerAcceptFileMemo!); + final escrowPuzzlehash = offerFile.getEscrowPuzzlehash( + requestorPrivateKey: requestorPrivateKey, + clawbackDelaySeconds: messageCoinInfo.exchangeValidityTime, + sweepPaymentHash: lightningPaymentRequest.paymentHash!, + fulfillerPublicKey: messageCoinInfo.fulfillerPublicKey, + ); - final exchangeInfo = offerFile.getExchangeInfo(deserializedOfferAcceptFile, requestorPrivateKey); + switch (exchangeType) { + case ExchangeType.xchToBtc: + await completeXchToBtcExchange( + mojos: mojos, + exchangeValidityTime: exchangeValidityTime, + escrowPuzzlehash: escrowPuzzlehash, + initializationCoinId: initializationCoinId, + paymentHash: paymentHash, + fulfillerPublicKey: fulfillerPublicKey, + requestorPrivateKey: requestorPrivateKey, + requestorPuzzlehash: requestorPuzzlehash, + keychain: keychain, + ); - if (choice == '1') { - await completeXchToBtcExchange(exchangeInfo, requestorPrivateKey); - } else { - await completeBtcToXchExchange(exchangeInfo, requestorPrivateKey); + break; + case ExchangeType.btcToXch: + await completeBtcToXchExchange( + mojos: mojos, + exchangeValidityTime: exchangeValidityTime, + escrowPuzzlehash: escrowPuzzlehash, + initializationCoinId: initializationCoinId, + lightningPaymentRequest: lightningPaymentRequest, + fulfillerPublicKey: fulfillerPublicKey, + requestorPrivateKey: requestorPrivateKey, + requestorPuzzlehash: requestorPuzzlehash, + keychain: keychain, + ); + break; } } -Future acceptCrossChainOffer(ChiaFullNodeInterface fullNodeFromUrl) async { - _fullNode = fullNodeFromUrl; - final requestorPrivateKey = PrivateKey.generate(); +Future takeCrossChainOffer(ChiaFullNodeInterface fullNodeFromUrl) async { + fullNode = fullNodeFromUrl; + + final keychainCoreSecret = KeychainCoreSecret.generate(); + final keychain = WalletKeychain.fromCoreSecret(keychainCoreSecret); + final masterPrivateKey = keychainCoreSecret.masterPrivateKey; + final derivationIndex = Random.secure().nextInt(10); + + final walletVector = + await WalletVector.fromPrivateKeyAsync(masterPrivateKey, derivationIndex); + + final requestorPrivateKey = walletVector.childPrivateKey; final requestorPublicKey = requestorPrivateKey.getG1(); + final requestorPuzzlehash = keychain.puzzlehashes.first; - print('\nPaste in the serialized cross chain offer file you want to accept:'); + print('\nPaste in the serialized cross chain offer file you want to take:'); String? serializedOfferFile; - CrossChainOfferFile? offerFile; - while (offerFile == null) { + MakerCrossChainOfferFile? makerOfferFile; + while (makerOfferFile == null) { stdout.write('> '); try { stdin.lineMode = false; serializedOfferFile = stdin.readLineSync()!.trim(); stdin.lineMode = true; - offerFile = CrossChainOfferFile.fromSerializedOfferFile(serializedOfferFile); - if (offerFile.prefix.name == 'ccoffer_accept') { + makerOfferFile = + MakerCrossChainOfferFile.fromSerializedOfferFile(serializedOfferFile); + } catch (e) { + if (serializedOfferFile!.startsWith('ccoffer_accept')) { print( "Wrong offer file type. The prefix should be 'ccoffer,' not 'ccoffer_accept.'", ); - offerFile = null; + print('\nPlease enter a valid cross chain offer file:'); + } else { + print('\nPlease enter a valid cross chain offer file:'); } - } catch (e) { - print('\nPlease enter a valid cross chain offer file:'); } } try { - CrossChainOfferService.checkValidity(offerFile); + CrossChainOfferFileService.checkValidity(makerOfferFile); } catch (e) { - print('\nThis cross chain offer has expired. Try again with a still valid offer.'); + print( + '\nThis cross chain offer has expired. Try again with a still valid offer.', + ); exit(exitCode); } - print('\nEnter how many minutes you want to allow for the exchange to complete before'); - print('it is aborted. Must be at least 10 minutes.'); - int? validityTime; - while (validityTime == null || validityTime < 600) { + print( + '\nEnter how many minutes you want to allow for the exchange to complete before', + ); + print('it is aborted. Must be at least 60 minutes.'); + int? exchangeValidityTime; + while (exchangeValidityTime == null || exchangeValidityTime < 3600) { stdout.write('> '); try { - validityTime = int.parse(stdin.readLineSync()!.trim()) * 60; - if (validityTime < 600) { - print('\nMust be at least 10 minutes.'); + exchangeValidityTime = int.parse(stdin.readLineSync()!.trim()) * 60; + if (exchangeValidityTime < 3600) { + print('\nMust be at least 60 minutes.'); } } catch (e) { print( @@ -245,361 +509,274 @@ Future acceptCrossChainOffer(ChiaFullNodeInterface fullNodeFromUrl) async } } - TakerCrossChainOfferFile? offerAcceptFile; - Address? messageAddress; - - if (offerFile.type == CrossChainOfferFileType.btcToXch) { - final btcToXchOfferFile = BtcToXchMakerOfferFile.fromSerializedOfferFile(serializedOfferFile!); - - messageAddress = btcToXchOfferFile.messageAddress; + final messageAddress = makerOfferFile.messageAddress; + final initializationCoinId = makerOfferFile.initializationCoinId; + final fulfillerPublicKey = makerOfferFile.publicKey; + final mojos = makerOfferFile.mojos; + final satoshis = makerOfferFile.satoshis; + TakerCrossChainOfferFile? takerOfferFile; + ExchangeType exchangeType; + LightningPaymentRequest? requestorPaymentRequest; + if (makerOfferFile.exchangeType == ExchangeType.btcToXch) { print( - '\nCreate a lightning payment request for ${btcToXchOfferFile.offeredAmount.amount} satoshis and paste it here:', + '\nCreate a lightning payment request for $satoshis satoshis and paste it here:', ); - LightningPaymentRequest? paymentRequest; - while (paymentRequest == null) { + while (requestorPaymentRequest == null) { stdout.write('> '); try { final paymentRequestString = stdin.readLineSync()!.trim().toLowerCase(); - paymentRequest = decodeLightningPaymentRequest(paymentRequestString); + requestorPaymentRequest = + decodeLightningPaymentRequest(paymentRequestString); } catch (e) { - print("\nCouldn't validate the lightning payment request. Please try again:"); + print( + "\nCouldn't validate the lightning payment request. Please try again:", + ); } } - offerAcceptFile = _crossChainOfferService.createXchToBtcAcceptFile( - serializedOfferFile: serializedOfferFile, - validityTime: validityTime, + exchangeType = ExchangeType.xchToBtc; + takerOfferFile = crossChainOfferService.createXchToBtcTakerOfferFile( + initializationCoinId: initializationCoinId, + serializedMakerOfferFile: serializedOfferFile!, + validityTime: exchangeValidityTime, requestorPublicKey: requestorPublicKey, - paymentRequest: paymentRequest, + paymentRequest: requestorPaymentRequest, ); } else { - final xchToBtcOfferFile = XchToBtcMakerOfferFile.fromSerializedOfferFile(serializedOfferFile!); - - messageAddress = xchToBtcOfferFile.messageAddress; - - offerAcceptFile = _crossChainOfferService.createBtcToXchAcceptFile( - serializedOfferFile: serializedOfferFile, - validityTime: validityTime, + exchangeType = ExchangeType.btcToXch; + takerOfferFile = crossChainOfferService.createBtcToXchTakerOfferFile( + initializationCoinId: initializationCoinId, + serializedMakerOfferFile: serializedOfferFile!, + validityTime: exchangeValidityTime, requestorPublicKey: requestorPublicKey, ); } - final serializedOfferAcceptFile = offerAcceptFile.serialize(requestorPrivateKey); + final serializedTakerOfferFile = + takerOfferFile.serialize(requestorPrivateKey); - await generateLogFile(requestorPrivateKey, serializedOfferFile, serializedOfferAcceptFile); + logFile = await generateLogFile( + mnemonicSeed: keychainCoreSecret.mnemonicString, + requestorPrivateKey: requestorPrivateKey, + serializedOfferFile: serializedOfferFile, + serializedTakerOfferFile: serializedTakerOfferFile, + ); - final keychainCoreSecret = KeychainCoreSecret.generate(); - final keychain = WalletKeychain.fromCoreSecret(keychainCoreSecret); + // ask for enough XCH for the exchange from user to cover message coin send, escrow transfer (in case of XCH holder) + // and clawback OR sweep + final amountToSend = minimumNotificationCoinAmount + + (fee * 2) + + (exchangeType == ExchangeType.xchToBtc ? makerOfferFile.mojos + fee : 0); final coinPuzzlehash = keychain.puzzlehashes.first; final coinAddress = Address.fromContext(coinPuzzlehash); final messagePuzzlehash = messageAddress.toPuzzlehash(); - print('\nA coin with a memo containing your serialized offer accept file below must be'); - print('sent to the message address indicated in the original offer file.'); - print(serializedOfferAcceptFile); - print('\nYou may either send a coin with the above memo yourself, OR you may send at'); - print('least 100 mojos the address provided by the program, and the program will send'); - print('the coin with the memo on your behalf.'); - - print('\nPlease indicate which method you would like to use:'); - print('1. Manually send coin with memo'); - print('2. Have program send coin with memo'); - String? choice; - while (choice != '1' && choice != '2') { - stdout.write('> '); - choice = stdin.readLineSync()!.trim(); - if (choice == '1') { - print('\nSend a coin with the above memo to the this address:'); - print(messageAddress.address); - print('\nPress any key to continue once you have done so.'); - stdin.readLineSync(); - } else if (choice == '2') { - print('\nSend at least 100 mojos the following address, and the program will send the'); - print('coin with memo on your behalf:'); - print(coinAddress.address); - - print('\nPress any key to continue once you have done so.'); - stdin.readLineSync(); - - final additionPuzzlehashes = []; - var transactionValidated = false; - var coins = []; - - while (coins.totalValue < 100) { - print('Waiting for coin...'); - await Future.delayed(const Duration(seconds: 10)); - - // if transaction hasn't been validated yet, keep checking mempool - if (transactionValidated == false) { - final mempoolItemsResponse = await _fullNode.getAllMempoolItems(); - mempoolItemsResponse.mempoolItemMap.forEach((key, item) { - additionPuzzlehashes.addAll(item.additions.map((addition) => addition.puzzlehash)); - }); - - if (additionPuzzlehashes.contains(coinPuzzlehash)) { - print('\nThe transaction has been validated and is now in the mempool.\n'); - transactionValidated = true; - } - } - - coins = await _fullNode.getCoinsByPuzzleHashes( - [coinPuzzlehash], - ); - } - - print('\nXCH received!'); - - final parentCoin = await _fullNode.getCoinById(coins[0].parentCoinInfo); - final changePuzzlehash = parentCoin!.puzzlehash; - - final messageSpendBundle = _standardWalletService.createSpendBundle( - payments: [ - Payment(50, messagePuzzlehash, memos: [serializedOfferAcceptFile]), - ], - coinsInput: coins, - changePuzzlehash: changePuzzlehash, - keychain: keychain, - fee: 50, - ); - - await _fullNode.pushTransaction(messageSpendBundle); - - print('\nSending coin with memo to message address...\n'); - } else { - print('\nNot a valid choice.'); - } - } - - await waitForMessageCoin(messagePuzzlehash, serializedOfferAcceptFile); - print('\nYour message coin has arrived!'); - - final exchangeInfo = offerAcceptFile.getExchangeInfo(offerFile, requestorPrivateKey); - - if (offerAcceptFile.type == CrossChainOfferFileType.xchToBtcAccept) { - await completeXchToBtcExchange(exchangeInfo, requestorPrivateKey); - } else { - await completeBtcToXchExchange(exchangeInfo, requestorPrivateKey); - } -} + print( + '\nPlease send ${amountToSend > mojoCutoff ? '${(amountToSend / mojosPerXch).toStringAsFixed(12)} XCH' : '$amountToSend mojos'} to the following address.', + ); + print( + 'These funds will be used to cover the transactions that make up the exchange.', + ); + print( + 'You can use the mnemonic found in the log file to claim any XCH leftover', + ); + print('at the end of the exchange or if the program closes prematurely.'); + print(coinAddress.address); + + final sentCoins = await waitForUserToSendXch(coinPuzzlehash, amountToSend); + + final messageSpendBundle = + exchangeOfferWalletService.createMessageSpendBundle( + messagePuzzlehash: messagePuzzlehash, + coinsInput: selectCoinsForAmount(sentCoins, minimumNotificationCoinAmount), + keychain: keychain, + serializedTakerOfferFile: serializedTakerOfferFile, + initializationCoinId: initializationCoinId, + fee: 50, + changePuzzlehash: requestorPuzzlehash, + ); -Future resumeCrossChainOfferExchange(ChiaFullNodeInterface fullNodeFromUrl) async { - _fullNode = fullNodeFromUrl; - print('\nPlease paste in the original cross chain offer file:'); - String? serializedOfferFile; - CrossChainOfferFile? offerFile; - while (offerFile == null) { - stdout.write('> '); - try { - stdin.lineMode = false; - serializedOfferFile = stdin.readLineSync()!.trim(); - stdin.lineMode = true; + await fullNode.pushTransaction(messageSpendBundle); - offerFile = CrossChainOfferFile.fromSerializedOfferFile(serializedOfferFile); - if (offerFile.prefix.name == 'ccoffer_accept') { - print( - "Wrong offer file type. The prefix should be 'ccoffer,' not 'ccoffer_accept.'", - ); - offerFile = null; - } - } catch (e) { - print('\nPlease enter a valid cross chain offer file:'); - } - } + await writeToLogFile( + logFile, + 'Message Spend Bundle', + messageSpendBundle.toJson().toString(), + ); - try { - CrossChainOfferService.checkValidity(offerFile); - } catch (e) { - print('\nThis cross chain offer has expired. Try again with a still valid offer.'); - exit(exitCode); - } + final messageCoinId = messageSpendBundle.coinSpends + .where( + (coinSpend) => + coinSpend.puzzleReveal.uncurry().mod == notificationProgram, + ) + .single + .coin + .id; + + await waitForTransactionToComplete( + coinBeingSpentId: messageCoinId, + startMessage: 'Sending message coin to maker...', + waitingMessage: 'Waiting for transaction to complete...', + completionMessage: 'Your message coin has arrived!', + ); - print('\nPlease paste in the cross chain offer accept file:'); - CrossChainOfferFile? offerAcceptFile; - String? serializedOfferAcceptFile; - while (offerAcceptFile == null) { - stdout.write('> '); - try { - stdin.lineMode = false; - serializedOfferAcceptFile = stdin.readLineSync()!.trim(); - stdin.lineMode = true; + final messageCoin = await fullNode.getCoinById(messageCoinId); + final messageCoinChild = + await fullNode.getSingleChildCoinFromCoin(messageCoin!); - offerAcceptFile = TakerCrossChainOfferFile.fromSerializedOfferFile(serializedOfferAcceptFile); - if (offerAcceptFile.prefix.name == 'ccoffer') { - print( - "Wrong offer file type. The prefix should be 'ccoffer_accept,' not 'ccoffer.'", - ); - offerAcceptFile = null; - } - } catch (e) { - print('\nPlease enter a valid cross chain offer accept file:'); - } - } + print( + '\nPress any key to start waiting for maker to accept or decline your message coin', + ); + stdin.readLineSync(); - print('\nPlease paste in the private key you used for this exchange:'); - PrivateKey? requestorPrivateKey; - while (requestorPrivateKey == null) { - stdout.write('> '); - try { - final privateKeyInput = PrivateKey.fromHex(stdin.readLineSync()!.trim()); - if (offerFile.publicKey == privateKeyInput.getG1()) { - // user made offer - requestorPrivateKey = privateKeyInput; - - if (offerFile.type == CrossChainOfferFileType.xchToBtc) { - final xchToBtcOfferFile = - XchToBtcMakerOfferFile.fromSerializedOfferFile(serializedOfferFile!); - final exchangeInfo = - xchToBtcOfferFile.getExchangeInfo(offerAcceptFile, requestorPrivateKey); - - await completeXchToBtcExchange(exchangeInfo, requestorPrivateKey); - } else { - final btcToXchOfferFile = - BtcToXchMakerOfferFile.fromSerializedOfferFile(serializedOfferFile!); - final exchangeInfo = - btcToXchOfferFile.getExchangeInfo(offerAcceptFile, requestorPrivateKey); - - await completeBtcToXchExchange(exchangeInfo, requestorPrivateKey); - } - } else if (offerAcceptFile.publicKey == privateKeyInput.getG1()) { - // user is accepting offer - requestorPrivateKey = privateKeyInput; - - if (offerAcceptFile.type == CrossChainOfferFileType.xchToBtcAccept) { - final xchToBtcOfferAcceptFile = - XchToBtcTakerOfferFile.fromSerializedOfferFile(serializedOfferAcceptFile!); - final exchangeInfo = - xchToBtcOfferAcceptFile.getExchangeInfo(offerFile, requestorPrivateKey); - await completeXchToBtcExchange(exchangeInfo, requestorPrivateKey); - } else { - final btcToXchOfferAcceptFile = - BtcToXchTakerOfferFile.fromSerializedOfferFile(serializedOfferAcceptFile!); - final exchangeInfo = - btcToXchOfferAcceptFile.getExchangeInfo(offerFile, requestorPrivateKey); - await completeBtcToXchExchange(exchangeInfo, requestorPrivateKey); - } - } - } catch (e) { - print('\nInvalid key. Please try again:'); - } - } -} + await waitForMakerToSpendMessageCoinChild( + messageCoinChildId: messageCoinChild!.id, + initializationCoinId: initializationCoinId, + ); -Future waitForMessageCoin( - Puzzlehash messagePuzzlehash, - String serializedCrossChainOfferFile, -) async { - final additionPuzzlehashes = []; - var transactionValidated = false; + final lightningPaymentRequest = + (requestorPaymentRequest ?? makerOfferFile.lightningPaymentRequest)!; - while (true) { - print('Waiting for message coin to arrive...'); - await Future.delayed(const Duration(seconds: 10)); + final paymentHash = lightningPaymentRequest.paymentHash; - // if transaction hasn't been validated yet, keep checking mempool - if (transactionValidated == false) { - final mempoolItemsResponse = await _fullNode.getAllMempoolItems(); - mempoolItemsResponse.mempoolItemMap.forEach((key, item) { - additionPuzzlehashes.addAll(item.additions.map((addition) => addition.puzzlehash)); - }); - - if (additionPuzzlehashes.contains(messagePuzzlehash)) { - print('\nThe transaction has been validated and is now in the mempool.\n'); - transactionValidated = true; - } - } + final escrowPuzzlehash = takerOfferFile.getEscrowPuzzlehash( + requestorPrivateKey: requestorPrivateKey, + clawbackDelaySeconds: exchangeValidityTime, + sweepPaymentHash: paymentHash!, + fulfillerPublicKey: fulfillerPublicKey, + ); - if (serializedCrossChainOfferFile.startsWith('ccoffer_accept')) { - // in case of message coin sender: stop waiting once a coin with the right memo arrives at - // the message address - final verification = await _crossChainOfferService.verifyMessageCoinReceipt( - messagePuzzlehash, - serializedCrossChainOfferFile, + switch (exchangeType) { + case ExchangeType.xchToBtc: + await completeXchToBtcExchange( + mojos: mojos, + exchangeValidityTime: exchangeValidityTime, + escrowPuzzlehash: escrowPuzzlehash, + initializationCoinId: initializationCoinId, + paymentHash: paymentHash, + fulfillerPublicKey: fulfillerPublicKey, + requestorPrivateKey: requestorPrivateKey, + requestorPuzzlehash: requestorPuzzlehash, + keychain: keychain, ); - if (verification == true) return null; - } else { - // in case of message coin receiver: check if any coins at message address have a memo - // that can be deserialized in an accept offer file with an accepted offer hash that - // matches the original offer file - final offerAcceptFileMemo = - await _crossChainOfferService.getOfferAcceptFileFromMessagePuzzlehash( - messagePuzzlehash, - serializedCrossChainOfferFile, + + break; + case ExchangeType.btcToXch: + await completeBtcToXchExchange( + mojos: mojos, + exchangeValidityTime: exchangeValidityTime, + escrowPuzzlehash: escrowPuzzlehash, + initializationCoinId: initializationCoinId, + lightningPaymentRequest: lightningPaymentRequest, + fulfillerPublicKey: fulfillerPublicKey, + requestorPuzzlehash: requestorPuzzlehash, + requestorPrivateKey: requestorPrivateKey, + keychain: keychain, ); - if (offerAcceptFileMemo != null) return offerAcceptFileMemo; - } + break; } } Future> waitForEscrowCoins({ required int amount, required Puzzlehash escrowPuzzlehash, + required String waitingMessage, }) async { // wait for XCH to arrive at the escrow address - final additionPuzzlehashes = []; var transactionValidated = false; var escrowCoins = []; while (escrowCoins.totalValue < amount) { if (transactionValidated == false) { - print('Waiting for transfer to escrow address...'); + print(waitingMessage); } else { print('Waiting for transaction to complete...'); } await Future.delayed(const Duration(seconds: 10)); - // if transaction hasn't been validated yet, keep checking mempool if (transactionValidated == false) { - final mempoolItemsResponse = await _fullNode.getAllMempoolItems(); - mempoolItemsResponse.mempoolItemMap.forEach((key, item) { - additionPuzzlehashes.addAll(item.additions.map((addition) => addition.puzzlehash)); - }); - - if (additionPuzzlehashes.contains(escrowPuzzlehash)) { - print('\nThe transaction has been validated and is now in the mempool.\n'); - transactionValidated = true; - } + transactionValidated = + await isTransactionValidated(escrowPuzzlehash, amount); } - escrowCoins = await _fullNode.getCoinsByPuzzleHashes( + escrowCoins = await fullNode.getCoinsByPuzzleHashes( [escrowPuzzlehash], ); } print('\nThe escrow address has received sufficient XCH!'); - return escrowCoins; -} + final parentCoin = + await fullNode.getCoinById(escrowCoins.first.parentCoinInfo); + final sufficientConfirmationsHeight = parentCoin!.spentBlockIndex + 32; -Future completeBtcToXchExchange( - CrossChainOfferExchangeInfo exchangeInfo, - PrivateKey requestorPrivateKey, -) async { - final amountMojos = exchangeInfo.amountMojos; - final paymentRequest = exchangeInfo.paymentRequest; - final paymentHash = exchangeInfo.paymentHash; - final escrowPuzzlehash = exchangeInfo.escrowPuzzlehash; + print( + '\nWaiting 32 blocks for escrow transfer confirmation (until block ${parentCoin.spentBlockIndex}).\n', + ); + + while (true) { + await Future.delayed(const Duration(seconds: 30)); + + final currentHeight = await fullNode.getCurrentBlockIndex(); - print('\nYour counter party will send $amountMojos mojos to the following escrow address:'); + if (currentHeight != null) { + if (currentHeight >= sufficientConfirmationsHeight) { + print('\nEscrow transfer confirmed!'); + return escrowCoins; + } + print( + '${sufficientConfirmationsHeight - currentHeight} blocks remaining...', + ); + } + } +} + +Future completeBtcToXchExchange({ + required int mojos, + required int exchangeValidityTime, + required Puzzlehash escrowPuzzlehash, + required Bytes initializationCoinId, + required LightningPaymentRequest lightningPaymentRequest, + required JacobianPoint fulfillerPublicKey, + required PrivateKey requestorPrivateKey, + required Puzzlehash requestorPuzzlehash, + required WalletKeychain keychain, +}) async { + print( + '\nYour counter party will send $mojos mojos to the following escrow address:', + ); print(Address.fromContext(escrowPuzzlehash).address); - print('\nPress any key to start waiting for the XCH from your counter party.'); + print( + '\nPress any key to start waiting for the XCH from your counter party.', + ); stdin.readLineSync(); final escrowCoins = await waitForEscrowCoins( - amount: amountMojos, + amount: mojos, escrowPuzzlehash: escrowPuzzlehash, + waitingMessage: 'Waiting for escrow transfer...', ); - print('\nPlease paste the following lightning invoice into your BTC wallet and pay it.'); - print('Note that you must use a wallet that supports preimage reveal, such as Muun.'); - print(paymentRequest.paymentRequest); - print('\nAfter you have done so, you can find your lightning payment request'); - print('preimage by navigating to transaction history in your lightning wallet,'); + print( + '\nPlease paste the following lightning invoice into your BTC wallet and pay it.', + ); + print( + 'Note that you must use a wallet that supports preimage reveal, such as Muun.', + ); + print(lightningPaymentRequest.paymentRequest); + print( + '\nAfter you have done so, you can find your lightning payment request', + ); + print( + 'preimage by navigating to transaction history in your lightning wallet,', + ); print('clicking on the transaction, and viewing the payment details.'); print('\nPaste in the preimage below.'); - Bytes? preimage; + final paymentHash = lightningPaymentRequest.paymentHash; + Bytes? preimage; while (preimage == null) { stdout.write('> '); final preimageInput = stdin.readLineSync()!.trim().toLowerCase(); @@ -615,106 +792,365 @@ Future completeBtcToXchExchange( } } - print('\nPlease enter the address where you want to receive the XCH:'); - final sweepPuzzlehash = getRequestorPuzzlehash(); + print('\nPlease enter the address where you want the XCH to be swept to:'); + final sweepPuzzlehash = getUserPuzzlehash(); - final sweepSpendBundle = _btcToXchService.createSweepSpendBundle( - payments: [Payment(escrowCoins.totalValue, sweepPuzzlehash)], - coinsInput: escrowCoins, + final sweepSpendBundle = exchangeOfferWalletService.createSweepSpendBundle( + initializationCoinId: initializationCoinId, + escrowCoins: escrowCoins, + requestorPuzzlehash: sweepPuzzlehash, requestorPrivateKey: requestorPrivateKey, - clawbackDelaySeconds: exchangeInfo.validityTime, - sweepPaymentHash: paymentHash!, - sweepPreimage: preimage, - fulfillerPublicKey: exchangeInfo.fulfillerPublicKey, + exchangeValidityTime: exchangeValidityTime, + paymentHash: paymentHash!, + preimage: preimage, + fulfillerPublicKey: fulfillerPublicKey, + ); + + final unspentCoins = + await fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); + + final feeSpendBundle = standardWalletService.createFeeSpendBundle( + fee: fee, + standardCoins: selectCoinsForAmount(unspentCoins, fee), + keychain: keychain, + changePuzzlehash: requestorPuzzlehash, + ); + + final totalSweepSpendBundle = sweepSpendBundle + feeSpendBundle; + + await writeToLogFile( + logFile, + 'Sweep Spend Bundle', + totalSweepSpendBundle.toJson().toString(), ); - print('\nPushing spend bundle to sweep XCH to your address...'); - await generateSpendBundleFile(sweepSpendBundle); try { - await _fullNode.pushTransaction(sweepSpendBundle); - await verifyTransaction(escrowCoins, sweepPuzzlehash, _fullNode); + await fullNode.pushTransaction(totalSweepSpendBundle); } catch (e) { - print('\nTRANSACTION FAILED. The spend bundle was rejected. You may have responded'); + print( + '\nTRANSACTION FAILED. The spend bundle was rejected. You may have responded', + ); print('too late.'); } + + await waitForTransactionToComplete( + coinBeingSpentId: escrowCoins.first.id, + startMessage: 'Sweeping escrow address...', + waitingMessage: 'Waiting for sweep transaction to complete...', + completionMessage: 'XCH swept to your address. Exchange complete.', + ); } -Future completeXchToBtcExchange( - CrossChainOfferExchangeInfo exchangeInfo, - PrivateKey requestorPrivateKey, -) async { - final amountMojos = exchangeInfo.amountMojos; - final validityTime = exchangeInfo.validityTime; - final escrowPuzzlehash = exchangeInfo.escrowPuzzlehash; +Future completeXchToBtcExchange({ + required int mojos, + required int exchangeValidityTime, + required Puzzlehash escrowPuzzlehash, + required Bytes initializationCoinId, + required Bytes paymentHash, + required JacobianPoint fulfillerPublicKey, + required PrivateKey requestorPrivateKey, + required Puzzlehash requestorPuzzlehash, + required WalletKeychain keychain, +}) async { + print( + '\nThe program will send the amount of XCH being exchanged to the escrow address,', + ); + print( + 'where it will be held until your counterparty pays the lightning invoice.', + ); + print('Press any key to proceed.'); + stdin.readLineSync(); - print('\nPlease send $amountMojos mojos to the following escrow address to complete the'); - print('exchange:'); - print(escrowPuzzlehash.toAddressWithContext().address); + var unspentCoins = + await fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); - print('\nPress any key to continue once you have done so.'); - stdin.readLineSync(); + final escrowTransferSpendBundle = + exchangeOfferWalletService.createEscrowTransferSpendBundle( + initializationCoinId: initializationCoinId, + mojos: mojos, + escrowPuzzlehash: escrowPuzzlehash, + coinsInput: selectCoinsForAmount(unspentCoins, mojos + fee), + keychain: keychain, + requestorPrivateKey: requestorPrivateKey, + fee: fee, + changePuzzlehash: requestorPuzzlehash, + ); + + await fullNode.pushTransaction(escrowTransferSpendBundle); + + await writeToLogFile( + logFile, + 'Escrow Transfer Spend Bundle', + escrowTransferSpendBundle.toJson().toString(), + ); + + print('Transfering XCH to escrow address...\n'); final escrowCoins = await waitForEscrowCoins( - amount: amountMojos, + amount: mojos, escrowPuzzlehash: escrowPuzzlehash, + waitingMessage: 'Waiting for transaction to complete...', ); - print('\nEnter the address where the XCH will be returned in the event the exchange'); + print( + '\nEnter the address where the XCH will be returned in the event the exchange', + ); print('is aborted or fails:'); - final clawbackPuzzlehash = getRequestorPuzzlehash(); + final clawbackPuzzlehash = getUserPuzzlehash(); - final clawbackSpendBundle = _xchToBtcService.createClawbackSpendBundle( - payments: [Payment(escrowCoins.totalValue, clawbackPuzzlehash)], - coinsInput: escrowCoins, + final clawbackSpendBundle = + exchangeOfferWalletService.createClawbackSpendBundle( + initializationCoinId: paymentHash, + escrowCoins: escrowCoins, + requestorPuzzlehash: clawbackPuzzlehash, requestorPrivateKey: requestorPrivateKey, - clawbackDelaySeconds: validityTime, - sweepPaymentHash: exchangeInfo.paymentHash!, - fulfillerPublicKey: exchangeInfo.fulfillerPublicKey, + exchangeValidityTime: exchangeValidityTime, + paymentHash: paymentHash, + fulfillerPublicKey: fulfillerPublicKey, + ); + + unspentCoins = await fullNode.getCoinsByPuzzleHashes(keychain.puzzlehashes); + + final feeSpendBundle = standardWalletService.createFeeSpendBundle( + fee: fee, + standardCoins: selectCoinsForAmount(unspentCoins, fee), + keychain: keychain, + changePuzzlehash: requestorPuzzlehash, ); - final validityTimeMinutes = validityTime ~/ 60; + final totalClawbackSpendBundle = clawbackSpendBundle + feeSpendBundle; - print('\nOnce your counter party has paid the lightning invoice you may safely exit the'); - print('program. The exchange complete.'); + await writeToLogFile( + logFile, + 'Clawback Spend Bundle', + totalClawbackSpendBundle.toJson().toString(), + ); + + final validityTimeMinutes = exchangeValidityTime ~/ 60; + + print( + '\nOnce your counter party has paid the lightning invoice you may safely exit the', + ); + print('program. The exchange is complete.'); - print('\nIf your counter party does not pay the lightning invoice, you may claw back'); + print( + '\nIf your counter party does not pay the lightning invoice, you may claw back', + ); print('your XCH after $validityTimeMinutes minutes.'); - await confirmClawback( - clawbackSpendBundle: clawbackSpendBundle, - clawbackDelayMinutes: validityTimeMinutes, - escrowCoins: escrowCoins, - clawbackPuzzlehash: clawbackPuzzlehash, - fullNode: _fullNode, + print( + "\nIf $validityTimeMinutes minutes haven't passed, the spend bundle will be rejected.", + ); + print('Proceed? Y/N'); + + var confirmation = ''; + while (!confirmation.startsWith('y')) { + stdout.write('> '); + confirmation = stdin.readLineSync()!.trim().toLowerCase(); + if (confirmation.toLowerCase().startsWith('y')) { + try { + await fullNode.pushTransaction(totalClawbackSpendBundle); + } catch (e) { + print( + '\nTRANSACTION FAILED. The spend bundle was rejected. If the clawback delay', + ); + print( + "period hasn't passed yet, keep waiting and manually push the transaction", + ); + print( + 'using spend bundle in log file with the following command:', + ); + print('https://docs.chia.net/full-node-rpc/#push_tx'); + print( + 'If it has, your counterparty may have already claimed funds from the escrow address.', + ); + } + } else if (confirmation.startsWith('n')) { + print( + '\nOnce $validityTimeMinutes minutes have passed, you may reclaim the XCH either by responding', + ); + print( + "with 'Y' here or by manually pushing the spend bundle using the spend bundle found in", + ); + print('the log file.'); + await Future.delayed(const Duration(seconds: 2)); + print( + '\nHave $validityTimeMinutes minutes passed? If so, push spend bundle to claw back funds?', + ); + } else { + print('\nNot a valid choice.'); + } + } + + await waitForTransactionToComplete( + coinBeingSpentId: escrowCoins.first.id, + startMessage: 'Clawing back XCH from escrow address...', + waitingMessage: 'Waiting for clawback to complete...', + completionMessage: + 'XCH has been clawed back. Exchange successfully aborted.', ); } -Future generateLogFile( - PrivateKey requestorPrivateKey, - String serializedOfferFile, [ - String? serializedOfferAcceptFile, -]) async { - final logFile = File('exchange-log-${DateTime.now().toString().replaceAll(' ', '-')}.txt') - ..createSync(recursive: true) - ..writeAsStringSync('Offer File:\n$serializedOfferFile', mode: FileMode.append); +Future generateLogFile({ + required String mnemonicSeed, + required PrivateKey requestorPrivateKey, + String? serializedOfferFile, + String? serializedTakerOfferFile, +}) async { + print('\nGenerating log file...'); - if (serializedOfferAcceptFile == null) { - print('\nPrinting serialized offer file and disposable private key to a file...'); - logFile.writeAsStringSync( + final logFile = File( + 'exchange-log-${DateTime.now().toString().replaceAll(' ', '-')}.txt', + ) + ..createSync(recursive: true) + ..writeAsStringSync('Mnemonic Seed:\n$mnemonicSeed', mode: FileMode.append) + ..writeAsStringSync( '\n\nPrivate Key:\n${requestorPrivateKey.toHex()}', mode: FileMode.append, ); - } else { - print('\nPrinting serialized offer file, serialized offer accept file, and'); - print('disposable private key to a file...'); + + if (serializedOfferFile != null && serializedTakerOfferFile != null) { logFile ..writeAsStringSync( - '\n\nOffer Accept File:\n$serializedOfferAcceptFile', + '\n\nOffer File:\n$serializedOfferFile', mode: FileMode.append, ) ..writeAsStringSync( - '\n\nPrivate Key:\n${requestorPrivateKey.toHex()}', + '\n\nTaker Offer File:\n$serializedTakerOfferFile', mode: FileMode.append, ); } + + return logFile; +} + +Future writeToLogFile(File logFile, String label, String content) async { + await logFile.writeAsString('\n\n$label:\n$content', mode: FileMode.append); +} + +Future> waitForUserToSendXch( + Puzzlehash targetPuzzlehash, + int amount, +) async { + print('\nPress any key to continue once you have done so.'); + stdin.readLineSync(); + + var transactionValidated = false; + var coins = []; + + while (coins.totalValue < amount) { + print('Waiting for XCH...'); + await Future.delayed(const Duration(seconds: 10)); + + if (transactionValidated == false) { + transactionValidated = + await isTransactionValidated(targetPuzzlehash, amount); + } + + coins = await fullNode.getCoinsByPuzzleHashes( + [targetPuzzlehash], + ); + } + + print('\nXCH received!'); + + return coins; +} + +Future isTransactionValidated( + Puzzlehash targetPuzzlehash, + int amount, +) async { + final mempoolItemsResponse = await fullNode.getAllMempoolItems(); + final mempoolItems = mempoolItemsResponse.mempoolItemMap.values; + + for (final mempoolItem in mempoolItems) { + for (final addition in mempoolItem.additions) { + if (addition.puzzlehash == targetPuzzlehash && + addition.amount == amount) { + print( + '\nThe transaction has been validated and is now in the mempool.\n', + ); + return true; + } + } + } + return false; +} + +Future isTransactionValidatedFromSpentCoinId(Bytes spentCoinId) async { + final mempoolItemsResponse = await fullNode.getAllMempoolItems(); + final mempoolItems = mempoolItemsResponse.mempoolItemMap.values; + + for (final mempoolItem in mempoolItems) { + for (final coinSpend in mempoolItem.spendBundle.coinSpends) { + if (coinSpend.coin.id == spentCoinId) { + print( + '\nThe transaction has been validated and is now in the mempool.\n', + ); + return true; + } + } + } + return false; +} + +Future waitForTransactionToComplete({ + required Bytes coinBeingSpentId, + required String startMessage, + required String waitingMessage, + required String completionMessage, +}) async { + var transactionValidated = false; + + print('\n$startMessage\n'); + + while (true) { + print(waitingMessage); + await Future.delayed(const Duration(seconds: 10)); + final coinBeingSpent = await fullNode.getCoinById(coinBeingSpentId); + + if (coinBeingSpent == null) continue; + + if (transactionValidated == false) { + transactionValidated = + await isTransactionValidatedFromSpentCoinId(coinBeingSpentId); + } + + if (coinBeingSpent.isSpent) { + print('\n$completionMessage'); + return; + } + } +} + +Future waitForMakerToSpendMessageCoinChild({ + required Bytes messageCoinChildId, + required Bytes initializationCoinId, +}) async { + var transactionValidated = false; + + while (true) { + print('Waiting for maker to accept or decline message coin...'); + await Future.delayed(const Duration(seconds: 10)); + final messageCoinChild = await fullNode.getCoinById(messageCoinChildId); + + if (transactionValidated == false) { + transactionValidated = + await isTransactionValidatedFromSpentCoinId(messageCoinChildId); + } + + if (messageCoinChild!.isSpent) { + final coinSpend = await fullNode.getCoinSpend(messageCoinChild); + final memos = await coinSpend!.memos; + + if (memos.contains(initializationCoinId)) { + print('\nMaker accepted message coin!'); + return; + } else { + print('\nMaker declined message coin. The exchange will not proceed.'); + exit(exitCode); + } + } + } } diff --git a/lib/src/command/exchange/exchange_btc.dart b/lib/src/command/exchange/exchange_btc.dart index 237a90aa..5cfc16a2 100644 --- a/lib/src/command/exchange/exchange_btc.dart +++ b/lib/src/command/exchange/exchange_btc.dart @@ -22,16 +22,22 @@ class Amounts { final int satoshis; } +const mojoCutoff = 10000000; + Future getLogFile() async { // find any log files of previous exchange sessions final currentDirFiles = await Directory.current.list().toList(); final logFileEntities = currentDirFiles - .where((file) => File(file.path).uri.pathSegments.last.startsWith('exchange-log')) + .where( + (file) => + File(file.path).uri.pathSegments.last.startsWith('exchange-log'), + ) .toList(); // if there aren't any, generate a new log file if (logFileEntities.isEmpty) { - final logFilePath = 'exchange-log-${DateTime.now().toString().replaceAll(' ', '-')}.txt'; + final logFilePath = + 'exchange-log-${DateTime.now().toString().replaceAll(' ', '-')}.txt'; File(logFilePath).createSync(recursive: true); return File(logFilePath); } @@ -50,7 +56,8 @@ Future getLogFile() async { stdout.write('> '); final choice = stdin.readLineSync()!.trim(); if (choice == '0') { - final logFilePath = 'exchange-log-${DateTime.now().toString().replaceAll(' ', '-')}.txt'; + final logFilePath = + 'exchange-log-${DateTime.now().toString().replaceAll(' ', '-')}.txt'; File(logFilePath).createSync(recursive: true); return File(logFilePath); } else if (logFiles.asMap().containsKey(int.parse(choice) - 1)) { @@ -77,8 +84,12 @@ Future chooseExchangePath(ChiaFullNodeInterface fullNode) async { await exchangeBtcForXch(fullNode); } } else { - print('\nDo you have XCH that you want to exchange for BTC, or do you have BTC that'); - print('you want to exchange for XCH? Please note that you and your counter party must'); + print( + '\nDo you have XCH that you want to exchange for BTC, or do you have BTC that', + ); + print( + 'you want to exchange for XCH? Please note that you and your counter party must', + ); print('select reciprocal paths.'); print('\n1. Exchange XCH for BTC'); print('2. Exchange BTC for XCH'); @@ -177,9 +188,11 @@ Future exchangeXchForBtc(ChiaFullNodeInterface fullNode) async { if (logList.length > 7) { clawbackPuzzlehash = Puzzlehash.fromHex(logList[7]); } else { - print('\nEnter the address where the XCH will be returned in the event the exchange'); + print( + '\nEnter the address where the XCH will be returned in the event the exchange', + ); print('is aborted or fails.'); - clawbackPuzzlehash = getRequestorPuzzlehash(); + clawbackPuzzlehash = getUserPuzzlehash(); await updateLogFile(clawbackPuzzlehash.toHex()); } @@ -187,7 +200,7 @@ Future exchangeXchForBtc(ChiaFullNodeInterface fullNode) async { var escrowCoins = await fullNode.getCoinsByPuzzleHashes([escrowPuzzlehash]); if (escrowCoins.isEmpty) { print( - '\nTransfer ${(amounts.mojos > 10000000) ? '${amounts.xch.toStringAsFixed(9)} XCH' : '${amounts.mojos} mojos or ${amounts.xch} XCH'} to the following escrow address:', + '\nTransfer ${(amounts.mojos > mojoCutoff) ? '${amounts.xch.toStringAsFixed(9)} XCH' : '${amounts.mojos} mojos or ${amounts.xch} XCH'} to the following escrow address:', ); print(escrowAddress.address); await Future.delayed(const Duration(seconds: 2)); @@ -213,13 +226,19 @@ Future exchangeXchForBtc(ChiaFullNodeInterface fullNode) async { fulfillerPublicKey: btcHolderPublicKey, ); - print('\nWait for your counter party to pay the lightning payment request, then share'); - print('with them the disposable private key below to allow them to claim the XCH:'); + print( + '\nWait for your counter party to pay the lightning payment request, then share', + ); + print( + 'with them the disposable private key below to allow them to claim the XCH:', + ); print(xchHolderPrivateKey.toHex()); await Future.delayed(const Duration(seconds: 2)); print('\nPress any key to continue.'); stdin.readLineSync(); - print('If the payment request is paid and you have shared your private key, you may'); + print( + 'If the payment request is paid and you have shared your private key, you may', + ); print('safely exit the program. The exchange is complete.'); await Future.delayed(const Duration(seconds: 2)); print( @@ -227,13 +246,19 @@ Future exchangeXchForBtc(ChiaFullNodeInterface fullNode) async { ); print('you may claw back the XCH to your address.'); await Future.delayed(const Duration(seconds: 2)); - print('\nAlternatively, if both parties agree to abort the exchange, you may receive'); - print('the XCH back sooner if your counter party provides their private key.'); + print( + '\nAlternatively, if both parties agree to abort the exchange, you may receive', + ); + print( + 'the XCH back sooner if your counter party provides their private key.', + ); await Future.delayed(const Duration(seconds: 2)); print('\nSelect an option below.'); print('1. The lightning payment request has been paid. Quit program.'); print('2. $clawbackDelayMinutes minutes have passed. Claw back funds.'); - print('3. Exchange has been aborted or failed. Use counter party private key to'); + print( + '3. Exchange has been aborted or failed. Use counter party private key to', + ); print('receive funds back early.'); // determine how to conclude exchange based on user input @@ -260,7 +285,9 @@ Future exchangeXchForBtc(ChiaFullNodeInterface fullNode) async { fullNode: fullNode, ); } else if (choice == '3') { - print("\nIf you haven't already received it, ask your counter party to share their"); + print( + "\nIf you haven't already received it, ask your counter party to share their", + ); print('private key and paste it below.'); var input = ''; @@ -272,7 +299,8 @@ Future exchangeXchForBtc(ChiaFullNodeInterface fullNode) async { if (privateKeyInput.getG1() == btcHolderPublicKey) { btcHolderPrivateKey = privateKeyInput; - clawbackSpendBundleWithPk = xchToBtcService.createClawbackSpendBundleWithPk( + clawbackSpendBundleWithPk = + xchToBtcService.createClawbackSpendBundleWithPk( payments: [Payment(escrowCoins.totalValue, clawbackPuzzlehash)], coinsInput: escrowCoins, requestorPrivateKey: xchHolderPrivateKey, @@ -282,7 +310,9 @@ Future exchangeXchForBtc(ChiaFullNodeInterface fullNode) async { ); } } catch (e) { - print("\nCouldn't verify input as private key. Please try again or enter '2' to"); + print( + "\nCouldn't verify input as private key. Please try again or enter '2' to", + ); print( 'instead claw back funds without private key after $clawbackDelayMinutes minutes have passed.', ); @@ -359,7 +389,9 @@ Future exchangeBtcForXch(ChiaFullNodeInterface fullNode) async { ); print('a timeout of $clawbackDelayMinutes minutes.'); await Future.delayed(const Duration(seconds: 2)); - print('\nPaste the lightning payment request from your counter party here:'); + print( + '\nPaste the lightning payment request from your counter party here:', + ); sweepPaymentHash = await getPaymentHash(); } @@ -384,7 +416,7 @@ Future exchangeBtcForXch(ChiaFullNodeInterface fullNode) async { sweepPuzzlehash = Puzzlehash.fromHex(logList[7]); } else { print('\nEnter the address where you would like the XCH delivered.'); - sweepPuzzlehash = getRequestorPuzzlehash(); + sweepPuzzlehash = getUserPuzzlehash(); await updateLogFile(sweepPuzzlehash.toHex()); } @@ -392,11 +424,15 @@ Future exchangeBtcForXch(ChiaFullNodeInterface fullNode) async { var escrowCoins = await fullNode.getCoinsByPuzzleHashes([escrowPuzzlehash]); if (escrowCoins.isEmpty) { print( - '\nYour counter party should be sending ${(amounts.mojos > 10000000) ? '${amounts.xch.toStringAsFixed(9)} XCH' : '${amounts.mojos} mojos or ${amounts.xch} XCH'} to an escrow', + '\nYour counter party should be sending ${(amounts.mojos > mojoCutoff) ? '${amounts.xch.toStringAsFixed(9)} XCH' : '${amounts.mojos} mojos or ${amounts.xch} XCH'} to an escrow', + ); + print( + 'address, where it will be temporarily held for you until the next step.', ); - print('address, where it will be temporarily held for you until the next step.'); await Future.delayed(const Duration(seconds: 1)); - print('\nPress any key to continue once your counter party lets you know that they have'); + print( + '\nPress any key to continue once your counter party lets you know that they have', + ); print('sent the XCH.'); stdin.readLineSync(); @@ -410,27 +446,47 @@ Future exchangeBtcForXch(ChiaFullNodeInterface fullNode) async { print('\nXCH from your counter party has arrived at the escrow address!'); } - print('\nYou can verify this here: https://xchscan.com/address/${escrowAddress.address}'); - print('\nPay the lightning payment request after the payment has received sufficient'); + print( + '\nYou can verify this here: https://xchscan.com/address/${escrowAddress.address}', + ); + print( + '\nPay the lightning payment request after the payment has received sufficient', + ); print('confirmations.'); await Future.delayed(const Duration(seconds: 2)); print( '\nYou must pay and complete this exchange within $clawbackDelayMinutes minutes, or else the XCH will', ); - print('be returned to your counter party. If you wish to abort the exchange, do not'); + print( + 'be returned to your counter party. If you wish to abort the exchange, do not', + ); print('pay the lightning payment request.'); await Future.delayed(const Duration(seconds: 2)); - print("\nTo claim funds, you will use either your counter party's private key or the"); - print('preimage that is revealed after payment of the lightning payment request.'); - print('If you have not already received it, ask your counter party to share their'); + print( + "\nTo claim funds, you will use either your counter party's private key or the", + ); + print( + 'preimage that is revealed after payment of the lightning payment request.', + ); + print( + 'If you have not already received it, ask your counter party to share their', + ); print('disposable private key.'); await Future.delayed(const Duration(seconds: 2)); - print('\nIf your counter party is nonresponsive, find your lightning payment request'); - print('preimage by navigating to transaction history in your lightning wallet,'); + print( + '\nIf your counter party is nonresponsive, find your lightning payment request', + ); + print( + 'preimage by navigating to transaction history in your lightning wallet,', + ); print('clicking on the transaction, and viewing the payment details.'); await Future.delayed(const Duration(seconds: 2)); - print("\nPlease paste either your counter party's private key OR your preimage below."); - print("If you instead want to abort the exchange, enter 'q' for instructions on how"); + print( + "\nPlease paste either your counter party's private key OR your preimage below.", + ); + print( + "If you instead want to abort the exchange, enter 'q' for instructions on how", + ); print('on how to cleanly abort with your private key and then quit.'); PrivateKey? xchHolderPrivateKey; @@ -439,7 +495,9 @@ Future exchangeBtcForXch(ChiaFullNodeInterface fullNode) async { var input = ''; // determine how to conclude exchange based on user input - while (xchHolderPrivateKey == null && sweepPreimage == null && !input.startsWith('q')) { + while (xchHolderPrivateKey == null && + sweepPreimage == null && + !input.startsWith('q')) { stdout.write('> '); input = stdin.readLineSync()!.trim().toLowerCase(); @@ -470,8 +528,12 @@ Future exchangeBtcForXch(ChiaFullNodeInterface fullNode) async { fulfillerPublicKey: xchHolderPublicKey, ); } else { - print("\nCouldn't verify input as either private key or preimage. Please try again."); - print("If you tried inputting the your counter party's private key, try using"); + print( + "\nCouldn't verify input as either private key or preimage. Please try again.", + ); + print( + "If you tried inputting the your counter party's private key, try using", + ); print('your preimage instead.'); } } catch (e) { @@ -480,7 +542,9 @@ Future exchangeBtcForXch(ChiaFullNodeInterface fullNode) async { } if (input.startsWith('q')) { - print('\nPlease share your disposable private key below with your counter party to'); + print( + '\nPlease share your disposable private key below with your counter party to', + ); print('allow them to cleanly reclaim their XCH from the escrow address:'); print(btcHolderPrivateKey.toHex()); await Future.delayed(const Duration(seconds: 2)); @@ -495,7 +559,9 @@ Future exchangeBtcForXch(ChiaFullNodeInterface fullNode) async { await fullNode.pushTransaction(sweepSpendBundle); await verifyTransaction(escrowCoins, sweepPuzzlehash, fullNode); } catch (e) { - print('\nTRANSACTION FAILED. The spend bundle was rejected. You may have responded'); + print( + '\nTRANSACTION FAILED. The spend bundle was rejected. You may have responded', + ); print('after the agreed upon expiration time.'); } } @@ -511,26 +577,33 @@ Future updateLogFile(String input) async { Future generateRequestorDisposableKeys() async { // generate disposable private key and create signed public key for user final requestorPrivateKey = PrivateKey.generate(); - final requestorPublicKey = exchangeService.createSignedPublicKey(requestorPrivateKey); + final requestorPublicKey = + exchangeService.createSignedPublicKey(requestorPrivateKey); await updateLogFile(requestorPrivateKey.toHex()); - print('\nSend the following line with your signed public key to your counter party.'); + print( + '\nSend the following line with your signed public key to your counter party.', + ); print(requestorPublicKey); await Future.delayed(const Duration(seconds: 2)); return requestorPrivateKey; } -Future getFulfillerPublicKey(PrivateKey requestorPrivateKey) async { +Future getFulfillerPublicKey( + PrivateKey requestorPrivateKey, +) async { // get and validate counter party public key as pasted by user print("\nPaste your counter party's signed public key below."); while (true) { stdout.write('> '); try { - final fulfillerPublicKey = - exchangeService.parseSignedPublicKey(stdin.readLineSync()!.trim().toLowerCase()); + final fulfillerPublicKey = exchangeService + .parseSignedPublicKey(stdin.readLineSync()!.trim().toLowerCase()); if (fulfillerPublicKey == requestorPrivateKey.getG1()) { - print("\nThat's your signed public key. Ask your counter party for theirs."); + print( + "\nThat's your signed public key. Ask your counter party for theirs.", + ); } else { await updateLogFile(fulfillerPublicKey.toHex()); return fulfillerPublicKey; @@ -554,11 +627,15 @@ Future getAmounts() async { print('\nThese are the current prices of XCH and BTC:'); print('1 XCH = $btcPerXch BTC or ${usdPerXch.toStringAsFixed(2)} USD'); - print('1 BTC = ${xchPerBtc.toStringAsFixed(8)} XCH or ${usdPerBtc.toStringAsFixed(2)} USD'); + print( + '1 BTC = ${xchPerBtc.toStringAsFixed(8)} XCH or ${usdPerBtc.toStringAsFixed(2)} USD', + ); await Future.delayed(const Duration(seconds: 1)); // get amount being exchanged in terms of XCH or mojos, then calculate amount in other denomination - print('\nIndicate whether you want to input the amount to exchange in XCH or mojos:'); + print( + '\nIndicate whether you want to input the amount to exchange in XCH or mojos:', + ); print('1. XCH'); print('2. mojos'); @@ -576,7 +653,9 @@ Future getAmounts() async { } if (choice == '1') { - print('\nHow much XCH is being exchanged? Please note that if you and your counter'); + print( + '\nHow much XCH is being exchanged? Please note that if you and your counter', + ); print('party input different amounts, the exchange will fail.'); while (xchAmount == null || xchAmount == 0) { stdout.write('> '); @@ -589,7 +668,9 @@ Future getAmounts() async { } } } else if (choice == '2') { - print('\nHow many mojos are being exchanged? Please note that if you and your counter'); + print( + '\nHow many mojos are being exchanged? Please note that if you and your counter', + ); print('party input different amounts, the exchange will fail.'); while (xchAmountMojos == null || xchAmountMojos == 0) { stdout.write('> '); @@ -609,7 +690,9 @@ Future getAmounts() async { var btcAmountSatoshis = (btcAmount * 1e8).toInt(); if (btcAmountSatoshis == 0) btcAmountSatoshis = 1; - await updateLogFile('$xchAmount,$btcAmount,$xchAmountMojos,$btcAmountSatoshis'); + await updateLogFile( + '$xchAmount,$btcAmount,$xchAmountMojos,$btcAmountSatoshis', + ); final amounts = Amounts( xch: xchAmount, @@ -623,12 +706,20 @@ Future getAmounts() async { Future getClawbackDelay() async { // get clawback delay from user - print('\nYou and your counter party must agree on how much time you want to allow for'); - print('the exchange before it expires. It should be at least 10 minutes. Please note'); - print('that if you and your counter party input different expiration times, the'); + print( + '\nYou and your counter party must agree on how much time you want to allow for', + ); + print( + 'the exchange before it expires. It should be at least 10 minutes. Please note', + ); + print( + 'that if you and your counter party input different expiration times, the', + ); print('exchange will fail.'); await Future.delayed(const Duration(seconds: 2)); - print('\nIndicate your chosen expiration time in minutes or hit enter to default to 60.'); + print( + '\nIndicate your chosen expiration time in minutes or hit enter to default to 60.', + ); while (true) { stdout.write('> '); final input = stdin.readLineSync()!.trim(); @@ -655,17 +746,20 @@ Future getPaymentHash() async { stdout.write('> '); try { final paymentRequest = stdin.readLineSync()!.trim().toLowerCase(); - final decodedPaymentRequest = decodeLightningPaymentRequest(paymentRequest); + final decodedPaymentRequest = + decodeLightningPaymentRequest(paymentRequest); final sweepPaymentHash = decodedPaymentRequest.tags.paymentHash; await updateLogFile(sweepPaymentHash!.toHex()); return sweepPaymentHash; } catch (e) { - print("\nCouldn't validate the lightning payment request. Please try again:"); + print( + "\nCouldn't validate the lightning payment request. Please try again:", + ); } } } -Puzzlehash getRequestorPuzzlehash() { +Puzzlehash getUserPuzzlehash() { // get puzzlehash where user would like to receive XCH at while (true) { stdout.write('> '); @@ -683,11 +777,16 @@ Future generateSpendBundleFile(SpendBundle spendBundle) async { // generate json of spend bundle so user can manually push it if program fails await Future.delayed(const Duration(seconds: 2)); print('\nGenerating file with spend bundle JSON in the current directory...'); - final spendBundleHexFile = File('spend-bundle-hex.txt').openWrite()..write(spendBundle.toJson()); + final spendBundleHexFile = File('spend-bundle-hex.txt').openWrite() + ..write(spendBundle.toJson()); await spendBundleHexFile.flush(); await spendBundleHexFile.close(); - print('This is a last resort for you to use ONLY IF the program closes prematurely'); - print('or if you need to reattempt pushing the spend bundle. In this case, you can'); + print( + 'This is a last resort for you to use ONLY IF the program closes prematurely', + ); + print( + 'or if you need to reattempt pushing the spend bundle. In this case, you can', + ); print('use a command in the same format as shown here:'); print('https://docs.chia.net/full-node-rpc/#push_tx'); } @@ -701,7 +800,9 @@ Future confirmClawback({ }) async { // push clawback spend bundle after receiving confirmation from user - print("\nIf $clawbackDelayMinutes minutes haven't passed, the spend bundle will be rejected."); + print( + "\nIf $clawbackDelayMinutes minutes haven't passed, the spend bundle will be rejected.", + ); print('Proceed? Y/N'); var confirmation = ''; @@ -716,9 +817,15 @@ Future confirmClawback({ await fullNode.pushTransaction(clawbackSpendBundle); await verifyTransaction(escrowCoins, clawbackPuzzlehash, fullNode); } catch (e) { - print('\nTRANSACTION FAILED. The spend bundle was rejected. If the clawback delay'); - print("period hasn't passed yet, keep waiting and manually push the transaction"); - print('using the generated file. If it has, your counter party may have already'); + print( + '\nTRANSACTION FAILED. The spend bundle was rejected. If the clawback delay', + ); + print( + "period hasn't passed yet, keep waiting and manually push the transaction", + ); + print( + 'using the generated file. If it has, your counter party may have already', + ); print('claimed funds from the escrow address.'); } } else if (confirmation.startsWith('n')) { @@ -761,11 +868,14 @@ Future> verifyTransferToEscrowPuzzlehash({ if (transactionValidated == false) { final mempoolItemsResponse = await fullNode.getAllMempoolItems(); mempoolItemsResponse.mempoolItemMap.forEach((key, item) { - additionPuzzlehashes.addAll(item.additions.map((addition) => addition.puzzlehash)); + additionPuzzlehashes + .addAll(item.additions.map((addition) => addition.puzzlehash)); }); if (additionPuzzlehashes.contains(escrowPuzzlehash)) { - print('\nThe transaction has been validated and is now in the mempool.\n'); + print( + '\nThe transaction has been validated and is now in the mempool.\n', + ); transactionValidated = true; } @@ -776,28 +886,46 @@ Future> verifyTransferToEscrowPuzzlehash({ if (btcHolderPrivateKey != null) { // if BTC holder is still waiting, something might have gone wrong with transaction // give information to the user to allow them to cleanly abort the exchange - print('\nStill waiting for a transaction sending XCH to the escrow address.'); - print('Ask your countery party whether their transaction is validated or complete'); + print( + '\nStill waiting for a transaction sending XCH to the escrow address.', + ); + print( + 'Ask your countery party whether their transaction is validated or complete', + ); print("If it isn't, press any key to continue waiting."); await Future.delayed(const Duration(seconds: 2)); - print('\nIf the transaction looks complete on their end, something might have gone'); - print("wrong. It's possible that one of the two parties inputted an incorrect value"); - print("or that your selected amounts to exchange or expiration times didn't match."); + print( + '\nIf the transaction looks complete on their end, something might have gone', + ); + print( + "wrong. It's possible that one of the two parties inputted an incorrect value", + ); + print( + "or that your selected amounts to exchange or expiration times didn't match.", + ); await Future.delayed(const Duration(seconds: 2)); - print('\nIf this might be the case, please share your disposable private key below with'); - print('your counter party to abort the exchange and allow them to cleanly reclaim'); + print( + '\nIf this might be the case, please share your disposable private key below with', + ); + print( + 'your counter party to abort the exchange and allow them to cleanly reclaim', + ); print('their XCH from the escrow address:'); print(btcHolderPrivateKey.toHex()); await Future.delayed(const Duration(seconds: 1)); - print('\nPress any key to keep waiting or exit the program using Ctrl+C and reattempt'); + print( + '\nPress any key to keep waiting or exit the program using Ctrl+C and reattempt', + ); print('the exchange by running the command again.'); stdin.readLineSync(); } else { // if XCH holder is still waiting, they might not have sent the correct amount to the // correct address - print('\nStill waiting for a transaction sending XCH to the escrow address to be'); print( - 'validated. Please double check that you sent ${(amounts.mojos > 10000000) ? '${amounts.xch.toStringAsFixed(9)} XCH' : '${amounts.mojos} mojos or ${amounts.xch} XCH'} to the', + '\nStill waiting for a transaction sending XCH to the escrow address to be', + ); + print( + 'validated. Please double check that you sent ${(amounts.mojos > mojoCutoff) ? '${amounts.xch.toStringAsFixed(9)} XCH' : '${amounts.mojos} mojos or ${amounts.xch} XCH'} to the', ); print('following address:'); print(escrowPuzzlehash.toAddressWithContext().address); @@ -852,7 +980,8 @@ Future verifyTransaction( [requestorPuzzlehash], ); - recipientParentIds = recipientCoins.map((coin) => coin.parentCoinInfo).toList(); + recipientParentIds = + recipientCoins.map((coin) => coin.parentCoinInfo).toList(); } print('\nSuccess! The transaction is complete.'); diff --git a/lib/src/command/plot_nft/create_new_wallet_with_plotnft.dart b/lib/src/command/plot_nft/create_new_wallet_with_plotnft.dart index 813f8e91..1754c500 100644 --- a/lib/src/command/plot_nft/create_new_wallet_with_plotnft.dart +++ b/lib/src/command/plot_nft/create_new_wallet_with_plotnft.dart @@ -1,5 +1,7 @@ import 'package:chia_crypto_utils/chia_crypto_utils.dart'; +final plotNftWalletService = PlotNftWalletService(); + class PlotNFTDetails { const PlotNFTDetails({ required this.contractAddress, @@ -10,14 +12,18 @@ class PlotNFTDetails { final Address contractAddress; final Address payoutAddress; final Bytes launcherId; + + @override + String toString() => + 'PlotNFTDetails(contractAddress: $contractAddress, payoutAddress: $payoutAddress, launcherId: $launcherId)'; } -Future createNewWalletWithPlotNFT( - KeychainCoreSecret keychainSecret, - WalletKeychain keychain, - PoolService poolService, - ChiaFullNodeInterface fullNode, -) async { +Future createNewWalletWithPlotNFT({ + required KeychainCoreSecret keychainSecret, + required WalletKeychain keychain, + required ChiaFullNodeInterface fullNode, + PoolService? poolService, +}) async { final coins = await fullNode.getCoinsByPuzzleHashes( keychain.puzzlehashes, ); @@ -26,14 +32,44 @@ Future createNewWalletWithPlotNFT( final singletonWalletVector = keychain.getNextSingletonWalletVector(keychainSecret.masterPrivateKey); - final launcherId = await poolService.createPlotNftForPool( - p2SingletonDelayedPuzzlehash: delayPh, - singletonWalletVector: singletonWalletVector, - coins: coins, - keychain: keychain, - fee: 50, - changePuzzlehash: keychain.puzzlehashes[3], - ); + final changePuzzlehash = keychain.puzzlehashes[3]; + + final payoutPuzzlehash = keychain.puzzlehashes[1]; + + Bytes? launcherId; + if (poolService != null) { + launcherId = await poolService.createPlotNftForPool( + p2SingletonDelayedPuzzlehash: delayPh, + singletonWalletVector: singletonWalletVector, + coins: coins, + keychain: keychain, + fee: 50, + changePuzzlehash: changePuzzlehash, + ); + } else { + final initialTargetState = PoolState( + poolSingletonState: PoolSingletonState.selfPooling, + targetPuzzlehash: payoutPuzzlehash, + ownerPublicKey: singletonWalletVector.singletonOwnerPublicKey, + relativeLockHeight: 0, + ); + + final genesisCoin = coins[0]; + + final plotNftSpendBundle = plotNftWalletService.createPoolNftSpendBundle( + initialTargetState: initialTargetState, + keychain: keychain, + fee: 50, + coins: coins, + genesisCoinId: genesisCoin.id, + p2SingletonDelayedPuzzlehash: delayPh, + changePuzzlehash: changePuzzlehash, + ); + + await fullNode.pushTransaction(plotNftSpendBundle); + + launcherId = PlotNftWalletService.makeLauncherCoin(genesisCoin.id).id; + } var launcherCoin = await fullNode.getCoinById(launcherId); @@ -46,57 +82,52 @@ Future createNewWalletWithPlotNFT( final newPlotNft = await fullNode.getPlotNftByLauncherId(launcherId); print(newPlotNft); - final contractPuzzlehash = PlotNftWalletService.launcherIdToP2Puzzlehash( - launcherId, - PlotNftWalletService.defaultDelayTime, - delayPh, - ); - - final payoutPuzzlehash = keychain.puzzlehashes[1]; - final payoutAddress = Address.fromPuzzlehash( payoutPuzzlehash, ChiaNetworkContextWrapper().blockchainNetwork.addressPrefix, ); final contractAddress = Address.fromPuzzlehash( - contractPuzzlehash, + newPlotNft!.contractPuzzlehash, ChiaNetworkContextWrapper().blockchainNetwork.addressPrefix, ); print('Contract Address: ${contractAddress.address}'); print('Payout Address: ${payoutAddress.address}'); - final addFarmerResponse = await poolService.registerAsFarmerWithPool( - plotNft: newPlotNft!, - singletonWalletVector: singletonWalletVector, - payoutPuzzlehash: keychain.puzzlehashes[1], - ); - print('Pool welcome message: ${addFarmerResponse.welcomeMessage}'); - - GetFarmerResponse? farmerInfo; - var attempts = 0; - while (farmerInfo == null && attempts < 6) { - print('waiting for farmer information to become available...'); - try { - attempts = attempts + 1; - await Future.delayed(const Duration(seconds: 15)); - farmerInfo = await poolService.getFarmerInfo( - authenticationPrivateKey: singletonWalletVector.poolingAuthenticationPrivateKey, - launcherId: launcherId, - ); - } on PoolResponseException catch (e) { - if (e.poolErrorResponse.responseCode != PoolErrorState.farmerNotKnown) { - rethrow; - } - if (attempts == 5) { - print(e.poolErrorResponse.message); + if (poolService != null) { + final addFarmerResponse = await poolService.registerAsFarmerWithPool( + plotNft: newPlotNft, + singletonWalletVector: singletonWalletVector, + payoutPuzzlehash: payoutPuzzlehash, + ); + print('Pool welcome message: ${addFarmerResponse.welcomeMessage}'); + + GetFarmerResponse? farmerInfo; + var attempts = 0; + while (farmerInfo == null && attempts < 6) { + print('waiting for farmer information to become available...'); + try { + attempts = attempts + 1; + await Future.delayed(const Duration(seconds: 15)); + farmerInfo = await poolService.getFarmerInfo( + authenticationPrivateKey: + singletonWalletVector.poolingAuthenticationPrivateKey, + launcherId: launcherId, + ); + } on PoolResponseException catch (e) { + if (e.poolErrorResponse.responseCode != PoolErrorState.farmerNotKnown) { + rethrow; + } + if (attempts == 5) { + print(e.poolErrorResponse.message); + } } } - } - if (farmerInfo != null) { - print(farmerInfo); + if (farmerInfo != null) { + print(farmerInfo); + } } return PlotNFTDetails( diff --git a/lib/src/command/plot_nft/get_coins_for_command.dart b/lib/src/command/plot_nft/get_coins_for_command.dart new file mode 100644 index 00000000..8edb7b29 --- /dev/null +++ b/lib/src/command/plot_nft/get_coins_for_command.dart @@ -0,0 +1,60 @@ +import 'dart:io'; + +import 'package:chia_crypto_utils/chia_crypto_utils.dart'; + +Future> getCoinsForCommand({ + required String faucetRequestURL, + required String faucetRequestPayload, + required List puzzlehashes, + required ChiaFullNodeInterface fullNode, + required String message, +}) async { + final coinAddress = Address.fromPuzzlehash( + puzzlehashes.first, + ChiaNetworkContextWrapper().blockchainNetwork.addressPrefix, + ); + + if (faucetRequestURL.isNotEmpty && faucetRequestPayload.isNotEmpty) { + final theFaucetRequestPayload = faucetRequestPayload.replaceAll( + RegExp('SEND_TO_ADDRESS'), + coinAddress.address, + ); + + final result = await Process.run('curl', [ + '-s', + '-d', + theFaucetRequestPayload, + '-H', + 'Content-Type: application/json', + '-X', + 'POST', + faucetRequestURL, + ]); + + stdout.write(result.stdout); + stderr.write(result.stderr); + } else { + print( + '$message: ${coinAddress.address}\n', + ); + print('Press any key when coin has been sent'); + stdin.readLineSync(); + } + + var coins = []; + do { + coins = await fullNode.getCoinsByPuzzleHashes( + puzzlehashes, + ); + if (coins.isEmpty) { + print('waiting for coins'); + await Future.delayed(const Duration(seconds: 3)); + } + } while (coins.isEmpty); + + if (coins.isNotEmpty) { + print(coins); + } + + return coins; +} diff --git a/lib/src/command/plot_nft/get_farming_status.dart b/lib/src/command/plot_nft/get_farming_status.dart index d746d6a7..bb35c33a 100644 --- a/lib/src/command/plot_nft/get_farming_status.dart +++ b/lib/src/command/plot_nft/get_farming_status.dart @@ -13,7 +13,8 @@ Future getFarmingStatus( keychainSecret.masterPrivateKey, ); final farmerInfo = await poolService.getFarmerInfo( - authenticationPrivateKey: singletonWalletVector.poolingAuthenticationPrivateKey, + authenticationPrivateKey: + singletonWalletVector.poolingAuthenticationPrivateKey, launcherId: plotNft.launcherId, ); diff --git a/lib/src/command/standard/create_cold_wallet.dart b/lib/src/command/standard/create_cold_wallet.dart index 1e02444c..38206d7d 100644 --- a/lib/src/command/standard/create_cold_wallet.dart +++ b/lib/src/command/standard/create_cold_wallet.dart @@ -9,7 +9,8 @@ Future createColdWallet() async { final fingerprint = keychainSecret.masterPublicKey.getFingerprint(); final masterPublicKeyHex = keychainSecret.masterPublicKey.toHex(); - final farmerPublicKeyHex = masterSkToFarmerSk(masterPrivateKey).getG1().toHex(); + final farmerPublicKeyHex = + masterSkToFarmerSk(masterPrivateKey).getG1().toHex(); final poolPublicKeyHex = masterSkToPoolSk(masterPrivateKey).getG1().toHex(); print('Fingerprint: $fingerprint'); @@ -28,7 +29,8 @@ Future createColdWallet() async { final set = WalletSet.fromPrivateKey(keychainSecret.masterPrivateKey, i); walletSet.add(set); - final address = Address.fromPuzzlehash(set.hardened.puzzlehash, 'xch').address; + final address = + Address.fromPuzzlehash(set.hardened.puzzlehash, 'xch').address; print(' $address'); } } diff --git a/lib/src/context/full_node_context.dart b/lib/src/context/full_node_context.dart index c59eadd2..edf59fc0 100644 --- a/lib/src/context/full_node_context.dart +++ b/lib/src/context/full_node_context.dart @@ -5,7 +5,8 @@ import 'package:get_it/get_it.dart'; class FullNodeContext { GetIt get getIt => GetIt.I; static const urlInstanceName = 'FullNodeContext.url'; - static const certificateBytesInstanceName = 'FullNodeContext.certificateBytes'; + static const certificateBytesInstanceName = + 'FullNodeContext.certificateBytes'; static const keyBytesInstanceName = 'FullNodeContext.keyBytes'; String get url { @@ -22,7 +23,9 @@ class FullNodeContext { } Bytes? get certificateBytes { - if (!getIt.isRegistered(instanceName: certificateBytesInstanceName)) { + if (!getIt.isRegistered( + instanceName: certificateBytesInstanceName, + )) { return null; } return getIt.get(instanceName: certificateBytesInstanceName); @@ -30,7 +33,10 @@ class FullNodeContext { void setCertificateBytes(Bytes certificateBytes) { getIt - ..registerSingleton(certificateBytes, instanceName: certificateBytesInstanceName) + ..registerSingleton( + certificateBytes, + instanceName: certificateBytesInstanceName, + ) ..allowReassignment = true; } diff --git a/lib/src/context/logging_context.dart b/lib/src/context/logging_context.dart index c7dd722a..4f1a97fc 100644 --- a/lib/src/context/logging_context.dart +++ b/lib/src/context/logging_context.dart @@ -3,7 +3,8 @@ import 'package:get_it/get_it.dart'; class LoggingContext { GetIt get getIt => GetIt.I; - static const includencludeTimestampInstanceName = 'logging_context_include_timestamp'; + static const includencludeTimestampInstanceName = + 'logging_context_include_timestamp'; void setLogger(LoggingFunction logger) { getIt @@ -25,17 +26,21 @@ class LoggingContext { }) { final currentLogTypes = logTypes; final newLogTypes = {}; - if ((info != null && info) || (info == null && currentLogTypes.contains(LogType.info))) { + if ((info != null && info) || + (info == null && currentLogTypes.contains(LogType.info))) { newLogTypes.add(LogType.info); } - if ((error != null && error) || (error == null && currentLogTypes.contains(LogType.error))) { + if ((error != null && error) || + (error == null && currentLogTypes.contains(LogType.error))) { newLogTypes.add(LogType.error); } - if ((api != null && api) || (api == null && currentLogTypes.contains(LogType.api))) { + if ((api != null && api) || + (api == null && currentLogTypes.contains(LogType.api))) { newLogTypes.add(LogType.api); } - if ((debug != null && debug) || (debug == null && currentLogTypes.contains(LogType.debug))) { + if ((debug != null && debug) || + (debug == null && currentLogTypes.contains(LogType.debug))) { newLogTypes.add(LogType.debug); } @@ -168,7 +173,9 @@ class LoggingContext { } bool get includeTimestamp { - if (!getIt.isRegistered(instanceName: includencludeTimestampInstanceName)) { + if (!getIt.isRegistered( + instanceName: includencludeTimestampInstanceName, + )) { return defaultIncludeTimestamp; } return getIt.get(instanceName: includencludeTimestampInstanceName); diff --git a/lib/src/context/pool_context.dart b/lib/src/context/pool_context.dart index d870266f..87de9eea 100644 --- a/lib/src/context/pool_context.dart +++ b/lib/src/context/pool_context.dart @@ -20,7 +20,9 @@ class PoolContext { } Bytes? get certificateBytes { - if (!getIt.isRegistered(instanceName: certificateBytesInstanceName)) { + if (!getIt.isRegistered( + instanceName: certificateBytesInstanceName, + )) { return null; } return getIt.get(instanceName: certificateBytesInstanceName); @@ -28,7 +30,10 @@ class PoolContext { void setCertificateBytes(Bytes certificateBytes) { getIt - ..registerSingleton(certificateBytes, instanceName: certificateBytesInstanceName) + ..registerSingleton( + certificateBytes, + instanceName: certificateBytesInstanceName, + ) ..allowReassignment = true; } } diff --git a/lib/src/core/constants.dart b/lib/src/core/constants.dart index 5ea380e7..27aae937 100644 --- a/lib/src/core/constants.dart +++ b/lib/src/core/constants.dart @@ -1,4 +1,5 @@ import 'package:chia_crypto_utils/chia_crypto_utils.dart'; -final burnPuzzlehash = - Puzzlehash.fromHex('0x000000000000000000000000000000000000000000000000000000000000dead'); +final burnPuzzlehash = Puzzlehash.fromHex( + '0x000000000000000000000000000000000000000000000000000000000000dead', +); diff --git a/lib/src/core/models/additions_and_removals.dart b/lib/src/core/models/additions_and_removals.dart index fd6a3eb3..dbc04d39 100644 --- a/lib/src/core/models/additions_and_removals.dart +++ b/lib/src/core/models/additions_and_removals.dart @@ -2,8 +2,8 @@ import 'package:chia_crypto_utils/chia_crypto_utils.dart'; class AdditionsAndRemovals { AdditionsAndRemovals({ - required this.additions, - required this.removals, + required this.additions, + required this.removals, }); final List additions; diff --git a/lib/src/core/models/address/btc_address.dart b/lib/src/core/models/address/btc_address.dart index b4f82120..4b110fc0 100644 --- a/lib/src/core/models/address/btc_address.dart +++ b/lib/src/core/models/address/btc_address.dart @@ -7,7 +7,8 @@ class BtcAddress extends Equatable implements CryptoAddress { const BtcAddress(this.address); static BtcAddress? tryParse(String address) { - if (_parseBipAddress(address) != null || _parseSegwitAddress(address) != null) { + if (_parseBipAddress(address) != null || + _parseSegwitAddress(address) != null) { return BtcAddress(address); } return null; diff --git a/lib/src/core/models/block_record.dart b/lib/src/core/models/block_record.dart index 1ea804f1..0a7eec91 100644 --- a/lib/src/core/models/block_record.dart +++ b/lib/src/core/models/block_record.dart @@ -1,7 +1,11 @@ import 'package:chia_crypto_utils/chia_crypto_utils.dart'; class BlockRecord { - BlockRecord({required this.headerHash, required this.height, required this.timestamp}); + BlockRecord({ + required this.headerHash, + required this.height, + required this.timestamp, + }); factory BlockRecord.fromJson(Map json) { return BlockRecord( headerHash: Bytes.fromHex(json['header_hash'] as String), @@ -14,6 +18,7 @@ class BlockRecord { int height; int? timestamp; - DateTime? get dateTime => - (timestamp != null) ? DateTime.fromMillisecondsSinceEpoch(timestamp! * 1000) : null; + DateTime? get dateTime => (timestamp != null) + ? DateTime.fromMillisecondsSinceEpoch(timestamp! * 1000) + : null; } diff --git a/lib/src/core/models/blockchain_state.dart b/lib/src/core/models/blockchain_state.dart index 3480ee53..35ac017a 100644 --- a/lib/src/core/models/blockchain_state.dart +++ b/lib/src/core/models/blockchain_state.dart @@ -12,7 +12,9 @@ class BlockchainState { factory BlockchainState.fromJson(Map json) { return BlockchainState( difficulty: json['difficulty'] as int, - peak: json['peak'] != null ? Peak.fromJson(json['peak'] as Map) : null, + peak: json['peak'] != null + ? Peak.fromJson(json['peak'] as Map) + : null, ); } final int difficulty; @@ -29,7 +31,8 @@ class Peak { factory Peak.fromJson(Map json) { return Peak( - farmerPuzzlehash: Puzzlehash.fromHex(json['farmer_puzzle_hash'] as String), + farmerPuzzlehash: + Puzzlehash.fromHex(json['farmer_puzzle_hash'] as String), headerHash: Bytes.fromHex(json['header_hash'] as String), height: json['height'] as int, timestamp: json['timestamp'] as int?, @@ -40,6 +43,7 @@ class Peak { int height; int? timestamp; - DateTime? get dateTime => - (timestamp != null) ? DateTime.fromMillisecondsSinceEpoch(timestamp! * 1000) : null; + DateTime? get dateTime => (timestamp != null) + ? DateTime.fromMillisecondsSinceEpoch(timestamp! * 1000) + : null; } diff --git a/lib/src/core/models/coin.dart b/lib/src/core/models/coin.dart index 232f5fa1..0504eef8 100644 --- a/lib/src/core/models/coin.dart +++ b/lib/src/core/models/coin.dart @@ -17,7 +17,8 @@ class Coin extends CoinPrototype with ToBytesMixin { }); factory Coin.fromChiaCoinRecordJson(Map json) { - final coinPrototype = CoinPrototype.fromJson(json['coin'] as Map); + final coinPrototype = + CoinPrototype.fromJson(json['coin'] as Map); return Coin( confirmedBlockIndex: json['confirmed_block_index'] as int, spentBlockIndex: json['spent_block_index'] as int, @@ -105,7 +106,8 @@ class Coin extends CoinPrototype with ToBytesMixin { } extension CoinFunctionality on Coin { - DateTime get dateConfirmed => DateTime.fromMillisecondsSinceEpoch(timestamp * 1000); + DateTime get dateConfirmed => + DateTime.fromMillisecondsSinceEpoch(timestamp * 1000); SpendSafety getSpendSafety(int currentBlockHeight) { if (isSpent) { diff --git a/lib/src/core/models/coin_prototype.dart b/lib/src/core/models/coin_prototype.dart index 167dfc7b..137835da 100644 --- a/lib/src/core/models/coin_prototype.dart +++ b/lib/src/core/models/coin_prototype.dart @@ -39,10 +39,12 @@ class CoinPrototype with ToBytesMixin { } factory CoinPrototype.fromStream(Iterator iterator) { - final parentCoinInfoBytes = iterator.extractBytesAndAdvance(Puzzlehash.bytesLength); + final parentCoinInfoBytes = + iterator.extractBytesAndAdvance(Puzzlehash.bytesLength); final parentCoinInfo = Bytes(parentCoinInfoBytes); - final puzzlehashBytes = iterator.extractBytesAndAdvance(Puzzlehash.bytesLength); + final puzzlehashBytes = + iterator.extractBytesAndAdvance(Puzzlehash.bytesLength); final puzzlehash = Puzzlehash(puzzlehashBytes); // coin amount is encoded with 64 bits @@ -100,7 +102,8 @@ class CoinPrototype with ToBytesMixin { } int calculateTotalCoinValue(List coins) { - final total = coins.fold(0, (int previousValue, coin) => previousValue + coin.amount); + final total = + coins.fold(0, (int previousValue, coin) => previousValue + coin.amount); return total; } @@ -110,6 +113,9 @@ extension CoinValue on List { } Bytes get joinedIds { - return fold(Bytes.empty, (Bytes previousValue, coin) => previousValue + coin.id); + return fold( + Bytes.empty, + (Bytes previousValue, coin) => previousValue + coin.id, + ); } } diff --git a/lib/src/core/models/coin_spend.dart b/lib/src/core/models/coin_spend.dart index 2222d22e..27c7d47a 100644 --- a/lib/src/core/models/coin_spend.dart +++ b/lib/src/core/models/coin_spend.dart @@ -150,7 +150,9 @@ class CoinSpend extends Equatable with ToBytesMixin, ToJsonMixin { @override Bytes toBytes() { - return coin.toBytes() + Bytes(puzzleReveal.toBytes()) + Bytes(solution.toBytes()); + return coin.toBytes() + + Bytes(puzzleReveal.toBytes()) + + Bytes(solution.toBytes()); } SpendType? get type { @@ -175,7 +177,8 @@ class CoinSpend extends Equatable with ToBytesMixin, ToJsonMixin { final payments = await paymentsAsync; final memoStrings = payments.fold( [], - (List previousValue, payment) => previousValue + payment.memoStrings, + (List previousValue, payment) => + previousValue + payment.memoStrings, ); return memoStrings; } @@ -198,7 +201,8 @@ class CoinSpend extends Equatable with ToBytesMixin, ToJsonMixin { } @override - String toString() => 'CoinSpend(coin: $coin, puzzleReveal: $puzzleReveal, solution: $solution)'; + String toString() => + 'CoinSpend(coin: $coin, puzzleReveal: $puzzleReveal, solution: $solution)'; @override List get props => [coin, puzzleReveal, solution]; diff --git a/lib/src/core/models/coin_with_hint.dart b/lib/src/core/models/coin_with_hint.dart index 9ed32f86..2edfdaa2 100644 --- a/lib/src/core/models/coin_with_hint.dart +++ b/lib/src/core/models/coin_with_hint.dart @@ -30,8 +30,9 @@ class CoinWithHint extends Coin { hint: hint, ); } on InvalidPuzzleHashException catch (e, st) { - LoggingContext() - .error('Invalid puzzle hash in CoinWithHint.fromChiaCoinRecordJson: $json \n$st'); + LoggingContext().error( + 'Invalid puzzle hash in CoinWithHint.fromChiaCoinRecordJson: $json \n$st', + ); rethrow; } } @@ -51,7 +52,8 @@ class CoinWithHint extends Coin { hint: hint, ); } on InvalidPuzzleHashException catch (e, st) { - LoggingContext().error('Invalid puzzle hash in CoinWithHint.fromJson: $json \n$st'); + LoggingContext() + .error('Invalid puzzle hash in CoinWithHint.fromJson: $json \n$st'); rethrow; } } diff --git a/lib/src/core/models/coin_with_parent_spend.dart b/lib/src/core/models/coin_with_parent_spend.dart index 87e9e7bd..44ccf408 100644 --- a/lib/src/core/models/coin_with_parent_spend.dart +++ b/lib/src/core/models/coin_with_parent_spend.dart @@ -1,13 +1,18 @@ import 'package:chia_crypto_utils/chia_crypto_utils.dart'; import 'package:deep_pick/deep_pick.dart'; -class CoinPrototypeWithParentSpend with CoinPrototypeDecoratorMixin implements CoinPrototype { +class CoinPrototypeWithParentSpend + with CoinPrototypeDecoratorMixin + implements CoinPrototype { CoinPrototypeWithParentSpend({ required this.delegate, required this.parentSpend, }); - factory CoinPrototypeWithParentSpend.fromCoin(CoinPrototype coin, CoinSpend parentSpend) { + factory CoinPrototypeWithParentSpend.fromCoin( + CoinPrototype coin, + CoinSpend parentSpend, + ) { return CoinPrototypeWithParentSpend( delegate: coin, parentSpend: parentSpend, @@ -35,7 +40,8 @@ class CoinWithParentSpend with CoinPrototypeDecoratorMixin implements Coin { factory CoinWithParentSpend.fromJson(Map json) { final coin = Coin.fromJson(json); - final parentSpend = pick(json, 'parent_coin_spend').letJsonOrNull(CoinSpend.fromJson); + final parentSpend = + pick(json, 'parent_coin_spend').letJsonOrNull(CoinSpend.fromJson); return CoinWithParentSpend.fromCoin(coin, parentSpend); } diff --git a/lib/src/core/models/conditions/agg_sig_me_condition.dart b/lib/src/core/models/conditions/agg_sig_me_condition.dart index c24e7eb7..ecfb8881 100644 --- a/lib/src/core/models/conditions/agg_sig_me_condition.dart +++ b/lib/src/core/models/conditions/agg_sig_me_condition.dart @@ -19,8 +19,8 @@ class AggSigMeCondition implements Condition { } static const conditionCode = 50; - final JacobianPoint publicKey; - final Bytes message; + final JacobianPoint publicKey; + final Bytes message; @override int get code => conditionCode; diff --git a/lib/src/core/models/conditions/assert_coin_id_condition.dart b/lib/src/core/models/conditions/assert_coin_id_condition.dart index db30a362..bf5b9f53 100644 --- a/lib/src/core/models/conditions/assert_coin_id_condition.dart +++ b/lib/src/core/models/conditions/assert_coin_id_condition.dart @@ -40,5 +40,6 @@ class AssertMyCoinIdCondition implements Condition { } @override - String toString() => 'AssertMyCoinIdCondition(code: $conditionCode, coinId: $coinId)'; + String toString() => + 'AssertMyCoinIdCondition(code: $conditionCode, coinId: $coinId)'; } diff --git a/lib/src/core/models/conditions/condition.dart b/lib/src/core/models/conditions/condition.dart index a4aed2d5..9590b0eb 100644 --- a/lib/src/core/models/conditions/condition.dart +++ b/lib/src/core/models/conditions/condition.dart @@ -10,7 +10,8 @@ typedef ConditionChecker = bool Function(Program program); typedef ConditionFromProgramConstructor = T Function(Program program); extension ToProgram on Iterable { - Program toProgram() => Program.list(map((condition) => condition.toProgram()).toList()); + Program toProgram() => + Program.list(map((condition) => condition.toProgram()).toList()); } extension ConditionArguments on Condition { diff --git a/lib/src/core/models/conditions/create_coin_announcement_condition.dart b/lib/src/core/models/conditions/create_coin_announcement_condition.dart index ac943e65..3d23aa2f 100644 --- a/lib/src/core/models/conditions/create_coin_announcement_condition.dart +++ b/lib/src/core/models/conditions/create_coin_announcement_condition.dart @@ -20,5 +20,6 @@ class CreateCoinAnnouncementCondition implements Condition { } @override - String toString() => 'CreateCoinAnnouncementCondition(code: $conditionCode, message: $message)'; + String toString() => + 'CreateCoinAnnouncementCondition(code: $conditionCode, message: $message)'; } diff --git a/lib/src/core/models/conditions/create_puzzle_announcement_condition.dart b/lib/src/core/models/conditions/create_puzzle_announcement_condition.dart index 1f8fd298..a3ac3411 100644 --- a/lib/src/core/models/conditions/create_puzzle_announcement_condition.dart +++ b/lib/src/core/models/conditions/create_puzzle_announcement_condition.dart @@ -40,5 +40,6 @@ class CreatePuzzleAnnouncementCondition implements Condition { } @override - String toString() => 'CreatePuzzleAnnouncementCondition(code: $conditionCode, message: $message)'; + String toString() => + 'CreatePuzzleAnnouncementCondition(code: $conditionCode, message: $message)'; } diff --git a/lib/src/core/models/conditions/reserve_fee_condition.dart b/lib/src/core/models/conditions/reserve_fee_condition.dart index e1b5e320..0e2ff7df 100644 --- a/lib/src/core/models/conditions/reserve_fee_condition.dart +++ b/lib/src/core/models/conditions/reserve_fee_condition.dart @@ -36,5 +36,6 @@ class ReserveFeeCondition implements Condition { } @override - String toString() => 'ReserveFeeCondition(code: $conditionCode, feeAmount: $feeAmount)'; + String toString() => + 'ReserveFeeCondition(code: $conditionCode, feeAmount: $feeAmount)'; } diff --git a/lib/src/core/models/full_block.dart b/lib/src/core/models/full_block.dart index 5fbfd88c..cc3eb3d8 100644 --- a/lib/src/core/models/full_block.dart +++ b/lib/src/core/models/full_block.dart @@ -7,8 +7,11 @@ class FullBlock extends Equatable with ToJsonMixin { factory FullBlock.fromJson(Map json) { return FullBlock( - pick(json, 'transactions_generator').letStringOrNull(Program.deserializeHex), - pick(json, 'transactions_generator_ref_list').asListOrNull((p0) => p0.asIntOrThrow()) ?? [], + pick(json, 'transactions_generator') + .letStringOrNull(Program.deserializeHex), + pick(json, 'transactions_generator_ref_list') + .asListOrNull((p0) => p0.asIntOrThrow()) ?? + [], ); } @@ -16,7 +19,8 @@ class FullBlock extends Equatable with ToJsonMixin { final List transactionGeneratorRefList; @override - List get props => [transactionGenerator, transactionGeneratorRefList]; + List get props => + [transactionGenerator, transactionGeneratorRefList]; @override Map toJson() => { diff --git a/lib/src/core/models/keychain_core_secret.dart b/lib/src/core/models/keychain_core_secret.dart index 9c9b9732..96caaa63 100644 --- a/lib/src/core/models/keychain_core_secret.dart +++ b/lib/src/core/models/keychain_core_secret.dart @@ -56,7 +56,9 @@ class KeychainCoreSecret with ToBytesMixin { return KeychainCoreSecret(mnemonic, masterPrivateKey); } - static Future fromMnemonicAsync(List mnemonic) async { + static Future fromMnemonicAsync( + List mnemonic, + ) async { final seed = await generateSeedFromMnemonicAsync(mnemonic); final privateKey = PrivateKey.fromSeed(seed); @@ -68,7 +70,8 @@ class KeychainCoreSecret with ToBytesMixin { @override Bytes toBytes() { - return serializeItem(mnemonic.join(mnemonicWordSeperator)) + masterPrivateKey.toBytes(); + return serializeItem(mnemonic.join(mnemonicWordSeperator)) + + masterPrivateKey.toBytes(); } static const mnemonicWordSeperator = ' '; @@ -108,18 +111,23 @@ class KeychainCoreSecret with ToBytesMixin { ); } - static Map _generatesSeedFromMnemonicTask(List mnemonic) { + static Map _generatesSeedFromMnemonicTask( + List mnemonic, + ) { final seed = bip39.mnemonicToSeed(mnemonic.join(mnemonicWordSeperator)); return { 'seed': Bytes(seed).toHex(), }; } - static Future generateSeedFromMnemonicAsync(List mnemonic) async { + static Future generateSeedFromMnemonicAsync( + List mnemonic, + ) async { return spawnAndWaitForIsolate( taskArgument: mnemonic, isolateTask: _generatesSeedFromMnemonicTask, - handleTaskCompletion: (taskResultJson) => Bytes.fromHex(taskResultJson['seed'] as String), + handleTaskCompletion: (taskResultJson) => + Bytes.fromHex(taskResultJson['seed'] as String), ); } diff --git a/lib/src/core/models/lineage_proof.dart b/lib/src/core/models/lineage_proof.dart index c7b2212f..25ea5c78 100644 --- a/lib/src/core/models/lineage_proof.dart +++ b/lib/src/core/models/lineage_proof.dart @@ -11,8 +11,10 @@ class LineageProof with ToBytesMixin, ToProgramMixin { }); factory LineageProof.fromJson(Map json) { return LineageProof( - parentCoinInfo: pick(json, 'parent_name').letStringOrNull(Puzzlehash.fromHex), - innerPuzzlehash: pick(json, 'inner_puzzle_hash').letStringOrNull(Puzzlehash.fromHex), + parentCoinInfo: + pick(json, 'parent_name').letStringOrNull(Puzzlehash.fromHex), + innerPuzzlehash: + pick(json, 'inner_puzzle_hash').letStringOrNull(Puzzlehash.fromHex), amount: pick(json, 'amount').asIntOrNull(), ); } @@ -32,6 +34,19 @@ class LineageProof with ToBytesMixin, ToProgramMixin { ); } + factory LineageProof.fromStream(Iterator iterator) { + final parentCoinInfo = Puzzlehash.maybeFromStream(iterator); + final innerPuzzlehash = Puzzlehash.maybeFromStream(iterator); + + final amount = maybeIntFrom64BitsStream(iterator); + + return LineageProof( + parentCoinInfo: parentCoinInfo, + innerPuzzlehash: innerPuzzlehash, + amount: amount, + ); + } + final Bytes? parentCoinInfo; final Puzzlehash? innerPuzzlehash; final int? amount; diff --git a/lib/src/core/models/payment.dart b/lib/src/core/models/payment.dart index 79fb1009..1766896e 100644 --- a/lib/src/core/models/payment.dart +++ b/lib/src/core/models/payment.dart @@ -13,14 +13,20 @@ class Payment { : memos is List ? memos.map((memo) => Memo(utf8.encode(memo))).toList() : memos is List - ? memos.map((memo) => Memo(utf8.encode(memo.toString()))).toList() + ? memos + .map((memo) => Memo(utf8.encode(memo.toString()))) + .toList() : memos is List ? memos.map((e) => Memo(e.byteList)).toList() : throw ArgumentError( 'Unsupported type for memos. Must be Bytes, String, or int', ); - factory Payment.ofType(int amount, Puzzlehash puzzlehash, {required GeneralCoinType type}) { + factory Payment.ofType( + int amount, + Puzzlehash puzzlehash, { + required GeneralCoinType type, + }) { switch (type) { case GeneralCoinType.standard: return Payment(amount, puzzlehash); @@ -46,7 +52,8 @@ class Payment { return CreateCoinCondition(puzzlehash, amount, memos: memos); } - NotarizedPayment toNotarizedPayment(Bytes nonce) => NotarizedPayment.fromPayment(this, nonce); + NotarizedPayment toNotarizedPayment(Bytes nonce) => + NotarizedPayment.fromPayment(this, nonce); List get memoStrings { if (memos == null) { @@ -75,11 +82,14 @@ class Payment { } @override - String toString() => 'Payment(amount: $amount, puzzlehash: $puzzlehash, memos: $memos)'; + String toString() => + 'Payment(amount: $amount, puzzlehash: $puzzlehash, memos: $memos)'; @override bool operator ==(Object other) => - other is Payment && puzzlehash == other.puzzlehash && amount == other.amount; + other is Payment && + puzzlehash == other.puzzlehash && + amount == other.amount; @override int get hashCode => puzzlehash.hashCode ^ amount.hashCode; @@ -87,12 +97,19 @@ class Payment { extension PaymentIterable on Iterable { int get totalValue { - return fold(0, (int previousValue, payment) => previousValue + payment.amount); + return fold( + 0, + (int previousValue, payment) => previousValue + payment.amount, + ); } - List get memos => - fold([], (previousValue, element) => previousValue + (element.memos ?? [])); + List get memos => fold( + [], + (previousValue, element) => previousValue + (element.memos ?? []), + ); - List get memoStrings => - fold([], (previousValue, element) => previousValue + (element.memoStrings)); + List get memoStrings => fold( + [], + (previousValue, element) => previousValue + (element.memoStrings), + ); } diff --git a/lib/src/core/models/singleton_wallet_vector.dart b/lib/src/core/models/singleton_wallet_vector.dart index a05db11f..e580ae16 100644 --- a/lib/src/core/models/singleton_wallet_vector.dart +++ b/lib/src/core/models/singleton_wallet_vector.dart @@ -9,10 +9,16 @@ class SingletonWalletVector with ToBytesMixin { required this.derivationIndex, }); - SingletonWalletVector.fromMasterPrivateKey(PrivateKey masterPrivateKey, this.derivationIndex) - : singletonOwnerPrivateKey = masterSkToSingletonOwnerSk(masterPrivateKey, derivationIndex), - poolingAuthenticationPrivateKey = - masterSkToPoolingAuthenticationSk(masterPrivateKey, derivationIndex, 0); + SingletonWalletVector.fromMasterPrivateKey( + PrivateKey masterPrivateKey, + this.derivationIndex, + ) : singletonOwnerPrivateKey = + masterSkToSingletonOwnerSk(masterPrivateKey, derivationIndex), + poolingAuthenticationPrivateKey = masterSkToPoolingAuthenticationSk( + masterPrivateKey, + derivationIndex, + 0, + ); factory SingletonWalletVector.fromStream(Iterator iterator) { final singletonOwnerPrivateKey = PrivateKey.fromStream(iterator); @@ -39,7 +45,14 @@ class SingletonWalletVector with ToBytesMixin { final int derivationIndex; JacobianPoint get singletonOwnerPublicKey => singletonOwnerPrivateKey.getG1(); - JacobianPoint get poolingAuthenticationPublicKey => poolingAuthenticationPrivateKey.getG1(); + JacobianPoint get poolingAuthenticationPublicKey => + poolingAuthenticationPrivateKey.getG1(); + Puzzlehash get plotNftHint => makePlotNftHint(singletonOwnerPublicKey); + + static Puzzlehash makePlotNftHint(JacobianPoint singletonOwnerPublicKey) => + Puzzlehash( + singletonOwnerPublicKey.toBytes().sha256Hash(), + ); @override Bytes toBytes() { @@ -61,7 +74,8 @@ class SingletonWalletVector with ToBytesMixin { other is SingletonWalletVector && runtimeType == other.runtimeType && singletonOwnerPrivateKey == other.singletonOwnerPrivateKey && - poolingAuthenticationPrivateKey == other.poolingAuthenticationPrivateKey && + poolingAuthenticationPrivateKey == + other.poolingAuthenticationPrivateKey && derivationIndex == other.derivationIndex; } } diff --git a/lib/src/core/models/spend_bundle.dart b/lib/src/core/models/spend_bundle.dart index c793a177..6f5b23ee 100644 --- a/lib/src/core/models/spend_bundle.dart +++ b/lib/src/core/models/spend_bundle.dart @@ -46,7 +46,8 @@ class SpendBundle with ToBytesMixin, ToJsonMixin { } final firstSignatureByte = iterator.current; - final restOfSignatureBytes = iterator.extractBytesAndAdvance(JacobianPoint.g2BytesLength - 1); + final restOfSignatureBytes = + iterator.extractBytesAndAdvance(JacobianPoint.g2BytesLength - 1); final signature = JacobianPoint.fromBytesG2( [firstSignatureByte, ...restOfSignatureBytes], @@ -70,8 +71,8 @@ class SpendBundle with ToBytesMixin, ToJsonMixin { .map((dynamic e) => CoinSpend.fromJson(e as Map)) .toList(); - final aggregatedSignature = - pick(json, 'aggregated_signature').letStringOrNull(JacobianPoint.fromHexG2); + final aggregatedSignature = pick(json, 'aggregated_signature') + .letStringOrNull(JacobianPoint.fromHexG2); return SpendBundle( coinSpends: coinSpends, @@ -82,12 +83,13 @@ class SpendBundle with ToBytesMixin, ToJsonMixin { } factory SpendBundle.fromCamelJson(Map json) { - final coinSpends = ((json['coinSpends'] ?? json['coinSolutions']) as Iterable) + final coinSpends = ((json['coinSpends'] ?? json['coinSolutions']) + as Iterable) .map((dynamic e) => CoinSpend.fromCamelJson(e as Map)) .toList(); - final aggregatedSignature = - pick(json, 'aggregatedSignature').letStringOrNull(JacobianPoint.fromHexG2); + final aggregatedSignature = pick(json, 'aggregatedSignature') + .letStringOrNull(JacobianPoint.fromHexG2); return SpendBundle.withNullableSignatures( coinSpends: coinSpends, @@ -120,7 +122,10 @@ class SpendBundle with ToBytesMixin, ToJsonMixin { bool get isSigned => aggregatedSignature != null; - static Future ofCoin(Bytes coinId, ChiaFullNodeInterface fullNode) { + static Future ofCoin( + Bytes coinId, + ChiaFullNodeInterface fullNode, + ) { return constructSpendBundleOfCoin(coinId, fullNode); } @@ -224,7 +229,8 @@ class SpendBundle with ToBytesMixin, ToJsonMixin { if (other.coinSpends.length != coinSpends.length) { return false; } - final otherHexCoinSpends = other.coinSpends.map((cs) => cs.toHex()).toList(); + final otherHexCoinSpends = + other.coinSpends.map((cs) => cs.toHex()).toList(); for (final coinSpend in coinSpends) { if (!otherHexCoinSpends.contains(coinSpend.toHex())) { return false; @@ -283,7 +289,8 @@ class SpendBundle with ToBytesMixin, ToJsonMixin { @override Bytes toBytes() { - return serializeListChia(coinSpends) + Bytes(aggregatedSignature?.toBytes() ?? []); + return serializeListChia(coinSpends) + + Bytes(aggregatedSignature?.toBytes() ?? []); } void debug() { diff --git a/lib/src/core/models/wallet_keychain.dart b/lib/src/core/models/wallet_keychain.dart index 8db922c2..b7a902d0 100644 --- a/lib/src/core/models/wallet_keychain.dart +++ b/lib/src/core/models/wallet_keychain.dart @@ -24,29 +24,36 @@ class WalletKeychain with ToBytesMixin { void incrementAndCallUpdate() { totalWalletVectorsGenerated++; - onProgressUpdate?.call(totalWalletVectorsGenerated / totalWalletVectorsToGenerate); + onProgressUpdate + ?.call(totalWalletVectorsGenerated / totalWalletVectorsToGenerate); } final masterPrivateKey = coreSecret.masterPrivateKey; final walletVectors = LinkedHashMap(); - final unhardenedWalletVectors = LinkedHashMap(); + final unhardenedWalletVectors = + LinkedHashMap(); for (var i = 0; i < walletSize; i++) { - final walletVector = WalletVector.fromMasterPrivateKey(masterPrivateKey, i); + final walletVector = + WalletVector.fromMasterPrivateKey(masterPrivateKey, i); incrementAndCallUpdate(); - final unhardenedWalletVector = UnhardenedWalletVector.fromPrivateKey(masterPrivateKey, i); + final unhardenedWalletVector = + UnhardenedWalletVector.fromPrivateKey(masterPrivateKey, i); incrementAndCallUpdate(); walletVectors[walletVector.puzzlehash] = walletVector; - unhardenedWalletVectors[unhardenedWalletVector.puzzlehash] = unhardenedWalletVector; + unhardenedWalletVectors[unhardenedWalletVector.puzzlehash] = + unhardenedWalletVector; } final singletonVectors = {}; for (var i = 0; i < plotNftWalletSize; i++) { - final singletonWalletVector = SingletonWalletVector.fromMasterPrivateKey(masterPrivateKey, i); + final singletonWalletVector = + SingletonWalletVector.fromMasterPrivateKey(masterPrivateKey, i); incrementAndCallUpdate(); - singletonVectors[singletonWalletVector.singletonOwnerPublicKey] = singletonWalletVector; + singletonVectors[singletonWalletVector.singletonOwnerPublicKey] = + singletonWalletVector; } return WalletKeychain( @@ -60,8 +67,10 @@ class WalletKeychain with ToBytesMixin { final iterator = bytes.iterator; final hardenedWalletVectorMap = LinkedHashMap(); - final unhardenedWalletVectorMap = LinkedHashMap(); - final singletonWalletVectorMap = LinkedHashMap(); + final unhardenedWalletVectorMap = + LinkedHashMap(); + final singletonWalletVectorMap = + LinkedHashMap(); final nHardenedWalletVectors = intFrom32BitsStream(iterator); for (var _ = 0; _ < nHardenedWalletVectors; _++) { @@ -90,11 +99,13 @@ class WalletKeychain with ToBytesMixin { singletonWalletVectorsMap: singletonWalletVectorMap, ); } - factory WalletKeychain.fromHex(String hex) => WalletKeychain.fromBytes(Bytes.fromHex(hex)); + factory WalletKeychain.fromHex(String hex) => + WalletKeychain.fromBytes(Bytes.fromHex(hex)); factory WalletKeychain.fromWalletSets(List walletSets) { final newHardenedMap = LinkedHashMap(); - final newUnhardenedMap = LinkedHashMap(); + final newUnhardenedMap = + LinkedHashMap(); for (final walletSet in walletSets) { newHardenedMap[walletSet.hardened.puzzlehash] = walletSet.hardened; @@ -168,19 +179,24 @@ class WalletKeychain with ToBytesMixin { List get singletonWalletVectors => singletonWalletVectorsMap.values.toList(); - SingletonWalletVector getNextSingletonWalletVector(PrivateKey masterPrivateKey) { - final usedDerivationIndices = singletonWalletVectors.map((wv) => wv.derivationIndex).toList(); + SingletonWalletVector getNextSingletonWalletVector( + PrivateKey masterPrivateKey, + ) { + final usedDerivationIndices = + singletonWalletVectors.map((wv) => wv.derivationIndex).toList(); var newDerivationIndex = 0; while (usedDerivationIndices.contains(newDerivationIndex)) { newDerivationIndex++; } - final newSingletonWalletVector = - SingletonWalletVector.fromMasterPrivateKey(masterPrivateKey, newDerivationIndex); + final newSingletonWalletVector = SingletonWalletVector.fromMasterPrivateKey( + masterPrivateKey, + newDerivationIndex, + ); - singletonWalletVectorsMap[newSingletonWalletVector.singletonOwnerPublicKey] = - newSingletonWalletVector; + singletonWalletVectorsMap[newSingletonWalletVector + .singletonOwnerPublicKey] = newSingletonWalletVector; return newSingletonWalletVector; } @@ -192,7 +208,8 @@ class WalletKeychain with ToBytesMixin { final singletonOwnerPublicKey = args.singletonOwnerPublicKey; const maxIndexToCheck = 1000; for (var i = 0; i < maxIndexToCheck; i++) { - final singletonOwnerSecretKey = masterSkToSingletonOwnerSk(masterPrivateKey, i); + final singletonOwnerSecretKey = + masterSkToSingletonOwnerSk(masterPrivateKey, i); if (singletonOwnerSecretKey.getG1() == singletonOwnerPublicKey) { final newSingletonWalletVector = SingletonWalletVector.fromMasterPrivateKey(masterPrivateKey, i); @@ -208,12 +225,16 @@ class WalletKeychain with ToBytesMixin { }; } - Future addSingletonWalletVectorForSingletonOwnerPublicKeyAsync( + Future + addSingletonWalletVectorForSingletonOwnerPublicKeyAsync( JacobianPoint singletonOwnerPublicKey, PrivateKey masterPrivateKey, ) async { final newSingletonWalletVector = await spawnAndWaitForIsolate( - taskArgument: AddsSingletonWalletVectorArguments(singletonOwnerPublicKey, masterPrivateKey), + taskArgument: AddsSingletonWalletVectorArguments( + singletonOwnerPublicKey, + masterPrivateKey, + ), isolateTask: _getSingletonWalletVectorForSingletonOwnerPublicKeyTask, handleTaskCompletion: (taskResultJson) { final result = taskResultJson['singleton_wallet_vector'] as String?; @@ -230,7 +251,8 @@ class WalletKeychain with ToBytesMixin { ); } - singletonWalletVectorsMap[singletonOwnerPublicKey] = newSingletonWalletVector; + singletonWalletVectorsMap[singletonOwnerPublicKey] = + newSingletonWalletVector; return newSingletonWalletVector; } @@ -240,11 +262,13 @@ class WalletKeychain with ToBytesMixin { ) { const maxIndexToCheck = 1000; for (var i = 0; i < maxIndexToCheck; i++) { - final singletonOwnerSecretKey = masterSkToSingletonOwnerSk(masterPrivateKey, i); + final singletonOwnerSecretKey = + masterSkToSingletonOwnerSk(masterPrivateKey, i); if (singletonOwnerSecretKey.getG1() == singletonOwnerPublicKey) { final newSingletonWalletVector = SingletonWalletVector.fromMasterPrivateKey(masterPrivateKey, i); - singletonWalletVectorsMap[singletonOwnerPublicKey] = newSingletonWalletVector; + singletonWalletVectorsMap[singletonOwnerPublicKey] = + newSingletonWalletVector; return newSingletonWalletVector; } } @@ -253,7 +277,9 @@ class WalletKeychain with ToBytesMixin { ); } - SingletonWalletVector? getSingletonWalletVector(JacobianPoint ownerPublicKey) { + SingletonWalletVector? getSingletonWalletVector( + JacobianPoint ownerPublicKey, + ) { return singletonWalletVectorsMap[ownerPublicKey]; } @@ -282,11 +308,13 @@ class WalletKeychain with ToBytesMixin { hardenedMap.values.map((wv) => wv.puzzlehash), ).toList(); - List get walletPuzzlehashes => LinkedHashSet.from( + List get walletPuzzlehashes => + LinkedHashSet.from( unhardenedMap.values.map((wv) => wv.walletPuzzlehash), ).toList(); - List get walletPuzzlehashesHardened => LinkedHashSet.from( + List get walletPuzzlehashesHardened => + LinkedHashSet.from( hardenedMap.values.map((wv) => wv.walletPuzzlehash), ).toList(); @@ -296,11 +324,14 @@ class WalletKeychain with ToBytesMixin { 'Puzzlehashes for given Asset Id are not in keychain', ); } - return unhardenedMap.values.map((v) => v.assetIdtoOuterPuzzlehash[assetId]!).toList(); + return unhardenedMap.values + .map((v) => v.assetIdtoOuterPuzzlehash[assetId]!) + .toList(); } bool hasAssetId(Puzzlehash assetId) { - return unhardenedMap.values.first.assetIdtoOuterPuzzlehash.containsKey(assetId); + return unhardenedMap.values.first.assetIdtoOuterPuzzlehash + .containsKey(assetId); } MixedPuzzlehashes addPuzzleHashes( @@ -312,17 +343,24 @@ class WalletKeychain with ToBytesMixin { final hardenedPuzzlehashes = []; final outerPuzzlehashes = >{}; - for (var i = currentDerivationIndex; i < currentDerivationIndex + numberOfPuzzleHashes; i++) { - final walletVector = WalletVector.fromMasterPrivateKey(masterPrivateKey, i); - final unhardenedWalletVector = UnhardenedWalletVector.fromPrivateKey(masterPrivateKey, i); + for (var i = currentDerivationIndex; + i < currentDerivationIndex + numberOfPuzzleHashes; + i++) { + final walletVector = + WalletVector.fromMasterPrivateKey(masterPrivateKey, i); + final unhardenedWalletVector = + UnhardenedWalletVector.fromPrivateKey(masterPrivateKey, i); hardenedPuzzlehashes.add(walletVector.walletPuzzlehash); unhardenedPuzzlehashes.add(unhardenedWalletVector.walletPuzzlehash); - for (final assetId in unhardenedWalletVectors.first.assetIdtoOuterPuzzlehash.keys) { - final outerPuzzleHash = makeOuterPuzzleHash(walletVector.puzzlehash, assetId); + for (final assetId + in unhardenedWalletVectors.first.assetIdtoOuterPuzzlehash.keys) { + final outerPuzzleHash = + makeOuterPuzzleHash(walletVector.puzzlehash, assetId); - unhardenedWalletVector.assetIdtoOuterPuzzlehash[assetId] = outerPuzzleHash; + unhardenedWalletVector.assetIdtoOuterPuzzlehash[assetId] = + outerPuzzleHash; unhardenedMap[outerPuzzleHash] = unhardenedWalletVector; outerPuzzlehashes.update( @@ -338,7 +376,8 @@ class WalletKeychain with ToBytesMixin { return MixedPuzzlehashes( hardened: hardenedPuzzlehashes, unhardened: unhardenedPuzzlehashes, - outer: outerPuzzlehashes.map((key, value) => MapEntry(key, value.toList())), + outer: + outerPuzzlehashes.map((key, value) => MapEntry(key, value.toList())), ); } @@ -367,12 +406,26 @@ class WalletKeychain with ToBytesMixin { ); } - static Puzzlehash makeOuterPuzzleHash(Puzzlehash innerPuzzleHash, Puzzlehash assetId) { - return makeOuterPuzzleHashForCatProgram(innerPuzzleHash, assetId, cat2Program); + static Puzzlehash makeOuterPuzzleHash( + Puzzlehash innerPuzzleHash, + Puzzlehash assetId, + ) { + return makeOuterPuzzleHashForCatProgram( + innerPuzzleHash, + assetId, + cat2Program, + ); } - static Puzzlehash makeCat1OuterPuzzleHash(Puzzlehash innerPuzzleHash, Puzzlehash assetId) { - return makeOuterPuzzleHashForCatProgram(innerPuzzleHash, assetId, cat1Program); + static Puzzlehash makeCat1OuterPuzzleHash( + Puzzlehash innerPuzzleHash, + Puzzlehash assetId, + ) { + return makeOuterPuzzleHashForCatProgram( + innerPuzzleHash, + assetId, + cat1Program, + ); } List addOuterPuzzleHashesForInnerPuzzlehashes( @@ -409,14 +462,20 @@ class WalletKeychain with ToBytesMixin { for (final innerPuzzlehash in innerPuzzlehashes) { final walletVector = unhardenedMap[innerPuzzlehash]; if (walletVector == null) { - throw KeyMismatchException('Inner puzzlehash $innerPuzzlehash does not belong to keychain'); + throw KeyMismatchException( + 'Inner puzzlehash $innerPuzzlehash does not belong to keychain', + ); } if (walletVector.assetIdtoOuterPuzzlehash.containsKey(assetId)) { continue; } - final outerPuzzleHash = - makeOuterPuzzleHashForCatProgram(walletVector.puzzlehash, assetId, program); - outerPuzzleHashes.add(WalletPuzzlehash(outerPuzzleHash, walletVector.derivationIndex)); + final outerPuzzleHash = makeOuterPuzzleHashForCatProgram( + walletVector.puzzlehash, + assetId, + program, + ); + outerPuzzleHashes + .add(WalletPuzzlehash(outerPuzzleHash, walletVector.derivationIndex)); walletVector.assetIdtoOuterPuzzlehash[assetId] = outerPuzzleHash; entriesToAdd[outerPuzzleHash] = walletVector; @@ -444,10 +503,15 @@ class WalletKeychain with ToBytesMixin { ), ); } else { - final outerPuzzleHash = - makeOuterPuzzleHashForCatProgram(walletVector.puzzlehash, assetId, program); + final outerPuzzleHash = makeOuterPuzzleHashForCatProgram( + walletVector.puzzlehash, + assetId, + program, + ); - outerPuzzleHashes.add(WalletPuzzlehash(outerPuzzleHash, walletVector.derivationIndex)); + outerPuzzleHashes.add( + WalletPuzzlehash(outerPuzzleHash, walletVector.derivationIndex), + ); walletVector.assetIdtoOuterPuzzlehash[assetId] = outerPuzzleHash; entriesToAdd[outerPuzzleHash] = walletVector; } @@ -484,10 +548,16 @@ class MixedPuzzlehashes { MixedPuzzlehashes.fromJson(Map json) : hardened = (json['hardened'] as Iterable) - .map((dynamic e) => WalletPuzzlehash.fromJson(e as Map)) + .map( + (dynamic e) => + WalletPuzzlehash.fromJson(e as Map), + ) .toList(), unhardened = (json['unhardened'] as Iterable) - .map((dynamic e) => WalletPuzzlehash.fromJson(e as Map)) + .map( + (dynamic e) => + WalletPuzzlehash.fromJson(e as Map), + ) .toList(), outer = pick(json, 'outer').asJsonOrThrow().map( (key, value) => MapEntry( @@ -504,8 +574,10 @@ class MixedPuzzlehashes { Map toJson() => { 'hardened': hardened.map((e) => e.toJson()).toList(), 'unhardened': unhardened.map((e) => e.toJson()).toList(), - 'outer': - outer.map((key, value) => MapEntry(key.toHex(), value.map((e) => e.toJson()).toList())), + 'outer': outer.map( + (key, value) => + MapEntry(key.toHex(), value.map((e) => e.toJson()).toList()), + ), }; } @@ -520,7 +592,8 @@ class WalletPuzzlehash extends Puzzlehash { super(Bytes.fromHex(json['puzzlehash'] as String)); @override - WalletAddress toAddressWithContext() => WalletAddress.fromContext(this, derivationIndex); + WalletAddress toAddressWithContext() => + WalletAddress.fromContext(this, derivationIndex); @override WalletAddress toAddress(String ticker) => WalletAddress.fromPuzzlehash(this, ticker, derivationIndex); @@ -546,7 +619,10 @@ class WalletKeychainFromCoreSecretIsolateArguments { } class AddsSingletonWalletVectorArguments { - AddsSingletonWalletVectorArguments(this.singletonOwnerPublicKey, this.masterPrivateKey); + AddsSingletonWalletVectorArguments( + this.singletonOwnerPublicKey, + this.masterPrivateKey, + ); final JacobianPoint singletonOwnerPublicKey; final PrivateKey masterPrivateKey; @@ -566,9 +642,16 @@ class WalletAddress extends Address { return WalletAddress(address.address, derivationIndex: derivationIndex); } - factory WalletAddress.fromContext(Puzzlehash puzzlehash, int derivationIndex) { + factory WalletAddress.fromContext( + Puzzlehash puzzlehash, + int derivationIndex, + ) { final addressPrefix = NetworkContext().blockchainNetwork.addressPrefix; - return WalletAddress.fromPuzzlehash(puzzlehash, addressPrefix, derivationIndex); + return WalletAddress.fromPuzzlehash( + puzzlehash, + addressPrefix, + derivationIndex, + ); } final int derivationIndex; diff --git a/lib/src/core/models/wallet_vector.dart b/lib/src/core/models/wallet_vector.dart index abb39ce9..47209b12 100644 --- a/lib/src/core/models/wallet_vector.dart +++ b/lib/src/core/models/wallet_vector.dart @@ -15,7 +15,8 @@ class WalletVector with ToBytesMixin { PrivateKey masterPrivateKey, int derivationIndex, ) { - final childPrivateKeyHardened = masterSkToWalletSk(masterPrivateKey, derivationIndex); + final childPrivateKeyHardened = + masterSkToWalletSk(masterPrivateKey, derivationIndex); final childPublicKeyHardened = childPrivateKeyHardened.getG1(); final puzzleHardened = getPuzzleFromPk(childPublicKeyHardened); @@ -72,7 +73,8 @@ class WalletVector with ToBytesMixin { } static String _fromPrivateKeyTask(_PrivateKeyWithDerivationIndex arg) { - final walletVector = WalletVector.fromMasterPrivateKey(arg.privateKey, arg.derivationIndex); + final walletVector = + WalletVector.fromMasterPrivateKey(arg.privateKey, arg.derivationIndex); return walletVector.toHex(); } @@ -116,8 +118,12 @@ class UnhardenedWalletVector extends WalletVector { required super.puzzlehash, required super.derivationIndex, Map? assetIdtoOuterPuzzlehash, - }) : assetIdtoOuterPuzzlehash = assetIdtoOuterPuzzlehash ?? {}; - factory UnhardenedWalletVector.fromStream(Iterator iterator, int derivationIndex) { + }) : assetIdtoOuterPuzzlehash = + assetIdtoOuterPuzzlehash ?? {}; + factory UnhardenedWalletVector.fromStream( + Iterator iterator, + int derivationIndex, + ) { final childPrivateKey = PrivateKey.fromStream(iterator); final puzzlehash = Puzzlehash.fromStream(iterator); @@ -199,7 +205,8 @@ class UnhardenedWalletVector extends WalletVector { } for (final assetId in assetIdtoOuterPuzzlehash.keys) { - if (other.assetIdtoOuterPuzzlehash[assetId] != assetIdtoOuterPuzzlehash[assetId]) { + if (other.assetIdtoOuterPuzzlehash[assetId] != + assetIdtoOuterPuzzlehash[assetId]) { return false; } } diff --git a/lib/src/core/puzzles/p2_conditions/p2_conditions.clsp b/lib/src/core/puzzles/p2_conditions/p2_conditions.clsp new file mode 100644 index 00000000..dd90b75c --- /dev/null +++ b/lib/src/core/puzzles/p2_conditions/p2_conditions.clsp @@ -0,0 +1,3 @@ +(mod (conditions) + (qq (q . (unquote conditions))) +) diff --git a/lib/src/core/puzzles/p2_conditions/p2_conditions.clvm.hex b/lib/src/core/puzzles/p2_conditions/p2_conditions.clvm.hex new file mode 100644 index 00000000..7e300c44 --- /dev/null +++ b/lib/src/core/puzzles/p2_conditions/p2_conditions.clvm.hex @@ -0,0 +1 @@ +ff04ffff0101ff0280 \ No newline at end of file diff --git a/lib/src/core/puzzles/p2_conditions/p2_conditions.clvm.hex.dart b/lib/src/core/puzzles/p2_conditions/p2_conditions.clvm.hex.dart new file mode 100644 index 00000000..bcd483cf --- /dev/null +++ b/lib/src/core/puzzles/p2_conditions/p2_conditions.clvm.hex.dart @@ -0,0 +1,5 @@ +import 'package:chia_crypto_utils/chia_crypto_utils.dart'; + +final p2ConditionsProgram = Program.deserializeHex( + 'ff04ffff0101ff0280', +); diff --git a/lib/src/core/puzzles/p2_conditions/p2_conditions.clvm.hex.sha256tree b/lib/src/core/puzzles/p2_conditions/p2_conditions.clvm.hex.sha256tree new file mode 100644 index 00000000..11e75b5c --- /dev/null +++ b/lib/src/core/puzzles/p2_conditions/p2_conditions.clvm.hex.sha256tree @@ -0,0 +1 @@ +1c77d7d5efde60a7a1d2d27db6d746bc8e568aea1ef8586ca967a0d60b83cc36 diff --git a/lib/src/core/service/base_wallet.dart b/lib/src/core/service/base_wallet.dart index e3d6d9a9..4e185fe0 100644 --- a/lib/src/core/service/base_wallet.dart +++ b/lib/src/core/service/base_wallet.dart @@ -15,20 +15,24 @@ class BaseWalletService { required List payments, required List coinsInput, Puzzlehash? changePuzzlehash, + bool allowLeftOver = false, int fee = 0, int surplus = 0, Bytes? originId, List coinIdsToAssert = const [], List coinAnnouncementsToAssert = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], List additionalConditions = const [], - required Program Function(Puzzlehash puzzlehash) makePuzzleRevealFromPuzzlehash, + required Program Function(Puzzlehash puzzlehash) + makePuzzleRevealFromPuzzlehash, Program Function(Program standardSolution)? transformStandardSolution, // required JacobianPoint Function(CoinSpend coinSpend) makeSignatureForCoinSpend, void Function(Bytes message)? useCoinMessage, }) { Program makeSolutionFromConditions(List conditions) { - final standardSolution = BaseWalletService.makeSolutionFromConditions(conditions); + final standardSolution = + BaseWalletService.makeSolutionFromConditions(conditions); if (transformStandardSolution == null) { return standardSolution; } @@ -37,7 +41,8 @@ class BaseWalletService { // copy coins input since coins list is modified in this function final coins = List.from(coinsInput); - final totalCoinValue = coins.fold(0, (int previousValue, coin) => previousValue + coin.amount); + final totalCoinValue = + coins.fold(0, (int previousValue, coin) => previousValue + coin.amount); final totalPaymentAmount = payments.fold( 0, @@ -45,14 +50,15 @@ class BaseWalletService { ); final change = totalCoinValue - totalPaymentAmount - fee - surplus; - if (changePuzzlehash == null && change > 0) { + if (changePuzzlehash == null && change > 0 && !allowLeftOver) { throw ChangePuzzlehashNeededException(); } final spends = []; // returns -1 if originId is given but is not in coins - final originIndex = originId == null ? 0 : coins.indexWhere((coin) => coin.id == originId); + final originIndex = + originId == null ? 0 : coins.indexWhere((coin) => coin.id == originId); if (originIndex == -1) { throw OriginIdNotInCoinsException(); @@ -88,8 +94,8 @@ class BaseWalletService { ); } - if (change > 0) { - conditions.add(CreateCoinCondition(changePuzzlehash!, change)); + if (change > 0 && changePuzzlehash != null) { + conditions.add(CreateCoinCondition(changePuzzlehash, change)); createdCoins.add( CoinPrototype( parentCoinInfo: coin.id, @@ -119,16 +125,19 @@ class BaseWalletService { Bytes.empty, (Bytes previousValue, coin) => previousValue + coin.id, ); - final message = (existingCoinsMessage + createdCoinsMessage).sha256Hash(); + final message = + (existingCoinsMessage + createdCoinsMessage).sha256Hash(); useCoinMessage?.call(message); conditions.add(CreateCoinAnnouncementCondition(message)); for (final coinIdToAssert in coinIdsToAssert) { - conditions.add(AssertCoinAnnouncementCondition(coinIdToAssert, message)); + conditions + .add(AssertCoinAnnouncementCondition(coinIdToAssert, message)); } - primaryAssertCoinAnnouncement = AssertCoinAnnouncementCondition(coin.id, message); + primaryAssertCoinAnnouncement = + AssertCoinAnnouncementCondition(coin.id, message); solution = makeSolutionFromConditions(conditions); } else { @@ -138,7 +147,8 @@ class BaseWalletService { } final puzzle = makePuzzleRevealFromPuzzlehash(coin.puzzlehash); - final coinSpend = CoinSpend(coin: coin, puzzleReveal: puzzle, solution: solution); + final coinSpend = + CoinSpend(coin: coin, puzzleReveal: puzzle, solution: solution); spends.add(coinSpend); } @@ -196,26 +206,31 @@ class BaseWalletService { SpendBundleSignResult _signSpendBundle( SpendBundle spendBundle, { - required PrivateKey? Function(Puzzlehash puzzlehash) getPrivateKeyForPuzzlehash, + required PrivateKey? Function(Puzzlehash puzzlehash) + getPrivateKeyForPuzzlehash, bool Function(CoinSpend coinSpend)? filterCoinSpends, }) { PrivateKey? getPrivateKeyForPublicKey(JacobianPoint publicKey) { - final puzzlehashAssumingSyntheticPk = getPuzzleForSyntheticPk(publicKey).hash(); + final puzzlehashAssumingSyntheticPk = + getPuzzleForSyntheticPk(publicKey).hash(); - final privateKey = getPrivateKeyForPuzzlehash(puzzlehashAssumingSyntheticPk); + final privateKey = + getPrivateKeyForPuzzlehash(puzzlehashAssumingSyntheticPk); if (privateKey != null) { return calculateSyntheticPrivateKey(privateKey); } - final puzzlehashAssumingNonSyntheticPk = getPuzzleFromPk(publicKey).hash(); + final puzzlehashAssumingNonSyntheticPk = + getPuzzleFromPk(publicKey).hash(); return getPrivateKeyForPuzzlehash(puzzlehashAssumingNonSyntheticPk); } var totalSpendBundle = spendBundle; - final aggSigMeConditionsWithFullMessages = []; + final aggSigMeConditionsWithFullMessages = + []; final spendsToSign = filterCoinSpends != null ? spendBundle.coinSpends.where(filterCoinSpends) @@ -230,12 +245,16 @@ class BaseWalletService { ); for (final aggSigMeCondition in aggSigMeConditions) { - final fullMessage = - constructFullAggSigMeMessage(aggSigMeCondition.message, coinSpend.coin.id); - aggSigMeConditionsWithFullMessages - .add(AggSigMeConditionWithFullMessage(aggSigMeCondition, fullMessage)); + final fullMessage = constructFullAggSigMeMessage( + aggSigMeCondition.message, + coinSpend.coin.id, + ); + aggSigMeConditionsWithFullMessages.add( + AggSigMeConditionWithFullMessage(aggSigMeCondition, fullMessage), + ); - final privateKey = getPrivateKeyForPublicKey(aggSigMeCondition.publicKey); + final privateKey = + getPrivateKeyForPublicKey(aggSigMeCondition.publicKey); if (privateKey == null) { continue; @@ -312,7 +331,9 @@ class BaseWalletService { CoinSpend coinSpend, { bool useSyntheticOffset = true, }) { - final privateKey0 = useSyntheticOffset ? calculateSyntheticPrivateKey(privateKey) : privateKey; + final privateKey0 = useSyntheticOffset + ? calculateSyntheticPrivateKey(privateKey) + : privateKey; final messagesToSign = getAddSigMeMessage(coinSpend, privateKey0); @@ -327,7 +348,9 @@ class BaseWalletService { } Bytes constructFullAggSigMeMessage(Bytes baseMessage, Bytes coinId) { - return baseMessage + coinId + Bytes.fromHex(blockchainNetwork.aggSigMeExtraData); + return baseMessage + + coinId + + Bytes.fromHex(blockchainNetwork.aggSigMeExtraData); } List getAddSigMeMessage(CoinSpend coinSpend, PrivateKey privateKey) { @@ -336,11 +359,14 @@ class BaseWalletService { final aggSigMeConditions = result.toList().where((conditionProgram) { return AggSigMeCondition.isThisCondition(conditionProgram) && - AggSigMeCondition.fromProgram(conditionProgram).publicKey == privateKey.getG1(); + AggSigMeCondition.fromProgram(conditionProgram).publicKey == + privateKey.getG1(); }).map(AggSigMeCondition.fromProgram); if (aggSigMeConditions.length > 1) { - print('multiple agg sig me conditions: ${aggSigMeConditions.map((e) => e.toProgram())}'); + print( + 'multiple agg sig me conditions: ${aggSigMeConditions.map((e) => e.toProgram())}', + ); return [ constructFullAggSigMeMessage(aggSigMeConditions.last.message, coin.id), ]; @@ -405,7 +431,10 @@ class BaseWalletService { ConditionChecker conditionChecker, ConditionFromProgramConstructor conditionFromProgramConstructor, ) { - return result.where(conditionChecker).map((p) => conditionFromProgramConstructor(p)).toList(); + return result + .where(conditionChecker) + .map((p) => conditionFromProgramConstructor(p)) + .toList(); } static Program makeSolutionFromProgram(Program program) { @@ -420,10 +449,12 @@ class BaseWalletService { final publicKeys = []; final messages = >[]; for (final spend in spendBundle.coinSpends) { - final outputConditions = spend.puzzleReveal.run(spend.solution).program.toList(); + final outputConditions = + spend.puzzleReveal.run(spend.solution).program.toList(); // look for assert agg sig me condition - final aggSigMeProgram = outputConditions.singleWhere(AggSigMeCondition.isThisCondition); + final aggSigMeProgram = + outputConditions.singleWhere(AggSigMeCondition.isThisCondition); final aggSigMeCondition = AggSigMeCondition.fromProgram(aggSigMeProgram); publicKeys.add(aggSigMeCondition.publicKey); diff --git a/lib/src/core/service/wallet.dart b/lib/src/core/service/wallet.dart index 12b372ba..0a5d6c7d 100644 --- a/lib/src/core/service/wallet.dart +++ b/lib/src/core/service/wallet.dart @@ -15,7 +15,10 @@ abstract class Wallet { Future> getCoins(); - Future> getCatCoinsByAssetId(Puzzlehash assetId, {int catVersion = 2}); + Future> getCatCoinsByAssetId( + Puzzlehash assetId, { + int catVersion = 2, + }); Future getNftRecordByLauncherId(Bytes launcherId); } @@ -26,17 +29,27 @@ extension MixedCoinsGetterX on Wallet { /// [InsufficientCatBalanceException], or /// [InsufficientNftBalanceException] /// if there are not enough coins for a requested type - Future getMixedCoinsForAmounts(MixedAmounts amounts, {int catVersion = 2}) async { + Future getMixedCoinsForAmounts( + MixedAmounts amounts, { + int catVersion = 2, + }) async { // standard final allCoins = await getCoins(); - final standardCoinsForOffer = selectStandardCoinsForAmount(allCoins, amounts.standard); + final standardCoinsForOffer = + selectStandardCoinsForAmount(allCoins, amounts.standard); // cat final catCoinsForOffer = []; for (final requestedCat in amounts.cat.entries) { - final catCoins = await getCatCoinsByAssetId(requestedCat.key, catVersion: catVersion); - catCoinsForOffer - .addAll(selectCatCoinsForAmount(catCoins, requestedCat.value, assetId: requestedCat.key)); + final catCoins = + await getCatCoinsByAssetId(requestedCat.key, catVersion: catVersion); + catCoinsForOffer.addAll( + selectCatCoinsForAmount( + catCoins, + requestedCat.value, + assetId: requestedCat.key, + ), + ); } // nft @@ -45,7 +58,8 @@ extension MixedCoinsGetterX on Wallet { for (final requestedNft in amounts.nft.entries) { final nftRecord = await getNftRecordByLauncherId(requestedNft.key); if (nftRecord == null) { - LoggingContext().error('could not find offer requested nft ${requestedNft.key}'); + LoggingContext() + .error('could not find offer requested nft ${requestedNft.key}'); throw InsufficientNftBalanceException(requestedNft.key); } try { @@ -90,7 +104,8 @@ extension SendCoinsX on Wallet { int catVersion = 2, }) async { final coins = await getCatCoinsByAssetId(assetId, catVersion: catVersion); - final coinsForAmount = selectCatCoinsForAmount(coins, payments.totalValue, assetId: assetId); + final coinsForAmount = + selectCatCoinsForAmount(coins, payments.totalValue, assetId: assetId); final standardCoins = await getCoins(); @@ -131,7 +146,8 @@ extension SendCoinsX on Wallet { int fee = 50, }) async { final coins = await getCoins(); - final coinsForAmount = selectStandardCoinsForAmount(coins, payments.totalValue); + final coinsForAmount = + selectStandardCoinsForAmount(coins, payments.totalValue); final walletService = StandardWalletService(); diff --git a/lib/src/custom_coins/dependent_coin/models/dependent_coin.dart b/lib/src/custom_coins/dependent_coin/models/dependent_coin.dart index 7859bdf1..9c8d424c 100644 --- a/lib/src/custom_coins/dependent_coin/models/dependent_coin.dart +++ b/lib/src/custom_coins/dependent_coin/models/dependent_coin.dart @@ -12,8 +12,10 @@ class DependentCoin with CoinPrototypeDecoratorMixin { final delegate = CoinPrototype.fromJson(json); return DependentCoin( delegate: delegate, - primaryCoinId: pick(json, 'primary_coin_id').letStringOrThrow(Bytes.fromHex), - primaryCoinMessage: pick(json, 'primary_coin_message').letStringOrThrow(Bytes.fromHex), + primaryCoinId: + pick(json, 'primary_coin_id').letStringOrThrow(Bytes.fromHex), + primaryCoinMessage: + pick(json, 'primary_coin_message').letStringOrThrow(Bytes.fromHex), ); } diff --git a/lib/src/custom_coins/dependent_coin/service/dependent_coin_wallet_service.dart b/lib/src/custom_coins/dependent_coin/service/dependent_coin_wallet_service.dart index 303040ae..f36723d4 100644 --- a/lib/src/custom_coins/dependent_coin/service/dependent_coin_wallet_service.dart +++ b/lib/src/custom_coins/dependent_coin/service/dependent_coin_wallet_service.dart @@ -48,7 +48,11 @@ class DependentCoinWalletService { final creationSpendBundle = standardWalletService.createSpendBundle( payments: dependentCoins .map( - (e) => Payment(amountPerCoin, e.puzzlehash, memos: [e.primaryCoinId]), + (e) => Payment( + amountPerCoin, + e.puzzlehash, + memos: [e.primaryCoinId], + ), ) .toList(), coinsInput: coins, @@ -58,7 +62,10 @@ class DependentCoinWalletService { fee: fee, ); - return DependentCoinsWithCreationBundle(creationSpendBundle, dependentCoins); + return DependentCoinsWithCreationBundle( + creationSpendBundle, + dependentCoins, + ); } SpendBundle createFeeCoinSpendBundle({ @@ -69,7 +76,9 @@ class DependentCoinWalletService { CoinSpend( coin: dependentCoin, puzzleReveal: dependentCoin.fullPuzzle, - solution: makeSolutionFromConditions([ReserveFeeCondition(dependentCoin.amount)]), + solution: makeSolutionFromConditions( + [ReserveFeeCondition(dependentCoin.amount)], + ), ), ], ); @@ -87,7 +96,10 @@ class DependentCoinWalletService { puzzleReveal: dependentCoin.fullPuzzle, solution: makeSolutionFromConditions([ ReserveFeeCondition(fee), - CreateCoinCondition(destinationPuzzlehash, dependentCoin.amount - fee), + CreateCoinCondition( + destinationPuzzlehash, + dependentCoin.amount - fee, + ), ]), ), ], @@ -115,8 +127,10 @@ class PrimaryCoinInfo { class DependentCoinsWithCreationBundle { DependentCoinsWithCreationBundle(this.creationBundle, this.dependentCoins); factory DependentCoinsWithCreationBundle.fromJson(Map json) { - final dependentCoins = pick(json, 'dependent_coins').letJsonListOrThrow(DependentCoin.fromJson); - final creationBundle = pick(json, 'creation_bundle').letJsonOrThrow(SpendBundle.fromJson); + final dependentCoins = pick(json, 'dependent_coins') + .letJsonListOrThrow(DependentCoin.fromJson); + final creationBundle = + pick(json, 'creation_bundle').letJsonOrThrow(SpendBundle.fromJson); return DependentCoinsWithCreationBundle(creationBundle, dependentCoins); } @@ -124,12 +138,15 @@ class DependentCoinsWithCreationBundle { final List dependentCoins; Map get primaryIdToDependantCoinMap { - return Map.fromEntries(dependentCoins.map((e) => MapEntry(e.primaryCoinId, e))); + return Map.fromEntries( + dependentCoins.map((e) => MapEntry(e.primaryCoinId, e)), + ); } Map toJson() { return { - 'dependent_coins': dependentCoins.map((e) => e.dependentCoinToJson()).toList(), + 'dependent_coins': + dependentCoins.map((e) => e.dependentCoinToJson()).toList(), 'creation_bundle': creationBundle.toJson(), }; } diff --git a/lib/src/did/models/chia_did_info.dart b/lib/src/did/models/chia_did_info.dart index 7c303f1b..2d73a34f 100644 --- a/lib/src/did/models/chia_did_info.dart +++ b/lib/src/did/models/chia_did_info.dart @@ -17,7 +17,8 @@ class ChiaDidInfo with ToJsonMixin { }); factory ChiaDidInfo.fromJson(Map json) { return ChiaDidInfo( - originCoin: pick(json, 'origin_coin').letJsonOrThrow(CoinPrototype.fromJson), + originCoin: + pick(json, 'origin_coin').letJsonOrThrow(CoinPrototype.fromJson), backupIds: pick(json, 'backup_ids').letStringListOrNull(Bytes.fromHex), requiredBackupIds: pick(json, 'num_of_backup_ids_needed').asIntOrNull(), parentInfo: pick(json, 'parent_info').letListOrNull((listItem) { @@ -27,13 +28,18 @@ class ChiaDidInfo with ToJsonMixin { LineageProof.fromJson(typed[1] as Map), ); }), - currentInnerPuzzle: pick(json, 'current_inner').letStringOrThrow(Program.deserializeHex), - metadata: pick(json, 'metadata') - .letJsonOrNull((json) => json.map((key, value) => MapEntry(key, value.toString()))), + currentInnerPuzzle: + pick(json, 'current_inner').letStringOrThrow(Program.deserializeHex), + metadata: pick(json, 'metadata').letJsonOrNull( + (json) => json.map((key, value) => MapEntry(key, value.toString())), + ), tempCoin: pick(json, 'temp_coin').letJsonOrNull(CoinPrototype.fromJson), - tempPuzzlehash: pick(json, 'temp_puzhash').letStringOrNull(Puzzlehash.fromHex), - tempPubkey: pick(json, 'temp_pubkey').letStringOrNull(JacobianPoint.fromHexG1), - sentRecoveryTransaction: pick(json, 'sent_recovery_transaction').asBoolOrNull(), + tempPuzzlehash: + pick(json, 'temp_puzhash').letStringOrNull(Puzzlehash.fromHex), + tempPubkey: + pick(json, 'temp_pubkey').letStringOrNull(JacobianPoint.fromHexG1), + sentRecoveryTransaction: + pick(json, 'sent_recovery_transaction').asBoolOrNull(), ); } @@ -57,7 +63,8 @@ class ChiaDidInfo with ToJsonMixin { 'origin_coin': originCoin.toJson(), 'backup_ids': backupIds?.map((id) => id.toHex()).toList(), 'num_of_backup_ids_needed': requiredBackupIds, - 'parent_info': parentInfo?.map((e) => [e.item1.toHex(), e.item2.toJson()]).toList(), + 'parent_info': + parentInfo?.map((e) => [e.item1.toHex(), e.item2.toJson()]).toList(), 'current_inner': currentInnerPuzzle.toHex(), 'temp_coin': null, 'temp_puzhash': null, diff --git a/lib/src/did/models/conditions/did_exit_condition.dart b/lib/src/did/models/conditions/did_exit_condition.dart index d19ec16c..55b34ce9 100644 --- a/lib/src/did/models/conditions/did_exit_condition.dart +++ b/lib/src/did/models/conditions/did_exit_condition.dart @@ -32,7 +32,8 @@ class DidExitCondition implements Condition { if (conditionParts.length != 3) { return false; } - if (conditionParts[0].toInt() != conditionCode || conditionParts[2].toInt() != magicNumber) { + if (conditionParts[0].toInt() != conditionCode || + conditionParts[2].toInt() != magicNumber) { return false; } return true; diff --git a/lib/src/did/models/did.dart b/lib/src/did/models/did.dart index 22249961..a6ad4a11 100644 --- a/lib/src/did/models/did.dart +++ b/lib/src/did/models/did.dart @@ -43,7 +43,9 @@ class DidInfo implements DidRecord { return Bytes.fromHex(serializedDid); } - Future fetchOriginCoin(ChiaFullNodeInterface fullNode) async { + Future fetchOriginCoin( + ChiaFullNodeInterface fullNode, + ) async { final originCoin = await fullNode.getCoinById(did); if (originCoin != null) { diff --git a/lib/src/did/models/did_info_with_origin_coin.dart b/lib/src/did/models/did_info_with_origin_coin.dart index cb04502a..2955e744 100644 --- a/lib/src/did/models/did_info_with_origin_coin.dart +++ b/lib/src/did/models/did_info_with_origin_coin.dart @@ -2,7 +2,10 @@ import 'package:chia_crypto_utils/chia_crypto_utils.dart'; import 'package:tuple/tuple.dart'; class DidInfoWithOriginCoin with DidInfoDecoratorMixin, ToJsonMixin { - const DidInfoWithOriginCoin({required this.didInfo, required this.originCoin}); + const DidInfoWithOriginCoin({ + required this.didInfo, + required this.originCoin, + }); @override final DidInfo didInfo; diff --git a/lib/src/did/models/did_metadata.dart b/lib/src/did/models/did_metadata.dart index 324f7a59..759ade3f 100644 --- a/lib/src/did/models/did_metadata.dart +++ b/lib/src/did/models/did_metadata.dart @@ -29,7 +29,12 @@ class DidMetadata with ToProgramMixin { return Program.list( map.entries - .map((e) => Program.cons(Program.fromString(e.key), Program.fromString(e.value))) + .map( + (e) => Program.cons( + Program.fromString(e.key), + Program.fromString(e.value), + ), + ) .toList(), ); } diff --git a/lib/src/did/models/did_record.dart b/lib/src/did/models/did_record.dart index d83e7236..2e82d108 100644 --- a/lib/src/did/models/did_record.dart +++ b/lib/src/did/models/did_record.dart @@ -15,11 +15,17 @@ abstract class DidRecord { required List hints, required CoinSpend parentSpend, }) = _DidRecord; - static DidRecord? fromParentCoinSpend(CoinSpend parentSpend, CoinPrototype coin) { + static DidRecord? fromParentCoinSpend( + CoinSpend parentSpend, + CoinPrototype coin, + ) { return _DidRecord.fromParentCoinSpend(parentSpend, coin); } - static Future fromParentCoinSpendAsync(CoinSpend parentSpend, CoinPrototype coin) { + static Future fromParentCoinSpendAsync( + CoinSpend parentSpend, + CoinPrototype coin, + ) { return _DidRecord.fromParentCoinSpendAsync(parentSpend, coin); } @@ -58,7 +64,10 @@ class _DidRecord implements DidRecord { required this.parentSpend, }); - static DidRecord? fromParentCoinSpend(CoinSpend parentSpend, CoinPrototype coin) { + static DidRecord? fromParentCoinSpend( + CoinSpend parentSpend, + CoinPrototype coin, + ) { final uncurriedPuzzle = parentSpend.puzzleReveal.uncurry(); if (uncurriedPuzzle.mod != singletonTopLayerV1Program) { return null; @@ -76,7 +85,8 @@ class _DidRecord implements DidRecord { // check for exit spend final innerSolution = parentSpend.solution.rest().rest().first(); - final didExitConditions = DIDWalletService.extractP2ConditionsFromInnerSolution( + final didExitConditions = + DIDWalletService.extractP2ConditionsFromInnerSolution( innerSolution, DidExitCondition.isThisCondition, DidExitCondition.fromProgram, @@ -87,7 +97,8 @@ class _DidRecord implements DidRecord { } // inner puzzle is second curried argument of did full puzzle - final uncurriedInnerPuzzle = UncurriedDidInnerPuzzle.fromProgram(parentInnerPuzzle); + final uncurriedInnerPuzzle = + UncurriedDidInnerPuzzle.fromProgram(parentInnerPuzzle); return _constructDidRecord( coin: coin, @@ -120,7 +131,8 @@ class _DidRecord implements DidRecord { // check for exit spend final innerSolution = parentSpend.solution.rest().rest().first(); - final didExitConditions = DIDWalletService.extractP2ConditionsFromInnerSolution( + final didExitConditions = + DIDWalletService.extractP2ConditionsFromInnerSolution( innerSolution, DidExitCondition.isThisCondition, DidExitCondition.fromProgram, @@ -131,7 +143,8 @@ class _DidRecord implements DidRecord { } // inner puzzle is second curried argument of did full puzzle - final uncurriedInnerPuzzle = await UncurriedDidInnerPuzzle.fromProgramAsync(parentInnerPuzzle); + final uncurriedInnerPuzzle = + await UncurriedDidInnerPuzzle.fromProgramAsync(parentInnerPuzzle); return _constructDidRecord( coin: coin, @@ -179,7 +192,8 @@ class _DidRecord implements DidRecord { } }(); - final createCoinConditions = BaseWalletService.extractConditionsFromProgramList( + final createCoinConditions = + BaseWalletService.extractConditionsFromProgramList( parentSpend.outputProgram.toList(), CreateCoinCondition.isThisCondition, CreateCoinCondition.fromProgram, @@ -219,7 +233,8 @@ class _DidRecord implements DidRecord { case SpendMode.recovery: //puzzle has been changed: new pubkey final publicKeyBytes = innerSolution.toList()[4].atom; - final uncurriedInnerPuzzle = UncurriedDidInnerPuzzle.fromProgram(parentInnerPuzzle); + final uncurriedInnerPuzzle = + UncurriedDidInnerPuzzle.fromProgram(parentInnerPuzzle); final didInnerPuzzle = DIDWalletService.createInnerPuzzleForPk( publicKey: JacobianPoint.fromBytesG1(publicKeyBytes), @@ -264,7 +279,9 @@ class _DidRecord implements DidRecord { DidRecord copyWith({ required Puzzlehash backUpIdsHash, }) { - final backupIds = backUpIdsHash == Program.list([]).hash() ? [] : this.backupIds; + final backupIds = backUpIdsHash == Program.list([]).hash() + ? [] + : this.backupIds; return _DidRecord( did: did, coin: coin, @@ -379,13 +396,17 @@ extension ToSpendableDid on DidRecord { taskArgument: keychain, isolateTask: _toDidInfoTask, handleTaskCompletion: (taskResultJson) { - final innerPuzzle = pick(taskResultJson, 'inner_puzzle').asStringOrNull(); + final innerPuzzle = + pick(taskResultJson, 'inner_puzzle').asStringOrNull(); if (innerPuzzle == null) { return null; } - return DidInfo(delegate: this, innerPuzzle: Program.deserialize(innerPuzzle.hexToBytes())); + return DidInfo( + delegate: this, + innerPuzzle: Program.deserialize(innerPuzzle.hexToBytes()), + ); }, ); } @@ -408,5 +429,6 @@ extension ToSpendableDid on DidRecord { } extension HashBytesList on Iterable { - Puzzlehash programHash() => Program.list(map(Program.fromAtom).toList()).hash(); + Puzzlehash programHash() => + Program.list(map(Program.fromAtom).toList()).hash(); } diff --git a/lib/src/did/models/did_record_with_origin_coin.dart b/lib/src/did/models/did_record_with_origin_coin.dart index 4bb5ff4f..58726b80 100644 --- a/lib/src/did/models/did_record_with_origin_coin.dart +++ b/lib/src/did/models/did_record_with_origin_coin.dart @@ -1,7 +1,10 @@ import 'package:chia_crypto_utils/chia_crypto_utils.dart'; class DidRecordWithOriginCoin { - const DidRecordWithOriginCoin({required this.didRecord, required this.originCoin}); + const DidRecordWithOriginCoin({ + required this.didRecord, + required this.originCoin, + }); final DidRecord didRecord; final CoinPrototype originCoin; @@ -16,7 +19,9 @@ class DidRecordWithOriginCoin { return null; } - Future toDidInfoWithOriginCoinAsync(WalletKeychain keychain) async { + Future toDidInfoWithOriginCoinAsync( + WalletKeychain keychain, + ) async { final didInfo = await didRecord.toDidInfoAsync(keychain); if (didInfo != null) { diff --git a/lib/src/did/models/full_did_record.dart b/lib/src/did/models/full_did_record.dart index 8f210be8..4ef74e37 100644 --- a/lib/src/did/models/full_did_record.dart +++ b/lib/src/did/models/full_did_record.dart @@ -35,7 +35,8 @@ class FullDidRecord implements DidRecord { Program get singletonStructure => delegate.singletonStructure; @override - DidInfo? toDidInfoForPk(JacobianPoint publicKey) => delegate.toDidInfoForPk(publicKey); + DidInfo? toDidInfoForPk(JacobianPoint publicKey) => + delegate.toDidInfoForPk(publicKey); @override DidInfo? toDidInfoFromParentInfo() => delegate.toDidInfoFromParentInfo(); @@ -50,8 +51,12 @@ class FullDidRecord implements DidRecord { return null; } - static Future fromParentCoinSpendAsync(CoinSpend parentSpend, Coin coin) async { - final didRecord = await DidRecord.fromParentCoinSpendAsync(parentSpend, coin); + static Future fromParentCoinSpendAsync( + CoinSpend parentSpend, + Coin coin, + ) async { + final didRecord = + await DidRecord.fromParentCoinSpendAsync(parentSpend, coin); if (didRecord != null) { return FullDidRecord(didRecord, coin); @@ -60,11 +65,16 @@ class FullDidRecord implements DidRecord { return null; } - Future fetchOriginCoin(ChiaFullNodeInterface fullNode) async { + Future fetchOriginCoin( + ChiaFullNodeInterface fullNode, + ) async { final originCoin = await fullNode.getCoinById(did); if (originCoin != null) { - return FullDidRecordWithOriginCoin(didRecord: this, originCoin: originCoin); + return FullDidRecordWithOriginCoin( + didRecord: this, + originCoin: originCoin, + ); } return null; diff --git a/lib/src/did/models/full_did_record_with_origin_coin.dart b/lib/src/did/models/full_did_record_with_origin_coin.dart index a921e3df..061b2689 100644 --- a/lib/src/did/models/full_did_record_with_origin_coin.dart +++ b/lib/src/did/models/full_did_record_with_origin_coin.dart @@ -1,7 +1,10 @@ import 'package:chia_crypto_utils/chia_crypto_utils.dart'; class FullDidRecordWithOriginCoin { - const FullDidRecordWithOriginCoin({required this.didRecord, required this.originCoin}); + const FullDidRecordWithOriginCoin({ + required this.didRecord, + required this.originCoin, + }); final FullDidRecord didRecord; final CoinPrototype originCoin; diff --git a/lib/src/did/models/mixins/did_info_decorator_mixin.dart b/lib/src/did/models/mixins/did_info_decorator_mixin.dart index ac46c2ce..7427c935 100644 --- a/lib/src/did/models/mixins/did_info_decorator_mixin.dart +++ b/lib/src/did/models/mixins/did_info_decorator_mixin.dart @@ -52,12 +52,15 @@ mixin DidInfoDecoratorMixin implements DidInfo { Program get p2Puzzle => didInfo.p2Puzzle; @override - DidInfo toDidInfoForPk(JacobianPoint publicKey) => didInfo.toDidInfoForPk(publicKey); + DidInfo toDidInfoForPk(JacobianPoint publicKey) => + didInfo.toDidInfoForPk(publicKey); @override DidInfo toDidInfoFromParentInfo() => didInfo.toDidInfoFromParentInfo(); @override - Future fetchOriginCoin(ChiaFullNodeInterface fullNode) => + Future fetchOriginCoin( + ChiaFullNodeInterface fullNode, + ) => didInfo.fetchOriginCoin(fullNode); } diff --git a/lib/src/did/models/uncurried_did_inner_puzzle.dart b/lib/src/did/models/uncurried_did_inner_puzzle.dart index 9d92b5dd..05574857 100644 --- a/lib/src/did/models/uncurried_did_inner_puzzle.dart +++ b/lib/src/did/models/uncurried_did_inner_puzzle.dart @@ -23,8 +23,11 @@ class UncurriedDidInnerPuzzle { return maybeFromUncurriedProgram(uncurriedPuzzle); } - static Future fromProgramAsync(Program innerPuzzle) async { - final uncurried = maybeFromUncurriedProgram(await innerPuzzle.uncurryAsync()); + static Future fromProgramAsync( + Program innerPuzzle, + ) async { + final uncurried = + maybeFromUncurriedProgram(await innerPuzzle.uncurryAsync()); if (uncurried == null) { throw InvalidDidException(); } @@ -32,7 +35,9 @@ class UncurriedDidInnerPuzzle { return uncurried; } - static UncurriedDidInnerPuzzle? maybeFromUncurriedProgram(ModAndArguments uncurriedPuzzle) { + static UncurriedDidInnerPuzzle? maybeFromUncurriedProgram( + ModAndArguments uncurriedPuzzle, + ) { if (uncurriedPuzzle.mod != didInnerPuzzleProgram) { return null; } @@ -53,7 +58,8 @@ class UncurriedDidInnerPuzzle { final Program singletonStructureProgram; final Program metadataProgram; - int get nVerificationsRequired => numberOfVerificationsRequiredProgram.toInt(); + int get nVerificationsRequired => + numberOfVerificationsRequiredProgram.toInt(); Puzzlehash get backUpIdsHash => Puzzlehash(backUpIdsHashProgram.atom); DidMetadata get metadata => DidMetadata.fromProgram(metadataProgram); } diff --git a/lib/src/did/models/uncurried_did_puzzle.dart b/lib/src/did/models/uncurried_did_puzzle.dart index 1c712ba1..6b678423 100644 --- a/lib/src/did/models/uncurried_did_puzzle.dart +++ b/lib/src/did/models/uncurried_did_puzzle.dart @@ -21,7 +21,9 @@ class UncurriedDidPuzzle { return maybeFromUncurriedProgram(uncurriedPuzzle); } - static UncurriedDidPuzzle? maybeFromUncurriedProgram(ModAndArguments uncurriedPuzzle) { + static UncurriedDidPuzzle? maybeFromUncurriedProgram( + ModAndArguments uncurriedPuzzle, + ) { if (uncurriedPuzzle.mod != singletonTopLayerV1Program) { return null; } @@ -31,7 +33,8 @@ class UncurriedDidPuzzle { final parentInnerPuzzle = arguments[1]; final did = singletonStructure.rest().first().atom; - final uncurriedInnerPuzzle = UncurriedDidInnerPuzzle.maybeFromProgram(parentInnerPuzzle); + final uncurriedInnerPuzzle = + UncurriedDidInnerPuzzle.maybeFromProgram(parentInnerPuzzle); if (uncurriedInnerPuzzle == null) { return null; } diff --git a/lib/src/did/service/did_signing_service.dart b/lib/src/did/service/did_signing_service.dart index 6d4136f7..c8b654df 100644 --- a/lib/src/did/service/did_signing_service.dart +++ b/lib/src/did/service/did_signing_service.dart @@ -35,7 +35,10 @@ class PrivateKeyDidSigningService implements DidSigningService { SpendBundle didBundle, ) async { return didBundle - .signWithPrivateKey(didPrivateKey, filterCoinSpends: DidSigningService._isDidSpend) + .signWithPrivateKey( + didPrivateKey, + filterCoinSpends: DidSigningService._isDidSpend, + ) .signedBundle .aggregatedSignature!; } @@ -111,7 +114,8 @@ class WalletConnectDidSigningService implements DidSigningService { singletonStructure: didRecord.singletonStructure, backUpIdsHash: didRecord.backUpIdsHash, nVerificationsRequired: didRecord.nVerificationsRequired, - backupIds: chiaDidInfo.backupIds?.map(Puzzlehash.new).toList() ?? didRecord.backupIds, + backupIds: chiaDidInfo.backupIds?.map(Puzzlehash.new).toList() ?? + didRecord.backupIds, hints: didRecord.hints, parentSpend: didRecord.parentSpend, ), @@ -122,13 +126,17 @@ class WalletConnectDidSigningService implements DidSigningService { /// throws [MissingDidException] if the did is not found in any of the connected fingerprints @override Future signDidBundle(SpendBundle didBundle) async { - final uncurriedDidPuzzle = - UncurriedDidPuzzle.fromProgram(didBundle.coinSpends.single.puzzleReveal); - final fingerprint = (await _getChiaDidInfoForDid(uncurriedDidPuzzle.did)).fingerprint; + final uncurriedDidPuzzle = UncurriedDidPuzzle.fromProgram( + didBundle.coinSpends.single.puzzleReveal, + ); + final fingerprint = + (await _getChiaDidInfoForDid(uncurriedDidPuzzle.did)).fingerprint; return _withInitializedClient((client) async { - final response = - await client.signSpendBundle(fingerprint: fingerprint, spendBundle: didBundle); + final response = await client.signSpendBundle( + fingerprint: fingerprint, + spendBundle: didBundle, + ); return response.signature; }); @@ -146,8 +154,9 @@ class WalletConnectDidSigningService implements DidSigningService { ); for (final walletInfo in response.wallets) { try { - final didWalletInfo = - ChiaDidInfo.fromJson(jsonDecode(walletInfo.data) as Map); + final didWalletInfo = ChiaDidInfo.fromJson( + jsonDecode(walletInfo.data) as Map, + ); if (didWalletInfo.did == did) { return ChiaDidInfoWithFingerprint(fingerprint, didWalletInfo); } diff --git a/lib/src/did/service/wallet.dart b/lib/src/did/service/wallet.dart index 3dc69b77..17be7be2 100644 --- a/lib/src/did/service/wallet.dart +++ b/lib/src/did/service/wallet.dart @@ -17,7 +17,11 @@ class DIDWalletService extends BaseWalletService { Puzzlehash newInnerPuzzlehash, ) { final p2Solution = BaseWalletService.makeSolutionFromConditions([ - CreateCoinCondition(newInnerPuzzlehash, didInfo.coin.amount, memos: [newInnerPuzzlehash]), + CreateCoinCondition( + newInnerPuzzlehash, + didInfo.coin.amount, + memos: [newInnerPuzzlehash], + ), ]); final innerSolution = makeRunInnerPuzzleModeInnerSolution(p2Solution); @@ -27,10 +31,15 @@ class DIDWalletService extends BaseWalletService { Program.fromInt(didInfo.coin.amount), innerSolution, ]); - final coinSpend = - CoinSpend(coin: didInfo.coin, puzzleReveal: didInfo.fullPuzzle, solution: fullSolution); + final coinSpend = CoinSpend( + coin: didInfo.coin, + puzzleReveal: didInfo.fullPuzzle, + solution: fullSolution, + ); - return SpendBundle(coinSpends: [coinSpend]).signWithPrivateKey(privateKey).signedBundle; + return SpendBundle(coinSpends: [coinSpend]) + .signWithPrivateKey(privateKey) + .signedBundle; } SpendBundle createExitSpend( @@ -60,7 +69,9 @@ class DIDWalletService extends BaseWalletService { solution: fullSolution, ); - return SpendBundle(coinSpends: [coinSpend]).signWithPrivateKey(privateKey).signedBundle; + return SpendBundle(coinSpends: [coinSpend]) + .signWithPrivateKey(privateKey) + .signedBundle; } SpendBundle createRecoverySpendBundle( @@ -71,7 +82,8 @@ class DIDWalletService extends BaseWalletService { List recoveryIds, SpendBundle messageSpendBundle, ) { - final recoveringDidInfo = recoveringDidRecord.toDidInfoFromParentInfoOrThrow(); + final recoveringDidInfo = + recoveringDidRecord.toDidInfoFromParentInfoOrThrow(); final recoveringCoin = recoveringDidInfo.coin; final newPublicKey = newPrivateKey.getG1(); @@ -85,15 +97,23 @@ class DIDWalletService extends BaseWalletService { ); final innerPuzzle = recoveringDidInfo.innerPuzzle; - final fullPuzzle = DIDWalletService.makeFullPuzzle(innerPuzzle, recoveringDidInfo.did); + final fullPuzzle = + DIDWalletService.makeFullPuzzle(innerPuzzle, recoveringDidInfo.did); final parentInfo = recoveringDidInfo.lineageProof; final fullSolution = Program.list( - [parentInfo.toProgram(), Program.fromInt(recoveringCoin.amount), innerSolution], + [ + parentInfo.toProgram(), + Program.fromInt(recoveringCoin.amount), + innerSolution + ], ); - final coinSpend = - CoinSpend(coin: recoveringCoin, puzzleReveal: fullPuzzle, solution: fullSolution); + final coinSpend = CoinSpend( + coin: recoveringCoin, + puzzleReveal: fullPuzzle, + solution: fullSolution, + ); final message = newInnerPuzzlehash; final sigs = [AugSchemeMPL.sign(newPrivateKey, message)]; @@ -102,7 +122,8 @@ class DIDWalletService extends BaseWalletService { } final aggSigs = AugSchemeMPL.aggregate(sigs); - return SpendBundle(coinSpends: [coinSpend], signatures: {aggSigs}) + messageSpendBundle; + return SpendBundle(coinSpends: [coinSpend], signatures: {aggSigs}) + + messageSpendBundle; } SpendBundle createTransferSpendBundle({ @@ -133,10 +154,12 @@ class DIDWalletService extends BaseWalletService { List puzzlesToAnnounce = const [], List createCoinAnnouncements = const [], List assertCoinAnnouncements = const [], - List assertPuzzleAnnouncements = const [], + List assertPuzzleAnnouncements = + const [], required WalletKeychain keychain, }) { - final walletVector = keychain.getWalletVectorOrThrow(didInfo.p2Puzzle.hash()); + final walletVector = + keychain.getWalletVectorOrThrow(didInfo.p2Puzzle.hash()); return createSpendBundleFromPrivateKey( didInfo: didInfo, @@ -159,7 +182,8 @@ class DIDWalletService extends BaseWalletService { List puzzlesToAnnounce = const [], List createCoinAnnouncements = const [], List assertCoinAnnouncements = const [], - List assertPuzzleAnnouncements = const [], + List assertPuzzleAnnouncements = + const [], }) { final spendBundle = createUnsignedSpendBundle( didInfo: didInfo, @@ -185,18 +209,21 @@ class DIDWalletService extends BaseWalletService { List puzzlesToAnnounce = const [], List createCoinAnnouncements = const [], List assertCoinAnnouncements = const [], - List assertPuzzleAnnouncements = const [], + List assertPuzzleAnnouncements = + const [], }) { final newInnerPuzzleHash = () { if (newP2Puzzlehash == null) { return didInfo.innerPuzzle.hash(); } - final uncurriedParent = UncurriedDidInnerPuzzle.fromProgram(didInfo.innerPuzzle); + final uncurriedParent = + UncurriedDidInnerPuzzle.fromProgram(didInfo.innerPuzzle); return calculateInnerPuzzleHash( p2Puzzlehash: newP2Puzzlehash, backupIdsHashProgram: uncurriedParent.backUpIdsHashProgram, - nVerificationsRequiredProgram: uncurriedParent.numberOfVerificationsRequiredProgram, + nVerificationsRequiredProgram: + uncurriedParent.numberOfVerificationsRequiredProgram, singletonStructure: uncurriedParent.singletonStructureProgram, metadataProgram: uncurriedParent.metadataProgram, ); @@ -251,20 +278,29 @@ class DIDWalletService extends BaseWalletService { }) { final recoveringCoinId = recoveringDidInfo.coin.id; - final messagePuzzle = - makeRecoveryMessagePuzzle(recoveringCoinId, newInnerPuzzlehash, newPublicKey); + final messagePuzzle = makeRecoveryMessagePuzzle( + recoveringCoinId, + newInnerPuzzlehash, + newPublicKey, + ); final innerMessage = messagePuzzle.hash(); final innerPuzzle = attestmentMakerDidInfo.innerPuzzle; final p2Solution = BaseWalletService.makeSolutionFromConditions([ - CreateCoinCondition(innerPuzzle.hash(), attestmentMakerDidInfo.coin.amount), + CreateCoinCondition( + innerPuzzle.hash(), + attestmentMakerDidInfo.coin.amount, + ), CreateCoinCondition(innerMessage, 0), ]); final innerSolution = makeRunInnerPuzzleModeInnerSolution(p2Solution); - final fullPuzzle = DIDWalletService.makeFullPuzzle(innerPuzzle, attestmentMakerDidInfo.did); + final fullPuzzle = DIDWalletService.makeFullPuzzle( + innerPuzzle, + attestmentMakerDidInfo.did, + ); final parentInfo = attestmentMakerDidInfo.lineageProof; final fullSolution = Program.list([ @@ -279,14 +315,18 @@ class DIDWalletService extends BaseWalletService { solution: fullSolution, ); - final messageSpend = createSpendForMessage(attestmentMakerDidInfo.coin.id, messagePuzzle); + final messageSpend = + createSpendForMessage(attestmentMakerDidInfo.coin.id, messagePuzzle); final messageSpendBundle = SpendBundle(coinSpends: [messageSpend]); final spendBundle = SpendBundle(coinSpends: [coinSpend]) .signWithPrivateKey(attestmentMakerPrivateKey) .signedBundle; - return Attestment(attestmentSpendBundle: spendBundle, messageSpendBundle: messageSpendBundle); + return Attestment( + attestmentSpendBundle: spendBundle, + messageSpendBundle: messageSpendBundle, + ); } static Program makeRecoveryMessagePuzzle( @@ -305,14 +345,21 @@ class DIDWalletService extends BaseWalletService { ]); } - static CoinSpend createSpendForMessage(Bytes attestmentMakerCoinId, Program messagePuzzle) { + static CoinSpend createSpendForMessage( + Bytes attestmentMakerCoinId, + Program messagePuzzle, + ) { final coin = CoinPrototype( parentCoinInfo: attestmentMakerCoinId, puzzlehash: messagePuzzle.hash(), amount: 0, ); final solution = Program.list([]); - return CoinSpend(coin: coin, puzzleReveal: messagePuzzle, solution: solution); + return CoinSpend( + coin: coin, + puzzleReveal: messagePuzzle, + solution: solution, + ); } SpendBundle createGenerateDIDSpendBundle({ @@ -342,7 +389,8 @@ class DIDWalletService extends BaseWalletService { final didInnerPuzzle = createInnerPuzzle( p2Puzzle: p2Puzzle, - backupIdsHash: Program.list(backupIds.map(Program.fromAtom).toList()).hash(), + backupIdsHash: + Program.list(backupIds.map(Program.fromAtom).toList()).hash(), launcherCoinId: launcherId, nVerificationsRequired: nVerificationsRequired ?? backupIds.length, metadataProgram: metadata?.toProgram(), @@ -359,7 +407,9 @@ class DIDWalletService extends BaseWalletService { final announcementMessage = genesisLauncherSolution.hash(); - final announcements = [AssertCoinAnnouncementCondition(launcherId, announcementMessage)]; + final announcements = [ + AssertCoinAnnouncementCondition(launcherId, announcementMessage) + ]; final standardSpendBundle = standardWalletService.createSpendBundle( payments: [Payment(amount, singletonLauncherProgram.hash())], @@ -445,10 +495,12 @@ class DIDWalletService extends BaseWalletService { WalletKeychain keychain, ) { for (final coinSpend in spendBundle.coinSpends) { - final unCurriedNftPuzzle = UncurriedDidPuzzle.maybeFromProgram(coinSpend.puzzleReveal); + final unCurriedNftPuzzle = + UncurriedDidPuzzle.maybeFromProgram(coinSpend.puzzleReveal); if (unCurriedNftPuzzle != null) { final p2Puzzlehash = unCurriedNftPuzzle.innerPuzzle.p2Puzzle.hash(); - final privateKey = keychain.getWalletVector(p2Puzzlehash)!.childPrivateKey; + final privateKey = + keychain.getWalletVector(p2Puzzlehash)!.childPrivateKey; return spendBundle.signWithPrivateKey(privateKey).signedBundle; } } @@ -462,7 +514,8 @@ class DIDWalletService extends BaseWalletService { required int nVerificationsRequired, required Program? metadataProgram, }) { - final singletonStructure = SingletonService.makeSingletonStructureProgram(launcherCoinId); + final singletonStructure = + SingletonService.makeSingletonStructureProgram(launcherCoinId); return constructInnerPuzzle( p2Puzzle: p2Puzzle, @@ -526,9 +579,11 @@ class DIDWalletService extends BaseWalletService { Program didInnerPuzzle, Bytes launcherCoinId, ) { - final singletonStructure = SingletonService.makeSingletonStructureProgram(launcherCoinId); + final singletonStructure = + SingletonService.makeSingletonStructureProgram(launcherCoinId); - return singletonTopLayerV1Program.curry([singletonStructure, didInnerPuzzle]); + return singletonTopLayerV1Program + .curry([singletonStructure, didInnerPuzzle]); } static Program makeRecoveryModeInnerSolution({ @@ -562,7 +617,8 @@ class DIDWalletService extends BaseWalletService { ConditionChecker conditionChecker, ConditionFromProgramConstructor conditionFromProgramConstructor, ) { - if (SpendMode.fromCode(solution.toList()[0].toInt()) != SpendMode.runInnerPuzzle) { + if (SpendMode.fromCode(solution.toList()[0].toInt()) != + SpendMode.runInnerPuzzle) { return []; } return BaseWalletService.extractConditionsFromSolution( diff --git a/lib/src/exchange/btc/cross_chain_offer/models/btc_to_xch_maker_offer_file.dart b/lib/src/exchange/btc/cross_chain_offer/models/btc_to_xch_maker_offer_file.dart index ad24253a..aa73dd10 100644 --- a/lib/src/exchange/btc/cross_chain_offer/models/btc_to_xch_maker_offer_file.dart +++ b/lib/src/exchange/btc/cross_chain_offer/models/btc_to_xch_maker_offer_file.dart @@ -3,27 +3,25 @@ import 'package:compute/compute.dart'; class BtcToXchMakerOfferFile implements MakerCrossChainOfferFile { BtcToXchMakerOfferFile({ - this.initializationCoinId, + required this.initializationCoinId, required this.offeredAmount, required this.requestedAmount, required this.messageAddress, required this.validityTime, required this.publicKey, }); - factory BtcToXchMakerOfferFile.fromJson(Map json) { - return BtcToXchMakerOfferFile( - initializationCoinId: (json['initialization_coin_id'] as String?)?.hexToBytes(), - offeredAmount: ExchangeAmount.fromJson(json['offered'] as Map), - requestedAmount: ExchangeAmount.fromJson(json['requested'] as Map), - messageAddress: - Address((json['message_address'] as Map)['address'] as String), - validityTime: json['validity_time'] as int, - publicKey: JacobianPoint.fromHexG1(json['public_key'] as String), - ); + + factory BtcToXchMakerOfferFile._fromSerializedOfferFileTask( + String serializedOfferFile, + ) { + return BtcToXchMakerOfferFile.fromSerializedOfferFile(serializedOfferFile); } - factory BtcToXchMakerOfferFile.fromSerializedOfferFile(String serializedOfferFile) { - final deserializedOfferFile = maybeFromSerializedOfferFile(serializedOfferFile); + factory BtcToXchMakerOfferFile.fromSerializedOfferFile( + String serializedOfferFile, + ) { + final deserializedOfferFile = + maybeFromSerializedOfferFile(serializedOfferFile); if (deserializedOfferFile == null) { throw InvalidCrossChainOfferType(CrossChainOfferFileType.btcToXch.name); @@ -31,12 +29,24 @@ class BtcToXchMakerOfferFile implements MakerCrossChainOfferFile { return deserializedOfferFile; } - factory BtcToXchMakerOfferFile._fromSerializedOfferFileTask(String serializedOfferFile) { - return BtcToXchMakerOfferFile.fromSerializedOfferFile(serializedOfferFile); + factory BtcToXchMakerOfferFile.fromJson(Map json) { + return BtcToXchMakerOfferFile( + initializationCoinId: + (json['initialization_coin_id'] as String).hexToBytes(), + offeredAmount: + ExchangeAmount.fromJson(json['offered'] as Map), + requestedAmount: + ExchangeAmount.fromJson(json['requested'] as Map), + messageAddress: Address( + (json['message_address'] as Map)['address'] as String, + ), + validityTime: json['validity_time'] as int, + publicKey: JacobianPoint.fromHexG1(json['public_key'] as String), + ); } @override - Bytes? initializationCoinId; + final Bytes initializationCoinId; @override final ExchangeAmount offeredAmount; @override @@ -56,18 +66,20 @@ class BtcToXchMakerOfferFile implements MakerCrossChainOfferFile { @override Map toJson() => { - 'initialization_coin_id': initializationCoinId?.toHex(), + 'initialization_coin_id': initializationCoinId.toHex(), 'offered': offeredAmount.toJson(), 'requested': requestedAmount.toJson(), 'message_address': { 'type': messageAddress.prefix, - 'address': messageAddress.address, + 'address': messageAddress.address }, 'validity_time': validityTime, 'public_key': publicKey.toHex(), }; - static BtcToXchMakerOfferFile? maybeFromSerializedOfferFile(String serializedOfferFile) { + static BtcToXchMakerOfferFile? maybeFromSerializedOfferFile( + String serializedOfferFile, + ) { try { final deserializedOfferFile = CrossChainOfferFile.fromSerializedOfferFile(serializedOfferFile); @@ -83,42 +95,12 @@ class BtcToXchMakerOfferFile implements MakerCrossChainOfferFile { static Future fromSerializedOfferFileAsync( String serializedOfferFile, ) async { - final result = - await compute(BtcToXchMakerOfferFile._fromSerializedOfferFileTask, serializedOfferFile); - - return result; - } - - @override - CrossChainOfferExchangeInfo getExchangeInfo( - CrossChainOfferFile offerAcceptFile, - PrivateKey requestorPrivateKey, - ) { - final xchToBtcOfferAcceptFile = offerAcceptFile as XchToBtcTakerOfferFile; - - final amountMojos = requestedAmount.amount; - final amountSatoshis = offeredAmount.amount; - final validityTime = xchToBtcOfferAcceptFile.validityTime; - final paymentRequest = xchToBtcOfferAcceptFile.lightningPaymentRequest; - final paymentHash = paymentRequest.tags.paymentHash!; - final fulfillerPublicKey = xchToBtcOfferAcceptFile.publicKey; - - final escrowPuzzlehash = BtcToXchService.generateEscrowPuzzlehash( - requestorPrivateKey: requestorPrivateKey, - clawbackDelaySeconds: validityTime, - sweepPaymentHash: paymentHash, - fulfillerPublicKey: fulfillerPublicKey, + final result = await compute( + BtcToXchMakerOfferFile._fromSerializedOfferFileTask, + serializedOfferFile, ); - return CrossChainOfferExchangeInfo( - requestorPublicKey: requestorPrivateKey.getG1(), - fulfillerPublicKey: fulfillerPublicKey, - amountMojos: amountMojos, - amountSatoshis: amountSatoshis, - validityTime: validityTime, - escrowPuzzlehash: escrowPuzzlehash, - paymentRequest: paymentRequest, - ); + return result; } @override diff --git a/lib/src/exchange/btc/cross_chain_offer/models/btc_to_xch_taker_offer_file.dart b/lib/src/exchange/btc/cross_chain_offer/models/btc_to_xch_taker_offer_file.dart index 00e26120..da2ef4ae 100644 --- a/lib/src/exchange/btc/cross_chain_offer/models/btc_to_xch_taker_offer_file.dart +++ b/lib/src/exchange/btc/cross_chain_offer/models/btc_to_xch_taker_offer_file.dart @@ -3,57 +3,69 @@ import 'package:compute/compute.dart'; class BtcToXchTakerOfferFile implements TakerCrossChainOfferFile { BtcToXchTakerOfferFile({ - this.initializationCoinId, + required this.initializationCoinId, required this.validityTime, required this.publicKey, required this.acceptedOfferHash, }); - factory BtcToXchTakerOfferFile.fromJson(Map json) { - return BtcToXchTakerOfferFile( - initializationCoinId: (json['initialization_coin_id'] as String?)?.hexToBytes(), - validityTime: json['validity_time'] as int, - publicKey: JacobianPoint.fromHexG1(json['public_key'] as String), - acceptedOfferHash: (json['accepted_offer_hash'] as String).hexToBytes(), - ); + + factory BtcToXchTakerOfferFile._fromSerializedOfferFileTask( + String serializedOfferFile, + ) { + return BtcToXchTakerOfferFile.fromSerializedOfferFile(serializedOfferFile); } - factory BtcToXchTakerOfferFile.fromSerializedOfferFile(String serializedOfferFile) { - final deserializedOfferFile = maybeFromSerializedOfferFile(serializedOfferFile); + factory BtcToXchTakerOfferFile.fromSerializedOfferFile( + String serializedOfferFile, + ) { + final deserializedOfferFile = + maybeFromSerializedOfferFile(serializedOfferFile); if (deserializedOfferFile == null) { - throw InvalidCrossChainOfferType(CrossChainOfferFileType.btcToXchAccept.name); + throw InvalidCrossChainOfferType( + CrossChainOfferFileType.btcToXchAccept.name, + ); } return deserializedOfferFile; } - factory BtcToXchTakerOfferFile._fromSerializedOfferFileTask(String serializedOfferFile) { - return BtcToXchTakerOfferFile.fromSerializedOfferFile(serializedOfferFile); + factory BtcToXchTakerOfferFile.fromJson(Map json) { + return BtcToXchTakerOfferFile( + initializationCoinId: + (json['initialization_coin_id'] as String).hexToBytes(), + validityTime: json['validity_time'] as int, + publicKey: JacobianPoint.fromHexG1(json['public_key'] as String), + acceptedOfferHash: (json['accepted_offer_hash'] as String).hexToBytes(), + ); } @override - Bytes? initializationCoinId; + final Bytes initializationCoinId; @override - int validityTime; + final int validityTime; @override - JacobianPoint publicKey; + final JacobianPoint publicKey; @override - Bytes acceptedOfferHash; + final Bytes acceptedOfferHash; @override LightningPaymentRequest? get lightningPaymentRequest => null; @override Map toJson() => { - 'initialization_coin_id': initializationCoinId?.toHex(), + 'initialization_coin_id': initializationCoinId.toHex(), 'validity_time': validityTime, 'public_key': publicKey.toHex(), 'accepted_offer_hash': acceptedOfferHash.toHex(), }; - static BtcToXchTakerOfferFile? maybeFromSerializedOfferFile(String serializedOfferFile) { + static BtcToXchTakerOfferFile? maybeFromSerializedOfferFile( + String serializedOfferFile, + ) { try { final deserializedOfferFile = CrossChainOfferFile.fromSerializedOfferFile(serializedOfferFile); - if (deserializedOfferFile.type != CrossChainOfferFileType.btcToXchAccept) { + if (deserializedOfferFile.type != + CrossChainOfferFileType.btcToXchAccept) { return null; } return deserializedOfferFile as BtcToXchTakerOfferFile; @@ -65,48 +77,20 @@ class BtcToXchTakerOfferFile implements TakerCrossChainOfferFile { static Future fromSerializedOfferFileAsync( String serializedOfferFile, ) async { - final result = - await compute(BtcToXchTakerOfferFile._fromSerializedOfferFileTask, serializedOfferFile); - - return result; - } - - @override - CrossChainOfferExchangeInfo getExchangeInfo( - CrossChainOfferFile offerFile, - PrivateKey requestorPrivateKey, - ) { - final xchToBtcOfferFile = offerFile as XchToBtcMakerOfferFile; - - final amountMojos = xchToBtcOfferFile.offeredAmount.amount; - final amountSatoshis = xchToBtcOfferFile.requestedAmount.amount; - final paymentRequest = xchToBtcOfferFile.lightningPaymentRequest; - final paymentHash = paymentRequest.tags.paymentHash!; - final fulfillerPublicKey = xchToBtcOfferFile.publicKey; - - final escrowPuzzlehash = BtcToXchService.generateEscrowPuzzlehash( - requestorPrivateKey: requestorPrivateKey, - clawbackDelaySeconds: validityTime, - sweepPaymentHash: paymentHash, - fulfillerPublicKey: fulfillerPublicKey, + final result = await compute( + BtcToXchTakerOfferFile._fromSerializedOfferFileTask, + serializedOfferFile, ); - return CrossChainOfferExchangeInfo( - requestorPublicKey: requestorPrivateKey.getG1(), - fulfillerPublicKey: fulfillerPublicKey, - amountMojos: amountMojos, - amountSatoshis: amountSatoshis, - validityTime: validityTime, - escrowPuzzlehash: escrowPuzzlehash, - paymentRequest: paymentRequest, - ); + return result; } @override CrossChainOfferFileType get type => CrossChainOfferFileType.btcToXchAccept; @override - CrossChainOfferFilePrefix get prefix => CrossChainOfferFilePrefix.ccoffer_accept; + CrossChainOfferFilePrefix get prefix => + CrossChainOfferFilePrefix.ccoffer_accept; @override Puzzlehash getEscrowPuzzlehash({ diff --git a/lib/src/exchange/btc/cross_chain_offer/models/cross_chain_offer_exchange_info.dart b/lib/src/exchange/btc/cross_chain_offer/models/cross_chain_offer_exchange_info.dart deleted file mode 100644 index 4dd3b0ca..00000000 --- a/lib/src/exchange/btc/cross_chain_offer/models/cross_chain_offer_exchange_info.dart +++ /dev/null @@ -1,23 +0,0 @@ -import 'package:chia_crypto_utils/chia_crypto_utils.dart'; - -class CrossChainOfferExchangeInfo { - CrossChainOfferExchangeInfo({ - required this.requestorPublicKey, - required this.fulfillerPublicKey, - required this.amountMojos, - required this.amountSatoshis, - required this.validityTime, - required this.escrowPuzzlehash, - required this.paymentRequest, - }); - - JacobianPoint requestorPublicKey; - JacobianPoint fulfillerPublicKey; - int amountMojos; - int amountSatoshis; - int validityTime; - Puzzlehash escrowPuzzlehash; - LightningPaymentRequest paymentRequest; - - Bytes? get paymentHash => paymentRequest.tags.paymentHash; -} diff --git a/lib/src/exchange/btc/cross_chain_offer/models/cross_chain_offer_file.dart b/lib/src/exchange/btc/cross_chain_offer/models/cross_chain_offer_file.dart index c8ec6d9b..97a25726 100644 --- a/lib/src/exchange/btc/cross_chain_offer/models/cross_chain_offer_file.dart +++ b/lib/src/exchange/btc/cross_chain_offer/models/cross_chain_offer_file.dart @@ -8,8 +8,11 @@ import 'package:compute/compute.dart'; /// The most general abstraction that all cross chain offer files implement and holds parameters /// that are common to all of concrete cross chain offer file classes. abstract class CrossChainOfferFile { - factory CrossChainOfferFile.fromSerializedOfferFile(String serializedOfferFile) { - final deserializedOfferFile = maybeFromSerializedOfferFile(serializedOfferFile); + factory CrossChainOfferFile.fromSerializedOfferFile( + String serializedOfferFile, + ) { + final deserializedOfferFile = + maybeFromSerializedOfferFile(serializedOfferFile); if (deserializedOfferFile == null) { throw InvalidCrossChainOfferFile(); @@ -17,13 +20,14 @@ abstract class CrossChainOfferFile { return deserializedOfferFile; } - factory CrossChainOfferFile._fromSerializedOfferFileTask(String serializedOfferFile) { + factory CrossChainOfferFile._fromSerializedOfferFileTask( + String serializedOfferFile, + ) { return CrossChainOfferFile.fromSerializedOfferFile(serializedOfferFile); } CrossChainOfferFilePrefix get prefix; CrossChainOfferFileType get type; - Bytes? get initializationCoinId; - set initializationCoinId(Bytes? id); + Bytes get initializationCoinId; int get validityTime; JacobianPoint get publicKey; LightningPaymentRequest? get lightningPaymentRequest; @@ -37,12 +41,9 @@ abstract class CrossChainOfferFile { required JacobianPoint fulfillerPublicKey, }); - CrossChainOfferExchangeInfo getExchangeInfo( - CrossChainOfferFile fulfillerOfferFile, - PrivateKey requestorPrivateKey, - ); - - static CrossChainOfferFile? maybeFromSerializedOfferFile(String serializedOfferFile) { + static CrossChainOfferFile? maybeFromSerializedOfferFile( + String serializedOfferFile, + ) { try { if (!serializedOfferFile.startsWith('ccoffer') && !serializedOfferFile.startsWith('ccoffer_accept')) { @@ -78,8 +79,11 @@ abstract class CrossChainOfferFile { break; } - final verification = - AugSchemeMPL.verify(deserializedOfferFile.publicKey, utf8.encode(data), signature); + final verification = AugSchemeMPL.verify( + deserializedOfferFile.publicKey, + utf8.encode(data), + signature, + ); if (verification == false) { throw BadSignatureOnOfferFile(); @@ -94,8 +98,10 @@ abstract class CrossChainOfferFile { static Future fromSerializedOfferFileAsync( String serializedOfferFile, ) async { - final result = - await compute(CrossChainOfferFile._fromSerializedOfferFileTask, serializedOfferFile); + final result = await compute( + CrossChainOfferFile._fromSerializedOfferFileTask, + serializedOfferFile, + ); return result; } @@ -111,14 +117,17 @@ extension Serialize on CrossChainOfferFile { throw FailedSignatureOnOfferFileException(); } - final signature = AugSchemeMPL.sign(requestorPrivateKey, utf8.encode(base64EncodedData)); + final signature = + AugSchemeMPL.sign(requestorPrivateKey, utf8.encode(base64EncodedData)); final signedData = utf8.encode('$base64EncodedData.${signature.toHex()}'); return bech32Encode(prefix.name, Bytes(signedData)); } Future serializeAsync(PrivateKey requestorPrivateKey) async { - final result = - await compute(_serializeOfferFileTask, _OfferFileWithPrivateKey(this, requestorPrivateKey)); + final result = await compute( + _serializeOfferFileTask, + _OfferFileWithPrivateKey(this, requestorPrivateKey), + ); return result; } @@ -129,25 +138,34 @@ extension Serialize on CrossChainOfferFile { } extension Role on CrossChainOfferFile { - ExchangeRole get role => - prefix == CrossChainOfferFilePrefix.ccoffer ? ExchangeRole.maker : ExchangeRole.taker; + ExchangeRole get role => prefix == CrossChainOfferFilePrefix.ccoffer + ? ExchangeRole.maker + : ExchangeRole.taker; } extension ExchangeOfferRecordType on CrossChainOfferFile { - ExchangeType get exchangeType => - type == CrossChainOfferFileType.xchToBtc || type == CrossChainOfferFileType.xchToBtcAccept - ? ExchangeType.xchToBtc - : ExchangeType.btcToXch; + ExchangeType get exchangeType => type == CrossChainOfferFileType.xchToBtc || + type == CrossChainOfferFileType.xchToBtcAccept + ? ExchangeType.xchToBtc + : ExchangeType.btcToXch; } -enum CrossChainOfferFileType { xchToBtc, xchToBtcAccept, btcToXch, btcToXchAccept } +enum CrossChainOfferFileType { + xchToBtc, + xchToBtcAccept, + btcToXch, + btcToXchAccept +} // ignore: constant_identifier_names enum CrossChainOfferFilePrefix { ccoffer, ccoffer_accept } -CrossChainOfferFileType parseCrossChainOfferFileTypeFromJson(Map json) { +CrossChainOfferFileType parseCrossChainOfferFileTypeFromJson( + Map json, +) { if (json.containsKey('offered')) { - final offeredAmount = ExchangeAmount.fromJson(json['offered'] as Map); + final offeredAmount = + ExchangeAmount.fromJson(json['offered'] as Map); if (offeredAmount.type == ExchangeAmountType.XCH) { return CrossChainOfferFileType.xchToBtc; } else { diff --git a/lib/src/exchange/btc/cross_chain_offer/models/exchange_amount.dart b/lib/src/exchange/btc/cross_chain_offer/models/exchange_amount.dart index 32f5a4e2..131c3f30 100644 --- a/lib/src/exchange/btc/cross_chain_offer/models/exchange_amount.dart +++ b/lib/src/exchange/btc/cross_chain_offer/models/exchange_amount.dart @@ -5,7 +5,8 @@ class ExchangeAmount { const ExchangeAmount({required this.type, required this.amount}); factory ExchangeAmount.fromJson(Map json) { return ExchangeAmount( - type: ExchangeAmountType.values.firstWhere((type) => type.name == json['type'] as String), + type: ExchangeAmountType.values + .firstWhere((type) => type.name == json['type'] as String), amount: json['amount'] as int, ); } @@ -20,7 +21,9 @@ class ExchangeAmount { @override bool operator ==(Object other) { - return other is ExchangeAmount && other.type == type && other.amount == amount; + return other is ExchangeAmount && + other.type == type && + other.amount == amount; } @override diff --git a/lib/src/exchange/btc/cross_chain_offer/models/index.dart b/lib/src/exchange/btc/cross_chain_offer/models/index.dart index 1a91daca..4e66f3f8 100644 --- a/lib/src/exchange/btc/cross_chain_offer/models/index.dart +++ b/lib/src/exchange/btc/cross_chain_offer/models/index.dart @@ -1,4 +1,3 @@ -export './cross_chain_offer_exchange_info.dart'; export './cross_chain_offer_file.dart'; export './exchange_amount.dart'; export 'btc_to_xch_maker_offer_file.dart'; diff --git a/lib/src/exchange/btc/cross_chain_offer/models/maker_cross_chain_offer_file.dart b/lib/src/exchange/btc/cross_chain_offer/models/maker_cross_chain_offer_file.dart index c32ef21e..55b3b1cb 100644 --- a/lib/src/exchange/btc/cross_chain_offer/models/maker_cross_chain_offer_file.dart +++ b/lib/src/exchange/btc/cross_chain_offer/models/maker_cross_chain_offer_file.dart @@ -3,8 +3,11 @@ import 'package:compute/compute.dart'; /// The abstract class that holds parameters unique to offer files generated by the maker of an offer. abstract class MakerCrossChainOfferFile implements CrossChainOfferFile { - factory MakerCrossChainOfferFile.fromSerializedOfferFile(String serializedOfferFile) { - final deserializedOfferFile = maybeFromSerializedOfferFile(serializedOfferFile); + factory MakerCrossChainOfferFile.fromSerializedOfferFile( + String serializedOfferFile, + ) { + final deserializedOfferFile = + maybeFromSerializedOfferFile(serializedOfferFile); if (deserializedOfferFile == null) { throw InvalidCrossChainOfferType('ccoffer'); @@ -12,8 +15,12 @@ abstract class MakerCrossChainOfferFile implements CrossChainOfferFile { return deserializedOfferFile; } - factory MakerCrossChainOfferFile._fromSerializedOfferFileTask(String serializedOfferFile) { - return MakerCrossChainOfferFile.fromSerializedOfferFile(serializedOfferFile); + factory MakerCrossChainOfferFile._fromSerializedOfferFileTask( + String serializedOfferFile, + ) { + return MakerCrossChainOfferFile.fromSerializedOfferFile( + serializedOfferFile, + ); } ExchangeAmount get offeredAmount; ExchangeAmount get requestedAmount; @@ -21,7 +28,9 @@ abstract class MakerCrossChainOfferFile implements CrossChainOfferFile { int get mojos; int get satoshis; - static MakerCrossChainOfferFile? maybeFromSerializedOfferFile(String serializedOfferFile) { + static MakerCrossChainOfferFile? maybeFromSerializedOfferFile( + String serializedOfferFile, + ) { try { final deserializedOfferFile = CrossChainOfferFile.fromSerializedOfferFile(serializedOfferFile); @@ -37,8 +46,10 @@ abstract class MakerCrossChainOfferFile implements CrossChainOfferFile { static Future fromSerializedOfferFileAsync( String serializedOfferFile, ) async { - final result = - await compute(MakerCrossChainOfferFile._fromSerializedOfferFileTask, serializedOfferFile); + final result = await compute( + MakerCrossChainOfferFile._fromSerializedOfferFileTask, + serializedOfferFile, + ); return result; } diff --git a/lib/src/exchange/btc/cross_chain_offer/models/taker_cross_chain_offer_file.dart b/lib/src/exchange/btc/cross_chain_offer/models/taker_cross_chain_offer_file.dart index 39d0a4e2..525d8639 100644 --- a/lib/src/exchange/btc/cross_chain_offer/models/taker_cross_chain_offer_file.dart +++ b/lib/src/exchange/btc/cross_chain_offer/models/taker_cross_chain_offer_file.dart @@ -4,8 +4,11 @@ import 'package:compute/compute.dart'; /// The abstract class that holds parameters unique to offer files that are generated by the taker /// of an offer and sent to the maker. abstract class TakerCrossChainOfferFile implements CrossChainOfferFile { - factory TakerCrossChainOfferFile.fromSerializedOfferFile(String serializedOfferFile) { - final deserializedOfferFile = maybeFromSerializedOfferFile(serializedOfferFile); + factory TakerCrossChainOfferFile.fromSerializedOfferFile( + String serializedOfferFile, + ) { + final deserializedOfferFile = + maybeFromSerializedOfferFile(serializedOfferFile); if (deserializedOfferFile == null) { throw InvalidCrossChainOfferType('ccoffer_accept'); @@ -13,12 +16,18 @@ abstract class TakerCrossChainOfferFile implements CrossChainOfferFile { return deserializedOfferFile; } - factory TakerCrossChainOfferFile._fromSerializedOfferFileTask(String serializedOfferFile) { - return TakerCrossChainOfferFile.fromSerializedOfferFile(serializedOfferFile); + factory TakerCrossChainOfferFile._fromSerializedOfferFileTask( + String serializedOfferFile, + ) { + return TakerCrossChainOfferFile.fromSerializedOfferFile( + serializedOfferFile, + ); } Bytes get acceptedOfferHash; - static TakerCrossChainOfferFile? maybeFromSerializedOfferFile(String serializedOfferFile) { + static TakerCrossChainOfferFile? maybeFromSerializedOfferFile( + String serializedOfferFile, + ) { try { final deserializedOfferFile = CrossChainOfferFile.fromSerializedOfferFile(serializedOfferFile); @@ -34,8 +43,10 @@ abstract class TakerCrossChainOfferFile implements CrossChainOfferFile { static Future fromSerializedOfferFileAsync( String serializedOfferFile, ) async { - final result = - await compute(TakerCrossChainOfferFile._fromSerializedOfferFileTask, serializedOfferFile); + final result = await compute( + TakerCrossChainOfferFile._fromSerializedOfferFileTask, + serializedOfferFile, + ); return result; } diff --git a/lib/src/exchange/btc/cross_chain_offer/models/xch_to_btc_maker_offer_file.dart b/lib/src/exchange/btc/cross_chain_offer/models/xch_to_btc_maker_offer_file.dart index e3831748..ba2f8ba5 100644 --- a/lib/src/exchange/btc/cross_chain_offer/models/xch_to_btc_maker_offer_file.dart +++ b/lib/src/exchange/btc/cross_chain_offer/models/xch_to_btc_maker_offer_file.dart @@ -3,7 +3,7 @@ import 'package:compute/compute.dart'; class XchToBtcMakerOfferFile implements MakerCrossChainOfferFile { XchToBtcMakerOfferFile({ - this.initializationCoinId, + required this.initializationCoinId, required this.offeredAmount, required this.requestedAmount, required this.messageAddress, @@ -11,23 +11,18 @@ class XchToBtcMakerOfferFile implements MakerCrossChainOfferFile { required this.publicKey, required this.lightningPaymentRequest, }); - factory XchToBtcMakerOfferFile.fromJson(Map json) { - return XchToBtcMakerOfferFile( - initializationCoinId: (json['initialization_coin_id'] as String?)?.hexToBytes(), - offeredAmount: ExchangeAmount.fromJson(json['offered'] as Map), - requestedAmount: ExchangeAmount.fromJson(json['requested'] as Map), - messageAddress: - Address((json['message_address'] as Map)['address'] as String), - validityTime: json['validity_time'] as int, - publicKey: JacobianPoint.fromHexG1(json['public_key'] as String), - lightningPaymentRequest: decodeLightningPaymentRequest( - (json['lightning_payment_request'] as Map)['payment_request'] as String, - ), - ); + + factory XchToBtcMakerOfferFile._fromSerializedOfferFileTask( + String serializedOfferFile, + ) { + return XchToBtcMakerOfferFile.fromSerializedOfferFile(serializedOfferFile); } - factory XchToBtcMakerOfferFile.fromSerializedOfferFile(String serializedOfferFile) { - final deserializedOfferFile = maybeFromSerializedOfferFile(serializedOfferFile); + factory XchToBtcMakerOfferFile.fromSerializedOfferFile( + String serializedOfferFile, + ) { + final deserializedOfferFile = + maybeFromSerializedOfferFile(serializedOfferFile); if (deserializedOfferFile == null) { throw InvalidCrossChainOfferType(CrossChainOfferFileType.xchToBtc.name); @@ -35,12 +30,28 @@ class XchToBtcMakerOfferFile implements MakerCrossChainOfferFile { return deserializedOfferFile; } - factory XchToBtcMakerOfferFile._fromSerializedOfferFileTask(String serializedOfferFile) { - return XchToBtcMakerOfferFile.fromSerializedOfferFile(serializedOfferFile); + factory XchToBtcMakerOfferFile.fromJson(Map json) { + return XchToBtcMakerOfferFile( + initializationCoinId: + (json['initialization_coin_id'] as String).hexToBytes(), + offeredAmount: + ExchangeAmount.fromJson(json['offered'] as Map), + requestedAmount: + ExchangeAmount.fromJson(json['requested'] as Map), + messageAddress: Address( + (json['message_address'] as Map)['address'] as String, + ), + validityTime: json['validity_time'] as int, + publicKey: JacobianPoint.fromHexG1(json['public_key'] as String), + lightningPaymentRequest: decodeLightningPaymentRequest( + (json['lightning_payment_request'] + as Map)['payment_request'] as String, + ), + ); } @override - Bytes? initializationCoinId; + final Bytes initializationCoinId; @override final ExchangeAmount offeredAmount; @override @@ -60,22 +71,24 @@ class XchToBtcMakerOfferFile implements MakerCrossChainOfferFile { @override Map toJson() => { - 'initialization_coin_id': initializationCoinId?.toHex(), + 'initialization_coin_id': initializationCoinId.toHex(), 'offered': offeredAmount.toJson(), 'requested': requestedAmount.toJson(), 'message_address': { 'type': messageAddress.prefix, - 'address': messageAddress.address, + 'address': messageAddress.address }, 'validity_time': validityTime, 'public_key': publicKey.toHex(), 'lightning_payment_request': { 'payment_request': lightningPaymentRequest.paymentRequest, - 'timeout': lightningPaymentRequest.tags.timeout, - }, + 'timeout': lightningPaymentRequest.tags.timeout + } }; - static XchToBtcMakerOfferFile? maybeFromSerializedOfferFile(String serializedOfferFile) { + static XchToBtcMakerOfferFile? maybeFromSerializedOfferFile( + String serializedOfferFile, + ) { try { final deserializedOfferFile = CrossChainOfferFile.fromSerializedOfferFile(serializedOfferFile); @@ -91,40 +104,12 @@ class XchToBtcMakerOfferFile implements MakerCrossChainOfferFile { static Future fromSerializedOfferFileAsync( String serializedOfferFile, ) async { - final result = - await compute(XchToBtcMakerOfferFile._fromSerializedOfferFileTask, serializedOfferFile); - - return result; - } - - @override - CrossChainOfferExchangeInfo getExchangeInfo( - CrossChainOfferFile offerAcceptFile, - PrivateKey requestorPrivateKey, - ) { - final btcToXchOfferAcceptFile = offerAcceptFile as BtcToXchTakerOfferFile; - - final amountMojos = offeredAmount.amount; - final amountSatoshis = requestedAmount.amount; - final validityTime = btcToXchOfferAcceptFile.validityTime; - final fulfillerPublicKey = btcToXchOfferAcceptFile.publicKey; - - final escrowPuzzlehash = XchToBtcService.generateEscrowPuzzlehash( - requestorPrivateKey: requestorPrivateKey, - clawbackDelaySeconds: validityTime, - sweepPaymentHash: lightningPaymentRequest.tags.paymentHash!, - fulfillerPublicKey: fulfillerPublicKey, + final result = await compute( + XchToBtcMakerOfferFile._fromSerializedOfferFileTask, + serializedOfferFile, ); - return CrossChainOfferExchangeInfo( - requestorPublicKey: requestorPrivateKey.getG1(), - fulfillerPublicKey: fulfillerPublicKey, - amountMojos: amountMojos, - amountSatoshis: amountSatoshis, - validityTime: validityTime, - escrowPuzzlehash: escrowPuzzlehash, - paymentRequest: lightningPaymentRequest, - ); + return result; } @override diff --git a/lib/src/exchange/btc/cross_chain_offer/models/xch_to_btc_taker_offer_file.dart b/lib/src/exchange/btc/cross_chain_offer/models/xch_to_btc_taker_offer_file.dart index 7d7fd255..ffdf6fc6 100644 --- a/lib/src/exchange/btc/cross_chain_offer/models/xch_to_btc_taker_offer_file.dart +++ b/lib/src/exchange/btc/cross_chain_offer/models/xch_to_btc_taker_offer_file.dart @@ -3,65 +3,78 @@ import 'package:compute/compute.dart'; class XchToBtcTakerOfferFile implements TakerCrossChainOfferFile { XchToBtcTakerOfferFile({ - this.initializationCoinId, + required this.initializationCoinId, required this.validityTime, required this.publicKey, required this.acceptedOfferHash, required this.lightningPaymentRequest, }); - factory XchToBtcTakerOfferFile.fromJson(Map json) { - return XchToBtcTakerOfferFile( - initializationCoinId: (json['initialization_coin_id'] as String?)?.hexToBytes(), - validityTime: json['validity_time'] as int, - publicKey: JacobianPoint.fromHexG1(json['public_key'] as String), - lightningPaymentRequest: decodeLightningPaymentRequest( - (json['lightning_payment_request'] as Map)['payment_request'] as String, - ), - acceptedOfferHash: (json['accepted_offer_hash'] as String).hexToBytes(), - ); + + factory XchToBtcTakerOfferFile._fromSerializedOfferFileTask( + String serializedOfferFile, + ) { + return XchToBtcTakerOfferFile.fromSerializedOfferFile(serializedOfferFile); } - factory XchToBtcTakerOfferFile.fromSerializedOfferFile(String serializedOfferFile) { - final deserializedOfferFile = maybeFromSerializedOfferFile(serializedOfferFile); + factory XchToBtcTakerOfferFile.fromSerializedOfferFile( + String serializedOfferFile, + ) { + final deserializedOfferFile = + maybeFromSerializedOfferFile(serializedOfferFile); if (deserializedOfferFile == null) { - throw InvalidCrossChainOfferType(CrossChainOfferFileType.xchToBtcAccept.name); + throw InvalidCrossChainOfferType( + CrossChainOfferFileType.xchToBtcAccept.name, + ); } return deserializedOfferFile; } - factory XchToBtcTakerOfferFile._fromSerializedOfferFileTask(String serializedOfferFile) { - return XchToBtcTakerOfferFile.fromSerializedOfferFile(serializedOfferFile); + factory XchToBtcTakerOfferFile.fromJson(Map json) { + return XchToBtcTakerOfferFile( + initializationCoinId: + (json['initialization_coin_id'] as String).hexToBytes(), + validityTime: json['validity_time'] as int, + publicKey: JacobianPoint.fromHexG1(json['public_key'] as String), + lightningPaymentRequest: decodeLightningPaymentRequest( + (json['lightning_payment_request'] + as Map)['payment_request'] as String, + ), + acceptedOfferHash: (json['accepted_offer_hash'] as String).hexToBytes(), + ); } @override - Bytes? initializationCoinId; + final Bytes initializationCoinId; @override - int validityTime; + final int validityTime; @override - JacobianPoint publicKey; + final JacobianPoint publicKey; @override - LightningPaymentRequest lightningPaymentRequest; + final LightningPaymentRequest lightningPaymentRequest; @override - Bytes acceptedOfferHash; + final Bytes acceptedOfferHash; @override Map toJson() => { - 'initialization_coin_id': initializationCoinId?.toHex(), + 'initialization_coin_id': initializationCoinId.toHex(), 'validity_time': validityTime, 'public_key': publicKey.toHex(), 'lightning_payment_request': { 'payment_request': lightningPaymentRequest.paymentRequest, - 'timeout': lightningPaymentRequest.tags.timeout, + 'timeout': lightningPaymentRequest.tags.timeout }, 'accepted_offer_hash': acceptedOfferHash.toHex(), }; - static XchToBtcTakerOfferFile? maybeFromSerializedOfferFile(String serializedOfferFile) { + static XchToBtcTakerOfferFile? maybeFromSerializedOfferFile( + String serializedOfferFile, + ) { try { final deserializedOfferFile = CrossChainOfferFile.fromSerializedOfferFile(serializedOfferFile); - if (deserializedOfferFile.type != CrossChainOfferFileType.xchToBtcAccept) { + if (deserializedOfferFile.type != + CrossChainOfferFileType.xchToBtcAccept) { return null; } return deserializedOfferFile as XchToBtcTakerOfferFile; @@ -73,46 +86,20 @@ class XchToBtcTakerOfferFile implements TakerCrossChainOfferFile { static Future fromSerializedOfferFileAsync( String serializedOfferFile, ) async { - final result = - await compute(XchToBtcTakerOfferFile._fromSerializedOfferFileTask, serializedOfferFile); - - return result; - } - - @override - CrossChainOfferExchangeInfo getExchangeInfo( - CrossChainOfferFile offerFile, - PrivateKey requestorPrivateKey, - ) { - final btcToXchOfferFile = offerFile as BtcToXchMakerOfferFile; - - final amountMojos = btcToXchOfferFile.requestedAmount.amount; - final amountSatoshis = btcToXchOfferFile.offeredAmount.amount; - final fulfillerPublicKey = btcToXchOfferFile.publicKey; - - final escrowPuzzlehash = XchToBtcService.generateEscrowPuzzlehash( - requestorPrivateKey: requestorPrivateKey, - clawbackDelaySeconds: validityTime, - sweepPaymentHash: lightningPaymentRequest.tags.paymentHash!, - fulfillerPublicKey: fulfillerPublicKey, + final result = await compute( + XchToBtcTakerOfferFile._fromSerializedOfferFileTask, + serializedOfferFile, ); - return CrossChainOfferExchangeInfo( - requestorPublicKey: requestorPrivateKey.getG1(), - fulfillerPublicKey: fulfillerPublicKey, - amountMojos: amountMojos, - amountSatoshis: amountSatoshis, - validityTime: validityTime, - escrowPuzzlehash: escrowPuzzlehash, - paymentRequest: lightningPaymentRequest, - ); + return result; } @override CrossChainOfferFileType get type => CrossChainOfferFileType.xchToBtcAccept; @override - CrossChainOfferFilePrefix get prefix => CrossChainOfferFilePrefix.ccoffer_accept; + CrossChainOfferFilePrefix get prefix => + CrossChainOfferFilePrefix.ccoffer_accept; @override Puzzlehash getEscrowPuzzlehash({ diff --git a/lib/src/exchange/btc/cross_chain_offer/service/cross_chain_offer_service.dart b/lib/src/exchange/btc/cross_chain_offer/service/cross_chain_offer_service.dart index 208b214b..61c68132 100644 --- a/lib/src/exchange/btc/cross_chain_offer/service/cross_chain_offer_service.dart +++ b/lib/src/exchange/btc/cross_chain_offer/service/cross_chain_offer_service.dart @@ -1,13 +1,8 @@ import 'package:chia_crypto_utils/chia_crypto_utils.dart'; -class CrossChainOfferService { - CrossChainOfferService(this.fullNode); - - final ChiaFullNodeInterface fullNode; - final DexieExchangeOfferApi dexieApi = DexieExchangeOfferApi(); - final standardWalletService = StandardWalletService(); - - XchToBtcMakerOfferFile createXchToBtcOfferFile({ +class CrossChainOfferFileService { + XchToBtcMakerOfferFile createXchToBtcMakerOfferFile({ + required Bytes initializationCoinId, required int amountMojos, required int amountSatoshis, required Address messageAddress, @@ -15,10 +10,13 @@ class CrossChainOfferService { required JacobianPoint requestorPublicKey, required LightningPaymentRequest paymentRequest, }) { - final offeredAmount = ExchangeAmount(type: ExchangeAmountType.XCH, amount: amountMojos); - final requestedAmount = ExchangeAmount(type: ExchangeAmountType.BTC, amount: amountSatoshis); + final offeredAmount = + ExchangeAmount(type: ExchangeAmountType.XCH, amount: amountMojos); + final requestedAmount = + ExchangeAmount(type: ExchangeAmountType.BTC, amount: amountSatoshis); return XchToBtcMakerOfferFile( + initializationCoinId: initializationCoinId, offeredAmount: offeredAmount, requestedAmount: requestedAmount, messageAddress: messageAddress, @@ -28,17 +26,21 @@ class CrossChainOfferService { ); } - BtcToXchMakerOfferFile createBtcToXchOfferFile({ + BtcToXchMakerOfferFile createBtcToXchMakerOfferFile({ + required Bytes initializationCoinId, required int amountMojos, required int amountSatoshis, required Address messageAddress, required int validityTime, required JacobianPoint requestorPublicKey, }) { - final offeredAmount = ExchangeAmount(type: ExchangeAmountType.BTC, amount: amountSatoshis); - final requestedAmount = ExchangeAmount(type: ExchangeAmountType.XCH, amount: amountMojos); + final offeredAmount = + ExchangeAmount(type: ExchangeAmountType.BTC, amount: amountSatoshis); + final requestedAmount = + ExchangeAmount(type: ExchangeAmountType.XCH, amount: amountMojos); return BtcToXchMakerOfferFile( + initializationCoinId: initializationCoinId, offeredAmount: offeredAmount, requestedAmount: requestedAmount, messageAddress: messageAddress, @@ -48,20 +50,24 @@ class CrossChainOfferService { } static void checkValidity(CrossChainOfferFile offerFile) { - if (offerFile.validityTime < (DateTime.now().millisecondsSinceEpoch / 1000)) { + if (offerFile.validityTime < + (DateTime.now().millisecondsSinceEpoch / 1000)) { throw ExpiredCrossChainOfferFile(); } } - XchToBtcTakerOfferFile createXchToBtcAcceptFile({ - required String serializedOfferFile, + XchToBtcTakerOfferFile createXchToBtcTakerOfferFile({ + required String serializedMakerOfferFile, + required Bytes initializationCoinId, required int validityTime, required JacobianPoint requestorPublicKey, required LightningPaymentRequest paymentRequest, }) { - final acceptedOfferHash = Bytes.encodeFromString(serializedOfferFile).sha256Hash(); + final acceptedOfferHash = + Bytes.encodeFromString(serializedMakerOfferFile).sha256Hash(); return XchToBtcTakerOfferFile( + initializationCoinId: initializationCoinId, validityTime: validityTime, publicKey: requestorPublicKey, lightningPaymentRequest: paymentRequest, @@ -69,92 +75,20 @@ class CrossChainOfferService { ); } - BtcToXchTakerOfferFile createBtcToXchAcceptFile({ - required String serializedOfferFile, + BtcToXchTakerOfferFile createBtcToXchTakerOfferFile({ + required String serializedMakerOfferFile, + required Bytes initializationCoinId, required int validityTime, required JacobianPoint requestorPublicKey, }) { - final acceptedOfferHash = Bytes.encodeFromString(serializedOfferFile).sha256Hash(); + final acceptedOfferHash = + Bytes.encodeFromString(serializedMakerOfferFile).sha256Hash(); return BtcToXchTakerOfferFile( + initializationCoinId: initializationCoinId, validityTime: validityTime, publicKey: requestorPublicKey, acceptedOfferHash: acceptedOfferHash, ); } - - // TODO(meeragjoshi): replace the below methods with the analogous methods in ExchangeOfferService once initialization coin id and message coin method are adapted into bin command - Future sendMessageCoin({ - required WalletKeychain keychain, - required List coinsInput, - required Puzzlehash messagePuzzlehash, - required PrivateKey requestorPrivateKey, - required String serializedOfferAcceptFile, - Puzzlehash? changePuzzlehash, - int fee = 0, - }) async { - final messageSpendBundle = standardWalletService.createSpendBundle( - payments: [ - Payment(50, messagePuzzlehash, memos: [serializedOfferAcceptFile]), - ], - coinsInput: coinsInput, - changePuzzlehash: changePuzzlehash, - keychain: keychain, - fee: fee, - ); - - await fullNode.pushTransaction(messageSpendBundle); - } - - Future verifyMessageCoinReceipt( - Puzzlehash messagePuzzlehash, - String serializedOfferAcceptFile, - ) async { - final coins = await fullNode.getCoinsByPuzzleHashes( - [messagePuzzlehash], - ); - - for (final coin in coins) { - final parentCoin = await fullNode.getCoinById(coin.parentCoinInfo); - final coinSpend = await fullNode.getCoinSpend(parentCoin!); - final memos = await coinSpend!.memoStrings; - - for (final memo in memos) { - if (memo == serializedOfferAcceptFile) return true; - } - } - - return false; - } - - Future getOfferAcceptFileFromMessagePuzzlehash( - Puzzlehash messagePuzzlehash, - String serializedOfferFile, - ) async { - final coins = await fullNode.getCoinsByPuzzleHashes( - [messagePuzzlehash], - ); - - for (final coin in coins) { - final parentCoin = await fullNode.getCoinById(coin.parentCoinInfo); - final coinSpend = await fullNode.getCoinSpend(parentCoin!); - final memos = await coinSpend!.memoStrings; - - for (final memo in memos) { - if (memo.startsWith('ccoffer_accept')) { - try { - final deserializedMemo = - await TakerCrossChainOfferFile.fromSerializedOfferFileAsync(memo); - - if (deserializedMemo.acceptedOfferHash == - Bytes.encodeFromString(serializedOfferFile).sha256Hash()) return memo; - } catch (e) { - print(e); - continue; - } - } - } - } - return null; - } } diff --git a/lib/src/exchange/btc/exchange_offer_record/models/exchange_offer_record.dart b/lib/src/exchange/btc/exchange_offer_record/models/exchange_offer_record.dart index 39c22b79..261ba27e 100644 --- a/lib/src/exchange/btc/exchange_offer_record/models/exchange_offer_record.dart +++ b/lib/src/exchange/btc/exchange_offer_record/models/exchange_offer_record.dart @@ -147,7 +147,8 @@ class ExchangeOfferRecord { DateTime get offerExpirationDateTime => DateTime.fromMillisecondsSinceEpoch(offerValidityTime * 1000); - String get offerExpirationDate => DateFormat.yMd().add_jm().format(offerExpirationDateTime); + String get offerExpirationDate => + DateFormat.yMd().add_jm().format(offerExpirationDateTime); bool get offerExpired => DateTime.now().isAfter(offerExpirationDateTime); @@ -155,7 +156,8 @@ class ExchangeOfferRecord { if (escrowTransferCompletedTime != null && exchangeValidityTime != null) { // the earliest you can spend a time-locked coin is 2 blocks later, since the time is checked // against the timestamp of the previous block - return escrowTransferCompletedTime!.add(Duration(seconds: exchangeValidityTime! + (2 * 19))); + return escrowTransferCompletedTime! + .add(Duration(seconds: exchangeValidityTime! + (2 * 19))); } return null; } @@ -181,7 +183,9 @@ class ExchangeOfferRecord { DateTime? get paymentRequestExpirationDateTime { if (lightningPaymentRequest != null) { return DateTime.fromMillisecondsSinceEpoch( - (lightningPaymentRequest!.timestamp + lightningPaymentRequest!.tags.timeout!) * 1000, + (lightningPaymentRequest!.timestamp + + lightningPaymentRequest!.tags.timeout!) * + 1000, ); } return null; @@ -203,8 +207,10 @@ class ExchangeOfferRecord { (role == ExchangeRole.taker && type == ExchangeType.btcToXch)) { return XchToBtcMakerOfferFile( initializationCoinId: initializationCoinId, - offeredAmount: ExchangeAmount(type: ExchangeAmountType.XCH, amount: mojos), - requestedAmount: ExchangeAmount(type: ExchangeAmountType.BTC, amount: satoshis), + offeredAmount: + ExchangeAmount(type: ExchangeAmountType.XCH, amount: mojos), + requestedAmount: + ExchangeAmount(type: ExchangeAmountType.BTC, amount: satoshis), messageAddress: messagePuzzlehash.toAddressWithContext(), validityTime: offerValidityTime, publicKey: requestorPublicKey, @@ -213,8 +219,10 @@ class ExchangeOfferRecord { } else { return BtcToXchMakerOfferFile( initializationCoinId: initializationCoinId, - offeredAmount: ExchangeAmount(type: ExchangeAmountType.BTC, amount: satoshis), - requestedAmount: ExchangeAmount(type: ExchangeAmountType.XCH, amount: mojos), + offeredAmount: + ExchangeAmount(type: ExchangeAmountType.BTC, amount: satoshis), + requestedAmount: + ExchangeAmount(type: ExchangeAmountType.XCH, amount: mojos), messageAddress: messagePuzzlehash.toAddressWithContext(), validityTime: offerValidityTime, publicKey: requestorPublicKey, @@ -231,14 +239,16 @@ class ExchangeOfferRecord { initializationCoinId: initializationCoinId, validityTime: exchangeValidityTime!, publicKey: fulfillerPublicKey!, - acceptedOfferHash: Bytes.encodeFromString(serializedMakerOfferFile).sha256Hash(), + acceptedOfferHash: + Bytes.encodeFromString(serializedMakerOfferFile).sha256Hash(), ).toJson(); } else { return XchToBtcTakerOfferFile( initializationCoinId: initializationCoinId, validityTime: exchangeValidityTime!, publicKey: fulfillerPublicKey!, - acceptedOfferHash: Bytes.encodeFromString(serializedMakerOfferFile).sha256Hash(), + acceptedOfferHash: + Bytes.encodeFromString(serializedMakerOfferFile).sha256Hash(), lightningPaymentRequest: lightningPaymentRequest!, ).toJson(); } @@ -284,23 +294,31 @@ class ExchangeOfferRecord { messagePuzzlehash: messagePuzzlehash ?? this.messagePuzzlehash, requestorPublicKey: requestorPublicKey ?? this.requestorPublicKey, offerValidityTime: offerValidityTime ?? this.offerValidityTime, - serializedMakerOfferFile: serializedMakerOfferFile ?? this.serializedMakerOfferFile, + serializedMakerOfferFile: + serializedMakerOfferFile ?? this.serializedMakerOfferFile, submittedToDexie: submittedToDexie ?? this.submittedToDexie, - serializedTakerOfferFile: serializedTakerOfferFile ?? this.serializedTakerOfferFile, - lightningPaymentRequest: lightningPaymentRequest ?? this.lightningPaymentRequest, + serializedTakerOfferFile: + serializedTakerOfferFile ?? this.serializedTakerOfferFile, + lightningPaymentRequest: + lightningPaymentRequest ?? this.lightningPaymentRequest, fulfillerPublicKey: fulfillerPublicKey ?? this.fulfillerPublicKey, exchangeValidityTime: exchangeValidityTime ?? this.exchangeValidityTime, escrowPuzzlehash: escrowPuzzlehash ?? this.escrowPuzzlehash, escrowCoinId: escrowCoinId ?? this.escrowCoinId, messageCoinId: messageCoinId ?? this.messageCoinId, initializedTime: initializedTime ?? this.initializedTime, - messageCoinReceivedTime: messageCoinReceivedTime ?? this.messageCoinReceivedTime, - messageCoinDeclinedTime: messageCoinDeclinedTime ?? this.messageCoinDeclinedTime, - messageCoinAcceptedTime: messageCoinAcceptedTime ?? this.messageCoinAcceptedTime, - escrowTransferCompletedTime: escrowTransferCompletedTime ?? this.escrowTransferCompletedTime, - escrowTransferConfirmedBlockIndex: - escrowTransferConfirmedBlockIndex ?? this.escrowTransferConfirmedBlockIndex, - escrowTransferConfirmedTime: escrowTransferConfirmedTime ?? this.escrowTransferConfirmedTime, + messageCoinReceivedTime: + messageCoinReceivedTime ?? this.messageCoinReceivedTime, + messageCoinDeclinedTime: + messageCoinDeclinedTime ?? this.messageCoinDeclinedTime, + messageCoinAcceptedTime: + messageCoinAcceptedTime ?? this.messageCoinAcceptedTime, + escrowTransferCompletedTime: + escrowTransferCompletedTime ?? this.escrowTransferCompletedTime, + escrowTransferConfirmedBlockIndex: escrowTransferConfirmedBlockIndex ?? + this.escrowTransferConfirmedBlockIndex, + escrowTransferConfirmedTime: + escrowTransferConfirmedTime ?? this.escrowTransferConfirmedTime, sweepTime: sweepTime ?? this.sweepTime, clawbackTime: clawbackTime ?? this.clawbackTime, canceledTime: canceledTime ?? this.canceledTime, diff --git a/lib/src/exchange/btc/exchange_offer_record/models/memo_wrappers/exchange_coin_memos.dart b/lib/src/exchange/btc/exchange_offer_record/models/memo_wrappers/exchange_coin_memos.dart index 73b3b81b..f6b2aa24 100644 --- a/lib/src/exchange/btc/exchange_offer_record/models/memo_wrappers/exchange_coin_memos.dart +++ b/lib/src/exchange/btc/exchange_offer_record/models/memo_wrappers/exchange_coin_memos.dart @@ -5,9 +5,13 @@ class ExchangeCoinMemos { required Bytes initializationCoinId, required PrivateKey requestorPrivateKey, }) { - final signature = AugSchemeMPL.sign(requestorPrivateKey, initializationCoinId); + final signature = + AugSchemeMPL.sign(requestorPrivateKey, initializationCoinId); - return ExchangeCoinMemos._(initializationCoinId: initializationCoinId, signature: signature); + return ExchangeCoinMemos._( + initializationCoinId: initializationCoinId, + signature: signature, + ); } ExchangeCoinMemos._({ @@ -26,7 +30,10 @@ class ExchangeCoinMemos { final initializationCoinId = memos[0]; final signature = JacobianPoint.fromBytesG2(memos[1]); - return ExchangeCoinMemos._(initializationCoinId: initializationCoinId, signature: signature); + return ExchangeCoinMemos._( + initializationCoinId: initializationCoinId, + signature: signature, + ); } bool verify(JacobianPoint publicKey) { diff --git a/lib/src/exchange/btc/exchange_offer_record/service/exchange_offer_record_hydration_service.dart b/lib/src/exchange/btc/exchange_offer_record/service/exchange_offer_record_hydration_service.dart index c9be2247..f4ed4662 100644 --- a/lib/src/exchange/btc/exchange_offer_record/service/exchange_offer_record_hydration_service.dart +++ b/lib/src/exchange/btc/exchange_offer_record/service/exchange_offer_record_hydration_service.dart @@ -6,7 +6,8 @@ class ExchangeOfferRecordHydrationService { ExchangeOfferRecordHydrationService(this.fullNode); final ChiaFullNodeInterface fullNode; - late ExchangeOfferService exchangeOfferService = ExchangeOfferService(fullNode); + late ExchangeOfferService exchangeOfferService = + ExchangeOfferService(fullNode); Future hydrateExchangeInitializationCoin( Coin initializationCoin, @@ -15,8 +16,10 @@ class ExchangeOfferRecordHydrationService { ) async { final initializationCoinId = initializationCoin.id; - final exchangeCoins = - await fullNode.getCoinsByHint(Puzzlehash(initializationCoinId), includeSpentCoins: true); + final exchangeCoins = await fullNode.getCoinsByHint( + Puzzlehash(initializationCoinId), + includeSpentCoins: true, + ); late final CoinSpend? initializationCoinSpend; late final DateTime? initializedTime; @@ -26,14 +29,16 @@ class ExchangeOfferRecordHydrationService { late final MakerCrossChainOfferFile? offerFile; try { initializationCoinSpend = await fullNode.getCoinSpend(initializationCoin); - initializedTime = - await fullNode.getDateTimeFromBlockIndex(initializationCoin.spentBlockIndex); + initializedTime = await fullNode + .getDateTimeFromBlockIndex(initializationCoin.spentBlockIndex); final memos = await initializationCoinSpend!.memos; derivationIndex = decodeInt(memos.first); - final wallectVector = - await WalletVector.fromPrivateKeyAsync(masterPrivateKey, derivationIndex); + final wallectVector = await WalletVector.fromPrivateKeyAsync( + masterPrivateKey, + derivationIndex, + ); requestorPrivateKey = wallectVector.childPrivateKey; serializedOfferFile = memos[1].decodedString; @@ -55,14 +60,18 @@ class ExchangeOfferRecordHydrationService { final requestorPublicKey = offerFile.publicKey; final requestorLightningPaymentRequest = offerFile.lightningPaymentRequest; - final submittedToDexie = await getDexieSubmissionStatus(serializedOfferFile); + final submittedToDexie = + await getDexieSubmissionStatus(serializedOfferFile); // check whether the 3 mojo addition from the initialization coin spend was spent, indicating cancelation - final cancelCoin = - await exchangeOfferService.getCancelCoin(initializationCoin, messagePuzzlehash); + final cancelCoin = await exchangeOfferService.getCancelCoin( + initializationCoin, + messagePuzzlehash, + ); late final DateTime? canceledTime; if (cancelCoin.isSpent) { - canceledTime = await fullNode.getDateTimeFromBlockIndex(cancelCoin.spentBlockIndex); + canceledTime = + await fullNode.getDateTimeFromBlockIndex(cancelCoin.spentBlockIndex); } else { canceledTime = null; } @@ -85,7 +94,8 @@ class ExchangeOfferRecordHydrationService { ); // look for message coins - final messageCoins = await fullNode.scroungeForReceivedNotificationCoins([messagePuzzlehash]); + final messageCoins = await fullNode + .scroungeForReceivedNotificationCoins([messagePuzzlehash]); if (messageCoins.isEmpty) { // still waiting for taker @@ -94,7 +104,8 @@ class ExchangeOfferRecordHydrationService { final messageCoinInfos = []; for (final messageCoin in messageCoins) { - final messageCoinInfo = await exchangeOfferService.parseAndValidateReceivedMessageCoin( + final messageCoinInfo = + await exchangeOfferService.parseAndValidateReceivedMessageCoin( messageCoin: messageCoin, initializationCoinId: initializationCoinId, serializedOfferFile: serializedOfferFile, @@ -123,8 +134,8 @@ class ExchangeOfferRecordHydrationService { final serializedOfferAcceptFile = messageCoinInfo.serializedOfferAcceptFile; final fulfillerPublicKey = messageCoinInfo.fulfillerPublicKey; final exchangeValidityTime = messageCoinInfo.exchangeValidityTime; - final lightningPaymentRequest = - requestorLightningPaymentRequest ?? messageCoinInfo.lightningPaymentRequest!; + final lightningPaymentRequest = requestorLightningPaymentRequest ?? + messageCoinInfo.lightningPaymentRequest!; final messageCoinReceivedTime = messageCoinInfo.messageCoinReceivedTime; @@ -152,7 +163,9 @@ class ExchangeOfferRecordHydrationService { return exchangeOfferRecordWithMessageCoin; } - final escrowCoins = exchangeCoins.where((coin) => coin.puzzlehash == escrowPuzzlehash).toList(); + final escrowCoins = exchangeCoins + .where((coin) => coin.puzzlehash == escrowPuzzlehash) + .toList(); final toRemove = []; for (final escrowCoin in escrowCoins) { @@ -176,16 +189,19 @@ class ExchangeOfferRecordHydrationService { // escrow transfer has been completed final escrowCoinId = escrowCoins.first.id; - final parentCoin = await fullNode.getCoinById(escrowCoins.first.parentCoinInfo); + final parentCoin = + await fullNode.getCoinById(escrowCoins.first.parentCoinInfo); final escrowTransferCompletedBlockIndex = parentCoin!.spentBlockIndex; - final escrowTransferCompletedTime = - await fullNode.getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); + final escrowTransferCompletedTime = await fullNode + .getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); final escrowTransferConfirmedBlockIndex = escrowTransferCompletedBlockIndex + blocksForSufficientConfirmation; - final escrowTransferConfirmedTime = await getConfirmedTime(escrowTransferCompletedBlockIndex); + final escrowTransferConfirmedTime = + await getConfirmedTime(escrowTransferCompletedBlockIndex); - final exchangeOfferRecordAfterEscrowTransfer = exchangeOfferRecordWithMessageCoin.copyWith( + final exchangeOfferRecordAfterEscrowTransfer = + exchangeOfferRecordWithMessageCoin.copyWith( escrowCoinId: escrowCoinId, escrowTransferCompletedTime: escrowTransferCompletedTime, escrowTransferConfirmedBlockIndex: escrowTransferConfirmedBlockIndex, @@ -202,7 +218,8 @@ class ExchangeOfferRecordHydrationService { // escrow coins have been swept or clawed back final completedBlockIndex = spentEscrowCoins.first.spentBlockIndex; - final completedTime = await fullNode.getDateTimeFromBlockIndex(completedBlockIndex); + final completedTime = + await fullNode.getDateTimeFromBlockIndex(completedBlockIndex); final requestorSpentEscrowCoins = await didRequestorSpendEscrowCoins( spentEscrowCoin: spentEscrowCoins.first, @@ -251,8 +268,8 @@ class ExchangeOfferRecordHydrationService { NotificationCoin sentMessageCoin, WalletKeychain keychain, ) async { - final messageCoinReceivedTime = - await fullNode.getDateTimeFromBlockIndex(sentMessageCoin.spentBlockIndex); + final messageCoinReceivedTime = await fullNode + .getDateTimeFromBlockIndex(sentMessageCoin.spentBlockIndex); final messagePuzzlehash = sentMessageCoin.targetPuzzlehash; late final Bytes? initializationCoinId; @@ -260,10 +277,13 @@ class ExchangeOfferRecordHydrationService { late final TakerCrossChainOfferFile? offerAcceptFile; try { initializationCoinId = sentMessageCoin.message.first; - serializedOfferAcceptFile = decodeStringFromBytes(sentMessageCoin.message[1]); + serializedOfferAcceptFile = + decodeStringFromBytes(sentMessageCoin.message[1]); offerAcceptFile = - await TakerCrossChainOfferFile.fromSerializedOfferFileAsync(serializedOfferAcceptFile!); + await TakerCrossChainOfferFile.fromSerializedOfferFileAsync( + serializedOfferAcceptFile!, + ); } catch (e) { LoggingContext().error(e.toString()); throw InvalidMessageCoinException(); @@ -272,7 +292,8 @@ class ExchangeOfferRecordHydrationService { final requestorPublicKey = offerAcceptFile.publicKey; final exchangeValidityTime = offerAcceptFile.validityTime; final exchangeType = offerAcceptFile.exchangeType; - final requestorLightningPaymentRequest = offerAcceptFile.lightningPaymentRequest; + final requestorLightningPaymentRequest = + offerAcceptFile.lightningPaymentRequest; const exchangeRole = ExchangeRole.taker; // find private key matching public key in offer accept file in keychain @@ -291,13 +312,16 @@ class ExchangeOfferRecordHydrationService { // get serialized offer file final initializationCoin = await fullNode.getCoinById(initializationCoinId); - final initializationCoinSpend = await fullNode.getCoinSpend(initializationCoin!); + final initializationCoinSpend = + await fullNode.getCoinSpend(initializationCoin!); final initializationCoinMemos = await initializationCoinSpend!.memos; final serializedOfferFile = initializationCoinMemos.last.decodedString!; late final MakerCrossChainOfferFile offerFile; try { - offerFile = await MakerCrossChainOfferFile.fromSerializedOfferFileAsync(serializedOfferFile); + offerFile = await MakerCrossChainOfferFile.fromSerializedOfferFileAsync( + serializedOfferFile, + ); } catch (e) { LoggingContext().error(e.toString()); throw InvalidInitializationCoinException(); @@ -320,19 +344,24 @@ class ExchangeOfferRecordHydrationService { fulfillerPublicKey: fulfillerPublicKey, ); - final submittedToDexie = await getDexieSubmissionStatus(serializedOfferFile); + final submittedToDexie = + await getDexieSubmissionStatus(serializedOfferFile); // check whether the 3 mojo addition from the initialization coin spend was spent, indicating cancelation - final cancelCoin = - await exchangeOfferService.getCancelCoin(initializationCoin, messagePuzzlehash); + final cancelCoin = await exchangeOfferService.getCancelCoin( + initializationCoin, + messagePuzzlehash, + ); late final DateTime? canceledTime; if (cancelCoin.isSpent) { - canceledTime = await fullNode.getDateTimeFromBlockIndex(cancelCoin.spentBlockIndex); + canceledTime = + await fullNode.getDateTimeFromBlockIndex(cancelCoin.spentBlockIndex); } else { canceledTime = null; } - final messageCoinChild = await fullNode.getSingleChildCoinFromCoin(sentMessageCoin); + final messageCoinChild = + await fullNode.getSingleChildCoinFromCoin(sentMessageCoin); if (messageCoinChild == null) { throw MissingMessageCoinChildException(); @@ -367,8 +396,8 @@ class ExchangeOfferRecordHydrationService { final makerMessageCoinSpend = await fullNode.getCoinSpend(messageCoinChild); final memos = await makerMessageCoinSpend!.memos; - final messageCoinChildSpentTime = - await fullNode.getDateTimeFromBlockIndex(messageCoinChild.spentBlockIndex); + final messageCoinChildSpentTime = await fullNode + .getDateTimeFromBlockIndex(messageCoinChild.spentBlockIndex); if (!memos.contains(initializationCoinId)) { // message coin was declined @@ -378,8 +407,8 @@ class ExchangeOfferRecordHydrationService { } // message coin was accepted, check for escrow transfer - final escrowCoins = - await fullNode.getCoinsByPuzzleHashes([escrowPuzzlehash], includeSpentCoins: true); + final escrowCoins = await fullNode + .getCoinsByPuzzleHashes([escrowPuzzlehash], includeSpentCoins: true); final toRemove = []; for (final escrowCoin in escrowCoins) { @@ -396,7 +425,8 @@ class ExchangeOfferRecordHydrationService { escrowCoins.removeWhere(toRemove.contains); - final exchangeOfferRecordAfterMessageCoinAcceptance = exchangeOfferRecord.copyWith( + final exchangeOfferRecordAfterMessageCoinAcceptance = + exchangeOfferRecord.copyWith( messageCoinAcceptedTime: messageCoinChildSpentTime, ); @@ -407,14 +437,16 @@ class ExchangeOfferRecordHydrationService { // funds were transfered to escrow address final escrowCoinId = escrowCoins.first.id; - final parentCoin = await fullNode.getCoinById(escrowCoins.first.parentCoinInfo); + final parentCoin = + await fullNode.getCoinById(escrowCoins.first.parentCoinInfo); final escrowTransferCompletedBlockIndex = parentCoin!.spentBlockIndex; - final escrowTransferCompletedTime = - await fullNode.getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); + final escrowTransferCompletedTime = await fullNode + .getDateTimeFromBlockIndex(escrowTransferCompletedBlockIndex); final escrowTransferConfirmedBlockIndex = escrowTransferCompletedBlockIndex + blocksForSufficientConfirmation; - final escrowTransferConfirmedTime = await getConfirmedTime(escrowTransferCompletedBlockIndex); + final escrowTransferConfirmedTime = + await getConfirmedTime(escrowTransferCompletedBlockIndex); final exchangeOfferRecordAfterEscrowTransfer = exchangeOfferRecordAfterMessageCoinAcceptance.copyWith( @@ -434,7 +466,8 @@ class ExchangeOfferRecordHydrationService { // escrow coins have been swept or clawed back final completedBlockIndex = spentEscrowCoins.first.spentBlockIndex; - final completedTime = await fullNode.getDateTimeFromBlockIndex(completedBlockIndex); + final completedTime = + await fullNode.getDateTimeFromBlockIndex(completedBlockIndex); final requestorSpentEscrowCoins = await didRequestorSpendEscrowCoins( spentEscrowCoin: spentEscrowCoins.first, @@ -480,7 +513,8 @@ class ExchangeOfferRecordHydrationService { } Future getConfirmedTime(int completedBlockIndex) async { - final expectedConfirmedBlockIndex = completedBlockIndex + blocksForSufficientConfirmation; + final expectedConfirmedBlockIndex = + completedBlockIndex + blocksForSufficientConfirmation; final currentBlockIndex = await fullNode.getCurrentBlockIndex(); if (currentBlockIndex != null) { @@ -488,8 +522,8 @@ class ExchangeOfferRecordHydrationService { // if we are 32 blocks past the completed block index, then check the next 20 blocks for the // closest block with a peak and therefore a date time for (var i = 0; i < 20; i++) { - final confirmedTime = - await fullNode.getDateTimeFromBlockIndex(expectedConfirmedBlockIndex + i); + final confirmedTime = await fullNode + .getDateTimeFromBlockIndex(expectedConfirmedBlockIndex + i); if (confirmedTime != null) return confirmedTime; } @@ -534,9 +568,11 @@ class ExchangeOfferRecordHydrationService { .then((value) => ExchangeCoinMemos.maybeFromMemos(value.memos)); // determine who spent the escrow coins by checking the key that was used to sign the memo - if (completionSpendMemos != null && completionSpendMemos.verify(requestorPublicKey)) { + if (completionSpendMemos != null && + completionSpendMemos.verify(requestorPublicKey)) { return true; - } else if (completionSpendMemos != null && completionSpendMemos.verify(fulfillerPublicKey)) { + } else if (completionSpendMemos != null && + completionSpendMemos.verify(fulfillerPublicKey)) { return false; } else { // if memos are incorrect, try to determine who spent the coins by checking whether the additions @@ -544,8 +580,8 @@ class ExchangeOfferRecordHydrationService { // if so, then the requestor was the one who spent the escrow coins, if not then it was the fulfilelr final additionPuzzlehashes = completionCoinSpend.additions.map((addition) => addition.puzzlehash); - final requestorPuzzlehashesInAdditions = - additionPuzzlehashes.where((ph) => requestorPuzzlehashes.contains(ph)); + final requestorPuzzlehashesInAdditions = additionPuzzlehashes + .where((ph) => requestorPuzzlehashes.contains(ph)); if (requestorPuzzlehashesInAdditions.isNotEmpty) { return true; diff --git a/lib/src/exchange/btc/exchange_offer_record/service/exchange_offer_service.dart b/lib/src/exchange/btc/exchange_offer_record/service/exchange_offer_service.dart index 5f9660c0..a92c417e 100644 --- a/lib/src/exchange/btc/exchange_offer_record/service/exchange_offer_service.dart +++ b/lib/src/exchange/btc/exchange_offer_record/service/exchange_offer_service.dart @@ -8,7 +8,8 @@ class ExchangeOfferService { final ChiaFullNodeInterface fullNode; final StandardWalletService standardWalletService = StandardWalletService(); - final ExchangeOfferWalletService exchangeOfferWalletService = ExchangeOfferWalletService(); + final ExchangeOfferWalletService exchangeOfferWalletService = + ExchangeOfferWalletService(); Future pushInitializationSpendBundle({ required Puzzlehash messagePuzzlehash, @@ -20,9 +21,11 @@ class ExchangeOfferService { Puzzlehash? changePuzzlehash, int fee = 0, List coinAnnouncementsToAssert = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], }) async { - final initializationSpendBundle = exchangeOfferWalletService.createInitializationSpendBundle( + final initializationSpendBundle = + exchangeOfferWalletService.createInitializationSpendBundle( messagePuzzlehash: messagePuzzlehash, coinsInput: coinsInput, keychain: keychain, @@ -51,14 +54,20 @@ class ExchangeOfferService { int fee = 0, Bytes? originId, List coinAnnouncementsToAssert = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], }) async { final initializationCoin = await fullNode.getCoinById(initializationCoinId); - final cancelCoin = await getCancelCoin(initializationCoin!, messagePuzzlehash); + final cancelCoin = + await getCancelCoin(initializationCoin!, messagePuzzlehash); - final walletVector = await WalletVector.fromPrivateKeyAsync(masterPrivateKey, derivationIndex); + final walletVector = await WalletVector.fromPrivateKeyAsync( + masterPrivateKey, + derivationIndex, + ); - final cancelationSpendBundle = exchangeOfferWalletService.createCancelationSpendBundle( + final cancelationSpendBundle = + exchangeOfferWalletService.createCancelationSpendBundle( initializationCoinId: initializationCoinId, targetPuzzlehash: targetPuzzlehash, cancelCoin: cancelCoin, @@ -99,18 +108,24 @@ class ExchangeOfferService { Puzzlehash? changePuzzlehash, Bytes? originId, List coinAnnouncementsToAssert = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], }) async { // check whether offer is canceled - final cancelCoin = - (await fullNode.getCoinsByPuzzleHashes([messagePuzzlehash], includeSpentCoins: true)) - .where((coin) => coin.parentCoinInfo == initializationCoinId && coin.amount == 3); + final cancelCoin = (await fullNode.getCoinsByPuzzleHashes( + [messagePuzzlehash], + includeSpentCoins: true, + )) + .where( + (coin) => coin.parentCoinInfo == initializationCoinId && coin.amount == 3, + ); if (cancelCoin.isNotEmpty) { if (cancelCoin.first.isSpent) throw OfferCanceledException(); } - final messageSpendBundle = exchangeOfferWalletService.createMessageSpendBundle( + final messageSpendBundle = + exchangeOfferWalletService.createMessageSpendBundle( messagePuzzlehash: messagePuzzlehash, coinsInput: coinsInput, keychain: keychain, @@ -136,7 +151,8 @@ class ExchangeOfferService { List declinedMessageCoinIds = const [], }) async { // find valid message coin that hasn't been accepted or declined yet - final messageCoins = await fullNode.scroungeForReceivedNotificationCoins([messagePuzzlehash]); + final messageCoins = await fullNode + .scroungeForReceivedNotificationCoins([messagePuzzlehash]); for (final messageCoin in messageCoins) { if (declinedMessageCoinIds.contains(messageCoin.id)) { @@ -174,17 +190,23 @@ class ExchangeOfferService { } try { - final serializedOfferAcceptFileMemo = decodeStringFromBytes(messageCoin.message.last); - final offerAcceptFile = await TakerCrossChainOfferFile.fromSerializedOfferFileAsync( + final serializedOfferAcceptFileMemo = + decodeStringFromBytes(messageCoin.message.last); + final offerAcceptFile = + await TakerCrossChainOfferFile.fromSerializedOfferFileAsync( serializedOfferAcceptFileMemo!, ); switch (exchangeType) { case ExchangeType.xchToBtc: - if (offerAcceptFile.type != CrossChainOfferFileType.btcToXchAccept) return null; + if (offerAcceptFile.type != CrossChainOfferFileType.btcToXchAccept) { + return null; + } break; case ExchangeType.btcToXch: - if (offerAcceptFile.type != CrossChainOfferFileType.xchToBtcAccept) return null; + if (offerAcceptFile.type != CrossChainOfferFileType.xchToBtcAccept) { + return null; + } break; } @@ -192,24 +214,32 @@ class ExchangeOfferService { Bytes.encodeFromString(serializedOfferFile).sha256Hash()) { LightningPaymentRequest? lightningPaymentRequest; if (offerAcceptFile.type == CrossChainOfferFileType.xchToBtcAccept) { - final xchToBtcOfferAcceptFile = offerAcceptFile as XchToBtcTakerOfferFile; + final xchToBtcOfferAcceptFile = + offerAcceptFile as XchToBtcTakerOfferFile; - lightningPaymentRequest = xchToBtcOfferAcceptFile.lightningPaymentRequest; + lightningPaymentRequest = + xchToBtcOfferAcceptFile.lightningPaymentRequest; - if (!validateLightningPaymentRequest(lightningPaymentRequest, satoshis!)) return null; + if (!validateLightningPaymentRequest( + lightningPaymentRequest, + satoshis!, + )) return null; } - final spentTime = await fullNode.getDateTimeFromBlockIndex(messageCoin.spentBlockIndex); + final spentTime = await fullNode + .getDateTimeFromBlockIndex(messageCoin.spentBlockIndex); - final messageCoinChild = await fullNode.getSingleChildCoinFromCoin(messageCoin); + final messageCoinChild = + await fullNode.getSingleChildCoinFromCoin(messageCoin); if (messageCoinChild == null) return null; if (messageCoinChild.isSpent) { - final messageCoinChildSpend = await fullNode.getCoinSpend(messageCoinChild); + final messageCoinChildSpend = + await fullNode.getCoinSpend(messageCoinChild); final spentMessageCoinChildMemos = await messageCoinChildSpend!.memos; - final messageCoinChildSpentTime = - await fullNode.getDateTimeFromBlockIndex(messageCoinChild.spentBlockIndex); + final messageCoinChildSpentTime = await fullNode + .getDateTimeFromBlockIndex(messageCoinChild.spentBlockIndex); if (spentMessageCoinChildMemos.contains(initializationCoinId)) { // message coin was accepted @@ -264,17 +294,23 @@ class ExchangeOfferService { int fee = 0, Bytes? originId, List coinAnnouncementsToAssert = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], }) async { - final messageCoinChild = await fullNode.getSingleChildCoinFromCoin(messageCoin); + final messageCoinChild = + await fullNode.getSingleChildCoinFromCoin(messageCoin); if (messageCoinChild == null) { throw MissingMessageCoinChildException(); } - final walletVector = await WalletVector.fromPrivateKeyAsync(masterPrivateKey, derivationIndex); + final walletVector = await WalletVector.fromPrivateKeyAsync( + masterPrivateKey, + derivationIndex, + ); - final acceptanceSpendBundle = exchangeOfferWalletService.createMessageCoinAcceptanceSpendBundle( + final acceptanceSpendBundle = + exchangeOfferWalletService.createMessageCoinAcceptanceSpendBundle( initializationCoinId: initializationCoinId, messageCoinChild: messageCoinChild, targetPuzzlehash: targetPuzzlehash, @@ -317,15 +353,20 @@ class ExchangeOfferService { int fee = 0, Bytes? originId, List coinAnnouncementsToAssert = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], }) async { - final messageCoinChild = await fullNode.getSingleChildCoinFromCoin(messageCoin); + final messageCoinChild = + await fullNode.getSingleChildCoinFromCoin(messageCoin); if (messageCoinChild == null) { throw MissingMessageCoinChildException(); } - final walletVector = await WalletVector.fromPrivateKeyAsync(masterPrivateKey, derivationIndex); + final walletVector = await WalletVector.fromPrivateKeyAsync( + masterPrivateKey, + derivationIndex, + ); final declinationSpendBundle = exchangeOfferWalletService.createMessageCoinDeclinationSpendBundle( @@ -368,9 +409,11 @@ class ExchangeOfferService { int fee = 0, Bytes? originId, List coinAnnouncementsToAssert = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], }) async { - final escrowSpendBundle = exchangeOfferWalletService.createEscrowTransferSpendBundle( + final escrowSpendBundle = + exchangeOfferWalletService.createEscrowTransferSpendBundle( initializationCoinId: initializationCoinId, mojos: mojos, escrowPuzzlehash: escrowPuzzlehash, @@ -403,9 +446,11 @@ class ExchangeOfferService { int fee = 0, Bytes? originId, List coinAnnouncementsToAssert = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], }) async { - final escrowCoins = await fullNode.getCoinsByPuzzleHashes([escrowPuzzlehash]); + final escrowCoins = + await fullNode.getCoinsByPuzzleHashes([escrowPuzzlehash]); final sweepSpendBundle = exchangeOfferWalletService.createSweepSpendBundle( initializationCoinId: initializationCoinId, @@ -455,11 +500,14 @@ class ExchangeOfferService { int fee = 0, Bytes? originId, List coinAnnouncementsToAssert = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], }) async { - final escrowCoins = await fullNode.getCoinsByPuzzleHashes([escrowPuzzlehash]); + final escrowCoins = + await fullNode.getCoinsByPuzzleHashes([escrowPuzzlehash]); - final clawbackSpendBundle = exchangeOfferWalletService.createClawbackSpendBundle( + final clawbackSpendBundle = + exchangeOfferWalletService.createClawbackSpendBundle( initializationCoinId: initializationCoinId, escrowCoins: escrowCoins, requestorPuzzlehash: requestorPuzzlehash, @@ -492,7 +540,8 @@ class ExchangeOfferService { return result; } - static int randomDerivationIndexForExchange() => Random.secure().nextInt(9000000) + 1000000; + static int randomDerivationIndexForExchange() => + Random.secure().nextInt(9000000) + 1000000; bool validateLightningPaymentRequest( LightningPaymentRequest lightningPaymentRequest, @@ -529,12 +578,18 @@ class ExchangeOfferService { return totalSpendBundle; } - Future getCancelCoin(Coin initializationCoin, Puzzlehash messagePuzzlehash) async { + Future getCancelCoin( + Coin initializationCoin, + Puzzlehash messagePuzzlehash, + ) async { try { - final initializationCoinSpend = await fullNode.getCoinSpend(initializationCoin); + final initializationCoinSpend = + await fullNode.getCoinSpend(initializationCoin); final additions = await initializationCoinSpend!.additionsAsync; - final cancelCoinId = - additions.where((addition) => addition.puzzlehash == messagePuzzlehash).single.id; + final cancelCoinId = additions + .where((addition) => addition.puzzlehash == messagePuzzlehash) + .single + .id; final cancelCoin = await fullNode.getCoinById(cancelCoinId); return cancelCoin!; } catch (e) { diff --git a/lib/src/exchange/btc/exchange_offer_record/service/exchange_offer_wallet_service.dart b/lib/src/exchange/btc/exchange_offer_record/service/exchange_offer_wallet_service.dart index 79bb3405..c2971ee2 100644 --- a/lib/src/exchange/btc/exchange_offer_record/service/exchange_offer_wallet_service.dart +++ b/lib/src/exchange/btc/exchange_offer_record/service/exchange_offer_wallet_service.dart @@ -19,7 +19,8 @@ class ExchangeOfferWalletService { Puzzlehash? changePuzzlehash, int fee = 0, List coinAnnouncementsToAssert = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], }) { final initializationSpendBundle = standardWalletService.createSpendBundle( payments: [ @@ -51,7 +52,8 @@ class ExchangeOfferWalletService { required WalletVector walletVector, Bytes? originId, List coinAnnouncementsToAssert = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], }) { final requestorPrivateKey = walletVector.childPrivateKey; @@ -60,7 +62,8 @@ class ExchangeOfferWalletService { requestorPrivateKey: requestorPrivateKey, ).toMemos(); - final messagePuzzlehashKeychain = makeKeychainFromWalletVector(walletVector); + final messagePuzzlehashKeychain = + makeKeychainFromWalletVector(walletVector); final cancelationSpendBundle = standardWalletService.createSpendBundle( payments: [ @@ -87,11 +90,13 @@ class ExchangeOfferWalletService { Puzzlehash? changePuzzlehash, Bytes? originId, List coinAnnouncementsToAssert = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], }) { final notificationService = NotificationWalletService(); - final notificationSpendBundle = notificationService.createNotificationSpendBundle( + final notificationSpendBundle = + notificationService.createNotificationSpendBundle( targetPuzzlehash: messagePuzzlehash, message: [ Memo(initializationCoinId), @@ -117,7 +122,8 @@ class ExchangeOfferWalletService { required WalletVector walletVector, Bytes? originId, List coinAnnouncementsToAssert = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], }) { final requestorPrivateKey = walletVector.childPrivateKey; @@ -126,7 +132,8 @@ class ExchangeOfferWalletService { requestorPrivateKey: requestorPrivateKey, ).toMemos(); - final messagePuzzlehashKeychain = makeKeychainFromWalletVector(walletVector); + final messagePuzzlehashKeychain = + makeKeychainFromWalletVector(walletVector); final acceptanceSpendBundle = standardWalletService.createSpendBundle( payments: [ @@ -152,9 +159,11 @@ class ExchangeOfferWalletService { required WalletVector walletVector, Bytes? originId, List coinAnnouncementsToAssert = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], }) { - final messagePuzzlehashKeychain = makeKeychainFromWalletVector(walletVector); + final messagePuzzlehashKeychain = + makeKeychainFromWalletVector(walletVector); final declinationSpendBundle = standardWalletService.createSpendBundle( payments: [ @@ -181,7 +190,8 @@ class ExchangeOfferWalletService { int fee = 0, Bytes? originId, List coinAnnouncementsToAssert = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], }) { final memos = ExchangeCoinMemos( initializationCoinId: initializationCoinId, @@ -219,7 +229,8 @@ class ExchangeOfferWalletService { required JacobianPoint fulfillerPublicKey, Bytes? originId, List coinAnnouncementsToAssert = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], }) { final btcToXchService = BtcToXchService(); final memos = ExchangeCoinMemos( @@ -259,7 +270,8 @@ class ExchangeOfferWalletService { required JacobianPoint fulfillerPublicKey, Bytes? originId, List coinAnnouncementsToAssert = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], }) { final xchToBtcService = XchToBtcService(); final memos = ExchangeCoinMemos( @@ -268,7 +280,9 @@ class ExchangeOfferWalletService { ).toMemos(); final clawbackSpendBundle = xchToBtcService.createClawbackSpendBundle( - payments: [Payment(escrowCoins.totalValue, requestorPuzzlehash, memos: memos)], + payments: [ + Payment(escrowCoins.totalValue, requestorPuzzlehash, memos: memos) + ], coinsInput: escrowCoins, requestorPrivateKey: requestorPrivateKey, clawbackDelaySeconds: exchangeValidityTime, @@ -282,7 +296,9 @@ class ExchangeOfferWalletService { return clawbackSpendBundle; } - static WalletKeychain makeKeychainFromWalletVector(WalletVector walletVector) { + static WalletKeychain makeKeychainFromWalletVector( + WalletVector walletVector, + ) { final hardenedMap = LinkedHashMap(); hardenedMap[walletVector.puzzlehash] = walletVector; diff --git a/lib/src/exchange/btc/service/btc_exchange_service.dart b/lib/src/exchange/btc/service/btc_exchange_service.dart index c91053c2..a9197437 100644 --- a/lib/src/exchange/btc/service/btc_exchange_service.dart +++ b/lib/src/exchange/btc/service/btc_exchange_service.dart @@ -16,7 +16,8 @@ class BtcExchangeService { int fee = 0, Bytes? originId, List coinAnnouncementsToAssert = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], }) { final requestorPublicKey = requestorPrivateKey.getG1(); @@ -81,7 +82,8 @@ class BtcExchangeService { final totalPublicKey = sweepPublicKey + clawbackPublicKey; - final puzzle = getPuzzleFromPkAndHiddenPuzzle(totalPublicKey, hiddenPuzzleProgram); + final puzzle = + getPuzzleFromPkAndHiddenPuzzle(totalPublicKey, hiddenPuzzleProgram); return puzzle; } @@ -128,7 +130,8 @@ class BtcExchangeService { p2DelayedOrPreimageSolution = Program.list([Program.fromAtom(sweepPreimage), delegatedSolution]); } else { - p2DelayedOrPreimageSolution = Program.list([Program.fromInt(0), delegatedSolution]); + p2DelayedOrPreimageSolution = + Program.list([Program.fromInt(0), delegatedSolution]); } final solution = Program.list( diff --git a/lib/src/exchange/btc/service/btc_to_xch_service.dart b/lib/src/exchange/btc/service/btc_to_xch_service.dart index cca1b18f..c954fb28 100644 --- a/lib/src/exchange/btc/service/btc_to_xch_service.dart +++ b/lib/src/exchange/btc/service/btc_to_xch_service.dart @@ -37,7 +37,8 @@ class BtcToXchService { int fee = 0, Bytes? originId, List coinAnnouncementsToAssert = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], }) { return exchangeService.createExchangeSpendBundle( payments: payments, @@ -66,7 +67,8 @@ class BtcToXchService { int fee = 0, Bytes? originId, List coinAnnouncementsToAssert = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], }) { final requestorPublicKey = requestorPrivateKey.getG1(); final fulfillerPublicKey = fulfillerPrivateKey.getG1(); diff --git a/lib/src/exchange/btc/service/xch_to_btc_service.dart b/lib/src/exchange/btc/service/xch_to_btc_service.dart index 165df026..26cbb4d8 100644 --- a/lib/src/exchange/btc/service/xch_to_btc_service.dart +++ b/lib/src/exchange/btc/service/xch_to_btc_service.dart @@ -34,7 +34,8 @@ class XchToBtcService { int fee = 0, Bytes? originId, List coinAnnouncementsToAssert = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], }) { return exchangeService.createExchangeSpendBundle( payments: payments, @@ -62,7 +63,8 @@ class XchToBtcService { int fee = 0, Bytes? originId, List coinAnnouncementsToAssert = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], }) { final requestorPublicKey = requestorPrivateKey.getG1(); final fulfillerPublicKey = fulfillerPrivateKey.getG1(); diff --git a/lib/src/exchange/btc/utils/decode_lightning_payment_request.dart b/lib/src/exchange/btc/utils/decode_lightning_payment_request.dart index 65f71ad7..5bda7d48 100644 --- a/lib/src/exchange/btc/utils/decode_lightning_payment_request.dart +++ b/lib/src/exchange/btc/utils/decode_lightning_payment_request.dart @@ -42,7 +42,8 @@ LightningPaymentRequest decodeLightningPaymentRequest(String paymentRequest) { final amountData = hrp.substring(prefix.length, hrp.length); if (multiplierMap.containsKey(amountData[amountData.length - 1])) { final multiplier = amountData.substring(amountData.length - 1); - final digits = double.parse(amountData.substring(0, amountData.length - 1)); + final digits = + double.parse(amountData.substring(0, amountData.length - 1)); amount = digits * multiplierMap[multiplier]!; } else { amount = double.parse(amountData); @@ -84,7 +85,11 @@ LightningPaymentRequest decodeLightningPaymentRequest(String paymentRequest) { } if (size > 10) { - taggedFieldData = bigIntToBytes(taggedFieldData as BigInt, (bitSize + 7) >> 3, Endian.big); + taggedFieldData = bigIntToBytes( + taggedFieldData as BigInt, + (bitSize + 7) >> 3, + Endian.big, + ); } if (type == 3) { @@ -102,7 +107,8 @@ LightningPaymentRequest decodeLightningPaymentRequest(String paymentRequest) { final decodedTags = decodeTags(encodedTags); // signature - final signatureData = convertBitsBigInt(taggedFields, 5, 520, pad: true)[0].toRadixString(16); + final signatureData = + convertBitsBigInt(taggedFields, 5, 520, pad: true)[0].toRadixString(16); final fullSignature = signatureData.substring(0, signatureData.length - 2); final rValue = fullSignature.substring(0, 64); final sValue = fullSignature.substring(64); @@ -166,7 +172,8 @@ PaymentRequestTags decodeTags(Map encodedTags) { final fallbackAddressData = data as Bytes; final version = fallbackAddressData[0]; final addressHash = fallbackAddressData.sublist(1).toHex(); - fallbackAddress = FallbackAddress(version: version, addressHash: addressHash); + fallbackAddress = + FallbackAddress(version: version, addressHash: addressHash); } break; case 13: @@ -212,14 +219,19 @@ PaymentRequestTags decodeTags(Map encodedTags) { RouteInfo decodeRouteInfo(List data) { final routeData = convertBits(data, 5, 8, pad: true); - final publicKey = convertBitsBigInt(routeData.sublist(0, 33), 8, 264, pad: true)[0] - .toRadixString(16) - .padLeft(66, '0'); + final publicKey = + convertBitsBigInt(routeData.sublist(0, 33), 8, 264, pad: true)[0] + .toRadixString(16) + .padLeft(66, '0'); final shortChannelId = - convertBitsBigInt(routeData.sublist(33, 41), 8, 64, pad: true)[0].toRadixString(16); - final feeBaseMsats = convertBits(routeData.sublist(41, 45), 8, 32, pad: true)[0]; - final feeProportionalMillionths = convertBits(routeData.sublist(45, 49), 8, 32, pad: true)[0]; - final cltvExpiryDelta = convertBits(routeData.sublist(49, 51), 8, 16, pad: true)[0]; + convertBitsBigInt(routeData.sublist(33, 41), 8, 64, pad: true)[0] + .toRadixString(16); + final feeBaseMsats = + convertBits(routeData.sublist(41, 45), 8, 32, pad: true)[0]; + final feeProportionalMillionths = + convertBits(routeData.sublist(45, 49), 8, 32, pad: true)[0]; + final cltvExpiryDelta = + convertBits(routeData.sublist(49, 51), 8, 16, pad: true)[0]; return RouteInfo( publicKey: publicKey, diff --git a/lib/src/networks/chia/chia_blockchain_network_loader.dart b/lib/src/networks/chia/chia_blockchain_network_loader.dart index 66886b20..a1e24279 100644 --- a/lib/src/networks/chia/chia_blockchain_network_loader.dart +++ b/lib/src/networks/chia/chia_blockchain_network_loader.dart @@ -12,10 +12,10 @@ class ChiaBlockchainNetworkLoader implements BlockchainNetworkLoader { final dynamic selectedNetwork = yaml['full_node']['selected_network']; return BlockchainNetwork( name: selectedNetwork as String, - addressPrefix: yaml['farmer']['network_overrides']['config'][selectedNetwork] - ['address_prefix']! as String, - aggSigMeExtraData: yaml['farmer']['network_overrides']['constants'][selectedNetwork] - ['GENESIS_CHALLENGE']! as String, + addressPrefix: yaml['farmer']['network_overrides']['config'] + [selectedNetwork]['address_prefix']! as String, + aggSigMeExtraData: yaml['farmer']['network_overrides']['constants'] + [selectedNetwork]['GENESIS_CHALLENGE']! as String, networkConfig: yaml, ); } diff --git a/lib/src/networks/chia/mainnet/mainnet_blockchain_network.dart b/lib/src/networks/chia/mainnet/mainnet_blockchain_network.dart index abb0b82c..ef7e9d9a 100644 --- a/lib/src/networks/chia/mainnet/mainnet_blockchain_network.dart +++ b/lib/src/networks/chia/mainnet/mainnet_blockchain_network.dart @@ -3,5 +3,6 @@ import 'package:chia_crypto_utils/chia_crypto_utils.dart'; final mainnetBlockchainNetwork = BlockchainNetwork( name: 'mainnet', addressPrefix: 'xch', - aggSigMeExtraData: 'ccd5bb71183532bff220ba46c268991a3ff07eb358e8255a65c30a2dce0e5fbb', + aggSigMeExtraData: + 'ccd5bb71183532bff220ba46c268991a3ff07eb358e8255a65c30a2dce0e5fbb', ); diff --git a/lib/src/networks/chia/testnet0/testnet0_blockchain_network.dart b/lib/src/networks/chia/testnet0/testnet0_blockchain_network.dart index 8f09c60d..fb64915e 100644 --- a/lib/src/networks/chia/testnet0/testnet0_blockchain_network.dart +++ b/lib/src/networks/chia/testnet0/testnet0_blockchain_network.dart @@ -3,5 +3,6 @@ import 'package:chia_crypto_utils/chia_crypto_utils.dart'; final testnet0BlockchainNetwork = BlockchainNetwork( name: 'testnet0', addressPrefix: 'txch', - aggSigMeExtraData: 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', + aggSigMeExtraData: + 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', ); diff --git a/lib/src/networks/chia/testnet10/testnet10_blockchain_network.dart b/lib/src/networks/chia/testnet10/testnet10_blockchain_network.dart index 3164e015..41cc57d7 100644 --- a/lib/src/networks/chia/testnet10/testnet10_blockchain_network.dart +++ b/lib/src/networks/chia/testnet10/testnet10_blockchain_network.dart @@ -3,5 +3,6 @@ import 'package:chia_crypto_utils/chia_crypto_utils.dart'; final testnet10BlockchainNetwork = BlockchainNetwork( name: 'testnet10', addressPrefix: 'txch', - aggSigMeExtraData: 'ae83525ba8d1dd3f09b277de18ca3e43fc0af20d20c4b3e92ef2a48bd291ccb2', + aggSigMeExtraData: + 'ae83525ba8d1dd3f09b277de18ca3e43fc0af20d20c4b3e92ef2a48bd291ccb2', ); diff --git a/lib/src/nft/models/nft_data/collection.dart b/lib/src/nft/models/nft_data/collection.dart index 58659ece..7f67d10e 100644 --- a/lib/src/nft/models/nft_data/collection.dart +++ b/lib/src/nft/models/nft_data/collection.dart @@ -12,7 +12,8 @@ class Collection { required this.banner, }); factory Collection.fromJson(Map json) { - final attributes = pick(json, 'attributes').letJsonListOrThrow(CollectionAttribute.fromJson); + final attributes = pick(json, 'attributes') + .letJsonListOrThrow(CollectionAttribute.fromJson); return Collection.fromAttributes( name: pick(json, 'name').asStringOrThrow(), @@ -61,7 +62,9 @@ extension AttributeMap on Iterable { }; } -class CollectionAttribute extends Equatable with ToJsonMixin implements Attribute { +class CollectionAttribute extends Equatable + with ToJsonMixin + implements Attribute { const CollectionAttribute({ required this.type, required this.value, diff --git a/lib/src/nft/models/nft_data/collection_override.dart b/lib/src/nft/models/nft_data/collection_override.dart index 0e9504db..4607437d 100644 --- a/lib/src/nft/models/nft_data/collection_override.dart +++ b/lib/src/nft/models/nft_data/collection_override.dart @@ -10,7 +10,9 @@ class NftCollectionOverride with ToJsonMixin { factory NftCollectionOverride.fromJson(Map json) { return NftCollectionOverride( name: pick(json, 'name').asStringOrNull(), - attributes: pick(json, 'attributes').letJsonListOrNull(CollectionAttribute.fromJson) ?? [], + attributes: pick(json, 'attributes') + .letJsonListOrNull(CollectionAttribute.fromJson) ?? + [], ); } diff --git a/lib/src/nft/models/nft_data/nft_data_0007.dart b/lib/src/nft/models/nft_data/nft_data_0007.dart index aef0e041..a5ebd8ca 100644 --- a/lib/src/nft/models/nft_data/nft_data_0007.dart +++ b/lib/src/nft/models/nft_data/nft_data_0007.dart @@ -24,7 +24,9 @@ class NftData0007 with ToJsonMixin { description: pick(json, 'description').asStringOrThrow(), sensitiveContent: pick(json, 'sensitive_content').asBoolOrFalse(), collection: pick(json, 'collection').letJsonOrThrow(Collection.fromJson), - attributes: pick(json, 'attributes').letJsonListOrNull(NftAttribute.fromJson) ?? [], + attributes: + pick(json, 'attributes').letJsonListOrNull(NftAttribute.fromJson) ?? + [], seriesNumber: pick(json, 'series_number').asIntOrNull(), seriesTotal: pick(json, 'series_total').asIntOrNull(), json: json, @@ -51,7 +53,8 @@ class NftData0007 with ToJsonMixin { final attributesWithOverrides = Map.fromEntries(collectionAttributes.map((e) => MapEntry(e.type, e))); - for (final attributeOverride in collectionOverride.attributes ?? []) { + for (final attributeOverride + in collectionOverride.attributes ?? []) { attributesWithOverrides[attributeOverride.type] = attributeOverride; } return NftData0007( diff --git a/lib/src/nft/models/nft_metadata.dart b/lib/src/nft/models/nft_metadata.dart index 753d83a1..b580d6e5 100644 --- a/lib/src/nft/models/nft_metadata.dart +++ b/lib/src/nft/models/nft_metadata.dart @@ -164,7 +164,8 @@ class NftMetadata with ToBytesMixin { final List? licenseUris; final Program? _licenseHashProgram; - Bytes? get licenseHash => getBytesFromTypeAmbiguousProgram(_licenseHashProgram); + Bytes? get licenseHash => + getBytesFromTypeAmbiguousProgram(_licenseHashProgram); final int? editionNumber; @@ -183,7 +184,9 @@ class NftMetadata with ToBytesMixin { } static Bytes? getBytesFromTypeAmbiguousProgram(Program? program) => - (program != null && program != Program.nil) ? Bytes.fromHex(program.string) : null; + (program != null && program != Program.nil) + ? Bytes.fromHex(program.string) + : null; } class NftMintingDataWithHashes extends NftMintingData with ToJsonMixin { @@ -299,7 +302,9 @@ class NftMintingData with ToJsonMixin { final editionMintEnd = editionMintStart + totalNftsToMint; final nftMintData = [ - for (var editionNumber = editionMintStart; editionNumber < editionMintEnd; editionNumber++) + for (var editionNumber = editionMintStart; + editionNumber < editionMintEnd; + editionNumber++) NftMintingData.editioned( dataUri: dataUri, metaUri: metadataUri, @@ -331,15 +336,20 @@ class NftMintingData with ToJsonMixin { Program.fromInt(mintNumber), ]).hash(); - Future attachHashes(UriHashProvider hashProvider) async { + Future attachHashes( + UriHashProvider hashProvider, + ) async { return NftMintingDataWithHashes( dataUri: dataUri, dataHash: await hashProvider.getHashForUri(dataUri), metaUri: metaUri, mintNumber: mintNumber, - metaHash: (metaUri != null) ? await hashProvider.getHashForUri(metaUri!) : null, + metaHash: + (metaUri != null) ? await hashProvider.getHashForUri(metaUri!) : null, licenseUri: licenseUri, - licenseHash: licenseUri == null ? null : await hashProvider.getHashForUri(licenseUri!), + licenseHash: licenseUri == null + ? null + : await hashProvider.getHashForUri(licenseUri!), isEditioned: isEditioned, ); } @@ -351,7 +361,8 @@ class NftMintingData with ToJsonMixin { 'meta_uri': metaUri, if (licenseUri != null) 'license_uri': licenseUri, 'edition_number': editionNumber, - if (targetPuzzlehash != null) 'target_puzzlehash': targetPuzzlehash?.toHex(), + if (targetPuzzlehash != null) + 'target_puzzlehash': targetPuzzlehash?.toHex(), }; } } diff --git a/lib/src/nft/models/nft_mint_info.dart b/lib/src/nft/models/nft_mint_info.dart index e1bb30c8..1a9308b2 100644 --- a/lib/src/nft/models/nft_mint_info.dart +++ b/lib/src/nft/models/nft_mint_info.dart @@ -13,10 +13,17 @@ class NftMintInfo with ToBytesMixin { final minterDid = Puzzlehash.maybeFromStream(iterator); - return NftMintInfo(mintHeight: mintHeight, mintTimestamp: mintTimestamp, minterDid: minterDid); + return NftMintInfo( + mintHeight: mintHeight, + mintTimestamp: mintTimestamp, + minterDid: minterDid, + ); } - static Future maybeFromEveSpend(CoinSpend eveSpend, Coin eveCoin) async { + static Future maybeFromEveSpend( + CoinSpend eveSpend, + Coin eveCoin, + ) async { try { final nftMintInfo = await fromEveSpend(eveSpend, eveCoin); return nftMintInfo; @@ -26,8 +33,12 @@ class NftMintInfo with ToBytesMixin { } /// throws [InvalidMintInfoException] - static Future fromEveSpend(CoinSpend eveSpend, Coin eveCoin) async { - final uncurriedNft = await UncurriedNftPuzzle.fromProgram(eveSpend.puzzleReveal); + static Future fromEveSpend( + CoinSpend eveSpend, + Coin eveCoin, + ) async { + final uncurriedNft = + await UncurriedNftPuzzle.fromProgram(eveSpend.puzzleReveal); if (uncurriedNft == null) { return null; } @@ -54,10 +65,14 @@ class NftMintInfo with ToBytesMixin { ); if (didMagicConditions.length > 1) { - throw InvalidMintInfoException('More than one nft didMagicConditions condition'); + throw InvalidMintInfoException( + 'More than one nft didMagicConditions condition', + ); } if (didMagicConditions.isEmpty) { - throw InvalidMintInfoException('Expected did magic condition but found none'); + throw InvalidMintInfoException( + 'Expected did magic condition but found none', + ); } return NftMintInfo( @@ -69,7 +84,8 @@ class NftMintInfo with ToBytesMixin { final int mintHeight; final int mintTimestamp; - DateTime get dateMinted => DateTime.fromMillisecondsSinceEpoch(mintTimestamp * 1000); + DateTime get dateMinted => + DateTime.fromMillisecondsSinceEpoch(mintTimestamp * 1000); final Bytes? minterDid; diff --git a/lib/src/nft/models/nft_record/did_nft_record.dart b/lib/src/nft/models/nft_record/did_nft_record.dart index 87fd088a..8150fa34 100644 --- a/lib/src/nft/models/nft_record/did_nft_record.dart +++ b/lib/src/nft/models/nft_record/did_nft_record.dart @@ -56,7 +56,8 @@ class DidNftRecord implements NftRecord { /// convert to [Nft] with keychain @override Nft toNft(WalletKeychain keychain) { - final publicKey = keychain.getWalletVectorOrThrow(p2Puzzlehash).childPublicKey; + final publicKey = + keychain.getWalletVectorOrThrow(p2Puzzlehash).childPublicKey; final p2Puzzle = getPuzzleFromPk(publicKey); final innerPuzzle = NftWalletService.constructOwnershipLayer( currentOwnerDid: ownershipLayerInfo.currentDid, diff --git a/lib/src/nft/models/nft_record/nft_record.dart b/lib/src/nft/models/nft_record/nft_record.dart index 4500d899..85da2c79 100644 --- a/lib/src/nft/models/nft_record/nft_record.dart +++ b/lib/src/nft/models/nft_record/nft_record.dart @@ -73,7 +73,10 @@ abstract class NftRecord { ); final nftOutputConditions = createCoinConditions.where( - (element) => element.amount == 1 && element.memos != null && element.memos!.isNotEmpty, + (element) => + element.amount == 1 && + element.memos != null && + element.memos!.isNotEmpty, ); if (nftOutputConditions.isEmpty) { @@ -100,7 +103,9 @@ abstract class NftRecord { final currentOwnershipLayerInfo = uncurriedNft.ownershipLayerInfo; final ownershipLayerInfo = didMagicConditions.isNotEmpty - ? currentOwnershipLayerInfo?.copyWith(newDid: didMagicConditions.single.targetDidOwner) + ? currentOwnershipLayerInfo?.copyWith( + newDid: didMagicConditions.single.targetDidOwner, + ) : currentOwnershipLayerInfo; if (ownershipLayerInfo != null) { @@ -140,7 +145,8 @@ abstract class NftRecord { CoinPrototype singletonCoin, { int? latestHeight, }) async { - final uncurriedNft = await UncurriedNftPuzzle.fromProgram(parentSpend.puzzleReveal); + final uncurriedNft = + await UncurriedNftPuzzle.fromProgram(parentSpend.puzzleReveal); if (uncurriedNft == null) { return null; } @@ -161,7 +167,8 @@ abstract class NftRecord { CoinPrototype singletonCoin, { int? latestHeight, }) { - final uncurriedNft = UncurriedNftPuzzle.fromProgramSync(parentSpend.puzzleReveal); + final uncurriedNft = + UncurriedNftPuzzle.fromProgramSync(parentSpend.puzzleReveal); if (uncurriedNft == null) { return null; } @@ -204,7 +211,9 @@ abstract class NftRecord { Program innermostSolution, ); - static Future> nftRecordsFromSpendBundle(SpendBundle spendBundle) async { + static Future> nftRecordsFromSpendBundle( + SpendBundle spendBundle, + ) async { final nftRecords = []; for (final coinWithParentSpend in spendBundle.netAdditonWithParentSpends) { if (coinWithParentSpend.parentSpend != null) { @@ -233,7 +242,9 @@ extension SharedFunctionality on NftRecord { innerPuzzle: innerPuzzle, ); if (coin.puzzlehash != fullPuzzle.hash()) { - throw Exception('NFT coin puzzle hash does not match constructed full puzzle'); + throw Exception( + 'NFT coin puzzle hash does not match constructed full puzzle', + ); } return Nft( delegate: this, @@ -247,7 +258,9 @@ extension SharedFunctionality on NftRecord { Set whitelistedAuthorities = const {}, }) async { final recordMetadataUrls = metadata.metaUris; - if (recordMetadataUrls == null || recordMetadataUrls.isEmpty || metadata.dataUris.isEmpty) { + if (recordMetadataUrls == null || + recordMetadataUrls.isEmpty || + metadata.dataUris.isEmpty) { return null; } @@ -269,7 +282,8 @@ extension SharedFunctionality on NftRecord { try { final data = await nftStorageApi.getNftData(metadataUrl); final collectionId = data.collection.id; - if (collectionOverrides != null && collectionOverrides.containsKey(collectionId)) { + if (collectionOverrides != null && + collectionOverrides.containsKey(collectionId)) { return HydratedNftRecord( delegate: this, data: data.withCollectionOverride(collectionOverrides[collectionId]!), @@ -283,8 +297,9 @@ extension SharedFunctionality on NftRecord { mintInfo: null, ); } on PickException catch (e, st) { - LoggingContext() - .error('error fetching nft($launcherId}) data: $e, $st. meta uris: $recordMetadataUrls'); + LoggingContext().error( + 'error fetching nft($launcherId}) data: $e, $st. meta uris: $recordMetadataUrls', + ); return null; } on FormatException catch (e, st) { LoggingContext().error('error fetching nft($launcherId}) data: $e, $st'); @@ -303,7 +318,8 @@ extension SharedFunctionality on NftRecord { if (mintInfo == null) { return null; } - if (whitelistedDIDs.isNotEmpty && !whitelistedDIDs.contains(mintInfo.minterDid)) { + if (whitelistedDIDs.isNotEmpty && + !whitelistedDIDs.contains(mintInfo.minterDid)) { return null; } @@ -323,7 +339,9 @@ extension SharedFunctionality on NftRecord { return hydrated.withMintInfo(mintInfo); } - Future fetchMintInfo(ChiaFullNodeInterface fullNode) async { + Future fetchMintInfo( + ChiaFullNodeInterface fullNode, + ) async { final mintInfo = await fullNode.getNftMintInfoForLauncherId(launcherId); if (mintInfo == null) { return null; @@ -343,7 +361,8 @@ extension WhiteListValidation on Iterable { bool validate(Set whitelistedAuthorities) { for (final uriToValidate in this) { if (!whitelistedAuthorities.any( - (whiteListedAuthority) => uriToValidate.authority.endsWith(whiteListedAuthority), + (whiteListedAuthority) => + uriToValidate.authority.endsWith(whiteListedAuthority), )) { return false; } diff --git a/lib/src/nft/models/proof_of_nft.dart b/lib/src/nft/models/proof_of_nft.dart index 99d27813..a0ee1dff 100644 --- a/lib/src/nft/models/proof_of_nft.dart +++ b/lib/src/nft/models/proof_of_nft.dart @@ -5,11 +5,13 @@ import 'package:chia_crypto_utils/chia_crypto_utils.dart'; class ProofOfNft { factory ProofOfNft.fromNft(NftRecord nft, WalletKeychain keychain) { final walletVector = keychain.getWalletVectorOrThrow(nft.p2Puzzlehash); - final syntheticPrivateKey = calculateSyntheticPrivateKey(walletVector.childPrivateKey); + final syntheticPrivateKey = + calculateSyntheticPrivateKey(walletVector.childPrivateKey); final syntheticPublicKey = syntheticPrivateKey.getG1(); final timestamp = DateTime.now(); final timestampBytes = encodeInt(timestamp.millisecondsSinceEpoch); - final signature = AugSchemeMPL.sign(syntheticPrivateKey, nft.launcherId + timestampBytes); + final signature = + AugSchemeMPL.sign(syntheticPrivateKey, nft.launcherId + timestampBytes); return ProofOfNft._( launcherId: nft.launcherId, @@ -87,7 +89,8 @@ class ProofOfNft { return nullResult; } - final p2PuzzleReveal = getP2PuzzleFromSyntheticPublicKey(syntheticPublicKey); + final p2PuzzleReveal = + getP2PuzzleFromSyntheticPublicKey(syntheticPublicKey); if (p2PuzzleReveal.hash() != nft.p2Puzzlehash) { return NftVerificationResult( nft: nft, diff --git a/lib/src/nft/models/uncurried_nft_puzzle.dart b/lib/src/nft/models/uncurried_nft_puzzle.dart index 17fc56f3..e40687a6 100644 --- a/lib/src/nft/models/uncurried_nft_puzzle.dart +++ b/lib/src/nft/models/uncurried_nft_puzzle.dart @@ -50,7 +50,8 @@ class UncurriedNftPuzzle { final currentDid = innerPuzzleArguments[1].maybeAtom; final transferProgram = innerPuzzleArguments[2]; - final uncurriedTransferProgramArguments = (await transferProgram.uncurryAsync()).arguments; + final uncurriedTransferProgramArguments = + (await transferProgram.uncurryAsync()).arguments; final royaltyAddress = uncurriedTransferProgramArguments[1].maybeAtom; final royaltyPercentage = uncurriedTransferProgramArguments[2].toInt(); @@ -96,7 +97,9 @@ class UncurriedNftPuzzle { return fromUnCurriedProgram(programAndArguments); } - static UncurriedNftPuzzle? fromUnCurriedProgram(ModAndArguments programAndArguments) { + static UncurriedNftPuzzle? fromUnCurriedProgram( + ModAndArguments programAndArguments, + ) { if (programAndArguments.mod != singletonTopLayerV1Program) { return null; } @@ -128,15 +131,17 @@ class UncurriedNftPuzzle { final currentDidAtom = innerPuzzleArguments[1].maybeAtom; final transferProgram = innerPuzzleArguments[2]; - final uncurriedTransferProgramArguments = transferProgram.uncurry().arguments; + final uncurriedTransferProgramArguments = + transferProgram.uncurry().arguments; final royaltyAddress = uncurriedTransferProgramArguments[1].maybeAtom; final royaltyPercentage = uncurriedTransferProgramArguments[2].toInt(); final p2Puzzle = innerPuzzleArguments[3]; - // ignore: use_if_null_to_convert_nulls_to_bools - final currentDid = currentDidAtom?.isNotEmpty == true ? currentDidAtom : null; + final currentDid = + // ignore: use_if_null_to_convert_nulls_to_bools + currentDidAtom?.isNotEmpty == true ? currentDidAtom : null; final ownershipLayerInfo = NftOwnershipLayerInfo( transferProgram: transferProgram, @@ -184,7 +189,8 @@ class UncurriedNftPuzzle { bool get doesSupportDid => ownershipLayerInfo != null; - Program get p2Puzzle => ownershipLayerInfo?.ownershipLayerP2Puzzle ?? innerPuzzle; + Program get p2Puzzle => + ownershipLayerInfo?.ownershipLayerP2Puzzle ?? innerPuzzle; Program getFullPuzzleWithNewInnerPuzzle(Program newInnerPuzzle) { return NftWalletService.createFullPuzzle( @@ -203,8 +209,9 @@ class UncurriedNftPuzzle { Program getInnerSolution(Program spendSolution) { final stateLayerInnerSolution = spendSolution.rest().rest().first().first(); - final innermostSolution = - doesSupportDid ? stateLayerInnerSolution.first() : stateLayerInnerSolution; + final innermostSolution = doesSupportDid + ? stateLayerInnerSolution.first() + : stateLayerInnerSolution; return innermostSolution; } } diff --git a/lib/src/nft/service/nft_wallet_service.dart b/lib/src/nft/service/nft_wallet_service.dart index 99a26c52..760bc3cc 100644 --- a/lib/src/nft/service/nft_wallet_service.dart +++ b/lib/src/nft/service/nft_wallet_service.dart @@ -9,7 +9,8 @@ class NftWalletService { final DIDWalletService didWalletService = DIDWalletService(); static List getPaymentsForCoinSpend(CoinSpend coinSpend) { - final unCurriedNft = UncurriedNftPuzzle.fromProgramSync(coinSpend.puzzleReveal); + final unCurriedNft = + UncurriedNftPuzzle.fromProgramSync(coinSpend.puzzleReveal); return BaseWalletService.extractPaymentsFromSolution( unCurriedNft!.getInnerSolution(coinSpend.solution), ); @@ -35,7 +36,8 @@ class NftWalletService { innerPuzzle: innerPuzzle, ); - final fullPuzzle = singletonTopLayerV1Program.curry([singletonStructure, singletonInnerPuzzle]); + final fullPuzzle = singletonTopLayerV1Program + .curry([singletonStructure, singletonInnerPuzzle]); return fullPuzzle; } @@ -109,7 +111,8 @@ class NftWalletService { DidInfo? targetDidInfo, PrivateKey? didPrivateKey, }) { - if ((royaltyPercentagePoints != 0 || royaltyPuzzleHash != null) && targetDidInfo == null) { + if ((royaltyPercentagePoints != 0 || royaltyPuzzleHash != null) && + targetDidInfo == null) { throw Exception('Royalty info is provided without initial DID'); } final did = targetDidInfo?.did; @@ -122,7 +125,8 @@ class NftWalletService { final launcherCoin = makeLauncherCoin(originCoin.id); final launcherCoinId = launcherCoin.id; - final minterPublicKey = keychain.getWalletVector(minterPuzzlehash)?.childPublicKey; + final minterPublicKey = + keychain.getWalletVector(minterPuzzlehash)?.childPublicKey; if (minterPublicKey == null) { throw Exception('Minter puzzle hash is not in keychain'); } @@ -165,7 +169,11 @@ class NftWalletService { ); final genesisLauncherSolution = Program.list( - [Program.fromAtom(eveCoin.puzzlehash), Program.fromInt(nftAmount), Program.list([])], + [ + Program.fromAtom(eveCoin.puzzlehash), + Program.fromInt(nftAmount), + Program.list([]) + ], ); final announcements = [ @@ -187,7 +195,9 @@ class NftWalletService { if (targetDidInfo != null) { final privateKeyToUse = didPrivateKey ?? - keychain.getWalletVectorOrThrow(targetDidInfo.p2Puzzle.hash()).childPrivateKey; + keychain + .getWalletVectorOrThrow(targetDidInfo.p2Puzzle.hash()) + .childPrivateKey; final didApprovalInfo = getDidApprovalInfo( didInfo: targetDidInfo, launcherIds: [launcherCoinId], @@ -230,7 +240,9 @@ class NftWalletService { hasUneditioned = true; } if (hasUneditioned && hasEditioned) { - throw InvalidNftDataException('Either all or none of the NFTs must have edition numbers'); + throw InvalidNftDataException( + 'Either all or none of the NFTs must have edition numbers', + ); } } @@ -269,13 +281,18 @@ class NftWalletService { ); final didPrivateKeyToUse = didPrivatKey ?? - keychain.getWalletVectorOrThrow(targetDidInfo.p2Puzzle.hash()).childPrivateKey; + keychain + .getWalletVectorOrThrow(targetDidInfo.p2Puzzle.hash()) + .childPrivateKey; return bundles.totalBundle + - bundles.unsignedDidSpendBundle.signWithPrivateKey(didPrivateKeyToUse).signedBundle; + bundles.unsignedDidSpendBundle + .signWithPrivateKey(didPrivateKeyToUse) + .signedBundle; } /// throws [InvalidNftDataException] - UnsignedDidSpendBundleWithTotalBundle createUnsignedDidNftBulkMintSpendBundle({ + UnsignedDidSpendBundleWithTotalBundle + createUnsignedDidNftBulkMintSpendBundle({ required Puzzlehash targetPuzzlehash, Puzzlehash? minterPuzzlehash, Puzzlehash? changePuzzlehash, @@ -291,8 +308,9 @@ class NftWalletService { _validateNftDatas(nftMintData); final additionalDidPayments = []; - final minterPublicKey = - keychain.getWalletVector(minterPuzzlehash ?? keychain.puzzlehashes.random)?.childPublicKey; + final minterPublicKey = keychain + .getWalletVector(minterPuzzlehash ?? keychain.puzzlehashes.random) + ?.childPublicKey; if (minterPublicKey == null) { throw Exception('Minter puzzle hash is not in keychain'); } @@ -340,7 +358,8 @@ class NftWalletService { intermediateCoinSpends.add(intermediateCoinSpend); final intermediateAnnouncementMessage = - (encodeInt(uniqueMintNumber) + encodeInt(totalNftsToMint)).sha256Hash(); + (encodeInt(uniqueMintNumber) + encodeInt(totalNftsToMint)) + .sha256Hash(); didAnnouncements.add( AssertCoinAnnouncementCondition( @@ -392,11 +411,19 @@ class NftWalletService { ); final genesisLauncherSolution = Program.list( - [Program.fromAtom(eveCoin.puzzlehash), Program.fromInt(nftAmount), Program.list([])], + [ + Program.fromAtom(eveCoin.puzzlehash), + Program.fromInt(nftAmount), + Program.list([]) + ], ); - didAnnouncements - .add(AssertCoinAnnouncementCondition(launcherId, genesisLauncherSolution.hash())); + didAnnouncements.add( + AssertCoinAnnouncementCondition( + launcherId, + genesisLauncherSolution.hash(), + ), + ); final launcherCoinSpend = CoinSpend( coin: launcherCoin, @@ -415,13 +442,15 @@ class NftWalletService { ); final conditionPrograms = nftSpendBundle.outputConditions; - final createPuzzleAnnouncements = BaseWalletService.extractConditionsFromProgramList( + final createPuzzleAnnouncements = + BaseWalletService.extractConditionsFromProgramList( conditionPrograms, CreatePuzzleAnnouncementCondition.isThisCondition, CreatePuzzleAnnouncementCondition.fromProgram, ); final evePuzzleAnnouncement = createPuzzleAnnouncements.first; - final announcementHash = (fullPuzzle.hash() + evePuzzleAnnouncement.message).sha256Hash(); + final announcementHash = + (fullPuzzle.hash() + evePuzzleAnnouncement.message).sha256Hash(); puzzleAssertions.add(AssertPuzzleAnnouncementCondition(announcementHash)); eveSpendBundles.add(nftSpendBundle); } @@ -444,15 +473,19 @@ class NftWalletService { didInfo: targetDidInfo, puzzlesToAnnounce: launcherIds, additionalPayments: additionalDidPayments, - createCoinAnnouncements: [CreateCoinAnnouncementCondition(standardMessage)], + createCoinAnnouncements: [ + CreateCoinAnnouncementCondition(standardMessage) + ], assertCoinAnnouncements: didAnnouncements, assertPuzzleAnnouncements: puzzleAssertions, ); - final unsignedBundle = SpendBundle(coinSpends: intermediateCoinSpends + launcherCoinSpends); + final unsignedBundle = + SpendBundle(coinSpends: intermediateCoinSpends + launcherCoinSpends); - final totalSpendBundle = - standardSpendBundle + unsignedBundle + SpendBundle.aggregate(eveSpendBundles); + final totalSpendBundle = standardSpendBundle + + unsignedBundle + + SpendBundle.aggregate(eveSpendBundles); return UnsignedDidSpendBundleWithTotalBundle( unsignedDidSpendBundle: unsignedDidBundle, @@ -485,7 +518,8 @@ class NftWalletService { DidInfo? targetDidInfo, List? tradePricesList, List coinAnnouncementsToAssert = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], }) async { final result = await compute( _makeNftSpendBundleTask, @@ -502,7 +536,8 @@ class NftWalletService { coinAnnouncementsToAssert: coinAnnouncementsToAssert, puzzleAnnouncementsToAssert: puzzleAnnouncementsToAssert, nftWalletService: this, - network: stringToNetwork(ChiaNetworkContextWrapper().blockchainNetwork.name), + network: + stringToNetwork(ChiaNetworkContextWrapper().blockchainNetwork.name), ), ); return SpendBundle.fromJson(result); @@ -519,13 +554,15 @@ class NftWalletService { DidInfo? targetDidInfo, List? tradePricesList, List coinAnnouncementsToAssert = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], List additionalConditions = const [], }) { final createCoinAnnouncements = []; SpendBundle? feeSpendBundle; if (fee > 0) { - createCoinAnnouncements.add(CreateCoinAnnouncementCondition(nftCoin.coin.id)); + createCoinAnnouncements + .add(CreateCoinAnnouncementCondition(nftCoin.coin.id)); feeSpendBundle = standardWalletService.createFeeSpendBundle( fee: fee, standardCoins: coinsForFee, @@ -560,7 +597,10 @@ class NftWalletService { Program.list([]), Program.cons( Program.fromInt(1), - Program.cons(magicCondition.toProgram(), standardInnerSolution.rest().first().rest()), + Program.cons( + magicCondition.toProgram(), + standardInnerSolution.rest().first().rest(), + ), ), Program.list([]), ]), @@ -666,7 +706,9 @@ class CreateNftSpendBundleArgument { final Network network; } -Map _makeNftSpendBundleTask(CreateNftSpendBundleArgument argument) { +Map _makeNftSpendBundleTask( + CreateNftSpendBundleArgument argument, +) { ChiaNetworkContextWrapper().registerNetworkContext( argument.network, ); diff --git a/lib/src/nft/utils/nft_data_csv_parser/nft_data_csv_parser.dart b/lib/src/nft/utils/nft_data_csv_parser/nft_data_csv_parser.dart index 0d1a89ef..4d2572dc 100644 --- a/lib/src/nft/utils/nft_data_csv_parser/nft_data_csv_parser.dart +++ b/lib/src/nft/utils/nft_data_csv_parser/nft_data_csv_parser.dart @@ -46,8 +46,10 @@ class NftDataCsvParser { description: pick(fieldRows[1][1]).asStringOrThrow(), twitter: pick(fieldRows[2][1]).asStringOrThrow(), website: pick(fieldRows[3][1]).asStringOrThrow(), - icon: UploadableValue(pick(fieldRows[4][1]).asStringOrThrow())..assertImage(), - banner: UploadableValue(pick(fieldRows[5][1]).asStringOrThrow())..assertImage(), + icon: UploadableValue(pick(fieldRows[4][1]).asStringOrThrow()) + ..assertImage(), + banner: UploadableValue(pick(fieldRows[5][1]).asStringOrThrow()) + ..assertImage(), editionTotal: pick(fieldRows[6][1]).asIntOrNull(), seriesTotal: pick(fieldRows[7][1]).asIntOrNull(), seriesNumber: pick(fieldRows[8][1]).asIntOrNull(), @@ -87,7 +89,8 @@ class NftDataCsvParser { .sublist(7) .map( (e) => UploadableAttribute( - type: pick(columnNumberToAttributeType[e.key]).asStringOrThrow(), + type: + pick(columnNumberToAttributeType[e.key]).asStringOrThrow(), value: UploadableValue(e.value.toString()), ), ) @@ -99,8 +102,8 @@ class NftDataCsvParser { NftThemeCsvData parseThemeDataFromFile(File file) { final rows = converter.convert(file.readAsStringSync()); - final sizeTableRowIndex = - rows.indexWhere((row) => pick(row[0]).asStringOrThrow().contains('size')); + final sizeTableRowIndex = rows + .indexWhere((row) => pick(row[0]).asStringOrThrow().contains('size')); final fieldRows = rows.sublist(0, sizeTableRowIndex); @@ -113,7 +116,9 @@ class NftDataCsvParser { return ThemeImageData( size: size, image: (image != null) ? (UploadableValue(image)..assertImage()) : null, - background: background != null ? (UploadableValue(background)..assertImage()) : null, + background: background != null + ? (UploadableValue(background)..assertImage()) + : null, ); }).toList(); @@ -129,7 +134,8 @@ class NftDataCsvParser { brightness: pick(fieldMap, 'brightness').asStringOrThrow(), buttonColor: pick(fieldMap, 'button_color').asStringOrThrow(), buttonOpacity: pick(fieldMap, 'button_opacity').asDoubleOrThrow(), - nftTextOutlineColor: pick(fieldMap, 'nft_text_outline_color').asStringOrNull(), + nftTextOutlineColor: + pick(fieldMap, 'nft_text_outline_color').asStringOrNull(), nftTextColor: pick(fieldMap, 'nft_text_color').asStringOrNull(), imageData: imageData, ); diff --git a/lib/src/nft/utils/nft_data_csv_parser/uploadable_value.dart b/lib/src/nft/utils/nft_data_csv_parser/uploadable_value.dart index 5af1e686..69bbb6a3 100644 --- a/lib/src/nft/utils/nft_data_csv_parser/uploadable_value.dart +++ b/lib/src/nft/utils/nft_data_csv_parser/uploadable_value.dart @@ -40,7 +40,9 @@ class UploadableValue extends Equatable { void assertImage() { if (_type != StringType.uri && _type != StringType.fileName) { - throw ArgumentError('Expected image but got ${_type.name} for value $_value'); + throw ArgumentError( + 'Expected image but got ${_type.name} for value $_value', + ); } } diff --git a/lib/src/notification/models/notification_coin.dart b/lib/src/notification/models/notification_coin.dart index 293e0fe1..dff00935 100644 --- a/lib/src/notification/models/notification_coin.dart +++ b/lib/src/notification/models/notification_coin.dart @@ -21,7 +21,11 @@ class NotificationCoin with CoinPrototypeDecoratorMixin implements Coin { final targetPuzzlehash = Puzzlehash(memos.first); final message = memos.sublist(1); - return NotificationCoin(delegate: coin, targetPuzzlehash: targetPuzzlehash, message: message); + return NotificationCoin( + delegate: coin, + targetPuzzlehash: targetPuzzlehash, + message: message, + ); } static Future fromParentSpend({ diff --git a/lib/src/notification/service/notification_service.dart b/lib/src/notification/service/notification_service.dart index 77b187e4..6cec8e62 100644 --- a/lib/src/notification/service/notification_service.dart +++ b/lib/src/notification/service/notification_service.dart @@ -15,10 +15,11 @@ class NotificationWalletService { int fee = 0, Bytes? originId, List coinAnnouncementsToAssert = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], }) { - final notificationPuzzle = - notificationProgram.curry([Program.fromAtom(targetPuzzlehash), Program.fromInt(amount)]); + final notificationPuzzle = notificationProgram + .curry([Program.fromAtom(targetPuzzlehash), Program.fromInt(amount)]); final notificationPuzzlehash = notificationPuzzle.hash(); final originCoin = originId != null @@ -37,9 +38,11 @@ class NotificationWalletService { solution: Program.nil, ); - final notificationSpendBundle = SpendBundle(coinSpends: [notificationCoinSpend]); + final notificationSpendBundle = + SpendBundle(coinSpends: [notificationCoinSpend]); - final messageCoinAnnouncement = AssertCoinAnnouncementCondition(notificationCoin.id, Bytes([])); + final messageCoinAnnouncement = + AssertCoinAnnouncementCondition(notificationCoin.id, Bytes([])); final standardSpendBundle = standardWalletService.createSpendBundle( payments: [ @@ -57,7 +60,10 @@ class NotificationWalletService { changePuzzlehash: changePuzzlehash, fee: fee, originId: originId, - coinAnnouncementsToAssert: [messageCoinAnnouncement, ...coinAnnouncementsToAssert], + coinAnnouncementsToAssert: [ + messageCoinAnnouncement, + ...coinAnnouncementsToAssert + ], puzzleAnnouncementsToAssert: puzzleAnnouncementsToAssert, ); diff --git a/lib/src/offer/mixins/generalized_map_mixin.dart b/lib/src/offer/mixins/generalized_map_mixin.dart index c18153ea..a9e01b41 100644 --- a/lib/src/offer/mixins/generalized_map_mixin.dart +++ b/lib/src/offer/mixins/generalized_map_mixin.dart @@ -12,9 +12,11 @@ mixin MixedTypeMixin { /// prototype pattern V clone(Map> map); Map get cat => - map[GeneralCoinType.cat]?.map((key, value) => MapEntry(key!, value)) ?? {}; + map[GeneralCoinType.cat]?.map((key, value) => MapEntry(key!, value)) ?? + {}; Map get nft => - map[GeneralCoinType.nft]?.map((key, value) => MapEntry(key!, value)) ?? {}; + map[GeneralCoinType.nft]?.map((key, value) => MapEntry(key!, value)) ?? + {}; Map toGeneralizedMap() { final generalizedMap = {}; diff --git a/lib/src/offer/models/drivers/cat_puzzle_driver.dart b/lib/src/offer/models/drivers/cat_puzzle_driver.dart index a6472df3..701b2bae 100644 --- a/lib/src/offer/models/drivers/cat_puzzle_driver.dart +++ b/lib/src/offer/models/drivers/cat_puzzle_driver.dart @@ -45,10 +45,14 @@ class CatPuzzleDriver implements PuzzleDriver { } @override - SpendType get type => catProgram == cat2Program ? SpendType.cat : SpendType.cat1; + SpendType get type => + catProgram == cat2Program ? SpendType.cat : SpendType.cat1; @override - OfferedCoin makeOfferedCoinFromParentSpend(CoinPrototype coin, CoinSpend parentSpend) { + OfferedCoin makeOfferedCoinFromParentSpend( + CoinPrototype coin, + CoinSpend parentSpend, + ) { if (type == SpendType.cat) { return OfferedCat2.fromOfferBundleParentSpend(coin, parentSpend); } @@ -73,7 +77,10 @@ class CatPuzzleDriver implements PuzzleDriver { } @override - CoinPrototype getChildCoinForP2Payment(CoinSpend coinSpend, Payment p2Payment) { + CoinPrototype getChildCoinForP2Payment( + CoinSpend coinSpend, + Payment p2Payment, + ) { final outerPuzzlehash = WalletKeychain.makeOuterPuzzleHashForCatProgram( p2Payment.puzzlehash, getAssetId(coinSpend.puzzleReveal), diff --git a/lib/src/offer/models/drivers/did_puzzle_driver.dart b/lib/src/offer/models/drivers/did_puzzle_driver.dart index 544b4f9b..cfae5e9b 100644 --- a/lib/src/offer/models/drivers/did_puzzle_driver.dart +++ b/lib/src/offer/models/drivers/did_puzzle_driver.dart @@ -15,18 +15,25 @@ class DidPuzzleDriver implements PuzzleDriver { @override Puzzlehash? getAssetId(Program fullPuzzle) { - return Puzzlehash.maybe(UncurriedDidPuzzle.maybeFromProgram(fullPuzzle)?.did); + return Puzzlehash.maybe( + UncurriedDidPuzzle.maybeFromProgram(fullPuzzle)?.did, + ); } @override - Program getNewFullPuzzleForP2Puzzle(Program currentFullPuzzle, Program p2Puzzle) { + Program getNewFullPuzzleForP2Puzzle( + Program currentFullPuzzle, + Program p2Puzzle, + ) { // TODO(nvjoshi): implement getNewFullPuzzleForP2Puzzle throw UnimplementedError(); } @override Program getP2Puzzle(CoinSpend coinSpend) { - return UncurriedDidPuzzle.fromProgram(coinSpend.puzzleReveal).innerPuzzle.p2Puzzle; + return UncurriedDidPuzzle.fromProgram(coinSpend.puzzleReveal) + .innerPuzzle + .p2Puzzle; } @override @@ -36,13 +43,19 @@ class DidPuzzleDriver implements PuzzleDriver { } @override - OfferedCoin makeOfferedCoinFromParentSpend(CoinPrototype coin, CoinSpend parentSpend) { + OfferedCoin makeOfferedCoinFromParentSpend( + CoinPrototype coin, + CoinSpend parentSpend, + ) { // TODO(nvjoshi): implement makeOfferedCoinFromParentSpend throw UnimplementedError(); } @override - CoinPrototype getChildCoinForP2Payment(CoinSpend coinSpend, Payment p2Payment) { + CoinPrototype getChildCoinForP2Payment( + CoinSpend coinSpend, + Payment p2Payment, + ) { return getSingletonChildFromCoinSpend(coinSpend); } diff --git a/lib/src/offer/models/drivers/nft_puzzle_driver.dart b/lib/src/offer/models/drivers/nft_puzzle_driver.dart index 3d8b3fb7..62e7411a 100644 --- a/lib/src/offer/models/drivers/nft_puzzle_driver.dart +++ b/lib/src/offer/models/drivers/nft_puzzle_driver.dart @@ -46,20 +46,25 @@ class NftPuzzleDriver implements PuzzleDriver { SpendType get type => SpendType.nft; @override - OfferedCoin makeOfferedCoinFromParentSpend(CoinPrototype coin, CoinSpend parentSpend) { + OfferedCoin makeOfferedCoinFromParentSpend( + CoinPrototype coin, + CoinSpend parentSpend, + ) { return OfferedNft.fromOfferBundleParentSpend(coin, parentSpend); } @override Program getP2Solution(CoinSpend coinSpend) { - final stateLayerInnerSolution = coinSpend.solution.rest().rest().first().first(); + final stateLayerInnerSolution = + coinSpend.solution.rest().rest().first().first(); return stateLayerInnerSolution; } @override Program getP2Puzzle(CoinSpend coinSpend) { - final uncurriedNft = UncurriedNftPuzzle.fromProgramSync(coinSpend.puzzleReveal); + final uncurriedNft = + UncurriedNftPuzzle.fromProgramSync(coinSpend.puzzleReveal); return uncurriedNft!.p2Puzzle; } @@ -70,7 +75,10 @@ class NftPuzzleDriver implements PuzzleDriver { } @override - CoinPrototype getChildCoinForP2Payment(CoinSpend coinSpend, Payment p2Payment) { + CoinPrototype getChildCoinForP2Payment( + CoinSpend coinSpend, + Payment p2Payment, + ) { return getSingletonChildFromCoinSpend(coinSpend); } } @@ -123,20 +131,25 @@ class DidNftPuzzleDriver implements PuzzleDriver { SpendType get type => SpendType.nft; @override - OfferedCoin makeOfferedCoinFromParentSpend(CoinPrototype coin, CoinSpend parentSpend) { + OfferedCoin makeOfferedCoinFromParentSpend( + CoinPrototype coin, + CoinSpend parentSpend, + ) { return OfferedNft.fromOfferBundleParentSpend(coin, parentSpend); } @override Program getP2Solution(CoinSpend coinSpend) { - final stateLayerInnerSolution = coinSpend.solution.rest().rest().first().first(); + final stateLayerInnerSolution = + coinSpend.solution.rest().rest().first().first(); return stateLayerInnerSolution.first(); } @override Program getP2Puzzle(CoinSpend coinSpend) { - final uncurriedNft = UncurriedNftPuzzle.fromProgramSync(coinSpend.puzzleReveal); + final uncurriedNft = + UncurriedNftPuzzle.fromProgramSync(coinSpend.puzzleReveal); return uncurriedNft!.p2Puzzle; } @@ -147,7 +160,10 @@ class DidNftPuzzleDriver implements PuzzleDriver { } @override - CoinPrototype getChildCoinForP2Payment(CoinSpend coinSpend, Payment p2Payment) { + CoinPrototype getChildCoinForP2Payment( + CoinSpend coinSpend, + Payment p2Payment, + ) { return getSingletonChildFromCoinSpend(coinSpend); } } diff --git a/lib/src/offer/models/drivers/puzzle_driver.dart b/lib/src/offer/models/drivers/puzzle_driver.dart index 9da2fce7..ec1bee51 100644 --- a/lib/src/offer/models/drivers/puzzle_driver.dart +++ b/lib/src/offer/models/drivers/puzzle_driver.dart @@ -6,7 +6,8 @@ import 'package:deep_pick/deep_pick.dart'; abstract class PuzzleDriver { static PuzzleDriver? match(Program fullPuzzle) { final uncurried = fullPuzzle.uncurry(); - final matchingDrivers = drivers.where((e) => e.doesMatchUncurried(uncurried, fullPuzzle)); + final matchingDrivers = + drivers.where((e) => e.doesMatchUncurried(uncurried, fullPuzzle)); if (matchingDrivers.isEmpty) { return null; } @@ -18,8 +19,8 @@ abstract class PuzzleDriver { List? driversToCheck, }) async { final unCurried = await fullPuzzle.uncurryAsync(); - final matchingDrivers = - (driversToCheck ?? drivers).where((e) => e.doesMatchUncurried(unCurried, fullPuzzle)); + final matchingDrivers = (driversToCheck ?? drivers) + .where((e) => e.doesMatchUncurried(unCurried, fullPuzzle)); if (matchingDrivers.isEmpty) { return null; } @@ -27,7 +28,10 @@ abstract class PuzzleDriver { } bool doesMatch(Program fullPuzzle); - bool doesMatchUncurried(ModAndArguments uncurriedFullPuzzle, Program fullPuzzle); + bool doesMatchUncurried( + ModAndArguments uncurriedFullPuzzle, + Program fullPuzzle, + ); Program getNewFullPuzzleForP2Puzzle( Program currentFullPuzzle, @@ -35,7 +39,10 @@ abstract class PuzzleDriver { ); Puzzlehash? getAssetId(Program fullPuzzle); - OfferedCoin makeOfferedCoinFromParentSpend(CoinPrototype coin, CoinSpend parentSpend); + OfferedCoin makeOfferedCoinFromParentSpend( + CoinPrototype coin, + CoinSpend parentSpend, + ); SpendType get type; @@ -64,7 +71,8 @@ extension PuzzlePayments on PuzzleDriver { final innerSolution = getP2Solution(coinSpend); final innerPuzzle = getP2Puzzle(coinSpend); - final createCoinConditions = BaseWalletService.extractConditionsFromProgramList( + final createCoinConditions = + BaseWalletService.extractConditionsFromProgramList( innerPuzzle.run(innerSolution).program.toList(), CreateCoinCondition.isThisCondition, CreateCoinCondition.fromProgram, @@ -78,8 +86,9 @@ extension PuzzlePayments on PuzzleDriver { taskArgument: PuzzleDriverAndCoinSpend(coinSpend, this), isolateTask: _getP2PaymentsTask, handleTaskCompletion: (taskResultJson) { - return pick(taskResultJson, 'payments') - .letStringListOrThrow((string) => Payment.fromProgram(Program.deserializeHex(string))); + return pick(taskResultJson, 'payments').letStringListOrThrow( + (string) => Payment.fromProgram(Program.deserializeHex(string)), + ); }, ); return result; @@ -90,7 +99,9 @@ extension PuzzlePayments on PuzzleDriver { taskArgument: PuzzleDriverAndCoinSpend(coinSpend, this), isolateTask: _getP2PuzzleHashTask, handleTaskCompletion: (taskResultJson) { - return Puzzlehash.fromHex(pick(taskResultJson, 'p2_puzzle_hash').asStringOrThrow()); + return Puzzlehash.fromHex( + pick(taskResultJson, 'p2_puzzle_hash').asStringOrThrow(), + ); }, ); return result; @@ -101,7 +112,9 @@ extension PuzzlePayments on PuzzleDriver { taskArgument: PuzzleDriverAndCoinSpend(coinSpend, this), isolateTask: _getP2PuzzleTask, handleTaskCompletion: (taskResultJson) { - return Program.deserializeHex(pick(taskResultJson, 'p2_puzzle').asStringOrThrow()); + return Program.deserializeHex( + pick(taskResultJson, 'p2_puzzle').asStringOrThrow(), + ); }, ); return result; @@ -135,20 +148,29 @@ extension PuzzlePayments on PuzzleDriver { } Map _getP2PuzzleTask(PuzzleDriverAndCoinSpend arguments) { - return {'p2_puzzle': arguments.puzzleDriver.getP2Puzzle(arguments.coinSpend).toHex()}; + return { + 'p2_puzzle': arguments.puzzleDriver.getP2Puzzle(arguments.coinSpend).toHex() + }; } Map _getP2PuzzleHashTask(PuzzleDriverAndCoinSpend arguments) { - return {'p2_puzzle_hash': arguments.puzzleDriver.getP2Puzzle(arguments.coinSpend).hash().toHex()}; + return { + 'p2_puzzle_hash': + arguments.puzzleDriver.getP2Puzzle(arguments.coinSpend).hash().toHex() + }; } -Map _getChildCoinForP2PaymentTask(PuzzleDriverCoinSpendAndPayment arguments) { +Map _getChildCoinForP2PaymentTask( + PuzzleDriverCoinSpendAndPayment arguments, +) { return arguments.puzzleDriver .getChildCoinForP2Payment(arguments.coinSpend, arguments.payment) .toJson(); } -Map _getChildCoinIdForP2PaymentTask(PuzzleDriverCoinSpendAndPayment arguments) { +Map _getChildCoinIdForP2PaymentTask( + PuzzleDriverCoinSpendAndPayment arguments, +) { return { 'coin_id': arguments.puzzleDriver .getChildCoinForP2Payment(arguments.coinSpend, arguments.payment) @@ -174,7 +196,11 @@ class PuzzleDriverAndCoinSpend { } class PuzzleDriverCoinSpendAndPayment extends PuzzleDriverAndCoinSpend { - PuzzleDriverCoinSpendAndPayment(super.coinSpend, super.puzzleDriver, this.payment); + PuzzleDriverCoinSpendAndPayment( + super.coinSpend, + super.puzzleDriver, + this.payment, + ); final Payment payment; } diff --git a/lib/src/offer/models/drivers/puzzle_info.dart b/lib/src/offer/models/drivers/puzzle_info.dart index ba0a5abd..2c4da6ca 100644 --- a/lib/src/offer/models/drivers/puzzle_info.dart +++ b/lib/src/offer/models/drivers/puzzle_info.dart @@ -24,7 +24,10 @@ class PuzzleInfo { SpendType get type => driver.type; - OfferedCoin? makeOfferedCoinFromParentSpend(CoinPrototype coin, CoinSpend parentSpend) { + OfferedCoin? makeOfferedCoinFromParentSpend( + CoinPrototype coin, + CoinSpend parentSpend, + ) { try { return driver.makeOfferedCoinFromParentSpend( coin, diff --git a/lib/src/offer/models/drivers/standard_puzzle_driver.dart b/lib/src/offer/models/drivers/standard_puzzle_driver.dart index 09bb332a..8bf84c6e 100644 --- a/lib/src/offer/models/drivers/standard_puzzle_driver.dart +++ b/lib/src/offer/models/drivers/standard_puzzle_driver.dart @@ -33,7 +33,10 @@ class StandardPuzzleDriver implements PuzzleDriver { SpendType get type => SpendType.standard; @override - OfferedCoin makeOfferedCoinFromParentSpend(CoinPrototype coin, CoinSpend parentSpend) { + OfferedCoin makeOfferedCoinFromParentSpend( + CoinPrototype coin, + CoinSpend parentSpend, + ) { return OfferedStandardCoin.fromOfferBundleCoin(coin); } @@ -48,7 +51,10 @@ class StandardPuzzleDriver implements PuzzleDriver { } @override - bool doesMatchUncurried(ModAndArguments uncurriedFullPuzzle, Program fullPuzzle) { + bool doesMatchUncurried( + ModAndArguments uncurriedFullPuzzle, + Program fullPuzzle, + ) { final mod = uncurriedFullPuzzle.mod; return mod == p2DelegatedPuzzleOrHiddenPuzzleProgram || // no curried args in settlement programs @@ -58,7 +64,10 @@ class StandardPuzzleDriver implements PuzzleDriver { } @override - CoinPrototype getChildCoinForP2Payment(CoinSpend coinSpend, Payment p2Payment) { + CoinPrototype getChildCoinForP2Payment( + CoinSpend coinSpend, + Payment p2Payment, + ) { return CoinPrototype( parentCoinInfo: coinSpend.coin.id, puzzlehash: p2Payment.puzzlehash, diff --git a/lib/src/offer/models/mixed_amounts.dart b/lib/src/offer/models/mixed_amounts.dart index 69e58184..1a174ce6 100644 --- a/lib/src/offer/models/mixed_amounts.dart +++ b/lib/src/offer/models/mixed_amounts.dart @@ -97,10 +97,18 @@ extension MixedAmountsBase on MixedAmounts { return MixedPayments({ for (final typeEntry in map.entries) typeEntry.key: Map.fromEntries( - typeEntry.value.entries.where((element) => element.value > 0).map((assetEntry) { + typeEntry.value.entries + .where((element) => element.value > 0) + .map((assetEntry) { return MapEntry( assetEntry.key, - [Payment.ofType(assetEntry.value, puzzlehash, type: typeEntry.key)], + [ + Payment.ofType( + assetEntry.value, + puzzlehash, + type: typeEntry.key, + ) + ], ); }), ), diff --git a/lib/src/offer/models/mixed_coins.dart b/lib/src/offer/models/mixed_coins.dart index 1afb558b..4c40254f 100644 --- a/lib/src/offer/models/mixed_coins.dart +++ b/lib/src/offer/models/mixed_coins.dart @@ -58,7 +58,9 @@ class MixedCoins { } Map get nftMap { - return Map.fromEntries(nfts.map((e) => MapEntry(Puzzlehash(e.launcherId), e))); + return Map.fromEntries( + nfts.map((e) => MapEntry(Puzzlehash(e.launcherId), e)), + ); } List get allCoins => diff --git a/lib/src/offer/models/mixed_notarized_payments.dart b/lib/src/offer/models/mixed_notarized_payments.dart index 81656623..1ece1827 100644 --- a/lib/src/offer/models/mixed_notarized_payments.dart +++ b/lib/src/offer/models/mixed_notarized_payments.dart @@ -4,7 +4,8 @@ import 'package:chia_crypto_utils/chia_crypto_utils.dart'; import 'package:meta/meta.dart'; @immutable -class MixedNotarizedPayments with MixedTypeMixin, MixedNotarizedPayments> { +class MixedNotarizedPayments + with MixedTypeMixin, MixedNotarizedPayments> { const MixedNotarizedPayments(this.map); @override @@ -20,7 +21,10 @@ class MixedNotarizedPayments with MixedTypeMixin, MixedNo void debug() { final catString = jsonEncode( - cat.map((key, value) => MapEntry(key.toString(), value.map((e) => e.toString()).toList())), + cat.map( + (key, value) => + MapEntry(key.toString(), value.map((e) => e.toString()).toList()), + ), ); print('{'); print(' standard: $standard,'); @@ -29,17 +33,25 @@ class MixedNotarizedPayments with MixedTypeMixin, MixedNo } @override - List add(List first, List second) { + List add( + List first, + List second, + ) { return first + second; } @override - MixedNotarizedPayments clone(Map>> map) { + MixedNotarizedPayments clone( + Map>> map, + ) { return MixedNotarizedPayments(map); } @override - List subtract(List first, List second) { + List subtract( + List first, + List second, + ) { throw UnimplementedError(); } } diff --git a/lib/src/offer/models/mixed_payments.dart b/lib/src/offer/models/mixed_payments.dart index a753941a..713b79f1 100644 --- a/lib/src/offer/models/mixed_payments.dart +++ b/lib/src/offer/models/mixed_payments.dart @@ -9,7 +9,9 @@ class RequestedMixedPayments { this.standard = const [], Map> this.cat = const {}, List nfts = const [], - }) : nft = Map.fromEntries(nfts.map((e) => MapEntry(Puzzlehash(e.nftRecord.launcherId), [e]))); + }) : nft = Map.fromEntries( + nfts.map((e) => MapEntry(Puzzlehash(e.nftRecord.launcherId), [e])), + ); final List standard; @@ -23,7 +25,9 @@ class RequestedMixedPayments { GeneralCoinType.standard: {null: standard}, GeneralCoinType.cat: cat, GeneralCoinType.nft: Map.fromEntries( - nft.entries.map((e) => MapEntry(e.key, [NftPayment(e.value.single.puzzlehash)])), + nft.entries.map( + (e) => MapEntry(e.key, [NftPayment(e.value.single.puzzlehash)]), + ), ), }); @@ -56,7 +60,9 @@ class MixedPayments with MixedTypeMixin, MixedPayments> { } @override - MixedPayments clone(Map>> map) { + MixedPayments clone( + Map>> map, + ) { return MixedPayments(map); } @@ -76,8 +82,10 @@ extension Notarize on MixedPayments { return MixedNotarizedPayments({ for (final entry in map.entries) entry.key: entry.value.map( - (assetId, payments) => - MapEntry(assetId, payments.map((p) => p.toNotarizedPayment(nonce)).toList()), + (assetId, payments) => MapEntry( + assetId, + payments.map((p) => p.toNotarizedPayment(nonce)).toList(), + ), ), }); } diff --git a/lib/src/offer/models/notarized_payment.dart b/lib/src/offer/models/notarized_payment.dart index 1cd5b231..842ec4fe 100644 --- a/lib/src/offer/models/notarized_payment.dart +++ b/lib/src/offer/models/notarized_payment.dart @@ -6,7 +6,11 @@ class NotarizedPayment implements Payment { NotarizedPayment.withDefaultNonce( int amount, Puzzlehash puzzlehash, - ) : payment = Payment.withRawMemos(amount, puzzlehash, [Memo(puzzlehash.byteList)]), + ) : payment = Payment.withRawMemos( + amount, + puzzlehash, + [Memo(puzzlehash.byteList)], + ), nonce = Puzzlehash.zeros(); final Payment payment; final Bytes nonce; @@ -30,7 +34,8 @@ class NotarizedPayment implements Payment { List get memoStrings => payment.memoStrings; @override - CreateCoinCondition toCreateCoinCondition() => payment.toCreateCoinCondition(); + CreateCoinCondition toCreateCoinCondition() => + payment.toCreateCoinCondition(); @override NotarizedPayment toNotarizedPayment(Bytes nonce) => this; diff --git a/lib/src/offer/models/offer.dart b/lib/src/offer/models/offer.dart index 09227296..2056ffc9 100644 --- a/lib/src/offer/models/offer.dart +++ b/lib/src/offer/models/offer.dart @@ -69,7 +69,9 @@ class Offer { ); } - static Future fromDummySpendBundleAsync(SpendBundle spendBundle) async { + static Future fromDummySpendBundleAsync( + SpendBundle spendBundle, + ) async { return Offer( offeredSpendBundle: SpendBundle.withNullableSignatures( coinSpends: Offer.getLeftOverCoinSpends(spendBundle), @@ -101,7 +103,8 @@ class Offer { } for (final addition in coinSpend.additions) { - final offeredCoin = puzzleDriver.makeOfferedCoinFromParentSpend(addition, coinSpend); + final offeredCoin = + puzzleDriver.makeOfferedCoinFromParentSpend(addition, coinSpend); if (offeredCoin != null) { offeredCoins.add(offeredCoin); } @@ -114,27 +117,31 @@ class Offer { final removalIds = offeredSpendBundle.removals.map((e) => e.id).toSet(); - return offeredCoins.where((element) => !removalIds.contains(element.coin.id)).toList(); + return offeredCoins + .where((element) => !removalIds.contains(element.coin.id)) + .toList(); } - MixedCoins get offeredCoins => MixedCoins.fromOfferedCoins(generalOfferedCoins); + MixedCoins get offeredCoins => + MixedCoins.fromOfferedCoins(generalOfferedCoins); MixedAmounts get offeredAmounts { final offeredCoins = this.offeredCoins; return MixedAmounts.fromMap({ GeneralCoinType.standard: {null: offeredCoins.standardCoins.totalValue}, - GeneralCoinType.cat: - offeredCoins.catMap.map((assetId, coins) => MapEntry(assetId, coins.totalValue)), - GeneralCoinType.nft: - offeredCoins.nftMap.map((launcherId, nft) => MapEntry(launcherId, nft.coin.amount)), + GeneralCoinType.cat: offeredCoins.catMap + .map((assetId, coins) => MapEntry(assetId, coins.totalValue)), + GeneralCoinType.nft: offeredCoins.nftMap + .map((launcherId, nft) => MapEntry(launcherId, nft.coin.amount)), }); } MixedAmounts get requestedAmounts { return MixedAmounts.fromMap({ for (final entry in requestedPayments.map.entries) - entry.key: entry.value.map((key, value) => MapEntry(key, value.totalValue)), + entry.key: + entry.value.map((key, value) => MapEntry(key, value.totalValue)), }); } @@ -156,7 +163,8 @@ class Offer { SpendBundle toSpendBundle([Puzzlehash? arbitragePuzzlehash]) { final arbitrageAmounts = arbitrage().toGeneralizedMap(); - if (arbitrageAmounts.values.any((element) => element != 0) && arbitragePuzzlehash == null) { + if (arbitrageAmounts.values.any((element) => element != 0) && + arbitragePuzzlehash == null) { throw ArgumentError( 'If there are left over coins, and arbitrage puzzlehash must be specified: $arbitrageAmounts', ); @@ -171,10 +179,14 @@ class Offer { final allPayments = List.of(payments); final arbitrageAmountForThisAsset = arbitrageAmounts[assetId]; - if (arbitrageAmountForThisAsset != null && arbitrageAmountForThisAsset > 0) { + if (arbitrageAmountForThisAsset != null && + arbitrageAmountForThisAsset > 0) { // TODO(nvjoshi2): add hint for nft allPayments.add( - NotarizedPayment.withDefaultNonce(arbitrageAmountForThisAsset, arbitragePuzzlehash!), + NotarizedPayment.withDefaultNonce( + arbitrageAmountForThisAsset, + arbitragePuzzlehash!, + ), ); } @@ -190,12 +202,15 @@ class Offer { return SpendBundle(coinSpends: completionCoinSpends) + offeredSpendBundle; } - Future toSpendBundleAsync([Puzzlehash? arbitragePuzzlehash]) async { + Future toSpendBundleAsync([ + Puzzlehash? arbitragePuzzlehash, + ]) async { return spawnAndWaitForIsolate( taskArgument: ToSpendBundleArgs( offer: this, arbitragePuzzlehash: arbitragePuzzlehash, - network: stringToNetwork(ChiaNetworkContextWrapper().blockchainNetwork.name), + network: + stringToNetwork(ChiaNetworkContextWrapper().blockchainNetwork.name), ), isolateTask: _toSpendBundleTask, handleTaskCompletion: SpendBundle.fromJson, @@ -213,7 +228,8 @@ class Offer { requestedPayments.toGeneralizedMap().forEach((assetId, payments) { final driver = driverDict[assetId]!; - final puzzleReveal = driver.getNewFullPuzzleForP2Puzzle(defaultSettlementProgram); + final puzzleReveal = + driver.getNewFullPuzzleForP2Puzzle(defaultSettlementProgram); dummyCoinSpends.add( CoinSpend( coin: CoinPrototype( @@ -251,13 +267,17 @@ class Offer { return innerSolutions; } - static List getPaymentsFromPrograms(List programs) { + static List getPaymentsFromPrograms( + List programs, + ) { final payments = []; for (final program in programs) { final programCons = program.cons; final nonce = programCons[0].atom; payments.addAll( - programCons[1].toList().map((p) => Payment.fromProgram(p).toNotarizedPayment(nonce)), + programCons[1] + .toList() + .map((p) => Payment.fromProgram(p).toNotarizedPayment(nonce)), ); } @@ -305,8 +325,9 @@ class Offer { case SpendType.did: break; case SpendType.standard: - requestedStandardPayments - .addAll(Offer.getPaymentsFromPrograms(coinSpend.solution.toList())); + requestedStandardPayments.addAll( + Offer.getPaymentsFromPrograms(coinSpend.solution.toList()), + ); break; case SpendType.cat: case SpendType.cat1: @@ -350,8 +371,9 @@ class Offer { case SpendType.did: break; case SpendType.standard: - requestedStandardPayments - .addAll(Offer.getPaymentsFromPrograms(coinSpend.solution.toList())); + requestedStandardPayments.addAll( + Offer.getPaymentsFromPrograms(coinSpend.solution.toList()), + ); break; case SpendType.cat: case SpendType.cat1: @@ -373,7 +395,8 @@ class Offer { } Program? get requestedPaymentsSettlementProgram { - final assertPuzzleAnnouncements = BaseWalletService.extractConditionsFromProgramList( + final assertPuzzleAnnouncements = + BaseWalletService.extractConditionsFromProgramList( offeredSpendBundle.outputConditions, AssertPuzzleAnnouncementCondition.isThisCondition, AssertPuzzleAnnouncementCondition.fromProgram, @@ -388,7 +411,8 @@ class Offer { settlementPaymentsProgram, // settlementPaymentsProgram, ]) { - final settlementProgramAnnouncementHashes = OfferWalletService.calculateAnnouncements( + final settlementProgramAnnouncementHashes = + OfferWalletService.calculateAnnouncements( requestedPayments, driverDict, settlementProgram, @@ -396,9 +420,12 @@ class Offer { (e) => e.announcementHash, ); - if (bundleAnnouncementHashes.any(settlementProgramAnnouncementHashes.contains)) { + if (bundleAnnouncementHashes + .any(settlementProgramAnnouncementHashes.contains)) { if (matchingSettlementProgram != null) { - throw Exception('Multiple settlement programs used in announcement creation'); + throw Exception( + 'Multiple settlement programs used in announcement creation', + ); } matchingSettlementProgram = settlementProgram; } @@ -415,7 +442,8 @@ class Offer { final driver = PuzzleInfo.match(coinSpend.puzzleReveal); // overwrite with real assets, not dummy spends if (driver != null && - (dictionary[driver.assetId] == null || coinSpend.coin.puzzlehash != Puzzlehash.zeros())) { + (dictionary[driver.assetId] == null || + coinSpend.coin.puzzlehash != Puzzlehash.zeros())) { dictionary[driver.assetId] = driver; } } @@ -453,8 +481,9 @@ class Offer { ) { final driverDict = {}; for (final requestedNft in requestedNfts) { - driverDict[requestedNft.launcherId] = - PuzzleInfo.match(requestedNft.getFullPuzzleWithNewP2Puzzle(defaultSettlementProgram))!; + driverDict[requestedNft.launcherId] = PuzzleInfo.match( + requestedNft.getFullPuzzleWithNewP2Puzzle(defaultSettlementProgram), + )!; } for (final requestedAssetId in requestedPayments.cat.keys) { @@ -469,7 +498,8 @@ class Offer { } for (final offeredCat in mixedCoins.cats) { - driverDict[offeredCat.assetId] = PuzzleInfo.match(offeredCat.parentCoinSpend.puzzleReveal)!; + driverDict[offeredCat.assetId] = + PuzzleInfo.match(offeredCat.parentCoinSpend.puzzleReveal)!; } for (final nft in mixedCoins.nfts) { @@ -494,7 +524,8 @@ class Offer { } Future validateCoins(ChiaFullNodeInterface fullNode) async { - final hasSpentCoins = await fullNode.checkForSpentCoins(offeredSpendBundle.coins); + final hasSpentCoins = + await fullNode.checkForSpentCoins(offeredSpendBundle.coins); return !hasSpentCoins; } diff --git a/lib/src/offer/models/offered_coin.dart b/lib/src/offer/models/offered_coin.dart index e69de29b..8b137891 100644 --- a/lib/src/offer/models/offered_coin.dart +++ b/lib/src/offer/models/offered_coin.dart @@ -0,0 +1 @@ + diff --git a/lib/src/offer/models/offered_coin/offered_cat1.dart b/lib/src/offer/models/offered_coin/offered_cat1.dart index e88e7a7e..2e70b0b5 100644 --- a/lib/src/offer/models/offered_coin/offered_cat1.dart +++ b/lib/src/offer/models/offered_coin/offered_cat1.dart @@ -4,16 +4,26 @@ import 'package:chia_crypto_utils/src/offer/models/offered_coin/offered_coin.dar class OfferedCat1 implements OfferedCoin { OfferedCat1(this.coin, this.settlementProgram); - factory OfferedCat1.fromOfferBundleParentSpend(CoinPrototype coin, CoinSpend parentSpend) { - final deconstructedCatPuzzle = _catWalletService.matchCatPuzzle(parentSpend.puzzleReveal); + factory OfferedCat1.fromOfferBundleParentSpend( + CoinPrototype coin, + CoinSpend parentSpend, + ) { + final deconstructedCatPuzzle = + _catWalletService.matchCatPuzzle(parentSpend.puzzleReveal); if (deconstructedCatPuzzle == null) { throw InvalidCatException(message: 'invalid cat 1'); } final matchingSettlementProgram = () { - for (final settlementProgram in [settlementPaymentsProgram, settlementPaymentsProgramOld]) { + for (final settlementProgram in [ + settlementPaymentsProgram, + settlementPaymentsProgramOld + ]) { if (_catWalletService - .makeCatPuzzle(deconstructedCatPuzzle.assetId, settlementProgram) + .makeCatPuzzle( + deconstructedCatPuzzle.assetId, + settlementProgram, + ) .hash() == coin.puzzlehash) { return settlementProgram; @@ -49,7 +59,8 @@ class OfferedCat1 implements OfferedCoin { return CoinSpend( coin: coin, - puzzleReveal: _catWalletService.makeCatPuzzle(coin.assetId, settlementProgram), + puzzleReveal: + _catWalletService.makeCatPuzzle(coin.assetId, settlementProgram), solution: solution, ); } @@ -57,7 +68,8 @@ class OfferedCat1 implements OfferedCoin { @override SpendType get type => SpendType.cat1; - static CatWalletService get _catWalletService => CatWalletService.fromCatProgram(cat1Program); + static CatWalletService get _catWalletService => + CatWalletService.fromCatProgram(cat1Program); @override Bytes get assetId => coin.assetId; diff --git a/lib/src/offer/models/offered_coin/offered_cat2.dart b/lib/src/offer/models/offered_coin/offered_cat2.dart index d3aa074b..7b8ba57f 100644 --- a/lib/src/offer/models/offered_coin/offered_cat2.dart +++ b/lib/src/offer/models/offered_coin/offered_cat2.dart @@ -4,16 +4,26 @@ import 'package:chia_crypto_utils/src/offer/models/offered_coin/offered_coin.dar class OfferedCat2 implements OfferedCoin { OfferedCat2(this.coin, this.settlementProgram); - factory OfferedCat2.fromOfferBundleParentSpend(CoinPrototype coin, CoinSpend parentSpend) { - final deconstructedCatPuzzle = _catWalletService.matchCatPuzzle(parentSpend.puzzleReveal); + factory OfferedCat2.fromOfferBundleParentSpend( + CoinPrototype coin, + CoinSpend parentSpend, + ) { + final deconstructedCatPuzzle = + _catWalletService.matchCatPuzzle(parentSpend.puzzleReveal); if (deconstructedCatPuzzle == null) { throw InvalidCatException(message: 'invalid cat 2'); } final matchingSettlementProgram = () { - for (final settlementProgram in [settlementPaymentsProgram, settlementPaymentsProgramOld]) { + for (final settlementProgram in [ + settlementPaymentsProgram, + settlementPaymentsProgramOld + ]) { if (_catWalletService - .makeCatPuzzle(deconstructedCatPuzzle.assetId, settlementProgram) + .makeCatPuzzle( + deconstructedCatPuzzle.assetId, + settlementProgram, + ) .hash() == coin.puzzlehash) { return settlementProgram; @@ -49,7 +59,8 @@ class OfferedCat2 implements OfferedCoin { return CoinSpend( coin: coin, - puzzleReveal: _catWalletService.makeCatPuzzle(coin.assetId, settlementProgram), + puzzleReveal: + _catWalletService.makeCatPuzzle(coin.assetId, settlementProgram), solution: solution, ); } diff --git a/lib/src/offer/models/offered_coin/offered_nft.dart b/lib/src/offer/models/offered_coin/offered_nft.dart index 8ce4ffa8..e9c800ca 100644 --- a/lib/src/offer/models/offered_coin/offered_nft.dart +++ b/lib/src/offer/models/offered_coin/offered_nft.dart @@ -4,13 +4,19 @@ import 'package:chia_crypto_utils/src/offer/models/offered_coin/offered_coin.dar class OfferedNft implements OfferedCoin { OfferedNft(this.nft, this.settlementProgram); - factory OfferedNft.fromOfferBundleParentSpend(CoinPrototype coin, CoinSpend parentSpend) { + factory OfferedNft.fromOfferBundleParentSpend( + CoinPrototype coin, + CoinSpend parentSpend, + ) { final nftRecord = NftRecord.fromParentCoinSpend(parentSpend, coin); if (nftRecord == null) { throw InvalidNftException(); } final nftFullPuzzleAndSettlementProgram = () { - for (final settlementProgram in [settlementPaymentsProgram, settlementPaymentsProgramOld]) { + for (final settlementProgram in [ + settlementPaymentsProgram, + settlementPaymentsProgramOld + ]) { final fullPuzzleWithOfferInnerPuzzle = nftRecord.getFullPuzzleWithNewP2Puzzle(settlementProgram); if (fullPuzzleWithOfferInnerPuzzle.hash() == coin.puzzlehash) { diff --git a/lib/src/offer/models/offered_coin/offered_standard_coin.dart b/lib/src/offer/models/offered_coin/offered_standard_coin.dart index 6e6fdf54..d3bd725f 100644 --- a/lib/src/offer/models/offered_coin/offered_standard_coin.dart +++ b/lib/src/offer/models/offered_coin/offered_standard_coin.dart @@ -5,7 +5,10 @@ class OfferedStandardCoin implements OfferedCoin { OfferedStandardCoin(this.coin, this.settlementProgram); factory OfferedStandardCoin.fromOfferBundleCoin(CoinPrototype coin) { final matchingSettlementProgram = () { - for (final settlementProgram in [settlementPaymentsProgram, settlementPaymentsProgramOld]) { + for (final settlementProgram in [ + settlementPaymentsProgram, + settlementPaymentsProgramOld + ]) { if (settlementProgram.hash() == coin.puzzlehash) { return settlementProgram; } diff --git a/lib/src/offer/models/parsed_offer.dart b/lib/src/offer/models/parsed_offer.dart index 9aed634f..536c8323 100644 --- a/lib/src/offer/models/parsed_offer.dart +++ b/lib/src/offer/models/parsed_offer.dart @@ -9,8 +9,10 @@ class ParsedOffer with ToJsonMixin { factory ParsedOffer.fromJson(Map json) { return ParsedOffer( - offeredAmounts: pick(json, 'offeredAmounts').letJsonOrThrow(ParsedMixedAmounts.fromJson), - requestedAmounts: pick(json, 'requestedAmounts').letJsonOrThrow(ParsedMixedAmounts.fromJson), + offeredAmounts: pick(json, 'offeredAmounts') + .letJsonOrThrow(ParsedMixedAmounts.fromJson), + requestedAmounts: pick(json, 'requestedAmounts') + .letJsonOrThrow(ParsedMixedAmounts.fromJson), ); } final ParsedMixedAmounts offeredAmounts; diff --git a/lib/src/offer/service/cat1_offer_service.dart b/lib/src/offer/service/cat1_offer_service.dart index 98c96595..07710895 100644 --- a/lib/src/offer/service/cat1_offer_service.dart +++ b/lib/src/offer/service/cat1_offer_service.dart @@ -10,6 +10,9 @@ class Cat1OfferWalletService extends OfferWalletService { Offer offer, { TailDatabaseApi? tailDatabaseApi, }) async { - return OfferWalletService.parseOffer(offer, tailDatabaseApi: tailDatabaseApi); + return OfferWalletService.parseOffer( + offer, + tailDatabaseApi: tailDatabaseApi, + ); } } diff --git a/lib/src/offer/service/cat_offer_service_base.dart b/lib/src/offer/service/cat_offer_service_base.dart index 667aed2b..fe418856 100644 --- a/lib/src/offer/service/cat_offer_service_base.dart +++ b/lib/src/offer/service/cat_offer_service_base.dart @@ -38,14 +38,19 @@ class OfferWalletService { bool payRoyalties = true, }) { _validateCats(coinsForOffer); - if (coinsForOffer.nfts.any((element) => element.doesSupportDid) && payRoyalties) { + if (coinsForOffer.nfts.any((element) => element.doesSupportDid) && + payRoyalties) { return _makeNft1Offer( coinsForOffer: coinsForOffer, offeredAmounts: offeredAmounts.toMixedAmounts(), - requestedPayments: requestedPayments?.toMixedPayments() ?? const MixedPayments({}), + requestedPayments: + requestedPayments?.toMixedPayments() ?? const MixedPayments({}), changePuzzlehash: changePuzzlehash, keychain: keychain, - requestedNfts: requestedPayments?.nft.values.map((e) => e.single.nftRecord).toList() ?? [], + requestedNfts: requestedPayments?.nft.values + .map((e) => e.single.nftRecord) + .toList() ?? + [], fee: fee, settlementProgram: Offer.defaultSettlementProgram, additionalAggSigMeConditions: additionalAggSigMeConditions, @@ -54,10 +59,14 @@ class OfferWalletService { return _makeOffer( offeredCoins: coinsForOffer, offeredAmounts: offeredAmounts.toMixedAmounts(), - requestedPayments: requestedPayments?.toMixedPayments() ?? const MixedPayments({}), + requestedPayments: + requestedPayments?.toMixedPayments() ?? const MixedPayments({}), changePuzzlehash: changePuzzlehash, keychain: keychain, - requestedNfts: requestedPayments?.nft.values.map((e) => e.single.nftRecord).toList() ?? [], + requestedNfts: requestedPayments?.nft.values + .map((e) => e.single.nftRecord) + .toList() ?? + [], fee: fee, settlementProgram: Offer.defaultSettlementProgram, additionalAggSigMeConditions: additionalAggSigMeConditions, @@ -77,7 +86,8 @@ class OfferWalletService { }) { validateAmounts(offeredAmounts, offeredCoins); - if ((offeredCoins.allCoins.isNotEmpty || !offeredAmounts.isZero) && keychain == null) { + if ((offeredCoins.allCoins.isNotEmpty || !offeredAmounts.isZero) && + keychain == null) { throw Exception('keychain is needed if offering coins'); } @@ -91,7 +101,8 @@ class OfferWalletService { ); final nonce = createNonce(offeredCoins.allCoins); - final notarizedMixedPayments = requestedPayments.toMixedNotarizedPayments(nonce); + final notarizedMixedPayments = + requestedPayments.toMixedNotarizedPayments(nonce); final announcements = calculateAnnouncements( notarizedMixedPayments, driverDict, @@ -178,7 +189,8 @@ class OfferWalletService { }) { validateAmounts(offeredAmounts, coinsForOffer); - if ((coinsForOffer.allCoins.isNotEmpty || !offeredAmounts.isZero) && keychain == null) { + if ((coinsForOffer.allCoins.isNotEmpty || !offeredAmounts.isZero) && + keychain == null) { throw Exception('keychain is needed if offering coins'); } @@ -224,7 +236,10 @@ class OfferWalletService { .hash(); if (requestedPayment.amount > 0 && offerSideRoyaltySplit > 0) { tradePrices.add( - TradePrice(requestedPayment.amount ~/ offerSideRoyaltySplit, settlementPuzzleHash), + TradePrice( + requestedPayment.amount ~/ offerSideRoyaltySplit, + settlementPuzzleHash, + ), ); } } @@ -233,12 +248,15 @@ class OfferWalletService { final royaltyInfos = []; - for (final requestedRoyaltyEnabledNft in requestedRoyaltyEnabledNftRecords) { + for (final requestedRoyaltyEnabledNft + in requestedRoyaltyEnabledNftRecords) { royaltyInfos.add( RoyaltyInfo( launcherId: requestedRoyaltyEnabledNft.launcherId, - royaltyPuzzleHash: requestedRoyaltyEnabledNft.ownershipLayerInfo!.royaltyPuzzleHash!, - royaltyPercentage: requestedRoyaltyEnabledNft.ownershipLayerInfo!.royaltyPercentagePoints, + royaltyPuzzleHash: + requestedRoyaltyEnabledNft.ownershipLayerInfo!.royaltyPuzzleHash!, + royaltyPercentage: requestedRoyaltyEnabledNft + .ownershipLayerInfo!.royaltyPercentagePoints, ), ); } @@ -253,7 +271,8 @@ class OfferWalletService { // standard royalty payments - final royaltyPayments = >>{}; + final royaltyPayments = + >>{}; offeredAmounts.map.forEach((type, assetAmountMap) { royaltyPayments[type] = assetAmountMap.map((assetId, offeredAmount) { @@ -261,7 +280,8 @@ class OfferWalletService { for (final royaltyInfo in royaltyInfos) { final extraRoyaltyAmount = - ((offeredAmount ~/ requestSideRoyaltySplit) * (royaltyInfo.royaltyPercentage / 10000)) + ((offeredAmount ~/ requestSideRoyaltySplit) * + (royaltyInfo.royaltyPercentage / 10000)) .floor(); assetRoyaltyPayments.add( RoyaltyPaymentWithLauncherId( @@ -280,7 +300,8 @@ class OfferWalletService { }); final nonce = createNonce(coinsForOffer.allCoins); - final notarizedMixedPayments = requestedPayments.toMixedNotarizedPayments(nonce); + final notarizedMixedPayments = + requestedPayments.toMixedNotarizedPayments(nonce); final announcements = calculateAnnouncements( notarizedMixedPayments, driverDict, @@ -289,8 +310,9 @@ class OfferWalletService { royaltyPayments.forEach((type, assetPaymentType) { assetPaymentType.forEach((assetId, payments) { - final settlementHash = - driverDict[assetId]!.getNewFullPuzzleForP2Puzzle(Offer.defaultSettlementProgram).hash(); + final settlementHash = driverDict[assetId]! + .getNewFullPuzzleForP2Puzzle(Offer.defaultSettlementProgram) + .hash(); for (final payment in payments) { if (payment.amount > 0) { announcements.add( @@ -316,15 +338,17 @@ class OfferWalletService { offeredAmounts.cat.forEach((assetId, amount) { final catCoins = coinsForOffer.cats.where((c) => c.assetId == assetId); - final catRoyaltyPayments = - royaltyPayments[GeneralCoinType.cat]?[assetId] ?? []; + final catRoyaltyPayments = royaltyPayments[GeneralCoinType.cat] + ?[assetId] ?? + []; final royaltyPaymentsSum = catRoyaltyPayments.sum(); final catSpendBundle = catWalletService.createSpendBundle( payments: [ CatPayment(amount, offerPuzzlehash), - if (royaltyPaymentsSum > 0) CatPayment(royaltyPaymentsSum, offerPuzzlehash), + if (royaltyPaymentsSum > 0) + CatPayment(royaltyPaymentsSum, offerPuzzlehash), ], catCoinsInput: catCoins.toList(), keychain: keychain!, @@ -337,10 +361,12 @@ class OfferWalletService { if (royaltyPaymentsSum > 0) { final royaltyBundle = makeRoyaltySpendBundle( - driverDict[assetId]!.getNewFullPuzzleForP2Puzzle(Offer.defaultSettlementProgram), + driverDict[assetId]! + .getNewFullPuzzleForP2Puzzle(Offer.defaultSettlementProgram), catRoyaltyPayments, catSpendBundle, (coin, parentSpend, innerRoyaltySolution) { - final catProgram = parentSpend.type == SpendType.cat ? cat2Program : cat1Program; + final catProgram = + parentSpend.type == SpendType.cat ? cat2Program : cat1Program; final catCoin = CatCoin.fromParentSpend( parentCoinSpend: parentSpend, coin: coin, @@ -361,8 +387,9 @@ class OfferWalletService { }); if (offeredAmounts.standard > 0) { - final standardRoyaltyPayments = - royaltyPayments[GeneralCoinType.standard]?[null] ?? []; + final standardRoyaltyPayments = royaltyPayments[GeneralCoinType.standard] + ?[null] ?? + []; final royaltySum = standardRoyaltyPayments.sum(); final standardSpendBundle = standardWalletService.createSpendBundle( @@ -414,7 +441,10 @@ class OfferWalletService { (element) => element.amount * (offeredRoyaltyInfos - .singleWhere((element) => element.launcherId == nft.launcherId) + .singleWhere( + (element) => + element.launcherId == nft.launcherId, + ) .royaltyPercentage / 10000) > 0, @@ -443,9 +473,11 @@ class OfferWalletService { CoinPrototype coin, CoinSpend parentSpend, Program innerRoyaltySolution, - ) makeSolutionFromInnerSolution, + ) + makeSolutionFromInnerSolution, ) { - var royaltyPayments = List.from(royaltyPayments_); + var royaltyPayments = + List.from(royaltyPayments_); CoinPrototypeWithParentSpend? royaltyCoinWithParentSpend; final royaltyPuzzleHash = offerPuzzle.hash(); var totalBundle = SpendBundle.empty; @@ -453,7 +485,9 @@ class OfferWalletService { final duplicatePayments = []; final deDuplicatedPayments = []; for (final royaltyPayment in royaltyPayments) { - if (deDuplicatedPayments.map((e) => e.payment).contains(royaltyPayment.payment)) { + if (deDuplicatedPayments + .map((e) => e.payment) + .contains(royaltyPayment.payment)) { duplicatePayments.add(royaltyPayment); } else { deDuplicatedPayments.add(royaltyPayment); @@ -480,12 +514,17 @@ class OfferWalletService { royaltyCoinWithParentSpend = () { for (final coin in mainSpendBundle.additions) { final royaltyPaymentAmount = royaltyPayments.sum(); - if (coin.amount == royaltyPaymentAmount && coin.puzzlehash == royaltyPuzzleHash) { + if (coin.amount == royaltyPaymentAmount && + coin.puzzlehash == royaltyPuzzleHash) { final royaltyCoin = coin; - final coinSpend = mainSpendBundle.coinSpends - .singleWhere((element) => element.coin.id == royaltyCoin.parentCoinInfo); + final coinSpend = mainSpendBundle.coinSpends.singleWhere( + (element) => element.coin.id == royaltyCoin.parentCoinInfo, + ); - return CoinPrototypeWithParentSpend.fromCoin(royaltyCoin, coinSpend); + return CoinPrototypeWithParentSpend.fromCoin( + royaltyCoin, + coinSpend, + ); } } }(); @@ -507,7 +546,8 @@ class OfferWalletService { if (duplicatePayments.isNotEmpty) { royaltyPayments = duplicatePayments; royaltyCoinWithParentSpend = CoinPrototypeWithParentSpend.fromCoin( - newCoinSpend.additions.firstWhere((a) => a.puzzlehash == royaltyPuzzleHash), + newCoinSpend.additions + .firstWhere((a) => a.puzzlehash == royaltyPuzzleHash), newCoinSpend, ); throw Exception('ha'); @@ -580,8 +620,8 @@ class OfferWalletService { changePuzzlehash: changePuzzlehash ?? puzzlehash, requestedNfts: offeredNfts, fee: fee, - settlementProgram: - askOffer.requestedPaymentsSettlementProgram ?? Offer.defaultSettlementProgram, + settlementProgram: askOffer.requestedPaymentsSettlementProgram ?? + Offer.defaultSettlementProgram, ); } return _makeOffer( @@ -592,8 +632,8 @@ class OfferWalletService { changePuzzlehash: changePuzzlehash ?? puzzlehash, requestedNfts: offeredNfts, fee: fee, - settlementProgram: - askOffer.requestedPaymentsSettlementProgram ?? Offer.defaultSettlementProgram, + settlementProgram: askOffer.requestedPaymentsSettlementProgram ?? + Offer.defaultSettlementProgram, ); }(); @@ -620,8 +660,9 @@ class OfferWalletService { if (payments.isEmpty) { return; } - final settlementPuzzlehash = - driverDict[assetId]!.getNewFullPuzzleForP2Puzzle(settlementProgram).hash(); + final settlementPuzzlehash = driverDict[assetId]! + .getNewFullPuzzleForP2Puzzle(settlementProgram) + .hash(); final message = Program.cons( Program.fromAtom(payments[0].nonce), Program.list(payments.map((p) => p.toProgram()).toList()), @@ -629,7 +670,8 @@ class OfferWalletService { announcements.add( AssertPuzzleAnnouncementCondition( - AssertCoinAnnouncementCondition(settlementPuzzlehash, message).announcementId, + AssertCoinAnnouncementCondition(settlementPuzzlehash, message) + .announcementId, ), ); }); diff --git a/lib/src/offer/service/offer_service.dart b/lib/src/offer/service/offer_service.dart index e798a01f..8aa51f56 100644 --- a/lib/src/offer/service/offer_service.dart +++ b/lib/src/offer/service/offer_service.dart @@ -30,7 +30,8 @@ class OfferService { final intermediateCoinIdToAdditions = >{}; - for (final additionWithParentSpend in takeOfferSpendBundle.netAdditonWithParentSpends) { + for (final additionWithParentSpend + in takeOfferSpendBundle.netAdditonWithParentSpends) { intermediateCoinIdToAdditions.update( additionWithParentSpend.parentSpend!.coin.id, (value) => [ @@ -52,9 +53,10 @@ class OfferService { final parentSpendIds = []; - for (final intermediateSpendWithAdditions in intermediateCoinSpendsWithAdditions) { - final originCoinSpend = - coinSpendMap[intermediateSpendWithAdditions.coinSpend.coin.parentCoinInfo]; + for (final intermediateSpendWithAdditions + in intermediateCoinSpendsWithAdditions) { + final originCoinSpend = coinSpendMap[ + intermediateSpendWithAdditions.coinSpend.coin.parentCoinInfo]; if (originCoinSpend == null) { continue; } @@ -63,9 +65,10 @@ class OfferService { } final parentSpends = await fullNode.getCoinSpendsByIds(parentSpendIds); - for (final intermediateSpendWithAdditions in intermediateCoinSpendsWithAdditions) { - final originCoinSpend = - coinSpendMap[intermediateSpendWithAdditions.coinSpend.coin.parentCoinInfo]; + for (final intermediateSpendWithAdditions + in intermediateCoinSpendsWithAdditions) { + final originCoinSpend = coinSpendMap[ + intermediateSpendWithAdditions.coinSpend.coin.parentCoinInfo]; if (originCoinSpend == null) { continue; @@ -84,7 +87,8 @@ class OfferService { final Wallet wallet; final OfferWalletService walletService; - int get catVersion => walletService.catWalletService.spendType == SpendType.cat ? 2 : 1; + int get catVersion => + walletService.catWalletService.spendType == SpendType.cat ? 2 : 1; Future createOffer({ required MixedAmounts offeredAmounts, @@ -94,8 +98,10 @@ class OfferService { }) async { final keychain = await wallet.getKeychain(); - final offeredCoins = - await wallet.getMixedCoinsForAmounts(offeredAmounts, catVersion: catVersion); + final offeredCoins = await wallet.getMixedCoinsForAmounts( + offeredAmounts, + catVersion: catVersion, + ); return walletService.makeOffer( offeredAmounts: OfferedMixedAmounts( @@ -118,12 +124,15 @@ class OfferService { }) async { final keychain = await wallet.getKeychain(); - final offeredCoins = - await wallet.getMixedCoinsForAmounts(offeredAmounts, catVersion: catVersion); + final offeredCoins = await wallet.getMixedCoinsForAmounts( + offeredAmounts, + catVersion: catVersion, + ); final dummyBundle = await spawnAndWaitForIsolate( taskArgument: CreateOfferArgs( - network: stringToNetwork(ChiaNetworkContextWrapper().blockchainNetwork.name), + network: + stringToNetwork(ChiaNetworkContextWrapper().blockchainNetwork.name), offerWalletService: walletService, offeredAmounts: offeredAmounts, offeredCoins: offeredCoins, @@ -139,7 +148,9 @@ class OfferService { return Offer.fromDummySpendBundleAsync(dummyBundle); } - static Map _createOfferDummySpendBundle(CreateOfferArgs args) { + static Map _createOfferDummySpendBundle( + CreateOfferArgs args, + ) { ChiaNetworkContextWrapper().registerNetworkContext(args.network); return args.offerWalletService .makeOffer( @@ -149,7 +160,8 @@ class OfferService { ), requestedPayments: args.requestedPayments, coinsForOffer: args.offeredCoins, - changePuzzlehash: args.changePuzzlehash ?? args.keychain.puzzlehashes.random, + changePuzzlehash: + args.changePuzzlehash ?? args.keychain.puzzlehashes.random, keychain: args.keychain, fee: args.fee, ) @@ -199,7 +211,8 @@ class OfferService { final dummyBundle = await spawnAndWaitForIsolate( taskArgument: TakeOfferArgs( - network: stringToNetwork(ChiaNetworkContextWrapper().blockchainNetwork.name), + network: + stringToNetwork(ChiaNetworkContextWrapper().blockchainNetwork.name), offerWalletService: walletService, askOffer: offer, coinsForOffer: coinsForOffer, @@ -285,16 +298,20 @@ class OfferedCoinLineage { void validate() { if (originalParentSpend != null && originalParentSpend!.coin.id != originalCoinSpend.coin.parentCoinInfo) { - throw Exception('originalParentSpend.coin.id!= originalCoinSpend.coin.parentCoinInfo'); + throw Exception( + 'originalParentSpend.coin.id!= originalCoinSpend.coin.parentCoinInfo', + ); } - if (originalCoinSpend.coin.id != intermediateSpendWithAdditions.coinSpend.coin.parentCoinInfo) { + if (originalCoinSpend.coin.id != + intermediateSpendWithAdditions.coinSpend.coin.parentCoinInfo) { throw Exception( 'originalCoinSpend.coin.id!= intermediateSpendWithAdditions.coinSpend.coin.parentCoinInfo', ); } for (final addition in intermediateSpendWithAdditions.additions) { - if (addition.parentCoinInfo != intermediateSpendWithAdditions.coinSpend.coin.id) { + if (addition.parentCoinInfo != + intermediateSpendWithAdditions.coinSpend.coin.id) { throw Exception('addition.parentCoinInfo != originalCoinSpend.coin.id'); } } diff --git a/lib/src/plot_nft/models/extra_data.dart b/lib/src/plot_nft/models/extra_data.dart index 4cab6a6a..84e0be3b 100644 --- a/lib/src/plot_nft/models/extra_data.dart +++ b/lib/src/plot_nft/models/extra_data.dart @@ -12,7 +12,8 @@ class PlotNftExtraData with ToBytesMixin { factory PlotNftExtraData.fromStream(Iterator iterator) { final poolState = PoolState.fromStream(iterator); - final delayTime = bytesToInt(iterator.extractBytesAndAdvance(4), Endian.big); + final delayTime = + bytesToInt(iterator.extractBytesAndAdvance(4), Endian.big); final delayPuzzlehash = Puzzlehash.fromStream(iterator); return PlotNftExtraData(poolState, delayTime, delayPuzzlehash); @@ -32,7 +33,8 @@ class PlotNftExtraData with ToBytesMixin { final delayTime = delayTimePrograms.single.rest().toInt(); final extraDataPrograms = extraDataProgramList.where( - (p) => String.fromCharCode(p.first().toInt()) == delayPuzzlehashIdentifier, + (p) => + String.fromCharCode(p.first().toInt()) == delayPuzzlehashIdentifier, ); if (extraDataPrograms.isEmpty || extraDataPrograms.length > 1) { throw InvalidPlotNftException(); diff --git a/lib/src/plot_nft/models/plot_nft.dart b/lib/src/plot_nft/models/plot_nft.dart index 36cf7721..bd97d0f4 100644 --- a/lib/src/plot_nft/models/plot_nft.dart +++ b/lib/src/plot_nft/models/plot_nft.dart @@ -7,7 +7,9 @@ class PlotNft with ToBytesMixin { required this.poolState, required this.delayTime, required this.delayPuzzlehash, + required this.lineageProof, }); + factory PlotNft.fromBytes(Bytes bytes) { final iterator = bytes.iterator; @@ -16,6 +18,7 @@ class PlotNft with ToBytesMixin { final poolState = PoolState.fromStream(iterator); final delayTime = intFrom64BitsStream(iterator); final delayPuzzlehash = Puzzlehash.fromStream(iterator); + final lineageProof = LineageProof.fromStream(iterator); return PlotNft( launcherId: launcherId, @@ -23,6 +26,7 @@ class PlotNft with ToBytesMixin { poolState: poolState, delayTime: delayTime, delayPuzzlehash: delayPuzzlehash, + lineageProof: lineageProof, ); } @@ -31,14 +35,23 @@ class PlotNft with ToBytesMixin { final PoolState poolState; final int delayTime; final Puzzlehash delayPuzzlehash; + final LineageProof lineageProof; - Puzzlehash get p2Puzzlehash => - PlotNftWalletService.launcherIdToP2Puzzlehash(launcherId, delayTime, delayPuzzlehash); + Puzzlehash get p2Puzzlehash => PlotNftWalletService.launcherIdToP2Puzzlehash( + launcherId, + delayTime, + delayPuzzlehash, + ); Future get p2PuzzlehashAsync => - PlotNftWalletService.launcherIdToP2PuzzlehashAsync(launcherId, delayTime, delayPuzzlehash); + PlotNftWalletService.launcherIdToP2PuzzlehashAsync( + launcherId, + delayTime, + delayPuzzlehash, + ); - Puzzlehash get contractPuzzlehash => PlotNftWalletService.launcherIdToP2Puzzlehash( + Puzzlehash get contractPuzzlehash => + PlotNftWalletService.launcherIdToP2Puzzlehash( launcherId, delayTime, delayPuzzlehash, @@ -55,10 +68,11 @@ class PlotNft with ToBytesMixin { singletonCoin.toBytes() + poolState.toBytes() + intTo64Bits(delayTime) + - delayPuzzlehash; + delayPuzzlehash + + lineageProof.toBytes(); } @override String toString() => - 'PlotNft(launcherId: $launcherId, singletonCoin: $singletonCoin, poolState: $poolState, delayTime: $delayTime, delayPuzzlehash: $delayPuzzlehash)'; + 'PlotNft(launcherId: $launcherId, singletonCoin: $singletonCoin, poolState: $poolState, delayTime: $delayTime, delayPuzzlehash: $delayPuzzlehash, lineagProof: $lineageProof'; } diff --git a/lib/src/plot_nft/models/pool_state.dart b/lib/src/plot_nft/models/pool_state.dart index 0968c96e..f2bc72b4 100644 --- a/lib/src/plot_nft/models/pool_state.dart +++ b/lib/src/plot_nft/models/pool_state.dart @@ -16,7 +16,9 @@ class PoolState with ToBytesMixin { }); factory PoolState.fromExtraDataProgram(Program extraDataProgram) { final extraDataConsBoxes = extraDataProgram.toList().where( - (p) => String.fromCharCode(p.first().toInt()) == PlotNftExtraData.poolStateIdentifier, + (p) => + String.fromCharCode(p.first().toInt()) == + PlotNftExtraData.poolStateIdentifier, ); if (extraDataConsBoxes.isEmpty || extraDataConsBoxes.length > 1) { throw InvalidPlotNftException(); @@ -47,7 +49,8 @@ class PoolState with ToBytesMixin { final poolUrlIsPresentBytes = iterator.extractBytesAndAdvance(1); if (poolUrlIsPresentBytes[0] == 1) { final lengthBytes = iterator.extractBytesAndAdvance(4); - final poolUrlBytes = iterator.extractBytesAndAdvance(bytesToInt(lengthBytes, Endian.big)); + final poolUrlBytes = + iterator.extractBytesAndAdvance(bytesToInt(lengthBytes, Endian.big)); poolUrl = utf8.decode(poolUrlBytes); } else if (poolUrlIsPresentBytes[0] != 0) { throw ArgumentError('invalid isPresent bytes'); diff --git a/lib/src/plot_nft/service/wallet.dart b/lib/src/plot_nft/service/wallet.dart index 93de4784..125fa919 100644 --- a/lib/src/plot_nft/service/wallet.dart +++ b/lib/src/plot_nft/service/wallet.dart @@ -1,5 +1,6 @@ import 'package:chia_crypto_utils/chia_crypto_utils.dart'; import 'package:chia_crypto_utils/src/plot_nft/models/exceptions/invalid_pool_singleton_exception.dart'; +import 'package:chia_crypto_utils/src/singleton/puzzles/singleton_output_inner_puzzle/singleton_output_inner_puzzle.clvm.hex.dart'; class PlotNftWalletService extends BaseWalletService { final standardWalletService = StandardWalletService(); @@ -17,7 +18,8 @@ class PlotNftWalletService extends BaseWalletService { required WalletKeychain keychain, Puzzlehash? changePuzzlehash, }) { - final launcherParent = coins.singleWhere((coin) => coin.id == genesisCoinId); + final launcherParent = + coins.singleWhere((coin) => coin.id == genesisCoinId); final genesisLauncherPuzzle = singletonLauncherProgram; final launcherCoin = makeLauncherCoin(launcherParent.id); @@ -29,7 +31,8 @@ class PlotNftWalletService extends BaseWalletService { isInitialState: true, ); - final fullPoolingPuzzle = SingletonService.puzzleForSingleton(launcherCoin.id, innerPuzzle); + final fullPoolingPuzzle = + SingletonService.puzzleForSingleton(launcherCoin.id, innerPuzzle); final puzzlehash = fullPoolingPuzzle.hash(); final plotNftExtraData = PlotNftExtraData( @@ -75,6 +78,364 @@ class PlotNftWalletService extends BaseWalletService { return createLauncherSpendBundle + launcherSpendBundle; } + Future createPlotNftMutationSpendBundle({ + required PlotNft plotNft, + List coinsForFee = const [], + Puzzlehash? changePuzzleHash, + int fee = 0, + required PoolState targetState, + required WalletKeychain keychain, + }) async { + final currentState = plotNft.poolState; + final launcherId = plotNft.launcherId; + final currentSingleton = plotNft.singletonCoin; + final delayPuzzlehash = plotNft.delayPuzzlehash; + final delayTime = plotNft.delayTime; + + final currentInnerPuzzle = poolStateToInnerPuzzle( + poolState: currentState, + launcherId: launcherId, + delayPuzzlehash: delayPuzzlehash, + delayTime: delayTime, + ); + + final newInnerPuzzle = poolStateToInnerPuzzle( + poolState: targetState, + launcherId: launcherId, + delayPuzzlehash: delayPuzzlehash, + delayTime: delayTime, + ); + + if (currentInnerPuzzle == newInnerPuzzle) { + throw Exception(); + } + + final uncurriedInnerPuzzle = currentInnerPuzzle.uncurry(); + final uncurriedInnerPuzzleProgram = uncurriedInnerPuzzle.mod; + + Program? innerSolution; + if (uncurriedInnerPuzzleProgram == poolMemberInnerpuzProgram) { + innerSolution = Program.list([ + Program.list( + [ + Program.cons( + Program.fromString('p'), + Program.fromAtom(targetState.toBytes()), + ) + ], + ), + Program.nil + ]); + } else if (uncurriedInnerPuzzleProgram == poolWaitingRoomInnerpuzProgram) { + innerSolution = Program.list([ + Program.fromInt(1), + Program.list( + [ + Program.cons( + Program.fromString('p'), + Program.fromAtom(targetState.toBytes()), + ) + ], + ), + Program.fromAtom(newInnerPuzzle.hash().toBytes()) + ]); + } else { + throw ArgumentError(); + } + + final fullPuzzle = + SingletonService.puzzleForSingleton(launcherId, currentInnerPuzzle); + + final fullSolution = Program.list([ + plotNft.lineageProof.toProgram(), + Program.fromInt(currentSingleton.amount), + innerSolution, + ]); + + final travelSpend = CoinSpend( + coin: currentSingleton, + puzzleReveal: fullPuzzle, + solution: fullSolution, + ); + + final travelSpendBundle = SpendBundle(coinSpends: [travelSpend]); + + final ownerPublicKey = currentState.ownerPublicKey; + final singletonWalletVector = + keychain.getSingletonWalletVector(ownerPublicKey); + final privateKey = singletonWalletVector!.singletonOwnerPrivateKey; + + final signedSpendBundle = travelSpendBundle.signPerCoinSpend( + (coinSpend) => standardWalletService.makeSignature( + privateKey, + coinSpend, + useSyntheticOffset: false, + ), + ); + + if (fee > 0) { + final feeSpendBundle = standardWalletService.createSpendBundle( + fee: fee, + payments: [], + coinsInput: coinsForFee, + keychain: keychain, + changePuzzlehash: changePuzzleHash, + ); + return signedSpendBundle + feeSpendBundle; + } + + return signedSpendBundle; + } + + Future createTransferPlotNftSpendBundle({ + required List coins, + required JacobianPoint targetOwnerPublicKey, + required PlotNft plotNft, + required WalletKeychain keychain, + Puzzlehash? changePuzzleHash, + PoolSingletonState? newPoolSingletonState, + String? poolUrl, + int fee = 0, + }) async { + PoolState? targetState; + if (poolUrl != null) { + final poolInfo = await PoolInterface.fromURL(poolUrl).getPoolInfo(); + targetState = PoolState( + poolSingletonState: PoolSingletonState.farmingToPool, + targetPuzzlehash: poolInfo.targetPuzzlehash, + ownerPublicKey: targetOwnerPublicKey, + relativeLockHeight: poolInfo.relativeLockHeight, + poolUrl: poolUrl, + ); + } else { + targetState = PoolState( + poolSingletonState: + newPoolSingletonState ?? plotNft.poolState.poolSingletonState, + targetPuzzlehash: plotNft.poolState.targetPuzzlehash, + ownerPublicKey: targetOwnerPublicKey, + relativeLockHeight: plotNft.poolState.relativeLockHeight, + ); + } + + final mutationSpendBundle = await createPlotNftMutationSpendBundle( + keychain: keychain, + plotNft: plotNft, + targetState: targetState, + ); + + final hint = SingletonWalletVector.makePlotNftHint(targetOwnerPublicKey); + + final treasureMapSpendBundle = standardWalletService.createSpendBundle( + payments: [ + Payment( + 1, + Puzzlehash(plotNft.launcherId), + memos: [hint], + ) + ], + coinsInput: coins, + keychain: keychain, + fee: fee, + changePuzzlehash: changePuzzleHash, + ); + + return mutationSpendBundle + treasureMapSpendBundle; + } + + Future createPlotNftTransferSpendBundle({ + required PlotNft plotNft, + List coinsForFee = const [], + required List coinsForTreasureMapCoin, + Puzzlehash? changePuzzleHash, + int fee = 0, + required PoolState targetState, + required Puzzlehash receiverPuzzlehash, + required WalletKeychain keychain, + }) async { + final currentState = plotNft.poolState; + if (![PoolSingletonState.leavingPool, PoolSingletonState.selfPooling] + .contains(currentState.poolSingletonState)) { + throw Exception( + 'Plot nft must be leaving pool or self pooling to transfer it', + ); + } + final launcherId = plotNft.launcherId; + final currentSingleton = plotNft.singletonCoin; + final delayPuzzlehash = plotNft.delayPuzzlehash; + final delayTime = plotNft.delayTime; + + final currentInnerPuzzle = poolStateToInnerPuzzle( + poolState: currentState, + launcherId: launcherId, + delayPuzzlehash: delayPuzzlehash, + delayTime: delayTime, + ); + + final newWaitingRoomInnerPuzzle = poolStateToInnerPuzzle( + poolState: targetState, + launcherId: launcherId, + delayPuzzlehash: delayPuzzlehash, + delayTime: delayTime, + ); + + if (currentInnerPuzzle == newWaitingRoomInnerPuzzle) { + throw Exception(); + } + + final uncurriedInnerPuzzle = currentInnerPuzzle.uncurry(); + final uncurriedInnerPuzzleProgram = uncurriedInnerPuzzle.mod; + + if (uncurriedInnerPuzzleProgram != poolWaitingRoomInnerpuzProgram) { + throw Exception('wrong inner puzzle'); + } + + final toP2ConditionsInnerSolution = Program.list([ + Program.fromInt(1), + Program.list( + [ + Program.cons( + Program.fromString('p'), + Program.fromAtom(targetState.toBytes()), + ) + ], + ), + Program.fromAtom(singletonOutputInnerPuzzleProgram.hash().toBytes()) + ]); + + final startingFullPuzzle = + SingletonService.puzzleForSingleton(launcherId, currentInnerPuzzle); + + final toP2ConditionsFullSolution = Program.list([ + plotNft.lineageProof.toProgram(), + Program.fromInt(currentSingleton.amount), + toP2ConditionsInnerSolution, + ]); + + final toP2ConditionsSpend = CoinSpend( + coin: currentSingleton, + puzzleReveal: startingFullPuzzle, + solution: toP2ConditionsFullSolution, + ); + + final toP2ConditionsSpendBundle = + SpendBundle(coinSpends: [toP2ConditionsSpend]); + final intermediaryCoin = toP2ConditionsSpendBundle.additions.single; + // print('intermediary coin amount: '); + // print(intermediaryCoin.amount); + final innerInnerSolution = Program.list([ + Program.list( + [ + CreateCoinCondition( + newWaitingRoomInnerPuzzle.hash(), + intermediaryCoin.amount, + memos: [receiverPuzzlehash], + ).toProgram(), + CreateCoinCondition( + Puzzlehash(launcherId), + 2, + memos: [receiverPuzzlehash], + ).toProgram(), + ], + ) + ]); + + // print( + // returnConditionsProgram + // .run( + // innerInnerSolution, + // ) + // .program, + // ); + + final innerP2Solution = Program.list([ + LineageProof( + parentCoinInfo: plotNft.singletonCoin.parentCoinInfo, + innerPuzzlehash: currentInnerPuzzle.hash(), + amount: intermediaryCoin.amount, + ).toProgram(), + Program.fromInt(currentSingleton.amount), + innerInnerSolution, + ]); + // final p2FullPuzzle = + // SingletonService.puzzleForSingleton(launcherId, singletonOutputInnerPuzzleProgram); + // print('expected full puzzle hash: ${p2FullPuzzle.hash()}'); + // print('expected inner puzzle hash: ${returnConditionsProgram.hash()}'); + final p2SpendBundle = SpendBundle( + coinSpends: [ + CoinSpend( + coin: intermediaryCoin, + puzzleReveal: SingletonService.puzzleForSingleton( + launcherId, + singletonOutputInnerPuzzleProgram, + ), + solution: innerP2Solution, + ) + ], + ); + + final ownerPublicKey = currentState.ownerPublicKey; + final singletonWalletVector = + keychain.getSingletonWalletVector(ownerPublicKey); + final privateKey = singletonWalletVector!.singletonOwnerPrivateKey; + + final signedSpendBundle = toP2ConditionsSpendBundle.signPerCoinSpend( + (coinSpend) => standardWalletService.makeSignature( + privateKey, + coinSpend, + useSyntheticOffset: false, + ), + ); + + final standardSupportsSpendBundle = makeStandardTransferSupportSpendBundle( + keychain: keychain, + coins: coinsForTreasureMapCoin, + changePuzzlehash: changePuzzleHash, + ); + + final transferSpendBundle = + signedSpendBundle + p2SpendBundle + standardSupportsSpendBundle; + + if (fee > 0) { + final feeSpendBundle = standardWalletService.createSpendBundle( + fee: fee, + payments: [], + coinsInput: coinsForFee, + keychain: keychain, + changePuzzlehash: changePuzzleHash, + ); + return transferSpendBundle + feeSpendBundle; + } + + return transferSpendBundle; + } + + SpendBundle makeStandardTransferSupportSpendBundle({ + required WalletKeychain keychain, + Puzzlehash? changePuzzlehash, + required List coins, + }) { + final changeAmount = coins.totalValue - 2; + if (changeAmount < 0) { + throw Exception( + 'not enough coin value to cover transfer support standard spend bundle', + ); + } + if (changeAmount > 0 && changePuzzlehash == null) { + throw Exception( + 'change puzzle hash is required when there are left over coins', + ); + } + return standardWalletService.createSpendBundle( + payments: [ + if (changeAmount > 0) Payment(changeAmount, changePuzzlehash!) + ], + coinsInput: coins, + keychain: keychain, + allowLeftOver: true, + changePuzzlehash: changePuzzlehash, + ); + } + Program poolStateToInnerPuzzle({ required PoolState poolState, required Bytes launcherId, @@ -143,7 +504,8 @@ class PlotNftWalletService extends BaseWalletService { required int delayTime, required Puzzlehash delayPuzzlehash, }) { - final p2SingletonPuzzlehash = launcherIdToP2Puzzlehash(launcherId, delayTime, delayPuzzlehash); + final p2SingletonPuzzlehash = + launcherIdToP2Puzzlehash(launcherId, delayTime, delayPuzzlehash); return poolWaitingRoomInnerpuzProgram.curry([ Program.fromAtom(targetPuzzlehash), Program.fromAtom(p2SingletonPuzzlehash), @@ -161,7 +523,8 @@ class PlotNftWalletService extends BaseWalletService { required int delayTime, required Puzzlehash delayPuzzlehash, }) { - final p2SingletonPuzzlehash = launcherIdToP2Puzzlehash(launcherId, delayTime, delayPuzzlehash); + final p2SingletonPuzzlehash = + launcherIdToP2Puzzlehash(launcherId, delayTime, delayPuzzlehash); return poolMemberInnerpuzProgram.curry([ Program.fromAtom(targetPuzzlehash), Program.fromAtom(p2SingletonPuzzlehash), @@ -172,7 +535,8 @@ class PlotNftWalletService extends BaseWalletService { } Bytes get poolRewardPrefix => - Bytes.fromHex(blockchainNetwork.aggSigMeExtraData).sublist(0, 16) + Bytes(List.filled(16, 0)); + Bytes.fromHex(blockchainNetwork.aggSigMeExtraData).sublist(0, 16) + + Bytes(List.filled(16, 0)); static Puzzlehash launcherIdToP2Puzzlehash( Bytes launcherId, @@ -214,7 +578,8 @@ class PlotNftWalletService extends BaseWalletService { delayTime: delayTime, ); - final fullPuzzle = SingletonService.puzzleForSingleton(launcherId, innerPuzzle); + final fullPuzzle = + SingletonService.puzzleForSingleton(launcherId, innerPuzzle); if (fullPuzzle.hash() != singletonPuzzlehash) { throw InvalidPoolSingletonException(); @@ -238,45 +603,49 @@ class PlotNftWalletService extends BaseWalletService { } static PoolState? coinSpendToPoolState(CoinSpend coinSpend) { - final fullSolution = coinSpend.solution; - - // check for launcher spend - if (coinSpend.coin.puzzlehash == singletonLauncherProgram.hash()) { - try { - final extraDataProgram = fullSolution.rest().rest().first(); - return PoolState.fromExtraDataProgram(extraDataProgram); - } catch (e) { - return null; - } - } - final innerSolution = fullSolution.rest().rest().first(); - final numberOfArguments = innerSolution.toList().length; - - switch (numberOfArguments) { - case 2: - // pool member - if (innerSolution.rest().first().toInt() != 0) { - return null; - } - - final extraDataProgram = innerSolution.first(); - if (extraDataProgram.isAtom) { - // absorbing + try { + final fullSolution = coinSpend.solution; + + // check for launcher spend + if (coinSpend.coin.puzzlehash == singletonLauncherProgram.hash()) { + try { + final extraDataProgram = fullSolution.rest().rest().first(); + return PoolState.fromExtraDataProgram(extraDataProgram); + } catch (e) { return null; } - - return PoolState.fromExtraDataProgram(extraDataProgram); - - case 3: - // pool waiting room - if (innerSolution.first().toInt() == 0) { - return null; - } - - final extraDataProgram = innerSolution.rest().first(); - return PoolState.fromExtraDataProgram(extraDataProgram); - default: - throw Exception('unexpected number of program arguments'); + } + final innerSolution = fullSolution.rest().rest().first(); + final numberOfArguments = innerSolution.toList().length; + + switch (numberOfArguments) { + case 2: + // pool member + if (innerSolution.rest().first().toInt() != 0) { + return null; + } + + final extraDataProgram = innerSolution.first(); + if (extraDataProgram.isAtom) { + // absorbing + return null; + } + + return PoolState.fromExtraDataProgram(extraDataProgram); + + case 3: + // pool waiting room + if (innerSolution.first().toInt() == 0) { + return null; + } + + final extraDataProgram = innerSolution.rest().first(); + return PoolState.fromExtraDataProgram(extraDataProgram); + default: + throw Exception('unexpected number of program arguments'); + } + } on Exception { + return null; } } } diff --git a/lib/src/singleton/puzzles/singleton_output_inner_puzzle/singleton_output_inner_puzzle.clsp b/lib/src/singleton/puzzles/singleton_output_inner_puzzle/singleton_output_inner_puzzle.clsp new file mode 100644 index 00000000..bf5d142f --- /dev/null +++ b/lib/src/singleton/puzzles/singleton_output_inner_puzzle/singleton_output_inner_puzzle.clsp @@ -0,0 +1,3 @@ +(mod (Truths conditions) + conditions +) diff --git a/lib/src/singleton/puzzles/singleton_output_inner_puzzle/singleton_output_inner_puzzle.clsp.hex b/lib/src/singleton/puzzles/singleton_output_inner_puzzle/singleton_output_inner_puzzle.clsp.hex new file mode 100644 index 00000000..eeee65ec --- /dev/null +++ b/lib/src/singleton/puzzles/singleton_output_inner_puzzle/singleton_output_inner_puzzle.clsp.hex @@ -0,0 +1 @@ +05 diff --git a/lib/src/singleton/puzzles/singleton_output_inner_puzzle/singleton_output_inner_puzzle.clvm.hex.dart b/lib/src/singleton/puzzles/singleton_output_inner_puzzle/singleton_output_inner_puzzle.clvm.hex.dart new file mode 100644 index 00000000..c5f38334 --- /dev/null +++ b/lib/src/singleton/puzzles/singleton_output_inner_puzzle/singleton_output_inner_puzzle.clvm.hex.dart @@ -0,0 +1,3 @@ +import 'package:chia_crypto_utils/chia_crypto_utils.dart'; + +final singletonOutputInnerPuzzleProgram = Program.deserializeHex('05'); diff --git a/lib/src/singleton/puzzles/singleton_top_layer/singleton_top_layer_debugging.clsp b/lib/src/singleton/puzzles/singleton_top_layer/singleton_top_layer_debugging.clsp new file mode 100644 index 00000000..19204e8e --- /dev/null +++ b/lib/src/singleton/puzzles/singleton_top_layer/singleton_top_layer_debugging.clsp @@ -0,0 +1,177 @@ +(mod (SINGLETON_STRUCT INNER_PUZZLE lineage_proof my_amount inner_solution) + +;; SINGLETON_STRUCT = (MOD_HASH . (LAUNCHER_ID . LAUNCHER_PUZZLE_HASH)) + +; SINGLETON_STRUCT, INNER_PUZZLE are curried in by the wallet + +; EXAMPLE SOLUTION '(0xfadeddab 0xdeadbeef 1 (0xdeadbeef 200) 50 ((51 0xfadeddab 100) (60 "trash") (51 deadbeef 0)))' + + +; This puzzle is a wrapper around an inner smart puzzle which guarantees uniqueness. +; It takes its singleton identity from a coin with a launcher puzzle which guarantees that it is unique. + + (include condition_codes.clvm) + (include curry-and-treehash.clinc) + (include singleton_truths.clib) + + ; takes a lisp tree and returns the hash of it + (defun sha256tree1 (TREE) + (if (l TREE) + (sha256 2 (sha256tree1 (f TREE)) (sha256tree1 (r TREE))) + (sha256 1 TREE) + ) + ) + + ; "assert" is a macro that wraps repeated instances of "if" + ; usage: (assert A0 A1 ... An R) + ; all of A0, A1, ... An must evaluate to non-null, or an exception is raised + ; return the value of R (if we get that far) + + (defmacro assert items + (if (r items) + (list if (f items) (c assert (r items)) (q . (x))) + (f items) + ) + ) + + (defun-inline mod_hash_for_singleton_struct (SINGLETON_STRUCT) (f SINGLETON_STRUCT)) + (defun-inline launcher_id_for_singleton_struct (SINGLETON_STRUCT) (f (r SINGLETON_STRUCT))) + (defun-inline launcher_puzzle_hash_for_singleton_struct (SINGLETON_STRUCT) (r (r SINGLETON_STRUCT))) + + ;; return the full puzzlehash for a singleton with the innerpuzzle curried in + ; puzzle-hash-of-curried-function is imported from curry-and-treehash.clinc + (defun-inline calculate_full_puzzle_hash (SINGLETON_STRUCT inner_puzzle_hash) + (puzzle-hash-of-curried-function (mod_hash_for_singleton_struct SINGLETON_STRUCT) + inner_puzzle_hash + (sha256tree1 SINGLETON_STRUCT) + ) + ) + + ; assembles information from the solution to create our own full ID including asserting our parent is a singleton + (defun create_my_ID (SINGLETON_STRUCT full_puzzle_hash parent_parent parent_inner_puzzle_hash parent_amount my_amount) + (sha256 (sha256 parent_parent (calculate_full_puzzle_hash SINGLETON_STRUCT parent_inner_puzzle_hash) parent_amount) + full_puzzle_hash + my_amount) + ) + + ;; take a boolean and a non-empty list of conditions + ;; strip off the first condition if a boolean is set + ;; this is used to remove `(CREATE_COIN xxx -113)` + ;; pretty sneaky, eh? + (defun strip_first_condition_if (boolean condition_list) + (if boolean + (r condition_list) + condition_list + ) + ) + + (defun-inline morph_condition (condition SINGLETON_STRUCT) + (list (f condition) (calculate_full_puzzle_hash SINGLETON_STRUCT (f (r condition))) (f (r (r condition)))) + ) + + ;; return the value of the coin created if this is a `CREATE_COIN` condition, or 0 otherwise + (defun-inline created_coin_value_or_0 (condition) + (if (= (f condition) CREATE_COIN) + (f (r (r condition))) + 0 + ) + ) + + ;; Returns a (bool . bool) + (defun odd_cons_m113 (output_amount) + (c + (= (logand output_amount 1) 1) ;; is it odd? + (= output_amount -113) ;; is it the escape value? + ) + ) + + ; Assert exactly one output with odd value exists - ignore it if value is -113 + + ;; this function iterates over the output conditions from the inner puzzle & solution + ;; and both checks that exactly one unique singleton child is created (with odd valued output), + ;; and wraps the inner puzzle with this same singleton wrapper puzzle + ;; + ;; The special case where the output value is -113 means a child singleton is intentionally + ;; *NOT* being created, thus forever ending this singleton's existence + + (defun check_and_morph_conditions_for_singleton (SINGLETON_STRUCT conditions has_odd_output_been_found) + (if conditions + (morph_next_condition SINGLETON_STRUCT conditions has_odd_output_been_found (odd_cons_m113 (created_coin_value_or_0 (f conditions)))) + (if has_odd_output_been_found + 0 + (x) ;; no odd output found + ) + ) + ) + + ;; a continuation of `check_and_morph_conditions_for_singleton` with booleans `is_output_odd` and `is_output_m113` + ;; precalculated + (defun morph_next_condition (SINGLETON_STRUCT conditions has_odd_output_been_found (is_output_odd . is_output_m113)) + (assert + (not (all is_output_odd has_odd_output_been_found)) + (strip_first_condition_if + is_output_m113 + (c (if is_output_odd + (morph_condition (f conditions) SINGLETON_STRUCT) + (f conditions) + ) + (check_and_morph_conditions_for_singleton SINGLETON_STRUCT (r conditions) (any is_output_odd has_odd_output_been_found)) + ) + ) + ) + ) + + ; this final stager asserts our ID + ; it also runs the innerpuz with the innersolution with the "truths" added + ; it then passes that output conditions from the innerpuz to the morph conditions function + (defun stager_three (SINGLETON_STRUCT lineage_proof my_id full_puzhash innerpuzhash my_amount INNER_PUZZLE inner_solution) + (c (list ASSERT_MY_COIN_ID my_id) (check_and_morph_conditions_for_singleton SINGLETON_STRUCT (a INNER_PUZZLE (c (truth_data_to_truth_struct my_id full_puzhash innerpuzhash my_amount lineage_proof SINGLETON_STRUCT) inner_solution)) 0)) + ) + + ; this checks whether we are an eve spend or not and calculates our full coin ID appropriately and passes it on to the final stager + ; if we are the eve spend it also adds the additional checks that our parent's puzzle is the standard launcher format and that out parent ID is the same as our singleton ID + + (defun stager_two (SINGLETON_STRUCT lineage_proof full_puzhash innerpuzhash my_amount INNER_PUZZLE inner_solution) + (stager_three + SINGLETON_STRUCT + lineage_proof + (if (is_not_eve_proof lineage_proof) + (create_my_ID + SINGLETON_STRUCT + full_puzhash + (parent_info_for_lineage_proof lineage_proof) + (puzzle_hash_for_lineage_proof lineage_proof) + (amount_for_lineage_proof lineage_proof) + my_amount + ) + (if (= + (launcher_id_for_singleton_struct SINGLETON_STRUCT) + (sha256 (parent_info_for_eve_proof lineage_proof) (launcher_puzzle_hash_for_singleton_struct SINGLETON_STRUCT) (amount_for_eve_proof lineage_proof)) + ) + (sha256 (launcher_id_for_singleton_struct SINGLETON_STRUCT) full_puzhash my_amount) + (x) + ) + ) + full_puzhash + innerpuzhash + my_amount + INNER_PUZZLE + inner_solution + ) + ) + + ; this calculates our current full puzzle hash and passes it to stager two + (defun stager_one (SINGLETON_STRUCT lineage_proof my_innerpuzhash my_amount INNER_PUZZLE inner_solution) + (stager_two SINGLETON_STRUCT lineage_proof (calculate_full_puzzle_hash SINGLETON_STRUCT my_innerpuzhash) my_innerpuzhash my_amount INNER_PUZZLE inner_solution) + ) + + + ; main + + ; if our value is not an odd amount then we are invalid + ; this calculates my_innerpuzhash and passes all values to stager_one + (if (logand my_amount 1) + (stager_one SINGLETON_STRUCT lineage_proof (sha256tree1 INNER_PUZZLE) my_amount INNER_PUZZLE inner_solution) + (x) + ) +) diff --git a/lib/src/singleton/puzzles/singleton_top_layer/singleton_top_layer_debugging.clsp.hex b/lib/src/singleton/puzzles/singleton_top_layer/singleton_top_layer_debugging.clsp.hex new file mode 100644 index 00000000..8e72c253 --- /dev/null +++ b/lib/src/singleton/puzzles/singleton_top_layer/singleton_top_layer_debugging.clsp.hex @@ -0,0 +1 @@ +ff02ffff01ff02ffff03ffff18ff2fffff010180ffff01ff02ff36ffff04ff02ffff04ff05ffff04ff17ffff04ffff02ff26ffff04ff02ffff04ff0bff80808080ffff04ff2fffff04ff0bffff04ff5fff808080808080808080ffff01ff088080ff0180ffff04ffff01ffffffff4602ff3304ffff0101ff02ffff02ffff03ff05ffff01ff02ff5cffff04ff02ffff04ff0dffff04ffff0bff2cffff0bff24ff3880ffff0bff2cffff0bff2cffff0bff24ff3480ff0980ffff0bff2cff0bffff0bff24ff8080808080ff8080808080ffff010b80ff0180ff02ffff03ff0bffff01ff02ff32ffff04ff02ffff04ff05ffff04ff0bffff04ff17ffff04ffff02ff2affff04ff02ffff04ffff02ffff03ffff09ff23ff2880ffff0181b3ff8080ff0180ff80808080ff80808080808080ffff01ff02ffff03ff17ff80ffff01ff088080ff018080ff0180ffffffff0bffff0bff17ffff02ff3affff04ff02ffff04ff09ffff04ff2fffff04ffff02ff26ffff04ff02ffff04ff05ff80808080ff808080808080ff5f80ff0bff81bf80ff02ffff03ffff20ffff22ff4fff178080ffff01ff02ff7effff04ff02ffff04ff6fffff04ffff04ffff02ffff03ff4fffff01ff04ff23ffff04ffff02ff3affff04ff02ffff04ff09ffff04ff53ffff04ffff02ff26ffff04ff02ffff04ff05ff80808080ff808080808080ffff04ff81b3ff80808080ffff011380ff0180ffff02ff7cffff04ff02ffff04ff05ffff04ff1bffff04ffff21ff4fff1780ff80808080808080ff8080808080ffff01ff088080ff0180ffff04ffff09ffff18ff05ffff010180ffff010180ffff09ff05ffff01818f8080ff0bff2cffff0bff24ff3080ffff0bff2cffff0bff2cffff0bff24ff3480ff0580ffff0bff2cffff02ff5cffff04ff02ffff04ff07ffff04ffff0bff24ff2480ff8080808080ffff0bff24ff8080808080ffffff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff26ffff04ff02ffff04ff09ff80808080ffff02ff26ffff04ff02ffff04ff0dff8080808080ffff01ff0bffff0101ff058080ff0180ff02ff5effff04ff02ffff04ff05ffff04ff0bffff04ffff02ff3affff04ff02ffff04ff09ffff04ff17ffff04ffff02ff26ffff04ff02ffff04ff05ff80808080ff808080808080ffff04ff17ffff04ff2fffff04ff5fffff04ff81bfff80808080808080808080ffff04ffff04ff20ffff04ff17ff808080ffff02ff7cffff04ff02ffff04ff05ffff04ffff02ff82017fffff04ffff04ffff04ff17ff2f80ffff04ffff04ff5fff81bf80ffff04ff0bff05808080ff8202ff8080ffff01ff80808080808080ffff02ff2effff04ff02ffff04ff05ffff04ff0bffff04ffff02ffff03ff3bffff01ff02ff22ffff04ff02ffff04ffff08ffff02ff05ffff04ff02ffff04ff17ffff04ff13ffff04ff2bffff04ff5bffff04ff5fff808080808080808080ffff04ff05ffff04ff17ffff04ff13ffff04ff2bffff04ff5bffff04ff5fff80808080808080808080ffff01ff02ffff03ffff09ff15ffff0bff13ff1dff2b8080ffff01ff0bff15ff17ff5f80ffff01ff088080ff018080ff0180ffff04ff17ffff04ff2fffff04ff5fffff04ff81bfffff04ff82017fff8080808080808080808080ff02ffff03ff05ffff011bffff010b80ff0180ff018080 diff --git a/lib/src/singleton/puzzles/singleton_top_layer/singleton_top_layer_debugging.clvm.hex.dart b/lib/src/singleton/puzzles/singleton_top_layer/singleton_top_layer_debugging.clvm.hex.dart new file mode 100644 index 00000000..2a6810cc --- /dev/null +++ b/lib/src/singleton/puzzles/singleton_top_layer/singleton_top_layer_debugging.clvm.hex.dart @@ -0,0 +1,7 @@ +// ignore_for_file: lines_longer_than_80_chars + +import 'package:chia_crypto_utils/src/clvm/program.dart'; + +final singletonTopLayerDebuggingProgram = Program.deserializeHex( + 'ff02ffff01ff02ffff03ffff18ff2fffff010180ffff01ff02ff36ffff04ff02ffff04ff05ffff04ff17ffff04ffff02ff26ffff04ff02ffff04ff0bff80808080ffff04ff2fffff04ff0bffff04ff5fff808080808080808080ffff01ff088080ff0180ffff04ffff01ffffffff4602ff3304ffff0101ff02ffff02ffff03ff05ffff01ff02ff5cffff04ff02ffff04ff0dffff04ffff0bff2cffff0bff24ff3880ffff0bff2cffff0bff2cffff0bff24ff3480ff0980ffff0bff2cff0bffff0bff24ff8080808080ff8080808080ffff010b80ff0180ff02ffff03ff0bffff01ff02ff32ffff04ff02ffff04ff05ffff04ff0bffff04ff17ffff04ffff02ff2affff04ff02ffff04ffff02ffff03ffff09ff23ff2880ffff0181b3ff8080ff0180ff80808080ff80808080808080ffff01ff02ffff03ff17ff80ffff01ff088080ff018080ff0180ffffffff0bffff0bff17ffff02ff3affff04ff02ffff04ff09ffff04ff2fffff04ffff02ff26ffff04ff02ffff04ff05ff80808080ff808080808080ff5f80ff0bff81bf80ff02ffff03ffff20ffff22ff4fff178080ffff01ff02ff7effff04ff02ffff04ff6fffff04ffff04ffff02ffff03ff4fffff01ff04ff23ffff04ffff02ff3affff04ff02ffff04ff09ffff04ff53ffff04ffff02ff26ffff04ff02ffff04ff05ff80808080ff808080808080ffff04ff81b3ff80808080ffff011380ff0180ffff02ff7cffff04ff02ffff04ff05ffff04ff1bffff04ffff21ff4fff1780ff80808080808080ff8080808080ffff01ff088080ff0180ffff04ffff09ffff18ff05ffff010180ffff010180ffff09ff05ffff01818f8080ff0bff2cffff0bff24ff3080ffff0bff2cffff0bff2cffff0bff24ff3480ff0580ffff0bff2cffff02ff5cffff04ff02ffff04ff07ffff04ffff0bff24ff2480ff8080808080ffff0bff24ff8080808080ffffff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff26ffff04ff02ffff04ff09ff80808080ffff02ff26ffff04ff02ffff04ff0dff8080808080ffff01ff0bffff0101ff058080ff0180ff02ff5effff04ff02ffff04ff05ffff04ff0bffff04ffff02ff3affff04ff02ffff04ff09ffff04ff17ffff04ffff02ff26ffff04ff02ffff04ff05ff80808080ff808080808080ffff04ff17ffff04ff2fffff04ff5fffff04ff81bfff80808080808080808080ffff04ffff04ff20ffff04ff17ff808080ffff02ff7cffff04ff02ffff04ff05ffff04ffff02ff82017fffff04ffff04ffff04ff17ff2f80ffff04ffff04ff5fff81bf80ffff04ff0bff05808080ff8202ff8080ffff01ff80808080808080ffff02ff2effff04ff02ffff04ff05ffff04ff0bffff04ffff02ffff03ff3bffff01ff02ff22ffff04ff02ffff04ffff08ffff02ff05ffff04ff02ffff04ff17ffff04ff13ffff04ff2bffff04ff5bffff04ff5fff808080808080808080ffff04ff05ffff04ff17ffff04ff13ffff04ff2bffff04ff5bffff04ff5fff80808080808080808080ffff01ff02ffff03ffff09ff15ffff0bff13ff1dff2b8080ffff01ff0bff15ff17ff5f80ffff01ff088080ff018080ff0180ffff04ff17ffff04ff2fffff04ff5fffff04ff81bfffff04ff82017fff8080808080808080808080ff02ffff03ff05ffff011bffff010b80ff0180ff018080', +); diff --git a/lib/src/singleton/service/singleton_service.dart b/lib/src/singleton/service/singleton_service.dart index 740ed9ad..16fbe15f 100644 --- a/lib/src/singleton/service/singleton_service.dart +++ b/lib/src/singleton/service/singleton_service.dart @@ -17,6 +17,7 @@ class SingletonService extends BaseWalletService { ), innerPuzzle, ]); + static Program makeSingletonStructureProgram(Bytes coinId) => Program.cons( Program.fromAtom(singletonTopLayerV1Program.hash()), Program.cons( @@ -65,7 +66,9 @@ class SingletonService extends BaseWalletService { ]); } - static CoinPrototype getMostRecentSingletonCoinFromCoinSpend(CoinSpend coinSpend) { + static CoinPrototype getMostRecentSingletonCoinFromCoinSpend( + CoinSpend coinSpend, + ) { final additions = coinSpend.additions; // cribbed from https://github.com/Chia-Network/chia-blockchain/blob/4230af1a59768f6a4f9578408f810d7d2114c343/chia/pools/pool_puzzles.py#L284 return additions.singleWhere((coin) => coin.amount.isOdd); diff --git a/lib/src/standard/service/wallet.dart b/lib/src/standard/service/wallet.dart index 9e05ba95..59174717 100644 --- a/lib/src/standard/service/wallet.dart +++ b/lib/src/standard/service/wallet.dart @@ -17,8 +17,10 @@ class StandardWalletService extends BaseWalletService { int fee = 0, int surplus = 0, Bytes? originId, + bool allowLeftOver = false, List coinAnnouncementsToAssert = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], List additionalConditions = const [], List coinIdsToAssert = const [], void Function(Bytes message)? useCoinMessage, @@ -52,7 +54,8 @@ class StandardWalletService extends BaseWalletService { int surplus = 0, Bytes? originId, List coinAnnouncementsToAssert = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], List additionalConditions = const [], List coinIdsToAssert = const [], void Function(Bytes message)? useCoinMessage, @@ -83,7 +86,8 @@ class StandardWalletService extends BaseWalletService { required WalletKeychain keychain, required Puzzlehash? changePuzzlehash, List coinAnnouncementsToAsset = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], List additionalConditions = const [], }) { assert( @@ -118,7 +122,8 @@ class StandardWalletService extends BaseWalletService { required WalletKeychain keychain, required Puzzlehash? changePuzzlehash, List coinAnnouncementsToAsset = const [], - List puzzleAnnouncementsToAssert = const [], + List puzzleAnnouncementsToAssert = + const [], List additionalConditions = const [], }) { assert( @@ -156,12 +161,15 @@ class StandardWalletService extends BaseWalletService { final coinsBeingSpent = []; Bytes? originId; for (final spend in spendBundle.coinSpends) { - final outputConditions = spend.puzzleReveal.run(spend.solution).program.toList(); + final outputConditions = + spend.puzzleReveal.run(spend.solution).program.toList(); // look for assert coin announcement condition - final assertCoinAnnouncementPrograms = - outputConditions.where(AssertCoinAnnouncementCondition.isThisCondition).toList(); - if (assertCoinAnnouncementPrograms.length == 1 && actualAssertCoinAnnouncementId == null) { + final assertCoinAnnouncementPrograms = outputConditions + .where(AssertCoinAnnouncementCondition.isThisCondition) + .toList(); + if (assertCoinAnnouncementPrograms.length == 1 && + actualAssertCoinAnnouncementId == null) { actualAssertCoinAnnouncementId = AssertCoinAnnouncementCondition.getAnnouncementIdFromProgram( assertCoinAnnouncementPrograms[0], diff --git a/lib/src/utils/bech32.dart b/lib/src/utils/bech32.dart index 69343125..30a4d821 100644 --- a/lib/src/utils/bech32.dart +++ b/lib/src/utils/bech32.dart @@ -42,7 +42,12 @@ List convertBits(List data, int from, int to, {required bool pad}) { } // conversion to arbitrarily long bit length -List convertBitsBigInt(List data, int from, int to, {required bool pad}) { +List convertBitsBigInt( + List data, + int from, + int to, { + required bool pad, +}) { var acc = BigInt.zero; var bits = 0; final result = []; diff --git a/lib/src/utils/compression.dart b/lib/src/utils/compression.dart index 3e4576d3..ad115802 100644 --- a/lib/src/utils/compression.dart +++ b/lib/src/utils/compression.dart @@ -59,7 +59,8 @@ Bytes compressObjectWithPuzzlesOptimized(Bytes objectBytes) { for (var version = 0; version < zDict.length; version++) { final compressedBytes = compressObjectWithPuzzles(objectBytes, version); - if (smallestCompression == null || compressedBytes.length < smallestCompression.length) { + if (smallestCompression == null || + compressedBytes.length < smallestCompression.length) { smallestCompression = compressedBytes; } } diff --git a/lib/src/utils/curry_and_tree_hash.dart b/lib/src/utils/curry_and_tree_hash.dart index 903320cf..2cd021ad 100644 --- a/lib/src/utils/curry_and_tree_hash.dart +++ b/lib/src/utils/curry_and_tree_hash.dart @@ -19,7 +19,8 @@ Puzzlehash shatreePair(Bytes leftHash, Bytes rightHash) { } Puzzlehash curryAndTreeHash(Program mod, List hashedArguments) { - final quotedModHash = Program.cons(Program.fromBigInt(keywords['q']!), mod).hash(); + final quotedModHash = + Program.cons(Program.fromBigInt(keywords['q']!), mod).hash(); final curedValues = curriedValuesTreeHash(hashedArguments); return shatreePair( A_KW_TREEHASH, diff --git a/lib/src/utils/exceptions/insufficient_balance_exception.dart b/lib/src/utils/exceptions/insufficient_balance_exception.dart index c4e37b85..fef0afb6 100644 --- a/lib/src/utils/exceptions/insufficient_balance_exception.dart +++ b/lib/src/utils/exceptions/insufficient_balance_exception.dart @@ -10,7 +10,8 @@ class InsufficientBalanceException implements Exception { final int currentBalance; } -class InsufficientStandardBalanceException extends InsufficientBalanceException { +class InsufficientStandardBalanceException + extends InsufficientBalanceException { InsufficientStandardBalanceException({ required super.requiredBalance, required super.currentBalance, @@ -36,7 +37,8 @@ class InsufficientCatBalanceException extends InsufficientBalanceException { } class InsufficientNftBalanceException extends InsufficientBalanceException { - InsufficientNftBalanceException(this.launcherId) : super(currentBalance: 0, requiredBalance: 1); + InsufficientNftBalanceException(this.launcherId) + : super(currentBalance: 0, requiredBalance: 1); final Bytes launcherId; @override diff --git a/lib/src/utils/key_derivation.dart b/lib/src/utils/key_derivation.dart index 02a6c077..793d989b 100644 --- a/lib/src/utils/key_derivation.dart +++ b/lib/src/utils/key_derivation.dart @@ -117,7 +117,8 @@ Future getPuzzleForPkAsync(JacobianPoint publicKey) { return spawnAndWaitForIsolate( taskArgument: publicKey, isolateTask: _getPuzzleFromPkTask, - handleTaskCompletion: (json) => Program.deserializeHex(json['puzzle'] as String), + handleTaskCompletion: (json) => + Program.deserializeHex(json['puzzle'] as String), ); } @@ -125,7 +126,10 @@ Map _getPuzzleFromPkTask(JacobianPoint publicKey) { return {'puzzle': getPuzzleFromPk(publicKey).toHex()}; } -Program getPuzzleFromPkAndHiddenPuzzle(JacobianPoint publicKey, Program hiddenPuzzleProgram) { +Program getPuzzleFromPkAndHiddenPuzzle( + JacobianPoint publicKey, + Program hiddenPuzzleProgram, +) { final syntheticPubKey = calculateSyntheticPublicKeyProgram.run( Program.list( [ @@ -135,13 +139,15 @@ Program getPuzzleFromPkAndHiddenPuzzle(JacobianPoint publicKey, Program hiddenPu ), ); - final curried = p2DelegatedPuzzleOrHiddenPuzzleProgram.curry([syntheticPubKey.program]); + final curried = + p2DelegatedPuzzleOrHiddenPuzzleProgram.curry([syntheticPubKey.program]); return curried; } Program getP2PuzzleFromSyntheticPublicKey(JacobianPoint syntheticPublicKey) { - return p2DelegatedPuzzleOrHiddenPuzzleProgram.curry([syntheticPublicKey.toBytes()]); + return p2DelegatedPuzzleOrHiddenPuzzleProgram + .curry([syntheticPublicKey.toBytes()]); } final groupOrder = BigInt.parse( @@ -149,7 +155,9 @@ final groupOrder = BigInt.parse( ); BigInt calculateSyntheticOffset(JacobianPoint publicKey) { - final blob = sha256.convert(publicKey.toBytes() + defaultHiddenPuzzleProgram.hash()).bytes; + final blob = sha256 + .convert(publicKey.toBytes() + defaultHiddenPuzzleProgram.hash()) + .bytes; final offset = bytesToBigInt(blob, Endian.big, signed: true); @@ -161,7 +169,8 @@ BigInt calculateSyntheticOffsetFromHiddenPuzzle( JacobianPoint publicKey, Program hiddenPuzzleProgram, ) { - final blob = sha256.convert(publicKey.toBytes() + hiddenPuzzleProgram.hash()).bytes; + final blob = + sha256.convert(publicKey.toBytes() + hiddenPuzzleProgram.hash()).bytes; final offset = bytesToBigInt(blob, Endian.big, signed: true); @@ -176,7 +185,8 @@ PrivateKey calculateSyntheticPrivateKey(PrivateKey privateKey) { final syntheticOffset = calculateSyntheticOffset(publicKey); - final syntheticSecretExponent = (secretExponent + syntheticOffset) % groupOrder; + final syntheticSecretExponent = + (secretExponent + syntheticOffset) % groupOrder; final blob = bigIntToBytes(syntheticSecretExponent, 32, Endian.big); final syntheticPrivateKey = PrivateKey.fromBytes(blob); @@ -190,10 +200,13 @@ PrivateKey calculateTotalPrivateKey( PrivateKey firstPrivateKey, PrivateKey secondPrivateKey, ) { - final syntheticOffset = calculateSyntheticOffsetFromHiddenPuzzle(totalPublicKey, hiddenPuzzle); + final syntheticOffset = + calculateSyntheticOffsetFromHiddenPuzzle(totalPublicKey, hiddenPuzzle); - final firstSecret = BigInt.parse(firstPrivateKey.toHex(), radix: 16) % groupOrder; - final secondSecret = BigInt.parse(secondPrivateKey.toHex(), radix: 16) % groupOrder; + final firstSecret = + BigInt.parse(firstPrivateKey.toHex(), radix: 16) % groupOrder; + final secondSecret = + BigInt.parse(secondPrivateKey.toHex(), radix: 16) % groupOrder; final totalSecret = firstSecret + secondSecret + syntheticOffset; diff --git a/lib/src/utils/mixins/summable_mixin.dart b/lib/src/utils/mixins/summable_mixin.dart index 6d4b3dc2..f6d8e272 100644 --- a/lib/src/utils/mixins/summable_mixin.dart +++ b/lib/src/utils/mixins/summable_mixin.dart @@ -3,5 +3,6 @@ abstract class Summable { } extension Sum on Iterable { - int sum() => fold(0, (int previousValue, item) => previousValue + item.amount); + int sum() => + fold(0, (int previousValue, item) => previousValue + item.amount); } diff --git a/lib/src/utils/select_coins_for_amount.dart b/lib/src/utils/select_coins_for_amount.dart index b383bfc4..e52dee0f 100644 --- a/lib/src/utils/select_coins_for_amount.dart +++ b/lib/src/utils/select_coins_for_amount.dart @@ -145,7 +145,9 @@ class ClosestValueCoinSelector implements CoinSelector { int minMojos = 50, required int? maxNumberOfCoins, }) { - final coinsWithDiffs = coins.map((e) => CoinWithDiff(e, (e.amount - amount).abs())).toList() + final coinsWithDiffs = coins + .map((e) => CoinWithDiff(e, (e.amount - amount).abs())) + .toList() ..sort((a, b) => a.diff.compareTo(b.diff)); final selectedCoins = []; @@ -240,7 +242,10 @@ List _selectSortedCoinsForAmount( } if (totalCoinValue < amount) { - throw InsufficientBalanceException(requiredBalance: amount, currentBalance: totalCoinValue); + throw InsufficientBalanceException( + requiredBalance: amount, + currentBalance: totalCoinValue, + ); } return selectedCoins; diff --git a/lib/src/utils/serialization.dart b/lib/src/utils/serialization.dart index 92da34b3..df4fa520 100644 --- a/lib/src/utils/serialization.dart +++ b/lib/src/utils/serialization.dart @@ -18,7 +18,8 @@ Bytes serializeListChia(List items) { Bytes serializeList(List items) { final bytes = items.fold( [], - (List previousValue, dynamic item) => [...previousValue, ...serializeItem(item)], + (List previousValue, dynamic item) => + [...previousValue, ...serializeItem(item)], ); return Bytes(bytes); } diff --git a/lib/src/utils/spawn_and_wait_for_isolate/models/progress_update_message.dart b/lib/src/utils/spawn_and_wait_for_isolate/models/progress_update_message.dart index 0f1ed677..30d75223 100644 --- a/lib/src/utils/spawn_and_wait_for_isolate/models/progress_update_message.dart +++ b/lib/src/utils/spawn_and_wait_for_isolate/models/progress_update_message.dart @@ -2,7 +2,8 @@ import 'package:chia_crypto_utils/src/utils/spawn_and_wait_for_isolate/models/is class ProgressUpdateMessage { ProgressUpdateMessage(this.progress); - ProgressUpdateMessage.fromJson(Map json) : progress = json['progress'] as double; + ProgressUpdateMessage.fromJson(Map json) + : progress = json['progress'] as double; final double progress; diff --git a/lib/src/utils/spawn_and_wait_for_isolate/models/result_message.dart b/lib/src/utils/spawn_and_wait_for_isolate/models/result_message.dart index 2814de05..d9aaf693 100644 --- a/lib/src/utils/spawn_and_wait_for_isolate/models/result_message.dart +++ b/lib/src/utils/spawn_and_wait_for_isolate/models/result_message.dart @@ -3,7 +3,8 @@ import 'package:chia_crypto_utils/src/utils/spawn_and_wait_for_isolate/models/is class ResultMessage { ResultMessage(this.body); - ResultMessage.fromJson(Map json) : body = json['body'] as Map; + ResultMessage.fromJson(Map json) + : body = json['body'] as Map; Map toJson() => { 'type': IsolateMessageType.result.name, diff --git a/lib/src/utils/spawn_and_wait_for_isolate/spawn_and_wait_for_isolate.dart b/lib/src/utils/spawn_and_wait_for_isolate/spawn_and_wait_for_isolate.dart index 382adc51..14e0346e 100644 --- a/lib/src/utils/spawn_and_wait_for_isolate/spawn_and_wait_for_isolate.dart +++ b/lib/src/utils/spawn_and_wait_for_isolate/spawn_and_wait_for_isolate.dart @@ -11,7 +11,8 @@ import 'package:chia_crypto_utils/src/utils/spawn_and_wait_for_isolate/models/re Future spawnAndWaitForIsolate({ required R taskArgument, required FutureOr> Function(R taskArgument) isolateTask, - required FutureOr Function(Map taskResultJson) handleTaskCompletion, + required FutureOr Function(Map taskResultJson) + handleTaskCompletion, }) { FutureOr> task( R taskArgument, @@ -36,8 +37,10 @@ Future spawnAndWaitForIsolateWithProgressUpdates({ required FutureOr> Function( R taskArgument, void Function(double progress) onProgressUpdate, - ) isolateTask, - required FutureOr Function(Map taskResultJson) handleTaskCompletion, + ) + isolateTask, + required FutureOr Function(Map taskResultJson) + handleTaskCompletion, }) async { final receivePort = ReceivePort(); final errorPort = ReceivePort(); @@ -52,7 +55,8 @@ Future spawnAndWaitForIsolateWithProgressUpdates({ switch (messageType) { case IsolateMessageType.progressUpdate: - final progressUpdateMessage = ProgressUpdateMessage.fromJson(messageJson); + final progressUpdateMessage = + ProgressUpdateMessage.fromJson(messageJson); onProgressUpdate(progressUpdateMessage.progress); break; case IsolateMessageType.result: @@ -74,12 +78,16 @@ Future spawnAndWaitForIsolateWithProgressUpdates({ final errors = message as List; errorPort.close(); if (!completer.isCompleted) { - completer.completeError(errors.first as Object, StackTrace.fromString(errors[1].toString())); + completer.completeError( + errors.first as Object, + StackTrace.fromString(errors[1].toString()), + ); } receivePort.close(); }); - final taskArgumentAndSendPort = TaskArgumentAndSendPort(taskArgument, receivePort.sendPort); + final taskArgumentAndSendPort = + TaskArgumentAndSendPort(taskArgument, receivePort.sendPort); await Isolate.spawn( _makeActualTask(isolateTask), @@ -97,17 +105,20 @@ Future spawnAndWaitForIsolateWithProgressUpdates({ // and sendport as a single parameter and uses the sendport to // send the resulting message to the recieve port -Future Function(TaskArgumentAndSendPort taskArgumentAndSendPort) _makeActualTask( +Future Function(TaskArgumentAndSendPort taskArgumentAndSendPort) + _makeActualTask( FutureOr> Function( R taskArgument, void Function(double progress) onProgressUpdate, - ) task, + ) + task, ) { return (TaskArgumentAndSendPort taskArgumentAndSendPort) async { final taskResultJson = await task( taskArgumentAndSendPort.taskArgument, (progress) { - taskArgumentAndSendPort.sendport.send(jsonEncode(ProgressUpdateMessage(progress).toJson())); + taskArgumentAndSendPort.sendport + .send(jsonEncode(ProgressUpdateMessage(progress).toJson())); }, ); taskArgumentAndSendPort.sendport.send( diff --git a/lib/src/utils/to_bytes_mixin.dart b/lib/src/utils/to_bytes_mixin.dart index 9ffe186d..51a5b608 100644 --- a/lib/src/utils/to_bytes_mixin.dart +++ b/lib/src/utils/to_bytes_mixin.dart @@ -31,7 +31,9 @@ extension StringToBytesX on String { Bytes toBytes() => Bytes(utf8.encode(this)); Bytes hexToBytes() { if (startsWith(Bytes.bytesPrefix)) { - return Bytes(const HexDecoder().convert(replaceFirst(Bytes.bytesPrefix, ''))); + return Bytes( + const HexDecoder().convert(replaceFirst(Bytes.bytesPrefix, '')), + ); } return Bytes(const HexDecoder().convert(this)); } diff --git a/pubspec.yaml b/pubspec.yaml index 7bbe74b8..1ef76dba 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -47,6 +47,7 @@ dev_dependencies: lints: ^1.0.0 rps: ^0.6.3 test: ^1.19.3 + test_process: ^2.1.0 very_good_analysis: ^3.1.0 false_secrets: diff --git a/test/api/nft_minting/nft_storage_upload_test.dart b/test/api/nft_minting/nft_storage_upload_test.dart index b1b2df8c..2b86b4e8 100644 --- a/test/api/nft_minting/nft_storage_upload_test.dart +++ b/test/api/nft_minting/nft_storage_upload_test.dart @@ -9,7 +9,8 @@ void main() { 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkaWQ6ZXRocjoweDUyYjUxMDJmOWI5Y2NBMTREMDBjMjNjY2QwOTE2YTBBQTREMGNmMjQiLCJpc3MiOiJuZnQtc3RvcmFnZSIsImlhdCI6MTY4OTAwNTQ0OTg3NCwibmFtZSI6ImJ1bGstbWludGluZy10ZXN0In0.5qdP1qwH4_SOoYCRrIdoXK0RDqzweXanzhxUCP8YH-g', ); - final response = await storage.uploadFile(File('./test/assets/irulast_logo.png')); + final response = + await storage.uploadFile(File('./test/assets/irulast_logo.png')); print(response.link); print(response.toJson()); }); diff --git a/test/bls_test.dart b/test/bls_test.dart index 2242cdea..a40528d9 100644 --- a/test/bls_test.dart +++ b/test/bls_test.dart @@ -29,7 +29,8 @@ class HkdfIn { final String prkExpected; final String okmExpected; int L; - HkdfIn(this.ikm, this.salt, this.info, this.prkExpected, this.okmExpected, this.L); + HkdfIn(this.ikm, this.salt, this.info, this.prkExpected, this.okmExpected, + this.L); } class Eip2333In { @@ -144,8 +145,14 @@ void main() { var child = BasicSchemeMPL.deriveChildSk(master, item.childIndex); expect(master.toBytes().length == 32, isTrue); expect(child.toBytes().length == 32, isTrue); - expect(bytesEqual(master.toBytes(), const HexDecoder().convert(item.masterSk)), isTrue); - expect(bytesEqual(child.toBytes(), const HexDecoder().convert(item.childSk)), isTrue); + expect( + bytesEqual( + master.toBytes(), const HexDecoder().convert(item.masterSk)), + isTrue); + expect( + bytesEqual( + child.toBytes(), const HexDecoder().convert(item.childSk)), + isTrue); }); } }); @@ -161,24 +168,31 @@ void main() { test('Multiplication', () => expect(f == e, isFalse)); var e_sq = e * e as Fq2; var e_sqrt = e_sq.modSqrt(); - test('Square and Root', () => expect(e_sqrt.pow(BigInt.two) == e_sq, isTrue)); + test('Square and Root', + () => expect(e_sqrt.pow(BigInt.two) == e_sq, isTrue)); var a2 = Fq( BigInt.parse('172487123095712930573140951348'), - BigInt.parse('3012492130751239573498573249085723940848571098237509182375'), + BigInt.parse( + '3012492130751239573498573249085723940848571098237509182375'), ); var b2 = Fq(BigInt.parse('172487123095712930573140951348'), BigInt.parse('3432984572394572309458723045723849')); var c2 = Fq2(BigInt.parse('172487123095712930573140951348'), [a2, b2]); test('Inequality', () => expect(b2 == c2, isFalse)); var g = Fq6(seventeen, [c, d, d * d * c]); - var h = Fq6(seventeen, [a + a * c, c * b * a, b * b * d * Fq(seventeen, BigInt.from(21))]); + var h = Fq6(seventeen, + [a + a * c, c * b * a, b * b * d * Fq(seventeen, BigInt.from(21))]); var i = Fq12(seventeen, [g, h]); test('Double Negation', () => expect(~(~i) == i, isTrue)); - test('Inverse Root Identity', () => expect(~i.root * i.root == Fq6.one(seventeen), isTrue)); + test('Inverse Root Identity', + () => expect(~i.root * i.root == Fq6.one(seventeen), isTrue)); var x = Fq12(seventeen, [Fq6.zero(seventeen), i.root]); - test('Inverse Identity', () => expect(~x * x == Fq12.one(seventeen), isTrue)); - var j = Fq6(seventeen, [a + a * c, Fq2.zero(seventeen), Fq2.zero(seventeen)]); - var j2 = Fq6(seventeen, [a + a * c, Fq2.zero(seventeen), Fq2.one(seventeen)]); + test('Inverse Identity', + () => expect(~x * x == Fq12.one(seventeen), isTrue)); + var j = + Fq6(seventeen, [a + a * c, Fq2.zero(seventeen), Fq2.zero(seventeen)]); + var j2 = + Fq6(seventeen, [a + a * c, Fq2.zero(seventeen), Fq2.one(seventeen)]); test('Extension Equaliy', () { expect(j == (a + a * c), isTrue); expect(j2 == (a + a * c), isFalse); @@ -192,7 +206,10 @@ void main() { var c3 = Fq12(defaultEc.q, [b3, b3]); for (var base in [a3, b3, c3]) { for (var expo in range(1, base.extension)) { - expect(base.qiPower(expo.toInt()) == base.pow(defaultEc.q.pow(expo.toInt())), isTrue); + expect( + base.qiPower(expo.toInt()) == + base.pow(defaultEc.q.pow(expo.toInt())), + isTrue); } } }); @@ -211,14 +228,19 @@ void main() { }); var g2 = JacobianPoint.generateG2(); test('Commutative', () { - expect(g2.x * (Fq(q, BigInt.two) * g2.y) == Fq(q, BigInt.two) * (g2.x * g2.y), isTrue); + expect( + g2.x * (Fq(q, BigInt.two) * g2.y) == + Fq(q, BigInt.two) * (g2.x * g2.y), + isTrue); expect(g2.isOnCurve, isTrue); }); var s = g2 + g2; test('Twist', () { expect(s.toAffine().twist().untwist() == s.toAffine(), isTrue); - expect((s.toAffine().twist() * five).untwist() == (s * five).toAffine(), isTrue); - expect(s.toAffine().twist() * five == (s * five).toAffine().twist(), isTrue); + expect((s.toAffine().twist() * five).untwist() == (s * five).toAffine(), + isTrue); + expect( + s.toAffine().twist() * five == (s * five).toAffine().twist(), isTrue); }); test('G2 Multiplication', () { expect(s.isOnCurve, isTrue); @@ -235,7 +257,8 @@ void main() { var g2_j2 = JacobianPoint.generateG2() * BigInt.two; test('Conversions', () { expect(g.toAffine().toJacobian() == g, isTrue); - expect((g_j * BigInt.two).toAffine() == g.toAffine() * BigInt.two, isTrue); + expect( + (g_j * BigInt.two).toAffine() == g.toAffine() * BigInt.two, isTrue); expect((g2_j + g2_j2).toAffine() == g2.toAffine() * three, isTrue); }); }); @@ -268,7 +291,8 @@ void main() { }); test('SWU', () { - var dst_1 = utf8.encode("QUUX-V01-CS02-with-BLS12381G2_XMD:SHA-256_SSWU_RO_"); + var dst_1 = + utf8.encode("QUUX-V01-CS02-with-BLS12381G2_XMD:SHA-256_SSWU_RO_"); var msg_1 = utf8.encode('abcdef0123456789'); var res = g2Map(msg_1, dst_1).toAffine(); expect( @@ -350,7 +374,8 @@ void main() { expect(pair == copy3, isTrue); var sk = BigInt.parse('728934712938472938472398074'); var pk = g1 * sk; - var Hm = y2 * BigInt.from(12371928312) + y2 * BigInt.parse('12903812903891023'); + var Hm = y2 * BigInt.from(12371928312) + + y2 * BigInt.parse('12903812903891023'); var sig = Hm * sk; expect(atePairing(g1, sig) == atePairing(pk, Hm), isTrue); }); @@ -364,7 +389,9 @@ void main() { var sk1 = BasicSchemeMPL.keyGen(seed1); var sk2 = BasicSchemeMPL.keyGen(seed2); test('Private and Public Key', () { - expect(sk1.toHex() == '4a353be3dac091a0a7e640620372f5e1e2e4401717c1e79cac6ffba8f6905604', + expect( + sk1.toHex() == + '4a353be3dac091a0a7e640620372f5e1e2e4401717c1e79cac6ffba8f6905604', isTrue); expect( sk1.getG1().toHex() == @@ -389,7 +416,9 @@ void main() { aggSig1.toHex() == 'aee003c8cdaf3531b6b0ca354031b0819f7586b5846796615aee8108fec75ef838d181f9d244a94d195d7b0231d4afcf06f27f0cc4d3c72162545c240de7d5034a7ef3a2a03c0159de982fbc2e7790aeb455e27beae91d64e077c70b5506dea3', isTrue); - expect(BasicSchemeMPL.aggregateVerify([sk1.getG1(), sk2.getG1()], [msg1, msg2], aggSig1), + expect( + BasicSchemeMPL.aggregateVerify( + [sk1.getG1(), sk2.getG1()], [msg1, msg2], aggSig1), isTrue); }); var msg3 = [1, 2, 3]; @@ -406,7 +435,9 @@ void main() { isTrue); expect( BasicSchemeMPL.aggregateVerify( - [sk1.getG1(), sk1.getG1(), sk2.getG1()], [msg3, msg4, msg5], aggSig2), + [sk1.getG1(), sk1.getG1(), sk2.getG1()], + [msg3, msg4, msg5], + aggSig2), isTrue); }); }); @@ -558,7 +589,8 @@ void main() { var pk = sk.getG1(); var message = [1, 2, 3, 4, 5]; var signature = AugSchemeMPL.sign(sk, message); - test('AugSchemeMPL Verify', () => expect(AugSchemeMPL.verify(pk, message, signature), isTrue)); + test('AugSchemeMPL Verify', + () => expect(AugSchemeMPL.verify(pk, message, signature), isTrue)); var sk_bytes = sk.toBytes(); var pk_bytes = pk.toBytes(); var signature_bytes = signature.toBytes(); @@ -582,8 +614,10 @@ void main() { var agg_sig = AugSchemeMPL.aggregate([sig1, sig2]); test( 'AugSchemeMPL Aggregate Verify 1', - () => - expect(AugSchemeMPL.aggregateVerify([pk1, pk2], [message, message2], agg_sig), isTrue)); + () => expect( + AugSchemeMPL.aggregateVerify( + [pk1, pk2], [message, message2], agg_sig), + isTrue)); var seed3 = [3] + seed.sublist(1); var sk3 = AugSchemeMPL.keyGen(seed3); var pk3 = sk3.getG1(); @@ -611,13 +645,19 @@ void main() { test( 'PopSchemeMPL Fast Aggregate Verify', () => expect( - PopSchemeMPL.fastAggregateVerify([pk1, pk2, pk3], message, pop_sig_agg), isTrue)); + PopSchemeMPL.fastAggregateVerify( + [pk1, pk2, pk3], message, pop_sig_agg), + isTrue)); var pop_agg_pk = pk1 + pk2 + pk3; - test('PopSchemeMPL Verify', - () => expect(PopSchemeMPL.verify(pop_agg_pk, message, pop_sig_agg), isTrue)); + test( + 'PopSchemeMPL Verify', + () => expect( + PopSchemeMPL.verify(pop_agg_pk, message, pop_sig_agg), isTrue)); var pop_agg_sk = PrivateKey.aggregate([sk1, sk2, sk3]); - test('PopSchemeMPL Aggregate Sign', - () => expect(PopSchemeMPL.sign(pop_agg_sk, message) == pop_sig_agg, isTrue)); + test( + 'PopSchemeMPL Aggregate Sign', + () => expect( + PopSchemeMPL.sign(pop_agg_sk, message) == pop_sig_agg, isTrue)); var master_sk = AugSchemeMPL.keyGen(seed); var child = AugSchemeMPL.deriveChildSk(master_sk, 152); AugSchemeMPL.deriveChildSk(child, 952); @@ -626,7 +666,8 @@ void main() { var grandchild_u = AugSchemeMPL.deriveChildSkUnhardened(child_u, 0); var child_u_pk = AugSchemeMPL.deriveChildPkUnhardened(master_pk, 22); var grandchild_u_pk = AugSchemeMPL.deriveChildPkUnhardened(child_u_pk, 0); - test('AugSchemeMPL Child Keys', () => expect(grandchild_u_pk == grandchild_u.getG1(), isTrue)); + test('AugSchemeMPL Child Keys', + () => expect(grandchild_u_pk == grandchild_u.getG1(), isTrue)); }); test('Current', () { diff --git a/test/cat/cat1_wallet_service_test.dart b/test/cat/cat1_wallet_service_test.dart index afc6862e..090ca89e 100644 --- a/test/cat/cat1_wallet_service_test.dart +++ b/test/cat/cat1_wallet_service_test.dart @@ -16,10 +16,12 @@ Future main() async { spentBlockIndex: 0, coinbase: false, timestamp: 274829924, - parentCoinInfo: - Bytes.fromHex('9e79c349dda91dd066d10c71094b3a55fce22ca6eb95b263c8df7f931a307bc8'), - puzzlehash: - Puzzlehash.fromHex('6b7a64b0c59c1b5f1fc037b6765f2f5a727c162a72a6147184fe1c632921db8f'), + parentCoinInfo: Bytes.fromHex( + '9e79c349dda91dd066d10c71094b3a55fce22ca6eb95b263c8df7f931a307bc8', + ), + puzzlehash: Puzzlehash.fromHex( + '6b7a64b0c59c1b5f1fc037b6765f2f5a727c162a72a6147184fe1c632921db8f', + ), amount: 1000, ); const otherCatParentJson = @@ -27,18 +29,24 @@ Future main() async { final otherParentCoinSpend = CoinSpend.fromJson( jsonDecode(otherCatParentJson) as Map, ); - final otherCat1 = CatCoin.fromParentSpend(coin: otherCoin, parentCoinSpend: otherParentCoinSpend); + final otherCat1 = CatCoin.fromParentSpend( + coin: otherCoin, + parentCoinSpend: otherParentCoinSpend, + ); ChiaNetworkContextWrapper().registerNetworkContext(Network.mainnet); final cat1WalletService = Cat1WalletService(); final catWalletService = Cat2WalletService(); - final cat1WalletKeychain = WalletKeychain.fromCoreSecret(TestData.keychainSecret, walletSize: 20) - ..addCat1OuterPuzzleHashesForAssetId(TestData.cat1AssetId); + final cat1WalletKeychain = + WalletKeychain.fromCoreSecret(TestData.keychainSecret, walletSize: 20) + ..addCat1OuterPuzzleHashesForAssetId(TestData.cat1AssetId); - final cat1ChangePuzzlehash = cat1WalletKeychain.unhardenedMap.values.toList()[0].puzzlehash; - final cat1TargetPuzzlehash = cat1WalletKeychain.unhardenedMap.values.toList()[1].puzzlehash; + final cat1ChangePuzzlehash = + cat1WalletKeychain.unhardenedMap.values.toList()[0].puzzlehash; + final cat1TargetPuzzlehash = + cat1WalletKeychain.unhardenedMap.values.toList()[1].puzzlehash; test('produces valid CAT1 spendbundle', () async { final payment = CatPayment(250, cat1TargetPuzzlehash); @@ -48,16 +56,25 @@ Future main() async { changePuzzlehash: cat1ChangePuzzlehash, keychain: cat1WalletKeychain, ); - expect(() => cat1WalletService.validateSpendBundle(spendBundle), returnsNormally); + expect( + () => cat1WalletService.validateSpendBundle(spendBundle), + returnsNormally, + ); }); - test('should not produce CAT1 spendbundle when payment amount exceeds total coin amounts', () { + test( + 'should not produce CAT1 spendbundle when payment amount exceeds total coin amounts', + () { const paymentAmount = 301; final payment = CatPayment(paymentAmount, cat1TargetPuzzlehash); expect( - TestData.cat1Coins.fold(0, (previousValue, catCoin) => previousValue + catCoin.amount), + TestData.cat1Coins.fold( + 0, + (previousValue, catCoin) => previousValue + catCoin.amount, + ), lessThan(paymentAmount), - reason: 'amounts for coin test data in this test must not exceed payment amount', + reason: + 'amounts for coin test data in this test must not exceed payment amount', ); expect( () => cat1WalletService.createSpendBundle( @@ -79,16 +96,24 @@ Future main() async { fee: 1000, standardCoinsForFee: [TestData.standardCoin], ); - expect(() => cat1WalletService.validateSpendBundle(spendBundle), returnsNormally); + expect( + () => cat1WalletService.validateSpendBundle(spendBundle), + returnsNormally, + ); }); - test('produces valid CAT1 spendbundle with fee and multiple payments', () async { + test('produces valid CAT1 spendbundle with fee and multiple payments', + () async { final payment = CatPayment.withStringMemos( 200, cat1TargetPuzzlehash, memos: const ['Chia is really cool'], ); - final payment1 = CatPayment.withIntMemos(100, cat1TargetPuzzlehash, memos: const [1000]); + final payment1 = CatPayment.withIntMemos( + 100, + cat1TargetPuzzlehash, + memos: const [1000], + ); final spendBundle = cat1WalletService.createSpendBundle( payments: [payment, payment1], catCoinsInput: TestData.cat1Coins, @@ -97,17 +122,25 @@ Future main() async { fee: 1000, standardCoinsForFee: [TestData.standardCoin], ); - expect(() => cat1WalletService.validateSpendBundle(spendBundle), returnsNormally); + expect( + () => cat1WalletService.validateSpendBundle(spendBundle), + returnsNormally, + ); }); - test('throws error when creating CAT2 spendbundle with fee and multiple payments with CAT1 coins', + test( + 'throws error when creating CAT2 spendbundle with fee and multiple payments with CAT1 coins', () async { final payment = CatPayment.withStringMemos( 200, cat1TargetPuzzlehash, memos: const ['Chia is really cool'], ); - final payment1 = CatPayment.withIntMemos(100, cat1TargetPuzzlehash, memos: const [1000]); + final payment1 = CatPayment.withIntMemos( + 100, + cat1TargetPuzzlehash, + memos: const [1000], + ); expect( () => catWalletService.createSpendBundle( payments: [payment, payment1], @@ -136,20 +169,27 @@ Future main() async { ); }); - test('should create valid spendbundle without change puzzlehash when there is no change', () { - final totalCoinsValue = - TestData.cat1Coins.fold(0, (int previousValue, coin) => previousValue + coin.amount); + test( + 'should create valid spendbundle without change puzzlehash when there is no change', + () { + final totalCoinsValue = TestData.cat1Coins + .fold(0, (int previousValue, coin) => previousValue + coin.amount); final spendBundle = cat1WalletService.createSpendBundle( payments: [CatPayment(totalCoinsValue, cat1TargetPuzzlehash)], catCoinsInput: TestData.cat1Coins, keychain: cat1WalletKeychain, ); - expect(() => cat1WalletService.validateSpendBundle(spendBundle), returnsNormally); + expect( + () => cat1WalletService.validateSpendBundle(spendBundle), + returnsNormally, + ); }); - test('throws error when creating CAT2 spendbundle without change puzzlehash with CAT1 coins', () { - final totalCoinsValue = - TestData.cat1Coins.fold(0, (int previousValue, coin) => previousValue + coin.amount); + test( + 'throws error when creating CAT2 spendbundle without change puzzlehash with CAT1 coins', + () { + final totalCoinsValue = TestData.cat1Coins + .fold(0, (int previousValue, coin) => previousValue + coin.amount); expect( () => catWalletService.createSpendBundle( payments: [CatPayment(totalCoinsValue, cat1TargetPuzzlehash)], @@ -160,7 +200,8 @@ Future main() async { ); }); - test('CAT1 wallet should throw exception when change puzzlehash is not given and there is change', + test( + 'CAT1 wallet should throw exception when change puzzlehash is not given and there is change', () { expect( () { @@ -174,7 +215,9 @@ Future main() async { ); }); - test('should throw exception when deconstructing a puzzle that is not a CAT1 puzzle', () { + test( + 'should throw exception when deconstructing a puzzle that is not a CAT1 puzzle', + () { expect( () { DeconstructedCatPuzzle( diff --git a/test/cat/cat_solution_parsing_test.dart b/test/cat/cat_solution_parsing_test.dart index 9a3d7307..4ed4e6cc 100644 --- a/test/cat/cat_solution_parsing_test.dart +++ b/test/cat/cat_solution_parsing_test.dart @@ -23,14 +23,17 @@ void main() { expect( parsed.previousCoinId, - Bytes.fromHex('0xee555b0273f7cae7bf7196a4087eb8b484000d8368cc11ce04a6fde8848b3e7a'), + Bytes.fromHex( + '0xee555b0273f7cae7bf7196a4087eb8b484000d8368cc11ce04a6fde8848b3e7a', + ), ); expect( parsed.thisCoinInfo, CoinPrototype( - parentCoinInfo: - Bytes.fromHex('0x1535144d3e1337a60e249eaa88cac595618895cabd1b6c32a4c6a62b895a8415'), + parentCoinInfo: Bytes.fromHex( + '0x1535144d3e1337a60e249eaa88cac595618895cabd1b6c32a4c6a62b895a8415', + ), puzzlehash: Puzzlehash.fromHex( '0x1787ae726f6e5d4a9b128dfe03548b08ab60ec8fba3228fa5d45648585f33484', ), @@ -41,8 +44,9 @@ void main() { expect( parsed.nextCoinProof, CoinPrototype( - parentCoinInfo: - Bytes.fromHex('0x5eea91688d21b0bf943426f989601eb3d1b29f342f5290cd960dcf697a14eb90'), + parentCoinInfo: Bytes.fromHex( + '0x5eea91688d21b0bf943426f989601eb3d1b29f342f5290cd960dcf697a14eb90', + ), puzzlehash: Puzzlehash.fromHex( '0x67a7f82634ec56ba4af0bb4c8bb0c5187f0be77c4d5efcce14b3a9558319f52d', ), diff --git a/test/cat/cat_wallet_service_test.dart b/test/cat/cat_wallet_service_test.dart index 9325b993..2b9626da 100644 --- a/test/cat/cat_wallet_service_test.dart +++ b/test/cat/cat_wallet_service_test.dart @@ -16,10 +16,12 @@ Future main() async { spentBlockIndex: 0, coinbase: false, timestamp: 274829924, - parentCoinInfo: - Bytes.fromHex('9e79c349dda91dd066d10c71094b3a55fce22ca6eb95b263c8df7f931a307bc8'), - puzzlehash: - Puzzlehash.fromHex('6b7a64b0c59c1b5f1fc037b6765f2f5a727c162a72a6147184fe1c632921db8f'), + parentCoinInfo: Bytes.fromHex( + '9e79c349dda91dd066d10c71094b3a55fce22ca6eb95b263c8df7f931a307bc8', + ), + puzzlehash: Puzzlehash.fromHex( + '6b7a64b0c59c1b5f1fc037b6765f2f5a727c162a72a6147184fe1c632921db8f', + ), amount: 1000, ); const otherCatParentJson = @@ -27,18 +29,24 @@ Future main() async { final otherParentCoinSpend = CoinSpend.fromJson( jsonDecode(otherCatParentJson) as Map, ); - final otherCat1 = CatCoin.fromParentSpend(coin: otherCoin, parentCoinSpend: otherParentCoinSpend); + final otherCat1 = CatCoin.fromParentSpend( + coin: otherCoin, + parentCoinSpend: otherParentCoinSpend, + ); ChiaNetworkContextWrapper().registerNetworkContext(Network.mainnet); final catWalletService = Cat2WalletService(); final cat1WalletService = Cat1WalletService(); - final catWalletKeychain = WalletKeychain.fromCoreSecret(TestData.keychainSecret, walletSize: 20) - ..addOuterPuzzleHashesForAssetId(TestData.catAssetId); + final catWalletKeychain = + WalletKeychain.fromCoreSecret(TestData.keychainSecret, walletSize: 20) + ..addOuterPuzzleHashesForAssetId(TestData.catAssetId); - final catChangePuzzlehash = catWalletKeychain.unhardenedMap.values.toList()[0].puzzlehash; - final catTargetPuzzlehash = catWalletKeychain.unhardenedMap.values.toList()[1].puzzlehash; + final catChangePuzzlehash = + catWalletKeychain.unhardenedMap.values.toList()[0].puzzlehash; + final catTargetPuzzlehash = + catWalletKeychain.unhardenedMap.values.toList()[1].puzzlehash; test('produces valid CAT2 spendbundle', () async { final payment = CatPayment(250, catTargetPuzzlehash); @@ -48,16 +56,25 @@ Future main() async { changePuzzlehash: catChangePuzzlehash, keychain: catWalletKeychain, ); - expect(() => catWalletService.validateSpendBundle(spendBundle), returnsNormally); + expect( + () => catWalletService.validateSpendBundle(spendBundle), + returnsNormally, + ); }); - test('should not produce CAT2 spendbundle when payment amount exceeds total coin amounts', () { + test( + 'should not produce CAT2 spendbundle when payment amount exceeds total coin amounts', + () { const paymentAmount = 301; final payment = CatPayment(paymentAmount, catTargetPuzzlehash); expect( - TestData.catCoins.fold(0, (previousValue, catCoin) => previousValue + catCoin.amount), + TestData.catCoins.fold( + 0, + (previousValue, catCoin) => previousValue + catCoin.amount, + ), lessThan(paymentAmount), - reason: 'amounts for coin test data in this test must not exceed payment amount', + reason: + 'amounts for coin test data in this test must not exceed payment amount', ); expect( () => catWalletService.createSpendBundle( @@ -79,12 +96,24 @@ Future main() async { fee: 1000, standardCoinsForFee: [TestData.standardCoin], ); - expect(() => catWalletService.validateSpendBundle(spendBundle), returnsNormally); + expect( + () => catWalletService.validateSpendBundle(spendBundle), + returnsNormally, + ); }); - test('produces valid CAT2 spendbundle with fee and multiple payments', () async { - final payment = CatPayment.withStringMemos(200, catTargetPuzzlehash, memos: const ['Chia is really cool']); - final payment1 = CatPayment.withIntMemos(100, catTargetPuzzlehash, memos: const [1000]); + test('produces valid CAT2 spendbundle with fee and multiple payments', + () async { + final payment = CatPayment.withStringMemos( + 200, + catTargetPuzzlehash, + memos: const ['Chia is really cool'], + ); + final payment1 = CatPayment.withIntMemos( + 100, + catTargetPuzzlehash, + memos: const [1000], + ); final spendBundle = catWalletService.createSpendBundle( payments: [payment, payment1], catCoinsInput: TestData.catCoins, @@ -93,13 +122,25 @@ Future main() async { fee: 1000, standardCoinsForFee: [TestData.standardCoin], ); - expect(() => catWalletService.validateSpendBundle(spendBundle), returnsNormally); + expect( + () => catWalletService.validateSpendBundle(spendBundle), + returnsNormally, + ); }); - test('throws error when creating CAT1 spendbundle with fee and multiple payments with CAT2 coins', + test( + 'throws error when creating CAT1 spendbundle with fee and multiple payments with CAT2 coins', () async { - final payment = CatPayment.withStringMemos(200, catTargetPuzzlehash, memos: const ['Chia is really cool']); - final payment1 = CatPayment.withIntMemos(100, catTargetPuzzlehash, memos: const [1000]); + final payment = CatPayment.withStringMemos( + 200, + catTargetPuzzlehash, + memos: const ['Chia is really cool'], + ); + final payment1 = CatPayment.withIntMemos( + 100, + catTargetPuzzlehash, + memos: const [1000], + ); expect( () => cat1WalletService.createSpendBundle( payments: [payment, payment1], @@ -128,20 +169,27 @@ Future main() async { ); }); - test('should create valid spendbundle without change puzzlehash when there is no change', () { - final totalCoinsValue = - TestData.catCoins.fold(0, (int previousValue, coin) => previousValue + coin.amount); + test( + 'should create valid spendbundle without change puzzlehash when there is no change', + () { + final totalCoinsValue = TestData.catCoins + .fold(0, (int previousValue, coin) => previousValue + coin.amount); final spendBundle = catWalletService.createSpendBundle( payments: [CatPayment(totalCoinsValue, catTargetPuzzlehash)], catCoinsInput: TestData.catCoins, keychain: catWalletKeychain, ); - expect(() => catWalletService.validateSpendBundle(spendBundle), returnsNormally); + expect( + () => catWalletService.validateSpendBundle(spendBundle), + returnsNormally, + ); }); - test('throws error when creating CAT1 spendbundle without change puzzlehash with CAT2 coins', () { - final totalCoinsValue = - TestData.catCoins.fold(0, (int previousValue, coin) => previousValue + coin.amount); + test( + 'throws error when creating CAT1 spendbundle without change puzzlehash with CAT2 coins', + () { + final totalCoinsValue = TestData.catCoins + .fold(0, (int previousValue, coin) => previousValue + coin.amount); expect( () => cat1WalletService.createSpendBundle( payments: [CatPayment(totalCoinsValue, catTargetPuzzlehash)], @@ -152,7 +200,8 @@ Future main() async { ); }); - test('CAT2 wallet should throw exception when change puzzlehash is not given and there is change', + test( + 'CAT2 wallet should throw exception when change puzzlehash is not given and there is change', () { expect( () { @@ -166,7 +215,9 @@ Future main() async { ); }); - test('should throw exception when deconstructing a puzzle that is not a CAT2 puzzle', () { + test( + 'should throw exception when deconstructing a puzzle that is not a CAT2 puzzle', + () { expect( () { DeconstructedCatPuzzle( diff --git a/test/cat/invalid_cat_exception_test.dart b/test/cat/invalid_cat_exception_test.dart index 1294ddb7..b85fe88a 100644 --- a/test/cat/invalid_cat_exception_test.dart +++ b/test/cat/invalid_cat_exception_test.dart @@ -9,6 +9,9 @@ void main() { test('should return the desired string form with message', () { const message = 'Invalid CAT exception message'; - expect(InvalidCatException(message: message).toString(), 'Invalid CAT: $message'); + expect( + InvalidCatException(message: message).toString(), + 'Invalid CAT: $message', + ); }); } diff --git a/test/cat/run_tail_condition_test.dart b/test/cat/run_tail_condition_test.dart index a33e97f6..2976ae33 100644 --- a/test/cat/run_tail_condition_test.dart +++ b/test/cat/run_tail_condition_test.dart @@ -5,8 +5,10 @@ import 'package:test/scaffolding.dart'; void main() { test('should return the desired string form', () { - final runTailCondition = - RunTailCondition(Program.fromInt(1234567890), Program.fromInt(1234567890)); + final runTailCondition = RunTailCondition( + Program.fromInt(1234567890), + Program.fromInt(1234567890), + ); expect( runTailCondition.toString(), 'RunTailCondition(code: ${RunTailCondition.conditionCode}, ' diff --git a/test/clsp/compilation_test.dart b/test/clsp/compilation_test.dart index 0f68d762..3bc5724c 100644 --- a/test/clsp/compilation_test.dart +++ b/test/clsp/compilation_test.dart @@ -11,9 +11,14 @@ Future main() async { return; } - Future checkCompilation(String pathToClsp, String pathToCompiledHex) async { - final process = - await Process.run('./test/clsp/compile_clsp.sh', [pathToClsp, pathToCompiledHex]); + Future checkCompilation( + String pathToClsp, + String pathToCompiledHex, + ) async { + final process = await Process.run( + './test/clsp/compile_clsp.sh', + [pathToClsp, pathToCompiledHex], + ); if (process.exitCode == 0) { return true; @@ -22,7 +27,8 @@ Future main() async { } } - test('should correctly return false when hex does not match clsp compilation', () async { + test('should correctly return false when hex does not match clsp compilation', + () async { final check = await checkCompilation( 'lib/src/cat/puzzles/tails/genesis_by_coin_id/genesis_by_coin_id.clsp', 'lib/src/cat/puzzles/tails/meltable_genesis_by_coin_id/meltable_genesis_by_coin_id.clvm.hex', @@ -40,7 +46,8 @@ Future main() async { expect(check, isTrue); }); - test('should check that hex of compiled delegated_tail.clsp is correct', () async { + test('should check that hex of compiled delegated_tail.clsp is correct', + () async { final check = await checkCompilation( 'lib/src/cat/puzzles/tails/delegated_tail/delegated_tail.clsp', 'lib/src/cat/puzzles/tails/delegated_tail/delegated_tail.clvm.hex', @@ -49,7 +56,9 @@ Future main() async { expect(check, isTrue); }); - test('should check that hex of compiled everything_with_signature.clsp is correct', () async { + test( + 'should check that hex of compiled everything_with_signature.clsp is correct', + () async { final check = await checkCompilation( 'lib/src/cat/puzzles/tails/everything_with_signature/everything_with_signature.clsp', 'lib/src/cat/puzzles/tails/everything_with_signature/everything_with_signature.clvm.hex', @@ -58,7 +67,8 @@ Future main() async { expect(check, isTrue); }); - test('should check that hex of compiled genesis_by_coin_id.clsp is correct', () async { + test('should check that hex of compiled genesis_by_coin_id.clsp is correct', + () async { final check = await checkCompilation( 'lib/src/cat/puzzles/tails/genesis_by_coin_id/genesis_by_coin_id.clsp', 'lib/src/cat/puzzles/tails/genesis_by_coin_id/genesis_by_coin_id.clvm.hex', @@ -67,7 +77,9 @@ Future main() async { expect(check, isTrue); }); - test('should check that hex of compiled meltable_genesis_by_coin_id.clsp is correct', () async { + test( + 'should check that hex of compiled meltable_genesis_by_coin_id.clsp is correct', + () async { final check = await checkCompilation( 'lib/src/cat/puzzles/tails/meltable_genesis_by_coin_id/meltable_genesis_by_coin_id.clsp', 'lib/src/cat/puzzles/tails/meltable_genesis_by_coin_id/meltable_genesis_by_coin_id.hex', @@ -76,7 +88,8 @@ Future main() async { expect(check, isTrue); }); - test('should check that hex of compiled calculate_synthetic_public_key.clsp is correct', + test( + 'should check that hex of compiled calculate_synthetic_public_key.clsp is correct', () async { final check = await checkCompilation( 'lib/src/core/puzzles/calculate_synthetic_public_key/calculate_synthetic_public_key.clsp', @@ -86,7 +99,9 @@ Future main() async { expect(check, isTrue); }); - test('should check that hex of compiled p2_delayed_or_preimage.clsp is correct', () async { + test( + 'should check that hex of compiled p2_delayed_or_preimage.clsp is correct', + () async { final check = await checkCompilation( 'lib/src/exchange/btc/puzzles/p2_delayed_or_preimage/p2_delayed_or_preimage.clsp', 'lib/src/exchange/btc/puzzles/p2_delayed_or_preimage/p2_delayed_or_preimage.clvm.hex', @@ -95,7 +110,8 @@ Future main() async { expect(check, isTrue); }); - test('should check that hex of compiled pool_member_innerpuz.clsp is correct', () async { + test('should check that hex of compiled pool_member_innerpuz.clsp is correct', + () async { final check = await checkCompilation( 'lib/src/plot_nft/puzzles/pool_member_inner_puz/pool_member_innerpuz.clsp', 'lib/src/plot_nft/puzzles/pool_member_inner_puz/pool_member_innerpuz.clvm.hex', @@ -104,7 +120,9 @@ Future main() async { expect(check, isTrue); }); - test('should check that hex of compiled pool_waitingroom_innerpuz.clsp is correct', () async { + test( + 'should check that hex of compiled pool_waitingroom_innerpuz.clsp is correct', + () async { final check = await checkCompilation( 'lib/src/plot_nft/puzzles/pool_waitingroom_innerpuz/pool_waitingroom_innerpuz.clsp', 'lib/src/plot_nft/puzzles/pool_waitingroom_innerpuz/pool_waitingroom_innerpuz.clvm.hex', @@ -113,7 +131,8 @@ Future main() async { expect(check, isTrue); }); - test('should check that hex of compiled p2_singleton_or_delayed_puzhash.clsp is correct', + test( + 'should check that hex of compiled p2_singleton_or_delayed_puzhash.clsp is correct', () async { final check = await checkCompilation( 'lib/src/singleton/puzzles/p2_singleton_or_delayed_puzhash/p2_singleton_or_delayed_puzhash.clsp', @@ -123,7 +142,8 @@ Future main() async { expect(check, isTrue); }); - test('should check that hex of compiled singleton_launcher.clsp is correct', () async { + test('should check that hex of compiled singleton_launcher.clsp is correct', + () async { final check = await checkCompilation( 'lib/src/singleton/puzzles/singleton_launcher/singleton_launcher.clsp', 'lib/src/singleton/puzzles/singleton_launcher/singleton_launcher.clvm.hex', @@ -132,7 +152,8 @@ Future main() async { expect(check, isTrue); }); - test('should check that hex of compiled singleton_top_layer.clsp is correct', () async { + test('should check that hex of compiled singleton_top_layer.clsp is correct', + () async { final check = await checkCompilation( 'lib/src/singleton/puzzles/singleton_top_layer/singleton_top_layer.clsp', 'lib/src/singleton/puzzles/singleton_top_layer/singleton_top_layer.clvm.hex', @@ -141,7 +162,9 @@ Future main() async { expect(check, isTrue); }); - test('should check that hex of compiled singleton_top_layer_v1_1.clsp is correct', () async { + test( + 'should check that hex of compiled singleton_top_layer_v1_1.clsp is correct', + () async { final check = await checkCompilation( 'lib/src/singleton/puzzles/singleton_top_layer_v1_1/singleton_top_layer_v1_1.clsp', 'lib/src/singleton/puzzles/singleton_top_layer_v1_1/singleton_top_layer_v1_1.clvm.hex', @@ -150,7 +173,8 @@ Future main() async { expect(check, isTrue); }); - test('should check that hex of compiled p2_delegated_puzzle_or_hidden_puzzle.clsp is correct', + test( + 'should check that hex of compiled p2_delegated_puzzle_or_hidden_puzzle.clsp is correct', () async { final check = await checkCompilation( 'lib/src/standard/puzzles/p2_delegated_puzzle_or_hidden_puzzle/p2_delegated_puzzle_or_hidden_puzzle.clsp', @@ -160,7 +184,8 @@ Future main() async { expect(check, isTrue); }); - test('should check that hex of compiled notification.clsp is correct', () async { + test('should check that hex of compiled notification.clsp is correct', + () async { final check = await checkCompilation( 'lib/src/notification/puzzles/notification/notification.clsp', 'lib/src/notification/puzzles/notification/notification.clvm.hex', @@ -169,7 +194,8 @@ Future main() async { expect(check, isTrue); }); - test('should check that hex of compiled curry_and_treehash.clsp is correct', () async { + test('should check that hex of compiled curry_and_treehash.clsp is correct', + () async { final check = await checkCompilation( 'lib/src/cat/puzzles/curry_and_treehash/curry_and_treehash.clsp', 'lib/src/cat/puzzles/curry_and_treehash/curry_and_treehash.clvm.hex', @@ -178,7 +204,8 @@ Future main() async { expect(check, isTrue); }); - test('should check that hex of compiled curried_condition.clsp is correct', () async { + test('should check that hex of compiled curried_condition.clsp is correct', + () async { final check = await checkCompilation( 'lib/src/custom_coins/dependent_coin/puzzles/curried_condition/curried_condition.clsp', 'lib/src/custom_coins/dependent_coin/puzzles/curried_condition/curried_condition.clvm.hex', @@ -187,7 +214,8 @@ Future main() async { expect(check, isTrue); }); - test('should check that hex of compiled did_innerpuz.clsp is correct', () async { + test('should check that hex of compiled did_innerpuz.clsp is correct', + () async { final check = await checkCompilation( 'lib/src/did/puzzles/did_innerpuz/did_innerpuz.clsp', 'lib/src/did/puzzles/did_innerpuz/did_innerpuz.clvm.hex', @@ -196,7 +224,9 @@ Future main() async { expect(check, isTrue); }); - test('should check that hex of compiled nft_intermediate_launcher.clsp is correct', () async { + test( + 'should check that hex of compiled nft_intermediate_launcher.clsp is correct', + () async { final check = await checkCompilation( 'lib/src/nft/puzzles/nft_intermediate_launcher/nft_intermediate_launcher.clsp', 'lib/src/nft/puzzles/nft_intermediate_launcher/nft_intermediate_launcher.clvm.hex', @@ -205,7 +235,9 @@ Future main() async { expect(check, isTrue); }); - test('should check that hex of compiled nft_metadata_updater_default.clsp is correct', () async { + test( + 'should check that hex of compiled nft_metadata_updater_default.clsp is correct', + () async { final check = await checkCompilation( 'lib/src/nft/puzzles/nft_metadata_updater_default/nft_metadata_updater_default.clsp', 'lib/src/nft/puzzles/nft_metadata_updater_default/nft_metadata_updater_default.clvm.hex', @@ -214,7 +246,8 @@ Future main() async { expect(check, isTrue); }); - test('should check that hex of compiled nft_ownership_layer.clsp is correct', () async { + test('should check that hex of compiled nft_ownership_layer.clsp is correct', + () async { final check = await checkCompilation( 'lib/src/nft/puzzles/nft_metadata_updater_default/nft_ownership_layer.clsp', 'lib/src/nft/puzzles/nft_intermediate_launcher/nft_ownership_layer.clvm.hex', @@ -234,7 +267,8 @@ Future main() async { expect(check, isTrue); }); - test('should check that hex of compiled nft_state_layer.clsp is correct', () async { + test('should check that hex of compiled nft_state_layer.clsp is correct', + () async { final check = await checkCompilation( 'lib/src/nft/puzzles/nft_metadata_updater_default/nft_state_layer.clsp', 'lib/src/nft/puzzles/nft_intermediate_launcher/nft_state_layer.clvm.hex', @@ -243,7 +277,8 @@ Future main() async { expect(check, isTrue); }); - test('should check that hex of compiled settlement_payments.clsp is correct', () async { + test('should check that hex of compiled settlement_payments.clsp is correct', + () async { final check = await checkCompilation( 'lib/src/offer/puzzles/settlement_payments/settlement_payments.clsp', 'lib/src/offer/puzzles/settlement_payments/settlement_payments.clvm.hex', @@ -252,14 +287,16 @@ Future main() async { expect(check, isTrue); }); - test('should check that hex of compiled default_hidden_puzzle.clsp is correct', () async { + test( + 'should check that hex of compiled default_hidden_puzzle.clsp is correct', + () async { // chia-dev-tools won't compile (=) due to error '= takes exactly 2 arguments' // comparing to hex value used in chia-blockchain/chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.py instead - final hex = - (await File('lib/src/standard/puzzles/default_hidden_puzzle/default_hidden_puzzle.clvm.hex') - .readAsString()) - .trim(); + final hex = (await File( + 'lib/src/standard/puzzles/default_hidden_puzzle/default_hidden_puzzle.clvm.hex', + ).readAsString()) + .trim(); expect(hex, equals('ff0980')); }); diff --git a/test/clvm/ambiguous_bytes_test.dart b/test/clvm/ambiguous_bytes_test.dart index c3ddd773..7037bf55 100644 --- a/test/clvm/ambiguous_bytes_test.dart +++ b/test/clvm/ambiguous_bytes_test.dart @@ -2,14 +2,18 @@ import 'package:chia_crypto_utils/chia_crypto_utils.dart'; import 'package:test/test.dart'; void main() { - final expectedBytes = - Bytes.fromHex('0xd8a339fbb28da3dd446519abdce314c067313c7955a321bf6c84717b91e18761'); + final expectedBytes = Bytes.fromHex( + '0xd8a339fbb28da3dd446519abdce314c067313c7955a321bf6c84717b91e18761', + ); final hexStringProgram = Program.fromString(expectedBytes.toHexWithPrefix()); final bytesProgram = expectedBytes.toProgram(); test('should convert program to bytes', () { for (final program in [hexStringProgram, bytesProgram]) { - expect(NftMetadata.getBytesFromTypeAmbiguousProgram(program), expectedBytes); + expect( + NftMetadata.getBytesFromTypeAmbiguousProgram(program), + expectedBytes, + ); } }); } diff --git a/test/clvm/clvm_test.dart b/test/clvm/clvm_test.dart index 10131eb0..2518317b 100644 --- a/test/clvm/clvm_test.dart +++ b/test/clvm/clvm_test.dart @@ -9,7 +9,8 @@ class RunIn { final String solution; final int? cost; final bool? strict; - RunIn(this.puzzle, {String? solution, this.cost, this.strict}) : solution = solution ?? '()'; + RunIn(this.puzzle, {String? solution, this.cost, this.strict}) + : solution = solution ?? '()'; } class RunOut { @@ -40,7 +41,8 @@ class DeserializeIn { class DeserializeOut { final String output; final bool showKeywords; - DeserializeOut(this.output, {bool? showKeywords}) : showKeywords = showKeywords ?? true; + DeserializeOut(this.output, {bool? showKeywords}) + : showKeywords = showKeywords ?? true; } void main() { @@ -90,7 +92,8 @@ void main() { RunOut('()', cost: 53, showKeywords: false), // args-01 RunIn('1', solution: '(((8 . 12) . (10 . 14)) . ((9 . 13) . (11 . 15)))'): - RunOut('(((8 . 12) 10 . 14) (9 . 13) 11 . 15)', cost: 53, showKeywords: false), + RunOut('(((8 . 12) 10 . 14) (9 . 13) 11 . 15)', + cost: 53, showKeywords: false), // args-02 RunIn('2', solution: '(((8 . 12) . (10 . 14)) . ((9 . 13) . (11 . 15)))'): RunOut('((8 . 12) 10 . 14)', cost: 57, showKeywords: false), @@ -136,11 +139,14 @@ void main() { // ash-1 RunIn('(ash (q . 7) (q . 1))'): RunOut('14', cost: 662), // ash-2 - RunIn('(ash (q . 7) (q . 100))'): RunOut('0x70000000000000000000000000', cost: 818), + RunIn('(ash (q . 7) (q . 100))'): + RunOut('0x70000000000000000000000000', cost: 818), // ash-3 - RunIn('(ash (q . -7) (q . 100))'): RunOut('0x90000000000000000000000000', cost: 818), + RunIn('(ash (q . -7) (q . 100))'): + RunOut('0x90000000000000000000000000', cost: 818), // ash-4 - RunIn('(ash (q . 0x90000000000000000000000000) (q . -100))'): RunOut('-7', cost: 698), + RunIn('(ash (q . 0x90000000000000000000000000) (q . -100))'): + RunOut('-7', cost: 698), // ash-5 RunIn('(ash (q . 1))'): null, // ash-6 @@ -173,7 +179,8 @@ void main() { // cons-2 RunIn('(c (q . 100) (q . ()))'): RunOut('(100)', cost: 100), // cons-3 - RunIn('(c (q . 100) (q . (200 300 400)))'): RunOut('(100 200 300 400)', cost: 100), + RunIn('(c (q . 100) (q . (200 300 400)))'): + RunOut('(100 200 300 400)', cost: 100), // cons-4 RunIn('(c (q . 100) (q . ((500 (200 300 400)))))'): RunOut('(100 (500 (200 300 400)))', cost: 100), @@ -193,50 +200,71 @@ void main() { RunIn('(/ (q . 0x00000000000000000000000000000000000000000000000000000000a) (q . 0x000000000000000000000000000000000000000000000000000000000000000000000005))'): RunOut('2', cost: 1308), // divmod-1 - RunIn('(divmod 2 5)', solution: '(80001 73)'): RunOut('(1095 . 66)', cost: 1280), + RunIn('(divmod 2 5)', solution: '(80001 73)'): + RunOut('(1095 . 66)', cost: 1280), // divmod-10 - RunIn('(divmod 2 5)', solution: '(80000 -10)'): RunOut('(-8000)', cost: 1270), + RunIn('(divmod 2 5)', solution: '(80000 -10)'): + RunOut('(-8000)', cost: 1270), // divmod-11 RunIn('(divmod (q . 0x0000000000000000000000000000000000000000000000000000000000000013881) (q . 0x0000000000000000000000000000000000000000000000000000049))'): RunOut('(1095 . 66)', cost: 1568), // divmod-12 - RunIn('(divmod (q . -10) (q . -7))'): RunOut('(1 . -3)', cost: 1198, showKeywords: false), + RunIn('(divmod (q . -10) (q . -7))'): + RunOut('(1 . -3)', cost: 1198, showKeywords: false), // divmod-13 - RunIn('(divmod (q . -10) (q . 7))'): RunOut('(-2 . 4)', cost: 1198, showKeywords: false), + RunIn('(divmod (q . -10) (q . 7))'): + RunOut('(-2 . 4)', cost: 1198, showKeywords: false), // divmod-14 - RunIn('(divmod (q . 10) (q . -7))'): RunOut('(-2 . -4)', cost: 1198, showKeywords: false), + RunIn('(divmod (q . 10) (q . -7))'): + RunOut('(-2 . -4)', cost: 1198, showKeywords: false), // divmod-15 - RunIn('(divmod (q . 10) (q . 7))'): RunOut('(1 . 3)', cost: 1198, showKeywords: false), + RunIn('(divmod (q . 10) (q . 7))'): + RunOut('(1 . 3)', cost: 1198, showKeywords: false), // divmod-16 - RunIn('(divmod (q . -10) (q . -70))'): RunOut('(() . -10)', cost: 1188, showKeywords: false), + RunIn('(divmod (q . -10) (q . -70))'): + RunOut('(() . -10)', cost: 1188, showKeywords: false), // divmod-17 - RunIn('(divmod (q . -10) (q . 70))'): RunOut('(-1 . 60)', cost: 1198, showKeywords: false), + RunIn('(divmod (q . -10) (q . 70))'): + RunOut('(-1 . 60)', cost: 1198, showKeywords: false), // divmod-18 - RunIn('(divmod (q . 10) (q . -70))'): RunOut('(-1 . -60)', cost: 1198, showKeywords: false), + RunIn('(divmod (q . 10) (q . -70))'): + RunOut('(-1 . -60)', cost: 1198, showKeywords: false), // divmod-19 - RunIn('(divmod (q . 10) (q . 70))'): RunOut('(() . 10)', cost: 1188, showKeywords: false), + RunIn('(divmod (q . 10) (q . 70))'): + RunOut('(() . 10)', cost: 1188, showKeywords: false), // divmod-2 - RunIn('(divmod 2 5)', solution: '(-80001 73)'): RunOut('(-1096 . 7)', cost: 1280), + RunIn('(divmod 2 5)', solution: '(-80001 73)'): + RunOut('(-1096 . 7)', cost: 1280), // divmod-20 - RunIn('(divmod (q . -100) (q . -7))'): RunOut('(14 . -2)', cost: 1198, showKeywords: false), + RunIn('(divmod (q . -100) (q . -7))'): + RunOut('(14 . -2)', cost: 1198, showKeywords: false), // divmod-21 - RunIn('(divmod (q . -100) (q . 7))'): RunOut('(-15 . 5)', cost: 1198, showKeywords: false), + RunIn('(divmod (q . -100) (q . 7))'): + RunOut('(-15 . 5)', cost: 1198, showKeywords: false), // divmod-22 - RunIn('(divmod (q . 100) (q . -7))'): RunOut('(-15 . -5)', cost: 1198, showKeywords: false), + RunIn('(divmod (q . 100) (q . -7))'): + RunOut('(-15 . -5)', cost: 1198, showKeywords: false), // divmod-23 - RunIn('(divmod (q . 100) (q . 7))'): RunOut('(14 . 2)', cost: 1198, showKeywords: false), + RunIn('(divmod (q . 100) (q . 7))'): + RunOut('(14 . 2)', cost: 1198, showKeywords: false), // divmod-24 - RunIn('(divmod (q . -100) (q . -70))'): RunOut('(1 . -30)', cost: 1198, showKeywords: false), + RunIn('(divmod (q . -100) (q . -70))'): + RunOut('(1 . -30)', cost: 1198, showKeywords: false), // divmod-25 - RunIn('(divmod (q . -100) (q . 70))'): RunOut('(-2 . 40)', cost: 1198, showKeywords: false), + RunIn('(divmod (q . -100) (q . 70))'): + RunOut('(-2 . 40)', cost: 1198, showKeywords: false), // divmod-26 - RunIn('(divmod (q . 100) (q . -70))'): RunOut('(-2 . -40)', cost: 1198, showKeywords: false), + RunIn('(divmod (q . 100) (q . -70))'): + RunOut('(-2 . -40)', cost: 1198, showKeywords: false), // divmod-27 - RunIn('(divmod (q . 100) (q . 70))'): RunOut('(1 . 30)', cost: 1198, showKeywords: false), + RunIn('(divmod (q . 100) (q . 70))'): + RunOut('(1 . 30)', cost: 1198, showKeywords: false), // divmod-3 - RunIn('(divmod 2 5)', solution: '(80001 -73)'): RunOut('(-1096 . -7)', cost: 1280), + RunIn('(divmod 2 5)', solution: '(80001 -73)'): + RunOut('(-1096 . -7)', cost: 1280), // divmod-4 - RunIn('(divmod 2 5)', solution: '(-80001 -73)'): RunOut('(1095 . -66)', cost: 1280), + RunIn('(divmod 2 5)', solution: '(-80001 -73)'): + RunOut('(1095 . -66)', cost: 1280), // divmod-5 RunIn('(divmod 2 5)', solution: '((200 80001) 73)'): null, // divmod-6 @@ -246,7 +274,8 @@ void main() { // divmod-8 RunIn('(divmod 2 5)', solution: '(80000 10)'): RunOut('(8000)', cost: 1270), // divmod-9 - RunIn('(divmod 2 5)', solution: '(-80000 10)'): RunOut('(-8000)', cost: 1270), + RunIn('(divmod 2 5)', solution: '(-80000 10)'): + RunOut('(-8000)', cost: 1270), // double-cons-1 RunIn('((+) 1 2 3 4)'): RunOut('10', cost: 1500), // double-cons-2 @@ -264,7 +293,8 @@ void main() { // env-4 RunIn('1', solution: '(100 200)'): RunOut('(100 200)', cost: 53), // env-5 - RunIn('1', solution: '((100 101 102) 105)'): RunOut('((100 101 102) 105)', cost: 53), + RunIn('1', solution: '((100 101 102) 105)'): + RunOut('((100 101 102) 105)', cost: 53), // equal-1 RunIn('(= (q . 10))'): null, // equal-10 @@ -285,9 +315,11 @@ void main() { // equal-7 RunIn("(= 3 3)"): null, // equal-8 - RunIn("(= (f 1) (+ (f (r 1)) (f (r (r 1)))))", solution: "(7 3 4)"): RunOut('1', cost: 1203), + RunIn("(= (f 1) (+ (f (r 1)) (f (r (r 1)))))", solution: "(7 3 4)"): + RunOut('1', cost: 1203), // equal-9 - RunIn("(= (f 1) (+ (f (r 1)) (f (r (r 1)))))", solution: "(7 3 3)"): RunOut('()', cost: 1203), + RunIn("(= (f 1) (+ (f (r 1)) (f (r (r 1)))))", solution: "(7 3 3)"): + RunOut('()', cost: 1203), // eval-1 RunIn('(a (q . 1) (q . (100 200)))'): RunOut('(100 200)', cost: 184), // eval-2 @@ -357,9 +389,11 @@ void main() { // if_3 RunIn('(i (q . 1) (q . 200) (q . 300))'): RunOut('200', cost: 103), // if_4 - RunIn('(i (f (r (r 1))) (f 1) (f (r 1)))', solution: '(200 300 400)'): RunOut('200', cost: 361), + RunIn('(i (f (r (r 1))) (f 1) (f (r 1)))', solution: '(200 300 400)'): + RunOut('200', cost: 361), // if_5 - RunIn('(i (f (r (r 1))) (f 1) (f (r 1)))', solution: '(200 300 1)'): RunOut('200', cost: 361), + RunIn('(i (f (r (r 1))) (f 1) (f (r 1)))', solution: '(200 300 1)'): + RunOut('200', cost: 361), // illegal-dot-expression RunIn('(q . . 0 1)'): null, // int-0 @@ -417,7 +451,8 @@ void main() { // lognot-3 RunIn('(lognot (q . 0))'): RunOut('-1', cost: 371), // lognot-4 - RunIn('(lognot (q . 734671943749191))'): RunOut('0xfd63d1dbc431b8', cost: 452), + RunIn('(lognot (q . 734671943749191))'): + RunOut('0xfd63d1dbc431b8', cost: 452), // lognot-5 RunIn('(lognot)'): null, // lognot-6 @@ -439,11 +474,14 @@ void main() { // lsh-1 RunIn('(lsh (q . 7) (q . 1))'): RunOut('14', cost: 343), // lsh-2 - RunIn('(lsh (q . 7) (q . 100))'): RunOut('0x70000000000000000000000000', cost: 499), + RunIn('(lsh (q . 7) (q . 100))'): + RunOut('0x70000000000000000000000000', cost: 499), // lsh-3 - RunIn('(lsh (q . -7) (q . 100))'): RunOut('0x0f90000000000000000000000000', cost: 512), + RunIn('(lsh (q . -7) (q . 100))'): + RunOut('0x0f90000000000000000000000000', cost: 512), // lsh-4 - RunIn('(lsh (q . 0x90000000000000000000000000) (q . -100))'): RunOut('9', cost: 379), + RunIn('(lsh (q . 0x90000000000000000000000000) (q . -100))'): + RunOut('9', cost: 379), // lsh-5 RunIn('(lsh (q . 1))'): null, // lsh-6 @@ -507,9 +545,12 @@ void main() { '(0x1337 . (0x1337 . (0x1337 . ((0x1337 . ((0x1337 . 42) . 0x1337)) . 0x1337))))'): RunOut('42', cost: 81, showKeywords: false), // path-11 - RunIn('0x000000000000000000000000'): RunOut('()', cost: 101, showKeywords: false), + RunIn('0x000000000000000000000000'): + RunOut('()', cost: 101, showKeywords: false), // path-2 - RunIn('44', solution: '(((0x1337 . (0x1337 . (42 . 0x1337))) . 0x1337) . 0x1337)'): + RunIn('44', + solution: + '(((0x1337 . (0x1337 . (42 . 0x1337))) . 0x1337) . 0x1337)'): RunOut('42', cost: 73, showKeywords: false), // path-3 RunIn('7708975405620101644641102810267383005', @@ -517,8 +558,11 @@ void main() { '(0x1337 . ((0x1337 . (0x1337 . (0x1337 . ((0x1337 . (0x1337 . (((0x1337 . ((0x1337 . (0x1337 . (0x1337 . (0x1337 . (0x1337 . ((0x1337 . (0x1337 . ((0x1337 . (((0x1337 . (0x1337 . (0x1337 . ((0x1337 . (((0x1337 . (((0x1337 . (0x1337 . (0x1337 . (0x1337 . ((0x1337 . ((0x1337 . (((((0x1337 . ((0x1337 . ((0x1337 . (0x1337 . (0x1337 . (((0x1337 . (0x1337 . ((0x1337 . (0x1337 . ((((0x1337 . (0x1337 . (0x1337 . (0x1337 . (((((0x1337 . (0x1337 . (0x1337 . (0x1337 . (0x1337 . (((((0x1337 . (((((0x1337 . ((0x1337 . (0x1337 . ((((0x1337 . ((((0x1337 . ((0x1337 . ((0x1337 . ((0x1337 . (0x1337 . (0x1337 . ((((0x1337 . (0x1337 . ((0x1337 . (((0x1337 . (0x1337 . (((0x1337 . (0x1337 . (0x1337 . (42 . 0x1337)))) . 0x1337) . 0x1337))) . 0x1337) . 0x1337)) . 0x1337))) . 0x1337) . 0x1337) . 0x1337)))) . 0x1337)) . 0x1337)) . 0x1337)) . 0x1337) . 0x1337) . 0x1337)) . 0x1337) . 0x1337) . 0x1337))) . 0x1337)) . 0x1337) . 0x1337) . 0x1337) . 0x1337)) . 0x1337) . 0x1337) . 0x1337) . 0x1337)))))) . 0x1337) . 0x1337) . 0x1337) . 0x1337))))) . 0x1337) . 0x1337) . 0x1337))) . 0x1337))) . 0x1337) . 0x1337)))) . 0x1337)) . 0x1337)) . 0x1337) . 0x1337) . 0x1337) . 0x1337)) . 0x1337)) . 0x1337))))) . 0x1337) . 0x1337)) . 0x1337) . 0x1337)) . 0x1337)))) . 0x1337) . 0x1337)) . 0x1337))) . 0x1337)))))) . 0x1337)) . 0x1337) . 0x1337))) . 0x1337)))) . 0x1337))'): RunOut('42', cost: 541, showKeywords: false), // path-4 - RunIn('1', solution: '(((0x1337 . (0x1337 . (42 . 0x1337))) . 0x1337) . 0x1337)'): - RunOut('(((4919 4919 42 . 4919) . 4919) . 4919)', cost: 53, showKeywords: false), + RunIn('1', + solution: + '(((0x1337 . (0x1337 . (42 . 0x1337))) . 0x1337) . 0x1337)'): + RunOut('(((4919 4919 42 . 4919) . 4919) . 4919)', + cost: 53, showKeywords: false), // path-5 RunIn( '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', @@ -619,14 +663,19 @@ void main() { // rest-4 RunIn('(r (r (q . ((100 200 300) 400 500))))'): RunOut('(500)', cost: 91), // sha256-1 - RunIn('(sha256 (f 1))', solution: '("hello.there.my.dear.friend")'): - RunOut('0x5272821c151fdd49f19cc58cf8833da5781c7478a36d500e8dc2364be39f8216', cost: 678), + RunIn('(sha256 (f 1))', solution: '("hello.there.my.dear.friend")'): RunOut( + '0x5272821c151fdd49f19cc58cf8833da5781c7478a36d500e8dc2364be39f8216', + cost: 678), // sha256-2 - RunIn('(sha256 (q . "hel") (q . "lo.there.my.dear.friend"))'): - RunOut('0x5272821c151fdd49f19cc58cf8833da5781c7478a36d500e8dc2364be39f8216', cost: 777), + RunIn('(sha256 (q . "hel") (q . "lo.there.my.dear.friend"))'): RunOut( + '0x5272821c151fdd49f19cc58cf8833da5781c7478a36d500e8dc2364be39f8216', + cost: 777), // sha256-3 - RunIn('(sha256 (f 1) (f (r 1)))', solution: '("hel" "lo.there.my.dear.friend")'): - RunOut('0x5272821c151fdd49f19cc58cf8833da5781c7478a36d500e8dc2364be39f8216', cost: 918), + RunIn('(sha256 (f 1) (f (r 1)))', + solution: + '("hel" "lo.there.my.dear.friend")'): RunOut( + '0x5272821c151fdd49f19cc58cf8833da5781c7478a36d500e8dc2364be39f8216', + cost: 918), // sha256-4 RunIn('(sha256 1)', solution: '(hello)'): null, // simple_add @@ -649,7 +698,8 @@ void main() { // strlen-3 RunIn('(strlen 1)', solution: '()'): RunOut('()', cost: 227), // strlen-4 - RunIn('(strlen 1)', solution: '"the quick brown fox jumps over the lazy dogs"'): + RunIn('(strlen 1)', + solution: '"the quick brown fox jumps over the lazy dogs"'): RunOut('44', cost: 281), // sub-1 RunIn('(- (q . 7) (q . 1))'): RunOut('6', cost: 805), @@ -665,7 +715,8 @@ void main() { // substr-00 RunIn('(substr (q . "abcdefghijkl") (q . 14))'): null, // substr-01 - RunIn('(substr (q . "abcdefghijkl") (q . 0))'): RunOut('"abcdefghijkl"', cost: 51), + RunIn('(substr (q . "abcdefghijkl") (q . 0))'): + RunOut('"abcdefghijkl"', cost: 51), // substr-02 RunIn('(substr (q . "abcdefghijkl") (q . -1))'): null, // substr-03 @@ -673,7 +724,8 @@ void main() { // substr-04 RunIn('(substr (q . "abcdefghijkl") (q . 11))'): RunOut('108', cost: 51), // substr-05 - RunIn('(substr (q . "abcdefghijkl") 2 5)', solution: '(0 4)'): RunOut('"abcd"', cost: 131), + RunIn('(substr (q . "abcdefghijkl") 2 5)', solution: '(0 4)'): + RunOut('"abcd"', cost: 131), // substr-06 RunIn('(substr (q . "abcdefghijkl") 2 5)', solution: '(0 12)'): RunOut('"abcdefghijkl"', cost: 131), @@ -682,13 +734,16 @@ void main() { // substr-08 RunIn('(substr (q . "abcdefghijkl") 2 5)', solution: '(0 13)'): null, // substr-09 - RunIn('(substr (q . "abcdefghijkl") 2 5)', solution: '(10 10)'): RunOut('()', cost: 131), + RunIn('(substr (q . "abcdefghijkl") 2 5)', solution: '(10 10)'): + RunOut('()', cost: 131), // substr-10 RunIn('(substr (q . "abcdefghijkl") 2 5)', solution: '(10 9)'): null, // substr-11 - RunIn('(substr (q . "abcdefghijkl") 2 5)', solution: '(1 4)'): RunOut('"bcd"', cost: 131), + RunIn('(substr (q . "abcdefghijkl") 2 5)', solution: '(1 4)'): + RunOut('"bcd"', cost: 131), // substr-12 - RunIn('(substr (q . "abcdefghijkl") 2 5)', solution: '(8 12)'): RunOut('"ijkl"', cost: 131), + RunIn('(substr (q . "abcdefghijkl") 2 5)', solution: '(8 12)'): + RunOut('"ijkl"', cost: 131), // substr-13 RunIn('(substr (q . ("abcdefghijkl")) 2 5)', solution: '(0 4)'): null, // substr-14 @@ -701,7 +756,8 @@ void main() { // substr-17 RunIn('(substr (q . "abcdefghijkl") 2 5)', solution: '(0 -1)'): null, // substr-18 - RunIn('(substr (q . "abcdefghijkl") 2 5)', solution: '(4294967297 3)'): null, + RunIn('(substr (q . "abcdefghijkl") 2 5)', solution: '(4294967297 3)'): + null, // trace-1 RunIn('(+ (q . 10) (f 1))', solution: '(51)'): RunOut('61', cost: 860), // trace-2 @@ -793,7 +849,8 @@ void main() { // ash-06 RunIn('(ash (q . 0xffff) (q . 0xffff))'): RunOut('-1'), // ash-07 - RunIn('(ash (q . 128) (q . 128))'): RunOut('0x008000000000000000000000000000000000'), + RunIn('(ash (q . 128) (q . 128))'): + RunOut('0x008000000000000000000000000000000000'), // ash-08 RunIn('(ash (q . -1) (q . -1))'): RunOut('-1'), // concat-01 @@ -831,7 +888,8 @@ void main() { // cons-05 RunIn('(c () ())'): RunOut('(())'), // cons-06 - RunIn('(c (q . (1 2)) (q . (1 2)))'): RunOut('((1 2) 1 2)', showKeywords: false), + RunIn('(c (q . (1 2)) (q . (1 2)))'): + RunOut('((1 2) 1 2)', showKeywords: false), // cons-07 RunIn('(c (q . 0xffff) (q . 0xffff))'): RunOut('(0xffff . 0xffff)'), // cons-08 @@ -869,7 +927,8 @@ void main() { // divmod-06 RunIn('(divmod (q . (1 2)) (q . (1 2)))'): null, // divmod-07 - RunIn('(divmod (q . 0xffff) (q . 0xffff))'): RunOut('(1)', showKeywords: false), + RunIn('(divmod (q . 0xffff) (q . 0xffff))'): + RunOut('(1)', showKeywords: false), // divmod-08 RunIn('(divmod (q . 128) (q . 128))'): RunOut('(1)', showKeywords: false), // divmod-09 @@ -957,7 +1016,8 @@ void main() { // if-06 RunIn('(i () () ())'): RunOut('()'), // if-07 - RunIn('(i (q . (1 2)) (q . (1 3)) (q . (1 4)))'): RunOut('(1 3)', showKeywords: false), + RunIn('(i (q . (1 2)) (q . (1 3)) (q . (1 4)))'): + RunOut('(1 3)', showKeywords: false), // if-08 RunIn('(i (q . 0xffff) (q . 0xffff) (q . 0xffff))'): RunOut('0xffff'), // if-09 @@ -1057,7 +1117,8 @@ void main() { // lsh-06 RunIn('(lsh (q . 0xffff) (q . 0xffff))'): RunOut('32767'), // lsh-07 - RunIn('(lsh (q . 128) (q . 128))'): RunOut('0x008000000000000000000000000000000000'), + RunIn('(lsh (q . 128) (q . 128))'): + RunOut('0x008000000000000000000000000000000000'), // lsh-08 RunIn('(lsh (q . -1) (q . -1))'): RunOut('127'), // mul-01 @@ -1179,27 +1240,28 @@ void main() { // rest-08 RunIn('(r (q . -1))'): null, // sha256-01 - RunIn('(sha256)'): RunOut('0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'), + RunIn('(sha256)'): RunOut( + '0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'), // sha256-02 - RunIn('(sha256 (q . 1))'): - RunOut('0x4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a'), + RunIn('(sha256 (q . 1))'): RunOut( + '0x4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a'), // sha256-03 - RunIn('(sha256 (q . 1) (q . 1))'): - RunOut('0x9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2'), + RunIn('(sha256 (q . 1) (q . 1))'): RunOut( + '0x9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2'), // sha256-04 - RunIn('(sha256 () ())'): - RunOut('0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'), + RunIn('(sha256 () ())'): RunOut( + '0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'), // sha256-05 RunIn('(sha256 (q . (1 2)) (q . (1 2)))'): null, // sha256-06 - RunIn('(sha256 (q . 0xffff) (q . 0xffff))'): - RunOut('0xad95131bc0b799c0b1af477fb14fcf26a6a9f76079e48bf090acb7e8367bfd0e'), + RunIn('(sha256 (q . 0xffff) (q . 0xffff))'): RunOut( + '0xad95131bc0b799c0b1af477fb14fcf26a6a9f76079e48bf090acb7e8367bfd0e'), // sha256-07 - RunIn('(sha256 (q . 128) (q . 128))'): - RunOut('0xda60b92bc70e999c07a6ded180a16c1e801e89a5722b565ea242d6aff2f507d8'), + RunIn('(sha256 (q . 128) (q . 128))'): RunOut( + '0xda60b92bc70e999c07a6ded180a16c1e801e89a5722b565ea242d6aff2f507d8'), // sha256-08 - RunIn('(sha256 (q . -1) (q . -1))'): - RunOut('0xca2fd00fa001190744c15c317643ab092e7048ce086a243e2be9437c898de1bb'), + RunIn('(sha256 (q . -1) (q . -1))'): RunOut( + '0xca2fd00fa001190744c15c317643ab092e7048ce086a243e2be9437c898de1bb'), // softfork-01 RunIn('(softfork)'): null, // softfork-02 @@ -1609,17 +1671,21 @@ void main() { // unknown-200 RunIn('(0xfffeffff00 (q . 1) (q . 2) (q . (1 10 20)))', strict: true): null, // unknown-201 - RunIn('(0xfffeffff00 (q . 1) (q . 2) (q . (1 10 20)))'): RunOut('()', cost: 4294901830), + RunIn('(0xfffeffff00 (q . 1) (q . 2) (q . (1 10 20)))'): + RunOut('()', cost: 4294901830), // unknown-202 RunIn('(0xfffeffff3f (q . 1) (q . 2) (q . (1 10 20)))', strict: true): null, // unknown-203 - RunIn('(0xfffeffff3f (q . 1) (q . 2) (q . (1 10 20)))'): RunOut('()', cost: 4294901830), + RunIn('(0xfffeffff3f (q . 1) (q . 2) (q . (1 10 20)))'): + RunOut('()', cost: 4294901830), // unknown-204 - RunIn('(0x7ffffffff00 (q . 1) (q . 2) (q . (1 10 20)))', strict: true): null, + RunIn('(0x7ffffffff00 (q . 1) (q . 2) (q . (1 10 20)))', strict: true): + null, // unknown-205 RunIn('(0x7ffffffff00 (q . 1) (q . 2) (q . (1 10 20)))'): null, // unknown-206 - RunIn('(0x7ffffffff3f (q . 1) (q . 2) (q . (1 10 20)))', strict: true): null, + RunIn('(0x7ffffffff3f (q . 1) (q . 2) (q . (1 10 20)))', strict: true): + null, // unknown-207 RunIn('(0x7ffffffff3f (q . 1) (q . 2) (q . (1 10 20)))'): null, // unknown-208 @@ -1651,11 +1717,13 @@ void main() { // unknown-22 RunIn('(0x17f )', strict: true): null, // unknown-220 - RunIn('(0x7ffffffff40 (q . 1) (q . 2) (q . (1 10 20)))', strict: true): null, + RunIn('(0x7ffffffff40 (q . 1) (q . 2) (q . (1 10 20)))', strict: true): + null, // unknown-221 RunIn('(0x7ffffffff40 (q . 1) (q . 2) (q . (1 10 20)))'): null, // unknown-222 - RunIn('(0x7ffffffff7f (q . 1) (q . 2) (q . (1 10 20)))', strict: true): null, + RunIn('(0x7ffffffff7f (q . 1) (q . 2) (q . (1 10 20)))', strict: true): + null, // unknown-223 RunIn('(0x7ffffffff7f (q . 1) (q . 2) (q . (1 10 20)))'): null, // unknown-224 @@ -1685,11 +1753,13 @@ void main() { // unknown-235 RunIn('(0xfffeffffbf (q . 1) (q . 2) (q . (1 10 20)))'): null, // unknown-236 - RunIn('(0x7ffffffff80 (q . 1) (q . 2) (q . (1 10 20)))', strict: true): null, + RunIn('(0x7ffffffff80 (q . 1) (q . 2) (q . (1 10 20)))', strict: true): + null, // unknown-237 RunIn('(0x7ffffffff80 (q . 1) (q . 2) (q . (1 10 20)))'): null, // unknown-238 - RunIn('(0x7ffffffffbf (q . 1) (q . 2) (q . (1 10 20)))', strict: true): null, + RunIn('(0x7ffffffffbf (q . 1) (q . 2) (q . (1 10 20)))', strict: true): + null, // unknown-239 RunIn('(0x7ffffffffbf (q . 1) (q . 2) (q . (1 10 20)))'): null, // unknown-24 @@ -1721,11 +1791,13 @@ void main() { // unknown-251 RunIn('(0xfffeffffff (q . 1) (q . 2) (q . (1 10 20)))'): null, // unknown-252 - RunIn('(0x7ffffffffc0 (q . 1) (q . 2) (q . (1 10 20)))', strict: true): null, + RunIn('(0x7ffffffffc0 (q . 1) (q . 2) (q . (1 10 20)))', strict: true): + null, // unknown-253 RunIn('(0x7ffffffffc0 (q . 1) (q . 2) (q . (1 10 20)))'): null, // unknown-254 - RunIn('(0x7ffffffffff (q . 1) (q . 2) (q . (1 10 20)))', strict: true): null, + RunIn('(0x7ffffffffff (q . 1) (q . 2) (q . (1 10 20)))', strict: true): + null, // unknown-255 RunIn('(0x7ffffffffff (q . 1) (q . 2) (q . (1 10 20)))'): null, // unknown-26 @@ -1823,11 +1895,13 @@ void main() { // unknown-72 RunIn('(0xfffeffff00 (q . 1) (q . 2) (q . 3))', strict: true): null, // unknown-73 - RunIn('(0xfffeffff00 (q . 1) (q . 2) (q . 3))'): RunOut('()', cost: 4294901830), + RunIn('(0xfffeffff00 (q . 1) (q . 2) (q . 3))'): + RunOut('()', cost: 4294901830), // unknown-74 RunIn('(0xfffeffff3f (q . 1) (q . 2) (q . 3))', strict: true): null, // unknown-75 - RunIn('(0xfffeffff3f (q . 1) (q . 2) (q . 3))'): RunOut('()', cost: 4294901830), + RunIn('(0xfffeffff3f (q . 1) (q . 2) (q . 3))'): + RunOut('()', cost: 4294901830), // unknown-76 RunIn('(0x7ffffffff00 (q . 1) (q . 2) (q . 3))', strict: true): null, // unknown-77 @@ -1885,7 +1959,8 @@ void main() { SerializeIn('1'): SerializeOut('01'), SerializeIn('0xffffabcdef'): SerializeOut('85ffffabcdef'), SerializeIn('"abcdef"'): SerializeOut('86616263646566'), - SerializeIn('(f (c (q . 20) (q . 30)))'): SerializeOut('ff05ffff04ffff0114ffff011e8080'), + SerializeIn('(f (c (q . 20) (q . 30)))'): + SerializeOut('ff05ffff04ffff0114ffff011e8080'), SerializeIn( '(+ 100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 100000000000000000000000000000000000))'): SerializeOut( @@ -1922,7 +1997,8 @@ void main() { : result.program.toSource(showKeywords: item.value!.showKeywords); expect(output, equals(expected.output), reason: 'Wrong output'); if (expected.cost != null) { - expect(result.cost.toInt(), equals(expected.cost! - 9), reason: 'Wrong cost'); + expect(result.cost.toInt(), equals(expected.cost! - 9), + reason: 'Wrong cost'); } } }); @@ -1947,7 +2023,8 @@ void main() { : result.program.toSource(showKeywords: item.value!.showKeywords); expect(output, equals(expected.output), reason: 'Wrong output'); if (expected.cost != null) { - expect(result.cost.toInt(), equals(expected.cost! - 9), reason: 'Wrong cost'); + expect(result.cost.toInt(), equals(expected.cost! - 9), + reason: 'Wrong cost'); } } }); @@ -1966,7 +2043,8 @@ void main() { } else { var puzzleProgram = Program.parse(puzzle); var expected = item.value!; - expect(puzzleProgram.toHex(), equals(expected.output), reason: 'Wrong output'); + expect(puzzleProgram.toHex(), equals(expected.output), + reason: 'Wrong output'); } }); } diff --git a/test/clvm/deserialization/deserialization_test.dart b/test/clvm/deserialization/deserialization_test.dart index 3e716b65..12eb6f62 100644 --- a/test/clvm/deserialization/deserialization_test.dart +++ b/test/clvm/deserialization/deserialization_test.dart @@ -7,7 +7,8 @@ import 'package:test/scaffolding.dart'; void main() { final imageBytes = - File(path.join(path.current, 'test/clvm/deserialization/image.jpeg')).readAsBytesSync(); + File(path.join(path.current, 'test/clvm/deserialization/image.jpeg')) + .readAsBytesSync(); test('should correctly serialize and deserialize a big clvm program', () { final bigProgram = Program.fromAtom(imageBytes); diff --git a/test/coin_splitting/split_calculation_test.dart b/test/coin_splitting/split_calculation_test.dart index daca3ff1..dac54932 100644 --- a/test/coin_splitting/split_calculation_test.dart +++ b/test/coin_splitting/split_calculation_test.dart @@ -67,8 +67,10 @@ void main() { }; test('should correctly calculate number of binary splits', () { - binarySplittingInputToExpectedOutputMap.forEach((desiredNumberOfCoins, expectedNumberOfSplits) { - final numberOfSplits = CoinSplittingService.calculateNumberOfNWidthSplitsRequired( + binarySplittingInputToExpectedOutputMap + .forEach((desiredNumberOfCoins, expectedNumberOfSplits) { + final numberOfSplits = + CoinSplittingService.calculateNumberOfNWidthSplitsRequired( desiredNumberOfCoins: desiredNumberOfCoins, initialSplitWidth: 2, ); @@ -76,7 +78,8 @@ void main() { final resultingCoinsFromNWidthSplits = pow(2, numberOfSplits).toInt(); - final numberOfDecaSplits = CoinSplittingService.calculateNumberOfDecaSplitsRequired( + final numberOfDecaSplits = + CoinSplittingService.calculateNumberOfDecaSplitsRequired( resultingCoinsFromNWidthSplits, desiredNumberOfCoins, ); @@ -85,8 +88,10 @@ void main() { }); test('should correctly calculate number of 7 splits', () { - septSplittingInputToExpectedOutputMap.forEach((desiredNumberOfCoins, expectedNumberOfSplits) { - final numberOfSplits = CoinSplittingService.calculateNumberOfNWidthSplitsRequired( + septSplittingInputToExpectedOutputMap + .forEach((desiredNumberOfCoins, expectedNumberOfSplits) { + final numberOfSplits = + CoinSplittingService.calculateNumberOfNWidthSplitsRequired( desiredNumberOfCoins: desiredNumberOfCoins, initialSplitWidth: 7, ); @@ -94,7 +99,8 @@ void main() { final resultingCoinsFromNWidthSplits = pow(7, numberOfSplits).toInt(); - final numberOfDecaSplits = CoinSplittingService.calculateNumberOfDecaSplitsRequired( + final numberOfDecaSplits = + CoinSplittingService.calculateNumberOfDecaSplitsRequired( resultingCoinsFromNWidthSplits, desiredNumberOfCoins, ); @@ -105,7 +111,8 @@ void main() { test('should correctly calculate number of 400 splits', () { forHundredSplittingInputToExpectedOutputMap .forEach((desiredNumberOfCoins, expectedNumberOfSplits) { - final numberOfSplits = CoinSplittingService.calculateNumberOfNWidthSplitsRequired( + final numberOfSplits = + CoinSplittingService.calculateNumberOfNWidthSplitsRequired( desiredNumberOfCoins: desiredNumberOfCoins, initialSplitWidth: 400, ); @@ -113,7 +120,8 @@ void main() { final resultingCoinsFromNWidthSplits = pow(400, numberOfSplits).toInt(); - final numberOfDecaSplits = CoinSplittingService.calculateNumberOfDecaSplitsRequired( + final numberOfDecaSplits = + CoinSplittingService.calculateNumberOfDecaSplitsRequired( resultingCoinsFromNWidthSplits, desiredNumberOfCoins, ); diff --git a/test/condition_stripping_test.dart b/test/condition_stripping_test.dart new file mode 100644 index 00000000..50c7dceb --- /dev/null +++ b/test/condition_stripping_test.dart @@ -0,0 +1,18 @@ +import 'package:chia_crypto_utils/chia_crypto_utils.dart'; + +void main() { + final createCoinConditionProgram = CreateCoinCondition( + Puzzlehash.fromHex( + '4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a', + ), + 200, + memos: [ + Puzzlehash.fromHex( + '9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2', + ) + ], + ).toProgram(); + print(createCoinConditionProgram.first()); + print(createCoinConditionProgram.rest().first()); + print(createCoinConditionProgram.rest().rest().first()); +} diff --git a/test/context/full_node_context_test.dart b/test/context/full_node_context_test.dart index 381fa087..0b97658a 100644 --- a/test/context/full_node_context_test.dart +++ b/test/context/full_node_context_test.dart @@ -3,7 +3,8 @@ import 'package:test/test.dart'; void main() { const testUrl = 'https://full-node-url.dev'; - final testCertificateBytes = Bytes.encodeFromString('these are certificate bytes'); + final testCertificateBytes = + Bytes.encodeFromString('these are certificate bytes'); final testKeyBytes = Bytes.encodeFromString('these are key bytes'); test('should save full node context correctly', () { FullNodeContext().setUrl(testUrl); diff --git a/test/context/logging_context_test.dart b/test/context/logging_context_test.dart index f911ad59..e74663a4 100644 --- a/test/context/logging_context_test.dart +++ b/test/context/logging_context_test.dart @@ -46,7 +46,8 @@ void main() { const lowLogLevelTextToLog = 'Howdy partner'; const mediumLogLevelTextToLog = 'Howdy partner, hows weather?'; - const highLogLevelTextToLog = 'Howdy partner, hows the weather in Guadalajara?'; + const highLogLevelTextToLog = + 'Howdy partner, hows the weather in Guadalajara?'; logFunction( lowLogLevelTextToLog, mediumLog: mediumLogLevelTextToLog, diff --git a/test/context/pool_context_test.dart b/test/context/pool_context_test.dart index 6fc270f1..440e70cc 100644 --- a/test/context/pool_context_test.dart +++ b/test/context/pool_context_test.dart @@ -3,7 +3,8 @@ import 'package:test/test.dart'; void main() { const testPoolUrl = 'https://cool-pool.io'; - final testCertificateBytes = Bytes.encodeFromString('these are certificate bytes'); + final testCertificateBytes = + Bytes.encodeFromString('these are certificate bytes'); test('should save full node context correctly', () { PoolContext().setPoolUrl(testPoolUrl); diff --git a/test/core/address_parsing_test.dart b/test/core/address_parsing_test.dart index 12e95d27..e0aefacc 100644 --- a/test/core/address_parsing_test.dart +++ b/test/core/address_parsing_test.dart @@ -3,7 +3,8 @@ import 'package:test/test.dart'; void main() { final mainnetAddresses = _CryptoAddresses( - xchAddress: 'xch1076qvs03vfdj8kyzzs9uulg3pzj5d8y9k0tzxp5ph06svu6wx0us6vltu9', + xchAddress: + 'xch1076qvs03vfdj8kyzzs9uulg3pzj5d8y9k0tzxp5ph06svu6wx0us6vltu9', btcAddresses: [ '1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2', //P2PKH '3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy', //P2SH diff --git a/test/core/keychain_test.dart b/test/core/keychain_test.dart index 76a552a8..13242a5a 100644 --- a/test/core/keychain_test.dart +++ b/test/core/keychain_test.dart @@ -11,7 +11,10 @@ void main() { } test('should get random puzzlehash', () { - expect(() => getNPuzzlehashes(0).random, throwsA(const TypeMatcher())); + expect( + () => getNPuzzlehashes(0).random, + throwsA(const TypeMatcher()), + ); for (var i = 1; i < 50; i++) { getNPuzzlehashes(i).random; } diff --git a/test/core/mnemonic_parsing_test.dart b/test/core/mnemonic_parsing_test.dart index 00b63691..4752816c 100644 --- a/test/core/mnemonic_parsing_test.dart +++ b/test/core/mnemonic_parsing_test.dart @@ -5,7 +5,8 @@ void main() { final secret = KeychainCoreSecret.generate(); test('should correctly parse mnemonic', () { - final fromString = KeychainCoreSecret.fromMnemonicString(secret.mnemonicString); + final fromString = + KeychainCoreSecret.fromMnemonicString(secret.mnemonicString); expect(fromString.fingerprint, secret.fingerprint); expect(fromString.mnemonicString, secret.mnemonicString); expect(fromString.mnemonic, secret.mnemonic); diff --git a/test/core/reserve_fee_condition_check.dart b/test/core/reserve_fee_condition_check.dart index 7b3fbf6f..3d78d5a0 100644 --- a/test/core/reserve_fee_condition_check.dart +++ b/test/core/reserve_fee_condition_check.dart @@ -3,15 +3,27 @@ import 'package:test/test.dart'; void main() { test('should determine if condition is reserve fee condition', () { - final createCoinCondition = CreateCoinCondition(Program.fromBool(false).hash(), 5); - final aggSigMeCondition = - AggSigMeCondition(JacobianPoint.generateG1(), Bytes.encodeFromString('yo')); + final createCoinCondition = + CreateCoinCondition(Program.fromBool(false).hash(), 5); + final aggSigMeCondition = AggSigMeCondition( + JacobianPoint.generateG1(), + Bytes.encodeFromString('yo'), + ); final reserveFeeCondition = ReserveFeeCondition(5); - expect(ReserveFeeCondition.isThisCondition(reserveFeeCondition.toProgram()), true); - expect(ReserveFeeCondition.isThisCondition(aggSigMeCondition.toProgram()), false); - expect(ReserveFeeCondition.isThisCondition(createCoinCondition.toProgram()), false); + expect( + ReserveFeeCondition.isThisCondition(reserveFeeCondition.toProgram()), + true, + ); + expect( + ReserveFeeCondition.isThisCondition(aggSigMeCondition.toProgram()), + false, + ); + expect( + ReserveFeeCondition.isThisCondition(createCoinCondition.toProgram()), + false, + ); final serialized = reserveFeeCondition.toProgram(); final deserialized = ReserveFeeCondition.fromProgram(serialized); diff --git a/test/core/reverse_engineer_spend_bundle_test.dart b/test/core/reverse_engineer_spend_bundle_test.dart index af517c85..38c59ddf 100644 --- a/test/core/reverse_engineer_spend_bundle_test.dart +++ b/test/core/reverse_engineer_spend_bundle_test.dart @@ -4,8 +4,9 @@ import 'package:test/expect.dart'; import 'package:test/scaffolding.dart'; void main() async { - final coinId = - Bytes.fromHex('0xc6bea28d7d6ccb64bdc6eef90743d2f7b9578224b35c98cec785447b6aabf004'); + final coinId = Bytes.fromHex( + '0xc6bea28d7d6ccb64bdc6eef90743d2f7b9578224b35c98cec785447b6aabf004', + ); ChiaNetworkContextWrapper().registerNetworkContext(Network.mainnet); final fullNode = EnhancedChiaFullNodeInterface.fromUrl('FULL_NODE_URL'); @@ -13,8 +14,9 @@ void main() async { test('should construct spend bundle for coin', () async { final spendBundle = await SpendBundle.ofCoin(coinId, fullNode); - final fetchedCoinSpends = - await fullNode.getCoinSpendsByIds(spendBundle!.coinSpends.map((e) => e.coin.id).toList()); + final fetchedCoinSpends = await fullNode.getCoinSpendsByIds( + spendBundle!.coinSpends.map((e) => e.coin.id).toList(), + ); for (final spendBundleCoinSpend in spendBundle.coinSpends) { expect(fetchedCoinSpends.containsValue(spendBundleCoinSpend), true); diff --git a/test/core/spend_bundle_serialization_test.dart b/test/core/spend_bundle_serialization_test.dart index 730ee6e9..1e759b25 100644 --- a/test/core/spend_bundle_serialization_test.dart +++ b/test/core/spend_bundle_serialization_test.dart @@ -13,7 +13,8 @@ void main() { // json of spendBundle from CAT-admin-tool const spendBundleJson = '{"aggregated_signature": "aeddfb01b15e715d5e467b008a4001d92addaf746d934722b6a2e19685826d29ae4b196027a6e4a6f29817ce7e36e56b01a00ba2f077db8da53c03e6e1d4f206f1ddbe03322e00438b24ab75870ac7627af2f8eed311e0b9de3a56edbcf29fde", "coin_spends": [{"coin": {"parent_coin_info": "0x4c51ae3b978a03024fa4f1b53a5b9bf30c9edafc9d47e72a9cc41b58768373bd", "puzzle_hash": "0x2668d136b5b5bab998ca966b05750172c0d853f0dd37f2653e0ff9ba37b3377e", "amount": 899999869900}, "puzzle_reveal": "0xff02ffff01ff02ffff01ff02ffff03ff0bffff01ff02ffff03ffff09ff05ffff1dff0bffff1effff0bff0bffff02ff06ffff04ff02ffff04ff17ff8080808080808080ffff01ff02ff17ff2f80ffff01ff088080ff0180ffff01ff04ffff04ff04ffff04ff05ffff04ffff02ff06ffff04ff02ffff04ff17ff80808080ff80808080ffff02ff17ff2f808080ff0180ffff04ffff01ff32ff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff06ffff04ff02ffff04ff09ff80808080ffff02ff06ffff04ff02ffff04ff0dff8080808080ffff01ff0bffff0101ff058080ff0180ff018080ffff04ffff01b0a1a7af6fae2dd8f6b6b80cac601f25ea116ece416b3af96303a1858c18d4c3d8738e6135385d3125ddaf1c18cc6e702dff018080", "solution": "0xff80ffff01ffff33ffa01c2121e077ca2d57e3a447718fa42c3064bdf13bc7bf07bb3f39d084beb8c23eff82271080ffff33ffa0bee26c7bd6ff40acde47ceca5338b0d1cb098d3d7c939ba2e00489f3edd5fbd1ff8600d18c2c04bc80ffff3cffa06872470ed8253f2a910134f839de55391e49f8fa3af9c6aff1289a0633617afe8080ff8080"}, {"coin": {"parent_coin_info": "0x7f4f681abcc8e76b9f816a9cecf2baf23178b01882a74fced57c1428beceec33", "puzzle_hash": "0x1c2121e077ca2d57e3a447718fa42c3064bdf13bc7bf07bb3f39d084beb8c23e", "amount": 10000}, "puzzle_reveal": "0xff02ffff01ff02ffff01ff02ff5effff04ff02ffff04ffff04ff05ffff04ffff0bff2cff0580ffff04ff0bff80808080ffff04ffff02ff17ff2f80ffff04ff5fffff04ffff02ff2effff04ff02ffff04ff17ff80808080ffff04ffff0bff82027fff82057fff820b7f80ffff04ff81bfffff04ff82017fffff04ff8202ffffff04ff8205ffffff04ff820bffff80808080808080808080808080ffff04ffff01ffffffff81ca3dff46ff0233ffff3c04ff01ff0181cbffffff02ff02ffff03ff05ffff01ff02ff32ffff04ff02ffff04ff0dffff04ffff0bff22ffff0bff2cff3480ffff0bff22ffff0bff22ffff0bff2cff5c80ff0980ffff0bff22ff0bffff0bff2cff8080808080ff8080808080ffff010b80ff0180ffff02ffff03ff0bffff01ff02ffff03ffff09ffff02ff2effff04ff02ffff04ff13ff80808080ff820b9f80ffff01ff02ff26ffff04ff02ffff04ffff02ff13ffff04ff5fffff04ff17ffff04ff2fffff04ff81bfffff04ff82017fffff04ff1bff8080808080808080ffff04ff82017fff8080808080ffff01ff088080ff0180ffff01ff02ffff03ff17ffff01ff02ffff03ffff20ff81bf80ffff0182017fffff01ff088080ff0180ffff01ff088080ff018080ff0180ffff04ffff04ff05ff2780ffff04ffff10ff0bff5780ff778080ff02ffff03ff05ffff01ff02ffff03ffff09ffff02ffff03ffff09ff11ff7880ffff0159ff8080ff0180ffff01818f80ffff01ff02ff7affff04ff02ffff04ff0dffff04ff0bffff04ffff04ff81b9ff82017980ff808080808080ffff01ff02ff5affff04ff02ffff04ffff02ffff03ffff09ff11ff7880ffff01ff04ff78ffff04ffff02ff36ffff04ff02ffff04ff13ffff04ff29ffff04ffff0bff2cff5b80ffff04ff2bff80808080808080ff398080ffff01ff02ffff03ffff09ff11ff2480ffff01ff04ff24ffff04ffff0bff20ff2980ff398080ffff010980ff018080ff0180ffff04ffff02ffff03ffff09ff11ff7880ffff0159ff8080ff0180ffff04ffff02ff7affff04ff02ffff04ff0dffff04ff0bffff04ff17ff808080808080ff80808080808080ff0180ffff01ff04ff80ffff04ff80ff17808080ff0180ffffff02ffff03ff05ffff01ff04ff09ffff02ff26ffff04ff02ffff04ff0dffff04ff0bff808080808080ffff010b80ff0180ff0bff22ffff0bff2cff5880ffff0bff22ffff0bff22ffff0bff2cff5c80ff0580ffff0bff22ffff02ff32ffff04ff02ffff04ff07ffff04ffff0bff2cff2c80ff8080808080ffff0bff2cff8080808080ffff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff2effff04ff02ffff04ff09ff80808080ffff02ff2effff04ff02ffff04ff0dff8080808080ffff01ff0bff2cff058080ff0180ffff04ffff04ff28ffff04ff5fff808080ffff02ff7effff04ff02ffff04ffff04ffff04ff2fff0580ffff04ff5fff82017f8080ffff04ffff02ff7affff04ff02ffff04ff0bffff04ff05ffff01ff808080808080ffff04ff17ffff04ff81bfffff04ff82017fffff04ffff0bff8204ffffff02ff36ffff04ff02ffff04ff09ffff04ff820affffff04ffff0bff2cff2d80ffff04ff15ff80808080808080ff8216ff80ffff04ff8205ffffff04ff820bffff808080808080808080808080ff02ff2affff04ff02ffff04ff5fffff04ff3bffff04ffff02ffff03ff17ffff01ff09ff2dffff0bff27ffff02ff36ffff04ff02ffff04ff29ffff04ff57ffff04ffff0bff2cff81b980ffff04ff59ff80808080808080ff81b78080ff8080ff0180ffff04ff17ffff04ff05ffff04ff8202ffffff04ffff04ffff04ff24ffff04ffff0bff7cff2fff82017f80ff808080ffff04ffff04ff30ffff04ffff0bff81bfffff0bff7cff15ffff10ff82017fffff11ff8202dfff2b80ff8202ff808080ff808080ff138080ff80808080808080808080ff018080ffff04ffff01a072dec062874cd4d3aab892a0906688a1ae412b0109982e1797a170add88bdcdcffff04ffff01a0625c2184e97576f5df1be46c15b2b8771c79e4e6f0aa42d3bfecaebe733f4b8cffff04ffff01ff01ffff33ff80ff818fffff02ffff01ff02ffff01ff04ffff04ff04ffff04ff05ffff04ffff02ff06ffff04ff02ffff04ff82027fff80808080ff80808080ffff02ff82027fffff04ff0bffff04ff17ffff04ff2fffff04ff5fffff04ff81bfff82057f80808080808080ffff04ffff01ff31ff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff06ffff04ff02ffff04ff09ff80808080ffff02ff06ffff04ff02ffff04ff0dff8080808080ffff01ff0bffff0101ff058080ff0180ff018080ffff04ffff01b0add4758d972b7c2bd84798749ee2094c0c9e52b5b6618c985d4a8e841bf464a4079efa01e372d2307b6c26e6d1cceae6ff018080ffffff02ffff01ff02ffff03ff2fffff01ff0880ffff01ff02ffff03ffff09ff2dff0280ff80ffff01ff088080ff018080ff0180ffff04ffff01a026081b15441311d9a207a078b650a05766975814fd5aa6935a759ddaf2a05af0ff018080ff808080ffff33ffa00b7a3d5e723e0b046fd51f95cabf2d3e2616f05d9d1833e8166052b43d9454adff822710ffffa00b7a3d5e723e0b046fd51f95cabf2d3e2616f05d9d1833e8166052b43d9454ad808080ff0180808080", "solution": "0xff80ff80ffa0691e1d0bcf9ac53e2c50578c98f96aa3fca155e867dd20f18f3b1830541488f3ffffa07f4f681abcc8e76b9f816a9cecf2baf23178b01882a74fced57c1428beceec33ffa01c2121e077ca2d57e3a447718fa42c3064bdf13bc7bf07bb3f39d084beb8c23eff82271080ffffa07f4f681abcc8e76b9f816a9cecf2baf23178b01882a74fced57c1428beceec33ffa0b0d05bdb7ed1b96763a8cec0a67ad6c76f129da3417f2ea220a62a9858f45e83ff82271080ff80ff8080"}]}'; - final spendBundle = SpendBundle.fromJson(jsonDecode(spendBundleJson) as Map); + final spendBundle = + SpendBundle.fromJson(jsonDecode(spendBundleJson) as Map); test('should correctly serialize SpendBundle', () { expect(spendBundle.toHex(), equals(spendBundleSerializedHex)); diff --git a/test/did/did_test.dart b/test/did/did_test.dart index d0882b4e..82dbe1db 100644 --- a/test/did/did_test.dart +++ b/test/did/did_test.dart @@ -42,7 +42,8 @@ void main() { }); test('should fail with coin mismatch', () { expect( - () => DidRecord.fromParentCoinSpend(parentSpend, otherCoin)!.toDidInfoOrThrow(ownerKeychain), + () => DidRecord.fromParentCoinSpend(parentSpend, otherCoin)! + .toDidInfoOrThrow(ownerKeychain), throwsA(isA()), ); }); @@ -54,8 +55,10 @@ void main() { ); }); - test('should correctly construct DID record from parent spend asynchronously', () async { - final didRecordAsync = await DidRecord.fromParentCoinSpendAsync(parentSpend, coin); + test('should correctly construct DID record from parent spend asynchronously', + () async { + final didRecordAsync = + await DidRecord.fromParentCoinSpendAsync(parentSpend, coin); expect( didRecordAsync!.toDidInfoOrThrow(ownerKeychain), diff --git a/test/did/invalid_did_exception_test.dart b/test/did/invalid_did_exception_test.dart index 531ea05e..70abbbab 100644 --- a/test/did/invalid_did_exception_test.dart +++ b/test/did/invalid_did_exception_test.dart @@ -9,6 +9,9 @@ void main() { test('should return the desired string form with message', () { const message = 'Invalid DID exception message'; - expect(InvalidDidException(message: message).toString(), 'Coin is not a DID: $message'); + expect( + InvalidDidException(message: message).toString(), + 'Coin is not a DID: $message', + ); }); } diff --git a/test/did/invalid_did_spend_mode_code_exception_test.dart b/test/did/invalid_did_spend_mode_code_exception_test.dart index 55198840..8c9eaf50 100644 --- a/test/did/invalid_did_spend_mode_code_exception_test.dart +++ b/test/did/invalid_did_spend_mode_code_exception_test.dart @@ -4,7 +4,8 @@ import 'package:test/scaffolding.dart'; void main() { test('should return the desired string form with message', () { - final invalidDIDSpendModeCodeException = InvalidDIDSpendModeCodeException(invalidCode: 2); + final invalidDIDSpendModeCodeException = + InvalidDIDSpendModeCodeException(invalidCode: 2); expect( invalidDIDSpendModeCodeException.toString(), 'Spend mode code ${invalidDIDSpendModeCodeException.invalidCode} is invalid. ' diff --git a/test/did/sign_did_bundle_test.dart b/test/did/sign_did_bundle_test.dart index 196560d2..9333a49b 100644 --- a/test/did/sign_did_bundle_test.dart +++ b/test/did/sign_did_bundle_test.dart @@ -10,13 +10,15 @@ void main() { ) as Map, ); - final privateKey = - PrivateKey.fromHex('0ebdfc43fb7be1f78a50782ed76251520de6686b80e645f0b4e658868a9e792f'); + final privateKey = PrivateKey.fromHex( + '0ebdfc43fb7be1f78a50782ed76251520de6686b80e645f0b4e658868a9e792f', + ); final fullDidPuzzle = spendBundle.coinSpends.single.puzzleReveal; - final p2FromDriver = - PuzzleDriver.match(fullDidPuzzle)!.getP2Puzzle(spendBundle.coinSpends.single).hash(); + final p2FromDriver = PuzzleDriver.match(fullDidPuzzle)! + .getP2Puzzle(spendBundle.coinSpends.single) + .hash(); print(p2FromDriver); diff --git a/test/did/spend_mode_test.dart b/test/did/spend_mode_test.dart index 4ef94969..3f7db1f1 100644 --- a/test/did/spend_mode_test.dart +++ b/test/did/spend_mode_test.dart @@ -4,6 +4,9 @@ import 'package:test/scaffolding.dart'; void main() { test('should fail on invalid spend mode code', () { - expect(() => SpendMode.fromCode(2), throwsA(isA())); + expect( + () => SpendMode.fromCode(2), + throwsA(isA()), + ); }); } diff --git a/test/exchange/btc/cross_chain_offer/dexie_test.dart b/test/exchange/btc/cross_chain_offer/dexie_test.dart index 7045e9f1..3f5c9566 100644 --- a/test/exchange/btc/cross_chain_offer/dexie_test.dart +++ b/test/exchange/btc/cross_chain_offer/dexie_test.dart @@ -5,58 +5,45 @@ import 'package:test/test.dart'; Future main() async { final dexieApi = DexieExchangeOfferApi(); - final currentUnixTimestamp = DateTime.now().millisecondsSinceEpoch ~/ 1000; - final offerValidityTime = currentUnixTimestamp + 3600; - const offeredAmount = ExchangeAmount(type: ExchangeAmountType.XCH, amount: 1000000000000); - const requestedAmount = ExchangeAmount(type: ExchangeAmountType.BTC, amount: 200000); - const messageAddress = Address('xch1m29jusdya59y5g3qhsqqd2tqwn0kgh2fg8ux7xt9x4vzs7927rmqmhsu02'); + final initializationCoinId = Bytes.fromHex( + '5db0138082bf1aa2144b736d67bdbcaa7d2cd9b07bab3bba15c8cd3d97df7eb4', + ); + final currentUnixTimeStamp = DateTime.now().millisecondsSinceEpoch ~/ 1000; + final offerValidityTime = currentUnixTimeStamp + 3600; + const offeredAmount = + ExchangeAmount(type: ExchangeAmountType.XCH, amount: 1000000000000); + const requestedAmount = + ExchangeAmount(type: ExchangeAmountType.BTC, amount: 200000); + const messageAddress = + Address('xch1m29jusdya59y5g3qhsqqd2tqwn0kgh2fg8ux7xt9x4vzs7927rmqmhsu02'); const serializedLightningPaymentRequest = 'lnbc2m1pjq55klpp5trkvjhdsplmnsg458yaesk7ejpe4e3a4zx4tqucaqcl8ekh6j9vqdqqcqzzgxqyz5vqrzjqwnvuc0u4txn35cafc7w94gxvq5p3cu9dd95f7hlrh0fvs46wpvhdertnqk95dh65cqqqqryqqqqthqqpyrzjqw8c7yfutqqy3kz8662fxutjvef7q2ujsxtt45csu0k688lkzu3ldertnqk95dh65cqqqqryqqqqthqqpysp5t9es5tal7dzrzu9t076w54qyr9h9eeguk0yw5efywn8898lg53gq9qypqsqr3c469cu5t6wd6zmsequvp33ccvg83aymgs2hj6ljrzkngk8y73knlj7zdtnt82jzths0mp87e9uenr2ejj05nwqsjcwc0s54gnnteqqlg9uls'; - final lightningPaymentRequest = decodeLightningPaymentRequest(serializedLightningPaymentRequest); - - group( - 'should successfully send post request with offer file to dexie', - () { - test('without initialization coin id', () async { - final privateKey = PrivateKey.generate(); - final publicKey = privateKey.getG1(); - - final offerFile = XchToBtcMakerOfferFile( - offeredAmount: offeredAmount, - requestedAmount: requestedAmount, - messageAddress: messageAddress, - validityTime: offerValidityTime, - publicKey: publicKey, - lightningPaymentRequest: lightningPaymentRequest, - ); - - final serializedOfferFile = offerFile.serialize(privateKey); - final response = await dexieApi.postOffer(serializedOfferFile); - - expect(response.success, equals(true)); - }); - - test('with initialization coin id', () async { - final privateKey = PrivateKey.generate(); - final publicKey = privateKey.getG1(); - - final offerFile = XchToBtcMakerOfferFile( - initializationCoinId: - Bytes.fromHex('5db0138082bf1aa2144b736d67bdbcaa7d2cd9b07bab3bba15c8cd3d97df7eb4'), - offeredAmount: offeredAmount, - requestedAmount: requestedAmount, - messageAddress: messageAddress, - validityTime: offerValidityTime, - publicKey: publicKey, - lightningPaymentRequest: lightningPaymentRequest, - ); - - final serializedOfferFile = offerFile.serialize(privateKey); - - final response = await dexieApi.postOffer(serializedOfferFile); - - expect(response.success, equals(true)); - }); + final lightningPaymentRequest = + decodeLightningPaymentRequest(serializedLightningPaymentRequest); + + test( + 'should send post request to dexie', + () async { + final privateKey = PrivateKey.generate(); + final publicKey = privateKey.getG1(); + + final offerFile = XchToBtcMakerOfferFile( + initializationCoinId: Bytes.fromHex( + '5db0138082bf1aa2144b736d67bdbcaa7d2cd9b07bab3bba15c8cd3d97df7eb4', + ), + offeredAmount: offeredAmount, + requestedAmount: requestedAmount, + messageAddress: messageAddress, + validityTime: offerValidityTime, + publicKey: publicKey, + lightningPaymentRequest: lightningPaymentRequest, + ); + + final serializedOfferFile = offerFile.serialize(privateKey); + + final response = await dexieApi.postOffer(serializedOfferFile); + + expect(response.success, equals(true)); }, skip: 'sends post request to dexie', ); @@ -70,11 +57,13 @@ Future main() async { expect(response.offerJson!['id'], equals(dexieId)); }); - test('inspect offer query should fail if offer has not been posted', () async { + test('inspect offer query should fail if offer has not been posted', + () async { final privateKey = PrivateKey.generate(); final publicKey = privateKey.getG1(); final offerFile = XchToBtcMakerOfferFile( + initializationCoinId: initializationCoinId, offeredAmount: offeredAmount, requestedAmount: requestedAmount, messageAddress: messageAddress, diff --git a/test/exchange/btc/cross_chain_offer/offer_file_serialization_test.dart b/test/exchange/btc/cross_chain_offer/offer_file_serialization_test.dart index 743c88d0..69a9135d 100644 --- a/test/exchange/btc/cross_chain_offer/offer_file_serialization_test.dart +++ b/test/exchange/btc/cross_chain_offer/offer_file_serialization_test.dart @@ -3,31 +3,39 @@ import 'package:chia_crypto_utils/src/exchange/btc/cross_chain_offer/exceptions/ import 'package:test/test.dart'; void main() { - test('should correctly serialize and deserialize XCH to BTC offer file', () { - final privateKey = - PrivateKey.fromHex('308f34305ed545c7b6bdefe9fff88176dc3b1a68c40f9065e2cf24c98bf6a4e1'); + final initializationCoinId = Bytes.fromHex( + '5db0138082bf1aa2144b736d67bdbcaa7d2cd9b07bab3bba15c8cd3d97df7eb4', + ); - const offeredAmount = ExchangeAmount(type: ExchangeAmountType.XCH, amount: 1000); + final privateKey = PrivateKey.fromHex( + '308f34305ed545c7b6bdefe9fff88176dc3b1a68c40f9065e2cf24c98bf6a4e1', + ); + final publicKey = privateKey.getG1(); - const requestedAmount = ExchangeAmount(type: ExchangeAmountType.BTC, amount: 1); + const messageAddress = + Address('xch1m29jusdya59y5g3qhsqqd2tqwn0kgh2fg8ux7xt9x4vzs7927rmqmhsu02'); - const messageAddress = - Address('xch1m29jusdya59y5g3qhsqqd2tqwn0kgh2fg8ux7xt9x4vzs7927rmqmhsu02'); + const offerValidityTime = 1671649043; - final publicKey = privateKey.getG1(); + const exchangeValidityTime = 3600; - const paymentRequest = - 'lnbc1u1p3huyzkpp5vw6fkrw9lr3pvved40zpp4jway4g4ee6uzsaj208dxqxgm2rtkvqdqqcqzzgxqyz5vqrzjqwnvuc0u4txn35cafc7w94gxvq5p3cu9dd95f7hlrh0fvs46wpvhdrxkxglt5qydruqqqqryqqqqthqqpyrzjqw8c7yfutqqy3kz8662fxutjvef7q2ujsxtt45csu0k688lkzu3ldrxkxglt5qydruqqqqryqqqqthqqpysp5jzgpj4990chtj9f9g2f6mhvgtzajzckx774yuh0klnr3hmvrqtjq9qypqsqkrvl3sqd4q4dm9axttfa6frg7gffguq3rzuvvm2fpuqsgg90l4nz8zgc3wx7gggm04xtwq59vftm25emwp9mtvmvjg756dyzn2dm98qpakw4u8'; + const paymentRequest = + 'lnbc1u1p3huyzkpp5vw6fkrw9lr3pvved40zpp4jway4g4ee6uzsaj208dxqxgm2rtkvqdqqcqzzgxqyz5vqrzjqwnvuc0u4txn35cafc7w94gxvq5p3cu9dd95f7hlrh0fvs46wpvhdrxkxglt5qydruqqqqryqqqqthqqpyrzjqw8c7yfutqqy3kz8662fxutjvef7q2ujsxtt45csu0k688lkzu3ldrxkxglt5qydruqqqqryqqqqthqqpysp5jzgpj4990chtj9f9g2f6mhvgtzajzckx774yuh0klnr3hmvrqtjq9qypqsqkrvl3sqd4q4dm9axttfa6frg7gffguq3rzuvvm2fpuqsgg90l4nz8zgc3wx7gggm04xtwq59vftm25emwp9mtvmvjg756dyzn2dm98qpakw4u8'; + final decodedPaymentRequest = decodeLightningPaymentRequest(paymentRequest); - const validityTime = 1671649043; + test('should correctly serialize and deserialize XCH to BTC offer file', () { + const offeredAmount = + ExchangeAmount(type: ExchangeAmountType.XCH, amount: 1000); - final decodedPaymentRequest = decodeLightningPaymentRequest(paymentRequest); + const requestedAmount = + ExchangeAmount(type: ExchangeAmountType.BTC, amount: 1); final offerFile = XchToBtcMakerOfferFile( + initializationCoinId: initializationCoinId, offeredAmount: offeredAmount, requestedAmount: requestedAmount, messageAddress: messageAddress, - validityTime: validityTime, + validityTime: offerValidityTime, publicKey: publicKey, lightningPaymentRequest: decodedPaymentRequest, ); @@ -36,10 +44,14 @@ void main() { final deserializedOfferFile = XchToBtcMakerOfferFile.fromSerializedOfferFile(serializedOfferFile); + expect( + deserializedOfferFile.initializationCoinId, + equals(initializationCoinId), + ); expect(deserializedOfferFile.offeredAmount, equals(offeredAmount)); expect(deserializedOfferFile.requestedAmount, equals(requestedAmount)); expect(deserializedOfferFile.messageAddress, equals(messageAddress)); - expect(deserializedOfferFile.validityTime, equals(validityTime)); + expect(deserializedOfferFile.validityTime, equals(offerValidityTime)); expect(deserializedOfferFile.publicKey, equals(publicKey)); expect( deserializedOfferFile.lightningPaymentRequest.paymentRequest, @@ -48,25 +60,18 @@ void main() { }); test('should correctly serialize and deserialize BTC to XCH offer file', () { - final privateKey = - PrivateKey.fromHex('308f34305ed545c7b6bdefe9fff88176dc3b1a68c40f9065e2cf24c98bf6a4e1'); - - const offeredAmount = ExchangeAmount(type: ExchangeAmountType.BTC, amount: 1); + const offeredAmount = + ExchangeAmount(type: ExchangeAmountType.BTC, amount: 1); - const requestedAmount = ExchangeAmount(type: ExchangeAmountType.XCH, amount: 1000); - - const messageAddress = - Address('xch1m29jusdya59y5g3qhsqqd2tqwn0kgh2fg8ux7xt9x4vzs7927rmqmhsu02'); - - final publicKey = privateKey.getG1(); - - const validityTime = 1671649043; + const requestedAmount = + ExchangeAmount(type: ExchangeAmountType.XCH, amount: 1000); final offerFile = BtcToXchMakerOfferFile( + initializationCoinId: initializationCoinId, offeredAmount: offeredAmount, requestedAmount: requestedAmount, messageAddress: messageAddress, - validityTime: validityTime, + validityTime: offerValidityTime, publicKey: publicKey, ); @@ -74,77 +79,85 @@ void main() { final deserializedOfferFile = BtcToXchMakerOfferFile.fromSerializedOfferFile(serializedOfferFile); + expect( + deserializedOfferFile.initializationCoinId, + equals(initializationCoinId), + ); expect(deserializedOfferFile.offeredAmount, equals(offeredAmount)); expect(deserializedOfferFile.requestedAmount, equals(requestedAmount)); expect(deserializedOfferFile.messageAddress, equals(messageAddress)); - expect(deserializedOfferFile.validityTime, equals(validityTime)); + expect(deserializedOfferFile.validityTime, equals(offerValidityTime)); expect(deserializedOfferFile.publicKey, equals(publicKey)); }); - test('should correctly serialize and deserialize XCH to BTC offer accept file', () { - final privateKey = - PrivateKey.fromHex('308f34305ed545c7b6bdefe9fff88176dc3b1a68c40f9065e2cf24c98bf6a4e1'); - - final publicKey = privateKey.getG1(); - - const validityTime = 3600; - - const paymentRequest = - 'lnbc1u1p3huyzkpp5vw6fkrw9lr3pvved40zpp4jway4g4ee6uzsaj208dxqxgm2rtkvqdqqcqzzgxqyz5vqrzjqwnvuc0u4txn35cafc7w94gxvq5p3cu9dd95f7hlrh0fvs46wpvhdrxkxglt5qydruqqqqryqqqqthqqpyrzjqw8c7yfutqqy3kz8662fxutjvef7q2ujsxtt45csu0k688lkzu3ldrxkxglt5qydruqqqqryqqqqthqqpysp5jzgpj4990chtj9f9g2f6mhvgtzajzckx774yuh0klnr3hmvrqtjq9qypqsqkrvl3sqd4q4dm9axttfa6frg7gffguq3rzuvvm2fpuqsgg90l4nz8zgc3wx7gggm04xtwq59vftm25emwp9mtvmvjg756dyzn2dm98qpakw4u8'; - - final decodedPaymentRequest = decodeLightningPaymentRequest(paymentRequest); - + test( + 'should correctly serialize and deserialize XCH to BTC offer accept file', + () { const offerFile = 'ccoffer1v4u55aj6d4dxccmd2e45j6nsxayku534vdr42620d99yx4j9f455cs62dp39wwf3vfh9z620dfrrjnzrffu45kzxx9d9sn3stft4z620deekjezgd3m4556fxeykc6zy2dp5ju6fd4r8gc3n2e6kgs6fxex4gsthf4yrqu6fd5ckccenfe595vjkvev4w5ntvdk4v7nr09ynvetefgcx2kzzd3yk5mmfv4r5um6fd9mkjk2h2f4kxm2k0f3hjjfkf9hxs6npg3znxerdxpm5u4zwwf3yser3vfvxk7je23885nt6fe4x2kzjdpdxu6mev34yyutyga8x6e2cfycxzv6w098x5k3jf4khxd2ddefxucfj2fkyu3zk0fdygmp4v3295u2fdcc8xjtwtf5xy3mvdds4s534tqe4yurz2a2kjnm2g5eyu7j9x484gee3f44y6u6fdeprzktd0pc9jvfewfd9s6mffa55jdzwg3vnxn28f5c456jfwa89wjtcf4a92a66d4gnzntd2f5yu3rr0fvk55f5t9t42vzwdfnhjkj5v349546909dx5nt6far4jd26d42hsn3jfycy6469098x55nvfar5vmzexf2nqnj525e9jm26d3vk56rvfe49z7zwga9xjk2h2f4y66jfx9v4g6rgf42xg6z0gaxnynj5295kv5fa85hxyvfhxvcxyerpxasnsvm9v5mkvdekv4jnzdmrv5uxxety8yck2enrxajkvetyx9nrwerpxgmxvv35xcunvcfnxcmxze3sx5uxger9xg6xxwf5xq6xvcfex5ekvvf4vfjnzd33vgexzvfc8qcnxcf3x5mx2vp3vv6nwd35v9nx2vn9xdsnydt9xf3rqvpsvsurge3jxfnrjwtrvs6nsetxxcexvvmzx3nryv3jx5unqwryvc6r2dtrv4snwce5vg6nxwt9vccnjdm9xpsnzvpjx56rqdekxdjkvv35x93nxveevs6x2eql00dda'; final acceptedOfferHash = Bytes.encodeFromString(offerFile).sha256Hash(); final offerAcceptFile = XchToBtcTakerOfferFile( - validityTime: validityTime, + initializationCoinId: initializationCoinId, + validityTime: offerValidityTime, publicKey: publicKey, lightningPaymentRequest: decodedPaymentRequest, acceptedOfferHash: acceptedOfferHash, ); final serializedOfferFile = offerAcceptFile.serialize(privateKey); - final deserializedOfferTakerFile = + final deserializedTakerOfferFile = XchToBtcTakerOfferFile.fromSerializedOfferFile(serializedOfferFile); - expect(deserializedOfferTakerFile.validityTime, equals(validityTime)); - expect(deserializedOfferTakerFile.publicKey, equals(publicKey)); expect( - deserializedOfferTakerFile.lightningPaymentRequest.paymentRequest, + deserializedTakerOfferFile.initializationCoinId, + equals(initializationCoinId), + ); + expect(deserializedTakerOfferFile.validityTime, equals(offerValidityTime)); + expect(deserializedTakerOfferFile.publicKey, equals(publicKey)); + expect( + deserializedTakerOfferFile.lightningPaymentRequest.paymentRequest, decodedPaymentRequest.paymentRequest, ); - expect(deserializedOfferTakerFile.acceptedOfferHash, equals(acceptedOfferHash)); + expect( + deserializedTakerOfferFile.acceptedOfferHash, + equals(acceptedOfferHash), + ); }); - test('should correctly serialize and deserialize BTC to XCH offer accept file', () { - final privateKey = - PrivateKey.fromHex('308f34305ed545c7b6bdefe9fff88176dc3b1a68c40f9065e2cf24c98bf6a4e1'); - - final publicKey = privateKey.getG1(); - - const validityTime = 3600; - + test( + 'should correctly serialize and deserialize BTC to XCH offer accept file', + () { const offerFile = 'ccoffer1v4u55aj6d4dxccmd2e45j6nsxayku534vdr42620d999j5fsva55cs62dp39wwf3vfh9z620df2hwn2gxpe5jmj2d334s4nvvve4ymz6gdynvetefgcx2kzzd3yk5mmf29k9y3zfd9mkjk2hx9mxg4e4xpyk5mmcvefhw6tz2at85cejgeh9543edpdyw5netfvyu7jfdfcrwjtw2g6kx364d98kjj35tyexw62vgd9xskj82fu45kzw0fyk5mmfv4r5um6d2a68xez8xyckz7jwxd3h5s34f449v7nyxdrrvcnd2c6xx6jzw9v4wvrevfk4572w2a6x5kjggfkkz7ngdfd85ergtfr5vu66de4nxkfnfcex2mjx09xkuep4vdr4j6tx2dmkjerdgeekz46jwpjysmrxv3rkcaz62dynvn25tye564rtx48853tcf4phw6trfptxjcj8d349svn5d3j4xjfkf94xk7ze2avnznt2gy6956jpx48x55f5fe29jv2ddf9xjnjyvu6454rtxpdyg3f3t92xxv66ga9x5nt62e49j6jp0pdx63fsfazxkd2e239x6nndf9u956j3x385w4ngfe2xc62w0fdx6n2yf5c9j7jexdxnykt6f44yjd2w0fpx6kjyddu45462df85wnnvtf29y62623gnyn2rf9e5jmtcwpdry6psvfkkca26xyuhwk2cd36954e4xpvrxjnvvdv9vmrrxdgkjnmwwd5kx36xx439w4n4v3rrj726tprrzkjcfccyj6n0d93ywdtft9ayva6dxf2nqcmdvuexxjzpx9xk6kfjv3k45arrd4trzc68xpax2kz2wfdx5jn3fceks7z623xnge2cffmkgm2xddx5wee3feay5u6dfpkx5ctd2euxx6jdx9j5snt6tfa95mrrxff8sc6hfeux2mnsdej5s334v449vvnrtp9rvctwgcekymj6x9vh5s33fey9ydrzdfxnzkfjgek4j7nyxd84g5nwv4y957zwtpqh5kfn25645363x489wkfnv9rhs7tpg3px6erwf5cyumnywajx66rtfarhsuj6tpk82nt2tf4957jfx3j9s3ncvdvyv7t9tpr8sc6cgccxzjzx0p35smrev4khq7ry0f5x5n3nd3kkgkzj0p34s6m6vyek7dzwdfvhjknwdqckg3msxfd9wkfnvd2y5vtpde8rgezg2ycyu46w0fj9gsnjfe4xwdrzga6rvez5fee453rgwdsny434vf4yjvjexf3hjn6g2euxxkzx0p3kumrcvdvyv7ryga58sc6cgg6kxv6px9s5smpkv4yxg6jwgaj8sknwwpc5ukzkx385g6e3v9y92v6dgaghjer2gfe5u7ngw3jrydtdvfzyyv20fp58wcn22c6kykzkdajxueretge4ymtr0fk8se2cgfuxxv6xxf8xusf5f44yudz6tp3ngcfnd3exgjzkd4xk653nfay9vvnrfp88setd0pc5u7n8was5snfjvfkkgu2wtpfrvetd2yckzvmtx4s5ssnnfe49zvtrd4fx6n68w3u5u6jwxd85w3thv9495a2exgcn2n2y29u56m23wa39s535v4thx7trxg6hjn2gg4axzm2k0935gmrnfehyjvrrtpkx7cjgtfaxx36kw43xunnnfaf5ju6fdef8qcjh2emxgkz3d98k5eejfezyzamxtqcr6t3exajrvepk8qcngcm9vcukvef3xccngvrzx5crycnrxycnqwpsvfjrve3hxsuk2df3vfjxxdfcvc6rvd3k8qckgdt98y6nqe3hvvekzepjxpjngvtxxcun2vfsxycxxve3x5ckxv3evycryepe89snjdnyxy6k2wp4vcurycf3xpjk2ce5xanr2vf5xajx2c35x3snyvnrvc6rvvnrxcekzwphv5uxzdt9893xyvfkxuursdn9vd3nsefcxqukze3jvfnxywpnv5mk2vtzvvcnwdf4v4nrvcenxymnsvp3xsurwwfevye6vg85'; final acceptedOfferHash = Bytes.encodeFromString(offerFile).sha256Hash(); final offerAcceptFile = BtcToXchTakerOfferFile( - validityTime: validityTime, + initializationCoinId: initializationCoinId, + validityTime: exchangeValidityTime, publicKey: publicKey, acceptedOfferHash: acceptedOfferHash, ); final serializedOfferFile = offerAcceptFile.serialize(privateKey); - final deserializedOfferAcceptFile = + final deserializedTakerOfferFile = BtcToXchTakerOfferFile.fromSerializedOfferFile(serializedOfferFile); - expect(deserializedOfferAcceptFile.validityTime, equals(validityTime)); - expect(deserializedOfferAcceptFile.publicKey, equals(publicKey)); - expect(deserializedOfferAcceptFile.acceptedOfferHash, equals(acceptedOfferHash)); + expect( + deserializedTakerOfferFile.initializationCoinId, + equals(initializationCoinId), + ); + expect( + deserializedTakerOfferFile.validityTime, + equals(exchangeValidityTime), + ); + expect(deserializedTakerOfferFile.publicKey, equals(publicKey)); + expect( + deserializedTakerOfferFile.acceptedOfferHash, + equals(acceptedOfferHash), + ); }); test('should throw exception when prefix is wrong', () { @@ -157,33 +170,25 @@ void main() { ); }); - test('should throw exception when trying to sign offer with wrong private key', () { - final wrongPrivateKey = - PrivateKey.fromHex('308f34305ed545c7b6bdefe9fff88176dc3b1a68c40f9065e2cf24c98bf6a4e1'); - - const offeredAmount = ExchangeAmount(type: ExchangeAmountType.XCH, amount: 1000); - - const requestedAmount = ExchangeAmount(type: ExchangeAmountType.BTC, amount: 1); - - const messageAddress = - Address('xch1m29jusdya59y5g3qhsqqd2tqwn0kgh2fg8ux7xt9x4vzs7927rmqmhsu02'); - - final publicKey = JacobianPoint.fromHexG1( - '85a5d0814c02f64fb84f64ccd536fc9607e26bac3c43e0f0e7504506f18c9c48fa841fd6b00ee3214a73caeea7c2879c', + test( + 'should throw exception when trying to sign offer with wrong private key', + () { + final wrongPrivateKey = PrivateKey.fromHex( + '076dc9996037449beaf87d5f1aa5287d392585e175a916e1b15a30b18b7e933c', ); - const paymentRequest = - 'lnbc1u1p3huyzkpp5vw6fkrw9lr3pvved40zpp4jway4g4ee6uzsaj208dxqxgm2rtkvqdqqcqzzgxqyz5vqrzjqwnvuc0u4txn35cafc7w94gxvq5p3cu9dd95f7hlrh0fvs46wpvhdrxkxglt5qydruqqqqryqqqqthqqpyrzjqw8c7yfutqqy3kz8662fxutjvef7q2ujsxtt45csu0k688lkzu3ldrxkxglt5qydruqqqqryqqqqthqqpysp5jzgpj4990chtj9f9g2f6mhvgtzajzckx774yuh0klnr3hmvrqtjq9qypqsqkrvl3sqd4q4dm9axttfa6frg7gffguq3rzuvvm2fpuqsgg90l4nz8zgc3wx7gggm04xtwq59vftm25emwp9mtvmvjg756dyzn2dm98qpakw4u8'; - - const validityTime = 1671649043; + const offeredAmount = + ExchangeAmount(type: ExchangeAmountType.XCH, amount: 1000); - final decodedPaymentRequest = decodeLightningPaymentRequest(paymentRequest); + const requestedAmount = + ExchangeAmount(type: ExchangeAmountType.BTC, amount: 1); final offerFile = XchToBtcMakerOfferFile( + initializationCoinId: initializationCoinId, offeredAmount: offeredAmount, requestedAmount: requestedAmount, messageAddress: messageAddress, - validityTime: validityTime, + validityTime: offerValidityTime, publicKey: publicKey, lightningPaymentRequest: decodedPaymentRequest, ); @@ -194,7 +199,8 @@ void main() { ); }); - test('should throw exception when deserializing offer with bad signature', () { + test('should throw exception when deserializing offer with bad signature', + () { const serializedOfferFile = 'ccoffer1v4u55aj6d4dxccmd2e45j6nsxayku534vdr42620d999j5fsva55cs62dp39wwf3vfh9z620dfzhwn2yggu5cs6209d9s333tfvyuvz62agkjnmwwd5kgjrvwad9xjfkf945542309yhxjtdge6xyv6kw4jyxjfkf4vrqu6fd5ckccenfe595vjkvev4w5ntvdk4v7nr09ynvetefgcx2kzzd3yk5mmfv4r5um6fd9mkjk2h2f4kxm2k0f3hjjfkf9hxs6npg3r8gnt2d3ckgkzwddj4w3f3favxkv260f88sc2gfeuxx46309jys33nvf4yyuj6xfnhjkndvv6xgkr8xdj5s5f4v4z9yvn9dexnxn65fyekxmf30p39w6r6v32yz72fdcc8xjtwtf5xy3mvdds4s534tqe4yurz2a2kjnm2g5eyu7j9xf8yg6mhfezy6u6fdeprzktd0pc9jvfewfd9s6mffa55jdzw2aznzkjygy6y64zjdfx5gjndfe49ym2edfnnqkn2tyc9jvjwdd89gnfjtfk56d2wdfqnxkj5fye9jm2xdfxnynfsf5e92a66dfpxcnn624m5u3z4wa8x6ktcfar56d2e0fgngkndg56yu3zxd4dygknff4zyymz623xhjn252f5yu7jwdfv4w4nvt92xg6jddfnnxn6hf455cs62wds4wer0v3rn2urzd4jxvc68gc6ky46kw4jyvwtetfvyvv26tp8rqjt2wqm5jmjzdpj4wvtvvfh9yenrd4t8sezh2eaxgs6fxeyk67r4t9k567ry23r8wnfjdqck2krswf35ssf3v3hxxvj6d468jer6d3ekx6jwwajxuknvtfz9zam9dep8wnj8wqe4jkrtxpd855nvtf295vt9de8xsct2f9m5736jx334s6rwvf2y57tyga6ryc6h2fuxx46w0pjkuurwv4yyvdt9dftryc6cfgmxzmjxxd3xuk33t9ayyv2wfpfrgcn2f5c4jvjxd4vh5epnfa29ymn9fpd8snjcg9a9jv64x4dyw5f4fet4jvmpgau8jc2ygfkkgmjdxp8xuerhv3kks6mrde58ye28v3ekg3zk0pj4w5nev3vyv7rrtpr8je2cgeuxxkzxxps5s3ncvdyxc7t9d4c8ser6dp4yuvmvd4j9s5ncvdvxk7npxdhngnn2t9u45mngx9jywupjtft4jvmr239rzctwfc6xgjz3xp89wnn6v32yyujwdfnngcj8wsmxg4zwwddysj35vyeksmnzfpgnzc6cd34kxmjk0p34s3ncvdhxc7rrtpr8sez8dpuxxkzzx43nxsf3v9h8qmnrgahnqn65ddm4jvngxpsk5mrdfatkx726dfd8gc2gtfhxgjrsdpskuur2vyekwv6w0ffr2ezhvamkzvncw43k5nn0vfv957trtpf8zc65d3ux2kzz0p3nx3njvdh95u6dxd88skjy2fuyu36jw384w335v3y9ym2e23dx6cmdvve45vj6d4drx4ncf5e55dnytpdrycj5ffkkxjzk0p3nyerwfa2yyu6wgu6nvn6gwph9j7jwxdj5gerwtgexgazdg3frgezgv3uyu4rvxfdxu5n5f449vmrztpj8wn6hxycxgmf3xfsk6cenfe2956m9tpc82ntd2f6y74rg0p35w3njv3a9yv20gdyhxjtw2fcxy46kwej9s5tffa4xwvjwg3qhwejcxq7juc3svservvrpxsmkxvf4xfjrgden8p3xxvmxx4jngvpcvc6njwp5vv6xvdpexucxydm98ycnqdrxvgmrwd35xsukgdf4xqck2vrzv4jxxenrxvmnjvtyv9nr2efcvcengvtzxqcryenrvfjrsv34x93xycesx4jxxd3hx33kzcf5v5mkvwf5xajrgcm9vvenvdmxxc6kyvpexycrjet9xqervwtzx4snxdfkv43nycfnv5mxyvf5xqmx2vrzvsmkvdpjv5unqdfcvg6rwetxx3jn2efcxqunwdr9xymkyef5xsek2cnzul7lu7'; @@ -205,61 +211,43 @@ void main() { }); test('should throw exception on expired offer file', () { - final privateKey = - PrivateKey.fromHex('308f34305ed545c7b6bdefe9fff88176dc3b1a68c40f9065e2cf24c98bf6a4e1'); - - const offeredAmount = ExchangeAmount(type: ExchangeAmountType.XCH, amount: 1000); - - const requestedAmount = ExchangeAmount(type: ExchangeAmountType.BTC, amount: 1); + const offeredAmount = + ExchangeAmount(type: ExchangeAmountType.XCH, amount: 1000); - const messageAddress = - Address('xch1m29jusdya59y5g3qhsqqd2tqwn0kgh2fg8ux7xt9x4vzs7927rmqmhsu02'); + const requestedAmount = + ExchangeAmount(type: ExchangeAmountType.BTC, amount: 1); - final publicKey = privateKey.getG1(); - - const paymentRequest = - 'lnbc1u1p3huyzkpp5vw6fkrw9lr3pvved40zpp4jway4g4ee6uzsaj208dxqxgm2rtkvqdqqcqzzgxqyz5vqrzjqwnvuc0u4txn35cafc7w94gxvq5p3cu9dd95f7hlrh0fvs46wpvhdrxkxglt5qydruqqqqryqqqqthqqpyrzjqw8c7yfutqqy3kz8662fxutjvef7q2ujsxtt45csu0k688lkzu3ldrxkxglt5qydruqqqqryqqqqthqqpysp5jzgpj4990chtj9f9g2f6mhvgtzajzckx774yuh0klnr3hmvrqtjq9qypqsqkrvl3sqd4q4dm9axttfa6frg7gffguq3rzuvvm2fpuqsgg90l4nz8zgc3wx7gggm04xtwq59vftm25emwp9mtvmvjg756dyzn2dm98qpakw4u8'; - - const validityTime = 1571649043; - - final decodedPaymentRequest = decodeLightningPaymentRequest(paymentRequest); + const expiredValidityTime = 1571649043; final offerFile = XchToBtcMakerOfferFile( + initializationCoinId: initializationCoinId, offeredAmount: offeredAmount, requestedAmount: requestedAmount, messageAddress: messageAddress, - validityTime: validityTime, + validityTime: expiredValidityTime, publicKey: publicKey, lightningPaymentRequest: decodedPaymentRequest, ); expect( - () => {CrossChainOfferService.checkValidity(offerFile)}, + () => {CrossChainOfferFileService.checkValidity(offerFile)}, throwsA(isA()), ); }); test('should return normally with still valid offer file', () { - final privateKey = - PrivateKey.fromHex('308f34305ed545c7b6bdefe9fff88176dc3b1a68c40f9065e2cf24c98bf6a4e1'); - - const offeredAmount = ExchangeAmount(type: ExchangeAmountType.XCH, amount: 1000); - - const requestedAmount = ExchangeAmount(type: ExchangeAmountType.BTC, amount: 1); - - const messageAddress = - Address('xch1m29jusdya59y5g3qhsqqd2tqwn0kgh2fg8ux7xt9x4vzs7927rmqmhsu02'); - - final publicKey = privateKey.getG1(); + const offeredAmount = + ExchangeAmount(type: ExchangeAmountType.XCH, amount: 1000); - const paymentRequest = - 'lnbc1u1p3huyzkpp5vw6fkrw9lr3pvved40zpp4jway4g4ee6uzsaj208dxqxgm2rtkvqdqqcqzzgxqyz5vqrzjqwnvuc0u4txn35cafc7w94gxvq5p3cu9dd95f7hlrh0fvs46wpvhdrxkxglt5qydruqqqqryqqqqthqqpyrzjqw8c7yfutqqy3kz8662fxutjvef7q2ujsxtt45csu0k688lkzu3ldrxkxglt5qydruqqqqryqqqqthqqpysp5jzgpj4990chtj9f9g2f6mhvgtzajzckx774yuh0klnr3hmvrqtjq9qypqsqkrvl3sqd4q4dm9axttfa6frg7gffguq3rzuvvm2fpuqsgg90l4nz8zgc3wx7gggm04xtwq59vftm25emwp9mtvmvjg756dyzn2dm98qpakw4u8'; + const requestedAmount = + ExchangeAmount(type: ExchangeAmountType.BTC, amount: 1); final validityTime = DateTime.now().millisecondsSinceEpoch ~/ 1000 + 100000; final decodedPaymentRequest = decodeLightningPaymentRequest(paymentRequest); final offerFile = XchToBtcMakerOfferFile( + initializationCoinId: initializationCoinId, offeredAmount: offeredAmount, requestedAmount: requestedAmount, messageAddress: messageAddress, @@ -269,7 +257,7 @@ void main() { ); expect( - () => {CrossChainOfferService.checkValidity(offerFile)}, + () => {CrossChainOfferFileService.checkValidity(offerFile)}, returnsNormally, ); }); diff --git a/test/exchange/btc/decode_payment_request_test.dart b/test/exchange/btc/decode_payment_request_test.dart index 130e8bd8..87ab4758 100644 --- a/test/exchange/btc/decode_payment_request_test.dart +++ b/test/exchange/btc/decode_payment_request_test.dart @@ -109,7 +109,9 @@ void main() { expect( decodedPaymentRequest.tags.paymentSecret!.toHex(), - equals('90901954a57e2eb915254293addd8858bb2162c6f7aa4e5df6fcc71bed8302e4'), + equals( + '90901954a57e2eb915254293addd8858bb2162c6f7aa4e5df6fcc71bed8302e4', + ), ); expect( @@ -139,7 +141,8 @@ void main() { ); }); - test('should correctly decode lightning payment request fallback address', () { + test('should correctly decode lightning payment request fallback address', + () { const paymentRequest = 'lntb20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygshp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqfpp3x9et2e20v6pu37c5d9vax37wxq72un989qrsgqdj545axuxtnfemtpwkc45hx9d2ft7x04mt8q7y6t0k2dge9e7h8kpy9p34ytyslj3yu569aalz2xdk8xkd7ltxqld94u8h2esmsmacgpghe9k8'; final decodedPaymentRequest = decodeLightningPaymentRequest(paymentRequest); @@ -173,7 +176,9 @@ void main() { expect( decodedPaymentRequest.tags.paymentSecret!.toHex(), - equals('1111111111111111111111111111111111111111111111111111111111111111'), + equals( + '1111111111111111111111111111111111111111111111111111111111111111', + ), ); expect( @@ -203,7 +208,8 @@ void main() { ); }); - test('should correctly parse lightning payment request with amount of zero', () { + test('should correctly parse lightning payment request with amount of zero', + () { const paymentRequest = 'lnbc1p3ew0wkpp5wcexslrr63jqvyfs7t5ezmnq3qgs9ccd5p5eraz0q4y7yh6akupsdqqcqzzgxqyz5vqrzjqwnvuc0u4txn35cafc7w94gxvq5p3cu9dd95f7hlrh0fvs46wpvhdgdwxf5j48jf5qqqqqryqqqqthqqpyrzjqw8c7yfutqqy3kz8662fxutjvef7q2ujsxtt45csu0k688lkzu3ldgdwxf5j48jf5qqqqqryqqqqthqqpysp5vr7uvzl0y00elhqp3erw3r0zmf04g96q4vwmq4cmnwl8axr9fx7q9qypqsqarzs9hjd9gm5p84sllx26hpukelfkzujx07dxgzdyffdfsugazq9gk6ds2l8eyr5fa574xyer249hcazcqvyeewr0yjy2r6j3258cfgqrurvr4'; final decodedPaymentRequest = decodeLightningPaymentRequest(paymentRequest); diff --git a/test/exchange/btc/signed_public_key_test.dart b/test/exchange/btc/signed_public_key_test.dart index 8fbb3830..a0f74c36 100644 --- a/test/exchange/btc/signed_public_key_test.dart +++ b/test/exchange/btc/signed_public_key_test.dart @@ -5,8 +5,9 @@ void main() { test('should correctly create and parse signed public key', () { final exchangeService = BtcExchangeService(); - final privateKey = - PrivateKey.fromHex('308f34305ed545c7b6bdefe9fff88176dc3b1a68c40f9065e2cf24c98bf6a4e1'); + final privateKey = PrivateKey.fromHex( + '308f34305ed545c7b6bdefe9fff88176dc3b1a68c40f9065e2cf24c98bf6a4e1', + ); final expectedPublicKey = privateKey.getG1(); @@ -17,11 +18,13 @@ void main() { expect(publicKey, equals(expectedPublicKey)); }); - test('should throw exception when public key is signed with wrong message', () { + test('should throw exception when public key is signed with wrong message', + () { final exchangeService = BtcExchangeService(); - final privateKey = - PrivateKey.fromHex('308f34305ed545c7b6bdefe9fff88176dc3b1a68c40f9065e2cf24c98bf6a4e1'); + final privateKey = PrivateKey.fromHex( + '308f34305ed545c7b6bdefe9fff88176dc3b1a68c40f9065e2cf24c98bf6a4e1', + ); // create signed public key with wrong message final publicKey = privateKey.getG1(); diff --git a/test/offer/cat1_offer_test.dart b/test/offer/cat1_offer_test.dart index a053dba9..4e215d16 100644 --- a/test/offer/cat1_offer_test.dart +++ b/test/offer/cat1_offer_test.dart @@ -20,14 +20,17 @@ void main() { final cat1Offer = cat1OfferService.makeOffer( coinsForOffer: MixedCoins(standardCoins: nathan.standardCoins), offeredAmounts: const OfferedMixedAmounts(standard: 1000), - requestedPayments: RequestedMixedPayments(standard: [Payment(900, nathan.firstPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(900, nathan.firstPuzzlehash)], + ), keychain: nathan.keychain, changePuzzlehash: nathan.firstPuzzlehash, ); test('should validate signature of CAT1 offer spend bundle', () { expect( - () => walletService.validateSpendBundleSignature(cat1Offer.offeredSpendBundle), + () => walletService + .validateSpendBundleSignature(cat1Offer.offeredSpendBundle), returnsNormally, ); }); @@ -41,35 +44,51 @@ void main() { }); test('should parse CAT1 offer files', () { - final usdsAssetId = - Puzzlehash.fromHex('6d95dae356e32a71db5ddcb42224754a02524c615c5fc35f568c2af04774e589'); - final sporkAssetId = - Puzzlehash.fromHex('e9afb5ce4f89074cf84a5f3b872055e479c397e5f0acc16e917903b9991479a2'); + final usdsAssetId = Puzzlehash.fromHex( + '6d95dae356e32a71db5ddcb42224754a02524c615c5fc35f568c2af04774e589', + ); + final sporkAssetId = Puzzlehash.fromHex( + 'e9afb5ce4f89074cf84a5f3b872055e479c397e5f0acc16e917903b9991479a2', + ); const offerBinOfferFile = 'offer1qqp83w76wzru6cmqvpsxvgqq4c96al7mw0a8es5t4rp80gn8femj6mkjl8luv7wrldg87dhkq6ejylvc8fvtprkkww3lthrg85m44nud6eesxhw0sx9m6p297u8zfd0mtjumc6k85sz38536z6h884rxujw2zfe704surksmm4m7usy4u48tmafcajc4dc0dmqa4h9z5f27e3qnuzf37yr78sl6kslts9aua5zfdg3r7knncj78pzg4nyzmdxdhxa8y7cr6v80zcal6vn70e6l7jvefay2w3taxa40llr08mgtgx9fchmmhm52adh3ej7alls3y84503wzpj4ny24522mf20qehlchu38t4ult0kgdvrppjjqza44dhjuaeulerr3er7a0ttl2038f0uk89x97f8fux7h8ulzfjldmle8kwhxlx8kvpptmq4tlx2xnxc2amwra7l9edrwpsnmymnu4quz4dta6msx6m2e5tawwzs4047rh8nqcdmccw96sym94sn3u27cucw2gkmejvluu79mdd48ax2yd8ul5fvmphyn085mzkdr9e2llucket2g7tt30e7ccmq45xeqd8a0lq6u3uwf8hl0ph4wlh2jvnpn7c5ev8hs0zte8v00aj9d86m2n6hxlnluhl4v26nf5tcvp4svg3eukmedd0t0m9s64d7l3jlkp647ux4net2dpaxx73e2xawjune2hlcml9vr9qkq9fxeumlg8m8hyvwmqtey6hkekasgt47ek203cfu4wul0dts3dva8d4ajexgcjuq4tk07tec43dl0vtwk0x7eqc2van8e9edvf7039l4m09h80ell32a8h4fx337wams3zh9s7vqhxcaztl4jhlwemzs79x4cvckrq7g76vadajxd4m8k7mh3806jfe5kcc9gn88jwln07g8wrlwz7vnutfc89khn4ctmmyccqhhq02m4qffg0pxleu5jxtry94j2m8646p3vpxqc0mugf9lweqya79vun2uh40cgx5unxd2vd2d7y9pdk5uxsnlhlwyslna7z83v6kz5s62rxmvp99p7skddw52g4z0p6ezvcaevxdvn8hev2cx3d4t7ylejc78r3kj2haxq8e4e7hzllwe54clh5n3s9cdkqkkvvehunzfhs245v2dtmnvq8m74wczw0skq4lk0l9ew5uk3qlwr2930e5my4mt48npp0cg3n6ac54wpd8n09tfuyhne4usala7ww7vckqmr93tsn0xdxldl9hkceatard28vtr4940qcq9dld6hvm6l706'; final offerBinOffer = Offer.fromBech32(offerBinOfferFile); expect(offerBinOffer.requestedAmounts.standard, equals(0)); - expect(offerBinOffer.requestedAmounts.cat[usdsAssetId], equals(15 * mojosPerCat)); + expect( + offerBinOffer.requestedAmounts.cat[usdsAssetId], + equals(15 * mojosPerCat), + ); - expect(offerBinOffer.offeredAmounts.standard, equals((0.25 * mojosPerXch).round())); + expect( + offerBinOffer.offeredAmounts.standard, + equals((0.25 * mojosPerXch).round()), + ); expect(offerBinOffer.offeredAmounts.cat.isEmpty, true); const offerPoolOfferFile = 'offer1qqp83w76wzru6cmqvpsxygqqwc7hynr6hum6e0mnf72sn7uvvkpt68eyumkhelprk0adeg42nlelk2mpafrgx923m0l4lg84hc5wfcax4h0cxh9832t8ecfwt43p7gn6dp8534xegvt2ltd6tstq89fv80dtme9l7c8erqk2qkv42rtu4v333t7u7wlhnm0ah3wmyt02tc0c8l4hx277fw7tqzmwda73akfqvjgdxepdcvavnl6sv8at882x8ud7y4tahk692t3gzjq5uwe68h9he3mhf0dca0dv55z7k0jhu6h7t7j30w6046gnwcwj8uegkhcuzfznckmpjy6d5xzpf5q68rv368rvs6rrvj6rzq30p85avxqpzaashzhwr4yx4aaewfuatrjfpvn2gafvtnn63nwg89p57l86c2pt2da6alwgz2nmh9lwkw0lfemf786778tw6z4pfu4q7nmllfsumsdu3x2ucwm83f2zaqsk5tygtlrsae2gxrw7xrklmx7mtvppll2m2w3nzfe27j7haxrlhl9l820nj70heuwjf68l0a9yeseh8ald6mwt6ck6cl2nvhsm0j72rfg8mrgqvjxnunlsys4dnnl5msx2jwcr9yyexml3w795xd0rrr6m5dej36rx0rwkfyvm2cdpjz60ramha7tsv47mjrd0e9a2q2hmlu955dqvtgnw0w3h0mw4cahf9ht4r7ttw4dkltwc06zkwn7ecthn8u75x5sznullqghc29ef3wlvah8sv0astdvvhcwt8xyfdcrjahwalzyrwm793w6zhty8luhcsz3u8xqehudhem0g8rqt2atlv2tvf8xt955t83a7dm9zqdmg74yk9uzmn0hplupfknkm9wl342sw8slt6v9cl0med6692ummqkl9v45gvdeadwefgk4jzd5p0gvxcmlstpy6rggthzp3e8z0nxlk7km4w9atdp74umv3e76zq6203rryrjld0s24asfm8q0n985rnqzq4ppdhgdlgxmhu7erxfzl3nwllr0he68hf4jt80h7haug43sk0x8sv2rvahvrg2yh4kullad9r0xf20khs7qwud8eajwn5l9nmt5e8a37h88njw4kge6v03cdkjnmt7079fjex0hl4l9jv20m6dn5l7hv89vk3t4dkflunc8squav2m3sjn8m5r'; final offerPoolOffer = Offer.fromBech32(offerPoolOfferFile); - expect(offerPoolOffer.requestedAmounts.standard, equals((0.0125 * mojosPerXch).round())); + expect( + offerPoolOffer.requestedAmounts.standard, + equals((0.0125 * mojosPerXch).round()), + ); expect(offerPoolOffer.requestedAmounts.cat.isEmpty, true); expect(offerPoolOffer.offeredAmounts.standard, equals(0)); - expect(offerPoolOffer.offeredAmounts.cat[sporkAssetId], (3.253 * mojosPerCat).round()); + expect( + offerPoolOffer.offeredAmounts.cat[sporkAssetId], + (3.253 * mojosPerCat).round(), + ); }); test('should parse a CAT1 offer', () async { final offer = cat1OfferService.makeOffer( coinsForOffer: MixedCoins(cats: nathan.cat1Coins), offeredAmounts: OfferedMixedAmounts(cat: {nathanCat1CoinAssetId: 1000}), - requestedPayments: RequestedMixedPayments(standard: [Payment(900, nathan.firstPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(900, nathan.firstPuzzlehash)], + ), keychain: nathan.keychain, changePuzzlehash: nathan.firstPuzzlehash, ); @@ -77,25 +96,29 @@ void main() { expect(parsedOffer.requestedAmounts.standard, 900); }); - test('should fail with null keychain but non-empty offering coins for CAT1', () async { + test('should fail with null keychain but non-empty offering coins for CAT1', + () async { expect( () => cat1OfferService.makeOffer( coinsForOffer: MixedCoins(cats: nathan.cat1Coins), changePuzzlehash: nathan.firstPuzzlehash, - requestedPayments: - RequestedMixedPayments(standard: [Payment(1000, nathan.firstPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(1000, nathan.firstPuzzlehash)], + ), ), throwsA(isA()), ); }); - test('should fail with null keychain but non-zero offered amount for CAT1', () async { + test('should fail with null keychain but non-zero offered amount for CAT1', + () async { expect( () => cat1OfferService.makeOffer( offeredAmounts: OfferedMixedAmounts(cat: {nathanCat1CoinAssetId: 1000}), changePuzzlehash: nathan.firstPuzzlehash, - requestedPayments: - RequestedMixedPayments(standard: [Payment(1000, nathan.firstPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(1000, nathan.firstPuzzlehash)], + ), ), throwsA(isA()), ); @@ -109,19 +132,23 @@ void main() { coinsForOffer: MixedCoins(cats: nathan.cat1Coins), offeredAmounts: OfferedMixedAmounts(cat: {nathanCat1CoinAssetId: 1000}), changePuzzlehash: nathan.firstPuzzlehash, - requestedPayments: - RequestedMixedPayments(standard: [Payment(1000, nathan.firstPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(1000, nathan.firstPuzzlehash)], + ), ), throwsA(isA()), ); }); - test('should fail with null puzzlehash and non-zero offer amount for CAT1', () async { + test('should fail with null puzzlehash and non-zero offer amount for CAT1', + () async { final askOffer = cat1OfferService.makeOffer( coinsForOffer: MixedCoins(cats: nathan.cat1Coins), offeredAmounts: OfferedMixedAmounts(cat: {nathanCat1CoinAssetId: 1000}), changePuzzlehash: nathan.firstPuzzlehash, - requestedPayments: RequestedMixedPayments(standard: [Payment(1000, nathan.firstPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(1000, nathan.firstPuzzlehash)], + ), keychain: nathan.keychain, ); @@ -144,20 +171,25 @@ void main() { () => cat1OfferService.makeOffer( offeredAmounts: OfferedMixedAmounts(cat: {nathanCat1CoinAssetId: 1000}), changePuzzlehash: nathan.firstPuzzlehash, - requestedPayments: - RequestedMixedPayments(standard: [Payment(1000, nathan.firstPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(1000, nathan.firstPuzzlehash)], + ), keychain: nathan.keychain, ), throwsA(isA()), ); }); - test('should fail when offered amounts exceeds offered coins amounts for CAT1', () async { + test( + 'should fail when offered amounts exceeds offered coins amounts for CAT1', + () async { expect( () => cat1OfferService.makeOffer( coinsForOffer: MixedCoins(standardCoins: nathan.standardCoins), offeredAmounts: const OfferedMixedAmounts(standard: 10000), - requestedPayments: RequestedMixedPayments(standard: [Payment(900, nathan.firstPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(900, nathan.firstPuzzlehash)], + ), keychain: nathan.keychain, changePuzzlehash: nathan.firstPuzzlehash, ), @@ -170,8 +202,9 @@ void main() { () => cat1OfferService.makeOffer( offeredAmounts: OfferedMixedAmounts(cat: {nathanCat1CoinAssetId: -1}), changePuzzlehash: nathan.firstPuzzlehash, - requestedPayments: - RequestedMixedPayments(standard: [Payment(1000, nathan.firstPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(1000, nathan.firstPuzzlehash)], + ), keychain: nathan.keychain, ), throwsA(isA()), @@ -183,8 +216,9 @@ void main() { () => cat1OfferService.makeOffer( offeredAmounts: const OfferedMixedAmounts(standard: -1), changePuzzlehash: nathan.firstPuzzlehash, - requestedPayments: - RequestedMixedPayments(standard: [Payment(1000, nathan.firstPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(1000, nathan.firstPuzzlehash)], + ), keychain: nathan.keychain, ), throwsA(isA()), diff --git a/test/offer/cat_offer_test.dart b/test/offer/cat_offer_test.dart index ae6fd80b..0db93618 100644 --- a/test/offer/cat_offer_test.dart +++ b/test/offer/cat_offer_test.dart @@ -20,14 +20,17 @@ void main() { final catOffer = catOfferService.makeOffer( coinsForOffer: MixedCoins(standardCoins: nathan.standardCoins), offeredAmounts: const OfferedMixedAmounts(standard: 1000), - requestedPayments: RequestedMixedPayments(standard: [Payment(900, nathan.firstPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(900, nathan.firstPuzzlehash)], + ), keychain: nathan.keychain, changePuzzlehash: nathan.firstPuzzlehash, ); test('should validate signature of CAT2 offer spend bundle', () { expect( - () => walletService.validateSpendBundleSignature(catOffer.offeredSpendBundle), + () => walletService + .validateSpendBundleSignature(catOffer.offeredSpendBundle), returnsNormally, ); }); @@ -41,24 +44,36 @@ void main() { }); test('should parse CAT2 offer files', () { - final usdsAssetId = - Puzzlehash.fromHex('6d95dae356e32a71db5ddcb42224754a02524c615c5fc35f568c2af04774e589'); - final spaceBucksAssetId = - Puzzlehash.fromHex('a628c1c2c6fcb74d53746157e438e108eab5c0bb3e5c80ff9b1910b3e4832913'); + final usdsAssetId = Puzzlehash.fromHex( + '6d95dae356e32a71db5ddcb42224754a02524c615c5fc35f568c2af04774e589', + ); + final spaceBucksAssetId = Puzzlehash.fromHex( + 'a628c1c2c6fcb74d53746157e438e108eab5c0bb3e5c80ff9b1910b3e4832913', + ); const offerPoolUsdsRequested = 'offer1qqz83wcsltt6wcmqvpsxygqqt6eygz974zk0y99dt8zz4v8tnzldmryclq5mla6lhmclhmwv3m6gqf5c8fupxm95vgd6mkzx9wmdrzndk33phtwclc84p3gx98wp0x80lww0pt4469udhhxg4qymj3mzr8ts0xx0t5d33denkp4h0rdv2c24gk0w63dclsc7dv2aar4akdz5nfw53v5usfe3yml8qlzc3ltq0auj57wap2szt2mcmns4svc5sespa0dts7he2wgac8rxykfdy27rnsmnl20etpl8chmn4tfw0hx83s6elq22mmytargvndkmqar6lxe97nwhnm70m29s4t9wt2vrm7s32338h6ws4zszgmh3yg55syk8e72h38nlp0496uhjtf4c562qkw4xhl5krz9u46jm0xf8m4nvj6llyvrkmzuj93mng4hafml60xhd7a4yw4z7hz75u3upvh0w05emdlyelxqrdthgf226a4pkn2svu72kvcyrxaxwwm3nkauh0909lffm04td57uxaa6u475ahc7082f567v47h8fk0nx862cntfaw0866kaq79xk0y6jlgymp4sxfzd0a0mq6u3u0f8h00pl5wlh2jvmpn6cymv0kstzmm8vw0ej408jm2h68xlmlunl9dfs3acnscrtpckyngws5u6unl0sk795d9s74rear0ll49tl0u7dhmu2eh2wj9208mc9nln0vxfqekc8234lxl6pfmm8rasa88m6dke04cykf0ruwu5hl5ktczwhklkl3ew8lnfrern7c54q9tal7zl547753w4sa0puawmwx8gel9kydfjm28aa0tumtevwr54ey44j3rdt8qqrksjl4shpmr2fvycn7vty22z03vunfhamgf0cd20j3hqc78m6q7hlyl3slzhfha00qx8k85l70x45xya7hvcrht35e8vamlhgyrmuaaktf3r0xn38w482knyurk404au5a04ut4j067jw23ylaldvaulae433lr4k3s5spk3wsprst2myfh'; final offerPoolUsdsOffer = Offer.fromBech32(offerPoolUsdsRequested); expect(offerPoolUsdsOffer.requestedAmounts.standard, equals(0)); - expect(offerPoolUsdsOffer.requestedAmounts.cat[usdsAssetId], equals(0.42 * mojosPerCat)); + expect( + offerPoolUsdsOffer.requestedAmounts.cat[usdsAssetId], + equals(0.42 * mojosPerCat), + ); - expect(offerPoolUsdsOffer.offeredAmounts.standard, equals((0.01 * mojosPerXch).round())); + expect( + offerPoolUsdsOffer.offeredAmounts.standard, + equals((0.01 * mojosPerXch).round()), + ); expect(offerPoolUsdsOffer.offeredAmounts.cat.isEmpty, true); const offerPoolSpacebucksOffered = 'offer1qqz83wcsltt6wcmqvpsxygqqwc7hynr6hum6e0mnf72sn7uvvkpt68eyumkhelprk0adeg42nlelk2mpafs8tkhg2qa9qmxp3mp9hd0p40egtjc2t8lh9kldt70h3gatft30gztnle5ddrtp8wtnjqv43qkdaujr743dltdr67vx6ha0l3huslr8awq67r6wyntkln06xaw7uslmlum2vhd4aux33s8klqaq3nukvc7hamu5ln0wk239xhgnk0ykmh4e822jut6tl42stnl992lsqrhuxf4kll47yznx4q93kms3ljm8wqkh3f9tru5n0fw5680m9gwyzvfylpcrz0ykg6d3lg7d3lg7d3mg7d3mf7vpn60ydxclw34husq27uz7d7e7y77xkmf5mcmrwvn2gthfzkxx75q7vu7hqmrw6r8vmfwj8264q42mvn8ruzskxlaklvrfwfyx87ch3j83dt4crhtkcpkrjk6jvreexejdv959tq2ucyx7w4tyvzpnwmzstjnaz8z3kg6r93dzvttjn669sut6jmgsnhm5c7x3u784dzelwvuzdm5ulf5j7se8maqe6xlleg0jtm5z34qgyrrgsz6vhl30yr2vf77lqfhr5yzkpqedtehls2z93ud9em0uh8xaz58hvlyjdzvl5n67a0w6jwazhefxwtjfarrxmlsd23jl7l7phua7ce3jtumxet0nzesaz772t0n4q6q3e87r848cwead0cmhwedugg0fl8lc95mj4un3dwr942lam05va4l83w3dxa86m4e3ev3djxul4cjwtwrfkl74lu83cqvkznlnlla6u2v7ekwhtmynp9l6xx0rdnld2a52e2ektdgks4rlum7fkzc3z68chls9adkrwv8hth4a7xheueyaunekn7dd00626mn0w0lfff0eexfr040lq9kj84xsl2lcq5znpvf95r2yny6lmhhrwrhq0n7hrd9wulqh78td6gpv62eur0f4ytsnye6ksgtgwze8esk9q5pv0ek3g6796alwnkljxwym0haww8jntk9uwjmlalj5sw6g5jewfskk74ad64w0r4pv8lxl5mjpejn6austdsul8ed8katmxt038vu0lx0rnl6kkts5a5aduc23nxcgndthdkt03hlcx52m844h46gr2924hzlk5jkcxsq8kk0twyf29uts'; - final offerPoolSpacebucksOffer = Offer.fromBech32(offerPoolSpacebucksOffered); - expect(offerPoolSpacebucksOffer.requestedAmounts.standard, equals((3.0 * mojosPerXch).round())); + final offerPoolSpacebucksOffer = + Offer.fromBech32(offerPoolSpacebucksOffered); + expect( + offerPoolSpacebucksOffer.requestedAmounts.standard, + equals((3.0 * mojosPerXch).round()), + ); expect(offerPoolSpacebucksOffer.requestedAmounts.cat.isEmpty, true); expect(offerPoolSpacebucksOffer.offeredAmounts.standard, equals(0)); @@ -72,39 +87,47 @@ void main() { final offer = catOfferService.makeOffer( coinsForOffer: MixedCoins(cats: nathan.cat2Coins), offeredAmounts: OfferedMixedAmounts(cat: {nathanCatCoinAssetId: 1000}), - requestedPayments: RequestedMixedPayments(standard: [Payment(900, nathan.firstPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(900, nathan.firstPuzzlehash)], + ), keychain: nathan.keychain, changePuzzlehash: nathan.firstPuzzlehash, ); try { - final parsedOffer = - await OfferWalletService.parseOffer(offer, tailDatabaseApi: TailDatabaseApi()); + final parsedOffer = await OfferWalletService.parseOffer( + offer, + tailDatabaseApi: TailDatabaseApi(), + ); expect(parsedOffer.requestedAmounts.standard, 900); } on FormatException { //pass } }); - test('should fail with null keychain but non-empty offering coins for CAT2', () async { + test('should fail with null keychain but non-empty offering coins for CAT2', + () async { expect( () => catOfferService.makeOffer( coinsForOffer: MixedCoins(cats: nathan.cat2Coins), changePuzzlehash: nathan.firstPuzzlehash, - requestedPayments: - RequestedMixedPayments(standard: [Payment(1000, nathan.firstPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(1000, nathan.firstPuzzlehash)], + ), ), throwsA(isA()), ); }); - test('should fail with null keychain but non-zero offered amount for CAT2', () async { + test('should fail with null keychain but non-zero offered amount for CAT2', + () async { expect( () => catOfferService.makeOffer( offeredAmounts: OfferedMixedAmounts(cat: {nathanCatCoinAssetId: 1000}), changePuzzlehash: nathan.firstPuzzlehash, - requestedPayments: - RequestedMixedPayments(standard: [Payment(1000, nathan.firstPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(1000, nathan.firstPuzzlehash)], + ), keychain: nathan.keychain, ), throwsA(isA()), @@ -119,19 +142,23 @@ void main() { coinsForOffer: MixedCoins(cats: nathan.cat2Coins), offeredAmounts: OfferedMixedAmounts(cat: {nathanCatCoinAssetId: 1000}), changePuzzlehash: nathan.firstPuzzlehash, - requestedPayments: - RequestedMixedPayments(standard: [Payment(1000, nathan.firstPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(1000, nathan.firstPuzzlehash)], + ), ), throwsA(isA()), ); }); - test('should fail with null puzzlehash and non-zero offer amount for CAT2', () async { + test('should fail with null puzzlehash and non-zero offer amount for CAT2', + () async { final askOffer = catOfferService.makeOffer( coinsForOffer: MixedCoins(cats: nathan.cat2Coins), offeredAmounts: OfferedMixedAmounts(cat: {nathanCatCoinAssetId: 1000}), changePuzzlehash: nathan.firstPuzzlehash, - requestedPayments: RequestedMixedPayments(standard: [Payment(1000, nathan.firstPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(1000, nathan.firstPuzzlehash)], + ), keychain: nathan.keychain, ); @@ -157,8 +184,9 @@ void main() { coinsForOffer: MixedCoins(cats: nathan.cat1Coins), offeredAmounts: OfferedMixedAmounts(cat: {nathanCat1CoinAssetId: 1000}), changePuzzlehash: nathan.firstPuzzlehash, - requestedPayments: - RequestedMixedPayments(standard: [Payment(1000, nathan.firstPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(1000, nathan.firstPuzzlehash)], + ), keychain: nathan.keychain, ), throwsA(isA()), @@ -170,20 +198,25 @@ void main() { () => catOfferService.makeOffer( offeredAmounts: OfferedMixedAmounts(cat: {nathanCatCoinAssetId: 1000}), changePuzzlehash: nathan.firstPuzzlehash, - requestedPayments: - RequestedMixedPayments(standard: [Payment(1000, nathan.firstPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(1000, nathan.firstPuzzlehash)], + ), keychain: nathan.keychain, ), throwsA(isA()), ); }); - test('should fail when offered amounts exceeds offered coins amounts for CAT2', () async { + test( + 'should fail when offered amounts exceeds offered coins amounts for CAT2', + () async { expect( () => catOfferService.makeOffer( coinsForOffer: MixedCoins(standardCoins: nathan.standardCoins), offeredAmounts: const OfferedMixedAmounts(standard: 10000), - requestedPayments: RequestedMixedPayments(standard: [Payment(900, nathan.firstPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(900, nathan.firstPuzzlehash)], + ), keychain: nathan.keychain, changePuzzlehash: nathan.firstPuzzlehash, ), @@ -196,8 +229,9 @@ void main() { () => catOfferService.makeOffer( offeredAmounts: OfferedMixedAmounts(cat: {nathanCatCoinAssetId: -1}), changePuzzlehash: nathan.firstPuzzlehash, - requestedPayments: - RequestedMixedPayments(standard: [Payment(1000, nathan.firstPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(1000, nathan.firstPuzzlehash)], + ), keychain: nathan.keychain, ), throwsA(isA()), @@ -209,8 +243,9 @@ void main() { () => catOfferService.makeOffer( offeredAmounts: const OfferedMixedAmounts(standard: -1), changePuzzlehash: nathan.firstPuzzlehash, - requestedPayments: - RequestedMixedPayments(standard: [Payment(1000, nathan.firstPuzzlehash)]), + requestedPayments: RequestedMixedPayments( + standard: [Payment(1000, nathan.firstPuzzlehash)], + ), keychain: nathan.keychain, ), throwsA(isA()), @@ -232,7 +267,8 @@ void main() { expect(offer.offeredCoins.cats.length, 1); }); - test('should create an offer from an offer file offering both CAT and NFT', () async { + test('should create an offer from an offer file offering both CAT and NFT', + () async { const offerFile = 'offer1qqzh3wcuu2ryhmwu0v6ffhg7qlc8z2d00deqkhwlpp5usmg5hxzzfa6m5s5xdrp3p3nge339d9x8g425z3znmm4aeqj522y2gs22zgjzvk29f6zx5j0rxg66wht8h43uv7kaxw0089nlhqa4vmkmt8mdau7hk04luuanx2q5fg2vtcd8utvh4mxgxhnm3q6hcw6l3y4jck8gct3ct000lzdc4vun6l8zt3wdsm9mhltgflm87vrps65nzetn04aczrdlj6w3us5l0pv3dg96cjjkagmqn78r6n3ytdlxt33r2xg3er3whew8rg7e90x09hctgcls7znyew2ua8eakrte93j3ya4m87pxxa94j4x4r5uhtyfaexkkqgznrzgl3ezs3ww8dv7sj3arzdr4t9x9jt85kt53y608nttlgfmma3wz973y0d9egn9kytdky5035w5ete2te7rxw4zedgdyltxp5uwd9mfq7dlkgqwq9cssrrzzrlu9w8yt00gdahya2u9vae5hm5kmcsll0cnranrv4xedrec4hdxu546mkuvrju3vav267jaqs7r5p9y0p2flkj7hnjcyd2c77y00j8jzxj3lx6uf2apl8s935xwal8ajvwu0a00x8qg6ly6nnyd6qm20p3krqkv6mkfkn9mkl68lx9e6j8c0pugv9ly6p5qy9x8lm5gxv7krgwg02wghn2k48f5p68424n7kwnhgpltnv3etxu26qk04dka67ww23xtatmkgftc8lvzq0yafhf4x44ps94p2q4sspxplr38pk45czk9u5unez9yzcuf8esasvyssgmczj5tyau8kyjzdrlyzwj7gyzpp5y29tnaqzz7zwrd0r2qq743rl8aqfcygx3xc9zv9gcgvzmaakxyuup5n4kmwhddg4ejtyuucdws2j2u9vgt356hreylycldqz4gerjdasmrh3lphfq7mhmfs537kj7f6k76v5k57jv879p8f6cn4jffpc0luwq0ze828q54qxeyaxv6qywgggg2sl5pusxxdwp0klaslr5x5lrqkpk35854xvxcwfs8qgp9psn5nuruaxqph59wecamzdzhpkvfctg5dnknnslrp4v49l28wq8dtf56jm5tgt2ctwvg7svxhgddrsmgdj9lhsy0wr9z0hytcgyn9gsn8x8p56sjz75x0ejyk5ke4hq7eqmrcf35vze2k405eh0svjg8c4avmrtqtum6gpk0y2q057kg2trtzl2ea845x7hx6jrhpmkxhw2j29ajvftmt68aj8p7c6eclsncw85gflld5kaqhcphzxv8w8q2p0jr8f8078hcandan4uhx729vxqtjteaymqrntdqcxur2a7gc95tn552judqrtwxc4wuwykanm9e7emu2gcgy8qgcagh37s7pllnwyzxzr6taasm52ehecca9mgj0wk38ffqygae7tc0hk0zvee8nzw5r48e26xvravphk7850lcdf75ll4svsax8g5zs052ntmthc4mda099s7rka8wd2hpwkr4n9ktwnhwg4yhkflzhkfjnuduqtccesdvvrgg78snx23wlaj553llepuxy8pnum5k7ts6jk38g8eq8zgw36pessu5k8n0cclv5wnl8ta6vj7xtsjsk6qt3e7lx37zmj96e9hkqg7z909p4cgfrkfvj73zjpav9j375zyknyd3a7xv6rcc2kk5z8rw7jephu0vgs0f6gvvp9hhpktacsq92vhjw6e49fj7n0p9ec5umvu0jlhzd7wj67s7eg9g7kpdytrd39u7hh9c0f8ral8a3plap0egsvh6mlh9cn26r064yc8hvzsm5plru32x3kmpm3rn4xy7ddrjelj95e9sd3lphvh37d8n7yeza4hm2un8uvwtc4k8s7cz76qu3r5emwqme0md8ug93qkyj6jrvg93qkyjmjrv0uur7l35vghummp8plm5sfm2hhrlpnq5vm5j567klrl3hmkus4mt52ghasme0kul4gxd3dpjlsn9n6u9xtwl24nrhf44z04zem5x0wakwpe5aw0hnm62djq02c39wp5keu7dfqzly9e4t07ryzy5g3xesap3gd4wgx9ep8k96n4hul6p38vwtpfh33a225x0cst4c0n2vh2wk8hndk05959t78wpp5ksme2wjs78ytas848hg0r9j5my9mmlm3prktnptdfla0qdpd63u9xkljvjn8mjvmk3n06tfnhm8ema9540tf7v0em0z8gvwze5c5vqr24rgwgv83l8rcum2j3wz9n3m6yprtrrn3u87ucsxgc6kmkmz0dr02m5ydgn7kk5ulqzy88qqqhemp3lulmslecaeycjkwxkd6akajjrnlm9thcjrvhu4pk7nku3rmv80thdkvpqe9a4ln3zcz0q2jfuy5rahn0cr6qqaqqwsq8gqr5qp6r7hqlsq6r7nlq2wr7r25w4dv87z9h2dd2dh6kcyzu78q7h9hlp0taf970aat32ze87afpywtxpqn3mldz074v7u7qsed50ea64dqk6xh43puf0lfcrr26379l09g6qzr9n6qtuxev4gu5efnk8qv6ck77nujfdwasgg72rte8y977nh84lcdcpr09z8pcsgxrmdcsetnt5rstj7vk3de4gnnrpqr08wag3d42wdrwc8y4fjjcn8rwehzs33svfh04azwul2pysupwqpcqqvqqxqqrqqps9xrupsp7e7hycqpk8hfyzsp76nsp6mcvl3jm7neaatj8er2cn9feqn393ca7ug5hwkdymjacwscx9nuefsxss8m0m55tnwq4mlt4dn0y5r5z9892c5882and6hmhug5pzprrhgzl2cqzfjt4nru44s70j5a294qtjhz0s4rz53f2m20k3cpcawp640pr3twgvzzdrcqudngaw0va08zav5nrvyqx9k4hhcqehkjuw0h29s8ytnz2t63h42we98m7cfq8q836xnyu9208jq5sysqpsqqcqqvqqxqqrq8qqpsr7s4qqe9j69gu976g4dw2q7xdlvnf5x52vw5730wgqulv8lrw57plzwpd23syk3h023t9x76n6ursqqqhnnyzvj26g4jn04lte9ctdagd84fp66vyrx58utvzjzr7gyl4664d4946p2ay5hcvkrymktg3ttwax8mtyw9nhyd765us6yyajzzezuqyeewtue48uvfamn4u4h8wt7cw7fczw0kf7j8vnfevk9xjhw94r8d4uwl4v46n3asygpyyqvzqxpqrqspsgqcpsyqvz0k9gyt0rtfrtzl6m8zcn7j5jxjtwxusjewf87gvaujxzmr4q80jkm66eslpj2udh972mmnxavpt0mj4r5rz3mj70kech8r5h4d8na9dznhg6rtpkq2vmck6eqse4et8ycadzp4s3xnhvaf96ka77x9f28fzdk7rvmeklchfa7mf2uuxyw3ppvs679kvkh4z9a7swexkmw5q376mckcvr9f9zmjz53rntm07zfx7377q4jrpezu6cz8r6sgcjggqcyqvzqxpqrqspsrqgqcy8v2ugzcy2h62tt0hc0d0my28r45lss95ut8jepdr02h5m22eapwwpde6grgvr24mhdldt5drvth97a5v3q8fkd0xtl0fszelgyhm4kp8g577ga6d6eld3p0zmqeu8ar0mkv0e6k27d2lf6x2f5t3pjjl8u9f775h0n6sqjzcm57vp5gazzzezz5fv7ks5czcvdat9q6vkdp7a5mv24aur88plk8n0e777nc77vrcfgq2p0r5jeadr2wul2pysuz7qpcyqvzqxpqrqspsdxrupsf7e7hyczpk8hfyzsf76nsgys5ttljmues4a0jf53tew2nueedm8v77g4d38s9uumcu4f5kpyydsv556zlkhfupn6ftexta9r5zf05t92ys3jtjle4t4euvnhvd6endss5v6se5kgyh2djd9ynhptr5a3er47kum8fsx6hn9rrvkw8wmg57xh6avlv6dup53r5ufyrqhhhnrufl45krau9ytrua4lvf5739rq69tz2wrqyxujk5xgjtqv326m6wzzezry9u8208jqzqysspsgqcyqvzqxpqrq8qspst7s4qhfzhyrg7j9clks550gmpvhmdzs598q3wlmm352asep0sryzm62n5rcvnr968a05njpggp039rpnp70mvv8cmvxwftduthd08e76t9k6xactza6fr69xrlkph9u02kuxdgzn0g4fa96ku3fs3e0jlfkcmrjlpr9xrn8unxg73jyyajyze9j50fjm56fj3ev95a883ykd2k9p5v99z5rtdm727cvx5uvqkmmpnvahuwep0q6jflswe7yqvzqxpqrqspsgqcpsyqvzrk9wypv67n7n9nh5ysm8k86udswamw54ru5z4nz97pwmzky8wj9dfvuuk9gwgft5defx4zmw3fgp4y238tjjq08fzcuwh4y6ctwtx9hvmtnxh5er8pse8jpzmqcu2qtqlgjufmeml7z42dqx5ldwf3udw940f0qz2zmv40n4mwgcd20gazzwer0clnlehtzfqyzds56sryd5azan6caxuayhgfzmgkl8x98f09jj5nefyxrh9cpfd7rmz8punhafspcc0m9znk9pn3m7ndad4yz5wujw37e845jyk9xdr0zek2c82eq600a24uy59yaqvmsc8j2hwlmc4emtlf93qqekwh8hd2ct62glmxqrky692dpa8vl98tl6c5ddnph56mdck22n6nxg9lfjzmmdfazcc8g52hft26rzsspex4088gvtqy9v80f42eadm6jwra22rx5v2tl4ekpt0zkz8wfesym8kh8t7vfaf9a6h937p3j06dlarc7fstygnlywv0c29yxgjzmf8t5emmea7hyrwued95uah385hupzgdw4eenm36avnmeytsnflmgrpeetlny2wn70wuzmv4903p4lym4ukpj2vgsmq5jpz2yfgpyqgj3z2yf5c0sxfw37lyctll2ykg7s0k6xh8jh743p48wh34h8f23yu2rzyyls4lges4ehwzzp6677d5u0x5spa8c6al7nun5yxplc6uhxauuwk56kk5t76zmlj3wrs8dh29w8uh7l30w0z0jf3rdmwlj5c3wlkgjav9ful5zawt8arndv84maeewtd7l5faaq0h9nddev9my2d8wtdlduzvxfjwak97x3efjec8rgnvwa2lwtp808k8dv9fagyh3cg7sm7vc3m0fjynt9ylhufy6flzfvv48t532azll08v7t2lmryvulh2f7eqaedsefc9we55gqwsxpzqn59nxvq2pfuw020kazda3yckv95pxgn3knrw72h29wwg3ph2ndlafak45gmkgnzl2r5zmt26rw7fh46ulz80uzjlf2uyxn0qpdg0hhn656u9ykltexxhd8k2xsw7kuqxkq8tqr4sp6cqavqwklktm9tnytlcfdmxz0yssn5qe377lmgar8w4f5pd6l22naayaae6uc9j29wvhn2gq4naclvuw8n79yza00576qfapmfwj9gk66zw0559xvfqmtkw9g0cc8t5dwtym8trtu4x4erlktrjzytfr7kuvtwxks4vw89sj5kpldg5ujjahxdr82uqx94nemx9c7eyx4ldtvg3nwly90mffgeqk2lm00arxn4pr8msmpv0ggehaddfcqy9gvwq3d2t8t8rmgt8t556m37lxe9m0ef7tflgey9cupa3zh5lcyh5umuuxlhp7qltju9c49ekwf4aegny7mnttn9gwh42znx46gymsfv6aum9qwnh9f0ddrk5vhvuhda52gh83h3nyfjs6ka8pl9xetw66f56vkh4ujxtu89fym962dplsx4wkhnmsxu0k77'; final offer = Offer.fromBech32(offerFile); diff --git a/test/offer/mixed_amounts_test.dart b/test/offer/mixed_amounts_test.dart index 22369133..6e613aa1 100644 --- a/test/offer/mixed_amounts_test.dart +++ b/test/offer/mixed_amounts_test.dart @@ -6,7 +6,8 @@ import '../util/test_data.dart'; void main() { test('should return the desired string form using a CAT1 coin', () { - final mixedAmounts = MixedAmounts(cat: {TestData.validCat1Coin0.assetId: 1000}); + final mixedAmounts = + MixedAmounts(cat: {TestData.validCat1Coin0.assetId: 1000}); expect( mixedAmounts.toString(), 'MixedAmounts(standard: ${mixedAmounts.standard}, cat: ${mixedAmounts.cat}, nftLauncherIds: {})', @@ -14,7 +15,8 @@ void main() { }); test('should return the desired string form using a CAT2 coin', () { - final mixedAmounts = MixedAmounts(cat: {TestData.validCatCoin0.assetId: 1000}); + final mixedAmounts = + MixedAmounts(cat: {TestData.validCatCoin0.assetId: 1000}); expect( mixedAmounts.toString(), 'MixedAmounts(standard: ${mixedAmounts.standard}, cat: ${mixedAmounts.cat}, nftLauncherIds: {})', diff --git a/test/offer/mixed_notarized_payments_test.dart b/test/offer/mixed_notarized_payments_test.dart index cdf1886d..14482ff3 100644 --- a/test/offer/mixed_notarized_payments_test.dart +++ b/test/offer/mixed_notarized_payments_test.dart @@ -9,7 +9,9 @@ void main() { final mixedNotarizedPayments = MixedNotarizedPayments( { GeneralCoinType.standard: {null: notarizedPayments}, - GeneralCoinType.cat: {TestData.standardCoin.puzzlehash: notarizedPayments}, + GeneralCoinType.cat: { + TestData.standardCoin.puzzlehash: notarizedPayments + }, }, ); diff --git a/test/pool/authentication_payload_test.dart b/test/pool/authentication_payload_test.dart index f3c2042e..16d9d225 100644 --- a/test/pool/authentication_payload_test.dart +++ b/test/pool/authentication_payload_test.dart @@ -3,14 +3,17 @@ import 'package:test/test.dart'; void main() { // CreateWalletWithPlotNFTCommand used to generate test values - final launcherId = - Bytes.fromHex('08f65801d644b71f1388d269c284f48ad5ce0a7b3cc83a3a13f54708f88dea78'); - final targetPuzzlehash = - Puzzlehash.fromHex('6bde1e0c6f9d3b93dc5e7e878723257ede573deeed59e3b4a90f5c86de1a0bd3'); + final launcherId = Bytes.fromHex( + '08f65801d644b71f1388d269c284f48ad5ce0a7b3cc83a3a13f54708f88dea78', + ); + final targetPuzzlehash = Puzzlehash.fromHex( + '6bde1e0c6f9d3b93dc5e7e878723257ede573deeed59e3b4a90f5c86de1a0bd3', + ); const authenticationToken = 5553478; - final authenticationSecretKey = - PrivateKey.fromHex('4405803e8ee6473da0d3d316a2bfa12bdf0fb03ab321872fbd258b536613a865'); + final authenticationSecretKey = PrivateKey.fromHex( + '4405803e8ee6473da0d3d316a2bfa12bdf0fb03ab321872fbd258b536613a865', + ); final authenticationPayload = AuthenticationPayload( endpoint: AuthenticationEndpoint.get_farmer, diff --git a/test/pool/get_farmer_response_test.dart b/test/pool/get_farmer_response_test.dart index dcd126f2..90c22d18 100644 --- a/test/pool/get_farmer_response_test.dart +++ b/test/pool/get_farmer_response_test.dart @@ -20,7 +20,9 @@ void main() { ); expect( getFarmerResponse.payoutInstructions, - Puzzlehash.fromHex('f7b8e2be4865eaedaeac80f0577f41b89fc0b32f9536e458809548192ea9c528'), + Puzzlehash.fromHex( + 'f7b8e2be4865eaedaeac80f0577f41b89fc0b32f9536e458809548192ea9c528', + ), ); expect(getFarmerResponse.currentDifficulty, 1); expect(getFarmerResponse.currentPoints, 9999); diff --git a/test/pool/plot_nft_test.dart b/test/pool/plot_nft_test.dart index 0f126243..64eeda92 100644 --- a/test/pool/plot_nft_test.dart +++ b/test/pool/plot_nft_test.dart @@ -4,17 +4,30 @@ import 'package:test/test.dart'; void main() { // CreateWalletWithPlotNFTCommand used to generate test values final singletonCoin = CoinPrototype( - parentCoinInfo: - Puzzlehash.fromHex('17ff3c80192a7e616926e9194d69fd3fa0def1827964b1bf4f05d6b7de3f43c9'), - puzzlehash: - Puzzlehash.fromHex('01178c847be8e6766954ebf9db5c20dc263d02d0bb3cc057a1412fd1d7158daf'), + parentCoinInfo: Puzzlehash.fromHex( + '17ff3c80192a7e616926e9194d69fd3fa0def1827964b1bf4f05d6b7de3f43c9', + ), + puzzlehash: Puzzlehash.fromHex( + '01178c847be8e6766954ebf9db5c20dc263d02d0bb3cc057a1412fd1d7158daf', + ), + amount: 1, + ); + + final lineageProof = LineageProof( + parentCoinInfo: Puzzlehash.fromHex( + 'e453b4a08681ec44f5b4a35af34e96de1ac8b70b28f22a32274100729a7d7f23', + ), + innerPuzzlehash: Puzzlehash.fromHex( + '58533d495d2c2157cc607011288e844438bea09237b634bd40c40e42730b4862', + ), amount: 1, ); final poolState = PoolState( poolSingletonState: PoolSingletonState.farmingToPool, - targetPuzzlehash: - Puzzlehash.fromHex('6bde1e0c6f9d3b93dc5e7e878723257ede573deeed59e3b4a90f5c86de1a0bd3'), + targetPuzzlehash: Puzzlehash.fromHex( + '6bde1e0c6f9d3b93dc5e7e878723257ede573deeed59e3b4a90f5c86de1a0bd3', + ), ownerPublicKey: JacobianPoint.fromHexG1( '0x95b96e957115f0bc3858163c9d89b948b895d1296dc660030f635ebc62d5d99cbdb38c6e0c995d5d92ef907e34195e8e', ), @@ -22,13 +35,16 @@ void main() { ); final plotNft = PlotNft( - launcherId: - Puzzlehash.fromHex('17ff3c80192a7e616926e9194d69fd3fa0def1827964b1bf4f05d6b7de3f43c9'), + launcherId: Puzzlehash.fromHex( + '17ff3c80192a7e616926e9194d69fd3fa0def1827964b1bf4f05d6b7de3f43c9', + ), singletonCoin: singletonCoin, poolState: poolState, delayTime: 604800, - delayPuzzlehash: - Puzzlehash.fromHex('a229c30fba7b35557ec417fbce1fc9eaf2bac74e574b2f0b079c03bde3c99d16'), + delayPuzzlehash: Puzzlehash.fromHex( + 'a229c30fba7b35557ec417fbce1fc9eaf2bac74e574b2f0b079c03bde3c99d16', + ), + lineageProof: lineageProof, ); test('should correctly serialize and deserialize plot nft', () { diff --git a/test/pool/pool_info_test.dart b/test/pool/pool_info_test.dart index 191bdeca..3f060d7e 100644 --- a/test/pool/pool_info_test.dart +++ b/test/pool/pool_info_test.dart @@ -41,7 +41,9 @@ void main() { ); expect( poolInfo.targetPuzzlehash, - Puzzlehash.fromHex('0x6bde1e0c6f9d3b93dc5e7e878723257ede573deeed59e3b4a90f5c86de1a0bd3'), + Puzzlehash.fromHex( + '0x6bde1e0c6f9d3b93dc5e7e878723257ede573deeed59e3b4a90f5c86de1a0bd3', + ), ); expect( poolInfo.authenticationTokenTimeout, diff --git a/test/pool/post_farmer_payload_test.dart b/test/pool/post_farmer_payload_test.dart index ab6036a7..e22f64ec 100644 --- a/test/pool/post_farmer_payload_test.dart +++ b/test/pool/post_farmer_payload_test.dart @@ -2,7 +2,8 @@ import 'package:chia_crypto_utils/chia_crypto_utils.dart'; import 'package:test/test.dart'; void main() { - const chiaPayloadHashHex = '12cce226f66188ea5c93d8337f0fa7512cec31c383e5ca897dcba04f60e5cec0'; + const chiaPayloadHashHex = + '12cce226f66188ea5c93d8337f0fa7512cec31c383e5ca897dcba04f60e5cec0'; final launcherId = Program.fromBool(true).hash(); const authenticationToken = 12689; @@ -26,7 +27,8 @@ void main() { expect(payload.toJson(), { 'launcher_id': payload.launcherId.toHexWithPrefix(), 'authentication_token': payload.authenticationToken, - 'authentication_public_key': payload.authenticationPublicKey.toHexWithPrefix(), + 'authentication_public_key': + payload.authenticationPublicKey.toHexWithPrefix(), 'payout_instructions': payload.payoutPuzzlehash.toHexWithPrefix(), 'suggested_difficulty': payload.suggestedDifficulty, }); diff --git a/test/src/core/models/keychain_core_secret_serialization_test.dart b/test/src/core/models/keychain_core_secret_serialization_test.dart index e294b983..4bb8f5fb 100644 --- a/test/src/core/models/keychain_core_secret_serialization_test.dart +++ b/test/src/core/models/keychain_core_secret_serialization_test.dart @@ -6,7 +6,8 @@ void main() { test('should serialize and deserialize keychain core secret', () { final keychainsSecretSerialized = keychainSecret.toBytes(); - final keychainSecretDeSerialized = KeychainCoreSecret.fromBytes(keychainsSecretSerialized); + final keychainSecretDeSerialized = + KeychainCoreSecret.fromBytes(keychainsSecretSerialized); final keychainSecretReSerialized = keychainSecretDeSerialized.toBytes(); expect(keychainSecretReSerialized, equals(keychainsSecretSerialized)); diff --git a/test/src/core/models/wallet_keychain_serialization_test.dart b/test/src/core/models/wallet_keychain_serialization_test.dart index 323351d6..20c69b5f 100644 --- a/test/src/core/models/wallet_keychain_serialization_test.dart +++ b/test/src/core/models/wallet_keychain_serialization_test.dart @@ -23,7 +23,8 @@ void main() async { test('should correctly serialize and deserialize a WalletKeychain', () { final walletKeychainSerialized = walletKeychain.toBytes(); - final walletKeychainDeserialized = WalletKeychain.fromBytes(walletKeychainSerialized); + final walletKeychainDeserialized = + WalletKeychain.fromBytes(walletKeychainSerialized); expect( walletKeychainDeserialized.hardenedWalletVectors.length, @@ -34,7 +35,9 @@ void main() async { equals(walletKeychain.hardenedWalletVectors.length), ); - for (var i = 0; i < walletKeychainDeserialized.hardenedWalletVectors.length; i++) { + for (var i = 0; + i < walletKeychainDeserialized.hardenedWalletVectors.length; + i++) { expect( walletKeychainDeserialized.hardenedWalletVectors[i], equals(walletKeychain.hardenedWalletVectors[i]), @@ -51,11 +54,15 @@ void main() async { equals(walletKeychain.unhardenedWalletVectors.length), ); - final deserializeUnhardenedWalletVectors = walletKeychainDeserialized.unhardenedWalletVectors; - final originalUnhardenedWalletVectors = walletKeychain.unhardenedWalletVectors; + final deserializeUnhardenedWalletVectors = + walletKeychainDeserialized.unhardenedWalletVectors; + final originalUnhardenedWalletVectors = + walletKeychain.unhardenedWalletVectors; - deserializeUnhardenedWalletVectors.sort((a, b) => a.puzzlehash.compareTo(b.puzzlehash)); - originalUnhardenedWalletVectors.sort((a, b) => a.puzzlehash.compareTo(b.puzzlehash)); + deserializeUnhardenedWalletVectors + .sort((a, b) => a.puzzlehash.compareTo(b.puzzlehash)); + originalUnhardenedWalletVectors + .sort((a, b) => a.puzzlehash.compareTo(b.puzzlehash)); for (var i = 0; i < deserializeUnhardenedWalletVectors.length; i++) { expect( @@ -74,7 +81,9 @@ void main() async { equals(walletKeychain.singletonWalletVectors.length), ); - for (var i = 0; i < walletKeychainDeserialized.singletonWalletVectors.length; i++) { + for (var i = 0; + i < walletKeychainDeserialized.singletonWalletVectors.length; + i++) { expect( walletKeychainDeserialized.singletonWalletVectors[i], equals(walletKeychain.singletonWalletVectors[i]), diff --git a/test/src/core/models/wallet_vector_test.dart b/test/src/core/models/wallet_vector_test.dart index 397e0d7a..60cc1025 100644 --- a/test/src/core/models/wallet_vector_test.dart +++ b/test/src/core/models/wallet_vector_test.dart @@ -53,7 +53,8 @@ void main() { 'UnhardenedWalletWector serializarion and deserialization to bytes must work', () async { final keychainSecret = KeychainCoreSecret.fromMnemonic(testMnemonic); - final walletSet = WalletSet.fromPrivateKey(keychainSecret.masterPrivateKey, 0); + final walletSet = + WalletSet.fromPrivateKey(keychainSecret.masterPrivateKey, 0); final keychain = WalletKeychain.fromWalletSets([walletSet]) ..addOuterPuzzleHashesForAssetId( Puzzlehash.fromHex( @@ -80,7 +81,8 @@ void main() { 'SingletonWalletVector serializarion and deserialization to bytes must work', () async { final keychainSecret = KeychainCoreSecret.fromMnemonic(testMnemonic); - final walletSet = WalletSet.fromPrivateKey(keychainSecret.masterPrivateKey, 0); + final walletSet = + WalletSet.fromPrivateKey(keychainSecret.masterPrivateKey, 0); final keychain = WalletKeychain.fromWalletSets([walletSet]) ..getNextSingletonWalletVector(keychainSecret.masterPrivateKey) ..getNextSingletonWalletVector(keychainSecret.masterPrivateKey); diff --git a/test/standard/wallet_service_test.dart b/test/standard/wallet_service_test.dart index 0a37d2f5..e1841c26 100644 --- a/test/standard/wallet_service_test.dart +++ b/test/standard/wallet_service_test.dart @@ -46,13 +46,16 @@ void main() { final keychainSecret = KeychainCoreSecret.fromMnemonic(testMnemonic); final walletsSetList = [ - for (var i = 0; i < 20; i++) WalletSet.fromPrivateKey(keychainSecret.masterPrivateKey, i), + for (var i = 0; i < 20; i++) + WalletSet.fromPrivateKey(keychainSecret.masterPrivateKey, i), ]; final walletKeychain = WalletKeychain.fromWalletSets(walletsSetList); - final coinPuzzlehash = walletKeychain.unhardenedMap.values.toList()[0].puzzlehash; - final changePuzzlehash = walletKeychain.unhardenedMap.values.toList()[1].puzzlehash; + final coinPuzzlehash = + walletKeychain.unhardenedMap.values.toList()[0].puzzlehash; + final changePuzzlehash = + walletKeychain.unhardenedMap.values.toList()[1].puzzlehash; final parentInfo0 = Bytes([ 227, @@ -210,7 +213,10 @@ void main() { test('Should create valid spendbundle with multiple payments', () { final spendBundle = walletService.createSpendBundle( - payments: [Payment(548000, destinationPuzzlehash), Payment(2000, destinationPuzzlehash)], + payments: [ + Payment(548000, destinationPuzzlehash), + Payment(2000, destinationPuzzlehash) + ], coinsInput: coins, changePuzzlehash: changePuzzlehash, keychain: walletKeychain, @@ -257,7 +263,8 @@ void main() { ); }); - test('Should create valid spendbundle with total amount less than coin value', () { + test('Should create valid spendbundle with total amount less than coin value', + () { final spendBundle = walletService.createSpendBundle( payments: [Payment(3000, destinationPuzzlehash)], coinsInput: coins, @@ -281,8 +288,11 @@ void main() { ); }); - test('Should create valid spendbundle without change puzzlehash when there is no change', () { - final totalCoinsValue = coins.fold(0, (int previousValue, coin) => previousValue + coin.amount); + test( + 'Should create valid spendbundle without change puzzlehash when there is no change', + () { + final totalCoinsValue = + coins.fold(0, (int previousValue, coin) => previousValue + coin.amount); final spendBundle = walletService.createSpendBundle( payments: [Payment(totalCoinsValue, destinationPuzzlehash)], coinsInput: coins, @@ -292,7 +302,9 @@ void main() { walletService.validateSpendBundle(spendBundle); }); - test('Should throw exception when change puzzlehash is not given and there is change', () { + test( + 'Should throw exception when change puzzlehash is not given and there is change', + () { expect( () { walletService.createSpendBundle( diff --git a/test/util/mock_chia_enthusiast.dart b/test/util/mock_chia_enthusiast.dart index 82056da5..6d8ded59 100644 --- a/test/util/mock_chia_enthusiast.dart +++ b/test/util/mock_chia_enthusiast.dart @@ -34,8 +34,9 @@ class MockChiaEnthusiast extends ChiaEnthusiastBase { spentBlockIndex: 0, coinbase: false, timestamp: 2748299274, - parentCoinInfo: - Bytes.fromHex('c1fdd54dd268a26fde78bb203a32a14ca942f015a9343d4ea5e9961f997256a1'), + parentCoinInfo: Bytes.fromHex( + 'c1fdd54dd268a26fde78bb203a32a14ca942f015a9343d4ea5e9961f997256a1', + ), puzzlehash: firstPuzzlehash, amount: 2000, ); @@ -49,8 +50,9 @@ class MockChiaEnthusiast extends ChiaEnthusiastBase { spentBlockIndex: 0, coinbase: false, timestamp: 274829924, - parentCoinInfo: - Bytes.fromHex('c1fdd54dd268a26fde78bb203a32a14ca942f015a9343d4ea5e9961f997256a1'), + parentCoinInfo: Bytes.fromHex( + 'c1fdd54dd268a26fde78bb203a32a14ca942f015a9343d4ea5e9961f997256a1', + ), puzzlehash: firstPuzzlehash, amount: 1000, ); @@ -65,8 +67,9 @@ class MockChiaEnthusiast extends ChiaEnthusiastBase { void addCatCoins() { const parentCoinSpendJson = '{"coin": {"parent_coin_info": "fe1cecf0d1c5ebce655f8a1c3ff1c532e1a05e60c209e34fbe645d89b9e96bf1", "puzzle_hash": "d9638d7c7e2cebfd7e6c023a5538e7ec7b7259ef85959c873b2c124fd393e67b", "amount": 2200000}, "puzzle_reveal": "ff02ffff01ff02ffff01ff02ff5effff04ff02ffff04ffff04ff05ffff04ffff0bff34ff0580ffff04ff0bff80808080ffff04ffff02ff17ff2f80ffff04ff5fffff04ffff02ff2effff04ff02ffff04ff17ff80808080ffff04ffff02ff2affff04ff02ffff04ff82027fffff04ff82057fffff04ff820b7fff808080808080ffff04ff81bfffff04ff82017fffff04ff8202ffffff04ff8205ffffff04ff820bffff80808080808080808080808080ffff04ffff01ffffffff3d46ff02ff333cffff0401ff01ff81cb02ffffff20ff02ffff03ff05ffff01ff02ff32ffff04ff02ffff04ff0dffff04ffff0bff7cffff0bff34ff2480ffff0bff7cffff0bff7cffff0bff34ff2c80ff0980ffff0bff7cff0bffff0bff34ff8080808080ff8080808080ffff010b80ff0180ffff02ffff03ffff22ffff09ffff0dff0580ff2280ffff09ffff0dff0b80ff2280ffff15ff17ffff0181ff8080ffff01ff0bff05ff0bff1780ffff01ff088080ff0180ffff02ffff03ff0bffff01ff02ffff03ffff09ffff02ff2effff04ff02ffff04ff13ff80808080ff820b9f80ffff01ff02ff56ffff04ff02ffff04ffff02ff13ffff04ff5fffff04ff17ffff04ff2fffff04ff81bfffff04ff82017fffff04ff1bff8080808080808080ffff04ff82017fff8080808080ffff01ff088080ff0180ffff01ff02ffff03ff17ffff01ff02ffff03ffff20ff81bf80ffff0182017fffff01ff088080ff0180ffff01ff088080ff018080ff0180ff04ffff04ff05ff2780ffff04ffff10ff0bff5780ff778080ffffff02ffff03ff05ffff01ff02ffff03ffff09ffff02ffff03ffff09ff11ff5880ffff0159ff8080ff0180ffff01818f80ffff01ff02ff26ffff04ff02ffff04ff0dffff04ff0bffff04ffff04ff81b9ff82017980ff808080808080ffff01ff02ff7affff04ff02ffff04ffff02ffff03ffff09ff11ff5880ffff01ff04ff58ffff04ffff02ff76ffff04ff02ffff04ff13ffff04ff29ffff04ffff0bff34ff5b80ffff04ff2bff80808080808080ff398080ffff01ff02ffff03ffff09ff11ff7880ffff01ff02ffff03ffff20ffff02ffff03ffff09ffff0121ffff0dff298080ffff01ff02ffff03ffff09ffff0cff29ff80ff3480ff5c80ffff01ff0101ff8080ff0180ff8080ff018080ffff0109ffff01ff088080ff0180ffff010980ff018080ff0180ffff04ffff02ffff03ffff09ff11ff5880ffff0159ff8080ff0180ffff04ffff02ff26ffff04ff02ffff04ff0dffff04ff0bffff04ff17ff808080808080ff80808080808080ff0180ffff01ff04ff80ffff04ff80ff17808080ff0180ffff02ffff03ff05ffff01ff04ff09ffff02ff56ffff04ff02ffff04ff0dffff04ff0bff808080808080ffff010b80ff0180ff0bff7cffff0bff34ff2880ffff0bff7cffff0bff7cffff0bff34ff2c80ff0580ffff0bff7cffff02ff32ffff04ff02ffff04ff07ffff04ffff0bff34ff3480ff8080808080ffff0bff34ff8080808080ffff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff2effff04ff02ffff04ff09ff80808080ffff02ff2effff04ff02ffff04ff0dff8080808080ffff01ff0bffff0101ff058080ff0180ffff04ffff04ff30ffff04ff5fff808080ffff02ff7effff04ff02ffff04ffff04ffff04ff2fff0580ffff04ff5fff82017f8080ffff04ffff02ff26ffff04ff02ffff04ff0bffff04ff05ffff01ff808080808080ffff04ff17ffff04ff81bfffff04ff82017fffff04ffff02ff2affff04ff02ffff04ff8204ffffff04ffff02ff76ffff04ff02ffff04ff09ffff04ff820affffff04ffff0bff34ff2d80ffff04ff15ff80808080808080ffff04ff8216ffff808080808080ffff04ff8205ffffff04ff820bffff808080808080808080808080ff02ff5affff04ff02ffff04ff5fffff04ff3bffff04ffff02ffff03ff17ffff01ff09ff2dffff02ff2affff04ff02ffff04ff27ffff04ffff02ff76ffff04ff02ffff04ff29ffff04ff57ffff04ffff0bff34ff81b980ffff04ff59ff80808080808080ffff04ff81b7ff80808080808080ff8080ff0180ffff04ff17ffff04ff05ffff04ff8202ffffff04ffff04ffff04ff78ffff04ffff0eff5cffff02ff2effff04ff02ffff04ffff04ff2fffff04ff82017fff808080ff8080808080ff808080ffff04ffff04ff20ffff04ffff0bff81bfff5cffff02ff2effff04ff02ffff04ffff04ff15ffff04ffff10ff82017fffff11ff8202dfff2b80ff8202ff80ff808080ff8080808080ff808080ff138080ff80808080808080808080ff018080ffff04ffff01a037bef360ee858133b69d595a906dc45d01af50379dad515eb9518abb7c1d2a7affff04ffff01a00ed71c399419b16df76ae7cde9fa257f1dbf845bef462b7f9ea6de8d181cdf97ffff04ffff01ff02ffff01ff02ffff01ff02ffff03ff0bffff01ff02ffff03ffff09ff05ffff1dff0bffff1effff0bff0bffff02ff06ffff04ff02ffff04ff17ff8080808080808080ffff01ff02ff17ff2f80ffff01ff088080ff0180ffff01ff04ffff04ff04ffff04ff05ffff04ffff02ff06ffff04ff02ffff04ff17ff80808080ff80808080ffff02ff17ff2f808080ff0180ffff04ffff01ff32ff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff06ffff04ff02ffff04ff09ff80808080ffff02ff06ffff04ff02ffff04ff0dff8080808080ffff01ff0bffff0101ff058080ff0180ff018080ffff04ffff01b0a347236fae530f3d88d8c8e31c144753934afc87465d690249b625c6211a33ffafa7859fea936b4d558f3c9a0454a869ff018080ff0180808080", "solution": "ffff80ffff01ffff33ffa0bae24162efbd568f89bc7a340798a6118df0189eb9e3f8697bcea27af99f8f79ff831e8480ffffa0bae24162efbd568f89bc7a340798a6118df0189eb9e3f8697bcea27af99f8f798080ffff33ffa0fdeb96380a70839c20471530a1ff87953e5e6b0f8244c162e1b95b9e5a6913ecff83030d4080ffff3cffa05f00170220ea8ae31a680e7a8e185d554a63f21eb63388d43c341250084b65c180ffff3fffa07d0a1bdcf9ffdaedc48e54eb55ec3d7318b6c1bc8029c62f5731b19f2f87fa678080ff8080ffffa022843326cad1524573740facdeb9157c2bed5ea8f2db41f7dae05b3a96e337f0ffa08a0000beb0c8cafa2416e41a2960dd9b0da500f2f0f0e0b3ebc1985dfa0aa6dcff8502357fc2e080ffa09e1043ca4182bd46cbeacdcc77e4ec10d98aca0591642aeffa4eb363d3866a7dffffa0fe1cecf0d1c5ebce655f8a1c3ff1c532e1a05e60c209e34fbe645d89b9e96bf1ffa0d9638d7c7e2cebfd7e6c023a5538e7ec7b7259ef85959c873b2c124fd393e67bff832191c080ffffa0fe1cecf0d1c5ebce655f8a1c3ff1c532e1a05e60c209e34fbe645d89b9e96bf1ffa08df97826f24a789c619fac173229a3f943565957735b0d97e0bd742f7167ac7dff832191c080ff80ff8080"}'; - final parentCoinSpend = - CoinSpend.fromJson(jsonDecode(parentCoinSpendJson) as Map); + final parentCoinSpend = CoinSpend.fromJson( + jsonDecode(parentCoinSpendJson) as Map, + ); final coin0 = Coin( confirmedBlockIndex: 17409283, spentBlockIndex: 0, diff --git a/test/util/test_data.dart b/test/util/test_data.dart index 8f9193b5..540cfa89 100644 --- a/test/util/test_data.dart +++ b/test/util/test_data.dart @@ -39,16 +39,20 @@ class TestData { '8351d5afd1ab40bf37565d25600c9b147dcda344e19d413b2c468316d1efd312f61a1eca02a74f8d5f0d6e79911c23ca'; static const chiaPoolPublicKeyHex = '926c9b71f4cfc3f8a595fc77d7edc509e2f426704489eaba6f86728bc391c628c402e00190ba3617931649d8c53b5520'; - static const chiaFirstAddress = - Address('txch1v8vergyvwugwv0tmxwnmeecuxh3tat5jaskkunnn79zjz0muds0qlg2szv'); - static final firstWalletSet = WalletSet.fromPrivateKey(keychainSecret.masterPrivateKey, 0); + static const chiaFirstAddress = Address( + 'txch1v8vergyvwugwv0tmxwnmeecuxh3tat5jaskkunnn79zjz0muds0qlg2szv', + ); + static final firstWalletSet = + WalletSet.fromPrivateKey(keychainSecret.masterPrivateKey, 0); // ChiaCoinRecord Data static final chiaCoinRecordJson = { 'coin': { 'amount': 250000000000, - 'parent_coin_info': '0x27ae41e4649b934ca495991b7852b855000000000000000000000000000000d8', - 'puzzle_hash': '0x0b7a3d5e723e0b046fd51f95cabf2d3e2616f05d9d1833e8166052b43d9454ad', + 'parent_coin_info': + '0x27ae41e4649b934ca495991b7852b855000000000000000000000000000000d8', + 'puzzle_hash': + '0x0b7a3d5e723e0b046fd51f95cabf2d3e2616f05d9d1833e8166052b43d9454ad', }, 'coinbase': true, 'confirmed_block_index': 217, @@ -56,63 +60,80 @@ class TestData { 'spent_block_index': 0, 'timestamp': 1653407000, }; - static final chiaCoinRecordFromJson = ChiaCoinRecord.fromJson(chiaCoinRecordJson); - static final coinFromChiaCoinRecordJson = Coin.fromChiaCoinRecordJson(chiaCoinRecordJson); + static final chiaCoinRecordFromJson = + ChiaCoinRecord.fromJson(chiaCoinRecordJson); + static final coinFromChiaCoinRecordJson = + Coin.fromChiaCoinRecordJson(chiaCoinRecordJson); // Coin Data static const parentCoinSpendJson = '{"coin": {"parent_coin_info": "88ab5f0a47c96b6dd8e0faa86f6f7711730c7a0f30aaa080a62b27139fa3fcb6", "puzzle_hash": "0b7a3d5e723e0b046fd51f95cabf2d3e2616f05d9d1833e8166052b43d9454ad", "amount": 10000}, "puzzle_reveal": "ff02ffff01ff02ffff01ff02ffff03ff0bffff01ff02ffff03ffff09ff05ffff1dff0bffff1effff0bff0bffff02ff06ffff04ff02ffff04ff17ff8080808080808080ffff01ff02ff17ff2f80ffff01ff088080ff0180ffff01ff04ffff04ff04ffff04ff05ffff04ffff02ff06ffff04ff02ffff04ff17ff80808080ff80808080ffff02ff17ff2f808080ff0180ffff04ffff01ff32ff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff06ffff04ff02ffff04ff09ff80808080ffff02ff06ffff04ff02ffff04ff0dff8080808080ffff01ff0bffff0101ff058080ff0180ff018080ffff04ffff01b0a4eb51326d2b1583201e22173c8d0e05a595c73039776ef179b7c40123794ebd43efb93364f5cf3ac3549d7b6851c10dff018080", "solution": "ff80ffff01ffff33ffa00b7a3d5e723e0b046fd51f95cabf2d3e2616f05d9d1833e8166052b43d9454adff82232880ffff34ff8203e880ffff3dffa0ece7df847532f6bebd02f1031133fea2f051d67bd8731b197a0efaae09bf09d180ffff3cffa043512694375995ddd59daf7983537433623c65f027522021a58f7f83dba3420e8080ff8080"}'; - static final parentCoinSpend = - CoinSpend.fromJson(jsonDecode(parentCoinSpendJson) as Map); + static final parentCoinSpend = CoinSpend.fromJson( + jsonDecode(parentCoinSpendJson) as Map, + ); static final standardCoin = Coin( confirmedBlockIndex: 16409283, spentBlockIndex: 0, coinbase: false, timestamp: 274829924, - parentCoinInfo: - Bytes.fromHex('0ea1f9522c7e365cbc502fa6d7ae90d8a5e43a6e983d0e25797094f0110f19cf'), - puzzlehash: - Puzzlehash.fromHex('0b7a3d5e723e0b046fd51f95cabf2d3e2616f05d9d1833e8166052b43d9454ad'), + parentCoinInfo: Bytes.fromHex( + '0ea1f9522c7e365cbc502fa6d7ae90d8a5e43a6e983d0e25797094f0110f19cf', + ), + puzzlehash: Puzzlehash.fromHex( + '0b7a3d5e723e0b046fd51f95cabf2d3e2616f05d9d1833e8166052b43d9454ad', + ), amount: 9000, ); // CAT1 Data - static const cat1Hex = '625c2184e97576f5df1be46c15b2b8771c79e4e6f0aa42d3bfecaebe733f4b8c'; + static const cat1Hex = + '625c2184e97576f5df1be46c15b2b8771c79e4e6f0aa42d3bfecaebe733f4b8c'; static final cat1AssetId = Puzzlehash.fromHex(cat1Hex); static const cat1ParentCoinSpendJson = '{"coin": {"parent_coin_info": "f4151ea2a45da9a31c748f71c866f27d17b91b605aeafa4089c35c685be72f77", "puzzle_hash": "778fd03bdb07f0f99046738bc6981dafacbbc0c09fecce04006576f301b74b12", "amount": 100}, "puzzle_reveal": "ff02ffff01ff02ffff01ff02ff5effff04ff02ffff04ffff04ff05ffff04ffff0bff2cff0580ffff04ff0bff80808080ffff04ffff02ff17ff2f80ffff04ff5fffff04ffff02ff2effff04ff02ffff04ff17ff80808080ffff04ffff0bff82027fff82057fff820b7f80ffff04ff81bfffff04ff82017fffff04ff8202ffffff04ff8205ffffff04ff820bffff80808080808080808080808080ffff04ffff01ffffffff81ca3dff46ff0233ffff3c04ff01ff0181cbffffff02ff02ffff03ff05ffff01ff02ff32ffff04ff02ffff04ff0dffff04ffff0bff22ffff0bff2cff3480ffff0bff22ffff0bff22ffff0bff2cff5c80ff0980ffff0bff22ff0bffff0bff2cff8080808080ff8080808080ffff010b80ff0180ffff02ffff03ff0bffff01ff02ffff03ffff09ffff02ff2effff04ff02ffff04ff13ff80808080ff820b9f80ffff01ff02ff26ffff04ff02ffff04ffff02ff13ffff04ff5fffff04ff17ffff04ff2fffff04ff81bfffff04ff82017fffff04ff1bff8080808080808080ffff04ff82017fff8080808080ffff01ff088080ff0180ffff01ff02ffff03ff17ffff01ff02ffff03ffff20ff81bf80ffff0182017fffff01ff088080ff0180ffff01ff088080ff018080ff0180ffff04ffff04ff05ff2780ffff04ffff10ff0bff5780ff778080ff02ffff03ff05ffff01ff02ffff03ffff09ffff02ffff03ffff09ff11ff7880ffff0159ff8080ff0180ffff01818f80ffff01ff02ff7affff04ff02ffff04ff0dffff04ff0bffff04ffff04ff81b9ff82017980ff808080808080ffff01ff02ff5affff04ff02ffff04ffff02ffff03ffff09ff11ff7880ffff01ff04ff78ffff04ffff02ff36ffff04ff02ffff04ff13ffff04ff29ffff04ffff0bff2cff5b80ffff04ff2bff80808080808080ff398080ffff01ff02ffff03ffff09ff11ff2480ffff01ff04ff24ffff04ffff0bff20ff2980ff398080ffff010980ff018080ff0180ffff04ffff02ffff03ffff09ff11ff7880ffff0159ff8080ff0180ffff04ffff02ff7affff04ff02ffff04ff0dffff04ff0bffff04ff17ff808080808080ff80808080808080ff0180ffff01ff04ff80ffff04ff80ff17808080ff0180ffffff02ffff03ff05ffff01ff04ff09ffff02ff26ffff04ff02ffff04ff0dffff04ff0bff808080808080ffff010b80ff0180ff0bff22ffff0bff2cff5880ffff0bff22ffff0bff22ffff0bff2cff5c80ff0580ffff0bff22ffff02ff32ffff04ff02ffff04ff07ffff04ffff0bff2cff2c80ff8080808080ffff0bff2cff8080808080ffff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff2effff04ff02ffff04ff09ff80808080ffff02ff2effff04ff02ffff04ff0dff8080808080ffff01ff0bff2cff058080ff0180ffff04ffff04ff28ffff04ff5fff808080ffff02ff7effff04ff02ffff04ffff04ffff04ff2fff0580ffff04ff5fff82017f8080ffff04ffff02ff7affff04ff02ffff04ff0bffff04ff05ffff01ff808080808080ffff04ff17ffff04ff81bfffff04ff82017fffff04ffff0bff8204ffffff02ff36ffff04ff02ffff04ff09ffff04ff820affffff04ffff0bff2cff2d80ffff04ff15ff80808080808080ff8216ff80ffff04ff8205ffffff04ff820bffff808080808080808080808080ff02ff2affff04ff02ffff04ff5fffff04ff3bffff04ffff02ffff03ff17ffff01ff09ff2dffff0bff27ffff02ff36ffff04ff02ffff04ff29ffff04ff57ffff04ffff0bff2cff81b980ffff04ff59ff80808080808080ff81b78080ff8080ff0180ffff04ff17ffff04ff05ffff04ff8202ffffff04ffff04ffff04ff24ffff04ffff0bff7cff2fff82017f80ff808080ffff04ffff04ff30ffff04ffff0bff81bfffff0bff7cff15ffff10ff82017fffff11ff8202dfff2b80ff8202ff808080ff808080ff138080ff80808080808080808080ff018080ffff04ffff01a072dec062874cd4d3aab892a0906688a1ae412b0109982e1797a170add88bdcdcffff04ffff01a0' '$cat1Hex' 'ffff04ffff01ff02ffff01ff02ffff01ff02ffff03ff0bffff01ff02ffff03ffff09ff05ffff1dff0bffff1effff0bff0bffff02ff06ffff04ff02ffff04ff17ff8080808080808080ffff01ff02ff17ff2f80ffff01ff088080ff0180ffff01ff04ffff04ff04ffff04ff05ffff04ffff02ff06ffff04ff02ffff04ff17ff80808080ff80808080ffff02ff17ff2f808080ff0180ffff04ffff01ff32ff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff06ffff04ff02ffff04ff09ff80808080ffff02ff06ffff04ff02ffff04ff0dff8080808080ffff01ff0bffff0101ff058080ff0180ff018080ffff04ffff01b0b51851c33c513e1d4f0b16534b81e91fb6fd3353384887e94ed53c350295bbbbb909ee9ef26b6ff4e82a96bfc7e364b8ff018080ff0180808080", "solution": "ffff80ffff01ffff3cffa07cc11210514345fcccc45f12135335d51c1ca5ba926fe3f4e070916c1dbd9c2180ffff33ffa06b9af21702cb537ddeaa7c16f44e182099aa3c9354e60fed18a0bacbcccaea4fff8200c880ffff33ffa06b9af21702cb537ddeaa7c16f44e182099aa3c9354e60fed18a0bacbcccaea4fff6480ffff33ffa00b7a3d5e723e0b046fd51f95cabf2d3e2616f05d9d1833e8166052b43d9454adff820d168080ff8080ffffa06f756fb68aeb4a89d6844e57c5778877be620b7bc495b43b3b3f3ff633d01814ffa00b7a3d5e723e0b046fd51f95cabf2d3e2616f05d9d1833e8166052b43d9454adff820d1680ffa019cf756cd15ca67fa80e0da8bba572a03b64c74d6ba111e82826b02d7d43c648ffffa0f4151ea2a45da9a31c748f71c866f27d17b91b605aeafa4089c35c685be72f77ffa0778fd03bdb07f0f99046738bc6981dafacbbc0c09fecce04006576f301b74b12ff6480ffffa0f4151ea2a45da9a31c748f71c866f27d17b91b605aeafa4089c35c685be72f77ffa00b7a3d5e723e0b046fd51f95cabf2d3e2616f05d9d1833e8166052b43d9454adff820d1680ff820ddeff8080"}'; - static final cat1ParentCoinSpend = - CoinSpend.fromJson(jsonDecode(cat1ParentCoinSpendJson) as Map); + static final cat1ParentCoinSpend = CoinSpend.fromJson( + jsonDecode(cat1ParentCoinSpendJson) as Map, + ); static final validCat1BaseCoin0 = Coin( confirmedBlockIndex: 17409283, spentBlockIndex: 0, coinbase: false, timestamp: 2748299274, - parentCoinInfo: - Bytes.fromHex('c1fdd54dd268a26fde78bb203a32a14ca942f015a9343d4ea5e9961f997256a1'), - puzzlehash: - Puzzlehash.fromHex('778fd03bdb07f0f99046738bc6981dafacbbc0c09fecce04006576f301b74b12'), + parentCoinInfo: Bytes.fromHex( + 'c1fdd54dd268a26fde78bb203a32a14ca942f015a9343d4ea5e9961f997256a1', + ), + puzzlehash: Puzzlehash.fromHex( + '778fd03bdb07f0f99046738bc6981dafacbbc0c09fecce04006576f301b74b12', + ), amount: 200, ); - static final validCat1Coin0 = - CatCoin.fromParentSpend(parentCoinSpend: cat1ParentCoinSpend, coin: validCat1BaseCoin0); - static final invalidCatCoin0 = - CatCoin.fromParentSpend(parentCoinSpend: cat1ParentCoinSpend, coin: validCat1BaseCoin0); + static final validCat1Coin0 = CatCoin.fromParentSpend( + parentCoinSpend: cat1ParentCoinSpend, + coin: validCat1BaseCoin0, + ); + static final invalidCatCoin0 = CatCoin.fromParentSpend( + parentCoinSpend: cat1ParentCoinSpend, + coin: validCat1BaseCoin0, + ); static final validCat1BaseCoin1 = Coin( confirmedBlockIndex: 17409283, spentBlockIndex: 0, coinbase: false, timestamp: 274829924, - parentCoinInfo: - Bytes.fromHex('c1fdd54dd268a26fde78bb203a32a14ca942f015a9343d4ea5e9961f997256a1'), - puzzlehash: - Puzzlehash.fromHex('5db372b6e7577013035b4ee3fced2a7466d6ff1d3716b182afe520d83ee3427a'), + parentCoinInfo: Bytes.fromHex( + 'c1fdd54dd268a26fde78bb203a32a14ca942f015a9343d4ea5e9961f997256a1', + ), + puzzlehash: Puzzlehash.fromHex( + '5db372b6e7577013035b4ee3fced2a7466d6ff1d3716b182afe520d83ee3427a', + ), amount: 100, ); - static final validCat1Coin1 = - CatCoin.fromParentSpend(coin: validCat1BaseCoin1, parentCoinSpend: cat1ParentCoinSpend); + static final validCat1Coin1 = CatCoin.fromParentSpend( + coin: validCat1BaseCoin1, + parentCoinSpend: cat1ParentCoinSpend, + ); static final cat1Coins = [validCat1Coin0, validCat1Coin1]; static final cat1Message = [TestData.validCat1Coin0] .fold( @@ -120,49 +141,66 @@ class TestData { (Bytes previousValue, coin) => previousValue + coin.id, ) .sha256Hash(); - static final cat1AssertCoinAnnouncementCondition = AssertCoinAnnouncementCondition( + static final cat1AssertCoinAnnouncementCondition = + AssertCoinAnnouncementCondition( TestData.validCat1Coin0.id, cat1Message, morphBytes: Bytes.fromHex('ca'), ); static final cat1NotarizedPayment = NotarizedPayment.fromPayment( - Payment(1000, validCat1Coin0.puzzlehash, memos: const ['test', 'test2', 'test3']), + Payment( + 1000, + validCat1Coin0.puzzlehash, + memos: const ['test', 'test2', 'test3'], + ), Puzzlehash.zeros(), ); // CAT2 Data - static const catHex = '0ed71c399419b16df76ae7cde9fa257f1dbf845bef462b7f9ea6de8d181cdf97'; + static const catHex = + '0ed71c399419b16df76ae7cde9fa257f1dbf845bef462b7f9ea6de8d181cdf97'; static final catAssetId = Puzzlehash.fromHex(catHex); static const catParentCoinSpendJson = '{"coin": {"parent_coin_info": "fe1cecf0d1c5ebce655f8a1c3ff1c532e1a05e60c209e34fbe645d89b9e96bf1", "puzzle_hash": "d9638d7c7e2cebfd7e6c023a5538e7ec7b7259ef85959c873b2c124fd393e67b", "amount": 2200000}, "puzzle_reveal": "ff02ffff01ff02ffff01ff02ff5effff04ff02ffff04ffff04ff05ffff04ffff0bff34ff0580ffff04ff0bff80808080ffff04ffff02ff17ff2f80ffff04ff5fffff04ffff02ff2effff04ff02ffff04ff17ff80808080ffff04ffff02ff2affff04ff02ffff04ff82027fffff04ff82057fffff04ff820b7fff808080808080ffff04ff81bfffff04ff82017fffff04ff8202ffffff04ff8205ffffff04ff820bffff80808080808080808080808080ffff04ffff01ffffffff3d46ff02ff333cffff0401ff01ff81cb02ffffff20ff02ffff03ff05ffff01ff02ff32ffff04ff02ffff04ff0dffff04ffff0bff7cffff0bff34ff2480ffff0bff7cffff0bff7cffff0bff34ff2c80ff0980ffff0bff7cff0bffff0bff34ff8080808080ff8080808080ffff010b80ff0180ffff02ffff03ffff22ffff09ffff0dff0580ff2280ffff09ffff0dff0b80ff2280ffff15ff17ffff0181ff8080ffff01ff0bff05ff0bff1780ffff01ff088080ff0180ffff02ffff03ff0bffff01ff02ffff03ffff09ffff02ff2effff04ff02ffff04ff13ff80808080ff820b9f80ffff01ff02ff56ffff04ff02ffff04ffff02ff13ffff04ff5fffff04ff17ffff04ff2fffff04ff81bfffff04ff82017fffff04ff1bff8080808080808080ffff04ff82017fff8080808080ffff01ff088080ff0180ffff01ff02ffff03ff17ffff01ff02ffff03ffff20ff81bf80ffff0182017fffff01ff088080ff0180ffff01ff088080ff018080ff0180ff04ffff04ff05ff2780ffff04ffff10ff0bff5780ff778080ffffff02ffff03ff05ffff01ff02ffff03ffff09ffff02ffff03ffff09ff11ff5880ffff0159ff8080ff0180ffff01818f80ffff01ff02ff26ffff04ff02ffff04ff0dffff04ff0bffff04ffff04ff81b9ff82017980ff808080808080ffff01ff02ff7affff04ff02ffff04ffff02ffff03ffff09ff11ff5880ffff01ff04ff58ffff04ffff02ff76ffff04ff02ffff04ff13ffff04ff29ffff04ffff0bff34ff5b80ffff04ff2bff80808080808080ff398080ffff01ff02ffff03ffff09ff11ff7880ffff01ff02ffff03ffff20ffff02ffff03ffff09ffff0121ffff0dff298080ffff01ff02ffff03ffff09ffff0cff29ff80ff3480ff5c80ffff01ff0101ff8080ff0180ff8080ff018080ffff0109ffff01ff088080ff0180ffff010980ff018080ff0180ffff04ffff02ffff03ffff09ff11ff5880ffff0159ff8080ff0180ffff04ffff02ff26ffff04ff02ffff04ff0dffff04ff0bffff04ff17ff808080808080ff80808080808080ff0180ffff01ff04ff80ffff04ff80ff17808080ff0180ffff02ffff03ff05ffff01ff04ff09ffff02ff56ffff04ff02ffff04ff0dffff04ff0bff808080808080ffff010b80ff0180ff0bff7cffff0bff34ff2880ffff0bff7cffff0bff7cffff0bff34ff2c80ff0580ffff0bff7cffff02ff32ffff04ff02ffff04ff07ffff04ffff0bff34ff3480ff8080808080ffff0bff34ff8080808080ffff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff2effff04ff02ffff04ff09ff80808080ffff02ff2effff04ff02ffff04ff0dff8080808080ffff01ff0bffff0101ff058080ff0180ffff04ffff04ff30ffff04ff5fff808080ffff02ff7effff04ff02ffff04ffff04ffff04ff2fff0580ffff04ff5fff82017f8080ffff04ffff02ff26ffff04ff02ffff04ff0bffff04ff05ffff01ff808080808080ffff04ff17ffff04ff81bfffff04ff82017fffff04ffff02ff2affff04ff02ffff04ff8204ffffff04ffff02ff76ffff04ff02ffff04ff09ffff04ff820affffff04ffff0bff34ff2d80ffff04ff15ff80808080808080ffff04ff8216ffff808080808080ffff04ff8205ffffff04ff820bffff808080808080808080808080ff02ff5affff04ff02ffff04ff5fffff04ff3bffff04ffff02ffff03ff17ffff01ff09ff2dffff02ff2affff04ff02ffff04ff27ffff04ffff02ff76ffff04ff02ffff04ff29ffff04ff57ffff04ffff0bff34ff81b980ffff04ff59ff80808080808080ffff04ff81b7ff80808080808080ff8080ff0180ffff04ff17ffff04ff05ffff04ff8202ffffff04ffff04ffff04ff78ffff04ffff0eff5cffff02ff2effff04ff02ffff04ffff04ff2fffff04ff82017fff808080ff8080808080ff808080ffff04ffff04ff20ffff04ffff0bff81bfff5cffff02ff2effff04ff02ffff04ffff04ff15ffff04ffff10ff82017fffff11ff8202dfff2b80ff8202ff80ff808080ff8080808080ff808080ff138080ff80808080808080808080ff018080ffff04ffff01a037bef360ee858133b69d595a906dc45d01af50379dad515eb9518abb7c1d2a7affff04ffff01a00ed71c399419b16df76ae7cde9fa257f1dbf845bef462b7f9ea6de8d181cdf97ffff04ffff01ff02ffff01ff02ffff01ff02ffff03ff0bffff01ff02ffff03ffff09ff05ffff1dff0bffff1effff0bff0bffff02ff06ffff04ff02ffff04ff17ff8080808080808080ffff01ff02ff17ff2f80ffff01ff088080ff0180ffff01ff04ffff04ff04ffff04ff05ffff04ffff02ff06ffff04ff02ffff04ff17ff80808080ff80808080ffff02ff17ff2f808080ff0180ffff04ffff01ff32ff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff06ffff04ff02ffff04ff09ff80808080ffff02ff06ffff04ff02ffff04ff0dff8080808080ffff01ff0bffff0101ff058080ff0180ff018080ffff04ffff01b0a347236fae530f3d88d8c8e31c144753934afc87465d690249b625c6211a33ffafa7859fea936b4d558f3c9a0454a869ff018080ff0180808080", "solution": "ffff80ffff01ffff33ffa0bae24162efbd568f89bc7a340798a6118df0189eb9e3f8697bcea27af99f8f79ff831e8480ffffa0bae24162efbd568f89bc7a340798a6118df0189eb9e3f8697bcea27af99f8f798080ffff33ffa0fdeb96380a70839c20471530a1ff87953e5e6b0f8244c162e1b95b9e5a6913ecff83030d4080ffff3cffa05f00170220ea8ae31a680e7a8e185d554a63f21eb63388d43c341250084b65c180ffff3fffa07d0a1bdcf9ffdaedc48e54eb55ec3d7318b6c1bc8029c62f5731b19f2f87fa678080ff8080ffffa022843326cad1524573740facdeb9157c2bed5ea8f2db41f7dae05b3a96e337f0ffa08a0000beb0c8cafa2416e41a2960dd9b0da500f2f0f0e0b3ebc1985dfa0aa6dcff8502357fc2e080ffa09e1043ca4182bd46cbeacdcc77e4ec10d98aca0591642aeffa4eb363d3866a7dffffa0fe1cecf0d1c5ebce655f8a1c3ff1c532e1a05e60c209e34fbe645d89b9e96bf1ffa0d9638d7c7e2cebfd7e6c023a5538e7ec7b7259ef85959c873b2c124fd393e67bff832191c080ffffa0fe1cecf0d1c5ebce655f8a1c3ff1c532e1a05e60c209e34fbe645d89b9e96bf1ffa08df97826f24a789c619fac173229a3f943565957735b0d97e0bd742f7167ac7dff832191c080ff80ff8080"}'; - static final catParentCoinSpend = - CoinSpend.fromJson(jsonDecode(catParentCoinSpendJson) as Map); + static final catParentCoinSpend = CoinSpend.fromJson( + jsonDecode(catParentCoinSpendJson) as Map, + ); static final validCatBaseCoin0 = Coin( confirmedBlockIndex: 17409283, spentBlockIndex: 0, coinbase: false, timestamp: 2748299274, parentCoinInfo: catParentCoinSpend.coin.id, - puzzlehash: - WalletKeychain.makeOuterPuzzleHash(firstWalletSet.unhardened.puzzlehash, catAssetId), + puzzlehash: WalletKeychain.makeOuterPuzzleHash( + firstWalletSet.unhardened.puzzlehash, + catAssetId, + ), amount: 200, ); - static final validCatCoin0 = - CatCoin.fromParentSpend(coin: validCatBaseCoin0, parentCoinSpend: catParentCoinSpend); - static final invalidCat1Coin0 = - CatCoin.fromParentSpend(coin: validCat1BaseCoin0, parentCoinSpend: catParentCoinSpend); + static final validCatCoin0 = CatCoin.fromParentSpend( + coin: validCatBaseCoin0, + parentCoinSpend: catParentCoinSpend, + ); + static final invalidCat1Coin0 = CatCoin.fromParentSpend( + coin: validCat1BaseCoin0, + parentCoinSpend: catParentCoinSpend, + ); static final validCatBaseCoin1 = Coin( confirmedBlockIndex: 17409283, spentBlockIndex: 0, coinbase: false, timestamp: 274829924, parentCoinInfo: catParentCoinSpend.coin.id, - puzzlehash: - WalletKeychain.makeOuterPuzzleHash(firstWalletSet.unhardened.puzzlehash, catAssetId), + puzzlehash: WalletKeychain.makeOuterPuzzleHash( + firstWalletSet.unhardened.puzzlehash, + catAssetId, + ), amount: 100, ); - static final validCatCoin1 = - CatCoin.fromParentSpend(coin: validCatBaseCoin1, parentCoinSpend: catParentCoinSpend); + static final validCatCoin1 = CatCoin.fromParentSpend( + coin: validCatBaseCoin1, + parentCoinSpend: catParentCoinSpend, + ); static final catCoins = [validCatCoin0, validCatCoin1]; static final catMessage = [TestData.validCatCoin0] .fold( @@ -170,12 +208,17 @@ class TestData { (Bytes previousValue, coin) => previousValue + coin.id, ) .sha256Hash(); - static final catAssertCoinAnnouncementCondition = AssertCoinAnnouncementCondition( + static final catAssertCoinAnnouncementCondition = + AssertCoinAnnouncementCondition( TestData.validCatCoin0.id, catMessage, ); static final catNotarizedPayment = NotarizedPayment.fromPayment( - Payment(1000, validCatCoin0.puzzlehash, memos: const ['test', 'test2', 'test3']), + Payment( + 1000, + validCatCoin0.puzzlehash, + memos: const ['test', 'test2', 'test3'], + ), Puzzlehash.zeros(), ); } diff --git a/test/utils_test/uri_validation.dart b/test/utils_test/uri_validation.dart index 9fb72f81..2dea630a 100644 --- a/test/utils_test/uri_validation.dart +++ b/test/utils_test/uri_validation.dart @@ -2,7 +2,9 @@ import 'package:chia_crypto_utils/chia_crypto_utils.dart'; import 'package:test/test.dart'; void main() { - final namesdaoUri = Uri.parse('https://storage1.xchstorage.cyou/namesdao/__nathan-4977960.jpg'); + final namesdaoUri = Uri.parse( + 'https://storage1.xchstorage.cyou/namesdao/__nathan-4977960.jpg', + ); final nftStorageUri = Uri.parse( 'https://bafkreidazmyjo7hkges45moaxx3n3tjpw6se7nzifimpif65r73pmttrk4.ipfs.nftstorage.link/', @@ -10,7 +12,8 @@ void main() { test('should validate uris', () { expect( - [namesdaoUri, nftStorageUri].validate({'pfs.nftstorage.link', 'storage1.xchstorage.cyou'}), + [namesdaoUri, nftStorageUri] + .validate({'pfs.nftstorage.link', 'storage1.xchstorage.cyou'}), true, ); }); diff --git a/test/utils_test/utils_test.dart b/test/utils_test/utils_test.dart index 0f169142..cab29cc6 100644 --- a/test/utils_test/utils_test.dart +++ b/test/utils_test/utils_test.dart @@ -52,11 +52,14 @@ const chiaFirstAddress = Address( void main() async { // get chia wallet sets generated from testMnemonic - var filePath = path.join(path.current, 'test/utils_test/resources/chia_wallet_sets.csv'); + var filePath = + path.join(path.current, 'test/utils_test/resources/chia_wallet_sets.csv'); filePath = path.normalize(filePath); final input = File(filePath).openRead(); - final chiaWalletSetRows = - await input.transform(utf8.decoder).transform(const CsvToListConverter(eol: '\n')).toList(); + final chiaWalletSetRows = await input + .transform(utf8.decoder) + .transform(const CsvToListConverter(eol: '\n')) + .toList(); test('should generate correct puzzle hashes from mnemonic', () { final keychainSecret = KeychainCoreSecret.fromMnemonic(testMnemonic); @@ -64,7 +67,8 @@ void main() async { final fingerprint = keychainSecret.masterPublicKey.getFingerprint(); final masterPublicKeyHex = keychainSecret.masterPublicKey.toHex(); - final farmerPublicKeyHex = masterSkToFarmerSk(masterPrivateKey).getG1().toHex(); + final farmerPublicKeyHex = + masterSkToFarmerSk(masterPrivateKey).getG1().toHex(); final poolPublicKeyHex = masterSkToPoolSk(masterPrivateKey).getG1().toHex(); expect(fingerprint, chiaFingerprint);