public async Task UpdatingToUsedNameIsAllowed() { await using var fxToken = await TestToken.CreateAsync(_network); await using var fxOther = await TestToken.CreateAsync(_network); var updateParams = new UpdateTokenParams { Token = fxToken.Record.Token, Name = fxOther.Params.Name, Signatory = fxToken.AdminPrivateKey }; await fxToken.Client.UpdateTokenAsync(updateParams); var info = await fxToken.Client.GetTokenInfoAsync(fxToken.Record.Token); Assert.Equal(fxToken.Record.Token, info.Token); Assert.Equal(fxToken.Params.Symbol, info.Symbol); Assert.Equal(fxOther.Params.Name, info.Name); Assert.Equal(fxToken.TreasuryAccount.Record.Address, info.Treasury); Assert.Equal(fxToken.Params.Circulation, info.Circulation); Assert.Equal(fxToken.Params.Decimals, info.Decimals); Assert.Equal(fxToken.Params.Administrator, info.Administrator); Assert.Equal(fxToken.Params.GrantKycEndorsement, info.GrantKycEndorsement); Assert.Equal(fxToken.Params.SuspendEndorsement, info.SuspendEndorsement); Assert.Equal(fxToken.Params.ConfiscateEndorsement, info.ConfiscateEndorsement); Assert.Equal(fxToken.Params.SupplyEndorsement, info.SupplyEndorsement); Assert.Equal(TokenTradableStatus.Tradable, info.TradableStatus); Assert.Equal(TokenKycStatus.Revoked, info.KycStatus); Assert.False(info.Deleted); }
public async Task AnyAccountWithAdminKeyCanUpdate() { await using var fxAccount = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.InitialBalance = 120_00_000_000); await using var fxToken = await TestToken.CreateAsync(_network); var newName = Generator.String(30, 50); var updateParams = new UpdateTokenParams { Token = fxToken.Record.Token, Name = newName, Signatory = fxToken.AdminPrivateKey }; var receipt = await fxToken.Client.UpdateTokenAsync(updateParams, ctx => { ctx.Payer = fxAccount.Record.Address; ctx.Signatory = fxAccount.PrivateKey; }); Assert.Equal(ResponseCode.Success, receipt.Status); var info = await fxToken.Client.GetTokenInfoAsync(fxToken.Record.Token); Assert.Equal(newName, info.Name); }
public async Task UpdatesRequireAdminKey() { await using var fxToken = await TestToken.CreateAsync(_network); var updateParams = new UpdateTokenParams { Token = fxToken.Record.Token, Name = Generator.String(30, 50) }; var tex = await Assert.ThrowsAsync <TransactionException>(async() => { await fxToken.Client.UpdateTokenAsync(updateParams); }); Assert.Equal(ResponseCode.InvalidSignature, tex.Status); Assert.StartsWith("Unable to update Token, status: InvalidSignature", tex.Message); var info = await fxToken.Client.GetTokenInfoAsync(fxToken.Record.Token); Assert.Equal(fxToken.Record.Token, info.Token); Assert.Equal(fxToken.Params.Symbol, info.Symbol); Assert.Equal(fxToken.Params.Name, info.Name); Assert.Equal(fxToken.TreasuryAccount.Record.Address, info.Treasury); Assert.Equal(fxToken.Params.Circulation, info.Circulation); Assert.Equal(fxToken.Params.Decimals, info.Decimals); Assert.Equal(fxToken.Params.Administrator, info.Administrator); Assert.Equal(fxToken.Params.GrantKycEndorsement, info.GrantKycEndorsement); Assert.Equal(fxToken.Params.SuspendEndorsement, info.SuspendEndorsement); Assert.Equal(fxToken.Params.ConfiscateEndorsement, info.ConfiscateEndorsement); Assert.Equal(fxToken.Params.SupplyEndorsement, info.SupplyEndorsement); Assert.Equal(TokenTradableStatus.Tradable, info.TradableStatus); Assert.Equal(TokenKycStatus.Revoked, info.KycStatus); Assert.False(info.Deleted); }
public async Task CanUpdateTreasuryToContract() { await using var fxContract = await GreetingContract.CreateAsync(_network); await using var fxToken = await TestToken.CreateAsync(_network); // Note: Contract did not need to sign. await fxContract.Client.AssociateTokenAsync(fxToken, fxContract, fxContract.PrivateKey); var updateParams = new UpdateTokenParams { Token = fxToken.Record.Token, Treasury = fxContract.ContractRecord.Contract, Signatory = new Signatory(fxToken.AdminPrivateKey, fxContract.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(fxContract.ContractRecord.Contract, info.Treasury); Assert.Equal(fxToken.Params.Circulation, await fxToken.Client.GetContractTokenBalanceAsync(fxContract, fxToken)); }
public async Task CanUpdateTokenAndGetRecord() { await using var fxToken = await TestToken.CreateAsync(_network); await using var fxTemplate = await TestToken.CreateAsync(_network); // It looks like changing the treasury requires the receiving account to be // associated first, since it still has to sign the update transaction anyway, // this seems unecessary. await fxTemplate.TreasuryAccount.Client.AssociateTokenAsync(fxToken, fxTemplate.TreasuryAccount, fxTemplate.TreasuryAccount); var newSymbol = Generator.UppercaseAlphaCode(20); var newName = Generator.String(20, 50); var updateParams = new UpdateTokenParams { Token = fxToken.Record.Token, Treasury = fxTemplate.Params.Treasury, Administrator = fxTemplate.Params.Administrator, GrantKycEndorsement = fxTemplate.Params.GrantKycEndorsement, SuspendEndorsement = fxTemplate.Params.SuspendEndorsement, ConfiscateEndorsement = fxTemplate.Params.ConfiscateEndorsement, SupplyEndorsement = fxTemplate.Params.SupplyEndorsement, Symbol = newSymbol, Name = newName, Expiration = DateTime.UtcNow.AddDays(90), RenewPeriod = fxTemplate.Params.RenewPeriod, RenewAccount = fxTemplate.RenewAccount, Signatory = new Signatory(fxToken.Params.Signatory, fxTemplate.Params.Signatory) }; var record = await fxToken.Client.UpdateTokenWithRecordAsync(updateParams); 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 fxToken.Client.GetTokenInfoAsync(fxToken.Record.Token); Assert.Equal(fxToken.Record.Token, info.Token); Assert.Equal(newSymbol, info.Symbol); Assert.Equal(newName, info.Name); Assert.Equal(fxTemplate.TreasuryAccount.Record.Address, info.Treasury); Assert.Equal(fxToken.Params.Circulation, info.Circulation); Assert.Equal(fxToken.Params.Decimals, info.Decimals); Assert.Equal(fxTemplate.Params.Administrator, info.Administrator); Assert.Equal(fxTemplate.Params.GrantKycEndorsement, info.GrantKycEndorsement); Assert.Equal(fxTemplate.Params.SuspendEndorsement, info.SuspendEndorsement); Assert.Equal(fxTemplate.Params.ConfiscateEndorsement, info.ConfiscateEndorsement); Assert.Equal(fxTemplate.Params.SupplyEndorsement, info.SupplyEndorsement); Assert.Equal(TokenTradableStatus.Tradable, info.TradableStatus); Assert.Equal(TokenKycStatus.Revoked, info.KycStatus); Assert.False(info.Deleted); }
public async Task CanUpdateToken() { await using var fxToken = await TestToken.CreateAsync(_network); await using var fxTemplate = await TestToken.CreateAsync(_network); await fxTemplate.TreasuryAccount.Client.AssociateTokenAsync(fxToken, fxTemplate.TreasuryAccount, fxTemplate.TreasuryAccount); var newSymbol = Generator.UppercaseAlphaCode(20); var newName = Generator.String(20, 50); var updateParams = new UpdateTokenParams { Token = fxToken.Record.Token, Treasury = fxTemplate.Params.Treasury, Administrator = fxTemplate.Params.Administrator, GrantKycEndorsement = fxTemplate.Params.GrantKycEndorsement, SuspendEndorsement = fxTemplate.Params.SuspendEndorsement, ConfiscateEndorsement = fxTemplate.Params.ConfiscateEndorsement, SupplyEndorsement = fxTemplate.Params.SupplyEndorsement, Symbol = newSymbol, Name = newName, Expiration = DateTime.UtcNow.AddDays(90), RenewPeriod = fxTemplate.Params.RenewPeriod, RenewAccount = fxTemplate.RenewAccount, Signatory = new Signatory(fxToken.Params.Signatory, fxTemplate.Params.Signatory), Memo = fxTemplate.Params.Memo }; var receipt = await fxToken.Client.UpdateTokenAsync(updateParams); Assert.Equal(ResponseCode.Success, receipt.Status); var info = await fxToken.Client.GetTokenInfoAsync(fxToken.Record.Token); Assert.Equal(fxToken.Record.Token, info.Token); Assert.Equal(newSymbol, info.Symbol); Assert.Equal(newName, info.Name); Assert.Equal(fxTemplate.TreasuryAccount.Record.Address, info.Treasury); Assert.Equal(fxToken.Params.Circulation, info.Circulation); Assert.Equal(fxToken.Params.Decimals, info.Decimals); Assert.Equal(fxTemplate.Params.Administrator, info.Administrator); Assert.Equal(fxTemplate.Params.GrantKycEndorsement, info.GrantKycEndorsement); Assert.Equal(fxTemplate.Params.SuspendEndorsement, info.SuspendEndorsement); Assert.Equal(fxTemplate.Params.ConfiscateEndorsement, info.ConfiscateEndorsement); Assert.Equal(fxTemplate.Params.SupplyEndorsement, info.SupplyEndorsement); Assert.Equal(TokenTradableStatus.Tradable, info.TradableStatus); Assert.Equal(TokenKycStatus.Revoked, info.KycStatus); Assert.Equal(fxTemplate.Params.Memo, info.Memo); Assert.False(info.Deleted); }
protected async Task HandleValidSubmit() { _output = null; await _network.ExecuteAsync(_input.Gateway, _input.Payer, async client => { var updateParams = new UpdateTokenParams { Token = _input.Token }; if (_input.UpdateTreasury) { updateParams.Treasury = _input.Treasury ?? Address.None; } if (_input.UpdateAdministrator) { updateParams.Administrator = _input.Administrator ?? Endorsement.None; } if (_input.UpdateGrantKycEndorsement) { updateParams.GrantKycEndorsement = _input.GrantKycEndorsement ?? Endorsement.None; } if (_input.UpdateSuspendEndorsement) { updateParams.SuspendEndorsement = _input.SuspendEndorsement ?? Endorsement.None; } if (_input.UpdateConfiscateEndorsement) { updateParams.ConfiscateEndorsement = _input.ConfiscateEndorsement ?? Endorsement.None; } if (_input.UpdateSupplyEndorsement) { updateParams.SupplyEndorsement = _input.SupplyEndorsement ?? Endorsement.None; } if (_input.UpdateSymbol) { updateParams.Symbol = _input.Symbol?.Trim(); } if (_input.UpdateName) { updateParams.Name = _input.Name?.Trim(); } if (_input.UpdateRenewAccount) { var isAdding = _input.RenewAccount == null; updateParams.RenewAccount = isAdding ? Address.None : _input.RenewAccount; updateParams.RenewPeriod = TimeSpan.FromDays(90); } _output = await client.UpdateTokenAsync(updateParams, ctx => ctx.Memo = _input.Memo?.Trim()); }); }
public async Task EmptyUpdateParametersRaisesError() { await using var fxToken = await TestToken.CreateAsync(_network); var updateParams = new UpdateTokenParams { Token = fxToken.Record.Token, Signatory = fxToken.Params.Signatory }; var ae = await Assert.ThrowsAsync <ArgumentException>(async() => { await fxToken.Client.UpdateTokenAsync(updateParams); }); Assert.Equal("updateParameters", ae.ParamName); Assert.StartsWith("The Topic Updates contain no update properties, it is blank.", ae.Message); }
public async Task CanUpdateMemoToEmpty() { await using var fxToken = await TestToken.CreateAsync(_network); var updateParams = new UpdateTokenParams { Token = fxToken.Record.Token, Memo = string.Empty, Signatory = fxToken.AdminPrivateKey }; var receipt = await fxToken.Client.UpdateTokenAsync(updateParams); Assert.Equal(ResponseCode.Success, receipt.Status); var info = await fxToken.Client.GetTokenInfoAsync(fxToken.Record.Token); Assert.Empty(info.Memo); }
public async Task UpdatingTheTreasuryWithoutSigningWithoutAdminKeyRaisesError() { 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 = fxAccount.PrivateKey }; var tex = await Assert.ThrowsAsync <TransactionException>(async() => { await fxToken.Client.UpdateTokenAsync(updateParams); }); Assert.Equal(ResponseCode.InvalidSignature, tex.Status); Assert.StartsWith("Unable to update Token, status: InvalidSignature", tex.Message); var info = await fxToken.Client.GetTokenInfoAsync(fxToken.Record.Token); Assert.Equal(fxToken.Record.Token, info.Token); Assert.Equal(fxToken.Params.Symbol, info.Symbol); Assert.Equal(fxToken.Params.Name, info.Name); Assert.Equal(fxToken.TreasuryAccount.Record.Address, info.Treasury); Assert.Equal(fxToken.Params.Circulation, info.Circulation); Assert.Equal(fxToken.Params.Decimals, info.Decimals); Assert.Equal(fxToken.Params.Administrator, info.Administrator); Assert.Equal(fxToken.Params.GrantKycEndorsement, info.GrantKycEndorsement); Assert.Equal(fxToken.Params.SuspendEndorsement, info.SuspendEndorsement); Assert.Equal(fxToken.Params.ConfiscateEndorsement, info.ConfiscateEndorsement); Assert.Equal(fxToken.Params.SupplyEndorsement, info.SupplyEndorsement); Assert.Equal(TokenTradableStatus.Tradable, info.TradableStatus); Assert.Equal(TokenKycStatus.Revoked, info.KycStatus); Assert.False(info.Deleted); Assert.Equal(fxToken.Params.Memo, info.Memo); Assert.Equal(fxToken.Params.Circulation, await fxToken.Client.GetAccountTokenBalanceAsync(fxToken.TreasuryAccount, fxToken)); Assert.Equal(0UL, await fxToken.Client.GetAccountTokenBalanceAsync(fxAccount, fxToken)); }
public async Task CannotUpdateImutableToken() { var(newPublicKey, newPrivateKey) = Generator.KeyPair(); await using var fxToken = await TestToken.CreateAsync(_network, fx => fx.Params.Administrator = null); var updateParams = new UpdateTokenParams { Token = fxToken.Record.Token, SupplyEndorsement = newPublicKey, Signatory = fxToken.AdminPrivateKey }; var tex = await Assert.ThrowsAsync <TransactionException>(async() => { await fxToken.Client.UpdateTokenAsync(updateParams); }); Assert.Equal(ResponseCode.TokenIsImmutable, tex.Status); Assert.StartsWith("Unable to update Token, status: TokenIsImmutable", tex.Message); }
public async Task CanUpdateSupplyEndorsement() { var(newPublicKey, newPrivateKey) = Generator.KeyPair(); await using var fxToken = await TestToken.CreateAsync(_network); var updateParams = new UpdateTokenParams { Token = fxToken.Record.Token, SupplyEndorsement = newPublicKey, Signatory = fxToken.AdminPrivateKey }; var receipt = await fxToken.Client.UpdateTokenAsync(updateParams); Assert.Equal(ResponseCode.Success, receipt.Status); var info = await fxToken.Client.GetTokenInfoAsync(fxToken.Record.Token); Assert.Equal(updateParams.SupplyEndorsement, info.SupplyEndorsement); }
public async Task CanUpdateRenewPeriod() { await using var fxToken = await TestToken.CreateAsync(_network); var newRenwew = TimeSpan.FromDays(89); var updateParams = new UpdateTokenParams { Token = fxToken.Record.Token, RenewPeriod = newRenwew, Signatory = fxToken.AdminPrivateKey }; var receipt = await fxToken.Client.UpdateTokenAsync(updateParams); Assert.Equal(ResponseCode.Success, receipt.Status); var info = await fxToken.Client.GetTokenInfoAsync(fxToken.Record.Token); Assert.Equal(newRenwew, info.RenewPeriod); }
public async Task CanUpdateExpiration() { await using var fxToken = await TestToken.CreateAsync(_network); var newExpiration = Generator.TruncateToSeconds(DateTime.UtcNow.AddDays(90)); var updateParams = new UpdateTokenParams { Token = fxToken.Record.Token, Expiration = newExpiration, Signatory = fxToken.AdminPrivateKey }; var receipt = await fxToken.Client.UpdateTokenAsync(updateParams); Assert.Equal(ResponseCode.Success, receipt.Status); var info = await fxToken.Client.GetTokenInfoAsync(fxToken.Record.Token); Assert.Equal(newExpiration, info.Expiration); }
public async Task CanUpdateSymbol() { await using var fxToken = await TestToken.CreateAsync(_network); var newSymbol = Generator.UppercaseAlphaCode(20); var updateParams = new UpdateTokenParams { Token = fxToken.Record.Token, Symbol = newSymbol, Signatory = fxToken.AdminPrivateKey }; var receipt = await fxToken.Client.UpdateTokenAsync(updateParams); Assert.Equal(ResponseCode.Success, receipt.Status); var info = await fxToken.Client.GetTokenInfoAsync(fxToken.Record.Token); Assert.Equal(newSymbol, info.Symbol); }
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 CanUpdateName() { await using var fxToken = await TestToken.CreateAsync(_network); var newName = Generator.String(30, 50); var updateParams = new UpdateTokenParams { Token = fxToken.Record.Token, Name = newName, Signatory = fxToken.AdminPrivateKey }; var receipt = await fxToken.Client.UpdateTokenAsync(updateParams); Assert.Equal(ResponseCode.Success, receipt.Status); var info = await fxToken.Client.GetTokenInfoAsync(fxToken.Record.Token); Assert.Equal(newName, info.Name); }
public async Task CannotRemoveSupplyEndorsement() { await using var fxToken = await TestToken.CreateAsync(_network); var updateParams = new UpdateTokenParams { Token = fxToken.Record.Token, SupplyEndorsement = Endorsement.None, Signatory = fxToken.AdminPrivateKey }; var pex = await Assert.ThrowsAsync <PrecheckException>(async() => { await fxToken.Client.UpdateTokenAsync(updateParams); }); Assert.Equal(ResponseCode.InvalidSupplyKey, pex.Status); Assert.StartsWith("Transaction Failed Pre-Check: InvalidSupplyKey", pex.Message); var info = await fxToken.Client.GetTokenInfoAsync(fxToken.Record.Token); Assert.Equal(fxToken.Record.Token, info.Token); Assert.Equal(fxToken.Params.Symbol, info.Symbol); Assert.Equal(fxToken.Params.Name, info.Name); Assert.Equal(fxToken.TreasuryAccount.Record.Address, info.Treasury); Assert.Equal(fxToken.Params.Circulation, info.Circulation); Assert.Equal(fxToken.Params.Decimals, info.Decimals); Assert.Equal(fxToken.Params.Administrator, info.Administrator); Assert.Equal(fxToken.Params.GrantKycEndorsement, info.GrantKycEndorsement); Assert.Equal(fxToken.Params.SuspendEndorsement, info.SuspendEndorsement); Assert.Equal(fxToken.Params.ConfiscateEndorsement, info.ConfiscateEndorsement); Assert.Equal(fxToken.Params.SupplyEndorsement, info.SupplyEndorsement); Assert.Equal(TokenTradableStatus.Tradable, info.TradableStatus); Assert.Equal(TokenKycStatus.Revoked, info.KycStatus); Assert.False(info.Deleted); Assert.Equal(fxToken.Params.Memo, info.Memo); }
/// <summary> /// Updates the changeable properties of a hedera network Token. /// </summary> /// <param name="updateParameters"> /// The Token update parameters, includes a required /// <see cref="Address"/> or <code>Symbol</code> reference to the Token /// to update plus a number of changeable properties of the Token. /// </param> /// <param name="configure"> /// Optional callback method providing an opportunity to modify /// the execution configuration for just this method call. /// It is executed prior to submitting the request to the network. /// </param> /// <returns> /// A transaction record containing the details of the results. /// of the request. /// </returns> /// <exception cref="ArgumentOutOfRangeException">If required arguments are missing.</exception> /// <exception cref="InvalidOperationException">If required context configuration is missing.</exception> /// <exception cref="PrecheckException">If the gateway node create rejected the request upon submission.</exception> /// <exception cref="ConsensusException">If the network was unable to come to consensus before the duration of the transaction expired.</exception> /// <exception cref="TransactionException">If the network rejected the create request as invalid or had missing data.</exception> public async Task <TransactionRecord> UpdateTokenWithRecordAsync(UpdateTokenParams updateParameters, Action <IContext>?configure = null) { return(new TransactionRecord(await ExecuteTransactionAsync(new TokenUpdateTransactionBody(updateParameters), configure, true, updateParameters.Signatory).ConfigureAwait(false))); }
internal static UpdateTokenParams UpdateParameters(UpdateTokenParams updateParameters) { if (updateParameters is null) { throw new ArgumentNullException(nameof(updateParameters), "Token Update Parameters argument is missing. Please check that it is not null."); } if (updateParameters.Token.IsNullOrNone()) { throw new ArgumentNullException(nameof(updateParameters.Token), "The Token is missing. Please check that it is not null or empty."); } if (updateParameters.Treasury is null && updateParameters.Administrator is null && updateParameters.GrantKycEndorsement is null && updateParameters.SuspendEndorsement is null && updateParameters.ConfiscateEndorsement is null && updateParameters.SupplyEndorsement is null && string.IsNullOrWhiteSpace(updateParameters.Symbol) && string.IsNullOrWhiteSpace(updateParameters.Name) && !updateParameters.Expiration.HasValue && !updateParameters.RenewPeriod.HasValue && updateParameters.RenewAccount is null) { throw new ArgumentException("The Topic Updates contain no update properties, it is blank.", nameof(updateParameters)); } if (!string.IsNullOrWhiteSpace(updateParameters.Symbol)) { if (updateParameters.Symbol.Trim().Length != updateParameters.Symbol.Length) { throw new ArgumentOutOfRangeException(nameof(updateParameters.Symbol), "The new token symbol cannot contain leading or trailing white space."); } if (updateParameters.Symbol.Length > 32) { throw new ArgumentOutOfRangeException(nameof(updateParameters.Symbol), "The new token symbol cannot exceed 32 characters in length."); } if (!updateParameters.Symbol.Equals(updateParameters.Symbol.ToUpperInvariant())) { throw new ArgumentOutOfRangeException(nameof(updateParameters.Symbol), "The new token symbol must contain upper case characters."); } } if (!string.IsNullOrWhiteSpace(updateParameters.Name)) { if (updateParameters.Name.Trim().Length != updateParameters.Name.Length) { throw new ArgumentOutOfRangeException(nameof(updateParameters.Name), "The new token name cannot contain leading or trailing white space."); } } if (updateParameters.Expiration.HasValue) { if (updateParameters.Expiration.Value < DateTime.UtcNow) { throw new ArgumentOutOfRangeException(nameof(updateParameters.Expiration), "The new expiration can not be set to the past."); } } if (updateParameters.RenewPeriod.HasValue) { if (updateParameters.RenewPeriod.Value.TotalSeconds < 1) { throw new ArgumentOutOfRangeException(nameof(updateParameters.RenewPeriod), "The renew period must be non negative."); } } return(updateParameters); }