public async Task CanEmbedMessagesInTheSignatureItself() { var(_, privateKey) = Generator.Ed25519KeyPair(); var randomBytes = Generator.SHA384Hash(); await using var fx = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.InitialBalance = 0); await AssertHg.CryptoBalanceAsync(fx, 0); var transferAmount = Generator.Integer(10, 100); var receipt = await fx.Client.TransferAsync(_network.Payer, fx.Record.Address, transferAmount, ctx => { ctx.Signatory = new Signatory(_network.PrivateKey, new Signatory(CustomSigner)); }); Assert.Equal(ResponseCode.Success, receipt.Status); await AssertHg.CryptoBalanceAsync(fx, transferAmount); Task CustomSigner(IInvoice invoice) { var message = Encoding.ASCII.GetBytes("This is an Embedded Message"); var signingKey = TestKeys.ImportPrivateEd25519KeyFromBytes(privateKey); invoice.AddSignature(KeyType.Ed25519, message, message); return(Task.CompletedTask); } }
public async Task ReceiptForScheduledExecutionCanBeObtainedImmediately() { var initialBalance = (ulong)Generator.Integer(100, 1000); var transferAmount = initialBalance / 2; await using var fxSender = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.InitialBalance = initialBalance); await using var fxReceiver = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.InitialBalance = initialBalance); await using var fxPayer = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.InitialBalance = 20_00_000_000); var pendingSignatory = new Signatory(fxSender.PrivateKey, new PendingParams { PendingPayer = fxPayer }); var schedulingReceipt = await fxSender.Client.TransferAsync(fxSender, fxReceiver, (long)transferAmount, pendingSignatory); var signingReceipt = await fxPayer.Client.SignPendingTransactionAsync(schedulingReceipt.Pending.Id, fxPayer); var executedReceipt = await fxPayer.Client.GetReceiptAsync(schedulingReceipt.Pending.TxId); Assert.Equal(ResponseCode.Success, executedReceipt.Status); Assert.Equal(schedulingReceipt.Pending.TxId, executedReceipt.Id); Assert.NotNull(executedReceipt.CurrentExchangeRate); Assert.NotNull(executedReceipt.NextExchangeRate); Assert.Null(executedReceipt.Pending); await AssertHg.CryptoBalanceAsync(fxSender, initialBalance - transferAmount); await AssertHg.CryptoBalanceAsync(fxReceiver, initialBalance + transferAmount); Assert.True(await fxPayer.Client.GetAccountBalanceAsync(fxPayer) < fxPayer.CreateParams.InitialBalance); }
public async Task UnrelatedPublicKeysCanSignUnrelatedMessage() { var(_, privateKey) = Generator.Ed25519KeyPair(); await using var fx = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.InitialBalance = 0); await AssertHg.CryptoBalanceAsync(fx, 0); var transferAmount = Generator.Integer(10, 100); var receipt = await fx.Client.TransferAsync(_network.Payer, fx.Record.Address, transferAmount, ctx => { ctx.Signatory = new Signatory(_network.PrivateKey, new Signatory(CustomSigner)); }); Assert.Equal(ResponseCode.Success, receipt.Status); await AssertHg.CryptoBalanceAsync(fx, transferAmount); Task CustomSigner(IInvoice invoice) { var randomBytes = Generator.SHA384Hash(); var signingKey = TestKeys.ImportPrivateEd25519KeyFromBytes(privateKey); var prefix = signingKey.PublicKey.Export(KeyBlobFormat.PkixPublicKey).TakeLast(32).Take(6).ToArray(); var signature = SignatureAlgorithm.Ed25519.Sign(signingKey, randomBytes.Span); invoice.AddSignature(KeyType.Ed25519, prefix, signature); return(Task.CompletedTask); } }
public async Task CanSignTransactionWithExtraSignature() { var(_, privateKey) = Generator.KeyPair(); await using var fx = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.InitialBalance = 0); await AssertHg.CryptoBalanceAsync(fx, 0); var transferAmount = Generator.Integer(10, 100); var receipt = await fx.Client.TransferAsync(_network.Payer, fx.Record.Address, transferAmount, ctx => { ctx.Signatory = new Signatory(_network.PrivateKey, privateKey); }); Assert.Equal(ResponseCode.Success, receipt.Status); await AssertHg.CryptoBalanceAsync(fx, transferAmount); }
async Task TransferringAssetAppliesSingleFixedHbarCommision() { await using var fxBuyer = await TestAccount.CreateAsync(_network, ctx => ctx.CreateParams.InitialBalance = 10_00_000_000); await using var fxSeller = await TestAccount.CreateAsync(_network, ctx => ctx.CreateParams.InitialBalance = 0); await using var fxBenefactor = await TestAccount.CreateAsync(_network, ctx => ctx.CreateParams.InitialBalance = 0); await using var fxAsset = await TestAsset.CreateAsync(_network, fx => { fx.Params.Royalties = new FixedRoyalty[] { new FixedRoyalty(fxBenefactor, Address.None, 1_00_000_000) }; fx.Params.GrantKycEndorsement = null; }, fxBuyer, fxSeller); Assert.Equal(ResponseCode.Success, fxAsset.Record.Status); var movedAsset = new Asset(fxAsset, 1); await fxAsset.Client.TransferAssetAsync(movedAsset, fxAsset.TreasuryAccount, fxSeller, fxAsset.TreasuryAccount); await AssertHg.AssetBalanceAsync(fxAsset, fxBuyer, 0); await AssertHg.AssetBalanceAsync(fxAsset, fxSeller, 1); await AssertHg.AssetBalanceAsync(fxAsset, fxBenefactor, 0); await AssertHg.AssetBalanceAsync(fxAsset, fxAsset.TreasuryAccount, fxAsset.Metadata.Length - 1); await AssertHg.CryptoBalanceAsync(fxBuyer, 10_00_000_000); await AssertHg.CryptoBalanceAsync(fxSeller, 0); await AssertHg.CryptoBalanceAsync(fxBenefactor, 0); var record = await fxAsset.Client.TransferWithRecordAsync(new TransferParams { AssetTransfers = new[] { new AssetTransfer(movedAsset, fxSeller, fxBuyer) }, CryptoTransfers = new Dictionary <AddressOrAlias, long> { { fxBuyer.Record.Address, -5_00_000_000 },
public async Task ScheduledReceiptDoesNotExistUntilCompletelySigned() { var initialBalance = (ulong)Generator.Integer(100, 1000); var transferAmount = initialBalance / 2; await using var fxSender = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.InitialBalance = initialBalance); await using var fxReceiver = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.InitialBalance = initialBalance); await using var fxPayer = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.InitialBalance = 20_00_000_000); var pendingSignatory = new Signatory(fxSender.PrivateKey, new PendingParams { PendingPayer = fxPayer }); var record = await fxSender.Client.TransferWithRecordAsync(fxSender, fxReceiver, (long)transferAmount, pendingSignatory); var info = await fxPayer.Client.GetPendingTransactionInfoAsync(record.Pending.Id); Assert.Equal(record.Pending.Id, info.Id); Assert.Equal(record.Pending.TxId, info.TxId); Assert.Equal(_network.Payer, info.Creator); Assert.Equal(fxPayer.Record.Address, info.Payer); Assert.Single(info.Endorsements); Assert.Equal(new Endorsement(fxSender.PublicKey), info.Endorsements[0]); Assert.Null(info.Administrator); Assert.Empty(info.Memo); Assert.True(info.Expiration > DateTime.MinValue); Assert.Null(info.Executed); Assert.Null(info.Deleted); Assert.False(info.PendingTransactionBody.IsEmpty); AssertHg.NotEmpty(info.Ledger); await AssertHg.CryptoBalanceAsync(fxSender, initialBalance); await AssertHg.CryptoBalanceAsync(fxReceiver, initialBalance); var tex = await Assert.ThrowsAsync <TransactionException>(async() => { await fxPayer.Client.GetReceiptAsync(record.Pending.TxId); }); Assert.Equal(ResponseCode.ReceiptNotFound, tex.Status); Assert.StartsWith("Network failed to return a transaction receipt, Status Code Returned: ReceiptNotFound", tex.Message); var executedReceipts = await fxPayer.Client.GetAllReceiptsAsync(record.Pending.TxId); Assert.Empty(executedReceipts); var signingReceipt = await fxPayer.Client.SignPendingTransactionAsync(record.Pending.Id, fxPayer); Assert.Equal(ResponseCode.Success, signingReceipt.Status); // Since it was not created by this TX, it won't be included Assert.Equal(Address.None, signingReceipt.Pending.Id); // But, the executed TX ID will still be returned. Assert.Equal(record.Pending.TxId, signingReceipt.Pending.TxId); var executedReceipt = await fxPayer.Client.GetReceiptAsync(record.Pending.TxId); Assert.Equal(ResponseCode.Success, executedReceipt.Status); Assert.Equal(record.Pending.TxId, executedReceipt.Id); Assert.NotNull(executedReceipt.CurrentExchangeRate); Assert.NotNull(executedReceipt.NextExchangeRate); Assert.Null(executedReceipt.Pending); await AssertHg.CryptoBalanceAsync(fxSender, initialBalance - transferAmount); await AssertHg.CryptoBalanceAsync(fxReceiver, initialBalance + transferAmount); Assert.True(await fxPayer.Client.GetAccountBalanceAsync(fxPayer) < fxPayer.CreateParams.InitialBalance); var executedRecord = await fxPayer.Client.GetTransactionRecordAsync(record.Pending.TxId); Assert.Equal(ResponseCode.Success, executedRecord.Status); Assert.Equal(record.Pending.TxId, executedRecord.Id); Assert.InRange(executedRecord.Fee, 0UL, ulong.MaxValue); Assert.Equal(executedRecord.Transfers[fxSender], -(long)transferAmount); Assert.Equal(executedRecord.Transfers[fxReceiver], (long)transferAmount); Assert.True(executedRecord.Transfers[fxPayer] < 0); Assert.Empty(executedRecord.TokenTransfers); Assert.False(executedRecord.Hash.IsEmpty); Assert.NotNull(executedRecord.Concensus); Assert.NotNull(executedRecord.CurrentExchangeRate); Assert.NotNull(executedRecord.NextExchangeRate); Assert.Empty(executedRecord.Memo); Assert.Null(executedRecord.Pending); }
public async Task CanScheduleATransferThatShouldImmediatelyExecute() { var initialBalance = (ulong)Generator.Integer(100, 1000); var transferAmount = initialBalance / 2; await using var fxSender = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.InitialBalance = initialBalance); await using var fxReceiver = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.InitialBalance = initialBalance); await using var fxPayer = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.InitialBalance = 20_00_000_000); var pendingSignatory = new Signatory(fxPayer.PrivateKey, fxSender.PrivateKey, new PendingParams { PendingPayer = fxPayer }); var record = await fxSender.Client.TransferWithRecordAsync(fxSender, fxReceiver, (long)transferAmount, pendingSignatory); var info = await fxPayer.Client.GetPendingTransactionInfoAsync(record.Pending.Id); Assert.Equal(record.Pending.Id, info.Id); Assert.Equal(record.Pending.TxId, info.TxId); Assert.Equal(_network.Payer, info.Creator); Assert.Equal(fxPayer.Record.Address, info.Payer); Assert.Equal(2, info.Endorsements.Length); Assert.Equal(new Endorsement(fxPayer.PublicKey), info.Endorsements[0]); Assert.Null(info.Administrator); Assert.Empty(info.Memo); Assert.True(info.Expiration > DateTime.MinValue); Assert.True(record.Concensus <= info.Executed); Assert.Null(info.Deleted); Assert.False(info.PendingTransactionBody.IsEmpty); AssertHg.NotEmpty(info.Ledger); await AssertHg.CryptoBalanceAsync(fxSender, initialBalance - transferAmount); await AssertHg.CryptoBalanceAsync(fxReceiver, initialBalance + transferAmount); Assert.True(await fxPayer.Client.GetAccountBalanceAsync(fxPayer) < fxPayer.CreateParams.InitialBalance); var executedReceipt = await fxPayer.Client.GetReceiptAsync(record.Pending.TxId); Assert.Equal(ResponseCode.Success, executedReceipt.Status); Assert.Equal(record.Pending.TxId, executedReceipt.Id); Assert.NotNull(executedReceipt.CurrentExchangeRate); Assert.NotNull(executedReceipt.NextExchangeRate); Assert.Null(executedReceipt.Pending); var executedRecord = await fxPayer.Client.GetTransactionRecordAsync(record.Pending.TxId); Assert.Equal(ResponseCode.Success, executedRecord.Status); Assert.Equal(record.Pending.TxId, executedRecord.Id); Assert.InRange(executedRecord.Fee, 0UL, ulong.MaxValue); Assert.Equal(executedRecord.Transfers[fxSender], -(long)transferAmount); Assert.Equal(executedRecord.Transfers[fxReceiver], (long)transferAmount); Assert.True(executedRecord.Transfers[fxPayer] < 0); Assert.Empty(executedRecord.TokenTransfers); Assert.False(executedRecord.Hash.IsEmpty); Assert.NotNull(executedRecord.Concensus); Assert.NotNull(executedRecord.CurrentExchangeRate); Assert.NotNull(executedRecord.NextExchangeRate); Assert.Empty(executedRecord.Memo); Assert.Null(executedRecord.Pending); }