UnstakeTokensMapper implements StatefulActionToParticleGroupsMapper<UnstakeTokensAction> { @Override public List<ParticleGroup> mapToParticleGroups(UnstakeTokensAction unstake, Stream<Particle> store) throws StageActionException { final RRI tokenRef = unstake.getRRI(); List<StakedTokensParticle> stakeConsumables = store .map(StakedTokensParticle.class::cast) .filter(p -> p.getTokenDefinitionReference().equals(tokenRef)) .collect(Collectors.toList()); final List<SpunParticle> unstakeParticles; try { unstakeParticles = mapToParticles(unstake, stakeConsumables); } catch (NotEnoughFungiblesException e) { throw new InsufficientFundsException( tokenRef, TokenUnitConversions.subunitsToUnits(e.getCurrent()), unstake.getAmount() ); } return Collections.singletonList( ParticleGroup.of(unstakeParticles) ); } UnstakeTokensMapper(); @Override Set<ShardedParticleStateId> requiredState(UnstakeTokensAction action); @Override List<ParticleGroup> mapToParticleGroups(UnstakeTokensAction unstake, Stream<Particle> store);  }
@Test public void when_unstaking_tokens_with_funds__then_error_is_not_thrown() { RadixAddress address1 = RadixAddress.from("JEbhKQzBn4qJzWJFBbaPioA2GTeaQhuUjYWkanTE6N8VvvPpvM8"); RadixAddress address2 = RadixAddress.from("23B6fH3FekJeP6e5guhZAk6n9z4fmTo5Tngo3a11Wg5R8gsWTV2x"); RRI token = RRI.of(address1, "COOKIE"); UnstakeTokensAction action = mock(UnstakeTokensAction.class); when(action.getAmount()).thenReturn(new BigDecimal(1)); when(action.getFrom()).thenReturn(address1); when(action.getRRI()).thenReturn(token); when(action.getDelegate()).thenReturn(address2); UnstakeTokensMapper transferTranslator = new UnstakeTokensMapper(); transferTranslator.mapToParticleGroups(action, Stream.of( new StakedTokensParticle( address2, UInt256.MAX_VALUE, UInt256.ONE, address1, 0, token, ImmutableMap.of() ) )); }