@wishknish/knishio-client-ts 0.8.3 → 0.9.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.
@@ -54,11 +54,10 @@ import {
54
54
  Client,
55
55
  OperationResult
56
56
  } from '@urql/core'
57
- import { createClient as createWSClient, Client as WSClient } from 'graphql-ws'
58
- import { pipe, map, SubscriptionLike } from 'wonka'
57
+ import { createClient as createWSClient, Client as WSClient, type SubscribePayload } from 'graphql-ws'
58
+ import { pipe, map, subscribe, type Subscription } from 'wonka'
59
59
  import type { DocumentNode } from 'graphql'
60
60
  import type Wallet from '@/core/Wallet'
61
- import { GraphQLRequestSchema, GraphQLResponseSchema, parseWithSchema } from '@/schemas'
62
61
 
63
62
  // Enhanced type definitions with proper constraints
64
63
  interface SocketConfig {
@@ -110,7 +109,7 @@ class UrqlClientWrapper {
110
109
  private $__authToken: string = ''
111
110
  private $__pubkey: string | null = null
112
111
  private $__wallet: Wallet | null = null
113
- private readonly serverUri: string
112
+ private serverUri: string
114
113
  private soketi: SocketConfig | null
115
114
  private cipherLink: boolean
116
115
  private readonly $__subscriptionManager: Map<string, SubscriptionManager> = new Map()
@@ -126,8 +125,7 @@ class UrqlClientWrapper {
126
125
 
127
126
  private createUrqlClient({
128
127
  serverUri,
129
- socket,
130
- encrypt
128
+ socket
131
129
  }: {
132
130
  serverUri: string
133
131
  socket?: SocketConfig | null
@@ -147,7 +145,7 @@ class UrqlClientWrapper {
147
145
  exchanges.push(subscriptionExchange({
148
146
  forwardSubscription: operation => ({
149
147
  subscribe: sink => {
150
- const disposable = wsClient.subscribe(operation, sink)
148
+ const disposable = wsClient.subscribe(operation as unknown as SubscribePayload, sink)
151
149
  return { unsubscribe: disposable }
152
150
  }
153
151
  })
@@ -209,12 +207,14 @@ class UrqlClientWrapper {
209
207
  throw new Error('Query is required for subscription')
210
208
  }
211
209
 
212
- const subscription: SubscriptionLike = pipe(
210
+ // wonka v6: subscribe is a pipe operator (no `.subscribe()` method on Source) → pipe(src, ..., subscribe(h))
211
+ const subscription: Subscription = pipe(
213
212
  this.$__client.subscription(query, variables),
214
213
  map(result => {
215
214
  closure(this.formatResponse<TData>(result))
216
- })
217
- ).subscribe(() => {})
215
+ }),
216
+ subscribe(() => {})
217
+ )
218
218
 
219
219
  // Store subscription for later cleanup
220
220
  if (operationName) {
@@ -238,8 +238,8 @@ class UrqlClientWrapper {
238
238
  if (result.error) {
239
239
  response.errors = [{
240
240
  message: result.error.message,
241
- locations: result.error.graphQLErrors?.[0]?.locations,
242
- path: result.error.graphQLErrors?.[0]?.path,
241
+ locations: result.error.graphQLErrors?.[0]?.locations as { line: number; column: number }[] | undefined,
242
+ path: result.error.graphQLErrors?.[0]?.path as (string | number)[] | undefined,
243
243
  extensions: result.error.graphQLErrors?.[0]?.extensions
244
244
  }]
245
245
  }
@@ -263,7 +263,7 @@ class UrqlClientWrapper {
263
263
  }
264
264
 
265
265
  unsubscribeAll(): void {
266
- this.$__subscriptionManager.forEach((subscription, operationName) => {
266
+ this.$__subscriptionManager.forEach((_subscription, operationName) => {
267
267
  this.unsubscribe(operationName)
268
268
  })
269
269
  }
@@ -178,10 +178,10 @@ export function generateSecretEnhanced(options: SecretGenerationOptions): string
178
178
  * Uses SHAKE256 with 256-bit output (64 hex characters)
179
179
  */
180
180
  export function generateBundleHash(secret: string, _source: string | null = null): BundleHash {
181
- if (!secret || secret.length === 0) {
182
- throw new Error('Secret is required for bundle hash generation')
183
- }
184
-
181
+ // Cross-SDK parity (c142): an empty secret hashes to shake256("") = 46b9dd2b… — matching
182
+ // JS/PHP/Kotlin/Rust/Python + the committed `empty_secret` vector. (Previously threw;
183
+ // no real caller passes an empty secret.)
184
+ //
185
185
  // CRITICAL: source parameter must be IGNORED to match JS SDK behavior.
186
186
  // JS SDK's generateBundleHash() accepts source but never uses it.
187
187
  // The bundle hash is an identity anchor and must be deterministic from secret alone.
@@ -71,9 +71,11 @@ export default class MutationClaimShadowWallet extends MutationProposeMolecule {
71
71
  bundle: this.$__molecule.bundle,
72
72
  token,
73
73
  batchId
74
- })
74
+ });
75
75
 
76
76
  // Initialize shadow wallet claim on the molecule
77
+ // (leading-paren statements REQUIRE the preceding semicolon — without it ASI parses
78
+ // `Wallet.create({...})(this.$__molecule)` and throws "Wallet.create(...) is not a function")
77
79
  (this.$__molecule as any).initShadowWalletClaim(wallet)
78
80
  this.$__molecule.sign({})
79
81
  this.$__molecule.check()
@@ -74,6 +74,24 @@ export default class MutationTransferTokens extends MutationProposeMolecule {
74
74
  (this.$__molecule as any).check((this.$__molecule as any).sourceWallet)
75
75
  }
76
76
 
77
+ /**
78
+ * Fills the Molecule for a MULTI-recipient transfer (one source funds N recipients)
79
+ */
80
+ fillMoleculeMulti({
81
+ recipientWallets,
82
+ amounts
83
+ }: {
84
+ recipientWallets: Wallet[]
85
+ amounts: number[]
86
+ }): void {
87
+ (this.$__molecule as any).initValues({
88
+ recipientWallets,
89
+ amounts
90
+ });
91
+ (this.$__molecule as any).sign({});
92
+ (this.$__molecule as any).check((this.$__molecule as any).sourceWallet)
93
+ }
94
+
77
95
  /**
78
96
  * Builds a Response object out of a JSON object
79
97
  * Matches JavaScript SDK createResponse method signature exactly
@@ -51,7 +51,6 @@ import ResponseQueryActiveSession from '@/response/ResponseQueryActiveSession'
51
51
  import { gql } from '@urql/core'
52
52
  import type { GraphQLClient as IGraphQLClient } from '@/types'
53
53
  import type KnishIOClient from '@/KnishIOClient'
54
- import type { BundleHash, MetaType, MetaId } from '@/types'
55
54
 
56
55
  /**
57
56
  * Query for retrieving a list of active User Sessions
@@ -51,7 +51,6 @@ import ResponsePolicy from '@/response/ResponsePolicy'
51
51
  import { gql } from '@urql/core'
52
52
  import type { GraphQLClient as IGraphQLClient } from '@/types'
53
53
  import type KnishIOClient from '@/KnishIOClient'
54
- import type { MetaType, MetaId } from '@/types'
55
54
 
56
55
  /**
57
56
  * Query for retrieving Policy information
@@ -75,14 +75,14 @@ export default class ResponseAuthorizationGuest extends Response {
75
75
  /**
76
76
  * Returns the reason for rejection
77
77
  */
78
- reason(): string {
78
+ override reason(): string {
79
79
  return 'Invalid response from server'
80
80
  }
81
81
 
82
82
  /**
83
83
  * Returns whether molecule was accepted or not
84
84
  */
85
- success(): boolean {
85
+ override success(): boolean {
86
86
  return this.payload() !== null
87
87
  }
88
88
 
@@ -48,6 +48,7 @@ License: https://github.com/WishKnish/KnishIO-Client-TS/blob/master/LICENSE
48
48
 
49
49
  import Response from './Response'
50
50
  import Wallet from '../core/Wallet'
51
+ import TokenUnit from '../core/TokenUnit'
51
52
  import type Query from '../query/Query'
52
53
 
53
54
  /**
@@ -134,12 +135,14 @@ export default class ResponseBalance extends Response {
134
135
  wallet.tokenFungibility = data.token.fungibility
135
136
  }
136
137
 
137
- // TODO: Implement TokenUnit support when TokenUnit class is available
138
- // if (data.tokenUnits && data.tokenUnits.length) {
139
- // for (const tokenUnitData of data.tokenUnits) {
140
- // wallet.tokenUnits.push(TokenUnit.createFromGraphQL(tokenUnitData))
141
- // }
142
- // }
138
+ // Stackable (NFT) token units — the validator serves Wallet.tokenUnits and QueryBalance
139
+ // selects them; parse them so a queried source wallet carries its units (otherwise every
140
+ // stackable transfer silently degrades to fungible). Mirrors ResponseWalletList.toClientWallet.
141
+ if (data.tokenUnits && data.tokenUnits.length) {
142
+ for (const tokenUnitData of data.tokenUnits) {
143
+ wallet.tokenUnits.push(TokenUnit.createFromGraphQL(tokenUnitData))
144
+ }
145
+ }
143
146
 
144
147
  // Set trade rates if available
145
148
  if (data.tradeRates && data.tradeRates.length) {
@@ -74,7 +74,7 @@ export default class ResponseLinkIdentifier extends Response {
74
74
  /**
75
75
  * Returns success status
76
76
  */
77
- success(): any {
77
+ override success(): any {
78
78
  return Dot.get(this.data(), 'set')
79
79
  }
80
80
 
@@ -75,14 +75,14 @@ export default class ResponseRequestAuthorizationGuest extends Response {
75
75
  /**
76
76
  * Returns the reason for rejection
77
77
  */
78
- reason(): string {
78
+ override reason(): string {
79
79
  return 'Invalid response from server'
80
80
  }
81
81
 
82
82
  /**
83
83
  * Returns whether authorization was successful
84
84
  */
85
- success(): boolean {
85
+ override success(): boolean {
86
86
  return this.payload() !== null
87
87
  }
88
88
 
@@ -49,7 +49,6 @@ License: https://github.com/WishKnish/KnishIO-Client-TS/blob/master/LICENSE
49
49
  import type { GraphQLClient as IGraphQLClient } from '@/types'
50
50
  import { CodeException } from '@/exception'
51
51
  import type { DocumentNode } from 'graphql'
52
- import { GraphQLRequestSchema, parseWithSchema } from '@/schemas'
53
52
 
54
53
  // Define subscription-specific types for better type safety
55
54
  interface SubscriptionRequest {
@@ -72,7 +71,9 @@ interface SubscriptionCreateParams {
72
71
  }
73
72
 
74
73
  // Type for GraphQL client with subscription support
75
- interface GraphQLSubscriptionClient extends IGraphQLClient {
74
+ // Omit the base's required subscribe/getUri, then re-add as OPTIONAL variants (a passed client may
75
+ // not implement them) — avoids TS2430 (an optional member can't override a required base member).
76
+ interface GraphQLSubscriptionClient extends Omit<IGraphQLClient, 'subscribe' | 'getUri'> {
76
77
  subscribe?: (request: SubscriptionRequest, closure: (result: unknown) => void) => Promise<string>
77
78
  getUri?: () => string | null
78
79
  }
@@ -58,19 +58,14 @@ License: https://github.com/WishKnish/KnishIO-Client-TS/blob/master/LICENSE
58
58
 
59
59
  import type {
60
60
  AtomIsotope,
61
- KnishIOErrorType,
62
- QueryType,
63
- MutationType,
64
- SubscriptionType
61
+ KnishIOErrorType
65
62
  } from '../constants'
66
63
 
67
64
  import type {
68
65
  WalletAddress,
69
66
  BundleHash,
70
67
  TokenSlug,
71
- Position,
72
68
  MolecularHash,
73
- CellSlug,
74
69
  BatchId,
75
70
  AtomParams,
76
71
  WalletParams,
@@ -129,6 +129,18 @@ export interface TransferTokenOptions {
129
129
  callbackUrl?: string | null
130
130
  }
131
131
 
132
+ /**
133
+ * One destination of a multi-recipient transfer (see KnishIOClient.transferTokens).
134
+ * Provide EITHER units (stackable/NFT: amount = units.length) OR amount (fungible), not both.
135
+ * batchId makes the recipient a claimable shadow under that batch.
136
+ */
137
+ export interface TransferRecipientInput {
138
+ bundleHash: BundleHash | string
139
+ units?: string[]
140
+ amount?: number | null
141
+ batchId?: string | null
142
+ }
143
+
132
144
  export interface RequestTokensOptions {
133
145
  to: WalletAddress | string
134
146
  amount: number | string
@@ -269,16 +281,6 @@ export interface ActiveSessionOptions {
269
281
  metaId?: MetaId | string | null
270
282
  }
271
283
 
272
- export interface UserActivityOptions {
273
- bundleHash?: BundleHash | string | null
274
- metaType?: MetaType | string | null
275
- metaId?: MetaId | string | null
276
- dateFrom?: string | null
277
- dateTo?: string | null
278
- limit?: number | null
279
- offset?: number | null
280
- }
281
-
282
284
  export interface PolicyQueryOptions {
283
285
  metaType?: MetaType | string | null
284
286
  metaId?: MetaId | string | null
@@ -478,15 +480,6 @@ export interface ResponseQueryActiveSession extends BaseResponse<{
478
480
  expiresAt: string
479
481
  }> {}
480
482
 
481
- export interface ResponseQueryUserActivity extends BaseResponse<{
482
- activities: Array<{
483
- type: string
484
- description: string
485
- data: Record<string, unknown>
486
- createdAt: string
487
- }>
488
- }> {}
489
-
490
483
  export interface ResponsePolicy extends BaseResponse<{
491
484
  policy: Record<string, unknown>
492
485
  metaType: MetaType | null
@@ -239,7 +239,7 @@ export function isKnishIOErrorType(value: unknown): value is KnishIOErrorType {
239
239
  'WRONG_TOKEN_TYPE_ERROR'
240
240
  ] as const
241
241
 
242
- return typeof value === 'string' && errorTypes.includes(value as KnishIOErrorType)
242
+ return typeof value === 'string' && (errorTypes as readonly string[]).includes(value)
243
243
  }
244
244
 
245
245
  /**
@@ -282,8 +282,7 @@ export function isQueryType(value: unknown): value is QueryType {
282
282
  'Batch',
283
283
  'ActiveSession',
284
284
  'Policy',
285
- 'Token',
286
- 'UserActivity'
285
+ 'Token'
287
286
  ] as const
288
287
 
289
288
  return typeof value === 'string' && queryTypes.includes(value as QueryType)
@@ -61,8 +61,6 @@ License: https://github.com/WishKnish/KnishIO-Client-TS/blob/master/LICENSE
61
61
  * - Performance optimization hints
62
62
  */
63
63
 
64
- import { z } from 'zod'
65
- import type { ValidationResult } from './ValidationService'
66
64
 
67
65
  // =============================================================================
68
66
  // UNIVERSAL CONFIGURATION TYPES
@@ -227,16 +225,16 @@ export class ConfigValidator {
227
225
 
228
226
  // Enhanced validations
229
227
  if (options.includeWarnings !== false) {
230
- result.warnings.push(...this.generateWarnings(result.data))
228
+ result.warnings.push(...this.generateWarnings(result.data!))
231
229
  }
232
230
 
233
231
  if (options.includeRecommendations !== false) {
234
- result.recommendations.push(...this.generateRecommendations(result.data, options))
232
+ result.recommendations.push(...this.generateRecommendations(result.data!, options))
235
233
  }
236
234
 
237
235
  // Performance validation
238
236
  if (options.includePerformanceHints !== false) {
239
- result.warnings.push(...this.generatePerformanceWarnings(result.data))
237
+ result.warnings.push(...this.generatePerformanceWarnings(result.data!))
240
238
  }
241
239
 
242
240
  } catch (error) {
@@ -57,20 +57,9 @@ License: https://github.com/WishKnish/KnishIO-Client-TS/blob/master/LICENSE
57
57
  */
58
58
 
59
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
60
  import {
70
61
  Schemas,
71
62
  safeParse,
72
- validateStrict,
73
- validateWithDefaults,
74
63
  createTypeGuard,
75
64
  type ValidatedClientConfig,
76
65
  type ValidatedTransferParams,
@@ -164,8 +153,8 @@ export class ValidationService {
164
153
  this.logValidation('ClientConfig', true)
165
154
  return {
166
155
  success: true,
167
- data: parseResult.data,
168
- warnings: this.generateConfigWarnings(parseResult.data)
156
+ data: parseResult.data as ValidatedClientConfig,
157
+ warnings: this.generateConfigWarnings(parseResult.data as ValidatedClientConfig)
169
158
  }
170
159
  } catch (error) {
171
160
  this.logValidation('ClientConfig', false, String(error))
@@ -193,7 +182,9 @@ export class ValidationService {
193
182
  KNISHIO_SERVER_SDK_VERSION: process.env.KNISHIO_SERVER_SDK_VERSION
194
183
  }
195
184
 
196
- const parseResult = safeParse(Schemas.EnvironmentConfig, env)
185
+ // cast: EnvironmentConfig uses .default()/.optional() so its inferred input≠output type and
186
+ // doesn't structurally match safeParse's ZodType<T> param; ZodTypeAny sidesteps the mismatch.
187
+ const parseResult = safeParse(Schemas.EnvironmentConfig as z.ZodTypeAny, env)
197
188
 
198
189
  if (!parseResult.success) {
199
190
  return {
@@ -320,7 +311,7 @@ export class ValidationService {
320
311
  received: 'error',
321
312
  path: [],
322
313
  message: err.message
323
- } as z.ZodIssue)),
314
+ } as unknown as z.ZodIssue)),
324
315
  context: 'GraphQLResponse'
325
316
  }
326
317
  }
@@ -49,17 +49,19 @@ License: https://github.com/WishKnish/KnishIO-Client-TS/blob/master/LICENSE
49
49
  import type Atom from '@/core/Atom'
50
50
 
51
51
  // Define structured value types for better type safety
52
- type StructuredValue =
53
- | string
54
- | number
55
- | boolean
56
- | null
52
+ type StructuredValue =
53
+ | string
54
+ | number
55
+ | boolean
56
+ | null
57
57
  | undefined
58
58
  | StructuredObject
59
59
  | StructuredArray
60
60
 
61
- type StructuredObject = Record<string, StructuredValue>
62
- type StructuredArray = StructuredValue[]
61
+ // interfaces (not type aliases) so the recursion goes alias->interface->alias, which TS permits
62
+ // (an all-type-alias cycle triggers TS2456 "circularly references itself").
63
+ interface StructuredObject { [key: string]: StructuredValue }
64
+ interface StructuredArray extends Array<StructuredValue> {}
63
65
 
64
66
  // Define types for hashable values
65
67
  type HashableValue =
@@ -95,7 +97,7 @@ export default class HashAtom {
95
97
  // Extract atom properties with type safety
96
98
  for (const key of Object.keys(atom)) {
97
99
  if (Object.prototype.hasOwnProperty.call(atom, key)) {
98
- parameters[key] = (atom as Record<string, unknown>)[key]
100
+ parameters[key] = (atom as unknown as Record<string, unknown>)[key]
99
101
  }
100
102
  }
101
103
 
@@ -113,7 +115,7 @@ export default class HashAtom {
113
115
 
114
116
  if (isArray(object)) {
115
117
  const result: StructuredArray = []
116
- for (const value of object) {
118
+ for (const value of (object as unknown[])) {
117
119
  result.push(HashAtom.isStructure(value) ? HashAtom.structure(value) : value as StructuredValue)
118
120
  }
119
121
  return result
@@ -1,153 +0,0 @@
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
- import Query from './Query'
50
- import ResponseQueryUserActivity from '@/response/ResponseQueryUserActivity'
51
- import { gql } from '@urql/core'
52
- import type { GraphQLClient as IGraphQLClient } from '@/types'
53
- import type KnishIOClient from '@/KnishIOClient'
54
- import type { BundleHash, MetaType, MetaId } from '@/types'
55
-
56
- /**
57
- * Query for retrieving information about user activity
58
- */
59
- export default class QueryUserActivity extends Query {
60
- /**
61
- * Constructor
62
- */
63
- constructor(graphQLClient: IGraphQLClient, knishIOClient: KnishIOClient) {
64
- super(graphQLClient, knishIOClient)
65
-
66
- this.$__query = gql`
67
- query UserActivity(
68
- $bundleHash: String
69
- $metaType: String
70
- $metaId: String
71
- $ipAddress: String
72
- $browser: String
73
- $osCpu: String
74
- $resolution: String
75
- $timeZone: String
76
- $countBy: [CountByUserActivity]
77
- $interval: span
78
- ) {
79
- UserActivity(
80
- bundleHash: $bundleHash
81
- metaType: $metaType
82
- metaId: $metaId
83
- ipAddress: $ipAddress
84
- browser: $browser
85
- osCpu: $osCpu
86
- resolution: $resolution
87
- timeZone: $timeZone
88
- countBy: $countBy
89
- interval: $interval
90
- ) {
91
- createdAt
92
- bundleHash
93
- metaType
94
- metaId
95
- instances {
96
- bundleHash
97
- metaType
98
- metaId
99
- jsonData
100
- createdAt
101
- updatedAt
102
- }
103
- instanceCount {
104
- ...SubFields
105
- ...Recursive
106
- }
107
- }
108
- }
109
-
110
- fragment SubFields on InstanceCountType {
111
- id
112
- count
113
- }
114
-
115
- fragment Recursive on InstanceCountType {
116
- instances {
117
- ...SubFields
118
- instances {
119
- ...SubFields
120
- instances {
121
- ...SubFields
122
- instances {
123
- ...SubFields
124
- instances {
125
- ...SubFields
126
- instances {
127
- ...SubFields
128
- instances {
129
- ...SubFields
130
- instances {
131
- ...SubFields
132
- }
133
- }
134
- }
135
- }
136
- }
137
- }
138
- }
139
- }
140
- }
141
- `
142
- }
143
-
144
- /**
145
- * Returns a Response object
146
- */
147
- override createResponse(json: Record<string, any>): ResponseQueryUserActivity {
148
- return new ResponseQueryUserActivity({
149
- query: this,
150
- json
151
- })
152
- }
153
- }