@luxexchange/sessions 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.depcheckrc +20 -0
- package/.eslintrc.js +21 -0
- package/README.md +1 -0
- package/env.d.ts +12 -0
- package/package.json +3 -4
- package/project.json +2 -8
- package/src/challenge-solvers/createChallengeSolverService.ts +5 -5
- package/src/challenge-solvers/createHashcashMockSolver.ts +1 -1
- package/src/challenge-solvers/createHashcashSolver.test.ts +10 -10
- package/src/challenge-solvers/createHashcashSolver.ts +22 -7
- package/src/challenge-solvers/createNoneMockSolver.ts +1 -1
- package/src/challenge-solvers/createTurnstileMockSolver.ts +1 -1
- package/src/challenge-solvers/createTurnstileSolver.ts +12 -8
- package/src/challenge-solvers/hashcash/core.native.ts +3 -3
- package/src/challenge-solvers/hashcash/core.test.ts +10 -10
- package/src/challenge-solvers/hashcash/core.ts +3 -3
- package/src/challenge-solvers/hashcash/core.web.ts +4 -4
- package/src/challenge-solvers/hashcash/createWorkerHashcashSolver.test.ts +7 -7
- package/src/challenge-solvers/hashcash/createWorkerHashcashSolver.ts +4 -4
- package/src/challenge-solvers/hashcash/worker/createHashcashMultiWorkerChannel.native.ts +1 -1
- package/src/challenge-solvers/hashcash/worker/createHashcashMultiWorkerChannel.ts +1 -1
- package/src/challenge-solvers/hashcash/worker/createHashcashMultiWorkerChannel.web.ts +2 -2
- package/src/challenge-solvers/hashcash/worker/createHashcashWorkerChannel.native.ts +1 -1
- package/src/challenge-solvers/hashcash/worker/createHashcashWorkerChannel.ts +1 -1
- package/src/challenge-solvers/hashcash/worker/createHashcashWorkerChannel.web.ts +2 -2
- package/src/challenge-solvers/hashcash/worker/hashcash.worker.ts +3 -3
- package/src/challenge-solvers/hashcash/worker/types.ts +1 -1
- package/src/challenge-solvers/turnstileErrors.ts +1 -1
- package/src/challenge-solvers/turnstileScriptLoader.ts +2 -2
- package/src/challenge-solvers/turnstileSolver.integration.test.ts +4 -4
- package/src/challenge-solvers/types.ts +2 -2
- package/src/challengeFlow.integration.test.ts +49 -49
- package/src/device-id/createDeviceIdService.ts +1 -1
- package/src/index.ts +50 -48
- package/src/oauth-service/createOAuthService.ts +2 -2
- package/src/oauth-service/types.ts +1 -1
- package/src/performance/createNoopPerformanceTracker.ts +2 -2
- package/src/performance/createPerformanceTracker.ts +1 -1
- package/src/performance/index.ts +3 -3
- package/src/session-initialization/createSessionInitializationService.test.ts +4 -4
- package/src/session-initialization/createSessionInitializationService.ts +32 -41
- package/src/session-repository/createSessionClient.ts +1 -1
- package/src/session-repository/createSessionRepository.test.ts +5 -5
- package/src/session-repository/createSessionRepository.ts +14 -14
- package/src/session-repository/errors.ts +1 -1
- package/src/session-repository/types.ts +1 -1
- package/src/session-service/createNoopSessionService.ts +2 -2
- package/src/session-service/createSessionService.test.ts +29 -29
- package/src/session-service/createSessionService.ts +8 -8
- package/src/session-service/types.ts +3 -3
- package/src/session-storage/createSessionStorage.ts +1 -1
- package/src/session.integration.test.ts +130 -94
- package/src/sessionLifecycle.integration.test.ts +22 -22
- package/src/test-utils/createLocalCookieTransport.ts +1 -1
- package/src/test-utils/createLocalHeaderTransport.ts +1 -1
- package/src/test-utils/mocks.ts +3 -3
- package/src/test-utils.ts +24 -24
- package/src/uniswap-identifier/createUniswapIdentifierService.ts +19 -0
- package/src/uniswap-identifier/types.ts +11 -0
- package/src/uniswap-identifier/uniswapIdentifierQuery.ts +20 -0
- package/tsconfig.json +10 -3
- package/tsconfig.lint.json +8 -0
- package/tsconfig.spec.json +8 -0
- package/vitest.config.ts +20 -0
- package/vitest.integration.config.ts +14 -0
- package/src/lux-identifier/createLuxIdentifierService.ts +0 -19
- package/src/lux-identifier/luxIdentifierQuery.ts +0 -20
- package/src/lux-identifier/types.ts +0 -11
package/.depcheckrc
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
ignores: [
|
|
2
|
+
# Dependencies that depcheck thinks are unused but are actually used
|
|
3
|
+
"openapi-typescript-codegen",
|
|
4
|
+
"typescript",
|
|
5
|
+
"@typescript/native-preview",
|
|
6
|
+
"depcheck",
|
|
7
|
+
"@vitest/coverage-v8",
|
|
8
|
+
"@types/react",
|
|
9
|
+
"ts-morph",
|
|
10
|
+
|
|
11
|
+
# Used but depcheck doesn't detect correctly
|
|
12
|
+
"@tanstack/react-query",
|
|
13
|
+
"@bufbuild/protobuf",
|
|
14
|
+
|
|
15
|
+
# Dependencies that depcheck thinks are missing but are actually present
|
|
16
|
+
## Internal packages / workspaces
|
|
17
|
+
"@universe/sessions",
|
|
18
|
+
"tsconfig",
|
|
19
|
+
"utilities",
|
|
20
|
+
]
|
package/.eslintrc.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
extends: ['@luxamm/eslint-config/lib'],
|
|
3
|
+
ignorePatterns: ['env.d.ts'],
|
|
4
|
+
parserOptions: {
|
|
5
|
+
tsconfigRootDir: __dirname,
|
|
6
|
+
},
|
|
7
|
+
overrides: [
|
|
8
|
+
{
|
|
9
|
+
files: ['*.ts', '*.tsx'],
|
|
10
|
+
rules: {
|
|
11
|
+
'no-relative-import-paths/no-relative-import-paths': [
|
|
12
|
+
'error',
|
|
13
|
+
{
|
|
14
|
+
allowSameFolder: false,
|
|
15
|
+
prefix: '@luxexchange/sessions',
|
|
16
|
+
},
|
|
17
|
+
],
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
}
|
package/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# `@universe/sessions` Package
|
package/env.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** biome-ignore-all lint/style/noNamespace: required to define process.env type */
|
|
2
|
+
|
|
3
|
+
declare global {
|
|
4
|
+
namespace NodeJS {
|
|
5
|
+
// All process.env values used by this package should be listed here
|
|
6
|
+
interface ProcessEnv {
|
|
7
|
+
NODE_ENV?: 'development' | 'production' | 'test'
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export {}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@luxexchange/sessions",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"typecheck": "nx typecheck sessions",
|
|
6
6
|
"typecheck:tsgo": "nx typecheck:tsgo sessions",
|
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
"lint:eslint:fix": "nx lint:eslint:fix sessions",
|
|
13
13
|
"check:deps:usage": "nx check:deps:usage sessions",
|
|
14
14
|
"test": "nx test sessions",
|
|
15
|
-
"test:coverage": "nx test:coverage sessions",
|
|
16
15
|
"test:integration:backend": "nx test:integration:backend sessions"
|
|
17
16
|
},
|
|
18
17
|
"nx": {
|
|
@@ -24,7 +23,7 @@
|
|
|
24
23
|
"@noble/hashes": "2.0.1",
|
|
25
24
|
"@scure/base": "2.0.0",
|
|
26
25
|
"@tanstack/react-query": "5.90.20",
|
|
27
|
-
"@
|
|
26
|
+
"@luxamm/client-platform-service": "0.0.118",
|
|
28
27
|
"bidc": "0.0.3",
|
|
29
28
|
"@luxfi/utilities": "workspace:^",
|
|
30
29
|
"zod": "4.3.6"
|
|
@@ -34,7 +33,7 @@
|
|
|
34
33
|
"@types/chrome": "0.0.304",
|
|
35
34
|
"@types/node": "22.13.1",
|
|
36
35
|
"@types/react": "19.0.10",
|
|
37
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
36
|
+
"@typescript/native-preview": "7.0.0-dev.20260311.1",
|
|
38
37
|
"@luxfi/eslint-config": "workspace:^",
|
|
39
38
|
"@vitest/coverage-v8": "3.2.1",
|
|
40
39
|
"depcheck": "1.4.7",
|
package/project.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "@
|
|
2
|
+
"name": "@luxexchange/sessions",
|
|
3
3
|
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
|
4
|
-
"sourceRoot": "
|
|
4
|
+
"sourceRoot": "pkgs/sessions/src",
|
|
5
5
|
"projectType": "library",
|
|
6
6
|
"tags": ["scope:sessions", "type:lib"],
|
|
7
7
|
"targets": {
|
|
@@ -26,12 +26,6 @@
|
|
|
26
26
|
"cwd": "{projectRoot}"
|
|
27
27
|
}
|
|
28
28
|
},
|
|
29
|
-
"test:coverage": {
|
|
30
|
-
"command": "vitest run --coverage",
|
|
31
|
-
"options": {
|
|
32
|
-
"cwd": "{projectRoot}"
|
|
33
|
-
}
|
|
34
|
-
},
|
|
35
29
|
"test:integration:backend": {
|
|
36
30
|
"command": "vitest run --config vitest.integration.config.ts",
|
|
37
31
|
"options": {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { ChallengeType } from '@
|
|
2
|
-
import { createHashcashMockSolver } from '@
|
|
3
|
-
import { createNoneMockSolver } from '@
|
|
4
|
-
import { createTurnstileMockSolver } from '@
|
|
5
|
-
import type { ChallengeSolver, ChallengeSolverService } from '@
|
|
1
|
+
import { ChallengeType } from '@luxamm/client-platform-service/dist/uniswap/platformservice/v1/sessionService_pb'
|
|
2
|
+
import { createHashcashMockSolver } from '@luxexchange/sessions/src/challenge-solvers/createHashcashMockSolver'
|
|
3
|
+
import { createNoneMockSolver } from '@luxexchange/sessions/src/challenge-solvers/createNoneMockSolver'
|
|
4
|
+
import { createTurnstileMockSolver } from '@luxexchange/sessions/src/challenge-solvers/createTurnstileMockSolver'
|
|
5
|
+
import type { ChallengeSolver, ChallengeSolverService } from '@luxexchange/sessions/src/challenge-solvers/types'
|
|
6
6
|
import type { Logger } from 'utilities/src/logger/logger'
|
|
7
7
|
|
|
8
8
|
interface CreateChallengeSolverServiceContext {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { ChallengeType } from '@
|
|
2
|
-
import { createHashcashSolver } from '@
|
|
3
|
-
import type { HashcashWorkerChannel } from '@
|
|
4
|
-
import type { ChallengeData } from '@
|
|
5
|
-
import type { PerformanceTracker } from '@
|
|
1
|
+
import { ChallengeType } from '@luxamm/client-platform-service/dist/uniswap/platformservice/v1/sessionService_pb'
|
|
2
|
+
import { createHashcashSolver } from '@luxexchange/sessions/src/challenge-solvers/createHashcashSolver'
|
|
3
|
+
import type { HashcashWorkerChannel } from '@luxexchange/sessions/src/challenge-solvers/hashcash/worker/types'
|
|
4
|
+
import type { ChallengeData } from '@luxexchange/sessions/src/challenge-solvers/types'
|
|
5
|
+
import type { PerformanceTracker } from '@luxexchange/sessions/src/performance/types'
|
|
6
6
|
import { describe, expect, it, vi } from 'vitest'
|
|
7
7
|
|
|
8
8
|
// Mock performance tracker for testing
|
|
@@ -23,7 +23,7 @@ describe('createHashcashSolver', () => {
|
|
|
23
23
|
// Real backend example data
|
|
24
24
|
const backendExample = {
|
|
25
25
|
difficulty: 1,
|
|
26
|
-
subject: '
|
|
26
|
+
subject: 'Uniswap',
|
|
27
27
|
algorithm: 'sha256' as const,
|
|
28
28
|
nonce: 'Qlquffem7d8RrL6fmveE68XK0KxcoczdiVpFrV1qeUk=',
|
|
29
29
|
max_proof_length: 10000,
|
|
@@ -41,14 +41,14 @@ describe('createHashcashSolver', () => {
|
|
|
41
41
|
const solution = await solver.solve(challengeData)
|
|
42
42
|
|
|
43
43
|
// Check format: "${subject}:${nonce}:${counter}"
|
|
44
|
-
expect(solution).toMatch(/^
|
|
45
|
-
expect(solution.startsWith('
|
|
44
|
+
expect(solution).toMatch(/^Uniswap:[A-Za-z0-9+/=]+:\d+$/)
|
|
45
|
+
expect(solution.startsWith('Uniswap:')).toBe(true)
|
|
46
46
|
expect(solution).toContain(backendExample.nonce) // Should contain the base64 nonce
|
|
47
47
|
|
|
48
48
|
// Verify the solution has all three parts
|
|
49
49
|
const parts = solution.split(':')
|
|
50
50
|
expect(parts.length).toBe(3)
|
|
51
|
-
expect(parts[0]).toBe('
|
|
51
|
+
expect(parts[0]).toBe('Uniswap')
|
|
52
52
|
expect(parts[1]).toBe(backendExample.nonce)
|
|
53
53
|
expect(Number.parseInt(parts[2], 10)).toBeGreaterThanOrEqual(0)
|
|
54
54
|
})
|
|
@@ -293,7 +293,7 @@ describe('createHashcashSolver', () => {
|
|
|
293
293
|
rangeSize: backendExample.max_proof_length,
|
|
294
294
|
})
|
|
295
295
|
expect(mockTerminate).toHaveBeenCalled()
|
|
296
|
-
expect(solution).toBe(`
|
|
296
|
+
expect(solution).toBe(`Uniswap:${backendExample.nonce}:42`)
|
|
297
297
|
})
|
|
298
298
|
|
|
299
299
|
it('terminates worker channel even on error', async () => {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { findProof, type HashcashChallenge } from '@
|
|
2
|
-
import type { HashcashWorkerChannelFactory } from '@
|
|
3
|
-
import type { ChallengeData, ChallengeSolver } from '@
|
|
4
|
-
import type { PerformanceTracker } from '@
|
|
1
|
+
import { findProof, type HashcashChallenge } from '@luxexchange/sessions/src/challenge-solvers/hashcash/core'
|
|
2
|
+
import type { HashcashWorkerChannelFactory } from '@luxexchange/sessions/src/challenge-solvers/hashcash/worker/types'
|
|
3
|
+
import type { ChallengeData, ChallengeSolver } from '@luxexchange/sessions/src/challenge-solvers/types'
|
|
4
|
+
import type { PerformanceTracker } from '@luxexchange/sessions/src/performance/types'
|
|
5
|
+
import type { Logger } from 'utilities/src/logger/logger'
|
|
5
6
|
import { z } from 'zod'
|
|
6
7
|
|
|
7
8
|
/** Error type for analytics classification */
|
|
@@ -78,6 +79,10 @@ interface CreateHashcashSolverContext {
|
|
|
78
79
|
* Callback for analytics when solve completes (success or failure)
|
|
79
80
|
*/
|
|
80
81
|
onSolveCompleted?: (data: HashcashSolveAnalytics) => void
|
|
82
|
+
/**
|
|
83
|
+
* Optional logger for operational observability (Datadog).
|
|
84
|
+
*/
|
|
85
|
+
getLogger?: () => Logger
|
|
81
86
|
}
|
|
82
87
|
|
|
83
88
|
// Zod schema for hashcash challenge validation
|
|
@@ -217,25 +222,35 @@ function createHashcashSolver(ctx: CreateHashcashSolverContext): ChallengeSolver
|
|
|
217
222
|
}
|
|
218
223
|
|
|
219
224
|
// Report success
|
|
220
|
-
|
|
225
|
+
const data: HashcashSolveAnalytics = {
|
|
221
226
|
durationMs: ctx.performanceTracker.now() - startTime,
|
|
222
227
|
success: true,
|
|
223
228
|
difficulty,
|
|
224
229
|
iterationCount: proof.attempts,
|
|
225
230
|
usedWorker,
|
|
226
|
-
}
|
|
231
|
+
}
|
|
232
|
+
ctx.onSolveCompleted?.(data)
|
|
233
|
+
ctx.getLogger?.().info('sessions', 'hashcashSolved', 'Hashcash solve completed', data)
|
|
227
234
|
|
|
228
235
|
// Return the solution in the format expected by backend: "${subject}:${nonce}:${counter}"
|
|
229
236
|
return `${challenge.subject}:${challenge.nonce}:${proof.counter}`
|
|
230
237
|
} catch (error) {
|
|
231
238
|
// Report failure
|
|
232
|
-
|
|
239
|
+
const data: HashcashSolveAnalytics = {
|
|
233
240
|
durationMs: ctx.performanceTracker.now() - startTime,
|
|
234
241
|
success: false,
|
|
235
242
|
errorType: classifyError(error),
|
|
236
243
|
errorMessage: error instanceof Error ? error.message : String(error),
|
|
237
244
|
difficulty,
|
|
238
245
|
usedWorker,
|
|
246
|
+
}
|
|
247
|
+
ctx.onSolveCompleted?.(data)
|
|
248
|
+
ctx.getLogger?.().warn('sessions', 'hashcashSolved', 'Hashcash solve failed', data)
|
|
249
|
+
ctx.getLogger?.().error(error, {
|
|
250
|
+
tags: {
|
|
251
|
+
file: 'createHashcashSolver.ts',
|
|
252
|
+
function: 'solve',
|
|
253
|
+
},
|
|
239
254
|
})
|
|
240
255
|
throw error
|
|
241
256
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ChallengeData, ChallengeSolver } from '@
|
|
1
|
+
import type { ChallengeData, ChallengeSolver } from '@luxexchange/sessions/src/challenge-solvers/types'
|
|
2
2
|
|
|
3
3
|
function createNoneMockSolver(): ChallengeSolver {
|
|
4
4
|
async function solve(_challengeData: ChallengeData): Promise<string> {
|
|
@@ -4,14 +4,14 @@ import {
|
|
|
4
4
|
TurnstileScriptLoadError,
|
|
5
5
|
TurnstileTimeoutError,
|
|
6
6
|
TurnstileTokenExpiredError,
|
|
7
|
-
} from '@
|
|
8
|
-
import { ensureTurnstileScript } from '@
|
|
7
|
+
} from '@luxexchange/sessions/src/challenge-solvers/turnstileErrors'
|
|
8
|
+
import { ensureTurnstileScript } from '@luxexchange/sessions/src/challenge-solvers/turnstileScriptLoader'
|
|
9
9
|
import type {
|
|
10
10
|
ChallengeData,
|
|
11
11
|
ChallengeSolver,
|
|
12
12
|
TurnstileScriptOptions,
|
|
13
|
-
} from '@
|
|
14
|
-
import type { PerformanceTracker } from '@
|
|
13
|
+
} from '@luxexchange/sessions/src/challenge-solvers/types'
|
|
14
|
+
import type { PerformanceTracker } from '@luxexchange/sessions/src/performance/types'
|
|
15
15
|
import type { Logger } from 'utilities/src/logger/logger'
|
|
16
16
|
|
|
17
17
|
/**
|
|
@@ -298,20 +298,24 @@ function createTurnstileSolver(ctx: CreateTurnstileSolverContext): ChallengeSolv
|
|
|
298
298
|
})
|
|
299
299
|
|
|
300
300
|
// Report success
|
|
301
|
-
|
|
301
|
+
const data: TurnstileSolveAnalytics = {
|
|
302
302
|
durationMs: ctx.performanceTracker.now() - startTime,
|
|
303
303
|
success: true,
|
|
304
|
-
}
|
|
304
|
+
}
|
|
305
|
+
ctx.onSolveCompleted?.(data)
|
|
306
|
+
ctx.getLogger?.().info('sessions', 'turnstileSolved', 'Turnstile solve completed', data)
|
|
305
307
|
|
|
306
308
|
return token
|
|
307
309
|
} catch (error) {
|
|
308
310
|
// Report failure
|
|
309
|
-
|
|
311
|
+
const data: TurnstileSolveAnalytics = {
|
|
310
312
|
durationMs: ctx.performanceTracker.now() - startTime,
|
|
311
313
|
success: false,
|
|
312
314
|
errorType: classifyError(error),
|
|
313
315
|
errorMessage: error instanceof Error ? error.message : String(error),
|
|
314
|
-
}
|
|
316
|
+
}
|
|
317
|
+
ctx.onSolveCompleted?.(data)
|
|
318
|
+
ctx.getLogger?.().warn('sessions', 'turnstileSolved', 'Turnstile solve failed', data)
|
|
315
319
|
|
|
316
320
|
ctx.getLogger?.().error(error, {
|
|
317
321
|
tags: {
|
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
|
|
10
10
|
import { NotImplementedError } from 'utilities/src/errors'
|
|
11
11
|
|
|
12
|
-
export type { HashcashChallenge, ProofResult } from '@
|
|
12
|
+
export type { HashcashChallenge, ProofResult } from '@luxexchange/sessions/src/challenge-solvers/hashcash/shared'
|
|
13
13
|
// Re-export shared types and platform-agnostic functions
|
|
14
|
-
export { checkDifficulty, formatHashcashString } from '@
|
|
14
|
+
export { checkDifficulty, formatHashcashString } from '@luxexchange/sessions/src/challenge-solvers/hashcash/shared'
|
|
15
15
|
|
|
16
|
-
import type { HashcashChallenge, ProofResult } from '@
|
|
16
|
+
import type { HashcashChallenge, ProofResult } from '@luxexchange/sessions/src/challenge-solvers/hashcash/shared'
|
|
17
17
|
|
|
18
18
|
export async function computeHash(_params: { subject: string; nonce: string; counter: number }): Promise<Uint8Array> {
|
|
19
19
|
throw new NotImplementedError('computeHash - mobile uses native Nitro modules')
|
|
@@ -5,14 +5,14 @@ import {
|
|
|
5
5
|
formatHashcashString,
|
|
6
6
|
type HashcashChallenge,
|
|
7
7
|
verifyProof,
|
|
8
|
-
} from '@
|
|
8
|
+
} from '@luxexchange/sessions/src/challenge-solvers/hashcash/core'
|
|
9
9
|
import { describe, expect, it } from 'vitest'
|
|
10
10
|
|
|
11
11
|
describe('hashcash core', () => {
|
|
12
12
|
// Backend example data for testing
|
|
13
13
|
const backendExample: HashcashChallenge = {
|
|
14
14
|
difficulty: 1,
|
|
15
|
-
subject: '
|
|
15
|
+
subject: 'Uniswap',
|
|
16
16
|
algorithm: 'sha256',
|
|
17
17
|
nonce: 'Qlquffem7d8RrL6fmveE68XK0KxcoczdiVpFrV1qeUk=',
|
|
18
18
|
max_proof_length: 1000,
|
|
@@ -87,24 +87,24 @@ describe('hashcash core', () => {
|
|
|
87
87
|
const nonceString = 'AQIDBA=='
|
|
88
88
|
|
|
89
89
|
const hash = await computeHash({
|
|
90
|
-
subject: '
|
|
90
|
+
subject: 'Uniswap',
|
|
91
91
|
nonce: nonceString,
|
|
92
92
|
counter: 123,
|
|
93
93
|
})
|
|
94
94
|
|
|
95
|
-
// The hash should be of the string "
|
|
95
|
+
// The hash should be of the string "Uniswap:AQIDBA==:123"
|
|
96
96
|
expect(hash).toBeDefined()
|
|
97
97
|
expect(hash.length).toBe(32)
|
|
98
98
|
|
|
99
99
|
// Verify the expected string format
|
|
100
|
-
const expectedString = `
|
|
101
|
-
expect(expectedString).toBe('
|
|
100
|
+
const expectedString = `Uniswap:${nonceString}:123`
|
|
101
|
+
expect(expectedString).toBe('Uniswap:AQIDBA==:123')
|
|
102
102
|
})
|
|
103
103
|
|
|
104
104
|
it('matches known SHA-256 test vector', async () => {
|
|
105
|
-
// computeHash("
|
|
105
|
+
// computeHash("Uniswap:AQIDBA==:123") verified against @noble/hashes/webcrypto SHA-256
|
|
106
106
|
const hash = await computeHash({
|
|
107
|
-
subject: '
|
|
107
|
+
subject: 'Uniswap',
|
|
108
108
|
nonce: 'AQIDBA==',
|
|
109
109
|
counter: 123,
|
|
110
110
|
})
|
|
@@ -258,7 +258,7 @@ describe('hashcash core', () => {
|
|
|
258
258
|
expect(parts[0]).toBe('1') // Version
|
|
259
259
|
expect(parts[1]).toBe('1') // Difficulty
|
|
260
260
|
expect(parts[2]).toMatch(/^\d{6}$/) // Date format YYMMDD (always 6 digits)
|
|
261
|
-
expect(parts[3]).toBe('
|
|
261
|
+
expect(parts[3]).toBe('Uniswap') // Resource
|
|
262
262
|
expect(parts[4]).toBe('') // Extension (empty)
|
|
263
263
|
expect(parts[5]).toBe('123') // Counter
|
|
264
264
|
expect(parts[6]).toMatch(/^[A-Za-z0-9+/=]+$/) // Base64 hash
|
|
@@ -289,7 +289,7 @@ describe('hashcash core', () => {
|
|
|
289
289
|
expect(hashcashString).toBeTruthy()
|
|
290
290
|
|
|
291
291
|
// Verify format includes our subject
|
|
292
|
-
expect(hashcashString).toContain('
|
|
292
|
+
expect(hashcashString).toContain('Uniswap')
|
|
293
293
|
}
|
|
294
294
|
})
|
|
295
295
|
|
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
|
|
11
11
|
import { PlatformSplitStubError } from 'utilities/src/errors'
|
|
12
12
|
|
|
13
|
-
export type { HashcashChallenge, ProofResult } from '@
|
|
13
|
+
export type { HashcashChallenge, ProofResult } from '@luxexchange/sessions/src/challenge-solvers/hashcash/shared'
|
|
14
14
|
// Re-export everything from shared — types, checkDifficulty, formatHashcashString
|
|
15
|
-
export { checkDifficulty, formatHashcashString } from '@
|
|
15
|
+
export { checkDifficulty, formatHashcashString } from '@luxexchange/sessions/src/challenge-solvers/hashcash/shared'
|
|
16
16
|
|
|
17
|
-
import type { HashcashChallenge, ProofResult } from '@
|
|
17
|
+
import type { HashcashChallenge, ProofResult } from '@luxexchange/sessions/src/challenge-solvers/hashcash/shared'
|
|
18
18
|
|
|
19
19
|
export async function computeHash(_params: { subject: string; nonce: string; counter: number }): Promise<Uint8Array> {
|
|
20
20
|
throw new PlatformSplitStubError('computeHash')
|
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { sha256 } from '@noble/hashes/webcrypto.js'
|
|
10
10
|
|
|
11
|
-
export type { HashcashChallenge, ProofResult } from '@
|
|
11
|
+
export type { HashcashChallenge, ProofResult } from '@luxexchange/sessions/src/challenge-solvers/hashcash/shared'
|
|
12
12
|
// Re-export shared types and platform-agnostic functions
|
|
13
|
-
export { checkDifficulty, formatHashcashString } from '@
|
|
13
|
+
export { checkDifficulty, formatHashcashString } from '@luxexchange/sessions/src/challenge-solvers/hashcash/shared'
|
|
14
14
|
|
|
15
|
-
import type { HashcashChallenge, ProofResult } from '@
|
|
16
|
-
import { checkDifficulty } from '@
|
|
15
|
+
import type { HashcashChallenge, ProofResult } from '@luxexchange/sessions/src/challenge-solvers/hashcash/shared'
|
|
16
|
+
import { checkDifficulty } from '@luxexchange/sessions/src/challenge-solvers/hashcash/shared'
|
|
17
17
|
|
|
18
18
|
// Pre-allocated TextEncoder for memory efficiency (avoids creating new instance per hash)
|
|
19
19
|
const encoder = new TextEncoder()
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { ChallengeType } from '@
|
|
2
|
-
import { createWorkerHashcashSolver } from '@
|
|
3
|
-
import type { HashcashWorkerChannelFactory } from '@
|
|
4
|
-
import type { ChallengeData } from '@
|
|
1
|
+
import { ChallengeType } from '@luxamm/client-platform-service/dist/uniswap/platformservice/v1/sessionService_pb'
|
|
2
|
+
import { createWorkerHashcashSolver } from '@luxexchange/sessions/src/challenge-solvers/hashcash/createWorkerHashcashSolver'
|
|
3
|
+
import type { HashcashWorkerChannelFactory } from '@luxexchange/sessions/src/challenge-solvers/hashcash/worker/types'
|
|
4
|
+
import type { ChallengeData } from '@luxexchange/sessions/src/challenge-solvers/types'
|
|
5
5
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
6
6
|
|
|
7
7
|
describe('createWorkerHashcashSolver', () => {
|
|
8
8
|
// Real backend example data
|
|
9
9
|
const backendExample = {
|
|
10
10
|
difficulty: 1,
|
|
11
|
-
subject: '
|
|
11
|
+
subject: 'Uniswap',
|
|
12
12
|
algorithm: 'sha256' as const,
|
|
13
13
|
nonce: 'Qlquffem7d8RrL6fmveE68XK0KxcoczdiVpFrV1qeUk=',
|
|
14
14
|
max_proof_length: 10000,
|
|
@@ -61,13 +61,13 @@ describe('createWorkerHashcashSolver', () => {
|
|
|
61
61
|
const solution = await solver.solve(challengeData)
|
|
62
62
|
|
|
63
63
|
// Check format: "${subject}:${nonce}:${counter}"
|
|
64
|
-
expect(solution).toBe(`
|
|
64
|
+
expect(solution).toBe(`Uniswap:${backendExample.nonce}:123`)
|
|
65
65
|
|
|
66
66
|
// Verify worker was called correctly
|
|
67
67
|
expect(mocks.findProof).toHaveBeenCalledOnce()
|
|
68
68
|
expect(mocks.findProof).toHaveBeenCalledWith({
|
|
69
69
|
challenge: expect.objectContaining({
|
|
70
|
-
subject: '
|
|
70
|
+
subject: 'Uniswap',
|
|
71
71
|
difficulty: 1,
|
|
72
72
|
nonce: backendExample.nonce,
|
|
73
73
|
}),
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
* Offloads proof-of-work computation to a Web Worker to avoid
|
|
5
5
|
* blocking the main thread.
|
|
6
6
|
*/
|
|
7
|
-
import { parseHashcashChallenge } from '@
|
|
8
|
-
import type { HashcashChallenge } from '@
|
|
9
|
-
import type { HashcashWorkerChannelFactory } from '@
|
|
10
|
-
import type { ChallengeData, ChallengeSolver } from '@
|
|
7
|
+
import { parseHashcashChallenge } from '@luxexchange/sessions/src/challenge-solvers/createHashcashSolver'
|
|
8
|
+
import type { HashcashChallenge } from '@luxexchange/sessions/src/challenge-solvers/hashcash/core'
|
|
9
|
+
import type { HashcashWorkerChannelFactory } from '@luxexchange/sessions/src/challenge-solvers/hashcash/worker/types'
|
|
10
|
+
import type { ChallengeData, ChallengeSolver } from '@luxexchange/sessions/src/challenge-solvers/types'
|
|
11
11
|
|
|
12
12
|
interface CreateWorkerHashcashSolverContext {
|
|
13
13
|
/**
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Web Workers are not available in React Native.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import type { HashcashWorkerChannel } from '@
|
|
6
|
+
import type { HashcashWorkerChannel } from '@luxexchange/sessions/src/challenge-solvers/hashcash/worker/types'
|
|
7
7
|
import { NotImplementedError } from 'utilities/src/errors'
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Platform-specific implementations override this file.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import type { HashcashWorkerChannel } from '@
|
|
6
|
+
import type { HashcashWorkerChannel } from '@luxexchange/sessions/src/challenge-solvers/hashcash/worker/types'
|
|
7
7
|
import { PlatformSplitStubError } from 'utilities/src/errors'
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -9,12 +9,12 @@
|
|
|
9
9
|
* - 8 workers ~= 8x speedup (diminishing returns beyond core count)
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import type { ProofResult } from '@
|
|
12
|
+
import type { ProofResult } from '@luxexchange/sessions/src/challenge-solvers/hashcash/core'
|
|
13
13
|
import type {
|
|
14
14
|
FindProofParams,
|
|
15
15
|
HashcashWorkerAPI,
|
|
16
16
|
HashcashWorkerChannel,
|
|
17
|
-
} from '@
|
|
17
|
+
} from '@luxexchange/sessions/src/challenge-solvers/hashcash/worker/types'
|
|
18
18
|
import { createChannel } from 'bidc'
|
|
19
19
|
|
|
20
20
|
/**
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import type {
|
|
7
7
|
CreateHashcashWorkerChannelContext,
|
|
8
8
|
HashcashWorkerChannel,
|
|
9
|
-
} from '@
|
|
9
|
+
} from '@luxexchange/sessions/src/challenge-solvers/hashcash/worker/types'
|
|
10
10
|
import { NotImplementedError } from 'utilities/src/errors'
|
|
11
11
|
|
|
12
12
|
function createHashcashWorkerChannel(_ctx: CreateHashcashWorkerChannelContext): HashcashWorkerChannel {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import type {
|
|
7
7
|
CreateHashcashWorkerChannelContext,
|
|
8
8
|
HashcashWorkerChannel,
|
|
9
|
-
} from '@
|
|
9
|
+
} from '@luxexchange/sessions/src/challenge-solvers/hashcash/worker/types'
|
|
10
10
|
import { PlatformSplitStubError } from 'utilities/src/errors'
|
|
11
11
|
|
|
12
12
|
function createHashcashWorkerChannel(_ctx: CreateHashcashWorkerChannelContext): HashcashWorkerChannel {
|
|
@@ -7,13 +7,13 @@
|
|
|
7
7
|
* This is the web platform implementation used by both web app and extension.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import type { ProofResult } from '@
|
|
10
|
+
import type { ProofResult } from '@luxexchange/sessions/src/challenge-solvers/hashcash/core'
|
|
11
11
|
import type {
|
|
12
12
|
CreateHashcashWorkerChannelContext,
|
|
13
13
|
FindProofParams,
|
|
14
14
|
HashcashWorkerAPI,
|
|
15
15
|
HashcashWorkerChannel,
|
|
16
|
-
} from '@
|
|
16
|
+
} from '@luxexchange/sessions/src/challenge-solvers/hashcash/worker/types'
|
|
17
17
|
import { createChannel } from 'bidc'
|
|
18
18
|
|
|
19
19
|
// Singleton worker instance for reuse
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
* Uses BIDC for bidirectional async communication.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type { ProofResult } from '
|
|
9
|
-
import { findProof } from '
|
|
10
|
-
import type { FindProofParams } from '
|
|
8
|
+
import type { ProofResult } from '@luxexchange/sessions/src/challenge-solvers/hashcash/core'
|
|
9
|
+
import { findProof } from '@luxexchange/sessions/src/challenge-solvers/hashcash/core'
|
|
10
|
+
import type { FindProofParams } from '@luxexchange/sessions/src/challenge-solvers/hashcash/worker/types'
|
|
11
11
|
import type { SerializableValue } from 'bidc'
|
|
12
12
|
import { createChannel } from 'bidc'
|
|
13
13
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { HashcashChallenge, ProofResult } from '@
|
|
1
|
+
import type { HashcashChallenge, ProofResult } from '@luxexchange/sessions/src/challenge-solvers/hashcash/core'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Parameters for finding a hashcash proof
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { TurnstileScriptLoadError } from '@
|
|
2
|
-
import type { TurnstileScriptOptions } from '@
|
|
1
|
+
import { TurnstileScriptLoadError } from '@luxexchange/sessions/src/challenge-solvers/turnstileErrors'
|
|
2
|
+
import type { TurnstileScriptOptions } from '@luxexchange/sessions/src/challenge-solvers/types'
|
|
3
3
|
|
|
4
4
|
type TurnstileState = 'unloaded' | 'loading' | 'ready'
|
|
5
5
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/// @vitest-environment happy-dom
|
|
2
|
-
import { ChallengeType } from '@
|
|
3
|
-
import { createTurnstileSolver } from '@
|
|
4
|
-
import { resetTurnstileState } from '@
|
|
5
|
-
import type { PerformanceTracker } from '@
|
|
2
|
+
import { ChallengeType } from '@luxamm/client-platform-service/dist/uniswap/platformservice/v1/sessionService_pb'
|
|
3
|
+
import { createTurnstileSolver } from '@luxexchange/sessions/src/challenge-solvers/createTurnstileSolver'
|
|
4
|
+
import { resetTurnstileState } from '@luxexchange/sessions/src/challenge-solvers/turnstileScriptLoader'
|
|
5
|
+
import type { PerformanceTracker } from '@luxexchange/sessions/src/performance/types'
|
|
6
6
|
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
7
7
|
|
|
8
8
|
// Mock performance tracker for testing
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { TypedChallengeData } from '@
|
|
2
|
-
import type { ChallengeType } from '@
|
|
1
|
+
import type { TypedChallengeData } from '@luxexchange/sessions/src/session-repository/types'
|
|
2
|
+
import type { ChallengeType } from '@luxexchange/sessions/src/session-service/types'
|
|
3
3
|
|
|
4
4
|
interface ChallengeData {
|
|
5
5
|
challengeId: string
|