diff --git a/package.json b/package.json index 443ad8c..ce8efe4 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "start": "pnpm build && node ./dist/worker/worker.js", "prepare": "husky", "ci_validate": "node ./dist/bin/validateJSONRecipients.js", - "validate": "pnpm tsc && node ./dist/bin/validateJSONRecipients.js" + "validate": "pnpm build && node ./dist/bin/validateJSONRecipients.js" }, "packageManager": "pnpm@8.15.5", "keywords": [], diff --git a/packages/lit-task-auto-top-up/package.json b/packages/lit-task-auto-top-up/package.json index 3145eee..a3249e3 100644 --- a/packages/lit-task-auto-top-up/package.json +++ b/packages/lit-task-auto-top-up/package.json @@ -32,12 +32,13 @@ "dev": "echo 'This will use stub when #371 is fixed.' && pnpm build && echo 'Built the package for local use! Carry on.'" }, "dependencies": { + "@date-fns/tz": "^1.1.2", "@hokify/agenda": "^6.3.0", "@lit-protocol/contracts-sdk": "^6.4.0", "awaity": "^1.0.0", "bs58": "^5.0.0", "consola": "^3.2.3", - "date-and-time": "2.4.1", + "date-fns": "^4.1.0", "lodash": "^4.17.21", "multiformats": "9.7.1", "verror": "^1.10.1", @@ -45,7 +46,6 @@ "zod": "^3.22.4" }, "devDependencies": { - "@types/date-and-time": "0.13.0", "chai": "^5.1.0" } } diff --git a/packages/lit-task-auto-top-up/src/Classes/TaskHandler.ts b/packages/lit-task-auto-top-up/src/Classes/TaskHandler.ts index a70c354..cc956db 100644 --- a/packages/lit-task-auto-top-up/src/Classes/TaskHandler.ts +++ b/packages/lit-task-auto-top-up/src/Classes/TaskHandler.ts @@ -1,7 +1,8 @@ +import { TZDate } from '@date-fns/tz'; import { Job } from '@hokify/agenda'; import awaity from 'awaity'; // Awaity is a cjs package, breaks `import` with named imports in ESM import { ConsolaInstance } from 'consola'; -import date from 'date-and-time'; +import { addDays, isSameDay } from 'date-fns'; import VError from 'verror'; import { mintCapacityCreditNFT } from '../actions/mintCapacityCreditNFT'; @@ -34,7 +35,7 @@ export class TaskHandler { const tokens = await this.fetchExistingTokens({ recipientAddress }); const { noUsableTokensTomorrow, unexpiredTokens } = this.getExistingTokenDetails({ tokens, - today: new Date(), + today: TZDate.tz('UTC'), }); if (noUsableTokensTomorrow) { @@ -63,7 +64,7 @@ export class TaskHandler { } getExistingTokenDetails({ today, tokens }: { today: Date; tokens: CapacityToken[] }) { - const tomorrow = date.addDays(today, 1); + const tomorrow = addDays(today, 1); // Only mint a new token if the recipient... // 1. Has no NFTs at all @@ -80,9 +81,8 @@ export class TaskHandler { if (isExpired) { return true; } - return ( - date.isSameDay(new Date(timestamp), tomorrow) || date.isSameDay(new Date(timestamp), today) - ); + const tokenExpiresDate = new TZDate(timestamp, 'UTC'); + return isSameDay(tokenExpiresDate, tomorrow) || isSameDay(tokenExpiresDate, today); }); return { noUsableTokensTomorrow, diff --git a/packages/lit-task-auto-top-up/tests/expiredTokens/expiredTokens.ts b/packages/lit-task-auto-top-up/tests/expiredTokens/expiredTokens.ts index 05e4231..6f117c5 100644 --- a/packages/lit-task-auto-top-up/tests/expiredTokens/expiredTokens.ts +++ b/packages/lit-task-auto-top-up/tests/expiredTokens/expiredTokens.ts @@ -1,7 +1,15 @@ import { expect } from 'chai'; import { createConsola } from 'consola'; - -import { tokenFixtures, NOW, Expired, UnexpiredButInvalid, Unexpired } from './tokenFixtures'; +import { isSameDay } from 'date-fns'; + +import { + tokenFixtures, + NOW, + Expired, + UnexpiredButInvalid, + Unexpired, + MIDNIGHT_TODAY, +} from './tokenFixtures'; import { TaskHandler } from '../../src/index'; import { CapacityToken } from '../../src/types/types'; import { COMPLETE_CONFIG } from '../config'; @@ -44,6 +52,11 @@ function testAndAssert({ return true; } describe('Expired Tokens', () => { + describe('midnight today', () => { + it('should be a date set to midnight of the SAME DAY as the date provided', () => { + expect(isSameDay(NOW, MIDNIGHT_TODAY)).equal(true); + }); + }); describe('noUsableTokensTomorrow', () => { it('should be `true` when there are no tokens at all', () => { testAndAssert({}); diff --git a/packages/lit-task-auto-top-up/tests/expiredTokens/tokenFixtures.ts b/packages/lit-task-auto-top-up/tests/expiredTokens/tokenFixtures.ts index ed533c2..1177b90 100644 --- a/packages/lit-task-auto-top-up/tests/expiredTokens/tokenFixtures.ts +++ b/packages/lit-task-auto-top-up/tests/expiredTokens/tokenFixtures.ts @@ -1,4 +1,5 @@ -import date from 'date-and-time'; +import { TZDate } from '@date-fns/tz'; +import { startOfDay, addDays, subDays, addWeeks, addHours } from 'date-fns'; import { CapacityToken } from '../../src/types/types'; @@ -24,21 +25,26 @@ interface TokenFixtures { unexpired: Record; unexpiredButInvalid: Record; } -function getMidnightToday(now: Date) { - const midnightDate = new Date(now); - midnightDate.setHours(0, 0, 0, 0); - return midnightDate; -} -export const NOW = new Date(1712157737877); -export const MIDNIGHT_TODAY = getMidnightToday(NOW); -export const DAY_BEFORE_YESTERDAY = date.addDays(MIDNIGHT_TODAY, -2); -export const YESTERDAY = date.addDays(MIDNIGHT_TODAY, -1); -export const LATER_TODAY = date.addHours(NOW, 2); -export const TOMORROW = date.addDays(MIDNIGHT_TODAY, 1); -export const DAY_AFTER_TOMORROW = date.addDays(MIDNIGHT_TODAY, 2); -export const NEXT_WEEK = date.addDays(MIDNIGHT_TODAY, 7); -export const TWO_WEEKS_FROM_NOW = date.addDays(MIDNIGHT_TODAY, 14); +export const NOW = new TZDate(1712157737877, 'UTC'); +export const MIDNIGHT_TODAY = startOfDay(NOW); +export const YESTERDAY = subDays(MIDNIGHT_TODAY, 1); +export const DAY_BEFORE_YESTERDAY = subDays(MIDNIGHT_TODAY, 2); +export const LATER_TODAY = addHours(NOW, 2); +export const TOMORROW = addDays(MIDNIGHT_TODAY, 1); +export const DAY_AFTER_TOMORROW = addDays(MIDNIGHT_TODAY, 2); +export const NEXT_WEEK = addWeeks(MIDNIGHT_TODAY, 1); +export const TWO_WEEKS_FROM_NOW = addWeeks(MIDNIGHT_TODAY, 2); + +// console.log('NOW', NOW.toISOString()); +// console.log('MIDNIGHT_TODAY', MIDNIGHT_TODAY.toISOString()); +// console.log('DAY_BEFORE_YESTERDAY', DAY_BEFORE_YESTERDAY.toISOString()); +// console.log('YESTERDAY', YESTERDAY.toISOString()); +// console.log('LATER_TODAY', LATER_TODAY.toISOString()); +// console.log('TOMORROW', TOMORROW.toISOString()); +// console.log('DAY_AFTER_TOMORROW', DAY_AFTER_TOMORROW.toISOString()); +// console.log('NEXT_WEEK', NEXT_WEEK.toISOString()); +// console.log('TWO_WEEKS_FROM_NOW', TWO_WEEKS_FROM_NOW.toISOString()); export const tokenFixtures: TokenFixtures = { expired: { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8c56415..baba8b9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -108,6 +108,9 @@ importers: packages/lit-task-auto-top-up: dependencies: + '@date-fns/tz': + specifier: ^1.1.2 + version: 1.1.2 '@hokify/agenda': specifier: ^6.3.0 version: 6.3.0 @@ -123,9 +126,9 @@ importers: consola: specifier: ^3.2.3 version: 3.2.3 - date-and-time: - specifier: 2.4.1 - version: 2.4.1 + date-fns: + specifier: ^4.1.0 + version: 4.1.0 lodash: specifier: ^4.17.21 version: 4.17.21 @@ -142,9 +145,6 @@ importers: specifier: ^3.22.4 version: 3.22.4 devDependencies: - '@types/date-and-time': - specifier: 0.13.0 - version: 0.13.0 chai: specifier: ^5.1.0 version: 5.1.0 @@ -1024,6 +1024,10 @@ packages: kuler: 2.0.0 dev: true + /@date-fns/tz@1.1.2: + resolution: {integrity: sha512-Xmg2cPmOPQieCLAdf62KtFPU9y7wbQDq1OAzrs/bEQFvhtCPXDiks1CHDE/sTXReRfh/MICVkw/vY6OANHUGiA==} + dev: false + /@dotenvx/dotenvx@0.26.0: resolution: {integrity: sha512-fKyU2Ob4v5R1DwCL9/O4JmP4DO0rM5EH72c0U39IX1PR81C0QAjw2E+VYlaOH2rAUDLCLGec7IwIvz96GpDkDQ==} hasBin: true @@ -1618,7 +1622,7 @@ packages: dependencies: cron-parser: 4.9.0 date.js: 0.3.3 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4 human-interval: 2.0.1 luxon: 3.4.4 mongodb: 4.17.2 @@ -2601,10 +2605,6 @@ packages: resolution: {integrity: sha512-Wj71sXE4Q4AkGdG9Tvq1u/fquNz9EdG4LIJMwVVII7ashjD/8cf8fyIfJAjRr6YcsXnSE8cOGQPq1gqeR8z+3w==} dev: true - /@types/date-and-time@0.13.0: - resolution: {integrity: sha512-kHEncapIgrqaY8r2tyb19EvdKyhNjwheLl5cYTorsWJtURoI+oGm5ehW8CLAaq4dvu8x9z56FcXqAT4Mm5Nvzw==} - dev: true - /@types/debug@4.1.12: resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} dependencies: @@ -3796,8 +3796,8 @@ packages: is-data-view: 1.0.1 dev: true - /date-and-time@2.4.1: - resolution: {integrity: sha512-fG+ClATev+wHryqxOoGcTTegr5RhYE+tz/XHUkTQ/zvpWqQ90oOxjOhuMQ02bw87Oy9N3qBENCHHHSKdWJjgTg==} + /date-fns@4.1.0: + resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} dev: false /date.js@0.3.3: @@ -3837,6 +3837,18 @@ packages: ms: 2.1.3 dev: true + /debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: false + /debug@4.3.4(supports-color@8.1.1): resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} @@ -3848,6 +3860,7 @@ packages: dependencies: ms: 2.1.2 supports-color: 8.1.1 + dev: true /decamelize@4.0.0: resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} @@ -4956,6 +4969,7 @@ packages: /has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} + dev: true /has-property-descriptors@1.0.2: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} @@ -7381,6 +7395,7 @@ packages: engines: {node: '>=10'} dependencies: has-flag: 4.0.0 + dev: true /supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}