wip: use callstack
This commit is contained in:
parent
bb6d584ed2
commit
a0516f67ae
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import {
|
import {
|
||||||
Context,
|
Context,
|
||||||
extractContractArgs,
|
extractContractArgs,
|
||||||
@ -15,6 +16,7 @@ import { ResolvedOp, Task } from '../types';
|
|||||||
import { context, getRawContext, setRawContext } from './context';
|
import { context, getRawContext, setRawContext } from './context';
|
||||||
import { getAwaitedOps } from './promisifiedOps/awaited';
|
import { getAwaitedOps } from './promisifiedOps/awaited';
|
||||||
import { pushResolvedOp } from './promisifiedOps/resolved';
|
import { pushResolvedOp } from './promisifiedOps/resolved';
|
||||||
|
import { extractRootParent, getRoot, setRoot } from './utils';
|
||||||
|
|
||||||
let abortExecution: ((result: boolean) => void) | null = null;
|
let abortExecution: ((result: boolean) => void) | null = null;
|
||||||
|
|
||||||
@ -22,112 +24,141 @@ const handleState = () => {
|
|||||||
const ctx = getRawContext();
|
const ctx = getRawContext();
|
||||||
|
|
||||||
const resolvedOps = extractContractArgs(ctx.tx);
|
const resolvedOps = extractContractArgs(ctx.tx);
|
||||||
const methodArgs = getMethodArguments(ctx) as [unknown, unknown[], ResolvedOp[]];
|
const methodArgs = getMethodArguments(ctx) as [unknown, unknown[], ResolvedOp[], string?];
|
||||||
|
|
||||||
const initialArgs = methodArgs[1] ?? [];
|
const initialArgs = methodArgs[1] ?? [];
|
||||||
const previousOps = methodArgs[2] ?? [];
|
const previousOps = methodArgs[2] ?? [];
|
||||||
const allResolvedOps = [...previousOps, ...resolvedOps];
|
const allResolvedOps = [...previousOps, ...resolvedOps];
|
||||||
|
|
||||||
|
const root = methodArgs[3];
|
||||||
|
|
||||||
pushResolvedOp(allResolvedOps);
|
pushResolvedOp(allResolvedOps);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
args: initialArgs,
|
args: initialArgs,
|
||||||
methodName: methodArgs[0] as string,
|
methodName: methodArgs[0] as string,
|
||||||
ops: allResolvedOps,
|
ops: allResolvedOps,
|
||||||
isChildCall: previousOps.length > 0,
|
isChildCall: resolvedOps.length > 0,
|
||||||
|
root,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type Method = (...args: any[]) => Promise<void>;
|
||||||
|
|
||||||
|
type Resolver = (
|
||||||
|
currentMethod: Method,
|
||||||
|
args: any[],
|
||||||
|
resolve: (value: boolean | PromiseLike<boolean>) => void,
|
||||||
|
reject: (reason?: any) => void,
|
||||||
|
isChildCall: boolean,
|
||||||
|
rootParent?: string,
|
||||||
|
root?: string
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
const resolver: Resolver = (currentMethod, args, resolve, reject, isChildCall, root) => {
|
||||||
|
if (!isChildCall) {
|
||||||
|
extractRootParent(resolver.name);
|
||||||
|
} else {
|
||||||
|
if (!root) {
|
||||||
|
console.log('executor-root-not-set');
|
||||||
|
throw new Error('Root root is not set');
|
||||||
|
}
|
||||||
|
|
||||||
|
setRoot(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
currentMethod(...args).then(
|
||||||
|
() => {
|
||||||
|
console.log('executor-resolved');
|
||||||
|
resolve(true);
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
console.log('executor-rejected');
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const executor =
|
export const executor =
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
(method: (...args: any[]) => Promise<void>) =>
|
(method: (...args: any[]) => Promise<void>) =>
|
||||||
async (ctx: Context): Promise<NewTx[]> => {
|
async (ctx: Context): Promise<NewTx[]> => {
|
||||||
console.log('executor-start');
|
console.log('executor-start');
|
||||||
setRawContext(ctx);
|
setRawContext(ctx);
|
||||||
|
|
||||||
const { args, methodName, ops, isChildCall } = handleState();
|
const { args, methodName, ops, isChildCall, root } = handleState();
|
||||||
|
|
||||||
if (isChildCall && !isSelfCall(ctx)) {
|
if (isChildCall && !isSelfCall(ctx)) {
|
||||||
throw new Error('Only contract itself can call it');
|
throw new Error('Only contract itself can call it');
|
||||||
}
|
}
|
||||||
|
|
||||||
const execution = new Promise<boolean>((resolve, reject) => {
|
const execution = new Promise<boolean>((resolve, reject) => {
|
||||||
abortExecution = resolve;
|
abortExecution = resolve;
|
||||||
|
|
||||||
method(...args).then(
|
resolver(method, args, resolve, reject, isChildCall, root);
|
||||||
() => {
|
}).catch((error) => {
|
||||||
console.log('executor-resolved');
|
console.error(error);
|
||||||
resolve(true);
|
throw error;
|
||||||
},
|
});
|
||||||
() => {
|
|
||||||
console.log('executor-rejected');
|
|
||||||
reject();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
//@ts-expect-error
|
//@ts-expect-error
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||||
os.setTimeout(() => {
|
os.setTimeout(() => {
|
||||||
abortExecution?.(false);
|
abortExecution?.(false);
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
const isFullyExecuted = await execution;
|
const isFullyExecuted = await execution;
|
||||||
|
|
||||||
console.log('executor-executed');
|
console.log('executor-executed');
|
||||||
|
|
||||||
const { authInfo, availableCweb } = getCallParameters(ctx);
|
const { authInfo, availableCweb } = getCallParameters(ctx);
|
||||||
|
|
||||||
const awaitedOps = getAwaitedOps();
|
const awaitedOps = getAwaitedOps();
|
||||||
|
|
||||||
if (!awaitedOps.length) {
|
if (!awaitedOps.length) {
|
||||||
return [constructContinueTx(ctx, [constructDataUnverified({ isFullyExecuted })]), ...queue.gateway.unlock(ctx)];
|
return [constructContinueTx(ctx, [constructDataUnverified({ isFullyExecuted })]), ...queue.gateway.unlock(ctx)];
|
||||||
}
|
}
|
||||||
|
|
||||||
const callArgs: Task[] = [];
|
const callArgs: Task[] = [];
|
||||||
|
|
||||||
if (!isFullyExecuted) {
|
if (!isFullyExecuted) {
|
||||||
|
callArgs.push(awaitedOps.pop()!);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callArgs[0]?.isBatch) {
|
||||||
|
while (awaitedOps.at(-1)?.isBatch) {
|
||||||
callArgs.push(awaitedOps.pop()!);
|
callArgs.push(awaitedOps.pop()!);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (callArgs[0]?.isBatch) {
|
const callFee = 700n + BigInt(callArgs.length) * 100n;
|
||||||
while (awaitedOps.at(-1)?.isBatch) {
|
const opTxFee = awaitedOps.length ? 100n + BigInt(awaitedOps.length) * 100n : 0n;
|
||||||
callArgs.push(awaitedOps.pop()!);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const callFee = 700n + BigInt(callArgs.length) * 100n;
|
return [
|
||||||
const opTxFee = awaitedOps.length ? 100n + BigInt(awaitedOps.length) * 100n : 0n;
|
constructContinueTx(
|
||||||
|
ctx,
|
||||||
return [
|
awaitedOps.map(({ op }) => op),
|
||||||
constructContinueTx(
|
[
|
||||||
ctx,
|
{
|
||||||
awaitedOps.map(({ op }) => op),
|
callInfo: {
|
||||||
[
|
ref: constructContractRef(context.issuer, []),
|
||||||
{
|
methodInfo: {
|
||||||
callInfo: {
|
methodName,
|
||||||
ref: constructContractRef(context.issuer, []),
|
methodArgs: [
|
||||||
methodInfo: {
|
args,
|
||||||
methodName,
|
[...ops, ...Array(awaitedOps.length).fill({ SlotOp: 0 } satisfies ResolvedOp)] satisfies ResolvedOp[],
|
||||||
methodArgs: [
|
getRoot(),
|
||||||
args,
|
callArgs,
|
||||||
[
|
awaitedOps,
|
||||||
...ops,
|
],
|
||||||
...Array(awaitedOps.length).fill({ SlotOp: 0 } satisfies ResolvedOp),
|
|
||||||
] satisfies ResolvedOp[],
|
|
||||||
isFullyExecuted,
|
|
||||||
callArgs,
|
|
||||||
awaitedOps,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
contractInfo: {
|
|
||||||
providedCweb: availableCweb - callFee - opTxFee,
|
|
||||||
authenticated: authInfo,
|
|
||||||
},
|
|
||||||
contractArgs: callArgs.map(({ op }) => op),
|
|
||||||
},
|
},
|
||||||
|
contractInfo: {
|
||||||
|
providedCweb: availableCweb - callFee - opTxFee,
|
||||||
|
authenticated: authInfo,
|
||||||
|
},
|
||||||
|
contractArgs: callArgs.map(({ op }) => op),
|
||||||
},
|
},
|
||||||
]
|
},
|
||||||
),
|
]
|
||||||
];
|
),
|
||||||
};
|
];
|
||||||
|
};
|
||||||
|
|||||||
@ -1,10 +1,56 @@
|
|||||||
export const getStack = ({ skip = 0 }: { skip?: number } = {}) =>
|
let rootParent = '';
|
||||||
new Error().stack
|
let root = '';
|
||||||
?.split('\n')
|
|
||||||
|
export const extractRootParent = (name: string) => {
|
||||||
|
const stack = getStackItems();
|
||||||
|
|
||||||
|
if (stack[0] === name) {
|
||||||
|
rootParent = name;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getStackItems = ({ skip = 0 }: { skip?: number } = {}) => {
|
||||||
|
const slugs = new Error()
|
||||||
|
.stack!.split('\n')
|
||||||
.slice(2 + skip)
|
.slice(2 + skip)
|
||||||
.map((line) => {
|
.map((line) => {
|
||||||
const match = line.match(/at\s+([^\s(]+)/);
|
const match = line.match(/at\s+([^\s(]+)/);
|
||||||
return match ? match[1] : '';
|
return match ? match[1] : '';
|
||||||
})
|
})
|
||||||
.filter((name) => name && name !== 'Promise')
|
.filter((name) => name && !['<anonymous>', 'Promise'].includes(name));
|
||||||
.join('@') || '';
|
|
||||||
|
return slugs;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getStack = ({ skip = 0 }: { skip?: number } = {}) => {
|
||||||
|
const items = getStackItems({ skip });
|
||||||
|
|
||||||
|
if (rootParent) {
|
||||||
|
const rootIndex = items.findLastIndex((item) => item === rootParent);
|
||||||
|
|
||||||
|
if (rootIndex !== -1) {
|
||||||
|
const pureSlugs = items.slice(0, rootIndex);
|
||||||
|
|
||||||
|
return pureSlugs.join('@') || '@';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!root) {
|
||||||
|
console.log('set root');
|
||||||
|
console.log(JSON.stringify(items));
|
||||||
|
console.log(items.at(-1));
|
||||||
|
root = items.at(-1) ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return items.join('@') || '@';
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getRoot = () => {
|
||||||
|
return root;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const setRoot = (value: string) => {
|
||||||
|
root = value;
|
||||||
|
};
|
||||||
|
|||||||
@ -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="0xd0b364db47a35710320a815fbcae80435ae83e0a1730e70529f1b0b2a6b7bfd5"
|
VITE_CONTRACT_ADDRESS="0x6fd41997fb840f91cc9d3b1bf69015dc2cef975015b52d53bf04f4380ddd66c4"
|
||||||
Loading…
x
Reference in New Issue
Block a user