Skip to content

EVM-14: EVM domain port interfaces #151

@Puneethkumarck

Description

@Puneethkumarck

Context

In the hexagonal architecture, domain ports define the contracts that infrastructure adapters must implement. The EVM extension needs its own set of repository ports for blocks, transactions, failed transactions, large transfers, token transfers, accounts, stats, and a block stream port for the streaming adapter.

Specification

Package

`prism/src/main/java/com/stablebridge/prism/domain/port/`

Interfaces to create

EvmBlockStream
```java
public interface EvmBlockStream {
void subscribe(Consumer blockConsumer, Consumer<List> txConsumer);
void close();
}
```

Note: `subscribe` takes two consumers (block + transaction list). Methods are `subscribe` and `close` (not `start`/`stop`/`isRunning`).

EvmTransactionRepository
```java
public interface EvmTransactionRepository {
void bulkInsert(List transactions);
Optional findByHash(TransactionHash hash);
Page findByBlockNumber(long blockNumber, int limit, int offset);
Page findAll(int limit, int offset);
long countAll();
void deleteAboveBlock(long blockNumber);
}
```

Note: Method is `bulkInsert` (not `saveAll`). `findByHash` takes only `TransactionHash` (no `chainId` parameter). `findAll` and `countAll` with no filter parameters.

EvmFailedTransactionRepository
```java
public interface EvmFailedTransactionRepository {
void bulkInsert(List transactions);
void deleteAboveBlock(long blockNumber);
}
```

Note: Only `bulkInsert` and `deleteAboveBlock`. No find/query methods.

EvmTransferRepository
```java
public interface EvmTransferRepository {
void bulkInsert(List transfers);
Page findByMinAmount(BigDecimal minAmount, int limit, int offset);
long countByMinAmount(BigDecimal minAmount);
void deleteAboveBlock(long blockNumber);
}
```

Note: `findByMinAmount` and `countByMinAmount` (not `findRecent`/`findByAddress`).

EvmTokenTransferRepository
```java
public interface EvmTokenTransferRepository {
void bulkInsert(List transfers);
Page findAll(int limit, int offset);
Page findByToken(EvmAddress tokenAddress, int limit, int offset);
long countAll();
void deleteAboveBlock(long blockNumber);
}
```

Note: `findAll`, `findByToken`, `countAll`. No `findByAddress` or `findRecent`.

EvmAccountRepository
```java
public interface EvmAccountRepository {
void batchUpsert(List accounts);
Optional findByAddress(EvmAddress address);
}
```

Note: `batchUpsert` (not `saveAll`). `findByAddress` (no `chainId` parameter). NO `deleteAboveBlock` — accounts are not rolled back on reorg (cumulative counts remain, acceptable approximation for v1).

EvmBlockRepository
```java
public interface EvmBlockRepository {
void insert(EvmBlock block);
Optional findByNumber(long blockNumber);
Page findAll(int limit, int offset);
void deleteAboveBlock(long blockNumber);
long latestBlockNumber();
}
```

Note: `insert` (not `save`). Includes `latestBlockNumber()`. No `findLatest`.

EvmStatsRepository
```java
public interface EvmStatsRepository {
EvmIndexerStats getStats();
}
```

Note: `getStats()` takes no parameters (no `chainId`).

Design decisions

  • Plain interfaces with no annotations (not `@Singleton`, not `@Component`)
  • All method signatures use domain value objects (`TransactionHash`, `EvmAddress`, `EvmBlock`, etc.)
  • Reuse the existing `Page` type from the API module for paginated results
  • `EvmAccountRepository` does NOT have `deleteAboveBlock` — accounts are not rolled back during reorg (per functional spec section 4: "Account table is NOT rolled back — cumulative counts remain")
  • `bulkInsert` / `batchUpsert` naming for batch write operations
  • Follow existing Solana port patterns (`TransactionRepository`, `AccountRepository`, etc.)
  • `EvmBlockStream` follows a consumer-based subscription pattern

Acceptance Criteria

  • All 8 interfaces exist in the domain port package
  • All interfaces use domain value objects in their method signatures
  • `EvmTransactionRepository`: `bulkInsert`, `findByHash`, `findByBlockNumber`, `findAll`, `countAll`, `deleteAboveBlock`
  • `EvmFailedTransactionRepository`: `bulkInsert`, `deleteAboveBlock` only
  • `EvmTransferRepository`: `bulkInsert`, `findByMinAmount`, `countByMinAmount`, `deleteAboveBlock`
  • `EvmTokenTransferRepository`: `bulkInsert`, `findAll`, `findByToken`, `countAll`, `deleteAboveBlock`
  • `EvmAccountRepository`: `batchUpsert`, `findByAddress` — NO `deleteAboveBlock`
  • `EvmBlockRepository`: `insert`, `findByNumber`, `findAll`, `deleteAboveBlock`, `latestBlockNumber`
  • `EvmStatsRepository`: `getStats()` with no parameters
  • `EvmBlockStream`: `subscribe(Consumer, Consumer<List>)`, `close()`
  • No framework annotations on the interfaces
  • Zero framework imports (only `java.*` types and domain model types)
  • `./gradlew build` passes

Dependencies

References

Metadata

Metadata

Labels

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions