public async Task RunTest() { await using var client = _network.NewClient(); // Build a TX from Scratch, Including a Signature var txid = client.CreateNewTxId(); var transfers = new Proto.TransferList(); transfers.AccountAmounts.Add(new Proto.AccountAmount { AccountID = new Proto.AccountID(_network.Payer), Amount = -1 }); transfers.AccountAmounts.Add(new Proto.AccountAmount { AccountID = new Proto.AccountID(_network.Gateway), Amount = 1 }); var body = new Proto.TransactionBody { TransactionID = new Proto.TransactionID(txid), NodeAccountID = new Proto.AccountID(_network.Gateway), TransactionFee = 30_00_000_000, TransactionValidDuration = new Proto.Duration { Seconds = 180 }, Memo = "Unsafe Test", CryptoTransfer = new Proto.CryptoTransferTransactionBody { Transfers = transfers } }; var invoice = new Invoice(body, 6); await(_network.Signatory as ISignatory).SignAsync(invoice); var transaction = new Proto.Transaction { SignedTransactionBytes = invoice.GenerateSignedTransactionFromSignatures().ToByteString() }; using (new ConsoleRedirector(_network.Output)) { var arg0 = _network.Gateway.Url; var arg1 = _network.Gateway.AccountNum.ToString(); var arg2 = _network.Payer.AccountNum.ToString(); var arg3 = Hex.FromBytes(_network.PrivateKey); var arg4 = Hex.FromBytes(transaction.ToByteArray()); await Main(new string[] { arg0, arg1, arg2, arg3, arg4 }); } } }
public async Task SubmitUnsafeTransaction() { await using var client = _network.NewClient(); var systemAddress = await _network.GetSystemAccountAddress(); if (systemAddress is null) { _network.Output?.WriteLine("TEST SKIPPED: No access to System Administrator Account."); return; } // Ok, lets build a TX from Scratch, Including a Signature var txid = client.CreateNewTxId(); var transfers = new Proto.TransferList(); transfers.AccountAmounts.Add(new Proto.AccountAmount { AccountID = new Proto.AccountID(_network.Payer), Amount = -1 }); transfers.AccountAmounts.Add(new Proto.AccountAmount { AccountID = new Proto.AccountID(_network.Gateway), Amount = 1 }); var body = new Proto.TransactionBody { TransactionID = new Proto.TransactionID(txid), NodeAccountID = new Proto.AccountID(_network.Gateway), TransactionFee = 30_00_000_000, TransactionValidDuration = new Proto.Duration { Seconds = 180 }, Memo = "Unsafe Test", CryptoTransfer = new Proto.CryptoTransferTransactionBody { Transfers = transfers } }; var invoice = new Invoice(body, 6); await(_network.Signatory as ISignatory).SignAsync(invoice); var transaction = new Proto.Transaction { SignedTransactionBytes = invoice.GenerateSignedTransactionFromSignatures().ToByteString() }; var receipt = await client.SubmitUnsafeTransactionAsync(transaction.ToByteArray(), ctx => ctx.Payer = systemAddress); Assert.Equal(ResponseCode.Success, receipt.Status); Assert.Equal(txid, receipt.Id); }
private void FillCommonProperties(Hashgraph.TransactionRecord record) { record.Id = TransactionID.ToTxId(); record.Status = (ResponseCode)Receipt.Status; record.Hash = TransactionHash?.ToByteArray(); record.Concensus = ConsensusTimestamp?.ToDateTime(); record.Memo = Memo; record.Fee = TransactionFee; record.Transfers = TransferList.ToTransfers(); record.TokenTransfers = TokenTransferLists.ToTransfers(); if (Receipt.ExchangeRate != null) { record.CurrentExchangeRate = Receipt.ExchangeRate.CurrentRate?.ToExchangeRate(); record.NextExchangeRate = Receipt.ExchangeRate.NextRate?.ToExchangeRate(); } }
internal CryptoTransferTransactionBody(Address fromAddress, Address toAddress, long amount) : this() { if (fromAddress is null) { throw new ArgumentNullException(nameof(toAddress), "Account to transfer from is missing. Please check that it is not null."); } if (toAddress is null) { throw new ArgumentNullException(nameof(toAddress), "Account to transfer to is missing. Please check that it is not null."); } if (amount < 1) { throw new ArgumentOutOfRangeException(nameof(amount), "The amount to transfer must be non-negative."); } var xferList = new TransferList(); xferList.AccountAmounts.Add(new AccountAmount(fromAddress, -amount)); xferList.AccountAmounts.Add(new AccountAmount(toAddress, amount)); Transfers = xferList; }
public async Task SubmitUnsafeTransactionWithRecord() { await using var client = _network.NewClient(); var systemAddress = await _network.GetSystemAccountAddress(); if (systemAddress is null) { _network.Output?.WriteLine("TEST SKIPPED: No access to System Administrator Account."); return; } // Ok, lets build a TX from Scratch, Including a Signature var txid = client.CreateNewTxId(); var transfers = new Proto.TransferList(); transfers.AccountAmounts.Add(new Proto.AccountAmount { AccountID = new Proto.AccountID(_network.Payer), Amount = -1 }); transfers.AccountAmounts.Add(new Proto.AccountAmount { AccountID = new Proto.AccountID(_network.Gateway), Amount = 1 }); var body = new Proto.TransactionBody { TransactionID = new Proto.TransactionID(txid), NodeAccountID = new Proto.AccountID(_network.Gateway), TransactionFee = 30_00_000_000, TransactionValidDuration = new Proto.Duration { Seconds = 180 }, Memo = "Unsafe Test", CryptoTransfer = new Proto.CryptoTransferTransactionBody { Transfers = transfers } }; var invoice = new Invoice(body, 6); await(_network.Signatory as ISignatory).SignAsync(invoice); var transaction = new Proto.Transaction { SignedTransactionBytes = invoice.GenerateSignedTransactionFromSignatures().ToByteString() }; var record = await client.SubmitUnsafeTransactionWithRecordAsync(transaction.ToByteArray(), ctx => ctx.Payer = systemAddress); Assert.Equal(ResponseCode.Success, record.Status); Assert.Equal(txid, record.Id); Assert.False(record.Hash.IsEmpty); Assert.NotNull(record.Concensus); Assert.NotNull(record.CurrentExchangeRate); Assert.NotNull(record.NextExchangeRate); Assert.NotEmpty(record.Hash.ToArray()); Assert.Equal("Unsafe Test", record.Memo); Assert.InRange(record.Fee, 0UL, ulong.MaxValue); Assert.Equal(_network.Payer, record.Id.Address); Assert.Equal(3, record.Transfers.Count); Assert.Equal(-1 - (long)record.Fee, record.Transfers[_network.Payer]); } }
internal CryptoTransferTransactionBody(TransferParams transfers) : this() { if (transfers == null) { throw new ArgumentNullException(nameof(transfers), "The transfer parametes cannot not be null."); } var missingTransfers = true; if (transfers.CryptoTransfers is not null) { long sum = 0; var netRequests = new Dictionary <Hashgraph.Address, long>(); foreach (var transfer in transfers.CryptoTransfers) { if (transfer.Value == 0) { throw new ArgumentOutOfRangeException(nameof(transfers.CryptoTransfers), $"The amount to transfer crypto to/from {transfer.Key.ShardNum}.{transfer.Key.RealmNum}.{transfer.Key.AccountNum} must be a value, negative for transfers out, and positive for transfers in. A value of zero is not allowed."); } if (netRequests.TryGetValue(transfer.Key, out long value)) { netRequests[transfer.Key] = value + transfer.Value; } else { netRequests[transfer.Key] = transfer.Value; } sum += transfer.Value; } if (netRequests.Count == 0) { throw new ArgumentOutOfRangeException(nameof(transfers.CryptoTransfers), "The dictionary of crypto transfers can not be empty."); } if (sum != 0) { throw new ArgumentOutOfRangeException(nameof(transfers.CryptoTransfers), "The sum of crypto sends and receives does not balance."); } var xferList = new TransferList(); foreach (var transfer in netRequests) { if (transfer.Value != 0) { xferList.AccountAmounts.Add(new AccountAmount(transfer.Key, transfer.Value)); } } missingTransfers = xferList.AccountAmounts.Count == 0; Transfers = xferList; } if (transfers.TokenTransfers is not null) { foreach (var tokenGroup in transfers.TokenTransfers.GroupBy(txfer => txfer.Token)) { if (tokenGroup.Key.IsNullOrNone()) { throw new ArgumentException("Token", "The list of token transfers cannot contain a null or empty Token value."); } long sum = 0; var netRequests = new Dictionary <Address, long>(); foreach (var xfer in tokenGroup) { if (xfer.Address.IsNullOrNone()) { throw new ArgumentException(nameof(xfer.Address), "The list of token transfers cannot contain a null or empty account value."); } if (xfer.Amount == 0) { throw new ArgumentOutOfRangeException(nameof(xfer.Amount), $"The amount to transfer tokens to/from {xfer.Address.ShardNum}.{xfer.Address.RealmNum}.{xfer.Address.AccountNum} must be a value, negative for transfers out, and positive for transfers in. A value of zero is not allowed."); } if (netRequests.TryGetValue(xfer.Address, out long value)) { netRequests[xfer.Address] = value + xfer.Amount; } else { netRequests[xfer.Address] = xfer.Amount; } sum += xfer.Amount; } if (sum != 0) { throw new ArgumentOutOfRangeException(nameof(transfers.TokenTransfers), $"The sum of token sends and receives for {tokenGroup.Key.ShardNum}.{tokenGroup.Key.RealmNum}.{tokenGroup.Key.AccountNum} does not balance."); } var xferList = new TokenTransferList { Token = new TokenID(tokenGroup.Key) }; foreach (var netTransfer in netRequests) { if (netTransfer.Value != 0) { xferList.Transfers.Add(new AccountAmount(netTransfer.Key, netTransfer.Value)); } } if (xferList.Transfers.Count > 0) { TokenTransfers.Add(xferList); } } missingTransfers &= TokenTransfers.Count == 0; } if (missingTransfers) { throw new ArgumentException(nameof(transfers), "Both crypto and token transfer lists are null or empty. At least one must include net transfers."); } }