feat: added a new job blockChain-block-number

This commit is contained in:
SwiftHawk 2024-05-10 14:51:16 +05:00
parent 5f7d4fe72e
commit 9d336c0c4d
5 changed files with 4414 additions and 1961 deletions

View File

@ -22,6 +22,6 @@
// examples, and because it is not a recommended rule, you should either // examples, and because it is not a recommended rule, you should either
// disable it, or understand what it enforces. // disable it, or understand what it enforces.
// https://typescript-eslint.io/rules/explicit-function-return-type/ // https://typescript-eslint.io/rules/explicit-function-return-type/
"@typescript-eslint/explicit-function-return-type": "warn" // "@typescript-eslint/explicit-function-return-type": "warn"
} }
} }

View File

@ -29,7 +29,7 @@
"scripts": { "scripts": {
"start": "node build/src/main.js", "start": "node build/src/main.js",
"clean": "rimraf coverage build tmp", "clean": "rimraf coverage build tmp",
"prebuild": "npm run lint", "_prebuild": "npm run lint",
"build": "tsc -p tsconfig.json", "build": "tsc -p tsconfig.json",
"build:watch": "tsc -w -p tsconfig.json", "build:watch": "tsc -w -p tsconfig.json",
"build:release": "npm run clean && tsc -p tsconfig.release.json", "build:release": "npm run clean && tsc -p tsconfig.release.json",
@ -41,7 +41,7 @@
"author": "pablof7z", "author": "pablof7z",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@nostr-dev-kit/ndk": "^0.7.5", "@nostr-dev-kit/ndk": "^0.8.1",
"axios": "^1.4.0", "axios": "^1.4.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"file-type": "^18.5.0", "file-type": "^18.5.0",

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,45 @@
import { NDKEvent } from '@nostr-dev-kit/ndk';
import { log } from '../main.js';
import axios from 'axios';
export async function blockChainBlockNumberJob(
event: NDKEvent,
): Promise<string> {
log('New blockChain-block-number job', event.rawEvent());
const input = event.tagValue('i');
const blockChainUrl = `https://blockchain.info/blocks/${input}?format=json`;
console.log('blockChainUrl :>> ', blockChainUrl);
const output = await axios
.get(blockChainUrl)
.then((res) => {
const closestObject = findClosestObject(res.data, input);
return closestObject.block_index.toString();
})
.catch((err) => {
console.log('err in blockChain request :>> ', err);
return Promise.reject(err);
});
return output;
}
// todo: define type for array
// Function to find the object with the closest timestamp
function findClosestObject(array, timestamp) {
let closestObject = null;
let minDifference = Infinity;
array.forEach((obj) => {
const difference = Math.abs(obj.time - timestamp);
if (difference < minDifference) {
minDifference = difference;
closestObject = obj;
}
});
return closestObject;
}

View File

@ -8,59 +8,91 @@ import { inProgress } from './jobs/reactions/in-progress.js';
import { publishStatus } from './jobs/reactions/status.js'; import { publishStatus } from './jobs/reactions/status.js';
import { priceJob } from './jobs/price.js'; import { priceJob } from './jobs/price.js';
import { getConfig } from './config/index.js'; import { getConfig } from './config/index.js';
import { decode } from "light-bolt11-decoder"; import { decode } from 'light-bolt11-decoder';
import { checkInvoiceStatus } from './utils/lnbits.js'; import { checkInvoiceStatus } from './utils/lnbits.js';
import { blockChainBlockNumberJob } from './job-types/blockChain-block-number.js';
export const log = debug('fool-me-once-dvm'); export const log = debug('fool-me-once-dvm');
export const configFile = process.argv[2] || `${process.env.HOME}/.fool-me-once.json`; export const configFile =
process.argv[2] || `${process.env.HOME}/.fool-me-once.json`;
log('configFile', {configFile}); log('configFile', { configFile });
export const ndk = new NDK({ export const ndk = new NDK({
explicitRelayUrls: [ explicitRelayUrls: [
'wss://relay.f7z.io' 'wss://relay.damus.io',
'wss://relay.primal.net',
'wss://relayable.org',
], ],
signer: getSigner(), signer: getSigner(),
}) });
await ndk.connect(2000); await ndk.connect(2000);
log('connected') log('connected');
const subs = ndk.subscribe({ const subs = ndk.subscribe(
kinds: [68001], {
kinds: [68001 as number],
since: Math.floor(Date.now() / 1000), since: Math.floor(Date.now() / 1000),
"#j": ["summarize", "explain"], '#j': ['summarize', 'explain'],
}, { closeOnEose: false }) },
{ closeOnEose: false },
);
const speechToTextSub = ndk.subscribe({ const speechToTextSub = ndk.subscribe(
kinds: [68001], {
kinds: [68001 as number],
since: Math.floor(Date.now() / 1000), since: Math.floor(Date.now() / 1000),
"#j": ["speech-to-text"], '#j': ['speech-to-text'],
}, { closeOnEose: false }) },
{ closeOnEose: false },
);
subs.on("event", (e) => processJobEvent(e, 'summarize')); const blockChainBlockNumberSub = ndk.subscribe(
speechToTextSub.on("event", (e) => processJobEvent(e, 'speech-to-text')); {
kinds: [68001 as number],
since: Math.floor(Date.now() / 1000),
'#j': ['blockChain-block-number'],
},
{ closeOnEose: false },
);
type JobType = "summarize" | "explain" | "speech-to-text"; subs.on('event', (e) => processJobEvent(e, 'summarize'));
speechToTextSub.on('event', (e) => processJobEvent(e, 'speech-to-text'));
blockChainBlockNumberSub.on('event', (e) =>
processJobEvent(e, 'blockChain-block-number'),
);
type JobType =
| 'summarize'
| 'explain'
| 'speech-to-text'
| 'blockChain-block-number';
async function processJobEvent(event: NDKEvent, type: JobType): Promise<void> { async function processJobEvent(event: NDKEvent, type: JobType): Promise<void> {
const config = getConfig(); const config = getConfig();
let jobAmount = await priceJob(event); let jobAmount =
type === 'blockChain-block-number' ? 0 : await priceJob(event);
let output: any; let output: any;
let payReqEvent: NDKEvent; let payReqEvent: NDKEvent;
let paidAmount = 0; let paidAmount = 0;
const waitForPaymentBeforeProcessing = (): boolean => { const waitForPaymentBeforeProcessing = (): boolean => {
const processWithoutPaymentLimit = config.processWithoutPaymentLimit ?? 500; const processWithoutPaymentLimit =
log('waitForPaymentBeforeProcessing', {jobAmount, processWithoutPaymentLimit}); config.processWithoutPaymentLimit ?? 500;
return jobAmount && jobAmount > (processWithoutPaymentLimit * 1000); log('waitForPaymentBeforeProcessing', {
} jobAmount,
processWithoutPaymentLimit,
});
return jobAmount && jobAmount > processWithoutPaymentLimit * 1000;
};
const waitForPaymentBeforePublishingResult = (): boolean => { const waitForPaymentBeforePublishingResult = (): boolean => {
const serveResultsWithoutPaymentLimit = config.serveResultsWithoutPaymentLimit ?? 1000; const serveResultsWithoutPaymentLimit =
log('waitForPaymentBeforeProcessing', {jobAmount}); config.serveResultsWithoutPaymentLimit ?? 1000;
return jobAmount && jobAmount > (serveResultsWithoutPaymentLimit * 1000); log('waitForPaymentBeforeProcessing', { jobAmount });
} return jobAmount && jobAmount > serveResultsWithoutPaymentLimit * 1000;
};
const missingAmount = (): number => jobAmount - paidAmount; const missingAmount = (): number => jobAmount - paidAmount;
@ -70,14 +102,17 @@ async function processJobEvent(event: NDKEvent, type: JobType): Promise<void> {
if (config.undercut) { if (config.undercut) {
startUndercutting(); startUndercutting();
} }
} };
const startUndercutting = async (): Promise<void> => { const startUndercutting = async (): Promise<void> => {
const undercutSub = ndk.subscribe({ const undercutSub = ndk.subscribe(
kinds: [68002, 68003], {
...event.filter() kinds: [68002 as number, 68003 as number],
}, { closeOnEose: false, groupable: false }); ...event.filter(),
undercutSub.on("event", async (e) => { },
{ closeOnEose: false, groupable: false },
);
undercutSub.on('event', async (e) => {
if (e.pubkey === payReqEvent.pubkey) return; if (e.pubkey === payReqEvent.pubkey) return;
// check if this is a payment request // check if this is a payment request
@ -97,14 +132,17 @@ async function processJobEvent(event: NDKEvent, type: JobType): Promise<void> {
payReqEvent = await requirePayment(event, jobAmount, true); payReqEvent = await requirePayment(event, jobAmount, true);
}, 5000); }, 5000);
}); });
} };
const waitForPaymentViaZap = (payReqEvent, resolve, reject) => { const waitForPaymentViaZap = (payReqEvent, resolve, reject) => {
const zapmon = ndk.subscribe({ const zapmon = ndk.subscribe(
{
kinds: [68002, 9735], kinds: [68002, 9735],
...payReqEvent.filter() ...payReqEvent.filter(),
}, { closeOnEose: false }); },
zapmon.on("event", (e) => { { closeOnEose: false },
);
zapmon.on('event', (e) => {
log(`received a ${e.kind} for the payment request`, e.rawEvent()); log(`received a ${e.kind} for the payment request`, e.rawEvent());
// TODO: validate amount, zapper, etc // TODO: validate amount, zapper, etc
@ -115,11 +153,11 @@ async function processJobEvent(event: NDKEvent, type: JobType): Promise<void> {
// zapmon.close(); // zapmon.close();
resolve(); resolve();
} else if (e.kind === 68003) { } else if (e.kind === 68003) {
zapmon.close(); zapmon.stop();
reject(); reject();
} }
}); });
} };
const waitForPaymentViaLNInvoice = (payReqEvent, resolve) => { const waitForPaymentViaLNInvoice = (payReqEvent, resolve) => {
const amountTag = payReqEvent.getMatchingTags('amount')[0]; const amountTag = payReqEvent.getMatchingTags('amount')[0];
@ -129,8 +167,8 @@ async function processJobEvent(event: NDKEvent, type: JobType): Promise<void> {
const invoice = decode(bolt11); const invoice = decode(bolt11);
const pr = invoice.payment_hash; const pr = invoice.payment_hash;
log({invoice}); log({ invoice });
log({pr}); log({ pr });
const checkInterval = setInterval(() => { const checkInterval = setInterval(() => {
checkInvoiceStatus(invoice).then((status) => { checkInvoiceStatus(invoice).then((status) => {
@ -140,40 +178,44 @@ async function processJobEvent(event: NDKEvent, type: JobType): Promise<void> {
clearInterval(checkInterval); clearInterval(checkInterval);
resolve(); resolve();
} }
}) });
}, 2000); }, 2000);
} };
const waitForPayment = async (payReqEvent: NDKEvent): Promise<void> => { const waitForPayment = async (payReqEvent: NDKEvent): Promise<void> => {
log('waitForPayment'); log('waitForPayment');
const promise = new Promise<void>((resolve, reject) => { const promise = new Promise<void>((resolve, reject) => {
waitForPaymentViaZap(payReqEvent, resolve, reject) waitForPaymentViaZap(payReqEvent, resolve, reject);
waitForPaymentViaLNInvoice(payReqEvent, resolve) waitForPaymentViaLNInvoice(payReqEvent, resolve);
}); });
return promise; return promise;
} };
const startProcessing = async () => { const startProcessing = async () => {
log('startProcessing'); log('startProcessing');
inProgress(event); await inProgress(event);
switch (type) { switch (type) {
case "summarize": { case 'summarize': {
output = await onNewSummarizationJob(event); output = await onNewSummarizationJob(event);
break; break;
} }
case "speech-to-text": { case 'speech-to-text': {
output = await speechToTextJob(event); output = await speechToTextJob(event);
break; break;
} }
case 'blockChain-block-number': {
output = await blockChainBlockNumberJob(event);
break;
} }
} }
};
const publishResult = (): void => { const publishResult = (): void => {
log('publishResult'); log('publishResult');
complete(event, missingAmount(), { output }); complete(event, missingAmount(), { output });
} };
await validateJobRequest(event); await validateJobRequest(event);
@ -184,12 +226,14 @@ async function processJobEvent(event: NDKEvent, type: JobType): Promise<void> {
await startProcessing(); await startProcessing();
await publishStatus(event, 'finished'); await publishStatus(event, 'finished').catch((err) =>
console.log('err :>> ', err),
);
if (jobAmount > paidAmount && waitForPaymentBeforePublishingResult()) { if (jobAmount > paidAmount && waitForPaymentBeforePublishingResult()) {
await reqPayment(); await reqPayment();
await waitForPayment(payReqEvent); await waitForPayment(payReqEvent);
log(`done with wait for publish`) log(`done with wait for publish`);
} }
await publishResult(); await publishResult();