fix: small fixes and refactor

This commit is contained in:
Alex 2025-05-05 12:21:50 +03:00
parent 3f640d90ce
commit 7baec6736b
32 changed files with 166 additions and 157 deletions

View File

@ -12,6 +12,10 @@ export const constructCwebMain = (methods: Record<string, (...args: any[]) => Pr
const module: ContractHandlers = { handlers: {} }; const module: ContractHandlers = { handlers: {} };
Object.entries(methods).forEach(([name, handler]) => { Object.entries(methods).forEach(([name, handler]) => {
if (name.startsWith('_')) {
throw new Error('Do not start method names with "_" because they are reserved for internal use');
}
addMethodHandler(module, name, executor(handler)); addMethodHandler(module, name, executor(handler));
}); });

View File

@ -10,8 +10,8 @@ import {
import { CwebTake } from '@coinweb/contract-kit/dist/types/operations/take'; import { CwebTake } from '@coinweb/contract-kit/dist/types/operations/take';
import { getCallParameters, getContractIssuer } from 'lib/onchain'; import { getCallParameters, getContractIssuer } from 'lib/onchain';
import { pushAwaitedOp } from '../../../dist/onchain/ops';
import { ExecutorMethodArgs, ResolvedOp } from '../../types'; import { ExecutorMethodArgs, ResolvedOp } from '../../types';
import { pushAwaitedTask } from '../promisifiedFeatures';
import { uuid } from '../utils'; import { uuid } from '../utils';
import { extractOps } from './extractOps'; import { extractOps } from './extractOps';
@ -102,7 +102,7 @@ export const handleContext = (ctx: Context) => {
}; };
if (executionOpsTakeOp) { if (executionOpsTakeOp) {
pushAwaitedOp(executionOpsTakeOp); pushAwaitedTask(executionOpsTakeOp);
} }
return !!executionOpsTakeOp; //This is a flag to check if the execution should restart / TODO: refactor; return !!executionOpsTakeOp; //This is a flag to check if the execution should restart / TODO: refactor;

View File

@ -2,7 +2,7 @@ import { constructTake, extractRead, GRead, GTake, ResolvedOperation, ResolvedRe
import { CwebTake } from '@coinweb/contract-kit/dist/types/operations/take'; import { CwebTake } from '@coinweb/contract-kit/dist/types/operations/take';
import { ResolvedOp, TypedClaim } from '../../types'; import { ResolvedOp, TypedClaim } from '../../types';
import { resultKey } from '../claims/result'; import { resultKey } from '../claims';
import { mutexBlockLockKey, mutexBlockUnlockKey, mutexExecOpsKey, MutexExecOpsResult } from '../mutex'; import { mutexBlockLockKey, mutexBlockUnlockKey, mutexExecOpsKey, MutexExecOpsResult } from '../mutex';
import { isResolvedBlockOp, isResolvedReadOp, isResolvedTakeOp } from '../utils'; import { isResolvedBlockOp, isResolvedReadOp, isResolvedTakeOp } from '../utils';

View File

@ -2,7 +2,7 @@
import { Context, NewTx, getMethodArguments, isSelfCall } from '@coinweb/contract-kit'; import { Context, NewTx, getMethodArguments, isSelfCall } from '@coinweb/contract-kit';
import { context, getRawContext, handleContext } from './context'; import { context, getRawContext, handleContext } from './context';
import { pushResolvedOp } from './promisifiedOps/resolved'; import { pushResolvedOp } from './promisifiedFeatures/runtime/resolvedOps';
import { constructTx } from './utils'; import { constructTx } from './utils';
let abortExecution: ((result: boolean) => void) | null = null; let abortExecution: ((result: boolean) => void) | null = null;

View File

@ -1,4 +1,4 @@
import { markTaskBatch } from './promisifiedOps/awaited'; import { markTaskBatch } from './promisifiedFeatures/runtime/awaitedTasks';
import { getBatchId } from './utils'; import { getBatchId } from './utils';
export const opMarker = Symbol('opMarker'); export const opMarker = Symbol('opMarker');

View File

@ -1,3 +1,3 @@
export * from './context'; export * from './context';
export * from './executor'; export * from './promisifiedFeatures/features';
export * from './promisifiedOps'; export * from './constructCwebMain';

View File

@ -8,7 +8,7 @@ import {
ContractIssuer, ContractIssuer,
} from '@coinweb/contract-kit'; } from '@coinweb/contract-kit';
export const mutexBlockLockKey = 'mutex_block_lock'; export const mutexBlockLockKey = '_mutex_block_lock';
export const constructMutexBlockLockClaimKey = (lockId: string) => constructClaimKey([mutexBlockLockKey], [lockId]); export const constructMutexBlockLockClaimKey = (lockId: string) => constructClaimKey([mutexBlockLockKey], [lockId]);

View File

@ -10,7 +10,7 @@ import {
GStore, GStore,
} from '@coinweb/contract-kit'; } from '@coinweb/contract-kit';
export const mutexBlockUnlockKey = 'mutex_block_unlock'; export const mutexBlockUnlockKey = '_mutex_block_unlock';
export const constructMutexBlockUnlockClaimKey = (uniqueId: string) => export const constructMutexBlockUnlockClaimKey = (uniqueId: string) =>
constructClaimKey([mutexBlockUnlockKey], [uniqueId]); constructClaimKey([mutexBlockUnlockKey], [uniqueId]);

View File

@ -14,7 +14,7 @@ import { toHex } from 'lib/shared';
import { MutexExecOpsResult } from '../types'; import { MutexExecOpsResult } from '../types';
export const mutexExecOpsKey = 'mutex_exec_ops'; export const mutexExecOpsKey = '_mutex_exec_ops';
export const constructMutexExecOpsClaimKey = (execId: string) => constructClaimKey([mutexExecOpsKey], [execId]); export const constructMutexExecOpsClaimKey = (execId: string) => constructClaimKey([mutexExecOpsKey], [execId]);

View File

@ -6,13 +6,13 @@ import {
ContractIssuer, ContractIssuer,
GRead, GRead,
} from '@coinweb/contract-kit'; } from '@coinweb/contract-kit';
import { CwebRead } from '@coinweb/contract-kit/dist/esm/operations/read'; import { CwebRead } from '@coinweb/contract-kit/dist/types/operations/read';
import { toHex } from 'lib/shared'; import { toHex } from 'lib/shared';
import { rangeReadLimit } from '../settings'; import { rangeReadLimit } from '../settings';
import { LockedKey, MutexLockState } from '../types'; import { LockedKey, MutexLockState } from '../types';
export const mutexLockKey = 'mutex_lock'; export const mutexLockKey = '_mutex_lock';
export const constructMutexLockFirstPart = () => [mutexLockKey]; export const constructMutexLockFirstPart = () => [mutexLockKey];

View File

@ -1,14 +1,13 @@
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 { context } from '../context'; import { context } from '../../../context';
import { stopExecution } from '../executor'; import { stopExecution } from '../../../executor';
import { opMarker } from '../global'; import { opMarker } from '../../../global';
import { isResolvedChildOp, isResolvedExecOp, isResolvedSlotOp } from '../utils'; import { isResolvedChildOp, isResolvedExecOp, isResolvedSlotOp } from '../../../utils';
import { uuid } from '../utils'; import { uuid } from '../../../utils';
import { getAwaitedTasks, pushAwaitedTask } from '../../runtime/awaitedTasks';
import { getAwaitedTasks, pushAwaitedTask } from './awaited'; import { getUsedOps, saveUsedOps, shiftResolvedOp } from '../../runtime/resolvedOps';
import { getUsedOps, saveUsedOps, shiftResolvedOp } from './resolved';
let isRootDetected = false; let isRootDetected = false;

View File

@ -0,0 +1 @@
export * from './cwait';

View File

@ -0,0 +1,3 @@
export * from './cwait';
export * from './mutex';
export * from './ops';

View File

@ -0,0 +1 @@
export * from './lock';

View File

@ -0,0 +1,78 @@
import { getTime } from 'lib/onchain';
import { opMarker } from '../../../global';
import { LockedKey } from '../../../mutex';
import { isResolvedLockOp, isResolvedSlotOp, isResolvedUnlockOp, uuid } from '../../../utils';
import { pushAwaitedTask, shiftResolvedOp } from '../../runtime';
const unlock = (lockId: string, timestamp: number) => {
console.log('lockOp');
let opMarkerValue = false;
const result = new Promise<void>((resolve, reject) => {
try {
const { op, isOp } = shiftResolvedOp();
if (!isOp) {
pushAwaitedTask({ UnlockOp: { lockId, timestamp } });
opMarkerValue = true;
} else {
if (isResolvedSlotOp(op)) {
console.log('unlockOp-slotOp');
return;
}
if (!isResolvedUnlockOp(op)) {
console.log('unlockOp-error');
throw new Error('Unlock operation not found');
}
resolve();
}
} catch (error) {
reject(error);
}
});
(result as Promise<void> & { [opMarker]: boolean })[opMarker] = opMarkerValue;
return result;
};
export const lock = (keys: LockedKey[] | LockedKey) => {
console.log('lockOp');
let opMarkerValue = false;
const result = new Promise<() => Promise<void>>((resolve, reject) => {
try {
const { op, isOp } = shiftResolvedOp();
if (!isOp) {
pushAwaitedTask({
LockOp: { lockId: uuid(), keys: Array.isArray(keys) ? keys : [keys], timestamp: getTime() },
});
opMarkerValue = true;
} else {
if (isResolvedSlotOp(op)) {
console.log('lockOp-slotOp');
return;
}
if (!isResolvedLockOp(op)) {
console.log('lockOp-error');
throw new Error('Lock operation not found');
}
const result = op.LockOp;
resolve(() => unlock(result.lockId, result.timestamp));
}
} catch (error) {
reject(error);
}
});
(result as Promise<() => Promise<void>> & { [opMarker]: boolean })[opMarker] = opMarkerValue;
return result;
};

View File

@ -1,9 +1,8 @@
import { BlockFilter, constructBlock, extractBlock } from '@coinweb/contract-kit'; import { BlockFilter, constructBlock, extractBlock } from '@coinweb/contract-kit';
import { opMarker } from '../../global'; import { opMarker } from '../../../global';
import { isResolvedBlockOp, isResolvedSlotOp } from '../../utils'; import { isResolvedBlockOp, isResolvedSlotOp } from '../../../utils';
import { pushAwaitedTask } from '../awaited'; import { pushAwaitedTask, shiftResolvedOp } from '../../runtime';
import { shiftResolvedOp } from '../resolved';
export const blockOp = (filters: BlockFilter[]) => { export const blockOp = (filters: BlockFilter[]) => {
console.log('blockOp'); console.log('blockOp');

View File

@ -1,12 +1,11 @@
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 '../../../global';
import { isResolvedReadOp, isResolvedSlotOp } from '../../utils'; import { isResolvedReadOp, isResolvedSlotOp } from '../../../utils';
import { pushAwaitedTask } from '../awaited'; import { pushAwaitedTask, shiftResolvedOp } from '../../runtime';
import { shiftResolvedOp } from '../resolved';
export const rangeReadOp = <TClaims extends Claim[] = TypedClaim[]>( export const rangeReadOp = <TClaims extends Claim[] = TypedClaim[]>(
firstPart: ClaimKey['first_part'], firstPart: ClaimKey['first_part'],

View File

@ -1,11 +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 '../../../global';
import { isResolvedReadOp, isResolvedSlotOp } from '../../utils'; import { isResolvedReadOp, isResolvedSlotOp } from '../../../utils';
import { pushAwaitedTask } from '../awaited'; import { pushAwaitedTask, shiftResolvedOp } from '../../runtime';
import { shiftResolvedOp } from '../resolved';
export const readOp = <TClaim extends Claim = TypedClaim>(key: ClaimKey) => { export const readOp = <TClaim extends Claim = TypedClaim>(key: ClaimKey) => {
console.log('readOp'); console.log('readOp');

View File

@ -1,10 +1,9 @@
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 '../../../global';
import { isResolvedSlotOp, isResolvedStoreOp } from '../../utils'; import { isResolvedSlotOp, isResolvedStoreOp } from '../../../utils';
import { pushAwaitedTask } from '../awaited'; import { pushAwaitedTask, shiftResolvedOp } from '../../runtime';
import { shiftResolvedOp } from '../resolved';
export const storeOp = (claim: Claim, storeCweb?: bigint) => { export const storeOp = (claim: Claim, storeCweb?: bigint) => {
console.log('storeOp'); console.log('storeOp');

View File

@ -1,10 +1,9 @@
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 '../../../global';
import { isResolvedSlotOp, isResolvedTakeOp } from '../../utils'; import { isResolvedSlotOp, isResolvedTakeOp } from '../../../utils';
import { pushAwaitedTask } from '../awaited'; import { pushAwaitedTask, shiftResolvedOp } from '../../runtime';
import { shiftResolvedOp } from '../resolved';
export const takeOp = <TClaim extends Claim = TypedClaim>(key: ClaimKey) => { export const takeOp = <TClaim extends Claim = TypedClaim>(key: ClaimKey) => {
console.log('takeOp'); console.log('takeOp');

View File

@ -0,0 +1,2 @@
export * from './runtime';
export * from './features';

View File

@ -1,4 +1,4 @@
import { PreparedOp, Task } from '../../types'; import { PreparedOp, Task } from '../../../types';
const awaitedTasks: Task[] = []; const awaitedTasks: Task[] = [];

View File

@ -0,0 +1,2 @@
export * from './awaitedTasks';
export * from './resolvedOps';

View File

@ -1,4 +1,4 @@
import { ResolvedOp } from '../../types'; import { ResolvedOp } from '../../../types';
const resolvedOps: ResolvedOp[] = []; const resolvedOps: ResolvedOp[] = [];

View File

@ -1,4 +0,0 @@
export * from './awaited';
export * from './cwait';
export * from './ops';
export * from './resolved';

View File

@ -1,42 +0,0 @@
import { ResolvedLockOp } from '../../../types';
import { opMarker } from '../../global';
import { LockedKey } from '../../mutex';
import { isResolvedLockOp, isResolvedSlotOp, uuid } from '../../utils';
import { pushAwaitedTask } from '../awaited';
import { shiftResolvedOp } from '../resolved';
export const lockOp = (keys: LockedKey[] | LockedKey) => {
console.log('lockOp');
let opMarkerValue = false;
const result = new Promise<ResolvedLockOp['LockOp']>((resolve, reject) => {
try {
const { op, isOp } = shiftResolvedOp();
if (!isOp) {
pushAwaitedTask({ LockOp: { lockId: uuid(), keys: Array.isArray(keys) ? keys : [keys] } });
opMarkerValue = true;
} else {
if (isResolvedSlotOp(op)) {
console.log('storeOp-slotOp');
return;
}
if (!isResolvedLockOp(op)) {
console.log('lockOp-error');
throw new Error('Lock operation not found');
}
const result = op.LockOp;
resolve(result);
}
} catch (error) {
reject(error);
}
});
(result as Promise<ResolvedLockOp['LockOp']> & { [opMarker]: boolean })[opMarker] = opMarkerValue;
return result;
};

View File

@ -1,38 +0,0 @@
import { opMarker } from '../../global';
import { isResolvedSlotOp, isResolvedUnlockOp } from '../../utils';
import { pushAwaitedTask } from '../awaited';
import { shiftResolvedOp } from '../resolved';
export const unlock = (lockId: string) => {
console.log('lockOp');
let opMarkerValue = false;
const result = new Promise<void>((resolve, reject) => {
try {
const { op, isOp } = shiftResolvedOp();
if (!isOp) {
pushAwaitedTask({ UnlockOp: { lockId } });
opMarkerValue = true;
} else {
if (isResolvedSlotOp(op)) {
console.log('unlockOp-slotOp');
return;
}
if (!isResolvedUnlockOp(op)) {
console.log('unlockOp-error');
throw new Error('Unlock operation not found');
}
resolve();
}
} catch (error) {
reject(error);
}
});
(result as Promise<void> & { [opMarker]: boolean })[opMarker] = opMarkerValue;
return result;
};

View File

@ -152,6 +152,22 @@ export const prepareInThreadTxs = ({
resolvedChildOps.push({ SlotOp: { ok: true } }); resolvedChildOps.push({ SlotOp: { ok: true } });
}); });
if (preparedExecOps.length > 0) {
const execId = uuid();
const { callInfo, fee, ops } = constructExecOpsCall({
issuer: context.issuer,
ops: preparedExecOps,
processId: context.thisId,
execId,
});
childCalls.push({ callInfo });
txFee += fee;
callArgs.push(...ops);
}
const returnTxs: NewTx[] = []; const returnTxs: NewTx[] = [];
if (callArgs.length) { if (callArgs.length) {
@ -230,21 +246,5 @@ export const prepareInThreadTxs = ({
} }
} }
if (preparedExecOps.length > 0) {
const execId = uuid();
const { callInfo, fee, ops } = constructExecOpsCall({
issuer: context.issuer,
ops: preparedExecOps,
processId: context.thisId,
execId,
});
childCalls.push({ callInfo });
txFee += fee;
callArgs.push(...ops);
}
return { txs: returnTxs, calls: callsPrepared, txFee }; return { txs: returnTxs, calls: callsPrepared, txFee };
}; };

View File

@ -35,7 +35,7 @@ export const prepareOutThreadTxs = ({
const preparedCalls: FullCallInfo[] = []; const preparedCalls: FullCallInfo[] = [];
const preparedOps: PreparedOperation[] = []; const preparedOps: PreparedOperation[] = [];
const preparedStoreAndTakes: (PreparedExtendedStoreOp | GTake<CwebTake>)[] = []; const preparedExecOps: (PreparedExtendedStoreOp | GTake<CwebTake>)[] = [];
let txFee = 0n; let txFee = 0n;
let callsPrepared = 0; let callsPrepared = 0;
@ -77,7 +77,7 @@ export const prepareOutThreadTxs = ({
} }
case isPreparedStoreOp(op): case isPreparedStoreOp(op):
case isPreparedTakeOp(op): { case isPreparedTakeOp(op): {
preparedStoreAndTakes.push(op); preparedExecOps.push(op);
break; break;
} }
case isPreparedLockOp(op): { case isPreparedLockOp(op): {
@ -107,10 +107,10 @@ export const prepareOutThreadTxs = ({
siblingCallResolvedOps.push({ SlotOp: { ok: true } }); siblingCallResolvedOps.push({ SlotOp: { ok: true } });
}); });
if (preparedStoreAndTakes.length > 0) { if (preparedExecOps.length > 0) {
const { callInfo, fee } = constructExecOpsCall({ const { callInfo, fee } = constructExecOpsCall({
issuer: context.issuer, issuer: context.issuer,
ops: preparedStoreAndTakes, ops: preparedExecOps,
processId: context.thisId, processId: context.thisId,
}); });
@ -118,9 +118,17 @@ export const prepareOutThreadTxs = ({
txFee += fee; txFee += fee;
} }
if (preparedCalls.length > 0 || preparedOps.length > 0) {
return {
txs: [constructContinueTx(getRawContext(), preparedOps, preparedCalls)],
txFee,
calls: callsPrepared,
};
}
return { return {
txs: [constructContinueTx(getRawContext(), preparedOps, preparedCalls)], txs: [],
txFee, txFee: 0n,
calls: callsPrepared, calls: 0,
}; };
}; };

View File

@ -1,7 +1,7 @@
import { constructContinueTx, NewTx, passCwebFrom, sendCwebInterface } from '@coinweb/contract-kit'; import { constructContinueTx, NewTx, passCwebFrom, sendCwebInterface } from '@coinweb/contract-kit';
import { context, getRawContext } from '../../context'; import { context, getRawContext } from '../../context';
import { getAwaitedTasks } from '../../promisifiedOps'; import { getAwaitedTasks } from '../../promisifiedFeatures';
import { prepareInThreadTxs } from './prepareInThreadTxs'; import { prepareInThreadTxs } from './prepareInThreadTxs';
import { prepareOutThreadTxs } from './prepareOutThreadTxs'; import { prepareOutThreadTxs } from './prepareOutThreadTxs';

View File

@ -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="0xbf9ca1687e3441bed1afd495405778a9c06c2f5173829d47d9b87dfb150063d8" VITE_CONTRACT_ADDRESS="0xa99515a81ee23d07dd08a72ec06646374d28df16de9ccdde16ed7e421ad26c83"