refactor: final touches for the new client api

This commit is contained in:
ppedziwiatr
2021-08-26 21:11:07 +02:00
parent 354bc2e7db
commit f966e89616
8 changed files with 40 additions and 18 deletions

View File

@@ -47,7 +47,7 @@ async function main() {
const txs = loadTxFromFile(); const txs = loadTxFromFile();
const resumeFromContractTxId = 'YLVpmhSq5JmLltfg6R-5fL04rIRPrlSU22f6RQ6VyYE'; const resumeFromContractTxId = 'YLVpmhSq5JmLltfg6R-5fL04rIRPrlSU22f6RQ6VyYE';
let resumeFrom = true; let resumeFrom = false;
logger.info(`Checking ${txs.length} contracts`); logger.info(`Checking ${txs.length} contracts`);

View File

@@ -1,6 +1,6 @@
{ {
"name": "redstone-smartweave", "name": "redstone-smartweave",
"version": "0.1.0-alpha.1", "version": "0.2.0-alpha.1",
"description": "An implementation of the SmartWeave SDK.", "description": "An implementation of the SmartWeave SDK.",
"main": "lib/index.js", "main": "lib/index.js",
"types": "lib/index.d.ts", "types": "lib/index.d.ts",
@@ -15,6 +15,7 @@
"preversion": "yarn lint && yarn build", "preversion": "yarn lint && yarn build",
"version": "yarn format && git add -A src", "version": "yarn format && git add -A src",
"postversion": "git push && git push --tags", "postversion": "git push && git push --tags",
"yalc:publish": "yarn build && yalc publish --push",
"test": "jest" "test": "jest"
}, },
"license": "MIT", "license": "MIT",

View File

@@ -80,17 +80,21 @@ export class HandlerBasedContract<State> implements Contract<State> {
const evalStateResult = await stateEvaluator.eval(executionContext, []); const evalStateResult = await stateEvaluator.eval(executionContext, []);
logger.debug('Creating new intraction for view state');
const interaction: ContractInteraction<Input> = { const interaction: ContractInteraction<Input> = {
input, input,
caller: executionContext.caller caller: executionContext.caller
}; };
logger.trace('interaction', interaction);
const handler = (await this.smartweave.executorFactory.create( const handler = (await this.smartweave.executorFactory.create(
executionContext.contractDefinition executionContext.contractDefinition
)) as HandlerApi<State>; )) as HandlerApi<State>;
// TODO: what is the best way to create a transaction in this case? // TODO: what is the best way to create a transaction in this case?
return await handler.handle<Input, View>( const handleResult = await handler.handle<Input, View>(
executionContext, executionContext,
evalStateResult.state, evalStateResult.state,
interaction, interaction,
@@ -107,6 +111,15 @@ export class HandlerBasedContract<State> implements Contract<State> {
}, },
[] []
); );
if (handleResult.type !== 'ok') {
logger.fatal('Error while interacting with contract', {
type: handleResult.type,
error: handleResult.errorMessage
});
}
return handleResult;
} }
async viewStateForTx<Input, View>( async viewStateForTx<Input, View>(

View File

@@ -23,7 +23,7 @@ export class SmartWeaveNodeFactory extends SmartWeaveWebFactory {
* Returns a {@link SmartWeave} that is using file-based cache for {@link StateEvaluator} layer * Returns a {@link SmartWeave} that is using file-based cache for {@link StateEvaluator} layer
* and mem cache for the rest. * and mem cache for the rest.
*/ */
static fileCacheClient(arweave: Arweave, cacheBasePath?: string): SmartWeave { static fileCached(arweave: Arweave, cacheBasePath?: string): SmartWeave {
const definitionLoader = new ContractDefinitionLoader(arweave, new MemCache()); const definitionLoader = new ContractDefinitionLoader(arweave, new MemCache());
const interactionsLoader = new CacheableContractInteractionsLoader( const interactionsLoader = new CacheableContractInteractionsLoader(

View File

@@ -20,6 +20,7 @@ import { BsonFileBlockHeightSwCache, MemBlockHeightSwCache, MemCache } from '@sm
/** /**
* A factory that simplifies the process of creating different versions of {@link SmartWeave}. * A factory that simplifies the process of creating different versions of {@link SmartWeave}.
* All versions use the {@link Evolve} plugin. * All versions use the {@link Evolve} plugin.
* SmartWeave instances created by this factory can be safely used in a web environment.
*/ */
export class SmartWeaveWebFactory { export class SmartWeaveWebFactory {
/** /**
@@ -52,9 +53,9 @@ export class SmartWeaveWebFactory {
/** /**
* Returns a {@link SmartWeave} that (yup, you've guessed it!) does not use any caches. * Returns a {@link SmartWeave} that (yup, you've guessed it!) does not use any caches.
* This one is gonna be slooow... * This one is gonna be slooow!
*/ */
static noCacheClient(arweave: Arweave): SmartWeave { static nonCached(arweave: Arweave): SmartWeave {
const definitionLoader = new ContractDefinitionLoader(arweave); const definitionLoader = new ContractDefinitionLoader(arweave);
const interactionsLoader = new ContractInteractionsLoader(arweave); const interactionsLoader = new ContractInteractionsLoader(arweave);
const executorFactory = new HandlerExecutorFactory(arweave); const executorFactory = new HandlerExecutorFactory(arweave);

View File

@@ -59,14 +59,14 @@ export class DefaultStateEvaluator implements StateEvaluator {
executionContext.contractDefinition executionContext.contractDefinition
)) as HandlerApi<State>; )) as HandlerApi<State>;
logger.debug( logger.trace(
'missingInteractions', 'missingInteractions',
missingInteractions.map((int) => { missingInteractions.map((int) => {
return int.node.id; return int.node.id;
}) })
); );
logger.debug('Init state', JSON.stringify(baseState.state)); logger.trace('Init state', JSON.stringify(baseState.state));
for (const missingInteraction of missingInteractions) { for (const missingInteraction of missingInteractions) {
logger.debug( logger.debug(
@@ -125,11 +125,11 @@ export class DefaultStateEvaluator implements StateEvaluator {
private logResult<State>(result: InteractionResult<State, unknown>, currentTx: GQLNodeInterface) { private logResult<State>(result: InteractionResult<State, unknown>, currentTx: GQLNodeInterface) {
if (result.type === 'exception') { if (result.type === 'exception') {
logger.error(`${result.result}`); logger.error(`${result.errorMessage}`);
logger.error(`Executing of interaction: ${currentTx.id} threw exception.`); logger.error(`Executing of interaction: ${currentTx.id} threw exception.`);
} }
if (result.type === 'error') { if (result.type === 'error') {
logger.error(`${result.result}`); logger.error(`${result.errorMessage}`);
logger.error(`Executing of interaction: ${currentTx.id} returned error.`); logger.error(`Executing of interaction: ${currentTx.id} returned error.`);
} }
} }

View File

@@ -58,7 +58,7 @@ export class HandlerExecutorFactory implements ExecutorFactory<HandlerApi<unknow
const handler = contractFunction(swGlobal, BigNumber, clarity) as HandlerFunction<State, Input, Result>; const handler = contractFunction(swGlobal, BigNumber, clarity) as HandlerFunction<State, Input, Result>;
const stateCopy = JSON.parse(JSON.stringify(state)); const stateCopy = JSON.parse(JSON.stringify(state));
swGlobal._activeTx = interactionTx; swGlobal._activeTx = interactionTx;
logger.debug(`SmartWeave.contract.id: ${swGlobal.contract.id}`, swGlobal.contract.id); logger.debug(`SmartWeave.contract.id:`, swGlobal.contract.id);
self.assignReadContractState<Input, State>(swGlobal, contractDefinition, executionContext, currentTx); self.assignReadContractState<Input, State>(swGlobal, contractDefinition, executionContext, currentTx);
self.assignViewContractState<Input, State>(swGlobal, contractDefinition, executionContext); self.assignViewContractState<Input, State>(swGlobal, contractDefinition, executionContext);
@@ -80,14 +80,20 @@ export class HandlerExecutorFactory implements ExecutorFactory<HandlerApi<unknow
case 'ContractError': case 'ContractError':
return { return {
type: 'error', type: 'error',
result: err.message, errorMessage: err.message,
state state,
// note: previous version was writing error message to a "result" field,
// which fucks-up the HandlerResult type definition -
// HandlerResult.result had to be declared as 'Result | string' - and that led to a poor dev exp.
// TODO: this might be breaking change!
result: null
}; };
default: default:
return { return {
type: 'exception', type: 'exception',
result: `${(err && err.stack) || (err && err.message)}`, errorMessage: `${(err && err.stack) || (err && err.message)}`,
state state,
result: null
}; };
} }
} }
@@ -180,12 +186,13 @@ export type HandlerFunction<State, Input, Result> = (
// TODO: change to XOR between result and state? // TODO: change to XOR between result and state?
export type HandlerResult<State, Result> = { export type HandlerResult<State, Result> = {
result: string | Result; // this really sucks, but has to be declared this way to be backwards compatbile result: Result;
state: State; state: State;
}; };
export type InteractionResult<State, Result> = HandlerResult<State, Result> & { export type InteractionResult<State, Result> = HandlerResult<State, Result> & {
type: 'ok' | 'error' | 'exception'; type: 'ok' | 'error' | 'exception';
errorMessage?: string;
}; };
export type ContractInteraction<Input> = { export type ContractInteraction<Input> = {

View File

@@ -4,8 +4,8 @@ import { LogLevel, RedStoneLogger } from '../RedStoneLogger';
export const defaultLoggerOptions: ISettingsParam = { export const defaultLoggerOptions: ISettingsParam = {
displayFunctionName: false, displayFunctionName: false,
displayFilePath: 'hideNodeModulesOnly', displayFilePath: 'hidden',
displayLoggerName: false, displayLoggerName: true,
dateTimeTimezone: Intl.DateTimeFormat().resolvedOptions().timeZone, dateTimeTimezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
minLevel: 'debug' minLevel: 'debug'
}; };