public void TestAddressGenerationFromPublicKey() { var expected = "0bebd6f0febfaf32b4c77eae6755b1d83478dcc9185c33c318d4b0a24ba54d68"; var seed = Ed25519Seed.FromMnemonic("witch collapse practice feed shame open despair creek road again ice least"); var address = Ed25519Address.FromPublicKey(seed.KeyPair.PublicKey); Assert.AreEqual(expected, address.Address); }
public static ReceiptPayload Deserialize(byte[] payload) { var payloadType = BitConverter.ToInt32(payload.Take(4).ToArray(), 0); var pointer = 4; if (payloadType != ReceiptPayloadType) { throw new Exception($"Payload Type ({payloadType}) is not a receipt payload!"); } var migratedAt = BitConverter.ToInt32(payload.Skip(pointer).Take(4).ToArray(), 0); pointer += 4; var final = payload[pointer] == 1; pointer += 1; var fundCount = BitConverter.ToInt16(payload.Skip(pointer).Take(2).ToArray(), 0); pointer += 2; var funds = new List <MigratedFunds>(); for (var i = 0; i < fundCount; i++) { var tailTransactionHash = payload.Skip(pointer).Take(32).ToHex(); pointer += 32; var address = Ed25519Address.Deserialize(payload.Skip(pointer).Take(33).ToArray()); pointer += 33; var deposit = BitConverter.ToInt64(payload.Skip(pointer).Take(8).ToArray(), 0); pointer += 8; funds.Add(new MigratedFunds { Address = address, Deposit = deposit, TailTransactionHash = tailTransactionHash }); } var transactionLength = BitConverter.ToInt32(payload.Skip(pointer).Take(4).ToArray(), 0); pointer += 4; var transaction = Payload.Deserialize <TreasuryTransactionPayload>(payload.Skip(pointer).Take(transactionLength).ToArray()); return(new ReceiptPayload { Final = final, Funds = funds, MigratedAt = migratedAt, Transaction = transaction, Type = payloadType }); }
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)); }
public static Bech32Address FromEd25519Address(Ed25519Address address, Bip32Path path, string humanReadablePart) { var addressBytes = new List <byte>() { (byte)address.Type }; addressBytes.AddRange(address.Address.HexToBytes()); return(new Bech32Address { Balance = address.Balance, Path = path, Address = Crypto.Bech32.Encode(humanReadablePart, addressBytes.ToArray()) }); }
public void TestAddressCreationFromEd25519AddressAndBip31Path() { var expectedAddressBech32Address = "iota1qq97h4hsl6l67v45cal2ue64k8vrg7xueyv9cv7rrr2tpgjt54xks8esknu"; var address = new Ed25519Address { Address = "0bebd6f0febfaf32b4c77eae6755b1d83478dcc9185c33c318d4b0a24ba54d68", Balance = 100, DustAllowed = true }; var path = Bip44AddressGenerator.GenerateAddress(1, 1, false); var actual = Bech32Address.FromEd25519Address(address, path, "iota"); Assert.AreEqual(expectedAddressBech32Address, actual.Address); Assert.AreEqual(path.ToString(), actual.Path.ToString()); Assert.AreEqual(address.Balance, actual.Balance); }
public SendTransferRequest(Ed25519Seed seed, Ed25519Address receiver, long amount) : this(seed, new TransferOutput(receiver, amount)) { }
public TransferOutput(Ed25519Address receiver, long amount) { Receiver = receiver; Amount = amount; }
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); }