@wishknish/knishio-client-ts 0.7.0
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/LICENSE +674 -0
- package/README.md +425 -0
- package/dist/index.cjs +9961 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.iife.js +32241 -0
- package/dist/index.iife.js.map +1 -0
- package/dist/index.js +9853 -0
- package/dist/index.js.map +1 -0
- package/package.json +113 -0
- package/src/AuthToken.ts +214 -0
- package/src/KnishIOClient.ts +2020 -0
- package/src/constants.ts +398 -0
- package/src/core/Atom.ts +646 -0
- package/src/core/AtomMeta.ts +278 -0
- package/src/core/Meta.ts +428 -0
- package/src/core/Molecule.ts +825 -0
- package/src/core/PolicyMeta.ts +130 -0
- package/src/core/TokenUnit.ts +148 -0
- package/src/core/Wallet.ts +467 -0
- package/src/exception/AtomIndexException.ts +97 -0
- package/src/exception/AtomsMissingException.ts +109 -0
- package/src/exception/AuthorizationRejectedException.ts +63 -0
- package/src/exception/BalanceInsufficientException.ts +58 -0
- package/src/exception/BaseException.ts +275 -0
- package/src/exception/BatchIdException.ts +58 -0
- package/src/exception/CodeException.ts +119 -0
- package/src/exception/DecryptionKeyException.ts +65 -0
- package/src/exception/InvalidResponseException.ts +112 -0
- package/src/exception/MetaMissingException.ts +58 -0
- package/src/exception/MolecularHashMismatchException.ts +115 -0
- package/src/exception/MolecularHashMissingException.ts +58 -0
- package/src/exception/NegativeAmountException.ts +58 -0
- package/src/exception/PolicyInvalidException.ts +58 -0
- package/src/exception/SignatureMalformedException.ts +58 -0
- package/src/exception/SignatureMismatchException.ts +98 -0
- package/src/exception/StackableUnitAmountException.ts +65 -0
- package/src/exception/StackableUnitDecimalsException.ts +65 -0
- package/src/exception/TransferBalanceException.ts +98 -0
- package/src/exception/TransferMalformedException.ts +58 -0
- package/src/exception/TransferMismatchedException.ts +58 -0
- package/src/exception/TransferRemainderException.ts +58 -0
- package/src/exception/TransferToSelfException.ts +58 -0
- package/src/exception/TransferUnbalancedException.ts +58 -0
- package/src/exception/UnauthenticatedException.ts +147 -0
- package/src/exception/WalletCredentialException.ts +108 -0
- package/src/exception/WalletShadowException.ts +65 -0
- package/src/exception/WrongTokenTypeException.ts +58 -0
- package/src/exception/index.ts +272 -0
- package/src/index.ts +512 -0
- package/src/instance/rules/Callback.ts +257 -0
- package/src/instance/rules/Condition.ts +96 -0
- package/src/instance/rules/Meta.ts +163 -0
- package/src/instance/rules/Rule.ts +29 -0
- package/src/instance/rules/exception/RuleArgumentException.ts +65 -0
- package/src/libraries/CheckMolecule.ts +581 -0
- package/src/libraries/Decimal.ts +94 -0
- package/src/libraries/Dot.ts +202 -0
- package/src/libraries/GraphQLClient.ts +276 -0
- package/src/libraries/Hex.ts +155 -0
- package/src/libraries/UrqlClientWrapper.ts +336 -0
- package/src/libraries/array.ts +91 -0
- package/src/libraries/crypto.ts +816 -0
- package/src/libraries/strings.ts +458 -0
- package/src/mutation/Mutation.ts +103 -0
- package/src/mutation/MutationActiveSession.ts +108 -0
- package/src/mutation/MutationClaimShadowWallet.ts +91 -0
- package/src/mutation/MutationCreateIdentifier.ts +86 -0
- package/src/mutation/MutationCreateMeta.ts +92 -0
- package/src/mutation/MutationCreateRule.ts +90 -0
- package/src/mutation/MutationCreateToken.ts +92 -0
- package/src/mutation/MutationCreateWallet.ts +78 -0
- package/src/mutation/MutationDepositBufferToken.ts +72 -0
- package/src/mutation/MutationLinkIdentifier.ts +87 -0
- package/src/mutation/MutationProposeMolecule.ts +147 -0
- package/src/mutation/MutationRequestAuthorization.ts +77 -0
- package/src/mutation/MutationRequestAuthorizationGuest.ts +85 -0
- package/src/mutation/MutationRequestTokens.ts +98 -0
- package/src/mutation/MutationTransferTokens.ts +87 -0
- package/src/mutation/MutationWithdrawBufferToken.ts +73 -0
- package/src/query/Query.ts +187 -0
- package/src/query/QueryActiveSession.ts +89 -0
- package/src/query/QueryAtom.ts +275 -0
- package/src/query/QueryBalance.ts +102 -0
- package/src/query/QueryBatch.ts +145 -0
- package/src/query/QueryBatchHistory.ts +86 -0
- package/src/query/QueryContinuId.ts +91 -0
- package/src/query/QueryMetaType.ts +177 -0
- package/src/query/QueryMetaTypeViaAtom.ts +199 -0
- package/src/query/QueryPolicy.ts +91 -0
- package/src/query/QueryToken.ts +90 -0
- package/src/query/QueryUserActivity.ts +153 -0
- package/src/query/QueryWalletBundle.ts +92 -0
- package/src/query/QueryWalletList.ts +106 -0
- package/src/response/EnhancedResponse.ts +345 -0
- package/src/response/Response.ts +254 -0
- package/src/response/ResponseActiveSession.ts +72 -0
- package/src/response/ResponseAtom.ts +132 -0
- package/src/response/ResponseAuthorizationGuest.ts +119 -0
- package/src/response/ResponseBalance.ts +153 -0
- package/src/response/ResponseClaimShadowWallet.ts +56 -0
- package/src/response/ResponseContinuId.ts +101 -0
- package/src/response/ResponseCreateIdentifier.ts +56 -0
- package/src/response/ResponseCreateMeta.ts +58 -0
- package/src/response/ResponseCreateRule.ts +56 -0
- package/src/response/ResponseCreateToken.ts +58 -0
- package/src/response/ResponseCreateWallet.ts +58 -0
- package/src/response/ResponseLinkIdentifier.ts +87 -0
- package/src/response/ResponseMetaBatch.ts +72 -0
- package/src/response/ResponseMetaType.ts +108 -0
- package/src/response/ResponseMetaTypeViaAtom.ts +108 -0
- package/src/response/ResponsePolicy.ts +90 -0
- package/src/response/ResponseProposeMolecule.ts +155 -0
- package/src/response/ResponseQueryActiveSession.ts +105 -0
- package/src/response/ResponseQueryUserActivity.ts +89 -0
- package/src/response/ResponseRequestAuthorization.ts +100 -0
- package/src/response/ResponseRequestAuthorizationGuest.ts +133 -0
- package/src/response/ResponseRequestTokens.ts +58 -0
- package/src/response/ResponseTransferTokens.ts +72 -0
- package/src/response/ResponseWalletBundle.ts +95 -0
- package/src/response/ResponseWalletList.ts +165 -0
- package/src/schemas/index.ts +457 -0
- package/src/subscribe/ActiveSessionSubscribe.ts +72 -0
- package/src/subscribe/ActiveWalletSubscribe.ts +99 -0
- package/src/subscribe/CreateMoleculeSubscribe.ts +106 -0
- package/src/subscribe/Subscribe.ts +182 -0
- package/src/subscribe/WalletStatusSubscribe.ts +70 -0
- package/src/subscribe/index.ts +59 -0
- package/src/types/assertions.ts +722 -0
- package/src/types/client.ts +567 -0
- package/src/types/crypto.ts +541 -0
- package/src/types/graphql.ts +630 -0
- package/src/types/guards.ts +659 -0
- package/src/types/index.ts +614 -0
- package/src/types/response.ts +133 -0
- package/src/types/template-literals.ts +382 -0
- package/src/validation/UNIVERSAL_CONFIGURATION_INTERFACES.ts +580 -0
- package/src/validation/ValidationService.ts +607 -0
- package/src/validation/schemas.ts +447 -0
- package/src/versions/HashAtom.ts +170 -0
- package/src/versions/Version4.ts +120 -0
- package/src/versions/index.ts +80 -0
|
@@ -0,0 +1,607 @@
|
|
|
1
|
+
/*
|
|
2
|
+
(
|
|
3
|
+
(/(
|
|
4
|
+
(//(
|
|
5
|
+
(///(
|
|
6
|
+
(/////(
|
|
7
|
+
(//////( )
|
|
8
|
+
(////////( (/)
|
|
9
|
+
(////////( (///)
|
|
10
|
+
(//////////( (////)
|
|
11
|
+
(//////////( (//////)
|
|
12
|
+
(////////////( (///////)
|
|
13
|
+
(/////////////( (/////////)
|
|
14
|
+
(//////////////( (///////////)
|
|
15
|
+
(///////////////( (/////////////)
|
|
16
|
+
(////////////////( (//////////////)
|
|
17
|
+
((((((((((((((((((( (((((((((((((((
|
|
18
|
+
((((((((((((((((((( ((((((((((((((
|
|
19
|
+
((((((((((((((((((( ((((((((((((((
|
|
20
|
+
(((((((((((((((((((( (((((((((((((
|
|
21
|
+
(((((((((((((((((((( ((((((((((((
|
|
22
|
+
((((((((((((((((((( ((((((((((((
|
|
23
|
+
((((((((((((((((((( ((((((((((
|
|
24
|
+
((((((((((((((((((/ (((((((((
|
|
25
|
+
(((((((((((((((((( ((((((((
|
|
26
|
+
((((((((((((((((( (((((((
|
|
27
|
+
(((((((((((((((((( (((((
|
|
28
|
+
################# ##
|
|
29
|
+
################ #
|
|
30
|
+
################# ##
|
|
31
|
+
%################ ###
|
|
32
|
+
###############( ####
|
|
33
|
+
############### ####
|
|
34
|
+
############### ######
|
|
35
|
+
%#############( (#######
|
|
36
|
+
%############# #########
|
|
37
|
+
############( ##########
|
|
38
|
+
########### #############
|
|
39
|
+
######### ##############
|
|
40
|
+
%######
|
|
41
|
+
|
|
42
|
+
Powered by Knish.IO: Connecting a Decentralized World
|
|
43
|
+
|
|
44
|
+
Please visit https://github.com/WishKnish/KnishIO-Client-TS for information.
|
|
45
|
+
|
|
46
|
+
License: https://github.com/WishKnish/KnishIO-Client-TS/blob/master/LICENSE
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* ValidationService - Centralized validation for KnishIO SDK
|
|
51
|
+
*
|
|
52
|
+
* Implements 2025 TypeScript patterns:
|
|
53
|
+
* - Zod runtime validation with compile-time types
|
|
54
|
+
* - Result<T, E> pattern for error handling
|
|
55
|
+
* - Builder pattern for validation chains
|
|
56
|
+
* - Branded types for domain safety
|
|
57
|
+
*/
|
|
58
|
+
|
|
59
|
+
import { z } from 'zod'
|
|
60
|
+
import type {
|
|
61
|
+
KnishIOClientConfig,
|
|
62
|
+
TransferParams,
|
|
63
|
+
CreateTokenParams,
|
|
64
|
+
RequestTokensParams,
|
|
65
|
+
BalanceQueryParams,
|
|
66
|
+
MetaQueryParams,
|
|
67
|
+
WalletQueryParams
|
|
68
|
+
} from '@/types'
|
|
69
|
+
import {
|
|
70
|
+
Schemas,
|
|
71
|
+
safeParse,
|
|
72
|
+
validateStrict,
|
|
73
|
+
validateWithDefaults,
|
|
74
|
+
createTypeGuard,
|
|
75
|
+
type ValidatedClientConfig,
|
|
76
|
+
type ValidatedTransferParams,
|
|
77
|
+
type ValidatedGraphQLResponse
|
|
78
|
+
} from './schemas'
|
|
79
|
+
|
|
80
|
+
// =============================================================================
|
|
81
|
+
// RESULT TYPE PATTERN (2025 TYPESCRIPT)
|
|
82
|
+
// =============================================================================
|
|
83
|
+
|
|
84
|
+
export type ValidationResult<T, E = ValidationError> =
|
|
85
|
+
| { success: true; data: T; warnings?: string[] }
|
|
86
|
+
| { success: false; error: E }
|
|
87
|
+
|
|
88
|
+
export interface ValidationError {
|
|
89
|
+
code: 'VALIDATION_ERROR' | 'SCHEMA_ERROR' | 'TYPE_ERROR'
|
|
90
|
+
message: string
|
|
91
|
+
field?: string
|
|
92
|
+
value?: unknown
|
|
93
|
+
details?: z.ZodIssue[]
|
|
94
|
+
context?: string
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface ValidationOptions {
|
|
98
|
+
strict?: boolean
|
|
99
|
+
allowUnknown?: boolean
|
|
100
|
+
stripUnknown?: boolean
|
|
101
|
+
context?: string
|
|
102
|
+
warnings?: boolean
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// =============================================================================
|
|
106
|
+
// VALIDATION SERVICE CLASS
|
|
107
|
+
// =============================================================================
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Centralized validation service using Zod schemas
|
|
111
|
+
* Provides type-safe validation with enhanced error reporting
|
|
112
|
+
*/
|
|
113
|
+
export class ValidationService {
|
|
114
|
+
private static instance: ValidationService
|
|
115
|
+
private validationHistory: Array<{
|
|
116
|
+
timestamp: number
|
|
117
|
+
schema: string
|
|
118
|
+
success: boolean
|
|
119
|
+
error?: string
|
|
120
|
+
}> = []
|
|
121
|
+
|
|
122
|
+
private constructor() {}
|
|
123
|
+
|
|
124
|
+
static getInstance(): ValidationService {
|
|
125
|
+
if (!ValidationService.instance) {
|
|
126
|
+
ValidationService.instance = new ValidationService()
|
|
127
|
+
}
|
|
128
|
+
return ValidationService.instance
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// =============================================================================
|
|
132
|
+
// CORE VALIDATION METHODS
|
|
133
|
+
// =============================================================================
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Validate client configuration with environment overrides
|
|
137
|
+
*/
|
|
138
|
+
validateClientConfig(config: unknown): ValidationResult<ValidatedClientConfig> {
|
|
139
|
+
try {
|
|
140
|
+
// First get environment-mapped client config
|
|
141
|
+
const envResult = this.validateEnvironmentConfig()
|
|
142
|
+
const envMappedConfig = envResult.success ? envResult.data : {}
|
|
143
|
+
|
|
144
|
+
// Merge environment config with provided config (provided config takes precedence)
|
|
145
|
+
const mergedConfig = {
|
|
146
|
+
...envMappedConfig,
|
|
147
|
+
...(typeof config === 'object' && config !== null ? config : {})
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const parseResult = safeParse(Schemas.ClientConfig, mergedConfig)
|
|
151
|
+
|
|
152
|
+
if (!parseResult.success) {
|
|
153
|
+
return {
|
|
154
|
+
success: false,
|
|
155
|
+
error: {
|
|
156
|
+
code: 'VALIDATION_ERROR',
|
|
157
|
+
message: 'Invalid client configuration',
|
|
158
|
+
details: parseResult.error.issues,
|
|
159
|
+
context: 'ClientConfig'
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
this.logValidation('ClientConfig', true)
|
|
165
|
+
return {
|
|
166
|
+
success: true,
|
|
167
|
+
data: parseResult.data,
|
|
168
|
+
warnings: this.generateConfigWarnings(parseResult.data)
|
|
169
|
+
}
|
|
170
|
+
} catch (error) {
|
|
171
|
+
this.logValidation('ClientConfig', false, String(error))
|
|
172
|
+
return {
|
|
173
|
+
success: false,
|
|
174
|
+
error: {
|
|
175
|
+
code: 'SCHEMA_ERROR',
|
|
176
|
+
message: `Validation failed: ${error}`,
|
|
177
|
+
context: 'ClientConfig'
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Validate environment configuration and map to client config format
|
|
185
|
+
*/
|
|
186
|
+
validateEnvironmentConfig(): ValidationResult<Record<string, any>> {
|
|
187
|
+
try {
|
|
188
|
+
const env = {
|
|
189
|
+
NODE_ENV: process.env.NODE_ENV,
|
|
190
|
+
KNISHIO_NODE_URI: process.env.KNISHIO_NODE_URI,
|
|
191
|
+
KNISHIO_CELL_SLUG: process.env.KNISHIO_CELL_SLUG,
|
|
192
|
+
KNISHIO_LOGGING: process.env.KNISHIO_LOGGING,
|
|
193
|
+
KNISHIO_SERVER_SDK_VERSION: process.env.KNISHIO_SERVER_SDK_VERSION
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const parseResult = safeParse(Schemas.EnvironmentConfig, env)
|
|
197
|
+
|
|
198
|
+
if (!parseResult.success) {
|
|
199
|
+
return {
|
|
200
|
+
success: false,
|
|
201
|
+
error: {
|
|
202
|
+
code: 'VALIDATION_ERROR',
|
|
203
|
+
message: 'Invalid environment configuration',
|
|
204
|
+
details: parseResult.error.issues,
|
|
205
|
+
context: 'Environment'
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Map environment variables to client configuration properties
|
|
211
|
+
const validatedEnv = parseResult.data
|
|
212
|
+
const clientConfig: Record<string, any> = {}
|
|
213
|
+
|
|
214
|
+
// Map KNISHIO_NODE_URI to uri
|
|
215
|
+
if (validatedEnv.KNISHIO_NODE_URI) {
|
|
216
|
+
clientConfig.uri = validatedEnv.KNISHIO_NODE_URI
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Map KNISHIO_CELL_SLUG to cellSlug
|
|
220
|
+
if (validatedEnv.KNISHIO_CELL_SLUG) {
|
|
221
|
+
clientConfig.cellSlug = validatedEnv.KNISHIO_CELL_SLUG
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Map KNISHIO_LOGGING to logging
|
|
225
|
+
if (validatedEnv.KNISHIO_LOGGING !== undefined) {
|
|
226
|
+
clientConfig.logging = validatedEnv.KNISHIO_LOGGING
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Map KNISHIO_SERVER_SDK_VERSION to serverSdkVersion
|
|
230
|
+
if (validatedEnv.KNISHIO_SERVER_SDK_VERSION !== undefined) {
|
|
231
|
+
clientConfig.serverSdkVersion = validatedEnv.KNISHIO_SERVER_SDK_VERSION
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return { success: true, data: clientConfig }
|
|
235
|
+
} catch (error) {
|
|
236
|
+
return {
|
|
237
|
+
success: false,
|
|
238
|
+
error: {
|
|
239
|
+
code: 'SCHEMA_ERROR',
|
|
240
|
+
message: `Environment validation failed: ${error}`,
|
|
241
|
+
context: 'Environment'
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Validate transfer parameters with business logic
|
|
249
|
+
*/
|
|
250
|
+
validateTransferParams(params: unknown): ValidationResult<ValidatedTransferParams> {
|
|
251
|
+
try {
|
|
252
|
+
const parseResult = safeParse(Schemas.TransferParams, params)
|
|
253
|
+
|
|
254
|
+
if (!parseResult.success) {
|
|
255
|
+
return {
|
|
256
|
+
success: false,
|
|
257
|
+
error: {
|
|
258
|
+
code: 'VALIDATION_ERROR',
|
|
259
|
+
message: 'Invalid transfer parameters',
|
|
260
|
+
details: parseResult.error.issues,
|
|
261
|
+
context: 'TransferParams'
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Additional business logic validation
|
|
267
|
+
const businessValidation = this.validateTransferBusinessLogic(parseResult.data)
|
|
268
|
+
if (!businessValidation.success) {
|
|
269
|
+
return businessValidation
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
this.logValidation('TransferParams', true)
|
|
273
|
+
return {
|
|
274
|
+
success: true,
|
|
275
|
+
data: parseResult.data,
|
|
276
|
+
warnings: this.generateTransferWarnings(parseResult.data)
|
|
277
|
+
}
|
|
278
|
+
} catch (error) {
|
|
279
|
+
this.logValidation('TransferParams', false, String(error))
|
|
280
|
+
return {
|
|
281
|
+
success: false,
|
|
282
|
+
error: {
|
|
283
|
+
code: 'SCHEMA_ERROR',
|
|
284
|
+
message: `Transfer validation failed: ${error}`,
|
|
285
|
+
context: 'TransferParams'
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Validate GraphQL response structure
|
|
293
|
+
*/
|
|
294
|
+
validateGraphQLResponse(response: unknown): ValidationResult<ValidatedGraphQLResponse> {
|
|
295
|
+
try {
|
|
296
|
+
const parseResult = safeParse(Schemas.GraphQLResponse, response)
|
|
297
|
+
|
|
298
|
+
if (!parseResult.success) {
|
|
299
|
+
return {
|
|
300
|
+
success: false,
|
|
301
|
+
error: {
|
|
302
|
+
code: 'VALIDATION_ERROR',
|
|
303
|
+
message: 'Invalid GraphQL response format',
|
|
304
|
+
details: parseResult.error.issues,
|
|
305
|
+
context: 'GraphQLResponse'
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Check for GraphQL errors
|
|
311
|
+
if (parseResult.data.errors && parseResult.data.errors.length > 0) {
|
|
312
|
+
return {
|
|
313
|
+
success: false,
|
|
314
|
+
error: {
|
|
315
|
+
code: 'VALIDATION_ERROR',
|
|
316
|
+
message: 'GraphQL response contains errors',
|
|
317
|
+
details: parseResult.data.errors.map(err => ({
|
|
318
|
+
code: 'invalid_type',
|
|
319
|
+
expected: 'success',
|
|
320
|
+
received: 'error',
|
|
321
|
+
path: [],
|
|
322
|
+
message: err.message
|
|
323
|
+
} as z.ZodIssue)),
|
|
324
|
+
context: 'GraphQLResponse'
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
this.logValidation('GraphQLResponse', true)
|
|
330
|
+
return { success: true, data: parseResult.data }
|
|
331
|
+
} catch (error) {
|
|
332
|
+
this.logValidation('GraphQLResponse', false, String(error))
|
|
333
|
+
return {
|
|
334
|
+
success: false,
|
|
335
|
+
error: {
|
|
336
|
+
code: 'SCHEMA_ERROR',
|
|
337
|
+
message: `GraphQL response validation failed: ${error}`,
|
|
338
|
+
context: 'GraphQLResponse'
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// =============================================================================
|
|
345
|
+
// BUILDER PATTERN FOR VALIDATION CHAINS
|
|
346
|
+
// =============================================================================
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Create a validation chain builder
|
|
350
|
+
*/
|
|
351
|
+
createValidationChain<T>(): ValidationChainBuilder<T> {
|
|
352
|
+
return new ValidationChainBuilder<T>(this)
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// =============================================================================
|
|
356
|
+
// TYPE GUARDS AND UTILITIES
|
|
357
|
+
// =============================================================================
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Runtime type guards for common types
|
|
361
|
+
*/
|
|
362
|
+
readonly typeGuards = {
|
|
363
|
+
isWalletAddress: createTypeGuard(Schemas.WalletAddress),
|
|
364
|
+
isBundleHash: createTypeGuard(Schemas.BundleHash),
|
|
365
|
+
isTokenSlug: createTypeGuard(Schemas.TokenSlug),
|
|
366
|
+
isClientConfig: createTypeGuard(Schemas.ClientConfig),
|
|
367
|
+
isTransferParams: createTypeGuard(Schemas.TransferParams),
|
|
368
|
+
isGraphQLResponse: createTypeGuard(Schemas.GraphQLResponse)
|
|
369
|
+
} as const
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Validate any value against a specific schema
|
|
373
|
+
*/
|
|
374
|
+
validate<T>(schema: z.ZodType<T>, value: unknown, options: ValidationOptions = {}): ValidationResult<T> {
|
|
375
|
+
try {
|
|
376
|
+
const parseResult = safeParse(schema, value)
|
|
377
|
+
|
|
378
|
+
if (!parseResult.success) {
|
|
379
|
+
return {
|
|
380
|
+
success: false,
|
|
381
|
+
error: {
|
|
382
|
+
code: 'VALIDATION_ERROR',
|
|
383
|
+
message: options.context ? `Validation failed in ${options.context}` : 'Validation failed',
|
|
384
|
+
details: parseResult.error.issues,
|
|
385
|
+
context: options.context
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
return { success: true, data: parseResult.data }
|
|
391
|
+
} catch (error) {
|
|
392
|
+
return {
|
|
393
|
+
success: false,
|
|
394
|
+
error: {
|
|
395
|
+
code: 'SCHEMA_ERROR',
|
|
396
|
+
message: `Schema validation failed: ${error}`,
|
|
397
|
+
context: options.context
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// =============================================================================
|
|
404
|
+
// BUSINESS LOGIC VALIDATION
|
|
405
|
+
// =============================================================================
|
|
406
|
+
|
|
407
|
+
private validateTransferBusinessLogic(params: ValidatedTransferParams): ValidationResult<ValidatedTransferParams> {
|
|
408
|
+
const warnings: string[] = []
|
|
409
|
+
|
|
410
|
+
// Check for self-transfer
|
|
411
|
+
if (params.recipient === params.recipient) {
|
|
412
|
+
warnings.push('Transfer to same address detected')
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// Validate amount ranges
|
|
416
|
+
const amount = Number(params.amount)
|
|
417
|
+
if (amount > 1000000) {
|
|
418
|
+
warnings.push('Large transfer amount detected - consider splitting')
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
return { success: true, data: params, warnings }
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
private generateConfigWarnings(config: ValidatedClientConfig): string[] {
|
|
425
|
+
const warnings: string[] = []
|
|
426
|
+
|
|
427
|
+
if (!config.uri) {
|
|
428
|
+
warnings.push('No URI specified - using default')
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
if (config.logging) {
|
|
432
|
+
warnings.push('Logging enabled - may impact performance')
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
if (config.serverSdkVersion && config.serverSdkVersion < 4) {
|
|
436
|
+
warnings.push('Using older server SDK version - consider upgrading')
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
return warnings
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
private generateTransferWarnings(params: ValidatedTransferParams): string[] {
|
|
443
|
+
const warnings: string[] = []
|
|
444
|
+
|
|
445
|
+
if (!params.token) {
|
|
446
|
+
warnings.push('No token specified - using default USER token')
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
if (!params.metaType && !params.metaId) {
|
|
450
|
+
warnings.push('No metadata specified for transfer')
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
return warnings
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// =============================================================================
|
|
457
|
+
// VALIDATION LOGGING AND MONITORING
|
|
458
|
+
// =============================================================================
|
|
459
|
+
|
|
460
|
+
private logValidation(schema: string, success: boolean, error?: string): void {
|
|
461
|
+
this.validationHistory.push({
|
|
462
|
+
timestamp: Date.now(),
|
|
463
|
+
schema,
|
|
464
|
+
success,
|
|
465
|
+
error
|
|
466
|
+
})
|
|
467
|
+
|
|
468
|
+
// Keep only last 1000 validations
|
|
469
|
+
if (this.validationHistory.length > 1000) {
|
|
470
|
+
this.validationHistory = this.validationHistory.slice(-1000)
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* Get validation statistics
|
|
476
|
+
*/
|
|
477
|
+
getValidationStats(): {
|
|
478
|
+
total: number
|
|
479
|
+
successful: number
|
|
480
|
+
failed: number
|
|
481
|
+
successRate: number
|
|
482
|
+
schemaStats: Record<string, number>
|
|
483
|
+
recentFailures: Array<{
|
|
484
|
+
schema: string
|
|
485
|
+
error?: string
|
|
486
|
+
timestamp: number
|
|
487
|
+
}>
|
|
488
|
+
} {
|
|
489
|
+
const total = this.validationHistory.length
|
|
490
|
+
const successful = this.validationHistory.filter(v => v.success).length
|
|
491
|
+
const failed = total - successful
|
|
492
|
+
|
|
493
|
+
const schemaStats = this.validationHistory.reduce((acc, v) => {
|
|
494
|
+
acc[v.schema] = (acc[v.schema] || 0) + 1
|
|
495
|
+
return acc
|
|
496
|
+
}, {} as Record<string, number>)
|
|
497
|
+
|
|
498
|
+
return {
|
|
499
|
+
total,
|
|
500
|
+
successful,
|
|
501
|
+
failed,
|
|
502
|
+
successRate: total > 0 ? (successful / total) * 100 : 0,
|
|
503
|
+
schemaStats,
|
|
504
|
+
recentFailures: this.validationHistory
|
|
505
|
+
.filter(v => !v.success)
|
|
506
|
+
.slice(-10)
|
|
507
|
+
.map(v => ({ schema: v.schema, error: v.error, timestamp: v.timestamp }))
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/**
|
|
512
|
+
* Clear validation history
|
|
513
|
+
*/
|
|
514
|
+
clearValidationHistory(): void {
|
|
515
|
+
this.validationHistory = []
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// =============================================================================
|
|
520
|
+
// VALIDATION CHAIN BUILDER (FLUENT PATTERN)
|
|
521
|
+
// =============================================================================
|
|
522
|
+
|
|
523
|
+
export class ValidationChainBuilder<T> {
|
|
524
|
+
private validators: Array<(value: T) => ValidationResult<T>> = []
|
|
525
|
+
|
|
526
|
+
constructor(private service: ValidationService) {}
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* Add a schema validation step
|
|
530
|
+
*/
|
|
531
|
+
schema<U>(schema: z.ZodType<U>): ValidationChainBuilder<T> {
|
|
532
|
+
this.validators.push((value) =>
|
|
533
|
+
this.service.validate(schema, value) as ValidationResult<T>
|
|
534
|
+
)
|
|
535
|
+
return this
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Add a custom validation step
|
|
540
|
+
*/
|
|
541
|
+
custom(validator: (value: T) => ValidationResult<T>): ValidationChainBuilder<T> {
|
|
542
|
+
this.validators.push(validator)
|
|
543
|
+
return this
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* Add a business logic validation step
|
|
548
|
+
*/
|
|
549
|
+
business(validator: (value: T) => boolean, errorMessage: string): ValidationChainBuilder<T> {
|
|
550
|
+
this.validators.push((value) => {
|
|
551
|
+
if (validator(value)) {
|
|
552
|
+
return { success: true, data: value }
|
|
553
|
+
}
|
|
554
|
+
return {
|
|
555
|
+
success: false,
|
|
556
|
+
error: {
|
|
557
|
+
code: 'VALIDATION_ERROR',
|
|
558
|
+
message: errorMessage,
|
|
559
|
+
value,
|
|
560
|
+
context: 'BusinessLogic'
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
})
|
|
564
|
+
return this
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
/**
|
|
568
|
+
* Execute the validation chain
|
|
569
|
+
*/
|
|
570
|
+
validate(value: unknown): ValidationResult<T> {
|
|
571
|
+
let currentValue = value as T
|
|
572
|
+
|
|
573
|
+
for (const validator of this.validators) {
|
|
574
|
+
const result = validator(currentValue)
|
|
575
|
+
if (!result.success) {
|
|
576
|
+
return result
|
|
577
|
+
}
|
|
578
|
+
currentValue = result.data
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
return { success: true, data: currentValue }
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
// =============================================================================
|
|
586
|
+
// SINGLETON INSTANCE AND UTILITIES
|
|
587
|
+
// =============================================================================
|
|
588
|
+
|
|
589
|
+
// Export singleton instance
|
|
590
|
+
export const validationService = ValidationService.getInstance()
|
|
591
|
+
|
|
592
|
+
// Convenience functions
|
|
593
|
+
export const validateClientConfig = (config: unknown): ValidationResult<ValidatedClientConfig> =>
|
|
594
|
+
validationService.validateClientConfig(config)
|
|
595
|
+
|
|
596
|
+
export const validateTransferParams = (params: unknown): ValidationResult<ValidatedTransferParams> =>
|
|
597
|
+
validationService.validateTransferParams(params)
|
|
598
|
+
|
|
599
|
+
export const validateGraphQLResponse = (response: unknown): ValidationResult<ValidatedGraphQLResponse> =>
|
|
600
|
+
validationService.validateGraphQLResponse(response)
|
|
601
|
+
|
|
602
|
+
// Type guard exports
|
|
603
|
+
export const { typeGuards } = validationService
|
|
604
|
+
|
|
605
|
+
// Validation chain factory
|
|
606
|
+
export const createValidationChain = <T>(): ValidationChainBuilder<T> =>
|
|
607
|
+
validationService.createValidationChain<T>()
|