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);
    }
Example #6
0
    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);
    }
Example #8
0
    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);
    }
Example #9
0
        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);
    }
Example #11
0
    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);
    }
Example #13
0
    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);
    }
Example #14
0
    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);
        }
    }
Example #15
0
    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);
    }
Example #16
0
        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);
        }
Example #17
0
    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);
    }
Example #18
0
        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);
        }
Example #19
0
    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);
    }
Example #20
0
    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);
        }
    }
Example #21
0
    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);
    }
Example #22
0
    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);
        }
    }
Example #23
0
    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);
    }
Example #24
0
    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);
    }
Example #25
0
    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);
        }
    }
Example #26
0
    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);
    }
Example #27
0
    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);
    }
Example #28
0
    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);
        }
Example #30
0
    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);
    }