GameProposal ACCEPT
- create new GameBoard state - test
This commit is contained in:
parent
e235ecb942
commit
7f7722ecc0
@ -19,7 +19,8 @@ import com.fasterxml.jackson.databind.JsonMappingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import djmil.cordacheckers.cordaclient.dao.HoldingIdentity;
|
||||
import djmil.cordacheckers.cordaclient.dao.Color;
|
||||
import djmil.cordacheckers.cordaclient.dao.Piece;
|
||||
import djmil.cordacheckers.cordaclient.dao.GameBoard;
|
||||
import djmil.cordacheckers.cordaclient.dao.GameProposal;
|
||||
import djmil.cordacheckers.cordaclient.dao.VirtualNode;
|
||||
import djmil.cordacheckers.cordaclient.dao.VirtualNodeList;
|
||||
@ -28,7 +29,10 @@ import djmil.cordacheckers.cordaclient.dao.flow.ResponseBody;
|
||||
import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameProposalCreateReq;
|
||||
import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameProposalCreateRes;
|
||||
import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameProposalListRes;
|
||||
import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameProposalActionReq.Action;
|
||||
import djmil.cordacheckers.cordaclient.dao.flow.arguments.Empty;
|
||||
import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameBoardListRes;
|
||||
import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameProposalActionAcceptRes;
|
||||
import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameProposalActionReq;
|
||||
import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameProposalActionRes;
|
||||
|
||||
@ -68,7 +72,7 @@ public class CordaClient {
|
||||
public List<GameProposal> gameProposalList(HoldingIdentity holdingIdentity) {
|
||||
|
||||
final RequestBody requestBody = new RequestBody(
|
||||
"list-" + UUID.randomUUID(),
|
||||
"gp.list-" + UUID.randomUUID(),
|
||||
"djmil.cordacheckers.gameproposal.ListFlow",
|
||||
new Empty()
|
||||
);
|
||||
@ -88,67 +92,111 @@ public class CordaClient {
|
||||
}
|
||||
|
||||
public UUID gameProposalCreate(
|
||||
HoldingIdentity sender,
|
||||
HoldingIdentity receiver,
|
||||
Color receiverColor,
|
||||
HoldingIdentity issuer,
|
||||
HoldingIdentity acquier,
|
||||
Piece.Color acquierColor,
|
||||
String message
|
||||
) throws JsonMappingException, JsonProcessingException {
|
||||
final GameProposalCreateReq createGameProposal = new GameProposalCreateReq(
|
||||
receiver.x500Name(),
|
||||
receiverColor,
|
||||
message
|
||||
);
|
||||
|
||||
final RequestBody requestBody = new RequestBody(
|
||||
"create-" + UUID.randomUUID(),
|
||||
"gp.create-" + UUID.randomUUID(),
|
||||
"djmil.cordacheckers.gameproposal.CreateFlow",
|
||||
createGameProposal
|
||||
new GameProposalCreateReq(
|
||||
acquier.x500Name(),
|
||||
acquierColor,
|
||||
message
|
||||
)
|
||||
);
|
||||
|
||||
final GameProposalCreateRes createResult = cordaFlowExecute(
|
||||
sender,
|
||||
issuer,
|
||||
requestBody,
|
||||
GameProposalCreateRes.class
|
||||
);
|
||||
|
||||
if (createResult.failureStatus() != null) {
|
||||
System.out.println("GameProposalCreateFlow failed: " + createResult.failureStatus());
|
||||
System.out.println("GameProposal.CreateFlow failed: " + createResult.failureStatus());
|
||||
throw new RuntimeException("GameProsal: CreateFlow execution has failed");
|
||||
}
|
||||
|
||||
return createResult.successStatus();
|
||||
}
|
||||
|
||||
public String gameProposalAction(
|
||||
HoldingIdentity self,
|
||||
UUID gameProposalUuid,
|
||||
GameProposalActionReq.Action action
|
||||
public String gameProposalReject(
|
||||
HoldingIdentity myHoldingIdentity,
|
||||
UUID gameProposalUuid
|
||||
) {
|
||||
final GameProposalActionReq rejectGameProposal = new GameProposalActionReq(
|
||||
gameProposalUuid.toString(),
|
||||
action
|
||||
);
|
||||
|
||||
final RequestBody requestBody = new RequestBody(
|
||||
"reject-" + UUID.randomUUID(),
|
||||
"gp.reject-" +UUID.randomUUID(),
|
||||
"djmil.cordacheckers.gameproposal.ActionFlow",
|
||||
rejectGameProposal
|
||||
new GameProposalActionReq(
|
||||
gameProposalUuid.toString(),
|
||||
Action.REJECT
|
||||
)
|
||||
);
|
||||
|
||||
final GameProposalActionRes actionResult = cordaFlowExecute(
|
||||
self,
|
||||
myHoldingIdentity,
|
||||
requestBody,
|
||||
GameProposalActionRes.class
|
||||
);
|
||||
|
||||
if (actionResult.failureStatus() != null) {
|
||||
System.out.println("GameProposalActionFlow failed: " + actionResult.failureStatus());
|
||||
System.out.println("GameProposal.ActionFlow failed: " + actionResult.failureStatus());
|
||||
throw new RuntimeException("GameProsal: ActionFlow execution has failed");
|
||||
}
|
||||
|
||||
return actionResult.successStatus();
|
||||
}
|
||||
|
||||
public UUID gameProposalAccept(
|
||||
HoldingIdentity myHoldingIdentity,
|
||||
UUID gameProposalUuid
|
||||
) {
|
||||
final RequestBody requestBody = new RequestBody(
|
||||
"gp.accept-" +UUID.randomUUID(),
|
||||
"djmil.cordacheckers.gameproposal.ActionFlow",
|
||||
new GameProposalActionReq(
|
||||
gameProposalUuid.toString(),
|
||||
Action.ACCEPT
|
||||
)
|
||||
);
|
||||
|
||||
final GameProposalActionAcceptRes actionResult = cordaFlowExecute(
|
||||
myHoldingIdentity,
|
||||
requestBody,
|
||||
GameProposalActionAcceptRes.class
|
||||
);
|
||||
|
||||
if (actionResult.failureStatus() != null) {
|
||||
System.out.println("GameProposal.ActionFlow failed: " + actionResult.failureStatus());
|
||||
throw new RuntimeException("GameProsal: ActionFlow execution has failed");
|
||||
}
|
||||
|
||||
return actionResult.successStatus();
|
||||
}
|
||||
|
||||
public List<GameBoard> gameBoardList(HoldingIdentity holdingIdentity) {
|
||||
|
||||
final RequestBody requestBody = new RequestBody(
|
||||
"gb.list-" + UUID.randomUUID(),
|
||||
"djmil.cordacheckers.gameboard.ListFlow",
|
||||
new Empty()
|
||||
);
|
||||
|
||||
final GameBoardListRes listFlowResult = cordaFlowExecute(
|
||||
holdingIdentity,
|
||||
requestBody,
|
||||
GameBoardListRes.class
|
||||
);
|
||||
|
||||
if (listFlowResult.failureStatus() != null) {
|
||||
System.out.println("GameBoard.ListFlow failed: " + listFlowResult.failureStatus());
|
||||
throw new RuntimeException("GameBoard: ListFlow execution has failed");
|
||||
}
|
||||
|
||||
return listFlowResult.successStatus();
|
||||
}
|
||||
|
||||
private <T> T cordaFlowExecute(HoldingIdentity holdingIdentity, RequestBody requestBody, Class<T> flowResultType) {
|
||||
|
||||
try {
|
||||
|
@ -1,6 +0,0 @@
|
||||
package djmil.cordacheckers.cordaclient.dao;
|
||||
|
||||
public enum Color {
|
||||
WHITE,
|
||||
BLACK
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package djmil.cordacheckers.cordaclient.dao;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface CordaState {
|
||||
public UUID id();
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package djmil.cordacheckers.cordaclient.dao;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
|
||||
@JsonDeserialize
|
||||
public record GameBoard(
|
||||
String opponentName,
|
||||
Piece.Color opponentColor,
|
||||
Boolean opponentMove,
|
||||
Map<Integer, Piece> board,
|
||||
String message,
|
||||
UUID id) implements CordaState {
|
||||
|
||||
}
|
@ -8,8 +8,8 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
public record GameProposal(
|
||||
String issuer,
|
||||
String acquier,
|
||||
Color acquierColor,
|
||||
Piece.Color acquierColor,
|
||||
String message,
|
||||
UUID id) {
|
||||
UUID id) implements CordaState {
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,41 @@
|
||||
package djmil.cordacheckers.cordaclient.dao;
|
||||
|
||||
public class Piece {
|
||||
|
||||
public enum Type {
|
||||
MAN,
|
||||
KING,
|
||||
}
|
||||
|
||||
public enum Color {
|
||||
WHITE,
|
||||
BLACK,
|
||||
}
|
||||
|
||||
Color color;
|
||||
Type type;
|
||||
|
||||
public Piece() {
|
||||
this.color = null;
|
||||
this.type = null;
|
||||
}
|
||||
|
||||
public Piece(Color color, Type type) {
|
||||
this.color = color;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Color getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return color +"." +type;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package djmil.cordacheckers.cordaclient.dao.flow.arguments;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
import djmil.cordacheckers.cordaclient.dao.GameBoard;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public record GameBoardListRes(List<GameBoard> successStatus, String failureStatus) {
|
||||
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package djmil.cordacheckers.cordaclient.dao.flow.arguments;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public record GameProposalActionAcceptRes(UUID successStatus, String transactionId, String failureStatus) {
|
||||
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
package djmil.cordacheckers.cordaclient.dao.flow.arguments;
|
||||
|
||||
import djmil.cordacheckers.cordaclient.dao.Color;
|
||||
import djmil.cordacheckers.cordaclient.dao.Piece;
|
||||
|
||||
public record GameProposalCreateReq(String opponentName, Color opponentColor, String message) {
|
||||
public record GameProposalCreateReq(String opponentName, Piece.Color opponentColor, String message) {
|
||||
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ import com.fasterxml.jackson.databind.JsonMappingException;
|
||||
import djmil.cordacheckers.cordaclient.CordaClient;
|
||||
import djmil.cordacheckers.cordaclient.dao.HoldingIdentity;
|
||||
import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameProposalCreateReq;
|
||||
import djmil.cordacheckers.cordaclient.dao.Color;
|
||||
import djmil.cordacheckers.cordaclient.dao.Piece;
|
||||
import djmil.cordacheckers.cordaclient.dao.GameProposal;
|
||||
import djmil.cordacheckers.user.HoldingIdentityResolver;
|
||||
import djmil.cordacheckers.user.User;
|
||||
@ -61,7 +61,7 @@ public class GameProposalController {
|
||||
final HoldingIdentity gpSender = sender.getHoldingIdentity();
|
||||
// TODO: throw execption with custom type
|
||||
final HoldingIdentity gpReceiver = holdingIdentityResolver.getByUsername(gpRequest.opponentName());
|
||||
final Color gpReceiverColor = gpRequest.opponentColor();
|
||||
final Piece.Color gpReceiverColor = gpRequest.opponentColor();
|
||||
|
||||
// TODO handle expectionns here
|
||||
UUID newGameProposalUuid = cordaClient.gameProposalCreate(
|
||||
|
@ -1,19 +1,5 @@
|
||||
package djmil.cordacheckers.cordaclient;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||
|
||||
import djmil.cordacheckers.cordaclient.dao.Color;
|
||||
import djmil.cordacheckers.cordaclient.dao.GameProposal;
|
||||
import djmil.cordacheckers.cordaclient.dao.VirtualNode;
|
||||
import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameProposalActionReq.Action;
|
||||
import djmil.cordacheckers.user.HoldingIdentityResolver;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
@ -22,6 +8,20 @@ import java.util.UUID;
|
||||
|
||||
import javax.naming.InvalidNameException;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||
|
||||
import djmil.cordacheckers.cordaclient.dao.CordaState;
|
||||
import djmil.cordacheckers.cordaclient.dao.GameBoard;
|
||||
import djmil.cordacheckers.cordaclient.dao.GameProposal;
|
||||
import djmil.cordacheckers.cordaclient.dao.Piece;
|
||||
import djmil.cordacheckers.cordaclient.dao.VirtualNode;
|
||||
import djmil.cordacheckers.user.HoldingIdentityResolver;
|
||||
|
||||
@SpringBootTest
|
||||
public class CordaClientTest {
|
||||
@Autowired
|
||||
@ -49,7 +49,7 @@ public class CordaClientTest {
|
||||
void testGemeProposalCreate() throws JsonMappingException, JsonProcessingException {
|
||||
final String gpIssuer = "alice";
|
||||
final String gpAcquier = "bob";
|
||||
final Color gpAcquierColor = Color.WHITE;
|
||||
final Piece.Color gpAcquierColor = Piece.Color.WHITE;
|
||||
final String gpMessage = "GameProposal create test";
|
||||
|
||||
final UUID createdGpUuid = cordaClient.gameProposalCreate(
|
||||
@ -78,58 +78,118 @@ public class CordaClientTest {
|
||||
|
||||
@Test
|
||||
void testGemeProposalReject() throws JsonMappingException, JsonProcessingException {
|
||||
final String gpSender = "alice";
|
||||
final String gpReceiver = "bob";
|
||||
final Color gpReceiverColor = Color.WHITE;
|
||||
final String gpIssuer = "alice";
|
||||
final String gpAcquier = "bob";
|
||||
final Piece.Color gpReceiverColor = Piece.Color.WHITE;
|
||||
final String gpMessage = "GameProposal REJECT test";
|
||||
|
||||
final UUID gpUuid = cordaClient.gameProposalCreate(
|
||||
holdingIdentityResolver.getByUsername(gpSender),
|
||||
holdingIdentityResolver.getByUsername(gpReceiver),
|
||||
holdingIdentityResolver.getByUsername(gpIssuer),
|
||||
holdingIdentityResolver.getByUsername(gpAcquier),
|
||||
gpReceiverColor,
|
||||
gpMessage
|
||||
);
|
||||
|
||||
System.out.println("Create GP UUID "+ gpUuid);
|
||||
|
||||
assertThatThrownBy(() -> {
|
||||
cordaClient.gameProposalAction(
|
||||
holdingIdentityResolver.getByUsername(gpSender),
|
||||
gpUuid,
|
||||
Action.REJECT);
|
||||
assertThatThrownBy(() -> { // Issuer can not reject
|
||||
cordaClient.gameProposalReject(
|
||||
holdingIdentityResolver.getByUsername(gpIssuer),
|
||||
gpUuid);
|
||||
});
|
||||
|
||||
final String rejectRes = cordaClient.gameProposalAction(
|
||||
holdingIdentityResolver.getByUsername(gpReceiver),
|
||||
gpUuid,
|
||||
Action.REJECT
|
||||
final String rejectRes = cordaClient.gameProposalReject(
|
||||
holdingIdentityResolver.getByUsername(gpAcquier),
|
||||
gpUuid
|
||||
);
|
||||
|
||||
assertThat(rejectRes).isEqualToIgnoringCase("REJECTED");
|
||||
|
||||
List<GameProposal> gpListSender = cordaClient.gameProposalList(
|
||||
holdingIdentityResolver.getByUsername(gpSender));
|
||||
holdingIdentityResolver.getByUsername(gpIssuer));
|
||||
|
||||
assertThat(findByUuid(gpListSender, gpUuid)).isNull();
|
||||
|
||||
List<GameProposal> gpListReceiver = cordaClient.gameProposalList(
|
||||
holdingIdentityResolver.getByUsername(gpReceiver));
|
||||
holdingIdentityResolver.getByUsername(gpAcquier));
|
||||
|
||||
assertThat(findByUuid(gpListReceiver, gpUuid)).isNull();
|
||||
|
||||
// GameProposal can not be rejected twice
|
||||
assertThatThrownBy(() -> {
|
||||
cordaClient.gameProposalAction(
|
||||
holdingIdentityResolver.getByUsername(gpSender),
|
||||
gpUuid,
|
||||
Action.REJECT);
|
||||
cordaClient.gameProposalReject(
|
||||
holdingIdentityResolver.getByUsername(gpIssuer),
|
||||
gpUuid);
|
||||
});
|
||||
}
|
||||
|
||||
private GameProposal findByUuid(List<GameProposal> gpList, UUID uuid) {
|
||||
for (GameProposal gameProposal : gpList) {
|
||||
if (gameProposal.id().compareTo(uuid) == 0)
|
||||
return gameProposal;
|
||||
@Test
|
||||
void testGemeProposalAccept() throws JsonMappingException, JsonProcessingException {
|
||||
final String gpIssuer = "alice";
|
||||
final String gpAcquier = "bob";
|
||||
final Piece.Color gpAcquierColor = Piece.Color.WHITE;
|
||||
final String gpMessage = "GameProposal ACCEPT test";
|
||||
|
||||
final UUID gpUuid = cordaClient.gameProposalCreate(
|
||||
holdingIdentityResolver.getByUsername(gpIssuer),
|
||||
holdingIdentityResolver.getByUsername(gpAcquier),
|
||||
gpAcquierColor,
|
||||
gpMessage
|
||||
);
|
||||
|
||||
System.out.println("New GameProposal UUID "+ gpUuid);
|
||||
|
||||
assertThatThrownBy(() -> { // Issuer can not accept
|
||||
cordaClient.gameProposalAccept(
|
||||
holdingIdentityResolver.getByUsername(gpIssuer),
|
||||
gpUuid);
|
||||
});
|
||||
|
||||
final UUID newGameBoardId = cordaClient.gameProposalAccept(
|
||||
holdingIdentityResolver.getByUsername(gpAcquier),
|
||||
gpUuid
|
||||
);
|
||||
|
||||
System.out.println("New GameBoard UUID "+newGameBoardId);
|
||||
|
||||
List<GameBoard> gbListIssuer = cordaClient.gameBoardList(
|
||||
holdingIdentityResolver.getByUsername(gpIssuer));
|
||||
|
||||
GameBoard gbAlice = findByUuid(gbListIssuer, newGameBoardId);
|
||||
assertThat(gbAlice).isNotNull();
|
||||
assertThat(gbAlice.opponentName()).isEqualToIgnoringCase(gpAcquier);
|
||||
assertThat(gbAlice.opponentColor()).isEqualByComparingTo(gpAcquierColor);
|
||||
assertThat(gbAlice.opponentMove()).isEqualTo(true);
|
||||
|
||||
|
||||
List<GameBoard> gbListAcquier = cordaClient.gameBoardList(
|
||||
holdingIdentityResolver.getByUsername(gpAcquier));
|
||||
|
||||
GameBoard bgBob = findByUuid(gbListAcquier, newGameBoardId);
|
||||
assertThat(bgBob).isNotNull();
|
||||
assertThat(bgBob.opponentName()).isEqualToIgnoringCase(gpIssuer);
|
||||
assertThat(bgBob.opponentColor()).isEqualByComparingTo(Piece.Color.BLACK);
|
||||
assertThat(bgBob.opponentMove()).isEqualTo(false);
|
||||
|
||||
assertThatThrownBy(() -> { // GameProposal can not be accepted twice
|
||||
cordaClient.gameProposalAccept(
|
||||
holdingIdentityResolver.getByUsername(gpAcquier),
|
||||
gpUuid);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGemeProposalList() throws JsonMappingException, JsonProcessingException {
|
||||
List <GameBoard> gbList = cordaClient.gameBoardList(
|
||||
holdingIdentityResolver.getByUsername("bob"));
|
||||
|
||||
System.out.println("GB list: " +gbList);
|
||||
}
|
||||
|
||||
private <T extends CordaState> T findByUuid(List<T> statesList, UUID uuid) {
|
||||
for (T state : statesList) {
|
||||
if (state.id().compareTo(uuid) == 0)
|
||||
return state;
|
||||
};
|
||||
return null;
|
||||
}
|
||||
|
@ -0,0 +1,69 @@
|
||||
package djmil.cordacheckers.contracts;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import djmil.cordacheckers.states.GameProposalState;
|
||||
import net.corda.v5.base.annotations.Suspendable;
|
||||
import net.corda.v5.base.exceptions.CordaRuntimeException;
|
||||
import net.corda.v5.ledger.utxo.Command;
|
||||
import net.corda.v5.ledger.utxo.transaction.UtxoLedgerTransaction;
|
||||
|
||||
import static djmil.cordacheckers.contracts.GameProposalContract.Action;
|
||||
|
||||
public class GameBoardContract implements net.corda.v5.ledger.utxo.Contract {
|
||||
|
||||
private final static Logger log = LoggerFactory.getLogger(GameBoardContract.class);
|
||||
|
||||
public static class Move implements Command { }
|
||||
public static class Surrender implements Command { }
|
||||
public static class ClaimVictory implements Command { }
|
||||
public static class ProposeDraw implements Command { }
|
||||
|
||||
@Override
|
||||
public void verify(UtxoLedgerTransaction trx) {
|
||||
log.info("GameBoardContract.verify()");
|
||||
|
||||
requireThat(trx.getCommands().size() == 1, REQUIRE_SINGLE_COMMAND);
|
||||
Command command = trx.getCommands().get(0);
|
||||
}
|
||||
|
||||
@Suspendable
|
||||
public static GameProposalState getReferanceGameProposalState(UtxoLedgerTransaction trx) {
|
||||
final List<Command> commandList = trx.getCommands();
|
||||
requireThat(commandList.size() == 1, REQUIRE_SINGLE_COMMAND);
|
||||
|
||||
final Command command = commandList.get(0);
|
||||
|
||||
if (command instanceof Action && (Action)command == Action.ACCEPT) {
|
||||
return trx.getInputStates(GameProposalState.class)
|
||||
.stream()
|
||||
.reduce( (a, b) -> {throw new IllegalStateException(SINGLE_STATE_EXPECTED);} )
|
||||
.get();
|
||||
|
||||
} else
|
||||
if (command instanceof GameBoardContract.Move)
|
||||
{
|
||||
List<GameProposalState> refStates = trx.getReferenceStates(GameProposalState.class);
|
||||
if (refStates.size() == 1) {
|
||||
return (GameProposalState) refStates.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalStateException(NO_REFERANCE_GAMEPROPOSAL_STATE_FOR_TRXID +trx.getId());
|
||||
}
|
||||
|
||||
private static void requireThat(boolean asserted, String errorMessage) {
|
||||
if(!asserted) {
|
||||
throw new CordaRuntimeException("Failed requirement: " + errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
static final String REQUIRE_SINGLE_COMMAND = "Require a single command";
|
||||
static final String UNKNOWN_COMMAND = "Unsupported command";
|
||||
|
||||
static final String SINGLE_STATE_EXPECTED = "Single state expected";
|
||||
static final String NO_REFERANCE_GAMEPROPOSAL_STATE_FOR_TRXID = "No reference GamePropsal state found for trx.id ";
|
||||
}
|
@ -3,7 +3,7 @@ package djmil.cordacheckers.contracts;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
//import djmil.cordacheckers.states.GameProposalResolutionState;
|
||||
import djmil.cordacheckers.states.GameBoardState;
|
||||
import djmil.cordacheckers.states.GameProposalState;
|
||||
import net.corda.v5.base.exceptions.CordaRuntimeException;
|
||||
import net.corda.v5.base.types.MemberX500Name;
|
||||
@ -47,11 +47,11 @@ public class GameProposalContract implements net.corda.v5.ledger.utxo.Contract {
|
||||
}
|
||||
}
|
||||
|
||||
public MemberX500Name getSender(StateAndRef<GameProposalState> utxoGameProposal) {
|
||||
public MemberX500Name getInitiator(StateAndRef<GameProposalState> utxoGameProposal) {
|
||||
return getInitiator(utxoGameProposal.getState().getContractState());
|
||||
}
|
||||
|
||||
public MemberX500Name getReceiver(StateAndRef<GameProposalState> utxoGameProposal) {
|
||||
public MemberX500Name getRespondent(StateAndRef<GameProposalState> utxoGameProposal) {
|
||||
return getRespondent(utxoGameProposal.getState().getContractState());
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ public class GameProposalContract implements net.corda.v5.ledger.utxo.Contract {
|
||||
|
||||
requireThat(trx.getCommands().size() == 1, REQUIRE_SINGLE_COMMAND);
|
||||
|
||||
switch ((Action)(trx.getCommands().get(0))) {
|
||||
switch ((trx.getCommands(Action.class).get(0))) {
|
||||
case CREATE: {
|
||||
requireThat(trx.getInputContractStates().isEmpty(), CREATE_INPUT_STATE);
|
||||
requireThat(trx.getOutputContractStates().size() == 1, CREATE_OUTPUT_STATE);
|
||||
@ -72,12 +72,21 @@ public class GameProposalContract implements net.corda.v5.ledger.utxo.Contract {
|
||||
GameProposalState outputState = trx.getOutputStates(GameProposalState.class).get(0);
|
||||
requireThat(outputState != null, CREATE_OUTPUT_STATE);
|
||||
|
||||
requireThat(outputState.getRecipientColor() != null, NON_NULL_RECIPIENT_COLOR);
|
||||
requireThat(outputState.getAcquierColor() != null, NON_NULL_RECIPIENT_COLOR);
|
||||
break; }
|
||||
|
||||
case ACCEPT:
|
||||
throw new CordaRuntimeException("Unimplemented!");
|
||||
//break;
|
||||
requireThat(trx.getInputContractStates().size() == 1, ACCEPT_INPUT_STATE);
|
||||
requireThat(trx.getOutputContractStates().size() == 1, ACCEPT_OUTPUT_STATE);
|
||||
|
||||
GameProposalState inGameProposal = trx.getInputStates(GameProposalState.class).get(0);
|
||||
requireThat(inGameProposal != null, ACCEPT_INPUT_STATE);
|
||||
|
||||
GameBoardState outGameBoard = trx.getOutputStates(GameBoardState.class).get(0);
|
||||
requireThat(outGameBoard != null, ACCEPT_INPUT_STATE);
|
||||
|
||||
requireThat(outGameBoard.getParticipants().containsAll(inGameProposal.getParticipants()), ACCEPT_PARTICIPANTS);
|
||||
break;
|
||||
|
||||
case REJECT:
|
||||
requireThat(trx.getInputContractStates().size() == 1, REJECT_INPUT_STATE);
|
||||
@ -114,4 +123,8 @@ public class GameProposalContract implements net.corda.v5.ledger.utxo.Contract {
|
||||
|
||||
static final String CANCEL_INPUT_STATE = "Cancel command should have exactly one GameProposal input state";
|
||||
static final String CANCEL_OUTPUT_STATE = "Cancel command should have no output states";
|
||||
|
||||
static final String ACCEPT_INPUT_STATE = "Accept command should have exactly one GameProposal input state";
|
||||
static final String ACCEPT_OUTPUT_STATE = "Accept command should have exactly one GameBoard output state";
|
||||
static final String ACCEPT_PARTICIPANTS = "Accept command: GameBoard participants should math GameProposal participants";
|
||||
}
|
||||
|
@ -0,0 +1,93 @@
|
||||
package djmil.cordacheckers.states;
|
||||
|
||||
import java.security.PublicKey;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import djmil.cordacheckers.contracts.GameBoardContract;
|
||||
import djmil.cordacheckers.states.Piece.Color;
|
||||
import net.corda.v5.base.annotations.ConstructorForDeserialization;
|
||||
import net.corda.v5.ledger.utxo.BelongsToContract;
|
||||
import net.corda.v5.ledger.utxo.ContractState;
|
||||
import net.corda.v5.ledger.utxo.StateAndRef;
|
||||
|
||||
@BelongsToContract(GameBoardContract.class)
|
||||
public class GameBoardState implements ContractState {
|
||||
|
||||
Map<Integer, Piece> board;
|
||||
Piece.Color moveColor;
|
||||
String message;
|
||||
UUID id;
|
||||
List<PublicKey> participants;
|
||||
|
||||
public GameBoardState(
|
||||
StateAndRef<GameProposalState> utxoGameBoard
|
||||
) {
|
||||
this.board = new LinkedHashMap<Integer, Piece>(initialBoard);
|
||||
this.moveColor = Piece.Color.WHITE;
|
||||
this.message = null;
|
||||
this.id = UUID.randomUUID();
|
||||
this.participants = utxoGameBoard.getState().getContractState().getParticipants();
|
||||
}
|
||||
|
||||
@ConstructorForDeserialization
|
||||
public GameBoardState(Map<Integer, Piece> board, Color moveColor, String message, UUID id,
|
||||
List<PublicKey> participants) {
|
||||
this.board = board;
|
||||
this.moveColor = moveColor;
|
||||
this.message = message;
|
||||
this.id = id;
|
||||
this.participants = participants;
|
||||
}
|
||||
|
||||
public Map<Integer, Piece> getBoard() {
|
||||
return board;
|
||||
}
|
||||
|
||||
public Piece.Color getMoveColor() {
|
||||
return moveColor;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public List<PublicKey> getParticipants() {
|
||||
return participants;
|
||||
}
|
||||
|
||||
public final static Map<Integer, Piece> initialBoard = Map.ofEntries(
|
||||
// Inspired by Checkers notation rules: https://www.bobnewell.net/nucleus/checkers.php
|
||||
Map.entry( 1, new Piece(Piece.Color.BLACK, Piece.Type.MAN)),
|
||||
Map.entry( 2, new Piece(Piece.Color.BLACK, Piece.Type.MAN)),
|
||||
Map.entry( 3, new Piece(Piece.Color.BLACK, Piece.Type.MAN)),
|
||||
Map.entry( 4, new Piece(Piece.Color.BLACK, Piece.Type.MAN)),
|
||||
Map.entry( 5, new Piece(Piece.Color.BLACK, Piece.Type.MAN)),
|
||||
Map.entry( 6, new Piece(Piece.Color.BLACK, Piece.Type.MAN)),
|
||||
Map.entry( 7, new Piece(Piece.Color.BLACK, Piece.Type.MAN)),
|
||||
Map.entry( 8, new Piece(Piece.Color.BLACK, Piece.Type.MAN)),
|
||||
Map.entry( 9, new Piece(Piece.Color.BLACK, Piece.Type.MAN)),
|
||||
Map.entry(10, new Piece(Piece.Color.BLACK, Piece.Type.MAN)),
|
||||
Map.entry(11, new Piece(Piece.Color.BLACK, Piece.Type.MAN)),
|
||||
Map.entry(12, new Piece(Piece.Color.BLACK, Piece.Type.MAN)),
|
||||
|
||||
Map.entry(21, new Piece(Piece.Color.WHITE, Piece.Type.MAN)),
|
||||
Map.entry(22, new Piece(Piece.Color.WHITE, Piece.Type.MAN)),
|
||||
Map.entry(23, new Piece(Piece.Color.WHITE, Piece.Type.MAN)),
|
||||
Map.entry(24, new Piece(Piece.Color.WHITE, Piece.Type.MAN)),
|
||||
Map.entry(25, new Piece(Piece.Color.WHITE, Piece.Type.MAN)),
|
||||
Map.entry(26, new Piece(Piece.Color.WHITE, Piece.Type.MAN)),
|
||||
Map.entry(27, new Piece(Piece.Color.WHITE, Piece.Type.MAN)),
|
||||
Map.entry(28, new Piece(Piece.Color.WHITE, Piece.Type.MAN)),
|
||||
Map.entry(29, new Piece(Piece.Color.WHITE, Piece.Type.MAN)),
|
||||
Map.entry(30, new Piece(Piece.Color.WHITE, Piece.Type.MAN)),
|
||||
Map.entry(31, new Piece(Piece.Color.WHITE, Piece.Type.MAN)),
|
||||
Map.entry(32, new Piece(Piece.Color.WHITE, Piece.Type.MAN))
|
||||
);
|
||||
}
|
@ -15,24 +15,23 @@ public class GameProposalState implements ContractState {
|
||||
|
||||
MemberX500Name issuer;
|
||||
MemberX500Name acquier;
|
||||
Piece.Color recipientColor;
|
||||
Piece.Color acquierColor;
|
||||
String message;
|
||||
UUID id;
|
||||
List<PublicKey> participants;
|
||||
|
||||
// Allows serialisation and to use a specified UUID
|
||||
@ConstructorForDeserialization
|
||||
public GameProposalState(
|
||||
MemberX500Name issuer,
|
||||
MemberX500Name acquier,
|
||||
Piece.Color recipientColor,
|
||||
Piece.Color acquierColor,
|
||||
String message,
|
||||
UUID id,
|
||||
List<PublicKey> participants
|
||||
) {
|
||||
this.issuer = issuer;
|
||||
this.acquier = acquier;
|
||||
this.recipientColor = recipientColor;
|
||||
this.acquierColor = acquierColor;
|
||||
this.message = message;
|
||||
this.id = id;
|
||||
this.participants = participants;
|
||||
@ -46,8 +45,8 @@ public class GameProposalState implements ContractState {
|
||||
return acquier;
|
||||
}
|
||||
|
||||
public Piece.Color getRecipientColor() {
|
||||
return recipientColor;
|
||||
public Piece.Color getAcquierColor() {
|
||||
return acquierColor;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
@ -61,4 +60,29 @@ public class GameProposalState implements ContractState {
|
||||
public List<PublicKey> getParticipants() {
|
||||
return participants;
|
||||
}
|
||||
|
||||
public MemberX500Name getWhitePlayerName() {
|
||||
return acquierColor == Piece.Color.WHITE ? getAcquier() : getIssuer();
|
||||
}
|
||||
|
||||
public MemberX500Name getBlackPlayerName() {
|
||||
return acquierColor == Piece.Color.BLACK ? getAcquier() : getIssuer();
|
||||
}
|
||||
|
||||
public MemberX500Name getOpponentName(MemberX500Name myName) {
|
||||
if (issuer.compareTo(myName) == 0)
|
||||
return acquier;
|
||||
|
||||
if (acquier.compareTo(myName) == 0)
|
||||
return issuer;
|
||||
|
||||
throw new RuntimeException(myName +" seems to be not involved in " + id +" game");
|
||||
}
|
||||
|
||||
public Piece.Color getOpponentColor(MemberX500Name myName) {
|
||||
final MemberX500Name opponentName = getOpponentName(myName);
|
||||
|
||||
return getWhitePlayerName().compareTo(opponentName) == 0 ? Piece.Color.WHITE : Piece.Color.BLACK;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package djmil.cordacheckers.states;
|
||||
|
||||
import net.corda.v5.base.annotations.ConstructorForDeserialization;
|
||||
import net.corda.v5.base.annotations.CordaSerializable;
|
||||
|
||||
@CordaSerializable
|
||||
@ -20,5 +21,18 @@ public class Piece {
|
||||
Color color;
|
||||
Type type;
|
||||
|
||||
|
||||
@ConstructorForDeserialization
|
||||
public Piece(Color color, Type type) {
|
||||
this.color = color;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Color getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,80 @@
|
||||
package djmil.cordacheckers.gameboard;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import djmil.cordacheckers.FlowResult;
|
||||
import djmil.cordacheckers.contracts.GameBoardContract;
|
||||
import djmil.cordacheckers.states.GameBoardState;
|
||||
import djmil.cordacheckers.states.GameProposalState;
|
||||
import net.corda.v5.application.flows.ClientRequestBody;
|
||||
import net.corda.v5.application.flows.ClientStartableFlow;
|
||||
import net.corda.v5.application.flows.CordaInject;
|
||||
import net.corda.v5.application.marshalling.JsonMarshallingService;
|
||||
import net.corda.v5.application.membership.MemberLookup;
|
||||
import net.corda.v5.base.annotations.Suspendable;
|
||||
import net.corda.v5.base.types.MemberX500Name;
|
||||
import net.corda.v5.crypto.SecureHash;
|
||||
import net.corda.v5.ledger.utxo.StateAndRef;
|
||||
import net.corda.v5.ledger.utxo.UtxoLedgerService;
|
||||
import net.corda.v5.ledger.utxo.transaction.UtxoLedgerTransaction;
|
||||
|
||||
public class ListFlow implements ClientStartableFlow {
|
||||
|
||||
private final static Logger log = LoggerFactory.getLogger(ListFlow.class);
|
||||
|
||||
@CordaInject
|
||||
public MemberLookup memberLookup;
|
||||
|
||||
@CordaInject
|
||||
public UtxoLedgerService utxoLedgerService;
|
||||
|
||||
@CordaInject
|
||||
public JsonMarshallingService jsonMarshallingService;
|
||||
|
||||
@Suspendable
|
||||
@Override
|
||||
public String call(ClientRequestBody requestBody) {
|
||||
|
||||
try {
|
||||
final var unconsumedGameBoardList = utxoLedgerService
|
||||
.findUnconsumedStatesByType(GameBoardState.class);
|
||||
|
||||
List<ListItem> res = new LinkedList<ListItem>();
|
||||
for (StateAndRef<GameBoardState> gbState :unconsumedGameBoardList) {
|
||||
// NOTE: lambda operations (aka .map) can not be used with UtxoLedgerService instances
|
||||
res.add(prepareListItem(gbState));
|
||||
}
|
||||
|
||||
return new FlowResult(res)
|
||||
.toJsonEncodedString(jsonMarshallingService);
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.warn("GameBoard.ListFlow failed to process utxo request body " + requestBody + " because: " + e.getMessage());
|
||||
return new FlowResult(e).toJsonEncodedString(jsonMarshallingService);
|
||||
}
|
||||
}
|
||||
|
||||
@Suspendable
|
||||
private ListItem prepareListItem(StateAndRef<GameBoardState> stateAndRef) {
|
||||
final MemberX500Name myName = memberLookup.myInfo().getName();
|
||||
|
||||
final SecureHash trxId = stateAndRef.getRef().getTransactionId();
|
||||
|
||||
final UtxoLedgerTransaction utxoGameBoard = utxoLedgerService
|
||||
.findLedgerTransaction(trxId);
|
||||
|
||||
final GameProposalState referanceGameProposal = GameBoardContract
|
||||
.getReferanceGameProposalState(utxoGameBoard);
|
||||
|
||||
return new ListItem(
|
||||
stateAndRef.getState().getContractState(),
|
||||
referanceGameProposal.getOpponentName(myName),
|
||||
referanceGameProposal.getOpponentColor(myName)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package djmil.cordacheckers.gameboard;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import djmil.cordacheckers.states.GameBoardState;
|
||||
import djmil.cordacheckers.states.Piece;
|
||||
import net.corda.v5.base.types.MemberX500Name;
|
||||
|
||||
// Class to hold results of the List flow.
|
||||
// JsonMarshallingService can only serialize simple classes that the underlying Jackson serializer recognises,
|
||||
// hence creating a DTO style object which consists only of Strings and a UUIDs. It is possible to create custom
|
||||
// serializers for the JsonMarshallingService in the future.
|
||||
|
||||
public class ListItem {
|
||||
public final String opponentName;
|
||||
public final Piece.Color opponentColor;
|
||||
public final Boolean opponentMove;
|
||||
public final Object board;
|
||||
public final String message;
|
||||
public final UUID id;
|
||||
|
||||
// Serialisation service requires a default constructor
|
||||
public ListItem() {
|
||||
this.opponentName = null;
|
||||
this.opponentColor = null;
|
||||
this.opponentMove = null;
|
||||
this.board = null;
|
||||
this.message = null;
|
||||
this.id = null;
|
||||
}
|
||||
|
||||
public ListItem(GameBoardState gameBoard, MemberX500Name opponentName, Piece.Color opponentColor) {
|
||||
this.opponentName = opponentName.getCommonName();
|
||||
this.opponentColor = opponentColor;
|
||||
this.opponentMove = opponentColor == gameBoard.getMoveColor();
|
||||
this.board = gameBoard.getBoard();
|
||||
this.message = gameBoard.getMessage();
|
||||
this.id = gameBoard.getId();
|
||||
}
|
||||
|
||||
}
|
@ -1,13 +1,12 @@
|
||||
package djmil.cordacheckers.gameproposal;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import djmil.cordacheckers.FlowResult;
|
||||
import djmil.cordacheckers.states.GameBoardState;
|
||||
import djmil.cordacheckers.states.GameProposalState;
|
||||
import net.corda.v5.application.flows.ClientRequestBody;
|
||||
import net.corda.v5.application.flows.ClientStartableFlow;
|
||||
@ -15,7 +14,6 @@ import net.corda.v5.application.flows.CordaInject;
|
||||
import net.corda.v5.application.flows.FlowEngine;
|
||||
import net.corda.v5.application.marshalling.JsonMarshallingService;
|
||||
import net.corda.v5.base.annotations.Suspendable;
|
||||
import net.corda.v5.base.exceptions.CordaRuntimeException;
|
||||
import net.corda.v5.crypto.SecureHash;
|
||||
import net.corda.v5.ledger.utxo.StateAndRef;
|
||||
import net.corda.v5.ledger.utxo.UtxoLedgerService;
|
||||
@ -47,12 +45,19 @@ public class ActionFlow implements ClientStartableFlow {
|
||||
final ActionFlowArgs args = requestBody.getRequestBodyAs(jsonMarshallingService, ActionFlowArgs.class);
|
||||
final Action action = args.getAction();
|
||||
|
||||
final StateAndRef<GameProposalState> inputState = findUnconsumedGameProposalState(args.getGameProposalUuid());
|
||||
final StateAndRef<GameProposalState> utxoGameProposal = findUnconsumedGameProposalState(args.getGameProposalUuid());
|
||||
|
||||
final UtxoSignedTransaction trx = prepareSignedTransaction(action, inputState);
|
||||
final UtxoSignedTransaction trx = prepareSignedTransaction(action, utxoGameProposal);
|
||||
|
||||
final SecureHash trxId = this.flowEngine
|
||||
.subFlow( new CommitSubFlow(trx, action.getReceiver(inputState)) );
|
||||
.subFlow( new CommitSubFlow(trx, action.getRespondent(utxoGameProposal)) );
|
||||
|
||||
if (action == Action.ACCEPT) {
|
||||
GameBoardState newGb = (GameBoardState)trx.getOutputStateAndRefs().get(0).getState().getContractState();
|
||||
|
||||
return new FlowResult(newGb.getId(), trxId)
|
||||
.toJsonEncodedString(jsonMarshallingService);
|
||||
}
|
||||
|
||||
return new FlowResult(action+"ED", trxId) // REJECT+ED
|
||||
.toJsonEncodedString(jsonMarshallingService);
|
||||
@ -71,36 +76,31 @@ public class ActionFlow implements ClientStartableFlow {
|
||||
* Note, this is an inefficient way to perform this operation if there are a large
|
||||
* number of 'active' GameProposals exists in storage.
|
||||
*/
|
||||
List<StateAndRef<GameProposalState>> stateAndRefs = this.ledgerService
|
||||
return this.ledgerService
|
||||
.findUnconsumedStatesByType(GameProposalState.class)
|
||||
.stream()
|
||||
.filter(sar -> sar.getState().getContractState().getId().equals(gameProposalUuid))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (stateAndRefs.size() != 1) {
|
||||
throw new CordaRuntimeException("Expected only one GameProposal state with id " + gameProposalUuid +
|
||||
", but found " + stateAndRefs.size());
|
||||
}
|
||||
|
||||
return stateAndRefs.get(0);
|
||||
.reduce((a, b) -> {throw new IllegalStateException("Multiple states: " +a +", " +b);})
|
||||
.get();
|
||||
}
|
||||
|
||||
@Suspendable
|
||||
private UtxoSignedTransaction prepareSignedTransaction(
|
||||
Action action,
|
||||
StateAndRef<GameProposalState> inputState
|
||||
StateAndRef<GameProposalState> utxoGameProposal
|
||||
) {
|
||||
UtxoTransactionBuilder trxBuilder = ledgerService.createTransactionBuilder()
|
||||
.setNotary(inputState.getState().getNotaryName())
|
||||
.setNotary(utxoGameProposal.getState().getNotaryName())
|
||||
.setTimeWindowBetween(Instant.now(), Instant.now().plusMillis(Duration.ofDays(1).toMillis()))
|
||||
.addInputState(inputState.getRef())
|
||||
.addInputState(utxoGameProposal.getRef())
|
||||
.addCommand(action)
|
||||
.addSignatories(inputState.getState().getContractState().getParticipants());
|
||||
.addSignatories(utxoGameProposal.getState().getContractState().getParticipants());
|
||||
|
||||
if (action == Action.ACCEPT) {
|
||||
// TODO
|
||||
// .addOutputState(outputState)
|
||||
throw new RuntimeException(action +" unimplemented");
|
||||
trxBuilder = trxBuilder
|
||||
.addOutputState(new GameBoardState(utxoGameProposal));
|
||||
//A state cannot be both an input and a reference input in the same transaction
|
||||
//.addReferenceState(utxoGameProposal.getRef());
|
||||
}
|
||||
|
||||
return trxBuilder.toSignedTransaction();
|
||||
|
@ -21,6 +21,7 @@ import static djmil.cordacheckers.contracts.GameProposalContract.Action;
|
||||
|
||||
@InitiatedBy(protocol = "game-proposal")
|
||||
public class CommitResponderFlow implements ResponderFlow {
|
||||
|
||||
private final static Logger log = LoggerFactory.getLogger(CommitResponderFlow.class);
|
||||
|
||||
@CordaInject
|
||||
@ -38,7 +39,7 @@ public class CommitResponderFlow implements ResponderFlow {
|
||||
|
||||
final GameProposalState gameProposal = getGameProposal(ledgerTransaction);
|
||||
|
||||
checkSessionParticipants(session, gameProposal, action);
|
||||
checkParticipants(session, gameProposal, action);
|
||||
|
||||
/*
|
||||
* Other checks / actions ?
|
||||
@ -59,7 +60,7 @@ public class CommitResponderFlow implements ResponderFlow {
|
||||
}
|
||||
|
||||
@Suspendable
|
||||
void checkSessionParticipants(
|
||||
void checkParticipants(
|
||||
FlowSession session,
|
||||
GameProposalState gameProposal,
|
||||
Action action
|
||||
@ -90,6 +91,6 @@ public class CommitResponderFlow implements ResponderFlow {
|
||||
default:
|
||||
throw new RuntimeException(Action.UNSUPPORTED_ACTION_VALUE_OF +action);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ import net.corda.v5.application.flows.ClientRequestBody;
|
||||
import net.corda.v5.application.flows.ClientStartableFlow;
|
||||
import net.corda.v5.application.flows.CordaInject;
|
||||
import net.corda.v5.application.flows.FlowEngine;
|
||||
import net.corda.v5.application.flows.InitiatingFlow;
|
||||
import net.corda.v5.application.marshalling.JsonMarshallingService;
|
||||
import net.corda.v5.application.membership.MemberLookup;
|
||||
import net.corda.v5.base.annotations.Suspendable;
|
||||
|
@ -29,7 +29,7 @@ public class ListFlow implements ClientStartableFlow {
|
||||
@Override
|
||||
public String call(ClientRequestBody requestBody) {
|
||||
try {
|
||||
log.info("ListChatsFlow.call() called");
|
||||
log.info("ListFlow.call() called");
|
||||
|
||||
// Queries the VNode's vault for unconsumed states and converts the resulting
|
||||
// List<StateAndRef<GameProposalState>> to a _serializable_ List<ListItem> DTO
|
||||
@ -41,7 +41,7 @@ public class ListFlow implements ClientStartableFlow {
|
||||
|
||||
return new FlowResult(unconsumedGameProposaList).toJsonEncodedString(jsonMarshallingService);
|
||||
} catch (Exception e) {
|
||||
log.warn("CreateGameProposal flow failed to process utxo request body " + requestBody + " because: " + e.getMessage());
|
||||
log.warn("ListFlow failed to process utxo request body " + requestBody + " because: " + e.getMessage());
|
||||
return new FlowResult(e).toJsonEncodedString(jsonMarshallingService);
|
||||
}
|
||||
}
|
||||
|
@ -3,16 +3,17 @@ package djmil.cordacheckers.gameproposal;
|
||||
import java.util.UUID;
|
||||
|
||||
import djmil.cordacheckers.states.GameProposalState;
|
||||
import djmil.cordacheckers.states.Piece;
|
||||
|
||||
// Class to hold results of the List flow.
|
||||
// The GameProposal(s) cannot be returned directly as the JsonMarshallingService can only serialize simple classes
|
||||
// that the underlying Jackson serializer recognises, hence creating a DTO style object which consists only of Strings
|
||||
// and a UUID. It is possible to create custom serializers for the JsonMarshallingService in the future.
|
||||
// JsonMarshallingService can only serialize simple classes that the underlying Jackson serializer recognises,
|
||||
// hence creating a DTO style object which consists only of Strings and a UUIDs. It is possible to create custom
|
||||
// serializers for the JsonMarshallingService in the future.
|
||||
|
||||
public class ListItem {
|
||||
public final String issuer;
|
||||
public final String acquier;
|
||||
public final String acquierColor;
|
||||
public final Piece.Color acquierColor;
|
||||
public final String message;
|
||||
public final UUID id;
|
||||
|
||||
@ -28,7 +29,7 @@ public class ListItem {
|
||||
public ListItem(GameProposalState state) {
|
||||
this.issuer = state.getIssuer().getCommonName();
|
||||
this.acquier = state.getAcquier().getCommonName();
|
||||
this.acquierColor = state.getRecipientColor().name();
|
||||
this.acquierColor = state.getAcquierColor();
|
||||
this.message = state.getMessage();
|
||||
this.id = state.getId();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user