public async Task CanResumeASuspendedAccount() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxAsset = await TestAsset.CreateAsync(_network, fx => { fx.Params.GrantKycEndorsement = null; fx.Params.InitializeSuspended = false; }, fxAccount); var circulation = fxAsset.Metadata.Length; var xferAmount = circulation / 3; await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenTradableStatus.Tradable); await fxAsset.Client.SuspendTokenAsync(fxAsset.Record.Token, fxAccount, fxAsset.SuspendPrivateKey); await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenTradableStatus.Suspended); await fxAsset.Client.ResumeTokenAsync(fxAsset.Record.Token, fxAccount, fxAsset.SuspendPrivateKey); await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenTradableStatus.Tradable); await fxAsset.Client.TransferAssetAsync(new Asset(fxAsset, 1), fxAsset.TreasuryAccount, fxAccount, fxAsset.TreasuryAccount); await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenTradableStatus.Tradable); }
public async Task CanReumeTokenCoinTradingAndGetRecord() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxToken = await TestToken.CreateAsync(_network, fx => { fx.Params.GrantKycEndorsement = null; fx.Params.InitializeSuspended = true; }, fxAccount); var circulation = fxToken.Params.Circulation; var xferAmount = circulation / 3; await AssertHg.TokenStatusAsync(fxToken, fxAccount, TokenTradableStatus.Suspended); var record = await fxToken.Client.ResumeTokenWithRecordAsync(fxToken.Record.Token, fxAccount, fxToken.SuspendPrivateKey); Assert.Equal(ResponseCode.Success, record.Status); Assert.False(record.Hash.IsEmpty); Assert.NotNull(record.Concensus); Assert.NotNull(record.CurrentExchangeRate); Assert.NotNull(record.NextExchangeRate); Assert.NotEmpty(record.Hash.ToArray()); Assert.Empty(record.Memo); Assert.InRange(record.Fee, 0UL, ulong.MaxValue); Assert.Equal(_network.Payer, record.Id.Address); await AssertHg.TokenStatusAsync(fxToken, fxAccount, TokenTradableStatus.Tradable); await fxToken.Client.TransferTokensAsync(fxToken, fxToken.TreasuryAccount, fxAccount, (long)xferAmount, fxToken.TreasuryAccount); await AssertHg.TokenStatusAsync(fxToken, fxAccount, TokenTradableStatus.Tradable); }
public async Task CanAssociateMultipleTokensWithAccount() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxToken1 = await TestToken.CreateAsync(_network); await using var fxToken2 = await TestToken.CreateAsync(_network); var tokens = new Address[] { fxToken1.Record.Token, fxToken2.Record.Token }; await AssertHg.TokenNotAssociatedAsync(fxToken1, fxAccount); await AssertHg.TokenNotAssociatedAsync(fxToken2, fxAccount); var receipt = await fxAccount.Client.AssociateTokensAsync(tokens, fxAccount.Record.Address, fxAccount.PrivateKey); Assert.Equal(ResponseCode.Success, receipt.Status); var association = await AssertHg.TokenIsAssociatedAsync(fxToken1, fxAccount); Assert.Equal(fxToken1.Record.Token, association.Token); Assert.Equal(fxToken1.Params.Symbol, association.Symbol); Assert.Equal(0UL, association.Balance); Assert.Equal(TokenKycStatus.Revoked, association.KycStatus); Assert.Equal(TokenTradableStatus.Tradable, association.TradableStatus); association = await AssertHg.TokenIsAssociatedAsync(fxToken2, fxAccount); Assert.Equal(fxToken2.Record.Token, association.Token); Assert.Equal(fxToken2.Params.Symbol, association.Symbol); Assert.Equal(0UL, association.Balance); Assert.Equal(TokenKycStatus.Revoked, association.KycStatus); Assert.Equal(TokenTradableStatus.Tradable, association.TradableStatus); }
public async Task CanResumeASuspendedAccount() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxToken = await TestToken.CreateAsync(_network, fx => { fx.Params.GrantKycEndorsement = null; fx.Params.InitializeSuspended = false; }, fxAccount); var circulation = fxToken.Params.Circulation; var xferAmount = circulation / 3; await AssertHg.TokenStatusAsync(fxToken, fxAccount, TokenTradableStatus.Tradable); await fxToken.Client.SuspendTokenAsync(fxToken.Record.Token, fxAccount, fxToken.SuspendPrivateKey); await AssertHg.TokenStatusAsync(fxToken, fxAccount, TokenTradableStatus.Suspended); await fxToken.Client.ResumeTokenAsync(fxToken.Record.Token, fxAccount, fxToken.SuspendPrivateKey); await AssertHg.TokenStatusAsync(fxToken, fxAccount, TokenTradableStatus.Tradable); await fxToken.Client.TransferTokensAsync(fxToken, fxToken.TreasuryAccount, fxAccount, (long)xferAmount, fxToken.TreasuryAccount); await AssertHg.TokenStatusAsync(fxToken, fxAccount, TokenTradableStatus.Tradable); }
public async Task CanNotScheduleReumeTokenCoinTrading() { await using var fxPayer = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.InitialBalance = 20_00_000_000); await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxToken = await TestToken.CreateAsync(_network, fx => { fx.Params.GrantKycEndorsement = null; fx.Params.InitializeSuspended = true; }, fxAccount); await AssertHg.TokenStatusAsync(fxToken, fxAccount, TokenTradableStatus.Suspended); var tex = await Assert.ThrowsAsync <TransactionException>(async() => { await fxToken.Client.ResumeTokenAsync( fxToken.Record.Token, fxAccount, new Signatory( fxToken.SuspendPrivateKey, new PendingParams { PendingPayer = fxPayer })); }); Assert.Equal(ResponseCode.ScheduledTransactionNotInWhitelist, tex.Status); Assert.StartsWith("Unable to schedule transaction, status: ScheduledTransactionNotInWhitelist", tex.Message); }
public async Task RevokeTokenCoinsRequiresGrantKeySignature() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxAsset = await TestAsset.CreateAsync(_network, null, fxAccount); var circulation = (ulong)fxAsset.Metadata.Length; await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenKycStatus.Revoked); await fxAsset.Client.GrantTokenKycAsync(fxAsset, fxAccount, fxAsset.GrantPrivateKey); await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenKycStatus.Granted); await fxAsset.Client.TransferAssetAsync(new Asset(fxAsset, 1), fxAsset.TreasuryAccount, fxAccount, fxAsset.TreasuryAccount); var tex = await Assert.ThrowsAsync <TransactionException>(async() => { await fxAsset.Client.RevokeTokenKycAsync(fxAsset.Record.Token, fxAccount); }); Assert.Equal(ResponseCode.InvalidSignature, tex.Status); Assert.Equal(ResponseCode.InvalidSignature, tex.Receipt.Status); Assert.StartsWith("Unable to Revoke Token, status: InvalidSignature", tex.Message); await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenKycStatus.Granted); }
public async Task CanReumeTokenCoinTradingFromAnyAccountWithSuspendKey() { await using var fxOther = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.InitialBalance = 100_00_000_000); await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxToken = await TestToken.CreateAsync(_network, fx => { fx.Params.GrantKycEndorsement = null; fx.Params.InitializeSuspended = true; }, fxAccount); var circulation = fxToken.Params.Circulation; var xferAmount = circulation / 3; await AssertHg.TokenStatusAsync(fxToken, fxAccount, TokenTradableStatus.Suspended); await fxToken.Client.ResumeTokenAsync(fxToken.Record.Token, fxAccount, fxToken.SuspendPrivateKey, ctx => { ctx.Payer = fxOther.Record.Address; ctx.Signatory = fxOther.PrivateKey; }); await AssertHg.TokenStatusAsync(fxToken, fxAccount, TokenTradableStatus.Tradable); await fxToken.Client.TransferTokensAsync(fxToken, fxToken.TreasuryAccount, fxAccount, (long)xferAmount, fxToken.TreasuryAccount); await AssertHg.TokenStatusAsync(fxToken, fxAccount, TokenTradableStatus.Tradable); }
public async Task CanSubmitMessageToOpenTopic() { await using var fx = await TestTopic.CreateAsync(_network, fx => { fx.Params.Participant = null; }); var message = Encoding.ASCII.GetBytes(Generator.String(10, 100)); var receipt = await fx.Client.SubmitMessageAsync(fx.Record.Topic, message); Assert.Equal(ResponseCode.Success, receipt.Status); Assert.Equal(1ul, receipt.SequenceNumber); Assert.False(receipt.RunningHash.IsEmpty); Assert.Equal(3ul, receipt.RunningHashVersion); var info = await fx.Client.GetTopicInfoAsync(fx.Record.Topic); Assert.Equal(fx.Memo, info.Memo); Assert.NotEmpty(info.RunningHash.ToArray()); Assert.Equal(1UL, info.SequenceNumber); Assert.True(info.Expiration > DateTime.MinValue); Assert.Equal(new Endorsement(fx.AdminPublicKey), info.Administrator); Assert.Null(info.Participant); Assert.True(info.AutoRenewPeriod > TimeSpan.MinValue); Assert.Equal(fx.TestAccount.Record.Address, info.RenewAccount); AssertHg.NotEmpty(info.Ledger); }
public async Task CanSuspendTokenCoinTradingFromAnyAccountWithSuspendKey() { await using var fxOther = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.InitialBalance = 120_00_000_000); await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxToken = await TestToken.CreateAsync(_network, fx => { fx.Params.GrantKycEndorsement = null; fx.Params.InitializeSuspended = false; }, fxAccount); var circulation = fxToken.Params.Circulation; var xferAmount = circulation / 3; await AssertHg.TokenStatusAsync(fxToken, fxAccount, TokenTradableStatus.Tradable); await fxToken.Client.SuspendTokenAsync(fxToken.Record.Token, fxAccount, fxToken.SuspendPrivateKey, ctx => { ctx.Payer = fxOther.Record.Address; ctx.Signatory = fxOther.PrivateKey; }); await AssertHg.TokenStatusAsync(fxToken, fxAccount, TokenTradableStatus.Suspended); var tex = await Assert.ThrowsAsync <TransactionException>(async() => { await fxToken.Client.TransferTokensAsync(fxToken, fxToken.TreasuryAccount, fxAccount, (long)xferAmount, fxToken.TreasuryAccount); }); Assert.Equal(ResponseCode.AccountFrozenForToken, tex.Status); Assert.StartsWith("Unable to execute transfers, status: AccountFrozenForToken", tex.Message); await AssertHg.TokenStatusAsync(fxToken, fxAccount, TokenTradableStatus.Suspended); }
public async Task CannotSuspendAssetWhenFreezeNotEnabled() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxAsset = await TestAsset.CreateAsync(_network, fx => { fx.Params.GrantKycEndorsement = null; fx.Params.SuspendEndorsement = null; fx.Params.InitializeSuspended = false; }, fxAccount); await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenTradableStatus.NotApplicable); var tex = await Assert.ThrowsAsync <TransactionException>(async() => { await fxAsset.Client.SuspendTokenAsync(fxAsset.Record.Token, fxAccount, fxAsset.SuspendPrivateKey); }); Assert.Equal(ResponseCode.TokenHasNoFreezeKey, tex.Status); Assert.Equal(ResponseCode.TokenHasNoFreezeKey, tex.Receipt.Status); Assert.StartsWith("Unable to Suspend Token, status: TokenHasNoFreezeKey", tex.Message); await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenTradableStatus.NotApplicable); await fxAsset.Client.TransferAssetAsync(new Asset(fxAsset, 1), fxAsset.TreasuryAccount, fxAccount, fxAsset.TreasuryAccount); await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenTradableStatus.NotApplicable); }
public async Task CanCallWithRecordPayerSignatory() { SubmitMessageRecord record = null; await using var fx = await TestTopic.CreateAsync(_network); var expectedSequenceNumber = Generator.Integer(10, 20); for (int i = 0; i < expectedSequenceNumber; i++) { var message = Encoding.ASCII.GetBytes(Generator.String(10, 100)); record = await fx.Client.SubmitMessageWithRecordAsync(fx.Record.Topic, message, ctx => ctx.Signatory = new Signatory(fx.ParticipantPrivateKey, _network.PrivateKey)); Assert.Equal(ResponseCode.Success, record.Status); Assert.Equal((ulong)i + 1, record.SequenceNumber); Assert.False(record.RunningHash.IsEmpty); Assert.False(record.Hash.IsEmpty); Assert.NotNull(record.Concensus); Assert.Empty(record.Memo); Assert.InRange(record.Fee, 0UL, ulong.MaxValue); Assert.Equal(_network.Payer, record.Id.Address); } var info = await fx.Client.GetTopicInfoAsync(fx.Record.Topic); Assert.Equal((ulong)expectedSequenceNumber, info.SequenceNumber); Assert.Equal((ulong)expectedSequenceNumber, record.SequenceNumber); Assert.Equal(info.RunningHash.ToArray(), record.RunningHash.ToArray()); AssertHg.NotEmpty(info.Ledger); }
public async Task CanSuspendAssetTrading() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxAsset = await TestAsset.CreateAsync(_network, fx => { fx.Params.GrantKycEndorsement = null; fx.Params.InitializeSuspended = false; }, fxAccount); await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenTradableStatus.Tradable); await fxAsset.Client.SuspendTokenAsync(fxAsset.Record.Token, fxAccount, fxAsset.SuspendPrivateKey); await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenTradableStatus.Suspended); var tex = await Assert.ThrowsAsync <TransactionException>(async() => { await fxAsset.Client.TransferAssetAsync(new Asset(fxAsset, 1), fxAsset.TreasuryAccount, fxAccount, fxAsset.TreasuryAccount); }); Assert.Equal(ResponseCode.AccountFrozenForToken, tex.Status); Assert.Equal(ResponseCode.AccountFrozenForToken, tex.Receipt.Status); Assert.StartsWith("Unable to execute transfers, status: AccountFrozenForToken", tex.Message); await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenTradableStatus.Suspended); }
public async Task CanGrantAssetsAndGetRecordWithoutExtraSignatory() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxAsset = await TestAsset.CreateAsync(_network, null, fxAccount); await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenKycStatus.Revoked); var record = await fxAsset.Client.GrantTokenKycWithRecordAsync(fxAsset.Record.Token, fxAccount, ctx => ctx.Signatory = new Signatory(_network.Signatory, fxAsset.GrantPrivateKey)); Assert.Equal(ResponseCode.Success, record.Status); Assert.False(record.Hash.IsEmpty); Assert.NotNull(record.Concensus); Assert.NotNull(record.CurrentExchangeRate); Assert.NotNull(record.NextExchangeRate); Assert.NotEmpty(record.Hash.ToArray()); Assert.Empty(record.Memo); Assert.InRange(record.Fee, 0UL, ulong.MaxValue); Assert.Equal(_network.Payer, record.Id.Address); await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenKycStatus.Granted); await fxAsset.Client.TransferAssetAsync(new Asset(fxAsset, 1), fxAsset.TreasuryAccount, fxAccount, fxAsset.TreasuryAccount); await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenKycStatus.Granted); }
public async Task CanGrantAssetsToAliasAccountDefect() { // Granting Access to an asset with an account using its alias address has not yet been // implemented by the network, although it will accept the transaction. var testFailException = (await Assert.ThrowsAsync <TransactionException>(CanGrantAssetsToAliasAccount)); Assert.StartsWith("Unable to Grant Token, status: InvalidAccountId", testFailException.Message); //[Fact(DisplayName = "Grant Assets: Can Grant Asset Coins to Alias Account")] async Task CanGrantAssetsToAliasAccount() { await using var fxAccount = await TestAliasAccount.CreateAsync(_network); await using var fxAsset = await TestAsset.CreateAsync(_network); await fxAsset.Client.AssociateTokenAsync(fxAsset.Record.Token, fxAccount, fxAccount.PrivateKey); await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenKycStatus.Revoked); await fxAsset.Client.GrantTokenKycAsync(fxAsset.Record.Token, fxAccount.Alias, fxAsset.GrantPrivateKey); await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenKycStatus.Granted); await fxAsset.Client.TransferAssetAsync(new Asset(fxAsset, 1), fxAsset.TreasuryAccount, fxAccount, fxAsset.TreasuryAccount); await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenKycStatus.Granted); } }
public async Task CanRevokeTokenCoinsFromAnyAccountWithGrantKey() { await using var fxOther = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.InitialBalance = 120_00_000_000); await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxAsset = await TestAsset.CreateAsync(_network, null, fxAccount); var circulation = (ulong)fxAsset.Metadata.Length; await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenKycStatus.Revoked); await fxAsset.Client.GrantTokenKycAsync(fxAsset, fxAccount, fxAsset.GrantPrivateKey); await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenKycStatus.Granted); await fxAsset.Client.TransferAssetAsync(new Asset(fxAsset, 1), fxAsset.TreasuryAccount, fxAccount, fxAsset.TreasuryAccount); await fxAsset.Client.RevokeTokenKycAsync(fxAsset.Record.Token, fxAccount, fxAsset.GrantPrivateKey, ctx => { ctx.Payer = fxOther.Record.Address; ctx.Signatory = fxOther.PrivateKey; }); await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenKycStatus.Revoked); var tex = await Assert.ThrowsAsync <TransactionException>(async() => { await fxAsset.Client.TransferAssetAsync(new Asset(fxAsset, 2), fxAsset.TreasuryAccount, fxAccount, fxAsset.TreasuryAccount); }); Assert.Equal(ResponseCode.AccountKycNotGrantedForToken, tex.Status); Assert.Equal(ResponseCode.AccountKycNotGrantedForToken, tex.Receipt.Status); Assert.StartsWith("Unable to execute transfers, status: AccountKycNotGrantedForToken", tex.Message); }
public async Task CanSuspendAResumedAccount() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxToken = await TestToken.CreateAsync(_network, fx => { fx.Params.GrantKycEndorsement = null; fx.Params.InitializeSuspended = true; }, fxAccount); var circulation = fxToken.Params.Circulation; var xferAmount = circulation / 3; await AssertHg.TokenStatusAsync(fxToken, fxAccount, TokenTradableStatus.Suspended); await fxToken.Client.ResumeTokenAsync(fxToken.Record.Token, fxAccount, fxToken.SuspendPrivateKey); await AssertHg.TokenStatusAsync(fxToken, fxAccount, TokenTradableStatus.Tradable); await fxToken.Client.SuspendTokenAsync(fxToken.Record.Token, fxAccount, fxToken.SuspendPrivateKey); await AssertHg.TokenStatusAsync(fxToken, fxAccount, TokenTradableStatus.Suspended); var tex = await Assert.ThrowsAsync <TransactionException>(async() => { await fxToken.Client.TransferTokensAsync(fxToken, fxToken.TreasuryAccount, fxAccount, (long)xferAmount, fxToken.TreasuryAccount); }); Assert.Equal(ResponseCode.AccountFrozenForToken, tex.Status); Assert.StartsWith("Unable to execute transfers, status: AccountFrozenForToken", tex.Message); await AssertHg.TokenStatusAsync(fxToken, fxAccount, TokenTradableStatus.Suspended); }
public async Task CanRevokeTokens() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxAsset = await TestAsset.CreateAsync(_network, null, fxAccount); await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenKycStatus.Revoked); await fxAsset.Client.GrantTokenKycAsync(fxAsset, fxAccount, fxAsset.GrantPrivateKey); await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenKycStatus.Granted); await fxAsset.Client.TransferAssetAsync(new Asset(fxAsset, 1), fxAsset.TreasuryAccount, fxAccount, fxAsset.TreasuryAccount); await fxAsset.Client.RevokeTokenKycAsync(fxAsset.Record.Token, fxAccount, fxAsset.GrantPrivateKey); await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenKycStatus.Revoked); var tex = await Assert.ThrowsAsync <TransactionException>(async() => { await fxAsset.Client.TransferAssetAsync(new Asset(fxAsset, 2), fxAsset.TreasuryAccount, fxAccount, fxAsset.TreasuryAccount); }); Assert.Equal(ResponseCode.AccountKycNotGrantedForToken, tex.Status); Assert.Equal(ResponseCode.AccountKycNotGrantedForToken, tex.Receipt.Status); Assert.StartsWith("Unable to execute transfers, status: AccountKycNotGrantedForToken", tex.Message); }
public async Task SuspendTokenRequiresSuspendKeyToSignTransaciton() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxToken = await TestToken.CreateAsync(_network, fx => { fx.Params.GrantKycEndorsement = null; fx.Params.InitializeSuspended = false; }); var circulation = fxToken.Params.Circulation; var xferAmount = circulation / 3; await AssertHg.TokenNotAssociatedAsync(fxToken, fxAccount); var tex = await Assert.ThrowsAsync <TransactionException>(async() => { await fxToken.Client.SuspendTokenAsync(fxToken.Record.Token, fxAccount); }); Assert.Equal(ResponseCode.InvalidSignature, tex.Status); Assert.StartsWith("Unable to Suspend Token, status: InvalidSignature", tex.Message); await AssertHg.TokenNotAssociatedAsync(fxToken, fxAccount); }
public async Task CanNotScheduleRevokeTokenCoins() { await using var fxPayer = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.InitialBalance = 20_00_000_000); await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxAsset = await TestAsset.CreateAsync(_network, null, fxAccount); var circulation = (ulong)fxAsset.Metadata.Length; await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenKycStatus.Revoked); await fxAsset.Client.GrantTokenKycAsync(fxAsset, fxAccount, fxAsset.GrantPrivateKey); await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenKycStatus.Granted); await fxAsset.Client.TransferAssetAsync(new Asset(fxAsset, 1), fxAsset.TreasuryAccount, fxAccount, fxAsset.TreasuryAccount); var tex = await Assert.ThrowsAsync <TransactionException>(async() => { await fxAsset.Client.RevokeTokenKycAsync( fxAsset.Record.Token, fxAccount, new Signatory( fxAsset.GrantPrivateKey, new PendingParams { PendingPayer = fxPayer })); }); Assert.Equal(ResponseCode.ScheduledTransactionNotInWhitelist, tex.Status); Assert.Equal(ResponseCode.ScheduledTransactionNotInWhitelist, tex.Receipt.Status); Assert.StartsWith("Unable to schedule transaction, status: ScheduledTransactionNotInWhitelist", tex.Message); }
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 ResumingAnUnfrozenAccountIsNoop() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxToken = await TestToken.CreateAsync(_network, fx => { fx.Params.GrantKycEndorsement = null; fx.Params.InitializeSuspended = false; }, fxAccount); var circulation = fxToken.Params.Circulation; var xferAmount = circulation / 3; await AssertHg.TokenStatusAsync(fxToken, fxAccount, TokenTradableStatus.Tradable); await fxToken.Client.ResumeTokenAsync(fxToken.Record.Token, fxAccount, fxToken.SuspendPrivateKey); var info = (await fxAccount.Client.GetAccountInfoAsync(fxAccount)).Tokens.FirstOrDefault(t => t.Token == fxToken.Record.Token); Assert.Equal(0Ul, info.Balance); Assert.Equal(fxToken.Params.Decimals, info.Decimals); Assert.Equal(TokenTradableStatus.Tradable, info.TradableStatus); Assert.False(info.AutoAssociated); await fxToken.Client.TransferTokensAsync(fxToken, fxToken.TreasuryAccount, fxAccount, (long)xferAmount, fxToken.TreasuryAccount); info = (await fxAccount.Client.GetAccountInfoAsync(fxAccount)).Tokens.FirstOrDefault(t => t.Token == fxToken.Record.Token); Assert.Equal(xferAmount, info.Balance); Assert.Equal(fxToken.Params.Decimals, info.Decimals); Assert.Equal(TokenTradableStatus.Tradable, info.TradableStatus); Assert.False(info.AutoAssociated); }
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 CanNotResumeTokenWhenFreezeNotEnabled() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxToken = await TestToken.CreateAsync(_network, fx => { fx.Params.GrantKycEndorsement = null; fx.Params.SuspendEndorsement = null; fx.Params.InitializeSuspended = false; }, fxAccount); var circulation = fxToken.Params.Circulation; var xferAmount = circulation / 3; await AssertHg.TokenStatusAsync(fxToken, fxAccount, TokenTradableStatus.NotApplicable); var tex = await Assert.ThrowsAsync <TransactionException>(async() => { await fxToken.Client.ResumeTokenAsync(fxToken.Record.Token, fxAccount, fxToken.SuspendPrivateKey); }); Assert.Equal(ResponseCode.TokenHasNoFreezeKey, tex.Status); Assert.StartsWith("Unable to Resume Token, status: TokenHasNoFreezeKey", tex.Message); var info = (await fxAccount.Client.GetAccountInfoAsync(fxAccount)).Tokens.FirstOrDefault(t => t.Token == fxToken.Record.Token); Assert.Equal(0Ul, info.Balance); Assert.Equal(fxToken.Params.Decimals, info.Decimals); Assert.Equal(TokenTradableStatus.NotApplicable, info.TradableStatus); Assert.False(info.AutoAssociated); await fxToken.Client.TransferTokensAsync(fxToken, fxToken.TreasuryAccount, fxAccount, (long)xferAmount, fxToken.TreasuryAccount); await AssertHg.TokenStatusAsync(fxToken, fxAccount, TokenTradableStatus.NotApplicable); }
public async Task CanContinueAPausedAccount() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxToken = await TestToken.CreateAsync(_network, fx => { fx.Params.GrantKycEndorsement = null; }, fxAccount); var circulation = fxToken.Params.Circulation; var xferAmount = circulation / 3; await AssertHg.TokenPausedAsync(fxToken, TokenTradableStatus.Tradable); await fxToken.Client.PauseTokenAsync(fxToken.Record.Token, fxToken.PausePrivateKey); await AssertHg.TokenPausedAsync(fxToken, TokenTradableStatus.Suspended); await fxToken.Client.ContinueTokenAsync(fxToken.Record.Token, fxToken.PausePrivateKey); await AssertHg.TokenPausedAsync(fxToken, TokenTradableStatus.Tradable); await fxToken.Client.TransferTokensAsync(fxToken, fxToken.TreasuryAccount, fxAccount, (long)xferAmount, fxToken.TreasuryAccount); await AssertHg.TokenPausedAsync(fxToken, TokenTradableStatus.Tradable); }
public async Task CanReusmeTokenCoinTradingWithAiasAccountDefect() { // Resuming a token with an account using its alias address has not yet been // implemented by the network, although it will accept the transaction. var testFailException = (await Assert.ThrowsAsync <TransactionException>(CanReusmeTokenCoinTradingWithAiasAccount)); Assert.StartsWith("Unable to Resume Token, status: InvalidAccountId", testFailException.Message); //[Fact(DisplayName = "Resume Tokens: Can Reume Token Coin Trading with Alias Account")] async Task CanReusmeTokenCoinTradingWithAiasAccount() { await using var fxAccount = await TestAliasAccount.CreateAsync(_network); await using var fxToken = await TestToken.CreateAsync(_network, fx => { fx.Params.GrantKycEndorsement = null; fx.Params.InitializeSuspended = true; }); await fxToken.Client.AssociateTokenAsync(fxToken.Record.Token, fxAccount, fxAccount.PrivateKey); var circulation = fxToken.Params.Circulation; var xferAmount = circulation / 3; await AssertHg.TokenStatusAsync(fxToken, fxAccount, TokenTradableStatus.Suspended); await fxToken.Client.ResumeTokenAsync(fxToken.Record.Token, fxAccount.Alias, fxToken.SuspendPrivateKey); await AssertHg.TokenStatusAsync(fxToken, fxAccount, TokenTradableStatus.Tradable); await fxToken.Client.TransferTokensAsync(fxToken, fxToken.TreasuryAccount, fxAccount, (long)xferAmount, fxToken.TreasuryAccount); await AssertHg.TokenStatusAsync(fxToken, fxAccount, TokenTradableStatus.Tradable); } }
public async Task ContinueTokenRequiresSuspendKeyToSignTransaction() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxToken = await TestToken.CreateAsync(_network, fx => { fx.Params.GrantKycEndorsement = null; }, fxAccount); await fxToken.Client.PauseTokenAsync(fxToken.Record.Token, fxToken.PausePrivateKey); var circulation = fxToken.Params.Circulation; var xferAmount = circulation / 3; await AssertHg.TokenPausedAsync(fxToken, TokenTradableStatus.Suspended); var tex = await Assert.ThrowsAsync <TransactionException>(async() => { await fxToken.Client.ContinueTokenAsync(fxToken.Record.Token, fxAccount); }); Assert.Equal(ResponseCode.InvalidSignature, tex.Status); Assert.StartsWith("Unable to Continue Token, status: InvalidSignature", tex.Message); tex = await Assert.ThrowsAsync <TransactionException>(async() => { await fxToken.Client.TransferTokensAsync(fxToken, fxToken.TreasuryAccount, fxAccount, (long)xferAmount, fxToken.TreasuryAccount); }); Assert.Equal(ResponseCode.TokenIsPaused, tex.Status); Assert.StartsWith("Unable to execute transfers, status: TokenIsPaused", tex.Message); }
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 CanNotContinueTokenWhenPauseNotEnabled() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxToken = await TestToken.CreateAsync(_network, fx => { fx.Params.GrantKycEndorsement = null; fx.Params.PauseEndorsement = null; }, fxAccount); var circulation = fxToken.Params.Circulation; var xferAmount = circulation / 3; await AssertHg.TokenPausedAsync(fxToken, TokenTradableStatus.NotApplicable); var tex = await Assert.ThrowsAsync <TransactionException>(async() => { await fxToken.Client.ContinueTokenAsync(fxToken.Record.Token, fxToken.PausePrivateKey); }); Assert.Equal(ResponseCode.TokenHasNoPauseKey, tex.Status); Assert.StartsWith("Unable to Continue Token, status: TokenHasNoPauseKey", tex.Message); await fxToken.Client.TransferTokensAsync(fxToken, fxToken.TreasuryAccount, fxAccount, (long)xferAmount, fxToken.TreasuryAccount); await AssertHg.TokenPausedAsync(fxToken, TokenTradableStatus.NotApplicable); }
public async Task CanAssociateTokenWithAccountAndGetRecordNoExtraSignatory() { await using var fxAccount = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.InitialBalance = 120_00_000_000); await using var fxToken = await TestToken.CreateAsync(_network); await AssertHg.TokenNotAssociatedAsync(fxToken, fxAccount); var record = await fxAccount.Client.AssociateTokenWithRecordAsync(fxToken.Record.Token, fxAccount.Record.Address, ctx => { ctx.Payer = fxAccount.Record.Address; ctx.Signatory = fxAccount.PrivateKey; }); Assert.Equal(ResponseCode.Success, record.Status); Assert.Equal(ResponseCode.Success, record.Status); Assert.False(record.Hash.IsEmpty); Assert.NotNull(record.Concensus); Assert.NotNull(record.CurrentExchangeRate); Assert.NotNull(record.NextExchangeRate); Assert.NotEmpty(record.Hash.ToArray()); Assert.Empty(record.Memo); Assert.InRange(record.Fee, 0UL, ulong.MaxValue); Assert.Equal(fxAccount.Record.Address, record.Id.Address); var association = await AssertHg.TokenIsAssociatedAsync(fxToken, fxAccount); Assert.Equal(fxToken.Record.Token, association.Token); Assert.Equal(fxToken.Params.Symbol, association.Symbol); Assert.Equal(0UL, association.Balance); Assert.Equal(TokenKycStatus.Revoked, association.KycStatus); Assert.Equal(TokenTradableStatus.Tradable, association.TradableStatus); }
public async Task ResumingAnUnfrozenAccountIsNoop() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxAsset = await TestAsset.CreateAsync(_network, fx => { fx.Params.GrantKycEndorsement = null; fx.Params.InitializeSuspended = false; }, fxAccount); var circulation = (ulong)fxAsset.Metadata.Length; await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenTradableStatus.Tradable); await fxAsset.Client.ResumeTokenAsync(fxAsset.Record.Token, fxAccount, fxAsset.SuspendPrivateKey); var info = (await fxAccount.Client.GetAccountInfoAsync(fxAccount)).Tokens.FirstOrDefault(t => t.Token == fxAsset.Record.Token); Assert.Equal(0Ul, info.Balance); Assert.Equal(0U, info.Decimals); Assert.Equal(TokenTradableStatus.Tradable, info.TradableStatus); Assert.False(info.AutoAssociated); await fxAsset.Client.TransferAssetAsync(new Asset(fxAsset, 1), fxAsset.TreasuryAccount, fxAccount, fxAsset.TreasuryAccount); info = (await fxAccount.Client.GetAccountInfoAsync(fxAccount)).Tokens.FirstOrDefault(t => t.Token == fxAsset.Record.Token); Assert.Equal(1UL, info.Balance); Assert.Equal(0U, info.Decimals); Assert.Equal(TokenTradableStatus.Tradable, info.TradableStatus); Assert.False(info.AutoAssociated); }