public async Task CanGetTransferRecordShowingTransfers() { await using var fx = await TestAccount.CreateAsync(_network); var transferAmount = (long)Generator.Integer(10, 100); var newBalance = await fx.Client.GetAccountBalanceAsync(fx.Record.Address); Assert.Equal(fx.CreateParams.InitialBalance, newBalance); var record = await fx.Client.TransferWithRecordAsync(_network.Payer, fx.Record.Address, transferAmount); Assert.Equal(ResponseCode.Success, record.Status); Assert.Equal(4, record.Transfers.Count); Assert.Equal(-transferAmount - (long)record.Fee, record.Transfers[_network.Payer]); Assert.Equal(transferAmount, record.Transfers[fx.Record.Address]); Assert.Empty(record.TokenTransfers); var newBalanceAfterTransfer = await fx.Client.GetAccountBalanceAsync(fx.Record.Address); Assert.Equal(fx.CreateParams.InitialBalance + (ulong)transferAmount, newBalanceAfterTransfer); }
public async Task CanUpdateTreasury() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxToken = await TestToken.CreateAsync(_network, null, fxAccount); var updateParams = new UpdateTokenParams { Token = fxToken.Record.Token, Treasury = fxAccount.Record.Address, Signatory = new Signatory(fxToken.AdminPrivateKey, fxAccount.PrivateKey) }; var receipt = await fxToken.Client.UpdateTokenAsync(updateParams); Assert.Equal(ResponseCode.Success, receipt.Status); var info = await fxToken.Client.GetTokenInfoAsync(fxToken.Record.Token); Assert.Equal(fxAccount.Record.Address, info.Treasury); }
public async Task CantUpdateAutoAssociateValueToGreatherThanOneThousand() { await using var fxAccount = await TestAccount.CreateAsync(_network); var ex = await Assert.ThrowsAsync <ArgumentOutOfRangeException>(async() => { var record = await fxAccount.Client.UpdateAccountWithRecordAsync(new UpdateAccountParams { Address = fxAccount, AutoAssociationLimit = 1001, Signatory = fxAccount }); }); Assert.Equal("AutoAssociationLimit", ex.ParamName); Assert.StartsWith("The maximum number of auto-associaitons must be between zero and 1000.", ex.Message); var info = await fxAccount.Client.GetAccountInfoAsync(fxAccount); Assert.Equal(fxAccount.CreateParams.AutoAssociationLimit, info.AutoAssociationLimit); }
public async Task NoTokenBalanceRecordExistsWhenDissociated() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxToken = await TestToken.CreateAsync(_network, null, fxAccount); 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(fxToken.Params.Decimals, association.Decimals); Assert.Equal(TokenKycStatus.Revoked, association.KycStatus); Assert.Equal(TokenTradableStatus.Tradable, association.TradableStatus); var receipt = await fxAccount.Client.DissociateTokenAsync(fxToken.Record.Token, fxAccount.Record.Address, fxAccount.PrivateKey); Assert.Equal(ResponseCode.Success, receipt.Status); await AssertHg.TokenNotAssociatedAsync(fxToken, fxAccount); }
public async Task CanUpdateProxyStake() { var fx = await TestAccount.CreateAsync(_network); var originalInfo = await fx.Client.GetAccountInfoAsync(fx.Record.Address); Assert.Equal(new Address(0, 0, 0), originalInfo.Proxy); var updateResult = await fx.Client.UpdateAccountAsync(new UpdateAccountParams { Address = fx.Record.Address, Signatory = fx.PrivateKey, Proxy = _network.Gateway }); Assert.Equal(ResponseCode.Success, updateResult.Status); var updatedInfo = await fx.Client.GetAccountInfoAsync(fx.Record.Address); Assert.Equal(_network.Gateway, updatedInfo.Proxy); }
public async Task CanCreateAClaimAsync() { await using var test = await TestAccount.CreateAsync(_network); var(publicKey1, privateKey1) = Generator.KeyPair(); var(publicKey2, privateKey2) = Generator.KeyPair(); var claim = new Claim { Address = test.Record.Address, Hash = Generator.SHA384Hash(), Endorsements = new Endorsement[] { publicKey1, publicKey2 }, ClaimDuration = TimeSpan.FromDays(Generator.Integer(10, 20)) }; var receipt = await test.Client.AddClaimAsync(claim, ctx => { ctx.Payer = _network.PayerWithKeys(privateKey1, privateKey2); }); Assert.Equal(ResponseCode.Success, receipt.Status); }
public async Task CanNotScheduleADeleteFile() { await using var fxPayer = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.InitialBalance = 20_00_000_000); await using var fxFile = await TestFile.CreateAsync(_network); var tex = await Assert.ThrowsAsync <TransactionException>(async() => { await fxFile.Client.DeleteFileAsync( fxFile.Record.File, new Signatory( fxFile.PrivateKey, new PendingParams { PendingPayer = fxPayer })); }); Assert.Equal(ResponseCode.ScheduledTransactionNotInWhitelist, tex.Status); Assert.StartsWith("Unable to schedule transaction, status: ScheduledTransactionNotInWhitelist", tex.Message); }
public async Task CanMultiTransferCryptoToNewAccount() { await using var fx = await TestAccount.CreateAsync(_network); var transferAmount = (long)Generator.Integer(10, 100); var newBalance = await fx.Client.GetAccountBalanceAsync(fx.Record.Address); Assert.Equal(fx.CreateParams.InitialBalance, newBalance); var transfers = new TransferParams { CryptoTransfers = new Dictionary <Address, long> { { _network.Payer, -transferAmount }, { fx.Record.Address, transferAmount } } }; var receipt = await fx.Client.TransferAsync(transfers); var newBalanceAfterTransfer = await fx.Client.GetAccountBalanceAsync(fx.Record.Address); Assert.Equal(fx.CreateParams.InitialBalance + (ulong)transferAmount, newBalanceAfterTransfer); }
public async Task CanConfiscateAnAssetGetRecord() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxAsset = await TestAsset.CreateAsync(_network, fx => fx.Params.GrantKycEndorsement = null, fxAccount); var initialCirculation = (ulong)fxAsset.Metadata.Length; var xferAmount = 2ul; var expectedTreasury = initialCirculation - xferAmount; var serialNumbersTransfered = Enumerable.Range(1, 2).Select(i => (long)i); var transferParams = new TransferParams { AssetTransfers = serialNumbersTransfered.Select(sn => new AssetTransfer(new Asset(fxAsset.Record.Token, sn), fxAsset.TreasuryAccount, fxAccount)), Signatory = fxAsset.TreasuryAccount }; await fxAsset.Client.TransferAsync(transferParams); Assert.Equal(xferAmount, await fxAccount.Client.GetAccountTokenBalanceAsync(fxAccount, fxAsset)); Assert.Equal(expectedTreasury, await fxAccount.Client.GetAccountTokenBalanceAsync(fxAsset.TreasuryAccount, fxAsset)); Assert.Equal(initialCirculation, (await fxAsset.Client.GetTokenInfoAsync(fxAsset)).Circulation); var record = await fxAsset.Client.ConfiscateAssetWithRecordAsync(new Asset(fxAsset.Record.Token, 1), fxAccount, fxAsset.ConfiscatePrivateKey); 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); Assert.Equal(initialCirculation - 1, record.Circulation); Assert.Equal(1ul, await fxAccount.Client.GetAccountTokenBalanceAsync(fxAccount, fxAsset)); Assert.Equal(expectedTreasury, await fxAccount.Client.GetAccountTokenBalanceAsync(fxAsset.TreasuryAccount, fxAsset)); Assert.Equal(initialCirculation - 1, (await fxAsset.Client.GetTokenInfoAsync(fxAsset)).Circulation); Assert.Null(record.ParentTransactionConcensus); }
public async Task CanExecuteMultiTransferTokensAndCrypto() { await using var fxAccount1 = await TestAccount.CreateAsync(_network); await using var fxAccount2 = await TestAccount.CreateAsync(_network); await using var fxToken = await TestToken.CreateAsync(_network, fx => fx.Params.GrantKycEndorsement = null, fxAccount1, fxAccount2); var tokenAmount = fxToken.Params.Circulation / 3; var expectedTreasury = fxToken.Params.Circulation - 2 * tokenAmount; var cryptoAmount = (long)Generator.Integer(100, 200); var transfers = new TransferParams { CryptoTransfers = new Dictionary <Address, long> { { _network.Payer, -2 * cryptoAmount }, { fxAccount1, cryptoAmount }, { fxAccount2, cryptoAmount } }, TokenTransfers = new TokenTransfer[] { new TokenTransfer(fxToken, fxAccount1, (long)tokenAmount), new TokenTransfer(fxToken, fxAccount2, (long)tokenAmount), new TokenTransfer(fxToken, fxToken.TreasuryAccount, -2 * (long)tokenAmount) }, Signatory = new Signatory(_network.Signatory, fxToken.TreasuryAccount.PrivateKey) }; var receipt = await fxToken.Client.TransferAsync(transfers); Assert.Equal(ResponseCode.Success, receipt.Status); Assert.NotNull(receipt.CurrentExchangeRate); Assert.NotNull(receipt.NextExchangeRate); Assert.Equal(_network.Payer, receipt.Id.Address); Assert.Equal(fxAccount1.CreateParams.InitialBalance + (ulong)cryptoAmount, await fxAccount1.Client.GetAccountBalanceAsync(fxAccount1)); Assert.Equal(fxAccount2.CreateParams.InitialBalance + (ulong)cryptoAmount, await fxAccount2.Client.GetAccountBalanceAsync(fxAccount2)); Assert.Equal(tokenAmount, await fxAccount1.Client.GetAccountTokenBalanceAsync(fxAccount1, fxToken)); Assert.Equal(tokenAmount, await fxAccount2.Client.GetAccountTokenBalanceAsync(fxAccount2, fxToken)); Assert.Equal(expectedTreasury, await fxToken.Client.GetAccountTokenBalanceAsync(fxToken.TreasuryAccount, fxToken)); }
public async Task CannotConfiscateWhenNoConfiscationEndorsement() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxAsset = await TestAsset.CreateAsync(_network, fx => { fx.Params.GrantKycEndorsement = null; fx.Params.ConfiscateEndorsement = null; }, fxAccount); var initialCirculation = (ulong)fxAsset.Metadata.Length; var xferAmount = 2ul; var expectedTreasury = initialCirculation - xferAmount; var serialNumbersTransfered = Enumerable.Range(1, 2).Select(i => (long)i); var transferParams = new TransferParams { AssetTransfers = serialNumbersTransfered.Select(sn => new AssetTransfer(new Asset(fxAsset.Record.Token, sn), fxAsset.TreasuryAccount, fxAccount)), Signatory = fxAsset.TreasuryAccount }; await fxAsset.Client.TransferAsync(transferParams); Assert.Equal(xferAmount, await fxAccount.Client.GetAccountTokenBalanceAsync(fxAccount, fxAsset)); Assert.Equal(expectedTreasury, await fxAccount.Client.GetAccountTokenBalanceAsync(fxAsset.TreasuryAccount, fxAsset)); Assert.Equal(initialCirculation, (await fxAsset.Client.GetTokenInfoAsync(fxAsset)).Circulation); var tex = await Assert.ThrowsAsync <TransactionException>(async() => { await fxAsset.Client.ConfiscateAssetAsync(new Asset(fxAsset, 1), fxAccount, fxAsset.ConfiscatePrivateKey); }); Assert.Equal(ResponseCode.TokenHasNoWipeKey, tex.Status); Assert.Equal(ResponseCode.TokenHasNoWipeKey, tex.Receipt.Status); Assert.StartsWith("Unable to Confiscate Token, status: TokenHasNoWipeKey", tex.Message); Assert.Equal(xferAmount, await fxAccount.Client.GetAccountTokenBalanceAsync(fxAccount, fxAsset)); Assert.Equal(expectedTreasury, await fxAccount.Client.GetAccountTokenBalanceAsync(fxAsset.TreasuryAccount, fxAsset)); Assert.Equal(initialCirculation, (await fxAsset.Client.GetTokenInfoAsync(fxAsset)).Circulation); }
public async Task CanUpdateMultiplePropertiesAtOnce() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxTempate = await TestAccount.CreateAsync(_network); var record = await fxAccount.Client.UpdateAccountWithRecordAsync(new UpdateAccountParams { Address = fxAccount, Signatory = new Signatory(fxAccount, fxTempate), Endorsement = fxTempate.CreateParams.Endorsement, RequireReceiveSignature = fxTempate.CreateParams.RequireReceiveSignature, Proxy = fxTempate, Memo = fxTempate.CreateParams.Memo }); 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); var info = await fxAccount.Client.GetAccountInfoAsync(fxAccount); Assert.Equal(fxAccount.Record.Address, info.Address); Assert.NotNull(info.SmartContractId); Assert.False(info.Deleted); Assert.Equal(fxTempate.Record.Address, info.Proxy); Assert.Equal(0, info.ProxiedToAccount); Assert.Equal(fxTempate.PublicKey, info.Endorsement); Assert.Equal(fxAccount.CreateParams.InitialBalance, info.Balance); Assert.Equal(fxTempate.CreateParams.RequireReceiveSignature, info.ReceiveSignatureRequired); Assert.True(info.AutoRenewPeriod.TotalSeconds > 0); Assert.True(info.Expiration > DateTime.MinValue); Assert.Equal(fxTempate.CreateParams.Memo, info.Memo); }
public async Task CanScheduleCreateAccount() { // Not whitelisted on testnet. var tex = await Assert.ThrowsAsync <TransactionException>(async() => { await using var fxPayer = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.InitialBalance = 20_00_000_000); var fxAccount = await TestAccount.CreateAsync(_network, fx => { fx.CreateParams.Signatory = new PendingParams { PendingPayer = fxPayer }; }); // When this is whitelisted, the fillowing should pass. var transactionReceipt = await fxPayer.Client.SignPendingTransactionAsync(fxAccount.Record.Pending.Id, fxPayer); var pendingReceipt = await fxPayer.Client.GetReceiptAsync(fxAccount.Record.Pending.TxId); Assert.Equal(ResponseCode.Success, pendingReceipt.Status); var createReceipt = Assert.IsType <CreateAccountReceipt>(pendingReceipt); var account = createReceipt.Address; var info = await fxPayer.Client.GetAccountInfoAsync(account); Assert.Equal(account, info.Address); Assert.NotNull(info.SmartContractId); Assert.False(info.Deleted); Assert.NotNull(info.Proxy); Assert.Equal(Address.None, info.Proxy); Assert.Equal(0, info.ProxiedToAccount); Assert.Equal(fxAccount.CreateParams.Endorsement, info.Endorsement); Assert.Equal(fxAccount.CreateParams.InitialBalance, info.Balance); Assert.Equal(fxAccount.CreateParams.RequireReceiveSignature, info.ReceiveSignatureRequired); Assert.Equal(fxAccount.CreateParams.AutoRenewPeriod.TotalSeconds, info.AutoRenewPeriod.TotalSeconds); Assert.True(info.Expiration > DateTime.MinValue); }); Assert.Equal(ResponseCode.ScheduledTransactionNotInWhitelist, tex.Status); Assert.StartsWith("Unable to schedule transaction, status: ScheduledTransactionNotInWhitelist", tex.Message); }
public async Task ResumeAssetRequiresSuspendKeyToSignTransaction() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxAsset = await TestAsset.CreateAsync(_network, fx => { fx.Params.GrantKycEndorsement = null; fx.Params.InitializeSuspended = true; }, fxAccount); var circulation = fxAsset.Metadata.Length; var xferAmount = circulation / 3; await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenTradableStatus.Suspended); var tex = await Assert.ThrowsAsync <TransactionException>(async() => { await fxAsset.Client.ResumeTokenAsync(fxAsset.Record.Token, fxAccount); }); Assert.Equal(ResponseCode.InvalidSignature, tex.Status); Assert.Equal(ResponseCode.InvalidSignature, tex.Receipt.Status); Assert.StartsWith("Unable to Resume Token, status: InvalidSignature", tex.Message); 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.Suspended, info.TradableStatus); Assert.False(info.AutoAssociated); 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); }
public async Task CanAssociateMultipleTokensWithAccountNoExtraSignatory() { await using var fxAccount = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.InitialBalance = 120_00_000_000); 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, ctx => { ctx.Payer = fxAccount.Record.Address; ctx.Signatory = 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(fxToken1.Params.Decimals, association.Decimals); 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(fxToken2.Params.Decimals, association.Decimals); Assert.Equal(TokenKycStatus.Revoked, association.KycStatus); Assert.Equal(TokenTradableStatus.Tradable, association.TradableStatus); }
public async Task CanNotScheduleCallContract() { await using var fxPayer = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.InitialBalance = 20_00_000_000); await using var fxContract = await StatefulContract.CreateAsync(_network); var tex = await Assert.ThrowsAsync <TransactionException>(async() => { await fxContract.Client.CallContractWithRecordAsync(new CallContractParams { Contract = fxContract.ContractRecord.Contract, Gas = await _network.TinybarsFromGas(400), FunctionName = "get_message", Signatory = new PendingParams { PendingPayer = fxPayer } }); }); Assert.Equal(ResponseCode.ScheduledTransactionNotInWhitelist, tex.Status); Assert.StartsWith("Unable to schedule transaction, status: ScheduledTransactionNotInWhitelist", tex.Message); }
public async Task CanRevokeTokensAndGetRecord() { 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 record = await fxAsset.Client.RevokeTokenKycWithRecordAsync(fxAsset.Record.Token, fxAccount, 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.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 DeletingMissingAccountThrowsError() { await using var test = await TestAccount.CreateAsync(_network); var(publicKey1, privateKey1) = Generator.KeyPair(); var(publicKey2, privateKey2) = Generator.KeyPair(); var claim = new Claim { Address = test.Record.Address, Hash = Generator.SHA384Hash(), Endorsements = new Endorsement[] { publicKey1, publicKey2 }, ClaimDuration = TimeSpan.FromDays(Generator.Integer(10, 20)) }; var exception = await Assert.ThrowsAsync <ArgumentNullException>(async() => { await test.Client.GetClaimAsync(null, claim.Hash); }); Assert.Equal("address", exception.ParamName); Assert.StartsWith("Account Address is missing. Please check that it is not null.", exception.Message); }
public async Task CanSuspendTokenCoinTradingAndGetRecordNoExtraSignatory() { 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); var record = await fxToken.Client.SuspendTokenWithRecordAsync(fxToken.Record.Token, fxAccount, ctx => ctx.Signatory = new Signatory(_network.Signatory, 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.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 CanGrantAssetCoinsFromWnyAccountWithGrantKey() { 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); await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenKycStatus.Revoked); await fxAsset.Client.GrantTokenKycAsync(fxAsset.Record.Token, fxAccount, fxAsset.GrantPrivateKey, ctx => { ctx.Payer = fxOther.Record.Address; ctx.Signatory = fxOther.PrivateKey; }); 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 CanNotScheduleMintTokenCoins() { await using var fxPayer = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.InitialBalance = 20_00_000_000); await using var fxToken = await TestToken.CreateAsync(_network); var tex = await Assert.ThrowsAsync <TransactionException>(async() => { await fxToken.Client.MintTokenAsync( fxToken.Record.Token, fxToken.Params.Circulation, new Signatory( fxToken.SupplyPrivateKey, new PendingParams { PendingPayer = fxPayer })); }); Assert.Equal(ResponseCode.ScheduledTransactionNotInWhitelist, tex.Status); Assert.StartsWith("Unable to schedule transaction, status: ScheduledTransactionNotInWhitelist", tex.Message); }
public async Task DissociationRequiresAccount() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxToken = await TestToken.CreateAsync(_network, null, fxAccount); var ane = await Assert.ThrowsAsync <ArgumentNullException>(async() => { await fxAccount.Client.DissociateTokenAsync(fxToken.Record.Token, null); }); Assert.Equal("account", ane.ParamName); Assert.StartsWith("Account Address/Alias is missing. Please check that it is not null.", ane.Message); var tex = await Assert.ThrowsAsync <TransactionException>(async() => { await fxAccount.Client.DissociateTokenAsync(fxToken.Record.Token, Address.None); }); Assert.Equal(ResponseCode.InvalidAccountId, tex.Status); Assert.StartsWith("Unable to Dissociate Token from Account, status: InvalidAccountId", tex.Message); }
public async Task CanDissociateMultipleTokensWithAccount() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxToken1 = await TestToken.CreateAsync(_network, null, fxAccount); await using var fxToken2 = await TestToken.CreateAsync(_network, null, fxAccount); var tokens = new Address[] { fxToken1.Record.Token, fxToken2.Record.Token }; await AssertHg.TokenIsAssociatedAsync(fxToken1, fxAccount); await AssertHg.TokenIsAssociatedAsync(fxToken2, fxAccount); var receipt = await fxAccount.Client.DissociateTokensAsync(tokens, fxAccount.Record.Address, fxAccount.PrivateKey); Assert.Equal(ResponseCode.Success, receipt.Status); await AssertHg.TokenNotAssociatedAsync(fxToken1, fxAccount); await AssertHg.TokenNotAssociatedAsync(fxToken2, fxAccount); }
public async Task CanAssociateAssetWithAccount() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxAsset = await TestAsset.CreateAsync(_network, fx => fx.Metadata = null); await AssertHg.AssetNotAssociatedAsync(fxAsset, fxAccount); var receipt = await fxAccount.Client.AssociateTokenAsync(fxAsset.Record.Token, fxAccount.Record.Address, fxAccount.PrivateKey); Assert.Equal(ResponseCode.Success, receipt.Status); var association = await AssertHg.AssetIsAssociatedAsync(fxAsset, fxAccount); Assert.Equal(fxAsset.Record.Token, association.Token); Assert.Equal(fxAsset.Params.Symbol, association.Symbol); Assert.Equal(0UL, association.Balance); Assert.Equal(0UL, association.Decimals); Assert.Equal(TokenKycStatus.Revoked, association.KycStatus); Assert.Equal(TokenTradableStatus.Tradable, association.TradableStatus); Assert.False(association.AutoAssociated); }
public async Task CanSendFromAliasAccount() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxAlias = await TestAliasAccount.CreateAsync(_network); var aliasStartingBalance = await fxAlias.Client.GetAccountBalanceAsync(fxAlias.Alias); var transferAmount = (aliasStartingBalance) / 2 + 1; var accountStartingBalance = await fxAlias.Client.GetAccountBalanceAsync(fxAccount); var receipt = await fxAlias.Client.TransferAsync(fxAlias.Alias, fxAccount.Record.Address, (long)transferAmount, fxAlias.PrivateKey); var accountEndingBalance = await fxAlias.Client.GetAccountBalanceAsync(fxAccount); Assert.Equal(accountStartingBalance + (ulong)transferAmount, accountEndingBalance); var aliasEndingBalance = await fxAlias.Client.GetAccountBalanceAsync(fxAlias.Alias); Assert.Equal(aliasStartingBalance - (ulong)transferAmount, aliasEndingBalance); }
public async Task CanLowerLimitTokenAutoAssociation() { await using var fxAccount = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.AutoAssociationLimit = 100); await using var fxToken1 = await TestToken.CreateAsync(_network, fx => fx.Params.GrantKycEndorsement = null); await using var fxToken2 = await TestToken.CreateAsync(_network, fx => fx.Params.GrantKycEndorsement = null); await AssertHg.TokenNotAssociatedAsync(fxToken1, fxAccount); await AssertHg.TokenNotAssociatedAsync(fxToken2, fxAccount); var xferAmount1 = fxToken1.Params.Circulation / 2; var receipt = await fxToken1.Client.TransferTokensAsync(fxToken1, fxToken1.TreasuryAccount, fxAccount, (long)xferAmount1, fxToken1.TreasuryAccount); Assert.Equal(ResponseCode.Success, receipt.Status); await fxAccount.Client.UpdateAccountAsync(new UpdateAccountParams { Address = fxAccount, AutoAssociationLimit = 1, Signatory = fxAccount }); var tex = await Assert.ThrowsAsync <TransactionException>(async() => { var xferAmount2 = fxToken2.Params.Circulation / 2; var receipt2 = await fxToken2.Client.TransferTokensAsync(fxToken2, fxToken2.TreasuryAccount, fxAccount, (long)xferAmount2, fxToken2.TreasuryAccount); }); Assert.Equal(ResponseCode.NoRemainingAutomaticAssociations, tex.Status); Assert.StartsWith("Unable to execute transfers, status: NoRemainingAutomaticAssociations", tex.Message); await AssertHg.TokenIsAssociatedAsync(fxToken1, fxAccount); await AssertHg.TokenNotAssociatedAsync(fxToken2, fxAccount); await AssertHg.TokenBalanceAsync(fxToken1, fxAccount, xferAmount1); }
public async Task CanConfiscateAnAssetFromAnyAccountWithConfiscateKey() { 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, fx => fx.Params.GrantKycEndorsement = null, fxAccount); var initialCirculation = (ulong)fxAsset.Metadata.Length; var xferAmount = 2ul; var expectedTreasury = initialCirculation - xferAmount; var serialNumbersTransfered = Enumerable.Range(1, 2).Select(i => (long)i); var transferParams = new TransferParams { AssetTransfers = serialNumbersTransfered.Select(sn => new AssetTransfer(new Asset(fxAsset.Record.Token, sn), fxAsset.TreasuryAccount, fxAccount)), Signatory = fxAsset.TreasuryAccount }; await fxAsset.Client.TransferAsync(transferParams); Assert.Equal(xferAmount, await fxAccount.Client.GetAccountTokenBalanceAsync(fxAccount, fxAsset)); Assert.Equal(expectedTreasury, await fxAccount.Client.GetAccountTokenBalanceAsync(fxAsset.TreasuryAccount, fxAsset)); Assert.Equal(initialCirculation, (await fxAsset.Client.GetTokenInfoAsync(fxAsset)).Circulation); var receipt = await fxAsset.Client.ConfiscateAssetAsync(new Asset(fxAsset, 1), fxAccount, fxAsset.ConfiscatePrivateKey, ctx => { ctx.Payer = fxOther.Record.Address; ctx.Signatory = fxOther.PrivateKey; }); Assert.Equal(ResponseCode.Success, receipt.Status); Assert.Equal(initialCirculation - 1, receipt.Circulation); Assert.Equal(1ul, await fxAccount.Client.GetAccountTokenBalanceAsync(fxAccount, fxAsset)); Assert.Equal(expectedTreasury, await fxAccount.Client.GetAccountTokenBalanceAsync(fxAsset.TreasuryAccount, fxAsset)); Assert.Equal(initialCirculation - 1, (await fxAsset.Client.GetTokenInfoAsync(fxAsset)).Circulation); }
public async Task CanRevokeTokensAndGetRecordWithoutExtraSignatory() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxToken = await TestToken.CreateAsync(_network, null, fxAccount); var circulation = fxToken.Params.Circulation; var xferAmount = circulation / 3; await AssertHg.TokenStatusAsync(fxToken, fxAccount, TokenKycStatus.Revoked); await fxToken.Client.GrantTokenKycAsync(fxToken, fxAccount, fxToken.GrantPrivateKey); await AssertHg.TokenStatusAsync(fxToken, fxAccount, TokenKycStatus.Granted); await fxToken.Client.TransferTokensAsync(fxToken, fxToken.TreasuryAccount, fxAccount, (long)xferAmount, fxToken.TreasuryAccount); var record = await fxToken.Client.RevokeTokenKycWithRecordAsync(fxToken.Record.Token, fxAccount, ctx => ctx.Signatory = new Signatory(_network.Signatory, fxToken.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.TokenStatusAsync(fxToken, fxAccount, TokenKycStatus.Revoked); var tex = await Assert.ThrowsAsync <TransactionException>(async() => { await fxToken.Client.TransferTokensAsync(fxToken, fxToken.TreasuryAccount, fxAccount, (long)xferAmount, fxToken.TreasuryAccount); }); Assert.Equal(ResponseCode.AccountKycNotGrantedForToken, tex.Status); Assert.StartsWith("Unable to execute transfers, status: AccountKycNotGrantedForToken", tex.Message); }
public async Task AssociationRequiresAccount() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var fxToken = await TestToken.CreateAsync(_network); var ane = await Assert.ThrowsAsync <ArgumentNullException>(async() => { await fxAccount.Client.AssociateTokenAsync(fxToken.Record.Token, null); }); Assert.Equal("account", ane.ParamName); Assert.StartsWith("Account Address is missing. Please check that it is not null or empty", ane.Message); ane = await Assert.ThrowsAsync <ArgumentNullException>(async() => { await fxAccount.Client.AssociateTokenAsync(fxToken.Record.Token, Address.None); }); Assert.Equal("account", ane.ParamName); Assert.StartsWith("Account Address is missing. Please check that it is not null or empty", ane.Message); }
public async Task CanCreateTokenWithFixedRoyalty() { await using var fxAccount = await TestAccount.CreateAsync(_network); await using var comToken = await TestToken.CreateAsync(_network, null, fxAccount); await using var fxToken = await TestToken.CreateAsync(_network, fx => { fx.Params.Royalties = new FixedRoyalty[] { new FixedRoyalty(fxAccount, comToken, 100) }; }, fxAccount); Assert.Equal(ResponseCode.Success, fxToken.Record.Status); var info = await fxToken.Client.GetTokenInfoAsync(fxToken.Record.Token); Assert.Single(info.Royalties); Assert.Equal(fxToken.Params.Royalties.First(), info.Royalties[0]); }