Compare commits
2 Commits
e9025efa22
...
186b719a94
| Author | SHA1 | Date | |
|---|---|---|---|
| 186b719a94 | |||
| 748cb6f8f5 |
@ -4,4 +4,4 @@ NPM_PASSWORD=
|
|||||||
# This is needed when working with WASM modules (nodeLinker: node-modules is mandatory)
|
# This is needed when working with WASM modules (nodeLinker: node-modules is mandatory)
|
||||||
NODE_OPTIONS="--experimental-wasm-modules --no-warnings=ExperimentalWarning --max-old-space-size=8192"
|
NODE_OPTIONS="--experimental-wasm-modules --no-warnings=ExperimentalWarning --max-old-space-size=8192"
|
||||||
|
|
||||||
REGISTRATION_PROFILE=devnet
|
REGISTRATION_PROFILE=test
|
||||||
|
|||||||
@ -47,7 +47,7 @@
|
|||||||
"@coinweb/self-register": "0.1.3",
|
"@coinweb/self-register": "0.1.3",
|
||||||
"@coinweb/claims-client": "0.1.6-debug",
|
"@coinweb/claims-client": "0.1.6-debug",
|
||||||
"@coinweb/contract-kit": "0.2.6",
|
"@coinweb/contract-kit": "0.2.6",
|
||||||
"@coinweb/testing-sdk": "0.0.9-remote",
|
"@coinweb/testing-sdk": "0.0.10-mutex",
|
||||||
"@coinweb/minimal-sdk": "1.2.21"
|
"@coinweb/minimal-sdk": "1.2.21"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@ -9,5 +9,5 @@ export enum PUBLIC_METHODS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const FEE = {
|
export const FEE = {
|
||||||
ADD_WORD: 100000n,
|
ADD_WORD: 10000000n,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -3,7 +3,8 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yarn g:tsc -p tsconfig.build.json",
|
"clean": "rm -rf dist",
|
||||||
|
"build": "yarn clean && yarn g:tsc -p tsconfig.build.json",
|
||||||
"dev": "yarn g:tsc -p tsconfig.build.json --watch",
|
"dev": "yarn g:tsc -p tsconfig.build.json --watch",
|
||||||
"lint": "yarn g:lint .",
|
"lint": "yarn g:lint .",
|
||||||
"publish:lib": "node scripts/publish.js"
|
"publish:lib": "node scripts/publish.js"
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import { CwebTake } from '@coinweb/contract-kit/dist/types/operations/take';
|
|||||||
import { getCallParameters, getContractIssuer } from 'lib/onchain';
|
import { getCallParameters, getContractIssuer } from 'lib/onchain';
|
||||||
|
|
||||||
import { ExecutorMethodArgs, ResolvedOp } from '../../types';
|
import { ExecutorMethodArgs, ResolvedOp } from '../../types';
|
||||||
import { pushAwaitedTask } from '../promisifiedFeatures';
|
import { pushAwaitedTask } from '../runtime';
|
||||||
|
|
||||||
import { extractOps } from './extractOps';
|
import { extractOps } from './extractOps';
|
||||||
|
|
||||||
|
|||||||
@ -112,7 +112,7 @@ export const extractOps = ({
|
|||||||
throw new Error('Wrong mutex unlock result');
|
throw new Error('Wrong mutex unlock result');
|
||||||
}
|
}
|
||||||
|
|
||||||
extractedOps.push({ SlotOp: { ok: true } });
|
extractedOps.push({ UnlockOp: 0 });
|
||||||
|
|
||||||
i += 2;
|
i += 2;
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@ -1,69 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
import { Context, NewTx, getMethodArguments, isSelfCall } from '@coinweb/contract-kit';
|
|
||||||
|
|
||||||
import { Task } from '../types';
|
|
||||||
|
|
||||||
import { context, getRawContext, handleContext } from './context';
|
|
||||||
import { getAwaitedTasks } from './promisifiedFeatures';
|
|
||||||
import { pushResolvedOp } from './promisifiedFeatures/runtime/resolvedOps';
|
|
||||||
import { constructTx } from './utils';
|
|
||||||
|
|
||||||
let abortExecution: ((result: { isFullyExecuted: boolean; awaitedTasks: Task[] }) => void) | null = null;
|
|
||||||
|
|
||||||
export const executor = (method: (...args: any[]) => Promise<void>) => {
|
|
||||||
return async (ctx: Context): Promise<NewTx[]> => {
|
|
||||||
console.log('executor-start >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>');
|
|
||||||
const shouldRestart = handleContext(ctx);
|
|
||||||
pushResolvedOp(context.ops);
|
|
||||||
|
|
||||||
if (getMethodArguments(getRawContext()).length > 2 && !isSelfCall(ctx)) {
|
|
||||||
throw new Error('Wrong contract call, check the call arguments');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldRestart) {
|
|
||||||
const awaitedTasks = getAwaitedTasks();
|
|
||||||
|
|
||||||
return constructTx(awaitedTasks, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
const execution = new Promise<{ isFullyExecuted: boolean; awaitedTasks: Task[] }>((resolve, reject) => {
|
|
||||||
abortExecution = resolve;
|
|
||||||
|
|
||||||
method(...context.initialArgs).then(
|
|
||||||
() => {
|
|
||||||
console.log('<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< executor-resolved');
|
|
||||||
const awaitedTasks = getAwaitedTasks();
|
|
||||||
resolve({ isFullyExecuted: true, awaitedTasks });
|
|
||||||
},
|
|
||||||
(error) => {
|
|
||||||
console.log(' <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<executor-rejected');
|
|
||||||
console.log(error);
|
|
||||||
reject(error);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
//@ts-expect-error
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
||||||
os.setTimeout(() => {
|
|
||||||
const awaitedTasks = getAwaitedTasks();
|
|
||||||
abortExecution?.({ isFullyExecuted: false, awaitedTasks });
|
|
||||||
}, 0);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { isFullyExecuted, awaitedTasks } = await execution;
|
|
||||||
|
|
||||||
return constructTx(awaitedTasks, isFullyExecuted);
|
|
||||||
} catch (error) {
|
|
||||||
console.log('<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< executor-error');
|
|
||||||
console.log((error as Error).message);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const stopExecution = () => {
|
|
||||||
console.log('stopExecution');
|
|
||||||
const awaitedTasks = getAwaitedTasks();
|
|
||||||
abortExecution?.({ isFullyExecuted: false, awaitedTasks });
|
|
||||||
};
|
|
||||||
@ -1,8 +1,10 @@
|
|||||||
import { Task } from '../../../types';
|
import { getAwaitedTasks } from '../../runtime';
|
||||||
|
|
||||||
import { prepareTx } from './prepareTxs';
|
import { prepareTx } from './prepareTxs';
|
||||||
|
|
||||||
export const constructTx = (awaitedTasks: Task[], isFullyExecuted: boolean) => {
|
export const constructTx = (isFullyExecuted: boolean) => {
|
||||||
|
const awaitedTasks = getAwaitedTasks();
|
||||||
|
|
||||||
const { calls, txFee } = prepareTx({ awaitedTasks, isFullyExecuted, txFee: 0n });
|
const { calls, txFee } = prepareTx({ awaitedTasks, isFullyExecuted, txFee: 0n });
|
||||||
|
|
||||||
const { txs } = prepareTx({ awaitedTasks, isFullyExecuted, txFee, callsCount: calls });
|
const { txs } = prepareTx({ awaitedTasks, isFullyExecuted, txFee, callsCount: calls });
|
||||||
@ -22,8 +22,8 @@ import {
|
|||||||
isPreparedStoreOp,
|
isPreparedStoreOp,
|
||||||
isPreparedTakeOp,
|
isPreparedTakeOp,
|
||||||
isPreparedUnlockOp,
|
isPreparedUnlockOp,
|
||||||
} from '../typeGuards';
|
} from '../../utils/opTypeGuards';
|
||||||
import { uuid } from '../uuid';
|
import { uuid } from '../../utils/uuid';
|
||||||
|
|
||||||
export const prepareInThreadTxs = ({
|
export const prepareInThreadTxs = ({
|
||||||
cwebPerCall,
|
cwebPerCall,
|
||||||
@ -160,11 +160,12 @@ export const prepareInThreadTxs = ({
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case isPreparedUnlockOp(op): {
|
case isPreparedUnlockOp(op): {
|
||||||
|
console.log('prepareInThreadTxs >>> unlockOp');
|
||||||
const { callInfo, fee, ops } = constructUnlockCall(
|
const { callInfo, fee, ops } = constructUnlockCall(
|
||||||
context.issuer,
|
context.issuer,
|
||||||
op.UnlockOp.lockId,
|
op.UnlockOp.lockId,
|
||||||
op.UnlockOp.timestamp,
|
op.UnlockOp.timestamp,
|
||||||
false
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
childCalls.push({ callInfo });
|
childCalls.push({ callInfo });
|
||||||
@ -194,6 +195,9 @@ export const prepareInThreadTxs = ({
|
|||||||
childCalls.push({ callInfo });
|
childCalls.push({ callInfo });
|
||||||
txFee += fee;
|
txFee += fee;
|
||||||
|
|
||||||
|
console.log(txFee);
|
||||||
|
console.log(context.funds.availableCweb);
|
||||||
|
|
||||||
callArgs.push(...ops);
|
callArgs.push(...ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,6 +210,7 @@ export const prepareInThreadTxs = ({
|
|||||||
|
|
||||||
if ('StoreOp' in latestCallArg && (latestCallArg.StoreOp.key.first_part as [string])[0] === resultKey) {
|
if ('StoreOp' in latestCallArg && (latestCallArg.StoreOp.key.first_part as [string])[0] === resultKey) {
|
||||||
//SAVE RESULT CLAIMS
|
//SAVE RESULT CLAIMS
|
||||||
|
console.log('SAVE RESULT CLAIMS');
|
||||||
if (callArgs.length > 1) {
|
if (callArgs.length > 1) {
|
||||||
throw new Error('Unexpected count of result ops');
|
throw new Error('Unexpected count of result ops');
|
||||||
}
|
}
|
||||||
@ -221,10 +226,12 @@ export const prepareInThreadTxs = ({
|
|||||||
|
|
||||||
const cwebToStore = availableCweb + storedCweb - BigInt(takeOps.length) * 100n - 500n;
|
const cwebToStore = availableCweb + storedCweb - BigInt(takeOps.length) * 100n - 500n;
|
||||||
|
|
||||||
|
console.log('cwebToStore: ', cwebToStore);
|
||||||
|
|
||||||
resultOps.push(
|
resultOps.push(
|
||||||
constructFundsClaimStore(context.parentId, cwebToStore),
|
passCwebFrom(context.issuer, availableCweb),
|
||||||
...takeOps,
|
...takeOps,
|
||||||
passCwebFrom(context.issuer, availableCweb)
|
constructFundsClaimStore(context.parentId, cwebToStore)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,6 +242,8 @@ export const prepareInThreadTxs = ({
|
|||||||
txFee += 800n + outThreadFee + BigInt(takeOps.length) * 100n;
|
txFee += 800n + outThreadFee + BigInt(takeOps.length) * 100n;
|
||||||
callsPrepared++;
|
callsPrepared++;
|
||||||
|
|
||||||
|
console.log('provided cweb: ', cwebPerCall - txFee + storedCweb);
|
||||||
|
|
||||||
returnTxs.push(
|
returnTxs.push(
|
||||||
constructContinueTx(
|
constructContinueTx(
|
||||||
getRawContext(),
|
getRawContext(),
|
||||||
@ -18,7 +18,7 @@ import {
|
|||||||
isPreparedStoreOp,
|
isPreparedStoreOp,
|
||||||
isPreparedTakeOp,
|
isPreparedTakeOp,
|
||||||
isPreparedUnlockOp,
|
isPreparedUnlockOp,
|
||||||
} from '../typeGuards';
|
} from '../../utils/opTypeGuards';
|
||||||
|
|
||||||
export const prepareOutThreadTxs = ({
|
export const prepareOutThreadTxs = ({
|
||||||
ops,
|
ops,
|
||||||
@ -95,6 +95,7 @@ export const prepareOutThreadTxs = ({
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case isPreparedUnlockOp(op): {
|
case isPreparedUnlockOp(op): {
|
||||||
|
console.log('prepareOutThreadTxs >>> unlockOp');
|
||||||
const { callInfo, fee } = constructUnlockCall(context.issuer, op.UnlockOp.lockId, op.UnlockOp.timestamp, false);
|
const { callInfo, fee } = constructUnlockCall(context.issuer, op.UnlockOp.lockId, op.UnlockOp.timestamp, false);
|
||||||
|
|
||||||
preparedCalls.push({ callInfo });
|
preparedCalls.push({ callInfo });
|
||||||
42
packages/cwait/src/onchain/executor/executor.ts
Normal file
42
packages/cwait/src/onchain/executor/executor.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
import { Context, NewTx, getMethodArguments, isSelfCall } from '@coinweb/contract-kit';
|
||||||
|
|
||||||
|
import { context, getRawContext, handleContext } from '../context';
|
||||||
|
import { execLoop, setNextExec, stopExecution } from '../runtime';
|
||||||
|
import { pushResolvedOp } from '../runtime/resolvedOps';
|
||||||
|
|
||||||
|
import { constructTx } from './constructTx';
|
||||||
|
|
||||||
|
export const executor = (method: (...args: any[]) => Promise<void>) => {
|
||||||
|
return async (ctx: Context): Promise<NewTx[]> => {
|
||||||
|
console.log('executor-start >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>');
|
||||||
|
const shouldRestart = handleContext(ctx);
|
||||||
|
pushResolvedOp(context.ops);
|
||||||
|
|
||||||
|
if (getMethodArguments(getRawContext()).length > 2 && !isSelfCall(ctx)) {
|
||||||
|
throw new Error('Wrong contract call, check the call arguments');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldRestart) {
|
||||||
|
console.log('<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< executor-finish-restart');
|
||||||
|
return constructTx(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//@ts-expect-error
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||||
|
os.setTimeout(() => {
|
||||||
|
stopExecution();
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
try {
|
||||||
|
setNextExec(() => method(...context.initialArgs));
|
||||||
|
const isFullyExecuted = await execLoop();
|
||||||
|
console.log('<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< executor-finish-end');
|
||||||
|
return constructTx(isFullyExecuted);
|
||||||
|
} catch (error) {
|
||||||
|
console.log((error as Error).message);
|
||||||
|
console.log('<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< executor-error');
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
1
packages/cwait/src/onchain/executor/index.ts
Normal file
1
packages/cwait/src/onchain/executor/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './executor';
|
||||||
@ -2,10 +2,9 @@ import { ContractHandlers as ContractHandlersOrig, SELF_REGISTER_HANDLER_NAME }
|
|||||||
import { selfRegisterHandler } from '@coinweb/self-register';
|
import { selfRegisterHandler } from '@coinweb/self-register';
|
||||||
import { queue } from 'lib/onchain';
|
import { queue } from 'lib/onchain';
|
||||||
|
|
||||||
import { addMethodHandler, ContractHandlers, executeHandler } from '../contract-kit';
|
import { addMethodHandler, ContractHandlers, executeHandler } from '../../../contract-kit';
|
||||||
|
import { executor } from '../../executor';
|
||||||
import { executor } from './executor';
|
import { mutexMethods } from '../../mutex';
|
||||||
import { mutexMethods } from './mutex';
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
export const constructCwebMain = (methods: Record<string, (...args: any[]) => Promise<void>>) => async () => {
|
export const constructCwebMain = (methods: Record<string, (...args: any[]) => Promise<void>>) => async () => {
|
||||||
@ -0,0 +1 @@
|
|||||||
|
export * from './constructCwebMain';
|
||||||
@ -1,12 +1,23 @@
|
|||||||
import { constructStore } from '@coinweb/contract-kit/dist/esm/operations/store';
|
import { constructStore } from '@coinweb/contract-kit/dist/esm/operations/store';
|
||||||
|
|
||||||
import { constructResultClaim } from '../../../claims/result';
|
import { constructResultClaim } from '../../claims/result';
|
||||||
import { stopExecution } from '../../../executor';
|
import { opMarker } from '../../globals/promise';
|
||||||
import { opMarker } from '../../../global';
|
import { setNextExec, stopExecution } from '../../runtime';
|
||||||
import { isResolvedChildOp, isResolvedExecOp, isResolvedSlotOp } from '../../../utils';
|
import {
|
||||||
import { uuid } from '../../../utils';
|
freezeAwaitedTasks,
|
||||||
import { getAwaitedTasksCount, pushAwaitedTask } from '../../runtime/awaitedTasks';
|
getAwaitedTasksCount,
|
||||||
import { getUsedOps, saveUsedOps, shiftResolvedOp } from '../../runtime/resolvedOps';
|
pushAwaitedTask,
|
||||||
|
unfreezeAwaitedTasks,
|
||||||
|
} from '../../runtime/awaitedTasks';
|
||||||
|
import {
|
||||||
|
freezeResolvedOps,
|
||||||
|
getUsedOps,
|
||||||
|
saveUsedOps,
|
||||||
|
shiftResolvedOp,
|
||||||
|
unfreezeResolvedOps,
|
||||||
|
} from '../../runtime/resolvedOps';
|
||||||
|
import { isResolvedChildOp, isResolvedExecOp, isResolvedSlotOp } from '../../utils';
|
||||||
|
import { uuid } from '../../utils';
|
||||||
|
|
||||||
let isRootDetected = false;
|
let isRootDetected = false;
|
||||||
|
|
||||||
@ -44,13 +55,24 @@ export const cwait = <TAsyncCallback extends (...args: any[]) => Promise<unknown
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isResolvedExecOp(op)) {
|
if (isResolvedExecOp(op)) {
|
||||||
saveUsedOps();
|
freezeAwaitedTasks();
|
||||||
|
freezeResolvedOps();
|
||||||
|
|
||||||
asyncCallback(...args);
|
setNextExec(async () => {
|
||||||
|
unfreezeAwaitedTasks();
|
||||||
|
unfreezeResolvedOps();
|
||||||
|
|
||||||
if (!getAwaitedTasksCount()) {
|
saveUsedOps();
|
||||||
pushAwaitedTask(constructStore(constructResultClaim(op.ExecOp.id, getUsedOps())));
|
|
||||||
}
|
await asyncCallback(...args);
|
||||||
|
|
||||||
|
if (!getAwaitedTasksCount()) {
|
||||||
|
console.log('push result claim');
|
||||||
|
|
||||||
|
pushAwaitedTask(constructStore(constructResultClaim(op.ExecOp.id, getUsedOps())));
|
||||||
|
stopExecution();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
stopExecution();
|
stopExecution();
|
||||||
|
|
||||||
@ -61,7 +83,7 @@ export const cwait = <TAsyncCallback extends (...args: any[]) => Promise<unknown
|
|||||||
return asyncCallback(...args);
|
return asyncCallback(...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error('Read operation not found');
|
throw new Error('Exec or Child operation not found');
|
||||||
}
|
}
|
||||||
}) as TAsyncCallback;
|
}) as TAsyncCallback;
|
||||||
};
|
};
|
||||||
@ -1,3 +1,4 @@
|
|||||||
export * from './cwait';
|
export * from './cwait';
|
||||||
export * from './mutex';
|
export * from './mutex';
|
||||||
export * from './ops';
|
export * from './ops';
|
||||||
|
export * from './constructCwebMain';
|
||||||
@ -1,12 +1,12 @@
|
|||||||
import { getTime } from 'lib/onchain';
|
import { getTime } from 'lib/onchain';
|
||||||
|
|
||||||
import { opMarker } from '../../../global';
|
import { opMarker } from '../../globals/promise';
|
||||||
import { LockedKey } from '../../../mutex';
|
import { LockedKey } from '../../mutex';
|
||||||
import { isResolvedLockOp, isResolvedSlotOp, isResolvedUnlockOp, uuid } from '../../../utils';
|
|
||||||
import { pushAwaitedTask, shiftResolvedOp } from '../../runtime';
|
import { pushAwaitedTask, shiftResolvedOp } from '../../runtime';
|
||||||
|
import { isResolvedLockOp, isResolvedSlotOp, isResolvedUnlockOp, uuid } from '../../utils';
|
||||||
|
|
||||||
const unlock = (lockId: string, timestamp: number) => {
|
const unlock = (lockId: string, timestamp: number) => {
|
||||||
console.log('lockOp');
|
console.log('unlockOp');
|
||||||
let opMarkerValue = false;
|
let opMarkerValue = false;
|
||||||
|
|
||||||
const result = new Promise<void>((resolve, reject) => {
|
const result = new Promise<void>((resolve, reject) => {
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import { BlockFilter, constructBlock, extractBlock } from '@coinweb/contract-kit';
|
import { BlockFilter, constructBlock, extractBlock } from '@coinweb/contract-kit';
|
||||||
|
|
||||||
import { opMarker } from '../../../global';
|
import { opMarker } from '../../globals/promise';
|
||||||
import { isResolvedBlockOp, isResolvedSlotOp } from '../../../utils';
|
import { isResolvedBlockOp, isResolvedSlotOp } from '../../utils';
|
||||||
import { pushAwaitedTask, shiftResolvedOp } from '../../runtime';
|
import { pushAwaitedTask, shiftResolvedOp } from '../../runtime';
|
||||||
|
|
||||||
export const blockOp = (filters: BlockFilter[]) => {
|
export const blockOp = (filters: BlockFilter[]) => {
|
||||||
@ -1,10 +1,10 @@
|
|||||||
import { Claim, ClaimKey, constructRangeRead, extractRead } from '@coinweb/contract-kit';
|
import { Claim, ClaimKey, constructRangeRead, extractRead } from '@coinweb/contract-kit';
|
||||||
import { ClaimRange } from '@coinweb/contract-kit/dist/types/operations/read';
|
import { ClaimRange } from '@coinweb/contract-kit/dist/types/operations/read';
|
||||||
|
|
||||||
import { TypedClaim } from '../../../../types';
|
import { TypedClaim } from '../../../types';
|
||||||
import { context } from '../../../context';
|
import { context } from '../../context';
|
||||||
import { opMarker } from '../../../global';
|
import { opMarker } from '../../globals/promise';
|
||||||
import { isResolvedReadOp, isResolvedSlotOp } from '../../../utils';
|
import { isResolvedReadOp, isResolvedSlotOp } from '../../utils';
|
||||||
import { pushAwaitedTask, shiftResolvedOp } from '../../runtime';
|
import { pushAwaitedTask, shiftResolvedOp } from '../../runtime';
|
||||||
|
|
||||||
export const rangeReadOp = <TClaims extends Claim[] = TypedClaim[]>(
|
export const rangeReadOp = <TClaims extends Claim[] = TypedClaim[]>(
|
||||||
@ -1,10 +1,10 @@
|
|||||||
import { Claim, ClaimKey, constructRead, extractRead } from '@coinweb/contract-kit';
|
import { Claim, ClaimKey, constructRead, extractRead } from '@coinweb/contract-kit';
|
||||||
|
|
||||||
import { TypedClaim } from '../../../../types';
|
import { TypedClaim } from '../../../types';
|
||||||
import { context } from '../../../context';
|
import { context } from '../../context';
|
||||||
import { opMarker } from '../../../global';
|
import { opMarker } from '../../globals/promise';
|
||||||
import { isResolvedReadOp, isResolvedSlotOp } from '../../../utils';
|
|
||||||
import { pushAwaitedTask, shiftResolvedOp } from '../../runtime';
|
import { pushAwaitedTask, shiftResolvedOp } from '../../runtime';
|
||||||
|
import { isResolvedReadOp, isResolvedSlotOp } from '../../utils';
|
||||||
|
|
||||||
export const readOp = <TClaim extends Claim = TypedClaim>(key: ClaimKey) => {
|
export const readOp = <TClaim extends Claim = TypedClaim>(key: ClaimKey) => {
|
||||||
let opMarkerValue = false;
|
let opMarkerValue = false;
|
||||||
@ -22,10 +22,14 @@ export const readOp = <TClaim extends Claim = TypedClaim>(key: ClaimKey) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isResolvedReadOp(op)) {
|
if (!isResolvedReadOp(op)) {
|
||||||
|
console.log(JSON.stringify(op));
|
||||||
|
|
||||||
throw new Error('Read operation not found');
|
throw new Error('Read operation not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
const claim = (extractRead(op)?.[0]?.content ?? null) as TClaim | null;
|
const claim = (extractRead(op)?.[0]?.content ?? null) as TClaim | null;
|
||||||
|
|
||||||
|
console.log('ResolveRead claim: ', claim);
|
||||||
resolve(claim);
|
resolve(claim);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -1,8 +1,8 @@
|
|||||||
import { Claim, constructStore } from '@coinweb/contract-kit';
|
import { Claim, constructStore } from '@coinweb/contract-kit';
|
||||||
import { extractStore } from '@coinweb/contract-kit/dist/esm/operations/store';
|
import { extractStore } from '@coinweb/contract-kit/dist/esm/operations/store';
|
||||||
|
|
||||||
import { opMarker } from '../../../global';
|
import { opMarker } from '../../globals/promise';
|
||||||
import { isResolvedSlotOp, isResolvedStoreOp } from '../../../utils';
|
import { isResolvedSlotOp, isResolvedStoreOp } from '../../utils';
|
||||||
import { pushAwaitedTask, shiftResolvedOp } from '../../runtime';
|
import { pushAwaitedTask, shiftResolvedOp } from '../../runtime';
|
||||||
|
|
||||||
export const storeOp = (claim: Claim, storeCweb?: bigint) => {
|
export const storeOp = (claim: Claim, storeCweb?: bigint) => {
|
||||||
@ -1,8 +1,8 @@
|
|||||||
import { Claim, ClaimKey, constructTake, extractTake } from '@coinweb/contract-kit';
|
import { Claim, ClaimKey, constructTake, extractTake } from '@coinweb/contract-kit';
|
||||||
|
|
||||||
import { TypedClaim } from '../../../../types';
|
import { TypedClaim } from '../../../types';
|
||||||
import { opMarker } from '../../../global';
|
import { opMarker } from '../../globals/promise';
|
||||||
import { isResolvedSlotOp, isResolvedTakeOp } from '../../../utils';
|
import { isResolvedSlotOp, isResolvedTakeOp } from '../../utils';
|
||||||
import { pushAwaitedTask, shiftResolvedOp } from '../../runtime';
|
import { pushAwaitedTask, shiftResolvedOp } from '../../runtime';
|
||||||
|
|
||||||
export const takeOp = <TClaim extends Claim = TypedClaim>(key: ClaimKey) => {
|
export const takeOp = <TClaim extends Claim = TypedClaim>(key: ClaimKey) => {
|
||||||
1
packages/cwait/src/onchain/globals/index.ts
Normal file
1
packages/cwait/src/onchain/globals/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './promise';
|
||||||
@ -1,5 +1,8 @@
|
|||||||
import { markTaskBatch } from './promisifiedFeatures/runtime/awaitedTasks';
|
import { markTaskBatch } from '../runtime/awaitedTasks';
|
||||||
import { getBatchId } from './utils';
|
|
||||||
|
let batchId = 0;
|
||||||
|
|
||||||
|
const getBatchId = () => batchId++;
|
||||||
|
|
||||||
export const opMarker = Symbol('opMarker');
|
export const opMarker = Symbol('opMarker');
|
||||||
|
|
||||||
@ -1,3 +1,3 @@
|
|||||||
export * from './context';
|
import './globals';
|
||||||
export * from './promisifiedFeatures/features';
|
|
||||||
export * from './constructCwebMain';
|
export * from './features';
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { constructContractRef, ContractIssuer } from '@coinweb/contract-kit';
|
|||||||
|
|
||||||
import { constructMutexBlockUnlockClaimTake, constructMutexUnlockBlock } from '../claims';
|
import { constructMutexBlockUnlockClaimTake, constructMutexUnlockBlock } from '../claims';
|
||||||
import { unlockMethodName } from '../methods';
|
import { unlockMethodName } from '../methods';
|
||||||
|
import { unlockFee } from '../settings';
|
||||||
import { MutexUnlockArgs } from '../types';
|
import { MutexUnlockArgs } from '../types';
|
||||||
|
|
||||||
export const constructUnlockCall = (issuer: ContractIssuer, ...[lockId, timestamp, notify]: MutexUnlockArgs) => {
|
export const constructUnlockCall = (issuer: ContractIssuer, ...[lockId, timestamp, notify]: MutexUnlockArgs) => {
|
||||||
@ -13,7 +14,7 @@ export const constructUnlockCall = (issuer: ContractIssuer, ...[lockId, timestam
|
|||||||
methodArgs: [lockId, timestamp] satisfies MutexUnlockArgs,
|
methodArgs: [lockId, timestamp] satisfies MutexUnlockArgs,
|
||||||
},
|
},
|
||||||
contractInfo: {
|
contractInfo: {
|
||||||
providedCweb: 1000n,
|
providedCweb: unlockFee,
|
||||||
authenticated: null,
|
authenticated: null,
|
||||||
},
|
},
|
||||||
contractArgs: [],
|
contractArgs: [],
|
||||||
@ -21,6 +22,6 @@ export const constructUnlockCall = (issuer: ContractIssuer, ...[lockId, timestam
|
|||||||
ops: notify
|
ops: notify
|
||||||
? ([constructMutexUnlockBlock(lockId, issuer), constructMutexBlockUnlockClaimTake(lockId)] as const)
|
? ([constructMutexUnlockBlock(lockId, issuer), constructMutexBlockUnlockClaimTake(lockId)] as const)
|
||||||
: [],
|
: [],
|
||||||
fee: 1200n,
|
fee: unlockFee + (notify ? 1000n : 800n),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { constructContinueTx, constructContractRef, constructTake, Context, passCwebFrom } from '@coinweb/contract-kit';
|
import { constructContinueTx, constructContractRef, constructTake, Context, passCwebFrom } from '@coinweb/contract-kit';
|
||||||
import { getCallParameters, getContractIssuer, getMethodArguments } from 'lib/onchain';
|
import { getCallParameters, getContractIssuer, getMethodArguments } from 'lib/onchain';
|
||||||
|
|
||||||
import { constructMutexLockClaimKey } from '../claims';
|
import { constructMutexBlockUnlockClaimStore, constructMutexLockClaimKey } from '../claims';
|
||||||
import { lockFee } from '../settings';
|
import { lockFee } from '../settings';
|
||||||
import { MutexUnlockArgs } from '../types';
|
import { MutexUnlockArgs } from '../types';
|
||||||
|
|
||||||
@ -16,7 +16,11 @@ export const mutexUnlock = (context: Context) => {
|
|||||||
return [
|
return [
|
||||||
constructContinueTx(
|
constructContinueTx(
|
||||||
context,
|
context,
|
||||||
[passCwebFrom(issuer, availableCweb), constructTake(constructMutexLockClaimKey(lockId, timestamp))],
|
[
|
||||||
|
passCwebFrom(issuer, availableCweb),
|
||||||
|
constructTake(constructMutexLockClaimKey(lockId, timestamp)),
|
||||||
|
constructMutexBlockUnlockClaimStore(lockId),
|
||||||
|
],
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
callInfo: {
|
callInfo: {
|
||||||
|
|||||||
@ -1,2 +0,0 @@
|
|||||||
export * from './runtime';
|
|
||||||
export * from './features';
|
|
||||||
@ -1,8 +1,13 @@
|
|||||||
import { PreparedOp, Task } from '../../../types';
|
import { PreparedOp, Task } from '../../types';
|
||||||
|
|
||||||
const awaitedTasks: Task[] = [];
|
const awaitedTasks: Task[] = [];
|
||||||
|
let isFreezed = false;
|
||||||
|
|
||||||
export const pushAwaitedTask = (op: PreparedOp) => {
|
export const pushAwaitedTask = (op: PreparedOp) => {
|
||||||
|
if (isFreezed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
awaitedTasks.push({ op, batchId: -1 });
|
awaitedTasks.push({ op, batchId: -1 });
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -15,3 +20,11 @@ export const markTaskBatch = (count: number, batchId: number) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getAwaitedTasksCount = () => awaitedTasks.length;
|
export const getAwaitedTasksCount = () => awaitedTasks.length;
|
||||||
|
|
||||||
|
export const freezeAwaitedTasks = () => {
|
||||||
|
isFreezed = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const unfreezeAwaitedTasks = () => {
|
||||||
|
isFreezed = false;
|
||||||
|
};
|
||||||
41
packages/cwait/src/onchain/runtime/execLoop.ts
Normal file
41
packages/cwait/src/onchain/runtime/execLoop.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
let abortExecution: ((isFullyExecuted: boolean) => void) | null = null;
|
||||||
|
|
||||||
|
export const stopExecution = (isFullyExecuted = false) => {
|
||||||
|
console.log('stopExecution');
|
||||||
|
abortExecution?.(isFullyExecuted);
|
||||||
|
};
|
||||||
|
|
||||||
|
type ExecTask = () => Promise<void>;
|
||||||
|
|
||||||
|
let execQueue: ExecTask[] = [];
|
||||||
|
export const setNextExec = (task: ExecTask) => (execQueue = [task]);
|
||||||
|
|
||||||
|
export const execLoop = async (): Promise<boolean> => {
|
||||||
|
const nextExec = execQueue.pop();
|
||||||
|
|
||||||
|
if (nextExec) {
|
||||||
|
const execution = new Promise<boolean>((resolve, reject) => {
|
||||||
|
abortExecution = resolve;
|
||||||
|
|
||||||
|
nextExec().then(
|
||||||
|
() => {
|
||||||
|
resolve(true);
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
console.log(error);
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const isFullyExecuted = await execution;
|
||||||
|
|
||||||
|
if (isFullyExecuted) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return execLoop();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
@ -1,2 +1,3 @@
|
|||||||
export * from './awaitedTasks';
|
export * from './awaitedTasks';
|
||||||
|
export * from './execLoop';
|
||||||
export * from './resolvedOps';
|
export * from './resolvedOps';
|
||||||
@ -1,11 +1,16 @@
|
|||||||
import { ResolvedOp } from '../../../types';
|
import { ResolvedOp } from '../../types';
|
||||||
|
|
||||||
const resolvedOps: ResolvedOp[] = [];
|
const resolvedOps: ResolvedOp[] = [];
|
||||||
|
|
||||||
let usedOps: ResolvedOp[] = [];
|
let usedOps: ResolvedOp[] = [];
|
||||||
let isSavingUsed = false;
|
let isSavingUsed = false;
|
||||||
|
let isFreezed = false;
|
||||||
|
|
||||||
export const pushResolvedOp = (op: ResolvedOp | ResolvedOp[]) => {
|
export const pushResolvedOp = (op: ResolvedOp | ResolvedOp[]) => {
|
||||||
|
if (isFreezed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (Array.isArray(op)) {
|
if (Array.isArray(op)) {
|
||||||
resolvedOps.push(...op);
|
resolvedOps.push(...op);
|
||||||
} else {
|
} else {
|
||||||
@ -15,8 +20,8 @@ export const pushResolvedOp = (op: ResolvedOp | ResolvedOp[]) => {
|
|||||||
|
|
||||||
export const shiftResolvedOp = () => {
|
export const shiftResolvedOp = () => {
|
||||||
const result = {
|
const result = {
|
||||||
isOp: resolvedOps.length > 0,
|
isOp: resolvedOps.length > 0 && !isFreezed,
|
||||||
op: resolvedOps.shift(),
|
op: isFreezed ? undefined : resolvedOps.shift(),
|
||||||
} as
|
} as
|
||||||
| {
|
| {
|
||||||
isOp: true;
|
isOp: true;
|
||||||
@ -31,6 +36,8 @@ export const shiftResolvedOp = () => {
|
|||||||
usedOps.push(result.op);
|
usedOps.push(result.op);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('shiftResolvedOp: ', JSON.stringify(result));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -40,3 +47,11 @@ export const saveUsedOps = () => {
|
|||||||
usedOps = [];
|
usedOps = [];
|
||||||
isSavingUsed = true;
|
isSavingUsed = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const freezeResolvedOps = () => {
|
||||||
|
isFreezed = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const unfreezeResolvedOps = () => {
|
||||||
|
isFreezed = false;
|
||||||
|
};
|
||||||
@ -1,3 +0,0 @@
|
|||||||
let batchId = 0;
|
|
||||||
|
|
||||||
export const getBatchId = () => batchId++;
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
export const getStack = ({ skip = 0 }: { skip?: number } = {}) =>
|
|
||||||
new Error().stack
|
|
||||||
?.split('\n')
|
|
||||||
.slice(2 + skip)
|
|
||||||
.map((line) => {
|
|
||||||
const match = line.match(/at\s+([^\s(]+)/);
|
|
||||||
return match ? match[1] : '';
|
|
||||||
})
|
|
||||||
.filter((name) => name && name !== 'Promise')
|
|
||||||
.join('@') || '';
|
|
||||||
@ -1,5 +1,2 @@
|
|||||||
export * from './batchId';
|
export * from './opTypeGuards';
|
||||||
export * from './callstack';
|
|
||||||
export * from './constructTx';
|
|
||||||
export * from './typeGuards';
|
|
||||||
export * from './uuid';
|
export * from './uuid';
|
||||||
|
|||||||
@ -9,5 +9,5 @@
|
|||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"types": ["vitest/globals"]
|
"types": ["vitest/globals"]
|
||||||
},
|
},
|
||||||
"include": ["**/*.ts", "vitest.*.ts", "__tests__", "scripts/publish.js", "src/onchain/utils"]
|
"include": ["**/*.ts", "vitest.*.ts", "__tests__", "scripts/publish.js", "src/onchain/utils", "src/onchain/executor/constructTx"]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
VITE_API_URL='https://api-cloud.coinweb.io/wallet'
|
VITE_API_URL='https://api-cloud.coinweb.io/wallet'
|
||||||
VITE_EXPLORER_URL='https://explorer.coinweb.io'
|
VITE_EXPLORER_URL='https://explorer.coinweb.io'
|
||||||
|
|
||||||
VITE_CONTRACT_ADDRESS="0xedca91a29553fa2466e89eef02ac06dc49ab68be5e81fa91d05765cab79ec02a"
|
VITE_CONTRACT_ADDRESS="0xc599810e4861b7b1ae25695d58eeef10556fc84f87f72fafa31c0921e86e92be"
|
||||||
|
|||||||
10
yarn.lock
10
yarn.lock
@ -379,16 +379,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@coinweb/testing-sdk@npm:0.0.9-remote":
|
"@coinweb/testing-sdk@npm:0.0.10-mutex":
|
||||||
version: 0.0.9-remote
|
version: 0.0.10-mutex
|
||||||
resolution: "@coinweb/testing-sdk@npm:0.0.9-remote"
|
resolution: "@coinweb/testing-sdk@npm:0.0.10-mutex"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@coinweb/contract-kit": "npm:0.2.0"
|
"@coinweb/contract-kit": "npm:0.2.0"
|
||||||
"@coinweb/minimal-sdk": "npm:1.2.19"
|
"@coinweb/minimal-sdk": "npm:1.2.18"
|
||||||
json-stable-stringify: "npm:^1.1.1"
|
json-stable-stringify: "npm:^1.1.1"
|
||||||
lodash.isequal: "npm:^4.5.0"
|
lodash.isequal: "npm:^4.5.0"
|
||||||
secp256k1: "npm:^5.0.0"
|
secp256k1: "npm:^5.0.0"
|
||||||
checksum: 10c0/80212780455d4bc2c1082d62ce382c6d07c6b5a107dc372f630c2257de686ec7e072c5d7a0b966e611b73f8b49ef9d6d8b68fbd66de1d968992a6b18444f218b
|
checksum: 10c0/84785ecc631510aa39189792826cff454700cba96d13d6c9f93f4166ee035fb1c8a8c0f2eab0f51d7d5fe127c661c7964792f8dfacffb9bec5eaf3a6da7fc744
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user