예제 #1
0
 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()
     });
 }
예제 #2
0
        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());
            });
        }
예제 #3
0
 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
     });
 }
예제 #6
0
        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);
        }
예제 #8
0
        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);
        }
예제 #9
0
        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);
        }
예제 #10
0
        // 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
            });
        }
예제 #11
0
 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));
 }
예제 #12
0
        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);
        }
예제 #13
0
        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);
        }
예제 #14
0
        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);
        }