public async Task CannotPassToAKCYNonGrantedAccount()
    {
        await using var fxAccount1 = await TestAccount.CreateAsync(_network);

        await using var fxAccount2 = await TestAccount.CreateAsync(_network);

        await using var fxAsset = await TestAsset.CreateAsync(_network, null, fxAccount1, fxAccount2);

        await fxAsset.Client.GrantTokenKycAsync(fxAsset, fxAccount1, fxAsset.GrantPrivateKey);

        var asset = new Asset(fxAsset, 1);

        await fxAsset.Client.TransferAssetAsync(asset, fxAsset.TreasuryAccount, fxAccount1, fxAsset.TreasuryAccount);

        Assert.Equal(1UL, await fxAccount1.Client.GetAccountTokenBalanceAsync(fxAccount1, fxAsset));
        Assert.Equal(0UL, await fxAccount1.Client.GetAccountTokenBalanceAsync(fxAccount2, fxAsset));

        var tex = await Assert.ThrowsAsync <TransactionException>(async() =>
        {
            await fxAsset.Client.TransferAssetAsync(asset, fxAccount1, fxAccount2, fxAccount1);
        });

        Assert.Equal(ResponseCode.AccountKycNotGrantedForToken, tex.Status);
        Assert.Equal(ResponseCode.AccountKycNotGrantedForToken, tex.Receipt.Status);
        Assert.StartsWith("Unable to execute transfers, status: AccountKycNotGrantedForToken", tex.Message);

        Assert.Equal(1UL, await fxAccount1.Client.GetAccountTokenBalanceAsync(fxAccount1, fxAsset));
        Assert.Equal(0UL, await fxAccount1.Client.GetAccountTokenBalanceAsync(fxAccount2, fxAsset));
    }
Example #2
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 #3
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 #4
0
    public async Task CanNotBurnSingleAssetTheTreasuryDoesNotOwn()
    {
        await using var fxAccount = await TestAccount.CreateAsync(_network);

        await using var fxAsset = await TestAsset.CreateAsync(_network, fx => fx.Params.GrantKycEndorsement = null, fxAccount);

        var amountToTransfer        = 2 * fxAsset.Metadata.Length / 3;
        var expectedTreasury        = fxAsset.Metadata.Length - amountToTransfer;
        var serialNumbersTransfered = Enumerable.Range(1, amountToTransfer).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((ulong)amountToTransfer, await fxAccount.Client.GetAccountTokenBalanceAsync(fxAccount, fxAsset));
        Assert.Equal((ulong)expectedTreasury, await fxAsset.Client.GetAccountTokenBalanceAsync(fxAsset.TreasuryAccount, fxAsset));
        Assert.Equal((ulong)fxAsset.Metadata.Length, (await fxAsset.Client.GetTokenInfoAsync(fxAsset)).Circulation);

        var tex = await Assert.ThrowsAsync <TransactionException>(async() =>
        {
            await fxAsset.Client.BurnAssetAsync(new Asset(fxAsset.Record.Token, 1), fxAsset.SupplyPrivateKey);
        });

        Assert.Equal(ResponseCode.TreasuryMustOwnBurnedNft, tex.Status);
        Assert.Equal(ResponseCode.TreasuryMustOwnBurnedNft, tex.Receipt.Status);
        Assert.StartsWith("Unable to Burn Token Coins, status: TreasuryMustOwnBurnedNft", tex.Message);

        Assert.Equal((ulong)amountToTransfer, await fxAccount.Client.GetAccountTokenBalanceAsync(fxAccount, fxAsset));
        Assert.Equal((ulong)expectedTreasury, await fxAsset.Client.GetAccountTokenBalanceAsync(fxAsset.TreasuryAccount, fxAsset));
        Assert.Equal((ulong)fxAsset.Metadata.Length, (await fxAsset.Client.GetTokenInfoAsync(fxAsset)).Circulation);
    }
    public async Task DeletingAssetPreventsAssetTransfersAmongstThirdParties()
    {
        await using var fxAccount1 = await TestAccount.CreateAsync(_network);

        await using var fxAccount2 = await TestAccount.CreateAsync(_network);

        await using var fxAsset = await TestAsset.CreateAsync(_network, fx => fx.Params.GrantKycEndorsement = null, fxAccount1, fxAccount2);

        await fxAsset.Client.TransferAssetAsync(new Asset(fxAsset.Record.Token, 1), fxAsset.TreasuryAccount.Record.Address, fxAccount1.Record.Address, fxAsset.TreasuryAccount.PrivateKey);

        await fxAsset.Client.TransferAssetAsync(new Asset(fxAsset.Record.Token, 2), fxAsset.TreasuryAccount.Record.Address, fxAccount2.Record.Address, fxAsset.TreasuryAccount.PrivateKey);

        var record = await fxAccount1.Client.DeleteTokenAsync(fxAsset.Record.Token, fxAsset.AdminPrivateKey);

        Assert.Equal(ResponseCode.Success, record.Status);

        var tex = await Assert.ThrowsAsync <TransactionException>(async() =>
        {
            await fxAsset.Client.TransferAssetAsync(new Asset(fxAsset.Record.Token, 1), fxAccount1.Record.Address, fxAccount2.Record.Address, fxAccount1.PrivateKey);
        });

        Assert.Equal(ResponseCode.TokenWasDeleted, tex.Status);
        Assert.Equal(ResponseCode.TokenWasDeleted, tex.Receipt.Status);
        Assert.StartsWith("Unable to execute transfers, status: TokenWasDeleted", tex.Message);
    }
    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 #7
0
    public async Task CanBurnAssetCoinsFromAnyAccountWithSupplyKey()
    {
        await using var fxAccount = await TestAccount.CreateAsync(_network, ctx => ctx.CreateParams.InitialBalance = 60_000_000_000);

        await using var fxAsset = await TestAsset.CreateAsync(_network);

        Assert.NotNull(fxAsset.Record);
        Assert.NotNull(fxAsset.Record.Token);
        Assert.True(fxAsset.Record.Token.AccountNum > 0);
        Assert.Equal(ResponseCode.Success, fxAsset.Record.Status);

        var amountToDestory     = fxAsset.Metadata.Length / 3 + 1;
        var expectedCirculation = (ulong)(fxAsset.Metadata.Length - amountToDestory);
        var serialNumbers       = Enumerable.Range(1, amountToDestory).Select(i => (long)i);

        var receipt = await fxAccount.Client.BurnAssetsAsync(fxAsset, serialNumbers, fxAsset.SupplyPrivateKey, ctx =>
        {
            ctx.Payer     = fxAccount.Record.Address;
            ctx.Signatory = fxAccount.PrivateKey;
        });

        Assert.Equal(ResponseCode.Success, receipt.Status);
        Assert.Equal(expectedCirculation, receipt.Circulation);

        var info = await fxAsset.Client.GetTokenInfoAsync(fxAsset);

        Assert.Equal(expectedCirculation, info.Circulation);
    }
Example #8
0
    public async Task CanConfiscateASingleAsset()
    {
        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.Record.Token, 1), fxAccount, fxAsset.ConfiscatePrivateKey);

        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 ContinueAssetRequiresSuspendKeyToSignTransaction()
    {
        await using var fxAccount = await TestAccount.CreateAsync(_network);

        await using var fxAsset = await TestAsset.CreateAsync(_network, fx =>
        {
            fx.Params.GrantKycEndorsement = null;
        }, fxAccount);

        await fxAsset.Client.PauseTokenAsync(fxAsset.Record.Token, fxAsset.PausePrivateKey);

        var circulation = fxAsset.Metadata.Length;
        var xferAmount  = circulation / 3;

        await AssertHg.AssetPausedAsync(fxAsset, TokenTradableStatus.Suspended);

        var tex = await Assert.ThrowsAsync <TransactionException>(async() =>
        {
            await fxAsset.Client.ContinueTokenAsync(fxAsset.Record.Token, fxAccount);
        });

        Assert.Equal(ResponseCode.InvalidSignature, tex.Status);
        Assert.Equal(ResponseCode.InvalidSignature, tex.Receipt.Status);
        Assert.StartsWith("Unable to Continue Token, status: InvalidSignature", tex.Message);

        tex = await Assert.ThrowsAsync <TransactionException>(async() =>
        {
            await fxAsset.Client.TransferAssetAsync(new Asset(fxAsset, 1), fxAsset.TreasuryAccount, fxAccount, fxAsset.TreasuryAccount);
        });

        Assert.Equal(ResponseCode.TokenIsPaused, tex.Status);
        Assert.Equal(ResponseCode.TokenIsPaused, tex.Receipt.Status);
        Assert.StartsWith("Unable to execute transfers, status: TokenIsPaused", tex.Message);
    }
Example #10
0
    public async Task MintAssetRecordIncludesAssetTransfers()
    {
        await using var fxAsset = await TestAsset.CreateAsync(_network, fx => fx.Metadata = null);

        var metadata = Enumerable.Range(1, Generator.Integer(2, 10)).Select(_ => Generator.SHA384Hash()).ToArray();
        var record   = await fxAsset.Client.MintAssetWithRecordAsync(fxAsset.Record.Token, metadata, fxAsset.SupplyPrivateKey);

        Assert.Equal(metadata.Length, record.SerialNumbers.Count);
        Assert.Empty(record.TokenTransfers);
        Assert.Equal(metadata.Length, record.AssetTransfers.Count);
        Assert.Empty(record.Royalties);
        Assert.Empty(record.Associations);

        for (var i = 0; i < metadata.Length; i++)
        {
            var ssn  = record.SerialNumbers[i];
            var xfer = record.AssetTransfers.FirstOrDefault(x => x.Asset.SerialNum == ssn);
            Assert.NotNull(xfer);
            Assert.Equal(fxAsset.Record.Token, xfer.Asset);
            Assert.Equal(Address.None, xfer.From);
            Assert.Equal(fxAsset.TreasuryAccount.Record.Address, xfer.To);
        }
        Assert.Equal((ulong)metadata.Length, await fxAsset.Client.GetAccountTokenBalanceAsync(fxAsset.TreasuryAccount, fxAsset));
        Assert.Equal((ulong)metadata.Length, (await fxAsset.Client.GetTokenInfoAsync(fxAsset)).Circulation);
    }
Example #11
0
    public async Task CanConfiscateAssetCoins()
    {
        await using var fxAccount = await TestAccount.CreateAsync(_network);

        await using var fxAsset = await TestAsset.CreateAsync(_network, fx => fx.Params.GrantKycEndorsement = null, fxAccount);

        var circulation               = (ulong)fxAsset.Metadata.Length;
        var xferAmount                = circulation / (ulong)Generator.Integer(3, 5) + 1;
        var expectedTreasury          = (ulong)fxAsset.Metadata.Length - xferAmount;
        var serialNumbersToConfiscate = Enumerable.Range(1, (int)xferAmount).Select(i => (long)i);

        await fxAsset.Client.TransferAsync(new TransferParams
        {
            AssetTransfers = serialNumbersToConfiscate.Select(sn => new AssetTransfer(new Asset(fxAsset.Record.Token, sn), fxAsset.TreasuryAccount, fxAccount)),
            Signatory      = fxAsset.TreasuryAccount
        });

        Assert.Equal(xferAmount, await fxAccount.Client.GetAccountTokenBalanceAsync(fxAccount, fxAsset));
        Assert.Equal(expectedTreasury, await fxAccount.Client.GetAccountTokenBalanceAsync(fxAsset.TreasuryAccount, fxAsset));
        Assert.Equal(circulation, (await fxAsset.Client.GetTokenInfoAsync(fxAsset)).Circulation);

        var receipt = await fxAsset.Client.ConfiscateAssetsAsync(fxAsset.Record.Token, serialNumbersToConfiscate, fxAccount, fxAsset.ConfiscatePrivateKey);

        Assert.Equal(ResponseCode.Success, receipt.Status);
        Assert.Equal(expectedTreasury, receipt.Circulation);

        Assert.Equal(0ul, await fxAccount.Client.GetAccountTokenBalanceAsync(fxAccount, fxAsset));
        Assert.Equal(expectedTreasury, await fxAccount.Client.GetAccountTokenBalanceAsync(fxAsset.TreasuryAccount, fxAsset));
        Assert.Equal(expectedTreasury, (await fxAsset.Client.GetTokenInfoAsync(fxAsset)).Circulation);
    }
Example #12
0
    public async Task CanPauseAssetTrading()
    {
        await using var fxAccount = await TestAccount.CreateAsync(_network);

        await using var fxAsset = await TestAsset.CreateAsync(_network, fx =>
        {
            fx.Params.GrantKycEndorsement = null;
        }, fxAccount);

        await AssertHg.AssetPausedAsync(fxAsset, TokenTradableStatus.Tradable);

        await fxAsset.Client.PauseTokenAsync(fxAsset.Record.Token, fxAsset.PausePrivateKey);

        await AssertHg.AssetPausedAsync(fxAsset, 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.TokenIsPaused, tex.Status);
        Assert.Equal(ResponseCode.TokenIsPaused, tex.Receipt.Status);
        Assert.StartsWith("Unable to execute transfers, status: TokenIsPaused", tex.Message);

        await AssertHg.AssetPausedAsync(fxAsset, TokenTradableStatus.Suspended);
    }
    async Task MetadataAndSerialNumbersTransferProperly()
    {
        await using var fxAccount = await TestAccount.CreateAsync(_network);

        await using var fxAsset = await TestAsset.CreateAsync(_network, fx => fx.Params.GrantKycEndorsement = null, fxAccount);

        var circulation      = (ulong)fxAsset.Metadata.Length;
        var serialNumbers    = Enumerable.Range(1, fxAsset.Metadata.Length).Where(i => i % 2 == 0).Select(i => (long)i).ToArray();
        var xferCount        = (ulong)serialNumbers.Length;
        var expectedTreasury = circulation - xferCount;

        var transfers = new TransferParams
        {
            AssetTransfers = serialNumbers.Select(sn => new AssetTransfer(new Asset(fxAsset, sn), fxAsset.TreasuryAccount, fxAccount)),
            Signatory      = fxAsset.TreasuryAccount.PrivateKey
        };
        var receipt = await fxAsset.Client.TransferAsync(transfers);

        // Double check balances.
        Assert.Equal(xferCount, await fxAccount.Client.GetAccountTokenBalanceAsync(fxAccount, fxAsset));
        Assert.Equal(circulation - xferCount, await fxAccount.Client.GetAccountTokenBalanceAsync(fxAsset.TreasuryAccount, fxAsset));

        // Double Check Metadata
        for (long sn = 1; sn <= (long)circulation; sn++)
        {
            var id    = new Asset(fxAsset.Record.Token, sn);
            var asset = await fxAccount.Client.GetAssetInfoAsync(id);

            Assert.Equal(sn, asset.Asset.SerialNum);
            Assert.Equal(fxAsset.Record.Token, asset.Asset);
            Assert.Equal(asset.Asset.SerialNum % 2 == 0 ? fxAccount.Record.Address : fxAsset.TreasuryAccount.Record.Address, asset.Owner);
            Assert.True(fxAsset.Metadata[sn - 1].Span.SequenceEqual(asset.Metadata.Span));
        }
    }
    public async Task CanTransferAssetsToContract()
    {
        await using var fxContract = await GreetingContract.CreateAsync(_network);

        await using var fxAsset = await TestAsset.CreateAsync(_network, fx =>
        {
            fx.Params.GrantKycEndorsement = null;
            fx.Params.InitializeSuspended = false;
        });

        await fxContract.Client.AssociateTokenAsync(fxAsset.Record.Token, fxContract.ContractRecord.Contract, fxContract.PrivateKey);

        var asset = new Asset(fxAsset, 1);

        var receipt = await fxAsset.Client.TransferAssetAsync(asset, fxAsset.TreasuryAccount, fxContract.ContractRecord.Contract, fxAsset.TreasuryAccount);

        Assert.Equal(ResponseCode.Success, receipt.Status);

        var info = await fxContract.Client.GetContractInfoAsync(fxContract);

        var association = info.Tokens.FirstOrDefault(t => t.Token == fxAsset.Record.Token);

        Assert.NotNull(association);
        Assert.Equal(fxAsset.Record.Token, association.Token);
        Assert.Equal(fxAsset.Params.Symbol, association.Symbol);
        Assert.Equal(1U, association.Balance);
        Assert.Equal(0U, association.Decimals);
        Assert.Equal(TokenKycStatus.NotApplicable, association.KycStatus);
        Assert.Equal(TokenTradableStatus.Tradable, association.TradableStatus);
        Assert.False(association.AutoAssociated);
    }
    public async Task CanSuspendAssetTradingFromAnyAccountWithSuspendKey()
    {
        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;
            fx.Params.InitializeSuspended = false;
        }, fxAccount);

        await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenTradableStatus.Tradable);

        await fxAsset.Client.SuspendTokenAsync(fxAsset.Record.Token, fxAccount, fxAsset.SuspendPrivateKey, ctx =>
        {
            ctx.Payer     = fxOther.Record.Address;
            ctx.Signatory = fxOther.PrivateKey;
        });

        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 CanNotContinueAssetWhenPauseNotEnabled()
    {
        await using var fxAccount = await TestAccount.CreateAsync(_network);

        await using var fxAsset = await TestAsset.CreateAsync(_network, fx =>
        {
            fx.Params.GrantKycEndorsement = null;
            fx.Params.PauseEndorsement    = null;
        }, fxAccount);

        var circulation = fxAsset.Metadata.Length;
        var xferAmount  = circulation / 3;

        await AssertHg.AssetPausedAsync(fxAsset, TokenTradableStatus.NotApplicable);

        var tex = await Assert.ThrowsAsync <TransactionException>(async() =>
        {
            await fxAsset.Client.ContinueTokenAsync(fxAsset.Record.Token, fxAsset.PausePrivateKey);
        });

        Assert.Equal(ResponseCode.TokenHasNoPauseKey, tex.Status);
        Assert.Equal(ResponseCode.TokenHasNoPauseKey, tex.Receipt.Status);
        Assert.StartsWith("Unable to Continue Token, status: TokenHasNoPauseKey", tex.Message);

        await fxAsset.Client.TransferAssetAsync(new Asset(fxAsset, 1), fxAsset.TreasuryAccount, fxAccount, fxAsset.TreasuryAccount);

        await AssertHg.AssetPausedAsync(fxAsset, TokenTradableStatus.NotApplicable);
    }
    public async Task CanSuspendAResumedAccount()
    {
        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);

        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.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 #18
0
    public async Task CanReumeAssetCoinTradingFromAnyAccountWithSuspendKey()
    {
        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 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);

        await fxAsset.Client.ResumeTokenAsync(fxAsset.Record.Token, fxAccount, fxAsset.SuspendPrivateKey, ctx =>
        {
            ctx.Payer     = fxOther.Record.Address;
            ctx.Signatory = fxOther.PrivateKey;
        });

        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 CanNotScheduleSuspendAssetTrading()
    {
        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, fx =>
        {
            fx.Params.GrantKycEndorsement = null;
            fx.Params.InitializeSuspended = false;
        }, fxAccount);

        await AssertHg.AssetStatusAsync(fxAsset, fxAccount, TokenTradableStatus.Tradable);

        var tex = await Assert.ThrowsAsync <TransactionException>(async() =>
        {
            await fxAsset.Client.SuspendTokenAsync(
                fxAsset.Record.Token,
                fxAccount,
                new Signatory(
                    fxAsset.SuspendPrivateKey,
                    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 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);
    }
Example #21
0
    public async Task BurnAssetRecordIncludesAssetTransfers()
    {
        await using var fxAsset = await TestAsset.CreateAsync(_network);

        var amountToDestroy     = fxAsset.Metadata.Length / 3 + 1;
        var expectedCirculation = (ulong)(fxAsset.Metadata.Length - amountToDestroy);
        var serialNumbers       = Enumerable.Range(1, amountToDestroy).Select(i => (long)i);

        var record = await fxAsset.Client.BurnAssetsWithRecordAsync(fxAsset, serialNumbers, fxAsset.SupplyPrivateKey);

        Assert.Empty(record.TokenTransfers);
        Assert.Equal(amountToDestroy, record.AssetTransfers.Count);
        Assert.Empty(record.Royalties);
        Assert.Empty(record.Associations);
        Assert.Equal(expectedCirculation, record.Circulation);

        for (int ssn = 1; ssn <= amountToDestroy; ssn++)
        {
            var asset = new Asset(fxAsset.Record.Token, ssn);
            var xfer  = record.AssetTransfers.FirstOrDefault(x => x.Asset == asset);
            Assert.NotNull(xfer);
            Assert.Equal(fxAsset.TreasuryAccount.Record.Address, xfer.From);
            Assert.Equal(Address.None, xfer.To);
        }
        Assert.Equal(expectedCirculation, await fxAsset.Client.GetAccountTokenBalanceAsync(fxAsset.TreasuryAccount, fxAsset));
        Assert.Equal(expectedCirculation, (await fxAsset.Client.GetTokenInfoAsync(fxAsset)).Circulation);
    }
Example #22
0
    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);
    }
Example #23
0
    public async Task DeletingAssetPreventsAssetTransfers()
    {
        await using var fxAccount = await TestAccount.CreateAsync(_network);

        await using var fxAsset = await TestAsset.CreateAsync(_network, fx => fx.Params.GrantKycEndorsement = null, fxAccount);

        var transferParams = new TransferParams
        {
            AssetTransfers = new AssetTransfer[] { new AssetTransfer(new Asset(fxAsset.Record.Token, 1), fxAsset.TreasuryAccount, fxAccount) },
            Signatory      = fxAsset.TreasuryAccount
        };

        await fxAsset.Client.TransferAsync(transferParams);

        var record = await fxAccount.Client.DeleteTokenAsync(fxAsset.Record.Token, fxAsset.AdminPrivateKey);

        Assert.Equal(ResponseCode.Success, record.Status);

        transferParams = new TransferParams
        {
            AssetTransfers = new AssetTransfer[] { new AssetTransfer(new Asset(fxAsset.Record.Token, 2), fxAsset.TreasuryAccount, fxAccount) },
            Signatory      = fxAsset.TreasuryAccount
        };

        var tex = await Assert.ThrowsAsync <TransactionException>(async() =>
        {
            await fxAsset.Client.TransferAsync(transferParams);
        });

        Assert.Equal(ResponseCode.TokenWasDeleted, tex.Status);
        Assert.Equal(ResponseCode.TokenWasDeleted, tex.Receipt.Status);
        Assert.StartsWith("Unable to execute transfers, status: TokenWasDeleted", tex.Message);
    }
Example #24
0
    public async Task CanReumeAssetCoinTradingAndGetRecordNoExtraSignatory()
    {
        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 record = await fxAsset.Client.ResumeTokenWithRecordAsync(fxAsset.Record.Token, fxAccount, ctx => ctx.Signatory = new Signatory(_network.Signatory, fxAsset.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.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);
    }
Example #25
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 #26
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 #27
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);
    }
Example #28
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);
    }
    public async Task CanGetAssetTokenInfo()
    {
        await using var fx = await TestAsset.CreateAsync(_network);

        Assert.Equal(ResponseCode.Success, fx.Record.Status);

        var info = await fx.Client.GetTokenInfoAsync(fx.Record.Token);

        Assert.Equal(fx.Record.Token, info.Token);
        Assert.Equal(fx.Params.Symbol, info.Symbol);
        Assert.Equal(fx.TreasuryAccount.Record.Address, info.Treasury);
        Assert.Equal((ulong)fx.Metadata.Length, info.Circulation);
        Assert.Equal(0u, info.Decimals);
        Assert.Equal(fx.Params.Ceiling, info.Ceiling);
        Assert.Equal(fx.Params.Administrator, info.Administrator);
        Assert.Equal(fx.Params.GrantKycEndorsement, info.GrantKycEndorsement);
        Assert.Equal(fx.Params.SuspendEndorsement, info.SuspendEndorsement);
        Assert.Equal(fx.Params.PauseEndorsement, info.PauseEndorsement);
        Assert.Equal(fx.Params.ConfiscateEndorsement, info.ConfiscateEndorsement);
        Assert.Equal(fx.Params.SupplyEndorsement, info.SupplyEndorsement);
        Assert.Equal(fx.Params.RoyaltiesEndorsement, info.RoyaltiesEndorsement);
        Assert.Equal(TokenTradableStatus.Tradable, info.TradableStatus);
        Assert.Equal(TokenTradableStatus.Tradable, info.PauseStatus);
        Assert.Equal(TokenKycStatus.Revoked, info.KycStatus);
        Assert.Empty(info.Royalties);
        Assert.Equal(TokenType.Asset, info.Type);
        Assert.False(info.Deleted);
    }
    public async Task CanExecuteMultiTransferAssets()
    {
        await using var fxAccount1 = await TestAccount.CreateAsync(_network);

        await using var fxAccount2 = await TestAccount.CreateAsync(_network);

        await using var fxAsset = await TestAsset.CreateAsync(_network, fx => fx.Params.GrantKycEndorsement = null, fxAccount1, fxAccount2);

        var transfers = new TransferParams
        {
            AssetTransfers = new AssetTransfer[]
            {
                new AssetTransfer(new Asset(fxAsset, 1), fxAsset.TreasuryAccount, fxAccount1),
                new AssetTransfer(new Asset(fxAsset, 2), fxAsset.TreasuryAccount, fxAccount2)
            },
            Signatory = fxAsset.TreasuryAccount.PrivateKey
        };
        var receipt = await fxAsset.Client.TransferAsync(transfers);

        Assert.Equal(ResponseCode.Success, receipt.Status);

        Assert.Equal(1UL, await fxAccount1.Client.GetAccountTokenBalanceAsync(fxAccount1, fxAsset));
        Assert.Equal(1UL, await fxAccount2.Client.GetAccountTokenBalanceAsync(fxAccount2, fxAsset));
        Assert.Equal((ulong)fxAsset.Metadata.Length - 2, await fxAsset.Client.GetAccountTokenBalanceAsync(fxAsset.TreasuryAccount, fxAsset));
    }