public Task <CreateTransactionResponse> GetDestroyTransaction(BitcoinAddress bitcoinAddres, decimal modelAmount, IAsset asset, Guid transactionId) { return(Retry.Try(async() => { var context = new TransactionBuildContext(_connectionParams.Network, _pregeneratedOutputsQueueFactory); return await context.Build(async() => { var builder = new TransactionBuilder(); var assetId = new BitcoinAssetId(asset.BlockChainAssetId, _connectionParams.Network).AssetId; var coins = (await _bitcoinOutputsService.GetColoredUnspentOutputs(bitcoinAddres.ToString(), assetId)).ToList(); builder.SetChange(bitcoinAddres, ChangeType.Colored); builder.AddCoins(coins); var assetMoney = new AssetMoney(assetId, modelAmount, asset.MultiplierPower); var changeAddress = BitcoinAddress.Create(_baseSettings.ChangeAddress, _connectionParams.Network); _transactionBuildHelper.SendAssetWithChange(builder, context, coins, changeAddress, assetMoney, bitcoinAddres); await _transactionBuildHelper.AddFee(builder, context); var tx = builder.BuildTransaction(true); uint markerPosition; var colorMarker = ColorMarker.Get(tx, out markerPosition); for (var i = 0; i < colorMarker.Quantities.Length; i++) { if ((long)colorMarker.Quantities[i] == assetMoney.Quantity && tx.Outputs[i + 1].ScriptPubKey.GetDestinationAddress(_connectionParams.Network) == changeAddress) { colorMarker.Quantities[i] = 0; break; } } tx.Outputs[markerPosition].ScriptPubKey = colorMarker.GetScript(); await SaveSpentOutputs(transactionId, tx); await _signRequestRepository.InsertTransactionId(transactionId); await SaveNewOutputs(transactionId, tx, context); return new CreateTransactionResponse(tx.ToHex(), transactionId); }); }, exception => (exception as BackendException)?.Code == ErrorCode.TransactionConcurrentInputsProblem, 3, _log)); }
private Task GenerateColorOutputs(string assetId) { return(Retry.Try(async() => { var asset = await _assetRepostory.GetItemAsync(assetId); var setting = await GetAssetSetting(assetId); var hotWallet = OpenAssetsHelper.ParseAddress(setting.HotWallet); var assetIdObj = new BitcoinAssetId(asset.BlockChainAssetId).AssetId; var outputs = await _bitcoinOutputsService.GetColoredUnspentOutputs(setting.HotWallet, assetIdObj, 0, false); var balance = outputs.Aggregate(new AssetMoney(assetIdObj, 0), (accum, coin) => accum + coin.Amount); var outputSize = new AssetMoney(assetIdObj, setting.OutputSize, asset.MultiplierPower); var changeBalance = new AssetMoney(assetIdObj); if (setting.ChangeWallet != setting.HotWallet && !string.IsNullOrEmpty(setting.ChangeWallet)) { var changeOutputs = await _bitcoinOutputsService.GetColoredUnspentOutputs(setting.ChangeWallet, assetIdObj, 0, false); changeBalance = changeOutputs.Aggregate(new AssetMoney(assetIdObj, 0), (accum, coin) => accum + coin.Amount); } if ((balance + changeBalance).ToDecimal(asset.MultiplierPower) < setting.MinBalance) { await SendBalanceNotifications(assetId, setting.HotWallet, setting.MinBalance); } var existingCoinsCount = outputs.Count(o => o.Amount <= outputSize && o.Amount.Quantity > outputSize.Quantity / 2); if (existingCoinsCount > setting.MinOutputsCount) { return; } var generateCnt = setting.MaxOutputsCount - existingCoinsCount; var coins = outputs.Where(o => o.Amount > outputSize * 2).ToList(); balance = coins.Aggregate(new AssetMoney(assetIdObj, 0), (accum, coin) => accum + coin.Amount); generateCnt = Math.Min(generateCnt, (int)(balance.Quantity / outputSize.Quantity)); if (generateCnt == 0) { return; } await GenerateOutputs(generateCnt, coins, hotWallet, outputSize, asset, setting); }, exception => (exception as BackendException)?.Code == ErrorCode.TransactionConcurrentInputsProblem, 3, _logger)); }
public Task <CreateTransactionResponse> GetDestroyTransaction(BitcoinAddress bitcoinAddres, decimal modelAmount, IAsset asset, Guid transactionId) { return(Retry.Try(async() => { var context = _transactionBuildContextFactory.Create(_connectionParams.Network); return await context.Build(async() => { var builder = new TransactionBuilder(); var assetId = new BitcoinAssetId(asset.BlockChainAssetId, _connectionParams.Network).AssetId; var coins = (await _bitcoinOutputsService.GetColoredUnspentOutputs(bitcoinAddres.ToString(), assetId)).ToList(); builder.SetChange(bitcoinAddres, ChangeType.Colored); builder.AddCoins(coins); var assetMoney = new AssetMoney(assetId, modelAmount, asset.MultiplierPower); var changeAddress = BitcoinAddress.Create(_baseSettings.ChangeAddress, _connectionParams.Network); _transactionBuildHelper.SendAssetWithChange(builder, context, coins, changeAddress, assetMoney, bitcoinAddres); await _transactionBuildHelper.AddFee(builder, context); var tx = builder.BuildTransaction(true); OpenAssetsHelper.DestroyColorCoin(tx, assetMoney, changeAddress, _connectionParams.Network); await _spentOutputService.SaveSpentOutputs(transactionId, tx); await SaveNewOutputs(transactionId, tx, context); return new CreateTransactionResponse(tx.ToHex(), transactionId); }); }, exception => (exception as BackendException)?.Code == ErrorCode.TransactionConcurrentInputsProblem, 3, _log)); }