MintTokensActionMapper implements StatefulActionToParticleGroupsMapper<MintTokensAction> { @Override public List<ParticleGroup> mapToParticleGroups(MintTokensAction mintTokensAction, Stream<Particle> store) throws StageActionException { if (mintTokensAction.getAmount().compareTo(BigDecimal.ZERO) <= 0) { throw new IllegalArgumentException("Mint amount must be greater than 0."); } final RRI tokenRef = mintTokensAction.getRRI(); Map<Class<? extends Particle>, List<Particle>> particles = store.collect(Collectors.groupingBy(Particle::getClass)); final List<Particle> tokDefParticles = particles.get(MutableSupplyTokenDefinitionParticle.class); if (tokDefParticles == null || tokDefParticles.stream().noneMatch(p -> ((MutableSupplyTokenDefinitionParticle) p).getRRI().equals(tokenRef)) ) { throw new UnknownTokenException(mintTokensAction.getRRI()); } final List<UnallocatedTokensParticle> currentParticles = particles.getOrDefault(UnallocatedTokensParticle.class, Collections.emptyList()) .stream() .map(UnallocatedTokensParticle.class::cast) .filter(p -> p.getTokDefRef().equals(tokenRef)) .collect(Collectors.toList()); final List<SpunParticle> mintParticles; try { mintParticles = mapToParticles(mintTokensAction, currentParticles); } catch (NotEnoughFungiblesException e) { throw new TokenOverMintException( mintTokensAction.getRRI(), TokenUnitConversions.subunitsToUnits(UInt256.MAX_VALUE), TokenUnitConversions.subunitsToUnits(UInt256.MAX_VALUE.subtract(e.getCurrent())), mintTokensAction.getAmount() ); } return Collections.singletonList( ParticleGroup.of(mintParticles) ); } MintTokensActionMapper(); @Override Set<ShardedParticleStateId> requiredState(MintTokensAction mintTokensAction); @Override List<ParticleGroup> mapToParticleGroups(MintTokensAction mintTokensAction, Stream<Particle> store);  }
@Test public void when_a_mint_action_is_created_with_zero_unallocated_tokens__then_a_overmint_exception_should_be_thrown() { MintTokensActionMapper mapper = new MintTokensActionMapper(); RRI token = mock(RRI.class); MintTokensAction mintTokensAction = MintTokensAction.create(token, mock(RadixAddress.class), BigDecimal.ONE); MutableSupplyTokenDefinitionParticle tokenDefinitionParticle = mock(MutableSupplyTokenDefinitionParticle.class); when(tokenDefinitionParticle.getRRI()).thenReturn(token); assertThatThrownBy(() -> mapper.mapToParticleGroups(mintTokensAction, Stream.of(tokenDefinitionParticle))) .isInstanceOf(TokenOverMintException.class); }
@Test public void when_a_mint_action_is_created_with_zero_particles__then_an_unknown_token_exception_should_be_thrown() { MintTokensActionMapper mapper = new MintTokensActionMapper(); MintTokensAction mintTokensAction = MintTokensAction.create(mock(RRI.class), mock(RadixAddress.class), BigDecimal.ONE); assertThatThrownBy(() -> mapper.mapToParticleGroups(mintTokensAction, Stream.empty())) .isInstanceOf(UnknownTokenException.class); }
@Test public void when_a_mint_action_is_created_with_no_corresponding_token_definition__then_an_unknown_token_exception_should_be_thrown() { MintTokensActionMapper mapper = new MintTokensActionMapper(); MintTokensAction mintTokensAction = MintTokensAction.create(mock(RRI.class), mock(RadixAddress.class), BigDecimal.ONE); MutableSupplyTokenDefinitionParticle tokenDefinitionParticle = mock(MutableSupplyTokenDefinitionParticle.class); when(tokenDefinitionParticle.getRRI()).thenReturn(mock(RRI.class)); assertThatThrownBy(() -> mapper.mapToParticleGroups(mintTokensAction, Stream.of(tokenDefinitionParticle))) .isInstanceOf(UnknownTokenException.class); }