コード例 #1
0
ファイル: Helper.cs プロジェクト: LykkeCity/SolarCoinApi
        public static TransitQueueMessage ToTransitQueueMessage(this TransactionMongoEntity entity)
        {
            var result = new TransitQueueMessage {
                TxId = entity.TxId
            };

            foreach (var vin in entity.Vins)
            {
                result.Vins.Add(new Vin {
                    Address = vin.Addresses, Amount = vin.Amount
                });
            }

            foreach (var vout in entity.Vouts)
            {
                result.Vouts.Add(new Vout {
                    Address = vout.Addresses, Amount = vout.Amount
                });
            }

            return(result);
        }
コード例 #2
0
ファイル: Tests.cs プロジェクト: LykkeCity/SolarCoinApi
        public async Task cashin_handler_test()
        {
            long s = 100000000; // accedpted vout amounts are in satoshis, should conver to solar coins, 1 slr = 10^8 satoshis

            //Arrange

            var hotWalletAddress = Guid.NewGuid().ToString();
            var txFee            = 0.01m;
            var minTxAmount      = 0.1m;


            //Arranging generated wallets storage
            var generatedWallets = new NoSqlTableInMemory <WalletStorageEntity>();

            generatedWallets.Insert(new WalletStorageEntity {
                PartitionKey = "part", RowKey = Guid.NewGuid().ToString(), Address = "8first_generated_address", PrivateKey = "first_priv_key"
            });
            generatedWallets.Insert(new WalletStorageEntity {
                PartitionKey = "part", RowKey = Guid.NewGuid().ToString(), Address = "8second_generated_address", PrivateKey = "second_priv_key"
            });
            generatedWallets.Insert(new WalletStorageEntity {
                PartitionKey = "part", RowKey = Guid.NewGuid().ToString(), Address = "8third_generated_address", PrivateKey = "third_priv_key"
            });
            generatedWallets.Insert(new WalletStorageEntity {
                PartitionKey = "part", RowKey = Guid.NewGuid().ToString(), Address = "8fourth_generated_address", PrivateKey = "fourth_priv_key"
            });

            var fakeTxesQueue = Substitute.For <IQueueExt>();

            var fakeRpcClient = Substitute.For <IJsonRpcClient>();

            fakeRpcClient.CreateRawTransaction(Arg.Any <object[]>(), Arg.Any <Dictionary <string, decimal> >()).Returns("string");
            fakeRpcClient.SignRawTransaction(Arg.Any <string>(), Arg.Any <string>()).Returns(new SignRawTransactionResponseModel());
            fakeRpcClient.SendRawTransaction(Arg.Any <string>()).Returns("string");

            var fakeSlackNotifier = Substitute.For <ISlackNotifier>();

            var fakeLogger = Substitute.For <ILog>();


            var queueTrigger = new CashInHandlerQueueTrigger("SolarCoinApi.Test.CashInHandlerJobRunner", generatedWallets, fakeLogger, fakeTxesQueue, fakeRpcClient, fakeSlackNotifier, hotWalletAddress, txFee, minTxAmount);



            string txId    = Guid.NewGuid().ToString();
            var    message = new TransitQueueMessage
            {
                TxId  = txId,
                Vouts = new List <Vout>
                {
                    new Vout {
                        Address = "8third_generated_address", Amount = (long)(2.3652m * s)
                    },
                    new Vout {
                        Address = "some_unrelated_address_1", Amount = (long)(5m * s)
                    },                                                                       // should be ignored
                    new Vout {
                        Address = "some_unrelated_address_2", Amount = (long)(6.365m * s)
                    },                                                                           // should be ignored
                    new Vout {
                        Address = "8third_generated_address", Amount = (long)(2.146m * s)
                    },
                    new Vout {
                        Address = "some_unrelated_address_3", Amount = (long)(9.213m * s)
                    },                                                                           // should be ignored
                    new Vout {
                        Address = "8first_generated_address", Amount = (long)(0.09m * s)
                    },                                                                          // this shouldn't be put to queue because it's less than min tx amount
                    new Vout {
                        Address = "8fourth_generated_address", Amount = (long)(100.2568m * s)
                    }
                }
            };



            // Act
            await queueTrigger.ReceiveMessage(message);

            // Assert

            // Check if all relevant outputs where put in the queue correctly
            await fakeTxesQueue.Received(1).PutRawMessageAsync(Arg.Is <string>(x => JsonConvert.DeserializeObject <QueueModel>(x).Equals(new QueueModel {
                Address = "8third_generated_address", TxId = txId, Amount = 2.3652m + 2.146m
            })));

            await fakeTxesQueue.Received(1).PutRawMessageAsync(Arg.Is <string>(x => JsonConvert.DeserializeObject <QueueModel>(x).Equals(new QueueModel {
                Address = "8fourth_generated_address", TxId = txId, Amount = 100.2568m
            })));

            await fakeTxesQueue.Received(2).PutRawMessageAsync(Arg.Any <string>());

            // Check if all relevant outputs where transferred to the hot wallet
            await fakeRpcClient.Received(1).CreateRawTransaction(
                Arg.Is <object[]>(
                    x => x.Count() == 1 &&
                    x.All(y => (string)(y.GetType().GetProperty("txid").GetValue(y)) == txId) &&
                    x.Any(y => (int)(y.GetType().GetProperty("vout").GetValue(y)) == 6)),
                Arg.Is <Dictionary <string, decimal> >(x => x.Count == 1 && x[hotWalletAddress] == 100.2568m - txFee));

            await fakeRpcClient.Received(1).CreateRawTransaction(
                Arg.Is <object[]>(x => x.Count() == 2 &&
                                  x.All(y => (string)(y.GetType().GetProperty("txid").GetValue(y)) == txId) &&
                                  x.Any(y => (int)(y.GetType().GetProperty("vout").GetValue(y)) == 0) &&
                                  x.Any(y => (int)(y.GetType().GetProperty("vout").GetValue(y)) == 3)),
                Arg.Is <Dictionary <string, decimal> >(x => x.Count == 1 && x[hotWalletAddress] == 2.3652m + 2.146m - txFee));

            await fakeRpcClient.Received(2).CreateRawTransaction(Arg.Any <object[]>(), Arg.Any <Dictionary <string, decimal> >());

            await fakeRpcClient.Received(1).SignRawTransaction(Arg.Any <string>(), "third_priv_key");

            await fakeRpcClient.Received(1).SignRawTransaction(Arg.Any <string>(), "fourth_priv_key");

            await fakeRpcClient.Received(2).SignRawTransaction(Arg.Any <string>(), Arg.Any <string>());

            await fakeRpcClient.Received(2).SendRawTransaction(Arg.Any <string>());
        }
コード例 #3
0
        public async Task ReceiveMessage(TransitQueueMessage message)
        {
            try
            {
                await _log.WriteInfoAsync(_component, "", message.TxId, "beginning to process");

                var ourVouts = new List <VoutEx>();

                // get outputs that where dedicated to our users
                for (int i = 0; i < message.Vouts.Count; i++)
                {
                    var vout = message.Vouts[i];

                    if (await _generatedWallets.GetDataAsync("part", vout.Address) != null)
                    {
                        ourVouts.Add(new VoutEx {
                            Address = vout.Address, Amount = vout.Amount, voutId = i
                        });
                    }
                }

                // if none of the outputs where dedicated to our users, return;
                if (ourVouts.Count == 0)
                {
                    await _log.WriteInfoAsync(_component, "", message.TxId, "didn't contain relevant addresses");

                    return;
                }


                foreach (var addr in ourVouts.Select(x => x.Address).Distinct())
                {
                    var changePerAddress      = ourVouts.Where(x => x.Address == addr).Sum(x => x.Amount);
                    var changePerAddressInSlr = changePerAddress / 100000000m;

                    if (changePerAddressInSlr < _minTxAmount)
                    {
                        continue;
                    }

                    var dest = new Dictionary <string, decimal> {
                        { _hotWalletAddress, changePerAddressInSlr - _txFee }
                    };

                    var userWallet = _generatedWallets.FirstOrDefault(x => x.Address == addr);

                    var rawTx = await _rpcClient.CreateRawTransaction(ourVouts.Where(x => x.Address == addr).Select(x => new { txid = message.TxId, vout = x.voutId }).ToArray(), dest);

                    var signedTx = await _rpcClient.SignRawTransaction(rawTx, userWallet.PrivateKey);

                    var sentTx = await _rpcClient.SendRawTransaction(signedTx.Hex);

                    await _log.WriteInfoAsync(_component, "", message.TxId, "transferred. posting to queue.");

                    await _txesQueue.PutRawMessageAsync(JsonConvert.SerializeObject(new QueueModel {
                        Address = addr, Amount = changePerAddressInSlr, TxId = message.TxId
                    }));
                }
            }
            catch (Exception e)
            {
                //await _slackNotifier.Notify(new SlackMessage { Sender = _component, Type = "Errors", Message = "Error occured during cashin handling" });
                await _log.WriteErrorAsync(_component, "", message.TxId, e);

                throw;
            }
        }