Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions .github/workflows/pr-preprod-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,8 @@ jobs:
# Output test result
echo "construction_result=${CONSTRUCTION_RESULT:-0}" >> $GITHUB_OUTPUT

# Don't fail the whole job if construction tests fail
# These are informational for now
exit 0
# Fail if construction tests failed
exit ${CONSTRUCTION_RESULT:-0}
env:
ROSETTA_URL: http://localhost:8082
CARDANO_NETWORK: preprod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
import java.math.BigInteger;
import java.util.*;

import static org.cardanofoundation.rosetta.common.util.Constants.ADA;
import static org.cardanofoundation.rosetta.common.util.Constants.ADA_DECIMALS;

@Component
@RequiredArgsConstructor
public class AccountMapperUtil {
Expand Down Expand Up @@ -76,7 +79,7 @@ public List<Coin> mapUtxosToCoins(List<Utxo> utxos,
Amt adaAsset = utxo.getAmounts().stream()
.filter(amt -> Constants.LOVELACE.equals(amt.getUnit()))
.findFirst()
.orElseGet(() -> new Amt(null, Constants.ADA, BigInteger.ZERO));
.orElseGet(() -> new Amt(null, ADA, BigInteger.ZERO));

String coinIdentifier = "%s:%d".formatted(utxo.getTxHash(), utxo.getOutputIndex());

Expand Down Expand Up @@ -144,8 +147,8 @@ private static int getDecimalsWithFallback(@NotNull TokenRegistryCurrencyData me

private CurrencyResponse getAdaCurrency() {
return CurrencyResponse.builder()
.symbol(Constants.ADA)
.decimals(Constants.ADA_DECIMALS)
.symbol(ADA)
.decimals(ADA_DECIMALS)
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public class CardanoConstructionServiceImpl implements CardanoConstructionServic

private final LedgerBlockService ledgerBlockService;
private final ProtocolParamService protocolParamService;
private final OperationService operationService;
private final TransactionOperationParser transactionOperationParser;
private final RestTemplate restTemplate;
private final OfflineSlotService offlineSlotService;

Expand All @@ -89,22 +89,27 @@ public class CardanoConstructionServiceImpl implements CardanoConstructionServic
@Override
public TransactionParsed parseTransaction(Network network, String transaction, boolean signed) {
Array decodeTransaction = decodeTransaction(transaction);

try {
TransactionData convertedTr = CborArrayToTransactionData.convert(decodeTransaction, signed);
List<Operation> operations = operationService.getOperationsFromTransactionData(convertedTr, network);
List<Operation> operations = transactionOperationParser.getOperationsFromTransactionData(convertedTr, network);
List<AccountIdentifier> accountIdentifierSigners = new ArrayList<>();

if (signed) {
log.info("[parseSignedTransaction] About to get signatures from parsed transaction");
List<String> accumulator = convertedTr.transactionExtraData().operations().stream()
.map(o -> operationService.getSignerFromOperation(network, o))
.map(o -> transactionOperationParser.getSignerFromOperation(network, o))
.flatMap(List::stream)
.toList();

accountIdentifierSigners = getUniqueAccountIdentifiers(accumulator);
}

return new TransactionParsed(operations, accountIdentifierSigners);
} catch (CborException | CborDeserializationException | CborSerializationException error) {
log.error("{} [parseTransaction] Cant instantiate transaction from transaction bytes",
error.getMessage(), error);

throw ExceptionFactory.invalidTransactionError();
}
}
Expand Down Expand Up @@ -624,7 +629,7 @@ private TransactionBody deserializeTransactionBody(String unsignedTransaction) {
private List<AccountIdentifier> getUniqueAccountIdentifiers(List<String> addresses) {
return new HashSet<>(addresses)
.stream()
.map(s -> new AccountIdentifier(s, null, null))
.map(address -> new AccountIdentifier(address, null, null))
.toList();
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package org.cardanofoundation.rosetta.api.construction.service;

import co.nstant.in.cbor.CborException;
import com.bloxbean.cardano.client.common.model.Network;
import com.bloxbean.cardano.client.exception.CborDeserializationException;
import com.bloxbean.cardano.client.exception.CborSerializationException;
import org.cardanofoundation.rosetta.common.model.cardano.transaction.TransactionData;
import org.openapitools.client.model.Operation;

import java.util.List;

/**
* Parser interface for extracting Rosetta operations from Cardano transactions.
* <p>
* This parser handles the conversion between Cardano transaction structures and Rosetta API
* operations, including inputs, outputs, certificates (staking, pool, governance), and withdrawals.
* </p>
*/
public interface TransactionOperationParser {

/**
* Extracts and constructs a complete list of Rosetta operations from transaction data.
* <p>
* This method processes all operation types from a Cardano transaction, including:
* <ul>
* <li>Input operations - UTxO consumption</li>
* <li>Output operations - UTxO creation</li>
* <li>Certificate operations - Staking registrations, delegations, pool operations</li>
* <li>Governance operations - DRep vote delegations, pool governance votes</li>
* <li>Withdrawal operations - Staking reward withdrawals</li>
* </ul>
* </p>
*
* @param data the transaction data containing the transaction body and extra metadata
* @param network the Cardano network (mainnet/testnet) for address generation
* @return a list of Rosetta operations representing all transaction activities
* @throws CborDeserializationException if CBOR deserialization fails
* @throws CborException if CBOR processing encounters an error
* @throws CborSerializationException if CBOR serialization fails
*/
List<Operation> getOperationsFromTransactionData(TransactionData data, Network network)
throws CborDeserializationException, CborException, CborSerializationException;

/**
* Determines the required signers for a given operation.
* <p>
* Different operation types require different signers:
* <ul>
* <li>Pool operations - Pool owners, reward address, and optionally payment address</li>
* <li>Staking operations - Stake address derived from staking credential</li>
* <li>Regular operations - Account address from the operation</li>
* </ul>
* </p>
*
* @param network the Cardano network for address generation
* @param operation the operation to extract signers from
* @return list of addresses that must sign this operation
*/
List<String> getSignerFromOperation(Network network, Operation operation);

}
Loading
Loading