Beispiel #1
0
        private static void ScanTransactions()
        {
            string lastIncomingTxHash = null;

            var transactionsOut = GetAllPaidTransactions();

            while (true)
            {
                try
                {
                    // get upto 25 last incoming deposit transactions up to the hash supplied.
                    var incomingTransactions = DepositAccount.GetIncomingTransactionsAsync(lastIncomingTxHash).Result;

                    // if no transactions, break.
                    if (incomingTransactions?.data?.Count == 0 || incomingTransactions?.data == null)
                    {
                        break;
                    }

                    // scan all incoming transactions to see if they need to be paid out assets
                    foreach (var t in incomingTransactions.data)
                    {
                        // set last hash to the hash of the last transaction in the previous list. (null on the first go round)
                        // you can only retrieve 25 txs at a time. providing the hash of the last transaction
                        // in the previous list will give the next 25 transactions that happened prior to the hash provided
                        lastIncomingTxHash = t.meta.hash.data;

                        // assume unpaid
                        var paid = false;

                        // loop all outgoing and unconfirmed outgoing transactions
                        foreach (var confTx in transactionsOut)
                        {
                            // if message is not null, could contain a payout hash
                            if (confTx?.transaction?.message?.payload == null)
                            {
                                continue;
                            }

                            // if the hash in the outgoing message matches the hash of the deposit transaction being checked,
                            // its been paid, so print out, declare paid and stop looping through outgoing txs
                            if (Encoding.UTF8.GetString(CryptoBytes.FromHexString(confTx.transaction.message.payload))
                                != (t.transaction.type == 4100 ? t.meta.innerHash.data : t.meta.hash.data))
                            {
                                continue;
                            }

                            // print out paid hash
                            Console.WriteLine("hash of paid tx:");
                            Console.WriteLine(Encoding.UTF8.GetString(CryptoBytes.FromHexString(confTx.transaction.message.payload)));
                            Console.WriteLine();

                            paid = true;
                            break;
                        }

                        // if paid, continue to check the next incoming transaction
                        if (paid)
                        {
                            continue;
                        }


                        // if the transaction isnt a transfer transaction, skip it.
                        // othertrans is support for multisig transfers.
                        if (t.transaction.type != 257 && t.transaction?.otherTrans?.type != 257)
                        {
                            continue;
                        }


                        // if deposit account does an accidental payment to itself it will pay itself out, so ignore any transactions to self on the off chance it happens.
                        //    manually convert tx signer to address in case public key of deposit address is not yet known.
                        if (new Address(Con.GetNetworkVersion().ToEncoded(new PublicKey(t.transaction.type == 4100
                                ? t.transaction.otherTrans?.signer : t.transaction?.signer))).Encoded == DepositAccount.Address.Encoded)
                        {
                            continue;
                        }

                        // create the recipient
                        var recipient = Con.GetNetworkVersion().ToEncoded(
                            new PublicKey(t.transaction.type == 4100
                                ? t.transaction.otherTrans?.signer
                                : t.transaction?.signer));


                        // declare
                        double wholeAssetQuantity = 0.0;

                        // get cost of asset
                        var xemPerMosaic = double.Parse(ConfigurationManager.AppSettings["xemPerMosaic"]);

                        // calculate quantity of asset to return.
                        wholeAssetQuantity += (t.transaction.type == 4100
                                                    ? t.transaction.otherTrans.amount
                                                    : t.transaction.amount)
                                              / xemPerMosaic;

                        // if transaction contains a mosaic of type xem, calculate whole assets to be paid out and include.
                        // xem can be sent both as version one and two type transactions ie. attached as a mosaic. in some cases people may send xem as a mosaic
                        // of type xem so catch it if they do.
                        if ((t.transaction.type == 4100 ? t.transaction.otherTrans.mosaics : t.transaction.mosaics) != null &&
                            (t.transaction.type == 4100 ? t.transaction.otherTrans.mosaics : t.transaction.mosaics).Exists(
                                e => e.mosaicId.namespaceId == "nem" && e.mosaicId.name == "xem"))
                        {
                            var mosaic = (t.transaction.type == 4100 ? t.transaction.otherTrans.mosaics : t.transaction.mosaics)
                                         .Single(e => e.mosaicId.namespaceId == "nem" && e.mosaicId.name == "xem");

                            wholeAssetQuantity += mosaic.quantity / xemPerMosaic;
                        }

                        // account for asset divisibility.
                        var assetUnits = (long)(wholeAssetQuantity * Math.Pow(10, long.Parse(MosaicToReturn.Properties[0].Value)));

                        // print out incoming hash
                        Console.WriteLine("incoming hash to pay: \n" + (t.transaction.type == 4100 ? t.meta.innerHash.data : t.meta.hash.data));

                        // payout asset
                        ReturnAsset(recipient, RoundUp(assetUnits, 6 - int.Parse(MosaicToReturn.Properties[0].Value)), t.transaction.type == 4100 ? t.meta.innerHash.data : t.meta.hash.data);

                        // could flood the network with transactions, so limit to 1 transactions per min,
                        // also helps disperse transaction fees among harvesters.
                        Thread.Sleep(10000);
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                }
            }

            Console.WriteLine("all transactions checked and paid");
        }