diff --git a/.github/workflows/gradle-build.yml b/.github/workflows/gradle-build.yml index fda5432c..96ff1894 100644 --- a/.github/workflows/gradle-build.yml +++ b/.github/workflows/gradle-build.yml @@ -9,18 +9,18 @@ on: jobs: build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 permissions: contents: read packages: write steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up JDK 8 - uses: actions/setup-java@v2 + uses: actions/setup-java@v3 with: java-version: '8' - distribution: 'adopt' + distribution: 'temurin' - name: Build with Gradle run: gradle build diff --git a/.github/workflows/gradle-publish.yml b/.github/workflows/gradle-publish.yml index e906088b..a1a39212 100644 --- a/.github/workflows/gradle-publish.yml +++ b/.github/workflows/gradle-publish.yml @@ -10,18 +10,18 @@ on: jobs: publish: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 permissions: contents: read packages: write steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up JDK 8 - uses: actions/setup-java@v2 + uses: actions/setup-java@v3 with: java-version: '8' - distribution: 'adopt' + distribution: 'temurin' - name: Build with Gradle run: gradle build diff --git a/api/build.gradle b/api/build.gradle index 8fe92f04..d81a3b52 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -1,19 +1,24 @@ dependencies { implementation project(':common') + implementation project(':crypto') implementation project(':pallet') implementation project(':rpc') - implementation project(':rpc:rpc-core') - implementation project(':rpc:rpc-sections') - implementation project(':rpc:rpc-types') + implementation project(':rpc:rpc-api') implementation project(':scale') - implementation project(':storage') implementation project(':transport') - implementation project(':types') + + api 'com.google.inject:guice:5.1.0' + + annotationProcessor project(':pallet:pallet-codegen') + annotationProcessor project(':rpc:rpc-codegen') testImplementation project(':tests') - testImplementation 'org.testcontainers:testcontainers:1.17.1' - testImplementation 'org.testcontainers:junit-jupiter:1.17.1' + testImplementation 'ch.qos.logback:logback-classic:1.2.11' + testImplementation 'org.testcontainers:testcontainers:1.17.3' + testImplementation 'org.testcontainers:junit-jupiter:1.17.3' + testImplementation 'org.awaitility:awaitility:4.2.0' + testImplementation 'org.hamcrest:hamcrest:2.2' testAnnotationProcessor project(':pallet:pallet-codegen') -} \ No newline at end of file +} diff --git a/api/src/main/java/com/strategyobject/substrateclient/api/Api.java b/api/src/main/java/com/strategyobject/substrateclient/api/Api.java index fbb8575f..8f8106d1 100644 --- a/api/src/main/java/com/strategyobject/substrateclient/api/Api.java +++ b/api/src/main/java/com/strategyobject/substrateclient/api/Api.java @@ -1,33 +1,73 @@ package com.strategyobject.substrateclient.api; -import com.strategyobject.substrateclient.pallet.GeneratedPalletResolver; -import com.strategyobject.substrateclient.rpc.Rpc; -import com.strategyobject.substrateclient.rpc.RpcImpl; +import com.google.inject.Module; +import com.strategyobject.substrateclient.pallet.PalletFactory; +import com.strategyobject.substrateclient.rpc.RpcSectionFactory; +import com.strategyobject.substrateclient.rpc.metadata.MetadataProvider; import com.strategyobject.substrateclient.transport.ProviderInterface; -import lombok.val; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Supplier; /** * Provides the ability to query a node and interact with the Polkadot or Substrate chains. * It allows interacting with blockchain in various ways: using RPC's queries directly or * accessing Pallets and its APIs, such as storages, transactions, etc. */ -public interface Api { - static DefaultApi with(ProviderInterface provider) { - val rpc = RpcImpl.with(provider); +@RequiredArgsConstructor +public class Api implements AutoCloseable { + private final @NonNull RpcSectionFactory rpcSectionFactory; + private final @NonNull PalletFactory palletFactory; + private final @NonNull MetadataProvider metadataProvider; + private final Map, Object> resolvedCache = new ConcurrentHashMap<>(); - return DefaultApi.with(rpc, GeneratedPalletResolver.with(rpc)); - } /** - * @return the instance that provides a proper API for querying the RPC's methods. + * Resolves the instance of a rpc by its definition. + * + * @param clazz the class of the rpc + * @param the type of the rpc + * @return appropriate instance of the rpc */ - Rpc rpc(); + public T rpc(@NonNull Class clazz) { + return clazz.cast(resolvedCache.computeIfAbsent(clazz, rpcSectionFactory::create)); + } /** * Resolves the instance of a pallet by its definition. + * * @param clazz the class of the pallet - * @param the type of the pallet + * @param the type of the pallet * @return appropriate instance of the pallet */ - T pallet(Class clazz); -} + public T pallet(@NonNull Class clazz) { + return clazz.cast(resolvedCache.computeIfAbsent(clazz, palletFactory::create)); + } + + /** + * Provides access to current version of metadata in use. + * + * @return MetadataProvider instance + */ + public MetadataProvider metadata() { + return metadataProvider; + } + + @Override + public void close() throws Exception { + if (rpcSectionFactory instanceof AutoCloseable) { + ((AutoCloseable) rpcSectionFactory).close(); + } + } + + public static ApiBuilder with(@NonNull Supplier providerInterface) { + return with(new DefaultModule(providerInterface.get())); + } + + public static ApiBuilder with(@NonNull M module) { + return new ApiBuilder<>(module); + } +} \ No newline at end of file diff --git a/api/src/main/java/com/strategyobject/substrateclient/api/ApiBuilder.java b/api/src/main/java/com/strategyobject/substrateclient/api/ApiBuilder.java new file mode 100644 index 00000000..d86e9b2d --- /dev/null +++ b/api/src/main/java/com/strategyobject/substrateclient/api/ApiBuilder.java @@ -0,0 +1,36 @@ +package com.strategyobject.substrateclient.api; + +import com.google.inject.Guice; +import com.google.inject.Module; +import com.strategyobject.substrateclient.transport.ProviderInterface; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.val; + +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; +import java.util.function.Function; + +@RequiredArgsConstructor +public class ApiBuilder { + private final @NonNull M module; + + public ApiBuilder configure(@NonNull Consumer configuration) { + configuration.accept(module); + return this; + } + + public ApiBuilder reconfigure(@NonNull Function configuration) { + return new ApiBuilder<>(configuration.apply(this.module)); + } + + public CompletableFuture build() { + val injector = Guice.createInjector(new RequireModule(), module); + val provider = injector.getInstance(ProviderInterface.class); + val result = provider.isConnected() ? + CompletableFuture.completedFuture(null) : + provider.connect(); + + return result.thenApply(ignored -> injector.getInstance(Api.class)); + } +} diff --git a/api/src/main/java/com/strategyobject/substrateclient/api/DefaultApi.java b/api/src/main/java/com/strategyobject/substrateclient/api/DefaultApi.java deleted file mode 100644 index 2ca53390..00000000 --- a/api/src/main/java/com/strategyobject/substrateclient/api/DefaultApi.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.strategyobject.substrateclient.api; - -import com.strategyobject.substrateclient.pallet.PalletResolver; -import com.strategyobject.substrateclient.rpc.Rpc; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -@RequiredArgsConstructor(staticName = "with") -public class DefaultApi implements Api, AutoCloseable { - private final @NonNull Rpc rpc; - private final @NonNull PalletResolver palletResolver; - private final Map, Object> palletCache = new ConcurrentHashMap<>(); - - @Override - public Rpc rpc() { - return rpc; - } - - @Override - public T pallet(@NonNull Class clazz) { - return clazz.cast(palletCache - .computeIfAbsent(clazz, palletResolver::resolve)); - } - - @Override - public void close() throws Exception { - if (rpc instanceof AutoCloseable) { - ((AutoCloseable) rpc).close(); - } - } -} \ No newline at end of file diff --git a/api/src/main/java/com/strategyobject/substrateclient/api/DefaultModule.java b/api/src/main/java/com/strategyobject/substrateclient/api/DefaultModule.java new file mode 100644 index 00000000..d9206626 --- /dev/null +++ b/api/src/main/java/com/strategyobject/substrateclient/api/DefaultModule.java @@ -0,0 +1,223 @@ +package com.strategyobject.substrateclient.api; + +import com.google.inject.AbstractModule; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import com.strategyobject.substrateclient.api.pallet.balances.AccountData; +import com.strategyobject.substrateclient.api.pallet.balances.AccountDataReader; +import com.strategyobject.substrateclient.api.pallet.system.System; +import com.strategyobject.substrateclient.common.types.Lambda; +import com.strategyobject.substrateclient.crypto.ss58.SS58AddressFormat; +import com.strategyobject.substrateclient.pallet.GeneratedPalletFactory; +import com.strategyobject.substrateclient.pallet.PalletFactory; +import com.strategyobject.substrateclient.pallet.events.EventDescriptor; +import com.strategyobject.substrateclient.pallet.events.EventDescriptorReader; +import com.strategyobject.substrateclient.pallet.events.EventRegistry; +import com.strategyobject.substrateclient.rpc.GeneratedRpcSectionFactory; +import com.strategyobject.substrateclient.rpc.RpcSectionFactory; +import com.strategyobject.substrateclient.rpc.api.section.State; +import com.strategyobject.substrateclient.rpc.context.RpcDecoderContext; +import com.strategyobject.substrateclient.rpc.context.RpcDecoderContextFactory; +import com.strategyobject.substrateclient.rpc.context.RpcEncoderContext; +import com.strategyobject.substrateclient.rpc.context.RpcEncoderContextFactory; +import com.strategyobject.substrateclient.rpc.metadata.ManualMetadataProvider; +import com.strategyobject.substrateclient.rpc.metadata.MetadataProvider; +import com.strategyobject.substrateclient.rpc.metadata.Pallet; +import com.strategyobject.substrateclient.rpc.metadata.PalletCollection; +import com.strategyobject.substrateclient.rpc.registries.RpcDecoderRegistry; +import com.strategyobject.substrateclient.rpc.registries.RpcEncoderRegistry; +import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; +import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; +import com.strategyobject.substrateclient.transport.ProviderInterface; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.val; + +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +@RequiredArgsConstructor +public class DefaultModule extends AbstractModule { + private static final String PREFIX = "com.strategyobject.substrateclient"; + + private final @NonNull ProviderInterface providerInterface; + + private Consumer configureScaleReaderRegistry = Lambda::noop; + private Consumer configureScaleWriterRegistry = Lambda::noop; + private BiConsumer configureRpcDecoderRegistry = Lambda::noop; + private BiConsumer configureRpcEncoderRegistry = Lambda::noop; + private Consumer configureEventRegistry = Lambda::noop; + + + public DefaultModule configureScaleReaderRegistry(Consumer configure) { + configureScaleReaderRegistry = configureScaleReaderRegistry.andThen(configure); + return this; + } + + public DefaultModule configureScaleWriterRegistry(Consumer configure) { + configureScaleWriterRegistry = configureScaleWriterRegistry.andThen(configure); + return this; + } + + public DefaultModule configureRpcDecoderRegistry(BiConsumer configure) { + configureRpcDecoderRegistry = configureRpcDecoderRegistry.andThen(configure); + return this; + } + + public DefaultModule configureRpcEncoderRegistry(BiConsumer configure) { + configureRpcEncoderRegistry = configureRpcEncoderRegistry.andThen(configure); + return this; + } + + public DefaultModule configureEventRegistry(Consumer configure) { + configureEventRegistry = configureEventRegistry.andThen(configure); + return this; + } + + @Override + protected void configure() { + try { + bind(ProviderInterface.class).toInstance(providerInterface); + bind(RpcSectionFactory.class) + .toConstructor( + GeneratedRpcSectionFactory.class.getConstructor( + ProviderInterface.class, + RpcEncoderRegistry.class, + ScaleWriterRegistry.class, + RpcDecoderRegistry.class, + ScaleReaderRegistry.class)) + .asEagerSingleton(); + bind(PalletFactory.class) + .toConstructor( + GeneratedPalletFactory.class.getConstructor( + ScaleReaderRegistry.class, + ScaleWriterRegistry.class, + State.class + )) + .asEagerSingleton(); + bind(Api.class) + .toConstructor( + Api.class.getConstructor( + RpcSectionFactory.class, + PalletFactory.class, + MetadataProvider.class)) + .asEagerSingleton(); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + @Provides + @Singleton + public ScaleReaderRegistry provideScaleReaderRegistry(MetadataProvider metadataProvider, + EventRegistry eventRegistry) { + val registry = new ScaleReaderRegistry(); + registry.registerAnnotatedFrom(PREFIX); + registry.register(new AccountDataReader(registry), System.AccountData.class, AccountData.class); + registry.register(new EventDescriptorReader(registry, metadataProvider, eventRegistry), EventDescriptor.class); + + configureScaleReaderRegistry.accept(registry); + return registry; + } + + @Provides + @Singleton + public ScaleWriterRegistry provideScaleWriterRegistry() { + val registry = new ScaleWriterRegistry(); + registry.registerAnnotatedFrom(PREFIX); + + configureScaleWriterRegistry.accept(registry); + return registry; + } + + @Provides + @Singleton + public RpcDecoderRegistry provideRpcDecoderRegistry(MetadataProvider metadataProvider, + ScaleReaderRegistry scaleReaderRegistry) { + val registry = new RpcDecoderRegistry(); + val context = new RpcDecoderContext( + metadataProvider, + registry, + scaleReaderRegistry); + registry.registerAnnotatedFrom(() -> context, PREFIX); + + configureRpcDecoderRegistry.accept(registry, () -> context); + return registry; + } + + @Provides + @Singleton + public RpcEncoderRegistry provideRpcEncoderRegistry(MetadataProvider metadataProvider, + ScaleWriterRegistry scaleWriterRegistry) { + val registry = new RpcEncoderRegistry(); + val context = new RpcEncoderContext( + metadataProvider, + registry, + scaleWriterRegistry); + registry.registerAnnotatedFrom(() -> context, PREFIX); + + configureRpcEncoderRegistry.accept(registry, () -> context); + return registry; + } + + @Provides + @Singleton + public EventRegistry provideEventRegistry() { + val registry = new EventRegistry(); + registry.registerAnnotatedFrom(PREFIX); + + configureEventRegistry.accept(registry); + return registry; + } + + @Provides + @Singleton + public MetadataProvider provideMetadata() { + // TODO. Use provider based on real Metadata + return new ManualMetadataProvider( + SS58AddressFormat.SUBSTRATE_ACCOUNT, + new PalletCollection( + new Pallet(0, "System"), + new Pallet(1, "Utility"), + new Pallet(2, "Babe"), + new Pallet(3, "Timestamp"), + new Pallet(4, "Authorship"), + new Pallet(5, "Indices"), + new Pallet(6, "Balances"), + new Pallet(7, "TransactionPayment"), + new Pallet(8, "Staking"), + new Pallet(9, "Session"), + new Pallet(10, "Democracy"), + new Pallet(11, "Council"), + new Pallet(12, "TechnicalCommittee"), + new Pallet(13, "Elections"), + new Pallet(14, "TechnicalMembership"), + new Pallet(15, "Grandpa"), + new Pallet(16, "Treasury"), + new Pallet(17, "Contracts"), + new Pallet(18, "Sudo"), + new Pallet(19, "ImOnline"), + new Pallet(20, "AuthorityDiscovery"), + new Pallet(21, "Offences"), + new Pallet(22, "Historical"), + new Pallet(23, "RandomnessCollectiveFlip"), + new Pallet(24, "Identity"), + new Pallet(25, "Society"), + new Pallet(26, "Recovery"), + new Pallet(27, "Vesting"), + new Pallet(28, "Scheduler"), + new Pallet(29, "Proxy"), + new Pallet(30, "Multisig"), + new Pallet(31, "Bounties"), + new Pallet(32, "Tips"), + new Pallet(33, "Assets"), + new Pallet(34, "Mmr"), + new Pallet(35, "Lottery"))); + } + + @Provides + @Singleton + public State provideState(RpcSectionFactory rpcSectionFactory) { + return rpcSectionFactory.create(State.class); + } +} diff --git a/api/src/main/java/com/strategyobject/substrateclient/api/RequireModule.java b/api/src/main/java/com/strategyobject/substrateclient/api/RequireModule.java new file mode 100644 index 00000000..21884ecb --- /dev/null +++ b/api/src/main/java/com/strategyobject/substrateclient/api/RequireModule.java @@ -0,0 +1,26 @@ +package com.strategyobject.substrateclient.api; + +import com.google.inject.AbstractModule; +import com.strategyobject.substrateclient.pallet.PalletFactory; +import com.strategyobject.substrateclient.rpc.RpcSectionFactory; +import com.strategyobject.substrateclient.rpc.metadata.MetadataProvider; +import com.strategyobject.substrateclient.rpc.registries.RpcDecoderRegistry; +import com.strategyobject.substrateclient.rpc.registries.RpcEncoderRegistry; +import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; +import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; +import com.strategyobject.substrateclient.transport.ProviderInterface; + +public class RequireModule extends AbstractModule { + @Override + protected void configure() { + requireBinding(ProviderInterface.class); + requireBinding(ScaleReaderRegistry.class); + requireBinding(ScaleWriterRegistry.class); + requireBinding(RpcDecoderRegistry.class); + requireBinding(RpcEncoderRegistry.class); + requireBinding(MetadataProvider.class); + requireBinding(RpcSectionFactory.class); + requireBinding(PalletFactory.class); + requireBinding(Api.class); + } +} diff --git a/api/src/main/java/com/strategyobject/substrateclient/api/pallet/balances/AccountData.java b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/balances/AccountData.java new file mode 100644 index 00000000..6ee56392 --- /dev/null +++ b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/balances/AccountData.java @@ -0,0 +1,27 @@ +package com.strategyobject.substrateclient.api.pallet.balances; + +import com.strategyobject.substrateclient.api.pallet.system.System; +import com.strategyobject.substrateclient.scale.ScaleType; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; +import lombok.Getter; +import lombok.Setter; + +import java.math.BigInteger; + +@ScaleReader +@Getter +@Setter +public class AccountData implements System.AccountData { + @Scale(ScaleType.U128.class) + private BigInteger free; + + @Scale(ScaleType.U128.class) + private BigInteger reserved; + + @Scale(ScaleType.U128.class) + private BigInteger miscFrozen; + + @Scale(ScaleType.U128.class) + private BigInteger feeFrozen; +} diff --git a/api/src/main/java/com/strategyobject/substrateclient/api/pallet/balances/Balances.java b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/balances/Balances.java new file mode 100644 index 00000000..33950f7b --- /dev/null +++ b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/balances/Balances.java @@ -0,0 +1,118 @@ +package com.strategyobject.substrateclient.api.pallet.balances; + +import com.strategyobject.substrateclient.pallet.annotation.Event; +import com.strategyobject.substrateclient.pallet.annotation.Pallet; +import com.strategyobject.substrateclient.rpc.api.AccountId; +import com.strategyobject.substrateclient.rpc.api.BalanceStatus; +import com.strategyobject.substrateclient.rpc.api.primitives.Balance; +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; +import lombok.Getter; +import lombok.Setter; + +@Pallet("Balances") +public interface Balances { + + /** + * An account was created with some free balance. \[account, free_balance\] + */ + @Event(index = 0) + @Getter + @Setter + @ScaleReader + class Endowed { + private AccountId account; + private Balance freeBalance; + } + + /** + * An account was removed whose balance was non-zero but below ExistentialDeposit, + * resulting in an outright loss. \[account, balance\] + */ + @Event(index = 1) + @Getter + @Setter + @ScaleReader + class DustLost { + private AccountId account; + private Balance balance; + } + + /** + * Transfer succeeded. \[from, to, value\] + */ + @Event(index = 2) + @Getter + @Setter + @ScaleReader + class Transfer { + private AccountId from; + private AccountId to; + private Balance value; + } + + /** + * A balance was set by root. \[who, free, reserved\] + */ + @Event(index = 3) + @Getter + @Setter + @ScaleReader + class BalanceSet { + private AccountId account; + private Balance free; + private Balance reserved; + } + + /** + * Some amount was deposited (e.g. for transaction fees). \[who, deposit\] + */ + @Event(index = 4) + @Getter + @Setter + @ScaleReader + class Deposit { + private AccountId account; + private Balance value; + } + + /** + * Some balance was reserved (moved from free to reserved). \[who, value\] + */ + @Event(index = 5) + @Getter + @Setter + @ScaleReader + class Reserved { + private AccountId account; + private Balance value; + } + + /** + * Some balance was unreserved (moved from reserved to free). \[who, value\] + */ + @Event(index = 6) + @Getter + @Setter + @ScaleReader + class Unreserved { + private AccountId account; + private Balance value; + } + + /** + * Some balance was moved from the reserve of the first account to the second account. + * Final argument indicates the destination balance type. + * \[from, to, balance, destination_status\] + */ + @Event(index = 7) + @Getter + @Setter + @ScaleReader + class ReserveRepatriated { + private AccountId from; + private AccountId to; + private Balance value; + private BalanceStatus destinationStatus; + } + +} diff --git a/api/src/main/java/com/strategyobject/substrateclient/api/pallet/grandpa/Authority.java b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/grandpa/Authority.java new file mode 100644 index 00000000..9b504f89 --- /dev/null +++ b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/grandpa/Authority.java @@ -0,0 +1,20 @@ +package com.strategyobject.substrateclient.api.pallet.grandpa; + +import com.strategyobject.substrateclient.crypto.PublicKey; +import com.strategyobject.substrateclient.scale.ScaleType; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; +import lombok.Getter; +import lombok.Setter; + +import java.math.BigInteger; + +@ScaleReader +@Getter +@Setter +public class Authority { + private PublicKey authorityId; + + @Scale(ScaleType.U64.class) + private BigInteger authorityWeight; +} diff --git a/api/src/main/java/com/strategyobject/substrateclient/api/pallet/grandpa/Grandpa.java b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/grandpa/Grandpa.java new file mode 100644 index 00000000..86d3b1c0 --- /dev/null +++ b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/grandpa/Grandpa.java @@ -0,0 +1,41 @@ +package com.strategyobject.substrateclient.api.pallet.grandpa; + +import com.strategyobject.substrateclient.pallet.annotation.Event; +import com.strategyobject.substrateclient.pallet.annotation.Pallet; +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Pallet("Grandpa") +public interface Grandpa { + + /** + * New authority set has been applied. \[authority_set\] + */ + @Event(index = 0) + @Getter + @Setter + @ScaleReader + class NewAuthorities { + private List authorityList; + } + + /** + * Current authority set has been paused. + */ + @Event(index = 1) + @ScaleReader + class Paused { + } + + /** + * Current authority set has been resumed. + */ + @Event(index = 2) + @ScaleReader + class Resumed { + } + +} diff --git a/api/src/main/java/com/strategyobject/substrateclient/api/pallet/indices/Indices.java b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/indices/Indices.java new file mode 100644 index 00000000..19904f07 --- /dev/null +++ b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/indices/Indices.java @@ -0,0 +1,48 @@ +package com.strategyobject.substrateclient.api.pallet.indices; + +import com.strategyobject.substrateclient.pallet.annotation.Event; +import com.strategyobject.substrateclient.pallet.annotation.Pallet; +import com.strategyobject.substrateclient.rpc.api.AccountId; +import com.strategyobject.substrateclient.rpc.api.primitives.AccountIndex; +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; +import lombok.Getter; +import lombok.Setter; + +@Pallet("Indices") +public interface Indices { + + /** + * An account index was assigned. \[index, who\] + */ + @Event(index = 0) + @Getter + @Setter + @ScaleReader + class IndexAssigned { + private AccountId account; + private AccountIndex index; + } + + /** + * An account index has been freed up (unassigned). \[index\] + */ + @Event(index = 1) + @Getter + @Setter + @ScaleReader + class IndexFreed { + private AccountIndex accountIndex; + } + + /** + * An account index has been frozen to its current account ID. \[index, who\] + */ + @Event(index = 2) + @Getter + @Setter + @ScaleReader + class IndexFrozen { + private AccountIndex index; + private AccountId account; + } +} diff --git a/api/src/main/java/com/strategyobject/substrateclient/api/pallet/proxy/Proxy.java b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/proxy/Proxy.java new file mode 100644 index 00000000..3a1142fc --- /dev/null +++ b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/proxy/Proxy.java @@ -0,0 +1,74 @@ +package com.strategyobject.substrateclient.api.pallet.proxy; + +import com.strategyobject.substrateclient.common.types.Result; +import com.strategyobject.substrateclient.common.types.Unit; +import com.strategyobject.substrateclient.pallet.annotation.Event; +import com.strategyobject.substrateclient.pallet.annotation.Pallet; +import com.strategyobject.substrateclient.rpc.api.AccountId; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockNumber; +import com.strategyobject.substrateclient.rpc.api.primitives.CallHash; +import com.strategyobject.substrateclient.rpc.api.runtime.DispatchError; +import com.strategyobject.substrateclient.scale.ScaleType; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; +import lombok.Getter; +import lombok.Setter; + +@Pallet("Proxy") +public interface Proxy { + + /** + * A proxy was executed correctly, with the given \[result\]. + */ + @Event(index = 0) + @Getter + @Setter + @ScaleReader + class ProxyExecuted { + private Result dispatchResult; + } + + /** + * Anonymous account has been created by new proxy with given + * disambiguation index and proxy type. \[anonymous, who, proxy_type, + * disambiguation_index\] + */ + @Event(index = 1) + @Getter + @Setter + @ScaleReader + class AnonymousCreated { + private AccountId anonymous; + private AccountId who; + private ProxyType proxyType; + @Scale(ScaleType.U16.class) + private Integer disambiguationIndex; + } + + /** + * An announcement was placed to make a call in the future. \[real, proxy, call_hash\] + */ + @Event(index = 2) + @Getter + @Setter + @ScaleReader + class Announced { + private AccountId real; + private AccountId proxy; + private CallHash callHash; + } + + /** + * A proxy was added. \[delegator, delegatee, proxy_type, delay\] + */ + @Event(index = 3) + @Getter + @Setter + @ScaleReader + class ProxyAdded { + private AccountId delegator; + private AccountId delegatee; + private ProxyType proxyType; + private BlockNumber blockNumber; + } +} diff --git a/api/src/main/java/com/strategyobject/substrateclient/api/pallet/proxy/ProxyType.java b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/proxy/ProxyType.java new file mode 100644 index 00000000..12c6c721 --- /dev/null +++ b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/proxy/ProxyType.java @@ -0,0 +1,14 @@ +package com.strategyobject.substrateclient.api.pallet.proxy; + +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; + +/** + * The type used to represent the kinds of proxying allowed. + */ +@ScaleReader +public enum ProxyType { + ANY, + NON_TRANSFER, + GOVERNANCE, + STAKING +} diff --git a/api/src/main/java/com/strategyobject/substrateclient/api/pallet/session/Session.java b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/session/Session.java new file mode 100644 index 00000000..f085f5be --- /dev/null +++ b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/session/Session.java @@ -0,0 +1,27 @@ +package com.strategyobject.substrateclient.api.pallet.session; + +import com.strategyobject.substrateclient.pallet.annotation.Event; +import com.strategyobject.substrateclient.pallet.annotation.Pallet; +import com.strategyobject.substrateclient.scale.ScaleType; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; +import lombok.Getter; +import lombok.Setter; + +@Pallet("Session") +public interface Session { + + /** + * New session has happened. Note that the argument is the \[session_index\], not the + * block number as the type might suggest. + */ + @Event(index = 0) + @Getter + @Setter + @ScaleReader + class NewSession { + @Scale(ScaleType.U32.class) + private Long sessionIndex; + } + +} diff --git a/api/src/main/java/com/strategyobject/substrateclient/api/pallet/staking/Staking.java b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/staking/Staking.java new file mode 100644 index 00000000..0f6bb1c6 --- /dev/null +++ b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/staking/Staking.java @@ -0,0 +1,161 @@ +package com.strategyobject.substrateclient.api.pallet.staking; + +import com.strategyobject.substrateclient.pallet.annotation.Event; +import com.strategyobject.substrateclient.pallet.annotation.Pallet; +import com.strategyobject.substrateclient.rpc.api.AccountId; +import com.strategyobject.substrateclient.rpc.api.primitives.Balance; +import com.strategyobject.substrateclient.scale.ScaleType; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; +import lombok.Getter; +import lombok.Setter; + +@Pallet("Staking") +public interface Staking { + + /** + * The era payout has been set; the first balance is the validator-payout; the second is + * the remainder from the maximum amount of reward. + * \[era_index, validator_payout, remainder\] + */ + @Event(index = 0) + @Getter + @Setter + @ScaleReader + class EraPaid { + @Scale(ScaleType.U32.class) + private Long eraIndex; + private Balance payout; + private Balance remainder; + } + + /** + * The nominator has been rewarded by this amount. \[stash, amount\] + */ + @Event(index = 1) + @Getter + @Setter + @ScaleReader + class Rewarded { + private AccountId stash; + private Balance amount; + } + + /** + * One validator (and its nominators) has been slashed by the given amount. + * \[validator, amount\] + */ + @Event(index = 2) + @Getter + @Setter + @ScaleReader + class Slashed { + private AccountId validator; + private Balance amount; + } + + /** + * An old slashing report from a prior era was discarded because it could + * not be processed. \[session_index\] + */ + @Event(index = 3) + @Getter + @Setter + @ScaleReader + class OldSlashingReportDiscarded { + @Scale(ScaleType.U32.class) + private Long sessionIndex; + } + + /** + * A new set of stakers was elected. + */ + @Event(index = 4) + @ScaleReader + class StakersElected { + } + + /** + * An account has bonded this amount. \[stash, amount\] + *

+ * NOTE: This event is only emitted when funds are bonded via a dispatchable. Notably, + * it will not be emitted for staking rewards when they are added to stake. + */ + @Event(index = 5) + @Getter + @Setter + @ScaleReader + class Bonded { + private AccountId stash; + private Balance amount; + } + + /** + * An account has unbonded this amount. \[stash, amount\] + */ + @Event(index = 6) + @Getter + @Setter + @ScaleReader + class Unbonded { + private AccountId stash; + private Balance amount; + } + + /** + * An account has called `withdraw_unbonded` and removed unbonding chunks worth `Balance` + * from the unlocking queue. \[stash, amount\] + */ + @Event(index = 7) + @Getter + @Setter + @ScaleReader + class Withdrawn { + private AccountId stash; + private Balance amount; + } + + /** + * A nominator has been kicked from a validator. \[nominator, stash\] + */ + @Event(index = 8) + @Getter + @Setter + @ScaleReader + class Kicked { + private AccountId nominator; + private AccountId stash; + } + + /** + * The election failed. No new era is planned. + */ + @Event(index = 9) + @ScaleReader + class StakingElectionFailed { + } + + /** + * An account has stopped participating as either a validator or nominator. \[stash\] + */ + @Event(index = 10) + @Getter + @Setter + @ScaleReader + class Chilled { + private AccountId stash; + } + + /** + * The stakers' rewards are getting paid. \[era_index, validator_stash\] + */ + @Event(index = 11) + @Getter + @Setter + @ScaleReader + class PayoutStarted { + @Scale(ScaleType.U32.class) + private Long eraIndex; + private AccountId validatorStash; + } +} diff --git a/api/src/main/java/com/strategyobject/substrateclient/api/pallet/sudo/Sudo.java b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/sudo/Sudo.java new file mode 100644 index 00000000..95b00111 --- /dev/null +++ b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/sudo/Sudo.java @@ -0,0 +1,49 @@ +package com.strategyobject.substrateclient.api.pallet.sudo; + +import com.strategyobject.substrateclient.common.types.Result; +import com.strategyobject.substrateclient.common.types.Unit; +import com.strategyobject.substrateclient.pallet.annotation.Event; +import com.strategyobject.substrateclient.pallet.annotation.Pallet; +import com.strategyobject.substrateclient.rpc.api.AccountId; +import com.strategyobject.substrateclient.rpc.api.runtime.DispatchError; +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; +import lombok.Getter; +import lombok.Setter; + +@Pallet("Sudo") +public interface Sudo { + + /** + * A sudo just took place. \[result\] + */ + @Event(index = 0) + @Getter + @Setter + @ScaleReader + class Sudid { + private Result dispatchResult; + } + + /** + * The \[sudoer\] just switched identity; the old key is supplied. + */ + @Event(index = 1) + @Getter + @Setter + @ScaleReader + class KeyChanged { + private AccountId sudoer; + } + + /** + * A sudo just took place. \[result\] + */ + @Event(index = 2) + @Getter + @Setter + @ScaleReader + class SudoAsDone { + private Result dispatchResult; + } + +} diff --git a/api/src/main/java/com/strategyobject/substrateclient/api/pallet/system/AccountInfo.java b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/system/AccountInfo.java new file mode 100644 index 00000000..b5a8478e --- /dev/null +++ b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/system/AccountInfo.java @@ -0,0 +1,24 @@ +package com.strategyobject.substrateclient.api.pallet.system; + +import com.strategyobject.substrateclient.scale.ScaleType; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@ScaleReader +public +class AccountInfo { + @Scale(ScaleType.U32.class) + private Long nonce; + + @Scale(ScaleType.U32.class) + private Long consumers; + + @Scale(ScaleType.U32.class) + private Long providers; + + private System.AccountData data; +} diff --git a/api/src/main/java/com/strategyobject/substrateclient/api/pallet/system/EventRecord.java b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/system/EventRecord.java new file mode 100644 index 00000000..f36635fa --- /dev/null +++ b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/system/EventRecord.java @@ -0,0 +1,30 @@ +package com.strategyobject.substrateclient.api.pallet.system; + +import com.strategyobject.substrateclient.pallet.events.EventDescriptor; +import com.strategyobject.substrateclient.rpc.api.primitives.Hash; +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +/** + * Record of an event happening. + */ +@Getter +@Setter +@ScaleReader +public class EventRecord { + /** + * Record of an event happening. + */ + private Phase phase; + /** + * The event descriptor holding event description data and the event itself. + */ + private EventDescriptor event; + /** + * The list of the topics this event has. + */ + private List topics; +} diff --git a/api/src/main/java/com/strategyobject/substrateclient/api/pallet/system/Phase.java b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/system/Phase.java new file mode 100644 index 00000000..b0a677c1 --- /dev/null +++ b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/system/Phase.java @@ -0,0 +1,61 @@ +package com.strategyobject.substrateclient.api.pallet.system; + +import com.google.common.base.Preconditions; +import com.strategyobject.substrateclient.common.types.union.Union; + +/** + * A phase of a block's execution. + */ +public class Phase extends Union { + + private Phase() { + } + + /** + * @return true if applying an extrinsic + */ + public boolean isApplyExtrinsic() { + return index == 0; + } + + /** + * @return true if finalizing the block + */ + public boolean isFinalization() { + return index == 1; + } + + /** + * @return true if initializing the block + */ + public boolean isInitialization() { + return index == 2; + } + + /** + * @return index of the extrinsic applied + */ + public long getApplyExtrinsicIndex() { + Preconditions.checkState(index == 0); + return (long) value; + } + + public static Phase ofApplyExtrinsic(long extrinsicIndex) { + Phase result = new Phase(); + result.value = extrinsicIndex; + result.index = 0; + return result; + } + + public static Phase ofFinalization() { + Phase result = new Phase(); + result.index = 1; + return result; + } + + public static Phase ofInitialization() { + Phase result = new Phase(); + result.index = 2; + return result; + } +} diff --git a/api/src/main/java/com/strategyobject/substrateclient/api/pallet/system/PhaseReader.java b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/system/PhaseReader.java new file mode 100644 index 00000000..031bcf63 --- /dev/null +++ b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/system/PhaseReader.java @@ -0,0 +1,36 @@ +package com.strategyobject.substrateclient.api.pallet.system; + +import com.google.common.base.Preconditions; +import com.strategyobject.substrateclient.scale.ScaleReader; +import com.strategyobject.substrateclient.scale.ScaleType; +import com.strategyobject.substrateclient.scale.annotation.AutoRegister; +import com.strategyobject.substrateclient.scale.readers.union.BaseUnionReader; +import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; +import lombok.NonNull; +import lombok.val; + +import java.io.IOException; +import java.io.InputStream; + +@AutoRegister(types = Phase.class) +public class PhaseReader extends BaseUnionReader { + private final ScaleReaderRegistry registry; + + public PhaseReader(ScaleReaderRegistry registry) { + super(3, + x -> Phase.ofApplyExtrinsic((Long) x), + x -> Phase.ofFinalization(), + x -> Phase.ofInitialization()); + + this.registry = registry; + } + + @Override + public Phase read(@NonNull InputStream stream, ScaleReader... readers) throws IOException { + Preconditions.checkArgument(readers == null || readers.length == 0); + + val u32Reader = registry.resolve(ScaleType.U32.class); + val voidReader = registry.resolve(Void.class); + return super.read(stream, u32Reader, voidReader, voidReader); + } +} diff --git a/api/src/main/java/com/strategyobject/substrateclient/api/pallet/system/System.java b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/system/System.java new file mode 100644 index 00000000..c1a10f2f --- /dev/null +++ b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/system/System.java @@ -0,0 +1,109 @@ +package com.strategyobject.substrateclient.api.pallet.system; + +import com.strategyobject.substrateclient.common.types.Into; +import com.strategyobject.substrateclient.pallet.annotation.*; +import com.strategyobject.substrateclient.pallet.storage.StorageNMap; +import com.strategyobject.substrateclient.rpc.api.AccountId; +import com.strategyobject.substrateclient.rpc.api.primitives.Hash; +import com.strategyobject.substrateclient.rpc.api.runtime.DispatchError; +import com.strategyobject.substrateclient.rpc.api.weights.DispatchInfo; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +/** + * The System pallet provides low-level access to core types and cross-cutting utilities. + * It acts as the base layer for other pallets to interact with the Substrate framework components. + */ +@Pallet("System") +public interface System { + interface AccountData extends Into { + } + + /** + * @return The full account information for a particular account ID. + */ + @Storage( + name = "Account", + keys = { + @StorageKey( + type = @Scale(AccountId.class), + hasher = StorageHasher.BLAKE2_128_CONCAT + ) + }) + StorageNMap account(); + + /** + * @return Events deposited for the current block. + */ + @Storage(name = "Events") + StorageNMap> events(); + + /** + * An extrinsic completed successfully. + */ + @Event(index = 0) + @Getter + @Setter + @ScaleReader + class ExtrinsicSuccess { + private DispatchInfo dispatchInfo; + } + + /** + * An extrinsic failed. + */ + @Event(index = 1) + @Getter + @Setter + @ScaleReader + class ExtrinsicFailedEvent { + private DispatchError dispatchError; + private DispatchInfo dispatchInfo; + } + + /** + * `:code` was updated. + */ + @Event(index = 2) + @ScaleReader + class CodeUpdatedEvent { + } + + /** + * A new account was created. + */ + @Event(index = 3) + @Getter + @Setter + @ScaleReader + class NewAccountEvent { + private AccountId account; + } + + /** + * An account was reaped. + */ + @Event(index = 4) + @Getter + @Setter + @ScaleReader + class KilledAccountEvent { + private AccountId account; + } + + /** + * On on-chain remark happened. + */ + @Event(index = 5) + @Getter + @Setter + @ScaleReader + class RemarkedEvent { + private AccountId sender; + private Hash hash; + } +} diff --git a/api/src/main/java/com/strategyobject/substrateclient/api/pallet/treasury/Treasury.java b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/treasury/Treasury.java new file mode 100644 index 00000000..0e58cecf --- /dev/null +++ b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/treasury/Treasury.java @@ -0,0 +1,100 @@ +package com.strategyobject.substrateclient.api.pallet.treasury; + +import com.strategyobject.substrateclient.pallet.annotation.Event; +import com.strategyobject.substrateclient.pallet.annotation.Pallet; +import com.strategyobject.substrateclient.rpc.api.AccountId; +import com.strategyobject.substrateclient.rpc.api.primitives.Balance; +import com.strategyobject.substrateclient.scale.ScaleType; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; +import lombok.Getter; +import lombok.Setter; + +@Pallet("Treasury") +public interface Treasury { + + /** + * New proposal. \[proposal_index\] + */ + @Event(index = 0) + @Getter + @Setter + @ScaleReader + class Proposed { + @Scale(ScaleType.U32.class) + private Long proposalIndex; + } + + /** + * We have ended a spend period and will now allocate funds. \[budget_remaining\] + */ + @Event(index = 1) + @Getter + @Setter + @ScaleReader + class Spending { + private Balance budgetRemaining; + } + + /** + * Some funds have been allocated. \[proposal_index, award, beneficiary\] + */ + @Event(index = 2) + @Getter + @Setter + @ScaleReader + class Awarded { + @Scale(ScaleType.U32.class) + private Long proposalIndex; + private Balance award; + private AccountId beneficiary; + } + + /** + * A proposal was rejected; funds were slashed. \[proposal_index, slashed\] + */ + @Event(index = 3) + @Getter + @Setter + @ScaleReader + class Rejected { + @Scale(ScaleType.U32.class) + private Long proposalIndex; + private Balance slashed; + } + + /** + * Some of our funds have been burnt. \[burn\] + */ + @Event(index = 4) + @Getter + @Setter + @ScaleReader + class Burnt { + private Balance value; + } + + /** + * Spending has finished; this is the amount that rolls over until next spend. + * \[budget_remaining\] + */ + @Event(index = 5) + @Getter + @Setter + @ScaleReader + class Rollover { + private Balance budgetRemaining; + } + + /** + * Some funds have been deposited. \[deposit\] + */ + @Event(index = 6) + @Getter + @Setter + @ScaleReader + class Deposit { + private Balance value; + } + +} diff --git a/api/src/main/java/com/strategyobject/substrateclient/api/pallet/utility/Utility.java b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/utility/Utility.java new file mode 100644 index 00000000..3717d25e --- /dev/null +++ b/api/src/main/java/com/strategyobject/substrateclient/api/pallet/utility/Utility.java @@ -0,0 +1,45 @@ +package com.strategyobject.substrateclient.api.pallet.utility; + +import com.strategyobject.substrateclient.pallet.annotation.Event; +import com.strategyobject.substrateclient.pallet.annotation.Pallet; +import com.strategyobject.substrateclient.rpc.api.runtime.DispatchError; +import com.strategyobject.substrateclient.scale.ScaleType; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; +import lombok.Getter; +import lombok.Setter; + +@Pallet("Utility") +public interface Utility { + + /** + * Batch of dispatches did not complete fully. Index of first failing dispatch given, as + * well as the error. \[index, error\] + */ + @Event(index = 0) + @Getter + @Setter + @ScaleReader + class BatchInterrupted { + @Scale(ScaleType.U32.class) + private Long index; + private DispatchError dispatchError; + } + + /** + * Batch of dispatches completed fully with no error. + */ + @Event(index = 1) + @ScaleReader + class BatchCompleted { + } + + /** + * A single item within a Batch of dispatches has completed with no error. + */ + @Event(index = 2) + @ScaleReader + class ItemCompleted { + } + +} diff --git a/api/src/test/java/com/strategyobject/substrateclient/api/ApiTest.java b/api/src/test/java/com/strategyobject/substrateclient/api/ApiTest.java new file mode 100644 index 00000000..704b53c8 --- /dev/null +++ b/api/src/test/java/com/strategyobject/substrateclient/api/ApiTest.java @@ -0,0 +1,123 @@ +package com.strategyobject.substrateclient.api; + +import com.google.inject.CreationException; +import com.google.inject.util.Modules; +import com.strategyobject.substrateclient.common.convert.HexConverter; +import com.strategyobject.substrateclient.crypto.ss58.SS58AddressFormat; +import com.strategyobject.substrateclient.pallet.PalletFactory; +import com.strategyobject.substrateclient.rpc.api.AccountId; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockNumber; +import com.strategyobject.substrateclient.rpc.api.primitives.Index; +import com.strategyobject.substrateclient.rpc.api.section.System; +import com.strategyobject.substrateclient.tests.containers.SubstrateVersion; +import com.strategyobject.substrateclient.tests.containers.TestSubstrateContainer; +import com.strategyobject.substrateclient.transport.ws.WsProvider; +import lombok.val; +import org.junit.jupiter.api.Test; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import java.math.BigInteger; +import java.util.concurrent.TimeUnit; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +@Testcontainers +class ApiTest { + private static final int WAIT_TIMEOUT = 1000; + + @Container + private final TestSubstrateContainer substrate = new TestSubstrateContainer(SubstrateVersion.V3_0_0); + + @Test + void getSystemPalletAndCall() throws Exception { // TODO move the test out of the project + val wsProvider = WsProvider.builder() + .setEndpoint(substrate.getWsAddress()); + + try (val api = Api.with(wsProvider).build().join()) { + val systemPallet = api.pallet(SystemPallet.class); + val blockHash = systemPallet + .blockHash() + .get(BlockNumber.GENESIS) + .get(WAIT_TIMEOUT, TimeUnit.SECONDS); + + assertNotNull(blockHash); + assertNotEquals(BigInteger.ZERO, new BigInteger(blockHash.getBytes())); + } + } + + @Test + void getSystemSectionAndCall() throws Exception { + val wsProvider = WsProvider.builder() + .setEndpoint(substrate.getWsAddress()); + + try (val api = Api.with(wsProvider).build().join()) { + val system = api.rpc(System.class); + val alicePublicKey = HexConverter.toBytes("0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"); + val actual = system.accountNextIndex(AccountId.fromBytes(alicePublicKey)).join(); + + assertEquals(Index.ZERO, actual); + } + } + + @Test + void getSS58AddressFormat() throws Exception { + val wsProvider = WsProvider.builder() + .setEndpoint(substrate.getWsAddress()); + + try (val api = Api.with(wsProvider).build().join()) { + val ss58AddressFormat = api.metadata().getSS58AddressFormat(); + + assertNotNull(ss58AddressFormat); + assertEquals(SS58AddressFormat.SUBSTRATE_ACCOUNT, ss58AddressFormat); + } + } + + @Test + void configureApi() throws Exception { + val wsProvider = WsProvider.builder() + .setEndpoint(substrate.getWsAddress()); + + val expected = mock(Index.class); + try (val api = Api.with(wsProvider) + .configure(defaultModule -> + defaultModule.configureRpcDecoderRegistry((registry, _factory) -> + registry.register((value, decoders) -> expected, Index.class))) + .build() + .join()) { + val system = api.rpc(System.class); + val alicePublicKey = HexConverter.toBytes("0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"); + val actual = system.accountNextIndex(AccountId.fromBytes(alicePublicKey)).join(); + + assertEquals(expected, actual); + } + } + + @Test + void reconfigureApi() throws Exception { + val wsProvider = WsProvider.builder() + .setEndpoint(substrate.getWsAddress()); + + val mockFactory = mock(PalletFactory.class); + try (val api = Api.with(wsProvider) + .reconfigure(defaultModule -> + Modules.override(defaultModule).with(binder -> + binder.bind(PalletFactory.class).toInstance(mockFactory))) + .build() + .join()) { + + api.pallet(SystemPallet.class); + verify(mockFactory).create(SystemPallet.class); + } + } + + @Test + void validateModule() { + val api = Api.with(binder -> { + }); + + assertThrows(CreationException.class, api::build); + } +} diff --git a/api/src/test/java/com/strategyobject/substrateclient/api/ApiTests.java b/api/src/test/java/com/strategyobject/substrateclient/api/ApiTests.java deleted file mode 100644 index dab720dc..00000000 --- a/api/src/test/java/com/strategyobject/substrateclient/api/ApiTests.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.strategyobject.substrateclient.api; - -import com.strategyobject.substrateclient.tests.containers.SubstrateVersion; -import com.strategyobject.substrateclient.tests.containers.TestSubstrateContainer; -import com.strategyobject.substrateclient.transport.ws.WsProvider; -import lombok.val; -import org.junit.jupiter.api.Test; -import org.testcontainers.junit.jupiter.Container; -import org.testcontainers.junit.jupiter.Testcontainers; - -import java.math.BigInteger; -import java.util.concurrent.TimeUnit; - -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -@Testcontainers -public class ApiTests { - private static final int WAIT_TIMEOUT = 1000; - - @Container - private final TestSubstrateContainer substrate = new TestSubstrateContainer(SubstrateVersion.V3_0_0); - - @Test - public void getSystemPalletAndCall() throws Exception { // TODO move the test out of the project - val wsProvider = WsProvider.builder() - .setEndpoint(substrate.getWsAddress()) - .build(); - wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - try (val api = Api.with(wsProvider)) { - val systemPallet = api.pallet(SystemPallet.class); - val blockHash = systemPallet - .blockHash() - .get(0) - .get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - assertNotNull(blockHash); - assertNotEquals(BigInteger.ZERO, new BigInteger(blockHash.getData())); - } - } -} diff --git a/rpc/rpc-sections/src/test/java/com/strategyobject/substrateclient/rpc/sections/substitutes/BalanceTransfer.java b/api/src/test/java/com/strategyobject/substrateclient/api/BalanceTransfer.java similarity index 57% rename from rpc/rpc-sections/src/test/java/com/strategyobject/substrateclient/rpc/sections/substitutes/BalanceTransfer.java rename to api/src/test/java/com/strategyobject/substrateclient/api/BalanceTransfer.java index 1c27ee97..6e8b5e62 100644 --- a/rpc/rpc-sections/src/test/java/com/strategyobject/substrateclient/rpc/sections/substitutes/BalanceTransfer.java +++ b/api/src/test/java/com/strategyobject/substrateclient/api/BalanceTransfer.java @@ -1,10 +1,10 @@ -package com.strategyobject.substrateclient.rpc.sections.substitutes; +package com.strategyobject.substrateclient.api; -import com.strategyobject.substrateclient.rpc.types.AddressId; -import com.strategyobject.substrateclient.rpc.types.Call; +import com.strategyobject.substrateclient.rpc.api.AddressId; +import com.strategyobject.substrateclient.rpc.api.Call; import com.strategyobject.substrateclient.scale.ScaleType; -import com.strategyobject.substrateclient.scale.annotations.Scale; -import com.strategyobject.substrateclient.scale.annotations.ScaleWriter; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleWriter; import lombok.Getter; import lombok.RequiredArgsConstructor; diff --git a/api/src/test/java/com/strategyobject/substrateclient/api/SystemPallet.java b/api/src/test/java/com/strategyobject/substrateclient/api/SystemPallet.java index fd5a9250..b3906592 100644 --- a/api/src/test/java/com/strategyobject/substrateclient/api/SystemPallet.java +++ b/api/src/test/java/com/strategyobject/substrateclient/api/SystemPallet.java @@ -1,21 +1,22 @@ package com.strategyobject.substrateclient.api; -import com.strategyobject.substrateclient.pallet.annotations.Pallet; -import com.strategyobject.substrateclient.pallet.annotations.Storage; -import com.strategyobject.substrateclient.pallet.annotations.StorageHasher; -import com.strategyobject.substrateclient.pallet.annotations.StorageKey; -import com.strategyobject.substrateclient.rpc.types.BlockHash; -import com.strategyobject.substrateclient.scale.annotations.Scale; -import com.strategyobject.substrateclient.storage.StorageNMap; +import com.strategyobject.substrateclient.pallet.annotation.Pallet; +import com.strategyobject.substrateclient.pallet.annotation.Storage; +import com.strategyobject.substrateclient.pallet.annotation.StorageHasher; +import com.strategyobject.substrateclient.pallet.annotation.StorageKey; +import com.strategyobject.substrateclient.pallet.storage.StorageNMap; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockHash; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockNumber; +import com.strategyobject.substrateclient.scale.annotation.Scale; @Pallet("System") public interface SystemPallet { @Storage( - value = "BlockHash", + name = "BlockHash", keys = { @StorageKey( - type = @Scale(Integer.class), - hasher = StorageHasher.TwoX64Concat + type = @Scale(BlockNumber.class), + hasher = StorageHasher.TWOX_64_CONCAT ) }) StorageNMap blockHash(); diff --git a/api/src/test/java/com/strategyobject/substrateclient/api/TestsHelper.java b/api/src/test/java/com/strategyobject/substrateclient/api/TestsHelper.java new file mode 100644 index 00000000..7bc9ce81 --- /dev/null +++ b/api/src/test/java/com/strategyobject/substrateclient/api/TestsHelper.java @@ -0,0 +1,57 @@ +package com.strategyobject.substrateclient.api; + +import com.strategyobject.substrateclient.crypto.ss58.SS58AddressFormat; +import com.strategyobject.substrateclient.rpc.GeneratedRpcSectionFactory; +import com.strategyobject.substrateclient.rpc.context.RpcDecoderContext; +import com.strategyobject.substrateclient.rpc.context.RpcEncoderContext; +import com.strategyobject.substrateclient.rpc.metadata.MetadataProvider; +import com.strategyobject.substrateclient.rpc.registries.RpcDecoderRegistry; +import com.strategyobject.substrateclient.rpc.registries.RpcEncoderRegistry; +import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; +import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; +import com.strategyobject.substrateclient.transport.ProviderInterface; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class TestsHelper { + public static final MetadataProvider METADATA_PROVIDER = mock(MetadataProvider.class); + + static { + when(METADATA_PROVIDER.getSS58AddressFormat()).thenReturn(SS58AddressFormat.SUBSTRATE_ACCOUNT); + } + + public static final ScaleReaderRegistry SCALE_READER_REGISTRY = new ScaleReaderRegistry() {{ + registerAnnotatedFrom("com.strategyobject.substrateclient"); + }}; + + public static final ScaleWriterRegistry SCALE_WRITER_REGISTRY = new ScaleWriterRegistry() {{ + registerAnnotatedFrom("com.strategyobject.substrateclient"); + }}; + + public static final RpcEncoderRegistry RPC_ENCODER_REGISTRY = new RpcEncoderRegistry(); + + static { + RPC_ENCODER_REGISTRY.registerAnnotatedFrom( + () -> new RpcEncoderContext(METADATA_PROVIDER, RPC_ENCODER_REGISTRY, SCALE_WRITER_REGISTRY), + "com.strategyobject.substrateclient"); + } + + public static final RpcDecoderRegistry RPC_DECODER_REGISTRY = new RpcDecoderRegistry(); + + static { + RPC_DECODER_REGISTRY.registerAnnotatedFrom( + () -> new RpcDecoderContext(METADATA_PROVIDER, RPC_DECODER_REGISTRY, SCALE_READER_REGISTRY), + "com.strategyobject.substrateclient"); + } + + public static GeneratedRpcSectionFactory createSectionFactory(ProviderInterface provider) { + return new GeneratedRpcSectionFactory( + provider, + RPC_ENCODER_REGISTRY, + SCALE_WRITER_REGISTRY, + RPC_DECODER_REGISTRY, + SCALE_READER_REGISTRY); + } +} + diff --git a/api/src/test/java/com/strategyobject/substrateclient/api/pallet/balances/BalancesTest.java b/api/src/test/java/com/strategyobject/substrateclient/api/pallet/balances/BalancesTest.java new file mode 100644 index 00000000..be3e7c81 --- /dev/null +++ b/api/src/test/java/com/strategyobject/substrateclient/api/pallet/balances/BalancesTest.java @@ -0,0 +1,129 @@ +package com.strategyobject.substrateclient.api.pallet.balances; + +import com.strategyobject.substrateclient.api.Api; +import com.strategyobject.substrateclient.api.BalanceTransfer; +import com.strategyobject.substrateclient.api.TestsHelper; +import com.strategyobject.substrateclient.api.pallet.system.EventRecord; +import com.strategyobject.substrateclient.api.pallet.system.System; +import com.strategyobject.substrateclient.common.convert.HexConverter; +import com.strategyobject.substrateclient.common.types.Size; +import com.strategyobject.substrateclient.crypto.Hasher; +import com.strategyobject.substrateclient.crypto.KeyPair; +import com.strategyobject.substrateclient.crypto.KeyRing; +import com.strategyobject.substrateclient.pallet.storage.Arg; +import com.strategyobject.substrateclient.rpc.api.*; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockHash; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockNumber; +import com.strategyobject.substrateclient.rpc.api.primitives.Index; +import com.strategyobject.substrateclient.rpc.api.section.Author; +import com.strategyobject.substrateclient.rpc.api.section.Chain; +import com.strategyobject.substrateclient.scale.ScaleUtils; +import com.strategyobject.substrateclient.scale.ScaleWriter; +import com.strategyobject.substrateclient.tests.containers.SubstrateVersion; +import com.strategyobject.substrateclient.tests.containers.TestSubstrateContainer; +import com.strategyobject.substrateclient.transport.ws.WsProvider; +import lombok.val; +import org.junit.jupiter.api.Test; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Supplier; +import java.util.stream.Stream; + +import static org.awaitility.Awaitility.await; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.iterableWithSize; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@Testcontainers +class BalancesTest { + private static final int WAIT_TIMEOUT = 30; + + @Container + private final TestSubstrateContainer substrate = new TestSubstrateContainer(SubstrateVersion.V3_0_0); + + @Test + void transfer() throws Exception { + val wsProvider = WsProvider.builder().setEndpoint(substrate.getWsAddress()); + + try (val api = Api.with(wsProvider).build().join()) { + AtomicReference> eventRecords = new AtomicReference<>(new ArrayList<>()); + val unsubscribe = api.pallet(System.class).events() + .subscribe((exception, block, value, keys) -> { + if (exception != null) { + throw new RuntimeException(exception); + } + + eventRecords.set(value); + }, Arg.EMPTY) + .join(); + + doTransfer(api); + + await() + .atMost(WAIT_TIMEOUT, TimeUnit.SECONDS) + .untilAtomic(eventRecords, iterableWithSize(greaterThan(1))); + + assertTrue(unsubscribe.get().join()); + Supplier> events = () -> eventRecords.get().stream().map(x -> x.getEvent().getEvent()); + assertTrue(events.get().anyMatch(x -> x instanceof Balances.Transfer)); + assertTrue(events.get().anyMatch(x -> x instanceof System.ExtrinsicSuccess)); + } + } + + private void doTransfer(Api api) { + val genesis = api.rpc(Chain.class).getBlockHash(BlockNumber.GENESIS).join(); + assertDoesNotThrow(() -> + api.rpc(Author.class).submitExtrinsic(createBalanceTransferExtrinsic(genesis)).join()); + } + + @SuppressWarnings({"unchecked"}) + private Extrinsic createBalanceTransferExtrinsic(BlockHash genesis) { + val specVersion = 264; + val txVersion = 2; + val moduleIndex = (byte) 6; + val callIndex = (byte) 0; + val tip = 0; + val call = new BalanceTransfer(moduleIndex, callIndex, AddressId.fromBytes(bobKeyPair().asPublicKey().getBytes()), BigInteger.valueOf(10)); + + val extra = new SignedExtra<>(specVersion, txVersion, genesis, genesis, new ImmortalEra(), Index.of(0), BigInteger.valueOf(tip)); + val writer = (ScaleWriter>>) TestsHelper.SCALE_WRITER_REGISTRY.resolve(SignedPayload.class); + val signedPayload = ScaleUtils.toBytes(new SignedPayload<>(call, extra), writer); + val keyRing = KeyRing.fromKeyPair(aliceKeyPair()); + + val signature = sign(keyRing, signedPayload); + + return Extrinsic.createSigned( + new SignaturePayload<>( + AddressId.fromBytes(aliceKeyPair().asPublicKey().getBytes()), + signature, + extra + ), call); + } + + private Signature sign(KeyRing keyRing, byte[] payload) { + val signature = payload.length > 256 ? Hasher.blake2(Size.of256, payload) : payload; + + return Sr25519Signature.from(keyRing.sign(() -> signature)); + } + + private KeyPair aliceKeyPair() { + val str = "0x98319d4ff8a9508c4bb0cf0b5a78d760a0b2082c02775e6e82370816fedfff48925a225d97aa00682d6a59b95b18780c10d" + + "7032336e88f3442b42361f4a66011d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"; + + return KeyPair.fromBytes(HexConverter.toBytes(str)); + } + + private KeyPair bobKeyPair() { + val str = "0x081ff694633e255136bdb456c20a5fc8fed21f8b964c11bb17ff534ce80ebd5941ae88f85d0c1bfc37be41c904e1dfc01de" + + "8c8067b0d6d5df25dd1ac0894a3258eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48"; + + return KeyPair.fromBytes(HexConverter.toBytes(str)); + } +} \ No newline at end of file diff --git a/api/src/test/java/com/strategyobject/substrateclient/api/pallet/system/SystemTest.java b/api/src/test/java/com/strategyobject/substrateclient/api/pallet/system/SystemTest.java new file mode 100644 index 00000000..f531ac7a --- /dev/null +++ b/api/src/test/java/com/strategyobject/substrateclient/api/pallet/system/SystemTest.java @@ -0,0 +1,77 @@ +package com.strategyobject.substrateclient.api.pallet.system; + +import com.strategyobject.substrateclient.api.Api; +import com.strategyobject.substrateclient.api.pallet.balances.AccountData; +import com.strategyobject.substrateclient.common.convert.HexConverter; +import com.strategyobject.substrateclient.pallet.storage.Arg; +import com.strategyobject.substrateclient.rpc.api.AccountId; +import com.strategyobject.substrateclient.tests.containers.SubstrateVersion; +import com.strategyobject.substrateclient.tests.containers.TestSubstrateContainer; +import com.strategyobject.substrateclient.transport.ws.WsProvider; +import lombok.val; +import org.junit.jupiter.api.Test; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import java.math.BigInteger; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +import static org.awaitility.Awaitility.await; +import static org.hamcrest.Matchers.notNullValue; +import static org.junit.jupiter.api.Assertions.*; + +@Testcontainers +class SystemTest { + private static final int WAIT_TIMEOUT = 30; + + @Container + private final TestSubstrateContainer substrate = new TestSubstrateContainer(SubstrateVersion.V3_0_0); + + @Test + void account() throws Exception { + val wsProvider = WsProvider.builder() + .setEndpoint(substrate.getWsAddress()); + + try (val api = Api.with(wsProvider).build().join()) { + val system = api.pallet(System.class); + + val alicePublicKey = HexConverter.toBytes("0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"); + val actual = system.account().get(AccountId.fromBytes(alicePublicKey)).join(); + + assertNotNull(actual); + assertEquals( + new BigInteger("1000000000000000000000"), + actual.getData().into(AccountData.class).getFree()); + } + } + + @Test + void events() throws Exception { + val wsProvider = WsProvider.builder() + .setEndpoint(substrate.getWsAddress()); + + try (val api = Api.with(wsProvider).build().join()) { + val system = api.pallet(System.class); + + AtomicReference> eventRecords = new AtomicReference<>(); + val unsubscribe = system.events() + .subscribe((exception, block, value, keys) -> eventRecords.set(value), Arg.EMPTY) + .join(); + + await() + .atMost(WAIT_TIMEOUT, TimeUnit.SECONDS) + .untilAtomic(eventRecords, notNullValue()); + + assertTrue(unsubscribe.get().join()); + assertEquals(1, eventRecords.get().size()); + assertEquals(0, eventRecords.get().get(0).getPhase().getIndex()); + + val eventHolder = eventRecords.get().get(0).getEvent(); + assertEquals(0, eventHolder.getEventIndex()); + assertEquals("System", eventHolder.getPallet().getName()); + assertTrue(eventHolder.getEvent() instanceof System.ExtrinsicSuccess); + } + } +} \ No newline at end of file diff --git a/build.gradle b/build.gradle index 9943fa37..e335d31f 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { allprojects { group = 'com.strategyobject.substrateclient' - version = '0.1.0' + version = '0.2.0' repositories { mavenLocal() @@ -17,7 +17,7 @@ allprojects { } subprojects { - apply plugin: 'java' + apply plugin: 'java-library' apply plugin: 'io.freefair.lombok' apply plugin: 'io.freefair.javadocs' apply plugin: 'maven-publish' @@ -26,17 +26,14 @@ subprojects { sourceCompatibility = '1.8' dependencies { - implementation 'com.google.guava:guava:30.1.1-jre' - implementation 'org.slf4j:slf4j-api:1.7.32' - - testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2' - testImplementation 'org.junit.jupiter:junit-jupiter-params:5.8.2' - testImplementation 'org.assertj:assertj-core:3.22.0' - testImplementation 'org.mockito:mockito-core:3.12.4' - testImplementation 'org.mockito:mockito-inline:3.12.4' - testImplementation 'org.slf4j:slf4j-simple:1.7.32' - - testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.2' + implementation 'com.google.guava:guava:31.1-jre' + implementation 'org.slf4j:slf4j-api:1.7.36' + + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.0' + testImplementation 'org.assertj:assertj-core:3.23.1' + testImplementation 'org.mockito:mockito-core:4.6.1' + testImplementation 'org.mockito:mockito-inline:4.6.1' + testImplementation 'org.slf4j:slf4j-simple:1.7.36' } test { @@ -61,4 +58,4 @@ subprojects { } } } -} \ No newline at end of file +} diff --git a/common/src/main/java/com/strategyobject/substrateclient/common/CommonType.java b/common/src/main/java/com/strategyobject/substrateclient/common/CommonType.java deleted file mode 100644 index 4d5aa968..00000000 --- a/common/src/main/java/com/strategyobject/substrateclient/common/CommonType.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.strategyobject.substrateclient.common; - -public interface CommonType { - class Array implements CommonType { - } -} diff --git a/common/src/main/java/com/strategyobject/substrateclient/common/codegen/AnnotationUtils.java b/common/src/main/java/com/strategyobject/substrateclient/common/codegen/AnnotationUtils.java index 735dd9d9..bf9e5b08 100644 --- a/common/src/main/java/com/strategyobject/substrateclient/common/codegen/AnnotationUtils.java +++ b/common/src/main/java/com/strategyobject/substrateclient/common/codegen/AnnotationUtils.java @@ -8,6 +8,7 @@ import javax.lang.model.AnnotatedConstruct; import javax.lang.model.element.AnnotationMirror; import java.lang.annotation.Annotation; +import java.util.Arrays; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -57,6 +58,20 @@ public static AnnotationSpec suppressWarnings(String... warnings) { .build(); } + public static boolean isAnnotatedWith(AnnotatedConstruct annotated, Class annotation) { + return annotated.getAnnotation(annotation) != null; + } + + @SafeVarargs + public static boolean isAnnotatedWithAny(AnnotatedConstruct annotated, Class... annotations) { + return Arrays.stream(annotations).anyMatch(x -> annotated.getAnnotation(x) != null); + } + + @SafeVarargs + public static boolean isAnnotatedWithAll(AnnotatedConstruct annotated, Class... annotations) { + return Arrays.stream(annotations).allMatch(x -> annotated.getAnnotation(x) != null); + } + private AnnotationUtils() { } } diff --git a/common/src/main/java/com/strategyobject/substrateclient/common/codegen/Constants.java b/common/src/main/java/com/strategyobject/substrateclient/common/codegen/Constants.java deleted file mode 100644 index 0b6e0068..00000000 --- a/common/src/main/java/com/strategyobject/substrateclient/common/codegen/Constants.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.strategyobject.substrateclient.common.codegen; - -import com.strategyobject.substrateclient.common.CommonType; - -public class Constants { - public static final Class ARRAY_TYPE = CommonType.Array.class; - - private Constants() { - } -} diff --git a/common/src/main/java/com/strategyobject/substrateclient/common/codegen/ProcessorContext.java b/common/src/main/java/com/strategyobject/substrateclient/common/codegen/ProcessorContext.java index 301b7fa5..8e42f698 100644 --- a/common/src/main/java/com/strategyobject/substrateclient/common/codegen/ProcessorContext.java +++ b/common/src/main/java/com/strategyobject/substrateclient/common/codegen/ProcessorContext.java @@ -43,7 +43,7 @@ public boolean isNonGeneric(@NonNull TypeMirror type) { return type.getKind().isPrimitive() || ((TypeElement) typeUtils.asElement(type)) .getTypeParameters() - .size() == 0; + .isEmpty(); } public TypeMirror erasure(@NonNull TypeMirror type) { diff --git a/common/src/main/java/com/strategyobject/substrateclient/common/codegen/TypeNotSupportedException.java b/common/src/main/java/com/strategyobject/substrateclient/common/codegen/TypeNotSupportedException.java index 58f5561f..afa10579 100644 --- a/common/src/main/java/com/strategyobject/substrateclient/common/codegen/TypeNotSupportedException.java +++ b/common/src/main/java/com/strategyobject/substrateclient/common/codegen/TypeNotSupportedException.java @@ -3,7 +3,11 @@ import javax.lang.model.type.TypeMirror; public class TypeNotSupportedException extends IllegalArgumentException { - public TypeNotSupportedException(TypeMirror type) { + public TypeNotSupportedException(String type) { super("Type is not supported: " + type); } + + public TypeNotSupportedException(TypeMirror type) { + this(type.toString()); + } } diff --git a/common/src/main/java/com/strategyobject/substrateclient/common/codegen/TypeTraverser.java b/common/src/main/java/com/strategyobject/substrateclient/common/codegen/TypeTraverser.java index c97e7f8d..56db007c 100644 --- a/common/src/main/java/com/strategyobject/substrateclient/common/codegen/TypeTraverser.java +++ b/common/src/main/java/com/strategyobject/substrateclient/common/codegen/TypeTraverser.java @@ -7,17 +7,18 @@ import javax.lang.model.type.*; import java.lang.reflect.Array; -import java.util.Collections; import java.util.LinkedList; import java.util.List; public abstract class TypeTraverser { private final Class clazz; - public TypeTraverser(Class clazz) { + protected TypeTraverser(Class clazz) { this.clazz = clazz; } + protected abstract T whenWildcard(TypeMirror override); + protected abstract T whenTypeVar(@NonNull TypeVariable type, TypeMirror override); protected abstract T whenPrimitiveType(@NonNull PrimitiveType type, TypeMirror override); @@ -30,12 +31,12 @@ public TypeTraverser(Class clazz) { protected abstract T whenArrayType(@NonNull ArrayType type, TypeMirror override, @NonNull T subtype); - protected boolean doTraverseArguments(@NonNull DeclaredType type, TypeMirror override) { - return true; - } - @SuppressWarnings("unchecked") public T traverse(@NonNull TypeMirror type) { + if (type.getKind() == TypeKind.WILDCARD) { + return whenWildcard(null); + } + if (type.getKind() == TypeKind.TYPEVAR) { return whenTypeVar((TypeVariable) type, null); } @@ -57,9 +58,8 @@ public T traverse(@NonNull TypeMirror type) { if (!(type instanceof DeclaredType)) { throw new TypeNotSupportedException(type); } - val declaredType = (DeclaredType) type; - val typeArguments = getTypeArgumentsOrDefault(declaredType, null); + val typeArguments = getTypeArguments(declaredType, null); if (typeArguments.size() == 0) { return whenNonGenericType(declaredType, null); } @@ -74,6 +74,10 @@ public T traverse(@NonNull TypeMirror type) { @SuppressWarnings({"unchecked", "UnstableApiUsage"}) public T traverse(@NonNull TypeMirror type, @NonNull TypeTraverser.TypeTreeNode typeOverride) { + if (type.getKind() == TypeKind.WILDCARD) { + return whenWildcard(typeOverride.type); + } + if (type.getKind() == TypeKind.TYPEVAR) { return whenTypeVar((TypeVariable) type, typeOverride.type); } @@ -109,7 +113,7 @@ public T traverse(@NonNull TypeMirror type, @NonNull TypeTraverser.TypeTreeNode } val declaredType = (DeclaredType) type; - val typeArguments = getTypeArgumentsOrDefault(declaredType, typeOverride.type); + val typeArguments = getTypeArguments(declaredType, typeOverride.type); val typeArgumentsSize = typeArguments.size(); val typeOverrideSize = typeOverride.children.size(); if (typeIsNonGeneric(typeArgumentsSize, typeOverrideSize)) { @@ -117,12 +121,17 @@ public T traverse(@NonNull TypeMirror type, @NonNull TypeTraverser.TypeTreeNode } if (typeIsOverriddenByNonGeneric(typeOverrideSize)) { + if (typeOverride.type != null) { + return whenGenericType(declaredType, typeOverride.type, (T[]) Array.newInstance(clazz, 0)); + } + return whenGenericType( declaredType, - typeOverride.type, + null, typeArguments.stream() .map(this::traverse) .toArray(x -> (T[]) Array.newInstance(clazz, typeArguments.size()))); + } if (typeOverrideSize != typeArgumentsSize) { @@ -160,7 +169,7 @@ public T traverse(@NonNull TypeTraverser.TypeTreeNode typeOverride) { } val declaredType = (DeclaredType) typeOverride.type; - if (typeOverride.children.size() == 0) { + if (typeOverride.children.isEmpty()) { return whenNonGenericType(declaredType, typeOverride.type); } @@ -172,10 +181,8 @@ public T traverse(@NonNull TypeTraverser.TypeTreeNode typeOverride) { .toArray(x -> (T[]) Array.newInstance(clazz, typeOverride.children.size()))); } - private List getTypeArgumentsOrDefault(DeclaredType declaredType, TypeMirror override) { - return (doTraverseArguments(declaredType, override) ? - declaredType.getTypeArguments() : - Collections.emptyList()); + protected List getTypeArguments(DeclaredType declaredType, TypeMirror override) { + return declaredType.getTypeArguments(); } private boolean typeIsNonGeneric(int typeArgumentsSize, int typeOverrideSize) { diff --git a/common/src/main/java/com/strategyobject/substrateclient/common/codegen/TypeUtils.java b/common/src/main/java/com/strategyobject/substrateclient/common/codegen/TypeUtils.java index 26b17de8..98ca9c46 100644 --- a/common/src/main/java/com/strategyobject/substrateclient/common/codegen/TypeUtils.java +++ b/common/src/main/java/com/strategyobject/substrateclient/common/codegen/TypeUtils.java @@ -8,7 +8,7 @@ import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; -import static com.strategyobject.substrateclient.common.utils.StringUtils.capitalize; +import static com.strategyobject.substrateclient.common.strings.StringUtils.capitalize; public class TypeUtils { private static final String SETTER_PREFIX = "set"; @@ -48,4 +48,7 @@ public static String getSimpleName(TypeMirror type) { throw new IllegalArgumentException(String.format("Cannot populate the name of %s", type)); } + + private TypeUtils() { + } } diff --git a/common/src/main/java/com/strategyobject/substrateclient/common/utils/HexConverter.java b/common/src/main/java/com/strategyobject/substrateclient/common/convert/HexConverter.java similarity index 91% rename from common/src/main/java/com/strategyobject/substrateclient/common/utils/HexConverter.java rename to common/src/main/java/com/strategyobject/substrateclient/common/convert/HexConverter.java index 14427fe8..bc511fe0 100644 --- a/common/src/main/java/com/strategyobject/substrateclient/common/utils/HexConverter.java +++ b/common/src/main/java/com/strategyobject/substrateclient/common/convert/HexConverter.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.common.utils; +package com.strategyobject.substrateclient.common.convert; import com.google.common.base.Preconditions; import lombok.NonNull; @@ -9,7 +9,9 @@ public class HexConverter { private static final char[] HEX = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; public static String toHex(byte @NonNull [] data) { - Preconditions.checkArgument(data.length > 0); + if (data.length == 0) { + return "0x"; + } val hex = new char[(data.length * 2) + 2]; hex[0] = '0'; @@ -50,4 +52,7 @@ public static byte[] toBytes(@NonNull String hex) { return bytes; } + + private HexConverter() { + } } diff --git a/common/src/main/java/com/strategyobject/substrateclient/common/reflection/ClassUtils.java b/common/src/main/java/com/strategyobject/substrateclient/common/reflection/ClassUtils.java new file mode 100644 index 00000000..3ce1166a --- /dev/null +++ b/common/src/main/java/com/strategyobject/substrateclient/common/reflection/ClassUtils.java @@ -0,0 +1,19 @@ +package com.strategyobject.substrateclient.common.reflection; + +import lombok.val; + +public final class ClassUtils { + + public static boolean hasDefaultConstructor(Class clazz) { + for (val constructor : clazz.getConstructors()) { + if (constructor.getParameterCount() == 0) { + return true; + } + } + + return false; + } + + private ClassUtils() { + } +} diff --git a/common/src/main/java/com/strategyobject/substrateclient/common/reflection/Scanner.java b/common/src/main/java/com/strategyobject/substrateclient/common/reflection/Scanner.java index 75fb3f90..9d68a380 100644 --- a/common/src/main/java/com/strategyobject/substrateclient/common/reflection/Scanner.java +++ b/common/src/main/java/com/strategyobject/substrateclient/common/reflection/Scanner.java @@ -5,6 +5,7 @@ import org.reflections.util.ClasspathHelper; import org.reflections.util.ConfigurationBuilder; +import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Arrays; import java.util.Set; @@ -19,15 +20,18 @@ private Scanner(String[] prefixes) { .setUrls( Arrays.stream(prefixes) .flatMap(p -> ClasspathHelper.forPackage(p).stream()) - .collect(Collectors.toCollection(ArrayList::new))) - ); + .collect(Collectors.toCollection(ArrayList::new)))); } - public static Scanner forPrefixes(@NonNull String... prefixes){ + public static Scanner forPrefixes(@NonNull String... prefixes) { return new Scanner(prefixes); } public Set> getSubTypesOf(Class clazz) { return reflections.getSubTypesOf(clazz); } + + public Set> getTypesAnnotatedWith(Class annotation) { + return reflections.getTypesAnnotatedWith(annotation); + } } diff --git a/common/src/main/java/com/strategyobject/substrateclient/common/utils/StringUtils.java b/common/src/main/java/com/strategyobject/substrateclient/common/strings/StringUtils.java similarity index 95% rename from common/src/main/java/com/strategyobject/substrateclient/common/utils/StringUtils.java rename to common/src/main/java/com/strategyobject/substrateclient/common/strings/StringUtils.java index 4673604f..35749e5a 100644 --- a/common/src/main/java/com/strategyobject/substrateclient/common/utils/StringUtils.java +++ b/common/src/main/java/com/strategyobject/substrateclient/common/strings/StringUtils.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.common.utils; +package com.strategyobject.substrateclient.common.strings; import com.google.common.base.Preconditions; import lombok.NonNull; diff --git a/common/src/main/java/com/strategyobject/substrateclient/common/types/Array.java b/common/src/main/java/com/strategyobject/substrateclient/common/types/Array.java new file mode 100644 index 00000000..0fbc2434 --- /dev/null +++ b/common/src/main/java/com/strategyobject/substrateclient/common/types/Array.java @@ -0,0 +1,4 @@ +package com.strategyobject.substrateclient.common.types; + +public interface Array { +} diff --git a/common/src/main/java/com/strategyobject/substrateclient/common/types/Bounded.java b/common/src/main/java/com/strategyobject/substrateclient/common/types/Bounded.java new file mode 100644 index 00000000..c509ee88 --- /dev/null +++ b/common/src/main/java/com/strategyobject/substrateclient/common/types/Bounded.java @@ -0,0 +1,22 @@ +package com.strategyobject.substrateclient.common.types; + +import com.google.common.base.Preconditions; + +/** + * Upperbounds the size of a class. + * + * @param Size + */ +public interface Bounded { + /** + * Asserts that the size is correct. + * + * @param expected Expected size + * @param actual Actual size + */ + default void assertSize(S expected, int actual) { + Preconditions.checkArgument( + actual <= expected.getValue(), + "Provided size (%s) is invalid. Expected not more than %s.", actual, expected.getValue()); + } +} diff --git a/common/src/main/java/com/strategyobject/substrateclient/common/types/Bytes.java b/common/src/main/java/com/strategyobject/substrateclient/common/types/Bytes.java new file mode 100644 index 00000000..52347492 --- /dev/null +++ b/common/src/main/java/com/strategyobject/substrateclient/common/types/Bytes.java @@ -0,0 +1,8 @@ +package com.strategyobject.substrateclient.common.types; + +import lombok.NonNull; + +@FunctionalInterface +public interface Bytes { + byte @NonNull [] getBytes(); +} diff --git a/common/src/main/java/com/strategyobject/substrateclient/common/types/Enums.java b/common/src/main/java/com/strategyobject/substrateclient/common/types/Enums.java new file mode 100644 index 00000000..a157cace --- /dev/null +++ b/common/src/main/java/com/strategyobject/substrateclient/common/types/Enums.java @@ -0,0 +1,18 @@ +package com.strategyobject.substrateclient.common.types; + +import com.google.common.base.Preconditions; +import lombok.NonNull; + +public class Enums { + public static > E lookup(E @NonNull [] enumValues, int index) { + Preconditions.checkArgument(enumValues.length > 0); + Preconditions.checkArgument(index >= 0); + Preconditions.checkArgument(index < enumValues.length, + enumValues[0].getClass().getSimpleName() + " has no value associated with index " + index); + + return enumValues[index]; + } + + private Enums() { + } +} diff --git a/common/src/main/java/com/strategyobject/substrateclient/common/types/Fixed.java b/common/src/main/java/com/strategyobject/substrateclient/common/types/Fixed.java new file mode 100644 index 00000000..3798a8a3 --- /dev/null +++ b/common/src/main/java/com/strategyobject/substrateclient/common/types/Fixed.java @@ -0,0 +1,23 @@ +package com.strategyobject.substrateclient.common.types; + +import com.google.common.base.Preconditions; + +/** + * Sets the size of a class. + * + * @param Size + */ +public interface Fixed { + + /** + * Asserts that the size is correct. + * + * @param expected Expected size + * @param actual Actual size + */ + default void assertSize(S expected, int actual) { + Preconditions.checkArgument( + actual == expected.getValue(), + "Provided size (%s) is invalid. Expected %s.", actual, expected.getValue()); + } +} diff --git a/common/src/main/java/com/strategyobject/substrateclient/common/types/FixedBytes.java b/common/src/main/java/com/strategyobject/substrateclient/common/types/FixedBytes.java new file mode 100644 index 00000000..8dd39bf9 --- /dev/null +++ b/common/src/main/java/com/strategyobject/substrateclient/common/types/FixedBytes.java @@ -0,0 +1,26 @@ +package com.strategyobject.substrateclient.common.types; + +import com.google.common.base.Preconditions; +import lombok.EqualsAndHashCode; +import lombok.NonNull; + +@EqualsAndHashCode +public abstract class FixedBytes implements Fixed, Bytes { + private final byte @NonNull [] bytes; + + @Override + public byte @NonNull [] getBytes() { + return bytes; + } + + protected FixedBytes(byte @NonNull [] bytes, S size) { + Preconditions.checkNotNull(bytes); + assertSize(size, bytes.length); + + this.bytes = bytes; + } + + public int getSize() { + return bytes.length; + } +} diff --git a/common/src/main/java/com/strategyobject/substrateclient/common/types/Into.java b/common/src/main/java/com/strategyobject/substrateclient/common/types/Into.java new file mode 100644 index 00000000..af28ed24 --- /dev/null +++ b/common/src/main/java/com/strategyobject/substrateclient/common/types/Into.java @@ -0,0 +1,8 @@ +package com.strategyobject.substrateclient.common.types; + +public interface Into { + @SuppressWarnings("unchecked") + default T into(Class clazz) { + return (T) this; + } +} diff --git a/common/src/main/java/com/strategyobject/substrateclient/common/types/Lambda.java b/common/src/main/java/com/strategyobject/substrateclient/common/types/Lambda.java new file mode 100644 index 00000000..d5099ceb --- /dev/null +++ b/common/src/main/java/com/strategyobject/substrateclient/common/types/Lambda.java @@ -0,0 +1,15 @@ +package com.strategyobject.substrateclient.common.types; + +public final class Lambda { + + public static void noop(T ignored) { + // do nothing + } + + public static void noop(T0 _x, T1 _y) { + // do nothing + } + + private Lambda() { + } +} diff --git a/types/src/main/java/com/strategyobject/substrateclient/types/Result.java b/common/src/main/java/com/strategyobject/substrateclient/common/types/Result.java similarity index 99% rename from types/src/main/java/com/strategyobject/substrateclient/types/Result.java rename to common/src/main/java/com/strategyobject/substrateclient/common/types/Result.java index f36f5039..51325dcf 100644 --- a/types/src/main/java/com/strategyobject/substrateclient/types/Result.java +++ b/common/src/main/java/com/strategyobject/substrateclient/common/types/Result.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types; +package com.strategyobject.substrateclient.common.types; import lombok.val; diff --git a/types/src/main/java/com/strategyobject/substrateclient/types/Size.java b/common/src/main/java/com/strategyobject/substrateclient/common/types/Size.java similarity index 79% rename from types/src/main/java/com/strategyobject/substrateclient/types/Size.java rename to common/src/main/java/com/strategyobject/substrateclient/common/types/Size.java index 11a1c49b..156ddc2a 100644 --- a/types/src/main/java/com/strategyobject/substrateclient/types/Size.java +++ b/common/src/main/java/com/strategyobject/substrateclient/common/types/Size.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types; +package com.strategyobject.substrateclient.common.types; public interface Size { int getValue(); @@ -8,6 +8,7 @@ public interface Size { Of64 of64 = new Of64(); Of96 of96 = new Of96(); Of128 of128 = new Of128(); + Of256 of256 = new Of256(); class Zero implements Size { @Override @@ -43,4 +44,11 @@ public int getValue() { return 128; } } + + class Of256 implements Size { + @Override + public int getValue() { + return 256; + } + } } diff --git a/common/src/main/java/com/strategyobject/substrateclient/common/types/Unit.java b/common/src/main/java/com/strategyobject/substrateclient/common/types/Unit.java new file mode 100644 index 00000000..85059d52 --- /dev/null +++ b/common/src/main/java/com/strategyobject/substrateclient/common/types/Unit.java @@ -0,0 +1,12 @@ +package com.strategyobject.substrateclient.common.types; + +public class Unit { + private static final Unit UNIT = new Unit(); + + public static Unit get() { + return UNIT; + } + + private Unit() { + } +} diff --git a/types/src/main/java/com/strategyobject/substrateclient/types/tuples/Pair.java b/common/src/main/java/com/strategyobject/substrateclient/common/types/tuple/Pair.java similarity index 76% rename from types/src/main/java/com/strategyobject/substrateclient/types/tuples/Pair.java rename to common/src/main/java/com/strategyobject/substrateclient/common/types/tuple/Pair.java index 52fb6c04..2c1f23eb 100644 --- a/types/src/main/java/com/strategyobject/substrateclient/types/tuples/Pair.java +++ b/common/src/main/java/com/strategyobject/substrateclient/common/types/tuple/Pair.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types.tuples; +package com.strategyobject.substrateclient.common.types.tuple; import lombok.Getter; import lombok.RequiredArgsConstructor; diff --git a/types/src/main/java/com/strategyobject/substrateclient/types/union/Union.java b/common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union.java similarity index 69% rename from types/src/main/java/com/strategyobject/substrateclient/types/union/Union.java rename to common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union.java index 7a0c24a4..15bf5c2c 100644 --- a/types/src/main/java/com/strategyobject/substrateclient/types/union/Union.java +++ b/common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types.union; +package com.strategyobject.substrateclient.common.types.union; public abstract class Union { protected int index; diff --git a/types/src/main/java/com/strategyobject/substrateclient/types/union/Union1.java b/common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union1.java similarity index 89% rename from types/src/main/java/com/strategyobject/substrateclient/types/union/Union1.java rename to common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union1.java index 966238a8..9665f46f 100644 --- a/types/src/main/java/com/strategyobject/substrateclient/types/union/Union1.java +++ b/common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union1.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types.union; +package com.strategyobject.substrateclient.common.types.union; import lombok.NonNull; import lombok.val; diff --git a/types/src/main/java/com/strategyobject/substrateclient/types/union/Union10.java b/common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union10.java similarity index 98% rename from types/src/main/java/com/strategyobject/substrateclient/types/union/Union10.java rename to common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union10.java index 0e17291c..78cd0bf5 100644 --- a/types/src/main/java/com/strategyobject/substrateclient/types/union/Union10.java +++ b/common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union10.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types.union; +package com.strategyobject.substrateclient.common.types.union; import com.google.common.base.Preconditions; import lombok.NonNull; diff --git a/types/src/main/java/com/strategyobject/substrateclient/types/union/Union11.java b/common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union11.java similarity index 99% rename from types/src/main/java/com/strategyobject/substrateclient/types/union/Union11.java rename to common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union11.java index 15777e79..e48725ee 100644 --- a/types/src/main/java/com/strategyobject/substrateclient/types/union/Union11.java +++ b/common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union11.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types.union; +package com.strategyobject.substrateclient.common.types.union; import com.google.common.base.Preconditions; import lombok.NonNull; diff --git a/types/src/main/java/com/strategyobject/substrateclient/types/union/Union12.java b/common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union12.java similarity index 99% rename from types/src/main/java/com/strategyobject/substrateclient/types/union/Union12.java rename to common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union12.java index 07bfe149..68dcd6f0 100644 --- a/types/src/main/java/com/strategyobject/substrateclient/types/union/Union12.java +++ b/common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union12.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types.union; +package com.strategyobject.substrateclient.common.types.union; import com.google.common.base.Preconditions; import lombok.NonNull; diff --git a/types/src/main/java/com/strategyobject/substrateclient/types/union/Union2.java b/common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union2.java similarity index 94% rename from types/src/main/java/com/strategyobject/substrateclient/types/union/Union2.java rename to common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union2.java index 3bd1608d..102cfad0 100644 --- a/types/src/main/java/com/strategyobject/substrateclient/types/union/Union2.java +++ b/common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union2.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types.union; +package com.strategyobject.substrateclient.common.types.union; import com.google.common.base.Preconditions; import lombok.NonNull; diff --git a/types/src/main/java/com/strategyobject/substrateclient/types/union/Union3.java b/common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union3.java similarity index 96% rename from types/src/main/java/com/strategyobject/substrateclient/types/union/Union3.java rename to common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union3.java index 6627d8c4..f0f3e083 100644 --- a/types/src/main/java/com/strategyobject/substrateclient/types/union/Union3.java +++ b/common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union3.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types.union; +package com.strategyobject.substrateclient.common.types.union; import com.google.common.base.Preconditions; import lombok.NonNull; diff --git a/types/src/main/java/com/strategyobject/substrateclient/types/union/Union4.java b/common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union4.java similarity index 97% rename from types/src/main/java/com/strategyobject/substrateclient/types/union/Union4.java rename to common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union4.java index 137720aa..776ccdc4 100644 --- a/types/src/main/java/com/strategyobject/substrateclient/types/union/Union4.java +++ b/common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union4.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types.union; +package com.strategyobject.substrateclient.common.types.union; import com.google.common.base.Preconditions; import lombok.NonNull; diff --git a/types/src/main/java/com/strategyobject/substrateclient/types/union/Union5.java b/common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union5.java similarity index 97% rename from types/src/main/java/com/strategyobject/substrateclient/types/union/Union5.java rename to common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union5.java index e25c7435..f0143292 100644 --- a/types/src/main/java/com/strategyobject/substrateclient/types/union/Union5.java +++ b/common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union5.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types.union; +package com.strategyobject.substrateclient.common.types.union; import com.google.common.base.Preconditions; import lombok.NonNull; diff --git a/types/src/main/java/com/strategyobject/substrateclient/types/union/Union6.java b/common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union6.java similarity index 98% rename from types/src/main/java/com/strategyobject/substrateclient/types/union/Union6.java rename to common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union6.java index fc864618..e6fe50e7 100644 --- a/types/src/main/java/com/strategyobject/substrateclient/types/union/Union6.java +++ b/common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union6.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types.union; +package com.strategyobject.substrateclient.common.types.union; import com.google.common.base.Preconditions; import lombok.NonNull; diff --git a/types/src/main/java/com/strategyobject/substrateclient/types/union/Union7.java b/common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union7.java similarity index 98% rename from types/src/main/java/com/strategyobject/substrateclient/types/union/Union7.java rename to common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union7.java index 0bd0ebf3..c89b34da 100644 --- a/types/src/main/java/com/strategyobject/substrateclient/types/union/Union7.java +++ b/common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union7.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types.union; +package com.strategyobject.substrateclient.common.types.union; import com.google.common.base.Preconditions; import lombok.NonNull; diff --git a/types/src/main/java/com/strategyobject/substrateclient/types/union/Union8.java b/common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union8.java similarity index 98% rename from types/src/main/java/com/strategyobject/substrateclient/types/union/Union8.java rename to common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union8.java index 91157fdc..34cc694f 100644 --- a/types/src/main/java/com/strategyobject/substrateclient/types/union/Union8.java +++ b/common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union8.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types.union; +package com.strategyobject.substrateclient.common.types.union; import com.google.common.base.Preconditions; import lombok.NonNull; diff --git a/types/src/main/java/com/strategyobject/substrateclient/types/union/Union9.java b/common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union9.java similarity index 98% rename from types/src/main/java/com/strategyobject/substrateclient/types/union/Union9.java rename to common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union9.java index c2ae5055..b90903c9 100644 --- a/types/src/main/java/com/strategyobject/substrateclient/types/union/Union9.java +++ b/common/src/main/java/com/strategyobject/substrateclient/common/types/union/Union9.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types.union; +package com.strategyobject.substrateclient.common.types.union; import com.google.common.base.Preconditions; import lombok.NonNull; diff --git a/common/src/test/java/com/strategyobject/substrateclient/common/utils/HexConverterTests.java b/common/src/test/java/com/strategyobject/substrateclient/common/convert/HexConverterTests.java similarity index 94% rename from common/src/test/java/com/strategyobject/substrateclient/common/utils/HexConverterTests.java rename to common/src/test/java/com/strategyobject/substrateclient/common/convert/HexConverterTests.java index ab58dbf2..1a5cac9f 100644 --- a/common/src/test/java/com/strategyobject/substrateclient/common/utils/HexConverterTests.java +++ b/common/src/test/java/com/strategyobject/substrateclient/common/convert/HexConverterTests.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.common.utils; +package com.strategyobject.substrateclient.common.convert; import com.strategyobject.substrateclient.tests.TestSuite; import lombok.AccessLevel; @@ -12,7 +12,7 @@ import static org.junit.jupiter.api.Assertions.*; -public class HexConverterTests { +class HexConverterTests { @TestFactory Stream toHex() { return TestSuite.of( @@ -21,15 +21,15 @@ Stream toHex() { Test.toHex(new byte[]{(byte) 255, 0}, "0xff00"), Test.toHex(new byte[]{(byte) 0, (byte) 255}, "0x00ff"), Test.toHex(new byte[]{127, (byte) 128}, "0x7f80"), - Test.toHex(new byte[]{(byte) 128, (byte) 127}, "0x807f") + Test.toHex(new byte[]{(byte) 128, (byte) 127}, "0x807f"), + Test.toHex(new byte[0], "0x") ); } @TestFactory Stream toHexThrows() { return TestSuite.of( - Test.toHex(null, IllegalArgumentException.class), - Test.toHex(new byte[]{}, IllegalArgumentException.class) + Test.toHex(null, IllegalArgumentException.class) ); } @@ -57,7 +57,7 @@ Stream toBytesThrows() { } @AllArgsConstructor(access = AccessLevel.PRIVATE) - static class Test extends TestSuite.TestCase { + static class Test implements TestSuite.TestCase { private final String displayName; private final Executable executable; diff --git a/common/src/test/java/com/strategyobject/substrateclient/common/eventemitter/EventEmitterTest.java b/common/src/test/java/com/strategyobject/substrateclient/common/eventemitter/EventEmitterTest.java index 81436286..3fbc7776 100644 --- a/common/src/test/java/com/strategyobject/substrateclient/common/eventemitter/EventEmitterTest.java +++ b/common/src/test/java/com/strategyobject/substrateclient/common/eventemitter/EventEmitterTest.java @@ -43,7 +43,7 @@ void HandlerNotCalledOnDifferentEvent() { emitter.emit(TestEvents.TWO); - assertEquals(hitCount[0], 0); + assertEquals(0, hitCount[0]); } @Test diff --git a/common/src/test/java/com/strategyobject/substrateclient/common/utils/StringUtilsTest.java b/common/src/test/java/com/strategyobject/substrateclient/common/strings/StringUtilsTest.java similarity index 94% rename from common/src/test/java/com/strategyobject/substrateclient/common/utils/StringUtilsTest.java rename to common/src/test/java/com/strategyobject/substrateclient/common/strings/StringUtilsTest.java index f6c9d6f2..4db4208a 100644 --- a/common/src/test/java/com/strategyobject/substrateclient/common/utils/StringUtilsTest.java +++ b/common/src/test/java/com/strategyobject/substrateclient/common/strings/StringUtilsTest.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.common.utils; +package com.strategyobject.substrateclient.common.strings; import lombok.val; import org.junit.jupiter.api.Test; diff --git a/common/src/test/java/com/strategyobject/substrateclient/common/types/EnumsTest.java b/common/src/test/java/com/strategyobject/substrateclient/common/types/EnumsTest.java new file mode 100644 index 00000000..7e958d7f --- /dev/null +++ b/common/src/test/java/com/strategyobject/substrateclient/common/types/EnumsTest.java @@ -0,0 +1,28 @@ +package com.strategyobject.substrateclient.common.types; + +import lombok.val; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class EnumsTest { + + enum TestEnum { + YES, NO, MAYBE + } + + @Test + void lookup() { + val actual = Enums.lookup(TestEnum.values(), 0); + + assertEquals(TestEnum.YES, actual); + } + + @Test + void lookupOutOfBounds() { + val values = TestEnum.values(); + val thrown = assertThrows(RuntimeException.class, () -> Enums.lookup(values, 10)); + + assertTrue(thrown.getMessage().contains("TestEnum")); + } +} \ No newline at end of file diff --git a/types/src/test/java/com/strategyobject/substrateclient/types/ResultTest.java b/common/src/test/java/com/strategyobject/substrateclient/common/types/ResultTest.java similarity index 98% rename from types/src/test/java/com/strategyobject/substrateclient/types/ResultTest.java rename to common/src/test/java/com/strategyobject/substrateclient/common/types/ResultTest.java index a8debcdf..f1f6f03a 100644 --- a/types/src/test/java/com/strategyobject/substrateclient/types/ResultTest.java +++ b/common/src/test/java/com/strategyobject/substrateclient/common/types/ResultTest.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types; +package com.strategyobject.substrateclient.common.types; import lombok.val; import org.junit.jupiter.api.Test; @@ -9,8 +9,7 @@ import static org.junit.jupiter.api.Assertions.*; class ResultTest { - - + @Test void isOk() { assertTrue(Result.ok(1).isOk()); diff --git a/types/src/test/java/com/strategyobject/substrateclient/types/union/Union10Test.java b/common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union10Test.java similarity index 88% rename from types/src/test/java/com/strategyobject/substrateclient/types/union/Union10Test.java rename to common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union10Test.java index abf62b66..3e9d5253 100644 --- a/types/src/test/java/com/strategyobject/substrateclient/types/union/Union10Test.java +++ b/common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union10Test.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types.union; +package com.strategyobject.substrateclient.common.types.union; import lombok.val; import org.junit.jupiter.api.Assertions; @@ -16,8 +16,8 @@ void getItem0() { val expected = false; val union = Union10.withItem0(expected); - Assertions.assertEquals(0, union.getIndex()); - Assertions.assertEquals(expected, union.getItem0()); + assertEquals(0, union.getIndex()); + assertEquals(expected, union.getItem0()); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); @@ -34,9 +34,9 @@ void getItem1() { val expected = 1; val union = Union10.withItem1(expected); - Assertions.assertEquals(1, union.getIndex()); + assertEquals(1, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); - Assertions.assertEquals(expected, union.getItem1()); + assertEquals(expected, union.getItem1()); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); @@ -52,10 +52,10 @@ void getItem2() { val expected = "2"; val union = Union10.withItem2(expected); - Assertions.assertEquals(2, union.getIndex()); + assertEquals(2, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); - Assertions.assertEquals(expected, union.getItem2()); + assertEquals(expected, union.getItem2()); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); Assertions.assertThrows(IllegalStateException.class, union::getItem5); @@ -70,11 +70,11 @@ void getItem3() { val expected = 3f; val union = Union10.withItem3(expected); - Assertions.assertEquals(3, union.getIndex()); + assertEquals(3, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); - Assertions.assertEquals(expected, union.getItem3()); + assertEquals(expected, union.getItem3()); Assertions.assertThrows(IllegalStateException.class, union::getItem4); Assertions.assertThrows(IllegalStateException.class, union::getItem5); Assertions.assertThrows(IllegalStateException.class, union::getItem6); @@ -88,12 +88,12 @@ void getItem4() { val expected = true; val union = Union10.withItem4(expected); - Assertions.assertEquals(4, union.getIndex()); + assertEquals(4, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); - Assertions.assertEquals(expected, union.getItem4()); + assertEquals(expected, union.getItem4()); Assertions.assertThrows(IllegalStateException.class, union::getItem5); Assertions.assertThrows(IllegalStateException.class, union::getItem6); Assertions.assertThrows(IllegalStateException.class, union::getItem7); @@ -106,13 +106,13 @@ void getItem5() { val expected = 5; val union = Union10.withItem5(expected); - Assertions.assertEquals(5, union.getIndex()); + assertEquals(5, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); - Assertions.assertEquals(expected, union.getItem5()); + assertEquals(expected, union.getItem5()); Assertions.assertThrows(IllegalStateException.class, union::getItem6); Assertions.assertThrows(IllegalStateException.class, union::getItem7); Assertions.assertThrows(IllegalStateException.class, union::getItem8); @@ -124,14 +124,14 @@ void getItem6() { val expected = "6"; val union = Union10.withItem6(expected); - Assertions.assertEquals(6, union.getIndex()); + assertEquals(6, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); Assertions.assertThrows(IllegalStateException.class, union::getItem5); - Assertions.assertEquals(expected, union.getItem6()); + assertEquals(expected, union.getItem6()); Assertions.assertThrows(IllegalStateException.class, union::getItem7); Assertions.assertThrows(IllegalStateException.class, union::getItem8); Assertions.assertThrows(IllegalStateException.class, union::getItem9); @@ -142,7 +142,7 @@ void getItem7() { val expected = 7f; val union = Union10.withItem7(expected); - Assertions.assertEquals(7, union.getIndex()); + assertEquals(7, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); @@ -150,7 +150,7 @@ void getItem7() { Assertions.assertThrows(IllegalStateException.class, union::getItem4); Assertions.assertThrows(IllegalStateException.class, union::getItem5); Assertions.assertThrows(IllegalStateException.class, union::getItem6); - Assertions.assertEquals(expected, union.getItem7()); + assertEquals(expected, union.getItem7()); Assertions.assertThrows(IllegalStateException.class, union::getItem8); Assertions.assertThrows(IllegalStateException.class, union::getItem9); } @@ -160,7 +160,7 @@ void getItem8() { val expected = false; val union = Union10.withItem8(expected); - Assertions.assertEquals(8, union.getIndex()); + assertEquals(8, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); @@ -169,7 +169,7 @@ void getItem8() { Assertions.assertThrows(IllegalStateException.class, union::getItem5); Assertions.assertThrows(IllegalStateException.class, union::getItem6); Assertions.assertThrows(IllegalStateException.class, union::getItem7); - Assertions.assertEquals(expected, union.getItem8()); + assertEquals(expected, union.getItem8()); Assertions.assertThrows(IllegalStateException.class, union::getItem9); } @@ -178,7 +178,7 @@ void getItem9() { val expected = 9; val union = Union10.withItem9(expected); - Assertions.assertEquals(9, union.getIndex()); + assertEquals(9, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); @@ -188,7 +188,7 @@ void getItem9() { Assertions.assertThrows(IllegalStateException.class, union::getItem6); Assertions.assertThrows(IllegalStateException.class, union::getItem7); Assertions.assertThrows(IllegalStateException.class, union::getItem8); - Assertions.assertEquals(expected, union.getItem9()); + assertEquals(expected, union.getItem9()); } @SuppressWarnings({"unchecked", "rawtypes"}) diff --git a/types/src/test/java/com/strategyobject/substrateclient/types/union/Union11Test.java b/common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union11Test.java similarity index 89% rename from types/src/test/java/com/strategyobject/substrateclient/types/union/Union11Test.java rename to common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union11Test.java index 19a501db..489262ae 100644 --- a/types/src/test/java/com/strategyobject/substrateclient/types/union/Union11Test.java +++ b/common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union11Test.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types.union; +package com.strategyobject.substrateclient.common.types.union; import lombok.val; import org.junit.jupiter.api.Assertions; @@ -16,8 +16,8 @@ void getItem0() { val expected = false; val union = Union11.withItem0(expected); - Assertions.assertEquals(0, union.getIndex()); - Assertions.assertEquals(expected, union.getItem0()); + assertEquals(0, union.getIndex()); + assertEquals(expected, union.getItem0()); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); @@ -35,9 +35,9 @@ void getItem1() { val expected = 1; val union = Union11.withItem1(expected); - Assertions.assertEquals(1, union.getIndex()); + assertEquals(1, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); - Assertions.assertEquals(expected, union.getItem1()); + assertEquals(expected, union.getItem1()); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); @@ -54,10 +54,10 @@ void getItem2() { val expected = "2"; val union = Union11.withItem2(expected); - Assertions.assertEquals(2, union.getIndex()); + assertEquals(2, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); - Assertions.assertEquals(expected, union.getItem2()); + assertEquals(expected, union.getItem2()); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); Assertions.assertThrows(IllegalStateException.class, union::getItem5); @@ -73,11 +73,11 @@ void getItem3() { val expected = 3f; val union = Union11.withItem3(expected); - Assertions.assertEquals(3, union.getIndex()); + assertEquals(3, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); - Assertions.assertEquals(expected, union.getItem3()); + assertEquals(expected, union.getItem3()); Assertions.assertThrows(IllegalStateException.class, union::getItem4); Assertions.assertThrows(IllegalStateException.class, union::getItem5); Assertions.assertThrows(IllegalStateException.class, union::getItem6); @@ -92,12 +92,12 @@ void getItem4() { val expected = true; val union = Union11.withItem4(expected); - Assertions.assertEquals(4, union.getIndex()); + assertEquals(4, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); - Assertions.assertEquals(expected, union.getItem4()); + assertEquals(expected, union.getItem4()); Assertions.assertThrows(IllegalStateException.class, union::getItem5); Assertions.assertThrows(IllegalStateException.class, union::getItem6); Assertions.assertThrows(IllegalStateException.class, union::getItem7); @@ -111,13 +111,13 @@ void getItem5() { val expected = 5; val union = Union11.withItem5(expected); - Assertions.assertEquals(5, union.getIndex()); + assertEquals(5, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); - Assertions.assertEquals(expected, union.getItem5()); + assertEquals(expected, union.getItem5()); Assertions.assertThrows(IllegalStateException.class, union::getItem6); Assertions.assertThrows(IllegalStateException.class, union::getItem7); Assertions.assertThrows(IllegalStateException.class, union::getItem8); @@ -130,14 +130,14 @@ void getItem6() { val expected = "6"; val union = Union11.withItem6(expected); - Assertions.assertEquals(6, union.getIndex()); + assertEquals(6, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); Assertions.assertThrows(IllegalStateException.class, union::getItem5); - Assertions.assertEquals(expected, union.getItem6()); + assertEquals(expected, union.getItem6()); Assertions.assertThrows(IllegalStateException.class, union::getItem7); Assertions.assertThrows(IllegalStateException.class, union::getItem8); Assertions.assertThrows(IllegalStateException.class, union::getItem9); @@ -149,7 +149,7 @@ void getItem7() { val expected = 7f; val union = Union11.withItem7(expected); - Assertions.assertEquals(7, union.getIndex()); + assertEquals(7, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); @@ -157,7 +157,7 @@ void getItem7() { Assertions.assertThrows(IllegalStateException.class, union::getItem4); Assertions.assertThrows(IllegalStateException.class, union::getItem5); Assertions.assertThrows(IllegalStateException.class, union::getItem6); - Assertions.assertEquals(expected, union.getItem7()); + assertEquals(expected, union.getItem7()); Assertions.assertThrows(IllegalStateException.class, union::getItem8); Assertions.assertThrows(IllegalStateException.class, union::getItem9); Assertions.assertThrows(IllegalStateException.class, union::getItem10); @@ -168,7 +168,7 @@ void getItem8() { val expected = false; val union = Union11.withItem8(expected); - Assertions.assertEquals(8, union.getIndex()); + assertEquals(8, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); @@ -177,7 +177,7 @@ void getItem8() { Assertions.assertThrows(IllegalStateException.class, union::getItem5); Assertions.assertThrows(IllegalStateException.class, union::getItem6); Assertions.assertThrows(IllegalStateException.class, union::getItem7); - Assertions.assertEquals(expected, union.getItem8()); + assertEquals(expected, union.getItem8()); Assertions.assertThrows(IllegalStateException.class, union::getItem9); Assertions.assertThrows(IllegalStateException.class, union::getItem10); } @@ -187,7 +187,7 @@ void getItem9() { val expected = 9; val union = Union11.withItem9(expected); - Assertions.assertEquals(9, union.getIndex()); + assertEquals(9, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); @@ -197,7 +197,7 @@ void getItem9() { Assertions.assertThrows(IllegalStateException.class, union::getItem6); Assertions.assertThrows(IllegalStateException.class, union::getItem7); Assertions.assertThrows(IllegalStateException.class, union::getItem8); - Assertions.assertEquals(expected, union.getItem9()); + assertEquals(expected, union.getItem9()); Assertions.assertThrows(IllegalStateException.class, union::getItem10); } @@ -206,7 +206,7 @@ void getItem10() { val expected = "10"; val union = Union11.withItem10(expected); - Assertions.assertEquals(10, union.getIndex()); + assertEquals(10, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); @@ -217,7 +217,7 @@ void getItem10() { Assertions.assertThrows(IllegalStateException.class, union::getItem7); Assertions.assertThrows(IllegalStateException.class, union::getItem8); Assertions.assertThrows(IllegalStateException.class, union::getItem9); - Assertions.assertEquals(expected, union.getItem10()); + assertEquals(expected, union.getItem10()); } @SuppressWarnings({"unchecked", "rawtypes"}) diff --git a/types/src/test/java/com/strategyobject/substrateclient/types/union/Union12Test.java b/common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union12Test.java similarity index 90% rename from types/src/test/java/com/strategyobject/substrateclient/types/union/Union12Test.java rename to common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union12Test.java index 06132bcd..81f4a461 100644 --- a/types/src/test/java/com/strategyobject/substrateclient/types/union/Union12Test.java +++ b/common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union12Test.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types.union; +package com.strategyobject.substrateclient.common.types.union; import lombok.val; import org.junit.jupiter.api.Assertions; @@ -16,8 +16,8 @@ void getItem0() { val expected = false; val union = Union12.withItem0(expected); - Assertions.assertEquals(0, union.getIndex()); - Assertions.assertEquals(expected, union.getItem0()); + assertEquals(0, union.getIndex()); + assertEquals(expected, union.getItem0()); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); @@ -36,9 +36,9 @@ void getItem1() { val expected = 1; val union = Union12.withItem1(expected); - Assertions.assertEquals(1, union.getIndex()); + assertEquals(1, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); - Assertions.assertEquals(expected, union.getItem1()); + assertEquals(expected, union.getItem1()); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); @@ -56,10 +56,10 @@ void getItem2() { val expected = "2"; val union = Union12.withItem2(expected); - Assertions.assertEquals(2, union.getIndex()); + assertEquals(2, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); - Assertions.assertEquals(expected, union.getItem2()); + assertEquals(expected, union.getItem2()); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); Assertions.assertThrows(IllegalStateException.class, union::getItem5); @@ -76,11 +76,11 @@ void getItem3() { val expected = 3f; val union = Union12.withItem3(expected); - Assertions.assertEquals(3, union.getIndex()); + assertEquals(3, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); - Assertions.assertEquals(expected, union.getItem3()); + assertEquals(expected, union.getItem3()); Assertions.assertThrows(IllegalStateException.class, union::getItem4); Assertions.assertThrows(IllegalStateException.class, union::getItem5); Assertions.assertThrows(IllegalStateException.class, union::getItem6); @@ -96,12 +96,12 @@ void getItem4() { val expected = true; val union = Union12.withItem4(expected); - Assertions.assertEquals(4, union.getIndex()); + assertEquals(4, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); - Assertions.assertEquals(expected, union.getItem4()); + assertEquals(expected, union.getItem4()); Assertions.assertThrows(IllegalStateException.class, union::getItem5); Assertions.assertThrows(IllegalStateException.class, union::getItem6); Assertions.assertThrows(IllegalStateException.class, union::getItem7); @@ -116,13 +116,13 @@ void getItem5() { val expected = 5; val union = Union12.withItem5(expected); - Assertions.assertEquals(5, union.getIndex()); + assertEquals(5, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); - Assertions.assertEquals(expected, union.getItem5()); + assertEquals(expected, union.getItem5()); Assertions.assertThrows(IllegalStateException.class, union::getItem6); Assertions.assertThrows(IllegalStateException.class, union::getItem7); Assertions.assertThrows(IllegalStateException.class, union::getItem8); @@ -136,14 +136,14 @@ void getItem6() { val expected = "6"; val union = Union12.withItem6(expected); - Assertions.assertEquals(6, union.getIndex()); + assertEquals(6, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); Assertions.assertThrows(IllegalStateException.class, union::getItem5); - Assertions.assertEquals(expected, union.getItem6()); + assertEquals(expected, union.getItem6()); Assertions.assertThrows(IllegalStateException.class, union::getItem7); Assertions.assertThrows(IllegalStateException.class, union::getItem8); Assertions.assertThrows(IllegalStateException.class, union::getItem9); @@ -156,7 +156,7 @@ void getItem7() { val expected = 7f; val union = Union12.withItem7(expected); - Assertions.assertEquals(7, union.getIndex()); + assertEquals(7, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); @@ -164,7 +164,7 @@ void getItem7() { Assertions.assertThrows(IllegalStateException.class, union::getItem4); Assertions.assertThrows(IllegalStateException.class, union::getItem5); Assertions.assertThrows(IllegalStateException.class, union::getItem6); - Assertions.assertEquals(expected, union.getItem7()); + assertEquals(expected, union.getItem7()); Assertions.assertThrows(IllegalStateException.class, union::getItem8); Assertions.assertThrows(IllegalStateException.class, union::getItem9); Assertions.assertThrows(IllegalStateException.class, union::getItem10); @@ -176,7 +176,7 @@ void getItem8() { val expected = false; val union = Union12.withItem8(expected); - Assertions.assertEquals(8, union.getIndex()); + assertEquals(8, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); @@ -185,7 +185,7 @@ void getItem8() { Assertions.assertThrows(IllegalStateException.class, union::getItem5); Assertions.assertThrows(IllegalStateException.class, union::getItem6); Assertions.assertThrows(IllegalStateException.class, union::getItem7); - Assertions.assertEquals(expected, union.getItem8()); + assertEquals(expected, union.getItem8()); Assertions.assertThrows(IllegalStateException.class, union::getItem9); Assertions.assertThrows(IllegalStateException.class, union::getItem10); Assertions.assertThrows(IllegalStateException.class, union::getItem11); @@ -196,7 +196,7 @@ void getItem9() { val expected = 9; val union = Union12.withItem9(expected); - Assertions.assertEquals(9, union.getIndex()); + assertEquals(9, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); @@ -206,7 +206,7 @@ void getItem9() { Assertions.assertThrows(IllegalStateException.class, union::getItem6); Assertions.assertThrows(IllegalStateException.class, union::getItem7); Assertions.assertThrows(IllegalStateException.class, union::getItem8); - Assertions.assertEquals(expected, union.getItem9()); + assertEquals(expected, union.getItem9()); Assertions.assertThrows(IllegalStateException.class, union::getItem10); Assertions.assertThrows(IllegalStateException.class, union::getItem11); } @@ -216,7 +216,7 @@ void getItem10() { val expected = "10"; val union = Union12.withItem10(expected); - Assertions.assertEquals(10, union.getIndex()); + assertEquals(10, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); @@ -227,7 +227,7 @@ void getItem10() { Assertions.assertThrows(IllegalStateException.class, union::getItem7); Assertions.assertThrows(IllegalStateException.class, union::getItem8); Assertions.assertThrows(IllegalStateException.class, union::getItem9); - Assertions.assertEquals(expected, union.getItem10()); + assertEquals(expected, union.getItem10()); Assertions.assertThrows(IllegalStateException.class, union::getItem11); } @@ -236,7 +236,7 @@ void getItem11() { val expected = 11f; val union = Union12.withItem11(expected); - Assertions.assertEquals(11, union.getIndex()); + assertEquals(11, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); @@ -248,7 +248,7 @@ void getItem11() { Assertions.assertThrows(IllegalStateException.class, union::getItem8); Assertions.assertThrows(IllegalStateException.class, union::getItem9); Assertions.assertThrows(IllegalStateException.class, union::getItem10); - Assertions.assertEquals(expected, union.getItem11()); + assertEquals(expected, union.getItem11()); } @SuppressWarnings({"unchecked", "rawtypes"}) diff --git a/types/src/test/java/com/strategyobject/substrateclient/types/union/Union1Test.java b/common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union1Test.java similarity index 89% rename from types/src/test/java/com/strategyobject/substrateclient/types/union/Union1Test.java rename to common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union1Test.java index b67b438b..60f6bc16 100644 --- a/types/src/test/java/com/strategyobject/substrateclient/types/union/Union1Test.java +++ b/common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union1Test.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types.union; +package com.strategyobject.substrateclient.common.types.union; import lombok.val; import org.junit.jupiter.api.Test; diff --git a/types/src/test/java/com/strategyobject/substrateclient/types/union/Union2Test.java b/common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union2Test.java similarity index 78% rename from types/src/test/java/com/strategyobject/substrateclient/types/union/Union2Test.java rename to common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union2Test.java index 4aa50217..58f57383 100644 --- a/types/src/test/java/com/strategyobject/substrateclient/types/union/Union2Test.java +++ b/common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union2Test.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types.union; +package com.strategyobject.substrateclient.common.types.union; import lombok.val; import org.junit.jupiter.api.Assertions; @@ -16,8 +16,8 @@ void getItem0() { val expected = false; val union = Union2.withItem0(expected); - Assertions.assertEquals(0, union.getIndex()); - Assertions.assertEquals(expected, union.getItem0()); + assertEquals(0, union.getIndex()); + assertEquals(expected, union.getItem0()); Assertions.assertThrows(IllegalStateException.class, union::getItem1); } @@ -26,9 +26,9 @@ void getItem1() { val expected = 1; val union = Union2.withItem1(expected); - Assertions.assertEquals(1, union.getIndex()); + assertEquals(1, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); - Assertions.assertEquals(expected, union.getItem1()); + assertEquals(expected, union.getItem1()); } @SuppressWarnings({"unchecked", "rawtypes"}) diff --git a/types/src/test/java/com/strategyobject/substrateclient/types/union/Union3Test.java b/common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union3Test.java similarity index 80% rename from types/src/test/java/com/strategyobject/substrateclient/types/union/Union3Test.java rename to common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union3Test.java index 665f36e1..b2b5b63c 100644 --- a/types/src/test/java/com/strategyobject/substrateclient/types/union/Union3Test.java +++ b/common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union3Test.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types.union; +package com.strategyobject.substrateclient.common.types.union; import lombok.val; import org.junit.jupiter.api.Assertions; @@ -16,8 +16,8 @@ void getItem0() { val expected = false; val union = Union3.withItem0(expected); - Assertions.assertEquals(0, union.getIndex()); - Assertions.assertEquals(expected, union.getItem0()); + assertEquals(0, union.getIndex()); + assertEquals(expected, union.getItem0()); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); } @@ -27,9 +27,9 @@ void getItem1() { val expected = 1; val union = Union3.withItem1(expected); - Assertions.assertEquals(1, union.getIndex()); + assertEquals(1, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); - Assertions.assertEquals(expected, union.getItem1()); + assertEquals(expected, union.getItem1()); Assertions.assertThrows(IllegalStateException.class, union::getItem2); } @@ -38,10 +38,10 @@ void getItem2() { val expected = "2"; val union = Union3.withItem2(expected); - Assertions.assertEquals(2, union.getIndex()); + assertEquals(2, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); - Assertions.assertEquals(expected, union.getItem2()); + assertEquals(expected, union.getItem2()); } @SuppressWarnings({"unchecked", "rawtypes"}) diff --git a/types/src/test/java/com/strategyobject/substrateclient/types/union/Union4Test.java b/common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union4Test.java similarity index 81% rename from types/src/test/java/com/strategyobject/substrateclient/types/union/Union4Test.java rename to common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union4Test.java index b2302ba1..fbd7de15 100644 --- a/types/src/test/java/com/strategyobject/substrateclient/types/union/Union4Test.java +++ b/common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union4Test.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types.union; +package com.strategyobject.substrateclient.common.types.union; import lombok.val; import org.junit.jupiter.api.Assertions; @@ -16,8 +16,8 @@ void getItem0() { val expected = false; val union = Union4.withItem0(expected); - Assertions.assertEquals(0, union.getIndex()); - Assertions.assertEquals(expected, union.getItem0()); + assertEquals(0, union.getIndex()); + assertEquals(expected, union.getItem0()); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); @@ -28,9 +28,9 @@ void getItem1() { val expected = 1; val union = Union4.withItem1(expected); - Assertions.assertEquals(1, union.getIndex()); + assertEquals(1, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); - Assertions.assertEquals(expected, union.getItem1()); + assertEquals(expected, union.getItem1()); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); } @@ -40,10 +40,10 @@ void getItem2() { val expected = "2"; val union = Union4.withItem2(expected); - Assertions.assertEquals(2, union.getIndex()); + assertEquals(2, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); - Assertions.assertEquals(expected, union.getItem2()); + assertEquals(expected, union.getItem2()); Assertions.assertThrows(IllegalStateException.class, union::getItem3); } @@ -52,11 +52,11 @@ void getItem3() { val expected = 3f; val union = Union4.withItem3(expected); - Assertions.assertEquals(3, union.getIndex()); + assertEquals(3, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); - Assertions.assertEquals(expected, union.getItem3()); + assertEquals(expected, union.getItem3()); } @SuppressWarnings({"unchecked", "rawtypes"}) diff --git a/types/src/test/java/com/strategyobject/substrateclient/types/union/Union5Test.java b/common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union5Test.java similarity index 83% rename from types/src/test/java/com/strategyobject/substrateclient/types/union/Union5Test.java rename to common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union5Test.java index cd727b91..306192ed 100644 --- a/types/src/test/java/com/strategyobject/substrateclient/types/union/Union5Test.java +++ b/common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union5Test.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types.union; +package com.strategyobject.substrateclient.common.types.union; import lombok.val; import org.junit.jupiter.api.Assertions; @@ -16,8 +16,8 @@ void getItem0() { val expected = false; val union = Union5.withItem0(expected); - Assertions.assertEquals(0, union.getIndex()); - Assertions.assertEquals(expected, union.getItem0()); + assertEquals(0, union.getIndex()); + assertEquals(expected, union.getItem0()); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); @@ -29,9 +29,9 @@ void getItem1() { val expected = 1; val union = Union5.withItem1(expected); - Assertions.assertEquals(1, union.getIndex()); + assertEquals(1, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); - Assertions.assertEquals(expected, union.getItem1()); + assertEquals(expected, union.getItem1()); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); @@ -42,10 +42,10 @@ void getItem2() { val expected = "2"; val union = Union5.withItem2(expected); - Assertions.assertEquals(2, union.getIndex()); + assertEquals(2, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); - Assertions.assertEquals(expected, union.getItem2()); + assertEquals(expected, union.getItem2()); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); } @@ -55,11 +55,11 @@ void getItem3() { val expected = 3f; val union = Union5.withItem3(expected); - Assertions.assertEquals(3, union.getIndex()); + assertEquals(3, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); - Assertions.assertEquals(expected, union.getItem3()); + assertEquals(expected, union.getItem3()); Assertions.assertThrows(IllegalStateException.class, union::getItem4); } @@ -68,12 +68,12 @@ void getItem4() { val expected = true; val union = Union5.withItem4(expected); - Assertions.assertEquals(4, union.getIndex()); + assertEquals(4, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); - Assertions.assertEquals(expected, union.getItem4()); + assertEquals(expected, union.getItem4()); } @SuppressWarnings({"unchecked", "rawtypes"}) diff --git a/types/src/test/java/com/strategyobject/substrateclient/types/union/Union6Test.java b/common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union6Test.java similarity index 84% rename from types/src/test/java/com/strategyobject/substrateclient/types/union/Union6Test.java rename to common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union6Test.java index 231d1d7b..eafafb72 100644 --- a/types/src/test/java/com/strategyobject/substrateclient/types/union/Union6Test.java +++ b/common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union6Test.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types.union; +package com.strategyobject.substrateclient.common.types.union; import lombok.val; import org.junit.jupiter.api.Assertions; @@ -16,8 +16,8 @@ void getItem0() { val expected = false; val union = Union6.withItem0(expected); - Assertions.assertEquals(0, union.getIndex()); - Assertions.assertEquals(expected, union.getItem0()); + assertEquals(0, union.getIndex()); + assertEquals(expected, union.getItem0()); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); @@ -30,9 +30,9 @@ void getItem1() { val expected = 1; val union = Union6.withItem1(expected); - Assertions.assertEquals(1, union.getIndex()); + assertEquals(1, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); - Assertions.assertEquals(expected, union.getItem1()); + assertEquals(expected, union.getItem1()); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); @@ -44,10 +44,10 @@ void getItem2() { val expected = "2"; val union = Union6.withItem2(expected); - Assertions.assertEquals(2, union.getIndex()); + assertEquals(2, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); - Assertions.assertEquals(expected, union.getItem2()); + assertEquals(expected, union.getItem2()); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); Assertions.assertThrows(IllegalStateException.class, union::getItem5); @@ -58,11 +58,11 @@ void getItem3() { val expected = 3f; val union = Union6.withItem3(expected); - Assertions.assertEquals(3, union.getIndex()); + assertEquals(3, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); - Assertions.assertEquals(expected, union.getItem3()); + assertEquals(expected, union.getItem3()); Assertions.assertThrows(IllegalStateException.class, union::getItem4); Assertions.assertThrows(IllegalStateException.class, union::getItem5); } @@ -72,12 +72,12 @@ void getItem4() { val expected = true; val union = Union6.withItem4(expected); - Assertions.assertEquals(4, union.getIndex()); + assertEquals(4, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); - Assertions.assertEquals(expected, union.getItem4()); + assertEquals(expected, union.getItem4()); Assertions.assertThrows(IllegalStateException.class, union::getItem5); } @@ -86,13 +86,13 @@ void getItem5() { val expected = 5; val union = Union6.withItem5(expected); - Assertions.assertEquals(5, union.getIndex()); + assertEquals(5, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); - Assertions.assertEquals(expected, union.getItem5()); + assertEquals(expected, union.getItem5()); } @SuppressWarnings({"unchecked", "rawtypes"}) diff --git a/types/src/test/java/com/strategyobject/substrateclient/types/union/Union7Test.java b/common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union7Test.java similarity index 86% rename from types/src/test/java/com/strategyobject/substrateclient/types/union/Union7Test.java rename to common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union7Test.java index c5460bc7..d5b048db 100644 --- a/types/src/test/java/com/strategyobject/substrateclient/types/union/Union7Test.java +++ b/common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union7Test.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types.union; +package com.strategyobject.substrateclient.common.types.union; import lombok.val; import org.junit.jupiter.api.Assertions; @@ -16,8 +16,8 @@ void getItem0() { val expected = false; val union = Union7.withItem0(expected); - Assertions.assertEquals(0, union.getIndex()); - Assertions.assertEquals(expected, union.getItem0()); + assertEquals(0, union.getIndex()); + assertEquals(expected, union.getItem0()); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); @@ -31,9 +31,9 @@ void getItem1() { val expected = 1; val union = Union7.withItem1(expected); - Assertions.assertEquals(1, union.getIndex()); + assertEquals(1, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); - Assertions.assertEquals(expected, union.getItem1()); + assertEquals(expected, union.getItem1()); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); @@ -46,10 +46,10 @@ void getItem2() { val expected = "2"; val union = Union7.withItem2(expected); - Assertions.assertEquals(2, union.getIndex()); + assertEquals(2, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); - Assertions.assertEquals(expected, union.getItem2()); + assertEquals(expected, union.getItem2()); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); Assertions.assertThrows(IllegalStateException.class, union::getItem5); @@ -61,11 +61,11 @@ void getItem3() { val expected = 3f; val union = Union7.withItem3(expected); - Assertions.assertEquals(3, union.getIndex()); + assertEquals(3, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); - Assertions.assertEquals(expected, union.getItem3()); + assertEquals(expected, union.getItem3()); Assertions.assertThrows(IllegalStateException.class, union::getItem4); Assertions.assertThrows(IllegalStateException.class, union::getItem5); Assertions.assertThrows(IllegalStateException.class, union::getItem6); @@ -76,12 +76,12 @@ void getItem4() { val expected = true; val union = Union7.withItem4(expected); - Assertions.assertEquals(4, union.getIndex()); + assertEquals(4, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); - Assertions.assertEquals(expected, union.getItem4()); + assertEquals(expected, union.getItem4()); Assertions.assertThrows(IllegalStateException.class, union::getItem5); Assertions.assertThrows(IllegalStateException.class, union::getItem6); } @@ -91,13 +91,13 @@ void getItem5() { val expected = 5; val union = Union7.withItem5(expected); - Assertions.assertEquals(5, union.getIndex()); + assertEquals(5, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); - Assertions.assertEquals(expected, union.getItem5()); + assertEquals(expected, union.getItem5()); Assertions.assertThrows(IllegalStateException.class, union::getItem6); } @@ -106,14 +106,14 @@ void getItem6() { val expected = 6f; val union = Union7.withItem6(expected); - Assertions.assertEquals(6, union.getIndex()); + assertEquals(6, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); Assertions.assertThrows(IllegalStateException.class, union::getItem5); - Assertions.assertEquals(expected, union.getItem6()); + assertEquals(expected, union.getItem6()); } @SuppressWarnings({"unchecked", "rawtypes"}) diff --git a/types/src/test/java/com/strategyobject/substrateclient/types/union/Union8Test.java b/common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union8Test.java similarity index 87% rename from types/src/test/java/com/strategyobject/substrateclient/types/union/Union8Test.java rename to common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union8Test.java index e78f75aa..fa8d10b4 100644 --- a/types/src/test/java/com/strategyobject/substrateclient/types/union/Union8Test.java +++ b/common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union8Test.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types.union; +package com.strategyobject.substrateclient.common.types.union; import lombok.val; import org.junit.jupiter.api.Assertions; @@ -16,8 +16,8 @@ void getItem0() { val expected = false; val union = Union8.withItem0(expected); - Assertions.assertEquals(0, union.getIndex()); - Assertions.assertEquals(expected, union.getItem0()); + assertEquals(0, union.getIndex()); + assertEquals(expected, union.getItem0()); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); @@ -32,9 +32,9 @@ void getItem1() { val expected = 1; val union = Union8.withItem1(expected); - Assertions.assertEquals(1, union.getIndex()); + assertEquals(1, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); - Assertions.assertEquals(expected, union.getItem1()); + assertEquals(expected, union.getItem1()); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); @@ -48,10 +48,10 @@ void getItem2() { val expected = "2"; val union = Union8.withItem2(expected); - Assertions.assertEquals(2, union.getIndex()); + assertEquals(2, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); - Assertions.assertEquals(expected, union.getItem2()); + assertEquals(expected, union.getItem2()); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); Assertions.assertThrows(IllegalStateException.class, union::getItem5); @@ -64,11 +64,11 @@ void getItem3() { val expected = 3f; val union = Union8.withItem3(expected); - Assertions.assertEquals(3, union.getIndex()); + assertEquals(3, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); - Assertions.assertEquals(expected, union.getItem3()); + assertEquals(expected, union.getItem3()); Assertions.assertThrows(IllegalStateException.class, union::getItem4); Assertions.assertThrows(IllegalStateException.class, union::getItem5); Assertions.assertThrows(IllegalStateException.class, union::getItem6); @@ -80,12 +80,12 @@ void getItem4() { val expected = true; val union = Union8.withItem4(expected); - Assertions.assertEquals(4, union.getIndex()); + assertEquals(4, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); - Assertions.assertEquals(expected, union.getItem4()); + assertEquals(expected, union.getItem4()); Assertions.assertThrows(IllegalStateException.class, union::getItem5); Assertions.assertThrows(IllegalStateException.class, union::getItem6); Assertions.assertThrows(IllegalStateException.class, union::getItem7); @@ -96,13 +96,13 @@ void getItem5() { val expected = 5; val union = Union8.withItem5(expected); - Assertions.assertEquals(5, union.getIndex()); + assertEquals(5, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); - Assertions.assertEquals(expected, union.getItem5()); + assertEquals(expected, union.getItem5()); Assertions.assertThrows(IllegalStateException.class, union::getItem6); Assertions.assertThrows(IllegalStateException.class, union::getItem7); } @@ -112,14 +112,14 @@ void getItem6() { val expected = 6f; val union = Union8.withItem6(expected); - Assertions.assertEquals(6, union.getIndex()); + assertEquals(6, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); Assertions.assertThrows(IllegalStateException.class, union::getItem5); - Assertions.assertEquals(expected, union.getItem6()); + assertEquals(expected, union.getItem6()); Assertions.assertThrows(IllegalStateException.class, union::getItem7); } @@ -128,7 +128,7 @@ void getItem7() { val expected = false; val union = Union8.withItem7(expected); - Assertions.assertEquals(7, union.getIndex()); + assertEquals(7, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); @@ -136,7 +136,7 @@ void getItem7() { Assertions.assertThrows(IllegalStateException.class, union::getItem4); Assertions.assertThrows(IllegalStateException.class, union::getItem5); Assertions.assertThrows(IllegalStateException.class, union::getItem6); - Assertions.assertEquals(expected, union.getItem7()); + assertEquals(expected, union.getItem7()); } @SuppressWarnings({"unchecked", "rawtypes"}) diff --git a/types/src/test/java/com/strategyobject/substrateclient/types/union/Union9Test.java b/common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union9Test.java similarity index 88% rename from types/src/test/java/com/strategyobject/substrateclient/types/union/Union9Test.java rename to common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union9Test.java index 8b69c368..013fb489 100644 --- a/types/src/test/java/com/strategyobject/substrateclient/types/union/Union9Test.java +++ b/common/src/test/java/com/strategyobject/substrateclient/common/types/union/Union9Test.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.types.union; +package com.strategyobject.substrateclient.common.types.union; import lombok.val; import org.junit.jupiter.api.Assertions; @@ -16,8 +16,8 @@ void getItem0() { val expected = false; val union = Union9.withItem0(expected); - Assertions.assertEquals(0, union.getIndex()); - Assertions.assertEquals(expected, union.getItem0()); + assertEquals(0, union.getIndex()); + assertEquals(expected, union.getItem0()); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); @@ -33,9 +33,9 @@ void getItem1() { val expected = 1; val union = Union9.withItem1(expected); - Assertions.assertEquals(1, union.getIndex()); + assertEquals(1, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); - Assertions.assertEquals(expected, union.getItem1()); + assertEquals(expected, union.getItem1()); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); @@ -50,10 +50,10 @@ void getItem2() { val expected = "2"; val union = Union9.withItem2(expected); - Assertions.assertEquals(2, union.getIndex()); + assertEquals(2, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); - Assertions.assertEquals(expected, union.getItem2()); + assertEquals(expected, union.getItem2()); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); Assertions.assertThrows(IllegalStateException.class, union::getItem5); @@ -67,11 +67,11 @@ void getItem3() { val expected = 3f; val union = Union9.withItem3(expected); - Assertions.assertEquals(3, union.getIndex()); + assertEquals(3, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); - Assertions.assertEquals(expected, union.getItem3()); + assertEquals(expected, union.getItem3()); Assertions.assertThrows(IllegalStateException.class, union::getItem4); Assertions.assertThrows(IllegalStateException.class, union::getItem5); Assertions.assertThrows(IllegalStateException.class, union::getItem6); @@ -84,12 +84,12 @@ void getItem4() { val expected = true; val union = Union9.withItem4(expected); - Assertions.assertEquals(4, union.getIndex()); + assertEquals(4, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); - Assertions.assertEquals(expected, union.getItem4()); + assertEquals(expected, union.getItem4()); Assertions.assertThrows(IllegalStateException.class, union::getItem5); Assertions.assertThrows(IllegalStateException.class, union::getItem6); Assertions.assertThrows(IllegalStateException.class, union::getItem7); @@ -101,13 +101,13 @@ void getItem5() { val expected = 5; val union = Union9.withItem5(expected); - Assertions.assertEquals(5, union.getIndex()); + assertEquals(5, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); - Assertions.assertEquals(expected, union.getItem5()); + assertEquals(expected, union.getItem5()); Assertions.assertThrows(IllegalStateException.class, union::getItem6); Assertions.assertThrows(IllegalStateException.class, union::getItem7); Assertions.assertThrows(IllegalStateException.class, union::getItem8); @@ -118,14 +118,14 @@ void getItem6() { val expected = "6"; val union = Union9.withItem6(expected); - Assertions.assertEquals(6, union.getIndex()); + assertEquals(6, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); Assertions.assertThrows(IllegalStateException.class, union::getItem3); Assertions.assertThrows(IllegalStateException.class, union::getItem4); Assertions.assertThrows(IllegalStateException.class, union::getItem5); - Assertions.assertEquals(expected, union.getItem6()); + assertEquals(expected, union.getItem6()); Assertions.assertThrows(IllegalStateException.class, union::getItem7); Assertions.assertThrows(IllegalStateException.class, union::getItem8); } @@ -135,7 +135,7 @@ void getItem7() { val expected = false; val union = Union9.withItem7(expected); - Assertions.assertEquals(7, union.getIndex()); + assertEquals(7, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); @@ -143,7 +143,7 @@ void getItem7() { Assertions.assertThrows(IllegalStateException.class, union::getItem4); Assertions.assertThrows(IllegalStateException.class, union::getItem5); Assertions.assertThrows(IllegalStateException.class, union::getItem6); - Assertions.assertEquals(expected, union.getItem7()); + assertEquals(expected, union.getItem7()); Assertions.assertThrows(IllegalStateException.class, union::getItem8); } @@ -152,7 +152,7 @@ void getItem8() { val expected = 8; val union = Union9.withItem8(expected); - Assertions.assertEquals(8, union.getIndex()); + assertEquals(8, union.getIndex()); Assertions.assertThrows(IllegalStateException.class, union::getItem0); Assertions.assertThrows(IllegalStateException.class, union::getItem1); Assertions.assertThrows(IllegalStateException.class, union::getItem2); @@ -161,7 +161,7 @@ void getItem8() { Assertions.assertThrows(IllegalStateException.class, union::getItem5); Assertions.assertThrows(IllegalStateException.class, union::getItem6); Assertions.assertThrows(IllegalStateException.class, union::getItem7); - Assertions.assertEquals(expected, union.getItem8()); + assertEquals(expected, union.getItem8()); } @SuppressWarnings({"unchecked", "rawtypes"}) diff --git a/crypto/build.gradle b/crypto/build.gradle index 46706d93..d37a6051 100644 --- a/crypto/build.gradle +++ b/crypto/build.gradle @@ -1,8 +1,9 @@ dependencies { + implementation project(":common") + implementation 'com.github.multiformats:java-multibase:1.1.0' implementation 'org.bouncycastle:bcprov-jdk15on:1.70' - implementation project(":common") - implementation project(":types") + implementation 'net.openhft:zero-allocation-hashing:0.16' } test { diff --git a/crypto/src/jni-crypto/src/sr25519.rs b/crypto/src/jni-crypto/src/sr25519.rs index 2e565be0..ee2568a2 100644 --- a/crypto/src/jni-crypto/src/sr25519.rs +++ b/crypto/src/jni-crypto/src/sr25519.rs @@ -2,10 +2,9 @@ // Only `#[wasm_bindgen]` and `use wasm_bindgen::prelude::*;` were removed. use curve25519_dalek::scalar::Scalar; - use schnorrkel::{ - ExpansionMode, Keypair, MiniSecretKey, PublicKey, SecretKey, Signature, - derive::{Derivation, ChainCode, CHAIN_CODE_LENGTH}, + derive::{CHAIN_CODE_LENGTH, ChainCode, Derivation}, ExpansionMode, Keypair, MiniSecretKey, PublicKey, SecretKey, + Signature, }; // We must make sure that this is the same as declared in the substrate source code. @@ -150,9 +149,10 @@ pub mod tests { extern crate rand; extern crate schnorrkel; - use super::*; use hex_literal::hex; - use schnorrkel::{SIGNATURE_LENGTH, KEYPAIR_LENGTH, SECRET_KEY_LENGTH}; + use schnorrkel::{KEYPAIR_LENGTH, SECRET_KEY_LENGTH, SIGNATURE_LENGTH}; + + use super::*; fn generate_random_seed() -> Vec { (0..32).map(|_| rand::random::()).collect() diff --git a/crypto/src/jni-crypto/src/sr25519_jni.rs b/crypto/src/jni-crypto/src/sr25519_jni.rs index 883d08cd..516f566f 100644 --- a/crypto/src/jni-crypto/src/sr25519_jni.rs +++ b/crypto/src/jni-crypto/src/sr25519_jni.rs @@ -3,11 +3,11 @@ use jni::{ objects::JClass, sys::{jboolean, jbyteArray}, }; +use std::any::Any; +use std::ops::Deref; +use std::panic::catch_unwind; use crate::sr25519::*; -use std::panic::catch_unwind; -use std::ops::Deref; -use std::any::Any; #[no_mangle] pub extern "system" fn Java_com_strategyobject_substrateclient_crypto_sr25519_Native_deriveKeyPairHard( diff --git a/crypto/src/main/java/com/strategyobject/substrateclient/crypto/CryptoProvider.java b/crypto/src/main/java/com/strategyobject/substrateclient/crypto/CryptoProvider.java index 3777c21c..4f985583 100644 --- a/crypto/src/main/java/com/strategyobject/substrateclient/crypto/CryptoProvider.java +++ b/crypto/src/main/java/com/strategyobject/substrateclient/crypto/CryptoProvider.java @@ -1,12 +1,12 @@ package com.strategyobject.substrateclient.crypto; -import com.strategyobject.substrateclient.types.*; +import com.strategyobject.substrateclient.common.types.Bytes; import lombok.NonNull; public interface CryptoProvider { KeyPair createPairFromSeed(@NonNull Seed seed); - SignatureData sign(@NonNull PublicKey publicKey, @NonNull SecretKey secretKey, @NonNull Signable message); + SignatureData sign(@NonNull PublicKey publicKey, @NonNull SecretKey secretKey, @NonNull Bytes message); - boolean verify(@NonNull SignatureData signature, @NonNull Signable message, @NonNull PublicKey publicKey); + boolean verify(@NonNull SignatureData signature, @NonNull Bytes message, @NonNull PublicKey publicKey); } diff --git a/crypto/src/main/java/com/strategyobject/substrateclient/crypto/Hasher.java b/crypto/src/main/java/com/strategyobject/substrateclient/crypto/Hasher.java new file mode 100644 index 00000000..dc7c5055 --- /dev/null +++ b/crypto/src/main/java/com/strategyobject/substrateclient/crypto/Hasher.java @@ -0,0 +1,39 @@ +package com.strategyobject.substrateclient.crypto; + +import com.strategyobject.substrateclient.common.types.Size; +import lombok.val; +import net.openhft.hashing.LongHashFunction; +import org.bouncycastle.crypto.digests.Blake2bDigest; + +public class Hasher { + public static byte[] blake2(Size size, byte[] value) { + val digest = new Blake2bDigest(size.getValue()); + digest.update(value, 0, value.length); + + val result = new byte[digest.getDigestSize()]; + digest.doFinal(result, 0); + return result; + } + + public static long xx(long seed, byte[] value) { + return LongHashFunction.xx(seed).hashBytes(value); + } + + public static byte[] xx64(long seed, byte[] value) { + val hash = xx(seed, value); + + return new byte[]{ + (byte) (hash), + (byte) (hash >> 8), + (byte) (hash >> 16), + (byte) (hash >> 24), + (byte) (hash >> 32), + (byte) (hash >> 40), + (byte) (hash >> 48), + (byte) (hash >> 56) + }; + } + + private Hasher() { + } +} diff --git a/types/src/main/java/com/strategyobject/substrateclient/types/KeyPair.java b/crypto/src/main/java/com/strategyobject/substrateclient/crypto/KeyPair.java similarity index 54% rename from types/src/main/java/com/strategyobject/substrateclient/types/KeyPair.java rename to crypto/src/main/java/com/strategyobject/substrateclient/crypto/KeyPair.java index 6c8c7c1b..47bdf50f 100644 --- a/types/src/main/java/com/strategyobject/substrateclient/types/KeyPair.java +++ b/crypto/src/main/java/com/strategyobject/substrateclient/crypto/KeyPair.java @@ -1,5 +1,7 @@ -package com.strategyobject.substrateclient.types; +package com.strategyobject.substrateclient.crypto; +import com.strategyobject.substrateclient.common.types.FixedBytes; +import com.strategyobject.substrateclient.common.types.Size; import lombok.NonNull; import java.util.Arrays; @@ -17,10 +19,10 @@ public static KeyPair fromBytes(byte @NonNull [] data) { } public SecretKey asSecretKey() { - return SecretKey.fromBytes(Arrays.copyOfRange(getData(), 0, SECRET_KEY_LENGTH)); + return SecretKey.fromBytes(Arrays.copyOfRange(getBytes(), 0, SECRET_KEY_LENGTH)); } public PublicKey asPublicKey() { - return PublicKey.fromBytes(Arrays.copyOfRange(getData(), SECRET_KEY_LENGTH, SECRET_KEY_LENGTH + PUBLIC_KEY_LENGTH)); + return PublicKey.fromBytes(Arrays.copyOfRange(getBytes(), SECRET_KEY_LENGTH, SECRET_KEY_LENGTH + PUBLIC_KEY_LENGTH)); } } diff --git a/crypto/src/main/java/com/strategyobject/substrateclient/crypto/KeyRing.java b/crypto/src/main/java/com/strategyobject/substrateclient/crypto/KeyRing.java index b9da9a7e..d587e45f 100644 --- a/crypto/src/main/java/com/strategyobject/substrateclient/crypto/KeyRing.java +++ b/crypto/src/main/java/com/strategyobject/substrateclient/crypto/KeyRing.java @@ -1,7 +1,7 @@ package com.strategyobject.substrateclient.crypto; +import com.strategyobject.substrateclient.common.types.Bytes; import com.strategyobject.substrateclient.crypto.sr25519.Sr25519NativeCryptoProvider; -import com.strategyobject.substrateclient.types.*; import lombok.Getter; import lombok.NonNull; import lombok.val; @@ -33,15 +33,15 @@ public static KeyRing fromSeed(@NonNull Seed seed) { return new KeyRing(seed); } - public SignatureData sign(@NonNull Signable message) { + public SignatureData sign(@NonNull Bytes message) { return cryptoProvider.sign(publicKey, secretKey, message); } - public boolean verifyOwn(@NonNull SignatureData signature, @NonNull Signable message) { + public boolean verifyOwn(@NonNull SignatureData signature, @NonNull Bytes message) { return cryptoProvider.verify(signature, message, publicKey); } - public boolean verify(@NonNull SignatureData signature, @NonNull Signable message, @NonNull PublicKey publicKey) { + public boolean verify(@NonNull SignatureData signature, @NonNull Bytes message, @NonNull PublicKey publicKey) { return cryptoProvider.verify(signature, message, publicKey); } } diff --git a/types/src/main/java/com/strategyobject/substrateclient/types/PublicKey.java b/crypto/src/main/java/com/strategyobject/substrateclient/crypto/PublicKey.java similarity index 59% rename from types/src/main/java/com/strategyobject/substrateclient/types/PublicKey.java rename to crypto/src/main/java/com/strategyobject/substrateclient/crypto/PublicKey.java index f3ff98c5..4cfcfdf1 100644 --- a/types/src/main/java/com/strategyobject/substrateclient/types/PublicKey.java +++ b/crypto/src/main/java/com/strategyobject/substrateclient/crypto/PublicKey.java @@ -1,6 +1,7 @@ -package com.strategyobject.substrateclient.types; - +package com.strategyobject.substrateclient.crypto; +import com.strategyobject.substrateclient.common.types.FixedBytes; +import com.strategyobject.substrateclient.common.types.Size; import lombok.NonNull; public class PublicKey extends FixedBytes { diff --git a/types/src/main/java/com/strategyobject/substrateclient/types/SecretKey.java b/crypto/src/main/java/com/strategyobject/substrateclient/crypto/SecretKey.java similarity index 59% rename from types/src/main/java/com/strategyobject/substrateclient/types/SecretKey.java rename to crypto/src/main/java/com/strategyobject/substrateclient/crypto/SecretKey.java index 673ba8b7..581ecb1f 100644 --- a/types/src/main/java/com/strategyobject/substrateclient/types/SecretKey.java +++ b/crypto/src/main/java/com/strategyobject/substrateclient/crypto/SecretKey.java @@ -1,5 +1,7 @@ -package com.strategyobject.substrateclient.types; +package com.strategyobject.substrateclient.crypto; +import com.strategyobject.substrateclient.common.types.FixedBytes; +import com.strategyobject.substrateclient.common.types.Size; import lombok.NonNull; public class SecretKey extends FixedBytes { diff --git a/types/src/main/java/com/strategyobject/substrateclient/types/Seed.java b/crypto/src/main/java/com/strategyobject/substrateclient/crypto/Seed.java similarity index 57% rename from types/src/main/java/com/strategyobject/substrateclient/types/Seed.java rename to crypto/src/main/java/com/strategyobject/substrateclient/crypto/Seed.java index 5a2759a0..cefe8f34 100644 --- a/types/src/main/java/com/strategyobject/substrateclient/types/Seed.java +++ b/crypto/src/main/java/com/strategyobject/substrateclient/crypto/Seed.java @@ -1,6 +1,7 @@ -package com.strategyobject.substrateclient.types; - +package com.strategyobject.substrateclient.crypto; +import com.strategyobject.substrateclient.common.types.FixedBytes; +import com.strategyobject.substrateclient.common.types.Size; import lombok.NonNull; public class Seed extends FixedBytes { diff --git a/types/src/main/java/com/strategyobject/substrateclient/types/SignatureData.java b/crypto/src/main/java/com/strategyobject/substrateclient/crypto/SignatureData.java similarity index 61% rename from types/src/main/java/com/strategyobject/substrateclient/types/SignatureData.java rename to crypto/src/main/java/com/strategyobject/substrateclient/crypto/SignatureData.java index ff648558..af9e12b3 100644 --- a/types/src/main/java/com/strategyobject/substrateclient/types/SignatureData.java +++ b/crypto/src/main/java/com/strategyobject/substrateclient/crypto/SignatureData.java @@ -1,5 +1,7 @@ -package com.strategyobject.substrateclient.types; +package com.strategyobject.substrateclient.crypto; +import com.strategyobject.substrateclient.common.types.FixedBytes; +import com.strategyobject.substrateclient.common.types.Size; import lombok.NonNull; public class SignatureData extends FixedBytes { diff --git a/crypto/src/main/java/com/strategyobject/substrateclient/crypto/sr25519/Native.java b/crypto/src/main/java/com/strategyobject/substrateclient/crypto/sr25519/Native.java index f1f06a23..b49e5e31 100644 --- a/crypto/src/main/java/com/strategyobject/substrateclient/crypto/sr25519/Native.java +++ b/crypto/src/main/java/com/strategyobject/substrateclient/crypto/sr25519/Native.java @@ -85,4 +85,7 @@ private static String copyLibraryFromResourcesToTempDir() throws IOException { static native boolean verify(byte[] signature, byte[] message, byte[] publicKey) throws NativeException; static native byte[] agree(byte[] publicKey, byte[] secretKey) throws NativeException; + + private Native() { + } } diff --git a/crypto/src/main/java/com/strategyobject/substrateclient/crypto/sr25519/Sr25519NativeCryptoProvider.java b/crypto/src/main/java/com/strategyobject/substrateclient/crypto/sr25519/Sr25519NativeCryptoProvider.java index c9161883..56478a8f 100644 --- a/crypto/src/main/java/com/strategyobject/substrateclient/crypto/sr25519/Sr25519NativeCryptoProvider.java +++ b/crypto/src/main/java/com/strategyobject/substrateclient/crypto/sr25519/Sr25519NativeCryptoProvider.java @@ -1,33 +1,32 @@ package com.strategyobject.substrateclient.crypto.sr25519; -import com.strategyobject.substrateclient.crypto.CryptoProvider; -import com.strategyobject.substrateclient.crypto.NativeException; -import com.strategyobject.substrateclient.types.*; +import com.strategyobject.substrateclient.common.types.Bytes; +import com.strategyobject.substrateclient.crypto.*; import lombok.NonNull; public class Sr25519NativeCryptoProvider implements CryptoProvider { @Override public KeyPair createPairFromSeed(@NonNull Seed seed) { try { - return KeyPair.fromBytes(Native.fromSeed(seed.getData())); + return KeyPair.fromBytes(Native.fromSeed(seed.getBytes())); } catch (NativeException e) { throw new RuntimeException(e); } } @Override - public SignatureData sign(@NonNull PublicKey publicKey, @NonNull SecretKey secretKey, @NonNull Signable message) { + public SignatureData sign(@NonNull PublicKey publicKey, @NonNull SecretKey secretKey, @NonNull Bytes message) { try { - return SignatureData.fromBytes(Native.sign(publicKey.getData(), secretKey.getData(), message.getBytes())); + return SignatureData.fromBytes(Native.sign(publicKey.getBytes(), secretKey.getBytes(), message.getBytes())); } catch (NativeException e) { throw new RuntimeException(e); } } @Override - public boolean verify(@NonNull SignatureData signature, @NonNull Signable message, @NonNull PublicKey publicKey) { + public boolean verify(@NonNull SignatureData signature, @NonNull Bytes message, @NonNull PublicKey publicKey) { try { - return Native.verify(signature.getData(), message.getBytes(), publicKey.getData()); + return Native.verify(signature.getBytes(), message.getBytes(), publicKey.getBytes()); } catch (NativeException e) { throw new RuntimeException(e); } diff --git a/crypto/src/main/java/com/strategyobject/substrateclient/crypto/ss58/AddressWithPrefix.java b/crypto/src/main/java/com/strategyobject/substrateclient/crypto/ss58/AddressWithPrefix.java index 47b23c1d..eba52c47 100644 --- a/crypto/src/main/java/com/strategyobject/substrateclient/crypto/ss58/AddressWithPrefix.java +++ b/crypto/src/main/java/com/strategyobject/substrateclient/crypto/ss58/AddressWithPrefix.java @@ -10,5 +10,5 @@ @Getter public class AddressWithPrefix { private final byte @NonNull [] address; - private final short prefix; + private final SS58AddressFormat prefix; } diff --git a/crypto/src/main/java/com/strategyobject/substrateclient/crypto/ss58/SS58AddressFormat.java b/crypto/src/main/java/com/strategyobject/substrateclient/crypto/ss58/SS58AddressFormat.java new file mode 100644 index 00000000..082ecee9 --- /dev/null +++ b/crypto/src/main/java/com/strategyobject/substrateclient/crypto/ss58/SS58AddressFormat.java @@ -0,0 +1,37 @@ +package com.strategyobject.substrateclient.crypto.ss58; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor(staticName = "of") +@EqualsAndHashCode +public class SS58AddressFormat { + private final short prefix; + + /** + * Polkadot Relay-chain, standard account (*25519). + */ + public static final SS58AddressFormat POLKADOT_ACCOUNT = new SS58AddressFormat((short) 0); + + /** + * Bare 32-bit Schnorr/Ristretto 25519 (S/R 25519) key. + */ + public static final SS58AddressFormat BARE_SR_25519 = new SS58AddressFormat((short) 1); + + /** + * Kusama Relay-chain, standard account (*25519). + */ + public static final SS58AddressFormat KUSAMA_ACCOUNT = new SS58AddressFormat((short) 2); + + /** + * Bare 32-bit Edwards Ed25519 key. + */ + public static final SS58AddressFormat BARE_ED_25519 = new SS58AddressFormat((short) 3); + + /** + * Any Substrate network, standard account (*25519). + */ + public static final SS58AddressFormat SUBSTRATE_ACCOUNT = new SS58AddressFormat((short) 42); +} diff --git a/crypto/src/main/java/com/strategyobject/substrateclient/crypto/ss58/SS58Codec.java b/crypto/src/main/java/com/strategyobject/substrateclient/crypto/ss58/SS58Codec.java index 82dad5e2..c7a7f5f1 100644 --- a/crypto/src/main/java/com/strategyobject/substrateclient/crypto/ss58/SS58Codec.java +++ b/crypto/src/main/java/com/strategyobject/substrateclient/crypto/ss58/SS58Codec.java @@ -53,15 +53,17 @@ public static AddressWithPrefix decode(@NonNull String encoded) { throw new IllegalArgumentException("Incorrect checksum."); } - return AddressWithPrefix.from(Arrays.copyOfRange(data, typeLen, typeLen + ADDRESS_LENGTH), prefix); + return AddressWithPrefix.from( + Arrays.copyOfRange(data, typeLen, typeLen + ADDRESS_LENGTH), + SS58AddressFormat.of(prefix)); } - public static String encode(byte @NonNull [] address, short prefix) { + public static String encode(byte @NonNull [] address, SS58AddressFormat prefix) { Preconditions.checkArgument(address.length == ADDRESS_LENGTH, "The length of address must be 32, but was: " + address.length); - val ident = prefix & 0b0011_1111_1111_1111; - Preconditions.checkArgument(ident == prefix, + val ident = prefix.getPrefix() & 0b0011_1111_1111_1111; + Preconditions.checkArgument(ident == prefix.getPrefix(), "The prefix size is restricted by 14 bits."); byte[] data; diff --git a/crypto/src/test/java/com/strategyobject/substrateclient/crypto/sr25519/NativeTests.java b/crypto/src/test/java/com/strategyobject/substrateclient/crypto/sr25519/NativeTests.java index a7052da2..3f428916 100644 --- a/crypto/src/test/java/com/strategyobject/substrateclient/crypto/sr25519/NativeTests.java +++ b/crypto/src/test/java/com/strategyobject/substrateclient/crypto/sr25519/NativeTests.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.crypto.sr25519; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import com.strategyobject.substrateclient.crypto.NativeException; import lombok.val; import org.junit.jupiter.api.Test; @@ -12,7 +12,7 @@ import static com.strategyobject.substrateclient.crypto.sr25519.Native.*; import static org.junit.jupiter.api.Assertions.*; -public class NativeTests { +class NativeTests { @Test void deriveKeyPairHard() throws NativeException { val aliceChainCode = HexConverter.toBytes("14416c6963650000000000000000000000000000000000000000000000000000"); diff --git a/crypto/src/test/java/com/strategyobject/substrateclient/crypto/ss58/SS58CodecTests.java b/crypto/src/test/java/com/strategyobject/substrateclient/crypto/ss58/SS58CodecTests.java index 955ea8a5..b3ad967a 100644 --- a/crypto/src/test/java/com/strategyobject/substrateclient/crypto/ss58/SS58CodecTests.java +++ b/crypto/src/test/java/com/strategyobject/substrateclient/crypto/ss58/SS58CodecTests.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.crypto.ss58; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; @@ -8,7 +8,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; -public class SS58CodecTests { +class SS58CodecTests { @ParameterizedTest @CsvSource(value = { "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY:0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d:42", @@ -20,7 +20,7 @@ public class SS58CodecTests { }, delimiterString = ":") void encode(String expected, String hex, short prefix) { - val actual = SS58Codec.encode(HexConverter.toBytes(hex), prefix); + val actual = SS58Codec.encode(HexConverter.toBytes(hex), SS58AddressFormat.of(prefix)); assertEquals(expected, actual); } @@ -33,7 +33,9 @@ void encode(String expected, String hex, short prefix) { }, delimiterString = ":") void encodeThrows(String hex, short prefix) { - assertThrows(IllegalArgumentException.class, () -> SS58Codec.encode(HexConverter.toBytes(hex), prefix)); + val format = SS58AddressFormat.of(prefix); + val address = HexConverter.toBytes(hex); + assertThrows(IllegalArgumentException.class, () -> SS58Codec.encode(address, format)); } @ParameterizedTest @@ -49,7 +51,7 @@ void encodeThrows(String hex, short prefix) { void decode(String source, String hex, short prefix) { val actual = SS58Codec.decode(source); - val expected = AddressWithPrefix.from(HexConverter.toBytes(hex), prefix); + val expected = AddressWithPrefix.from(HexConverter.toBytes(hex), SS58AddressFormat.of(prefix)); assertEquals(expected, actual); } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 69a97150..aa991fce 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew.bat b/gradlew.bat index 107acd32..ac1b06f9 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,89 +1,89 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/pallet/build.gradle b/pallet/build.gradle index e5b3aca3..2c32da33 100644 --- a/pallet/build.gradle +++ b/pallet/build.gradle @@ -1,4 +1,18 @@ dependencies { - implementation project(':scale') + implementation project(':common') + implementation project(':crypto') implementation project(':rpc') + implementation project(':rpc:rpc-api') + implementation project(':scale') + + testImplementation project(':tests') + testCompileOnly project(':transport') + + testAnnotationProcessor project(':rpc:rpc-codegen') + + testImplementation 'org.testcontainers:testcontainers:1.17.3' + testImplementation 'org.testcontainers:junit-jupiter:1.17.3' + testImplementation 'ch.qos.logback:logback-classic:1.2.11' + testImplementation 'org.awaitility:awaitility:4.2.0' + testImplementation 'org.hamcrest:hamcrest:2.2' } \ No newline at end of file diff --git a/pallet/pallet-codegen/build.gradle b/pallet/pallet-codegen/build.gradle index fc9b225b..d91307d9 100644 --- a/pallet/pallet-codegen/build.gradle +++ b/pallet/pallet-codegen/build.gradle @@ -1,10 +1,9 @@ dependencies { implementation project(':common') implementation project(':rpc') - implementation project(':types') + implementation project(':rpc:rpc-api') implementation project(':scale') implementation project(':scale:scale-codegen') - implementation project(':storage') implementation project(':pallet') implementation 'com.squareup:javapoet:1.13.0' diff --git a/pallet/pallet-codegen/src/main/java/com.strategyobject.substrateclient.pallet/CompoundMethodProcessor.java b/pallet/pallet-codegen/src/main/java/com/strategyobject/substrateclient/pallet/codegen/CompoundMethodProcessor.java similarity index 95% rename from pallet/pallet-codegen/src/main/java/com.strategyobject.substrateclient.pallet/CompoundMethodProcessor.java rename to pallet/pallet-codegen/src/main/java/com/strategyobject/substrateclient/pallet/codegen/CompoundMethodProcessor.java index 9e48cb9a..c4b60208 100644 --- a/pallet/pallet-codegen/src/main/java/com.strategyobject.substrateclient.pallet/CompoundMethodProcessor.java +++ b/pallet/pallet-codegen/src/main/java/com/strategyobject/substrateclient/pallet/codegen/CompoundMethodProcessor.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.pallet; +package com.strategyobject.substrateclient.pallet.codegen; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.TypeSpec; diff --git a/pallet/pallet-codegen/src/main/java/com.strategyobject.substrateclient.pallet/Constants.java b/pallet/pallet-codegen/src/main/java/com/strategyobject/substrateclient/pallet/codegen/Constants.java similarity index 83% rename from pallet/pallet-codegen/src/main/java/com.strategyobject.substrateclient.pallet/Constants.java rename to pallet/pallet-codegen/src/main/java/com/strategyobject/substrateclient/pallet/codegen/Constants.java index 0fe76acc..8f2564d7 100644 --- a/pallet/pallet-codegen/src/main/java/com.strategyobject.substrateclient.pallet/Constants.java +++ b/pallet/pallet-codegen/src/main/java/com/strategyobject/substrateclient/pallet/codegen/Constants.java @@ -1,7 +1,7 @@ -package com.strategyobject.substrateclient.pallet; +package com.strategyobject.substrateclient.pallet.codegen; class Constants { - static final String RPC = "rpc"; + static final String STATE = "state"; static final String CLASS_NAME_TEMPLATE = "%sImpl"; static final String SCALE_READER_REGISTRY = "scaleReaderRegistry"; static final String SCALE_WRITER_REGISTRY = "scaleWriterRegistry"; @@ -12,4 +12,7 @@ class Constants { static final String BLAKE_2_128_CONCAT_INSTANCE = "getInstance"; static final String TWO_X64_CONCAT_INSTANCE = "getInstance"; static final String IDENTITY_INSTANCE = "getInstance"; + + private Constants() { + } } diff --git a/pallet/pallet-codegen/src/main/java/com.strategyobject.substrateclient.pallet/PalletAnnotatedInterface.java b/pallet/pallet-codegen/src/main/java/com/strategyobject/substrateclient/pallet/codegen/PalletAnnotatedInterface.java similarity index 62% rename from pallet/pallet-codegen/src/main/java/com.strategyobject.substrateclient.pallet/PalletAnnotatedInterface.java rename to pallet/pallet-codegen/src/main/java/com/strategyobject/substrateclient/pallet/codegen/PalletAnnotatedInterface.java index 22373635..5799a515 100644 --- a/pallet/pallet-codegen/src/main/java/com.strategyobject.substrateclient.pallet/PalletAnnotatedInterface.java +++ b/pallet/pallet-codegen/src/main/java/com/strategyobject/substrateclient/pallet/codegen/PalletAnnotatedInterface.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.pallet; +package com.strategyobject.substrateclient.pallet.codegen; import com.google.common.base.Strings; import com.squareup.javapoet.JavaFile; @@ -7,17 +7,20 @@ import com.squareup.javapoet.TypeSpec; import com.strategyobject.substrateclient.common.codegen.ProcessingException; import com.strategyobject.substrateclient.common.codegen.ProcessorContext; -import com.strategyobject.substrateclient.pallet.annotations.Pallet; -import com.strategyobject.substrateclient.rpc.Rpc; +import com.strategyobject.substrateclient.pallet.annotation.Pallet; +import com.strategyobject.substrateclient.rpc.api.section.State; +import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; +import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; import lombok.val; +import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; import java.io.IOException; +import java.util.stream.Stream; -import static com.strategyobject.substrateclient.pallet.Constants.CLASS_NAME_TEMPLATE; -import static com.strategyobject.substrateclient.pallet.Constants.RPC; +import static com.strategyobject.substrateclient.pallet.codegen.Constants.*; public class PalletAnnotatedInterface { private final TypeElement interfaceElement; @@ -54,11 +57,17 @@ public void generateClass(ProcessorContext context) throws ProcessingException, val typeSpecBuilder = TypeSpec.classBuilder(className) .addModifiers(Modifier.PUBLIC, Modifier.FINAL) .addSuperinterface(TypeName.get(interfaceElement.asType())) - .addField(Rpc.class, RPC, Modifier.FINAL, Modifier.PRIVATE); + .addField(ScaleReaderRegistry.class, SCALE_READER_REGISTRY, Modifier.PRIVATE, Modifier.FINAL) + .addField(ScaleWriterRegistry.class, SCALE_WRITER_REGISTRY, Modifier.PRIVATE, Modifier.FINAL) + .addField(State.class, STATE, Modifier.PRIVATE, Modifier.FINAL); val constructorBuilder = createConstructorBuilder(); - for (val method : interfaceElement.getEnclosedElements()) { + for (Element method : interfaceElement.getEnclosedElements()) { + if (!(method instanceof ExecutableElement)) { + continue; + } + this.methodProcessor.process(name, (ExecutableElement) method, typeSpecBuilder, @@ -72,12 +81,19 @@ public void generateClass(ProcessorContext context) throws ProcessingException, } private MethodSpec.Builder createConstructorBuilder() { - return MethodSpec.constructorBuilder() + val ctor = MethodSpec.constructorBuilder() .addModifiers(Modifier.PUBLIC) - .addParameter(Rpc.class, RPC) - .beginControlFlow("if ($L == null)", RPC) - .addStatement("throw new $T(\"$L can't be null.\")", IllegalArgumentException.class, RPC) - .endControlFlow() - .addStatement("this.$1L = $1L", RPC); + .addParameter(ScaleReaderRegistry.class, SCALE_READER_REGISTRY) + .addParameter(ScaleWriterRegistry.class, SCALE_WRITER_REGISTRY) + .addParameter(State.class, STATE); + + Stream.of(SCALE_READER_REGISTRY, SCALE_WRITER_REGISTRY, STATE) + .forEach(x -> + ctor.beginControlFlow("if ($L == null)", x) + .addStatement("throw new $T(\"$L can't be null.\")", IllegalArgumentException.class, x) + .endControlFlow() + .addStatement("this.$1L = $1L", x)); + + return ctor; } } diff --git a/pallet/pallet-codegen/src/main/java/com.strategyobject.substrateclient.pallet/PalletInterfaceProcessor.java b/pallet/pallet-codegen/src/main/java/com/strategyobject/substrateclient/pallet/codegen/PalletInterfaceProcessor.java similarity index 89% rename from pallet/pallet-codegen/src/main/java/com.strategyobject.substrateclient.pallet/PalletInterfaceProcessor.java rename to pallet/pallet-codegen/src/main/java/com/strategyobject/substrateclient/pallet/codegen/PalletInterfaceProcessor.java index 020cbc7c..ab945ff2 100644 --- a/pallet/pallet-codegen/src/main/java/com.strategyobject.substrateclient.pallet/PalletInterfaceProcessor.java +++ b/pallet/pallet-codegen/src/main/java/com/strategyobject/substrateclient/pallet/codegen/PalletInterfaceProcessor.java @@ -1,20 +1,21 @@ -package com.strategyobject.substrateclient.pallet; +package com.strategyobject.substrateclient.pallet.codegen; import com.google.auto.service.AutoService; import com.strategyobject.substrateclient.common.codegen.ProcessingException; import com.strategyobject.substrateclient.common.codegen.ProcessorContext; -import com.strategyobject.substrateclient.pallet.annotations.Pallet; +import com.strategyobject.substrateclient.pallet.annotation.Pallet; import lombok.val; import javax.annotation.processing.*; import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.TypeElement; import java.io.IOException; import java.util.Collections; import java.util.Set; -@SupportedAnnotationTypes("com.strategyobject.substrateclient.pallet.annotations.Pallet") +@SupportedAnnotationTypes("com.strategyobject.substrateclient.pallet.annotation.Pallet") @SupportedSourceVersion(SourceVersion.RELEASE_8) @AutoService(Processor.class) public class PalletInterfaceProcessor extends AbstractProcessor { @@ -35,7 +36,7 @@ public boolean process(Set annotations, RoundEnvironment return false; } - for (val annotatedElement : roundEnv.getElementsAnnotatedWith(Pallet.class)) { + for (Element annotatedElement : roundEnv.getElementsAnnotatedWith(Pallet.class)) { if (annotatedElement.getKind() != ElementKind.INTERFACE) { context.error( annotatedElement, diff --git a/pallet/pallet-codegen/src/main/java/com.strategyobject.substrateclient.pallet/PalletMethodProcessor.java b/pallet/pallet-codegen/src/main/java/com/strategyobject/substrateclient/pallet/codegen/PalletMethodProcessor.java similarity index 93% rename from pallet/pallet-codegen/src/main/java/com.strategyobject.substrateclient.pallet/PalletMethodProcessor.java rename to pallet/pallet-codegen/src/main/java/com/strategyobject/substrateclient/pallet/codegen/PalletMethodProcessor.java index 139cb6d3..79468ba1 100644 --- a/pallet/pallet-codegen/src/main/java/com.strategyobject.substrateclient.pallet/PalletMethodProcessor.java +++ b/pallet/pallet-codegen/src/main/java/com/strategyobject/substrateclient/pallet/codegen/PalletMethodProcessor.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.pallet; +package com.strategyobject.substrateclient.pallet.codegen; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.TypeSpec; diff --git a/pallet/pallet-codegen/src/main/java/com.strategyobject.substrateclient.pallet/StorageProcessor.java b/pallet/pallet-codegen/src/main/java/com/strategyobject/substrateclient/pallet/codegen/StorageProcessor.java similarity index 92% rename from pallet/pallet-codegen/src/main/java/com.strategyobject.substrateclient.pallet/StorageProcessor.java rename to pallet/pallet-codegen/src/main/java/com/strategyobject/substrateclient/pallet/codegen/StorageProcessor.java index cba323cc..799865c3 100644 --- a/pallet/pallet-codegen/src/main/java/com.strategyobject.substrateclient.pallet/StorageProcessor.java +++ b/pallet/pallet-codegen/src/main/java/com/strategyobject/substrateclient/pallet/codegen/StorageProcessor.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.pallet; +package com.strategyobject.substrateclient.pallet.codegen; import com.google.common.base.Strings; import com.squareup.javapoet.CodeBlock; @@ -9,18 +9,16 @@ import com.strategyobject.substrateclient.common.codegen.ProcessingException; import com.strategyobject.substrateclient.common.codegen.ProcessorContext; import com.strategyobject.substrateclient.common.codegen.TypeTraverser; -import com.strategyobject.substrateclient.pallet.annotations.Storage; -import com.strategyobject.substrateclient.pallet.annotations.StorageHasher; +import com.strategyobject.substrateclient.common.types.FixedBytes; +import com.strategyobject.substrateclient.common.types.Size; +import com.strategyobject.substrateclient.pallet.annotation.Storage; +import com.strategyobject.substrateclient.pallet.annotation.StorageHasher; +import com.strategyobject.substrateclient.pallet.storage.*; import com.strategyobject.substrateclient.scale.ScaleReader; import com.strategyobject.substrateclient.scale.ScaleWriter; import com.strategyobject.substrateclient.scale.codegen.ScaleAnnotationParser; import com.strategyobject.substrateclient.scale.codegen.reader.ReaderCompositor; import com.strategyobject.substrateclient.scale.codegen.writer.WriterCompositor; -import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; -import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; -import com.strategyobject.substrateclient.storage.*; -import com.strategyobject.substrateclient.types.FixedBytes; -import com.strategyobject.substrateclient.types.Size; import lombok.NonNull; import lombok.val; import lombok.var; @@ -32,7 +30,7 @@ import java.util.Objects; import static com.strategyobject.substrateclient.common.codegen.AnnotationUtils.suppressWarnings; -import static com.strategyobject.substrateclient.pallet.Constants.*; +import static com.strategyobject.substrateclient.pallet.codegen.Constants.*; class StorageProcessor extends PalletMethodProcessor { private static final String VALUE_READER = "valueReader"; @@ -104,8 +102,6 @@ private MethodSpec backFieldInitializer(String palletName, .addAnnotation(suppressWarnings("unchecked", "rawtypes")) .returns(TypeName.get(returnType)); - declareReaderAndWriterRegistries(methodSpecBuilder); - val scaleAnnotationParser = new ScaleAnnotationParser(context); val readerCompositor = ReaderCompositor.disallowOpenGeneric( context, @@ -160,7 +156,7 @@ private void assignStorageMapImpl(MethodSpec.Builder methodSpecBuilder, StorageNMapImpl.class, STORAGE_MAP, STORAGE_FACTORY_METHOD, - RPC, + STATE, VALUE_READER, KEY_PROVIDER); } @@ -174,7 +170,7 @@ private void assignKeyProvider(MethodSpec.Builder methodSpecBuilder, WriterCompositor writerCompositor, ProcessorContext context) throws ProcessingException { val storageName = AnnotationUtils.getValueFromAnnotation(storageAnnotation, - "value"); + "name"); methodSpecBuilder.addStatement("$1T $2L = $1T.$3L($4S, $5S)", StorageKeyProvider.class, @@ -298,19 +294,19 @@ private CodeBlock resolveHashingAlgorithm(AnnotationMirror keyAnnotation, val hasher = AnnotationUtils.getValueFromAnnotation(keyAnnotation, "hasher"); val hasherName = Objects.requireNonNull(hasher).getSimpleName().toString(); - if (hasherName.equals(StorageHasher.Blake2B128Concat.toString())) { + if (hasherName.equals(StorageHasher.BLAKE2_128_CONCAT.toString())) { builder.add("$T.$L()", Blake2B128Concat.class, BLAKE_2_128_CONCAT_INSTANCE); } - if (hasherName.equals(StorageHasher.TwoX64Concat.toString())) { + if (hasherName.equals(StorageHasher.TWOX_64_CONCAT.toString())) { builder.add("$T.$L()", TwoX64Concat.class, TWO_X64_CONCAT_INSTANCE); } - if (hasherName.equals(StorageHasher.Identity.toString())) { + if (hasherName.equals(StorageHasher.IDENTITY.toString())) { if (keySize < 0) { throw new ProcessingException( palletElement, @@ -318,7 +314,7 @@ private CodeBlock resolveHashingAlgorithm(AnnotationMirror keyAnnotation, "`%s` can only be applied to a key with fixed size.", storageAnnotation.getClass().getSimpleName(), palletElement.getQualifiedName().toString(), - StorageHasher.Identity.toString(), + StorageHasher.IDENTITY.toString(), method.getSimpleName()); } @@ -361,7 +357,7 @@ private void validateMethodSignature(ExecutableElement method, StorageNMap.class.getSimpleName()); } - if (method.getParameters().size() > 0) { + if (!method.getParameters().isEmpty()) { throw new ProcessingException( palletElement, "Method `%s.%s` mustn't have parameters.", @@ -422,7 +418,7 @@ private void validateKeys(ExecutableElement method, AnnotationMirror storageAnno private void ensureNameIsSet(ExecutableElement method, AnnotationMirror storageAnnotation) throws ProcessingException { val name = AnnotationUtils.getValueFromAnnotation(storageAnnotation, - "value"); + "name"); if (Strings.isNullOrEmpty(name)) { throw new ProcessingException( palletElement, @@ -432,10 +428,4 @@ private void ensureNameIsSet(ExecutableElement method, AnnotationMirror storageA method.getSimpleName()); } } - - private void declareReaderAndWriterRegistries(MethodSpec.Builder methodSpecBuilder) { - methodSpecBuilder - .addStatement("$1T $2L = $1T.getInstance()", ScaleReaderRegistry.class, SCALE_READER_REGISTRY) - .addStatement("$1T $2L = $1T.getInstance()", ScaleWriterRegistry.class, SCALE_WRITER_REGISTRY); - } } diff --git a/pallet/pallet-codegen/src/test/java/com/strategyobject/substrateclient/pallet/PalletInterfaceProcessorTests.java b/pallet/pallet-codegen/src/test/java/com/strategyobject/substrateclient/pallet/codegen/PalletInterfaceProcessorTests.java similarity index 91% rename from pallet/pallet-codegen/src/test/java/com/strategyobject/substrateclient/pallet/PalletInterfaceProcessorTests.java rename to pallet/pallet-codegen/src/test/java/com/strategyobject/substrateclient/pallet/codegen/PalletInterfaceProcessorTests.java index d7a84389..7ab6a739 100644 --- a/pallet/pallet-codegen/src/test/java/com/strategyobject/substrateclient/pallet/PalletInterfaceProcessorTests.java +++ b/pallet/pallet-codegen/src/test/java/com/strategyobject/substrateclient/pallet/codegen/PalletInterfaceProcessorTests.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.pallet; +package com.strategyobject.substrateclient.pallet.codegen; import com.google.testing.compile.Compilation; import com.google.testing.compile.JavaFileObjects; @@ -8,7 +8,7 @@ import static com.google.testing.compile.CompilationSubject.assertThat; import static com.google.testing.compile.Compiler.javac; -public class PalletInterfaceProcessorTests { +class PalletInterfaceProcessorTests { @Test void failsWhenAnnotationIsAppliedToClass() { val clazz = JavaFileObjects.forResource("ClassPallet.java"); @@ -88,8 +88,8 @@ void failsWhenStorageMethodReturnsIncorrectType() { } @Test - public void compiles() { - val generatedName = String.format("TestPalletImpl"); + void compiles() { + val generatedName = "TestPalletImpl"; val clazz = JavaFileObjects.forResource("TestPallet.java"); val compilation = javac() @@ -98,12 +98,13 @@ public void compiles() { assertThat(compilation).succeeded(); - assertContains(generatedName, compilation, "private final Rpc rpc;"); + assertContains(generatedName, compilation, "private final ScaleReaderRegistry scaleReaderRegistry;"); + assertContains(generatedName, compilation, "private final ScaleWriterRegistry scaleWriterRegistry;"); + assertContains(generatedName, compilation, "private final State state;"); assertContains(generatedName, compilation, "private final StorageNMap value;"); assertContains(generatedName, compilation, "private final StorageNMap map;"); assertContains(generatedName, compilation, "private final StorageNMap doubleMap;"); assertContains(generatedName, compilation, "private final StorageNMap tripleMap;"); - assertContains(generatedName, compilation, "public TestPalletImpl(Rpc rpc)"); assertContains(generatedName, compilation, "public StorageNMap value()"); assertContains(generatedName, compilation, "public StorageNMap map()"); assertContains(generatedName, compilation, "public StorageNMap doubleMap()"); diff --git a/pallet/pallet-codegen/src/test/resources/AmbiguousScale.java b/pallet/pallet-codegen/src/test/resources/AmbiguousScale.java index abef9033..bc58894a 100644 --- a/pallet/pallet-codegen/src/test/resources/AmbiguousScale.java +++ b/pallet/pallet-codegen/src/test/resources/AmbiguousScale.java @@ -1,17 +1,17 @@ -import com.strategyobject.substrateclient.pallet.annotations.Pallet; -import com.strategyobject.substrateclient.pallet.annotations.Storage; -import com.strategyobject.substrateclient.pallet.annotations.StorageHasher; -import com.strategyobject.substrateclient.pallet.annotations.StorageKey; +import com.strategyobject.substrateclient.pallet.annotation.Pallet; +import com.strategyobject.substrateclient.pallet.annotation.Storage; +import com.strategyobject.substrateclient.pallet.annotation.StorageHasher; +import com.strategyobject.substrateclient.pallet.annotation.StorageKey; import com.strategyobject.substrateclient.scale.ScaleType; -import com.strategyobject.substrateclient.scale.annotations.Scale; -import com.strategyobject.substrateclient.scale.annotations.ScaleGeneric; -import com.strategyobject.substrateclient.storage.StorageNMap; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleGeneric; +import com.strategyobject.substrateclient.pallet.storage.StorageNMap; @Pallet("Test") public interface AmbiguousScale { - @Storage(value = "Test", keys = { + @Storage(name = "Test", keys = { @StorageKey( - hasher = StorageHasher.Blake2B128Concat, + hasher = StorageHasher.BLAKE2_128_CONCAT, type = @Scale(ScaleType.I32.class), generic = @ScaleGeneric( template = "Option", diff --git a/pallet/pallet-codegen/src/test/resources/ClassPallet.java b/pallet/pallet-codegen/src/test/resources/ClassPallet.java index 98223c74..e1b1658c 100644 --- a/pallet/pallet-codegen/src/test/resources/ClassPallet.java +++ b/pallet/pallet-codegen/src/test/resources/ClassPallet.java @@ -1,9 +1,9 @@ -import com.strategyobject.substrateclient.pallet.annotations.Pallet; -import com.strategyobject.substrateclient.pallet.annotations.Storage; -import com.strategyobject.substrateclient.storage.StorageNMap; +import com.strategyobject.substrateclient.pallet.annotation.Pallet; +import com.strategyobject.substrateclient.pallet.annotation.Storage; +import com.strategyobject.substrateclient.pallet.storage.StorageNMap; @Pallet("Class") public abstract class ClassPallet { - @Storage("Test") + @Storage(name = "Test") public abstract StorageNMap test(); } diff --git a/pallet/pallet-codegen/src/test/resources/NotAStorage.java b/pallet/pallet-codegen/src/test/resources/NotAStorage.java index dc7afc92..5b4b802e 100644 --- a/pallet/pallet-codegen/src/test/resources/NotAStorage.java +++ b/pallet/pallet-codegen/src/test/resources/NotAStorage.java @@ -1,15 +1,15 @@ -import com.strategyobject.substrateclient.pallet.annotations.Pallet; -import com.strategyobject.substrateclient.pallet.annotations.Storage; -import com.strategyobject.substrateclient.pallet.annotations.StorageHasher; -import com.strategyobject.substrateclient.pallet.annotations.StorageKey; +import com.strategyobject.substrateclient.pallet.annotation.Pallet; +import com.strategyobject.substrateclient.pallet.annotation.Storage; +import com.strategyobject.substrateclient.pallet.annotation.StorageHasher; +import com.strategyobject.substrateclient.pallet.annotation.StorageKey; import com.strategyobject.substrateclient.scale.ScaleType; -import com.strategyobject.substrateclient.scale.annotations.Scale; +import com.strategyobject.substrateclient.scale.annotation.Scale; @Pallet("Test") public interface NotAStorage { - @Storage(value = "Test", keys = { + @Storage(name = "Test", keys = { @StorageKey( - hasher = StorageHasher.Blake2B128Concat, + hasher = StorageHasher.BLAKE2_128_CONCAT, type = @Scale(ScaleType.I32.class) ) }) diff --git a/pallet/pallet-codegen/src/test/resources/TestPallet.java b/pallet/pallet-codegen/src/test/resources/TestPallet.java index e39037fd..fcb0d8b3 100644 --- a/pallet/pallet-codegen/src/test/resources/TestPallet.java +++ b/pallet/pallet-codegen/src/test/resources/TestPallet.java @@ -1,32 +1,32 @@ -import com.strategyobject.substrateclient.pallet.annotations.Pallet; -import com.strategyobject.substrateclient.pallet.annotations.Storage; -import com.strategyobject.substrateclient.pallet.annotations.StorageHasher; -import com.strategyobject.substrateclient.pallet.annotations.StorageKey; -import com.strategyobject.substrateclient.rpc.types.AccountId; +import com.strategyobject.substrateclient.common.types.Result; +import com.strategyobject.substrateclient.pallet.annotation.Pallet; +import com.strategyobject.substrateclient.pallet.annotation.Storage; +import com.strategyobject.substrateclient.pallet.annotation.StorageHasher; +import com.strategyobject.substrateclient.pallet.annotation.StorageKey; +import com.strategyobject.substrateclient.pallet.storage.StorageNMap; +import com.strategyobject.substrateclient.rpc.api.AccountId; import com.strategyobject.substrateclient.scale.ScaleType; -import com.strategyobject.substrateclient.scale.annotations.Scale; -import com.strategyobject.substrateclient.scale.annotations.ScaleGeneric; -import com.strategyobject.substrateclient.storage.StorageNMap; -import com.strategyobject.substrateclient.types.Result; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleGeneric; @Pallet("Test") public interface TestPallet { - @Storage("Value") + @Storage(name = "Value") StorageNMap value(); @Storage( - value = "Map", + name = "Map", keys = { @StorageKey(type = @Scale(ScaleType.I32.class), - hasher = StorageHasher.TwoX64Concat) + hasher = StorageHasher.TWOX_64_CONCAT) }) StorageNMap map(); @Storage( - value = "DoubleMap", + name = "DoubleMap", keys = { @StorageKey(type = @Scale(ScaleType.I32.class), - hasher = StorageHasher.TwoX64Concat), + hasher = StorageHasher.TWOX_64_CONCAT), @StorageKey( generic = @ScaleGeneric( template = "Result", @@ -36,20 +36,20 @@ public interface TestPallet { @Scale(ScaleType.String.class) } ), - hasher = StorageHasher.Blake2B128Concat + hasher = StorageHasher.BLAKE2_128_CONCAT ) }) StorageNMap doubleMap(); @Storage( - value = "TripleMap", + name = "TripleMap", keys = { @StorageKey(type = @Scale(String.class), - hasher = StorageHasher.Blake2B128Concat), + hasher = StorageHasher.BLAKE2_128_CONCAT), @StorageKey(type = @Scale(ScaleType.I32.class), - hasher = StorageHasher.TwoX64Concat), + hasher = StorageHasher.TWOX_64_CONCAT), @StorageKey(type = @Scale(AccountId.class), - hasher = StorageHasher.Identity) + hasher = StorageHasher.IDENTITY) }) StorageNMap tripleMap(); } diff --git a/pallet/pallet-codegen/src/test/resources/UnnamedPallet.java b/pallet/pallet-codegen/src/test/resources/UnnamedPallet.java index 0785901a..c9371485 100644 --- a/pallet/pallet-codegen/src/test/resources/UnnamedPallet.java +++ b/pallet/pallet-codegen/src/test/resources/UnnamedPallet.java @@ -1,9 +1,9 @@ -import com.strategyobject.substrateclient.pallet.annotations.Pallet; -import com.strategyobject.substrateclient.pallet.annotations.Storage; -import com.strategyobject.substrateclient.storage.StorageNMap; +import com.strategyobject.substrateclient.pallet.annotation.Pallet; +import com.strategyobject.substrateclient.pallet.annotation.Storage; +import com.strategyobject.substrateclient.pallet.storage.StorageNMap; @Pallet("") public interface UnnamedPallet { - @Storage("Test") + @Storage(name = "Test") StorageNMap test(); } diff --git a/pallet/pallet-codegen/src/test/resources/UnnamedStorage.java b/pallet/pallet-codegen/src/test/resources/UnnamedStorage.java index b9b5c1f9..64e1e03b 100644 --- a/pallet/pallet-codegen/src/test/resources/UnnamedStorage.java +++ b/pallet/pallet-codegen/src/test/resources/UnnamedStorage.java @@ -1,9 +1,9 @@ -import com.strategyobject.substrateclient.pallet.annotations.Pallet; -import com.strategyobject.substrateclient.pallet.annotations.Storage; -import com.strategyobject.substrateclient.storage.StorageNMap; +import com.strategyobject.substrateclient.pallet.annotation.Pallet; +import com.strategyobject.substrateclient.pallet.annotation.Storage; +import com.strategyobject.substrateclient.pallet.storage.StorageNMap; @Pallet("Test") public interface UnnamedStorage { - @Storage("") + @Storage(name = "") StorageNMap unnamed(); } diff --git a/pallet/pallet-codegen/src/test/resources/WithoutScale.java b/pallet/pallet-codegen/src/test/resources/WithoutScale.java index 21bfc264..299a706b 100644 --- a/pallet/pallet-codegen/src/test/resources/WithoutScale.java +++ b/pallet/pallet-codegen/src/test/resources/WithoutScale.java @@ -1,13 +1,13 @@ -import com.strategyobject.substrateclient.pallet.annotations.Pallet; -import com.strategyobject.substrateclient.pallet.annotations.Storage; -import com.strategyobject.substrateclient.pallet.annotations.StorageHasher; -import com.strategyobject.substrateclient.pallet.annotations.StorageKey; -import com.strategyobject.substrateclient.storage.StorageNMap; +import com.strategyobject.substrateclient.pallet.annotation.Pallet; +import com.strategyobject.substrateclient.pallet.annotation.Storage; +import com.strategyobject.substrateclient.pallet.annotation.StorageHasher; +import com.strategyobject.substrateclient.pallet.annotation.StorageKey; +import com.strategyobject.substrateclient.pallet.storage.StorageNMap; @Pallet("Test") public interface WithoutScale { - @Storage(value = "Test", keys = { - @StorageKey(hasher = StorageHasher.Blake2B128Concat) + @Storage(name = "Test", keys = { + @StorageKey(hasher = StorageHasher.BLAKE2_128_CONCAT) }) StorageNMap test(); } diff --git a/pallet/src/main/java/com/strategyobject/substrateclient/pallet/GeneratedPalletResolver.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/GeneratedPalletFactory.java similarity index 50% rename from pallet/src/main/java/com/strategyobject/substrateclient/pallet/GeneratedPalletResolver.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/GeneratedPalletFactory.java index 13085dd0..c4023073 100644 --- a/pallet/src/main/java/com/strategyobject/substrateclient/pallet/GeneratedPalletResolver.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/GeneratedPalletFactory.java @@ -1,18 +1,23 @@ package com.strategyobject.substrateclient.pallet; -import com.strategyobject.substrateclient.pallet.annotations.Pallet; -import com.strategyobject.substrateclient.rpc.Rpc; +import com.strategyobject.substrateclient.pallet.annotation.Pallet; +import com.strategyobject.substrateclient.rpc.api.section.State; +import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; +import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.val; -@RequiredArgsConstructor(staticName = "with") -public class GeneratedPalletResolver implements PalletResolver { +@RequiredArgsConstructor +public class GeneratedPalletFactory implements PalletFactory { private static final String CLASS_NAME_TEMPLATE = "%sImpl"; - private final @NonNull Rpc rpc; + + private final @NonNull ScaleReaderRegistry scaleReaderRegistry; + private final @NonNull ScaleWriterRegistry scaleWriterRegistry; + private final @NonNull State state; @Override - public T resolve(Class interfaceClass) { + public T create(Class interfaceClass) { if (interfaceClass.getDeclaredAnnotationsByType(Pallet.class).length == 0) { throw new IllegalArgumentException( String.format("%s can't be constructed because it is not annotated with @%s.", @@ -23,9 +28,9 @@ public T resolve(Class interfaceClass) { Class implClazz; try { implClazz = Class.forName(String.format(CLASS_NAME_TEMPLATE, interfaceClass.getCanonicalName())); - val ctor = implClazz.getConstructor(Rpc.class); + val ctor = implClazz.getConstructor(ScaleReaderRegistry.class, ScaleWriterRegistry.class, State.class); - return interfaceClass.cast(ctor.newInstance(rpc)); + return interfaceClass.cast(ctor.newInstance(scaleReaderRegistry, scaleWriterRegistry, state)); } catch (ReflectiveOperationException e) { throw new RuntimeException(e); } diff --git a/pallet/src/main/java/com/strategyobject/substrateclient/pallet/PalletFactory.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/PalletFactory.java new file mode 100644 index 00000000..b3f26ff8 --- /dev/null +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/PalletFactory.java @@ -0,0 +1,5 @@ +package com.strategyobject.substrateclient.pallet; + +public interface PalletFactory { + T create(Class clazz); +} diff --git a/pallet/src/main/java/com/strategyobject/substrateclient/pallet/PalletResolver.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/PalletResolver.java deleted file mode 100644 index 22bfeec7..00000000 --- a/pallet/src/main/java/com/strategyobject/substrateclient/pallet/PalletResolver.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.strategyobject.substrateclient.pallet; - -public interface PalletResolver { - T resolve(Class clazz); -} diff --git a/pallet/src/main/java/com/strategyobject/substrateclient/pallet/annotation/Event.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/annotation/Event.java new file mode 100644 index 00000000..83862d04 --- /dev/null +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/annotation/Event.java @@ -0,0 +1,25 @@ +package com.strategyobject.substrateclient.pallet.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Indicates a pallet event. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface Event { + /** + * @return the index of an event + */ + int index(); + + /** + * Provide a pallet name that corresponds to the event if event class is not defined inside a pallet interface. + * + * @return pallet name that corresponds to the event + */ + String pallet() default ""; +} diff --git a/pallet/src/main/java/com/strategyobject/substrateclient/pallet/annotations/Pallet.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/annotation/Pallet.java similarity index 64% rename from pallet/src/main/java/com/strategyobject/substrateclient/pallet/annotations/Pallet.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/annotation/Pallet.java index 0d91ce76..6837de3d 100644 --- a/pallet/src/main/java/com/strategyobject/substrateclient/pallet/annotations/Pallet.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/annotation/Pallet.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.pallet.annotations; +package com.strategyobject.substrateclient.pallet.annotation; import lombok.NonNull; @@ -8,14 +8,14 @@ import java.lang.annotation.Target; /** - * Indicates the pallet which represents a proxy to the blockchain's pallet. - * The processor will generate proper implementations for the interfaces defined with this annotation. + * Indicates a pallet which represents a proxy to the blockchain's pallet. + * The processor will generate proper implementations for the interfaces marked with this annotation. */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Pallet { /** - * @return the name of the pallet + * @return the name of a pallet */ @NonNull String value(); diff --git a/pallet/src/main/java/com/strategyobject/substrateclient/pallet/annotations/Storage.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/annotation/Storage.java similarity index 63% rename from pallet/src/main/java/com/strategyobject/substrateclient/pallet/annotations/Storage.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/annotation/Storage.java index 651e078d..4db7e3f6 100644 --- a/pallet/src/main/java/com/strategyobject/substrateclient/pallet/annotations/Storage.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/annotation/Storage.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.pallet.annotations; +package com.strategyobject.substrateclient.pallet.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -6,18 +6,18 @@ import java.lang.annotation.Target; /** - * Indicates the storage of the pallet. + * Indicates a pallet storage. */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface Storage { /** - * @return the name of the storage + * @return the name of a storage */ - String value(); + String name(); /** - * @return the array of items which describe SCALE-codecs + * @return the array of items that describe SCALE-codecs * and hashing algorithms of storage's keys. */ StorageKey[] keys() default {}; diff --git a/pallet/src/main/java/com/strategyobject/substrateclient/pallet/annotations/StorageHasher.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/annotation/StorageHasher.java similarity index 67% rename from pallet/src/main/java/com/strategyobject/substrateclient/pallet/annotations/StorageHasher.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/annotation/StorageHasher.java index 69b6d4aa..e4e70fd5 100644 --- a/pallet/src/main/java/com/strategyobject/substrateclient/pallet/annotations/StorageHasher.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/annotation/StorageHasher.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.pallet.annotations; +package com.strategyobject.substrateclient.pallet.annotation; /** * Represents a kind of key's hash algorithm @@ -7,13 +7,13 @@ public enum StorageHasher { /** * Blake2 128 Concat hash algorithm. */ - Blake2B128Concat, + BLAKE2_128_CONCAT, /** * TwoX 64 Concat hash algorithm. */ - TwoX64Concat, + TWOX_64_CONCAT, /** * Identity hash algorithm. */ - Identity + IDENTITY } diff --git a/pallet/src/main/java/com/strategyobject/substrateclient/pallet/annotations/StorageKey.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/annotation/StorageKey.java similarity index 75% rename from pallet/src/main/java/com/strategyobject/substrateclient/pallet/annotations/StorageKey.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/annotation/StorageKey.java index 99866013..8f68ad28 100644 --- a/pallet/src/main/java/com/strategyobject/substrateclient/pallet/annotations/StorageKey.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/annotation/StorageKey.java @@ -1,7 +1,7 @@ -package com.strategyobject.substrateclient.pallet.annotations; +package com.strategyobject.substrateclient.pallet.annotation; -import com.strategyobject.substrateclient.scale.annotations.Scale; -import com.strategyobject.substrateclient.scale.annotations.ScaleGeneric; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleGeneric; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/pallet/src/main/java/com/strategyobject/substrateclient/pallet/events/EventDescriptor.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/events/EventDescriptor.java new file mode 100644 index 00000000..f82c9c97 --- /dev/null +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/events/EventDescriptor.java @@ -0,0 +1,28 @@ +package com.strategyobject.substrateclient.pallet.events; + +import com.strategyobject.substrateclient.rpc.metadata.Pallet; +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; + +/** + * The event descriptor holding event description data and the event itself. + */ +@Getter +@RequiredArgsConstructor +public class EventDescriptor { + /** + * Reference to the Pallet that produced the event. + */ + private final Pallet pallet; + + /** + * Index of the event. + */ + private final int eventIndex; + + /** + * The event itself. + */ + private final @NonNull Object event; +} diff --git a/pallet/src/main/java/com/strategyobject/substrateclient/pallet/events/EventDescriptorReader.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/events/EventDescriptorReader.java new file mode 100644 index 00000000..694dd997 --- /dev/null +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/events/EventDescriptorReader.java @@ -0,0 +1,39 @@ +package com.strategyobject.substrateclient.pallet.events; + +import com.google.common.base.Preconditions; +import com.strategyobject.substrateclient.common.io.Streamer; +import com.strategyobject.substrateclient.rpc.metadata.MetadataProvider; +import com.strategyobject.substrateclient.scale.ScaleReader; +import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.val; + +import java.io.IOException; +import java.io.InputStream; + +@RequiredArgsConstructor +public class EventDescriptorReader implements ScaleReader { + private final @NonNull ScaleReaderRegistry scaleReaderRegistry; + private final @NonNull MetadataProvider metadataProvider; + private final @NonNull EventRegistry eventRegistry; + + @Override + public EventDescriptor read(@NonNull InputStream stream, ScaleReader... readers) throws IOException { + Preconditions.checkArgument(readers == null || readers.length == 0); + + val palletIndex = Streamer.readByte(stream); + val pallet = metadataProvider.getPallets().get(palletIndex); + val eventIndex = Streamer.readByte(stream); + + val eventClass = eventRegistry.resolve(pallet.getName(), eventIndex); + if (eventClass == null) { + throw new RuntimeException( + String.format("Unknown event with index %d in pallet %s", eventIndex, pallet.getName())); + } + + val eventReader = scaleReaderRegistry.resolve(eventClass); + val event = eventReader.read(stream); + return new EventDescriptor(pallet, eventIndex, event); + } +} diff --git a/pallet/src/main/java/com/strategyobject/substrateclient/pallet/events/EventRegistry.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/events/EventRegistry.java new file mode 100644 index 00000000..7690359c --- /dev/null +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/events/EventRegistry.java @@ -0,0 +1,78 @@ +package com.strategyobject.substrateclient.pallet.events; + +import com.google.common.base.Strings; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.strategyobject.substrateclient.common.reflection.Scanner; +import com.strategyobject.substrateclient.pallet.annotation.Event; +import com.strategyobject.substrateclient.pallet.annotation.Pallet; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import lombok.val; +import lombok.var; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; + +@Slf4j +public class EventRegistry { + private final Map>> map = new ConcurrentHashMap<>(32); + + private Collection> expand(Class event, int offsetSize) { + return Lists.newArrayList( + Iterables.concat( + Collections.nCopies(offsetSize, null), + Collections.singleton(event))); + } + + public void registerAnnotatedFrom(String... prefixes) { + + Scanner.forPrefixes(prefixes) + .getTypesAnnotatedWith(Event.class) + .stream() + .sorted(Comparator.>comparingInt(x -> x.getAnnotation(Event.class).index()).reversed()) + .forEach(event -> { + val annotation = event.getAnnotation(Event.class); + + try { + val eventIndex = annotation.index(); + var palletName = annotation.pallet(); + if (Strings.isNullOrEmpty(palletName)) { + val pallet = event.getDeclaringClass(); + val palletAnnotation = pallet.getAnnotation(Pallet.class); + palletName = palletAnnotation.value(); + } + + log.info("Auto register event {} with index {} from {}", + event.getSimpleName(), + eventIndex, + palletName); + + register(palletName, eventIndex, event); + } catch (Exception e) { + log.error("Auto registration error", e); + } + }); + } + + public void register(@NonNull String pallet, int eventIndex, @NonNull Class event) { + val events = map.get(pallet); + if (events == null) { + map.put(pallet, new CopyOnWriteArrayList<>(expand(event, eventIndex))); + } else if (events.size() <= eventIndex) { + events.addAll(expand(event, eventIndex - events.size())); + } else { + events.set(eventIndex, event); + } + } + + public Class resolve(@NonNull String pallet, int eventIndex) { + val events = map.get(pallet); + if (events == null) { + return null; + } + + return events.get(eventIndex); + } +} diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/Arg.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/Arg.java similarity index 81% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/Arg.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/Arg.java index 97b4556e..17101978 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/Arg.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/Arg.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; import lombok.Getter; import lombok.NonNull; @@ -8,6 +8,8 @@ * It contains the list of keys which are required for the specific storage. */ public class Arg { + public static final Arg EMPTY = new Arg(new Object[0]); + /** * List of keys. */ @@ -20,6 +22,7 @@ private Arg(Object[] list) { /** * Creates a new Arg. + * * @param keys any number of keys. * @return a new Arg with given keys. */ diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/Blake2B128Concat.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/Blake2B128Concat.java similarity index 73% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/Blake2B128Concat.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/Blake2B128Concat.java index b232f01e..990ade0a 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/Blake2B128Concat.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/Blake2B128Concat.java @@ -1,8 +1,8 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; +import com.strategyobject.substrateclient.common.types.Size; +import com.strategyobject.substrateclient.crypto.Hasher; import lombok.NonNull; -import lombok.val; -import org.bouncycastle.crypto.digests.Blake2bDigest; import java.nio.ByteBuffer; @@ -15,15 +15,6 @@ public class Blake2B128Concat implements KeyHashingAlgorithm { private static final int BLAKE_128_HASH_SIZE = 16; private static volatile Blake2B128Concat instance; - private static byte[] blake2_128(byte[] value) { - val digest = new Blake2bDigest(128); - digest.update(value, 0, value.length); - - val result = new byte[digest.getDigestSize()]; - digest.doFinal(result, 0); - return result; - } - /** * @return the instance of the algorithm. */ @@ -45,7 +36,7 @@ public static Blake2B128Concat getInstance() { @Override public byte[] getHash(byte @NonNull [] encodedKey) { return ByteBuffer.allocate(BLAKE_128_HASH_SIZE + encodedKey.length) - .put(blake2_128(encodedKey)) + .put(Hasher.blake2(Size.of128, encodedKey)) .put(encodedKey) .array(); } diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/DiverseKeyValueCollection.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/DiverseKeyValueCollection.java similarity index 87% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/DiverseKeyValueCollection.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/DiverseKeyValueCollection.java index 07b59580..61966be2 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/DiverseKeyValueCollection.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/DiverseKeyValueCollection.java @@ -1,10 +1,10 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; import com.google.common.base.Preconditions; -import com.strategyobject.substrateclient.rpc.types.StorageData; -import com.strategyobject.substrateclient.rpc.types.StorageKey; +import com.strategyobject.substrateclient.common.types.tuple.Pair; +import com.strategyobject.substrateclient.rpc.api.storage.StorageData; +import com.strategyobject.substrateclient.rpc.api.storage.StorageKey; import com.strategyobject.substrateclient.scale.ScaleReader; -import com.strategyobject.substrateclient.types.tuples.Pair; import lombok.NonNull; import lombok.val; @@ -39,9 +39,9 @@ private DiverseKeyValueCollection(List> pairs, } /** - * @param pairs list of pairs of storage's keys and data. - * @param valueReaders list of scale readers which read the value from StorageData - * of the appropriate pair. + * @param pairs list of pairs of storage's keys and data. + * @param valueReaders list of scale readers which read the value from StorageData + * of the appropriate pair. * @param keyExtractors list of functions which extract keys * from StorageKey of the appropriate pair. * @return certain collection. diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/Entry.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/Entry.java similarity index 80% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/Entry.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/Entry.java index 62e10188..08b2f454 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/Entry.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/Entry.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; /** * Entry of keys and value of storage. diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/HomogeneousKeyValueCollection.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/HomogeneousKeyValueCollection.java similarity index 87% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/HomogeneousKeyValueCollection.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/HomogeneousKeyValueCollection.java index 50cadda3..37868cdb 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/HomogeneousKeyValueCollection.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/HomogeneousKeyValueCollection.java @@ -1,9 +1,9 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; -import com.strategyobject.substrateclient.rpc.types.StorageData; -import com.strategyobject.substrateclient.rpc.types.StorageKey; +import com.strategyobject.substrateclient.common.types.tuple.Pair; +import com.strategyobject.substrateclient.rpc.api.storage.StorageData; +import com.strategyobject.substrateclient.rpc.api.storage.StorageKey; import com.strategyobject.substrateclient.scale.ScaleReader; -import com.strategyobject.substrateclient.types.tuples.Pair; import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.val; diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/Identity.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/Identity.java similarity index 95% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/Identity.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/Identity.java index 461de980..ee72390e 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/Identity.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/Identity.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; import lombok.NonNull; diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/KeyCollection.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/KeyCollection.java similarity index 90% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/KeyCollection.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/KeyCollection.java index b3fc6790..153f4d11 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/KeyCollection.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/KeyCollection.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; import java.util.Iterator; diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/KeyCollectionImpl.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/KeyCollectionImpl.java similarity index 83% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/KeyCollectionImpl.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/KeyCollectionImpl.java index 83cee89f..ca0864f2 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/KeyCollectionImpl.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/KeyCollectionImpl.java @@ -1,7 +1,7 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; -import com.strategyobject.substrateclient.rpc.Rpc; -import com.strategyobject.substrateclient.rpc.types.StorageKey; +import com.strategyobject.substrateclient.rpc.api.section.State; +import com.strategyobject.substrateclient.rpc.api.storage.StorageKey; import com.strategyobject.substrateclient.scale.ScaleReader; import lombok.NonNull; import lombok.RequiredArgsConstructor; @@ -18,7 +18,7 @@ */ @RequiredArgsConstructor(staticName = "with") public class KeyCollectionImpl implements KeyCollection { - private final @NonNull Rpc rpc; + private final @NonNull State state; private final @NonNull List storageKeys; private final @NonNull ScaleReader valueReader; private final @NonNull Function> keyExtractor; @@ -30,8 +30,7 @@ public int size() { @Override public MultiQuery multi() { - return () -> rpc - .state() + return () -> state .queryStorageAt(storageKeys) .thenApplyAsync(changeSets -> HomogeneousKeyValueCollection.with( changeSets.stream() @@ -57,7 +56,7 @@ public QueryableKey next() { if (hasNext()) { val key = underlying.next(); - return QueryableKeyImpl.with(rpc, key, valueReader, keyExtractor); + return QueryableKeyImpl.with(state, key, valueReader, keyExtractor); } throw new NoSuchElementException(); diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/KeyConsumer.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/KeyConsumer.java similarity index 86% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/KeyConsumer.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/KeyConsumer.java index dd6f0713..b3a95f0d 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/KeyConsumer.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/KeyConsumer.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; import lombok.NonNull; diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/KeyHasher.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/KeyHasher.java similarity index 96% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/KeyHasher.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/KeyHasher.java index 88f71a1f..808cfc2b 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/KeyHasher.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/KeyHasher.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; import com.strategyobject.substrateclient.scale.ScaleReader; import com.strategyobject.substrateclient.scale.ScaleWriter; diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/KeyHashingAlgorithm.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/KeyHashingAlgorithm.java similarity index 92% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/KeyHashingAlgorithm.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/KeyHashingAlgorithm.java index b23815c1..bbd48f15 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/KeyHashingAlgorithm.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/KeyHashingAlgorithm.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; import lombok.NonNull; diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/KeyValueCollection.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/KeyValueCollection.java similarity index 82% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/KeyValueCollection.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/KeyValueCollection.java index 64af48b9..1b1117e3 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/KeyValueCollection.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/KeyValueCollection.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; import java.util.Iterator; diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/KeyValueConsumer.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/KeyValueConsumer.java similarity index 89% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/KeyValueConsumer.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/KeyValueConsumer.java index 71c63473..7abeef0c 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/KeyValueConsumer.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/KeyValueConsumer.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; import lombok.NonNull; diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/MultiQuery.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/MultiQuery.java similarity index 85% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/MultiQuery.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/MultiQuery.java index 5da27476..db87282b 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/MultiQuery.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/MultiQuery.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; import java.util.concurrent.CompletableFuture; diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/PagedKeyIterator.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/PagedKeyIterator.java similarity index 92% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/PagedKeyIterator.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/PagedKeyIterator.java index ce284a4b..acfb159d 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/PagedKeyIterator.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/PagedKeyIterator.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; import java.util.concurrent.CompletableFuture; diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/PagedKeyValueIterator.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/PagedKeyValueIterator.java similarity index 92% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/PagedKeyValueIterator.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/PagedKeyValueIterator.java index 6d0ea8de..54606165 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/PagedKeyValueIterator.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/PagedKeyValueIterator.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; import java.util.concurrent.CompletableFuture; diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/QueryableKey.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/QueryableKey.java similarity index 90% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/QueryableKey.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/QueryableKey.java index 3b08d82c..b78b15ea 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/QueryableKey.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/QueryableKey.java @@ -1,6 +1,6 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; -import com.strategyobject.substrateclient.rpc.types.StorageKey; +import com.strategyobject.substrateclient.rpc.api.storage.StorageKey; import com.strategyobject.substrateclient.scale.ScaleReader; import lombok.NonNull; @@ -10,6 +10,7 @@ /** * Represents a query to the storage. * Can be executed or joined to other queries. + * * @param the type of the value. */ public interface QueryableKey { diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/QueryableKeyImpl.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/QueryableKeyImpl.java similarity index 91% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/QueryableKeyImpl.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/QueryableKeyImpl.java index 294f9b00..2dba3670 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/QueryableKeyImpl.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/QueryableKeyImpl.java @@ -1,7 +1,7 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; -import com.strategyobject.substrateclient.rpc.Rpc; -import com.strategyobject.substrateclient.rpc.types.StorageKey; +import com.strategyobject.substrateclient.rpc.api.section.State; +import com.strategyobject.substrateclient.rpc.api.storage.StorageKey; import com.strategyobject.substrateclient.scale.ScaleReader; import lombok.NonNull; import lombok.RequiredArgsConstructor; @@ -22,15 +22,14 @@ */ @RequiredArgsConstructor(staticName = "with") class QueryableKeyImpl implements QueryableKey { - private final Rpc rpc; + private final State state; private final StorageKey key; private final ScaleReader valueReader; private final Function> keyExtractor; @Override public CompletableFuture execute() { - return rpc - .state() + return state .getStorage(key) .thenApplyAsync(d -> { if (d == null) { @@ -64,8 +63,7 @@ public void consume(@NonNull KeyConsumer consumer) { @Override public MultiQuery join(QueryableKey... others) { - return () -> rpc - .state() + return () -> state .queryStorageAt(concatKeys(others)) .thenApplyAsync(changeSets -> DiverseKeyValueCollection.with( changeSets.stream() diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/StorageChangeConsumer.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageChangeConsumer.java similarity index 60% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/StorageChangeConsumer.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageChangeConsumer.java index dda9a914..2ccac39d 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/StorageChangeConsumer.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageChangeConsumer.java @@ -1,6 +1,6 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; -import com.strategyobject.substrateclient.rpc.types.BlockHash; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockHash; import java.util.List; @@ -9,16 +9,18 @@ * exception, hash of the block where change happened, * the value and list of the keys of the entry. * Doesn't return result. + * * @param the type of the value. */ @FunctionalInterface public interface StorageChangeConsumer { /** * Performs this operation on the given arguments. + * * @param exception happened on event. - * @param block hash of the block where the change happened. - * @param value new value of the storage's entry. - * @param keys list of the storage entry's keys. + * @param block hash of the block where the change happened. + * @param value new value of the storage's entry. + * @param keys list of the storage entry's keys. */ void accept(Exception exception, BlockHash block, V value, List keys); } diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/StorageDoubleMap.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageDoubleMap.java similarity index 71% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/StorageDoubleMap.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageDoubleMap.java index 8b827b6f..dd413d35 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/StorageDoubleMap.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageDoubleMap.java @@ -1,7 +1,7 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; import com.google.common.annotations.Beta; -import com.strategyobject.substrateclient.rpc.types.BlockHash; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockHash; import lombok.NonNull; import java.util.concurrent.CompletableFuture; diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/StorageDoubleMapImpl.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageDoubleMapImpl.java similarity index 72% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/StorageDoubleMapImpl.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageDoubleMapImpl.java index ff3e1263..11e111a5 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/StorageDoubleMapImpl.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageDoubleMapImpl.java @@ -1,8 +1,8 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; import com.google.common.annotations.Beta; -import com.strategyobject.substrateclient.rpc.Rpc; -import com.strategyobject.substrateclient.rpc.types.BlockHash; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockHash; +import com.strategyobject.substrateclient.rpc.api.section.State; import com.strategyobject.substrateclient.scale.ScaleReader; import lombok.NonNull; import lombok.RequiredArgsConstructor; @@ -14,16 +14,16 @@ public class StorageDoubleMapImpl implements StorageDoubleMap { private final StorageNMap underlying; - private StorageDoubleMapImpl(@NonNull Rpc rpc, + private StorageDoubleMapImpl(@NonNull State state, @NonNull ScaleReader scaleReader, @NonNull StorageKeyProvider storageKeyProvider) { - underlying = StorageNMapImpl.with(rpc, scaleReader, storageKeyProvider); + underlying = StorageNMapImpl.with(state, scaleReader, storageKeyProvider); } - public static StorageDoubleMap with(@NonNull Rpc rpc, + public static StorageDoubleMap with(@NonNull State state, @NonNull ScaleReader scaleReader, @NonNull StorageKeyProvider storageKeyProvider) { - return new StorageDoubleMapImpl<>(rpc, scaleReader, storageKeyProvider); + return new StorageDoubleMapImpl<>(state, scaleReader, storageKeyProvider); } @Override diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/StorageKeyProvider.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageKeyProvider.java similarity index 86% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/StorageKeyProvider.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageKeyProvider.java index f24d2bd7..e3aef253 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/StorageKeyProvider.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageKeyProvider.java @@ -1,9 +1,9 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; import com.google.common.base.Preconditions; -import com.strategyobject.substrateclient.rpc.types.StorageKey; +import com.strategyobject.substrateclient.crypto.Hasher; +import com.strategyobject.substrateclient.rpc.api.storage.StorageKey; import lombok.*; -import net.openhft.hashing.LongHashFunction; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -40,8 +40,8 @@ private static void xxHash128(ByteBuffer buf, String value) { buf.order(ByteOrder.LITTLE_ENDIAN); buf.asLongBuffer() - .put(LongHashFunction.xx(0).hashBytes(encodedValue)) - .put(LongHashFunction.xx(1).hashBytes(encodedValue)); + .put(Hasher.xx(0, encodedValue)) + .put(Hasher.xx(1, encodedValue)); buf.position(buf.position() + XX_HASH_SIZE); buf.order(sourceOrder); @@ -124,12 +124,12 @@ public List extractKeys(StorageKey fullKey) { } /** - * @param fullKey StorageKey that contains pallet and storage names and all keys - * of the entry. - * @param queryKey StorageKey that contains pallet and storage names - * and may contain some keys of the entry. - * Note: all the keys must follow the same exact order as - * their sequence in the storage. + * @param fullKey StorageKey that contains pallet and storage names and all keys + * of the entry. + * @param queryKey StorageKey that contains pallet and storage names + * and may contain some keys of the entry. + * Note: all the keys must follow the same exact order as + * their sequence in the storage. * @param countOfKeysInQuery number of keys included in the queryKey. * @return the remaining keys of the entry which are not included in the queryKey. */ diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/StorageMap.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageMap.java similarity index 65% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/StorageMap.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageMap.java index 19f1d277..508c6deb 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/StorageMap.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageMap.java @@ -1,8 +1,8 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; import com.google.common.annotations.Beta; -import com.strategyobject.substrateclient.rpc.types.BlockHash; -import com.strategyobject.substrateclient.types.tuples.Pair; +import com.strategyobject.substrateclient.common.types.tuple.Pair; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockHash; import lombok.NonNull; import java.util.List; diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/StorageMapImpl.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageMapImpl.java similarity index 54% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/StorageMapImpl.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageMapImpl.java index b77b3ea7..feb38751 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/StorageMapImpl.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageMapImpl.java @@ -1,10 +1,10 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; import com.google.common.annotations.Beta; -import com.strategyobject.substrateclient.rpc.Rpc; -import com.strategyobject.substrateclient.rpc.types.BlockHash; +import com.strategyobject.substrateclient.common.types.tuple.Pair; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockHash; +import com.strategyobject.substrateclient.rpc.api.section.State; import com.strategyobject.substrateclient.scale.ScaleReader; -import com.strategyobject.substrateclient.types.tuples.Pair; import lombok.NonNull; import java.util.List; @@ -14,16 +14,16 @@ public class StorageMapImpl implements StorageMap { private final StorageNMap underlying; - private StorageMapImpl(@NonNull Rpc rpc, + private StorageMapImpl(@NonNull State state, @NonNull ScaleReader scaleReader, @NonNull StorageKeyProvider storageKeyProvider) { - underlying = StorageNMapImpl.with(rpc, scaleReader, storageKeyProvider); + underlying = StorageNMapImpl.with(state, scaleReader, storageKeyProvider); } - public static StorageMap with(@NonNull Rpc rpc, - @NonNull ScaleReader scaleReader, - @NonNull StorageKeyProvider storageKeyProvider) { - return new StorageMapImpl<>(rpc, scaleReader, storageKeyProvider); + public static StorageMap with(@NonNull State state, + @NonNull ScaleReader scaleReader, + @NonNull StorageKeyProvider storageKeyProvider) { + return new StorageMapImpl<>(state, scaleReader, storageKeyProvider); } @Override diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/StorageNMap.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageNMap.java similarity index 82% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/StorageNMap.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageNMap.java index d05c984c..7fa1e80b 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/StorageNMap.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageNMap.java @@ -1,8 +1,8 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; -import com.strategyobject.substrateclient.rpc.types.BlockHash; -import com.strategyobject.substrateclient.rpc.types.Hash; -import com.strategyobject.substrateclient.types.tuples.Pair; +import com.strategyobject.substrateclient.common.types.tuple.Pair; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockHash; +import com.strategyobject.substrateclient.rpc.api.primitives.Hash; import lombok.NonNull; import java.util.List; @@ -12,11 +12,13 @@ /** * Represents a storage of data in blockchain * that persists between the blocks. + * * @param the type of the value. */ public interface StorageNMap { /** * Returns the value by given key(s). + * * @param keys the keys of the storage's entry. * @return the value. */ @@ -25,15 +27,17 @@ public interface StorageNMap { /** * Returns the value by given key(s) * starting at block hash given as the first parameter. + * * @param block hash of the block * used as a starting point for the value request. - * @param keys the keys of the storage's entry. + * @param keys the keys of the storage's entry. * @return the value. */ CompletableFuture at(@NonNull BlockHash block, @NonNull Object... keys); /** * Retrieves the storage hash. + * * @param keys the keys of the storage's entry. * @return the hash. */ @@ -42,15 +46,17 @@ public interface StorageNMap { /** * Retrieves the storage hash * starting at block hash given as the first parameter. + * * @param block hash of the block * used as a starting point for the hash request. - * @param keys the keys of the storage's entry. + * @param keys the keys of the storage's entry. * @return the hash. */ CompletableFuture hashAt(@NonNull BlockHash block, @NonNull Object... keys); /** * Retrieves the storage size. + * * @param keys the keys of the storage's entry. * @return the size of the entry. */ @@ -59,9 +65,10 @@ public interface StorageNMap { /** * Retrieves the storage size * starting at block hash given as the first parameter. + * * @param block hash of the block * used as a starting point for the size request. - * @param keys the keys of the storage's entry. + * @param keys the keys of the storage's entry. * @return the size of the entry. */ CompletableFuture sizeAt(@NonNull BlockHash block, @NonNull Object... keys); @@ -69,6 +76,7 @@ public interface StorageNMap { /** * Returns a collection of keys, each item of which * contains the remaining keys of the entry. + * * @param keys some keys of the storage's entry. * Note: all the keys must follow the same strict order as * they appear in the storage. @@ -80,11 +88,12 @@ public interface StorageNMap { /** * Returns a collection of keys, each item of which * contains the remaining keys of the entry. + * * @param block hash of the block * since that the keys are requested. - * @param keys some keys of the storage's entry. - * Note: all the keys must follow the same strict order as - * their sequence in the storage. + * @param keys some keys of the storage's entry. + * Note: all the keys must follow the same strict order as + * their sequence in the storage. * @return collection of keys. */ CompletableFuture> keysAt(@NonNull BlockHash block, @NonNull Object... keys); @@ -94,10 +103,11 @@ public interface StorageNMap { * contains the remaining keys of the entry. * Each item of the iterator contains a key collection with size equal to the page's size * or smaller in case of the last page and the total number isn't multiple of the page's size. + * * @param pageSize number of items in collection per page. - * @param keys some keys of the storage's entry. - * Note: all the keys must follow the same strict order as - * their sequence in the storage. + * @param keys some keys of the storage's entry. + * Note: all the keys must follow the same strict order as + * their sequence in the storage. * @return iterator of key collections. */ PagedKeyIterator keysPaged(int pageSize, @NonNull Object... keys); @@ -119,6 +129,7 @@ public interface StorageNMap { /** * Returns a key-value collection, each item of which * contains the remaining keys of the entry and its value. + * * @param keys some keys of the storage's entry. * Note: all the keys must follow the same strict order as * they appear in the storage. @@ -131,10 +142,11 @@ public interface StorageNMap { * contains the remaining keys and the value. * Each item of the iterator contains a key-value collection with size equal to the page's size * or smaller in case of the last page and the total number isn't multiple of tbe page's size. + * * @param pageSize number of items in collection per page. - * @param keys some keys of the storage's entry. - * Note: all the keys must follow the same strict order as - * their sequence in the storage. + * @param keys some keys of the storage's entry. + * Note: all the keys must follow the same strict order as + * their sequence in the storage. * @return collection of key-values. */ PagedKeyValueIterator entriesPaged(int pageSize, @NonNull Object... keys); @@ -142,6 +154,7 @@ public interface StorageNMap { /** * Returns a collection of key-values, each item of which * contains all the keys of the entry and its value. + * * @param args any number of arguments to request * multiple entries. * @return collection of key-value. @@ -150,8 +163,9 @@ public interface StorageNMap { /** * Subscribes for changes on storage's entries with given args. + * * @param consumer that consumes changes. - * @param args any number of arguments. + * @param args any number of arguments. * @return an operation that allows to unsubscribe. */ CompletableFuture>> subscribe(@NonNull StorageChangeConsumer consumer, diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/StorageNMapImpl.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageNMapImpl.java similarity index 89% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/StorageNMapImpl.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageNMapImpl.java index 1213f966..32796cc1 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/StorageNMapImpl.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageNMapImpl.java @@ -1,11 +1,11 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; -import com.strategyobject.substrateclient.rpc.Rpc; -import com.strategyobject.substrateclient.rpc.types.BlockHash; -import com.strategyobject.substrateclient.rpc.types.Hash; -import com.strategyobject.substrateclient.rpc.types.StorageKey; +import com.strategyobject.substrateclient.common.types.tuple.Pair; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockHash; +import com.strategyobject.substrateclient.rpc.api.primitives.Hash; +import com.strategyobject.substrateclient.rpc.api.section.State; +import com.strategyobject.substrateclient.rpc.api.storage.StorageKey; import com.strategyobject.substrateclient.scale.ScaleReader; -import com.strategyobject.substrateclient.types.tuples.Pair; import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.val; @@ -22,7 +22,7 @@ */ @RequiredArgsConstructor(staticName = "with") public class StorageNMapImpl implements StorageNMap { - private final @NonNull Rpc rpc; + private final @NonNull State state; private final @NonNull ScaleReader scaleReader; private final @NonNull StorageKeyProvider storageKeyProvider; @@ -30,8 +30,7 @@ public class StorageNMapImpl implements StorageNMap { public CompletableFuture get(@NonNull Object... keys) { ensureAllKeysWerePassed(keys); - return rpc - .state() + return state .getStorage(storageKeyProvider.get(keys)) .thenApplyAsync(d -> { if (d == null) { @@ -58,8 +57,7 @@ private void ensureAllKeysWerePassed(@NonNull Object[] keys) { public CompletableFuture at(@NonNull BlockHash block, @NonNull Object... keys) { ensureAllKeysWerePassed(keys); - return rpc - .state() + return state .getStorage(storageKeyProvider.get(keys), block) .thenApplyAsync(d -> { if (d == null) { @@ -78,45 +76,36 @@ public CompletableFuture at(@NonNull BlockHash block, @NonNull Object... keys public CompletableFuture hash(@NonNull Object... keys) { ensureAllKeysWerePassed(keys); - return rpc - .state() - .getStorageHash(storageKeyProvider.get(keys)); + return state.getStorageHash(storageKeyProvider.get(keys)); } @Override public CompletableFuture hashAt(@NonNull BlockHash block, @NonNull Object... keys) { ensureAllKeysWerePassed(keys); - return rpc - .state() - .getStorageHash(storageKeyProvider.get(keys), block); + return state.getStorageHash(storageKeyProvider.get(keys), block); } @Override public CompletableFuture size(@NonNull Object... keys) { ensureAllKeysWerePassed(keys); - return rpc - .state() - .getStorageSize(storageKeyProvider.get(keys)); + return state.getStorageSize(storageKeyProvider.get(keys)); } @Override public CompletableFuture sizeAt(@NonNull BlockHash block, @NonNull Object... keys) { ensureAllKeysWerePassed(keys); - return rpc - .state() - .getStorageSize(storageKeyProvider.get(keys), block); + return state.getStorageSize(storageKeyProvider.get(keys), block); } @Override public CompletableFuture> keys(@NonNull Object... keys) { val queryKey = storageKeyProvider.get(keys); - return rpc - .state() + return state .getKeys(queryKey) - .thenApplyAsync(storageKeys -> KeyCollectionImpl.with(rpc, + .thenApplyAsync(storageKeys -> KeyCollectionImpl.with(state, storageKeys, scaleReader, key -> storageKeyProvider.extractKeys(key, queryKey, keys.length))); @@ -125,10 +114,9 @@ public CompletableFuture> keys(@NonNull Object... keys) { @Override public CompletableFuture> keysAt(@NonNull BlockHash block, @NonNull Object... keys) { val queryKey = storageKeyProvider.get(keys); - return rpc - .state() + return state .getKeys(queryKey, block) - .thenApplyAsync(storageKeys -> KeyCollectionImpl.with(rpc, + .thenApplyAsync(storageKeys -> KeyCollectionImpl.with(state, storageKeys, scaleReader, key -> storageKeyProvider.extractKeys(key, queryKey, keys.length))); @@ -161,9 +149,9 @@ public int number() { @Override public CompletableFuture moveNext() { val task = pageNumber == 0 ? - rpc.state().getKeysPaged(queryKey, pageSize) : + state.getKeysPaged(queryKey, pageSize) : size == pageSize ? - rpc.state().getKeysPaged(queryKey, pageSize, last) : + state.getKeysPaged(queryKey, pageSize, last) : CompletableFuture.completedFuture(Collections.emptyList()); return task @@ -172,7 +160,7 @@ public CompletableFuture moveNext() { doesCurrentExist = true; pageNumber++; last = storageKeys.get(storageKeys.size() - 1); - collection = KeyCollectionImpl.with(rpc, + collection = KeyCollectionImpl.with(state, storageKeys, scaleReader, key -> storageKeyProvider.extractKeys(key, queryKey, keys.length)); @@ -199,7 +187,7 @@ public KeyCollection current() { public QueryableKey query(@NonNull Object... keys) { ensureAllKeysWerePassed(keys); - return QueryableKeyImpl.with(rpc, + return QueryableKeyImpl.with(state, storageKeyProvider.get(keys), scaleReader, storageKeyProvider::extractKeys); @@ -209,8 +197,7 @@ public QueryableKey query(@NonNull Object... keys) { public CompletableFuture>>> history(@NonNull Object... keys) { ensureAllKeysWerePassed(keys); - return rpc - .state() + return state .queryStorageAt(Collections.singletonList(storageKeyProvider.get(keys))) .thenApplyAsync(set -> set .stream() @@ -260,7 +247,7 @@ public CompletableFuture moveNext() { if (throwable != null) { values.completeExceptionally(throwable); } else { - if (next) { + if (Boolean.TRUE.equals(next)) { underlying.current().multi().execute() .whenCompleteAsync((keyValues, e) -> { if (e != null) { @@ -308,8 +295,7 @@ public CompletableFuture> multi(@NonNull Arg... args) { }) .collect(Collectors.toList()); - return rpc - .state() + return state .queryStorageAt(keys) .thenApplyAsync(set -> { val pairs = set @@ -324,7 +310,8 @@ public CompletableFuture> multi(@NonNull Arg... args) { } @Override - public CompletableFuture>> subscribe(@NonNull StorageChangeConsumer consumer, @NonNull Arg... args) { + public CompletableFuture>> subscribe(@NonNull StorageChangeConsumer consumer, + @NonNull Arg... args) { if (args.length == 0) { throw new IllegalArgumentException("Subscription can't be requested with no arguments."); } @@ -337,8 +324,7 @@ public CompletableFuture>> subscribe(@NonNul }) .collect(Collectors.toList()); - return rpc - .state() + return state .subscribeStorage(queryKeys, (e, changeSet) -> { if (e != null) { consumer.accept(e, null, null, null); diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/StorageValue.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageValue.java similarity index 64% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/StorageValue.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageValue.java index 79632fd8..699f59c0 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/StorageValue.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageValue.java @@ -1,8 +1,8 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; import com.google.common.annotations.Beta; -import com.strategyobject.substrateclient.rpc.types.BlockHash; -import com.strategyobject.substrateclient.types.tuples.Pair; +import com.strategyobject.substrateclient.common.types.tuple.Pair; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockHash; import lombok.NonNull; import java.util.List; diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/StorageValueImpl.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageValueImpl.java similarity index 68% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/StorageValueImpl.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageValueImpl.java index bec78756..d6c121e1 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/StorageValueImpl.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/StorageValueImpl.java @@ -1,10 +1,10 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; import com.google.common.annotations.Beta; -import com.strategyobject.substrateclient.rpc.Rpc; -import com.strategyobject.substrateclient.rpc.types.BlockHash; +import com.strategyobject.substrateclient.common.types.tuple.Pair; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockHash; +import com.strategyobject.substrateclient.rpc.api.section.State; import com.strategyobject.substrateclient.scale.ScaleReader; -import com.strategyobject.substrateclient.types.tuples.Pair; import lombok.NonNull; import lombok.RequiredArgsConstructor; @@ -16,16 +16,16 @@ public class StorageValueImpl implements StorageValue { private final StorageNMap underlying; - private StorageValueImpl(@NonNull Rpc rpc, + private StorageValueImpl(@NonNull State state, @NonNull ScaleReader scaleReader, @NonNull StorageKeyProvider storageKeyProvider) { - underlying = StorageNMapImpl.with(rpc, scaleReader, storageKeyProvider); + underlying = StorageNMapImpl.with(state, scaleReader, storageKeyProvider); } - public static StorageValue with(@NonNull Rpc rpc, + public static StorageValue with(@NonNull State state, @NonNull ScaleReader scaleReader, @NonNull StorageKeyProvider storageKeyProvider) { - return new StorageValueImpl<>(rpc, scaleReader, storageKeyProvider); + return new StorageValueImpl<>(state, scaleReader, storageKeyProvider); } @Override diff --git a/storage/src/main/java/com/strategyobject/substrateclient/storage/TwoX64Concat.java b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/TwoX64Concat.java similarity index 69% rename from storage/src/main/java/com/strategyobject/substrateclient/storage/TwoX64Concat.java rename to pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/TwoX64Concat.java index 4a925691..6d648095 100644 --- a/storage/src/main/java/com/strategyobject/substrateclient/storage/TwoX64Concat.java +++ b/pallet/src/main/java/com/strategyobject/substrateclient/pallet/storage/TwoX64Concat.java @@ -1,8 +1,8 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; +import com.strategyobject.substrateclient.crypto.Hasher; import lombok.NonNull; import lombok.val; -import net.openhft.hashing.LongHashFunction; import java.nio.ByteBuffer; @@ -15,25 +15,10 @@ public class TwoX64Concat implements KeyHashingAlgorithm { private static final int XX_HASH_SIZE = 8; private static volatile TwoX64Concat instance; - private static byte[] xxHash64(byte[] value) { - val hash = LongHashFunction.xx(0).hashBytes(value); - - return new byte[]{ - (byte) (hash), - (byte) (hash >> 8), - (byte) (hash >> 16), - (byte) (hash >> 24), - (byte) (hash >> 32), - (byte) (hash >> 40), - (byte) (hash >> 48), - (byte) (hash >> 56) - }; - } - private static byte[] xxHash64Concat(byte[] value) { val buf = ByteBuffer.allocate(XX_HASH_SIZE + value.length); - buf.put(xxHash64(value)); + buf.put(Hasher.xx64(0, value)); buf.put(value); return buf.array(); diff --git a/pallet/src/test/java/com/strategyobject/substrateclient/pallet/GeneratedPalletFactoryTests.java b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/GeneratedPalletFactoryTests.java new file mode 100644 index 00000000..15d99c55 --- /dev/null +++ b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/GeneratedPalletFactoryTests.java @@ -0,0 +1,35 @@ +package com.strategyobject.substrateclient.pallet; + +import com.strategyobject.substrateclient.rpc.api.section.State; +import lombok.val; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; + +class GeneratedPalletFactoryTests { + private final GeneratedPalletFactory factory = new GeneratedPalletFactory( + TestsHelper.SCALE_READER_REGISTRY, + TestsHelper.SCALE_WRITER_REGISTRY, + mock(State.class)); + + @Test + void throwsWhenPalletIsNotAnnotated() { + assertThrows(IllegalArgumentException.class, + () -> factory.create(TestPalletNotAnnotated.class)); + } + + @Test + void throwsWhenPalletImplementationDoesNotHaveAppropriateConstructor() { + assertThrows(RuntimeException.class, + () -> factory.create(TestPalletWithoutConstructor.class)); + } + + @Test + void resolve() { + val pallet = factory.create(TestPallet.class); + + assertNotNull(pallet); + assertEquals(TestPalletImpl.class, pallet.getClass()); + } +} diff --git a/pallet/src/test/java/com/strategyobject/substrateclient/pallet/GeneratedPalletResolverTests.java b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/GeneratedPalletResolverTests.java deleted file mode 100644 index 1cf0d39e..00000000 --- a/pallet/src/test/java/com/strategyobject/substrateclient/pallet/GeneratedPalletResolverTests.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.strategyobject.substrateclient.pallet; - -import com.strategyobject.substrateclient.rpc.Rpc; -import lombok.val; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.mock; - -public class GeneratedPalletResolverTests { - @Test - public void throwsWhenPalletIsNotAnnotated() { - val rpc = mock(Rpc.class); - - val resolver = GeneratedPalletResolver.with(rpc); - - assertThrows(IllegalArgumentException.class, - () -> resolver.resolve(TestPalletNotAnnotated.class)); - } - - @Test - public void throwsWhenPalletImplementationDoesNotHaveAppropriateConstructor() { - val rpc = mock(Rpc.class); - - val resolver = GeneratedPalletResolver.with(rpc); - - assertThrows(RuntimeException.class, - () -> resolver.resolve(TestPalletWithoutConstructor.class)); - } - - @Test - public void resolve() { - val rpc = mock(Rpc.class); - - val resolver = GeneratedPalletResolver.with(rpc); - val pallet = resolver.resolve(TestPallet.class); - - assertNotNull(pallet); - assertEquals(TestPalletImpl.class, pallet.getClass()); - } -} diff --git a/pallet/src/test/java/com/strategyobject/substrateclient/pallet/TestPallet.java b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/TestPallet.java index 79fb2171..46ab6325 100644 --- a/pallet/src/test/java/com/strategyobject/substrateclient/pallet/TestPallet.java +++ b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/TestPallet.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.pallet; -import com.strategyobject.substrateclient.pallet.annotations.Pallet; +import com.strategyobject.substrateclient.pallet.annotation.Pallet; @Pallet("Test") public interface TestPallet { diff --git a/pallet/src/test/java/com/strategyobject/substrateclient/pallet/TestPalletImpl.java b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/TestPalletImpl.java index 3eb675a9..6fd372b9 100644 --- a/pallet/src/test/java/com/strategyobject/substrateclient/pallet/TestPalletImpl.java +++ b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/TestPalletImpl.java @@ -1,9 +1,13 @@ package com.strategyobject.substrateclient.pallet; -import com.strategyobject.substrateclient.rpc.Rpc; +import com.strategyobject.substrateclient.rpc.api.section.State; +import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; +import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; import lombok.RequiredArgsConstructor; @RequiredArgsConstructor public class TestPalletImpl implements TestPallet { - private final Rpc rpc; + private final ScaleReaderRegistry scaleReaderRegistry; + private final ScaleWriterRegistry scaleWriterRegistry; + private final State state; } diff --git a/pallet/src/test/java/com/strategyobject/substrateclient/pallet/TestPalletNotAnnotated.java b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/TestPalletNotAnnotated.java index 79e99755..8aa41efd 100644 --- a/pallet/src/test/java/com/strategyobject/substrateclient/pallet/TestPalletNotAnnotated.java +++ b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/TestPalletNotAnnotated.java @@ -1,6 +1,4 @@ package com.strategyobject.substrateclient.pallet; -import com.strategyobject.substrateclient.pallet.annotations.Pallet; - public interface TestPalletNotAnnotated { } diff --git a/pallet/src/test/java/com/strategyobject/substrateclient/pallet/TestPalletNotAnnotatedImpl.java b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/TestPalletNotAnnotatedImpl.java index 5d5ca68e..661febed 100644 --- a/pallet/src/test/java/com/strategyobject/substrateclient/pallet/TestPalletNotAnnotatedImpl.java +++ b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/TestPalletNotAnnotatedImpl.java @@ -1,9 +1,9 @@ package com.strategyobject.substrateclient.pallet; -import com.strategyobject.substrateclient.rpc.Rpc; +import com.strategyobject.substrateclient.rpc.api.section.State; import lombok.RequiredArgsConstructor; @RequiredArgsConstructor public class TestPalletNotAnnotatedImpl implements TestPalletNotAnnotated { - private final Rpc rpc; + private final State state; } diff --git a/pallet/src/test/java/com/strategyobject/substrateclient/pallet/TestPalletWithoutConstructor.java b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/TestPalletWithoutConstructor.java index 89f48dd9..e592cee4 100644 --- a/pallet/src/test/java/com/strategyobject/substrateclient/pallet/TestPalletWithoutConstructor.java +++ b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/TestPalletWithoutConstructor.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.pallet; -import com.strategyobject.substrateclient.pallet.annotations.Pallet; +import com.strategyobject.substrateclient.pallet.annotation.Pallet; @Pallet("Test") public interface TestPalletWithoutConstructor { diff --git a/pallet/src/test/java/com/strategyobject/substrateclient/pallet/TestsHelper.java b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/TestsHelper.java new file mode 100644 index 00000000..99cfe6fc --- /dev/null +++ b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/TestsHelper.java @@ -0,0 +1,57 @@ +package com.strategyobject.substrateclient.pallet; + +import com.strategyobject.substrateclient.crypto.ss58.SS58AddressFormat; +import com.strategyobject.substrateclient.rpc.GeneratedRpcSectionFactory; +import com.strategyobject.substrateclient.rpc.context.RpcDecoderContext; +import com.strategyobject.substrateclient.rpc.context.RpcEncoderContext; +import com.strategyobject.substrateclient.rpc.metadata.MetadataProvider; +import com.strategyobject.substrateclient.rpc.registries.RpcDecoderRegistry; +import com.strategyobject.substrateclient.rpc.registries.RpcEncoderRegistry; +import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; +import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; +import com.strategyobject.substrateclient.transport.ProviderInterface; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class TestsHelper { + public static final MetadataProvider METADATA_PROVIDER = mock(MetadataProvider.class); + + static { + when(METADATA_PROVIDER.getSS58AddressFormat()).thenReturn(SS58AddressFormat.SUBSTRATE_ACCOUNT); + } + + public static final ScaleReaderRegistry SCALE_READER_REGISTRY = new ScaleReaderRegistry() {{ + registerAnnotatedFrom("com.strategyobject.substrateclient"); + }}; + + public static final ScaleWriterRegistry SCALE_WRITER_REGISTRY = new ScaleWriterRegistry() {{ + registerAnnotatedFrom("com.strategyobject.substrateclient"); + }}; + + public static final RpcEncoderRegistry RPC_ENCODER_REGISTRY = new RpcEncoderRegistry(); + + static { + RPC_ENCODER_REGISTRY.registerAnnotatedFrom( + () -> new RpcEncoderContext(METADATA_PROVIDER, RPC_ENCODER_REGISTRY, SCALE_WRITER_REGISTRY), + "com.strategyobject.substrateclient"); + } + + public static final RpcDecoderRegistry RPC_DECODER_REGISTRY = new RpcDecoderRegistry(); + + static { + RPC_DECODER_REGISTRY.registerAnnotatedFrom( + () -> new RpcDecoderContext(METADATA_PROVIDER, RPC_DECODER_REGISTRY, SCALE_READER_REGISTRY), + "com.strategyobject.substrateclient"); + } + + public static GeneratedRpcSectionFactory createSectionFactory(ProviderInterface provider) { + return new GeneratedRpcSectionFactory( + provider, + RPC_ENCODER_REGISTRY, + SCALE_WRITER_REGISTRY, + RPC_DECODER_REGISTRY, + SCALE_READER_REGISTRY); + } +} + diff --git a/storage/src/test/java/com/strategyobject/substrateclient/storage/Blake2B128ConcatTests.java b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/storage/Blake2B128ConcatTests.java similarity index 81% rename from storage/src/test/java/com/strategyobject/substrateclient/storage/Blake2B128ConcatTests.java rename to pallet/src/test/java/com/strategyobject/substrateclient/pallet/storage/Blake2B128ConcatTests.java index 49a7222d..c0cc7780 100644 --- a/storage/src/test/java/com/strategyobject/substrateclient/storage/Blake2B128ConcatTests.java +++ b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/storage/Blake2B128ConcatTests.java @@ -1,10 +1,10 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import com.strategyobject.substrateclient.crypto.ss58.SS58Codec; -import com.strategyobject.substrateclient.rpc.types.AccountId; +import com.strategyobject.substrateclient.pallet.TestsHelper; +import com.strategyobject.substrateclient.rpc.api.AccountId; import com.strategyobject.substrateclient.scale.ScaleWriter; -import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; @@ -16,7 +16,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -public class Blake2B128ConcatTests { +class Blake2B128ConcatTests { private static Stream getTestCasesForGetHash() { return Stream.of( Arguments.of( @@ -42,14 +42,14 @@ private static Stream getTestCasesForGetHash() { @SuppressWarnings("unchecked") private static byte[] decode(Class type, T value) { val buf = new ByteArrayOutputStream(); - ((ScaleWriter) ScaleWriterRegistry.getInstance().resolve(type)).write(value, buf); + ((ScaleWriter) TestsHelper.SCALE_WRITER_REGISTRY.resolve(type)).write(value, buf); return buf.toByteArray(); } @ParameterizedTest @MethodSource("getTestCasesForGetHash") - public void getHash(byte[] encodedKey, String expectedInHex) { + void getHash(byte[] encodedKey, String expectedInHex) { val algorithm = Blake2B128Concat.getInstance(); val actual = algorithm.getHash(encodedKey); diff --git a/storage/src/test/java/com/strategyobject/substrateclient/storage/IdentityTests.java b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/storage/IdentityTests.java similarity index 73% rename from storage/src/test/java/com/strategyobject/substrateclient/storage/IdentityTests.java rename to pallet/src/test/java/com/strategyobject/substrateclient/pallet/storage/IdentityTests.java index 8f99e4e6..d11424e2 100644 --- a/storage/src/test/java/com/strategyobject/substrateclient/storage/IdentityTests.java +++ b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/storage/IdentityTests.java @@ -1,8 +1,9 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; -import com.strategyobject.substrateclient.rpc.types.BlockHash; +import com.strategyobject.substrateclient.pallet.TestsHelper; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockHash; +import com.strategyobject.substrateclient.rpc.api.primitives.Hash256; import com.strategyobject.substrateclient.scale.ScaleWriter; -import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; @@ -15,11 +16,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -public class IdentityTests { +class IdentityTests { private static Stream getTestCasesForGetHash() { return Stream.of( encode(Integer.class, -175), - encode(BlockHash.class, BlockHash.fromBytes(random(32))), + encode(BlockHash.class, Hash256.fromBytes(random(32))), "TestString".getBytes(StandardCharsets.UTF_8), random(new Random().nextInt(128) + 1)); } @@ -28,7 +29,7 @@ private static Stream getTestCasesForGetHash() { @SuppressWarnings("unchecked") private static byte[] encode(Class type, T value) { val buf = new ByteArrayOutputStream(); - ((ScaleWriter) ScaleWriterRegistry.getInstance().resolve(type)).write(value, buf); + ((ScaleWriter) TestsHelper.SCALE_WRITER_REGISTRY.resolve(type)).write(value, buf); return buf.toByteArray(); } @@ -42,7 +43,7 @@ private static byte[] random(int length) { @ParameterizedTest @MethodSource("getTestCasesForGetHash") - public void getHash(byte[] encodedKey) { + void getHash(byte[] encodedKey) { val algorithm = Identity.getInstance(); val actual = algorithm.getHash(encodedKey); diff --git a/storage/src/test/java/com/strategyobject/substrateclient/storage/KeyHasherTests.java b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/storage/KeyHasherTests.java similarity index 69% rename from storage/src/test/java/com/strategyobject/substrateclient/storage/KeyHasherTests.java rename to pallet/src/test/java/com/strategyobject/substrateclient/pallet/storage/KeyHasherTests.java index 7088e73f..3a0e58d6 100644 --- a/storage/src/test/java/com/strategyobject/substrateclient/storage/KeyHasherTests.java +++ b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/storage/KeyHasherTests.java @@ -1,14 +1,14 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import com.strategyobject.substrateclient.crypto.ss58.SS58Codec; -import com.strategyobject.substrateclient.rpc.types.AccountId; -import com.strategyobject.substrateclient.rpc.types.BlockHash; +import com.strategyobject.substrateclient.pallet.TestsHelper; +import com.strategyobject.substrateclient.rpc.api.AccountId; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockHash; +import com.strategyobject.substrateclient.rpc.api.primitives.Hash256; import com.strategyobject.substrateclient.scale.ScaleReader; import com.strategyobject.substrateclient.scale.ScaleWriter; import com.strategyobject.substrateclient.scale.readers.CompactIntegerReader; -import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; -import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; import com.strategyobject.substrateclient.scale.writers.CompactIntegerWriter; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; @@ -23,13 +23,13 @@ import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; -public class KeyHasherTests { +class KeyHasherTests { private static Stream getTestCasesForGetHash() { return Stream.of( Arguments.of( 10, - ScaleReaderRegistry.getInstance().resolve(Integer.class), - ScaleWriterRegistry.getInstance().resolve(Integer.class), + TestsHelper.SCALE_READER_REGISTRY.resolve(Integer.class), + TestsHelper.SCALE_WRITER_REGISTRY.resolve(Integer.class), TwoX64Concat.getInstance(), "0xa6b274250e6753f00a000000" ), @@ -38,15 +38,15 @@ private static Stream getTestCasesForGetHash() { SS58Codec.decode( "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty") .getAddress()), - ScaleReaderRegistry.getInstance().resolve(AccountId.class), - ScaleWriterRegistry.getInstance().resolve(AccountId.class), + TestsHelper.SCALE_READER_REGISTRY.resolve(AccountId.class), + TestsHelper.SCALE_WRITER_REGISTRY.resolve(AccountId.class), Blake2B128Concat.getInstance(), "0x4f9aea1afa791265fae359272badc1cf8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48" ), Arguments.of( - BlockHash.fromBytes(HexConverter.toBytes("0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef")), - ScaleReaderRegistry.getInstance().resolve(BlockHash.class), - ScaleWriterRegistry.getInstance().resolve(BlockHash.class), + Hash256.fromBytes(HexConverter.toBytes("0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef")), + TestsHelper.SCALE_READER_REGISTRY.resolve(BlockHash.class), + TestsHelper.SCALE_WRITER_REGISTRY.resolve(BlockHash.class), Identity.getInstance(), "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" ) @@ -59,8 +59,8 @@ private static Stream getTestCasesForExtractKey() { new ByteArrayInputStream( HexConverter.toBytes("0x5153cb1f00942ff401000000") ), - ScaleReaderRegistry.getInstance().resolve(Integer.class), - ScaleWriterRegistry.getInstance().resolve(Integer.class), + TestsHelper.SCALE_READER_REGISTRY.resolve(Integer.class), + TestsHelper.SCALE_WRITER_REGISTRY.resolve(Integer.class), TwoX64Concat.getInstance(), 1, 0 @@ -69,8 +69,8 @@ private static Stream getTestCasesForExtractKey() { new ByteArrayInputStream( HexConverter.toBytes("0x969e061847da7e84337ea78dc577cd1d05000000") ), - ScaleReaderRegistry.getInstance().resolve(Integer.class), - ScaleWriterRegistry.getInstance().resolve(Integer.class), + TestsHelper.SCALE_READER_REGISTRY.resolve(Integer.class), + TestsHelper.SCALE_WRITER_REGISTRY.resolve(Integer.class), Blake2B128Concat.getInstance(), 5, 0 @@ -89,8 +89,8 @@ private static Stream getTestCasesForExtractKey() { new ByteArrayInputStream( HexConverter.toBytes("0x") ), - ScaleReaderRegistry.getInstance().resolve(Void.class), - ScaleWriterRegistry.getInstance().resolve(Void.class), + TestsHelper.SCALE_READER_REGISTRY.resolve(Void.class), + TestsHelper.SCALE_WRITER_REGISTRY.resolve(Void.class), Identity.getInstance(), null, 0 @@ -100,8 +100,8 @@ private static Stream getTestCasesForExtractKey() { HexConverter.toBytes("0x4f9aea1afa791265fae359272badc1cf8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48" + "a6b274250e6753f00a000000") ), - ScaleReaderRegistry.getInstance().resolve(AccountId.class), - ScaleWriterRegistry.getInstance().resolve(AccountId.class), + TestsHelper.SCALE_READER_REGISTRY.resolve(AccountId.class), + TestsHelper.SCALE_WRITER_REGISTRY.resolve(AccountId.class), Blake2B128Concat.getInstance(), AccountId.fromBytes( SS58Codec.decode( @@ -112,17 +112,17 @@ private static Stream getTestCasesForExtractKey() { Arguments.of( new ByteArrayInputStream( HexConverter.toBytes("0xabcdef98765432100123456789abcdefabcdef98765432100123456789abcdef")), - ScaleReaderRegistry.getInstance().resolve(BlockHash.class), - ScaleWriterRegistry.getInstance().resolve(BlockHash.class), + TestsHelper.SCALE_READER_REGISTRY.resolve(BlockHash.class), + TestsHelper.SCALE_WRITER_REGISTRY.resolve(BlockHash.class), Identity.getInstance(), - BlockHash.fromBytes(HexConverter.toBytes("0xabcdef98765432100123456789abcdefabcdef98765432100123456789abcdef")), + Hash256.fromBytes(HexConverter.toBytes("0xabcdef98765432100123456789abcdefabcdef98765432100123456789abcdef")), 0 ), Arguments.of( new ByteArrayInputStream( HexConverter.toBytes("0x518366b5b1bc7c99d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d")), - ScaleReaderRegistry.getInstance().resolve(BlockHash.class), - ScaleWriterRegistry.getInstance().resolve(BlockHash.class), + TestsHelper.SCALE_READER_REGISTRY.resolve(BlockHash.class), + TestsHelper.SCALE_WRITER_REGISTRY.resolve(BlockHash.class), TwoX64Concat.getInstance(), AccountId.fromBytes( SS58Codec.decode( @@ -135,11 +135,11 @@ private static Stream getTestCasesForExtractKey() { @ParameterizedTest @MethodSource("getTestCasesForGetHash") - public void getHash(T key, - ScaleReader reader, - ScaleWriter writer, - KeyHashingAlgorithm algorithm, - String expectedInHex) throws IOException { + void getHash(T key, + ScaleReader reader, + ScaleWriter writer, + KeyHashingAlgorithm algorithm, + String expectedInHex) throws IOException { val hasher = KeyHasher.with(writer, reader, algorithm); val actual = hasher.getHash(key); @@ -149,12 +149,12 @@ public void getHash(T key, @ParameterizedTest @MethodSource("getTestCasesForExtractKey") - public void extractKey(InputStream stream, - ScaleReader reader, - ScaleWriter writer, - KeyHashingAlgorithm algorithm, - T expected, - int expectedAvailable) throws IOException { + void extractKey(InputStream stream, + ScaleReader reader, + ScaleWriter writer, + KeyHashingAlgorithm algorithm, + T expected, + int expectedAvailable) throws IOException { val hasher = KeyHasher.with(writer, reader, algorithm); val actual = hasher.extractKey(stream); diff --git a/storage/src/test/java/com/strategyobject/substrateclient/storage/StorageDoubleMapImplTests.java b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/storage/StorageDoubleMapImplTests.java similarity index 62% rename from storage/src/test/java/com/strategyobject/substrateclient/storage/StorageDoubleMapImplTests.java rename to pallet/src/test/java/com/strategyobject/substrateclient/pallet/storage/StorageDoubleMapImplTests.java index 405d5279..d9557382 100644 --- a/storage/src/test/java/com/strategyobject/substrateclient/storage/StorageDoubleMapImplTests.java +++ b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/storage/StorageDoubleMapImplTests.java @@ -1,14 +1,14 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; import com.strategyobject.substrateclient.crypto.ss58.SS58Codec; -import com.strategyobject.substrateclient.rpc.RpcImpl; -import com.strategyobject.substrateclient.rpc.types.AccountId; +import com.strategyobject.substrateclient.pallet.TestsHelper; +import com.strategyobject.substrateclient.rpc.api.AccountId; +import com.strategyobject.substrateclient.rpc.api.section.State; import com.strategyobject.substrateclient.scale.ScaleReader; import com.strategyobject.substrateclient.scale.ScaleWriter; -import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; -import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; import com.strategyobject.substrateclient.tests.containers.SubstrateVersion; import com.strategyobject.substrateclient.tests.containers.TestSubstrateContainer; +import com.strategyobject.substrateclient.transport.ws.ReconnectionPolicy; import com.strategyobject.substrateclient.transport.ws.WsProvider; import lombok.val; import org.junit.jupiter.api.Test; @@ -20,29 +20,31 @@ import static org.junit.jupiter.api.Assertions.assertNull; @Testcontainers -public class StorageDoubleMapImplTests { +class StorageDoubleMapImplTests { @Container static final TestSubstrateContainer substrate = new TestSubstrateContainer(SubstrateVersion.V3_0_0); private static final int CONNECTION_TIMEOUT = 1000; @Test @SuppressWarnings("unchecked") - public void societyVotes() throws Exception { - val wsProvider = WsProvider.builder() + void societyVotes() throws Exception { + try (val wsProvider = WsProvider.builder() .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() - .build(); - wsProvider.connect().get(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS); - try (val rpc = RpcImpl.with(wsProvider)) { + .withPolicy(ReconnectionPolicy.MANUAL) + .build()) { + wsProvider.connect().get(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS); + + val state = TestsHelper.createSectionFactory(wsProvider).create(State.class); val storage = StorageDoubleMapImpl.with( - rpc, - (ScaleReader) ScaleReaderRegistry.getInstance().resolve(Void.class), + state, + (ScaleReader) TestsHelper.SCALE_READER_REGISTRY.resolve(Void.class), StorageKeyProvider.of("Society", "Votes") - .use(KeyHasher.with((ScaleWriter) ScaleWriterRegistry.getInstance().resolve(AccountId.class), - (ScaleReader) ScaleReaderRegistry.getInstance().resolve(AccountId.class), + .use( + KeyHasher.with((ScaleWriter) TestsHelper.SCALE_WRITER_REGISTRY.resolve(AccountId.class), + (ScaleReader) TestsHelper.SCALE_READER_REGISTRY.resolve(AccountId.class), TwoX64Concat.getInstance()), - KeyHasher.with((ScaleWriter) ScaleWriterRegistry.getInstance().resolve(AccountId.class), - (ScaleReader) ScaleReaderRegistry.getInstance().resolve(AccountId.class), + KeyHasher.with((ScaleWriter) TestsHelper.SCALE_WRITER_REGISTRY.resolve(AccountId.class), + (ScaleReader) TestsHelper.SCALE_READER_REGISTRY.resolve(AccountId.class), TwoX64Concat.getInstance()))); val alice = AccountId.fromBytes( SS58Codec.decode( diff --git a/storage/src/test/java/com/strategyobject/substrateclient/storage/StorageKeyProviderTests.java b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/storage/StorageKeyProviderTests.java similarity index 81% rename from storage/src/test/java/com/strategyobject/substrateclient/storage/StorageKeyProviderTests.java rename to pallet/src/test/java/com/strategyobject/substrateclient/pallet/storage/StorageKeyProviderTests.java index d73c8807..f9469b48 100644 --- a/storage/src/test/java/com/strategyobject/substrateclient/storage/StorageKeyProviderTests.java +++ b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/storage/StorageKeyProviderTests.java @@ -1,13 +1,12 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import com.strategyobject.substrateclient.crypto.ss58.SS58Codec; -import com.strategyobject.substrateclient.rpc.types.AccountId; -import com.strategyobject.substrateclient.rpc.types.StorageKey; +import com.strategyobject.substrateclient.pallet.TestsHelper; +import com.strategyobject.substrateclient.rpc.api.AccountId; +import com.strategyobject.substrateclient.rpc.api.storage.StorageKey; import com.strategyobject.substrateclient.scale.ScaleReader; import com.strategyobject.substrateclient.scale.ScaleWriter; -import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; -import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; import lombok.NonNull; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; @@ -25,7 +24,7 @@ import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; -public class StorageKeyProviderTests { +class StorageKeyProviderTests { @SuppressWarnings("unchecked") private static Stream getTestCasesForGetBySingleKey() { return Stream.of( @@ -45,8 +44,8 @@ private static Stream getTestCasesForGetBySingleKey() { Arguments.of("System", "BlockHash", KeyHasher.with( - (ScaleWriter) ScaleWriterRegistry.getInstance().resolve(Integer.class), - (ScaleReader) ScaleReaderRegistry.getInstance().resolve(Integer.class), + (ScaleWriter) TestsHelper.SCALE_WRITER_REGISTRY.resolve(Integer.class), + (ScaleReader) TestsHelper.SCALE_READER_REGISTRY.resolve(Integer.class), TwoX64Concat.getInstance() ), 2, @@ -59,12 +58,12 @@ private static Stream getTestCasesForGetBySingleKey() { @SuppressWarnings({"unchecked", "SameParameterValue"}) private static ScaleReader resolveReader(Class clazz) { - return (ScaleReader) ScaleReaderRegistry.getInstance().resolve(clazz); + return (ScaleReader) TestsHelper.SCALE_READER_REGISTRY.resolve(clazz); } @SuppressWarnings({"unchecked", "SameParameterValue"}) private static ScaleWriter resolveWriter(Class clazz) { - return (ScaleWriter) ScaleWriterRegistry.getInstance().resolve(clazz); + return (ScaleWriter) TestsHelper.SCALE_WRITER_REGISTRY.resolve(clazz); } private static Stream getTestCasesForGetByDoubleKey() { @@ -188,7 +187,7 @@ private static StorageKeyProvider newFreeBalanceKeyProvider() { @CsvSource({ "SomePallet,SomeStorage,0x832718a9c64cbad10dc0772e2c2d3d9c2e186e85ed8948269c15e1c78ccd4305", "Sudo,Key,0x5c0d1176a568c1f92944340dbfed9e9c530ebca703c85910e7164cb7d1c9e47b"}) - public void getWithoutKey(String pallet, String storage, String expectedInHex) { + void getWithoutKey(String pallet, String storage, String expectedInHex) { val provider = StorageKeyProvider.of(pallet, storage); val storageKey = provider.get(); @@ -199,11 +198,11 @@ public void getWithoutKey(String pallet, String storage, String expectedInHex) { @ParameterizedTest @MethodSource("getTestCasesForGetBySingleKey") - public void getBySingleKey(String pallet, - String storage, - KeyHasher keyHasher, - T key, - String expectedInHex) { + void getBySingleKey(String pallet, + String storage, + KeyHasher keyHasher, + T key, + String expectedInHex) { val provider = StorageKeyProvider.of(pallet, storage) .use(keyHasher); @@ -215,13 +214,13 @@ public void getBySingleKey(String pallet, @ParameterizedTest @MethodSource("getTestCasesForGetByDoubleKey") - public void getByDoubleKey(String pallet, - String storage, - KeyHasher firstHasher, - F firstKey, - KeyHasher secondHasher, - S secondKey, - String expectedInHex) { + void getByDoubleKey(String pallet, + String storage, + KeyHasher firstHasher, + F firstKey, + KeyHasher secondHasher, + S secondKey, + String expectedInHex) { val provider = StorageKeyProvider.of(pallet, storage) .use(firstHasher, secondHasher); @@ -233,7 +232,7 @@ public void getByDoubleKey(String pallet, @ParameterizedTest @MethodSource("getTestCasesForExtractKeys") - public void extractKeys(StorageKeyProvider provider, StorageKey fullKey, List expected) { + void extractKeys(StorageKeyProvider provider, StorageKey fullKey, List expected) { val actual = provider.extractKeys(fullKey); assertArrayEquals(expected.toArray(), actual.toArray()); @@ -241,11 +240,11 @@ public void extractKeys(StorageKeyProvider provider, StorageKey fullKey, List expected) { + void extractKeysUsingQueryKey(StorageKeyProvider provider, + StorageKey fullKey, + StorageKey queryKey, + int countOfKeysInQuery, + List expected) { val actual = provider.extractKeys(fullKey, queryKey, countOfKeysInQuery); assertArrayEquals(expected.toArray(), actual.toArray()); diff --git a/storage/src/test/java/com/strategyobject/substrateclient/storage/StorageMapImplTests.java b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/storage/StorageMapImplTests.java similarity index 55% rename from storage/src/test/java/com/strategyobject/substrateclient/storage/StorageMapImplTests.java rename to pallet/src/test/java/com/strategyobject/substrateclient/pallet/storage/StorageMapImplTests.java index acd6c364..71baa5af 100644 --- a/storage/src/test/java/com/strategyobject/substrateclient/storage/StorageMapImplTests.java +++ b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/storage/StorageMapImplTests.java @@ -1,13 +1,13 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; -import com.strategyobject.substrateclient.rpc.RpcImpl; -import com.strategyobject.substrateclient.rpc.types.BlockHash; +import com.strategyobject.substrateclient.pallet.TestsHelper; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockHash; +import com.strategyobject.substrateclient.rpc.api.section.State; import com.strategyobject.substrateclient.scale.ScaleReader; import com.strategyobject.substrateclient.scale.ScaleWriter; -import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; -import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; import com.strategyobject.substrateclient.tests.containers.SubstrateVersion; import com.strategyobject.substrateclient.tests.containers.TestSubstrateContainer; +import com.strategyobject.substrateclient.transport.ws.ReconnectionPolicy; import com.strategyobject.substrateclient.transport.ws.WsProvider; import lombok.val; import org.junit.jupiter.api.Test; @@ -20,31 +20,32 @@ import static org.junit.jupiter.api.Assertions.assertNotEquals; @Testcontainers -public class StorageMapImplTests { +class StorageMapImplTests { @Container static final TestSubstrateContainer substrate = new TestSubstrateContainer(SubstrateVersion.V3_0_0); private static final int CONNECTION_TIMEOUT = 1000; @Test @SuppressWarnings("unchecked") - public void systemBlockHash() throws Exception { - val wsProvider = WsProvider.builder() + void systemBlockHash() throws Exception { + try (val wsProvider = WsProvider.builder() .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() - .build(); - wsProvider.connect().get(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS); - try (val rpc = RpcImpl.with(wsProvider)) { + .withPolicy(ReconnectionPolicy.MANUAL) + .build()) { + wsProvider.connect().get(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS); + + val state = TestsHelper.createSectionFactory(wsProvider).create(State.class); val storage = StorageMapImpl.with( - rpc, - (ScaleReader) ScaleReaderRegistry.getInstance().resolve(BlockHash.class), + state, + (ScaleReader) TestsHelper.SCALE_READER_REGISTRY.resolve(BlockHash.class), StorageKeyProvider.of("System", "BlockHash") - .use(KeyHasher.with((ScaleWriter) ScaleWriterRegistry.getInstance().resolve(Integer.class), - (ScaleReader) ScaleReaderRegistry.getInstance().resolve(Integer.class), + .use(KeyHasher.with((ScaleWriter) TestsHelper.SCALE_WRITER_REGISTRY.resolve(Integer.class), + (ScaleReader) TestsHelper.SCALE_READER_REGISTRY.resolve(Integer.class), TwoX64Concat.getInstance()))); val actual = storage.get(0).get(); - assertNotEquals(BigInteger.ZERO, new BigInteger(actual.getData())); + assertNotEquals(BigInteger.ZERO, new BigInteger(actual.getBytes())); } } } diff --git a/storage/src/test/java/com/strategyobject/substrateclient/storage/StorageNMapImplTests.java b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/storage/StorageNMapImplTests.java similarity index 54% rename from storage/src/test/java/com/strategyobject/substrateclient/storage/StorageNMapImplTests.java rename to pallet/src/test/java/com/strategyobject/substrateclient/pallet/storage/StorageNMapImplTests.java index 0d65c519..d4090ad8 100644 --- a/storage/src/test/java/com/strategyobject/substrateclient/storage/StorageNMapImplTests.java +++ b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/storage/StorageNMapImplTests.java @@ -1,17 +1,20 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; +import com.strategyobject.substrateclient.common.types.tuple.Pair; import com.strategyobject.substrateclient.crypto.ss58.SS58Codec; -import com.strategyobject.substrateclient.rpc.RpcImpl; -import com.strategyobject.substrateclient.rpc.types.AccountId; -import com.strategyobject.substrateclient.rpc.types.BlockHash; +import com.strategyobject.substrateclient.pallet.TestsHelper; +import com.strategyobject.substrateclient.rpc.api.AccountId; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockHash; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockNumber; +import com.strategyobject.substrateclient.rpc.api.section.Chain; +import com.strategyobject.substrateclient.rpc.api.section.State; import com.strategyobject.substrateclient.scale.ScaleReader; import com.strategyobject.substrateclient.scale.ScaleWriter; -import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; -import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; import com.strategyobject.substrateclient.tests.containers.SubstrateVersion; import com.strategyobject.substrateclient.tests.containers.TestSubstrateContainer; +import com.strategyobject.substrateclient.transport.ProviderInterface; +import com.strategyobject.substrateclient.transport.ws.ReconnectionPolicy; import com.strategyobject.substrateclient.transport.ws.WsProvider; -import com.strategyobject.substrateclient.types.tuples.Pair; import lombok.NonNull; import lombok.val; import lombok.var; @@ -28,25 +31,25 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; +import static org.awaitility.Awaitility.await; +import static org.hamcrest.Matchers.greaterThan; import static org.junit.jupiter.api.Assertions.*; -import static org.testcontainers.shaded.org.awaitility.Awaitility.await; -import static org.testcontainers.shaded.org.hamcrest.number.OrderingComparison.greaterThan; @Testcontainers -public class StorageNMapImplTests { +class StorageNMapImplTests { private static final int CONNECTION_TIMEOUT = 1000; private static final int WAIT_TIMEOUT = 10; @Container private final TestSubstrateContainer substrate = new TestSubstrateContainer(SubstrateVersion.V3_0_0); @SuppressWarnings("unchecked") - private static StorageNMapImpl newSystemBlockHashStorage(RpcImpl rpc) { + private static StorageNMapImpl newSystemBlockHashStorage(State state) { return StorageNMapImpl.with( - rpc, - (ScaleReader) ScaleReaderRegistry.getInstance().resolve(BlockHash.class), + state, + (ScaleReader) TestsHelper.SCALE_READER_REGISTRY.resolve(BlockHash.class), StorageKeyProvider.of("System", "BlockHash") - .use(KeyHasher.with((ScaleWriter) ScaleWriterRegistry.getInstance().resolve(Integer.class), - (ScaleReader) ScaleReaderRegistry.getInstance().resolve(Integer.class), + .use(KeyHasher.with((ScaleWriter) TestsHelper.SCALE_WRITER_REGISTRY.resolve(BlockNumber.class), + (ScaleReader) TestsHelper.SCALE_READER_REGISTRY.resolve(BlockNumber.class), TwoX64Concat.getInstance()))); } @@ -54,27 +57,27 @@ private static StorageNMapImpl newSystemBlockHashStorage(RpcImpl rpc) private WsProvider getConnectedProvider() throws InterruptedException, ExecutionException, TimeoutException { val wsProvider = WsProvider.builder() .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() + .withPolicy(ReconnectionPolicy.MANUAL) .build(); wsProvider.connect().get(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS); return wsProvider; } @Test - public void keys() throws Exception { - val wsProvider = getConnectedProvider(); - try (val rpc = RpcImpl.with(wsProvider)) { - val storage = newSystemBlockHashStorage(rpc); + void keys() throws Exception { + try (val wsProvider = getConnectedProvider()) { + val state = TestsHelper.createSectionFactory(wsProvider).create(State.class); + val storage = newSystemBlockHashStorage(state); val collection = storage.keys().get(); assertNotNull(collection); assertEquals(1, collection.size()); - val blockNumber = new AtomicReference(null); - collection.iterator().forEachRemaining(q -> q.consume((o -> blockNumber.set((Integer) o.get(0))))); + val blockNumber = new AtomicReference(null); + collection.iterator().forEachRemaining(q -> q.consume((o -> blockNumber.set((BlockNumber) o.get(0))))); - assertEquals(0, blockNumber.get()); + assertEquals(BlockNumber.GENESIS, blockNumber.get()); val blocks = collection.multi().execute().get(); val list = new ArrayList<>(); @@ -83,22 +86,22 @@ public void keys() throws Exception { assertEquals(1, list.size()); val block = (BlockHash) list.stream().findFirst().orElseThrow(RuntimeException::new); - assertNotEquals(BigInteger.ZERO, new BigInteger(block.getData())); + assertNotEquals(BigInteger.ZERO, new BigInteger(block.getBytes())); } } @Test - public void multiToDifferentStorages() throws Exception { - val wsProvider = getConnectedProvider(); - try (val rpc = RpcImpl.with(wsProvider)) { + void multiToDifferentStorages() throws Exception { + try (val wsProvider = getConnectedProvider()) { + val state = TestsHelper.createSectionFactory(wsProvider).create(State.class); val storageValue = StorageNMapImpl.with( - rpc, - ScaleReaderRegistry.getInstance().resolve(AccountId.class), + state, + TestsHelper.SCALE_READER_REGISTRY.resolve(AccountId.class), StorageKeyProvider.of("Sudo", "Key")); - val storageMap = newSystemBlockHashStorage(rpc); + val storageMap = newSystemBlockHashStorage(state); val getKey = storageValue.query(); - val getHash = storageMap.query(0); + val getHash = storageMap.query(BlockNumber.GENESIS); val multi = getKey.join(getHash); val collection = multi.execute().get(); @@ -107,7 +110,7 @@ public void multiToDifferentStorages() throws Exception { SS58Codec.decode( "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY") .getAddress()); - val expectedBlock = storageMap.get(0).get(); + val expectedBlock = storageMap.get(BlockNumber.GENESIS).get(); val list = new ArrayList<>(2); collection.iterator().forEachRemaining(e -> e.consume((value, keys) -> list.add(value))); @@ -118,56 +121,62 @@ public void multiToDifferentStorages() throws Exception { } @Test - public void entries() throws Exception { - val wsProvider = getConnectedProvider(); - try (val rpc = RpcImpl.with(wsProvider)) { - val storage = newSystemBlockHashStorage(rpc); + void entries() throws Exception { + try (val wsProvider = getConnectedProvider()) { + val state = TestsHelper.createSectionFactory(wsProvider).create(State.class); + val storage = newSystemBlockHashStorage(state); val collection = storage.entries().get(); assertNotNull(collection); - val blockNumber = new AtomicReference(null); + val blockNumber = new AtomicReference(null); val blockHash = new AtomicReference(null); collection.iterator().forEachRemaining(e -> e.consume((value, keys) -> { blockHash.set(value); - blockNumber.set((Integer) keys.get(0)); + blockNumber.set((BlockNumber) keys.get(0)); })); - assertEquals(0, blockNumber.get()); - assertNotEquals(BigInteger.ZERO, new BigInteger(blockHash.get().getData())); + assertEquals(BlockNumber.GENESIS, blockNumber.get()); + assertNotEquals(BigInteger.ZERO, new BigInteger(blockHash.get().getBytes())); } } @Test - public void multi() throws Exception { - val wsProvider = getConnectedProvider(); - try (val rpc = RpcImpl.with(wsProvider)) { - val storage = newSystemBlockHashStorage(rpc); - - val collection = storage.multi(Arg.of(0), Arg.of(1)).get(); + void multi() throws Exception { + try (val wsProvider = getConnectedProvider()) { + val state = TestsHelper.createSectionFactory(wsProvider).create(State.class); + val storage = newSystemBlockHashStorage(state); + + val collection = storage.multi( + Arg.of(BlockNumber.GENESIS), + Arg.of(BlockNumber.of(1))) + .get(); assertNotNull(collection); - val list = new ArrayList>(); - collection.iterator().forEachRemaining(e -> e.consume((value, keys) -> list.add(Pair.of((Integer) keys.get(0), value)))); + val list = new ArrayList>(); + collection.iterator() + .forEachRemaining(e -> + e.consume((value, keys) -> + list.add(Pair.of((BlockNumber) keys.get(0), value)))); assertEquals(2, list.size()); - assertEquals(0, list.get(0).getValue0()); - assertNotEquals(BigInteger.ZERO, new BigInteger(list.get(0).getValue1().getData())); + assertEquals(BlockNumber.GENESIS, list.get(0).getValue0()); + assertNotEquals(BigInteger.ZERO, new BigInteger(list.get(0).getValue1().getBytes())); - assertEquals(1, list.get(1).getValue0()); + assertEquals(BlockNumber.of(1), list.get(1).getValue0()); assertNull(list.get(1).getValue1()); } } @Test - public void keysPaged() throws Exception { - val wsProvider = getConnectedProvider(); - try (val rpc = RpcImpl.with(wsProvider)) { - waitForNewBlocks(rpc); + void keysPaged() throws Exception { + try (val wsProvider = getConnectedProvider()) { + val state = TestsHelper.createSectionFactory(wsProvider).create(State.class); + waitForNewBlocks(wsProvider); - val storage = newSystemBlockHashStorage(rpc); + val storage = newSystemBlockHashStorage(state); int pageSize = 2; val pages = storage.keysPaged(pageSize); @@ -188,12 +197,12 @@ public void keysPaged() throws Exception { } @Test - public void entriesPaged() throws Exception { - val wsProvider = getConnectedProvider(); - try (val rpc = RpcImpl.with(wsProvider)) { - waitForNewBlocks(rpc); + void entriesPaged() throws Exception { + try (val wsProvider = getConnectedProvider()) { + val state = TestsHelper.createSectionFactory(wsProvider).create(State.class); + waitForNewBlocks(wsProvider); - val storage = newSystemBlockHashStorage(rpc); + val storage = newSystemBlockHashStorage(state); int pageSize = 2; val pages = storage.entriesPaged(pageSize); @@ -201,14 +210,17 @@ public void entriesPaged() throws Exception { assertNotNull(pages); var pageCount = 0; - val pairs = new ArrayList>(); + val pairs = new ArrayList>(); while (pages.moveNext().join()) { - pages.current().iterator().forEachRemaining(e -> e.consume((value, keys) -> { - val key = (Integer) keys.get(0); - assertNotEquals(BigInteger.ZERO, new BigInteger(value.getData())); - - pairs.add(Pair.of(key, value)); - })); + pages.current() + .iterator() + .forEachRemaining(e -> + e.consume((value, keys) -> { + val key = (BlockNumber) keys.get(0); + assertNotEquals(BigInteger.ZERO, new BigInteger(value.getBytes())); + + pairs.add(Pair.of(key, value)); + })); pageCount++; assertEquals(pageCount, pages.number()); } @@ -221,26 +233,27 @@ public void entriesPaged() throws Exception { } @Test - public void subscribe() throws Exception { - val wsProvider = getConnectedProvider(); - try (val rpc = RpcImpl.with(wsProvider)) { - val blockNumber = 2; - val storage = newSystemBlockHashStorage(rpc); + void subscribe() throws Exception { + try (val wsProvider = getConnectedProvider()) { + val state = TestsHelper.createSectionFactory(wsProvider).create(State.class); + val blockNumber = BlockNumber.of(2); + val storage = newSystemBlockHashStorage(state); val blockHash = new AtomicReference(); val value = new AtomicReference(); - val argument = new AtomicInteger(); + val argument = new AtomicReference(); val unsubscribe = storage.subscribe((exception, block, v, keys) -> { if (exception == null) { blockHash.set(block); value.set(v); - argument.set((Integer) keys.get(0)); + argument.set((BlockNumber) keys.get(0)); } }, Arg.of(blockNumber)) .get(WAIT_TIMEOUT, TimeUnit.SECONDS); - waitForNewBlocks(rpc); + waitForNewBlocks(wsProvider); - val expectedValue = rpc.chain().getBlockHash(blockNumber).join(); + val chain = TestsHelper.createSectionFactory(wsProvider).create(Chain.class); + val expectedValue = chain.getBlockHash(blockNumber).join(); val history = storage.history(blockNumber).join(); val changedAt = history.stream() .findFirst() @@ -256,10 +269,11 @@ public void subscribe() throws Exception { } } - private void waitForNewBlocks(RpcImpl rpc) throws InterruptedException, ExecutionException, TimeoutException { + private void waitForNewBlocks(ProviderInterface wsProvider) throws Exception { + val chain = TestsHelper.createSectionFactory(wsProvider).create(Chain.class); + val blockCount = new AtomicInteger(0); - val unsubscribeFunc = rpc - .chain() + val unsubscribeFunc = chain .subscribeNewHeads((e, h) -> { if (e == null) { blockCount.incrementAndGet(); diff --git a/storage/src/test/java/com/strategyobject/substrateclient/storage/StorageValueImplTests.java b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/storage/StorageValueImplTests.java similarity index 53% rename from storage/src/test/java/com/strategyobject/substrateclient/storage/StorageValueImplTests.java rename to pallet/src/test/java/com/strategyobject/substrateclient/pallet/storage/StorageValueImplTests.java index 692f9669..ca5f43db 100644 --- a/storage/src/test/java/com/strategyobject/substrateclient/storage/StorageValueImplTests.java +++ b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/storage/StorageValueImplTests.java @@ -1,11 +1,14 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; import com.strategyobject.substrateclient.crypto.ss58.SS58Codec; -import com.strategyobject.substrateclient.rpc.RpcImpl; -import com.strategyobject.substrateclient.rpc.types.AccountId; -import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; +import com.strategyobject.substrateclient.pallet.TestsHelper; +import com.strategyobject.substrateclient.rpc.api.AccountId; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockNumber; +import com.strategyobject.substrateclient.rpc.api.section.Chain; +import com.strategyobject.substrateclient.rpc.api.section.State; import com.strategyobject.substrateclient.tests.containers.SubstrateVersion; import com.strategyobject.substrateclient.tests.containers.TestSubstrateContainer; +import com.strategyobject.substrateclient.transport.ws.ReconnectionPolicy; import com.strategyobject.substrateclient.transport.ws.WsProvider; import lombok.val; import org.junit.jupiter.api.Test; @@ -17,27 +20,28 @@ import static org.junit.jupiter.api.Assertions.assertEquals; @Testcontainers -public class StorageValueImplTests { +class StorageValueImplTests { @Container static final TestSubstrateContainer substrate = new TestSubstrateContainer(SubstrateVersion.V3_0_0); private static final int CONNECTION_TIMEOUT = 1000; @Test - public void sudoKey() throws Exception { + void sudoKey() throws Exception { val expected = AccountId.fromBytes( SS58Codec.decode( "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY") .getAddress()); - val wsProvider = WsProvider.builder() + try (val wsProvider = WsProvider.builder() .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() - .build(); - wsProvider.connect().get(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS); - try (val rpc = RpcImpl.with(wsProvider)) { + .withPolicy(ReconnectionPolicy.MANUAL) + .build()) { + wsProvider.connect().get(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS); + + val state = TestsHelper.createSectionFactory(wsProvider).create(State.class); val storage = StorageValueImpl.with( - rpc, - ScaleReaderRegistry.getInstance().resolve(AccountId.class), + state, + TestsHelper.SCALE_READER_REGISTRY.resolve(AccountId.class), StorageKeyProvider.of("Sudo", "Key")); val actual = storage.get().get(); @@ -47,22 +51,24 @@ public void sudoKey() throws Exception { } @Test - public void sudoKeyAtGenesis() throws Exception { + void sudoKeyAtGenesis() throws Exception { val expected = AccountId.fromBytes( SS58Codec.decode( "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY") .getAddress()); - val wsProvider = WsProvider.builder() + try (val wsProvider = WsProvider.builder() .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() - .build(); - wsProvider.connect().get(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS); - try (val rpc = RpcImpl.with(wsProvider)) { - val blockHash = rpc.chain().getBlockHash(0).get(); + .withPolicy(ReconnectionPolicy.MANUAL) + .build()) { + wsProvider.connect().get(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS); + val state = TestsHelper.createSectionFactory(wsProvider).create(State.class); + val chain = TestsHelper.createSectionFactory(wsProvider).create(Chain.class); + + val blockHash = chain.getBlockHash(BlockNumber.GENESIS).get(); val storage = StorageValueImpl.with( - rpc, - ScaleReaderRegistry.getInstance().resolve(AccountId.class), + state, + TestsHelper.SCALE_READER_REGISTRY.resolve(AccountId.class), StorageKeyProvider.of("Sudo", "Key")); val actual = storage.at(blockHash).get(); diff --git a/storage/src/test/java/com/strategyobject/substrateclient/storage/TwoX64ConcatTests.java b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/storage/TwoX64ConcatTests.java similarity index 85% rename from storage/src/test/java/com/strategyobject/substrateclient/storage/TwoX64ConcatTests.java rename to pallet/src/test/java/com/strategyobject/substrateclient/pallet/storage/TwoX64ConcatTests.java index 4e6b62fa..181b9e69 100644 --- a/storage/src/test/java/com/strategyobject/substrateclient/storage/TwoX64ConcatTests.java +++ b/pallet/src/test/java/com/strategyobject/substrateclient/pallet/storage/TwoX64ConcatTests.java @@ -1,10 +1,10 @@ -package com.strategyobject.substrateclient.storage; +package com.strategyobject.substrateclient.pallet.storage; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import com.strategyobject.substrateclient.crypto.ss58.SS58Codec; -import com.strategyobject.substrateclient.rpc.types.AccountId; +import com.strategyobject.substrateclient.pallet.TestsHelper; +import com.strategyobject.substrateclient.rpc.api.AccountId; import com.strategyobject.substrateclient.scale.ScaleWriter; -import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; @@ -17,7 +17,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -public class TwoX64ConcatTests { +class TwoX64ConcatTests { private static Stream getTestCasesForGetHash() { return Stream.of( Arguments.of( @@ -55,14 +55,14 @@ private static Stream getTestCasesForGetHash() { @SuppressWarnings("unchecked") private static byte[] decode(Class type, T value) { val buf = new ByteArrayOutputStream(); - ((ScaleWriter) ScaleWriterRegistry.getInstance().resolve(type)).write(value, buf); + ((ScaleWriter) TestsHelper.SCALE_WRITER_REGISTRY.resolve(type)).write(value, buf); return buf.toByteArray(); } @ParameterizedTest @MethodSource("getTestCasesForGetHash") - public void getHash(byte[] encodedKey, String expectedInHex) { + void getHash(byte[] encodedKey, String expectedInHex) { val algorithm = new TwoX64Concat(); val actual = algorithm.getHash(encodedKey); diff --git a/readme.md b/readme.md index 3f7afc25..91794749 100644 --- a/readme.md +++ b/readme.md @@ -1,5 +1,5 @@ - + # About @@ -40,7 +40,7 @@ The best approach to reach project’s goals is to use annotations and code gene - [x] `@Pallet`; - [ ] `@Transaction`; - [x] `@Storage`; - - [ ] `@EventHandler`. + - [x] `@Event`. These allow the generation of scale serializers, deserializers, RPC methods, code for interaction with pallet, etc. More examples you can find below. @@ -70,4 +70,4 @@ We take care of either lost responses or canceled futures by not holding handler - ### Tests run with substrate node. All API methods related to the substrate node will be tested for operability and compatibility. -Currently we use [test containers](https://www.testcontainers.org/) and docker image [parity/substrate:v3.0.0](https://hub.docker.com/layers/parity/substrate/v3.0.0/images/sha256-1aef07509d757c584320773c476dcb6077578bbf2f5e468ceb413dcf908897f1?context=explore). +Currently, we use [test containers](https://www.testcontainers.org/) and docker image [parity/substrate:v3.0.0](https://hub.docker.com/layers/parity/substrate/v3.0.0/images/sha256-1aef07509d757c584320773c476dcb6077578bbf2f5e468ceb413dcf908897f1?context=explore). diff --git a/rpc/build.gradle b/rpc/build.gradle index f8044c90..f1414121 100644 --- a/rpc/build.gradle +++ b/rpc/build.gradle @@ -1,5 +1,9 @@ dependencies { + implementation project(':common') + implementation project(':crypto') + implementation project(':scale') implementation project(':transport') - implementation project(':rpc:rpc-sections') - implementation project(':rpc:rpc-core') + + testImplementation project(':tests') + testImplementation 'com.google.code.gson:gson:2.9.0' } \ No newline at end of file diff --git a/rpc/rpc-api/build.gradle b/rpc/rpc-api/build.gradle new file mode 100644 index 00000000..a85aaa7d --- /dev/null +++ b/rpc/rpc-api/build.gradle @@ -0,0 +1,20 @@ +dependencies { + implementation project(':common') + implementation project(':crypto') + implementation project(':rpc') + implementation project(':scale') + implementation project(':transport') + + annotationProcessor project(':rpc:rpc-codegen') + annotationProcessor project(':scale:scale-codegen') + + testImplementation project(':tests') + + testAnnotationProcessor project(':scale:scale-codegen') + + testImplementation 'ch.qos.logback:logback-classic:1.2.11' + testImplementation 'org.testcontainers:testcontainers:1.17.3' + testImplementation 'org.testcontainers:junit-jupiter:1.17.3' + testImplementation 'org.awaitility:awaitility:4.2.0' + testImplementation 'org.hamcrest:hamcrest:2.2' +} \ No newline at end of file diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/AccountId.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/AccountId.java new file mode 100644 index 00000000..c048a954 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/AccountId.java @@ -0,0 +1,16 @@ +package com.strategyobject.substrateclient.rpc.api; + +import com.strategyobject.substrateclient.common.types.FixedBytes; +import com.strategyobject.substrateclient.common.types.Size; +import lombok.NonNull; + +public class AccountId extends FixedBytes { + + protected AccountId(byte[] data) { + super(data, Size.of32); + } + + public static AccountId fromBytes(byte @NonNull [] data) { + return new AccountId(data); + } +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/AccountIdEncoder.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/AccountIdEncoder.java new file mode 100644 index 00000000..2caf6528 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/AccountIdEncoder.java @@ -0,0 +1,25 @@ +package com.strategyobject.substrateclient.rpc.api; + +import com.google.common.base.Preconditions; +import com.strategyobject.substrateclient.crypto.ss58.SS58Codec; +import com.strategyobject.substrateclient.rpc.EncoderPair; +import com.strategyobject.substrateclient.rpc.RpcEncoder; +import com.strategyobject.substrateclient.rpc.annotation.AutoRegister; +import com.strategyobject.substrateclient.rpc.context.RpcEncoderContext; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@AutoRegister(types = AccountId.class) +public class AccountIdEncoder implements RpcEncoder { + private final @NonNull RpcEncoderContext rpcEncoderContext; + + @Override + public Object encode(AccountId source, EncoderPair... encoders) { + Preconditions.checkArgument(encoders == null || encoders.length == 0); + + return SS58Codec.encode( + source.getBytes(), + rpcEncoderContext.getMetadataProvider().getSS58AddressFormat()); + } +} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/AccountIdReader.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/AccountIdReader.java similarity index 77% rename from rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/AccountIdReader.java rename to rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/AccountIdReader.java index 9d7eff1d..a5e0690b 100644 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/AccountIdReader.java +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/AccountIdReader.java @@ -1,10 +1,10 @@ -package com.strategyobject.substrateclient.rpc.types; +package com.strategyobject.substrateclient.rpc.api; import com.google.common.base.Preconditions; import com.strategyobject.substrateclient.common.io.Streamer; +import com.strategyobject.substrateclient.common.types.Size; import com.strategyobject.substrateclient.scale.ScaleReader; -import com.strategyobject.substrateclient.scale.annotations.AutoRegister; -import com.strategyobject.substrateclient.types.Size; +import com.strategyobject.substrateclient.scale.annotation.AutoRegister; import lombok.NonNull; import java.io.IOException; diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/AdditionalExtra.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/AdditionalExtra.java new file mode 100644 index 00000000..9b84fd1a --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/AdditionalExtra.java @@ -0,0 +1,4 @@ +package com.strategyobject.substrateclient.rpc.api; + +public interface AdditionalExtra { +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Address.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Address.java new file mode 100644 index 00000000..844dcf2c --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Address.java @@ -0,0 +1,5 @@ +package com.strategyobject.substrateclient.rpc.api; + +public interface Address { + AddressKind getKind(); +} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/AddressId.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/AddressId.java similarity index 77% rename from rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/AddressId.java rename to rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/AddressId.java index 1e82b8fe..610b1c8b 100644 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/AddressId.java +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/AddressId.java @@ -1,6 +1,6 @@ -package com.strategyobject.substrateclient.rpc.types; +package com.strategyobject.substrateclient.rpc.api; -import com.strategyobject.substrateclient.scale.annotations.ScaleWriter; +import com.strategyobject.substrateclient.scale.annotation.ScaleWriter; import lombok.Getter; import lombok.NonNull; diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/AddressKind.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/AddressKind.java new file mode 100644 index 00000000..375a9647 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/AddressKind.java @@ -0,0 +1,8 @@ +package com.strategyobject.substrateclient.rpc.api; + +import com.strategyobject.substrateclient.scale.annotation.ScaleWriter; + +@ScaleWriter +public enum AddressKind { + ID +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/BalanceStatus.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/BalanceStatus.java new file mode 100644 index 00000000..1e8dfb15 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/BalanceStatus.java @@ -0,0 +1,19 @@ +package com.strategyobject.substrateclient.rpc.api; + +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; + +/** + * Status of funds. + */ +@ScaleReader +public enum BalanceStatus { + /** + * Funds are free, as corresponding to `free` item in Balances. + */ + FREE, + + /** + * Funds are reserved, as corresponding to `reserved` item in Balances. + */ + RESERVED +} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Block.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Block.java similarity index 63% rename from rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Block.java rename to rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Block.java index 65171ccc..bf1c2b56 100644 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Block.java +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Block.java @@ -1,6 +1,6 @@ -package com.strategyobject.substrateclient.rpc.types; +package com.strategyobject.substrateclient.rpc.api; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcDecoder; +import com.strategyobject.substrateclient.rpc.annotation.RpcDecoder; import lombok.Getter; import lombok.Setter; diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/BytesDecoder.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/BytesDecoder.java new file mode 100644 index 00000000..bb7b8d17 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/BytesDecoder.java @@ -0,0 +1,16 @@ +package com.strategyobject.substrateclient.rpc.api; + +import com.strategyobject.substrateclient.common.types.Bytes; +import com.strategyobject.substrateclient.common.convert.HexConverter; +import com.strategyobject.substrateclient.rpc.DecoderPair; +import com.strategyobject.substrateclient.rpc.annotation.AutoRegister; +import com.strategyobject.substrateclient.rpc.decoders.AbstractDecoder; +import com.strategyobject.substrateclient.transport.RpcObject; + +@AutoRegister(types = Bytes.class) +public class BytesDecoder extends AbstractDecoder { + @Override + protected Bytes decodeNonNull(RpcObject value, DecoderPair[] decoders) { + return () -> HexConverter.toBytes(value.asString()); + } +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/BytesEncoder.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/BytesEncoder.java new file mode 100644 index 00000000..7d816e74 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/BytesEncoder.java @@ -0,0 +1,27 @@ +package com.strategyobject.substrateclient.rpc.api; + +import com.google.common.base.Preconditions; +import com.strategyobject.substrateclient.common.types.Bytes; +import com.strategyobject.substrateclient.common.convert.HexConverter; +import com.strategyobject.substrateclient.rpc.EncoderPair; +import com.strategyobject.substrateclient.rpc.RpcEncoder; +import com.strategyobject.substrateclient.rpc.annotation.AutoRegister; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockHash; +import com.strategyobject.substrateclient.rpc.api.primitives.Hash; +import com.strategyobject.substrateclient.rpc.api.primitives.Hash256; + +@AutoRegister( + types = { + Bytes.class, + Hash256.class, + Hash.class, + BlockHash.class + }) +public class BytesEncoder implements RpcEncoder { + @Override + public Object encode(Bytes source, EncoderPair... encoders) { + Preconditions.checkArgument(encoders == null || encoders.length == 0); + + return HexConverter.toHex(source.getBytes()); + } +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Call.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Call.java new file mode 100644 index 00000000..7c8541aa --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Call.java @@ -0,0 +1,4 @@ +package com.strategyobject.substrateclient.rpc.api; + +public interface Call { +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Era.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Era.java new file mode 100644 index 00000000..9697bdd5 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Era.java @@ -0,0 +1,4 @@ +package com.strategyobject.substrateclient.rpc.api; + +public interface Era { +} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/EraKind.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/EraKind.java similarity index 78% rename from rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/EraKind.java rename to rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/EraKind.java index 64191a8f..84bb35d7 100644 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/EraKind.java +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/EraKind.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.rpc.types; +package com.strategyobject.substrateclient.rpc.api; import lombok.Getter; diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Extra.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Extra.java new file mode 100644 index 00000000..64c450aa --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Extra.java @@ -0,0 +1,4 @@ +package com.strategyobject.substrateclient.rpc.api; + +public interface Extra { +} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Extrinsic.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Extrinsic.java similarity index 71% rename from rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Extrinsic.java rename to rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Extrinsic.java index 7675f54f..fdb72166 100644 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Extrinsic.java +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Extrinsic.java @@ -1,14 +1,11 @@ -package com.strategyobject.substrateclient.rpc.types; +package com.strategyobject.substrateclient.rpc.api; -import com.strategyobject.substrateclient.scale.ScaleSelfWritable; import lombok.Getter; import java.util.Optional; -// ScaleWriter must be overridden. It must be represented in hex string as a byte array of scale. @Getter -public class Extrinsic - implements ScaleSelfWritable> { +public class Extrinsic { private final Optional> signature; private final C call; diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/ExtrinsicStatus.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/ExtrinsicStatus.java similarity index 74% rename from rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/ExtrinsicStatus.java rename to rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/ExtrinsicStatus.java index fd221449..78fd0e70 100644 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/ExtrinsicStatus.java +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/ExtrinsicStatus.java @@ -1,7 +1,8 @@ -package com.strategyobject.substrateclient.rpc.types; +package com.strategyobject.substrateclient.rpc.api; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcDecoder; -import com.strategyobject.substrateclient.scale.annotations.Scale; +import com.strategyobject.substrateclient.rpc.annotation.RpcDecoder; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockHash; +import com.strategyobject.substrateclient.scale.annotation.Scale; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -17,29 +18,29 @@ public interface ExtrinsicStatus { Status getStatus(); enum Status { - Future, - Ready, - Broadcast, - InBlock, - Retracted, - FinalityTimeout, - Finalized, - Usurped, - Dropped, - Invalid + FUTURE, + READY, + BROADCAST, + IN_BLOCK, + RETRACTED, + FINALITY_TIMEOUT, + FINALIZED, + USURPED, + DROPPED, + INVALID } class Future implements ExtrinsicStatus { @Override public Status getStatus() { - return Status.Future; + return Status.FUTURE; } } class Ready implements ExtrinsicStatus { @Override public Status getStatus() { - return Status.Ready; + return Status.READY; } } @@ -53,7 +54,7 @@ class Broadcast implements ExtrinsicStatus { @Override public Status getStatus() { - return Status.Broadcast; + return Status.BROADCAST; } } @@ -67,7 +68,7 @@ class InBlock implements ExtrinsicStatus { @Override public Status getStatus() { - return Status.InBlock; + return Status.IN_BLOCK; } } @@ -81,7 +82,7 @@ class Retracted implements ExtrinsicStatus { @Override public Status getStatus() { - return Status.Retracted; + return Status.RETRACTED; } } @@ -95,7 +96,7 @@ class FinalityTimeout implements ExtrinsicStatus { @Override public Status getStatus() { - return Status.FinalityTimeout; + return Status.FINALITY_TIMEOUT; } } @@ -109,7 +110,7 @@ class Finalized implements ExtrinsicStatus { @Override public Status getStatus() { - return Status.Finalized; + return Status.FINALIZED; } } @@ -123,21 +124,21 @@ class Usurped implements ExtrinsicStatus { @Override public Status getStatus() { - return Status.Usurped; + return Status.USURPED; } } class Dropped implements ExtrinsicStatus { @Override public Status getStatus() { - return Status.Dropped; + return Status.DROPPED; } } class Invalid implements ExtrinsicStatus { @Override public Status getStatus() { - return Status.Invalid; + return Status.INVALID; } } } diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/ExtrinsicStatusRpcDecoder.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/ExtrinsicStatusDecoder.java similarity index 69% rename from rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/ExtrinsicStatusRpcDecoder.java rename to rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/ExtrinsicStatusDecoder.java index bccbb99c..52437ecf 100644 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/ExtrinsicStatusRpcDecoder.java +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/ExtrinsicStatusDecoder.java @@ -1,20 +1,25 @@ -package com.strategyobject.substrateclient.rpc.types; +package com.strategyobject.substrateclient.rpc.api; -import com.strategyobject.substrateclient.rpc.core.DecoderPair; -import com.strategyobject.substrateclient.rpc.core.annotations.AutoRegister; -import com.strategyobject.substrateclient.rpc.core.decoders.AbstractDecoder; -import com.strategyobject.substrateclient.rpc.core.registries.RpcDecoderRegistry; +import com.strategyobject.substrateclient.rpc.DecoderPair; +import com.strategyobject.substrateclient.rpc.annotation.AutoRegister; +import com.strategyobject.substrateclient.rpc.context.RpcDecoderContext; +import com.strategyobject.substrateclient.rpc.decoders.AbstractDecoder; import com.strategyobject.substrateclient.transport.RpcObject; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; import java.util.HashMap; import java.util.Map; import java.util.Optional; @AutoRegister(types = ExtrinsicStatus.class) -public class ExtrinsicStatusRpcDecoder extends AbstractDecoder { +@RequiredArgsConstructor +public class ExtrinsicStatusDecoder extends AbstractDecoder { private static final Map STATUS_TO_VALUE = new HashMap<>(); private static final Map> STATUS_TO_CLASS = new HashMap<>(); + private final @NonNull RpcDecoderContext rpcDecoderContext; + static { STATUS_TO_VALUE.put("future", ExtrinsicStatus.Future); STATUS_TO_VALUE.put("ready", ExtrinsicStatus.Ready); @@ -35,14 +40,11 @@ protected ExtrinsicStatus decodeNonNull(RpcObject value, DecoderPair[] decode if (value.isString()) { decoded = Optional.ofNullable(STATUS_TO_VALUE.get(value.asString())); } else if (value.isMap()) { - decoded = (value.asMap()).entrySet().stream() + decoded = (value.asMap()).entrySet() + .stream() .filter(e -> STATUS_TO_CLASS.containsKey(e.getKey())) .findFirst() - .map(e -> - (ExtrinsicStatus) RpcDecoderRegistry.getInstance() - .resolve(STATUS_TO_CLASS.get(e.getKey())) - .decode(value) - ); + .map(e -> (ExtrinsicStatus) rpcDecoderContext.getRpcDecoderRegistry().resolve(STATUS_TO_CLASS.get(e.getKey())).decode(value)); } else { decoded = Optional.empty(); } diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/ExtrinsicWriter.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/ExtrinsicWriter.java new file mode 100644 index 00000000..9b39473e --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/ExtrinsicWriter.java @@ -0,0 +1,59 @@ +package com.strategyobject.substrateclient.rpc.api; + +import com.google.common.base.Preconditions; +import com.strategyobject.substrateclient.scale.ScaleDispatch; +import com.strategyobject.substrateclient.scale.ScaleType; +import com.strategyobject.substrateclient.scale.ScaleWriter; +import com.strategyobject.substrateclient.scale.annotation.AutoRegister; +import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; +import com.strategyobject.substrateclient.scale.writers.ByteArrayWriter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.val; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +@AutoRegister(types = Extrinsic.class) +@RequiredArgsConstructor +public class ExtrinsicWriter + implements ScaleWriter> { + private static final int VERSION = 4; + + private final @NonNull ScaleWriterRegistry registry; + + @Override + public void write(@NonNull Extrinsic value, + @NonNull OutputStream stream, + ScaleWriter... writers) throws IOException { + Preconditions.checkArgument(writers == null || writers.length == 0); + + val encodedExtrinsic = new ByteArrayOutputStream(); + writeExtrinsic(value, encodedExtrinsic); + wrapToVec(encodedExtrinsic, stream); + } + + private void wrapToVec(ByteArrayOutputStream encodedExtrinsic, OutputStream stream) throws IOException { + ((ByteArrayWriter) registry.resolve(byte[].class)).write(encodedExtrinsic.toByteArray(), stream); + } + + @SuppressWarnings("unchecked") + private void writeExtrinsic(Extrinsic value, ByteArrayOutputStream stream) throws IOException { + val u8Writer = (ScaleWriter) registry.resolve(ScaleType.U8.class); + val signature = value.getSignature(); + if (signature.isPresent()) { + u8Writer.write(VERSION | 0b1000_0000, stream); + + val dispatcher = registry.resolve(ScaleDispatch.class); + val signaturePayloadWriter = (ScaleWriter>) registry.resolve(SignaturePayload.class); + signaturePayloadWriter + .inject(dispatcher, dispatcher, dispatcher) + .write(signature.get(), stream); + } else { + u8Writer.write(VERSION & 0b0111_1111, stream); + } + + ((ScaleWriter) registry.resolve(ScaleDispatch.class)).write(value.getCall(), stream); + } +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/FixedBytesWriter.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/FixedBytesWriter.java new file mode 100644 index 00000000..299b8030 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/FixedBytesWriter.java @@ -0,0 +1,37 @@ +package com.strategyobject.substrateclient.rpc.api; + +import com.google.common.base.Preconditions; +import com.strategyobject.substrateclient.common.io.Streamer; +import com.strategyobject.substrateclient.common.types.FixedBytes; +import com.strategyobject.substrateclient.common.types.Size; +import com.strategyobject.substrateclient.crypto.PublicKey; +import com.strategyobject.substrateclient.crypto.SignatureData; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockHash; +import com.strategyobject.substrateclient.rpc.api.primitives.Hash; +import com.strategyobject.substrateclient.rpc.api.primitives.Hash256; +import com.strategyobject.substrateclient.scale.ScaleWriter; +import com.strategyobject.substrateclient.scale.annotation.AutoRegister; +import lombok.NonNull; + +import java.io.IOException; +import java.io.OutputStream; + +@AutoRegister( + types = { + AccountId.class, + Hash256.class, + Hash.class, + BlockHash.class, + PublicKey.class, + SignatureData.class + }) +public class FixedBytesWriter implements ScaleWriter> { + @Override + public void write(@NonNull FixedBytes value, + @NonNull OutputStream stream, + ScaleWriter... writers) throws IOException { + Preconditions.checkArgument(writers == null || writers.length == 0); + + Streamer.writeBytes(value.getBytes(), stream); + } +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Header.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Header.java new file mode 100644 index 00000000..635e5664 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Header.java @@ -0,0 +1,18 @@ +package com.strategyobject.substrateclient.rpc.api; + +import com.strategyobject.substrateclient.rpc.annotation.RpcDecoder; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockHash; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockNumber; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@RpcDecoder +public class Header { // TODO add rest fields + @Scale + private BlockHash parentHash; + + private BlockNumber number; +} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/ImmortalEra.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/ImmortalEra.java similarity index 53% rename from rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/ImmortalEra.java rename to rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/ImmortalEra.java index 3a16bc5e..3f279475 100644 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/ImmortalEra.java +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/ImmortalEra.java @@ -1,8 +1,8 @@ -package com.strategyobject.substrateclient.rpc.types; +package com.strategyobject.substrateclient.rpc.api; import com.strategyobject.substrateclient.scale.ScaleType; -import com.strategyobject.substrateclient.scale.annotations.Scale; -import com.strategyobject.substrateclient.scale.annotations.ScaleWriter; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleWriter; import lombok.Getter; @Getter diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Metadata.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Metadata.java new file mode 100644 index 00000000..ed9fc2a1 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Metadata.java @@ -0,0 +1,7 @@ +package com.strategyobject.substrateclient.rpc.api; + +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; + +@ScaleReader +public class Metadata { +} diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/MetadataRegistry.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/MetadataRegistry.java similarity index 94% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/MetadataRegistry.java rename to rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/MetadataRegistry.java index 006a8e58..eff13374 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/MetadataRegistry.java +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/MetadataRegistry.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.rpc.core; +package com.strategyobject.substrateclient.rpc.api; import java.util.concurrent.atomic.AtomicReference; diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/MortalEra.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/MortalEra.java similarity index 59% rename from rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/MortalEra.java rename to rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/MortalEra.java index 18972730..f122e342 100644 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/MortalEra.java +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/MortalEra.java @@ -1,8 +1,8 @@ -package com.strategyobject.substrateclient.rpc.types; +package com.strategyobject.substrateclient.rpc.api; import com.strategyobject.substrateclient.scale.ScaleType; -import com.strategyobject.substrateclient.scale.annotations.Scale; -import com.strategyobject.substrateclient.scale.annotations.ScaleWriter; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleWriter; import lombok.Getter; @Getter diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/RuntimeVersion.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/RuntimeVersion.java new file mode 100644 index 00000000..204ae8c7 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/RuntimeVersion.java @@ -0,0 +1,7 @@ +package com.strategyobject.substrateclient.rpc.api; + +import com.strategyobject.substrateclient.rpc.annotation.RpcDecoder; + +@RpcDecoder +public class RuntimeVersion { +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Signature.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Signature.java new file mode 100644 index 00000000..8a646db9 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Signature.java @@ -0,0 +1,5 @@ +package com.strategyobject.substrateclient.rpc.api; + +public interface Signature { + SignatureKind getKind(); +} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/SignatureKind.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignatureKind.java similarity index 81% rename from rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/SignatureKind.java rename to rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignatureKind.java index 64fc5d62..8b4e6e82 100644 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/SignatureKind.java +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignatureKind.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.rpc.types; +package com.strategyobject.substrateclient.rpc.api; import lombok.Getter; diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/SignatureKindScaleWriter.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignatureKindWriter.java similarity index 58% rename from rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/SignatureKindScaleWriter.java rename to rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignatureKindWriter.java index 46e5c0db..029b0cca 100644 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/SignatureKindScaleWriter.java +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignatureKindWriter.java @@ -1,21 +1,25 @@ -package com.strategyobject.substrateclient.rpc.types; +package com.strategyobject.substrateclient.rpc.api; import com.google.common.base.Preconditions; import com.strategyobject.substrateclient.scale.ScaleWriter; -import com.strategyobject.substrateclient.scale.annotations.AutoRegister; +import com.strategyobject.substrateclient.scale.annotation.AutoRegister; import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; import lombok.NonNull; +import lombok.RequiredArgsConstructor; import java.io.IOException; import java.io.OutputStream; @AutoRegister(types = SignatureKind.class) -public class SignatureKindScaleWriter implements ScaleWriter { +@RequiredArgsConstructor +public class SignatureKindWriter implements ScaleWriter { + private final @NonNull ScaleWriterRegistry registry; + @Override @SuppressWarnings("unchecked") public void write(@NonNull SignatureKind value, @NonNull OutputStream stream, ScaleWriter... writers) throws IOException { Preconditions.checkArgument(writers == null || writers.length == 0); - ((ScaleWriter) ScaleWriterRegistry.getInstance().resolve(byte.class)).write(value.getValue(), stream); + ((ScaleWriter) registry.resolve(byte.class)).write(value.getValue(), stream); } } diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignaturePayload.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignaturePayload.java new file mode 100644 index 00000000..8e8c8af5 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignaturePayload.java @@ -0,0 +1,14 @@ +package com.strategyobject.substrateclient.rpc.api; + +import com.strategyobject.substrateclient.scale.annotation.ScaleWriter; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Getter +@ScaleWriter +public class SignaturePayload { + private final A address; + private final S signature; + private final E extra; +} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/SignedAdditionalExtra.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignedAdditionalExtra.java similarity index 72% rename from rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/SignedAdditionalExtra.java rename to rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignedAdditionalExtra.java index 7bac64aa..9048ccc8 100644 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/SignedAdditionalExtra.java +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignedAdditionalExtra.java @@ -1,8 +1,9 @@ -package com.strategyobject.substrateclient.rpc.types; +package com.strategyobject.substrateclient.rpc.api; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockHash; import com.strategyobject.substrateclient.scale.ScaleType; -import com.strategyobject.substrateclient.scale.annotations.Scale; -import com.strategyobject.substrateclient.scale.annotations.ScaleWriter; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleWriter; import lombok.Getter; import lombok.NonNull; diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/SignedBlock.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignedBlock.java similarity index 54% rename from rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/SignedBlock.java rename to rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignedBlock.java index 9bb676ca..81312918 100644 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/SignedBlock.java +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignedBlock.java @@ -1,6 +1,6 @@ -package com.strategyobject.substrateclient.rpc.types; +package com.strategyobject.substrateclient.rpc.api; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcDecoder; +import com.strategyobject.substrateclient.rpc.annotation.RpcDecoder; import lombok.Getter; import lombok.Setter; diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/SignedExtension.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignedExtension.java similarity index 59% rename from rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/SignedExtension.java rename to rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignedExtension.java index e490e395..fb7638c0 100644 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/SignedExtension.java +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignedExtension.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.rpc.types; +package com.strategyobject.substrateclient.rpc.api; public interface SignedExtension { AdditionalExtra getAdditionalExtra(); diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/SignedExtra.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignedExtra.java similarity index 67% rename from rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/SignedExtra.java rename to rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignedExtra.java index 04ad7c3b..4b77207d 100644 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/SignedExtra.java +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignedExtra.java @@ -1,9 +1,10 @@ -package com.strategyobject.substrateclient.rpc.types; +package com.strategyobject.substrateclient.rpc.api; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockHash; +import com.strategyobject.substrateclient.rpc.api.primitives.Index; import com.strategyobject.substrateclient.scale.ScaleType; -import com.strategyobject.substrateclient.scale.annotations.Ignore; -import com.strategyobject.substrateclient.scale.annotations.Scale; -import com.strategyobject.substrateclient.scale.annotations.ScaleWriter; +import com.strategyobject.substrateclient.scale.annotation.Ignore; +import com.strategyobject.substrateclient.scale.annotation.Scale; import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -11,7 +12,6 @@ @RequiredArgsConstructor @Getter -@ScaleWriter public class SignedExtra implements Extra, SignedExtension { @Ignore private final long specVersion; @@ -22,8 +22,7 @@ public class SignedExtra implements Extra, SignedExtension { @Ignore private final BlockHash eraBlock; private final E era; - @Scale(ScaleType.CompactBigInteger.class) - private final BigInteger nonce; + private final Index nonce; @Scale(ScaleType.CompactBigInteger.class) private final BigInteger tip; diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignedExtraWriter.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignedExtraWriter.java new file mode 100644 index 00000000..33972480 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignedExtraWriter.java @@ -0,0 +1,33 @@ +package com.strategyobject.substrateclient.rpc.api; + +import com.google.common.base.Preconditions; +import com.strategyobject.substrateclient.rpc.api.primitives.Index; +import com.strategyobject.substrateclient.scale.ScaleDispatch; +import com.strategyobject.substrateclient.scale.ScaleType; +import com.strategyobject.substrateclient.scale.ScaleWriter; +import com.strategyobject.substrateclient.scale.annotation.AutoRegister; +import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.val; + +import java.io.IOException; +import java.io.OutputStream; +import java.math.BigInteger; + +@AutoRegister(types = com.strategyobject.substrateclient.rpc.api.SignedExtra.class) +@RequiredArgsConstructor +public class SignedExtraWriter implements ScaleWriter> { + private final @NonNull ScaleWriterRegistry registry; + + @Override + @SuppressWarnings({"unchecked"}) + public void write(@NonNull SignedExtra value, @NonNull OutputStream stream, ScaleWriter... writers) throws IOException { + Preconditions.checkArgument(writers == null || writers.length == 0); + + val dispatcher = registry.resolve(ScaleDispatch.class); + ((ScaleWriter) dispatcher).write(value.getEra(), stream); + ((ScaleWriter) registry.resolve(Index.class)).write(value.getNonce(), stream); + ((ScaleWriter) registry.resolve(ScaleType.CompactBigInteger.class)).write(value.getTip(), stream); + } +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignedPayload.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignedPayload.java new file mode 100644 index 00000000..8c60d298 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignedPayload.java @@ -0,0 +1,11 @@ +package com.strategyobject.substrateclient.rpc.api; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Getter +public class SignedPayload { + private final C call; + private final E extra; +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignedPayloadWriter.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignedPayloadWriter.java new file mode 100644 index 00000000..7c5ea55c --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/SignedPayloadWriter.java @@ -0,0 +1,30 @@ +package com.strategyobject.substrateclient.rpc.api; + +import com.google.common.base.Preconditions; +import com.strategyobject.substrateclient.scale.ScaleDispatch; +import com.strategyobject.substrateclient.scale.ScaleWriter; +import com.strategyobject.substrateclient.scale.annotation.AutoRegister; +import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.val; + +import java.io.IOException; +import java.io.OutputStream; + +@RequiredArgsConstructor +@AutoRegister(types = SignedPayload.class) +public class SignedPayloadWriter implements ScaleWriter> { + private final @NonNull ScaleWriterRegistry registry; + + @SuppressWarnings("unchecked") + @Override + public void write(@NonNull SignedPayload value, @NonNull OutputStream stream, ScaleWriter... writers) throws IOException { + Preconditions.checkArgument(writers == null || writers.length == 0); + + val dispatcher = registry.resolve(ScaleDispatch.class); + ((ScaleWriter) dispatcher).write(value.getCall(), stream); + ((ScaleWriter) dispatcher).write(value.getExtra(), stream); + ((ScaleWriter) dispatcher).write(value.getExtra().getAdditionalExtra(), stream); + } +} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Sr25519Signature.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Sr25519Signature.java similarity index 75% rename from rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Sr25519Signature.java rename to rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Sr25519Signature.java index 3d8039a6..957676a2 100644 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Sr25519Signature.java +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/Sr25519Signature.java @@ -1,7 +1,7 @@ -package com.strategyobject.substrateclient.rpc.types; +package com.strategyobject.substrateclient.rpc.api; -import com.strategyobject.substrateclient.scale.annotations.ScaleWriter; -import com.strategyobject.substrateclient.types.SignatureData; +import com.strategyobject.substrateclient.crypto.SignatureData; +import com.strategyobject.substrateclient.scale.annotation.ScaleWriter; import lombok.Getter; import lombok.NonNull; diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/AccountIndex.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/AccountIndex.java new file mode 100644 index 00000000..7a40ed5b --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/AccountIndex.java @@ -0,0 +1,23 @@ +package com.strategyobject.substrateclient.rpc.api.primitives; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.math.BigInteger; + +/** + * Index of an account. + */ +@RequiredArgsConstructor(staticName = "of") +@Getter +@EqualsAndHashCode +public class AccountIndex { + public static final AccountIndex ZERO = AccountIndex.of(BigInteger.ZERO); + + private final BigInteger value; + + public static AccountIndex of(long value) { + return of(BigInteger.valueOf(value)); + } +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/AccountIndexU32Reader.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/AccountIndexU32Reader.java new file mode 100644 index 00000000..fd1ed428 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/AccountIndexU32Reader.java @@ -0,0 +1,28 @@ +package com.strategyobject.substrateclient.rpc.api.primitives; + +import com.google.common.base.Preconditions; +import com.strategyobject.substrateclient.scale.ScaleReader; +import com.strategyobject.substrateclient.scale.ScaleType; +import com.strategyobject.substrateclient.scale.annotation.AutoRegister; +import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.val; + +import java.io.IOException; +import java.io.InputStream; + +@AutoRegister(types = AccountIndex.class) +@RequiredArgsConstructor +public class AccountIndexU32Reader implements ScaleReader { + private final @NonNull ScaleReaderRegistry registry; + + @SuppressWarnings("unchecked") + @Override + public AccountIndex read(@NonNull InputStream stream, ScaleReader... readers) throws IOException { + Preconditions.checkArgument(readers == null || readers.length == 0); + + val u32Reader = (ScaleReader) registry.resolve(ScaleType.U32.class); + return AccountIndex.of(u32Reader.read(stream)); + } +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/Balance.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/Balance.java new file mode 100644 index 00000000..7a5790f4 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/Balance.java @@ -0,0 +1,19 @@ +package com.strategyobject.substrateclient.rpc.api.primitives; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.math.BigInteger; + +/** + * Balance of an account. + */ +@RequiredArgsConstructor(staticName = "of") +@Getter +@EqualsAndHashCode +public class Balance { + public static final Balance ZERO = Balance.of(BigInteger.ZERO); + + private final BigInteger value; +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/BalanceU128Reader.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/BalanceU128Reader.java new file mode 100644 index 00000000..65ba32e8 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/BalanceU128Reader.java @@ -0,0 +1,29 @@ +package com.strategyobject.substrateclient.rpc.api.primitives; + +import com.google.common.base.Preconditions; +import com.strategyobject.substrateclient.scale.ScaleReader; +import com.strategyobject.substrateclient.scale.ScaleType; +import com.strategyobject.substrateclient.scale.annotation.AutoRegister; +import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.val; + +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; + +@AutoRegister(types = Balance.class) +@RequiredArgsConstructor +public class BalanceU128Reader implements ScaleReader { + private final @NonNull ScaleReaderRegistry registry; + + @SuppressWarnings("unchecked") + @Override + public Balance read(@NonNull InputStream stream, ScaleReader... readers) throws IOException { + Preconditions.checkArgument(readers == null || readers.length == 0); + + val u128Reader = (ScaleReader) registry.resolve(ScaleType.U128.class); + return Balance.of(u128Reader.read(stream)); + } +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/BlockHash.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/BlockHash.java new file mode 100644 index 00000000..798df230 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/BlockHash.java @@ -0,0 +1,4 @@ +package com.strategyobject.substrateclient.rpc.api.primitives; + +public interface BlockHash extends Hash { +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/BlockNumber.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/BlockNumber.java new file mode 100644 index 00000000..1b276a82 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/BlockNumber.java @@ -0,0 +1,23 @@ +package com.strategyobject.substrateclient.rpc.api.primitives; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.math.BigInteger; + +/** + * An index of a block. + */ +@RequiredArgsConstructor(staticName = "of") +@Getter +@EqualsAndHashCode +public class BlockNumber { + public static final BlockNumber GENESIS = BlockNumber.of(BigInteger.ZERO); + + private final BigInteger value; + + public static BlockNumber of(long value) { + return of(BigInteger.valueOf(value)); + } +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/BlockNumberDecoder.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/BlockNumberDecoder.java new file mode 100644 index 00000000..8595e1a3 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/BlockNumberDecoder.java @@ -0,0 +1,20 @@ +package com.strategyobject.substrateclient.rpc.api.primitives; + +import com.strategyobject.substrateclient.rpc.DecoderPair; +import com.strategyobject.substrateclient.rpc.annotation.AutoRegister; +import com.strategyobject.substrateclient.rpc.decoders.AbstractDecoder; +import com.strategyobject.substrateclient.transport.RpcObject; +import lombok.val; + +import java.math.BigInteger; + +@AutoRegister(types = BlockNumber.class) +public class BlockNumberDecoder extends AbstractDecoder { + @Override + protected BlockNumber decodeNonNull(RpcObject value, DecoderPair[] decoders) { + val stringValue = value.asString(); + val number = new BigInteger(stringValue.substring(2), 16); + + return BlockNumber.of(number); + } +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/BlockNumberEncoder.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/BlockNumberEncoder.java new file mode 100644 index 00000000..623456db --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/BlockNumberEncoder.java @@ -0,0 +1,14 @@ +package com.strategyobject.substrateclient.rpc.api.primitives; + +import com.strategyobject.substrateclient.rpc.EncoderPair; +import com.strategyobject.substrateclient.rpc.RpcEncoder; +import com.strategyobject.substrateclient.rpc.annotation.AutoRegister; + +@AutoRegister(types = BlockNumber.class) +public class BlockNumberEncoder implements RpcEncoder { + + @Override + public Object encode(BlockNumber source, EncoderPair... encoders) { + return "0x" + source.getValue().toString(16); + } +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/BlockNumberU32Reader.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/BlockNumberU32Reader.java new file mode 100644 index 00000000..8ca213d2 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/BlockNumberU32Reader.java @@ -0,0 +1,28 @@ +package com.strategyobject.substrateclient.rpc.api.primitives; + +import com.google.common.base.Preconditions; +import com.strategyobject.substrateclient.scale.ScaleReader; +import com.strategyobject.substrateclient.scale.ScaleType; +import com.strategyobject.substrateclient.scale.annotation.AutoRegister; +import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.val; + +import java.io.IOException; +import java.io.InputStream; + +@AutoRegister(types = BlockNumber.class) +@RequiredArgsConstructor +public class BlockNumberU32Reader implements ScaleReader { + private final @NonNull ScaleReaderRegistry registry; + + @SuppressWarnings("unchecked") + @Override + public BlockNumber read(@NonNull InputStream stream, ScaleReader... readers) throws IOException { + Preconditions.checkArgument(readers == null || readers.length == 0); + + val u32Reader = (ScaleReader) registry.resolve(ScaleType.U32.class); + return BlockNumber.of(u32Reader.read(stream)); + } +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/BlockNumberU32Writer.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/BlockNumberU32Writer.java new file mode 100644 index 00000000..18818788 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/BlockNumberU32Writer.java @@ -0,0 +1,26 @@ +package com.strategyobject.substrateclient.rpc.api.primitives; + +import com.google.common.base.Preconditions; +import com.strategyobject.substrateclient.scale.ScaleType; +import com.strategyobject.substrateclient.scale.ScaleWriter; +import com.strategyobject.substrateclient.scale.annotation.AutoRegister; +import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; + +import java.io.IOException; +import java.io.OutputStream; + +@AutoRegister(types = BlockNumber.class) +@RequiredArgsConstructor +public class BlockNumberU32Writer implements ScaleWriter { + private final @NonNull ScaleWriterRegistry registry; + + @SuppressWarnings("unchecked") + @Override + public void write(@NonNull BlockNumber value, @NonNull OutputStream stream, ScaleWriter... writers) throws IOException { + Preconditions.checkArgument(writers == null || writers.length == 0); + + ((ScaleWriter) registry.resolve(ScaleType.U32.class)).write(value.getValue().longValue(), stream); + } +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/CallHash.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/CallHash.java new file mode 100644 index 00000000..af6477e8 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/CallHash.java @@ -0,0 +1,4 @@ +package com.strategyobject.substrateclient.rpc.api.primitives; + +public interface CallHash extends Hash { +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/Hash.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/Hash.java new file mode 100644 index 00000000..b067ff23 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/Hash.java @@ -0,0 +1,11 @@ +package com.strategyobject.substrateclient.rpc.api.primitives; + +import com.strategyobject.substrateclient.common.types.Bytes; +import lombok.NonNull; + +/** + * A hash of some data used by the chain. + */ +public interface Hash extends Bytes { + byte @NonNull [] getBytes(); +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/Hash256.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/Hash256.java new file mode 100644 index 00000000..ffbe0857 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/Hash256.java @@ -0,0 +1,15 @@ +package com.strategyobject.substrateclient.rpc.api.primitives; + +import com.strategyobject.substrateclient.common.types.FixedBytes; +import com.strategyobject.substrateclient.common.types.Size; +import lombok.NonNull; + +public class Hash256 extends FixedBytes implements Hash, BlockHash, CallHash { + private Hash256(byte[] data) { + super(data, Size.of32); + } + + public static Hash256 fromBytes(byte @NonNull [] data) { + return new Hash256(data); + } +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/Hash256Decoder.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/Hash256Decoder.java new file mode 100644 index 00000000..d1f0e6cb --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/Hash256Decoder.java @@ -0,0 +1,15 @@ +package com.strategyobject.substrateclient.rpc.api.primitives; + +import com.strategyobject.substrateclient.common.convert.HexConverter; +import com.strategyobject.substrateclient.rpc.DecoderPair; +import com.strategyobject.substrateclient.rpc.annotation.AutoRegister; +import com.strategyobject.substrateclient.rpc.decoders.AbstractDecoder; +import com.strategyobject.substrateclient.transport.RpcObject; + +@AutoRegister(types = {Hash256.class, Hash.class, BlockHash.class, CallHash.class}) +public class Hash256Decoder extends AbstractDecoder { + @Override + protected Hash256 decodeNonNull(RpcObject value, DecoderPair[] decoders) { + return Hash256.fromBytes(HexConverter.toBytes(value.asString())); + } +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/Hash256Reader.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/Hash256Reader.java new file mode 100644 index 00000000..7e4d6ad1 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/Hash256Reader.java @@ -0,0 +1,21 @@ +package com.strategyobject.substrateclient.rpc.api.primitives; + +import com.google.common.base.Preconditions; +import com.strategyobject.substrateclient.common.io.Streamer; +import com.strategyobject.substrateclient.common.types.Size; +import com.strategyobject.substrateclient.scale.ScaleReader; +import com.strategyobject.substrateclient.scale.annotation.AutoRegister; +import lombok.NonNull; + +import java.io.IOException; +import java.io.InputStream; + +@AutoRegister(types = {Hash256.class, Hash.class, BlockHash.class, CallHash.class}) +public class Hash256Reader implements ScaleReader { + @Override + public Hash256 read(@NonNull InputStream stream, ScaleReader... readers) throws IOException { + Preconditions.checkArgument(readers == null || readers.length == 0); + + return Hash256.fromBytes(Streamer.readBytes(Size.of32.getValue(), stream)); + } +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/Index.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/Index.java new file mode 100644 index 00000000..ef7c1639 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/Index.java @@ -0,0 +1,28 @@ +package com.strategyobject.substrateclient.rpc.api.primitives; + +import com.strategyobject.substrateclient.scale.ScaleType; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleWriter; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.math.BigInteger; + +/** + * Index of a transaction in the chain. + */ +@RequiredArgsConstructor(staticName = "of") +@Getter +@EqualsAndHashCode +@ScaleWriter +public class Index { + public static final Index ZERO = Index.of(BigInteger.ZERO); + + @Scale(ScaleType.CompactBigInteger.class) + private final BigInteger value; + + public static Index of(long value) { + return of(BigInteger.valueOf(value)); + } +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/IndexDecoder.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/IndexDecoder.java new file mode 100644 index 00000000..f431fa76 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/primitives/IndexDecoder.java @@ -0,0 +1,14 @@ +package com.strategyobject.substrateclient.rpc.api.primitives; + +import com.strategyobject.substrateclient.rpc.DecoderPair; +import com.strategyobject.substrateclient.rpc.annotation.AutoRegister; +import com.strategyobject.substrateclient.rpc.decoders.AbstractDecoder; +import com.strategyobject.substrateclient.transport.RpcObject; + +@AutoRegister(types = Index.class) +public class IndexDecoder extends AbstractDecoder { + @Override + protected Index decodeNonNull(RpcObject value, DecoderPair[] decoders) { + return Index.of(value.asNumber().longValue()); + } +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/runtime/ArithmeticError.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/runtime/ArithmeticError.java new file mode 100644 index 00000000..3390f051 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/runtime/ArithmeticError.java @@ -0,0 +1,24 @@ +package com.strategyobject.substrateclient.rpc.api.runtime; + +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; + +/** + * Arithmetic errors. + */ +@ScaleReader +public enum ArithmeticError { + /** + * / Underflow. + */ + UNDERFLOW, + + /** + * / Overflow. + */ + OVERFLOW, + + /** + * / Division by zero. + */ + DIVISION_BY_ZERO +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/runtime/DispatchError.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/runtime/DispatchError.java new file mode 100644 index 00000000..d79cf424 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/runtime/DispatchError.java @@ -0,0 +1,144 @@ +package com.strategyobject.substrateclient.rpc.api.runtime; + +import com.google.common.base.Preconditions; +import com.strategyobject.substrateclient.common.types.union.Union; + +/** + * Reason why a dispatch call failed. + */ +public class DispatchError extends Union { + + private DispatchError() { + } + + /** + * @return true if some error occurred + */ + public boolean isOther() { + return index == 0; + } + + /** + * @return true if failed to lookup some data + */ + public boolean isCannotLookup() { + return index == 1; + } + + /** + * @return true if is a bad origin + */ + public boolean isBadOrigin() { + return index == 2; + } + + /** + * @return true if is a custom error in a module + */ + public boolean isModule() { + return index == 3; + } + + /** + * @return true if at least one consumer is remaining so the account cannot be destroyed + */ + public boolean isConsumerRemaining() { + return index == 4; + } + + /** + * @return true if there are no providers so the account cannot be created + */ + public boolean isNoProviders() { + return index == 5; + } + + /** + * @return true if is an error to do with tokens + */ + public boolean isToken() { + return index == 6; + } + + /** + * @return true if is an arithmetic error + */ + public boolean isArithmetic() { + return index == 7; + } + + /** + * @return module error + */ + public ModuleError getModuleError() { + Preconditions.checkState(index == 3); + return (ModuleError) value; + } + + /** + * @return token error + */ + public TokenError getTokenError() { + Preconditions.checkState(index == 6); + return (TokenError) value; + } + + /** + * @return arithmetic error + */ + public ArithmeticError getArithmeticError() { + Preconditions.checkState(index == 7); + return (ArithmeticError) value; + } + + public static DispatchError ofOther() { + DispatchError result = new DispatchError(); + result.index = 0; + return result; + } + + public static DispatchError ofCannotLookup() { + DispatchError result = new DispatchError(); + result.index = 1; + return result; + } + + public static DispatchError ofBadOrigin() { + DispatchError result = new DispatchError(); + result.index = 2; + return result; + } + + public static DispatchError ofModule(ModuleError moduleError) { + DispatchError result = new DispatchError(); + result.value = moduleError; + result.index = 3; + return result; + } + + public static DispatchError ofConsumerRemaining() { + DispatchError result = new DispatchError(); + result.index = 4; + return result; + } + + public static DispatchError ofNoProviders() { + DispatchError result = new DispatchError(); + result.index = 5; + return result; + } + + public static DispatchError ofToken(TokenError tokenError) { + DispatchError result = new DispatchError(); + result.value = tokenError; + result.index = 6; + return result; + } + + public static DispatchError ofArithmetic(ArithmeticError arithmeticError) { + DispatchError result = new DispatchError(); + result.value = arithmeticError; + result.index = 7; + return result; + } +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/runtime/DispatchErrorReader.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/runtime/DispatchErrorReader.java new file mode 100644 index 00000000..21378c8a --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/runtime/DispatchErrorReader.java @@ -0,0 +1,41 @@ +package com.strategyobject.substrateclient.rpc.api.runtime; + +import com.google.common.base.Preconditions; +import com.strategyobject.substrateclient.scale.ScaleReader; +import com.strategyobject.substrateclient.scale.annotation.AutoRegister; +import com.strategyobject.substrateclient.scale.readers.union.BaseUnionReader; +import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; +import lombok.NonNull; +import lombok.val; + +import java.io.IOException; +import java.io.InputStream; + +@AutoRegister(types = DispatchError.class) +public class DispatchErrorReader extends BaseUnionReader { + private final ScaleReaderRegistry registry; + + public DispatchErrorReader(ScaleReaderRegistry registry) { + super(8, + x -> DispatchError.ofOther(), + x -> DispatchError.ofCannotLookup(), + x -> DispatchError.ofBadOrigin(), + x -> DispatchError.ofModule((ModuleError) x), + x -> DispatchError.ofConsumerRemaining(), + x -> DispatchError.ofNoProviders(), + x -> DispatchError.ofToken((TokenError) x), + x -> DispatchError.ofArithmetic((ArithmeticError) x)); + + this.registry = registry; + } + + @Override + public DispatchError read(@NonNull InputStream stream, ScaleReader... readers) throws IOException { + Preconditions.checkArgument(readers == null || readers.length == 0); + + val moduleErrorReader = registry.resolve(ModuleError.class); + val tokenErrorReader = registry.resolve(TokenError.class); + val arithmeticErrorReader = registry.resolve(ArithmeticError.class); + return super.read(stream, moduleErrorReader, tokenErrorReader, arithmeticErrorReader); + } +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/runtime/ModuleError.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/runtime/ModuleError.java new file mode 100644 index 00000000..d9971981 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/runtime/ModuleError.java @@ -0,0 +1,27 @@ +package com.strategyobject.substrateclient.rpc.api.runtime; + +import com.strategyobject.substrateclient.scale.ScaleType; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; +import lombok.Getter; +import lombok.Setter; + +/** + * A custom error in a module. + */ +@ScaleReader +@Getter +@Setter +public class ModuleError { + /** + * Module index, matching the metadata module index. + */ + @Scale(ScaleType.U8.class) + private Integer index; + + /** + * Module specific error value. + */ + @Scale(ScaleType.U8.class) + private Integer error; +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/runtime/TokenError.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/runtime/TokenError.java new file mode 100644 index 00000000..6fa3dc8c --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/runtime/TokenError.java @@ -0,0 +1,44 @@ +package com.strategyobject.substrateclient.rpc.api.runtime; + +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; + +/** + * Description of what went wrong when trying to complete an operation on a token. + */ +@ScaleReader +public enum TokenError { + /** + * / Funds are unavailable. + */ + NO_FUNDS, + + /** + * / Account that must exist would die. + */ + WOULD_DIE, + + /** + * / Account cannot exist with the funds that would be given. + */ + BELOW_MINIMUM, + + /** + * / Account cannot be created. + */ + CANNOT_CREATE, + + /** + * / The asset in question is unknown. + */ + UNKNOWN_ASSET, + + /** + * / Funds exist but are frozen. + */ + FROZEN, + + /** + * / Operation is not supported by the asset. + */ + UNSUPPORTED, +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/section/Author.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/section/Author.java new file mode 100644 index 00000000..cce2d675 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/section/Author.java @@ -0,0 +1,64 @@ +package com.strategyobject.substrateclient.rpc.api.section; + +import com.strategyobject.substrateclient.common.types.Bytes; +import com.strategyobject.substrateclient.rpc.annotation.RpcCall; +import com.strategyobject.substrateclient.rpc.annotation.RpcInterface; +import com.strategyobject.substrateclient.rpc.annotation.RpcSubscription; +import com.strategyobject.substrateclient.rpc.api.Extrinsic; +import com.strategyobject.substrateclient.rpc.api.ExtrinsicStatus; +import com.strategyobject.substrateclient.rpc.api.primitives.Hash; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleGeneric; + +import java.util.concurrent.CompletableFuture; +import java.util.function.BiConsumer; +import java.util.function.Supplier; + +@RpcInterface("author") +public interface Author { + + /** + * Checks if the keystore has private keys for the given public key and key type. + * + * @param publicKey public key + * @param keyType type of key + * @return `true` if a private key could be found + */ + @RpcCall("hasKey") + CompletableFuture hasKey(Bytes publicKey, String keyType); + + /** + * Insert a key into the keystore. + * + * @param keyType type of key + * @param secretUri secret uri + * @param publicKey public key + * @return void + */ + @RpcCall("insertKey") + CompletableFuture insertKey(String keyType, String secretUri, Bytes publicKey); + + /** + * Submit hex-encoded extrinsic for inclusion in block. + * + * @param extrinsic extrinsic to submit + * @return hash of extrinsic + */ + @RpcCall("submitExtrinsic") + CompletableFuture submitExtrinsic( + @ScaleGeneric(template = "Extrinsic", types = @Scale(Extrinsic.class)) + Extrinsic extrinsic); + + /** + * Submit an extrinsic to watch. + * + * @param extrinsic extrinsic to submit + * @param callback callback handler + * @return unsubscribe delegate + */ + @RpcSubscription(type = "extrinsicUpdate", subscribeMethod = "submitAndWatchExtrinsic", unsubscribeMethod = "unwatchExtrinsic") + CompletableFuture>> submitAndWatchExtrinsic( + @ScaleGeneric(template = "Extrinsic", types = @Scale(Extrinsic.class)) + Extrinsic extrinsic, + BiConsumer callback); +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/section/Chain.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/section/Chain.java new file mode 100644 index 00000000..c5b52aae --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/section/Chain.java @@ -0,0 +1,68 @@ +package com.strategyobject.substrateclient.rpc.api.section; + +import com.strategyobject.substrateclient.rpc.annotation.RpcCall; +import com.strategyobject.substrateclient.rpc.annotation.RpcInterface; +import com.strategyobject.substrateclient.rpc.annotation.RpcSubscription; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockHash; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockNumber; +import com.strategyobject.substrateclient.rpc.api.Header; +import com.strategyobject.substrateclient.rpc.api.SignedBlock; + +import java.util.concurrent.CompletableFuture; +import java.util.function.BiConsumer; +import java.util.function.Supplier; + +@RpcInterface("chain") +public interface Chain { + + /** + * Get header and body of a relay chain block. + * + * @return current signed block + */ + @RpcCall("getBlock") + CompletableFuture getBlock(); + + /** + * Get header and body of a relay chain block. + * + * @param hash hash of the wanted block, or empty for the latest block + * @return signed block + */ + @RpcCall("getBlock") + CompletableFuture getBlock(BlockHash hash); + + /** + * Get hash of the n-th block in the canon chain. + * + * @return block hash + */ + @RpcCall("getBlockHash") + CompletableFuture getBlockHash(); + + /** + * Get hash of the n-th block in the canon chain. + * + * @param blockNumber number of wanted block + * @return block hash + */ + @RpcCall("getBlockHash") + CompletableFuture getBlockHash(BlockNumber blockNumber); + + /** + * Get hash of the last finalized block in the canon chain. + * + * @return hash of the last finalized block + */ + @RpcCall("getFinalizedHead") + CompletableFuture getFinalizedHead(); + + /** + * Retrieves the best header via subscription. + * + * @param callback callback handler + * @return unsubscribe delegate + */ + @RpcSubscription(type = "newHead", subscribeMethod = "subscribeNewHead", unsubscribeMethod = "unsubscribeNewHead") + CompletableFuture>> subscribeNewHeads(BiConsumer callback); +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/section/State.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/section/State.java new file mode 100644 index 00000000..2251dcec --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/section/State.java @@ -0,0 +1,226 @@ +package com.strategyobject.substrateclient.rpc.api.section; + +import com.strategyobject.substrateclient.rpc.annotation.RpcCall; +import com.strategyobject.substrateclient.rpc.annotation.RpcInterface; +import com.strategyobject.substrateclient.rpc.annotation.RpcSubscription; +import com.strategyobject.substrateclient.rpc.api.*; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockHash; +import com.strategyobject.substrateclient.rpc.api.primitives.Hash; +import com.strategyobject.substrateclient.rpc.api.storage.StorageChangeSet; +import com.strategyobject.substrateclient.rpc.api.storage.StorageData; +import com.strategyobject.substrateclient.rpc.api.storage.StorageKey; +import com.strategyobject.substrateclient.scale.annotation.Scale; + +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiConsumer; +import java.util.function.Supplier; + +@RpcInterface("state") +public interface State { + /** + * Returns the keys with prefix, leave empty to get all the keys. + * + * @param key prefix + * @return storage keys + */ + @RpcCall("getKeys") + CompletableFuture> getKeys(StorageKey key); + + + /** + * Returns the keys with prefix, leave empty to get all the keys. + * + * @param key prefix + * @param at block hash + * @return storage keys + */ + @RpcCall("getKeys") + CompletableFuture> getKeys(StorageKey key, BlockHash at); + + /** + * Returns the keys with prefix with pagination support. + * + * @param key prefix + * @param count up to count keys will be returned + * @return storage keys + */ + @RpcCall("getKeysPaged") + CompletableFuture> getKeysPaged(StorageKey key, int count); + + /** + * Returns the keys with prefix with pagination support. + * + * @param key prefix + * @param count up to count keys will be returned + * @param startKey if `start_key` is passed, return next keys in storage in lexicographic order + * @return storage keys + */ + @RpcCall("getKeysPaged") + CompletableFuture> getKeysPaged(StorageKey key, int count, StorageKey startKey); + + /** + * Returns the keys with prefix with pagination support. + * + * @param key prefix + * @param count up to count keys will be returned + * @param startKey if `start_key` is passed, return next keys in storage in lexicographic order + * @param at block hash + * @return storage keys + */ + @RpcCall("getKeysPaged") + CompletableFuture> getKeysPaged(StorageKey key, + int count, + StorageKey startKey, + BlockHash at); + + /** + * Returns the runtime metadata as an opaque blob. + * + * @return runtime metadata + */ + @RpcCall("getMetadata") + @Scale + CompletableFuture getMetadata(); + + /** + * Returns the runtime metadata as an opaque blob. + * + * @param at block hash + * @return runtime metadata + */ + @RpcCall("getMetadata") + @Scale + CompletableFuture getMetadata(BlockHash at); + + /** + * Get the runtime version. + * + * @return runtime version + */ + @RpcCall("getRuntimeVersion") + CompletableFuture getRuntimeVersion(); + + /** + * Get the runtime version. + * + * @param at block hash + * @return runtime version + */ + @RpcCall("getRuntimeVersion") + CompletableFuture getRuntimeVersion(BlockHash at); + + /** + * Returns a storage entry at a specific block's state. + * + * @param key storage key + * @return storage entry + */ + @RpcCall("getStorage") + CompletableFuture getStorage(StorageKey key); + + /** + * Returns a storage entry at a specific block's state. + * + * @param key storage key + * @param at block hash + * @return storage entry + */ + @RpcCall("getStorage") + CompletableFuture getStorage(StorageKey key, BlockHash at); + + /** + * Returns the hash of a storage entry at a block's state. + * + * @param key storage key + * @return hash of a storage entry + */ + @RpcCall("getStorageHash") + CompletableFuture getStorageHash(StorageKey key); + + /** + * Returns the hash of a storage entry at a block's state. + * + * @param key storage key + * @param at block hash + * @return hash of a storage entry + */ + @RpcCall("getStorageHash") + CompletableFuture getStorageHash(StorageKey key, BlockHash at); + + /** + * Returns the size of a storage entry at a block's state. + * + * @param key storage key + * @return size of a storage entry + */ + @RpcCall("getStorageSize") + CompletableFuture getStorageSize(StorageKey key); + + /** + * Returns the size of a storage entry at a block's state. + * + * @param key storage key + * @param at block hash + * @return size of a storage entry + */ + @RpcCall("getStorageSize") + CompletableFuture getStorageSize(StorageKey key, BlockHash at); + + /** + * Query historical storage entries (by key) starting from a block given as the second parameter. + * NOTE: This first returned result contains the initial state of storage for all keys. + * Subsequent values in the vector represent changes to the previous state (diffs). + * + * @param keys storage keys + * @param fromBlock hash of a starting block + * @return historical storage entries + */ + @RpcCall("queryStorage") + CompletableFuture> queryStorage(List keys, BlockHash fromBlock); + + /** + * Query historical storage entries (by key) starting from a block given as the second parameter. + * NOTE: This first returned result contains the initial state of storage for all keys. + * Subsequent values in the vector represent changes to the previous state (diffs). + * + * @param keys storage keys + * @param fromBlock hash of a starting block + * @param toBlock hash of an ending block + * @return historical storage entries + */ + @RpcCall("queryStorage") + CompletableFuture> queryStorage(List keys, + BlockHash fromBlock, + BlockHash toBlock); + + /** + * Query storage entries (by key) starting at block hash given as the second parameter. + * + * @param keys storage keys + * @return storage entries + */ + @RpcCall("queryStorageAt") + CompletableFuture> queryStorageAt(List keys); + + /** + * Query storage entries (by key) starting at block hash given as the second parameter. + * + * @param keys storage keys + * @param at block hash + * @return storage entries + */ + @RpcCall("queryStorageAt") + CompletableFuture> queryStorageAt(List keys, BlockHash at); + + /** + * Subscribes to storage changes for the provided keys. + * + * @param keys storage keys + * @param callback callback handler + * @return unsubscribe delegate + */ + @RpcSubscription(type = "storage", subscribeMethod = "subscribeStorage", unsubscribeMethod = "unsubscribeStorage") + CompletableFuture>> subscribeStorage(List keys, + BiConsumer callback); +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/section/System.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/section/System.java new file mode 100644 index 00000000..5db276bc --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/section/System.java @@ -0,0 +1,23 @@ +package com.strategyobject.substrateclient.rpc.api.section; + +import com.strategyobject.substrateclient.rpc.annotation.RpcCall; +import com.strategyobject.substrateclient.rpc.annotation.RpcInterface; +import com.strategyobject.substrateclient.rpc.api.AccountId; +import com.strategyobject.substrateclient.rpc.api.primitives.Index; + +import java.util.concurrent.CompletableFuture; + +@RpcInterface("system") +public interface System { + /** + * Returns the next valid index (aka nonce) for given account. + * This method takes into consideration all pending transactions + * currently in the pool and if no transactions are found in the pool + * it fallbacks to query the index from the runtime (aka. state nonce). + * + * @param accountId account + * @return the next account index available on the node + */ + @RpcCall("accountNextIndex") + CompletableFuture accountNextIndex(AccountId accountId); +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/storage/StorageChangeSet.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/storage/StorageChangeSet.java new file mode 100644 index 00000000..9aa2b3b7 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/storage/StorageChangeSet.java @@ -0,0 +1,19 @@ +package com.strategyobject.substrateclient.rpc.api.storage; + +import com.strategyobject.substrateclient.common.types.tuple.Pair; +import com.strategyobject.substrateclient.rpc.annotation.RpcDecoder; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockHash; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@RpcDecoder +@Getter +@Setter +public class StorageChangeSet { + @Scale + private BlockHash block; + private List> changes; +} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/StorageData.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/storage/StorageData.java similarity index 75% rename from rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/StorageData.java rename to rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/storage/StorageData.java index d32483b0..f10f43d9 100644 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/StorageData.java +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/storage/StorageData.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.rpc.types; +package com.strategyobject.substrateclient.rpc.api.storage; import lombok.Getter; import lombok.RequiredArgsConstructor; diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/StorageDataDecoder.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/storage/StorageDataDecoder.java similarity index 51% rename from rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/StorageDataDecoder.java rename to rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/storage/StorageDataDecoder.java index d904cc0c..88e28a40 100644 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/StorageDataDecoder.java +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/storage/StorageDataDecoder.java @@ -1,9 +1,9 @@ -package com.strategyobject.substrateclient.rpc.types; +package com.strategyobject.substrateclient.rpc.api.storage; -import com.strategyobject.substrateclient.common.utils.HexConverter; -import com.strategyobject.substrateclient.rpc.core.DecoderPair; -import com.strategyobject.substrateclient.rpc.core.annotations.AutoRegister; -import com.strategyobject.substrateclient.rpc.core.decoders.AbstractDecoder; +import com.strategyobject.substrateclient.common.convert.HexConverter; +import com.strategyobject.substrateclient.rpc.DecoderPair; +import com.strategyobject.substrateclient.rpc.annotation.AutoRegister; +import com.strategyobject.substrateclient.rpc.decoders.AbstractDecoder; import com.strategyobject.substrateclient.transport.RpcObject; @AutoRegister(types = StorageData.class) diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/StorageKey.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/storage/StorageKey.java similarity index 74% rename from rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/StorageKey.java rename to rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/storage/StorageKey.java index 2aa307d0..74bfbc55 100644 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/StorageKey.java +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/storage/StorageKey.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.rpc.types; +package com.strategyobject.substrateclient.rpc.api.storage; import lombok.Getter; import lombok.RequiredArgsConstructor; diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/StorageKeyDecoder.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/storage/StorageKeyDecoder.java similarity index 51% rename from rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/StorageKeyDecoder.java rename to rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/storage/StorageKeyDecoder.java index 6bee248f..a514e54d 100644 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/StorageKeyDecoder.java +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/storage/StorageKeyDecoder.java @@ -1,9 +1,9 @@ -package com.strategyobject.substrateclient.rpc.types; +package com.strategyobject.substrateclient.rpc.api.storage; -import com.strategyobject.substrateclient.common.utils.HexConverter; -import com.strategyobject.substrateclient.rpc.core.DecoderPair; -import com.strategyobject.substrateclient.rpc.core.annotations.AutoRegister; -import com.strategyobject.substrateclient.rpc.core.decoders.AbstractDecoder; +import com.strategyobject.substrateclient.common.convert.HexConverter; +import com.strategyobject.substrateclient.rpc.DecoderPair; +import com.strategyobject.substrateclient.rpc.annotation.AutoRegister; +import com.strategyobject.substrateclient.rpc.decoders.AbstractDecoder; import com.strategyobject.substrateclient.transport.RpcObject; @AutoRegister(types = StorageKey.class) diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/StorageKeyEncoder.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/storage/StorageKeyEncoder.java similarity index 55% rename from rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/StorageKeyEncoder.java rename to rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/storage/StorageKeyEncoder.java index 81272600..0cd75390 100644 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/StorageKeyEncoder.java +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/storage/StorageKeyEncoder.java @@ -1,10 +1,10 @@ -package com.strategyobject.substrateclient.rpc.types; +package com.strategyobject.substrateclient.rpc.api.storage; import com.google.common.base.Preconditions; -import com.strategyobject.substrateclient.common.utils.HexConverter; -import com.strategyobject.substrateclient.rpc.core.EncoderPair; -import com.strategyobject.substrateclient.rpc.core.RpcEncoder; -import com.strategyobject.substrateclient.rpc.core.annotations.AutoRegister; +import com.strategyobject.substrateclient.common.convert.HexConverter; +import com.strategyobject.substrateclient.rpc.EncoderPair; +import com.strategyobject.substrateclient.rpc.RpcEncoder; +import com.strategyobject.substrateclient.rpc.annotation.AutoRegister; import lombok.NonNull; @AutoRegister(types = StorageKey.class) diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/weights/DispatchClass.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/weights/DispatchClass.java new file mode 100644 index 00000000..7e60c13a --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/weights/DispatchClass.java @@ -0,0 +1,33 @@ +package com.strategyobject.substrateclient.rpc.api.weights; + +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; + +/** + * A generalized group of dispatch types. + */ +@ScaleReader +public enum DispatchClass { + /** + * A normal dispatch. + */ + NORMAL, + + /** + * An operational dispatch. + */ + OPERATIONAL, + + /** + * A mandatory dispatch. These kinds of dispatch are always included regardless of their + * weight, therefore it is critical that they are separately validated to ensure that a + * malicious validator cannot craft a valid but impossibly heavy block. Usually this just means + * ensuring that the extrinsic can only be included once and that it is always very light. + *

+ * The only real use case for this is inherent extrinsics that are required to execute in a + * block for the block to be valid, and it solves the issue in the case that the block + * initialization is sufficiently heavy to mean that those inherents do not fit into the + * block. Essentially, we assume that in these exceptional circumstances, it is better to + * allow an overweight block to be created than to not allow any block at all to be created. + */ + MANDATORY +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/weights/DispatchInfo.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/weights/DispatchInfo.java new file mode 100644 index 00000000..b6f94f5b --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/weights/DispatchInfo.java @@ -0,0 +1,33 @@ +package com.strategyobject.substrateclient.rpc.api.weights; + +import com.strategyobject.substrateclient.scale.ScaleType; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; +import lombok.Getter; +import lombok.Setter; + +import java.math.BigInteger; + +/** + * A bundle of static information collected from the `weight` attributes. + */ +@Getter +@Setter +@ScaleReader +public class DispatchInfo { + /** + * Weight of this transaction. + */ + @Scale(ScaleType.U64.class) + private BigInteger weight; + + /** + * Class of this transaction. + */ + private DispatchClass dispatchClass; + + /** + * Does this transaction pay fees. + */ + private Pays paysFee; +} diff --git a/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/weights/Pays.java b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/weights/Pays.java new file mode 100644 index 00000000..dcf5ffd8 --- /dev/null +++ b/rpc/rpc-api/src/main/java/com/strategyobject/substrateclient/rpc/api/weights/Pays.java @@ -0,0 +1,19 @@ +package com.strategyobject.substrateclient.rpc.api.weights; + +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; + +/** + * Explicit enum to denote if a transaction pays fee or not. + */ +@ScaleReader +public enum Pays { + /** + * Transactor will pay related fees. + */ + YES, + + /** + * Transactor will NOT pay related fees. + */ + NO +} diff --git a/rpc/rpc-sections/src/test/java/com/strategyobject/substrateclient/rpc/sections/AuthorTests.java b/rpc/rpc-api/src/test/java/com/strategyobject/substrateclient/rpc/api/section/AuthorTests.java similarity index 51% rename from rpc/rpc-sections/src/test/java/com/strategyobject/substrateclient/rpc/sections/AuthorTests.java rename to rpc/rpc-api/src/test/java/com/strategyobject/substrateclient/rpc/api/section/AuthorTests.java index da257966..aa4ccf8a 100644 --- a/rpc/rpc-sections/src/test/java/com/strategyobject/substrateclient/rpc/sections/AuthorTests.java +++ b/rpc/rpc-api/src/test/java/com/strategyobject/substrateclient/rpc/api/section/AuthorTests.java @@ -1,20 +1,24 @@ -package com.strategyobject.substrateclient.rpc.sections; +package com.strategyobject.substrateclient.rpc.api.section; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; +import com.strategyobject.substrateclient.common.types.Size; +import com.strategyobject.substrateclient.crypto.Hasher; +import com.strategyobject.substrateclient.crypto.KeyPair; import com.strategyobject.substrateclient.crypto.KeyRing; -import com.strategyobject.substrateclient.rpc.core.RpcGeneratedSectionFactory; -import com.strategyobject.substrateclient.rpc.core.RpcInterfaceInitializationException; -import com.strategyobject.substrateclient.rpc.sections.substitutes.BalanceTransfer; -import com.strategyobject.substrateclient.rpc.types.*; +import com.strategyobject.substrateclient.crypto.PublicKey; +import com.strategyobject.substrateclient.rpc.api.*; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockHash; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockNumber; +import com.strategyobject.substrateclient.rpc.api.primitives.Index; +import com.strategyobject.substrateclient.scale.ScaleUtils; +import com.strategyobject.substrateclient.scale.ScaleWriter; import com.strategyobject.substrateclient.tests.containers.SubstrateVersion; import com.strategyobject.substrateclient.tests.containers.TestSubstrateContainer; +import com.strategyobject.substrateclient.transport.ws.ReconnectionPolicy; import com.strategyobject.substrateclient.transport.ws.WsProvider; -import com.strategyobject.substrateclient.types.KeyPair; -import com.strategyobject.substrateclient.types.PublicKey; -import com.strategyobject.substrateclient.types.Signable; import lombok.val; import lombok.var; -import org.bouncycastle.crypto.digests.Blake2bDigest; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.testcontainers.containers.Network; import org.testcontainers.junit.jupiter.Container; @@ -32,7 +36,7 @@ import static org.junit.jupiter.api.Assertions.*; @Testcontainers -public class AuthorTests { +class AuthorTests { private static final int WAIT_TIMEOUT = 10; private static final Network network = Network.newNetwork(); private static final AtomicInteger NONCE = new AtomicInteger(0); @@ -41,50 +45,31 @@ public class AuthorTests { static final TestSubstrateContainer substrate = new TestSubstrateContainer(SubstrateVersion.V3_0_0) .withNetwork(network); - private static byte[] blake2(byte[] value) { - val digest = new Blake2bDigest(256); - digest.update(value, 0, value.length); - - val result = new byte[32]; - digest.doFinal(result, 0); - return result; - } - @Test - void hasKey() throws ExecutionException, InterruptedException, TimeoutException, RpcInterfaceInitializationException { - try (WsProvider wsProvider = WsProvider.builder() - .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() - .build()) { - wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - Author rpcSection = RpcGeneratedSectionFactory.create(Author.class, wsProvider); + void hasKey() throws Exception { + try (val wsProvider = connect()) { + val author = TestsHelper.createSectionFactory(wsProvider).create(Author.class); val publicKey = PublicKey.fromBytes( HexConverter.toBytes("0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d")); val keyType = "aura"; - var result = rpcSection.hasKey(publicKey, keyType).get(WAIT_TIMEOUT, TimeUnit.SECONDS); + var result = author.hasKey(publicKey, keyType).get(WAIT_TIMEOUT, TimeUnit.SECONDS); assertFalse(result); - rpcSection.insertKey(keyType, "alice", publicKey).get(WAIT_TIMEOUT, TimeUnit.SECONDS); - result = rpcSection.hasKey(publicKey, keyType).get(WAIT_TIMEOUT, TimeUnit.SECONDS); + author.insertKey(keyType, "alice", publicKey).get(WAIT_TIMEOUT, TimeUnit.SECONDS); + result = author.hasKey(publicKey, keyType).get(WAIT_TIMEOUT, TimeUnit.SECONDS); assertTrue(result); } } @Test - void insertKey() throws ExecutionException, InterruptedException, TimeoutException, RpcInterfaceInitializationException { - try (WsProvider wsProvider = WsProvider.builder() - .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() - .build()) { - wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - Author rpcSection = RpcGeneratedSectionFactory.create(Author.class, wsProvider); + void insertKey() throws Exception { + try (val wsProvider = connect()) { + val author = TestsHelper.createSectionFactory(wsProvider).create(Author.class); - assertDoesNotThrow(() -> rpcSection.insertKey("aura", + assertDoesNotThrow(() -> author.insertKey("aura", "alice", PublicKey.fromBytes( HexConverter.toBytes("0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"))) @@ -93,39 +78,30 @@ void insertKey() throws ExecutionException, InterruptedException, TimeoutExcepti } @Test - void submitExtrinsic() throws ExecutionException, InterruptedException, TimeoutException, RpcInterfaceInitializationException { - try (WsProvider wsProvider = WsProvider.builder() - .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() - .build()) { - wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - Chain chainSection = RpcGeneratedSectionFactory.create(Chain.class, wsProvider); - - val genesis = chainSection.getBlockHash(0).get(WAIT_TIMEOUT, TimeUnit.SECONDS); - Author authorSection = RpcGeneratedSectionFactory.create(Author.class, wsProvider); - - assertDoesNotThrow(() -> authorSection.submitExtrinsic(createBalanceTransferExtrinsic(genesis, NONCE.getAndIncrement())) + void submitExtrinsic() throws Exception { + try (val wsProvider = connect()) { + val sectionFactory = TestsHelper.createSectionFactory(wsProvider); + val chain = sectionFactory.create(Chain.class); + val genesis = chain.getBlockHash(BlockNumber.GENESIS).get(WAIT_TIMEOUT, TimeUnit.SECONDS); + + val author = sectionFactory.create(Author.class); + assertDoesNotThrow(() -> author.submitExtrinsic(createBalanceTransferExtrinsic(genesis, NONCE.getAndIncrement())) .get(WAIT_TIMEOUT, TimeUnit.SECONDS)); } } @Test - void submitAndWatchExtrinsic() throws ExecutionException, InterruptedException, TimeoutException, RpcInterfaceInitializationException { - try (WsProvider wsProvider = WsProvider.builder() - .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() - .build()) { - wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - Chain chainSection = RpcGeneratedSectionFactory.create(Chain.class, wsProvider); + void submitAndWatchExtrinsic() throws Exception { + try (val wsProvider = connect()) { + val sectionFactory = TestsHelper.createSectionFactory(wsProvider); - val genesis = chainSection.getBlockHash(0).get(WAIT_TIMEOUT, TimeUnit.SECONDS); - Author authorSection = RpcGeneratedSectionFactory.create(Author.class, wsProvider); + val chain = sectionFactory.create(Chain.class); + val genesis = chain.getBlockHash(BlockNumber.GENESIS).get(WAIT_TIMEOUT, TimeUnit.SECONDS); + val author = sectionFactory.create(Author.class); val updateCount = new AtomicInteger(0); val status = new AtomicReference(); - val unsubscribe = authorSection.submitAndWatchExtrinsic( + val unsubscribe = author.submitAndWatchExtrinsic( createBalanceTransferExtrinsic(genesis, NONCE.getAndIncrement()), (exception, extrinsicStatus) -> { updateCount.incrementAndGet(); @@ -141,35 +117,47 @@ void submitAndWatchExtrinsic() throws ExecutionException, InterruptedException, val result = unsubscribe.get().get(WAIT_TIMEOUT, TimeUnit.SECONDS); - assertTrue(result); + Assertions.assertTrue(result); } } + + private WsProvider connect() throws ExecutionException, InterruptedException, TimeoutException { + val wsProvider = WsProvider.builder() + .setEndpoint(substrate.getWsAddress()) + .withPolicy(ReconnectionPolicy.MANUAL) + .build(); + + wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); + return wsProvider; + } + + @SuppressWarnings({"unchecked"}) private Extrinsic createBalanceTransferExtrinsic(BlockHash genesis, int nonce) { val specVersion = 264; val txVersion = 2; val moduleIndex = (byte) 6; val callIndex = (byte) 0; val tip = 0; - val call = new BalanceTransfer(moduleIndex, callIndex, AddressId.fromBytes(bobKeyPair().asPublicKey().getData()), BigInteger.valueOf(10)); + val call = new BalanceTransfer(moduleIndex, callIndex, AddressId.fromBytes(bobKeyPair().asPublicKey().getBytes()), BigInteger.valueOf(10)); - val extra = new SignedExtra<>(specVersion, txVersion, genesis, genesis, new ImmortalEra(), BigInteger.valueOf(nonce), BigInteger.valueOf(tip)); - val signedPayload = new SignedPayload<>(call, extra); + val extra = new SignedExtra<>(specVersion, txVersion, genesis, genesis, new ImmortalEra(), Index.of(nonce), BigInteger.valueOf(tip)); + val writer = (ScaleWriter>>) TestsHelper.SCALE_WRITER_REGISTRY.resolve(SignedPayload.class); + val signedPayload = ScaleUtils.toBytes(new SignedPayload<>(call, extra), writer); val keyRing = KeyRing.fromKeyPair(aliceKeyPair()); val signature = sign(keyRing, signedPayload); return Extrinsic.createSigned( new SignaturePayload<>( - AddressId.fromBytes(aliceKeyPair().asPublicKey().getData()), + AddressId.fromBytes(aliceKeyPair().asPublicKey().getBytes()), signature, extra ), call); } - private Signature sign(KeyRing keyRing, Signable payload) { - var signed = payload.getBytes(); - val signature = signed.length > 256 ? blake2(signed) : signed; + private Signature sign(KeyRing keyRing, byte[] payload) { + val signature = payload.length > 256 ? Hasher.blake2(Size.of256, payload) : payload; return Sr25519Signature.from(keyRing.sign(() -> signature)); } diff --git a/rpc/rpc-api/src/test/java/com/strategyobject/substrateclient/rpc/api/section/BalanceTransfer.java b/rpc/rpc-api/src/test/java/com/strategyobject/substrateclient/rpc/api/section/BalanceTransfer.java new file mode 100644 index 00000000..09c38ee4 --- /dev/null +++ b/rpc/rpc-api/src/test/java/com/strategyobject/substrateclient/rpc/api/section/BalanceTransfer.java @@ -0,0 +1,22 @@ +package com.strategyobject.substrateclient.rpc.api.section; + +import com.strategyobject.substrateclient.rpc.api.AddressId; +import com.strategyobject.substrateclient.rpc.api.Call; +import com.strategyobject.substrateclient.scale.ScaleType; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleWriter; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.math.BigInteger; + +@RequiredArgsConstructor +@Getter +@ScaleWriter +public class BalanceTransfer implements Call { + private final byte moduleIndex; + private final byte callIndex; + private final AddressId destination; + @Scale(ScaleType.CompactBigInteger.class) + private final BigInteger amount; +} diff --git a/rpc/rpc-api/src/test/java/com/strategyobject/substrateclient/rpc/api/section/ChainTests.java b/rpc/rpc-api/src/test/java/com/strategyobject/substrateclient/rpc/api/section/ChainTests.java new file mode 100644 index 00000000..9562b229 --- /dev/null +++ b/rpc/rpc-api/src/test/java/com/strategyobject/substrateclient/rpc/api/section/ChainTests.java @@ -0,0 +1,144 @@ +package com.strategyobject.substrateclient.rpc.api.section; + +import com.strategyobject.substrateclient.rpc.api.primitives.BlockHash; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockNumber; +import com.strategyobject.substrateclient.tests.containers.SubstrateVersion; +import com.strategyobject.substrateclient.tests.containers.TestSubstrateContainer; +import com.strategyobject.substrateclient.transport.ws.ReconnectionPolicy; +import com.strategyobject.substrateclient.transport.ws.WsProvider; +import lombok.val; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.testcontainers.containers.Network; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import java.math.BigInteger; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +import static org.awaitility.Awaitility.await; +import static org.hamcrest.Matchers.greaterThan; +import static org.junit.jupiter.api.Assertions.*; + +@Testcontainers +class ChainTests { + private static final int WAIT_TIMEOUT = 10; + private static final Network network = Network.newNetwork(); + + @Container + static final TestSubstrateContainer substrate = new TestSubstrateContainer(SubstrateVersion.V3_0_0) + .withNetwork(network); + + @Test + void getFinalizedHead() throws Exception { + try (val wsProvider = connect()) { + val chain = TestsHelper.createSectionFactory(wsProvider).create(Chain.class); + val result = chain.getFinalizedHead().get(WAIT_TIMEOUT, TimeUnit.SECONDS); + + assertNotEquals(BigInteger.ZERO, new BigInteger(result.getBytes())); + } + } + + @Test + void subscribeNewHeads() throws Exception { + try (val wsProvider = connect()) { + val chain = TestsHelper.createSectionFactory(wsProvider).create(Chain.class); + + val blockCount = new AtomicInteger(0); + val blockHash = new AtomicReference(null); + + val unsubscribeFunc = chain + .subscribeNewHeads((e, h) -> { + if (blockCount.incrementAndGet() > 1) { + blockHash.compareAndSet(null, h.getParentHash()); + } + }) + .get(WAIT_TIMEOUT, TimeUnit.SECONDS); + + await() + .atMost(WAIT_TIMEOUT * 2, TimeUnit.SECONDS) + .untilAtomic(blockCount, greaterThan(2)); + + assertNotEquals(BigInteger.ZERO, new BigInteger(blockHash.get().getBytes())); + + val result = unsubscribeFunc.get().get(WAIT_TIMEOUT, TimeUnit.SECONDS); + + Assertions.assertTrue(result); + } + } + + @Test + void getBlockHash() throws Exception { + try (val wsProvider = connect()) { + val chain = TestsHelper.createSectionFactory(wsProvider).create(Chain.class); + val result = chain.getBlockHash().get(WAIT_TIMEOUT, TimeUnit.SECONDS); + + assertNotEquals(BigInteger.ZERO, new BigInteger(result.getBytes())); + } + } + + @Test + void getBlock() throws Exception { + try (val wsProvider = connect()) { + val chain = TestsHelper.createSectionFactory(wsProvider).create(Chain.class); + + val height = new AtomicInteger(0); + chain.subscribeNewHeads((e, header) -> { + if (header != null) { + height.set(header.getNumber().getValue().intValue()); + } + }); + + await() + .atMost(WAIT_TIMEOUT * 3, TimeUnit.SECONDS) + .untilAtomic(height, greaterThan(1)); + + val number = height.get(); + val blockHash = chain.getBlockHash(BlockNumber.of(number)).get(WAIT_TIMEOUT, TimeUnit.SECONDS); + + assertNotEquals(BigInteger.ZERO, new BigInteger(blockHash.getBytes())); + + val block = chain.getBlock(blockHash).get(WAIT_TIMEOUT, TimeUnit.SECONDS); + + assertNotEquals(BigInteger.ZERO, new BigInteger(block.getBlock().getHeader().getParentHash().getBytes())); + assertEquals(number, block.getBlock().getHeader().getNumber().getValue().intValue()); + } + } + + @Test + void getCurrentBlock() throws ExecutionException, InterruptedException, TimeoutException { + try (val wsProvider = connect()) { + val chain = TestsHelper.createSectionFactory(wsProvider).create(Chain.class); + + val height = new AtomicInteger(0); + chain.subscribeNewHeads((e, header) -> { + if (header != null) { + height.set(header.getNumber().getValue().intValue()); + } + }); + + await() + .atMost(WAIT_TIMEOUT * 3, TimeUnit.SECONDS) + .untilAtomic(height, greaterThan(2)); + + val block = chain.getBlock().get(WAIT_TIMEOUT, TimeUnit.SECONDS); + + assertNotEquals(BigInteger.ZERO, new BigInteger(block.getBlock().getHeader().getParentHash().getBytes())); + assertNotNull(block.getBlock().getHeader().getNumber()); + } + } + + private WsProvider connect() throws ExecutionException, InterruptedException, TimeoutException { + val wsProvider = WsProvider.builder() + .setEndpoint(substrate.getWsAddress()) + .withPolicy(ReconnectionPolicy.MANUAL) + .build(); + + wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); + return wsProvider; + } +} diff --git a/rpc/rpc-api/src/test/java/com/strategyobject/substrateclient/rpc/api/section/StateTests.java b/rpc/rpc-api/src/test/java/com/strategyobject/substrateclient/rpc/api/section/StateTests.java new file mode 100644 index 00000000..baad1d09 --- /dev/null +++ b/rpc/rpc-api/src/test/java/com/strategyobject/substrateclient/rpc/api/section/StateTests.java @@ -0,0 +1,186 @@ +package com.strategyobject.substrateclient.rpc.api.section; + +import com.strategyobject.substrateclient.common.convert.HexConverter; +import com.strategyobject.substrateclient.rpc.api.primitives.BlockNumber; +import com.strategyobject.substrateclient.rpc.api.storage.StorageKey; +import com.strategyobject.substrateclient.tests.containers.SubstrateVersion; +import com.strategyobject.substrateclient.tests.containers.TestSubstrateContainer; +import com.strategyobject.substrateclient.transport.ws.ReconnectionPolicy; +import com.strategyobject.substrateclient.transport.ws.WsProvider; +import lombok.val; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.testcontainers.containers.Network; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import java.util.Collections; +import java.util.concurrent.TimeUnit; + +import static org.junit.jupiter.api.Assertions.*; + +@Testcontainers +class StateTests { + private static final int WAIT_TIMEOUT = 10; + private static final Network network = Network.newNetwork(); + + private final StorageKey storageKey; + + @Container + static final TestSubstrateContainer substrate = new TestSubstrateContainer(SubstrateVersion.V3_0_0) + .withNetwork(network); + + StateTests() { + // xxhash128("Balances") = 0xc2261276cc9d1f8598ea4b6a74b15c2f + // xxhash128("StorageVersion") = 0x308ce9615de0775a82f8a94dc3d285a1 + val key = "0xc2261276cc9d1f8598ea4b6a74b15c2f308ce9615de0775a82f8a94dc3d285a1"; + storageKey = StorageKey.valueOf(HexConverter.toBytes(key)); + } + + @Test + void getRuntimeVersion() throws Exception { + try (val wsProvider = connect()) { + val state = TestsHelper.createSectionFactory(wsProvider).create(State.class); + + assertDoesNotThrow(() -> { + state.getRuntimeVersion().get(WAIT_TIMEOUT, TimeUnit.SECONDS); + }); + } + } + + @Test + void getMetadata() throws Exception { + try (val wsProvider = connect()) { + val state = TestsHelper.createSectionFactory(wsProvider).create(State.class); + + assertDoesNotThrow(() -> { + state.getMetadata().get(WAIT_TIMEOUT * 10, TimeUnit.SECONDS); + }); + } + } + + @Test + void getKeys() throws Exception { + try (val wsProvider = connect()) { + val state = TestsHelper.createSectionFactory(wsProvider).create(State.class); + + val keys = state.getKeys(storageKey).get(WAIT_TIMEOUT, TimeUnit.SECONDS); + + assertTrue(keys.size() > 0); + } + } + + @Test + void getStorage() throws Exception { + try (val wsProvider = connect()) { + val state = TestsHelper.createSectionFactory(wsProvider).create(State.class); + + val storageData = state.getStorage(storageKey).get(WAIT_TIMEOUT, TimeUnit.SECONDS); + + assertNotNull(storageData); + assertTrue(storageData.getData().length > 0); + } + } + + @Test + void getStorageHandlesNullResponse() throws Exception { + try (val wsProvider = connect()) { + val state = TestsHelper.createSectionFactory(wsProvider).create(State.class); + + val emptyKey = new byte[32]; + val storageData = state.getStorage(StorageKey.valueOf(emptyKey)).get(WAIT_TIMEOUT, TimeUnit.SECONDS); + + assertNull(storageData); + } + } + + @Test + void getStorageAtBlock() throws Exception { + try (val wsProvider = connect()) { + val chainSection = TestsHelper.createSectionFactory(wsProvider).create(Chain.class); + val blockHash = chainSection.getBlockHash(BlockNumber.GENESIS).get(WAIT_TIMEOUT, TimeUnit.SECONDS); + val state = TestsHelper.createSectionFactory(wsProvider).create(State.class); + + val storageData = state.getStorage(storageKey, blockHash).get(WAIT_TIMEOUT, TimeUnit.SECONDS); + + assertNotNull(storageData); + assertTrue(storageData.getData().length > 0); + } + } + + @Test + void getStorageHash() throws Exception { + try (val wsProvider = connect()) { + val state = TestsHelper.createSectionFactory(wsProvider).create(State.class); + + val hash = state.getStorageHash(storageKey).get(WAIT_TIMEOUT, TimeUnit.SECONDS); + + assertNotNull(hash); + assertTrue(hash.getBytes().length > 0); + } + } + + @Test + void getStorageHashAt() throws Exception { + try (val wsProvider = connect()) { + val chainSection = TestsHelper.createSectionFactory(wsProvider).create(Chain.class); + val blockHash = chainSection.getBlockHash(BlockNumber.GENESIS).get(WAIT_TIMEOUT, TimeUnit.SECONDS); + val state = TestsHelper.createSectionFactory(wsProvider).create(State.class); + + val hash = state.getStorageHash(storageKey, blockHash).get(WAIT_TIMEOUT, TimeUnit.SECONDS); + + assertNotNull(hash); + assertTrue(hash.getBytes().length > 0); + } + } + + @Test + void getStorageSize() throws Exception { + try (val wsProvider = connect()) { + val state = TestsHelper.createSectionFactory(wsProvider).create(State.class); + + val size = state.getStorageSize(storageKey).get(WAIT_TIMEOUT, TimeUnit.SECONDS); + + Assertions.assertEquals(1, size); + } + } + + @Test + void getStorageSizeAt() throws Exception { + try (val wsProvider = connect()) { + val chainSection = TestsHelper.createSectionFactory(wsProvider).create(Chain.class); + val blockHash = chainSection.getBlockHash(BlockNumber.GENESIS).get(WAIT_TIMEOUT, TimeUnit.SECONDS); + val state = TestsHelper.createSectionFactory(wsProvider).create(State.class); + + val size = state.getStorageSize(storageKey, blockHash).get(WAIT_TIMEOUT, TimeUnit.SECONDS); + + Assertions.assertEquals(1, size); + } + } + + @Test + void queryStorageAt() throws Exception { + try (val wsProvider = connect()) { + val state = TestsHelper.createSectionFactory(wsProvider).create(State.class); + + val changes = state + .queryStorageAt(Collections.singletonList(storageKey)) + .get(WAIT_TIMEOUT, TimeUnit.SECONDS); + + assertTrue(changes.size() > 0); + assertTrue(changes.get(0).getChanges().size() > 0); + assertNotNull(changes.get(0).getChanges().get(0).getValue0().getData()); + assertTrue(changes.get(0).getChanges().get(0).getValue0().getData().length > 0); + } + } + + private WsProvider connect() throws Exception { + val wsProvider = WsProvider.builder() + .setEndpoint(substrate.getWsAddress()) + .withPolicy(ReconnectionPolicy.MANUAL) + .build(); + + wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); + return wsProvider; + } +} diff --git a/rpc/rpc-sections/src/test/java/com/strategyobject/substrateclient/rpc/sections/SystemTests.java b/rpc/rpc-api/src/test/java/com/strategyobject/substrateclient/rpc/api/section/SystemTests.java similarity index 53% rename from rpc/rpc-sections/src/test/java/com/strategyobject/substrateclient/rpc/sections/SystemTests.java rename to rpc/rpc-api/src/test/java/com/strategyobject/substrateclient/rpc/api/section/SystemTests.java index a524db39..5448d981 100644 --- a/rpc/rpc-sections/src/test/java/com/strategyobject/substrateclient/rpc/sections/SystemTests.java +++ b/rpc/rpc-api/src/test/java/com/strategyobject/substrateclient/rpc/api/section/SystemTests.java @@ -1,11 +1,11 @@ -package com.strategyobject.substrateclient.rpc.sections; +package com.strategyobject.substrateclient.rpc.api.section; -import com.strategyobject.substrateclient.common.utils.HexConverter; -import com.strategyobject.substrateclient.rpc.core.RpcGeneratedSectionFactory; -import com.strategyobject.substrateclient.rpc.core.RpcInterfaceInitializationException; -import com.strategyobject.substrateclient.rpc.types.AccountId; +import com.strategyobject.substrateclient.common.convert.HexConverter; +import com.strategyobject.substrateclient.rpc.api.AccountId; +import com.strategyobject.substrateclient.rpc.api.primitives.Index; import com.strategyobject.substrateclient.tests.containers.SubstrateVersion; import com.strategyobject.substrateclient.tests.containers.TestSubstrateContainer; +import com.strategyobject.substrateclient.transport.ws.ReconnectionPolicy; import com.strategyobject.substrateclient.transport.ws.WsProvider; import lombok.val; import org.junit.jupiter.api.Test; @@ -13,14 +13,12 @@ import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; -import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; import static org.junit.jupiter.api.Assertions.assertEquals; @Testcontainers -public class SystemTests { +class SystemTests { private static final int WAIT_TIMEOUT = 10; private static final Network network = Network.newNetwork(); @@ -28,17 +26,20 @@ public class SystemTests { static final TestSubstrateContainer substrate = new TestSubstrateContainer(SubstrateVersion.V3_0_0).withNetwork(network); @Test - void accountNextIndex() throws ExecutionException, InterruptedException, TimeoutException, RpcInterfaceInitializationException { - try (WsProvider wsProvider = WsProvider.builder().setEndpoint(substrate.getWsAddress()).disableAutoConnect().build()) { + void accountNextIndex() throws Exception { + try (val wsProvider = WsProvider.builder() + .setEndpoint(substrate.getWsAddress()) + .withPolicy(ReconnectionPolicy.MANUAL) + .build()) { wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); - System rpcSection = RpcGeneratedSectionFactory.create(System.class, wsProvider); + val system = TestsHelper.createSectionFactory(wsProvider).create(System.class); val alicePublicKey = HexConverter.toBytes("0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"); - val result = rpcSection.accountNextIndex(AccountId.fromBytes(alicePublicKey)) + val result = system.accountNextIndex(AccountId.fromBytes(alicePublicKey)) .get(WAIT_TIMEOUT, TimeUnit.SECONDS); - assertEquals(0, result); + assertEquals(Index.ZERO, result); } } } diff --git a/rpc/rpc-api/src/test/java/com/strategyobject/substrateclient/rpc/api/section/TestsHelper.java b/rpc/rpc-api/src/test/java/com/strategyobject/substrateclient/rpc/api/section/TestsHelper.java new file mode 100644 index 00000000..673bcee0 --- /dev/null +++ b/rpc/rpc-api/src/test/java/com/strategyobject/substrateclient/rpc/api/section/TestsHelper.java @@ -0,0 +1,56 @@ +package com.strategyobject.substrateclient.rpc.api.section; + +import com.strategyobject.substrateclient.crypto.ss58.SS58AddressFormat; +import com.strategyobject.substrateclient.rpc.GeneratedRpcSectionFactory; +import com.strategyobject.substrateclient.rpc.context.RpcDecoderContext; +import com.strategyobject.substrateclient.rpc.context.RpcEncoderContext; +import com.strategyobject.substrateclient.rpc.metadata.MetadataProvider; +import com.strategyobject.substrateclient.rpc.registries.RpcDecoderRegistry; +import com.strategyobject.substrateclient.rpc.registries.RpcEncoderRegistry; +import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; +import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; +import com.strategyobject.substrateclient.transport.ProviderInterface; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class TestsHelper { + static final MetadataProvider METADATA_PROVIDER = mock(MetadataProvider.class); + + static { + when(METADATA_PROVIDER.getSS58AddressFormat()).thenReturn(SS58AddressFormat.SUBSTRATE_ACCOUNT); + } + + static final ScaleReaderRegistry SCALE_READER_REGISTRY = new ScaleReaderRegistry() {{ + registerAnnotatedFrom("com.strategyobject.substrateclient"); + }}; + + static final ScaleWriterRegistry SCALE_WRITER_REGISTRY = new ScaleWriterRegistry() {{ + registerAnnotatedFrom("com.strategyobject.substrateclient"); + }}; + + static final RpcEncoderRegistry RPC_ENCODER_REGISTRY = new RpcEncoderRegistry(); + + static { + RPC_ENCODER_REGISTRY.registerAnnotatedFrom( + () -> new RpcEncoderContext(METADATA_PROVIDER, RPC_ENCODER_REGISTRY, SCALE_WRITER_REGISTRY), + "com.strategyobject.substrateclient"); + } + + static final RpcDecoderRegistry RPC_DECODER_REGISTRY = new RpcDecoderRegistry(); + + static { + RPC_DECODER_REGISTRY.registerAnnotatedFrom( + () -> new RpcDecoderContext(METADATA_PROVIDER, RPC_DECODER_REGISTRY, SCALE_READER_REGISTRY), + "com.strategyobject.substrateclient"); + } + + static GeneratedRpcSectionFactory createSectionFactory(ProviderInterface provider) { + return new GeneratedRpcSectionFactory( + provider, + RPC_ENCODER_REGISTRY, + SCALE_WRITER_REGISTRY, + RPC_DECODER_REGISTRY, + SCALE_READER_REGISTRY); + } +} diff --git a/rpc/rpc-codegen/build.gradle b/rpc/rpc-codegen/build.gradle index 2f6ad931..6e85c798 100644 --- a/rpc/rpc-codegen/build.gradle +++ b/rpc/rpc-codegen/build.gradle @@ -1,6 +1,6 @@ dependencies { implementation project(':common') - implementation project(':rpc:rpc-core') + implementation project(':rpc') implementation project(':scale') implementation project(':scale:scale-codegen') implementation project(':transport') diff --git a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/Constants.java b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/Constants.java index 1e8b55ec..74a31230 100644 --- a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/Constants.java +++ b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/Constants.java @@ -1,9 +1,9 @@ package com.strategyobject.substrateclient.rpc.codegen; -import com.strategyobject.substrateclient.rpc.core.RpcSelfEncodable; +import com.strategyobject.substrateclient.rpc.RpcDispatch; public class Constants { - public static final Class RPC_SELF_ENCODABLE = RpcSelfEncodable.class; + public static final Class RPC_DISPATCH = RpcDispatch.class; public static final String AUTO_REGISTER_TYPES_ARG = "types"; public static final String PAIR_FACTORY_METHOD = "of"; diff --git a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/decoder/DecoderCompositor.java b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/decoder/DecoderCompositor.java index e9404519..b0e16044 100644 --- a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/decoder/DecoderCompositor.java +++ b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/decoder/DecoderCompositor.java @@ -1,12 +1,13 @@ package com.strategyobject.substrateclient.rpc.codegen.decoder; import com.squareup.javapoet.CodeBlock; -import com.strategyobject.substrateclient.common.codegen.Constants; import com.strategyobject.substrateclient.common.codegen.ProcessorContext; +import com.strategyobject.substrateclient.common.codegen.TypeNotSupportedException; import com.strategyobject.substrateclient.common.codegen.TypeTraverser; -import com.strategyobject.substrateclient.rpc.core.DecoderPair; -import com.strategyobject.substrateclient.rpc.core.RpcDecoder; -import com.strategyobject.substrateclient.rpc.core.RpcRegistryHelper; +import com.strategyobject.substrateclient.common.types.Array; +import com.strategyobject.substrateclient.rpc.DecoderPair; +import com.strategyobject.substrateclient.rpc.RpcDecoder; +import com.strategyobject.substrateclient.rpc.RpcRegistryHelper; import com.strategyobject.substrateclient.scale.ScaleReader; import com.strategyobject.substrateclient.scale.ScaleRegistryHelper; import lombok.NonNull; @@ -44,7 +45,7 @@ public DecoderCompositor(@NonNull ProcessorContext context, this.readerMethod = readerMethod; this.decoderRegistryVarName = decoderRegistryVarName; this.scaleRegistryVarName = scaleRegistryVarName; - this.arrayType = context.erasure(context.getType(Constants.ARRAY_TYPE)); + this.arrayType = context.erasure(context.getType(Array.class)); } private CodeBlock getTypeVarCodeBlock(TypeVariable type) { @@ -72,13 +73,21 @@ private CodeBlock getGenericCodeBlock(TypeMirror type, CodeBlock[] subtypes) { var builder = CodeBlock.builder() .add("$T.$L(", DecoderPair.class, PAIR_FACTORY_METHOD) - .add("$T.$L($T.class, ", RpcRegistryHelper.class, RESOLVE_AND_INJECT_METHOD, resolveType); + .add("$T.$L($L, $T.class, ", + RpcRegistryHelper.class, + RESOLVE_AND_INJECT_METHOD, + decoderRegistryVarName, + resolveType); for (var i = 0; i < subtypes.length; i++) { if (i > 0) builder.add(", "); builder.add(subtypes[i]); } - builder.add("), $T.$L($T.class, ", ScaleRegistryHelper.class, RESOLVE_AND_INJECT_METHOD, resolveType); + builder.add("), $T.$L($L, $T.class, ", + ScaleRegistryHelper.class, + RESOLVE_AND_INJECT_METHOD, + scaleRegistryVarName, + resolveType); for (var i = 0; i < subtypes.length; i++) { if (i > 0) builder.add(", "); builder.add(subtypes[i]); @@ -90,6 +99,11 @@ private CodeBlock getGenericCodeBlock(TypeMirror type, CodeBlock[] subtypes) { .add(")").build(); } + @Override + protected CodeBlock whenWildcard(TypeMirror override) { + throw new TypeNotSupportedException("WILDCARD"); + } + @Override protected CodeBlock whenTypeVar(@NonNull TypeVariable type, TypeMirror _override) { return getTypeVarCodeBlock(type); diff --git a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/decoder/RpcDecoderAnnotatedClass.java b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/decoder/RpcDecoderAnnotatedClass.java index a1df6fec..f1cd5743 100644 --- a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/decoder/RpcDecoderAnnotatedClass.java +++ b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/decoder/RpcDecoderAnnotatedClass.java @@ -1,18 +1,20 @@ package com.strategyobject.substrateclient.rpc.codegen.decoder; import com.squareup.javapoet.*; +import com.strategyobject.substrateclient.common.codegen.AnnotationUtils; import com.strategyobject.substrateclient.common.codegen.JavaPoet; import com.strategyobject.substrateclient.common.codegen.ProcessingException; import com.strategyobject.substrateclient.common.codegen.ProcessorContext; -import com.strategyobject.substrateclient.rpc.core.DecoderPair; -import com.strategyobject.substrateclient.rpc.core.RpcDecoder; -import com.strategyobject.substrateclient.rpc.core.annotations.AutoRegister; -import com.strategyobject.substrateclient.rpc.core.annotations.Ignore; -import com.strategyobject.substrateclient.rpc.core.registries.RpcDecoderRegistry; +import com.strategyobject.substrateclient.rpc.DecoderPair; +import com.strategyobject.substrateclient.rpc.RpcDecoder; +import com.strategyobject.substrateclient.rpc.annotation.AutoRegister; +import com.strategyobject.substrateclient.rpc.annotation.Ignore; +import com.strategyobject.substrateclient.rpc.context.RpcDecoderContext; +import com.strategyobject.substrateclient.rpc.registries.RpcDecoderRegistry; import com.strategyobject.substrateclient.scale.ScaleReader; import com.strategyobject.substrateclient.scale.ScaleUtils; -import com.strategyobject.substrateclient.scale.annotations.Scale; -import com.strategyobject.substrateclient.scale.annotations.ScaleGeneric; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleGeneric; import com.strategyobject.substrateclient.scale.codegen.ScaleAnnotationParser; import com.strategyobject.substrateclient.scale.codegen.reader.ReaderCompositor; import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; @@ -39,10 +41,11 @@ import static java.util.stream.Collectors.toMap; public class RpcDecoderAnnotatedClass { - private final static String DECODER_NAME_TEMPLATE = "%sDecoder"; + private static final String DECODER_NAME_TEMPLATE = "%sDecoder"; private static final String VALUE_ARG = "value"; private static final String RESULT_VAR = "result"; private static final String MAP_VAR = "sourceMap"; + private static final String CONTEXT = "context"; private final TypeElement classElement; private final Map typeVarMap; @@ -56,7 +59,7 @@ public RpcDecoderAnnotatedClass(@NonNull TypeElement classElement) { .collect(toMap(i -> typeParameters.get(i).toString(), Function.identity())); this.fields = classElement.getEnclosedElements().stream() .filter(e -> e.getKind() == ElementKind.FIELD) - .map(e -> (VariableElement) e) + .map(VariableElement.class::cast) .collect(Collectors.toList()); } @@ -69,7 +72,9 @@ public void generateDecoder(@NonNull ProcessorContext context) throws Processing .addMember(AUTO_REGISTER_TYPES_ARG, "{$L.class}", classElement.getQualifiedName().toString()) .build()) .addModifiers(Modifier.PUBLIC) - .addSuperinterface(ParameterizedTypeName.get(ClassName.get(RpcDecoder.class), classWildcardTyped)) + .addSuperinterface(ParameterizedTypeName.get(ClassName.get(RpcDecoder.class), classWildcardTyped)); + + injectDependencies(typeSpecBuilder) .addMethod(generateDecodeMethod(context, classWildcardTyped)); JavaFile.builder( @@ -99,11 +104,26 @@ private MethodSpec generateDecodeMethod(ProcessorContext context, TypeName class return methodSpec.build(); } + private TypeSpec.Builder injectDependencies(TypeSpec.Builder typeSpecBuilder) { + val ctor = MethodSpec.constructorBuilder() + .addModifiers(Modifier.PUBLIC) + .addParameter(RpcDecoderContext.class, CONTEXT) + .beginControlFlow("if ($L == null)", CONTEXT) + .addStatement("throw new $T(\"$L can't be null.\")", IllegalArgumentException.class, CONTEXT) + .endControlFlow() + .addStatement("this.$L = $L.getRpcDecoderRegistry()", DECODER_REGISTRY, CONTEXT) + .addStatement("this.$L = $L.getScaleReaderRegistry()", SCALE_READER_REGISTRY, CONTEXT) + .build(); + + return typeSpecBuilder + .addField(RpcDecoderRegistry.class, DECODER_REGISTRY, Modifier.PRIVATE, Modifier.FINAL) + .addField(ScaleReaderRegistry.class, SCALE_READER_REGISTRY, Modifier.PRIVATE, Modifier.FINAL) + .addMethod(ctor); + } + private void addMethodBody(MethodSpec.Builder methodSpec, ProcessorContext context) throws ProcessingException { val resultType = JavaPoet.setEachGenericParameterAs(classElement, TypeName.OBJECT); methodSpec - .addStatement("$1T $2L = $1T.getInstance()", RpcDecoderRegistry.class, DECODER_REGISTRY) - .addStatement("$1T $2L = $1T.getInstance()", ScaleReaderRegistry.class, SCALE_READER_REGISTRY) .addStatement("$T<$T, $T> $L = $L.asMap()", Map.class, String.class, RpcObject.class, MAP_VAR, VALUE_ARG) .addStatement("$1T $2L = new $1T()", resultType, RESULT_VAR) .beginControlFlow("try"); @@ -134,11 +154,11 @@ private void setFields(MethodSpec.Builder methodSpec, ProcessorContext context) SCALE_READER_REGISTRY); for (VariableElement field : fields) { - if (field.getAnnotation(Ignore.class) != null) { + if (AnnotationUtils.isAnnotatedWith(field, Ignore.class)) { continue; } - if (field.getAnnotation(Scale.class) != null || field.getAnnotation(ScaleGeneric.class) != null) { + if (AnnotationUtils.isAnnotatedWithAny(field, Scale.class, ScaleGeneric.class)) { setScaleField(methodSpec, context, field, scaleAnnotationParser, scaleReaderCompositor); } else { setField(methodSpec, field, context, decoderCompositor); diff --git a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/decoder/RpcDecoderProcessor.java b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/decoder/RpcDecoderProcessor.java index 24156fb6..31edceb6 100644 --- a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/decoder/RpcDecoderProcessor.java +++ b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/decoder/RpcDecoderProcessor.java @@ -3,17 +3,18 @@ import com.google.auto.service.AutoService; import com.strategyobject.substrateclient.common.codegen.ProcessingException; import com.strategyobject.substrateclient.common.codegen.ProcessorContext; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcDecoder; +import com.strategyobject.substrateclient.rpc.annotation.RpcDecoder; import lombok.val; import javax.annotation.processing.*; import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.TypeElement; import java.io.IOException; import java.util.Set; -@SupportedAnnotationTypes("com.strategyobject.substrateclient.rpc.core.annotations.RpcDecoder") +@SupportedAnnotationTypes("com.strategyobject.substrateclient.rpc.annotation.RpcDecoder") @SupportedSourceVersion(SourceVersion.RELEASE_8) @AutoService(Processor.class) public class RpcDecoderProcessor extends AbstractProcessor { @@ -34,7 +35,7 @@ public boolean process(Set annotations, RoundEnvironment return false; } - for (val annotatedElement : roundEnv.getElementsAnnotatedWith(RpcDecoder.class)) { + for (Element annotatedElement : roundEnv.getElementsAnnotatedWith(RpcDecoder.class)) { if (annotatedElement.getKind() != ElementKind.CLASS) { context.error( annotatedElement, diff --git a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/encoder/EncoderCompositor.java b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/encoder/EncoderCompositor.java index 158876ea..c4cfcf9b 100644 --- a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/encoder/EncoderCompositor.java +++ b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/encoder/EncoderCompositor.java @@ -1,12 +1,12 @@ package com.strategyobject.substrateclient.rpc.codegen.encoder; import com.squareup.javapoet.CodeBlock; -import com.strategyobject.substrateclient.common.codegen.Constants; import com.strategyobject.substrateclient.common.codegen.ProcessorContext; import com.strategyobject.substrateclient.common.codegen.TypeTraverser; -import com.strategyobject.substrateclient.rpc.core.EncoderPair; -import com.strategyobject.substrateclient.rpc.core.RpcEncoder; -import com.strategyobject.substrateclient.rpc.core.RpcRegistryHelper; +import com.strategyobject.substrateclient.common.types.Array; +import com.strategyobject.substrateclient.rpc.EncoderPair; +import com.strategyobject.substrateclient.rpc.RpcEncoder; +import com.strategyobject.substrateclient.rpc.RpcRegistryHelper; import com.strategyobject.substrateclient.scale.ScaleRegistryHelper; import com.strategyobject.substrateclient.scale.ScaleWriter; import lombok.NonNull; @@ -21,7 +21,6 @@ public class EncoderCompositor extends TypeTraverser { private final ProcessorContext context; private final Map typeVarMap; - private final TypeMirror selfEncodable; private final String encoderAccessor; private final String writerAccessor; private final String writerMethod; @@ -39,23 +38,18 @@ public EncoderCompositor(@NonNull ProcessorContext context, super(CodeBlock.class); this.context = context; this.typeVarMap = typeVarMap; - this.selfEncodable = context.erasure(context.getType(RPC_SELF_ENCODABLE)); this.encoderAccessor = encoderAccessor; this.writerAccessor = writerAccessor; this.writerMethod = writerMethod; this.encoderRegistryVarName = encoderRegistryVarName; this.scaleRegistryVarName = scaleRegistryVarName; - this.arrayType = context.erasure(context.getType(Constants.ARRAY_TYPE)); + this.arrayType = context.erasure(context.getType(Array.class)); } private CodeBlock getNonGenericCodeBlock(TypeMirror type) { return CodeBlock.builder() .add("$T.$L(($T) ", EncoderPair.class, PAIR_FACTORY_METHOD, RpcEncoder.class) - .add("$L.resolve($T.class)", - encoderRegistryVarName, - context.isAssignable(type, selfEncodable) ? - selfEncodable : - type) + .add("$L.resolve($T.class)", encoderRegistryVarName, type) .add(", ($T) ", ScaleWriter.class) .add("$L.resolve($T.class)", scaleRegistryVarName, type) .add(")") @@ -65,41 +59,45 @@ private CodeBlock getNonGenericCodeBlock(TypeMirror type) { private CodeBlock getGenericCodeBlock(TypeMirror type, CodeBlock[] subtypes) { TypeMirror resolveType = context.erasure(type); val builder = CodeBlock.builder() - .add("$T.$L(", EncoderPair.class, PAIR_FACTORY_METHOD); - - if (context.isAssignable(resolveType, selfEncodable)) { - builder.add("($T) registry.resolve($T.class)", selfEncodable, RpcEncoder.class); - } else { - builder.add("$T.$L($T.class, ", RpcRegistryHelper.class, RESOLVE_AND_INJECT_METHOD, resolveType); - for (var i = 0; i < subtypes.length; i++) { - if (i > 0) builder.add(", "); - builder.add(subtypes[i]); - } + .add("$T.$L(", EncoderPair.class, PAIR_FACTORY_METHOD) + .add("$T.$L($L, $T.class, ", + RpcRegistryHelper.class, + RESOLVE_AND_INJECT_METHOD, + encoderRegistryVarName, + resolveType); + + for (var i = 0; i < subtypes.length; i++) { + if (i > 0) builder.add(", "); + builder.add(subtypes[i]); } - builder.add("), $T.$L($T.class, ", ScaleRegistryHelper.class, RESOLVE_AND_INJECT_METHOD, resolveType); + builder.add("), $T.$L($L, $T.class, ", + ScaleRegistryHelper.class, + RESOLVE_AND_INJECT_METHOD, + scaleRegistryVarName, + resolveType); + for (var i = 0; i < subtypes.length; i++) { if (i > 0) builder.add(", "); builder.add(subtypes[i]); builder.add(".$L", writerMethod); } - builder.add(")"); - return builder.add(")").build(); + return builder.add("))").build(); } @Override - protected CodeBlock whenTypeVar(@NonNull TypeVariable type, TypeMirror _override) { - val builder = CodeBlock.builder() - .add("$T.$L(($T) ", EncoderPair.class, PAIR_FACTORY_METHOD, RpcEncoder.class); - - if (context.isAssignable(type, selfEncodable)) { - builder.add("$L.resolve($T.class)", encoderRegistryVarName, selfEncodable); - } else { - builder.add(encoderAccessor, typeVarMap.get(type.toString())); - } + protected CodeBlock whenWildcard(TypeMirror override) { + return CodeBlock.builder() + .add("$L.resolve($T.class)", encoderRegistryVarName, RPC_DISPATCH) + .build(); + } - return builder.add(", ($T) ", ScaleWriter.class) + @Override + protected CodeBlock whenTypeVar(@NonNull TypeVariable type, TypeMirror _override) { + return CodeBlock.builder() + .add("$T.$L(($T) ", EncoderPair.class, PAIR_FACTORY_METHOD, RpcEncoder.class) + .add(encoderAccessor, typeVarMap.get(type.toString())).add(", ($T) ", ScaleWriter.class) .add(writerAccessor, typeVarMap.get(type.toString())) .add(")") .build(); @@ -129,9 +127,4 @@ protected CodeBlock whenArrayPrimitiveType(@NonNull ArrayType type, TypeMirror _ protected CodeBlock whenArrayType(@NonNull ArrayType type, TypeMirror _override, @NonNull CodeBlock subtype) { return getGenericCodeBlock(arrayType, new CodeBlock[]{subtype}); } - - @Override - protected boolean doTraverseArguments(@NonNull DeclaredType type, TypeMirror override) { - return override != null || !context.isAssignable(context.erasure(type), selfEncodable); - } } diff --git a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/encoder/RpcEncoderAnnotatedClass.java b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/encoder/RpcEncoderAnnotatedClass.java index 5cc2c689..9d4ea9aa 100644 --- a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/encoder/RpcEncoderAnnotatedClass.java +++ b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/encoder/RpcEncoderAnnotatedClass.java @@ -1,18 +1,20 @@ package com.strategyobject.substrateclient.rpc.codegen.encoder; import com.squareup.javapoet.*; +import com.strategyobject.substrateclient.common.codegen.AnnotationUtils; import com.strategyobject.substrateclient.common.codegen.JavaPoet; import com.strategyobject.substrateclient.common.codegen.ProcessingException; import com.strategyobject.substrateclient.common.codegen.ProcessorContext; -import com.strategyobject.substrateclient.rpc.core.EncoderPair; -import com.strategyobject.substrateclient.rpc.core.RpcEncoder; -import com.strategyobject.substrateclient.rpc.core.annotations.AutoRegister; -import com.strategyobject.substrateclient.rpc.core.annotations.Ignore; -import com.strategyobject.substrateclient.rpc.core.registries.RpcEncoderRegistry; +import com.strategyobject.substrateclient.rpc.EncoderPair; +import com.strategyobject.substrateclient.rpc.RpcEncoder; +import com.strategyobject.substrateclient.rpc.annotation.AutoRegister; +import com.strategyobject.substrateclient.rpc.annotation.Ignore; +import com.strategyobject.substrateclient.rpc.context.RpcEncoderContext; +import com.strategyobject.substrateclient.rpc.registries.RpcEncoderRegistry; import com.strategyobject.substrateclient.scale.ScaleUtils; import com.strategyobject.substrateclient.scale.ScaleWriter; -import com.strategyobject.substrateclient.scale.annotations.Scale; -import com.strategyobject.substrateclient.scale.annotations.ScaleGeneric; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleGeneric; import com.strategyobject.substrateclient.scale.codegen.ScaleAnnotationParser; import com.strategyobject.substrateclient.scale.codegen.writer.WriterCompositor; import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; @@ -44,6 +46,7 @@ public class RpcEncoderAnnotatedClass { private static final String ENCODER_NAME_TEMPLATE = "%sEncoder"; private static final String SOURCE_ARG = "source"; private static final String RESULT_VAR = "result"; + private static final String CONTEXT = "context"; private final TypeElement classElement; private final Map typeVarMap; private final List fields; @@ -56,7 +59,7 @@ public RpcEncoderAnnotatedClass(@NonNull TypeElement classElement) { .collect(toMap(i -> typeParameters.get(i).toString(), Function.identity())); fields = classElement.getEnclosedElements().stream() .filter(e -> e.getKind() == ElementKind.FIELD) - .map(e -> (VariableElement) e) + .map(VariableElement.class::cast) .collect(Collectors.toList()); } @@ -69,7 +72,9 @@ public void generateEncoder(@NonNull ProcessorContext context) throws Processing .addMember(AUTO_REGISTER_TYPES_ARG, "{$L.class}", classElement.getQualifiedName().toString()) .build()) .addModifiers(Modifier.PUBLIC) - .addSuperinterface(ParameterizedTypeName.get(ClassName.get(RpcEncoder.class), classWildcardTyped)) + .addSuperinterface(ParameterizedTypeName.get(ClassName.get(RpcEncoder.class), classWildcardTyped)); + + injectDependencies(typeSpecBuilder) .addMethod(generateEncodeMethod(context, classWildcardTyped)); JavaFile.builder( @@ -78,6 +83,23 @@ public void generateEncoder(@NonNull ProcessorContext context) throws Processing ).build().writeTo(context.getFiler()); } + private TypeSpec.Builder injectDependencies(TypeSpec.Builder typeSpecBuilder) { + val ctor = MethodSpec.constructorBuilder() + .addModifiers(Modifier.PUBLIC) + .addParameter(RpcEncoderContext.class, CONTEXT) + .beginControlFlow("if ($L == null)", CONTEXT) + .addStatement("throw new $T(\"$L can't be null.\")", IllegalArgumentException.class, CONTEXT) + .endControlFlow() + .addStatement("this.$L = $L.getRpcEncoderRegistry()", ENCODER_REGISTRY, CONTEXT) + .addStatement("this.$L = $L.getScaleWriterRegistry()", SCALE_WRITER_REGISTRY, CONTEXT) + .build(); + + return typeSpecBuilder + .addField(RpcEncoderRegistry.class, ENCODER_REGISTRY, Modifier.PRIVATE, Modifier.FINAL) + .addField(ScaleWriterRegistry.class, SCALE_WRITER_REGISTRY, Modifier.PRIVATE, Modifier.FINAL) + .addMethod(ctor); + } + private MethodSpec generateEncodeMethod(ProcessorContext context, TypeName classWildcardTyped) throws ProcessingException { val methodSpec = MethodSpec.methodBuilder(ENCODE_METHOD_NAME) .addAnnotation(Override.class) @@ -93,7 +115,7 @@ private MethodSpec generateEncodeMethod(ProcessorContext context, TypeName class .varargs(true); shortcutIfNull(methodSpec); - addValidationRules(methodSpec, context); + addValidationRules(methodSpec); addMethodBody(methodSpec, context); return methodSpec.build(); @@ -101,8 +123,6 @@ private MethodSpec generateEncodeMethod(ProcessorContext context, TypeName class private void addMethodBody(MethodSpec.Builder methodSpec, ProcessorContext context) throws ProcessingException { methodSpec - .addStatement("$1T $2L = $1T.getInstance()", RpcEncoderRegistry.class, ENCODER_REGISTRY) - .addStatement("$1T $2L = $1T.getInstance()", ScaleWriterRegistry.class, SCALE_WRITER_REGISTRY) .addStatement("$1T<$2T, $3T> $4L = new $1T<>()", HashMap.class, String.class, Object.class, RESULT_VAR) .beginControlFlow("try"); @@ -130,11 +150,11 @@ private void setFields(MethodSpec.Builder methodSpec, ProcessorContext context) SCALE_WRITER_REGISTRY); for (VariableElement field : fields) { - if (field.getAnnotation(Ignore.class) != null) { + if (AnnotationUtils.isAnnotatedWith(field, Ignore.class)) { continue; } - if (field.getAnnotation(Scale.class) != null || field.getAnnotation(ScaleGeneric.class) != null) { + if (AnnotationUtils.isAnnotatedWithAny(field, Scale.class, ScaleGeneric.class)) { setScaleField(methodSpec, field, scaleAnnotationParser, scaleWriterCompositor); } else { setField(methodSpec, field, context, encoderCompositor); @@ -210,9 +230,9 @@ private void setScaleField(MethodSpec.Builder methodSpec, } - private void addValidationRules(MethodSpec.Builder methodSpec, ProcessorContext context) { + private void addValidationRules(MethodSpec.Builder methodSpec) { val classTypeParametersSize = classElement.getTypeParameters().size(); - if (classTypeParametersSize == 0 || context.isAssignable(classElement.asType(), context.erasure(context.getType(RPC_SELF_ENCODABLE)))) { + if (classTypeParametersSize == 0) { methodSpec.addStatement("if ($1L != null && $1L.length > 0) throw new $2T()", ENCODERS_ARG, IllegalArgumentException.class); } else { methodSpec diff --git a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/encoder/RpcEncoderProcessor.java b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/encoder/RpcEncoderProcessor.java index 374bbd4d..ab8b4ed1 100644 --- a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/encoder/RpcEncoderProcessor.java +++ b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/encoder/RpcEncoderProcessor.java @@ -3,17 +3,18 @@ import com.google.auto.service.AutoService; import com.strategyobject.substrateclient.common.codegen.ProcessingException; import com.strategyobject.substrateclient.common.codegen.ProcessorContext; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcEncoder; +import com.strategyobject.substrateclient.rpc.annotation.RpcEncoder; import lombok.val; import javax.annotation.processing.*; import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.TypeElement; import java.io.IOException; import java.util.Set; -@SupportedAnnotationTypes("com.strategyobject.substrateclient.rpc.core.annotations.RpcEncoder") +@SupportedAnnotationTypes("com.strategyobject.substrateclient.rpc.annotation.RpcEncoder") @SupportedSourceVersion(SourceVersion.RELEASE_8) @AutoService(Processor.class) public class RpcEncoderProcessor extends AbstractProcessor { @@ -34,7 +35,7 @@ public boolean process(Set annotations, RoundEnvironment return false; } - for (val annotatedElement : roundEnv.getElementsAnnotatedWith(RpcEncoder.class)) { + for (Element annotatedElement : roundEnv.getElementsAnnotatedWith(RpcEncoder.class)) { if (annotatedElement.getKind() != ElementKind.CLASS) { context.error( annotatedElement, diff --git a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/Constants.java b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/Constants.java index b16ddb9c..e841db2a 100644 --- a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/Constants.java +++ b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/Constants.java @@ -13,4 +13,7 @@ class Constants { public static final String UNSUBSCRIBE = "unsubscribe"; static final String THEN_APPLY_ASYNC = "thenApplyAsync"; static final String ACCEPT = "accept"; + + private Constants() { + } } diff --git a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcAnnotatedInterface.java b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcAnnotatedInterface.java index 2c1a19ee..f33d83ac 100644 --- a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcAnnotatedInterface.java +++ b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcAnnotatedInterface.java @@ -7,16 +7,22 @@ import com.squareup.javapoet.TypeSpec; import com.strategyobject.substrateclient.common.codegen.ProcessingException; import com.strategyobject.substrateclient.common.codegen.ProcessorContext; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcInterface; +import com.strategyobject.substrateclient.rpc.annotation.RpcInterface; +import com.strategyobject.substrateclient.rpc.registries.RpcDecoderRegistry; +import com.strategyobject.substrateclient.rpc.registries.RpcEncoderRegistry; +import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; +import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; import com.strategyobject.substrateclient.transport.ProviderInterface; import lombok.NonNull; import lombok.val; +import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; import java.io.IOException; +import static com.strategyobject.substrateclient.rpc.codegen.Constants.*; import static com.strategyobject.substrateclient.rpc.codegen.sections.Constants.CLASS_NAME_TEMPLATE; import static com.strategyobject.substrateclient.rpc.codegen.sections.Constants.PROVIDER_INTERFACE; @@ -58,9 +64,13 @@ public void generateClass(@NonNull ProcessorContext context) .addModifiers(Modifier.PUBLIC, Modifier.FINAL) .addSuperinterface(TypeName.get(interfaceElement.asType())) .addField(ProviderInterface.class, PROVIDER_INTERFACE) + .addField(RpcEncoderRegistry.class, ENCODER_REGISTRY) + .addField(ScaleWriterRegistry.class, SCALE_WRITER_REGISTRY) + .addField(RpcDecoderRegistry.class, DECODER_REGISTRY) + .addField(ScaleReaderRegistry.class, SCALE_READER_REGISTRY) .addMethod(createConstructor()); - for (val method : interfaceElement.getEnclosedElements()) { + for (Element method : interfaceElement.getEnclosedElements()) { methodProcessor.process(section, (ExecutableElement) method, typeSpecBuilder, context); } @@ -68,13 +78,31 @@ public void generateClass(@NonNull ProcessorContext context) } private MethodSpec createConstructor() { - return MethodSpec.constructorBuilder() + val methodSpec = MethodSpec.constructorBuilder() .addModifiers(Modifier.PUBLIC) .addParameter(ProviderInterface.class, PROVIDER_INTERFACE) - .beginControlFlow("if ($L == null)", PROVIDER_INTERFACE) - .addStatement("throw new $T(\"$L can't be null.\")", IllegalArgumentException.class, PROVIDER_INTERFACE) - .endControlFlow() - .addStatement("this.$1L = $1L", PROVIDER_INTERFACE) - .build(); + .addParameter(RpcEncoderRegistry.class, ENCODER_REGISTRY) + .addParameter(ScaleWriterRegistry.class, SCALE_WRITER_REGISTRY) + .addParameter(RpcDecoderRegistry.class, DECODER_REGISTRY) + .addParameter(ScaleReaderRegistry.class, SCALE_READER_REGISTRY); + + assignParameters(methodSpec, + PROVIDER_INTERFACE, + ENCODER_REGISTRY, + SCALE_WRITER_REGISTRY, + DECODER_REGISTRY, + SCALE_READER_REGISTRY); + + return methodSpec.build(); + } + + private void assignParameters(MethodSpec.Builder methodSpec, String... parameters) { + for (val parameter : parameters) { + methodSpec + .beginControlFlow("if ($L == null)", parameter) + .addStatement("throw new $T(\"$L can't be null.\")", IllegalArgumentException.class, parameter) + .endControlFlow() + .addStatement("this.$1L = $1L", parameter); + } } } diff --git a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcCallProcessor.java b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcCallProcessor.java index 621ec438..4abae637 100644 --- a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcCallProcessor.java +++ b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcCallProcessor.java @@ -5,7 +5,7 @@ import com.squareup.javapoet.MethodSpec; import com.strategyobject.substrateclient.common.codegen.ProcessingException; import com.strategyobject.substrateclient.common.codegen.ProcessorContext; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcCall; +import com.strategyobject.substrateclient.rpc.annotation.RpcCall; import lombok.NonNull; import lombok.val; @@ -41,7 +41,7 @@ protected void ensureAnnotationIsFilled(ExecutableElement method, RpcCall method @Override protected void onProcessStarting(ProcessorContext context) { - + // This should be empty } @Override @@ -52,7 +52,7 @@ protected void callProviderInterface(MethodSpec.Builder methodSpecBuilder, ProcessorContext context, BiFunction decoder) { val rpcMethodName = String.format(RPC_METHOD_NAME_TEMPLATE, section, annotation.value()); - val paramsArgument = method.getParameters().size() == 0 ? "" : String.format(", %s", PARAMS_VAR); + val paramsArgument = method.getParameters().isEmpty() ? "" : String.format(", %s", PARAMS_VAR); val isReturnVoid = isReturnVoid(method, context); val code = CodeBlock.builder() @@ -70,11 +70,6 @@ protected void callProviderInterface(MethodSpec.Builder methodSpecBuilder, methodSpecBuilder.addStatement(code.build()); } - @Override - protected boolean useDecodeRegistries(ExecutableElement method, ProcessorContext context) { - return !isReturnVoid(method, context); - } - @Override protected boolean shouldBePassedToProvider(ExecutableElement method, VariableElement param, ProcessorContext context) { return true; @@ -82,6 +77,7 @@ protected boolean shouldBePassedToProvider(ExecutableElement method, VariableEle @Override protected void onParametersVisited(ExecutableElement method) { + // This should be empty } @Override diff --git a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcInterfaceMethodValidatingProcessor.java b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcInterfaceMethodValidatingProcessor.java index d97e9b6d..e5062502 100644 --- a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcInterfaceMethodValidatingProcessor.java +++ b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcInterfaceMethodValidatingProcessor.java @@ -1,10 +1,11 @@ package com.strategyobject.substrateclient.rpc.codegen.sections; import com.squareup.javapoet.TypeSpec; +import com.strategyobject.substrateclient.common.codegen.AnnotationUtils; import com.strategyobject.substrateclient.common.codegen.ProcessingException; import com.strategyobject.substrateclient.common.codegen.ProcessorContext; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcCall; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcSubscription; +import com.strategyobject.substrateclient.rpc.annotation.RpcCall; +import com.strategyobject.substrateclient.rpc.annotation.RpcSubscription; import lombok.NonNull; import lombok.val; @@ -29,12 +30,10 @@ void process(@NonNull String section, private void ensureMethodIsNotAbstractOrProperlyAnnotated(Element method) throws ProcessingException { val modifiers = method.getModifiers(); - val requiresMethod = method.getAnnotation(RpcCall.class) != null; - val requiresSubscription = method.getAnnotation(RpcSubscription.class) != null; // Ensure method is not abstract or annotated with `RpcMethod` or `RpcSubscription` if (!(modifiers.contains(Modifier.STATIC) || modifiers.contains(Modifier.DEFAULT)) - && !(requiresMethod || requiresSubscription)) { + && !AnnotationUtils.isAnnotatedWithAny(method, RpcCall.class, RpcSubscription.class)) { throw new ProcessingException( interfaceElement, "Method `%s` can't be constructed because it doesn't have `@%s` or `@%s` annotation.", @@ -44,7 +43,7 @@ private void ensureMethodIsNotAbstractOrProperlyAnnotated(Element method) throws } // Ensure method doesn't have ambiguous annotations - if (requiresMethod && requiresSubscription) { + if (AnnotationUtils.isAnnotatedWithAll(method, RpcCall.class, RpcSubscription.class)) { throw new ProcessingException( interfaceElement, "Method `%s` can't be constructed because it has ambiguous annotations. Only one of `@%s` and `@%s` should be chosen.", diff --git a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcInterfaceProcessor.java b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcInterfaceProcessor.java index 29e86679..5ee2dd6f 100644 --- a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcInterfaceProcessor.java +++ b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcInterfaceProcessor.java @@ -3,18 +3,19 @@ import com.google.auto.service.AutoService; import com.strategyobject.substrateclient.common.codegen.ProcessingException; import com.strategyobject.substrateclient.common.codegen.ProcessorContext; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcInterface; +import com.strategyobject.substrateclient.rpc.annotation.RpcInterface; import lombok.val; import javax.annotation.processing.*; import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.TypeElement; import java.io.IOException; import java.util.Arrays; import java.util.Set; -@SupportedAnnotationTypes("com.strategyobject.substrateclient.rpc.core.annotations.RpcInterface") +@SupportedAnnotationTypes("com.strategyobject.substrateclient.rpc.annotation.RpcInterface") @SupportedSourceVersion(SourceVersion.RELEASE_8) @AutoService(Processor.class) public class RpcInterfaceProcessor extends AbstractProcessor { @@ -35,7 +36,7 @@ public boolean process(Set annotations, RoundEnvironment return false; } - for (val annotatedElement : roundEnv.getElementsAnnotatedWith(RpcInterface.class)) { + for (Element annotatedElement : roundEnv.getElementsAnnotatedWith(RpcInterface.class)) { if (annotatedElement.getKind() != ElementKind.INTERFACE) { context.error( annotatedElement, diff --git a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcMethodProcessor.java b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcMethodProcessor.java index 200d8faf..4f465a55 100644 --- a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcMethodProcessor.java +++ b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcMethodProcessor.java @@ -4,23 +4,20 @@ import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; +import com.strategyobject.substrateclient.common.codegen.AnnotationUtils; import com.strategyobject.substrateclient.common.codegen.ProcessingException; import com.strategyobject.substrateclient.common.codegen.ProcessorContext; +import com.strategyobject.substrateclient.rpc.RpcDecoder; import com.strategyobject.substrateclient.rpc.codegen.decoder.DecoderCompositor; import com.strategyobject.substrateclient.rpc.codegen.encoder.EncoderCompositor; -import com.strategyobject.substrateclient.rpc.core.RpcDecoder; -import com.strategyobject.substrateclient.rpc.core.registries.RpcDecoderRegistry; -import com.strategyobject.substrateclient.rpc.core.registries.RpcEncoderRegistry; import com.strategyobject.substrateclient.scale.ScaleReader; import com.strategyobject.substrateclient.scale.ScaleUtils; import com.strategyobject.substrateclient.scale.ScaleWriter; -import com.strategyobject.substrateclient.scale.annotations.Scale; -import com.strategyobject.substrateclient.scale.annotations.ScaleGeneric; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleGeneric; import com.strategyobject.substrateclient.scale.codegen.ScaleAnnotationParser; import com.strategyobject.substrateclient.scale.codegen.reader.ReaderCompositor; import com.strategyobject.substrateclient.scale.codegen.writer.WriterCompositor; -import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; -import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; import lombok.NonNull; import lombok.val; @@ -93,10 +90,6 @@ private void sendRequest(MethodSpec.Builder methodSpecBuilder, A annotation, ScaleAnnotationParser scaleAnnotationParser, ProcessorContext context) { - if (useDecodeRegistries(method, context)) { - declareDecoderAndReaderRegistries(methodSpecBuilder); - } - callProviderInterface(methodSpecBuilder, method, section, @@ -117,7 +110,7 @@ private CodeBlock getDecodeCodeBlock(AnnotatedConstruct annotated, String arg, ScaleAnnotationParser scaleAnnotationParser, ProcessorContext context) { - return annotated.getAnnotation(Scale.class) != null || annotated.getAnnotation(ScaleGeneric.class) != null ? + return AnnotationUtils.isAnnotatedWithAny(annotated, Scale.class, ScaleGeneric.class) ? getScaleReadCodeBlock(annotated, resultType, arg, scaleAnnotationParser, context) : getRpcDecodeCodeBlock(resultType, arg, context); } @@ -163,8 +156,6 @@ private CodeBlock getScaleReadCodeBlock(AnnotatedConstruct annotated, .build(); } - protected abstract boolean useDecodeRegistries(ExecutableElement method, ProcessorContext context); - private void processParameters(MethodSpec.Builder methodSpecBuilder, ExecutableElement method, ScaleAnnotationParser scaleAnnotationParser, @@ -175,8 +166,7 @@ private void processParameters(MethodSpec.Builder methodSpecBuilder, return; } - val writerCompositor = WriterCompositor.disallowOpenGeneric(context, - SCALE_WRITER_REGISTRY); + val writerCompositor = WriterCompositor.disallowOpenGeneric(context, SCALE_WRITER_REGISTRY); val encoderCompositor = new EncoderCompositor( context, EMPTY_TYPE_VAR_MAP, @@ -186,14 +176,11 @@ private void processParameters(MethodSpec.Builder methodSpecBuilder, ENCODER_REGISTRY, SCALE_WRITER_REGISTRY); - methodSpecBuilder - .addStatement("$1T<$2T> $3L = new $4T<$2T>()", - List.class, - Object.class, - PARAMS_VAR, - ArrayList.class) - .addStatement("$1T $2L = $1T.getInstance()", RpcEncoderRegistry.class, ENCODER_REGISTRY) - .addStatement("$1T $2L = $1T.getInstance()", ScaleWriterRegistry.class, SCALE_WRITER_REGISTRY); + methodSpecBuilder.addStatement("$1T<$2T> $3L = new $4T<$2T>()", + List.class, + Object.class, + PARAMS_VAR, + ArrayList.class); for (val param : method.getParameters()) { try { @@ -218,7 +205,7 @@ private void processParameter(MethodSpec.Builder methodSpecBuilder, if (shouldBePassedToProvider(method, param, context)) { CodeBlock encodeBlock; - if (param.getAnnotation(Scale.class) != null || param.getAnnotation(ScaleGeneric.class) != null) { + if (AnnotationUtils.isAnnotatedWithAny(param, Scale.class, ScaleGeneric.class)) { encodeBlock = getScaleWriteCodeBlock(param, scaleAnnotationParser, writerCompositor); } else { encodeBlock = getRpcEncodeCodeBlock(param, encoderCompositor); @@ -262,12 +249,6 @@ private CodeBlock getRpcEncodeCodeBlock(VariableElement param, protected abstract void onParametersVisited(ExecutableElement method) throws ProcessingException; - private void declareDecoderAndReaderRegistries(MethodSpec.Builder methodSpecBuilder) { - methodSpecBuilder - .addStatement("$1T $2L = $1T.getInstance()", RpcDecoderRegistry.class, DECODER_REGISTRY) - .addStatement("$1T $2L = $1T.getInstance()", ScaleReaderRegistry.class, SCALE_READER_REGISTRY); - } - protected abstract void ensureMethodHasAppropriateReturnType(ExecutableElement method, TypeMirror returnType, ProcessorContext context) throws ProcessingException; protected abstract void ensureAnnotationIsFilled(ExecutableElement method, A annotation) throws ProcessingException; diff --git a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcSubscriptionProcessor.java b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcSubscriptionProcessor.java index 5bf0f3b1..e2003715 100644 --- a/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcSubscriptionProcessor.java +++ b/rpc/rpc-codegen/src/main/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcSubscriptionProcessor.java @@ -5,7 +5,7 @@ import com.squareup.javapoet.MethodSpec; import com.strategyobject.substrateclient.common.codegen.ProcessingException; import com.strategyobject.substrateclient.common.codegen.ProcessorContext; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcSubscription; +import com.strategyobject.substrateclient.rpc.annotation.RpcSubscription; import com.strategyobject.substrateclient.transport.RpcObject; import lombok.NonNull; import lombok.val; @@ -56,15 +56,17 @@ protected void callProviderInterface(MethodSpec.Builder methodSpecBuilder, val unsubscribeMethod = String.format(RPC_METHOD_NAME_TEMPLATE, section, annotation.unsubscribeMethod()); val callBackCode = CodeBlock.builder() - .add("$1T<$2T, $3T> $4L = ($5L, $6L) -> { $7N.$8L($5L, ", + .add("$T<$T, $T> $L = ($L, $L) -> { ", BiConsumer.class, Exception.class, RpcObject.class, CALL_BACK_PROXY, CALL_BACK_EX_ARG, - CALL_BACK_ARG, - callbackName, - ACCEPT); + CALL_BACK_ARG) + .beginControlFlow("if ($L != null)", CALL_BACK_EX_ARG) + .addStatement("$N.$L($L, null)", callbackName, ACCEPT, CALL_BACK_EX_ARG) + .nextControlFlow("else") + .add("$N.$L($L, ", callbackName, ACCEPT, CALL_BACK_EX_ARG); if (isCallbackResultVoid(context)) { callBackCode.add("null"); @@ -72,9 +74,13 @@ protected void callProviderInterface(MethodSpec.Builder methodSpecBuilder, callBackCode.add(decoder.apply(callbackParameter, CALL_BACK_ARG)); } - callBackCode.add("); }"); + callBackCode + .add(");") + .endControlFlow() + .addStatement("}"); - methodSpecBuilder.addStatement(callBackCode.build()) + methodSpecBuilder + .addCode(callBackCode.build()) .addStatement(CodeBlock.builder() .add("return $L.$L($S, $S, $L, $L)", PROVIDER_INTERFACE, @@ -93,11 +99,6 @@ protected void callProviderInterface(MethodSpec.Builder methodSpecBuilder, .build()); } - @Override - protected boolean useDecodeRegistries(ExecutableElement method, ProcessorContext context) { - return !isCallbackResultVoid(context); - } - @Override protected boolean shouldBePassedToProvider(ExecutableElement method, VariableElement param, ProcessorContext context) throws ProcessingException { val paramType = param.asType(); diff --git a/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/decoder/RpcDecoderProcessorTests.java b/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/decoder/RpcDecoderProcessorTests.java index 698277e0..95f3fb6c 100644 --- a/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/decoder/RpcDecoderProcessorTests.java +++ b/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/decoder/RpcDecoderProcessorTests.java @@ -2,9 +2,11 @@ import com.google.gson.Gson; import com.google.testing.compile.JavaFileObjects; +import com.strategyobject.substrateclient.rpc.DecoderPair; import com.strategyobject.substrateclient.rpc.codegen.substitutes.TestDecodable; -import com.strategyobject.substrateclient.rpc.core.DecoderPair; -import com.strategyobject.substrateclient.rpc.core.registries.RpcDecoderRegistry; +import com.strategyobject.substrateclient.rpc.context.RpcDecoderContext; +import com.strategyobject.substrateclient.rpc.registries.RpcDecoderRegistry; +import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; import com.strategyobject.substrateclient.transport.RpcObject; import lombok.val; import org.junit.jupiter.api.Test; @@ -15,8 +17,10 @@ import static com.google.testing.compile.CompilationSubject.assertThat; import static com.google.testing.compile.Compiler.javac; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; -public class RpcDecoderProcessorTests { +class RpcDecoderProcessorTests { private final Gson gson = new Gson(); @Test @@ -56,7 +60,12 @@ void compiles() { @Test void compilesAndDecodes() { // TODO move this test out of the project - val registry = RpcDecoderRegistry.getInstance(); + val registry = new RpcDecoderRegistry(); + val context = mock(RpcDecoderContext.class); + when(context.getRpcDecoderRegistry()).thenReturn(registry); + when(context.getScaleReaderRegistry()).thenReturn(new ScaleReaderRegistry()); + registry.registerAnnotatedFrom(() -> context, "com.strategyobject.substrateclient.rpc.codegen.substitutes"); + val decoder = registry.resolve(TestDecodable.class) .inject(DecoderPair.of(registry.resolve(String.class), null)); diff --git a/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/encoder/RpcEncoderProcessorTests.java b/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/encoder/RpcEncoderProcessorTests.java index e51de859..74048858 100644 --- a/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/encoder/RpcEncoderProcessorTests.java +++ b/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/encoder/RpcEncoderProcessorTests.java @@ -2,10 +2,12 @@ import com.google.gson.Gson; import com.google.testing.compile.JavaFileObjects; +import com.strategyobject.substrateclient.rpc.EncoderPair; +import com.strategyobject.substrateclient.rpc.RpcEncoder; import com.strategyobject.substrateclient.rpc.codegen.substitutes.TestEncodable; -import com.strategyobject.substrateclient.rpc.core.EncoderPair; -import com.strategyobject.substrateclient.rpc.core.RpcEncoder; -import com.strategyobject.substrateclient.rpc.core.registries.RpcEncoderRegistry; +import com.strategyobject.substrateclient.rpc.context.RpcEncoderContext; +import com.strategyobject.substrateclient.rpc.registries.RpcEncoderRegistry; +import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; import lombok.val; import org.junit.jupiter.api.Test; @@ -18,8 +20,10 @@ import static com.google.testing.compile.CompilationSubject.assertThat; import static com.google.testing.compile.Compiler.javac; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; -public class RpcEncoderProcessorTests { +class RpcEncoderProcessorTests { private final Gson gson = new Gson(); @Test @@ -60,7 +64,12 @@ void compiles() { @Test @SuppressWarnings("unchecked") void compilesAndDecodes() { // TODO move this test out of the project - val registry = RpcEncoderRegistry.getInstance(); + val registry = new RpcEncoderRegistry(); + val context = mock(RpcEncoderContext.class); + when(context.getRpcEncoderRegistry()).thenReturn(registry); + when(context.getScaleWriterRegistry()).thenReturn(new ScaleWriterRegistry()); + registry.registerAnnotatedFrom(() -> context, "com.strategyobject.substrateclient.rpc.codegen.substitutes"); + val encoder = (RpcEncoder>) registry.resolve(TestEncodable.class) .inject( EncoderPair.of( diff --git a/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcInterfaceProcessorTest.java b/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcInterfaceProcessorTest.java index f5436c74..ad40337e 100644 --- a/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcInterfaceProcessorTest.java +++ b/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcInterfaceProcessorTest.java @@ -1,8 +1,8 @@ package com.strategyobject.substrateclient.rpc.codegen.sections; import com.google.testing.compile.JavaFileObjects; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcCall; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcSubscription; +import com.strategyobject.substrateclient.rpc.annotation.RpcCall; +import com.strategyobject.substrateclient.rpc.annotation.RpcSubscription; import lombok.val; import org.junit.jupiter.api.Test; @@ -127,5 +127,9 @@ void compilesTestSection() { .compile(clazz); assertThat(compilation).succeeded(); + assertThat(compilation) + .generatedSourceFile("com.strategyobject.substrateclient.rpc.sections.TestSectionImpl") + .contentsAsUtf8String() + .contains("scaleWriterRegistry.resolve(TestDispatch.class))"); } } diff --git a/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcSectionFactoryTest.java b/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcSectionFactoryTest.java index a239d3e5..4ba1318b 100644 --- a/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcSectionFactoryTest.java +++ b/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/sections/RpcSectionFactoryTest.java @@ -1,8 +1,11 @@ package com.strategyobject.substrateclient.rpc.codegen.sections; +import com.strategyobject.substrateclient.rpc.GeneratedRpcSectionFactory; import com.strategyobject.substrateclient.rpc.codegen.substitutes.TestSection; -import com.strategyobject.substrateclient.rpc.core.RpcGeneratedSectionFactory; -import com.strategyobject.substrateclient.rpc.core.RpcInterfaceInitializationException; +import com.strategyobject.substrateclient.rpc.registries.RpcDecoderRegistry; +import com.strategyobject.substrateclient.rpc.registries.RpcEncoderRegistry; +import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; +import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; import com.strategyobject.substrateclient.transport.ProviderInterface; import com.strategyobject.substrateclient.transport.RpcBoolean; import com.strategyobject.substrateclient.transport.RpcObject; @@ -10,7 +13,6 @@ import org.junit.jupiter.api.Test; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.anyList; @@ -18,20 +20,26 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -public class RpcSectionFactoryTest { +class RpcSectionFactoryTest { // TODO move this test out of the project @Test - void createsRpcSectionAndCallsMethod() throws ExecutionException, InterruptedException, RpcInterfaceInitializationException { + void createsRpcSectionAndCallsMethod() throws Exception { val expected = true; val sendFuture = CompletableFuture.completedFuture((RpcObject) new RpcBoolean(expected)); val provider = mock(ProviderInterface.class); - when(provider.send(anyString(), anyList())) - .thenReturn(sendFuture); + when(provider.send(anyString(), anyList())).thenReturn(sendFuture); - val rpcSection = RpcGeneratedSectionFactory.create(TestSection.class, provider); + try (val rpcGeneratedSectionFactory = new GeneratedRpcSectionFactory( + provider, + new RpcEncoderRegistry(), + new ScaleWriterRegistry(), + new RpcDecoderRegistry(), + new ScaleReaderRegistry())) { + val rpcSection = rpcGeneratedSectionFactory.create(TestSection.class); - val actual = rpcSection.doNothing("some").get(); + val actual = rpcSection.doNothing("some").get(); - assertEquals(expected, actual); + assertEquals(expected, actual); + } } } diff --git a/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/substitutes/TestDecodable.java b/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/substitutes/TestDecodable.java index 4b19d390..ed434d68 100644 --- a/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/substitutes/TestDecodable.java +++ b/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/substitutes/TestDecodable.java @@ -1,7 +1,7 @@ package com.strategyobject.substrateclient.rpc.codegen.substitutes; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcDecoder; -import com.strategyobject.substrateclient.scale.annotations.Scale; +import com.strategyobject.substrateclient.rpc.annotation.RpcDecoder; +import com.strategyobject.substrateclient.scale.annotation.Scale; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; diff --git a/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/substitutes/TestDispatch.java b/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/substitutes/TestDispatch.java new file mode 100644 index 00000000..faffe6dc --- /dev/null +++ b/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/substitutes/TestDispatch.java @@ -0,0 +1,7 @@ +package com.strategyobject.substrateclient.rpc.codegen.substitutes; + +import com.strategyobject.substrateclient.scale.annotation.ScaleWriter; + +@ScaleWriter +public class TestDispatch { +} diff --git a/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/substitutes/TestEncodable.java b/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/substitutes/TestEncodable.java index 0c9b4ab2..423079d1 100644 --- a/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/substitutes/TestEncodable.java +++ b/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/substitutes/TestEncodable.java @@ -1,7 +1,7 @@ package com.strategyobject.substrateclient.rpc.codegen.substitutes; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcEncoder; -import com.strategyobject.substrateclient.scale.annotations.Scale; +import com.strategyobject.substrateclient.rpc.annotation.RpcEncoder; +import com.strategyobject.substrateclient.scale.annotation.Scale; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; diff --git a/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/substitutes/TestSection.java b/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/substitutes/TestSection.java index e6d60939..1f6d3d46 100644 --- a/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/substitutes/TestSection.java +++ b/rpc/rpc-codegen/src/test/java/com/strategyobject/substrateclient/rpc/codegen/substitutes/TestSection.java @@ -1,7 +1,7 @@ package com.strategyobject.substrateclient.rpc.codegen.substitutes; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcCall; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcInterface; +import com.strategyobject.substrateclient.rpc.annotation.RpcCall; +import com.strategyobject.substrateclient.rpc.annotation.RpcInterface; import java.util.concurrent.CompletableFuture; diff --git a/rpc/rpc-codegen/src/test/resources/ClassSection.java b/rpc/rpc-codegen/src/test/resources/ClassSection.java index 0ea3d33b..4c0c9a81 100644 --- a/rpc/rpc-codegen/src/test/resources/ClassSection.java +++ b/rpc/rpc-codegen/src/test/resources/ClassSection.java @@ -1,7 +1,7 @@ package com.strategyobject.substrateclient.rpc.sections; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcCall; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcInterface; +import com.strategyobject.substrateclient.rpc.annotation.RpcCall; +import com.strategyobject.substrateclient.rpc.annotation.RpcInterface; import java.util.concurrent.CompletableFuture; diff --git a/rpc/rpc-codegen/src/test/resources/NamelessSection.java b/rpc/rpc-codegen/src/test/resources/NamelessSection.java index c0811f03..133176ae 100644 --- a/rpc/rpc-codegen/src/test/resources/NamelessSection.java +++ b/rpc/rpc-codegen/src/test/resources/NamelessSection.java @@ -1,7 +1,7 @@ package com.strategyobject.substrateclient.rpc.sections; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcCall; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcInterface; +import com.strategyobject.substrateclient.rpc.annotation.RpcCall; +import com.strategyobject.substrateclient.rpc.annotation.RpcInterface; import java.util.concurrent.CompletableFuture; diff --git a/rpc/rpc-codegen/src/test/resources/RpcDecodable.java b/rpc/rpc-codegen/src/test/resources/RpcDecodable.java index f32d8350..4ea20f5e 100644 --- a/rpc/rpc-codegen/src/test/resources/RpcDecodable.java +++ b/rpc/rpc-codegen/src/test/resources/RpcDecodable.java @@ -1,5 +1,5 @@ -import com.strategyobject.substrateclient.rpc.core.annotations.RpcDecoder; -import com.strategyobject.substrateclient.scale.annotations.Scale; +import com.strategyobject.substrateclient.rpc.annotation.RpcDecoder; +import com.strategyobject.substrateclient.scale.annotation.Scale; @RpcDecoder public class RpcDecodable { diff --git a/rpc/rpc-codegen/src/test/resources/RpcDecodableInterface.java b/rpc/rpc-codegen/src/test/resources/RpcDecodableInterface.java index 4cf88508..89e17007 100644 --- a/rpc/rpc-codegen/src/test/resources/RpcDecodableInterface.java +++ b/rpc/rpc-codegen/src/test/resources/RpcDecodableInterface.java @@ -1,4 +1,4 @@ -import com.strategyobject.substrateclient.rpc.core.annotations.RpcDecoder; +import com.strategyobject.substrateclient.rpc.annotation.RpcDecoder; @RpcDecoder public interface RpcDecodableInterface { diff --git a/rpc/rpc-codegen/src/test/resources/RpcDecodableWithoutSetter.java b/rpc/rpc-codegen/src/test/resources/RpcDecodableWithoutSetter.java index 24e0fa63..6a96215c 100644 --- a/rpc/rpc-codegen/src/test/resources/RpcDecodableWithoutSetter.java +++ b/rpc/rpc-codegen/src/test/resources/RpcDecodableWithoutSetter.java @@ -1,5 +1,5 @@ -import com.strategyobject.substrateclient.rpc.core.annotations.RpcDecoder; -import com.strategyobject.substrateclient.rpc.core.annotations.Scale; +import com.strategyobject.substrateclient.rpc.annotation.RpcDecoder; +import com.strategyobject.substrateclient.rpc.annotation.Scale; @RpcDecoder public class RpcDecodableWithoutSetter { diff --git a/rpc/rpc-codegen/src/test/resources/RpcEncodable.java b/rpc/rpc-codegen/src/test/resources/RpcEncodable.java index ad41eff8..8d0a5dbf 100644 --- a/rpc/rpc-codegen/src/test/resources/RpcEncodable.java +++ b/rpc/rpc-codegen/src/test/resources/RpcEncodable.java @@ -1,5 +1,5 @@ -import com.strategyobject.substrateclient.rpc.core.annotations.RpcEncoder; -import com.strategyobject.substrateclient.scale.annotations.Scale; +import com.strategyobject.substrateclient.rpc.annotation.RpcEncoder; +import com.strategyobject.substrateclient.scale.annotation.Scale; @RpcEncoder public class RpcEncodable { diff --git a/rpc/rpc-codegen/src/test/resources/RpcEncodableInterface.java b/rpc/rpc-codegen/src/test/resources/RpcEncodableInterface.java index 0761301c..b8aaa600 100644 --- a/rpc/rpc-codegen/src/test/resources/RpcEncodableInterface.java +++ b/rpc/rpc-codegen/src/test/resources/RpcEncodableInterface.java @@ -1,4 +1,4 @@ -import com.strategyobject.substrateclient.rpc.core.annotations.RpcEncoder; +import com.strategyobject.substrateclient.rpc.annotation.RpcEncoder; @RpcEncoder public interface RpcEncodableInterface { diff --git a/rpc/rpc-codegen/src/test/resources/RpcEncodableWithoutGetter.java b/rpc/rpc-codegen/src/test/resources/RpcEncodableWithoutGetter.java index a2d3d2e9..1392189d 100644 --- a/rpc/rpc-codegen/src/test/resources/RpcEncodableWithoutGetter.java +++ b/rpc/rpc-codegen/src/test/resources/RpcEncodableWithoutGetter.java @@ -1,5 +1,5 @@ -import com.strategyobject.substrateclient.rpc.core.annotations.RpcEncoder; -import com.strategyobject.substrateclient.rpc.core.annotations.Scale; +import com.strategyobject.substrateclient.rpc.annotation.RpcEncoder; +import com.strategyobject.substrateclient.rpc.annotation.Scale; @RpcEncoder public class RpcEncodableWithoutGetter { diff --git a/rpc/rpc-codegen/src/test/resources/SectionWithAmbiguousAnnotatedMethod.java b/rpc/rpc-codegen/src/test/resources/SectionWithAmbiguousAnnotatedMethod.java index aa212251..10819ec2 100644 --- a/rpc/rpc-codegen/src/test/resources/SectionWithAmbiguousAnnotatedMethod.java +++ b/rpc/rpc-codegen/src/test/resources/SectionWithAmbiguousAnnotatedMethod.java @@ -1,8 +1,8 @@ package com.strategyobject.substrateclient.rpc.sections; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcCall; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcInterface; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcSubscription; +import com.strategyobject.substrateclient.rpc.annotation.RpcCall; +import com.strategyobject.substrateclient.rpc.annotation.RpcInterface; +import com.strategyobject.substrateclient.rpc.annotation.RpcSubscription; import java.util.concurrent.CompletableFuture; diff --git a/rpc/rpc-codegen/src/test/resources/SectionWithIncorrectReturnOfMethod.java b/rpc/rpc-codegen/src/test/resources/SectionWithIncorrectReturnOfMethod.java index d9bba444..b198a931 100644 --- a/rpc/rpc-codegen/src/test/resources/SectionWithIncorrectReturnOfMethod.java +++ b/rpc/rpc-codegen/src/test/resources/SectionWithIncorrectReturnOfMethod.java @@ -1,7 +1,7 @@ package com.strategyobject.substrateclient.rpc.sections; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcCall; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcInterface; +import com.strategyobject.substrateclient.rpc.annotation.RpcCall; +import com.strategyobject.substrateclient.rpc.annotation.RpcInterface; @RpcInterface("empty") public interface SectionWithIncorrectReturnOfMethod { diff --git a/rpc/rpc-codegen/src/test/resources/SectionWithIncorrectReturnOfSubscription.java b/rpc/rpc-codegen/src/test/resources/SectionWithIncorrectReturnOfSubscription.java index 4ce64c41..c43527cc 100644 --- a/rpc/rpc-codegen/src/test/resources/SectionWithIncorrectReturnOfSubscription.java +++ b/rpc/rpc-codegen/src/test/resources/SectionWithIncorrectReturnOfSubscription.java @@ -1,7 +1,7 @@ package com.strategyobject.substrateclient.rpc.sections; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcInterface; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcSubscription; +import com.strategyobject.substrateclient.rpc.annotation.RpcInterface; +import com.strategyobject.substrateclient.rpc.annotation.RpcSubscription; import java.util.concurrent.CompletableFuture; import java.util.function.BiConsumer; diff --git a/rpc/rpc-codegen/src/test/resources/SectionWithManyCallbacks.java b/rpc/rpc-codegen/src/test/resources/SectionWithManyCallbacks.java index e211b10c..4fc8bc6e 100644 --- a/rpc/rpc-codegen/src/test/resources/SectionWithManyCallbacks.java +++ b/rpc/rpc-codegen/src/test/resources/SectionWithManyCallbacks.java @@ -1,7 +1,7 @@ package com.strategyobject.substrateclient.rpc.sections; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcInterface; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcSubscription; +import com.strategyobject.substrateclient.rpc.annotation.RpcInterface; +import com.strategyobject.substrateclient.rpc.annotation.RpcSubscription; import java.util.concurrent.CompletableFuture; import java.util.function.BiConsumer; diff --git a/rpc/rpc-codegen/src/test/resources/SectionWithoutAnnotatedMethod.java b/rpc/rpc-codegen/src/test/resources/SectionWithoutAnnotatedMethod.java index ded782d2..293d5bc8 100644 --- a/rpc/rpc-codegen/src/test/resources/SectionWithoutAnnotatedMethod.java +++ b/rpc/rpc-codegen/src/test/resources/SectionWithoutAnnotatedMethod.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.rpc.sections; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcInterface; +import com.strategyobject.substrateclient.rpc.annotation.RpcInterface; import java.util.concurrent.CompletableFuture; diff --git a/rpc/rpc-codegen/src/test/resources/SectionWithoutCallback.java b/rpc/rpc-codegen/src/test/resources/SectionWithoutCallback.java index 4023df24..f9d66d08 100644 --- a/rpc/rpc-codegen/src/test/resources/SectionWithoutCallback.java +++ b/rpc/rpc-codegen/src/test/resources/SectionWithoutCallback.java @@ -1,7 +1,7 @@ package com.strategyobject.substrateclient.rpc.sections; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcInterface; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcSubscription; +import com.strategyobject.substrateclient.rpc.annotation.RpcInterface; +import com.strategyobject.substrateclient.rpc.annotation.RpcSubscription; import java.util.concurrent.CompletableFuture; import java.util.function.Supplier; diff --git a/rpc/rpc-codegen/src/test/resources/TestSection.java b/rpc/rpc-codegen/src/test/resources/TestSection.java index b4619cbf..456c7d0d 100644 --- a/rpc/rpc-codegen/src/test/resources/TestSection.java +++ b/rpc/rpc-codegen/src/test/resources/TestSection.java @@ -1,8 +1,11 @@ package com.strategyobject.substrateclient.rpc.sections; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcCall; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcInterface; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcSubscription; +import com.strategyobject.substrateclient.rpc.annotation.RpcCall; +import com.strategyobject.substrateclient.rpc.annotation.RpcInterface; +import com.strategyobject.substrateclient.rpc.annotation.RpcSubscription; +import com.strategyobject.substrateclient.rpc.codegen.substitutes.TestDispatch; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleGeneric; import java.util.concurrent.CompletableFuture; import java.util.function.BiConsumer; @@ -11,7 +14,9 @@ @RpcInterface("empty") public interface TestSection { @RpcCall("doNothing") - CompletableFuture doNothing(boolean a); + CompletableFuture doNothing( + @ScaleGeneric(template = "TestDispatch", types = @Scale(TestDispatch.class)) + TestDispatch a); @RpcSubscription(type = "nothing", subscribeMethod = "subscribeNothing", unsubscribeMethod = "unsubscribeNothing") CompletableFuture>> subscribeNothing(boolean a, BiConsumer b); diff --git a/rpc/rpc-core/build.gradle b/rpc/rpc-core/build.gradle deleted file mode 100644 index 2cf62202..00000000 --- a/rpc/rpc-core/build.gradle +++ /dev/null @@ -1,9 +0,0 @@ -dependencies { - implementation project(':common') - implementation project(':scale') - implementation project(':transport') - - testImplementation project(':tests') - - testImplementation 'com.google.code.gson:gson:2.9.0' -} \ No newline at end of file diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/RpcGeneratedSectionFactory.java b/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/RpcGeneratedSectionFactory.java deleted file mode 100644 index 8222ab7f..00000000 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/RpcGeneratedSectionFactory.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.strategyobject.substrateclient.rpc.core; - -import com.strategyobject.substrateclient.rpc.core.annotations.RpcInterface; -import com.strategyobject.substrateclient.transport.ProviderInterface; -import lombok.NonNull; -import lombok.val; - -import java.lang.reflect.InvocationTargetException; - -public class RpcGeneratedSectionFactory { - private static final String CLASS_NAME_TEMPLATE = "%sImpl"; - - private RpcGeneratedSectionFactory() { - } - - public static T create(@NonNull Class interfaceClass, - @NonNull ProviderInterface provider) throws RpcInterfaceInitializationException { - if (interfaceClass.getDeclaredAnnotationsByType(RpcInterface.class).length == 0) { - throw new IllegalArgumentException( - String.format("`%s` can't be constructed because isn't annotated with `@%s`.", - interfaceClass.getSimpleName(), - RpcInterface.class.getSimpleName())); - } - - Class clazz; - try { - clazz = Class.forName(String.format(CLASS_NAME_TEMPLATE, interfaceClass.getCanonicalName())); - val ctor = clazz.getConstructor(ProviderInterface.class); - - return interfaceClass.cast(ctor.newInstance(provider)); - } catch (ClassCastException | ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { - throw new RpcInterfaceInitializationException(e); - } - } -} diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/RpcInterfaceInitializationException.java b/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/RpcInterfaceInitializationException.java deleted file mode 100644 index b66240c6..00000000 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/RpcInterfaceInitializationException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.strategyobject.substrateclient.rpc.core; - -public class RpcInterfaceInitializationException extends Exception { - public RpcInterfaceInitializationException(Throwable ex) { - super(ex); - } -} diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/RpcRegistryHelper.java b/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/RpcRegistryHelper.java deleted file mode 100644 index d0f3fdd8..00000000 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/RpcRegistryHelper.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.strategyobject.substrateclient.rpc.core; - -import com.strategyobject.substrateclient.rpc.core.registries.RpcDecoderRegistry; -import com.strategyobject.substrateclient.rpc.core.registries.RpcEncoderRegistry; -import lombok.val; - -public final class RpcRegistryHelper { - private RpcRegistryHelper() { - } - - @SuppressWarnings("unchecked") - public static RpcDecoder resolveAndInjectOrNull(Class clazz, DecoderPair... dependencies) { - val target = (RpcDecoder) RpcDecoderRegistry.getInstance().resolve(clazz); - - if (target == null) { - return null; - } - - return target.inject(dependencies); - } - - @SuppressWarnings("unchecked") - public static RpcEncoder resolveAndInjectOrNull(Class clazz, EncoderPair... dependencies) { - val target = (RpcEncoder) RpcEncoderRegistry.getInstance().resolve(clazz); - - if (target == null) { - return null; - } - - return target.inject(dependencies); - } -} diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/RpcSelfEncodable.java b/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/RpcSelfEncodable.java deleted file mode 100644 index 364dabcf..00000000 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/RpcSelfEncodable.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.strategyobject.substrateclient.rpc.core; - -import com.strategyobject.substrateclient.rpc.core.registries.RpcEncoderRegistry; - -public interface RpcSelfEncodable> { - @SuppressWarnings("unchecked") - default Object encode(T source) { - return ((RpcSelfEncodable) RpcEncoderRegistry.getInstance() - .resolve(this.getClass())) - .encode(source); - } -} diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/registries/RpcDecoderRegistry.java b/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/registries/RpcDecoderRegistry.java deleted file mode 100644 index dd14802c..00000000 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/registries/RpcDecoderRegistry.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.strategyobject.substrateclient.rpc.core.registries; - -import com.strategyobject.substrateclient.common.CommonType; -import com.strategyobject.substrateclient.common.reflection.Scanner; -import com.strategyobject.substrateclient.rpc.core.RpcDecoder; -import com.strategyobject.substrateclient.rpc.core.annotations.AutoRegister; -import com.strategyobject.substrateclient.rpc.core.decoders.*; -import lombok.NonNull; -import lombok.val; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -public final class RpcDecoderRegistry { - private static final Logger logger = LoggerFactory.getLogger(RpcDecoderRegistry.class); - private static final String ROOT_PREFIX = "com.strategyobject.substrateclient"; - private static volatile RpcDecoderRegistry instance; - private final Map, RpcDecoder> decoders; - - private RpcDecoderRegistry() { - decoders = new ConcurrentHashMap<>(128); - - register(new ListDecoder(), List.class); - register(new MapDecoder(), Map.class); - register(new VoidDecoder(), Void.class); - register(new BooleanDecoder(), Boolean.class, boolean.class); - register(new ByteDecoder(), Byte.class, byte.class); - register(new DoubleDecoder(), Double.class, double.class); - register(new FloatDecoder(), Float.class, float.class); - register(new IntDecoder(), Integer.class, int.class); - register(new LongDecoder(), Long.class, long.class); - register(new ShortDecoder(), Short.class, short.class); - register(new StringDecoder(), String.class); - register(new ArrayDecoder(), CommonType.Array.class); - - registerAnnotatedFrom(ROOT_PREFIX); - } - - public static RpcDecoderRegistry getInstance() { - if (instance == null) { - synchronized (RpcDecoderRegistry.class) { - if (instance == null) { - instance = new RpcDecoderRegistry(); - } - } - } - - return instance; - } - - public void registerAnnotatedFrom(String... prefixes) { - Scanner.forPrefixes(prefixes) - .getSubTypesOf(RpcDecoder.class).forEach(decoder -> { - val autoRegister = decoder.getAnnotation(AutoRegister.class); - if (autoRegister == null) { - return; - } - - try { - val types = autoRegister.types(); - logger.info("Auto register decoder {} for types: {}", decoder, types); - - final RpcDecoder instance = decoder.newInstance(); - register(instance, types); - } catch (InstantiationException | IllegalAccessException e) { - logger.error("Auto registration error", e); - } - }); - } - - public void register(@NonNull RpcDecoder decoder, @NonNull Class... clazz) { - for (val type : clazz) { - decoders.put(type, decoder); - } - } - - public RpcDecoder resolve(@NonNull Class clazz) { - return decoders.get(clazz); - } -} diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/registries/RpcEncoderRegistry.java b/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/registries/RpcEncoderRegistry.java deleted file mode 100644 index b4423f1c..00000000 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/registries/RpcEncoderRegistry.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.strategyobject.substrateclient.rpc.core.registries; - -import com.strategyobject.substrateclient.common.CommonType; -import com.strategyobject.substrateclient.common.reflection.Scanner; -import com.strategyobject.substrateclient.rpc.core.RpcEncoder; -import com.strategyobject.substrateclient.rpc.core.annotations.AutoRegister; -import com.strategyobject.substrateclient.rpc.core.encoders.ArrayEncoder; -import com.strategyobject.substrateclient.rpc.core.encoders.ListEncoder; -import com.strategyobject.substrateclient.rpc.core.encoders.MapEncoder; -import com.strategyobject.substrateclient.rpc.core.encoders.PlainEncoder; -import lombok.NonNull; -import lombok.val; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -public final class RpcEncoderRegistry { - private static final Logger logger = LoggerFactory.getLogger(RpcEncoderRegistry.class); - private static final String ROOT_PREFIX = "com.strategyobject.substrateclient"; - private static volatile RpcEncoderRegistry instance; - private final Map, RpcEncoder> encoders; - - private RpcEncoderRegistry() { - encoders = new ConcurrentHashMap<>(128); - - register(new PlainEncoder<>(), - Void.class, String.class, Boolean.class, boolean.class, Byte.class, byte.class, Double.class, double.class, - Float.class, float.class, Integer.class, int.class, Long.class, long.class, Short.class, short.class); - register(new ListEncoder(), List.class); - register(new MapEncoder(), Map.class); - register(new ArrayEncoder(), CommonType.Array.class); - - registerAnnotatedFrom(ROOT_PREFIX); - } - - public static RpcEncoderRegistry getInstance() { - if (instance == null) { - synchronized (RpcEncoderRegistry.class) { - if (instance == null) { - instance = new RpcEncoderRegistry(); - } - } - } - - return instance; - } - - public void registerAnnotatedFrom(String... prefixes) { - Scanner.forPrefixes(prefixes) - .getSubTypesOf(RpcEncoder.class).forEach(encoder -> { - val autoRegister = encoder.getAnnotation(AutoRegister.class); - if (autoRegister == null) { - return; - } - - try { - val types = autoRegister.types(); - logger.info("Auto register encoder {} for types: {}", encoder, types); - - final RpcEncoder instance = encoder.newInstance(); - register(instance, types); - } catch (InstantiationException | IllegalAccessException e) { - logger.error("Auto registration error", e); - } - }); - } - - public void register(@NonNull RpcEncoder encoder, @NonNull Class... clazz) { - for (val type : clazz) { - encoders.put(type, encoder); - } - } - - public RpcEncoder resolve(@NonNull Class clazz) { - return encoders.get(clazz); - } -} diff --git a/rpc/rpc-sections/build.gradle b/rpc/rpc-sections/build.gradle deleted file mode 100644 index f9995649..00000000 --- a/rpc/rpc-sections/build.gradle +++ /dev/null @@ -1,23 +0,0 @@ -dependencies { - implementation project(':common') - compileOnly project(':rpc:rpc-codegen') - compileOnly project(':rpc:rpc-core') - implementation project(':rpc:rpc-types') - implementation project(':scale') - compileOnly project(':transport') - implementation project(':types') - annotationProcessor project(':rpc:rpc-codegen') - - testImplementation project(':tests') - testCompileOnly project(':rpc:rpc-core') - testCompileOnly project(':common') - testCompileOnly project(':transport') - testImplementation project(':crypto') - testAnnotationProcessor project(':scale:scale-codegen') - - testImplementation 'org.testcontainers:testcontainers:1.17.1' - testImplementation 'org.testcontainers:junit-jupiter:1.17.1' - testImplementation 'ch.qos.logback:logback-classic:1.2.11' - testImplementation 'org.awaitility:awaitility:4.2.0' - testImplementation 'org.bouncycastle:bcprov-jdk15on:1.70' -} \ No newline at end of file diff --git a/rpc/rpc-sections/src/main/java/com/strategyobject/substrateclient/rpc/sections/Author.java b/rpc/rpc-sections/src/main/java/com/strategyobject/substrateclient/rpc/sections/Author.java deleted file mode 100644 index ce4bb979..00000000 --- a/rpc/rpc-sections/src/main/java/com/strategyobject/substrateclient/rpc/sections/Author.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.strategyobject.substrateclient.rpc.sections; - -import com.strategyobject.substrateclient.rpc.core.annotations.RpcCall; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcInterface; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcSubscription; -import com.strategyobject.substrateclient.rpc.types.Extrinsic; -import com.strategyobject.substrateclient.rpc.types.ExtrinsicStatus; -import com.strategyobject.substrateclient.rpc.types.Hash; -import com.strategyobject.substrateclient.scale.annotations.Scale; -import com.strategyobject.substrateclient.types.PublicKey; - -import java.util.concurrent.CompletableFuture; -import java.util.function.BiConsumer; -import java.util.function.Supplier; - -@RpcInterface("author") -public interface Author { - @RpcCall("hasKey") - CompletableFuture hasKey(@Scale PublicKey publicKey, String keyType); - - @RpcCall("insertKey") - CompletableFuture insertKey(String keyType, String secretUri, @Scale PublicKey publicKey); - - @RpcCall("submitExtrinsic") - @Scale - CompletableFuture submitExtrinsic(@Scale Extrinsic extrinsic); - - @RpcSubscription(type = "extrinsicUpdate", subscribeMethod = "submitAndWatchExtrinsic", unsubscribeMethod = "unwatchExtrinsic") - CompletableFuture>> submitAndWatchExtrinsic(@Scale Extrinsic extrinsic, - BiConsumer callback); -} diff --git a/rpc/rpc-sections/src/main/java/com/strategyobject/substrateclient/rpc/sections/Chain.java b/rpc/rpc-sections/src/main/java/com/strategyobject/substrateclient/rpc/sections/Chain.java deleted file mode 100644 index 550351a0..00000000 --- a/rpc/rpc-sections/src/main/java/com/strategyobject/substrateclient/rpc/sections/Chain.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.strategyobject.substrateclient.rpc.sections; - -import com.strategyobject.substrateclient.rpc.core.annotations.RpcCall; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcInterface; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcSubscription; -import com.strategyobject.substrateclient.rpc.types.BlockHash; -import com.strategyobject.substrateclient.rpc.types.Header; -import com.strategyobject.substrateclient.rpc.types.SignedBlock; -import com.strategyobject.substrateclient.scale.annotations.Scale; - -import java.util.concurrent.CompletableFuture; -import java.util.function.BiConsumer; -import java.util.function.Supplier; - -@RpcInterface("chain") -public interface Chain { - @RpcCall("getFinalizedHead") - @Scale - CompletableFuture getFinalizedHead(); - - @RpcSubscription(type = "newHead", subscribeMethod = "subscribeNewHead", unsubscribeMethod = "unsubscribeNewHead") - CompletableFuture>> subscribeNewHeads(BiConsumer callback); - - @RpcCall("getBlockHash") - @Scale - CompletableFuture getBlockHash(long number); - - @RpcCall("getBlock") - CompletableFuture getBlock(@Scale BlockHash hash); -} diff --git a/rpc/rpc-sections/src/main/java/com/strategyobject/substrateclient/rpc/sections/State.java b/rpc/rpc-sections/src/main/java/com/strategyobject/substrateclient/rpc/sections/State.java deleted file mode 100644 index 7f54a408..00000000 --- a/rpc/rpc-sections/src/main/java/com/strategyobject/substrateclient/rpc/sections/State.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.strategyobject.substrateclient.rpc.sections; - -import com.strategyobject.substrateclient.rpc.core.annotations.RpcCall; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcInterface; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcSubscription; -import com.strategyobject.substrateclient.rpc.types.*; -import com.strategyobject.substrateclient.scale.annotations.Scale; - -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.function.BiConsumer; -import java.util.function.Supplier; - -@RpcInterface("state") -public interface State { - @RpcCall("getRuntimeVersion") - CompletableFuture getRuntimeVersion(); - - @RpcCall("getMetadata") - @Scale - CompletableFuture getMetadata(); - - @RpcCall("getKeys") - CompletableFuture> getKeys(StorageKey key); - - @RpcCall("getKeys") - CompletableFuture> getKeys(StorageKey key, @Scale BlockHash at); - - @RpcCall("getKeysPaged") - CompletableFuture> getKeysPaged(StorageKey key, int count); - - @RpcCall("getKeysPaged") - CompletableFuture> getKeysPaged(StorageKey key, int count, StorageKey startKey); - - @RpcCall("getKeysPaged") - CompletableFuture> getKeysPaged(StorageKey key, - int count, - StorageKey startKey, - @Scale BlockHash at); - - @RpcCall("getStorage") - CompletableFuture getStorage(StorageKey key); - - @RpcCall("getStorage") - CompletableFuture getStorage(StorageKey key, @Scale BlockHash at); - - @RpcCall("getStorageHash") - @Scale - CompletableFuture getStorageHash(StorageKey key); - - @RpcCall("getStorageHash") - @Scale - CompletableFuture getStorageHash(StorageKey key, @Scale BlockHash at); - - @RpcCall("getStorageSize") - CompletableFuture getStorageSize(StorageKey key); - - @RpcCall("getStorageSize") - CompletableFuture getStorageSize(StorageKey key, @Scale BlockHash at); - - @RpcCall("queryStorage") - CompletableFuture> queryStorage(List keys, @Scale BlockHash fromBlock); - - @RpcCall("queryStorage") - CompletableFuture> queryStorage(List keys, - @Scale BlockHash fromBlock, - @Scale BlockHash toBlock); - - @RpcCall("queryStorageAt") - CompletableFuture> queryStorageAt(List keys); - - @RpcCall("queryStorageAt") - CompletableFuture> queryStorageAt(List keys, @Scale BlockHash at); - - @RpcSubscription(type = "storage", subscribeMethod = "subscribeStorage", unsubscribeMethod = "unsubscribeStorage") - CompletableFuture>> subscribeStorage(List keys, - BiConsumer callback); -} diff --git a/rpc/rpc-sections/src/main/java/com/strategyobject/substrateclient/rpc/sections/System.java b/rpc/rpc-sections/src/main/java/com/strategyobject/substrateclient/rpc/sections/System.java deleted file mode 100644 index e5103ea6..00000000 --- a/rpc/rpc-sections/src/main/java/com/strategyobject/substrateclient/rpc/sections/System.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.strategyobject.substrateclient.rpc.sections; - -import com.strategyobject.substrateclient.rpc.core.annotations.RpcCall; -import com.strategyobject.substrateclient.rpc.core.annotations.RpcInterface; -import com.strategyobject.substrateclient.rpc.types.AccountId; - -import java.util.concurrent.CompletableFuture; - -@RpcInterface("system") -public interface System { - @RpcCall("accountNextIndex") - CompletableFuture accountNextIndex(AccountId accountId); -} diff --git a/rpc/rpc-sections/src/test/java/com/strategyobject/substrateclient/rpc/sections/ChainTests.java b/rpc/rpc-sections/src/test/java/com/strategyobject/substrateclient/rpc/sections/ChainTests.java deleted file mode 100644 index a3425475..00000000 --- a/rpc/rpc-sections/src/test/java/com/strategyobject/substrateclient/rpc/sections/ChainTests.java +++ /dev/null @@ -1,132 +0,0 @@ -package com.strategyobject.substrateclient.rpc.sections; - -import com.strategyobject.substrateclient.rpc.core.RpcGeneratedSectionFactory; -import com.strategyobject.substrateclient.rpc.core.RpcInterfaceInitializationException; -import com.strategyobject.substrateclient.rpc.types.BlockHash; -import com.strategyobject.substrateclient.tests.containers.SubstrateVersion; -import com.strategyobject.substrateclient.tests.containers.TestSubstrateContainer; -import com.strategyobject.substrateclient.transport.ws.WsProvider; -import lombok.val; -import org.junit.jupiter.api.Test; -import org.testcontainers.containers.Network; -import org.testcontainers.junit.jupiter.Container; -import org.testcontainers.junit.jupiter.Testcontainers; - -import java.math.BigInteger; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -import static org.awaitility.Awaitility.await; -import static org.hamcrest.Matchers.greaterThan; -import static org.junit.jupiter.api.Assertions.*; - -@Testcontainers -public class ChainTests { - private static final int WAIT_TIMEOUT = 10; - private static final Network network = Network.newNetwork(); - - @Container - static final TestSubstrateContainer substrate = new TestSubstrateContainer(SubstrateVersion.V3_0_0) - .withNetwork(network); - - @Test - void getFinalizedHead() throws ExecutionException, InterruptedException, TimeoutException, RpcInterfaceInitializationException { - try (WsProvider wsProvider = WsProvider.builder() - .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() - .build()) { - wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - val rpcSection = RpcGeneratedSectionFactory.create(Chain.class, wsProvider); - - val result = rpcSection.getFinalizedHead().get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - assertNotEquals(BigInteger.ZERO, new BigInteger(result.getData())); - } - } - - @Test - void subscribeNewHeads() throws ExecutionException, InterruptedException, TimeoutException, RpcInterfaceInitializationException { - try (WsProvider wsProvider = WsProvider.builder() - .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() - .build()) { - wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - val rpcSection = RpcGeneratedSectionFactory.create(Chain.class, wsProvider); - - val blockCount = new AtomicInteger(0); - val blockHash = new AtomicReference(null); - - val unsubscribeFunc = rpcSection - .subscribeNewHeads((e, h) -> { - if (blockCount.incrementAndGet() > 1) { - blockHash.compareAndSet(null, h.getParentHash()); - } - }) - .get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - await() - .atMost(WAIT_TIMEOUT * 2, TimeUnit.SECONDS) - .untilAtomic(blockCount, greaterThan(2)); - - assertNotEquals(BigInteger.ZERO, new BigInteger(blockHash.get().getData())); - - val result = unsubscribeFunc.get().get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - assertTrue(result); - } - } - - @Test - void getBlockHash() throws ExecutionException, InterruptedException, TimeoutException, RpcInterfaceInitializationException { - try (WsProvider wsProvider = WsProvider.builder() - .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() - .build()) { - wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - val rpcSection = RpcGeneratedSectionFactory.create(Chain.class, wsProvider); - - val result = rpcSection.getBlockHash(0).get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - assertNotEquals(BigInteger.ZERO, new BigInteger(result.getData())); - } - } - - @Test - void getBlock() throws ExecutionException, InterruptedException, TimeoutException, RpcInterfaceInitializationException { - try (WsProvider wsProvider = WsProvider.builder() - .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() - .build()) { - wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - Chain rpcSection = RpcGeneratedSectionFactory.create(Chain.class, wsProvider); - - val height = new AtomicInteger(0); - rpcSection.subscribeNewHeads((e, header) -> { - if (header != null) { - height.set(header.getNumber().getValue().intValue()); - } - }); - - await() - .atMost(WAIT_TIMEOUT * 3, TimeUnit.SECONDS) - .untilAtomic(height, greaterThan(1)); - - val number = height.get(); - val blockHash = rpcSection.getBlockHash(number).get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - assertNotEquals(BigInteger.ZERO, new BigInteger(blockHash.getData())); - - val block = rpcSection.getBlock(blockHash).get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - assertNotEquals(BigInteger.ZERO, new BigInteger(block.getBlock().getHeader().getParentHash().getData())); - assertEquals(number, block.getBlock().getHeader().getNumber().getValue().intValue()); - } - } -} diff --git a/rpc/rpc-sections/src/test/java/com/strategyobject/substrateclient/rpc/sections/StateTests.java b/rpc/rpc-sections/src/test/java/com/strategyobject/substrateclient/rpc/sections/StateTests.java deleted file mode 100644 index 4f82ec22..00000000 --- a/rpc/rpc-sections/src/test/java/com/strategyobject/substrateclient/rpc/sections/StateTests.java +++ /dev/null @@ -1,251 +0,0 @@ -package com.strategyobject.substrateclient.rpc.sections; - -import com.strategyobject.substrateclient.common.utils.HexConverter; -import com.strategyobject.substrateclient.rpc.core.RpcGeneratedSectionFactory; -import com.strategyobject.substrateclient.rpc.core.RpcInterfaceInitializationException; -import com.strategyobject.substrateclient.rpc.types.StorageKey; -import com.strategyobject.substrateclient.tests.containers.SubstrateVersion; -import com.strategyobject.substrateclient.tests.containers.TestSubstrateContainer; -import com.strategyobject.substrateclient.transport.ws.WsProvider; -import lombok.val; -import org.junit.jupiter.api.Test; -import org.testcontainers.containers.Network; -import org.testcontainers.junit.jupiter.Container; -import org.testcontainers.junit.jupiter.Testcontainers; - -import java.util.Collections; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import static org.junit.jupiter.api.Assertions.*; - -@Testcontainers -public class StateTests { - private static final int WAIT_TIMEOUT = 10; - private static final Network network = Network.newNetwork(); - - @Container - static final TestSubstrateContainer substrate = new TestSubstrateContainer(SubstrateVersion.V3_0_0) - .withNetwork(network); - - @Test - void getRuntimeVersion() throws ExecutionException, InterruptedException, TimeoutException, RpcInterfaceInitializationException { - try (WsProvider wsProvider = WsProvider.builder() - .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() - .build()) { - wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - State rpcSection = RpcGeneratedSectionFactory.create(State.class, wsProvider); - - assertDoesNotThrow(() -> { - rpcSection.getRuntimeVersion().get(WAIT_TIMEOUT, TimeUnit.SECONDS); - }); - } - } - - @Test - void getMetadata() throws ExecutionException, InterruptedException, TimeoutException, RpcInterfaceInitializationException { - try (WsProvider wsProvider = WsProvider.builder() - .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() - .build()) { - wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - State rpcSection = RpcGeneratedSectionFactory.create(State.class, wsProvider); - - assertDoesNotThrow(() -> { - rpcSection.getMetadata().get(WAIT_TIMEOUT * 10, TimeUnit.SECONDS); - }); - } - } - - @Test - void getKeys() throws ExecutionException, InterruptedException, TimeoutException, RpcInterfaceInitializationException { - try (WsProvider wsProvider = WsProvider.builder() - .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() - .build()) { - wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - State rpcSection = RpcGeneratedSectionFactory.create(State.class, wsProvider); - - // xxhash128("Balances") = 0xc2261276cc9d1f8598ea4b6a74b15c2f - // xxhash128("StorageVersion") = 0x308ce9615de0775a82f8a94dc3d285a1 - val key = "0xc2261276cc9d1f8598ea4b6a74b15c2f308ce9615de0775a82f8a94dc3d285a1"; // TODO implement and use `xxhash` - val keys = rpcSection.getKeys(StorageKey.valueOf(HexConverter.toBytes(key))).get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - assertTrue(keys.size() > 0); - } - } - - @Test - void getStorage() throws ExecutionException, InterruptedException, TimeoutException, RpcInterfaceInitializationException { - try (WsProvider wsProvider = WsProvider.builder() - .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() - .build()) { - wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - State rpcSection = RpcGeneratedSectionFactory.create(State.class, wsProvider); - - // xxhash128("Balances") = 0xc2261276cc9d1f8598ea4b6a74b15c2f - // xxhash128("StorageVersion") = 0x308ce9615de0775a82f8a94dc3d285a1 - val key = "0xc2261276cc9d1f8598ea4b6a74b15c2f308ce9615de0775a82f8a94dc3d285a1"; // TODO implement and use `xxhash` - val storageData = rpcSection.getStorage(StorageKey.valueOf(HexConverter.toBytes(key))).get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - assertNotNull(storageData); - assertTrue(storageData.getData().length > 0); - } - } - - @Test - void getStorageHandlesNullResponse() throws ExecutionException, InterruptedException, TimeoutException, RpcInterfaceInitializationException { - try (WsProvider wsProvider = WsProvider.builder() - .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() - .build()) { - wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - State rpcSection = RpcGeneratedSectionFactory.create(State.class, wsProvider); - - val emptyKey = new byte[32]; - val storageData = rpcSection.getStorage(StorageKey.valueOf(emptyKey)).get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - assertNull(storageData); - } - } - - @Test - void getStorageAtBlock() throws ExecutionException, InterruptedException, TimeoutException, RpcInterfaceInitializationException { - try (WsProvider wsProvider = WsProvider.builder() - .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() - .build()) { - wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - val chainSection = RpcGeneratedSectionFactory.create(Chain.class, wsProvider); - val blockHash = chainSection.getBlockHash(0).get(WAIT_TIMEOUT, TimeUnit.SECONDS); - State rpcSection = RpcGeneratedSectionFactory.create(State.class, wsProvider); - - // xxhash128("Balances") = 0xc2261276cc9d1f8598ea4b6a74b15c2f - // xxhash128("StorageVersion") = 0x308ce9615de0775a82f8a94dc3d285a1 - val key = "0xc2261276cc9d1f8598ea4b6a74b15c2f308ce9615de0775a82f8a94dc3d285a1"; // TODO implement and use `xxhash` - val storageData = rpcSection.getStorage( - StorageKey.valueOf(HexConverter.toBytes(key)), - blockHash).get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - assertNotNull(storageData); - assertTrue(storageData.getData().length > 0); - } - } - - @Test - void getStorageHash() throws ExecutionException, InterruptedException, TimeoutException, RpcInterfaceInitializationException { - try (WsProvider wsProvider = WsProvider.builder() - .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() - .build()) { - wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - State rpcSection = RpcGeneratedSectionFactory.create(State.class, wsProvider); - - // xxhash128("Balances") = 0xc2261276cc9d1f8598ea4b6a74b15c2f - // xxhash128("StorageVersion") = 0x308ce9615de0775a82f8a94dc3d285a1 - val key = "0xc2261276cc9d1f8598ea4b6a74b15c2f308ce9615de0775a82f8a94dc3d285a1"; // TODO implement and use `xxhash` - val hash = rpcSection.getStorageHash(StorageKey.valueOf(HexConverter.toBytes(key))).get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - assertNotNull(hash); - assertTrue(hash.getData().length > 0); - } - } - - @Test - void getStorageHashAt() throws ExecutionException, InterruptedException, TimeoutException, RpcInterfaceInitializationException { - try (WsProvider wsProvider = WsProvider.builder() - .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() - .build()) { - wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - val chainSection = RpcGeneratedSectionFactory.create(Chain.class, wsProvider); - val blockHash = chainSection.getBlockHash(0).get(WAIT_TIMEOUT, TimeUnit.SECONDS); - State rpcSection = RpcGeneratedSectionFactory.create(State.class, wsProvider); - - // xxhash128("Balances") = 0xc2261276cc9d1f8598ea4b6a74b15c2f - // xxhash128("StorageVersion") = 0x308ce9615de0775a82f8a94dc3d285a1 - val key = "0xc2261276cc9d1f8598ea4b6a74b15c2f308ce9615de0775a82f8a94dc3d285a1"; // TODO implement and use `xxhash` - val hash = rpcSection.getStorageHash( - StorageKey.valueOf(HexConverter.toBytes(key)), - blockHash).get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - assertNotNull(hash); - assertTrue(hash.getData().length > 0); - } - } - - @Test - void getStorageSize() throws ExecutionException, InterruptedException, TimeoutException, RpcInterfaceInitializationException { - try (WsProvider wsProvider = WsProvider.builder() - .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() - .build()) { - wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - State rpcSection = RpcGeneratedSectionFactory.create(State.class, wsProvider); - - // xxhash128("Balances") = 0xc2261276cc9d1f8598ea4b6a74b15c2f - // xxhash128("StorageVersion") = 0x308ce9615de0775a82f8a94dc3d285a1 - val key = "0xc2261276cc9d1f8598ea4b6a74b15c2f308ce9615de0775a82f8a94dc3d285a1"; // TODO implement and use `xxhash` - val size = rpcSection.getStorageSize(StorageKey.valueOf(HexConverter.toBytes(key))).get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - assertEquals(1, size); - } - } - - @Test - void getStorageSizeAt() throws ExecutionException, InterruptedException, TimeoutException, RpcInterfaceInitializationException { - try (WsProvider wsProvider = WsProvider.builder() - .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() - .build()) { - wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - val chainSection = RpcGeneratedSectionFactory.create(Chain.class, wsProvider); - val blockHash = chainSection.getBlockHash(0).get(WAIT_TIMEOUT, TimeUnit.SECONDS); - State rpcSection = RpcGeneratedSectionFactory.create(State.class, wsProvider); - - // xxhash128("Balances") = 0xc2261276cc9d1f8598ea4b6a74b15c2f - // xxhash128("StorageVersion") = 0x308ce9615de0775a82f8a94dc3d285a1 - val key = "0xc2261276cc9d1f8598ea4b6a74b15c2f308ce9615de0775a82f8a94dc3d285a1"; // TODO implement and use `xxhash` - val size = rpcSection.getStorageSize( - StorageKey.valueOf(HexConverter.toBytes(key)), - blockHash).get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - assertEquals(1, size); - } - } - - @Test - void queryStorageAt() throws ExecutionException, InterruptedException, TimeoutException, RpcInterfaceInitializationException { - try (WsProvider wsProvider = WsProvider.builder() - .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() - .build()) { - wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - State rpcSection = RpcGeneratedSectionFactory.create(State.class, wsProvider); - - // xxhash128("Balances") = 0xc2261276cc9d1f8598ea4b6a74b15c2f - // xxhash128("StorageVersion") = 0x308ce9615de0775a82f8a94dc3d285a1 - val key = "0xc2261276cc9d1f8598ea4b6a74b15c2f308ce9615de0775a82f8a94dc3d285a1"; // TODO implement and use `xxhash` - val changes = rpcSection.queryStorageAt(Collections.singletonList(StorageKey.valueOf(HexConverter.toBytes(key)))).get(WAIT_TIMEOUT, TimeUnit.SECONDS); - - assertTrue(changes.size() > 0); - assertTrue(changes.get(0).getChanges().size() > 0); - assertNotNull(changes.get(0).getChanges().get(0).getValue0().getData()); - assertTrue(changes.get(0).getChanges().get(0).getValue0().getData().length > 0); - } - } -} diff --git a/rpc/rpc-sections/src/test/java/com/strategyobject/substrateclient/rpc/sections/substitutes/ExtrinsicBuilder.java b/rpc/rpc-sections/src/test/java/com/strategyobject/substrateclient/rpc/sections/substitutes/ExtrinsicBuilder.java deleted file mode 100644 index c8c59d7f..00000000 --- a/rpc/rpc-sections/src/test/java/com/strategyobject/substrateclient/rpc/sections/substitutes/ExtrinsicBuilder.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.strategyobject.substrateclient.rpc.sections.substitutes; - -public class ExtrinsicBuilder { - -} diff --git a/rpc/rpc-types/build.gradle b/rpc/rpc-types/build.gradle deleted file mode 100644 index c2287a6c..00000000 --- a/rpc/rpc-types/build.gradle +++ /dev/null @@ -1,11 +0,0 @@ -dependencies { - implementation project(':types') - implementation project(':scale') - implementation project(':rpc:rpc-core') - implementation project(':common') - implementation project(':crypto') - implementation project(':transport') - - annotationProcessor project(':rpc:rpc-codegen') - annotationProcessor project(':scale:scale-codegen') -} \ No newline at end of file diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/AccountId.java b/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/AccountId.java deleted file mode 100644 index f1dc6ad5..00000000 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/AccountId.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.strategyobject.substrateclient.rpc.types; - -import com.strategyobject.substrateclient.crypto.ss58.SS58Codec; -import com.strategyobject.substrateclient.rpc.core.MetadataRegistry; -import com.strategyobject.substrateclient.scale.ScaleSelfWritable; -import com.strategyobject.substrateclient.types.FixedBytes; -import com.strategyobject.substrateclient.types.Size; -import lombok.NonNull; -import lombok.var; - -import java.util.concurrent.atomic.AtomicReference; - -public class AccountId - extends FixedBytes - implements ScaleSelfWritable { - - private final AtomicReference encoded = new AtomicReference<>(null); - - protected AccountId(byte[] data) { - super(data, Size.of32); - } - - @Override - public String toString() { - var result = encoded.get(); - if (result != null) { - return result; - } - - result = SS58Codec.encode(getData(), MetadataRegistry.getInstance().getSS58AddressFormat()); - return encoded.compareAndSet(null, result) ? result : encoded.get(); - } - - public static AccountId fromBytes(byte @NonNull [] data) { - return new AccountId(data); - } -} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/AccountIdEncoder.java b/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/AccountIdEncoder.java deleted file mode 100644 index b0852a03..00000000 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/AccountIdEncoder.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.strategyobject.substrateclient.rpc.types; - -import com.google.common.base.Preconditions; -import com.strategyobject.substrateclient.rpc.core.EncoderPair; -import com.strategyobject.substrateclient.rpc.core.RpcEncoder; -import com.strategyobject.substrateclient.rpc.core.annotations.AutoRegister; - -@AutoRegister(types = AccountId.class) -public class AccountIdEncoder implements RpcEncoder { - @Override - public Object encode(AccountId source, EncoderPair... encoders) { - Preconditions.checkArgument(encoders == null || encoders.length == 0); - - return source.toString(); - } -} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/AdditionalExtra.java b/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/AdditionalExtra.java deleted file mode 100644 index 3cd5ed5a..00000000 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/AdditionalExtra.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.strategyobject.substrateclient.rpc.types; - -import com.strategyobject.substrateclient.scale.ScaleSelfWritable; - -public interface AdditionalExtra extends ScaleSelfWritable { -} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Address.java b/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Address.java deleted file mode 100644 index b0ad97cc..00000000 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Address.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.strategyobject.substrateclient.rpc.types; - -import com.strategyobject.substrateclient.scale.ScaleSelfWritable; - -public interface Address extends ScaleSelfWritable

{ - AddressKind getKind(); -} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/AddressKind.java b/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/AddressKind.java deleted file mode 100644 index 329c8e60..00000000 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/AddressKind.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.strategyobject.substrateclient.rpc.types; - -import lombok.Getter; - -public enum AddressKind { - ID((byte) 0); - - @Getter - private final byte value; - - AddressKind(byte value) { - this.value = value; - } -} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/AddressKindScaleWriter.java b/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/AddressKindScaleWriter.java deleted file mode 100644 index 3682f416..00000000 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/AddressKindScaleWriter.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.strategyobject.substrateclient.rpc.types; - -import com.google.common.base.Preconditions; -import com.strategyobject.substrateclient.scale.ScaleWriter; -import com.strategyobject.substrateclient.scale.annotations.AutoRegister; -import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; -import lombok.NonNull; - -import java.io.IOException; -import java.io.OutputStream; - -@AutoRegister(types = AddressKind.class) -public class AddressKindScaleWriter implements ScaleWriter { - @Override - @SuppressWarnings("unchecked") - public void write(@NonNull AddressKind value, @NonNull OutputStream stream, ScaleWriter... writers) throws IOException { - Preconditions.checkArgument(writers == null || writers.length == 0); - - ((ScaleWriter) ScaleWriterRegistry.getInstance().resolve(byte.class)).write(value.getValue(), stream); - } -} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/BlockHash.java b/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/BlockHash.java deleted file mode 100644 index 2283d23e..00000000 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/BlockHash.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.strategyobject.substrateclient.rpc.types; - -import com.strategyobject.substrateclient.scale.ScaleSelfWritable; -import com.strategyobject.substrateclient.types.FixedBytes; -import com.strategyobject.substrateclient.types.Size; -import lombok.NonNull; - -public class BlockHash - extends FixedBytes - implements ScaleSelfWritable { - protected BlockHash(byte[] data) { - super(data, Size.of32); - } - - public static BlockHash fromBytes(byte @NonNull [] data) { - return new BlockHash(data); - } -} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/BlockHashScaleReader.java b/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/BlockHashScaleReader.java deleted file mode 100644 index 40bb6b1f..00000000 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/BlockHashScaleReader.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.strategyobject.substrateclient.rpc.types; - -import com.google.common.base.Preconditions; -import com.strategyobject.substrateclient.common.io.Streamer; -import com.strategyobject.substrateclient.scale.ScaleReader; -import com.strategyobject.substrateclient.scale.annotations.AutoRegister; -import com.strategyobject.substrateclient.types.Size; -import lombok.NonNull; - -import java.io.IOException; -import java.io.InputStream; - -@AutoRegister(types = BlockHash.class) -public class BlockHashScaleReader implements ScaleReader { - @Override - public BlockHash read(@NonNull InputStream stream, ScaleReader... readers) throws IOException { - Preconditions.checkArgument(readers == null || readers.length == 0); - - return BlockHash.fromBytes(Streamer.readBytes(Size.of32.getValue(), stream)); - } -} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Call.java b/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Call.java deleted file mode 100644 index 2bc2ea87..00000000 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Call.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.strategyobject.substrateclient.rpc.types; - -import com.strategyobject.substrateclient.scale.ScaleSelfWritable; - -public interface Call extends ScaleSelfWritable { -} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Era.java b/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Era.java deleted file mode 100644 index b2ffac14..00000000 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Era.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.strategyobject.substrateclient.rpc.types; - -import com.strategyobject.substrateclient.scale.ScaleSelfWritable; - -public interface Era extends ScaleSelfWritable { -} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Extra.java b/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Extra.java deleted file mode 100644 index 32274892..00000000 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Extra.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.strategyobject.substrateclient.rpc.types; - -import com.strategyobject.substrateclient.scale.ScaleSelfWritable; - -public interface Extra extends ScaleSelfWritable { -} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/ExtrinsicScaleWriter.java b/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/ExtrinsicScaleWriter.java deleted file mode 100644 index 04bb277a..00000000 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/ExtrinsicScaleWriter.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.strategyobject.substrateclient.rpc.types; - -import com.google.common.base.Preconditions; -import com.strategyobject.substrateclient.scale.ScaleType; -import com.strategyobject.substrateclient.scale.ScaleWriter; -import com.strategyobject.substrateclient.scale.annotations.AutoRegister; -import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; -import lombok.NonNull; -import lombok.val; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -@AutoRegister(types = Extrinsic.class) -public class ExtrinsicScaleWriter implements ScaleWriter> { - private static final int VERSION = 4; - - @Override - public void write(@NonNull Extrinsic value, @NonNull OutputStream stream, ScaleWriter... writers) throws IOException { - Preconditions.checkArgument(writers == null || writers.length == 0); - - val encodedExtrinsic = new ByteArrayOutputStream(); - writeExtrinsic(value, encodedExtrinsic); - - wrapToVec(encodedExtrinsic, stream); - } - - @SuppressWarnings("unchecked") - private void wrapToVec(ByteArrayOutputStream encodedExtrinsic, OutputStream stream) throws IOException { - ((ScaleWriter)ScaleWriterRegistry.getInstance().resolve(ScaleType.CompactInteger.class)) - .write(encodedExtrinsic.size(), stream); - - stream.write(encodedExtrinsic.toByteArray()); - } - - @SuppressWarnings("unchecked") - private void writeExtrinsic(Extrinsic value, ByteArrayOutputStream stream) throws IOException { - val u8Writer = (ScaleWriter) ScaleWriterRegistry.getInstance().resolve(ScaleType.U8.class); - if (value.getSignature().isPresent()) { - u8Writer.write(VERSION | 0b1000_0000, stream); - val signature = (SignaturePayload) value.getSignature().get(); - signature.write(stream); - } else { - u8Writer.write(VERSION & 0b0111_1111, stream); - } - - value.getCall().write(stream); - } -} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/FixedBytesScaleWriter.java b/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/FixedBytesScaleWriter.java deleted file mode 100644 index fc41632b..00000000 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/FixedBytesScaleWriter.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.strategyobject.substrateclient.rpc.types; - -import com.google.common.base.Preconditions; -import com.strategyobject.substrateclient.common.io.Streamer; -import com.strategyobject.substrateclient.scale.ScaleWriter; -import com.strategyobject.substrateclient.scale.annotations.AutoRegister; -import com.strategyobject.substrateclient.types.FixedBytes; -import com.strategyobject.substrateclient.types.Size; -import lombok.NonNull; - -import java.io.IOException; -import java.io.OutputStream; - -@AutoRegister(types = {AccountId.class, BlockHash.class}) -public class FixedBytesScaleWriter implements ScaleWriter> { - @Override - public void write(@NonNull FixedBytes value, @NonNull OutputStream stream, ScaleWriter... writers) throws IOException { - Preconditions.checkArgument(writers == null || writers.length == 0); - - Streamer.writeBytes(value.getData(), stream); - } -} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Hash.java b/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Hash.java deleted file mode 100644 index 418afb73..00000000 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Hash.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.strategyobject.substrateclient.rpc.types; - -import com.strategyobject.substrateclient.scale.ScaleSelfWritable; -import com.strategyobject.substrateclient.types.FixedBytes; -import com.strategyobject.substrateclient.types.Size; -import lombok.NonNull; - -public class Hash extends FixedBytes implements ScaleSelfWritable { - private Hash(byte[] data) { - super(data, Size.of32); - } - - public static Hash fromBytes(byte @NonNull [] data) { - return new Hash(data); - } -} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/HashScaleReader.java b/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/HashScaleReader.java deleted file mode 100644 index 2f1f7723..00000000 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/HashScaleReader.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.strategyobject.substrateclient.rpc.types; - -import com.google.common.base.Preconditions; -import com.strategyobject.substrateclient.common.io.Streamer; -import com.strategyobject.substrateclient.scale.ScaleReader; -import com.strategyobject.substrateclient.scale.annotations.AutoRegister; -import com.strategyobject.substrateclient.types.Size; -import lombok.NonNull; - -import java.io.IOException; -import java.io.InputStream; - -@AutoRegister(types = Hash.class) -public class HashScaleReader implements ScaleReader { - @Override - public Hash read(@NonNull InputStream stream, ScaleReader... readers) throws IOException { - Preconditions.checkArgument(readers == null || readers.length == 0); - - return Hash.fromBytes(Streamer.readBytes(Size.of32.getValue(), stream)); - } -} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Header.java b/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Header.java deleted file mode 100644 index 8eded354..00000000 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Header.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.strategyobject.substrateclient.rpc.types; - -import com.strategyobject.substrateclient.rpc.core.annotations.RpcDecoder; -import com.strategyobject.substrateclient.scale.annotations.Scale; -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -@RpcDecoder -public class Header { // TODO add rest fields - @Scale - private BlockHash parentHash; - - private Number number; /* TODO probably it would be better to change the type to BigInteger - and support specific decoders */ -} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Metadata.java b/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Metadata.java deleted file mode 100644 index 638e36d1..00000000 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Metadata.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.strategyobject.substrateclient.rpc.types; - -import com.strategyobject.substrateclient.scale.ScaleSelfWritable; -import com.strategyobject.substrateclient.scale.annotations.ScaleReader; - -@ScaleReader -public class Metadata implements ScaleSelfWritable { -} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Number.java b/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Number.java deleted file mode 100644 index d66a76ee..00000000 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Number.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.strategyobject.substrateclient.rpc.types; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -import java.math.BigInteger; - -@RequiredArgsConstructor(staticName = "of") -@Getter -public class Number { - private final BigInteger value; -} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/NumberDecoder.java b/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/NumberDecoder.java deleted file mode 100644 index 38cdaaf4..00000000 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/NumberDecoder.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.strategyobject.substrateclient.rpc.types; - -import com.strategyobject.substrateclient.rpc.core.DecoderPair; -import com.strategyobject.substrateclient.rpc.core.annotations.AutoRegister; -import com.strategyobject.substrateclient.rpc.core.decoders.AbstractDecoder; -import com.strategyobject.substrateclient.transport.RpcObject; -import lombok.val; - -import java.math.BigInteger; - -@AutoRegister(types = Number.class) -public class NumberDecoder extends AbstractDecoder { - @Override - protected Number decodeNonNull(RpcObject value, DecoderPair[] decoders) { - val stringValue = value.asString(); - val number = new BigInteger(stringValue.substring(2), 16); - - return Number.of(number); - } -} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/RuntimeVersion.java b/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/RuntimeVersion.java deleted file mode 100644 index 2e9647b2..00000000 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/RuntimeVersion.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.strategyobject.substrateclient.rpc.types; - -import com.strategyobject.substrateclient.rpc.core.annotations.RpcDecoder; - -@RpcDecoder -public class RuntimeVersion { -} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Signature.java b/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Signature.java deleted file mode 100644 index f12d9d08..00000000 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/Signature.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.strategyobject.substrateclient.rpc.types; - -import com.strategyobject.substrateclient.scale.ScaleSelfWritable; - -public interface Signature extends ScaleSelfWritable { - SignatureKind getKind(); -} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/SignaturePayload.java b/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/SignaturePayload.java deleted file mode 100644 index fc69d962..00000000 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/SignaturePayload.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.strategyobject.substrateclient.rpc.types; - -import com.strategyobject.substrateclient.scale.ScaleSelfWritable; -import com.strategyobject.substrateclient.scale.annotations.ScaleWriter; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -@Getter -@ScaleWriter -public class SignaturePayload implements ScaleSelfWritable> { - private final A address; - private final S signature; - private final E extra; -} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/SignedPayload.java b/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/SignedPayload.java deleted file mode 100644 index de2ceeb7..00000000 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/SignedPayload.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.strategyobject.substrateclient.rpc.types; - -import com.strategyobject.substrateclient.types.Signable; -import lombok.Getter; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.val; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -@RequiredArgsConstructor -@Getter -public class SignedPayload - implements Signable { - private final C call; - private final E extra; - - @Override - public byte @NonNull [] getBytes() { - val buf = new ByteArrayOutputStream(); - try { - call.write(buf); - extra.write(buf); - extra.getAdditionalExtra().write(buf); - - return buf.toByteArray(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } -} diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/StorageChangeSet.java b/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/StorageChangeSet.java deleted file mode 100644 index 92d5631f..00000000 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/StorageChangeSet.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.strategyobject.substrateclient.rpc.types; - -import com.strategyobject.substrateclient.rpc.core.annotations.RpcDecoder; -import com.strategyobject.substrateclient.scale.annotations.Scale; -import com.strategyobject.substrateclient.types.tuples.Pair; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -import java.util.List; - -@RpcDecoder -@NoArgsConstructor -@Getter -@Setter -public class StorageChangeSet { - @Scale - private BlockHash block; - private List> changes; -} diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/DecoderPair.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/DecoderPair.java similarity index 92% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/DecoderPair.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/DecoderPair.java index 903107b7..2e2e69da 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/DecoderPair.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/DecoderPair.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.rpc.core; +package com.strategyobject.substrateclient.rpc; import com.strategyobject.substrateclient.scale.ScaleReader; import lombok.Getter; diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/EncoderPair.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/EncoderPair.java similarity index 92% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/EncoderPair.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/EncoderPair.java index 01870be5..76e7c1c0 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/EncoderPair.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/EncoderPair.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.rpc.core; +package com.strategyobject.substrateclient.rpc; import com.strategyobject.substrateclient.scale.ScaleWriter; import lombok.Getter; diff --git a/rpc/src/main/java/com/strategyobject/substrateclient/rpc/GeneratedRpcSectionFactory.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/GeneratedRpcSectionFactory.java new file mode 100644 index 00000000..ccb8c7cd --- /dev/null +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/GeneratedRpcSectionFactory.java @@ -0,0 +1,59 @@ +package com.strategyobject.substrateclient.rpc; + +import com.strategyobject.substrateclient.rpc.annotation.RpcInterface; +import com.strategyobject.substrateclient.rpc.registries.RpcDecoderRegistry; +import com.strategyobject.substrateclient.rpc.registries.RpcEncoderRegistry; +import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; +import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; +import com.strategyobject.substrateclient.transport.ProviderInterface; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.val; + +@RequiredArgsConstructor +public class GeneratedRpcSectionFactory implements RpcSectionFactory, AutoCloseable { + private static final String CLASS_NAME_TEMPLATE = "%sImpl"; + + private final ProviderInterface provider; + private final RpcEncoderRegistry rpcEncoderRegistry; + private final ScaleWriterRegistry scaleWriterRegistry; + private final RpcDecoderRegistry rpcDecoderRegistry; + private final ScaleReaderRegistry scaleReaderRegistry; + + @Override + public T create(@NonNull Class interfaceClass) { + if (interfaceClass.getDeclaredAnnotationsByType(RpcInterface.class).length == 0) { + throw new IllegalArgumentException( + String.format("`%s` can't be constructed because isn't annotated with `@%s`.", + interfaceClass.getSimpleName(), + RpcInterface.class.getSimpleName())); + } + + Class clazz; + try { + clazz = Class.forName(String.format(CLASS_NAME_TEMPLATE, interfaceClass.getCanonicalName())); + val ctor = clazz.getConstructor( + ProviderInterface.class, + RpcEncoderRegistry.class, + ScaleWriterRegistry.class, + RpcDecoderRegistry.class, + ScaleReaderRegistry.class); + + return interfaceClass.cast( + ctor.newInstance(provider, + rpcEncoderRegistry, + scaleWriterRegistry, + rpcDecoderRegistry, + scaleReaderRegistry)); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } + + @Override + public void close() throws Exception { + if (provider instanceof AutoCloseable) { + ((AutoCloseable) provider).close(); + } + } +} diff --git a/rpc/src/main/java/com/strategyobject/substrateclient/rpc/Rpc.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/Rpc.java deleted file mode 100644 index f709b1a3..00000000 --- a/rpc/src/main/java/com/strategyobject/substrateclient/rpc/Rpc.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.strategyobject.substrateclient.rpc; - -import com.strategyobject.substrateclient.rpc.sections.Author; -import com.strategyobject.substrateclient.rpc.sections.Chain; -import com.strategyobject.substrateclient.rpc.sections.State; -import com.strategyobject.substrateclient.rpc.sections.System; - -public interface Rpc { - Author author(); - - Chain chain(); - - State state(); - - System system(); -} diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/RpcDecoder.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/RpcDecoder.java similarity index 85% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/RpcDecoder.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/RpcDecoder.java index 5e6c6249..130d45e8 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/RpcDecoder.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/RpcDecoder.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.rpc.core; +package com.strategyobject.substrateclient.rpc; import com.strategyobject.substrateclient.transport.RpcObject; diff --git a/rpc/src/main/java/com/strategyobject/substrateclient/rpc/RpcDispatch.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/RpcDispatch.java new file mode 100644 index 00000000..be66b687 --- /dev/null +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/RpcDispatch.java @@ -0,0 +1,4 @@ +package com.strategyobject.substrateclient.rpc; + +public interface RpcDispatch { +} diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/RpcEncoder.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/RpcEncoder.java similarity index 81% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/RpcEncoder.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/RpcEncoder.java index 0c088b47..8da9d848 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/RpcEncoder.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/RpcEncoder.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.rpc.core; +package com.strategyobject.substrateclient.rpc; public interface RpcEncoder { Object encode(T source, EncoderPair... encoders); diff --git a/rpc/src/main/java/com/strategyobject/substrateclient/rpc/RpcImpl.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/RpcImpl.java deleted file mode 100644 index 6adb2d0f..00000000 --- a/rpc/src/main/java/com/strategyobject/substrateclient/rpc/RpcImpl.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.strategyobject.substrateclient.rpc; - -import com.strategyobject.substrateclient.rpc.core.RpcGeneratedSectionFactory; -import com.strategyobject.substrateclient.rpc.core.RpcInterfaceInitializationException; -import com.strategyobject.substrateclient.rpc.sections.Author; -import com.strategyobject.substrateclient.rpc.sections.Chain; -import com.strategyobject.substrateclient.rpc.sections.State; -import com.strategyobject.substrateclient.rpc.sections.System; -import com.strategyobject.substrateclient.transport.ProviderInterface; -import lombok.NonNull; - -public class RpcImpl implements Rpc, AutoCloseable { - private final ProviderInterface providerInterface; - private final Author author; - private final Chain chain; - private final State state; - private final System system; - - private RpcImpl(ProviderInterface providerInterface) { - this.providerInterface = providerInterface; - author = resolveSection(Author.class); - chain = resolveSection(Chain.class); - state = resolveSection(State.class); - system = resolveSection(System.class); - } - - private T resolveSection(Class clazz) { - try { - return RpcGeneratedSectionFactory.create(clazz, providerInterface); - } catch (RpcInterfaceInitializationException e) { - throw new RuntimeException(e); - } - } - - public static RpcImpl with(@NonNull ProviderInterface providerInterface) { - return new RpcImpl(providerInterface); - } - - @Override - public Author author() { - return author; - } - - @Override - public Chain chain() { - return chain; - } - - @Override - public State state() { - return state; - } - - @Override - public System system() { - return system; - } - - @Override - public void close() throws Exception { - if (providerInterface instanceof AutoCloseable) { - ((AutoCloseable) providerInterface).close(); - } - } -} diff --git a/rpc/src/main/java/com/strategyobject/substrateclient/rpc/RpcRegistryHelper.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/RpcRegistryHelper.java new file mode 100644 index 00000000..23d28860 --- /dev/null +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/RpcRegistryHelper.java @@ -0,0 +1,36 @@ +package com.strategyobject.substrateclient.rpc; + +import com.strategyobject.substrateclient.rpc.registries.RpcDecoderRegistry; +import com.strategyobject.substrateclient.rpc.registries.RpcEncoderRegistry; +import lombok.val; + +public final class RpcRegistryHelper { + private RpcRegistryHelper() { + } + + @SuppressWarnings("unchecked") + public static RpcDecoder resolveAndInjectOrNull(RpcDecoderRegistry registry, + Class clazz, + DecoderPair... dependencies) { + val target = (RpcDecoder) registry.resolve(clazz); + + if (target == null) { + return null; + } + + return target.inject(dependencies); + } + + @SuppressWarnings("unchecked") + public static RpcEncoder resolveAndInjectOrNull(RpcEncoderRegistry registry, + Class clazz, + EncoderPair... dependencies) { + val target = (RpcEncoder) registry.resolve(clazz); + + if (target == null) { + return null; + } + + return target.inject(dependencies); + } +} diff --git a/rpc/src/main/java/com/strategyobject/substrateclient/rpc/RpcSectionFactory.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/RpcSectionFactory.java new file mode 100644 index 00000000..8324d293 --- /dev/null +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/RpcSectionFactory.java @@ -0,0 +1,7 @@ +package com.strategyobject.substrateclient.rpc; + +import lombok.NonNull; + +public interface RpcSectionFactory { + T create(@NonNull Class interfaceClass); +} diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/annotations/AutoRegister.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/annotation/AutoRegister.java similarity index 83% rename from scale/src/main/java/com/strategyobject/substrateclient/scale/annotations/AutoRegister.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/annotation/AutoRegister.java index a8d35e99..118f46c5 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/annotations/AutoRegister.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/annotation/AutoRegister.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.scale.annotations; +package com.strategyobject.substrateclient.rpc.annotation; import lombok.NonNull; diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/annotations/Ignore.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/annotation/Ignore.java similarity index 80% rename from scale/src/main/java/com/strategyobject/substrateclient/scale/annotations/Ignore.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/annotation/Ignore.java index 89fb6b67..2197cee2 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/annotations/Ignore.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/annotation/Ignore.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.scale.annotations; +package com.strategyobject.substrateclient.rpc.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/annotations/RpcCall.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/annotation/RpcCall.java similarity index 80% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/annotations/RpcCall.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/annotation/RpcCall.java index 9c0cd426..ba404479 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/annotations/RpcCall.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/annotation/RpcCall.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.rpc.core.annotations; +package com.strategyobject.substrateclient.rpc.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/annotations/RpcDecoder.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/annotation/RpcDecoder.java similarity index 81% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/annotations/RpcDecoder.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/annotation/RpcDecoder.java index 1e2c3713..8a85a681 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/annotations/RpcDecoder.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/annotation/RpcDecoder.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.rpc.core.annotations; +package com.strategyobject.substrateclient.rpc.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/annotations/RpcEncoder.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/annotation/RpcEncoder.java similarity index 81% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/annotations/RpcEncoder.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/annotation/RpcEncoder.java index 5c7a6be9..3641e572 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/annotations/RpcEncoder.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/annotation/RpcEncoder.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.rpc.core.annotations; +package com.strategyobject.substrateclient.rpc.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/annotations/RpcInterface.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/annotation/RpcInterface.java similarity index 82% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/annotations/RpcInterface.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/annotation/RpcInterface.java index 4797eeb9..833ee64e 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/annotations/RpcInterface.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/annotation/RpcInterface.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.rpc.core.annotations; +package com.strategyobject.substrateclient.rpc.annotation; import lombok.NonNull; diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/annotations/RpcSubscription.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/annotation/RpcSubscription.java similarity index 84% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/annotations/RpcSubscription.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/annotation/RpcSubscription.java index 03beb642..047e065c 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/annotations/RpcSubscription.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/annotation/RpcSubscription.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.rpc.core.annotations; +package com.strategyobject.substrateclient.rpc.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/rpc/src/main/java/com/strategyobject/substrateclient/rpc/context/RpcDecoderContext.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/context/RpcDecoderContext.java new file mode 100644 index 00000000..39d99c65 --- /dev/null +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/context/RpcDecoderContext.java @@ -0,0 +1,15 @@ +package com.strategyobject.substrateclient.rpc.context; + +import com.strategyobject.substrateclient.rpc.metadata.MetadataProvider; +import com.strategyobject.substrateclient.rpc.registries.RpcDecoderRegistry; +import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class RpcDecoderContext { + private final MetadataProvider metadataProvider; + private final RpcDecoderRegistry rpcDecoderRegistry; + private final ScaleReaderRegistry scaleReaderRegistry; +} diff --git a/rpc/src/main/java/com/strategyobject/substrateclient/rpc/context/RpcDecoderContextFactory.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/context/RpcDecoderContextFactory.java new file mode 100644 index 00000000..0217c59d --- /dev/null +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/context/RpcDecoderContextFactory.java @@ -0,0 +1,5 @@ +package com.strategyobject.substrateclient.rpc.context; + +public interface RpcDecoderContextFactory { + RpcDecoderContext create(); +} diff --git a/rpc/src/main/java/com/strategyobject/substrateclient/rpc/context/RpcEncoderContext.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/context/RpcEncoderContext.java new file mode 100644 index 00000000..cd4353c6 --- /dev/null +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/context/RpcEncoderContext.java @@ -0,0 +1,15 @@ +package com.strategyobject.substrateclient.rpc.context; + +import com.strategyobject.substrateclient.rpc.metadata.MetadataProvider; +import com.strategyobject.substrateclient.rpc.registries.RpcEncoderRegistry; +import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class RpcEncoderContext { + private final MetadataProvider metadataProvider; + private final RpcEncoderRegistry rpcEncoderRegistry; + private final ScaleWriterRegistry scaleWriterRegistry; +} diff --git a/rpc/src/main/java/com/strategyobject/substrateclient/rpc/context/RpcEncoderContextFactory.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/context/RpcEncoderContextFactory.java new file mode 100644 index 00000000..90c935f4 --- /dev/null +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/context/RpcEncoderContextFactory.java @@ -0,0 +1,5 @@ +package com.strategyobject.substrateclient.rpc.context; + +public interface RpcEncoderContextFactory { + RpcEncoderContext create(); +} diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/AbstractDecoder.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/AbstractDecoder.java similarity index 78% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/AbstractDecoder.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/AbstractDecoder.java index f4920b6d..dea15a5d 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/AbstractDecoder.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/AbstractDecoder.java @@ -1,8 +1,8 @@ -package com.strategyobject.substrateclient.rpc.core.decoders; +package com.strategyobject.substrateclient.rpc.decoders; import com.google.common.base.Preconditions; -import com.strategyobject.substrateclient.rpc.core.DecoderPair; -import com.strategyobject.substrateclient.rpc.core.RpcDecoder; +import com.strategyobject.substrateclient.rpc.DecoderPair; +import com.strategyobject.substrateclient.rpc.RpcDecoder; import com.strategyobject.substrateclient.transport.RpcObject; public abstract class AbstractDecoder implements RpcDecoder { diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/ArrayDecoder.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/ArrayDecoder.java similarity index 85% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/ArrayDecoder.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/ArrayDecoder.java index f22f1af6..ca876685 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/ArrayDecoder.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/ArrayDecoder.java @@ -1,7 +1,7 @@ -package com.strategyobject.substrateclient.rpc.core.decoders; +package com.strategyobject.substrateclient.rpc.decoders; import com.google.common.base.Preconditions; -import com.strategyobject.substrateclient.rpc.core.DecoderPair; +import com.strategyobject.substrateclient.rpc.DecoderPair; import com.strategyobject.substrateclient.transport.RpcObject; import lombok.val; diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/BooleanDecoder.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/BooleanDecoder.java similarity index 67% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/BooleanDecoder.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/BooleanDecoder.java index 9a970dc1..696b0e2b 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/BooleanDecoder.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/BooleanDecoder.java @@ -1,6 +1,6 @@ -package com.strategyobject.substrateclient.rpc.core.decoders; +package com.strategyobject.substrateclient.rpc.decoders; -import com.strategyobject.substrateclient.rpc.core.DecoderPair; +import com.strategyobject.substrateclient.rpc.DecoderPair; import com.strategyobject.substrateclient.transport.RpcObject; public class BooleanDecoder extends AbstractDecoder { diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/ByteDecoder.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/ByteDecoder.java similarity index 68% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/ByteDecoder.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/ByteDecoder.java index 1e0fb28d..859f0477 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/ByteDecoder.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/ByteDecoder.java @@ -1,6 +1,6 @@ -package com.strategyobject.substrateclient.rpc.core.decoders; +package com.strategyobject.substrateclient.rpc.decoders; -import com.strategyobject.substrateclient.rpc.core.DecoderPair; +import com.strategyobject.substrateclient.rpc.DecoderPair; import com.strategyobject.substrateclient.transport.RpcObject; public class ByteDecoder extends AbstractDecoder { diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/DoubleDecoder.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/DoubleDecoder.java similarity index 68% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/DoubleDecoder.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/DoubleDecoder.java index bbb4058b..385d9423 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/DoubleDecoder.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/DoubleDecoder.java @@ -1,6 +1,6 @@ -package com.strategyobject.substrateclient.rpc.core.decoders; +package com.strategyobject.substrateclient.rpc.decoders; -import com.strategyobject.substrateclient.rpc.core.DecoderPair; +import com.strategyobject.substrateclient.rpc.DecoderPair; import com.strategyobject.substrateclient.transport.RpcObject; public class DoubleDecoder extends AbstractDecoder { diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/FloatDecoder.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/FloatDecoder.java similarity index 68% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/FloatDecoder.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/FloatDecoder.java index 09b19b0d..73deba7a 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/FloatDecoder.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/FloatDecoder.java @@ -1,6 +1,6 @@ -package com.strategyobject.substrateclient.rpc.core.decoders; +package com.strategyobject.substrateclient.rpc.decoders; -import com.strategyobject.substrateclient.rpc.core.DecoderPair; +import com.strategyobject.substrateclient.rpc.DecoderPair; import com.strategyobject.substrateclient.transport.RpcObject; public class FloatDecoder extends AbstractDecoder { diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/IntDecoder.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/IntDecoder.java similarity index 68% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/IntDecoder.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/IntDecoder.java index 4c6aafce..27ddd767 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/IntDecoder.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/IntDecoder.java @@ -1,6 +1,6 @@ -package com.strategyobject.substrateclient.rpc.core.decoders; +package com.strategyobject.substrateclient.rpc.decoders; -import com.strategyobject.substrateclient.rpc.core.DecoderPair; +import com.strategyobject.substrateclient.rpc.DecoderPair; import com.strategyobject.substrateclient.transport.RpcObject; public class IntDecoder extends AbstractDecoder { diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/ListDecoder.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/ListDecoder.java similarity index 86% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/ListDecoder.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/ListDecoder.java index 97e297da..6463fc99 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/ListDecoder.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/ListDecoder.java @@ -1,7 +1,7 @@ -package com.strategyobject.substrateclient.rpc.core.decoders; +package com.strategyobject.substrateclient.rpc.decoders; import com.google.common.base.Preconditions; -import com.strategyobject.substrateclient.rpc.core.DecoderPair; +import com.strategyobject.substrateclient.rpc.DecoderPair; import com.strategyobject.substrateclient.transport.RpcObject; import lombok.val; diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/LongDecoder.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/LongDecoder.java similarity index 68% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/LongDecoder.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/LongDecoder.java index bd9efa1e..f59659b4 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/LongDecoder.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/LongDecoder.java @@ -1,6 +1,6 @@ -package com.strategyobject.substrateclient.rpc.core.decoders; +package com.strategyobject.substrateclient.rpc.decoders; -import com.strategyobject.substrateclient.rpc.core.DecoderPair; +import com.strategyobject.substrateclient.rpc.DecoderPair; import com.strategyobject.substrateclient.transport.RpcObject; public class LongDecoder extends AbstractDecoder { diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/MapDecoder.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/MapDecoder.java similarity index 89% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/MapDecoder.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/MapDecoder.java index 3507df60..d6b5af13 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/MapDecoder.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/MapDecoder.java @@ -1,7 +1,7 @@ -package com.strategyobject.substrateclient.rpc.core.decoders; +package com.strategyobject.substrateclient.rpc.decoders; import com.google.common.base.Preconditions; -import com.strategyobject.substrateclient.rpc.core.DecoderPair; +import com.strategyobject.substrateclient.rpc.DecoderPair; import com.strategyobject.substrateclient.transport.RpcObject; import lombok.val; diff --git a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/PairDecoder.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/PairDecoder.java similarity index 70% rename from rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/PairDecoder.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/PairDecoder.java index d61ae91e..00eefc4e 100644 --- a/rpc/rpc-types/src/main/java/com/strategyobject/substrateclient/rpc/types/PairDecoder.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/PairDecoder.java @@ -1,14 +1,11 @@ -package com.strategyobject.substrateclient.rpc.types; +package com.strategyobject.substrateclient.rpc.decoders; import com.google.common.base.Preconditions; -import com.strategyobject.substrateclient.rpc.core.DecoderPair; -import com.strategyobject.substrateclient.rpc.core.annotations.AutoRegister; -import com.strategyobject.substrateclient.rpc.core.decoders.AbstractDecoder; +import com.strategyobject.substrateclient.common.types.tuple.Pair; +import com.strategyobject.substrateclient.rpc.DecoderPair; import com.strategyobject.substrateclient.transport.RpcObject; -import com.strategyobject.substrateclient.types.tuples.Pair; import lombok.val; -@AutoRegister(types = Pair.class) public class PairDecoder extends AbstractDecoder> { @Override protected Pair decodeNonNull(RpcObject value, DecoderPair[] decoders) { diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/ShortDecoder.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/ShortDecoder.java similarity index 68% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/ShortDecoder.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/ShortDecoder.java index 51a7cb75..d811a69f 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/ShortDecoder.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/ShortDecoder.java @@ -1,6 +1,6 @@ -package com.strategyobject.substrateclient.rpc.core.decoders; +package com.strategyobject.substrateclient.rpc.decoders; -import com.strategyobject.substrateclient.rpc.core.DecoderPair; +import com.strategyobject.substrateclient.rpc.DecoderPair; import com.strategyobject.substrateclient.transport.RpcObject; public class ShortDecoder extends AbstractDecoder { diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/StringDecoder.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/StringDecoder.java similarity index 67% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/StringDecoder.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/StringDecoder.java index d435f5e8..c40b1f18 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/StringDecoder.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/StringDecoder.java @@ -1,6 +1,6 @@ -package com.strategyobject.substrateclient.rpc.core.decoders; +package com.strategyobject.substrateclient.rpc.decoders; -import com.strategyobject.substrateclient.rpc.core.DecoderPair; +import com.strategyobject.substrateclient.rpc.DecoderPair; import com.strategyobject.substrateclient.transport.RpcObject; public class StringDecoder extends AbstractDecoder { diff --git a/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/UnitDecoder.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/UnitDecoder.java new file mode 100644 index 00000000..4effbb66 --- /dev/null +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/UnitDecoder.java @@ -0,0 +1,16 @@ +package com.strategyobject.substrateclient.rpc.decoders; + +import com.google.common.base.Preconditions; +import com.strategyobject.substrateclient.common.types.Unit; +import com.strategyobject.substrateclient.rpc.DecoderPair; +import com.strategyobject.substrateclient.rpc.RpcDecoder; +import com.strategyobject.substrateclient.transport.RpcObject; + +public class UnitDecoder implements RpcDecoder { + @Override + public Unit decode(RpcObject value, DecoderPair... decoders) { + Preconditions.checkArgument(decoders == null || decoders.length == 0); + + return Unit.get(); + } +} diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/VoidDecoder.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/VoidDecoder.java similarity index 65% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/VoidDecoder.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/VoidDecoder.java index bb62bb0c..d3931efc 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/decoders/VoidDecoder.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/decoders/VoidDecoder.java @@ -1,8 +1,8 @@ -package com.strategyobject.substrateclient.rpc.core.decoders; +package com.strategyobject.substrateclient.rpc.decoders; import com.google.common.base.Preconditions; -import com.strategyobject.substrateclient.rpc.core.DecoderPair; -import com.strategyobject.substrateclient.rpc.core.RpcDecoder; +import com.strategyobject.substrateclient.rpc.DecoderPair; +import com.strategyobject.substrateclient.rpc.RpcDecoder; import com.strategyobject.substrateclient.transport.RpcObject; public class VoidDecoder implements RpcDecoder { diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/encoders/ArrayEncoder.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/encoders/ArrayEncoder.java similarity index 78% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/encoders/ArrayEncoder.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/encoders/ArrayEncoder.java index 292ddb4f..311c48fe 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/encoders/ArrayEncoder.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/encoders/ArrayEncoder.java @@ -1,8 +1,8 @@ -package com.strategyobject.substrateclient.rpc.core.encoders; +package com.strategyobject.substrateclient.rpc.encoders; import com.google.common.base.Preconditions; -import com.strategyobject.substrateclient.rpc.core.EncoderPair; -import com.strategyobject.substrateclient.rpc.core.RpcEncoder; +import com.strategyobject.substrateclient.rpc.EncoderPair; +import com.strategyobject.substrateclient.rpc.RpcEncoder; import lombok.val; import java.util.Arrays; diff --git a/rpc/src/main/java/com/strategyobject/substrateclient/rpc/encoders/DispatchingEncoder.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/encoders/DispatchingEncoder.java new file mode 100644 index 00000000..99c3b372 --- /dev/null +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/encoders/DispatchingEncoder.java @@ -0,0 +1,20 @@ +package com.strategyobject.substrateclient.rpc.encoders; + +import com.strategyobject.substrateclient.rpc.EncoderPair; +import com.strategyobject.substrateclient.rpc.RpcEncoder; +import com.strategyobject.substrateclient.rpc.registries.RpcEncoderRegistry; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.val; + +@RequiredArgsConstructor +public class DispatchingEncoder implements RpcEncoder { + private final @NonNull RpcEncoderRegistry registry; + + @SuppressWarnings("unchecked") + @Override + public Object encode(@NonNull T source, EncoderPair... encoders) { + val encoder = (RpcEncoder) registry.resolve(source.getClass()); + return encoder.encode(source, encoders); + } +} diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/encoders/ListEncoder.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/encoders/ListEncoder.java similarity index 78% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/encoders/ListEncoder.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/encoders/ListEncoder.java index 0981a9f3..07a6fce2 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/encoders/ListEncoder.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/encoders/ListEncoder.java @@ -1,8 +1,8 @@ -package com.strategyobject.substrateclient.rpc.core.encoders; +package com.strategyobject.substrateclient.rpc.encoders; import com.google.common.base.Preconditions; -import com.strategyobject.substrateclient.rpc.core.EncoderPair; -import com.strategyobject.substrateclient.rpc.core.RpcEncoder; +import com.strategyobject.substrateclient.rpc.EncoderPair; +import com.strategyobject.substrateclient.rpc.RpcEncoder; import lombok.val; import java.util.List; diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/encoders/MapEncoder.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/encoders/MapEncoder.java similarity index 82% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/encoders/MapEncoder.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/encoders/MapEncoder.java index 7879c41e..9e64024f 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/encoders/MapEncoder.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/encoders/MapEncoder.java @@ -1,8 +1,8 @@ -package com.strategyobject.substrateclient.rpc.core.encoders; +package com.strategyobject.substrateclient.rpc.encoders; import com.google.common.base.Preconditions; -import com.strategyobject.substrateclient.rpc.core.EncoderPair; -import com.strategyobject.substrateclient.rpc.core.RpcEncoder; +import com.strategyobject.substrateclient.rpc.EncoderPair; +import com.strategyobject.substrateclient.rpc.RpcEncoder; import lombok.val; import java.util.Map; diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/encoders/PlainEncoder.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/encoders/PlainEncoder.java similarity index 60% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/encoders/PlainEncoder.java rename to rpc/src/main/java/com/strategyobject/substrateclient/rpc/encoders/PlainEncoder.java index 50a6f8db..376032c5 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/encoders/PlainEncoder.java +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/encoders/PlainEncoder.java @@ -1,8 +1,8 @@ -package com.strategyobject.substrateclient.rpc.core.encoders; +package com.strategyobject.substrateclient.rpc.encoders; import com.google.common.base.Preconditions; -import com.strategyobject.substrateclient.rpc.core.EncoderPair; -import com.strategyobject.substrateclient.rpc.core.RpcEncoder; +import com.strategyobject.substrateclient.rpc.EncoderPair; +import com.strategyobject.substrateclient.rpc.RpcEncoder; public class PlainEncoder implements RpcEncoder { @Override diff --git a/rpc/src/main/java/com/strategyobject/substrateclient/rpc/encoders/UnitEncoder.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/encoders/UnitEncoder.java new file mode 100644 index 00000000..9577d9a5 --- /dev/null +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/encoders/UnitEncoder.java @@ -0,0 +1,16 @@ +package com.strategyobject.substrateclient.rpc.encoders; + +import com.google.common.base.Preconditions; +import com.strategyobject.substrateclient.common.types.Unit; +import com.strategyobject.substrateclient.rpc.EncoderPair; +import com.strategyobject.substrateclient.rpc.RpcEncoder; + +public class UnitEncoder implements RpcEncoder { + + @Override + public Object encode(Unit source, EncoderPair... encoders) { + Preconditions.checkArgument(encoders == null || encoders.length == 0); + + return null; + } +} diff --git a/rpc/src/main/java/com/strategyobject/substrateclient/rpc/metadata/ManualMetadataProvider.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/metadata/ManualMetadataProvider.java new file mode 100644 index 00000000..d47a7567 --- /dev/null +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/metadata/ManualMetadataProvider.java @@ -0,0 +1,20 @@ +package com.strategyobject.substrateclient.rpc.metadata; + +import com.strategyobject.substrateclient.crypto.ss58.SS58AddressFormat; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class ManualMetadataProvider implements MetadataProvider { + private final SS58AddressFormat ss58AddressFormat; + private final PalletCollection palletCollection; + + @Override + public SS58AddressFormat getSS58AddressFormat() { + return ss58AddressFormat; + } + + @Override + public PalletCollection getPallets() { + return palletCollection; + } +} diff --git a/rpc/src/main/java/com/strategyobject/substrateclient/rpc/metadata/MetadataProvider.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/metadata/MetadataProvider.java new file mode 100644 index 00000000..acad1ddf --- /dev/null +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/metadata/MetadataProvider.java @@ -0,0 +1,10 @@ +package com.strategyobject.substrateclient.rpc.metadata; + + +import com.strategyobject.substrateclient.crypto.ss58.SS58AddressFormat; + +public interface MetadataProvider { + SS58AddressFormat getSS58AddressFormat(); + + PalletCollection getPallets(); +} diff --git a/rpc/src/main/java/com/strategyobject/substrateclient/rpc/metadata/Pallet.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/metadata/Pallet.java new file mode 100644 index 00000000..a4056cd7 --- /dev/null +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/metadata/Pallet.java @@ -0,0 +1,12 @@ +package com.strategyobject.substrateclient.rpc.metadata; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NonNull; + +@Getter +@AllArgsConstructor +public class Pallet { + private final int index; + private final @NonNull String name; +} diff --git a/rpc/src/main/java/com/strategyobject/substrateclient/rpc/metadata/PalletCollection.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/metadata/PalletCollection.java new file mode 100644 index 00000000..02733e5e --- /dev/null +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/metadata/PalletCollection.java @@ -0,0 +1,28 @@ +package com.strategyobject.substrateclient.rpc.metadata; + +import com.google.common.base.Preconditions; +import lombok.NonNull; + +import java.util.stream.IntStream; + +public class PalletCollection { + private final Pallet[] pallets; + + public PalletCollection(Pallet @NonNull ... pallets) { + Preconditions.checkArgument(pallets.length > 0); + Preconditions.checkArgument(pallets[0].getIndex() == 0); + Preconditions.checkArgument(pallets.length == 1 || + IntStream.range(1, pallets.length) + .allMatch(i -> pallets[i].getIndex() == pallets[i - 1].getIndex() + 1)); + + this.pallets = pallets; + } + + public Pallet get(int index) { + return pallets[index]; + } + + public int size() { + return pallets.length; + } +} diff --git a/rpc/src/main/java/com/strategyobject/substrateclient/rpc/registries/RpcDecoderRegistry.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/registries/RpcDecoderRegistry.java new file mode 100644 index 00000000..92f33e0d --- /dev/null +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/registries/RpcDecoderRegistry.java @@ -0,0 +1,81 @@ +package com.strategyobject.substrateclient.rpc.registries; + +import com.strategyobject.substrateclient.common.reflection.ClassUtils; +import com.strategyobject.substrateclient.common.reflection.Scanner; +import com.strategyobject.substrateclient.common.types.Array; +import com.strategyobject.substrateclient.common.types.Unit; +import com.strategyobject.substrateclient.common.types.tuple.Pair; +import com.strategyobject.substrateclient.rpc.RpcDecoder; +import com.strategyobject.substrateclient.rpc.annotation.AutoRegister; +import com.strategyobject.substrateclient.rpc.context.RpcDecoderContext; +import com.strategyobject.substrateclient.rpc.context.RpcDecoderContextFactory; +import com.strategyobject.substrateclient.rpc.decoders.*; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import lombok.val; + +import java.lang.reflect.InvocationTargetException; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@Slf4j +public class RpcDecoderRegistry { + private final Map, RpcDecoder> decoders; + + public RpcDecoderRegistry() { + decoders = new ConcurrentHashMap<>(128); + register(new ListDecoder(), List.class); + register(new MapDecoder(), Map.class); + register(new VoidDecoder(), Void.class, void.class); + register(new UnitDecoder(), Unit.class); + register(new BooleanDecoder(), Boolean.class, boolean.class); + register(new ByteDecoder(), Byte.class, byte.class); + register(new DoubleDecoder(), Double.class, double.class); + register(new FloatDecoder(), Float.class, float.class); + register(new IntDecoder(), Integer.class, int.class); + register(new LongDecoder(), Long.class, long.class); + register(new ShortDecoder(), Short.class, short.class); + register(new StringDecoder(), String.class); + register(new ArrayDecoder(), Array.class); + register(new PairDecoder(), Pair.class); + } + + public void registerAnnotatedFrom(RpcDecoderContextFactory rpcDecoderContextFactory, String... prefixes) { + Scanner.forPrefixes(prefixes) + .getSubTypesOf(RpcDecoder.class).forEach(decoder -> { + val autoRegister = decoder.getAnnotation(AutoRegister.class); + if (autoRegister == null) { + return; + } + + try { + val types = autoRegister.types(); + log.info("Auto register decoder {} for types: {}", decoder, types); + + RpcDecoder rpcDecoder; + if (ClassUtils.hasDefaultConstructor(decoder)) { + rpcDecoder = decoder.newInstance(); + } else { + val ctor = decoder.getConstructor(RpcDecoderContext.class); + rpcDecoder = ctor.newInstance(rpcDecoderContextFactory.create()); + } + + register(rpcDecoder, types); + } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | + InvocationTargetException e) { + log.error("Auto registration error", e); + } + }); + } + + public void register(@NonNull RpcDecoder decoder, @NonNull Class... clazz) { + for (val type : clazz) { + decoders.put(type, decoder); + } + } + + public RpcDecoder resolve(@NonNull Class clazz) { + return decoders.get(clazz); + } +} diff --git a/rpc/src/main/java/com/strategyobject/substrateclient/rpc/registries/RpcEncoderRegistry.java b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/registries/RpcEncoderRegistry.java new file mode 100644 index 00000000..932e22fe --- /dev/null +++ b/rpc/src/main/java/com/strategyobject/substrateclient/rpc/registries/RpcEncoderRegistry.java @@ -0,0 +1,76 @@ +package com.strategyobject.substrateclient.rpc.registries; + +import com.strategyobject.substrateclient.common.reflection.ClassUtils; +import com.strategyobject.substrateclient.common.reflection.Scanner; +import com.strategyobject.substrateclient.common.types.Array; +import com.strategyobject.substrateclient.common.types.Unit; +import com.strategyobject.substrateclient.rpc.RpcDispatch; +import com.strategyobject.substrateclient.rpc.RpcEncoder; +import com.strategyobject.substrateclient.rpc.annotation.AutoRegister; +import com.strategyobject.substrateclient.rpc.context.RpcEncoderContext; +import com.strategyobject.substrateclient.rpc.context.RpcEncoderContextFactory; +import com.strategyobject.substrateclient.rpc.encoders.*; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import lombok.val; + +import java.lang.reflect.InvocationTargetException; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@Slf4j +public class RpcEncoderRegistry { + private final Map, RpcEncoder> encoders; + + public RpcEncoderRegistry() { + encoders = new ConcurrentHashMap<>(128); + register(new PlainEncoder<>(), + Void.class, void.class, String.class, Boolean.class, boolean.class, Byte.class, byte.class, + Double.class, double.class, Float.class, float.class, Integer.class, int.class, Long.class, + long.class, Short.class, short.class); + register(new UnitEncoder(), Unit.class); + register(new ListEncoder(), List.class); + register(new MapEncoder(), Map.class); + register(new ArrayEncoder(), Array.class); + register(new DispatchingEncoder<>(this), RpcDispatch.class); + } + + public void registerAnnotatedFrom(RpcEncoderContextFactory rpcEncoderContextFactory, String... prefixes) { + Scanner.forPrefixes(prefixes) + .getSubTypesOf(RpcEncoder.class).forEach(encoder -> { + val autoRegister = encoder.getAnnotation(AutoRegister.class); + if (autoRegister == null) { + return; + } + + try { + val types = autoRegister.types(); + log.info("Auto register encoder {} for types: {}", encoder, types); + + RpcEncoder rpcEncoder; + if (ClassUtils.hasDefaultConstructor(encoder)) { + rpcEncoder = encoder.newInstance(); + } else { + val ctor = encoder.getConstructor(RpcEncoderContext.class); + rpcEncoder = ctor.newInstance(rpcEncoderContextFactory.create()); + } + + register(rpcEncoder, types); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException | + NoSuchMethodException e) { + log.error("Auto registration error", e); + } + }); + } + + public void register(@NonNull RpcEncoder encoder, @NonNull Class... clazz) { + for (val type : clazz) { + encoders.put(type, encoder); + } + } + + public RpcEncoder resolve(@NonNull Class clazz) { + return encoders.get(clazz); + } +} diff --git a/rpc/rpc-core/src/test/java/com/strategyobject/substrateclient/rpc/core/decoders/ArrayDecoderTest.java b/rpc/src/test/java/com/strategyobject/substrateclient/rpc/decoders/ArrayDecoderTest.java similarity index 87% rename from rpc/rpc-core/src/test/java/com/strategyobject/substrateclient/rpc/core/decoders/ArrayDecoderTest.java rename to rpc/src/test/java/com/strategyobject/substrateclient/rpc/decoders/ArrayDecoderTest.java index b565b2fc..943e5c92 100644 --- a/rpc/rpc-core/src/test/java/com/strategyobject/substrateclient/rpc/core/decoders/ArrayDecoderTest.java +++ b/rpc/src/test/java/com/strategyobject/substrateclient/rpc/decoders/ArrayDecoderTest.java @@ -1,6 +1,6 @@ -package com.strategyobject.substrateclient.rpc.core.decoders; +package com.strategyobject.substrateclient.rpc.decoders; -import com.strategyobject.substrateclient.rpc.core.DecoderPair; +import com.strategyobject.substrateclient.rpc.DecoderPair; import com.strategyobject.substrateclient.transport.RpcObject; import lombok.val; import org.junit.jupiter.api.Test; diff --git a/rpc/rpc-core/src/test/java/com/strategyobject/substrateclient/rpc/core/decoders/KnownDecoderTests.java b/rpc/src/test/java/com/strategyobject/substrateclient/rpc/decoders/KnownDecoderTests.java similarity index 92% rename from rpc/rpc-core/src/test/java/com/strategyobject/substrateclient/rpc/core/decoders/KnownDecoderTests.java rename to rpc/src/test/java/com/strategyobject/substrateclient/rpc/decoders/KnownDecoderTests.java index 657272f2..9b011202 100644 --- a/rpc/rpc-core/src/test/java/com/strategyobject/substrateclient/rpc/core/decoders/KnownDecoderTests.java +++ b/rpc/src/test/java/com/strategyobject/substrateclient/rpc/decoders/KnownDecoderTests.java @@ -1,7 +1,7 @@ -package com.strategyobject.substrateclient.rpc.core.decoders; +package com.strategyobject.substrateclient.rpc.decoders; -import com.strategyobject.substrateclient.rpc.core.DecoderPair; -import com.strategyobject.substrateclient.rpc.core.RpcDecoder; +import com.strategyobject.substrateclient.rpc.DecoderPair; +import com.strategyobject.substrateclient.rpc.RpcDecoder; import com.strategyobject.substrateclient.tests.TestSuite; import com.strategyobject.substrateclient.transport.RpcObject; import lombok.AccessLevel; @@ -16,10 +16,10 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -public class KnownDecoderTests { +class KnownDecoderTests { @TestFactory - public Stream decode() { + Stream decode() { return TestSuite.of( Test.decode(new BooleanDecoder(), RpcObject.of(true), true), Test.decode(new ByteDecoder(), RpcObject.of(5), (byte) 5), @@ -51,7 +51,7 @@ public Stream decode() { } @TestFactory - public Stream decodeRpcNull() { + Stream decodeRpcNull() { return TestSuite.of( Test.decodeRpcNull(new BooleanDecoder(), null), Test.decodeRpcNull(new ByteDecoder(), null), @@ -76,7 +76,7 @@ public Stream decodeRpcNull() { } @AllArgsConstructor(access = AccessLevel.PRIVATE) - static class Test extends TestSuite.TestCase { + static class Test implements TestSuite.TestCase { private final RpcDecoder decoder; private final RpcObject given; private final T expected; diff --git a/rpc/rpc-core/src/test/java/com/strategyobject/substrateclient/rpc/core/decoders/KnownEncoderTests.java b/rpc/src/test/java/com/strategyobject/substrateclient/rpc/decoders/KnownEncoderTests.java similarity index 85% rename from rpc/rpc-core/src/test/java/com/strategyobject/substrateclient/rpc/core/decoders/KnownEncoderTests.java rename to rpc/src/test/java/com/strategyobject/substrateclient/rpc/decoders/KnownEncoderTests.java index 5864a7ef..bee24dea 100644 --- a/rpc/rpc-core/src/test/java/com/strategyobject/substrateclient/rpc/core/decoders/KnownEncoderTests.java +++ b/rpc/src/test/java/com/strategyobject/substrateclient/rpc/decoders/KnownEncoderTests.java @@ -1,11 +1,11 @@ -package com.strategyobject.substrateclient.rpc.core.decoders; +package com.strategyobject.substrateclient.rpc.decoders; import com.google.gson.Gson; -import com.strategyobject.substrateclient.rpc.core.EncoderPair; -import com.strategyobject.substrateclient.rpc.core.RpcEncoder; -import com.strategyobject.substrateclient.rpc.core.encoders.ListEncoder; -import com.strategyobject.substrateclient.rpc.core.encoders.MapEncoder; -import com.strategyobject.substrateclient.rpc.core.encoders.PlainEncoder; +import com.strategyobject.substrateclient.rpc.EncoderPair; +import com.strategyobject.substrateclient.rpc.RpcEncoder; +import com.strategyobject.substrateclient.rpc.encoders.ListEncoder; +import com.strategyobject.substrateclient.rpc.encoders.MapEncoder; +import com.strategyobject.substrateclient.rpc.encoders.PlainEncoder; import com.strategyobject.substrateclient.tests.TestSuite; import lombok.AccessLevel; import lombok.AllArgsConstructor; @@ -20,7 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -public class KnownEncoderTests { +class KnownEncoderTests { private static Map getSourceMap() { val result = new HashMap(); @@ -41,7 +41,7 @@ private static Map getExpectedMap() { } @TestFactory - public Stream encode() { + Stream encode() { return TestSuite.of( Test.encode(new PlainEncoder<>(), false, false), Test.encode(new PlainEncoder<>(), (byte) 5, (byte) 5), @@ -68,7 +68,7 @@ public Stream encode() { } @AllArgsConstructor(access = AccessLevel.PRIVATE) - static class Test extends TestSuite.TestCase { + static class Test implements TestSuite.TestCase { private static final Gson GSON = new Gson(); private final RpcEncoder encoder; diff --git a/rpc/src/test/java/com/strategyobject/substrateclient/rpc/encoders/DispatchingEncoderTest.java b/rpc/src/test/java/com/strategyobject/substrateclient/rpc/encoders/DispatchingEncoderTest.java new file mode 100644 index 00000000..5e443b36 --- /dev/null +++ b/rpc/src/test/java/com/strategyobject/substrateclient/rpc/encoders/DispatchingEncoderTest.java @@ -0,0 +1,26 @@ +package com.strategyobject.substrateclient.rpc.encoders; + +import com.strategyobject.substrateclient.rpc.RpcDispatch; +import com.strategyobject.substrateclient.rpc.RpcEncoder; +import com.strategyobject.substrateclient.rpc.registries.RpcEncoderRegistry; +import com.strategyobject.substrateclient.rpc.substitutes.TestDispatch; +import com.strategyobject.substrateclient.rpc.substitutes.TestDispatchEncoder; +import lombok.val; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class DispatchingEncoderTest { + private final RpcEncoderRegistry registry = new RpcEncoderRegistry() {{ + register(new TestDispatchEncoder(this), TestDispatch.class); + }}; + + @SuppressWarnings("unchecked") + @Test + void encode() { + val encoder = (RpcEncoder) registry.resolve(RpcDispatch.class); + val actual = encoder.encode(new TestDispatch("test")); + + assertEquals("test", actual); + } +} \ No newline at end of file diff --git a/rpc/src/test/java/com/strategyobject/substrateclient/rpc/metadata/PalletCollectionTest.java b/rpc/src/test/java/com/strategyobject/substrateclient/rpc/metadata/PalletCollectionTest.java new file mode 100644 index 00000000..9b19dba2 --- /dev/null +++ b/rpc/src/test/java/com/strategyobject/substrateclient/rpc/metadata/PalletCollectionTest.java @@ -0,0 +1,44 @@ +package com.strategyobject.substrateclient.rpc.metadata; + +import lombok.val; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class PalletCollectionTest { + @Test + void get() { + val pallet1 = mock(Pallet.class); + when(pallet1.getIndex()).thenReturn(0); + val pallet2 = mock(Pallet.class); + when(pallet2.getIndex()).thenReturn(1); + val pallet3 = mock(Pallet.class); + when(pallet3.getIndex()).thenReturn(2); + + PalletCollection palletCollection = new PalletCollection( + pallet1, + pallet2, + pallet3 + ); + + assertEquals(3, palletCollection.size()); + assertEquals(pallet1, palletCollection.get(0)); + assertEquals(pallet2, palletCollection.get(1)); + assertEquals(pallet3, palletCollection.get(2)); + } + + @Test + void failsWhenIndexIsNotIncremental() { + val pallet1 = mock(Pallet.class); + when(pallet1.getIndex()).thenReturn(0); + val pallet2 = mock(Pallet.class); + when(pallet2.getIndex()).thenReturn(1); + val pallet3 = mock(Pallet.class); + when(pallet3.getIndex()).thenReturn(1); + + assertThrows(IllegalArgumentException.class, () -> new PalletCollection(pallet1, pallet2, pallet3)); + } +} \ No newline at end of file diff --git a/rpc/src/test/java/com/strategyobject/substrateclient/rpc/substitutes/TestDispatch.java b/rpc/src/test/java/com/strategyobject/substrateclient/rpc/substitutes/TestDispatch.java new file mode 100644 index 00000000..ac288e58 --- /dev/null +++ b/rpc/src/test/java/com/strategyobject/substrateclient/rpc/substitutes/TestDispatch.java @@ -0,0 +1,10 @@ +package com.strategyobject.substrateclient.rpc.substitutes; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class TestDispatch { + private final String value; +} diff --git a/rpc/src/test/java/com/strategyobject/substrateclient/rpc/substitutes/TestDispatchEncoder.java b/rpc/src/test/java/com/strategyobject/substrateclient/rpc/substitutes/TestDispatchEncoder.java new file mode 100644 index 00000000..9e2f476a --- /dev/null +++ b/rpc/src/test/java/com/strategyobject/substrateclient/rpc/substitutes/TestDispatchEncoder.java @@ -0,0 +1,19 @@ +package com.strategyobject.substrateclient.rpc.substitutes; + +import com.strategyobject.substrateclient.rpc.EncoderPair; +import com.strategyobject.substrateclient.rpc.RpcEncoder; +import com.strategyobject.substrateclient.rpc.registries.RpcEncoderRegistry; +import lombok.RequiredArgsConstructor; +import lombok.val; + +@RequiredArgsConstructor +public class TestDispatchEncoder implements RpcEncoder { + private final RpcEncoderRegistry rpcEncoderRegistry; + + @SuppressWarnings("unchecked") + @Override + public Object encode(TestDispatch source, EncoderPair... encoders) { + val encoder = (RpcEncoder) rpcEncoderRegistry.resolve(String.class); + return encoder.encode(source.getValue()); + } +} diff --git a/scale/build.gradle b/scale/build.gradle index 7cd8517c..c1e76db1 100644 --- a/scale/build.gradle +++ b/scale/build.gradle @@ -1,6 +1,5 @@ dependencies { implementation project(':common') - implementation project(':types') testImplementation project(':tests') } diff --git a/scale/scale-codegen/build.gradle b/scale/scale-codegen/build.gradle index d85b5311..2cdb810d 100644 --- a/scale/scale-codegen/build.gradle +++ b/scale/scale-codegen/build.gradle @@ -1,10 +1,12 @@ dependencies { - implementation project(':scale') implementation project(':common') + implementation project(':scale') compileOnly 'com.google.auto.service:auto-service-annotations:1.0.1' annotationProcessor 'com.google.auto.service:auto-service:1.0.1' implementation 'com.squareup:javapoet:1.13.0' + + testImplementation project(':tests') testImplementation 'com.google.testing.compile:compile-testing:0.19' } \ No newline at end of file diff --git a/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/ScaleAnnotationParser.java b/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/ScaleAnnotationParser.java index b6ef1d5e..a4eccffe 100644 --- a/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/ScaleAnnotationParser.java +++ b/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/ScaleAnnotationParser.java @@ -5,9 +5,9 @@ import com.strategyobject.substrateclient.common.codegen.ProcessorContext; import com.strategyobject.substrateclient.common.codegen.TypeTraverser; import com.strategyobject.substrateclient.common.codegen.TypeUtils; -import com.strategyobject.substrateclient.common.utils.StringUtils; -import com.strategyobject.substrateclient.scale.annotations.Scale; -import com.strategyobject.substrateclient.scale.annotations.ScaleGeneric; +import com.strategyobject.substrateclient.common.strings.StringUtils; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleGeneric; import lombok.NonNull; import lombok.val; import lombok.var; @@ -23,6 +23,8 @@ import static com.strategyobject.substrateclient.scale.codegen.ScaleProcessorHelper.SCALE_ANNOTATIONS_DEFAULT; public class ScaleAnnotationParser { + private static final String VALUE = "value"; + private static final String TEMPLATE = "template"; private final ProcessorContext context; public ScaleAnnotationParser(@NonNull ProcessorContext context) { @@ -30,14 +32,14 @@ public ScaleAnnotationParser(@NonNull ProcessorContext context) { } public TypeTraverser.TypeTreeNode parse(@NonNull AnnotatedConstruct annotated) { - val scaleType = AnnotationUtils.getValueFromAnnotation(annotated, Scale.class, "value"); + val scaleType = AnnotationUtils.getValueFromAnnotation(annotated, Scale.class, VALUE); if (scaleType != null) { return new TypeTraverser.TypeTreeNode(scaleType); } val scaleGeneric = AnnotationUtils.getAnnotationMirror(annotated, ScaleGeneric.class); if (scaleGeneric != null) { - val template = AnnotationUtils.getValueFromAnnotation(scaleGeneric, "template"); + val template = AnnotationUtils.getValueFromAnnotation(scaleGeneric, TEMPLATE); val typesMap = getTypesMap(scaleGeneric); return parseTemplate(template, typesMap); } @@ -47,13 +49,13 @@ public TypeTraverser.TypeTreeNode parse(@NonNull AnnotatedConstruct annotated) { public TypeTraverser.TypeTreeNode parse(AnnotationMirror annotation) { if (context.isSameType(annotation.getAnnotationType(), context.getType(Scale.class))) { - val scaleType = AnnotationUtils.getValueFromAnnotation(annotation, "value"); + val scaleType = AnnotationUtils.getValueFromAnnotation(annotation, VALUE); return new TypeTraverser.TypeTreeNode(scaleType); } if (context.isSameType(annotation.getAnnotationType(), context.getType(ScaleGeneric.class))) { - val template = AnnotationUtils.getValueFromAnnotation(annotation, "template"); + val template = AnnotationUtils.getValueFromAnnotation(annotation, TEMPLATE); val typesMap = getTypesMap(annotation); return parseTemplate(template, typesMap); @@ -64,8 +66,11 @@ public TypeTraverser.TypeTreeNode parse(AnnotationMirror annotation) { private TypeTraverser.TypeTreeNode parseTemplate(String template, Map typesMap) { val indexes = StringUtils.allIndexesOfAny(template, "<,>"); - if (indexes.size() == 0 || indexes.get(0) == 0) { - throw new IllegalArgumentException("Wrong template"); + if (indexes.size() == 0) { + return new TypeTraverser.TypeTreeNode(getMappedType(typesMap, template.trim())); + } + if (indexes.get(0) == 0) { + throw new IllegalArgumentException("Template cannot begin with a special character"); } val firstIndex = indexes.get(0); @@ -101,7 +106,7 @@ private TypeTraverser.TypeTreeNode parseTemplate(String template, Map getTypesMap(AnnotationMirror scaleGeneric) { val annotations = AnnotationUtils.>getValueFromAnnotation(scaleGeneric, "types"); val result = new HashMap(Objects.requireNonNull(annotations).size()); for (val annotation : annotations) { - var type = AnnotationUtils.getValueFromAnnotation(annotation, "value"); + var type = AnnotationUtils.getValueFromAnnotation(annotation, VALUE); var name = AnnotationUtils.getValueFromAnnotation(annotation, "name"); validateScaleAnnotationIsNotEmpty(name, type); diff --git a/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/ScaleProcessorHelper.java b/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/ScaleProcessorHelper.java index 17af269a..20a75c63 100644 --- a/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/ScaleProcessorHelper.java +++ b/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/ScaleProcessorHelper.java @@ -1,10 +1,10 @@ package com.strategyobject.substrateclient.scale.codegen; -import com.strategyobject.substrateclient.scale.ScaleSelfWritable; -import com.strategyobject.substrateclient.scale.annotations.Default; +import com.strategyobject.substrateclient.scale.ScaleDispatch; +import com.strategyobject.substrateclient.scale.annotation.Default; public class ScaleProcessorHelper { - public static final Class SCALE_SELF_WRITABLE = ScaleSelfWritable.class; + public static final Class SCALE_DISPATCH = ScaleDispatch.class; public static final Class SCALE_ANNOTATIONS_DEFAULT = Default.class; private static final String READER_NAME_TEMPLATE = "%sReader"; private static final String WRITER_NAME_TEMPLATE = "%sWriter"; @@ -16,4 +16,7 @@ public static String getReaderName(String className) { public static String getWriterName(String className) { return String.format(WRITER_NAME_TEMPLATE, className); } + + private ScaleProcessorHelper() { + } } diff --git a/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/reader/ReaderCompositor.java b/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/reader/ReaderCompositor.java index 1ae4da6e..6710f5ef 100644 --- a/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/reader/ReaderCompositor.java +++ b/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/reader/ReaderCompositor.java @@ -2,9 +2,10 @@ import com.google.common.base.Strings; import com.squareup.javapoet.CodeBlock; -import com.strategyobject.substrateclient.common.codegen.Constants; import com.strategyobject.substrateclient.common.codegen.ProcessorContext; +import com.strategyobject.substrateclient.common.codegen.TypeNotSupportedException; import com.strategyobject.substrateclient.common.codegen.TypeTraverser; +import com.strategyobject.substrateclient.common.types.Array; import lombok.NonNull; import lombok.var; @@ -28,7 +29,7 @@ private ReaderCompositor(ProcessorContext context, this.typeVarMap = typeVarMap; this.readerAccessor = readerAccessor; this.registryVarName = registryVarName; - this.arrayType = context.erasure(context.getType(Constants.ARRAY_TYPE)); + this.arrayType = context.erasure(context.getType(Array.class)); } public static ReaderCompositor forAnyType(@NonNull ProcessorContext context, @@ -83,6 +84,11 @@ private CodeBlock getGenericCodeBlock(TypeMirror type, TypeMirror override, Code } + @Override + protected CodeBlock whenWildcard(TypeMirror override) { + throw new TypeNotSupportedException("WILDCARD"); + } + @Override protected CodeBlock whenTypeVar(@NonNull TypeVariable type, TypeMirror _override) { return getTypeVarCodeBlock(type); diff --git a/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/reader/ScaleReaderAnnotatedClass.java b/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/reader/ScaleReaderAnnotatedClass.java index 40ff4b4a..196c964e 100644 --- a/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/reader/ScaleReaderAnnotatedClass.java +++ b/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/reader/ScaleReaderAnnotatedClass.java @@ -1,12 +1,10 @@ package com.strategyobject.substrateclient.scale.codegen.reader; import com.squareup.javapoet.*; -import com.strategyobject.substrateclient.common.codegen.JavaPoet; -import com.strategyobject.substrateclient.common.codegen.ProcessingException; -import com.strategyobject.substrateclient.common.codegen.ProcessorContext; +import com.strategyobject.substrateclient.common.codegen.*; import com.strategyobject.substrateclient.scale.ScaleReader; -import com.strategyobject.substrateclient.scale.annotations.AutoRegister; -import com.strategyobject.substrateclient.scale.annotations.Ignore; +import com.strategyobject.substrateclient.scale.annotation.AutoRegister; +import com.strategyobject.substrateclient.scale.annotation.Ignore; import com.strategyobject.substrateclient.scale.codegen.ScaleAnnotationParser; import com.strategyobject.substrateclient.scale.codegen.ScaleProcessorHelper; import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry; @@ -54,7 +52,9 @@ public void generateReader(@NonNull ProcessorContext context) throws IOException .addMember("types", "{$L.class}", classElement.getQualifiedName().toString()) .build()) .addModifiers(Modifier.PUBLIC) - .addSuperinterface(ParameterizedTypeName.get(ClassName.get(ScaleReader.class), classWildcardTyped)) + .addSuperinterface(ParameterizedTypeName.get(ClassName.get(ScaleReader.class), classWildcardTyped)); + + injectDependencies(typeSpecBuilder) .addMethod(generateReadMethod(classWildcardTyped, context)); JavaFile.builder( @@ -63,6 +63,21 @@ public void generateReader(@NonNull ProcessorContext context) throws IOException ).build().writeTo(context.getFiler()); } + private TypeSpec.Builder injectDependencies(TypeSpec.Builder typeSpecBuilder) { + val ctor = MethodSpec.constructorBuilder() + .addModifiers(Modifier.PUBLIC) + .addParameter(ScaleReaderRegistry.class, REGISTRY) + .beginControlFlow("if ($L == null)", REGISTRY) + .addStatement("throw new $T(\"$L can't be null.\")", IllegalArgumentException.class, REGISTRY) + .endControlFlow() + .addStatement("this.$1L = $1L", REGISTRY) + .build(); + + return typeSpecBuilder + .addField(ScaleReaderRegistry.class, REGISTRY, Modifier.PRIVATE, Modifier.FINAL) + .addMethod(ctor); + } + private MethodSpec generateReadMethod(TypeName classWildcardTyped, ProcessorContext context) throws ProcessingException { val methodSpec = MethodSpec.methodBuilder("read") @@ -104,7 +119,6 @@ private void addMethodBody(MethodSpec.Builder methodSpec, ProcessorContext context) throws ProcessingException { val resultType = JavaPoet.setEachGenericParameterAs(classElement, TypeName.OBJECT); methodSpec - .addStatement("$1T $2L = $1T.getInstance()", ScaleReaderRegistry.class, REGISTRY) .addStatement("$1T result = new $1T()", resultType) .beginControlFlow("try"); @@ -116,7 +130,7 @@ private void addMethodBody(MethodSpec.Builder methodSpec, for (Element element : classElement.getEnclosedElements()) { if (element instanceof VariableElement) { val field = (VariableElement) element; - if (field.getAnnotation(Ignore.class) == null) { + if (!AnnotationUtils.isAnnotatedWith(field, Ignore.class) && !field.getModifiers().contains(Modifier.STATIC)) { setField(methodSpec, field, context.getTypeUtils(), scaleAnnotationParser, compositor); } } diff --git a/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/reader/ScaleReaderAnnotatedEnum.java b/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/reader/ScaleReaderAnnotatedEnum.java new file mode 100644 index 00000000..dd1bae42 --- /dev/null +++ b/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/reader/ScaleReaderAnnotatedEnum.java @@ -0,0 +1,77 @@ +package com.strategyobject.substrateclient.scale.codegen.reader; + +import com.squareup.javapoet.*; +import com.strategyobject.substrateclient.common.codegen.ProcessingException; +import com.strategyobject.substrateclient.common.codegen.ProcessorContext; +import com.strategyobject.substrateclient.common.io.Streamer; +import com.strategyobject.substrateclient.common.types.Enums; +import com.strategyobject.substrateclient.scale.ScaleReader; +import com.strategyobject.substrateclient.scale.annotation.AutoRegister; +import com.strategyobject.substrateclient.scale.codegen.ScaleProcessorHelper; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.val; + +import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; +import java.io.IOException; +import java.io.InputStream; + +@RequiredArgsConstructor +public class ScaleReaderAnnotatedEnum { + private static final String READERS_ARG = "readers"; + private static final String ENUM_VALUES = "values"; + + private final @NonNull TypeElement enumElement; + + public void generateReader(@NonNull ProcessorContext context) throws IOException, ProcessingException { + val readerName = ScaleProcessorHelper.getReaderName(enumElement.getSimpleName().toString()); + val enumType = TypeName.get(enumElement.asType()); + + val typeSpecBuilder = TypeSpec.classBuilder(readerName) + .addAnnotation(AnnotationSpec.builder(AutoRegister.class) + .addMember("types", "{$L.class}", enumElement.getQualifiedName().toString()) + .build()) + .addModifiers(Modifier.PUBLIC) + .addSuperinterface(ParameterizedTypeName.get(ClassName.get(ScaleReader.class), enumType)) + .addField( + FieldSpec.builder(ArrayTypeName.of(enumType), ENUM_VALUES, Modifier.PRIVATE, Modifier.FINAL) + .initializer("$T.values()", enumType) + .build()) + .addMethod(generateReadMethod(enumType)); + + JavaFile.builder( + context.getPackageName(enumElement), + typeSpecBuilder.build() + ).build().writeTo(context.getFiler()); + } + + private MethodSpec generateReadMethod(TypeName enumType) { + val methodSpec = MethodSpec.methodBuilder("read") + .addAnnotation(Override.class) + .addModifiers(Modifier.PUBLIC) + .returns(enumType) + .addParameter(InputStream.class, "stream") + .addParameter(ArrayTypeName.of( + ParameterizedTypeName.get( + ClassName.get(ScaleReader.class), + WildcardTypeName.subtypeOf(Object.class))), + READERS_ARG) + .varargs(true) + .addException(IOException.class); + + addValidationRules(methodSpec); + addMethodBody(methodSpec); + return methodSpec.build(); + } + + private void addValidationRules(MethodSpec.Builder methodSpec) { + methodSpec + .addStatement("if (stream == null) throw new IllegalArgumentException(\"stream is null\")") + .addStatement("if (readers != null && readers.length > 0) throw new IllegalArgumentException()"); + } + + private void addMethodBody(MethodSpec.Builder methodSpec) { + methodSpec.addStatement("return $T.lookup($L, $T.readByte(stream))", Enums.class, ENUM_VALUES, Streamer.class); + } +} diff --git a/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/reader/ScaleReaderProcessor.java b/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/reader/ScaleReaderProcessor.java index 4222f718..9ac09a8c 100644 --- a/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/reader/ScaleReaderProcessor.java +++ b/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/reader/ScaleReaderProcessor.java @@ -3,17 +3,18 @@ import com.google.auto.service.AutoService; import com.strategyobject.substrateclient.common.codegen.ProcessingException; import com.strategyobject.substrateclient.common.codegen.ProcessorContext; -import com.strategyobject.substrateclient.scale.annotations.ScaleReader; +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; import lombok.val; import javax.annotation.processing.*; import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.TypeElement; import java.io.IOException; import java.util.Set; -@SupportedAnnotationTypes("com.strategyobject.substrateclient.scale.annotations.ScaleReader") +@SupportedAnnotationTypes("com.strategyobject.substrateclient.scale.annotation.ScaleReader") @SupportedSourceVersion(SourceVersion.RELEASE_8) @AutoService(Processor.class) public class ScaleReaderProcessor extends AbstractProcessor { @@ -34,11 +35,12 @@ public boolean process(Set annotations, RoundEnvironment return false; } - for (val annotatedElement : roundEnv.getElementsAnnotatedWith(ScaleReader.class)) { - if (annotatedElement.getKind() != ElementKind.CLASS) { + for (Element annotatedElement : roundEnv.getElementsAnnotatedWith(ScaleReader.class)) { + val elementKind = annotatedElement.getKind(); + if (!elementKind.isClass()) { context.error( annotatedElement, - "Only classes can be annotated with `@%s`.", + "Only classes and enums can be annotated with `@%s`.", ScaleReader.class.getSimpleName()); return true; @@ -46,7 +48,11 @@ public boolean process(Set annotations, RoundEnvironment val typeElement = (TypeElement) annotatedElement; try { - new ScaleReaderAnnotatedClass(typeElement).generateReader(context); + if (elementKind == ElementKind.CLASS) { + new ScaleReaderAnnotatedClass(typeElement).generateReader(context); + } else { + new ScaleReaderAnnotatedEnum(typeElement).generateReader(context); + } } catch (ProcessingException e) { context.error(typeElement, e); return true; diff --git a/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/writer/ScaleWriterAnnotatedClass.java b/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/writer/ScaleWriterAnnotatedClass.java index bf27c1c5..159aea4c 100644 --- a/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/writer/ScaleWriterAnnotatedClass.java +++ b/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/writer/ScaleWriterAnnotatedClass.java @@ -1,12 +1,13 @@ package com.strategyobject.substrateclient.scale.codegen.writer; import com.squareup.javapoet.*; +import com.strategyobject.substrateclient.common.codegen.AnnotationUtils; import com.strategyobject.substrateclient.common.codegen.JavaPoet; import com.strategyobject.substrateclient.common.codegen.ProcessingException; import com.strategyobject.substrateclient.common.codegen.ProcessorContext; import com.strategyobject.substrateclient.scale.ScaleWriter; -import com.strategyobject.substrateclient.scale.annotations.AutoRegister; -import com.strategyobject.substrateclient.scale.annotations.Ignore; +import com.strategyobject.substrateclient.scale.annotation.AutoRegister; +import com.strategyobject.substrateclient.scale.annotation.Ignore; import com.strategyobject.substrateclient.scale.codegen.ScaleAnnotationParser; import com.strategyobject.substrateclient.scale.codegen.ScaleProcessorHelper; import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; @@ -26,7 +27,6 @@ import static com.strategyobject.substrateclient.common.codegen.AnnotationUtils.suppressWarnings; import static com.strategyobject.substrateclient.common.codegen.TypeUtils.getGetterName; -import static com.strategyobject.substrateclient.scale.codegen.ScaleProcessorHelper.SCALE_SELF_WRITABLE; import static java.util.stream.Collectors.toMap; public class ScaleWriterAnnotatedClass { @@ -53,7 +53,9 @@ public void generateWriter(@NonNull ProcessorContext context) throws IOException .addMember("types", "{$L.class}", classElement.getQualifiedName().toString()) .build()) .addModifiers(Modifier.PUBLIC) - .addSuperinterface(ParameterizedTypeName.get(ClassName.get(ScaleWriter.class), classWildcardTyped)) + .addSuperinterface(ParameterizedTypeName.get(ClassName.get(ScaleWriter.class), classWildcardTyped)); + + injectDependencies(typeSpecBuilder) .addMethod(generateWriteMethod(classWildcardTyped, context)); JavaFile.builder( @@ -62,6 +64,21 @@ public void generateWriter(@NonNull ProcessorContext context) throws IOException ).build().writeTo(context.getFiler()); } + private TypeSpec.Builder injectDependencies(TypeSpec.Builder typeSpecBuilder) { + val ctor = MethodSpec.constructorBuilder() + .addModifiers(Modifier.PUBLIC) + .addParameter(ScaleWriterRegistry.class, REGISTRY) + .beginControlFlow("if ($L == null)", REGISTRY) + .addStatement("throw new $T(\"$L can't be null.\")", IllegalArgumentException.class, REGISTRY) + .endControlFlow() + .addStatement("this.$1L = $1L", REGISTRY) + .build(); + + return typeSpecBuilder + .addField(ScaleWriterRegistry.class, REGISTRY, Modifier.PRIVATE, Modifier.FINAL) + .addMethod(ctor); + } + private MethodSpec generateWriteMethod(TypeName classWildcardTyped, ProcessorContext context) throws ProcessingException { val methodSpec = MethodSpec.methodBuilder("write") @@ -75,22 +92,21 @@ private MethodSpec generateWriteMethod(TypeName classWildcardTyped, ParameterizedTypeName.get( ClassName.get(ScaleWriter.class), WildcardTypeName.subtypeOf(Object.class))), - "writers") + WRITERS_ARG) .varargs(true) .addException(IOException.class); - addValidationRules(methodSpec, context); + addValidationRules(methodSpec); addMethodBody(methodSpec, context); return methodSpec.build(); } - private void addValidationRules(MethodSpec.Builder methodSpec, - ProcessorContext context) { + private void addValidationRules(MethodSpec.Builder methodSpec) { methodSpec.addStatement("if (stream == null) throw new IllegalArgumentException(\"stream is null\")"); methodSpec.addStatement("if (value == null) throw new IllegalArgumentException(\"value is null\")"); val classTypeParametersSize = classElement.getTypeParameters().size(); - if (classTypeParametersSize == 0 || context.isAssignable(classElement.asType(), context.erasure(context.getType(SCALE_SELF_WRITABLE)))) { + if (classTypeParametersSize == 0) { methodSpec.addStatement("if (writers != null && writers.length > 0) throw new IllegalArgumentException()"); } else { methodSpec @@ -105,7 +121,6 @@ private void addValidationRules(MethodSpec.Builder methodSpec, private void addMethodBody(MethodSpec.Builder methodSpec, ProcessorContext context) throws ProcessingException { methodSpec - .addStatement("$1T registry = $1T.getInstance()", ScaleWriterRegistry.class) .beginControlFlow("try"); val scaleAnnotationParser = new ScaleAnnotationParser(context); @@ -116,7 +131,7 @@ private void addMethodBody(MethodSpec.Builder methodSpec, for (Element element : classElement.getEnclosedElements()) { if (element instanceof VariableElement) { val field = (VariableElement) element; - if (field.getAnnotation(Ignore.class) == null) { + if (!AnnotationUtils.isAnnotatedWith(field, Ignore.class) && !field.getModifiers().contains(Modifier.STATIC)) { setField(methodSpec, field, scaleAnnotationParser, compositor); } } diff --git a/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/writer/ScaleWriterAnnotatedEnum.java b/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/writer/ScaleWriterAnnotatedEnum.java new file mode 100644 index 00000000..23ab2d78 --- /dev/null +++ b/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/writer/ScaleWriterAnnotatedEnum.java @@ -0,0 +1,71 @@ +package com.strategyobject.substrateclient.scale.codegen.writer; + +import com.squareup.javapoet.*; +import com.strategyobject.substrateclient.common.codegen.ProcessingException; +import com.strategyobject.substrateclient.common.codegen.ProcessorContext; +import com.strategyobject.substrateclient.scale.ScaleWriter; +import com.strategyobject.substrateclient.scale.annotation.AutoRegister; +import com.strategyobject.substrateclient.scale.codegen.ScaleProcessorHelper; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.val; + +import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; +import java.io.IOException; +import java.io.OutputStream; + +@RequiredArgsConstructor +public class ScaleWriterAnnotatedEnum { + private static final String WRITERS_ARG = "writers"; + + private final @NonNull TypeElement enumElement; + + public void generateWriter(@NonNull ProcessorContext context) throws IOException, ProcessingException { + val writerName = ScaleProcessorHelper.getWriterName(enumElement.getSimpleName().toString()); + val enumType = TypeName.get(enumElement.asType()); + + val typeSpecBuilder = TypeSpec.classBuilder(writerName) + .addAnnotation(AnnotationSpec.builder(AutoRegister.class) + .addMember("types", "{$L.class}", enumElement.getQualifiedName().toString()) + .build()) + .addModifiers(Modifier.PUBLIC) + .addSuperinterface(ParameterizedTypeName.get(ClassName.get(ScaleWriter.class), enumType)) + .addMethod(generateWriteMethod(enumType)); + + JavaFile.builder( + context.getPackageName(enumElement), + typeSpecBuilder.build() + ).build().writeTo(context.getFiler()); + } + + private MethodSpec generateWriteMethod(TypeName classWildcardTyped) { + val methodSpec = MethodSpec.methodBuilder("write") + .addAnnotation(Override.class) + .addModifiers(Modifier.PUBLIC) + .returns(TypeName.VOID) + .addParameter(classWildcardTyped, "value") + .addParameter(OutputStream.class, "stream") + .addParameter(ArrayTypeName.of( + ParameterizedTypeName.get( + ClassName.get(ScaleWriter.class), + WildcardTypeName.subtypeOf(Object.class))), + WRITERS_ARG) + .varargs(true) + .addException(IOException.class); + + addValidationRules(methodSpec); + addMethodBody(methodSpec); + return methodSpec.build(); + } + + private void addValidationRules(MethodSpec.Builder methodSpec) { + methodSpec.addStatement("if (stream == null) throw new IllegalArgumentException(\"stream is null\")"); + methodSpec.addStatement("if (value == null) throw new IllegalArgumentException(\"value is null\")"); + methodSpec.addStatement("if (writers != null && writers.length > 0) throw new IllegalArgumentException()"); + } + + private void addMethodBody(MethodSpec.Builder methodSpec) { + methodSpec.addStatement("stream.write(value.ordinal())"); + } +} diff --git a/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/writer/ScaleWriterProcessor.java b/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/writer/ScaleWriterProcessor.java index cdd2e061..a0881a73 100644 --- a/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/writer/ScaleWriterProcessor.java +++ b/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/writer/ScaleWriterProcessor.java @@ -3,19 +3,18 @@ import com.google.auto.service.AutoService; import com.strategyobject.substrateclient.common.codegen.ProcessingException; import com.strategyobject.substrateclient.common.codegen.ProcessorContext; -import com.strategyobject.substrateclient.scale.annotations.ScaleWriter; +import com.strategyobject.substrateclient.scale.annotation.ScaleWriter; import lombok.val; import javax.annotation.processing.*; import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.TypeElement; import java.io.IOException; import java.util.Set; -import static com.strategyobject.substrateclient.scale.codegen.ScaleProcessorHelper.SCALE_SELF_WRITABLE; - -@SupportedAnnotationTypes("com.strategyobject.substrateclient.scale.annotations.ScaleWriter") +@SupportedAnnotationTypes("com.strategyobject.substrateclient.scale.annotation.ScaleWriter") @SupportedSourceVersion(SourceVersion.RELEASE_8) @AutoService(Processor.class) public class ScaleWriterProcessor extends AbstractProcessor { @@ -36,27 +35,24 @@ public boolean process(Set annotations, RoundEnvironment return false; } - for (val annotatedElement : roundEnv.getElementsAnnotatedWith(ScaleWriter.class)) { - if (annotatedElement.getKind() != ElementKind.CLASS) { + for (Element annotatedElement : roundEnv.getElementsAnnotatedWith(ScaleWriter.class)) { + val elementKind = annotatedElement.getKind(); + if (!elementKind.isClass()) { context.error( annotatedElement, - "Only classes can be annotated with `@%s`.", + "Only classes and enums can be annotated with `@%s`.", ScaleWriter.class.getSimpleName()); return true; } val typeElement = (TypeElement) annotatedElement; - if (!validateScaleSelfWritable(typeElement)) { - context.error( - typeElement, - "Classes implementing `%1$s` and annotated with `@%2$s` have to be either non generic or all its parameters have to implement `%1$s`", - SCALE_SELF_WRITABLE.getCanonicalName(), - ScaleWriter.class.getSimpleName()); - } - try { - new ScaleWriterAnnotatedClass(typeElement).generateWriter(context); + if (elementKind == ElementKind.CLASS) { + new ScaleWriterAnnotatedClass(typeElement).generateWriter(context); + } else { + new ScaleWriterAnnotatedEnum(typeElement).generateWriter(context); + } } catch (ProcessingException e) { context.error(typeElement, e); return true; @@ -68,15 +64,4 @@ public boolean process(Set annotations, RoundEnvironment return true; } - - private boolean validateScaleSelfWritable(TypeElement typeElement) { - val selfWritable = context.erasure(context.getType(SCALE_SELF_WRITABLE)); - if (!context.isAssignable(typeElement.asType(), selfWritable)) { - return true; - } - - val typeParameters = typeElement.getTypeParameters(); - return typeParameters.size() == 0 || - typeParameters.stream().allMatch(x -> context.isAssignable(x.asType(), selfWritable)); - } } diff --git a/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/writer/WriterCompositor.java b/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/writer/WriterCompositor.java index 5410e817..76e69d7d 100644 --- a/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/writer/WriterCompositor.java +++ b/scale/scale-codegen/src/main/java/com/strategyobject/substrateclient/scale/codegen/writer/WriterCompositor.java @@ -1,26 +1,24 @@ package com.strategyobject.substrateclient.scale.codegen.writer; import com.squareup.javapoet.CodeBlock; -import com.strategyobject.substrateclient.common.codegen.Constants; import com.strategyobject.substrateclient.common.codegen.ProcessorContext; import com.strategyobject.substrateclient.common.codegen.TypeTraverser; +import com.strategyobject.substrateclient.common.types.Array; import lombok.NonNull; import lombok.var; import javax.lang.model.type.*; import java.util.Map; -import static com.strategyobject.substrateclient.scale.codegen.ScaleProcessorHelper.SCALE_SELF_WRITABLE; +import static com.strategyobject.substrateclient.scale.codegen.ScaleProcessorHelper.SCALE_DISPATCH; public class WriterCompositor extends TypeTraverser { private final ProcessorContext context; private final Map typeVarMap; - private final TypeMirror selfWritable; private final String writerAccessor; private final String registryVarName; private final TypeMirror arrayType; - private WriterCompositor(ProcessorContext context, Map typeVarMap, String writerAccessor, @@ -29,10 +27,9 @@ private WriterCompositor(ProcessorContext context, this.context = context; this.typeVarMap = typeVarMap; - this.selfWritable = context.erasure(context.getType(SCALE_SELF_WRITABLE)); this.writerAccessor = writerAccessor; this.registryVarName = registryVarName; - this.arrayType = context.erasure(context.getType(Constants.ARRAY_TYPE)); + this.arrayType = context.erasure(context.getType(Array.class)); } public static WriterCompositor forAnyType(@NonNull ProcessorContext context, @@ -49,13 +46,7 @@ public static WriterCompositor disallowOpenGeneric(@NonNull ProcessorContext con private CodeBlock getNonGenericCodeBlock(TypeMirror type, TypeMirror override) { return CodeBlock.builder() - .add("$L.resolve($T.class)", - registryVarName, - override != null ? - override : - context.isAssignable(type, selfWritable) ? - selfWritable : - type) + .add("$L.resolve($T.class)", registryVarName, override != null ? override : type) .build(); } @@ -71,10 +62,6 @@ private CodeBlock getGenericCodeBlock(TypeMirror type, TypeMirror override, Code resolveType = override; } else { resolveType = context.erasure(type); - - if (context.isAssignable(resolveType, selfWritable)) { - return CodeBlock.builder().add("$L.resolve($T.class)", registryVarName, selfWritable).build(); - } } var builder = CodeBlock.builder().add("$L.resolve($T.class).inject(", registryVarName, resolveType); @@ -86,15 +73,18 @@ private CodeBlock getGenericCodeBlock(TypeMirror type, TypeMirror override, Code return builder.add(")").build(); } + @Override + protected CodeBlock whenWildcard(TypeMirror override) { + return CodeBlock.builder() + .add("$L.resolve($T.class)", registryVarName, SCALE_DISPATCH) + .build(); + } + @Override protected CodeBlock whenTypeVar(@NonNull TypeVariable type, TypeMirror _override) { - return context.isAssignable(type, selfWritable) ? - CodeBlock.builder() - .add("$L.resolve($T.class)", registryVarName, selfWritable) - .build() : - CodeBlock.builder() - .add(writerAccessor, typeVarMap.get(type.toString())) - .build(); + return CodeBlock.builder() + .add(writerAccessor, typeVarMap.get(type.toString())) + .build(); } @Override @@ -111,7 +101,7 @@ protected CodeBlock whenNonGenericType(@NonNull DeclaredType type, TypeMirror ov protected CodeBlock whenGenericType(@NonNull DeclaredType type, TypeMirror override, @NonNull CodeBlock[] subtypes) { TypeMirror resolveType; if (override != null) { - if (context.isNonGeneric(override)) { + if (subtypes.length == 0) { return CodeBlock.builder() .add("$L.resolve($T.class)", registryVarName, override) .build(); @@ -120,10 +110,6 @@ protected CodeBlock whenGenericType(@NonNull DeclaredType type, TypeMirror overr resolveType = override; } else { resolveType = context.erasure(type); - - if (context.isAssignable(resolveType, selfWritable)) { - return CodeBlock.builder().add("$L.resolve($T.class)", registryVarName, selfWritable).build(); - } } var builder = CodeBlock.builder().add("$L.resolve($T.class).inject(", registryVarName, resolveType); @@ -144,9 +130,4 @@ protected CodeBlock whenArrayPrimitiveType(@NonNull ArrayType type, TypeMirror o protected CodeBlock whenArrayType(@NonNull ArrayType type, TypeMirror override, @NonNull CodeBlock subtype) { return getGenericCodeBlock(arrayType, override, new CodeBlock[]{subtype}); } - - @Override - protected boolean doTraverseArguments(@NonNull DeclaredType type, TypeMirror override) { - return override != null || !context.isAssignable(context.erasure(type), selfWritable); - } } diff --git a/scale/scale-codegen/src/test/java/com/strategyobject/substrateclient/scale/codegen/reader/ScaleReaderProcessorTest.java b/scale/scale-codegen/src/test/java/com/strategyobject/substrateclient/scale/codegen/reader/ScaleReaderProcessorTest.java index 6dad89f7..4e5453d5 100644 --- a/scale/scale-codegen/src/test/java/com/strategyobject/substrateclient/scale/codegen/reader/ScaleReaderProcessorTest.java +++ b/scale/scale-codegen/src/test/java/com/strategyobject/substrateclient/scale/codegen/reader/ScaleReaderProcessorTest.java @@ -1,8 +1,15 @@ package com.strategyobject.substrateclient.scale.codegen.reader; import com.google.testing.compile.JavaFileObjects; +import com.strategyobject.substrateclient.tests.TestSuite; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; import lombok.val; +import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestFactory; + +import java.util.stream.Stream; import static com.google.testing.compile.CompilationSubject.assertThat; import static com.google.testing.compile.Compiler.javac; @@ -10,58 +17,50 @@ class ScaleReaderProcessorTest { @Test void failsWhenWrongTemplate() { - val nameless = JavaFileObjects.forResource("WrongTemplate.java"); + val clazz = JavaFileObjects.forResource("WrongTemplate.java"); val compilation = javac() .withProcessors(new ScaleReaderProcessor()) - .compile(nameless); + .compile(clazz); assertThat(compilation).failed(); assertThat(compilation) - .hadErrorContaining("Wrong template"); + .hadErrorContaining("brackets"); } - @Test - void compilesAnnotated() { - val clazz = JavaFileObjects.forResource("Annotated.java"); - - val compilation = javac() - .withProcessors(new ScaleReaderProcessor()) - .compile(clazz); - - assertThat(compilation).succeeded(); + @TestFactory + Stream compiles() { + return TestSuite.of( + TestCase.compile("Annotated.java"), + TestCase.compile("NonAnnotated.java"), + TestCase.compile("ComplexGeneric.java"), + TestCase.compile("Arrays.java"), + TestCase.compile("Enum.java") + ); } - @Test - void compilesNonAnnotated() { - val clazz = JavaFileObjects.forResource("NonAnnotated.java"); + @AllArgsConstructor(access = AccessLevel.PRIVATE) + static class TestCase implements TestSuite.TestCase { + private final String filename; - val compilation = javac() - .withProcessors(new ScaleReaderProcessor()) - .compile(clazz); + @Override + public String getDisplayName() { + return "compiles " + filename; + } - assertThat(compilation).succeeded(); - } + @Override + public void execute() { + val clazz = JavaFileObjects.forResource(filename); - @Test - void compilesComplexGeneric() { - val clazz = JavaFileObjects.forResource("ComplexGeneric.java"); - - val compilation = javac() - .withProcessors(new ScaleReaderProcessor()) - .compile(clazz); - - assertThat(compilation).succeeded(); - } - - @Test - void compilesArrays() { - val clazz = JavaFileObjects.forResource("Arrays.java"); + val compilation = javac() + .withProcessors(new ScaleReaderProcessor()) + .compile(clazz); - val compilation = javac() - .withProcessors(new ScaleReaderProcessor()) - .compile(clazz); + assertThat(compilation).succeeded(); + } - assertThat(compilation).succeeded(); + public static TestCase compile(String filename) { + return new TestCase(filename); + } } } diff --git a/scale/scale-codegen/src/test/java/com/strategyobject/substrateclient/scale/codegen/writer/ScaleWriterProcessorTest.java b/scale/scale-codegen/src/test/java/com/strategyobject/substrateclient/scale/codegen/writer/ScaleWriterProcessorTest.java index e05a0607..5f2c5817 100644 --- a/scale/scale-codegen/src/test/java/com/strategyobject/substrateclient/scale/codegen/writer/ScaleWriterProcessorTest.java +++ b/scale/scale-codegen/src/test/java/com/strategyobject/substrateclient/scale/codegen/writer/ScaleWriterProcessorTest.java @@ -1,9 +1,15 @@ package com.strategyobject.substrateclient.scale.codegen.writer; import com.google.testing.compile.JavaFileObjects; -import com.strategyobject.substrateclient.scale.codegen.reader.ScaleReaderProcessor; +import com.strategyobject.substrateclient.tests.TestSuite; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; import lombok.val; +import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestFactory; + +import java.util.stream.Stream; import static com.google.testing.compile.CompilationSubject.assertThat; import static com.google.testing.compile.Compiler.javac; @@ -19,85 +25,42 @@ void failsWhenWrongTemplate() { assertThat(compilation).failed(); assertThat(compilation) - .hadErrorContaining("Wrong template"); - } - - @Test - void failsWhenMissesScaleSelfWritable() { - val nameless = JavaFileObjects.forResource("MissesScaleSelfWritable.java"); - - val compilation = javac() - .withProcessors(new ScaleWriterProcessor()) - .compile(nameless); - - assertThat(compilation).failed(); - assertThat(compilation) - .hadErrorContaining("ScaleSelfWritable"); - } - - @Test - void compilesNonGenericScaleSelfWritable() { - val clazz = JavaFileObjects.forResource("NonGenericScaleSelfWritable.java"); - - val compilation = javac() - .withProcessors(new ScaleWriterProcessor()) - .compile(clazz); - - assertThat(compilation).succeeded(); - } - - @Test - void compilesGenericScaleSelfWritable() { - val clazz = JavaFileObjects.forResource("GenericScaleSelfWritable.java"); - - val compilation = javac() - .withProcessors(new ScaleWriterProcessor()) - .compile(clazz); - - assertThat(compilation).succeeded(); + .hadErrorContaining("brackets"); } - @Test - void compilesAnnotated() { - val clazz = JavaFileObjects.forResource("Annotated.java"); - - val compilation = javac() - .withProcessors(new ScaleWriterProcessor()) - .compile(clazz); - - assertThat(compilation).succeeded(); - } - - @Test - void compilesNonAnnotated() { - val clazz = JavaFileObjects.forResource("NonAnnotated.java"); - - val compilation = javac() - .withProcessors(new ScaleWriterProcessor()) - .compile(clazz); - - assertThat(compilation).succeeded(); + @TestFactory + Stream compiles() { + return TestSuite.of( + TestCase.compile("Annotated.java"), + TestCase.compile("NonAnnotated.java"), + TestCase.compile("ComplexGeneric.java"), + TestCase.compile("Arrays.java"), + TestCase.compile("Enum.java") + ); } - @Test - void compilesComplexGeneric() { - val clazz = JavaFileObjects.forResource("ComplexGeneric.java"); + @AllArgsConstructor(access = AccessLevel.PRIVATE) + static class TestCase implements TestSuite.TestCase { + private final String filename; - val compilation = javac() - .withProcessors(new ScaleWriterProcessor()) - .compile(clazz); + @Override + public String getDisplayName() { + return "compiles " + filename; + } - assertThat(compilation).succeeded(); - } + @Override + public void execute() { + val clazz = JavaFileObjects.forResource(filename); - @Test - void compilesArrays() { - val clazz = JavaFileObjects.forResource("Arrays.java"); + val compilation = javac() + .withProcessors(new ScaleWriterProcessor()) + .compile(clazz); - val compilation = javac() - .withProcessors(new ScaleWriterProcessor()) - .compile(clazz); + assertThat(compilation).succeeded(); + } - assertThat(compilation).succeeded(); + public static TestCase compile(String filename) { + return new TestCase(filename); + } } } \ No newline at end of file diff --git a/scale/scale-codegen/src/test/resources/Annotated.java b/scale/scale-codegen/src/test/resources/Annotated.java index cf26757c..9b22daba 100644 --- a/scale/scale-codegen/src/test/resources/Annotated.java +++ b/scale/scale-codegen/src/test/resources/Annotated.java @@ -1,10 +1,10 @@ package com.strategyobject.substrateclient.scale; +import com.strategyobject.substrateclient.common.types.Result; import com.strategyobject.substrateclient.scale.ScaleType.*; -import com.strategyobject.substrateclient.scale.annotations.ScaleReader; -import com.strategyobject.substrateclient.scale.annotations.ScaleWriter; -import com.strategyobject.substrateclient.scale.annotations.*; -import com.strategyobject.substrateclient.types.Result; +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; +import com.strategyobject.substrateclient.scale.annotation.ScaleWriter; +import com.strategyobject.substrateclient.scale.annotation.*; import java.lang.String; import java.math.BigInteger; @@ -86,7 +86,7 @@ public class Annotated { @Scale(ScaleType.String.class) } ) - private com.strategyobject.substrateclient.types.union.Union3 testUnion; + private com.strategyobject.substrateclient.common.types.union.Union3 testUnion; @ScaleGeneric( template = "Vec", @@ -245,11 +245,11 @@ public void setTestU128(BigInteger testU128) { this.testU128 = testU128; } - public com.strategyobject.substrateclient.types.union.Union3 getTestUnion() { + public com.strategyobject.substrateclient.common.types.union.Union3 getTestUnion() { return testUnion; } - public void setTestUnion(com.strategyobject.substrateclient.types.union.Union3 testUnion) { + public void setTestUnion(com.strategyobject.substrateclient.common.types.union.Union3 testUnion) { this.testUnion = testUnion; } diff --git a/scale/scale-codegen/src/test/resources/Arrays.java b/scale/scale-codegen/src/test/resources/Arrays.java index d76a730d..9ad1eaf4 100644 --- a/scale/scale-codegen/src/test/resources/Arrays.java +++ b/scale/scale-codegen/src/test/resources/Arrays.java @@ -1,9 +1,9 @@ package com.strategyobject.substrateclient.scale; -import com.strategyobject.substrateclient.scale.annotations.Scale; -import com.strategyobject.substrateclient.scale.annotations.ScaleGeneric; -import com.strategyobject.substrateclient.scale.annotations.ScaleReader; -import com.strategyobject.substrateclient.scale.annotations.ScaleWriter; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleGeneric; +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; +import com.strategyobject.substrateclient.scale.annotation.ScaleWriter; import java.util.List; import java.util.Optional; diff --git a/scale/scale-codegen/src/test/resources/ComplexGeneric.java b/scale/scale-codegen/src/test/resources/ComplexGeneric.java index 76553fe9..3d0746ee 100644 --- a/scale/scale-codegen/src/test/resources/ComplexGeneric.java +++ b/scale/scale-codegen/src/test/resources/ComplexGeneric.java @@ -1,10 +1,10 @@ package com.strategyobject.substrateclient.scale; +import com.strategyobject.substrateclient.common.types.Result; import com.strategyobject.substrateclient.scale.ScaleType.Vec; -import com.strategyobject.substrateclient.scale.annotations.ScaleReader; -import com.strategyobject.substrateclient.scale.annotations.ScaleWriter; -import com.strategyobject.substrateclient.scale.annotations.*; -import com.strategyobject.substrateclient.types.Result; +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; +import com.strategyobject.substrateclient.scale.annotation.ScaleWriter; +import com.strategyobject.substrateclient.scale.annotation.*; import java.util.List; import java.util.Map; diff --git a/scale/scale-codegen/src/test/resources/Enum.java b/scale/scale-codegen/src/test/resources/Enum.java new file mode 100644 index 00000000..a1239583 --- /dev/null +++ b/scale/scale-codegen/src/test/resources/Enum.java @@ -0,0 +1,16 @@ +package com.strategyobject.substrateclient.scale; + +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; +import com.strategyobject.substrateclient.scale.annotation.ScaleWriter; + +@ScaleReader +@ScaleWriter +public enum Enum { + MONDAY, + TUESDAY, + WEDNESDAY, + THURSDAY, + FRIDAY, + SATURDAY, + SUNDAY +} diff --git a/scale/scale-codegen/src/test/resources/GenericScaleSelfWritable.java b/scale/scale-codegen/src/test/resources/GenericScaleSelfWritable.java deleted file mode 100644 index 75e08a21..00000000 --- a/scale/scale-codegen/src/test/resources/GenericScaleSelfWritable.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.strategyobject.substrateclient.scale; - -import com.strategyobject.substrateclient.scale.annotations.Scale; -import com.strategyobject.substrateclient.scale.annotations.ScaleWriter; - -@ScaleWriter -public class GenericScaleSelfWritable< - T1 extends ScaleSelfWritable, - T2 extends ScaleSelfWritable, - T3 extends ScaleSelfWritable> implements ScaleSelfWritable> { - - @Scale - private T1 testGeneric1; - - @Scale - private T2 testGeneric2; - - @Scale - private T3 testGeneric3; - - public T1 getTestGeneric1() { - return testGeneric1; - } - - public void setTestGeneric1(T1 testGeneric1) { - this.testGeneric1 = testGeneric1; - } - - public T2 getTestGeneric2() { - return testGeneric2; - } - - public void setTestGeneric2(T2 testGeneric2) { - this.testGeneric2 = testGeneric2; - } - - public T3 getTestGeneric3() { - return testGeneric3; - } - - public void setTestGeneric3(T3 testGeneric3) { - this.testGeneric3 = testGeneric3; - } -} diff --git a/scale/scale-codegen/src/test/resources/MissesScaleSelfWritable.java b/scale/scale-codegen/src/test/resources/MissesScaleSelfWritable.java deleted file mode 100644 index 83718773..00000000 --- a/scale/scale-codegen/src/test/resources/MissesScaleSelfWritable.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.strategyobject.substrateclient.scale; - -import com.strategyobject.substrateclient.scale.annotations.ScaleWriter; - -@ScaleWriter -public class MissesScaleSelfWritable implements ScaleSelfWritable { - private String testString; - - public String getTestString() { - return testString; - } - - public void setTestString(String testString) { - this.testString = testString; - } -} diff --git a/scale/scale-codegen/src/test/resources/NonAnnotated.java b/scale/scale-codegen/src/test/resources/NonAnnotated.java index 99b75521..7f2ed4f1 100644 --- a/scale/scale-codegen/src/test/resources/NonAnnotated.java +++ b/scale/scale-codegen/src/test/resources/NonAnnotated.java @@ -1,8 +1,8 @@ package com.strategyobject.substrateclient.scale; -import com.strategyobject.substrateclient.scale.annotations.ScaleReader; -import com.strategyobject.substrateclient.scale.annotations.ScaleWriter; -import com.strategyobject.substrateclient.types.Result; +import com.strategyobject.substrateclient.common.types.Result; +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; +import com.strategyobject.substrateclient.scale.annotation.ScaleWriter; import java.math.BigInteger; import java.util.List; diff --git a/scale/scale-codegen/src/test/resources/NonGenericScaleSelfWritable.java b/scale/scale-codegen/src/test/resources/NonGenericScaleSelfWritable.java deleted file mode 100644 index 440cbfc3..00000000 --- a/scale/scale-codegen/src/test/resources/NonGenericScaleSelfWritable.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.strategyobject.substrateclient.scale; - -import com.strategyobject.substrateclient.scale.annotations.ScaleWriter; - -@ScaleWriter -public class NonGenericScaleSelfWritable implements ScaleSelfWritable { -} diff --git a/scale/scale-codegen/src/test/resources/WrongTemplate.java b/scale/scale-codegen/src/test/resources/WrongTemplate.java index 1d33d0e3..9560c4d2 100644 --- a/scale/scale-codegen/src/test/resources/WrongTemplate.java +++ b/scale/scale-codegen/src/test/resources/WrongTemplate.java @@ -1,11 +1,11 @@ package com.strategyobject.substrateclient.scale; +import com.strategyobject.substrateclient.common.types.Result; import com.strategyobject.substrateclient.scale.ScaleType.Vec; -import com.strategyobject.substrateclient.scale.annotations.Scale; -import com.strategyobject.substrateclient.scale.annotations.ScaleGeneric; -import com.strategyobject.substrateclient.scale.annotations.ScaleReader; -import com.strategyobject.substrateclient.scale.annotations.ScaleWriter; -import com.strategyobject.substrateclient.types.Result; +import com.strategyobject.substrateclient.scale.annotation.Scale; +import com.strategyobject.substrateclient.scale.annotation.ScaleGeneric; +import com.strategyobject.substrateclient.scale.annotation.ScaleReader; +import com.strategyobject.substrateclient.scale.annotation.ScaleWriter; import java.util.List; import java.util.Map; diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/ScaleDispatch.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/ScaleDispatch.java new file mode 100644 index 00000000..ad1de565 --- /dev/null +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/ScaleDispatch.java @@ -0,0 +1,4 @@ +package com.strategyobject.substrateclient.scale; + +public interface ScaleDispatch { +} diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/ScaleRegistryHelper.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/ScaleRegistryHelper.java index 612a5f26..bc79a7d4 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/ScaleRegistryHelper.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/ScaleRegistryHelper.java @@ -9,8 +9,10 @@ private ScaleRegistryHelper() { } @SuppressWarnings("unchecked") - public static ScaleReader resolveAndInjectOrNull(Class clazz, ScaleReader... dependencies) { - val target = (ScaleReader) ScaleReaderRegistry.getInstance().resolve(clazz); + public static ScaleReader resolveAndInjectOrNull(ScaleReaderRegistry registry, + Class clazz, + ScaleReader... dependencies) { + val target = (ScaleReader) registry.resolve(clazz); if (target == null) { return null; @@ -20,8 +22,10 @@ public static ScaleReader resolveAndInjectOrNull(Class clazz, ScaleRea } @SuppressWarnings("unchecked") - public static ScaleWriter resolveAndInjectOrNull(Class clazz, ScaleWriter... dependencies) { - val target = (ScaleWriter) ScaleWriterRegistry.getInstance().resolve(clazz); + public static ScaleWriter resolveAndInjectOrNull(ScaleWriterRegistry registry, + Class clazz, + ScaleWriter... dependencies) { + val target = (ScaleWriter) registry.resolve(clazz); if (target == null) { return null; diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/ScaleSelfWritable.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/ScaleSelfWritable.java deleted file mode 100644 index 13ae13c3..00000000 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/ScaleSelfWritable.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.strategyobject.substrateclient.scale; - -import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; -import lombok.NonNull; -import lombok.val; - -import java.io.IOException; -import java.io.OutputStream; - -public interface ScaleSelfWritable> { - @SuppressWarnings("unchecked") - default void write(@NonNull OutputStream stream) throws IOException { - val writer = (ScaleWriter) ScaleWriterRegistry - .getInstance() - .resolve(this.getClass()); - - writer.write((T) this, stream); - } -} diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/ScaleUtils.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/ScaleUtils.java index 552859a9..17bc87ae 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/ScaleUtils.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/ScaleUtils.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.NonNull; import lombok.val; @@ -9,26 +9,33 @@ import java.io.IOException; public final class ScaleUtils { - public static String toHexString(@NonNull T value, @NonNull ScaleWriter writer) { - val stream = new ByteArrayOutputStream(); + public static T fromBytes(byte @NonNull [] bytes, @NonNull ScaleReader reader) { + val stream = new ByteArrayInputStream(bytes); try { - writer.write(value, stream); + return reader.read(stream); } catch (IOException e) { throw new RuntimeException(e); } - - return HexConverter.toHex(stream.toByteArray()); } - public static T fromHexString(@NonNull String hex, @NonNull ScaleReader reader) { - val stream = new ByteArrayInputStream(HexConverter.toBytes(hex)); - + public static byte[] toBytes(T value, @NonNull ScaleWriter writer) { + val stream = new ByteArrayOutputStream(); try { - return reader.read(stream); + writer.write(value, stream); } catch (IOException e) { throw new RuntimeException(e); } + + return stream.toByteArray(); + } + + public static T fromHexString(@NonNull String hex, @NonNull ScaleReader reader) { + return fromBytes(HexConverter.toBytes(hex), reader); + } + + public static String toHexString(T value, @NonNull ScaleWriter writer) { + return HexConverter.toHex(toBytes(value, writer)); } private ScaleUtils() { diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/ScaleWriter.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/ScaleWriter.java index befa8d7f..e08c3756 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/ScaleWriter.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/ScaleWriter.java @@ -6,7 +6,7 @@ import java.io.OutputStream; public interface ScaleWriter { - void write(@NonNull T value, @NonNull OutputStream stream, ScaleWriter... writers) throws IOException; + void write(T value, @NonNull OutputStream stream, ScaleWriter... writers) throws IOException; default ScaleWriter inject(ScaleWriter... dependencies) { return (value, stream, writers) -> ScaleWriter.this.write(value, stream, dependencies); diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/annotations/AutoRegister.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/annotation/AutoRegister.java similarity index 82% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/annotations/AutoRegister.java rename to scale/src/main/java/com/strategyobject/substrateclient/scale/annotation/AutoRegister.java index b29fe35d..d5de1f5f 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/annotations/AutoRegister.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/annotation/AutoRegister.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.rpc.core.annotations; +package com.strategyobject.substrateclient.scale.annotation; import lombok.NonNull; diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/annotation/Default.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/annotation/Default.java new file mode 100644 index 00000000..0ccd44eb --- /dev/null +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/annotation/Default.java @@ -0,0 +1,4 @@ +package com.strategyobject.substrateclient.scale.annotation; + +public class Default { +} diff --git a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/annotations/Ignore.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/annotation/Ignore.java similarity index 79% rename from rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/annotations/Ignore.java rename to scale/src/main/java/com/strategyobject/substrateclient/scale/annotation/Ignore.java index 69bb3840..ac263a8f 100644 --- a/rpc/rpc-core/src/main/java/com/strategyobject/substrateclient/rpc/core/annotations/Ignore.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/annotation/Ignore.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.rpc.core.annotations; +package com.strategyobject.substrateclient.scale.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/annotations/Scale.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/annotation/Scale.java similarity index 85% rename from scale/src/main/java/com/strategyobject/substrateclient/scale/annotations/Scale.java rename to scale/src/main/java/com/strategyobject/substrateclient/scale/annotation/Scale.java index 3a9a5d4f..f29c2c59 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/annotations/Scale.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/annotation/Scale.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.scale.annotations; +package com.strategyobject.substrateclient.scale.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/annotations/ScaleGeneric.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/annotation/ScaleGeneric.java similarity index 84% rename from scale/src/main/java/com/strategyobject/substrateclient/scale/annotations/ScaleGeneric.java rename to scale/src/main/java/com/strategyobject/substrateclient/scale/annotation/ScaleGeneric.java index 112e0a94..c372e6b7 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/annotations/ScaleGeneric.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/annotation/ScaleGeneric.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.scale.annotations; +package com.strategyobject.substrateclient.scale.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/annotations/ScaleReader.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/annotation/ScaleReader.java similarity index 80% rename from scale/src/main/java/com/strategyobject/substrateclient/scale/annotations/ScaleReader.java rename to scale/src/main/java/com/strategyobject/substrateclient/scale/annotation/ScaleReader.java index 96b87ece..fd576f4c 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/annotations/ScaleReader.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/annotation/ScaleReader.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.scale.annotations; +package com.strategyobject.substrateclient.scale.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/annotations/ScaleWriter.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/annotation/ScaleWriter.java similarity index 80% rename from scale/src/main/java/com/strategyobject/substrateclient/scale/annotations/ScaleWriter.java rename to scale/src/main/java/com/strategyobject/substrateclient/scale/annotation/ScaleWriter.java index 24840f16..11b7298d 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/annotations/ScaleWriter.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/annotation/ScaleWriter.java @@ -1,4 +1,4 @@ -package com.strategyobject.substrateclient.scale.annotations; +package com.strategyobject.substrateclient.scale.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/annotations/Default.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/annotations/Default.java deleted file mode 100644 index a4663cc6..00000000 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/annotations/Default.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.strategyobject.substrateclient.scale.annotations; - -public class Default { -} diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/I8Reader.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/I8Reader.java index 3d000cd4..f3c78d44 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/I8Reader.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/I8Reader.java @@ -4,7 +4,6 @@ import com.strategyobject.substrateclient.common.io.Streamer; import com.strategyobject.substrateclient.scale.ScaleReader; import lombok.NonNull; -import lombok.val; import java.io.IOException; import java.io.InputStream; @@ -14,7 +13,6 @@ public class I8Reader implements ScaleReader { public Byte read(@NonNull InputStream stream, ScaleReader... readers) throws IOException { Preconditions.checkArgument(readers == null || readers.length == 0); - val bytes = Streamer.readBytes(1, stream); - return bytes[0]; + return (byte) Streamer.readByte(stream); } } diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/ResultReader.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/ResultReader.java index dcb4a0a4..63b435cb 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/ResultReader.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/ResultReader.java @@ -2,8 +2,8 @@ import com.google.common.base.Preconditions; import com.strategyobject.substrateclient.common.io.Streamer; +import com.strategyobject.substrateclient.common.types.Result; import com.strategyobject.substrateclient.scale.ScaleReader; -import com.strategyobject.substrateclient.types.Result; import lombok.NonNull; import lombok.val; diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/UnitReader.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/UnitReader.java new file mode 100644 index 00000000..0017ef44 --- /dev/null +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/UnitReader.java @@ -0,0 +1,17 @@ +package com.strategyobject.substrateclient.scale.readers; + +import com.google.common.base.Preconditions; +import com.strategyobject.substrateclient.common.types.Unit; +import com.strategyobject.substrateclient.scale.ScaleReader; +import lombok.NonNull; + +import java.io.InputStream; + +public class UnitReader implements ScaleReader { + @Override + public Unit read(@NonNull InputStream stream, ScaleReader... readers) { + Preconditions.checkArgument(readers == null || readers.length == 0); + + return Unit.get(); + } +} diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/BaseUnionReader.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/BaseUnionReader.java index 8a6ea7ff..1d05fcea 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/BaseUnionReader.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/BaseUnionReader.java @@ -2,8 +2,8 @@ import com.google.common.base.Preconditions; import com.strategyobject.substrateclient.common.io.Streamer; +import com.strategyobject.substrateclient.common.types.union.Union; import com.strategyobject.substrateclient.scale.ScaleReader; -import com.strategyobject.substrateclient.types.union.Union; import lombok.NonNull; import lombok.val; diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union10Reader.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union10Reader.java index 38a0f840..1791925b 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union10Reader.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union10Reader.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers.union; -import com.strategyobject.substrateclient.types.union.Union10; +import com.strategyobject.substrateclient.common.types.union.Union10; public class Union10Reader extends BaseUnionReader> { public Union10Reader() { diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union11Reader.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union11Reader.java index 8f4743b7..a47e3373 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union11Reader.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union11Reader.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers.union; -import com.strategyobject.substrateclient.types.union.Union11; +import com.strategyobject.substrateclient.common.types.union.Union11; public class Union11Reader extends BaseUnionReader> { public Union11Reader() { diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union12Reader.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union12Reader.java index 0e98403a..aac1178d 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union12Reader.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union12Reader.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers.union; -import com.strategyobject.substrateclient.types.union.Union12; +import com.strategyobject.substrateclient.common.types.union.Union12; public class Union12Reader extends BaseUnionReader> { public Union12Reader() { diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union1Reader.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union1Reader.java index 10fbbb79..04d7917c 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union1Reader.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union1Reader.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers.union; -import com.strategyobject.substrateclient.types.union.Union1; +import com.strategyobject.substrateclient.common.types.union.Union1; public class Union1Reader extends BaseUnionReader> { public Union1Reader() { diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union2Reader.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union2Reader.java index ef2a99ad..a70d8fcb 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union2Reader.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union2Reader.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers.union; -import com.strategyobject.substrateclient.types.union.Union2; +import com.strategyobject.substrateclient.common.types.union.Union2; public class Union2Reader extends BaseUnionReader> { public Union2Reader() { diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union3Reader.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union3Reader.java index 3719caa0..a4ce4271 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union3Reader.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union3Reader.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers.union; -import com.strategyobject.substrateclient.types.union.Union3; +import com.strategyobject.substrateclient.common.types.union.Union3; public class Union3Reader extends BaseUnionReader> { public Union3Reader() { diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union4Reader.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union4Reader.java index 46d95f18..c9096bb3 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union4Reader.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union4Reader.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers.union; -import com.strategyobject.substrateclient.types.union.Union4; +import com.strategyobject.substrateclient.common.types.union.Union4; public class Union4Reader extends BaseUnionReader> { public Union4Reader() { diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union5Reader.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union5Reader.java index b4a6134d..c44b08b9 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union5Reader.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union5Reader.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers.union; -import com.strategyobject.substrateclient.types.union.Union5; +import com.strategyobject.substrateclient.common.types.union.Union5; public class Union5Reader extends BaseUnionReader> { public Union5Reader() { diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union6Reader.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union6Reader.java index 49399975..deec8b05 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union6Reader.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union6Reader.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers.union; -import com.strategyobject.substrateclient.types.union.Union6; +import com.strategyobject.substrateclient.common.types.union.Union6; public class Union6Reader extends BaseUnionReader> { public Union6Reader() { diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union7Reader.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union7Reader.java index 1bcaebe6..5fa29b44 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union7Reader.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union7Reader.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers.union; -import com.strategyobject.substrateclient.types.union.Union7; +import com.strategyobject.substrateclient.common.types.union.Union7; public class Union7Reader extends BaseUnionReader> { public Union7Reader() { diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union8Reader.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union8Reader.java index 2e77b33b..1aa6093f 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union8Reader.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union8Reader.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers.union; -import com.strategyobject.substrateclient.types.union.Union8; +import com.strategyobject.substrateclient.common.types.union.Union8; public class Union8Reader extends BaseUnionReader> { public Union8Reader() { diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union9Reader.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union9Reader.java index dcec4eaa..48bacc83 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union9Reader.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/readers/union/Union9Reader.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers.union; -import com.strategyobject.substrateclient.types.union.Union9; +import com.strategyobject.substrateclient.common.types.union.Union9; public class Union9Reader extends BaseUnionReader> { public Union9Reader() { diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/registries/ScaleReaderRegistry.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/registries/ScaleReaderRegistry.java index e2d9d342..51a4ee67 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/registries/ScaleReaderRegistry.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/registries/ScaleReaderRegistry.java @@ -1,32 +1,32 @@ package com.strategyobject.substrateclient.scale.registries; -import com.strategyobject.substrateclient.common.CommonType; +import com.strategyobject.substrateclient.common.reflection.ClassUtils; import com.strategyobject.substrateclient.common.reflection.Scanner; +import com.strategyobject.substrateclient.common.types.Array; +import com.strategyobject.substrateclient.common.types.Result; +import com.strategyobject.substrateclient.common.types.Unit; +import com.strategyobject.substrateclient.common.types.union.*; import com.strategyobject.substrateclient.scale.ScaleReader; import com.strategyobject.substrateclient.scale.ScaleType; -import com.strategyobject.substrateclient.scale.annotations.AutoRegister; +import com.strategyobject.substrateclient.scale.annotation.AutoRegister; import com.strategyobject.substrateclient.scale.readers.*; import com.strategyobject.substrateclient.scale.readers.union.*; -import com.strategyobject.substrateclient.types.Result; -import com.strategyobject.substrateclient.types.union.*; import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; import lombok.val; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import java.lang.reflect.InvocationTargetException; import java.math.BigInteger; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; -public final class ScaleReaderRegistry { - private static final Logger logger = LoggerFactory.getLogger(ScaleReaderRegistry.class); - private static final String ROOT_PREFIX = "com.strategyobject.substrateclient"; - private static volatile ScaleReaderRegistry instance; +@Slf4j +public class ScaleReaderRegistry { private final Map, ScaleReader> readers; - private ScaleReaderRegistry() { + public ScaleReaderRegistry() { readers = new ConcurrentHashMap<>(128); register(new BoolReader(), ScaleType.Bool.class, Boolean.class, boolean.class); @@ -59,26 +59,14 @@ private ScaleReaderRegistry() { register(new Union11Reader(), Union11.class, ScaleType.Union11.class); register(new Union12Reader(), Union12.class, ScaleType.Union12.class); register(new VecReader(), ScaleType.Vec.class, List.class); - register(new ArrayReader(), CommonType.Array.class); + register(new ArrayReader(), Array.class); register(new BooleanArrayReader(), boolean[].class); register(new ByteArrayReader(), byte[].class); register(new ShortArrayReader(), short[].class); register(new IntArrayReader(), int[].class); register(new LongArrayReader(), long[].class); - register(new VoidReader(), Void.class); - - registerAnnotatedFrom(ROOT_PREFIX); - } - - public static ScaleReaderRegistry getInstance() { - if (instance == null) { - synchronized (ScaleReaderRegistry.class) { - if (instance == null) { - instance = new ScaleReaderRegistry(); - } - } - } - return instance; + register(new VoidReader(), Void.class, void.class); + register(new UnitReader(), Unit.class); } public void registerAnnotatedFrom(String... prefixes) { @@ -91,12 +79,21 @@ public void registerAnnotatedFrom(String... prefixes) { try { val types = autoRegister.types(); - logger.info("Auto register reader {} for types: {}", reader, types); + log.info("Auto register reader {} for types: {}", reader, types); + + + ScaleReader readerInstance; + if (ClassUtils.hasDefaultConstructor(reader)) { + readerInstance = reader.newInstance(); + } else { + val ctor = reader.getConstructor(ScaleReaderRegistry.class); + readerInstance = ctor.newInstance(this); + } - final ScaleReader readerInstance = reader.newInstance(); register(readerInstance, types); - } catch (InstantiationException | IllegalAccessException e) { - logger.error("Auto registration error", e); + } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | + InvocationTargetException e) { + log.error("Auto registration error", e); } }); } diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/registries/ScaleWriterRegistry.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/registries/ScaleWriterRegistry.java index 2368863e..d7fa4eb0 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/registries/ScaleWriterRegistry.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/registries/ScaleWriterRegistry.java @@ -1,35 +1,33 @@ package com.strategyobject.substrateclient.scale.registries; -import com.strategyobject.substrateclient.common.CommonType; +import com.strategyobject.substrateclient.common.reflection.ClassUtils; import com.strategyobject.substrateclient.common.reflection.Scanner; -import com.strategyobject.substrateclient.scale.ScaleSelfWritable; +import com.strategyobject.substrateclient.common.types.Array; +import com.strategyobject.substrateclient.common.types.Result; +import com.strategyobject.substrateclient.common.types.Unit; +import com.strategyobject.substrateclient.common.types.union.*; +import com.strategyobject.substrateclient.scale.ScaleDispatch; import com.strategyobject.substrateclient.scale.ScaleType; import com.strategyobject.substrateclient.scale.ScaleWriter; -import com.strategyobject.substrateclient.scale.annotations.AutoRegister; +import com.strategyobject.substrateclient.scale.annotation.AutoRegister; import com.strategyobject.substrateclient.scale.writers.*; import com.strategyobject.substrateclient.scale.writers.union.*; -import com.strategyobject.substrateclient.types.PublicKey; -import com.strategyobject.substrateclient.types.Result; -import com.strategyobject.substrateclient.types.SignatureData; -import com.strategyobject.substrateclient.types.union.*; import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; import lombok.val; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import java.lang.reflect.InvocationTargetException; import java.math.BigInteger; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; -public final class ScaleWriterRegistry { - private static final Logger logger = LoggerFactory.getLogger(ScaleWriterRegistry.class); - private static final String ROOT_PREFIX = "com.strategyobject.substrateclient"; - private static volatile ScaleWriterRegistry instance; +@Slf4j +public class ScaleWriterRegistry { private final Map, ScaleWriter> writers; - private ScaleWriterRegistry() { + public ScaleWriterRegistry() { writers = new ConcurrentHashMap<>(128); register(new BoolWriter(), ScaleType.Bool.class, Boolean.class, boolean.class); @@ -62,29 +60,15 @@ private ScaleWriterRegistry() { register(new Union11Writer(), Union11.class, ScaleType.Union11.class); register(new Union12Writer(), Union12.class, ScaleType.Union12.class); register(new VecWriter(), ScaleType.Vec.class, List.class); - register(new ArrayWriter(), CommonType.Array.class); + register(new ArrayWriter(), Array.class); register(new BooleanArrayWriter(), boolean[].class); register(new ByteArrayWriter(), byte[].class); register(new ShortArrayWriter(), short[].class); register(new IntArrayWriter(), int[].class); register(new LongArrayWriter(), long[].class); - register(new VoidWriter(), Void.class); - register(new SelfWriter(), ScaleSelfWritable.class); - register(new PublicKeyWriter(), PublicKey.class); - register(new SignatureDataWriter(), SignatureData.class); - - registerAnnotatedFrom(ROOT_PREFIX); - } - - public static ScaleWriterRegistry getInstance() { - if (instance == null) { - synchronized (ScaleWriterRegistry.class) { - if (instance == null) { - instance = new ScaleWriterRegistry(); - } - } - } - return instance; + register(new VoidWriter(), Void.class, void.class); + register(new UnitWriter(), Unit.class); + register(new DispatchingWriter<>(this), ScaleDispatch.class); } public void registerAnnotatedFrom(String... prefixes) { @@ -97,12 +81,20 @@ public void registerAnnotatedFrom(String... prefixes) { try { val types = autoRegister.types(); - logger.info("Auto register writer {} for types: {}", writer, types); + log.info("Auto register writer {} for types: {}", writer, types); + + ScaleWriter writerInstance; + if (ClassUtils.hasDefaultConstructor(writer)) { + writerInstance = writer.newInstance(); + } else { + val ctor = writer.getConstructor(ScaleWriterRegistry.class); + writerInstance = ctor.newInstance(this); + } - final ScaleWriter writerInstance = writer.newInstance(); register(writerInstance, types); - } catch (InstantiationException | IllegalAccessException e) { - logger.error("Auto registration error", e); + } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | + InvocationTargetException e) { + log.error("Auto registration error", e); } }); } diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/BoolWriter.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/BoolWriter.java index 8f583503..0ffad3d9 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/BoolWriter.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/BoolWriter.java @@ -12,6 +12,6 @@ public class BoolWriter implements ScaleWriter { public void write(@NonNull Boolean value, @NonNull OutputStream stream, ScaleWriter... writers) throws IOException { Preconditions.checkArgument(writers == null || writers.length == 0); - stream.write(value ? 1 : 0); + stream.write(Boolean.TRUE.equals(value) ? 1 : 0); } } diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/DispatchingWriter.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/DispatchingWriter.java new file mode 100644 index 00000000..d87581e6 --- /dev/null +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/DispatchingWriter.java @@ -0,0 +1,22 @@ +package com.strategyobject.substrateclient.scale.writers; + +import com.strategyobject.substrateclient.scale.ScaleWriter; +import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.val; + +import java.io.IOException; +import java.io.OutputStream; + +@RequiredArgsConstructor +public class DispatchingWriter implements ScaleWriter { + private final @NonNull ScaleWriterRegistry registry; + + @SuppressWarnings("unchecked") + @Override + public void write(@NonNull T value, @NonNull OutputStream stream, ScaleWriter... writers) throws IOException { + val writer = (ScaleWriter) registry.resolve(value.getClass()); + writer.write(value, stream, writers); + } +} diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/OptionBoolWriter.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/OptionBoolWriter.java index 7a57c28c..14ae75b0 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/OptionBoolWriter.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/OptionBoolWriter.java @@ -15,7 +15,7 @@ public void write(@NonNull Optional value, @NonNull OutputStream stream if (!value.isPresent()) { stream.write(0); - } else if (value.get()) { + } else if (Boolean.TRUE.equals(value.get())) { stream.write(1); } else { stream.write(2); diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/PublicKeyWriter.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/PublicKeyWriter.java deleted file mode 100644 index e05a0f9e..00000000 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/PublicKeyWriter.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.strategyobject.substrateclient.scale.writers; - -import com.google.common.base.Preconditions; -import com.strategyobject.substrateclient.common.io.Streamer; -import com.strategyobject.substrateclient.scale.ScaleWriter; -import com.strategyobject.substrateclient.types.PublicKey; -import lombok.NonNull; - -import java.io.IOException; -import java.io.OutputStream; - -public class PublicKeyWriter implements ScaleWriter { - @Override - public void write(@NonNull PublicKey value, @NonNull OutputStream stream, ScaleWriter... writers) throws IOException { - Preconditions.checkArgument(writers == null || writers.length == 0); - - Streamer.writeBytes(value.getData(), stream); - } -} \ No newline at end of file diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/ResultWriter.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/ResultWriter.java index 79c63a4d..a96efdcf 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/ResultWriter.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/ResultWriter.java @@ -1,8 +1,8 @@ package com.strategyobject.substrateclient.scale.writers; import com.google.common.base.Preconditions; +import com.strategyobject.substrateclient.common.types.Result; import com.strategyobject.substrateclient.scale.ScaleWriter; -import com.strategyobject.substrateclient.types.Result; import lombok.NonNull; import lombok.val; diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/SelfWriter.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/SelfWriter.java deleted file mode 100644 index d0fa25ef..00000000 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/SelfWriter.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.strategyobject.substrateclient.scale.writers; - -import com.google.common.base.Preconditions; -import com.strategyobject.substrateclient.scale.ScaleSelfWritable; -import com.strategyobject.substrateclient.scale.ScaleWriter; -import lombok.NonNull; - -import java.io.IOException; -import java.io.OutputStream; - -public class SelfWriter implements ScaleWriter> { - @Override - public void write(@NonNull ScaleSelfWritable value, @NonNull OutputStream stream, ScaleWriter... writers) throws IOException { - Preconditions.checkArgument(writers == null || writers.length == 0); - - value.write(stream); - } -} diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/SignatureDataWriter.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/SignatureDataWriter.java deleted file mode 100644 index 6d9ddfb9..00000000 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/SignatureDataWriter.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.strategyobject.substrateclient.scale.writers; - -import com.google.common.base.Preconditions; -import com.strategyobject.substrateclient.common.io.Streamer; -import com.strategyobject.substrateclient.scale.ScaleWriter; -import com.strategyobject.substrateclient.types.SignatureData; -import lombok.NonNull; - -import java.io.IOException; -import java.io.OutputStream; - -public class SignatureDataWriter implements ScaleWriter { - @Override - public void write(@NonNull SignatureData value, @NonNull OutputStream stream, ScaleWriter... writers) throws IOException { - Preconditions.checkArgument(writers == null || writers.length == 0); - - Streamer.writeBytes(value.getData(), stream); - } -} \ No newline at end of file diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/UnitWriter.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/UnitWriter.java new file mode 100644 index 00000000..a8efd40f --- /dev/null +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/UnitWriter.java @@ -0,0 +1,16 @@ +package com.strategyobject.substrateclient.scale.writers; + +import com.google.common.base.Preconditions; +import com.strategyobject.substrateclient.common.types.Unit; +import com.strategyobject.substrateclient.scale.ScaleWriter; +import lombok.NonNull; + +import java.io.OutputStream; + +public class UnitWriter implements ScaleWriter { + @Override + public void write(@NonNull Unit value, @NonNull OutputStream stream, ScaleWriter... writers) { + Preconditions.checkArgument(writers == null || writers.length == 0); + } +} + diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/VoidWriter.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/VoidWriter.java index 202ca033..c0dbbf6e 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/VoidWriter.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/VoidWriter.java @@ -8,8 +8,7 @@ public class VoidWriter implements ScaleWriter { @Override - public void write(@NonNull Void value, @NonNull OutputStream stream, ScaleWriter... writers) { + public void write(Void value, @NonNull OutputStream stream, ScaleWriter... writers) { Preconditions.checkArgument(writers == null || writers.length == 0); } } - diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/BaseUnionWriter.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/BaseUnionWriter.java index c1bb103a..1e2ece35 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/BaseUnionWriter.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/BaseUnionWriter.java @@ -1,8 +1,8 @@ package com.strategyobject.substrateclient.scale.writers.union; import com.google.common.base.Preconditions; +import com.strategyobject.substrateclient.common.types.union.Union; import com.strategyobject.substrateclient.scale.ScaleWriter; -import com.strategyobject.substrateclient.types.union.Union; import lombok.NonNull; import lombok.val; diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union10Writer.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union10Writer.java index 03999963..bdb7b9d9 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union10Writer.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union10Writer.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers.union; -import com.strategyobject.substrateclient.types.union.Union10; +import com.strategyobject.substrateclient.common.types.union.Union10; public class Union10Writer extends BaseUnionWriter> { public Union10Writer() { diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union11Writer.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union11Writer.java index 4c11fe7d..c24ad29e 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union11Writer.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union11Writer.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers.union; -import com.strategyobject.substrateclient.types.union.Union11; +import com.strategyobject.substrateclient.common.types.union.Union11; public class Union11Writer extends BaseUnionWriter> { public Union11Writer() { diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union12Writer.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union12Writer.java index 927cf8af..75c4eda9 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union12Writer.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union12Writer.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers.union; -import com.strategyobject.substrateclient.types.union.Union12; +import com.strategyobject.substrateclient.common.types.union.Union12; public class Union12Writer extends BaseUnionWriter> { public Union12Writer() { diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union1Writer.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union1Writer.java index 51851fe3..6820959b 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union1Writer.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union1Writer.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers.union; -import com.strategyobject.substrateclient.types.union.Union1; +import com.strategyobject.substrateclient.common.types.union.Union1; public class Union1Writer extends BaseUnionWriter> { public Union1Writer() { diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union2Writer.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union2Writer.java index e13c6e18..dd6cceb5 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union2Writer.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union2Writer.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers.union; -import com.strategyobject.substrateclient.types.union.Union2; +import com.strategyobject.substrateclient.common.types.union.Union2; public class Union2Writer extends BaseUnionWriter> { public Union2Writer() { diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union3Writer.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union3Writer.java index 5c3122ee..fd08fd8b 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union3Writer.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union3Writer.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers.union; -import com.strategyobject.substrateclient.types.union.Union3; +import com.strategyobject.substrateclient.common.types.union.Union3; public class Union3Writer extends BaseUnionWriter> { public Union3Writer() { diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union4Writer.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union4Writer.java index 49aefbe8..d5087c81 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union4Writer.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union4Writer.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers.union; -import com.strategyobject.substrateclient.types.union.Union4; +import com.strategyobject.substrateclient.common.types.union.Union4; public class Union4Writer extends BaseUnionWriter> { public Union4Writer() { diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union5Writer.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union5Writer.java index eb35270e..0ce392bb 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union5Writer.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union5Writer.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers.union; -import com.strategyobject.substrateclient.types.union.Union5; +import com.strategyobject.substrateclient.common.types.union.Union5; public class Union5Writer extends BaseUnionWriter> { public Union5Writer() { diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union6Writer.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union6Writer.java index d3433f53..111fc1ee 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union6Writer.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union6Writer.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers.union; -import com.strategyobject.substrateclient.types.union.Union6; +import com.strategyobject.substrateclient.common.types.union.Union6; public class Union6Writer extends BaseUnionWriter> { public Union6Writer() { diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union7Writer.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union7Writer.java index 7d35ee2c..571d65b4 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union7Writer.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union7Writer.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers.union; -import com.strategyobject.substrateclient.types.union.Union7; +import com.strategyobject.substrateclient.common.types.union.Union7; public class Union7Writer extends BaseUnionWriter> { public Union7Writer() { diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union8Writer.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union8Writer.java index 9fe80aa4..d54df164 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union8Writer.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union8Writer.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers.union; -import com.strategyobject.substrateclient.types.union.Union8; +import com.strategyobject.substrateclient.common.types.union.Union8; public class Union8Writer extends BaseUnionWriter> { public Union8Writer() { diff --git a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union9Writer.java b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union9Writer.java index 4ed4edf3..d40710d5 100644 --- a/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union9Writer.java +++ b/scale/src/main/java/com/strategyobject/substrateclient/scale/writers/union/Union9Writer.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers.union; -import com.strategyobject.substrateclient.types.union.Union9; +import com.strategyobject.substrateclient.common.types.union.Union9; public class Union9Writer extends BaseUnionWriter> { public Union9Writer() { diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/ScaleReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/ScaleReaderTest.java index 083f07ee..c3970710 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/ScaleReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/ScaleReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import com.strategyobject.substrateclient.scale.readers.I8Reader; import com.strategyobject.substrateclient.scale.readers.OptionReader; import com.strategyobject.substrateclient.scale.readers.VecReader; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/ScaleWriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/ScaleWriterTest.java index ac15824e..82275d0c 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/ScaleWriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/ScaleWriterTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import com.strategyobject.substrateclient.scale.writers.I8Writer; import com.strategyobject.substrateclient.scale.writers.OptionWriter; import com.strategyobject.substrateclient.scale.writers.VecWriter; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/ArrayReadersTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/ArrayReadersTest.java index 978fc890..9b530799 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/ArrayReadersTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/ArrayReadersTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import com.strategyobject.substrateclient.scale.ScaleReader; import com.strategyobject.substrateclient.tests.TestSuite; import lombok.AccessLevel; @@ -15,7 +15,7 @@ import java.util.function.BiConsumer; import java.util.stream.Stream; -public class ArrayReadersTest { +class ArrayReadersTest { @TestFactory Stream read() { @@ -73,7 +73,7 @@ Stream readEmpty() { } @AllArgsConstructor(access = AccessLevel.PRIVATE) - static class Test extends TestSuite.TestCase { + static class Test implements TestSuite.TestCase { private final ScaleReader reader; private final String given; private final T expected; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/BoolReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/BoolReaderTest.java index 87fa2faf..b95c4b69 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/BoolReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/BoolReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/CompactBigIntegerReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/CompactBigIntegerReaderTest.java index c23bdd75..716e155c 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/CompactBigIntegerReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/CompactBigIntegerReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/CompactIntegerReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/CompactIntegerReaderTest.java index b80f426a..656a9a11 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/CompactIntegerReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/CompactIntegerReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.api.Test; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/I128ReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/I128ReaderTest.java index 494e458f..7372e973 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/I128ReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/I128ReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/I16ReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/I16ReaderTest.java index fb224573..9b61fd13 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/I16ReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/I16ReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/I32ReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/I32ReaderTest.java index 6b321e1e..071eb115 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/I32ReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/I32ReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/I64ReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/I64ReaderTest.java index b0d4310a..6607cb35 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/I64ReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/I64ReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/I8ReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/I8ReaderTest.java index 3cde5433..4037b9bd 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/I8ReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/I8ReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/OptionBoolReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/OptionBoolReaderTest.java index f17cf054..b7b9e36a 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/OptionBoolReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/OptionBoolReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/OptionReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/OptionReaderTest.java index 5e5da3ae..e390a63d 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/OptionReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/OptionReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.api.Test; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/ResultReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/ResultReaderTest.java index 41b4abc6..2a854917 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/ResultReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/ResultReaderTest.java @@ -1,7 +1,7 @@ package com.strategyobject.substrateclient.scale.readers; -import com.strategyobject.substrateclient.common.utils.HexConverter; -import com.strategyobject.substrateclient.types.Result; +import com.strategyobject.substrateclient.common.types.Result; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.api.Test; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/StringReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/StringReaderTest.java index 8fe2e665..59d659d1 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/StringReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/StringReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.api.Test; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/U128ReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/U128ReaderTest.java index a8460851..8dc4aa90 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/U128ReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/U128ReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/U16ReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/U16ReaderTest.java index 63de19ac..e1c33c17 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/U16ReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/U16ReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/U32ReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/U32ReaderTest.java index 5f69d9e7..ee4cbbd2 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/U32ReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/U32ReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/U64ReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/U64ReaderTest.java index df782649..1ad3a461 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/U64ReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/U64ReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/U8ReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/U8ReaderTest.java index 1187b358..adb12ee2 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/U8ReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/U8ReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/VecReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/VecReaderTest.java index 6f25633b..a3ded195 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/VecReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/VecReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.api.Test; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union10ReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union10ReaderTest.java index 7b9c5c37..e728c95c 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union10ReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union10ReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers.union; -import com.strategyobject.substrateclient.types.union.Union10; +import com.strategyobject.substrateclient.common.types.union.Union10; import lombok.SneakyThrows; import org.junit.jupiter.api.Test; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union11ReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union11ReaderTest.java index 1a99d522..c559c594 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union11ReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union11ReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers.union; -import com.strategyobject.substrateclient.types.union.Union11; +import com.strategyobject.substrateclient.common.types.union.Union11; import lombok.SneakyThrows; import org.junit.jupiter.api.Test; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union12ReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union12ReaderTest.java index 80167ef4..4de36cad 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union12ReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union12ReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers.union; -import com.strategyobject.substrateclient.types.union.Union12; +import com.strategyobject.substrateclient.common.types.union.Union12; import lombok.SneakyThrows; import org.junit.jupiter.api.Test; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union1ReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union1ReaderTest.java index fd99a22b..ff22b9c8 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union1ReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union1ReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers.union; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import com.strategyobject.substrateclient.scale.readers.U8Reader; import lombok.SneakyThrows; import lombok.val; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union2ReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union2ReaderTest.java index f441b5e9..295405d1 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union2ReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union2ReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers.union; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import com.strategyobject.substrateclient.scale.readers.BoolReader; import com.strategyobject.substrateclient.scale.readers.U8Reader; import com.strategyobject.substrateclient.scale.readers.VoidReader; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union3ReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union3ReaderTest.java index 514d2545..0e84eb6d 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union3ReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union3ReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers.union; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import com.strategyobject.substrateclient.scale.readers.BoolReader; import com.strategyobject.substrateclient.scale.readers.U8Reader; import com.strategyobject.substrateclient.scale.readers.VoidReader; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union4ReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union4ReaderTest.java index fbba3e68..356042ab 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union4ReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union4ReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers.union; -import com.strategyobject.substrateclient.types.union.Union4; +import com.strategyobject.substrateclient.common.types.union.Union4; import lombok.SneakyThrows; import org.junit.jupiter.api.Test; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union5ReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union5ReaderTest.java index b998f24d..02bfe78d 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union5ReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union5ReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers.union; -import com.strategyobject.substrateclient.types.union.Union5; +import com.strategyobject.substrateclient.common.types.union.Union5; import lombok.SneakyThrows; import org.junit.jupiter.api.Test; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union6ReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union6ReaderTest.java index 3f3218e0..dbbddbe7 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union6ReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union6ReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers.union; -import com.strategyobject.substrateclient.types.union.Union6; +import com.strategyobject.substrateclient.common.types.union.Union6; import lombok.SneakyThrows; import org.junit.jupiter.api.Test; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union7ReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union7ReaderTest.java index aed2d82f..8a60abd8 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union7ReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union7ReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers.union; -import com.strategyobject.substrateclient.types.union.Union7; +import com.strategyobject.substrateclient.common.types.union.Union7; import lombok.SneakyThrows; import org.junit.jupiter.api.Test; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union8ReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union8ReaderTest.java index 773497fb..e76f10c6 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union8ReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union8ReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers.union; -import com.strategyobject.substrateclient.types.union.Union8; +import com.strategyobject.substrateclient.common.types.union.Union8; import lombok.SneakyThrows; import org.junit.jupiter.api.Test; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union9ReaderTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union9ReaderTest.java index 6e2c4f3a..9a044eb5 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union9ReaderTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/Union9ReaderTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.readers.union; -import com.strategyobject.substrateclient.types.union.Union9; +import com.strategyobject.substrateclient.common.types.union.Union9; import lombok.SneakyThrows; import org.junit.jupiter.api.Test; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/UnionReaderTester.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/UnionReaderTester.java index c5fd980e..7da6ae49 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/UnionReaderTester.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/readers/union/UnionReaderTester.java @@ -1,9 +1,9 @@ package com.strategyobject.substrateclient.scale.readers.union; +import com.strategyobject.substrateclient.common.types.union.Union; import com.strategyobject.substrateclient.scale.ScaleReader; import com.strategyobject.substrateclient.scale.readers.U8Reader; import com.strategyobject.substrateclient.scale.readers.VoidReader; -import com.strategyobject.substrateclient.types.union.Union; import lombok.SneakyThrows; import lombok.val; import lombok.var; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/substitutes/TestDispatch.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/substitutes/TestDispatch.java new file mode 100644 index 00000000..c2086c26 --- /dev/null +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/substitutes/TestDispatch.java @@ -0,0 +1,10 @@ +package com.strategyobject.substrateclient.scale.substitutes; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class TestDispatch { + private final String value; +} diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/substitutes/TestDispatchWriter.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/substitutes/TestDispatchWriter.java new file mode 100644 index 00000000..d7b07649 --- /dev/null +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/substitutes/TestDispatchWriter.java @@ -0,0 +1,22 @@ +package com.strategyobject.substrateclient.scale.substitutes; + +import com.strategyobject.substrateclient.scale.ScaleWriter; +import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.val; + +import java.io.IOException; +import java.io.OutputStream; + +@RequiredArgsConstructor +public class TestDispatchWriter implements ScaleWriter { + private final ScaleWriterRegistry scaleWriterRegistry; + + @SuppressWarnings("unchecked") + @Override + public void write(@NonNull TestDispatch value, @NonNull OutputStream stream, ScaleWriter... writers) throws IOException { + val writer = (ScaleWriter) scaleWriterRegistry.resolve(String.class); + writer.write(value.getValue(), stream); + } +} diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/ArrayWritersTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/ArrayWritersTest.java index bb949436..5f16ac06 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/ArrayWritersTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/ArrayWritersTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import com.strategyobject.substrateclient.scale.ScaleWriter; import com.strategyobject.substrateclient.tests.TestSuite; import lombok.AccessLevel; @@ -14,7 +14,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -public class ArrayWritersTest { +class ArrayWritersTest { @TestFactory Stream write() { val Array2DWriter = new ArrayWriter().inject( @@ -62,7 +62,7 @@ Stream writeEmpty() { } @AllArgsConstructor(access = AccessLevel.PRIVATE) - static class Test extends TestSuite.TestCase { + static class Test implements TestSuite.TestCase { private final ScaleWriter writer; private final T given; private final String expected; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/BoolWriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/BoolWriterTest.java index 3c6cdd03..a086e91b 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/BoolWriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/BoolWriterTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/CompactBigIntegerWriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/CompactBigIntegerWriterTest.java index b08923cb..f6837ff6 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/CompactBigIntegerWriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/CompactBigIntegerWriterTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/CompactIntegerWriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/CompactIntegerWriterTest.java index a99ba2f8..1dc3be26 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/CompactIntegerWriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/CompactIntegerWriterTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.api.Test; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/DispatchingWriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/DispatchingWriterTest.java new file mode 100644 index 00000000..0e3b46fc --- /dev/null +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/DispatchingWriterTest.java @@ -0,0 +1,33 @@ +package com.strategyobject.substrateclient.scale.writers; + +import com.strategyobject.substrateclient.common.convert.HexConverter; +import com.strategyobject.substrateclient.scale.ScaleDispatch; +import com.strategyobject.substrateclient.scale.ScaleWriter; +import com.strategyobject.substrateclient.scale.registries.ScaleWriterRegistry; +import com.strategyobject.substrateclient.scale.substitutes.TestDispatch; +import com.strategyobject.substrateclient.scale.substitutes.TestDispatchWriter; +import lombok.val; +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class DispatchingWriterTest { + private final ScaleWriterRegistry registry = new ScaleWriterRegistry() {{ + register(new TestDispatchWriter(this), TestDispatch.class); + }}; + + @SuppressWarnings("unchecked") + @Test + void write() throws IOException { + val writer = (ScaleWriter) registry.resolve(ScaleDispatch.class); + + val stream = new ByteArrayOutputStream(); + writer.write(new TestDispatch("test"), stream); + val actual = HexConverter.toHex(stream.toByteArray()); + + assertEquals("0x1074657374", actual); + } +} \ No newline at end of file diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/I128WriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/I128WriterTest.java index ddcf8de4..59bd146c 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/I128WriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/I128WriterTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/I16WriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/I16WriterTest.java index fa9fa36e..ef96ca73 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/I16WriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/I16WriterTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/I32WriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/I32WriterTest.java index 00777029..9783d1df 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/I32WriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/I32WriterTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/I64WriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/I64WriterTest.java index 06a275ff..27133d69 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/I64WriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/I64WriterTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/I8WriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/I8WriterTest.java index 3ad06895..d499e988 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/I8WriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/I8WriterTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/ResultWriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/ResultWriterTest.java index 6270382d..1523f282 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/ResultWriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/ResultWriterTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers; -import com.strategyobject.substrateclient.types.Result; +import com.strategyobject.substrateclient.common.types.Result; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.api.Test; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/StringWriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/StringWriterTest.java index 17843c6a..72b99dca 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/StringWriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/StringWriterTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.api.Test; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/U128WriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/U128WriterTest.java index b4b32ba8..9a0101e1 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/U128WriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/U128WriterTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/U16WriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/U16WriterTest.java index 994b07d5..dd1b21b4 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/U16WriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/U16WriterTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/U32WriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/U32WriterTest.java index df08a05b..0f2335fe 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/U32WriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/U32WriterTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/U64WriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/U64WriterTest.java index 9b666915..33d64876 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/U64WriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/U64WriterTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/U8WriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/U8WriterTest.java index fd3dd2cf..e2996a0f 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/U8WriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/U8WriterTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.params.ParameterizedTest; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/VecWriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/VecWriterTest.java index a31fb15c..7718057d 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/VecWriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/VecWriterTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers; -import com.strategyobject.substrateclient.common.utils.HexConverter; +import com.strategyobject.substrateclient.common.convert.HexConverter; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.api.Test; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/VoidWriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/VoidWriterTest.java new file mode 100644 index 00000000..f2d3024c --- /dev/null +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/VoidWriterTest.java @@ -0,0 +1,25 @@ +package com.strategyobject.substrateclient.scale.writers; + +import com.strategyobject.substrateclient.common.convert.HexConverter; +import lombok.SneakyThrows; +import lombok.val; +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayOutputStream; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class VoidWriterTest { + + private final VoidWriter voidWriter = new VoidWriter(); + + @SneakyThrows + @Test + void write() { + val stream = new ByteArrayOutputStream(); + voidWriter.write(null, stream); + val actual = HexConverter.toHex(stream.toByteArray()); + + assertEquals("0x", actual); + } +} \ No newline at end of file diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union10WriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union10WriterTest.java index 5ca18562..8ee2d483 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union10WriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union10WriterTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers.union; -import com.strategyobject.substrateclient.types.union.Union10; +import com.strategyobject.substrateclient.common.types.union.Union10; import org.junit.jupiter.api.Test; import java.util.function.Function; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union11WriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union11WriterTest.java index d1e5c37a..c08d22a5 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union11WriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union11WriterTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers.union; -import com.strategyobject.substrateclient.types.union.Union11; +import com.strategyobject.substrateclient.common.types.union.Union11; import org.junit.jupiter.api.Test; import java.util.function.Function; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union12WriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union12WriterTest.java index f18ed9fc..c5984033 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union12WriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union12WriterTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers.union; -import com.strategyobject.substrateclient.types.union.Union12; +import com.strategyobject.substrateclient.common.types.union.Union12; import org.junit.jupiter.api.Test; import java.util.function.Function; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union1WriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union1WriterTest.java index bed11352..a6a2fdd1 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union1WriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union1WriterTest.java @@ -1,7 +1,7 @@ package com.strategyobject.substrateclient.scale.writers.union; +import com.strategyobject.substrateclient.common.types.union.Union1; import com.strategyobject.substrateclient.scale.writers.I8Writer; -import com.strategyobject.substrateclient.types.union.Union1; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.api.Test; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union2WriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union2WriterTest.java index f46cc8bb..48e51943 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union2WriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union2WriterTest.java @@ -1,8 +1,8 @@ package com.strategyobject.substrateclient.scale.writers.union; +import com.strategyobject.substrateclient.common.types.union.Union2; import com.strategyobject.substrateclient.scale.writers.I8Writer; import com.strategyobject.substrateclient.scale.writers.VoidWriter; -import com.strategyobject.substrateclient.types.union.Union2; import lombok.SneakyThrows; import lombok.val; import org.junit.jupiter.api.Test; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union3WriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union3WriterTest.java index 45098e12..b6220806 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union3WriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union3WriterTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers.union; -import com.strategyobject.substrateclient.types.union.Union3; +import com.strategyobject.substrateclient.common.types.union.Union3; import org.junit.jupiter.api.Test; import java.util.function.Function; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union4WriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union4WriterTest.java index dd40d326..a5cadf15 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union4WriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union4WriterTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers.union; -import com.strategyobject.substrateclient.types.union.Union4; +import com.strategyobject.substrateclient.common.types.union.Union4; import org.junit.jupiter.api.Test; import java.util.function.Function; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union5WriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union5WriterTest.java index 45f1fa51..fbc86395 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union5WriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union5WriterTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers.union; -import com.strategyobject.substrateclient.types.union.Union5; +import com.strategyobject.substrateclient.common.types.union.Union5; import org.junit.jupiter.api.Test; import java.util.function.Function; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union6WriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union6WriterTest.java index 040d5e4a..e474cb67 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union6WriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union6WriterTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers.union; -import com.strategyobject.substrateclient.types.union.Union6; +import com.strategyobject.substrateclient.common.types.union.Union6; import org.junit.jupiter.api.Test; import java.util.function.Function; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union7WriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union7WriterTest.java index 8677a64c..598509e9 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union7WriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union7WriterTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers.union; -import com.strategyobject.substrateclient.types.union.Union7; +import com.strategyobject.substrateclient.common.types.union.Union7; import org.junit.jupiter.api.Test; import java.util.function.Function; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union8WriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union8WriterTest.java index c9939daa..22332406 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union8WriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union8WriterTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers.union; -import com.strategyobject.substrateclient.types.union.Union8; +import com.strategyobject.substrateclient.common.types.union.Union8; import org.junit.jupiter.api.Test; import java.util.function.Function; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union9WriterTest.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union9WriterTest.java index cc21f320..5eb31c2f 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union9WriterTest.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/Union9WriterTest.java @@ -1,6 +1,6 @@ package com.strategyobject.substrateclient.scale.writers.union; -import com.strategyobject.substrateclient.types.union.Union9; +import com.strategyobject.substrateclient.common.types.union.Union9; import org.junit.jupiter.api.Test; import java.util.function.Function; diff --git a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/UnionWriterTester.java b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/UnionWriterTester.java index 142e3db8..51d40765 100644 --- a/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/UnionWriterTester.java +++ b/scale/src/test/java/com/strategyobject/substrateclient/scale/writers/union/UnionWriterTester.java @@ -1,9 +1,9 @@ package com.strategyobject.substrateclient.scale.writers.union; +import com.strategyobject.substrateclient.common.types.union.Union; import com.strategyobject.substrateclient.scale.ScaleWriter; import com.strategyobject.substrateclient.scale.writers.I8Writer; import com.strategyobject.substrateclient.scale.writers.VoidWriter; -import com.strategyobject.substrateclient.types.union.Union; import lombok.SneakyThrows; import lombok.val; import lombok.var; diff --git a/settings.gradle b/settings.gradle index 64e2f05a..27850e9b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,20 +1,19 @@ rootProject.name = 'substrate-client' -include 'api' include 'common' +include 'tests' + include 'crypto' -include 'rpc' -include 'rpc:rpc-codegen' -include 'rpc:rpc-core' -include 'rpc:rpc-types' -include 'rpc:rpc-sections' -include 'types' include 'scale' include 'scale:scale-codegen' -include 'tests' include 'transport' -include 'types' -include 'storage' + +include 'rpc' +include 'rpc:rpc-codegen' + +include 'rpc:rpc-api' + include 'pallet' include 'pallet:pallet-codegen' +include 'api' diff --git a/storage/build.gradle b/storage/build.gradle deleted file mode 100644 index 703eee01..00000000 --- a/storage/build.gradle +++ /dev/null @@ -1,19 +0,0 @@ -dependencies { - implementation project(':common') - implementation project(':scale') - implementation project(':crypto') - implementation project(':types') - implementation project(':rpc') - implementation project(':rpc:rpc-types') - implementation project(':rpc:rpc-sections') - - implementation 'org.bouncycastle:bcprov-jdk15on:1.70' - implementation 'net.openhft:zero-allocation-hashing:0.15' - - testImplementation project(':tests') - testCompileOnly project(':transport') - - testImplementation 'org.testcontainers:testcontainers:1.17.1' - testImplementation 'org.testcontainers:junit-jupiter:1.17.1' - testImplementation 'ch.qos.logback:logback-classic:1.2.11' -} \ No newline at end of file diff --git a/tests/build.gradle b/tests/build.gradle index dfab4466..9c56050e 100644 --- a/tests/build.gradle +++ b/tests/build.gradle @@ -1,4 +1,4 @@ dependencies { - implementation 'org.testcontainers:testcontainers:1.17.1' - implementation 'org.junit.jupiter:junit-jupiter-api:5.8.2' + implementation 'org.testcontainers:testcontainers:1.17.3' + implementation 'org.junit.jupiter:junit-jupiter-api:5.9.0' } \ No newline at end of file diff --git a/tests/src/main/java/com/strategyobject/substrateclient/tests/TestSuite.java b/tests/src/main/java/com/strategyobject/substrateclient/tests/TestSuite.java index 7f99c498..805db30d 100644 --- a/tests/src/main/java/com/strategyobject/substrateclient/tests/TestSuite.java +++ b/tests/src/main/java/com/strategyobject/substrateclient/tests/TestSuite.java @@ -14,12 +14,12 @@ public static Stream of(TestCase... testCases) { private TestSuite() { } - public abstract static class TestCase { - public abstract String getDisplayName(); + public interface TestCase { + String getDisplayName(); - public abstract void execute() throws Throwable; + void execute() throws Throwable; - public DynamicTest generate() { + default DynamicTest generate() { return DynamicTest.dynamicTest(getDisplayName(), this::execute); } } diff --git a/tests/src/main/java/com/strategyobject/substrateclient/tests/containers/SubstrateVersion.java b/tests/src/main/java/com/strategyobject/substrateclient/tests/containers/SubstrateVersion.java index ee806ce1..0cff4c39 100644 --- a/tests/src/main/java/com/strategyobject/substrateclient/tests/containers/SubstrateVersion.java +++ b/tests/src/main/java/com/strategyobject/substrateclient/tests/containers/SubstrateVersion.java @@ -2,4 +2,7 @@ public class SubstrateVersion { public static final String V3_0_0 = "v3.0.0"; + + private SubstrateVersion() { + } } diff --git a/tests/src/main/java/com/strategyobject/substrateclient/tests/containers/TestSubstrateContainer.java b/tests/src/main/java/com/strategyobject/substrateclient/tests/containers/TestSubstrateContainer.java index 65b816ea..4f10f77a 100644 --- a/tests/src/main/java/com/strategyobject/substrateclient/tests/containers/TestSubstrateContainer.java +++ b/tests/src/main/java/com/strategyobject/substrateclient/tests/containers/TestSubstrateContainer.java @@ -9,7 +9,7 @@ public TestSubstrateContainer(String version) { super(IMAGE + version); addExposedPorts(30333, 9944, 9933); - withCommand("--tmp --dev --ws-external --rpc-methods=Unsafe --rpc-cors all --rpc-external"); + setCommand("--tmp --dev --ws-external --rpc-methods=Unsafe --rpc-cors all --rpc-external"); } public String getWsAddress() { diff --git a/transport/build.gradle b/transport/build.gradle index a01a0c33..dc087d02 100644 --- a/transport/build.gradle +++ b/transport/build.gradle @@ -6,8 +6,8 @@ dependencies { testImplementation project(':tests') testImplementation 'ch.qos.logback:logback-classic:1.2.11' - testImplementation 'org.testcontainers:testcontainers:1.17.1' - testImplementation 'org.testcontainers:junit-jupiter:1.17.1' - testImplementation 'org.testcontainers:toxiproxy:1.17.1' + testImplementation 'org.testcontainers:testcontainers:1.17.3' + testImplementation 'org.testcontainers:junit-jupiter:1.17.3' + testImplementation 'org.testcontainers:toxiproxy:1.17.3' testImplementation 'org.awaitility:awaitility:4.2.0' } \ No newline at end of file diff --git a/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcBoolean.java b/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcBoolean.java index 208e9239..40c36b39 100644 --- a/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcBoolean.java +++ b/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcBoolean.java @@ -3,7 +3,7 @@ import lombok.RequiredArgsConstructor; @RequiredArgsConstructor -public final class RpcBoolean extends RpcObject { +public final class RpcBoolean implements RpcObject { private final boolean value; diff --git a/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcList.java b/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcList.java index c0b44db1..0743d45c 100644 --- a/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcList.java +++ b/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcList.java @@ -5,7 +5,7 @@ import java.util.List; @RequiredArgsConstructor -public final class RpcList extends RpcObject { +public final class RpcList implements RpcObject { private final List list; diff --git a/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcMap.java b/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcMap.java index 64f80daa..b517009f 100644 --- a/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcMap.java +++ b/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcMap.java @@ -5,7 +5,7 @@ import java.util.Map; @RequiredArgsConstructor -public final class RpcMap extends RpcObject { +public final class RpcMap implements RpcObject { private final Map map; diff --git a/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcNull.java b/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcNull.java index a1da460d..c272be03 100644 --- a/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcNull.java +++ b/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcNull.java @@ -3,7 +3,7 @@ import java.util.List; import java.util.Map; -public final class RpcNull extends RpcObject { +public final class RpcNull implements RpcObject { @Override public boolean isNull() { return true; diff --git a/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcNumber.java b/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcNumber.java index 144054ea..b846c621 100644 --- a/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcNumber.java +++ b/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcNumber.java @@ -3,7 +3,7 @@ import lombok.RequiredArgsConstructor; @RequiredArgsConstructor -public final class RpcNumber extends RpcObject { +public final class RpcNumber implements RpcObject { private final Number value; diff --git a/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcObject.java b/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcObject.java index 65e95e21..ab3c4139 100644 --- a/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcObject.java +++ b/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcObject.java @@ -3,76 +3,77 @@ import java.util.List; import java.util.Map; -public abstract class RpcObject { +public interface RpcObject { - RpcObject() { - } - - public boolean isNull() { + default boolean isNull() { return false; } - public boolean isBoolean() { + default boolean isBoolean() { return false; } - public boolean isList() { + default boolean isList() { return false; } - public boolean isMap() { + default boolean isMap() { return false; } - public boolean isNumber() { + default boolean isNumber() { return false; } - public boolean isString() { + default boolean isString() { return false; } - public Boolean asBoolean() { + default Boolean asBoolean() { throw new IllegalStateException(); } - public List asList() { + default List asList() { throw new IllegalStateException(); } - public Map asMap() { + default Map asMap() { throw new IllegalStateException(); } - public Number asNumber() { + default Number asNumber() { throw new IllegalStateException(); } - public String asString() { + default String asString() { throw new IllegalStateException(); } - public static RpcObject ofNull() { + static RpcObject ofNull() { return new RpcNull(); } - public static RpcObject of(boolean value) { + static RpcObject of(boolean value) { return new RpcBoolean(value); } - public static RpcObject of(List list) { + static RpcObject of(List list) { return list == null ? new RpcNull() : new RpcList(list); } - public static RpcObject of(Map map) { + static RpcObject of(Map map) { return map == null ? new RpcNull() : new RpcMap(map); } - public static RpcObject of(Number value) { + static RpcObject of(long value) { + return new RpcNumber(value); + } + + static RpcObject of(Number value) { return value == null ? new RpcNull() : new RpcNumber(value); } - public static RpcObject of(String value) { + static RpcObject of(String value) { return value == null ? new RpcNull() : new RpcString(value); } diff --git a/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcString.java b/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcString.java index ffac54df..6e7b91e1 100644 --- a/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcString.java +++ b/transport/src/main/java/com/strategyobject/substrateclient/transport/RpcString.java @@ -3,7 +3,7 @@ import lombok.RequiredArgsConstructor; @RequiredArgsConstructor -public final class RpcString extends RpcObject { +public final class RpcString implements RpcObject { private final String value; diff --git a/transport/src/main/java/com/strategyobject/substrateclient/transport/coder/RpcObjectTypeAdapter.java b/transport/src/main/java/com/strategyobject/substrateclient/transport/coder/RpcObjectTypeAdapter.java index eef97e8a..c6e13562 100644 --- a/transport/src/main/java/com/strategyobject/substrateclient/transport/coder/RpcObjectTypeAdapter.java +++ b/transport/src/main/java/com/strategyobject/substrateclient/transport/coder/RpcObjectTypeAdapter.java @@ -7,6 +7,8 @@ import lombok.val; import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; import java.util.ArrayList; import java.util.HashMap; @@ -25,7 +27,7 @@ public RpcObject read(JsonReader in) throws IOException { case BOOLEAN: return new RpcBoolean(in.nextBoolean()); case NUMBER: - return new RpcNumber(in.nextDouble()); + return new RpcNumber(parseNumber(in)); case STRING: return new RpcString(in.nextString()); case BEGIN_ARRAY: @@ -48,4 +50,21 @@ public RpcObject read(JsonReader in) throws IOException { return new RpcMap(map); } } + + private Number parseNumber(JsonReader in) throws IOException { + val value = in.nextString(); + try { + return Long.parseLong(value); + } catch (NumberFormatException ignored) { + // Ignore + } + + try { + return new BigInteger(value); + } catch (NumberFormatException ignored) { + // Ignore + } + + return new BigDecimal(value); + } } diff --git a/transport/src/main/java/com/strategyobject/substrateclient/transport/ws/Delay.java b/transport/src/main/java/com/strategyobject/substrateclient/transport/ws/Delay.java new file mode 100644 index 00000000..f3eb72ca --- /dev/null +++ b/transport/src/main/java/com/strategyobject/substrateclient/transport/ws/Delay.java @@ -0,0 +1,28 @@ +package com.strategyobject.substrateclient.transport.ws; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.util.concurrent.TimeUnit; + +/** + * Represents a delay + */ +@RequiredArgsConstructor(staticName = "of") +@Getter +public class Delay { + /** + * The time to delay execution unit + */ + private final long value; + + /** + * The time unit of the delay parameter + */ + private final TimeUnit unit; + + /** + * A delay that should never be scheduled + */ + public static final Delay NEVER = Delay.of(-1, TimeUnit.SECONDS); +} diff --git a/transport/src/main/java/com/strategyobject/substrateclient/transport/ws/ExponentialBackoffReconnectionPolicy.java b/transport/src/main/java/com/strategyobject/substrateclient/transport/ws/ExponentialBackoffReconnectionPolicy.java new file mode 100644 index 00000000..c1758d41 --- /dev/null +++ b/transport/src/main/java/com/strategyobject/substrateclient/transport/ws/ExponentialBackoffReconnectionPolicy.java @@ -0,0 +1,123 @@ +package com.strategyobject.substrateclient.transport.ws; + +import com.google.common.base.Preconditions; +import lombok.*; +import lombok.extern.slf4j.Slf4j; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.LongAdder; + +/** + * Represents an exponential backoff retry policy + */ +@RequiredArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Slf4j +public class ExponentialBackoffReconnectionPolicy implements ReconnectionPolicy { + /** + * Max number of attempts + */ + private final long maxAttempts; + /** + * Initial delay, the time to delay execution unit + */ + private final long delay; + /** + * The time unit of the delay parameter + */ + private final TimeUnit unit; + /** + * Max delay + */ + private final long maxDelay; + /** + * A multiplier that's applied to delay after every attempt + */ + private final double factor; + + /** + * @param context contains a reason of disconnection and counter of attempts + * @return a unit of time to delay the next reconnection + */ + @Override + public @NonNull Delay getNextDelay(@NonNull ReconnectionContext context) { + try { + if (context.getPolicyContext().longValue() >= maxAttempts) { + log.info("Provider won't reconnect more."); + + return Delay.NEVER; + } + + var nextDelay = delay * Math.pow(factor, context.getPolicyContext().longValue()); + nextDelay = Math.min(nextDelay, maxDelay); + + log.info("Provider will try to reconnect after: {} {}", nextDelay, unit); + return Delay.of((long) nextDelay, unit); + } finally { + context.getPolicyContext().increment(); + } + } + + /** + * Returns the counter of attempts + */ + @Override + public LongAdder initContext() { + return new LongAdder(); + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private long delay = 15; + private TimeUnit unit = TimeUnit.SECONDS; + private long maxDelay = 150; + private long maxAttempts = 10; + private double factor = 2; + + Builder() { + } + + public Builder retryAfter(long delay, TimeUnit unit) { + Preconditions.checkArgument(delay >= 0); + + this.delay = delay; + this.unit = unit; + + return this; + } + + public Builder withFactor(double factor) { + Preconditions.checkArgument(factor > 0); + + this.factor = factor; + return this; + } + + public Builder withMaxDelay(long maxDelay) { + Preconditions.checkArgument(maxDelay >= 0); + + this.maxDelay = maxDelay; + return this; + } + + public Builder notMoreThan(long maxAttempts) { + Preconditions.checkArgument(maxAttempts >= 0); + + this.maxAttempts = maxAttempts; + return this; + } + + public ExponentialBackoffReconnectionPolicy build() { + return new ExponentialBackoffReconnectionPolicy( + this.maxAttempts, + this.delay, + this.unit, + this.maxDelay, + this.factor + ); + } + } +} diff --git a/transport/src/main/java/com/strategyobject/substrateclient/transport/ws/ReconnectionContext.java b/transport/src/main/java/com/strategyobject/substrateclient/transport/ws/ReconnectionContext.java new file mode 100644 index 00000000..a7e07ef0 --- /dev/null +++ b/transport/src/main/java/com/strategyobject/substrateclient/transport/ws/ReconnectionContext.java @@ -0,0 +1,29 @@ +package com.strategyobject.substrateclient.transport.ws; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * Represents a context why connection was closed + * + * @param a type of policy's context required for + * computing the next delay or other policy's purposes + */ +@RequiredArgsConstructor(staticName = "of") +@Getter +public class ReconnectionContext { + /** + * The code of the reason of disconnection + */ + private final int code; + + /** + * The text of the reason + */ + private final String reason; + + /** + * The policy's context + */ + private final T policyContext; +} diff --git a/transport/src/main/java/com/strategyobject/substrateclient/transport/ws/ReconnectionPolicy.java b/transport/src/main/java/com/strategyobject/substrateclient/transport/ws/ReconnectionPolicy.java new file mode 100644 index 00000000..6cea8e7f --- /dev/null +++ b/transport/src/main/java/com/strategyobject/substrateclient/transport/ws/ReconnectionPolicy.java @@ -0,0 +1,55 @@ +package com.strategyobject.substrateclient.transport.ws; + +import lombok.NonNull; + +/** + * @param a type of policy's context required for + * computing the next delay or other policy's purposes + * Represents a strategy of reconnection + */ +public interface ReconnectionPolicy { + + /** + * The method is called when connection was closed and probably should be reconnected. + * @param context contains a reason of disconnection and policy's context. + * @return a unit of time from now to delay reconnection. + */ + @NonNull Delay getNextDelay(@NonNull ReconnectionContext context); + + /** + * The method is called before the first connection or when the one successfully reestablished. + * @return a context required for the policy. + */ + T initContext(); + + /** + * @return the builder of ExponentialBackoffReconnectionPolicy + */ + static ExponentialBackoffReconnectionPolicy.Builder exponentialBackoff() { + return ExponentialBackoffReconnectionPolicy.builder(); + } + + /** + * @param the type of context + * @return the policy that's supposed to not reconnect automatically + */ + @SuppressWarnings("unchecked") + static ReconnectionPolicy manual() { + return (ReconnectionPolicy) MANUAL; + } + + /** + * The policy that's supposed to not reconnect automatically + */ + ReconnectionPolicy MANUAL = new ReconnectionPolicy() { + @Override + public @NonNull Delay getNextDelay(@NonNull ReconnectionContext context) { + return Delay.NEVER; + } + + @Override + public Void initContext() { + return null; + } + }; +} diff --git a/transport/src/main/java/com/strategyobject/substrateclient/transport/ws/WsProvider.java b/transport/src/main/java/com/strategyobject/substrateclient/transport/ws/WsProvider.java index 92edd0e0..f6f7c67e 100644 --- a/transport/src/main/java/com/strategyobject/substrateclient/transport/ws/WsProvider.java +++ b/transport/src/main/java/com/strategyobject/substrateclient/transport/ws/WsProvider.java @@ -18,7 +18,9 @@ import java.net.URISyntaxException; import java.util.*; import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiConsumer; +import java.util.function.Supplier; @Getter @Setter @@ -47,7 +49,7 @@ class WsStateAwaiting { } @Slf4j -public class WsProvider implements ProviderInterface, AutoCloseable { +public class WsProvider implements ProviderInterface, AutoCloseable { private static final int RESUBSCRIBE_TIMEOUT = 20; private static final Map ALIASES = new HashMap<>(); private static final ScheduledExecutorService timedOutHandlerCleaner; @@ -68,33 +70,33 @@ public class WsProvider implements ProviderInterface, AutoCloseable { private final Map waitingForId = new ConcurrentHashMap<>(); private final int heartbeatInterval; private final long responseTimeoutInMs; - private volatile int autoConnectMs; + private final AtomicReference reconnectionPolicyContext = new AtomicReference<>(); + private volatile ReconnectionPolicy reconnectionPolicy; private volatile WebSocketClient webSocket = null; private volatile CompletableFuture whenConnected = null; private volatile CompletableFuture whenDisconnected = null; private volatile ProviderStatus status = ProviderStatus.DISCONNECTED; + private final ScheduledExecutorService reconnector = Executors.newSingleThreadScheduledExecutor(); WsProvider(@NonNull URI endpoint, - int autoConnectMs, Map headers, int heartbeatInterval, - long responseTimeoutInMs) { + long responseTimeoutInMs, + @NonNull ReconnectionPolicy reconnectionPolicy) { Preconditions.checkArgument( endpoint.getScheme().matches("(?i)ws|wss"), "Endpoint should start with 'ws://', received " + endpoint); - Preconditions.checkArgument( - autoConnectMs >= 0, - "AutoConnect delay cannot be less than 0"); this.endpoint = endpoint; - this.autoConnectMs = autoConnectMs; this.headers = headers; this.heartbeatInterval = heartbeatInterval; this.responseTimeoutInMs = responseTimeoutInMs; + this.reconnectionPolicy = reconnectionPolicy; + this.reconnectionPolicyContext.set(reconnectionPolicy.initContext()); } - public static Builder builder() { - return new Builder(); + public static Builder builder() { + return new Builder<>(); } /** @@ -140,8 +142,8 @@ public synchronized CompletableFuture connect() { this.status = ProviderStatus.CONNECTING; - val whenConnected = new CompletableFuture(); - this.whenConnected = whenConnected; + val whenConnectedFuture = new CompletableFuture(); + this.whenConnected = whenConnectedFuture; try { val ws = WebSocket.builder() @@ -156,19 +158,19 @@ public synchronized CompletableFuture connect() { this.webSocket = ws; this.eventEmitter.once(ProviderInterfaceEmitted.CONNECTED, _x -> { - whenConnected.complete(null); + whenConnectedFuture.complete(null); this.whenConnected = null; }); ws.connect(); } catch (Exception ex) { log.error("Connect error", ex); - whenConnected.completeExceptionally(ex); + whenConnectedFuture.completeExceptionally(ex); this.emit(ProviderInterfaceEmitted.ERROR, ex); this.whenConnected = null; this.status = ProviderStatus.DISCONNECTED; } - return whenConnected; + return whenConnectedFuture; } /** @@ -188,11 +190,11 @@ public synchronized CompletableFuture disconnect() { return inProgress; } - val whenDisconnected = new CompletableFuture(); - this.whenDisconnected = whenDisconnected; + val whenDisconnectedFuture = new CompletableFuture(); + this.whenDisconnected = whenDisconnectedFuture; // switch off autoConnect, we are in manual mode now - this.autoConnectMs = 0; + this.reconnectionPolicy = ReconnectionPolicy.manual(); this.status = ProviderStatus.DISCONNECTING; val ws = this.webSocket; @@ -200,7 +202,7 @@ public synchronized CompletableFuture disconnect() { ws.close(CloseFrame.NORMAL); } - return whenDisconnected; + return whenDisconnectedFuture; } /** @@ -357,7 +359,7 @@ private synchronized void onSocketClose(int code, String reason) { code, reason); - if (this.autoConnectMs > 0) { + if (this.reconnectionPolicy != ReconnectionPolicy.MANUAL) { log.error(errorMessage); } @@ -370,16 +372,39 @@ private synchronized void onSocketClose(int code, String reason) { this.webSocket = null; this.status = ProviderStatus.DISCONNECTED; this.emit(ProviderInterfaceEmitted.DISCONNECTED); - val whenDisconnected = this.whenDisconnected; - if (whenDisconnected != null) { - whenDisconnected.complete(null); + val whenDisconnectedFuture = this.whenDisconnected; + if (whenDisconnectedFuture != null) { + whenDisconnectedFuture.complete(null); this.whenDisconnected = null; } - if (this.autoConnectMs > 0) { - log.info("Trying to reconnect to {}", this.endpoint); - this.connect(); + val whenConnectedFuture = this.whenConnected; + if (whenConnectedFuture != null) { + whenConnectedFuture.completeExceptionally(wsClosedException); + this.whenConnected = null; + } + + if (this.reconnectionPolicy != ReconnectionPolicy.MANUAL) { + scheduleReconnect(code, reason); + } + } + + private void scheduleReconnect(int code, String reason) { + val delay = reconnectionPolicy + .getNextDelay(ReconnectionContext.of(code, + reason, + reconnectionPolicyContext.get())); + if (delay.getValue() < 0) { + return; } + + reconnector.schedule( + () -> { + log.info("Trying to reconnect to {}", this.endpoint); + this.connect(); + }, + delay.getValue(), + delay.getUnit()); } private void onSocketError(Exception ex) { @@ -400,7 +425,7 @@ private void onSocketMessage(String message) { private void onSocketMessageResult(JsonRpcResponseSingle response) { val id = response.getId(); - val handler = (WsStateAwaiting) this.handlers.get(id); + val handler = this.handlers.get(id); if (handler == null) { log.error("Unable to find handler for id={}", id); return; @@ -465,6 +490,7 @@ public synchronized void onSocketOpen() { log.info("Connected to: {}", this.webSocket.getURI()); this.status = ProviderStatus.CONNECTED; + reconnectionPolicyContext.set(reconnectionPolicy.initContext()); this.emit(ProviderInterfaceEmitted.CONNECTED); this.resubscribe(); } @@ -472,6 +498,8 @@ public synchronized void onSocketOpen() { @Override public void close() { try { + reconnector.shutdownNow(); + val currentStatus = this.status; if (currentStatus == ProviderStatus.CONNECTED || currentStatus == ProviderStatus.DISCONNECTING) { this.disconnect(); @@ -482,13 +510,13 @@ public void close() { } private void resubscribe() { - Map subscriptions = new HashMap<>(this.subscriptions); + Map currentSubscriptions = new HashMap<>(this.subscriptions); this.subscriptions.clear(); try { CompletableFuture.allOf( - subscriptions.values() + currentSubscriptions.values() .stream() // only re-create subscriptions which are not in author (only area where // transactions are created, i.e. submissions such as 'author_submitAndWatchExtrinsic' @@ -514,27 +542,29 @@ private void resubscribe() { } } - public static class Builder { + public static class Builder implements Supplier { + private static final String DEFAULT_URI = "ws://127.0.0.1:9944"; + private URI endpoint; - private int autoConnectMs = 2500; private Map headers = null; private int heartbeatInterval = 30; private long responseTimeoutInMs = 20000; + private ReconnectionPolicy reconnectionPolicy; Builder() { try { - endpoint = new URI("ws://127.0.0.1:9944"); - } catch (URISyntaxException ex) { - ex.printStackTrace(); + endpoint = new URI(DEFAULT_URI); + } catch (URISyntaxException e) { + throw new RuntimeException(e); } } - public Builder setEndpoint(@NonNull URI endpoint) { + public Builder setEndpoint(@NonNull URI endpoint) { this.endpoint = endpoint; return this; } - public Builder setEndpoint(@NonNull String endpoint) { + public Builder setEndpoint(@NonNull String endpoint) { try { return setEndpoint(new URI(endpoint)); } catch (URISyntaxException ex) { @@ -542,42 +572,46 @@ public Builder setEndpoint(@NonNull String endpoint) { } } - public Builder setAutoConnectDelay(int autoConnectMs) { - this.autoConnectMs = autoConnectMs; - return this; - } - - public Builder disableAutoConnect() { - this.autoConnectMs = 0; - return this; - } - - public Builder setHeaders(Map headers) { + public Builder setHeaders(Map headers) { this.headers = headers; return this; } - public Builder setHeartbeatsInterval(int heartbeatInterval) { + public Builder setHeartbeatsInterval(int heartbeatInterval) { this.heartbeatInterval = heartbeatInterval; return this; } - public Builder disableHeartbeats() { + public Builder disableHeartbeats() { this.heartbeatInterval = 0; return this; } - public Builder setResponseTimeout(long timeout, TimeUnit timeUnit) { + public Builder setResponseTimeout(long timeout, TimeUnit timeUnit) { this.responseTimeoutInMs = timeUnit.toMillis(timeout); return this; } - public WsProvider build() { + @SuppressWarnings({"unchecked", "rawtypes"}) + public Builder withPolicy(ReconnectionPolicy policy) { + this.reconnectionPolicy = (ReconnectionPolicy) policy; + return (Builder) this; + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + public WsProvider build() { return new WsProvider(this.endpoint, - this.autoConnectMs, this.headers, this.heartbeatInterval, - this.responseTimeoutInMs); + this.responseTimeoutInMs, + this.reconnectionPolicy == null ? + ExponentialBackoffReconnectionPolicy.builder().build() : + this.reconnectionPolicy); + } + + @Override + public WsProvider get() { + return build(); } } -} +} \ No newline at end of file diff --git a/transport/src/test/java/com/strategyobject/substrateclient/transport/coder/RpcCoderTest.java b/transport/src/test/java/com/strategyobject/substrateclient/transport/coder/RpcCoderTest.java index 38ef8171..206cb46c 100644 --- a/transport/src/test/java/com/strategyobject/substrateclient/transport/coder/RpcCoderTest.java +++ b/transport/src/test/java/com/strategyobject/substrateclient/transport/coder/RpcCoderTest.java @@ -30,6 +30,24 @@ void decodeNullResult() { .isEqualTo(expected); } + @Test + void DecodeLongNumber() { + val json = "{\n" + + " \"result\": 506884800,\n" + + " \"id\": 0,\n" + + " \"jsonrpc\": \"3.0\"\n" + + "}"; + val actual = RpcCoder.decodeJson(json); + + val expected = new JsonRpcResponse(); + expected.jsonrpc = "3.0"; + expected.id = 0; + expected.result = RpcObject.of(506884800); + assertThat(actual) + .usingRecursiveComparison() + .isEqualTo(expected); + } + @Test void decodeJson() { val json = "{\n" + diff --git a/transport/src/test/java/com/strategyobject/substrateclient/transport/ws/ExponentialBackoffReconnectionPolicyTest.java b/transport/src/test/java/com/strategyobject/substrateclient/transport/ws/ExponentialBackoffReconnectionPolicyTest.java new file mode 100644 index 00000000..ef6ccf2f --- /dev/null +++ b/transport/src/test/java/com/strategyobject/substrateclient/transport/ws/ExponentialBackoffReconnectionPolicyTest.java @@ -0,0 +1,45 @@ +package com.strategyobject.substrateclient.transport.ws; + +import lombok.val; +import lombok.var; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import java.util.concurrent.TimeUnit; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class ExponentialBackoffReconnectionPolicyTest { + @ParameterizedTest + @CsvSource({ + "-1,10,20,SECONDS,5,1.5,7", + "10,5,10,SECONDS,10,2,10", + "20,5,100,SECONDS,10,2,3", + "10,10,10,MINUTES,10,2,10", + "5,100,5,MILLISECONDS,10,2,10", + "25,100,100,MILLISECONDS,3,0.5,3"}) + void getNextDelay(long expected, + long initialDelay, + long maxDelay, + TimeUnit unit, + int maxAttempts, + double factor, + int iterations) { + val policy = ExponentialBackoffReconnectionPolicy.builder() + .retryAfter(initialDelay, unit) + .withFactor(factor) + .withMaxDelay(maxDelay) + .notMoreThan(maxAttempts) + .build(); + val context = policy.initContext(); + + for (var i = 0; i < iterations - 1; i++) { + policy.getNextDelay(ReconnectionContext.of(-1, "some", context)); + } + + val delay = policy.getNextDelay(ReconnectionContext.of(-1, "some", context)); + + assertEquals(iterations, context.intValue()); + assertEquals(expected, delay.getValue()); + } +} \ No newline at end of file diff --git a/transport/src/test/java/com/strategyobject/substrateclient/transport/ws/WsProviderProxyTest.java b/transport/src/test/java/com/strategyobject/substrateclient/transport/ws/WsProviderProxyTest.java index c4582b3e..c79f0a1b 100644 --- a/transport/src/test/java/com/strategyobject/substrateclient/transport/ws/WsProviderProxyTest.java +++ b/transport/src/test/java/com/strategyobject/substrateclient/transport/ws/WsProviderProxyTest.java @@ -2,6 +2,7 @@ import com.strategyobject.substrateclient.tests.containers.SubstrateVersion; import com.strategyobject.substrateclient.tests.containers.TestSubstrateContainer; +import com.strategyobject.substrateclient.transport.ProviderInterfaceEmitted; import eu.rekawek.toxiproxy.model.ToxicDirection; import lombok.SneakyThrows; import lombok.val; @@ -13,14 +14,17 @@ import java.util.Map; import java.util.concurrent.CompletionException; +import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicInteger; import static org.awaitility.Awaitility.await; +import static org.hamcrest.Matchers.greaterThan; import static org.junit.jupiter.api.Assertions.*; @Testcontainers -public class WsProviderProxyTest { +class WsProviderProxyTest { static final Network network = Network.newNetwork(); @Container @@ -32,6 +36,7 @@ public class WsProviderProxyTest { .withNetwork(network) .withNetworkAliases("toxiproxy"); private static final int HEARTBEAT_INTERVAL = 5; + private static final int RECONNECT_INTERVAL = 5; private static final int WAIT_TIMEOUT = HEARTBEAT_INTERVAL * 3; final ToxiproxyContainer.ContainerProxy proxy = toxiproxy.getProxy(substrate, 9944); @@ -41,6 +46,10 @@ void canReconnect() { try (val wsProvider = WsProvider.builder() .setEndpoint(getWsAddress()) .setHeartbeatsInterval(HEARTBEAT_INTERVAL) + .withPolicy(ReconnectionPolicy.exponentialBackoff() + .retryAfter(RECONNECT_INTERVAL, TimeUnit.SECONDS) + .withMaxDelay(RECONNECT_INTERVAL) + .build()) .build()) { wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); @@ -53,7 +62,41 @@ void canReconnect() { proxy.setConnectionCut(false); await() - .atMost(WAIT_TIMEOUT, TimeUnit.SECONDS) + .atMost(RECONNECT_INTERVAL * 2, TimeUnit.SECONDS) + .until(wsProvider::isConnected); + } + } + + @Test + @SneakyThrows + void canReconnectWhenConnectionWasClosedForALongPeriod() { + try (val wsProvider = WsProvider.builder() + .setEndpoint(getWsAddress()) + .setHeartbeatsInterval(HEARTBEAT_INTERVAL) + .withPolicy(ReconnectionPolicy.exponentialBackoff() + .retryAfter(RECONNECT_INTERVAL, TimeUnit.SECONDS) + .withMaxDelay(RECONNECT_INTERVAL) + .build()) + .build()) { + + val disconnectionCounter = new AtomicInteger(0); + wsProvider.on(ProviderInterfaceEmitted.DISCONNECTED, i -> disconnectionCounter.incrementAndGet()); + wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); + assertTrue(wsProvider.isConnected()); + + val CLOSE_AFTER = 1000; + val toxic = proxy + .toxics() + .timeout("timeout", ToxicDirection.DOWNSTREAM, CLOSE_AFTER); + await() + .atLeast(CLOSE_AFTER, TimeUnit.MILLISECONDS) + .atMost(HEARTBEAT_INTERVAL + RECONNECT_INTERVAL * 4, TimeUnit.SECONDS) + .untilAtomic(disconnectionCounter, greaterThan(2)); + assertFalse(wsProvider.isConnected()); + + toxic.remove(); + await() + .atMost(RECONNECT_INTERVAL * 2, TimeUnit.SECONDS) .until(wsProvider::isConnected); } } @@ -61,21 +104,28 @@ void canReconnect() { @Test @SneakyThrows void canAutoConnectWhenServerAvailable() { - proxy.setConnectionCut(true); + val closed = proxy + .toxics() + .limitData("closed", ToxicDirection.DOWNSTREAM, 0); try (val wsProvider = WsProvider.builder() .setEndpoint(getWsAddress()) .disableHeartbeats() + .withPolicy(ReconnectionPolicy.exponentialBackoff() + .retryAfter(RECONNECT_INTERVAL, TimeUnit.SECONDS) + .withMaxDelay(RECONNECT_INTERVAL) + .build()) .build()) { - assertThrows( - TimeoutException.class, + val exception = assertThrows( + ExecutionException.class, () -> wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS)); + assertTrue(exception.getCause() instanceof WsClosedException); assertFalse(wsProvider.isConnected()); - proxy.setConnectionCut(false); + closed.remove(); await() - .atMost(WAIT_TIMEOUT, TimeUnit.SECONDS) + .atMost(RECONNECT_INTERVAL * 2, TimeUnit.SECONDS) .until(wsProvider::isConnected); } } @@ -85,7 +135,7 @@ void canAutoConnectWhenServerAvailable() { void throwsExceptionWhenCanNotSendRequestAndCleanHandler() { try (val wsProvider = WsProvider.builder() .setEndpoint(getWsAddress()) - .disableAutoConnect() + .withPolicy(ReconnectionPolicy.MANUAL) .build()) { wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); @@ -113,7 +163,7 @@ void throwsExceptionWhenResponseTimeoutAndCleanHandler() { try (val wsProvider = WsProvider.builder() .setEndpoint(getWsAddress()) .setResponseTimeout(responseTimeout, TimeUnit.MILLISECONDS) - .disableAutoConnect() + .withPolicy(ReconnectionPolicy.MANUAL) .build()) { wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); @@ -135,7 +185,7 @@ void throwsExceptionWhenResponseTimeoutAndCleanHandler() { } } - private Map getHandlersOf(WsProvider wsProvider) throws NoSuchFieldException, IllegalAccessException { + private Map getHandlersOf(WsProvider wsProvider) throws NoSuchFieldException, IllegalAccessException { val handlersFields = wsProvider.getClass().getDeclaredField("handlers"); handlersFields.setAccessible(true); diff --git a/transport/src/test/java/com/strategyobject/substrateclient/transport/ws/WsProviderTest.java b/transport/src/test/java/com/strategyobject/substrateclient/transport/ws/WsProviderTest.java index 2591a0ac..d75bcd49 100644 --- a/transport/src/test/java/com/strategyobject/substrateclient/transport/ws/WsProviderTest.java +++ b/transport/src/test/java/com/strategyobject/substrateclient/transport/ws/WsProviderTest.java @@ -30,7 +30,7 @@ class WsProviderTest { void canConnect() { try (val wsProvider = WsProvider.builder() .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() + .withPolicy(ReconnectionPolicy.MANUAL) .build()) { assertDoesNotThrow(() -> wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS)); @@ -55,7 +55,7 @@ void connectReturnsSameFutureWhenCalledMultiple() { void notifiesWhenConnected() { try (val wsProvider = WsProvider.builder() .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() + .withPolicy(ReconnectionPolicy.MANUAL) .build()) { val notified = new AtomicBoolean(); @@ -74,7 +74,7 @@ void notifiesWhenConnected() { void canCancelNotification() { try (val wsProvider = WsProvider.builder() .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() + .withPolicy(ReconnectionPolicy.MANUAL) .build()) { val notified = new AtomicBoolean(); @@ -91,7 +91,7 @@ void canCancelNotification() { void canDisconnect() { try (val wsProvider = WsProvider.builder() .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() + .withPolicy(ReconnectionPolicy.MANUAL) .build()) { wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); @@ -122,7 +122,7 @@ void disconnectReturnsSameFutureWhenCalledMultiple() { void notifiesWhenDisconnected() { try (val wsProvider = WsProvider.builder() .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() + .withPolicy(ReconnectionPolicy.MANUAL) .build()) { wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); @@ -143,7 +143,7 @@ void notifiesWhenDisconnected() { void canSend() { try (val wsProvider = WsProvider.builder() .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() + .withPolicy(ReconnectionPolicy.MANUAL) .build()) { wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); @@ -159,7 +159,7 @@ void canSend() { void canSubscribe() { try (val wsProvider = WsProvider.builder() .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() + .withPolicy(ReconnectionPolicy.MANUAL) .build()) { wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); @@ -183,7 +183,7 @@ void canSubscribe() { void canUnsubscribe() { try (val wsProvider = WsProvider.builder() .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() + .withPolicy(ReconnectionPolicy.MANUAL) .build()) { wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); @@ -210,7 +210,7 @@ void canUnsubscribe() { void sendThrowsRpcExceptions() { try (val wsProvider = WsProvider.builder() .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() + .withPolicy(ReconnectionPolicy.MANUAL) .build()) { wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); @@ -225,7 +225,7 @@ void sendThrowsRpcExceptions() { void supportsSubscriptions() { try (val wsProvider = WsProvider.builder() .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() + .withPolicy(ReconnectionPolicy.MANUAL) .build()) { assertTrue(wsProvider.hasSubscriptions()); @@ -237,7 +237,7 @@ void supportsSubscriptions() { void canReconnectManually() { try (val wsProvider = WsProvider.builder() .setEndpoint(substrate.getWsAddress()) - .disableAutoConnect() + .withPolicy(ReconnectionPolicy.MANUAL) .build()) { wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS); diff --git a/types/build.gradle b/types/build.gradle deleted file mode 100644 index 281f896d..00000000 --- a/types/build.gradle +++ /dev/null @@ -1 +0,0 @@ -dependencies {} \ No newline at end of file diff --git a/types/src/main/java/com/strategyobject/substrateclient/types/FixedBytes.java b/types/src/main/java/com/strategyobject/substrateclient/types/FixedBytes.java deleted file mode 100644 index 1668900c..00000000 --- a/types/src/main/java/com/strategyobject/substrateclient/types/FixedBytes.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.strategyobject.substrateclient.types; - -import com.google.common.base.Preconditions; -import lombok.EqualsAndHashCode; -import lombok.Getter; - -@EqualsAndHashCode -public abstract class FixedBytes { - @Getter - private final byte[] data; - - protected FixedBytes(byte[] data, S size) { - Preconditions.checkNotNull(data); - Preconditions.checkArgument( - data.length == size.getValue(), - "The data size must be %s; received %s.", size.getValue(), data.length); - - this.data = data; - } - - public int getSize() { - return data.length; - } -} diff --git a/types/src/main/java/com/strategyobject/substrateclient/types/Signable.java b/types/src/main/java/com/strategyobject/substrateclient/types/Signable.java deleted file mode 100644 index 1237eb78..00000000 --- a/types/src/main/java/com/strategyobject/substrateclient/types/Signable.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.strategyobject.substrateclient.types; - -import lombok.NonNull; - -public interface Signable { - byte @NonNull [] getBytes(); -}