-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #325 from Concordium/extend-examples
Extend examples
- Loading branch information
Showing
13 changed files
with
915 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
concordium-sdk-examples/src/main/java/com/concordium/sdk/examples/Aliases.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package com.concordium.sdk.examples; | ||
|
||
import com.concordium.sdk.types.AccountAddress; | ||
import picocli.CommandLine; | ||
|
||
import java.util.List; | ||
import java.util.concurrent.Callable; | ||
|
||
/** | ||
* Utility to check whether a list of accounts are all aliases of each other. | ||
*/ | ||
@CommandLine.Command(name = "Aliases", mixinStandardHelpOptions = true) | ||
public class Aliases implements Callable<Integer> { | ||
|
||
@CommandLine.Parameters( | ||
description = "List of addresses to check", | ||
arity = "2..." ) | ||
List<String> addresses; | ||
@Override | ||
public Integer call() throws Exception { | ||
String first = addresses.remove(0); | ||
AccountAddress addr = AccountAddress.from(first); | ||
for (String address : addresses) { | ||
|
||
if (!addr.isAliasOf(AccountAddress.from(address))) { | ||
System.out.println(address + " is not an alias of " + first); | ||
return 0; | ||
} | ||
} | ||
System.out.println("All addresses are aliases"); | ||
return 0; | ||
} | ||
|
||
public static void main(String[] args) { | ||
int exitCode = new CommandLine(new Aliases()).execute(args); | ||
System.exit(exitCode); | ||
} | ||
} |
183 changes: 183 additions & 0 deletions
183
concordium-sdk-examples/src/main/java/com/concordium/sdk/examples/BlockStats.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
package com.concordium.sdk.examples; | ||
|
||
import com.concordium.sdk.ClientV2; | ||
import com.concordium.sdk.Connection; | ||
import com.concordium.sdk.TLSConfig; | ||
import com.concordium.sdk.exceptions.ClientInitializationException; | ||
import com.concordium.sdk.requests.BlockQuery; | ||
import com.concordium.sdk.responses.BlockIdentifier; | ||
import com.concordium.sdk.responses.FinalizedBlockItemIterator; | ||
import com.concordium.sdk.responses.blockinfo.BlockInfo; | ||
import com.concordium.sdk.responses.blocksummary.specialoutcomes.PaydayAccountReward; | ||
import com.concordium.sdk.responses.blocksummary.specialoutcomes.PaydayFoundationReward; | ||
import com.concordium.sdk.responses.blocksummary.specialoutcomes.PaydayPoolReward; | ||
import com.concordium.sdk.responses.blocksummary.specialoutcomes.SpecialOutcome; | ||
import com.concordium.sdk.types.AbsoluteBlockHeight; | ||
import com.google.common.collect.ImmutableList; | ||
import picocli.CommandLine; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.net.URL; | ||
import java.time.ZonedDateTime; | ||
import java.time.format.DateTimeFormatter; | ||
import java.time.temporal.ChronoUnit; | ||
import java.util.Objects; | ||
import java.util.Optional; | ||
import java.util.concurrent.Callable; | ||
|
||
/** | ||
* Traverse blocks in a given span and query statistics. | ||
* For each block print | ||
* - Block hash | ||
* - Block slot time | ||
* - Receive time of the block at the given node | ||
* - Arrive time of the block at the given node | ||
* - Difference between receive and slot times | ||
* - Difference between arrive and slot times | ||
* - Number of events associated with payday | ||
* - Whether the block contains a finalization record | ||
* - The number of transactions included in the block | ||
*/ | ||
@CommandLine.Command(name = "BlockStats", mixinStandardHelpOptions = true) | ||
public class BlockStats implements Callable<Integer> { | ||
|
||
@CommandLine.Option( | ||
names = {"--endpoint"}, | ||
description = "GRPC interface of the node.", | ||
defaultValue = "http://localhost:20002") | ||
private String endpoint; | ||
|
||
@CommandLine.Option( | ||
names = {"--tls"}, | ||
description = "Whether to use TLS. Uses default trust store. Use --tls-path to supply certificate" | ||
) | ||
private boolean useTLS; | ||
|
||
@CommandLine.Option( | ||
names = {"--tls-path"}, | ||
description = "Path to the server certificate" | ||
) | ||
private Optional<String> tlsPath; | ||
|
||
@CommandLine.Option( | ||
names = {"--timeout"}, | ||
description = "GRPC request timeout in milliseconds.", | ||
defaultValue = "100000") | ||
private int timeout; | ||
|
||
@CommandLine.Option( | ||
names = {"--from"}, | ||
description = "Starting time (format 2024-01-22T10:15:30+01:00). Defaults to genesis" | ||
) | ||
private Optional<String> fromString; | ||
|
||
@CommandLine.Option( | ||
names = {"--to"}, | ||
description = "End time (format 2024-01-22T10:15:30+01:00). Defaults to the time the tool has run" | ||
) | ||
private Optional<String> toString; | ||
|
||
@Override | ||
public Integer call() throws IOException, ClientInitializationException { | ||
URL endpointUrl = new URL(this.endpoint); | ||
Connection.ConnectionBuilder connection = Connection.newBuilder() | ||
.host(endpointUrl.getHost()) | ||
.port(endpointUrl.getPort()) | ||
.timeout(timeout); | ||
|
||
if (useTLS) { | ||
if (tlsPath.isPresent()) { | ||
connection = connection.useTLS(TLSConfig.from(new File(tlsPath.get()))); | ||
} else { | ||
connection = connection.useTLS(TLSConfig.auto()); | ||
} | ||
} | ||
|
||
ClientV2 client = ClientV2.from(connection.build()); | ||
|
||
AbsoluteBlockHeight start; | ||
if (fromString.isPresent()) { | ||
ZonedDateTime from = ZonedDateTime.parse(fromString.get(), DateTimeFormatter.ISO_OFFSET_DATE_TIME); | ||
Optional<BlockInfo> startBlock = client.findAtLowestHeight((clientV2, query) -> { | ||
BlockInfo blockInfo = clientV2.getBlockInfo(query); | ||
ZonedDateTime blockTime = blockInfo.getBlockTime().getZonedDateTime(); | ||
if (from.isBefore(blockTime)) { | ||
return Optional.of(blockInfo); | ||
} else { | ||
return Optional.empty(); | ||
} | ||
|
||
}); | ||
if (startBlock.isPresent()) { | ||
start = AbsoluteBlockHeight.from(startBlock.get().getBlockHeight()); | ||
} else { | ||
throw new IllegalArgumentException("Last finalized block is not after the requested start time."); | ||
} | ||
|
||
} else { | ||
start = AbsoluteBlockHeight.from(0); | ||
} | ||
|
||
int blockCount = 0; | ||
int finalizationCount = 0; | ||
FinalizedBlockItemIterator blocks = client.getFinalizedBlocksFrom(start); | ||
ZonedDateTime endTime; | ||
endTime = toString.map(s -> ZonedDateTime.parse(s, DateTimeFormatter.ISO_OFFSET_DATE_TIME)).orElseGet(ZonedDateTime::now); | ||
String format = "%1$-64s | %2$-29s | %3$-29s | %4$-29s | %5$-13s | %6$-12s | %7$-14s | %8$-17s | %9$-17s | %10$-7s | %11$-6s | %12$-8s\n"; | ||
System.out.printf(format, | ||
"Block hash", "block time", "block receive time", "block arrive time", "receive delta", "arrive" + | ||
" delta", "#payday events", "finalization data", "transaction count", "round", "epoch", "baker id"); | ||
while (blocks.hasNext()) { | ||
BlockIdentifier block = blocks.next(); | ||
BlockQuery blockQuery = BlockQuery.HASH(block.getBlockHash()); | ||
BlockInfo blockInfo = client.getBlockInfo(blockQuery); | ||
ZonedDateTime blockTime = blockInfo.getBlockTime().getZonedDateTime(); | ||
if (endTime.isBefore(blockTime)) { | ||
break; | ||
} | ||
|
||
int paydayBlock = 0; | ||
ImmutableList<SpecialOutcome> events = client.getBlockSpecialEvents(blockQuery); | ||
for (SpecialOutcome event: events) { | ||
if (event.getClass().equals(PaydayFoundationReward.class) || event.getClass().equals(PaydayAccountReward.class) || event.getClass().equals(PaydayPoolReward.class)) { | ||
paydayBlock++; | ||
} | ||
} | ||
boolean hasFinalizationData = client.getBlockFinalizationSummary(blockQuery).isPresent(); | ||
|
||
System.out.printf(format, | ||
blockInfo.getBlockHash(), | ||
blockInfo.getBlockTime(), | ||
blockInfo.getBlockReceiveTime(), | ||
blockInfo.getBlockArriveTime(), | ||
ChronoUnit.MILLIS.between(blockInfo.getBlockTime().getZonedDateTime(), blockInfo.getBlockReceiveTime().getZonedDateTime()), | ||
ChronoUnit.MILLIS.between(blockInfo.getBlockTime().getZonedDateTime(), blockInfo.getBlockArriveTime().getZonedDateTime()), | ||
paydayBlock, | ||
hasFinalizationData, | ||
blockInfo.getTransactionCount(), | ||
blockInfo.getRound().isPresent() ? blockInfo.getRound().get().getValue().toString() : "", | ||
blockInfo.getEpoch().isPresent() ? blockInfo.getEpoch().get().getValue().toString() : "", | ||
Objects.isNull(blockInfo.getBlockBaker()) ? "" : blockInfo.getBlockBaker().toString() | ||
|
||
); | ||
|
||
if (hasFinalizationData) { | ||
finalizationCount++; | ||
} | ||
blockCount++; | ||
|
||
} | ||
blocks.drop(); | ||
System.out.println("Block count: " + blockCount); | ||
System.out.println("Finalization record count: " + finalizationCount); | ||
|
||
return 0; | ||
} | ||
|
||
public static void main(String[] args) { | ||
int exitCode = new CommandLine(new BlockStats()).execute(args); | ||
System.exit(exitCode); | ||
} | ||
} | ||
|
111 changes: 111 additions & 0 deletions
111
concordium-sdk-examples/src/main/java/com/concordium/sdk/examples/FindAccount.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
package com.concordium.sdk.examples; | ||
|
||
import com.concordium.sdk.ClientV2; | ||
import com.concordium.sdk.Connection; | ||
import com.concordium.sdk.TLSConfig; | ||
import com.concordium.sdk.exceptions.ClientInitializationException; | ||
import com.concordium.sdk.requests.BlockQuery; | ||
import com.concordium.sdk.responses.FindAccountResponse; | ||
import com.concordium.sdk.responses.blockinfo.BlockInfo; | ||
import com.concordium.sdk.responses.blockitemsummary.Details; | ||
import com.concordium.sdk.responses.blockitemsummary.Summary; | ||
import com.concordium.sdk.responses.blockitemsummary.Type; | ||
import com.concordium.sdk.transactions.*; | ||
import com.concordium.sdk.types.AccountAddress; | ||
import picocli.CommandLine; | ||
|
||
import java.io.File; | ||
import java.net.MalformedURLException; | ||
import java.net.URL; | ||
import java.util.Iterator; | ||
import java.util.Optional; | ||
import java.util.concurrent.Callable; | ||
|
||
/** | ||
* Find out when a given account was created on the chain. | ||
* That is, the block in which the account creation transaction is committed. | ||
*/ | ||
@CommandLine.Command(name = "FindAccount", mixinStandardHelpOptions = true) | ||
public class FindAccount implements Callable<Integer> { | ||
|
||
@CommandLine.Option( | ||
names = {"--endpoint"}, | ||
description = "GRPC interface of the node.", | ||
defaultValue = "http://localhost:20002") | ||
private String endpoint; | ||
|
||
@CommandLine.Option( | ||
names = {"--tls"}, | ||
description = "Whether to use TLS. Uses default trust store. Use --tls-path to supply certificate" | ||
) | ||
private boolean useTLS; | ||
|
||
@CommandLine.Option( | ||
names = {"--tls-path"}, | ||
description = "Path to the server certificate" | ||
) | ||
private Optional<String> tlsPath; | ||
|
||
@CommandLine.Option( | ||
names = {"--timeout"}, | ||
description = "GRPC request timeout in milliseconds.", | ||
defaultValue = "100000") | ||
private int timeout; | ||
|
||
@CommandLine.Option( | ||
names = {"--a", "--account"}, | ||
description = "Account to look for", | ||
defaultValue = "4AuT5RRmBwcdkLMA6iVjxTDb1FQmxwAh3wHBS22mggWL8xH6s3") | ||
private String account; | ||
|
||
@Override | ||
public Integer call() throws MalformedURLException, ClientInitializationException { | ||
URL endpointUrl = new URL(this.endpoint); | ||
Connection.ConnectionBuilder connection = Connection.newBuilder() | ||
.host(endpointUrl.getHost()) | ||
.port(endpointUrl.getPort()) | ||
.timeout(timeout); | ||
|
||
if (useTLS) { | ||
if (tlsPath.isPresent()) { | ||
connection = connection.useTLS(TLSConfig.from(new File(tlsPath.get()))); | ||
} else { | ||
connection = connection.useTLS(TLSConfig.auto()); | ||
} | ||
} | ||
|
||
ClientV2 client = ClientV2.from(connection.build()); | ||
|
||
Optional<FindAccountResponse> response = client.findAccountCreation(AccountAddress.from(account)); | ||
|
||
boolean isEmpty = !response.isPresent(); | ||
|
||
if (isEmpty) { | ||
System.out.println("Account not found."); | ||
return 0; | ||
} | ||
Hash blockHash = response.get().getBlockHash(); | ||
BlockQuery blockQuery = BlockQuery.HASH(blockHash); | ||
System.out.println("Account created in block: " + blockHash); | ||
BlockInfo blockInfo = client.getBlockInfo(blockQuery); | ||
System.out.println("Timestamp of the block: " + blockInfo.getBlockTime()); | ||
Iterator<Summary> summaries = client.getBlockTransactionEvents(blockQuery); | ||
while (summaries.hasNext()) { | ||
Summary summary = summaries.next(); | ||
Details details = summary.getDetails(); | ||
if (details.getType() == Type.ACCOUNT_CREATION) { | ||
if (details.getAccountCreationDetails().getAddress().isAliasOf(AccountAddress.from(account))) { | ||
System.out.println("Created by transaction hash: " + summary.getTransactionHash()); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
public static void main(String[] args) { | ||
int exitCode = new CommandLine(new FindAccount()).execute(args); | ||
System.exit(exitCode); | ||
} | ||
} |
Oops, something went wrong.