Esempio n. 1
0
        public async Task <GetUnspentAddressesResponse> GetUnspentAddressesAsync(GetUnspentAddressesRequest request)
        {
            var nodeInfo = await this.Client.GetNodeInfoAsync();

            var state = new InMemoryBip44GeneratorState
            {
                AccountIndex = request.AccountIndex,
                AddressIndex = request.AddressOptions.StartIndex,
                IsInternal   = false
            };

            var unspentAddresses = new List <Bech32Address>();
            var isFirst          = true;
            var zeroCount        = 0;

            var foundAll = false;

            do
            {
                var bip32Path = Bip44AddressGenerator.GenerateAddress(state, isFirst);
                isFirst = false;

                var addressSeed = request.Seed.GenerateSeedFromPath(bip32Path);
                var address     = Ed25519Address.FromPublicKey(addressSeed.KeyPair.PublicKey);

                var addressWithBalance = await this.Client.GetAddressFromEd25519Async(address.Address);

                if (addressWithBalance.Balance == 0)
                {
                    zeroCount++;
                    if (zeroCount >= request.AddressOptions.ZeroCount)
                    {
                        foundAll = true;
                    }
                }
                else
                {
                    unspentAddresses.Add(Bech32Address.FromEd25519Address(addressWithBalance, bip32Path, nodeInfo.Bech32Hrp));

                    if (unspentAddresses.Count == request.AddressOptions.RequiredCount)
                    {
                        foundAll = true;
                    }
                }
            } while (!foundAll);

            return(new GetUnspentAddressesResponse(unspentAddresses));
        }
Esempio n. 2
0
        private async Task <Dictionary <UTXOInput, Ed25519Seed> > CalculateInputsAsync(Ed25519Seed seed, List <TransferOutput> outputs, int zeroCount, int accountIndex, int startIndex)
        {
            var state = new InMemoryBip44GeneratorState
            {
                AccountIndex = accountIndex,
                AddressIndex = startIndex,
                IsInternal   = false
            };

            var inputs           = new Dictionary <UTXOInput, Ed25519Seed>();
            var consumedBalance  = 0L;
            var isFirst          = true;
            var zeroBalanceCount = 0;
            var requiredBalance  = outputs.Sum(o => o.Amount);

            var foundAll = false;

            do
            {
                var bip32Path = Bip44AddressGenerator.GenerateAddress(state, isFirst);
                isFirst = false;

                var addressSeed = seed.GenerateSeedFromPath(bip32Path);
                var address     = Ed25519Address.FromPublicKey(addressSeed.KeyPair.PublicKey);

                var addressOutputs = await this.Client.GetOutputsFromEd25519Async(address.Address);

                if (addressOutputs.Count == 0)
                {
                    zeroBalanceCount++;
                    if (zeroBalanceCount >= zeroCount)
                    {
                        foundAll = true;
                    }
                }
                else
                {
                    foreach (var outputId in addressOutputs.OutputIds)
                    {
                        var addressOutput = await this.Client.FindOutputByIdAsync(outputId);

                        if (!addressOutput.IsSpent &&
                            consumedBalance < requiredBalance)
                        {
                            if (addressOutput.Output.Amount == 0)
                            {
                                zeroBalanceCount++;
                                if (zeroBalanceCount >= zeroCount)
                                {
                                    foundAll = true;
                                }
                            }
                            else
                            {
                                consumedBalance += addressOutput.Output.Amount;

                                inputs.Add(
                                    new UTXOInput
                                {
                                    TransactionId = addressOutput.TransactionId, TransactionOutputIndex = addressOutput.OutputIndex
                                },
                                    addressSeed);

                                if (consumedBalance < requiredBalance)
                                {
                                    continue;
                                }

                                if (consumedBalance - requiredBalance > 0)
                                {
                                    outputs.Add(new TransferOutput(addressOutput.Output.Address, consumedBalance - requiredBalance));
                                }

                                foundAll = true;
                            }
                        }
                    }
                }
            } while (!foundAll);

            return(inputs);
        }