public static TransactionExecutionEntity FromDomain(TransactionExecutionAggregate aggregate) { return(new TransactionExecutionEntity { TransactionId = aggregate.TransactionId, Address = aggregate.Address, ClaimedGas = aggregate.ClaimedGas, GasAssetId = aggregate.GasAssetId, LockRejectedAt = aggregate.LockRejectedAt, LockAcquiredAt = aggregate.LockAcquiredAt, BroadcastingBlock = aggregate.BroadcastingBlock, AllGas = aggregate.AllGas, LockReleasedAt = aggregate.LockReleasedAt, TransactionExecutedAt = aggregate.TransactionExecutedAt, AssetInfoRetrievedAt = aggregate.AssetInfoRetrievedAt, GasBlockchainAssetId = aggregate.GasBlockchainAssetId, GasBlockchainType = aggregate.GasBlockchainType, NeoAssetId = aggregate.NeoAssetId, NeoBlockchainAssetId = aggregate.NeoBlockchainAssetId, NeoBlockchainType = aggregate.NeoBlockchainType, TransactionBroadcastedAt = aggregate.TransactionBroadcastedAt, TransactionBuiltAt = aggregate.TransactionBuiltAt, ClaimableGasNotAvailableReportedAt = aggregate.ClaimableGasNotAvailableReportedAt, TransactionClearedAt = aggregate.TransactionClearedAt, TransactionHash = aggregate.TransactionHash, TransactionSignedAt = aggregate.TransactionSignedAt, ETag = aggregate.Version, PartitionKey = AggregateKeysBuilder.BuildPartitionKey(aggregate.TransactionId), RowKey = AggregateKeysBuilder.BuildRowKey() }); }
public void Throws_Exception_On_Unregistered_Event() { // Arrange var register = TransitionRegisterFactory.StartRegistrationFor <TransactionExecutionAggregate, TransactionExecutionState>(); register.GetCurrentStateWith(a => a.State); register.From(TransactionExecutionState.Started) .On <SourceAddressLockedEvent>() .HandleTransition((a, e) => a.OnSourceAddressLocked()); var core = register.Build(); var aggregate = TransactionExecutionAggregate.Start ( Guid.NewGuid(), Guid.NewGuid(), 0, "", new[] { new TransactionOutputValueType("", 0) }, "", "", "", false ); // Act / Assert Assert.Throws <UnexpectedEventException>(() => { core.Switch(aggregate, new TransactionBuiltEvent()); }); }
public TransactionExecutionAggregate ToDomain([CanBeNull] TransactionExecutionBlobEntity blobData) { return(TransactionExecutionAggregate.Restore( version: ETag, transactionId: TransactionId, address: Address, neoAssetId: NeoAssetId, gasAssetId: GasAssetId, neoBlockchainType: NeoBlockchainType, neoBlockchainAssetId: NeoBlockchainAssetId, gasBlockchainType: GasBlockchainType, gasBlockchainAssetId: GasBlockchainAssetId, unsignedTransactionContext: blobData?.UnsignedTransactionContext, claimedGas: ClaimedGas, allGas: AllGas, signedTransactionContext: blobData?.SignedTransactionContext, transactionHash: TransactionHash, broadcastingBlock: BroadcastingBlock, lockAcquiredAt: LockAcquiredAt, lockRejectedAt: LockRejectedAt, assetInfoRetrievedAt: AssetInfoRetrievedAt, transactionBuiltAt: TransactionBuiltAt, claimableGasNotAvailableReportedAt: ClaimableGasNotAvailableReportedAt, transactionSignedAt: TransactionSignedAt, transactionBroadcastedAt: TransactionBroadcastedAt, transactionExecutedAt: TransactionExecutedAt, transactionClearedAt: TransactionClearedAt, lockReleasedAt: LockReleasedAt)); }
private async Task Handle(TransactionExecutionStartedEvent evt, ICommandSender sender) { var aggregate = await _repository.GetOrAddAsync( evt.TransactionId, () => TransactionExecutionAggregate.Start( evt.OperationId, evt.TransactionId, evt.TransactionNumber, evt.FromAddress, evt.Outputs .Select(e => e.ToDomain()) .ToArray(), evt.BlockchainType, evt.BlockchainAssetId, evt.AssetId, evt.IncludeFee)); _chaosKitty.Meow(evt.TransactionId); if (aggregate.State == TransactionExecutionState.Started) { sender.SendCommand ( new LockSourceAddressCommand { OperationId = aggregate.OperationId, TransactionId = aggregate.TransactionId, BlockchainType = aggregate.BlockchainType, FromAddress = aggregate.FromAddress }, Self ); } }
public static TransactionExecutionBlobEntity FromDomain(TransactionExecutionAggregate aggregate) { return(new TransactionExecutionBlobEntity { TransactionContext = aggregate.Context, SignedTransaction = aggregate.SignedTransaction }); }
public Task SaveAsync(TransactionExecutionAggregate aggregate) { var blobEntity = TransactionExecutionBlobEntity.FromDomain(aggregate); return(Task.WhenAll ( SaveBlobEntityAsync(aggregate.TransactionId, blobEntity), _aggregateRepository.SaveAsync(aggregate) )); }
private async Task Handle(TransactionStartedtEvent evt, ICommandSender sender) { var aggregate = await _repository.GetOrAddAsync(evt.TransactionId, () => TransactionExecutionAggregate.StartNew(evt.TransactionId, evt.Address, evt.NeoAssetId, evt.GasAssetId)); _chaosKitty.Meow(aggregate.TransactionId); sender.SendCommand(new AcquireLockCommand { TransactionId = aggregate.TransactionId }, Self); }
public void Can_Ignore_Events() { // Arrange var register = TransitionRegisterFactory.StartRegistrationFor <TransactionExecutionAggregate, TransactionExecutionState>(); register.GetCurrentStateWith(a => a.State); register.From(TransactionExecutionState.Started) .On <SourceAddressLockedEvent>() .HandleTransition((a, e) => a.OnSourceAddressLocked()); register.In(TransactionExecutionState.Started) .Ignore <TransactionExecutionStartedEvent>(); register.In(TransactionExecutionState.SourceAddressLocked) .Ignore <TransactionExecutionStartedEvent>() .Ignore <SourceAddressLockedEvent>(); var core = register.Build(); var aggregate = TransactionExecutionAggregate.Start ( Guid.NewGuid(), Guid.NewGuid(), 0, "", new[] { new TransactionOutputValueType("", 0) }, "", "", "", false ); // Act var result1 = core.Switch(aggregate, new TransactionExecutionStartedEvent()); var result2 = core.Switch(aggregate, new SourceAddressLockedEvent()); var result3 = core.Switch(aggregate, new TransactionExecutionStartedEvent()); var result4 = core.Switch(aggregate, new SourceAddressLockedEvent()); // Assert Assert.False(result1); Assert.True(result2); Assert.False(result3); Assert.False(result4); }
public void Test_Execution_To_Failue_On_Waiting_For_Transaction_Ending() { // Arrange var switcher = TransitionExecutionStateSwitcherBuilder.Build(); var aggregate = TransactionExecutionAggregate.Start ( Guid.NewGuid(), Guid.NewGuid(), 0, "", new[] { new TransactionOutputValueType("", 0) }, "", "", "", false ); // Act / Assert Assert.Equal(TransactionExecutionState.Started, aggregate.State); Assert.True(switcher.Switch(aggregate, new SourceAddressLockedEvent())); Assert.Equal(TransactionExecutionState.SourceAddressLocked, aggregate.State); Assert.True(switcher.Switch(aggregate, new TransactionBuiltEvent())); Assert.Equal(TransactionExecutionState.Built, aggregate.State); Assert.True(switcher.Switch(aggregate, new TransactionSignedEvent())); Assert.Equal(TransactionExecutionState.Signed, aggregate.State); Assert.True(switcher.Switch(aggregate, new TransactionBroadcastedEvent())); Assert.Equal(TransactionExecutionState.Broadcasted, aggregate.State); Assert.True(switcher.Switch(aggregate, new SourceAddressLockReleasedEvent())); Assert.Equal(TransactionExecutionState.WaitingForEnding, aggregate.State); Assert.True(switcher.Switch(aggregate, new TransactionExecutionFailedEvent { ErrorCode = TransactionExecutionResult.UnknownError })); Assert.Equal(TransactionExecutionState.WaitingForEndingFailed, aggregate.State); Assert.True(switcher.Switch(aggregate, new BroadcastedTransactionClearedEvent())); Assert.Equal(TransactionExecutionState.Cleared, aggregate.State); }
// ReSharper restore MemberCanBePrivate.Global #endregion #region Conversion public static TransactionExecutionEntity FromDomain(TransactionExecutionAggregate aggregate) { return(new TransactionExecutionEntity { ETag = aggregate.Version, PartitionKey = AggregateKeysBuilder.BuildPartitionKey(aggregate.TransactionId), RowKey = AggregateKeysBuilder.BuildRowKey(aggregate.TransactionId), State = aggregate.State, Result = aggregate.Result, StartMoment = aggregate.StartMoment, SourceAddressLockingMoment = aggregate.SourceAddressLockingMoment, BuildingMoment = aggregate.BuildingMoment, SigningMoment = aggregate.SigningMoment, BroadcastingMoment = aggregate.BroadcastingMoment, FinishMoment = aggregate.FinishMoment, BuildingFailureMoment = aggregate.BuildingFailureMoment, BroadcastinFailureMoment = aggregate.BroadcastinFailureMoment, WaitingForEndingStartMoment = aggregate.WaitingForEndingStartMoment, WaitingForEndingFailureMoment = aggregate.WaitingForEndingFailureMoment, SourceAddressReleaseMoment = aggregate.SourceAddressReleasingMoment, ClearedMoment = aggregate.ClearingMoment, OperationId = aggregate.OperationId, TransactionId = aggregate.TransactionId, TransactionNumber = aggregate.TransactionNumber, BlockchainType = aggregate.BlockchainType, FromAddress = aggregate.FromAddress, FromAddressContext = aggregate.FromAddressContext, Outputs = aggregate.Outputs .Select(TransactionOutputEntity.FromDomain) .ToArray(), AssetId = aggregate.AssetId, IncludeFee = aggregate.IncludeFee, BlockchainAssetId = aggregate.BlockchainAssetId, TransactionOutputs = aggregate.TransactionOutputs? .Select(TransactionOutputEntity.FromDomain) .ToArray(), Hash = aggregate.Hash, Fee = aggregate.Fee, Error = aggregate.Error, Block = aggregate.Block }); }
public TransactionExecutionAggregate ToDomain([CanBeNull] TransactionExecutionBlobEntity blobData) { return(TransactionExecutionAggregate.Restore( ETag, State, Result, StartMoment, SourceAddressLockingMoment, BuildingMoment, SigningMoment, BroadcastingMoment, FinishMoment, SourceAddressReleaseMoment, ClearedMoment, BuildingFailureMoment, BroadcastinFailureMoment, WaitingForEndingStartMoment, WaitingForEndingFailureMoment, OperationId, TransactionId, TransactionNumber, BlockchainType, FromAddress, FromAddressContext, Outputs .Select(x => x.ToDomain()) .ToArray(), AssetId, IncludeFee, blobData?.TransactionContext, BlockchainAssetId, blobData?.SignedTransaction, TransactionOutputs? .Select(o => o.ToDomain()) .ToArray(), Block, Fee, Hash, Error)); }
public void Can_Proceed_Valid_Transaction_Multiple_Register() { // Arrange var register = TransitionRegisterFactory.StartRegistrationFor <TransactionExecutionAggregate, TransactionExecutionState>(); register.GetCurrentStateWith(a => a.State); register.From(TransactionExecutionState.SourceAddressLocked, outputs => { outputs.On <TransactionBuiltEvent>() .HandleTransition((a, e) => a.OnBuilt(e.FromAddressContext, e.TransactionContext)); outputs.On <TransactionExecutionFailedEvent>() .HandleTransition((a, e) => a.OnBuildingFailed(e.ErrorCode, e.Error)); }); var core = register.Build(); var aggregate1 = TransactionExecutionAggregate.Start ( Guid.NewGuid(), Guid.NewGuid(), 0, "", new[] { new TransactionOutputValueType("", 0) }, "", "", "", false ); aggregate1.OnSourceAddressLocked(); var aggregate2 = TransactionExecutionAggregate.Start ( Guid.NewGuid(), Guid.NewGuid(), 0, "", new[] { new TransactionOutputValueType("", 0) }, "", "", "", false ); aggregate2.OnSourceAddressLocked(); // Act var result1 = core.Switch(aggregate1, new TransactionBuiltEvent()); var result2 = core.Switch(aggregate2, new TransactionExecutionFailedEvent { ErrorCode = TransactionExecutionResult.UnknownError }); // Assert Assert.True(result1); Assert.Equal(TransactionExecutionState.Built, aggregate1.State); Assert.True(result2); Assert.Equal(TransactionExecutionState.BuildingFailed, aggregate2.State); }
public void Check_Transition_Preconditions() { // Arrange var register = TransitionRegisterFactory.StartRegistrationFor <TransactionExecutionAggregate, TransactionExecutionState>(); register.GetCurrentStateWith(a => a.State); register.From(TransactionExecutionState.Started) .On <SourceAddressLockedEvent>() .WithPrecondition((a, e) => a.IncludeFee, (a, e) => "Include fee should be enabled") .WithPrecondition((a, e) => a.Outputs.Single().Amount > 0, (a, e) => "Amount should be positive number") .HandleTransition((a, e) => a.OnSourceAddressLocked()); var core = register.Build(); var aggregate1 = TransactionExecutionAggregate.Start ( Guid.NewGuid(), Guid.NewGuid(), 0, "", new[] { new TransactionOutputValueType("", 0) }, "", "", "", false ); var aggregate2 = TransactionExecutionAggregate.Start ( Guid.NewGuid(), Guid.NewGuid(), 0, "", new[] { new TransactionOutputValueType("", 1) }, "", "", "", true ); // Act Assert.Throws <UnexpectedEventException>(() => { try { core.Switch(aggregate1, new SourceAddressLockedEvent()); } catch (Exception e) { _output.WriteLine(e.ToString()); throw; } }); var result21 = core.Switch(aggregate2, new SourceAddressLockedEvent()); // Assert Assert.Equal(TransactionExecutionState.Started, aggregate1.State); Assert.True(result21); Assert.Equal(TransactionExecutionState.SourceAddressLocked, aggregate2.State); }
public void Can_Ignore_Already_Registered_Transition_With_Additional_Conditions() { // Arrange var register = TransitionRegisterFactory.StartRegistrationFor <TransactionExecutionAggregate, TransactionExecutionState>(); register.GetCurrentStateWith(a => a.State); register.From(TransactionExecutionState.Started) .On <SourceAddressLockedEvent>() .HandleTransition((a, e) => a.OnSourceAddressLocked()); register.In(TransactionExecutionState.Started) .Ignore <SourceAddressLockedEvent>((a, e) => a.IncludeFee) .Ignore <TransactionExecutionStartedEvent>(); var core = register.Build(); var aggregate1 = TransactionExecutionAggregate.Start ( Guid.NewGuid(), Guid.NewGuid(), 0, "", new[] { new TransactionOutputValueType("", 0) }, "", "", "", false ); var aggregate2 = TransactionExecutionAggregate.Start ( Guid.NewGuid(), Guid.NewGuid(), 0, "", new[] { new TransactionOutputValueType("", 0) }, "", "", "", true ); // Act var result11 = core.Switch(aggregate1, new TransactionExecutionStartedEvent()); var result12 = core.Switch(aggregate1, new SourceAddressLockedEvent()); var result21 = core.Switch(aggregate2, new TransactionExecutionStartedEvent()); var result22 = core.Switch(aggregate2, new SourceAddressLockedEvent()); // Assert Assert.False(result11); Assert.True(result12); Assert.Equal(TransactionExecutionState.SourceAddressLocked, aggregate1.State); Assert.False(result21); Assert.False(result22); Assert.Equal(TransactionExecutionState.Started, aggregate2.State); }