feat: extending builders API to allow to customize predefined SmartWeave instances

This commit is contained in:
ppedziwiatr
2021-08-31 14:56:16 +02:00
committed by Piotr Pędziwiatr
parent e52925da6f
commit cd0f24b10a
21 changed files with 81 additions and 49 deletions

View File

@@ -22,9 +22,9 @@ To further improve contract state evaluation time, one can additionally use AWS
- [Installation and import](#installation-and-import)
- [Examples](#examples)
- [Source code structure](#source-code-structure)
- [core package](#core-package)
- [contract package](#contract-package)
- [cache package](#cache-package)
- [core package](#core-package)
- [plugins package](#plugins-package)
- [legacy package](#legacy-package)
- [logger package](#logger-package)
@@ -51,22 +51,9 @@ Please follow instructions in its README.md (and detail-ish comments in the exam
### Source code structure
SDK's source code is divided into few main modules.
#### Contract package
Code located in the `contract` package contains base contract interface - `Contract` and its
"reference" implementation - `HandlerBasedContract` - that allows to interact with contracts.
To connect to a contract, first an instance of the `SmartWeave` must be created.
This package contains `SmartWeave` factories that supply some most common configurations (e.g. cached or non-cached).
Refer the TSDocs for more information.
#### Cache package
Code located in the `cache` package contains base interfaces - `SwCache` and `BlockHeightSwCache`
and some example implementations. These caches can be used while configuring `SmartWeave`
instance - to greatly improve processing speed (i.e. contract's state evaluation) .
Refer the TSDocs for more information.
#### Core package
Code located in the `core` package contains all the main modules of the reference SDK v2 implementation.
These modules are used to create instances of `SmartWeave`.
These modules are used to create instances of `SmartWeave` - main class that allows to connect to contracts.
There are currently 5 core interfaces:
1. `DefinitionLoader` - it is responsible for loading contract's definition (i.e. its source code, initial state, etc.)
Its reference implementation is `ContractDefinitionLoader`.
@@ -87,6 +74,18 @@ Additionally, the core package contains the definition of all the tags used by t
All interfaces and implementations are further described in TSDocs.
#### Contract package
Code located in the `contract` package contains base contract interface - `Contract` and its
"reference" implementation - `HandlerBasedContract` - that allows to interact with contracts.
To connect to a contract, first an instance of the `SmartWeave` must be created.
Refer the TSDocs for more information.
#### Cache package
Code located in the `cache` package contains base interfaces - `SwCache` and `BlockHeightSwCache`
and some example implementations. These caches can be used while configuring `SmartWeave`
instance - to greatly improve processing speed (i.e. contract's state evaluation) .
Refer the TSDocs for more information.
#### Plugins package
This package contains some example extensions to base implementation, adding features like "Evolve", caching
capabilities to `InteractionsLoader`, `ExecutorFactory` and `StateEvaluator`, etc.

View File

@@ -16,7 +16,7 @@ async function main() {
const logger = LoggerFactory.INST.create(__filename);
const smartWeave = SmartWeaveNodeFactory.memCached(arweave);
const contractTxId = 'SJ3l7474UHh3Dw6dWVT1bzsJ-8JvOewtGoDdOecWIZo';
const contractTxId = 'YLVpmhSq5JmLltfg6R-5fL04rIRPrlSU22f6RQ6VyYE';
// Kyve:
// C_1uo08qRuQAeDi9Y1I8fkaWYUC9IWkOrKDNe9EphJo
// OFD4GqQcqp-Y_Iqh8DN_0s3a_68oMvvnekeOEu_a45I

View File

@@ -1,6 +1,6 @@
export * from './Contract';
export * from './HandlerBasedContract';
export * from './web/SmartWeaveWebFactory';
export * from './node/SmartWeaveNodeFactory';
export * from './SmartWeave';
export * from './SmartWeaveBuilder';
export * from '../core/web/SmartWeaveWebFactory';
export * from '../core/node/SmartWeaveNodeFactory';
export * from '../core/SmartWeave';
export * from '../core/SmartWeaveBuilder';

View File

@@ -1,2 +0,0 @@
// TODO ;-)
// ...though there isn't that much to change/fix from the current version.

View File

@@ -23,7 +23,7 @@ export class SmartWeave {
readonly definitionLoader: DefinitionLoader,
readonly interactionsLoader: InteractionsLoader,
readonly interactionsSorter: InteractionsSorter,
readonly executorFactory: ExecutorFactory<HandlerApi<unknown>>, // TODO: really struggling with TS generics here...
readonly executorFactory: ExecutorFactory<HandlerApi<unknown>>,
readonly stateEvaluator: StateEvaluator
) {}

View File

@@ -1,5 +1,6 @@
import Arweave from 'arweave';
import {
DebuggableExecutorFactory,
DefinitionLoader,
ExecutorFactory,
HandlerApi,
@@ -43,6 +44,14 @@ export class SmartWeaveBuilder {
return this;
}
public overwriteSource(sourceCode: { [key: string]: string }): SmartWeave {
if (this._executorFactory == null) {
throw new Error('Set base ExecutorFactory first');
}
this._executorFactory = new DebuggableExecutorFactory(this._executorFactory, sourceCode);
return this.build();
}
build() {
return new SmartWeave(
this._arweave,

View File

@@ -1,16 +1,16 @@
export * from './DefinitionLoader';
export * from './modules/DefinitionLoader';
export * from './ExecutionContextModifier';
export * from './ExecutorFactory';
export * from './InteractionsLoader';
export * from './InteractionsSorter';
export * from './StateEvaluator';
export * from './modules/ExecutorFactory';
export * from './modules/InteractionsLoader';
export * from './modules/InteractionsSorter';
export * from './modules/StateEvaluator';
export * from './SmartWeaveTags';
export * from './ExecutionContext';
export * from './ContractDefinition';
export * from './impl/BlockHeightInteractionsSorter';
export * from './impl/ContractDefinitionLoader';
export * from './impl/ContractInteractionsLoader';
export * from './impl/DefaultStateEvaluator';
export * from './impl/HandlerExecutorFactory';
export * from './impl/LexicographicalInteractionsSorter';
export * from './modules/impl/BlockHeightInteractionsSorter';
export * from './modules/impl/ContractDefinitionLoader';
export * from './modules/impl/ContractInteractionsLoader';
export * from './modules/impl/DefaultStateEvaluator';
export * from './modules/impl/HandlerExecutorFactory';
export * from './modules/impl/LexicographicalInteractionsSorter';

View File

@@ -1,4 +1,10 @@
import { Contract, HandlerBasedContract, SmartWeave, SmartWeaveWebFactory } from '@smartweave/contract';
import {
Contract,
HandlerBasedContract,
SmartWeave,
SmartWeaveBuilder,
SmartWeaveWebFactory
} from '@smartweave/contract';
import Arweave from 'arweave';
import {
ContractDefinitionLoader,
@@ -20,10 +26,18 @@ import { BsonFileBlockHeightSwCache, MemBlockHeightSwCache, MemCache } from '@sm
*/
export class SmartWeaveNodeFactory extends SmartWeaveWebFactory {
/**
* Returns a {@link SmartWeave} that is using file-based cache for {@link StateEvaluator} layer
* Returns a fully configured {@link SmartWeave} that is using file-based cache for {@link StateEvaluator} layer
* and mem cache for the rest.
*/
static fileCached(arweave: Arweave, cacheBasePath?: string): SmartWeave {
return this.fileCachedBased(arweave, cacheBasePath).build();
}
/**
* Returns a preconfigured, fileCached {@link SmartWeaveBuilder}, that allows for customization of the SmartWeave instance.
* Use {@link SmartWeaveBuilder.build()} to finish the configuration.
*/
static fileCachedBased(arweave: Arweave, cacheBasePath?: string): SmartWeaveBuilder {
const definitionLoader = new ContractDefinitionLoader(arweave, new MemCache());
const interactionsLoader = new CacheableContractInteractionsLoader(
@@ -44,7 +58,6 @@ export class SmartWeaveNodeFactory extends SmartWeaveWebFactory {
.setInteractionsLoader(interactionsLoader)
.setInteractionsSorter(interactionsSorter)
.setExecutorFactory(executorFactory)
.setStateEvaluator(stateEvaluator)
.build();
.setStateEvaluator(stateEvaluator);
}
}

View File

@@ -1,5 +1,5 @@
import Arweave from 'arweave';
import { HandlerBasedContract, Contract, SmartWeave } from '@smartweave/contract';
import { HandlerBasedContract, Contract, SmartWeave, SmartWeaveBuilder } from '@smartweave/contract';
import {
CacheableContractInteractionsLoader,
CacheableExecutorFactory,
@@ -24,9 +24,17 @@ import { BsonFileBlockHeightSwCache, MemBlockHeightSwCache, MemCache } from '@sm
*/
export class SmartWeaveWebFactory {
/**
* Returns a {@link SmartWeave} that is using mem cache for all layers.
* Returns a fully configured {@link SmartWeave} that is using mem cache for all layers.
*/
static memCached(arweave: Arweave): SmartWeave {
return this.memCachedBased(arweave).build();
}
/**
* Returns a preconfigured, memCached {@link SmartWeaveBuilder}, that allows for customization of the SmartWeave instance.
* Use {@link SmartWeaveBuilder.build()} to finish the configuration.
*/
static memCachedBased(arweave: Arweave): SmartWeaveBuilder {
const definitionLoader = new ContractDefinitionLoader(arweave, new MemCache());
const interactionsLoader = new CacheableContractInteractionsLoader(
@@ -47,15 +55,22 @@ export class SmartWeaveWebFactory {
.setInteractionsLoader(interactionsLoader)
.setInteractionsSorter(interactionsSorter)
.setExecutorFactory(executorFactory)
.setStateEvaluator(stateEvaluator)
.build();
.setStateEvaluator(stateEvaluator);
}
/**
* Returns a {@link SmartWeave} that (yup, you've guessed it!) does not use any caches.
* This one is gonna be slooow!
* Returns a fully configured, nonCached {@link SmartWeave}.
*/
static nonCached(arweave: Arweave): SmartWeave {
return this.nonCachedBased(arweave).build();
}
/**
* Returns a preconfigured {@link SmartWeave} that (yup, you've guessed it!) does not use any caches.
* This one is gonna be slooow!
* Use {@link SmartWeaveBuilder.build()} to finish the configuration.
*/
static nonCachedBased(arweave: Arweave): SmartWeaveBuilder {
const definitionLoader = new ContractDefinitionLoader(arweave);
const interactionsLoader = new ContractInteractionsLoader(arweave);
const executorFactory = new HandlerExecutorFactory(arweave);
@@ -67,7 +82,6 @@ export class SmartWeaveWebFactory {
.setInteractionsLoader(interactionsLoader)
.setInteractionsSorter(interactionsSorter)
.setExecutorFactory(executorFactory)
.setStateEvaluator(stateEvaluator)
.build();
.setStateEvaluator(stateEvaluator);
}
}

View File

@@ -10,10 +10,9 @@ import { ContractDefinition, ExecutorFactory } from '@smartweave/core';
export class DebuggableExecutorFactory<Api> implements ExecutorFactory<Api> {
constructor(
private readonly baseImplementation: ExecutorFactory<Api>,
private readonly sourceCode: { [key: string]: string }
) {
// contract source code before default "normalization"
}
private readonly sourceCode: { [key: string]: string }
) {}
async create<State>(contractDefinition: ContractDefinition<State>): Promise<Api> {
if (Object.prototype.hasOwnProperty.call(this.sourceCode, contractDefinition.txId)) {